@3fn/core 13.0.0 → 14.0.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 (236) hide show
  1. package/.kiro/agents/ada-prompt.md +80 -132
  2. package/.kiro/agents/ada-prompt.md.attribution.json +45 -0
  3. package/.kiro/agents/ada.json +44 -59
  4. package/.kiro/agents/ada.json.attribution.json +13 -0
  5. package/.kiro/agents/data-prompt.md +83 -74
  6. package/.kiro/agents/data-prompt.md.attribution.json +53 -0
  7. package/.kiro/agents/data.json +31 -38
  8. package/.kiro/agents/data.json.attribution.json +13 -0
  9. package/.kiro/agents/kenya-prompt.md +83 -72
  10. package/.kiro/agents/kenya-prompt.md.attribution.json +53 -0
  11. package/.kiro/agents/kenya.json +27 -35
  12. package/.kiro/agents/kenya.json.attribution.json +13 -0
  13. package/.kiro/agents/leonardo-prompt.md +176 -234
  14. package/.kiro/agents/leonardo-prompt.md.attribution.json +45 -0
  15. package/.kiro/agents/leonardo.json +28 -36
  16. package/.kiro/agents/leonardo.json.attribution.json +13 -0
  17. package/.kiro/agents/lina-prompt.md +110 -151
  18. package/.kiro/agents/lina-prompt.md.attribution.json +53 -0
  19. package/.kiro/agents/lina.json +46 -59
  20. package/.kiro/agents/lina.json.attribution.json +13 -0
  21. package/.kiro/agents/sparky-prompt.md +89 -72
  22. package/.kiro/agents/sparky-prompt.md.attribution.json +53 -0
  23. package/.kiro/agents/sparky.json +37 -37
  24. package/.kiro/agents/sparky.json.attribution.json +13 -0
  25. package/.kiro/agents/stacy-prompt.md +74 -48
  26. package/.kiro/agents/stacy-prompt.md.attribution.json +45 -0
  27. package/.kiro/agents/stacy.json +28 -30
  28. package/.kiro/agents/stacy.json.attribution.json +13 -0
  29. package/.kiro/agents/thurgood-prompt.md +94 -138
  30. package/.kiro/agents/thurgood-prompt.md.attribution.json +45 -0
  31. package/.kiro/agents/thurgood.json +31 -35
  32. package/.kiro/agents/thurgood.json.attribution.json +13 -0
  33. package/.kiro/steering/AI-Collaboration-Principles.md +3 -3
  34. package/.kiro/steering/Civitas-System-Overview.md +5 -5
  35. package/.kiro/steering/DesignerPunk-Systems-Overview.md +6 -6
  36. package/.kiro/steering/Task-Completion-Protocol.md +98 -17
  37. package/.kiro/steering/core-goals.md +3 -3
  38. package/.kiro/steering/personal-note.md +1 -1
  39. package/.kiro/steering/start-up-tasks.md +14 -3
  40. package/application-mcp-server/src/index.ts +26 -0
  41. package/dist/ComponentTokens.android.kt +1 -1
  42. package/dist/ComponentTokens.ios.swift +1 -1
  43. package/dist/ComponentTokens.web.css +1 -1
  44. package/dist/DesignTokens.android.kt +1 -1
  45. package/dist/DesignTokens.dtcg.json +8 -5
  46. package/dist/DesignTokens.figma.json +2 -2
  47. package/dist/DesignTokens.ios.swift +1 -1
  48. package/dist/DesignTokens.web.css +1 -1
  49. package/dist/android/DesignTokens.android.kt +1 -1
  50. package/dist/blend/OklchBlendCalculator.js +1 -0
  51. package/dist/blend/ThemeAwareBlendUtilities.web.d.ts +13 -2
  52. package/dist/blend/ThemeAwareBlendUtilities.web.js +6 -1
  53. package/dist/browser/designerpunk.esm.js +22 -81
  54. package/dist/browser/designerpunk.esm.min.js +29 -32
  55. package/dist/browser/designerpunk.umd.js +22 -81
  56. package/dist/browser/designerpunk.umd.min.js +42 -45
  57. package/dist/browser/tokens.css +1 -1
  58. package/dist/components/core/Avatar-Base/platforms/web/Avatar.web.js +24 -5
  59. package/dist/components/core/Button-CTA/examples/BasicUsage.d.ts +16 -28
  60. package/dist/components/core/Button-CTA/examples/BasicUsage.js +18 -43
  61. package/dist/components/core/Button-CTA/platforms/web/ButtonCTA.web.d.ts +3 -15
  62. package/dist/components/core/Button-CTA/platforms/web/ButtonCTA.web.js +9 -58
  63. package/dist/components/core/Button-CTA/types.d.ts +0 -24
  64. package/dist/components/core/Button-CTA/types.js +6 -0
  65. package/dist/components/core/Input-Text-Base/types.d.ts +13 -1
  66. package/dist/components/core/Input-Text-Password/platforms/web/InputTextPassword.web.js +11 -2
  67. package/dist/generators/DTCGFormatGenerator.js +8 -0
  68. package/dist/integration/BuildErrorHandler.js +2 -2
  69. package/dist/ios/DesignTokens.ios.swift +1 -1
  70. package/dist/mcp/application-mcp.js +24 -0
  71. package/dist/mcp/docs-mcp.js +130 -15
  72. package/dist/mcp/product-mcp.js +25 -0
  73. package/dist/tokens/OpacityTokens.js +1 -1
  74. package/dist/tokens/semantic/BlendTokens.d.ts +10 -3
  75. package/dist/tokens/semantic/BlendTokens.js +17 -5
  76. package/dist/tokens/semantic/OpacityTokens.d.ts +4 -4
  77. package/dist/tokens/semantic/OpacityTokens.js +4 -4
  78. package/dist/types/ComponentTypes.d.ts +1 -1
  79. package/dist/types/generated/TokenTypes.d.ts +1 -1
  80. package/dist/types/generated/TokenTypes.js +1 -1
  81. package/dist/validators/StemmaTokenUsageValidator.js +3 -2
  82. package/dist/web/DesignTokens.web.css +1 -1
  83. package/governance/Component-Development-Guide.md +22 -12
  84. package/governance/Component-Development-Standards.md +2 -2
  85. package/governance/Component-Family-Avatar.md +0 -1
  86. package/governance/Component-Family-Badge.md +0 -1
  87. package/governance/Component-Family-Button.md +4 -17
  88. package/governance/Component-Family-Chip.md +0 -1
  89. package/governance/Component-Family-Container.md +0 -1
  90. package/governance/Component-Family-Data-Display.md +1 -2
  91. package/governance/Component-Family-Divider.md +1 -2
  92. package/governance/Component-Family-Form-Inputs.md +5 -5
  93. package/governance/Component-Family-Icon.md +1 -2
  94. package/governance/Component-Family-Loading.md +1 -2
  95. package/governance/Component-Family-Modal.md +1 -2
  96. package/governance/Component-Family-Navigation.md +0 -1
  97. package/governance/Component-Family-Progress.md +0 -1
  98. package/governance/Component-Inheritance-Structures.md +195 -76
  99. package/governance/Component-MCP-Document-Template.md +6 -5
  100. package/governance/Component-Primitive-vs-Semantic-Philosophy.md +1 -1
  101. package/governance/Component-Quick-Reference.md +33 -33
  102. package/governance/Component-Readiness-Status.md +54 -38
  103. package/governance/Component-Templates.md +32 -36
  104. package/governance/Contract-System-Reference.md +6 -6
  105. package/governance/MCP-Integration-Guide.md +1 -1
  106. package/governance/Process-Cross-Reference-Standards.md +31 -13
  107. package/governance/Process-Development-Workflow.md +49 -59
  108. package/governance/Process-File-Organization.md +24 -24
  109. package/governance/Process-Hook-Operations.md +19 -7
  110. package/governance/Process-Orchestration-Model-Selection.md +92 -0
  111. package/governance/Process-Spec-Planning.md +91 -39
  112. package/governance/Process-Task-Type-Definitions.md +80 -4
  113. package/governance/Product-Handoff-Protocol.md +2 -0
  114. package/governance/Rosetta-System-Architecture.md +6 -6
  115. package/governance/Test-Behavioral-Contract-Validation.md +38 -31
  116. package/governance/Test-Failure-Audit-Methodology.md +1 -1
  117. package/governance/Token-Family-Accessibility.md +1 -2
  118. package/governance/Token-Family-Blend.md +18 -16
  119. package/governance/Token-Family-Blur.md +0 -1
  120. package/governance/Token-Family-Border.md +1 -2
  121. package/governance/Token-Family-Color.md +0 -1
  122. package/governance/Token-Family-Glow.md +1 -2
  123. package/governance/Token-Family-Layering.md +0 -1
  124. package/governance/Token-Family-Motion.md +1 -2
  125. package/governance/Token-Family-Opacity.md +0 -1
  126. package/governance/Token-Family-Radius.md +1 -2
  127. package/governance/Token-Family-Responsive.md +1 -2
  128. package/governance/Token-Family-Shadow.md +1 -2
  129. package/governance/Token-Family-Sizing.md +0 -1
  130. package/governance/Token-Family-Spacing.md +1 -2
  131. package/governance/Token-Family-Typography.md +1 -2
  132. package/governance/Token-Governance.md +8 -8
  133. package/governance/Token-Quick-Reference.md +21 -21
  134. package/governance/Token-Resolution-Patterns.md +1 -1
  135. package/governance/Token-Semantic-Structure.md +1 -1
  136. package/governance/Web-Authoring-Standards.md +5 -5
  137. package/governance/browser-distribution-guide.md +1 -4
  138. package/governance/classification-map.md +368 -0
  139. package/governance/completion-documentation-guide.md +11 -8
  140. package/governance/component-meta-authoring-guide.md +1 -1
  141. package/governance/cross-platform-vs-platform-specific-decision-framework.md +1 -1
  142. package/governance/platform-implementation-guidelines.md +1 -1
  143. package/governance/release-management-system.md +2 -2
  144. package/governance/rosetta-system-principles.md +8 -6
  145. package/governance/stemma-system-principles.md +18 -17
  146. package/mcp-server/src/index.ts +24 -6
  147. package/mcp-server/src/indexer/DocumentIndexer.ts +119 -9
  148. package/mcp-server/src/indexer/__tests__/bare-id-crossrefs.test.ts +250 -0
  149. package/mcp-server/src/indexer/cross-ref-parser.ts +29 -1
  150. package/mcp-server/src/indexer/index-health.ts +27 -2
  151. package/mcp-server/src/query/__tests__/find-docs-calibration.test.ts +11 -26
  152. package/mcp-server/src/relocation-integrity-gate/__tests__/relocation-integrity-gate.test.ts +72 -5
  153. package/mcp-server/src/relocation-integrity-gate/relocation-integrity-gate.ts +81 -24
  154. package/mcp-server/src/tools/list-cross-references.ts +2 -2
  155. package/package.json +23 -21
  156. package/src/__tests__/browser-distribution/css-bundling.test.ts +6 -4
  157. package/src/__tests__/console-allowlist.json +14 -0
  158. package/src/__tests__/console-fail-setup.ts +169 -0
  159. package/src/__tests__/integration/Spec107-DesignLanguageContext.test.ts +16 -0
  160. package/src/__tests__/stemma-system/behavioral-contract-validation.test.ts +70 -17
  161. package/src/__tests__/stemma-system/contract-catalog-name-validation.test.ts +28 -0
  162. package/src/__tests__/stemma-system/form-inputs-contracts.test.ts +223 -16
  163. package/src/__tests__/stemma-system/input-text-native-base-call-alignment.test.ts +298 -0
  164. package/src/blend/OklchBlendCalculator.ts +3 -0
  165. package/src/blend/ThemeAwareBlendUtilities.android.kt +3 -0
  166. package/src/blend/ThemeAwareBlendUtilities.ios.swift +3 -0
  167. package/src/blend/ThemeAwareBlendUtilities.web.ts +9 -1
  168. package/src/blend/__tests__/InteractionStateAudit.test.ts +12 -9
  169. package/src/build/errors/__tests__/ErrorHandler.integration.test.ts +8 -0
  170. package/src/build/errors/__tests__/ErrorHandler.test.ts +5 -0
  171. package/src/build/workflow/__tests__/CICDIntegration.test.ts +12 -1
  172. package/src/cli/__tests__/init.test.ts +45 -11
  173. package/src/components/core/Avatar-Base/Avatar-Base.schema.yaml +1 -1
  174. package/src/components/core/Avatar-Base/__tests__/Avatar.accessibility.test.ts +121 -7
  175. package/src/components/core/Avatar-Base/__tests__/Avatar.image.test.ts +3 -0
  176. package/src/components/core/Avatar-Base/__tests__/Avatar.test.ts +15 -6
  177. package/src/components/core/Avatar-Base/contracts.yaml +11 -1
  178. package/src/components/core/Avatar-Base/platforms/web/Avatar.web.ts +24 -5
  179. package/src/components/core/Badge-Count-Base/contracts.yaml +1 -1
  180. package/src/components/core/Badge-Label-Base/contracts.yaml +1 -1
  181. package/src/components/core/Button-CTA/Button-CTA.schema.yaml +2 -12
  182. package/src/components/core/Button-CTA/README.md +3 -6
  183. package/src/components/core/Button-CTA/__tests__/ButtonCTA.test.ts +35 -89
  184. package/src/components/core/Button-CTA/__tests__/setup.test.ts +0 -2
  185. package/src/components/core/Button-CTA/__tests__/test-utils.ts +0 -2
  186. package/src/components/core/Button-CTA/contracts.yaml +6 -29
  187. package/src/components/core/Button-CTA/examples/BasicUsage.html +2 -14
  188. package/src/components/core/Button-CTA/examples/BasicUsage.tsx +17 -44
  189. package/src/components/core/Button-CTA/platforms/android/ButtonCTA.android.kt +12 -20
  190. package/src/components/core/Button-CTA/platforms/ios/ButtonCTA.ios.swift +12 -51
  191. package/src/components/core/Button-CTA/platforms/web/ButtonCTA.web.css +2 -26
  192. package/src/components/core/Button-CTA/platforms/web/ButtonCTA.web.ts +18 -71
  193. package/src/components/core/Button-CTA/types.ts +10 -28
  194. package/src/components/core/Chip-Base/__tests__/ChipBase.test.ts +13 -0
  195. package/src/components/core/Chip-Filter/__tests__/ChipFilter.test.ts +13 -0
  196. package/src/components/core/Chip-Input/__tests__/ChipInput.test.ts +13 -0
  197. package/src/components/core/Input-Text-Base/Input-Text-Base.schema.yaml +30 -2
  198. package/src/components/core/Input-Text-Base/README.md +25 -2
  199. package/src/components/core/Input-Text-Base/__tests__/focusIndicators.test.ts +16 -15
  200. package/src/components/core/Input-Text-Base/contracts.yaml +90 -0
  201. package/src/components/core/Input-Text-Base/platforms/android/InputTextBase.android.kt +26 -12
  202. package/src/components/core/Input-Text-Base/platforms/ios/InputTextBase.ios.swift +195 -59
  203. package/src/components/core/Input-Text-Base/types.ts +13 -1
  204. package/src/components/core/Input-Text-Email/Input-Text-Email.schema.yaml +5 -1
  205. package/src/components/core/Input-Text-Email/README.md +8 -7
  206. package/src/components/core/Input-Text-Email/platforms/android/InputTextEmail.android.kt +1 -4
  207. package/src/components/core/Input-Text-Email/platforms/ios/InputTextEmail.ios.swift +2 -16
  208. package/src/components/core/Input-Text-Password/Input-Text-Password.schema.yaml +10 -3
  209. package/src/components/core/Input-Text-Password/README.md +9 -8
  210. package/src/components/core/Input-Text-Password/contracts.yaml +5 -0
  211. package/src/components/core/Input-Text-Password/platforms/android/InputTextPassword.android.kt +17 -7
  212. package/src/components/core/Input-Text-Password/platforms/ios/InputTextPassword.ios.swift +22 -20
  213. package/src/components/core/Input-Text-Password/platforms/web/InputTextPassword.web.ts +11 -2
  214. package/src/components/core/Input-Text-PhoneNumber/Input-Text-PhoneNumber.schema.yaml +5 -1
  215. package/src/components/core/Input-Text-PhoneNumber/README.md +9 -8
  216. package/src/components/core/Input-Text-PhoneNumber/platforms/android/InputTextPhoneNumber.android.kt +2 -5
  217. package/src/components/core/Input-Text-PhoneNumber/platforms/ios/InputTextPhoneNumber.ios.swift +3 -17
  218. package/src/components/core/Nav-Header-App/contracts.yaml +1 -1
  219. package/src/components/core/Nav-SegmentedChoice-Base/contracts.yaml +1 -1
  220. package/src/components/core/Progress-Indicator-Connector-Base/contracts.yaml +1 -1
  221. package/src/components/core/Progress-Indicator-Label-Base/contracts.yaml +1 -1
  222. package/src/components/core/Progress-Indicator-Node-Base/contracts.yaml +1 -1
  223. package/src/components/core/Progress-Stepper-Base/__tests__/StepperBase.test.ts +5 -2
  224. package/src/components/core/Progress-Stepper-Detailed/__tests__/StepperDetailed.test.ts +5 -2
  225. package/src/generators/DTCGFormatGenerator.ts +6 -0
  226. package/src/generators/__tests__/DTCGConfigOptions.test.ts +14 -5
  227. package/src/integration/BuildErrorHandler.ts +2 -2
  228. package/src/tokens/OpacityTokens.ts +1 -1
  229. package/src/tokens/__tests__/OpacityTokens.test.ts +3 -1
  230. package/src/tokens/semantic/BlendTokens.ts +26 -5
  231. package/src/tokens/semantic/OpacityTokens.ts +4 -4
  232. package/src/tools/release/__tests__/ReleasePipeline.test.ts +1 -1
  233. package/src/types/ComponentTypes.ts +1 -1
  234. package/src/types/generated/TokenTypes.ts +1 -1
  235. package/src/validators/StemmaTokenUsageValidator.ts +3 -2
  236. package/token-index/semantics.yaml +1 -2
@@ -28,9 +28,7 @@
28
28
  * | concept query | must include | expected tier |
29
29
  * |------------------------|----------------------------------------|---------------|
30
30
  * | "RTL" | Web-Authoring-Standards.md | strong |
31
- * | | Component-Family-Form-Inputs.md | strong |
32
31
  * | "internationalization" | Web-Authoring-Standards.md | strong |
33
- * | | Component-Family-Form-Inputs.md | strong |
34
32
  * | "spec planning" | Process-Spec-Planning.md | strong |
35
33
  * | "EARS" | Process-Spec-Planning.md | strong |
36
34
  * | incidental-token case | only incidental match | partial |
@@ -60,7 +58,6 @@ const STEERING_DIR = path.resolve(__dirname, '../../../../governance');
60
58
  * absolute-path prefixes do not make the fixture brittle to CWD differences).
61
59
  */
62
60
  const RTL_DOC_A = 'Web-Authoring-Standards.md';
63
- const RTL_DOC_B = 'Component-Family-Form-Inputs.md';
64
61
  const SPEC_PLANNING_DOC = 'Process-Spec-Planning.md';
65
62
 
66
63
  // ---------------------------------------------------------------------------
@@ -132,7 +129,16 @@ describe('find_docs calibration fixtures — real corpus, tool boundary (Task 4.
132
129
  // Fixture 1 — RTL / right-to-left
133
130
  // -------------------------------------------------------------------------
134
131
 
135
- describe('fixture: "RTL" → Web-Authoring-Standards.md + Component-Family-Form-Inputs.md (strong via aliases)', () => {
132
+ describe('fixture: "RTL" → Web-Authoring-Standards.md (strong via aliases)', () => {
133
+ /**
134
+ * NOTE (119-B Task 4 alias prune, 2026-08-02): Component-Family-Form-Inputs.md
135
+ * previously carried the same RTL alias set as a second calibration fixture
136
+ * (Spec 121 Task 5). Its only RTL content was two passing bullets, so the
137
+ * aliases were replaced with form-inputs-scoped vocabulary (Lina's domain
138
+ * ruling). The RTL/internationalization recall floor is satisfied by
139
+ * Web-Authoring-Standards.md alone, which has real RTL/logical-properties
140
+ * content and keeps its aliases.
141
+ */
136
142
  let result: FindDocsHandlerResult;
137
143
 
138
144
  beforeAll(() => {
@@ -155,26 +161,11 @@ describe('find_docs calibration fixtures — real corpus, tool boundary (Task 4.
155
161
  expect(entry!.matchConfidence).toBe('strong');
156
162
  });
157
163
 
158
- it('includes Component-Family-Form-Inputs.md', () => {
159
- const entry = findEntry(result, RTL_DOC_B);
160
- expect(entry).toBeDefined();
161
- });
162
-
163
- it('classifies Component-Family-Form-Inputs.md as strong (aliases high-signal hit)', () => {
164
- const entry = findEntry(result, RTL_DOC_B);
165
- expect(entry!.matchConfidence).toBe('strong');
166
- });
167
-
168
164
  it('emits three distinct Layer fields on Web-Authoring-Standards.md (criterion b)', () => {
169
165
  const entry = findEntry(result, RTL_DOC_A);
170
166
  assertThreeDistinctLayers(entry!);
171
167
  });
172
168
 
173
- it('emits three distinct Layer fields on Component-Family-Form-Inputs.md (criterion b)', () => {
174
- const entry = findEntry(result, RTL_DOC_B);
175
- assertThreeDistinctLayers(entry!);
176
- });
177
-
178
169
  it('matchedOn for the aliases hit contains "aliases:rtl" (auditable evidence)', () => {
179
170
  const entry = findEntry(result, RTL_DOC_A);
180
171
  // aliases are high-signal; the token "rtl" must appear in matchedOn as an aliases hit
@@ -186,7 +177,7 @@ describe('find_docs calibration fixtures — real corpus, tool boundary (Task 4.
186
177
  // Fixture 2 — internationalization
187
178
  // -------------------------------------------------------------------------
188
179
 
189
- describe('fixture: "internationalization" → same two docs (strong)', () => {
180
+ describe('fixture: "internationalization" → Web-Authoring-Standards.md (strong)', () => {
190
181
  let result: FindDocsHandlerResult;
191
182
 
192
183
  beforeAll(() => {
@@ -199,12 +190,6 @@ describe('find_docs calibration fixtures — real corpus, tool boundary (Task 4.
199
190
  expect(entry!.matchConfidence).toBe('strong');
200
191
  });
201
192
 
202
- it('includes Component-Family-Form-Inputs.md at strong', () => {
203
- const entry = findEntry(result, RTL_DOC_B);
204
- expect(entry).toBeDefined();
205
- expect(entry!.matchConfidence).toBe('strong');
206
- });
207
-
208
193
  it('emits three distinct Layer fields (criterion b)', () => {
209
194
  const entry = findEntry(result, RTL_DOC_A);
210
195
  assertThreeDistinctLayers(entry!);
@@ -19,9 +19,12 @@ import {
19
19
  assertMustFixCouplings,
20
20
  assertScope,
21
21
  runRelocationIntegrityGate,
22
+ scanPromptReferences,
22
23
  LOCKED_IDENTITY_IDS,
23
24
  DEFAULT_PROJECT_ROOT,
25
+ DEFAULT_GOVERNANCE_DIR,
24
26
  } from '../relocation-integrity-gate';
27
+ import { DocumentIndexer } from '../../indexer/DocumentIndexer';
25
28
 
26
29
  describe('classifyReference — identity vs served vs template (Req 8 AC5)', () => {
27
30
  it('classifies a placeholder path-shape as template', () => {
@@ -198,20 +201,84 @@ describe('runRelocationIntegrityGate — full gate (the 119-A exit check, Req 8
198
201
  expect(result.unresolved).toEqual([]);
199
202
  });
200
203
 
201
- it('resolves every served prompt ref via the legacy-fallback (Req 8 AC1–AC3)', async () => {
204
+ it('resolves a served prompt ref via legacy-fallback — fixture prompt (Req 8 AC1–AC3)', async () => {
205
+ // Anti-vacuity moved OFF live data (2026-07-11, Spec 122 U6): the served floor
206
+ // (≥1 served `.kiro/steering/*.md` ref in the REAL agent prompts) died by progress —
207
+ // the 122 cutovers regenerate agent prompts into runtime-neutral MCP-cue form, removing
208
+ // `.kiro/steering/*.md` file references. With Leonardo (U6) cut over, ZERO live prompts
209
+ // carry served refs (same class as the template floor's death at U3). The served-
210
+ // resolution behavior is now exercised NON-VACUOUSLY against a fixture prompt carrying a
211
+ // real relocated-doc ref, resolved through a real indexer (frozen legacy manifest seeded);
212
+ // the live leg below keeps the every-served-ref-resolves invariant without an inventory floor.
213
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'rig-served-'));
214
+ const indexer = new DocumentIndexer();
215
+ await indexer.indexDirectory(DEFAULT_GOVERNANCE_DIR); // seeds the frozen legacy manifest at its tail
216
+ try {
217
+ fs.mkdirSync(path.join(root, '.kiro/agents'), { recursive: true });
218
+ fs.writeFileSync(
219
+ path.join(root, '.kiro/agents', 'fixture-prompt.md'),
220
+ '# Fixture\n\nSee `get_section({ path: ".kiro/steering/Token-Governance.md", heading: "Token Usage Governance" })`.\n',
221
+ );
222
+ const scan = scanPromptReferences(root, indexer);
223
+ const served = scan.references.filter((r) => r.role === 'served');
224
+ expect(served.length).toBeGreaterThanOrEqual(1);
225
+ expect(served.every((r) => r.resolved)).toBe(true);
226
+ expect(served.every((r) => r.strategy === 'legacy-fallback')).toBe(true);
227
+ } finally {
228
+ fs.rmSync(root, { recursive: true, force: true });
229
+ }
230
+ });
231
+
232
+ it('live prompts: every served ref (if any) resolves via legacy-fallback (Req 8 AC1–AC3)', async () => {
202
233
  const result = await runRelocationIntegrityGate();
203
234
  const served = result.references.filter((r) => r.role === 'served');
204
- expect(served.length).toBeGreaterThan(0);
235
+ // NO count floor: the live corpus legitimately holds zero served refs since U6 (the
236
+ // fixture leg above covers non-vacuous resolution). If any served refs exist, each must
237
+ // resolve via legacy-fallback; the resolutionMechanism description holds regardless.
205
238
  expect(served.every((r) => r.resolved)).toBe(true);
206
239
  expect(served.every((r) => r.strategy === 'legacy-fallback')).toBe(true);
207
240
  expect(result.resolutionMechanism).toMatch(/legacy-fallback/);
208
241
  });
209
242
 
210
- it('excludes template placeholders from pass/fail (Req 8 AC1 — not real refs)', async () => {
243
+ it('excludes template placeholders from pass/fail — fixture prompt (Req 8 AC1 — not real refs)', () => {
244
+ // Anti-vacuity moved OFF live data (2026-07-11, Spec 122 U3): the live floor
245
+ // (≥1 template in the real prompts) died by progress — Ada's U2 regeneration dropped
246
+ // `Token-Family-{Name}.md` (3 → 2) and Lina's U3 regeneration removed the corpus's
247
+ // LAST template placeholders (`Component-Family-{Name}.md` / `{FamilyName}`, 2 → 0),
248
+ // exactly as this test's old comment predicted. The exclusion behavior is now
249
+ // exercised non-vacuously via the extracted reference-axis seam on a fixture prompt;
250
+ // the live leg below keeps the invariant without an inventory floor.
251
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'rig-tpl-'));
252
+ try {
253
+ fs.mkdirSync(path.join(root, '.kiro/agents'), { recursive: true });
254
+ fs.writeFileSync(
255
+ path.join(root, '.kiro/agents', 'fixture-prompt.md'),
256
+ '# Fixture\n\nSee `get_document_summary({ path: ".kiro/steering/Component-Family-{Name}.md" })`.\n',
257
+ );
258
+ // A template-only scan must never touch the resolver — throwing stub proves it.
259
+ const neverCalled = {
260
+ resolveRef: (): never => {
261
+ throw new Error('resolveRef must not be called for a template placeholder');
262
+ },
263
+ };
264
+ const scan = scanPromptReferences(root, neverCalled);
265
+ const templates = scan.references.filter((r) => r.role === 'template');
266
+ expect(templates.length).toBe(1);
267
+ expect(templates[0].ref).toBe('.kiro/steering/Component-Family-{Name}.md');
268
+ expect(templates[0].resolved).toBe(false);
269
+ // a template ref must never appear in unresolved — the exclusion under test
270
+ expect(scan.unresolved).toEqual([]);
271
+ } finally {
272
+ fs.rmSync(root, { recursive: true, force: true });
273
+ }
274
+ });
275
+
276
+ it('live prompts: any template placeholder stays excluded from unresolved (Req 8 AC1)', async () => {
211
277
  const result = await runRelocationIntegrityGate();
212
278
  const templates = result.references.filter((r) => r.role === 'template');
213
- expect(templates.length).toBe(3);
214
- // a template ref must never appear in unresolved
279
+ // NO count floor: the live corpus legitimately holds zero placeholders since U3
280
+ // (see the fixture leg above for the non-vacuous exclusion assertion; the classifier
281
+ // routing itself is directly covered by the classifyReference tests).
215
282
  for (const t of templates) {
216
283
  expect(result.unresolved.some((u) => u.includes(t.ref))).toBe(false);
217
284
  }
@@ -269,14 +269,44 @@ export function assertMustFixCouplings(projectRoot: string): CouplingCheck[] {
269
269
  // non-identity .kiro/steering/ doc remains referenced in any agent JSON.
270
270
  {
271
271
  const dir = path.join(projectRoot, '.kiro/agents');
272
- const jsons = fs.readdirSync(dir).filter((f) => f.endsWith('.json')).sort();
272
+ const jsons = fs
273
+ .readdirSync(dir)
274
+ .filter((f) => f.endsWith('.json') && !f.endsWith('.attribution.json'))
275
+ .sort();
276
+
277
+ // Spec 122 cutover-ledger awareness (added at Ada's cutover, U2/PR #55): a GENERATED
278
+ // config carries only its designed ambient members — Ada's trim took the fleet total
279
+ // from 122 to 100 governance/ entries and broke the old flat `govEntries >= 120`
280
+ // floor, and every later cutover would break any fixed total again. The floor's real
281
+ // job is anti-vacuity over the HAND-maintained configs (proof the scan actually saw
282
+ // the remediated entries), so it is now PER-CONFIG (≥5 governance/ entries each; the
283
+ // thinnest hand config today carries 9) over NON-ledger configs only. Generated
284
+ // configs are exempt from the floor — their ref integrity is the generator gate's job
285
+ // (122-sweep-1-refs + 122-canonical-vs-truth) — but they stay IN the stray-relocating
286
+ // scan below: no config, hand or generated, may point a relocating doc at
287
+ // .kiro/steering/. When the ledger covers every seat, the floor leg is vacuously true
288
+ // and this gate's remediation duty is fully handed to the generation-era checks.
289
+ let ledgerAgents = new Set<string>();
290
+ try {
291
+ const ledgerText = fs.readFileSync(path.join(projectRoot, 'canonical/cutover-ledger.yaml'), 'utf-8');
292
+ ledgerAgents = new Set([...ledgerText.matchAll(/^\s*-\s*([a-z0-9-]+)\s*$/gm)].map((m) => m[1]));
293
+ } catch {
294
+ ledgerAgents = new Set(); // pre-122 tree: floor applies to all configs, as before
295
+ }
296
+
273
297
  let govEntries = 0;
298
+ const thinHandConfigs: string[] = [];
274
299
  const strayRelocating = new Set<string>();
275
300
  let strayIdentityLeak = false; // an .kiro/steering/ entry that is NOT an identity doc
276
301
  for (const j of jsons) {
277
302
  const content = fs.readFileSync(path.join(dir, j), 'utf-8');
303
+ const agentName = j.replace(/\.json$/, '');
278
304
  const govRe = /(?:file|skill):\/\/[^"]*governance\/[^"]*\.md/g;
279
- govEntries += (content.match(govRe) || []).length;
305
+ const configGovEntries = (content.match(govRe) || []).length;
306
+ govEntries += configGovEntries;
307
+ if (!ledgerAgents.has(agentName) && configGovEntries < 5) {
308
+ thinHandConfigs.push(`${j} (${configGovEntries})`);
309
+ }
280
310
  const steerRe = /(?:file|skill):\/\/[^"]*\.kiro\/steering\/([^"/]+\.md)/g;
281
311
  let mm: RegExpExecArray | null;
282
312
  while ((mm = steerRe.exec(content)) !== null) {
@@ -287,13 +317,13 @@ export function assertMustFixCouplings(projectRoot: string): CouplingCheck[] {
287
317
  }
288
318
  }
289
319
  }
290
- const ok = govEntries >= 120 && !strayIdentityLeak;
320
+ const ok = thinHandConfigs.length === 0 && !strayIdentityLeak;
291
321
  checks.push({
292
322
  surface: 'agent-definition resources[] (file:// + skill://)',
293
323
  remediated: ok,
294
324
  detail: ok
295
- ? `governance/ entries=${govEntries} (≥120); zero relocating docs left at .kiro/steering/`
296
- : `governance/ entries=${govEntries}; UNREMEDIATED relocating docs still at .kiro/steering/: ${[...strayRelocating].join(', ')}`,
325
+ ? `governance/ entries=${govEntries} (per-hand-config floor ≥5 held; ${ledgerAgents.size} generator-governed config(s) exempt); zero relocating docs left at .kiro/steering/`
326
+ : `governance/ entries=${govEntries}; hand configs under the ≥5 floor: ${thinHandConfigs.join(', ') || 'none'}; UNREMEDIATED relocating docs still at .kiro/steering/: ${[...strayRelocating].join(', ')}`,
297
327
  });
298
328
  }
299
329
 
@@ -511,27 +541,28 @@ export interface GateOptions {
511
541
  indexer?: DocumentIndexer;
512
542
  }
513
543
 
544
+ /** The reference axis's scan output — see {@link scanPromptReferences}. */
545
+ export interface PromptReferenceScan {
546
+ references: ReferenceCheck[];
547
+ unresolved: string[];
548
+ referencedIdentityIds: Set<string>;
549
+ }
550
+
514
551
  /**
515
- * Run the relocation-integrity gate (the 119-A exit check).
516
- *
517
- * Builds a real `DocumentIndexer` over `governance/` (the frozen legacy manifest is
518
- * seeded automatically at the tail of `indexDirectory`), then exercises the live
519
- * `resolveRef` per prompt reference. Identity refs bypass MCP (static presence);
520
- * must-fix couplings + family-guidance + scope are asserted statically.
552
+ * The reference axis (Req 8 AC1–AC5), extracted from the orchestrator as its own
553
+ * exported seam: scan every prompt under `projectRoot`, classify each steering ref
554
+ * (template / identity / served), and resolve served refs through the live indexer.
555
+ * Template placeholders are excluded from pass/fail here — they are recorded but
556
+ * NEVER pushed to `unresolved` — which is the behavior the fixture-based unit test
557
+ * exercises directly (the live corpus carries zero placeholders since the Spec 122
558
+ * U3 regeneration, so full-gate runs can no longer test this leg non-vacuously).
559
+ * Only served refs touch the indexer; a template-only or identity-only scan never
560
+ * calls `resolveRef`.
521
561
  */
522
- export async function runRelocationIntegrityGate(opts: GateOptions = {}): Promise<GateResult> {
523
- const projectRoot = opts.projectRoot ?? DEFAULT_PROJECT_ROOT;
524
- const governanceDir = opts.governanceDir ?? DEFAULT_GOVERNANCE_DIR;
525
-
526
- let indexer = opts.indexer;
527
- if (!indexer) {
528
- indexer = new DocumentIndexer();
529
- // indexDirectory seeds the frozen legacy manifest at its tail (re-seed
530
- // obligation) — so the legacy-fallback resolution mechanism is live here.
531
- await indexer.indexDirectory(governanceDir);
532
- }
533
-
534
- // --- Reference axis (Req 8 AC1–AC5) ---
562
+ export function scanPromptReferences(
563
+ projectRoot: string,
564
+ indexer: Pick<DocumentIndexer, 'resolveRef'>
565
+ ): PromptReferenceScan {
535
566
  const references: ReferenceCheck[] = [];
536
567
  const unresolved: string[] = [];
537
568
  const referencedIdentityIds = new Set<string>();
@@ -583,6 +614,32 @@ export async function runRelocationIntegrityGate(opts: GateOptions = {}): Promis
583
614
  }
584
615
  }
585
616
 
617
+ return { references, unresolved, referencedIdentityIds };
618
+ }
619
+
620
+ /**
621
+ * Run the relocation-integrity gate (the 119-A exit check).
622
+ *
623
+ * Builds a real `DocumentIndexer` over `governance/` (the frozen legacy manifest is
624
+ * seeded automatically at the tail of `indexDirectory`), then exercises the live
625
+ * `resolveRef` per prompt reference. Identity refs bypass MCP (static presence);
626
+ * must-fix couplings + family-guidance + scope are asserted statically.
627
+ */
628
+ export async function runRelocationIntegrityGate(opts: GateOptions = {}): Promise<GateResult> {
629
+ const projectRoot = opts.projectRoot ?? DEFAULT_PROJECT_ROOT;
630
+ const governanceDir = opts.governanceDir ?? DEFAULT_GOVERNANCE_DIR;
631
+
632
+ let indexer = opts.indexer;
633
+ if (!indexer) {
634
+ indexer = new DocumentIndexer();
635
+ // indexDirectory seeds the frozen legacy manifest at its tail (re-seed
636
+ // obligation) — so the legacy-fallback resolution mechanism is live here.
637
+ await indexer.indexDirectory(governanceDir);
638
+ }
639
+
640
+ // --- Reference axis (Req 8 AC1–AC5) ---
641
+ const { references, unresolved, referencedIdentityIds } = scanPromptReferences(projectRoot, indexer);
642
+
586
643
  // --- Identity axis (Req 8 AC5) ---
587
644
  const identity = assertIdentityPresence(projectRoot, referencedIdentityIds);
588
645
  for (const c of identity) {
@@ -16,13 +16,13 @@ import { ErrorHandler, MCPError } from '../utils/error-handler';
16
16
  */
17
17
  export const listCrossReferencesTool = {
18
18
  name: 'list_cross_references',
19
- description: 'List cross-references in a document. Returns all referenced documents with context, source section, and line number.',
19
+ description: 'List cross-references in a document. Returns all referenced documents with context, source section, and line number. Enumerates both `.md`-path links (target = the linked path, verbatim) and bare-id links validated against the doc-id index (target = the doc id); unresolvable bare-id targets are excluded (surfaced via index-health). Addressing contract (D5): the `path` parameter resolves through the same strategy chain as the other document tools — doc id, then indexed relative path, then legacy `.kiro/steering/…` path.',
20
20
  inputSchema: {
21
21
  type: 'object' as const,
22
22
  properties: {
23
23
  path: {
24
24
  type: 'string',
25
- description: 'Document path (e.g., ".kiro/steering/Component Development Guide.md")'
25
+ description: 'Document ref: doc id (e.g., "token-governance"), indexed relative path, or legacy `.kiro/steering/…` path — same resolver chain as get_document_summary'
26
26
  }
27
27
  },
28
28
  required: ['path'] as string[]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3fn/core",
3
- "version": "13.0.0",
3
+ "version": "14.0.0",
4
4
  "description": "True Native cross-platform design system with mathematical foundations",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Peter Michaels Allen",
@@ -42,42 +42,42 @@
42
42
  ],
43
43
  "exports": {
44
44
  ".": {
45
- "import": "./dist/browser/designerpunk.esm.js",
46
- "types": "./dist/browser-entry.d.ts"
45
+ "types": "./dist/browser-entry.d.ts",
46
+ "import": "./dist/browser/designerpunk.esm.js"
47
47
  },
48
48
  "./components": {
49
- "import": "./dist/browser/designerpunk.esm.js",
50
- "types": "./dist/browser-entry.d.ts"
49
+ "types": "./dist/browser-entry.d.ts",
50
+ "import": "./dist/browser/designerpunk.esm.js"
51
51
  },
52
52
  "./tokens.css": "./dist/DesignTokens.web.css",
53
53
  "./component-tokens.css": "./dist/ComponentTokens.web.css",
54
54
  "./config": {
55
+ "types": "./dist/config/index.d.ts",
55
56
  "import": "./dist/config/index.js",
56
- "require": "./dist/config/index.js",
57
- "types": "./dist/config/index.d.ts"
57
+ "require": "./dist/config/index.js"
58
58
  },
59
59
  "./types": {
60
+ "types": "./dist/types/index.d.ts",
60
61
  "import": "./dist/types/index.js",
61
- "require": "./dist/types/index.js",
62
- "types": "./dist/types/index.d.ts"
62
+ "require": "./dist/types/index.js"
63
63
  },
64
64
  "./build": {
65
+ "types": "./dist/build/tokens/index.d.ts",
65
66
  "import": "./dist/build/tokens/index.js",
66
- "require": "./dist/build/tokens/index.js",
67
- "types": "./dist/build/tokens/index.d.ts"
67
+ "require": "./dist/build/tokens/index.js"
68
68
  },
69
69
  "./blend": {
70
+ "types": "./dist/blend/index.d.ts",
70
71
  "import": "./dist/blend/index.js",
71
- "require": "./dist/blend/index.js",
72
- "types": "./dist/blend/index.d.ts"
72
+ "require": "./dist/blend/index.js"
73
73
  },
74
74
  "./jest-preset": {
75
75
  "require": "./dist/testing/jest-preset.js"
76
76
  },
77
77
  "./testing": {
78
+ "types": "./dist/testing/index.d.ts",
78
79
  "import": "./dist/testing/index.js",
79
- "require": "./dist/testing/index.js",
80
- "types": "./dist/testing/index.d.ts"
80
+ "require": "./dist/testing/index.js"
81
81
  },
82
82
  "./grid.css": "./src/styles/responsive-grid.css",
83
83
  "./fonts/inter.css": "./src/assets/fonts/inter/inter.css",
@@ -106,15 +106,15 @@
106
106
  "build:verify": "node verify-build.js",
107
107
  "build:validate": "npx tsx src/validators/buildValidation.ts",
108
108
  "lint": "eslint 'src/components/**/*.ts' 'src/components/**/*.tsx' --no-error-on-unmatched-pattern",
109
- "test": "jest --testPathIgnorePatterns='performance/__tests__|__tests__/performance|PerformanceValidation'",
109
+ "test": "jest --config jest.functional.config.js",
110
110
  "test:all": "jest",
111
+ "test:agent-generator": "jest --config tools/agent-generator/jest.config.js",
111
112
  "test:consumer": "jest --roots='<rootDir>/tests' --testMatch='**/consumer-integration.test.ts' --runInBand --testTimeout=120000 --forceExit",
112
113
  "test:resolution-matrix": "node src/config/__resolution-matrix__/run-matrix.js",
113
114
  "test:performance": "jest --testPathPatterns='performance/__tests__|__tests__/performance'",
114
115
  "test:performance:isolated": "jest --config jest.performance.config.js --runInBand",
115
- "test:quick": "jest --testPathIgnorePatterns='(performance|integration)'",
116
- "test:watch": "jest --watch --testPathIgnorePatterns='performance/__tests__|__tests__/performance'",
117
- "test:coverage": "jest --coverage --testPathIgnorePatterns='performance/__tests__|__tests__/performance'",
116
+ "test:watch": "jest --watch --config jest.functional.config.js",
117
+ "test:coverage": "jest --coverage --config jest.functional.config.js",
118
118
  "release:analyze": "npx tsx src/tools/release/cli/release-tool.ts analyze",
119
119
  "release:notes": "npx tsx src/tools/release/cli/release-tool.ts notes",
120
120
  "release:run": "npx tsx src/tools/release/cli/release-tool.ts release",
@@ -122,6 +122,7 @@
122
122
  "diagnose:release-issues": "node scripts/diagnose-release-issues.js",
123
123
  "audit:tokens": "node scripts/audit-component-tokens.js",
124
124
  "audit:tokens:detailed": "node scripts/audit-component-tokens.js -- --detailed",
125
+ "audit:coverage-map": "npx tsx tools/agent-generator/coverage-map.ts",
125
126
  "audit:mode-parity": "npx tsx src/validators/ModeParity.ts",
126
127
  "audit:theme-drift": "npx tsx src/tools/ThemeFileGenerator.ts > /tmp/theme-skeleton-check.ts && diff -u src/tokens/themes/dark/SemanticOverrides.ts /tmp/theme-skeleton-check.ts || echo '⚠️ Theme file drift detected — regenerate with: npm run generate:theme-skeleton'",
127
128
  "generate:theme-skeleton": "npx tsx src/tools/ThemeFileGenerator.ts",
@@ -133,8 +134,9 @@
133
134
  "check:drift": "node scripts/check-package-name-drift.js",
134
135
  "check:id-uniqueness": "tsx scripts/check-id-uniqueness.ts",
135
136
  "prepack": "npm run build",
136
- "prepublishOnly": "npm run build && npm run check:drift",
137
- "postpublish": "git diff --quiet token-index/ || (git add token-index/ && git commit -m 'Regenerate token-index (post-publish)' && git push origin main)"
137
+ "verify:token-index-clean": "git diff --quiet token-index/ || (echo '✖ token-index/ is stale relative to the committed state. Regenerate and commit it on the RELEASE BRANCH (it traverses the PR gate with the version bump) before publishing. See .kiro/hooks/RELEASE-FLOW.md.' && exit 1)",
138
+ "prepublishOnly": "npm run build && npm run check:drift && npm run verify:token-index-clean",
139
+ "postpublish": "git diff --quiet token-index/ || echo '⚠️ token-index/ changed during publish — commit it via a PR (main is branch-protected; never push it directly). See .kiro/hooks/RELEASE-FLOW.md.'"
138
140
  },
139
141
  "devDependencies": {
140
142
  "@types/glob": "^8.1.0",
@@ -183,11 +183,13 @@ describe('CSS Bundling for Browser Distribution', () => {
183
183
  expect(bundleContent).toMatch(/:hover/);
184
184
  });
185
185
 
186
- it('should contain disabled state styles', () => {
186
+ it('should not contain disabled state styles (no-disabled-states philosophy)', () => {
187
187
  const bundleContent = fs.readFileSync(ESM_BUNDLE_PATH, 'utf-8');
188
-
189
- // Components should have disabled styles
190
- expect(bundleContent).toMatch(/:disabled|--disabled/);
188
+
189
+ // DesignerPunk does not support disabled states: if an action is
190
+ // unavailable, the component should not be rendered. No component CSS
191
+ // should ship disabled selectors or modifier classes.
192
+ expect(bundleContent).not.toMatch(/:disabled|--disabled/);
191
193
  });
192
194
  });
193
195
 
@@ -0,0 +1,14 @@
1
+ [
2
+ { "suite": "src/components/core/Avatar-Base/__tests__/Avatar.accessibility.test.ts", "pattern": "^AvatarBaseElement: \"alt\" is required when \"src\" is provided\\.", "reason": "Spec 126 (O2, ratified 2026-07-09) resolved the original Req 5.4 / Req 9.2 tension this entry was seeded against: the warn condition is now `type === 'human' && src && alt == null && !decorative`, so a genuinely decorative or empty-alt (via setAttribute) fixture no longer warns at all. This entry is retained as a safety net, not a live suppression path — every fixture in this suite that legitimately triggers the warn (human + src + absent alt, incl. the property-form alt='' collapse) wraps it in a local jest.spyOn(console,'warn').mockImplementation(() => {}), which per console-fail-setup.ts's documented shadow behavior fully swallows the output before this hook ever sees it. Pattern updated to match the new Spec 126 message string (was: '\"alt\" prop is required when \"src\" is provided')." },
3
+ { "suite": "src/components/core/Chip-Base/__tests__/ChipBase.test.ts", "pattern": "^ChipBase: Could not calculate blend colors", "reason": "jsdom stylesheet limitation: jsdom never applies real CSS, so the blend-color token lookup cannot succeed and the component's designed CSS-fallback warn fires every run (fired async via rAF). PR #39 adjudicated as environmental noise, not a defect. Component-prefixed pattern (Lina review, PR #39) — a bare 'Could not calculate blend colors' substring is shared by Button components too; prefix-matching prevents accidentally swallowing a cross-component warn. Discharges the pending jsdom-stylesheet-limitation doc-addition (125-B-backlog.md item 5; Thurgood chip, 2026-07-09)." },
4
+ { "suite": "src/components/core/Chip-Filter/__tests__/ChipFilter.test.ts", "pattern": "^ChipFilter: Could not calculate blend colors", "reason": "jsdom stylesheet limitation: jsdom never applies real CSS, so the blend-color token lookup cannot succeed and the component's designed CSS-fallback warn fires every run (fired async via rAF). PR #39 adjudicated as environmental noise, not a defect. Component-prefixed pattern (Lina review, PR #39) — a bare 'Could not calculate blend colors' substring is shared by Button components too; prefix-matching prevents accidentally swallowing a cross-component warn. Discharges the pending jsdom-stylesheet-limitation doc-addition (125-B-backlog.md item 5; Thurgood chip, 2026-07-09)." },
5
+ { "suite": "src/components/core/Chip-Input/__tests__/ChipInput.test.ts", "pattern": "^ChipInput: Could not calculate blend colors", "reason": "jsdom stylesheet limitation: jsdom never applies real CSS, so the blend-color token lookup cannot succeed and the component's designed CSS-fallback warn fires every run (fired async via rAF). PR #39 adjudicated as environmental noise, not a defect. Component-prefixed pattern (Lina review, PR #39) — a bare 'Could not calculate blend colors' substring is shared by Button components too; prefix-matching prevents accidentally swallowing a cross-component warn. Discharges the pending jsdom-stylesheet-limitation doc-addition (125-B-backlog.md item 5; Thurgood chip, 2026-07-09)." },
6
+ { "suite": "src/build/errors/__tests__/ErrorHandler.test.ts", "pattern": "^\\[(ERROR|WARNING|INFO)\\]|^Suggestions:|^ {2}\\u2022 |^ {2}\\.\\.\\. and \\d+ more", "reason": "Deliberate error-path logging: this suite constructs BuildErrors with fake TEST_ERROR/CONFIG_ERROR/BUILD_ERROR codes specifically to assert ErrorHandler's own console-emitting default logger (ErrorHandler.ts defaultLogger/formatErrorMessage) — the console output IS the behavior under test. PR #39 adjudicated as expected noise (96 error blocks silenced fleet-wide, this suite's share among them)." },
7
+ { "suite": "src/build/errors/__tests__/ErrorHandler.integration.test.ts", "pattern": "^\\[(ERROR|WARNING|INFO)\\]|^Suggestions:|^ {2}\\u2022 |^ {2}\\.\\.\\. and \\d+ more", "reason": "Deliberate error-path logging: this suite exercises ErrorHandler/ErrorReporter integration with fake BUILD_ERROR/CONFIG_ERROR codes — the console output IS the behavior under test. PR #39 adjudicated as expected noise." },
8
+ { "suite": "product-mcp-server/src/__tests__/GapDetector.test.ts", "pattern": "^\\[mcp-product-server\\] Component directory not found: .* \\u2014 gap detection disabled$", "reason": "Deliberate error-path logging: the 'with missing component directory' tests intentionally point GapDetector at a nonexistent path to assert its disabled-gracefully behavior — the console.error IS the assertion target for the first test and expected repeat noise for the others in the same describe block. PR #39 adjudicated as expected." },
9
+ { "suite": "product-mcp-server/src/__tests__/ProductIndexerWalk.test.ts", "pattern": "^\\[mcp-product-server\\] Indexed: \\d+ screens, \\d+ domain objects, \\d+ templates, \\d+ one-off components$", "reason": "ProductIndexer.index() logs an informational indexing summary via console.error (not a failure signal) on every index() call. PR #39 adjudicated as expected per-run noise, silenced via a beforeAll spy in this suite." },
10
+ { "suite": "product-mcp-server/src/__tests__/Spec108-ProductTokens.test.ts", "pattern": "^\\[mcp-product-server\\] Indexed: \\d+ screens, \\d+ domain objects, \\d+ templates, \\d+ one-off components$", "reason": "ProductIndexer.index() logs an informational indexing summary via console.error (not a failure signal) on every index() call. PR #39 adjudicated as expected per-run noise, silenced via a beforeAll spy in this suite." },
11
+ { "suite": "src/__tests__/integration/Spec107-DesignLanguageContext.test.ts", "pattern": "^\\[mcp-product-server\\] Indexed: \\d+ screens, \\d+ domain objects, \\d+ templates, \\d+ one-off components$", "reason": "ProductIndexer.index() logs an informational indexing summary via console.error (not a failure signal); this suite's ProductIndexer instances are constructed inside nested beforeAll hooks, so PR #39 installed the spy in an outer beforeAll (not beforeEach) to be active before them. Adjudicated as expected noise." },
12
+ { "suite": "src/cli/__tests__/figma-extract.test.ts", "pattern": "^\\u274c |^Usage: npm run figma:extract|^\\s+npm run figma:extract|^\\s+Run the DTCG generator first|^$", "reason": "Genuinely novel class, adjudicated in this task (125-B Task 4.4, not part of PR #39): figma-extract is a CLI tool whose console.error output IS its product surface — every message this suite asserts on is the deliberate, deterministic error/usage text figma-extract.ts emits (arg validation, DTCG-load failures, extraction failures, usage banners, blank-line separators). This suite installs its own module-top-level console.error spy (mockConsoleError, restored per-file, not per-test) and reads its .mock.calls directly; this hook's beforeEach captures the CURRENT console.error before spying and calls through to it, so the suite's own assertions keep working unaffected." },
13
+ { "suite": "src/cli/__tests__/figma-push.test.ts", "pattern": "^\\u274c |^Resolution:|^\\s+\\d+\\.\\s|^\\s+-\\s|^\\s+Run the DTCG generator first|^$", "reason": "Genuinely novel class, adjudicated in this task (125-B Task 4.4, not part of PR #39): figma-push is a CLI tool whose console.error output IS its product surface — every message this suite asserts on is the deliberate, deterministic error/resolution text figma-push.ts emits (arg validation, DTCG-load failures, drift/sync-failure reporting with its numbered resolution steps and ' - <detail>' lists, blank-line separators). Same module-top-level console.error spy pattern as figma-extract.test.ts; this hook chains through to it rather than shadowing it." }
14
+ ]