@lumenflow/packs-software-delivery 4.24.0 → 5.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 (286) hide show
  1. package/dist/manifest-schema.d.ts +12 -0
  2. package/dist/manifest-schema.d.ts.map +1 -1
  3. package/dist/manifest-schema.js +10 -0
  4. package/dist/manifest-schema.js.map +1 -1
  5. package/dist/manifest.d.ts +21 -0
  6. package/dist/manifest.d.ts.map +1 -1
  7. package/dist/manifest.js +92 -1
  8. package/dist/manifest.js.map +1 -1
  9. package/dist/src/commands/index.d.ts +2 -0
  10. package/dist/src/commands/index.d.ts.map +1 -0
  11. package/dist/src/commands/index.js +5 -0
  12. package/dist/src/commands/index.js.map +1 -0
  13. package/dist/src/config/delivery-review-contract.d.ts +17 -0
  14. package/dist/src/config/delivery-review-contract.d.ts.map +1 -0
  15. package/dist/src/config/delivery-review-contract.js +19 -0
  16. package/dist/src/config/delivery-review-contract.js.map +1 -0
  17. package/dist/src/config/env-accessors.d.ts +16 -0
  18. package/dist/src/config/env-accessors.d.ts.map +1 -0
  19. package/dist/src/config/env-accessors.js +18 -0
  20. package/dist/src/config/env-accessors.js.map +1 -0
  21. package/dist/src/config/index.d.ts +3 -0
  22. package/dist/src/config/index.d.ts.map +1 -0
  23. package/dist/src/config/index.js +8 -0
  24. package/dist/src/config/index.js.map +1 -0
  25. package/dist/src/config/normalize-config-keys.d.ts +16 -0
  26. package/dist/src/config/normalize-config-keys.d.ts.map +1 -0
  27. package/dist/src/config/normalize-config-keys.js +18 -0
  28. package/dist/src/config/normalize-config-keys.js.map +1 -0
  29. package/dist/src/config/schemas/lumenflow-config-schema-types.d.ts +190 -0
  30. package/dist/src/config/schemas/lumenflow-config-schema-types.d.ts.map +1 -0
  31. package/dist/src/config/schemas/lumenflow-config-schema-types.js +182 -0
  32. package/dist/src/config/schemas/lumenflow-config-schema-types.js.map +1 -0
  33. package/dist/src/config/schemas/lumenflow-config-schema.d.ts +190 -0
  34. package/dist/src/config/schemas/lumenflow-config-schema.d.ts.map +1 -0
  35. package/dist/src/config/schemas/lumenflow-config-schema.js +182 -0
  36. package/dist/src/config/schemas/lumenflow-config-schema.js.map +1 -0
  37. package/dist/src/config/workspace-reader.d.ts +56 -0
  38. package/dist/src/config/workspace-reader.d.ts.map +1 -0
  39. package/dist/src/config/workspace-reader.js +209 -0
  40. package/dist/src/config/workspace-reader.js.map +1 -0
  41. package/dist/src/constants/backlog-patterns.d.ts +21 -0
  42. package/dist/src/constants/backlog-patterns.d.ts.map +1 -0
  43. package/dist/src/constants/backlog-patterns.js +26 -0
  44. package/dist/src/constants/backlog-patterns.js.map +1 -0
  45. package/dist/src/constants/client-ids.d.ts +16 -0
  46. package/dist/src/constants/client-ids.d.ts.map +1 -0
  47. package/dist/src/constants/client-ids.js +16 -0
  48. package/dist/src/constants/client-ids.js.map +1 -0
  49. package/dist/src/constants/config-contract.d.ts +2 -0
  50. package/dist/src/constants/config-contract.d.ts.map +1 -0
  51. package/dist/src/constants/config-contract.js +7 -0
  52. package/dist/src/constants/config-contract.js.map +1 -0
  53. package/dist/src/constants/docs-layout-presets.d.ts +31 -0
  54. package/dist/src/constants/docs-layout-presets.d.ts.map +1 -0
  55. package/dist/src/constants/docs-layout-presets.js +41 -0
  56. package/dist/src/constants/docs-layout-presets.js.map +1 -0
  57. package/dist/src/constants/duration-constants.d.ts +11 -0
  58. package/dist/src/constants/duration-constants.d.ts.map +1 -0
  59. package/dist/src/constants/duration-constants.js +13 -0
  60. package/dist/src/constants/duration-constants.js.map +1 -0
  61. package/dist/src/constants/gate-constants.d.ts +24 -0
  62. package/dist/src/constants/gate-constants.d.ts.map +1 -0
  63. package/dist/src/constants/gate-constants.js +26 -0
  64. package/dist/src/constants/gate-constants.js.map +1 -0
  65. package/dist/src/constants/index.d.ts +18 -0
  66. package/dist/src/constants/index.d.ts.map +1 -0
  67. package/dist/src/constants/index.js +29 -0
  68. package/dist/src/constants/index.js.map +1 -0
  69. package/dist/src/constants/lock-constants.d.ts +29 -0
  70. package/dist/src/constants/lock-constants.d.ts.map +1 -0
  71. package/dist/src/constants/lock-constants.js +31 -0
  72. package/dist/src/constants/lock-constants.js.map +1 -0
  73. package/dist/src/constants/object-guards.d.ts +9 -0
  74. package/dist/src/constants/object-guards.d.ts.map +1 -0
  75. package/dist/src/constants/object-guards.js +11 -0
  76. package/dist/src/constants/object-guards.js.map +1 -0
  77. package/dist/src/constants/section-headings.d.ts +35 -0
  78. package/dist/src/constants/section-headings.d.ts.map +1 -0
  79. package/dist/src/constants/section-headings.js +82 -0
  80. package/dist/src/constants/section-headings.js.map +1 -0
  81. package/dist/src/constants/wu-cli-constants.d.ts +434 -0
  82. package/dist/src/constants/wu-cli-constants.d.ts.map +1 -0
  83. package/dist/src/constants/wu-cli-constants.js +439 -0
  84. package/dist/src/constants/wu-cli-constants.js.map +1 -0
  85. package/dist/src/constants/wu-domain-constants.d.ts +296 -0
  86. package/dist/src/constants/wu-domain-constants.d.ts.map +1 -0
  87. package/dist/src/constants/wu-domain-constants.js +400 -0
  88. package/dist/src/constants/wu-domain-constants.js.map +1 -0
  89. package/dist/src/constants/wu-git-constants.d.ts +2 -0
  90. package/dist/src/constants/wu-git-constants.d.ts.map +1 -0
  91. package/dist/src/constants/wu-git-constants.js +7 -0
  92. package/dist/src/constants/wu-git-constants.js.map +1 -0
  93. package/dist/src/constants/wu-id-format.d.ts +138 -0
  94. package/dist/src/constants/wu-id-format.d.ts.map +1 -0
  95. package/dist/src/constants/wu-id-format.js +265 -0
  96. package/dist/src/constants/wu-id-format.js.map +1 -0
  97. package/dist/src/constants/wu-paths-constants.d.ts +254 -0
  98. package/dist/src/constants/wu-paths-constants.d.ts.map +1 -0
  99. package/dist/src/constants/wu-paths-constants.js +276 -0
  100. package/dist/src/constants/wu-paths-constants.js.map +1 -0
  101. package/dist/src/constants/wu-statuses.d.ts +209 -0
  102. package/dist/src/constants/wu-statuses.d.ts.map +1 -0
  103. package/dist/src/constants/wu-statuses.js +245 -0
  104. package/dist/src/constants/wu-statuses.js.map +1 -0
  105. package/dist/src/constants/wu-type-helpers.d.ts +28 -0
  106. package/dist/src/constants/wu-type-helpers.d.ts.map +1 -0
  107. package/dist/src/constants/wu-type-helpers.js +49 -0
  108. package/dist/src/constants/wu-type-helpers.js.map +1 -0
  109. package/dist/src/constants/wu-ui-constants.d.ts +236 -0
  110. package/dist/src/constants/wu-ui-constants.d.ts.map +1 -0
  111. package/dist/src/constants/wu-ui-constants.js +238 -0
  112. package/dist/src/constants/wu-ui-constants.js.map +1 -0
  113. package/dist/src/constants/wu-validation-constants.d.ts +61 -0
  114. package/dist/src/constants/wu-validation-constants.d.ts.map +1 -0
  115. package/dist/src/constants/wu-validation-constants.js +69 -0
  116. package/dist/src/constants/wu-validation-constants.js.map +1 -0
  117. package/dist/src/domain/index.d.ts +4 -0
  118. package/dist/src/domain/index.d.ts.map +1 -0
  119. package/dist/src/domain/index.js +6 -0
  120. package/dist/src/domain/index.js.map +1 -0
  121. package/dist/src/domain/orchestration.constants.d.ts +111 -0
  122. package/dist/src/domain/orchestration.constants.d.ts.map +1 -0
  123. package/dist/src/domain/orchestration.constants.js +130 -0
  124. package/dist/src/domain/orchestration.constants.js.map +1 -0
  125. package/dist/src/domain/orchestration.schemas.d.ts +307 -0
  126. package/dist/src/domain/orchestration.schemas.d.ts.map +1 -0
  127. package/dist/src/domain/orchestration.schemas.js +214 -0
  128. package/dist/src/domain/orchestration.schemas.js.map +1 -0
  129. package/dist/src/domain/orchestration.types.d.ts +134 -0
  130. package/dist/src/domain/orchestration.types.d.ts.map +1 -0
  131. package/dist/src/domain/orchestration.types.js +5 -0
  132. package/dist/src/domain/orchestration.types.js.map +1 -0
  133. package/dist/src/methodology/incremental-test.d.ts +33 -0
  134. package/dist/src/methodology/incremental-test.d.ts.map +1 -0
  135. package/dist/src/methodology/incremental-test.js +73 -0
  136. package/dist/src/methodology/incremental-test.js.map +1 -0
  137. package/dist/src/methodology/index.d.ts +3 -0
  138. package/dist/src/methodology/index.d.ts.map +1 -0
  139. package/dist/src/methodology/index.js +6 -0
  140. package/dist/src/methodology/index.js.map +1 -0
  141. package/dist/src/methodology/manual-test-validator.d.ts +97 -0
  142. package/dist/src/methodology/manual-test-validator.d.ts.map +1 -0
  143. package/dist/src/methodology/manual-test-validator.js +248 -0
  144. package/dist/src/methodology/manual-test-validator.js.map +1 -0
  145. package/dist/src/policy/coverage-gate.d.ts +127 -0
  146. package/dist/src/policy/coverage-gate.d.ts.map +1 -0
  147. package/dist/src/policy/coverage-gate.js +211 -0
  148. package/dist/src/policy/coverage-gate.js.map +1 -0
  149. package/dist/src/policy/gates-agent-mode.d.ts +107 -0
  150. package/dist/src/policy/gates-agent-mode.d.ts.map +1 -0
  151. package/dist/src/policy/gates-agent-mode.js +138 -0
  152. package/dist/src/policy/gates-agent-mode.js.map +1 -0
  153. package/dist/src/policy/gates-config-internal.d.ts +54 -0
  154. package/dist/src/policy/gates-config-internal.d.ts.map +1 -0
  155. package/dist/src/policy/gates-config-internal.js +108 -0
  156. package/dist/src/policy/gates-config-internal.js.map +1 -0
  157. package/dist/src/policy/gates-config.d.ts +67 -0
  158. package/dist/src/policy/gates-config.d.ts.map +1 -0
  159. package/dist/src/policy/gates-config.js +193 -0
  160. package/dist/src/policy/gates-config.js.map +1 -0
  161. package/dist/src/policy/gates-coverage.d.ts +48 -0
  162. package/dist/src/policy/gates-coverage.d.ts.map +1 -0
  163. package/dist/src/policy/gates-coverage.js +182 -0
  164. package/dist/src/policy/gates-coverage.js.map +1 -0
  165. package/dist/src/policy/gates-presets.d.ts +51 -0
  166. package/dist/src/policy/gates-presets.d.ts.map +1 -0
  167. package/dist/src/policy/gates-presets.js +117 -0
  168. package/dist/src/policy/gates-presets.js.map +1 -0
  169. package/dist/src/policy/gates-schemas.d.ts +142 -0
  170. package/dist/src/policy/gates-schemas.d.ts.map +1 -0
  171. package/dist/src/policy/gates-schemas.js +67 -0
  172. package/dist/src/policy/gates-schemas.js.map +1 -0
  173. package/dist/src/policy/index.d.ts +19 -0
  174. package/dist/src/policy/index.d.ts.map +1 -0
  175. package/dist/src/policy/index.js +21 -0
  176. package/dist/src/policy/index.js.map +1 -0
  177. package/dist/src/policy/package-manager-resolver.d.ts +79 -0
  178. package/dist/src/policy/package-manager-resolver.d.ts.map +1 -0
  179. package/dist/src/policy/package-manager-resolver.js +245 -0
  180. package/dist/src/policy/package-manager-resolver.js.map +1 -0
  181. package/dist/src/policy/resolve-policy.d.ts +337 -0
  182. package/dist/src/policy/resolve-policy.d.ts.map +1 -0
  183. package/dist/src/policy/resolve-policy.js +353 -0
  184. package/dist/src/policy/resolve-policy.js.map +1 -0
  185. package/dist/src/ports/config.ports.d.ts +83 -0
  186. package/dist/src/ports/config.ports.d.ts.map +1 -0
  187. package/dist/src/ports/config.ports.js +4 -0
  188. package/dist/src/ports/config.ports.js.map +1 -0
  189. package/dist/src/ports/dashboard-renderer.port.d.ts +113 -0
  190. package/dist/src/ports/dashboard-renderer.port.d.ts.map +1 -0
  191. package/dist/src/ports/dashboard-renderer.port.js +4 -0
  192. package/dist/src/ports/dashboard-renderer.port.js.map +1 -0
  193. package/dist/src/ports/index.d.ts +5 -0
  194. package/dist/src/ports/index.d.ts.map +1 -0
  195. package/dist/src/ports/index.js +10 -0
  196. package/dist/src/ports/index.js.map +1 -0
  197. package/dist/src/ports/sync-validator.ports.d.ts +52 -0
  198. package/dist/src/ports/sync-validator.ports.d.ts.map +1 -0
  199. package/dist/src/ports/sync-validator.ports.js +4 -0
  200. package/dist/src/ports/sync-validator.ports.js.map +1 -0
  201. package/dist/src/ports/wu-helpers.ports.d.ts +157 -0
  202. package/dist/src/ports/wu-helpers.ports.d.ts.map +1 -0
  203. package/dist/src/ports/wu-helpers.ports.js +4 -0
  204. package/dist/src/ports/wu-helpers.ports.js.map +1 -0
  205. package/dist/src/ports/wu-state.ports.d.ts +209 -0
  206. package/dist/src/ports/wu-state.ports.d.ts.map +1 -0
  207. package/dist/src/ports/wu-state.ports.js +4 -0
  208. package/dist/src/ports/wu-state.ports.js.map +1 -0
  209. package/dist/src/primitives/index.d.ts +2 -0
  210. package/dist/src/primitives/index.d.ts.map +1 -0
  211. package/dist/src/primitives/index.js +5 -0
  212. package/dist/src/primitives/index.js.map +1 -0
  213. package/dist/src/runtime/index.d.ts +2 -0
  214. package/dist/src/runtime/index.d.ts.map +1 -0
  215. package/dist/src/runtime/index.js +6 -0
  216. package/dist/src/runtime/index.js.map +1 -0
  217. package/dist/src/runtime/work-classifier.d.ts +103 -0
  218. package/dist/src/runtime/work-classifier.d.ts.map +1 -0
  219. package/dist/src/runtime/work-classifier.js +427 -0
  220. package/dist/src/runtime/work-classifier.js.map +1 -0
  221. package/dist/src/sandbox/index.d.ts +6 -0
  222. package/dist/src/sandbox/index.d.ts.map +1 -0
  223. package/dist/src/sandbox/index.js +10 -0
  224. package/dist/src/sandbox/index.js.map +1 -0
  225. package/dist/src/sandbox/sandbox-allowlist.d.ts +16 -0
  226. package/dist/src/sandbox/sandbox-allowlist.d.ts.map +1 -0
  227. package/dist/src/sandbox/sandbox-allowlist.js +77 -0
  228. package/dist/src/sandbox/sandbox-allowlist.js.map +1 -0
  229. package/dist/src/sandbox/sandbox-backend-linux.d.ts +6 -0
  230. package/dist/src/sandbox/sandbox-backend-linux.d.ts.map +1 -0
  231. package/dist/src/sandbox/sandbox-backend-linux.js +67 -0
  232. package/dist/src/sandbox/sandbox-backend-linux.js.map +1 -0
  233. package/dist/src/sandbox/sandbox-backend-macos.d.ts +6 -0
  234. package/dist/src/sandbox/sandbox-backend-macos.d.ts.map +1 -0
  235. package/dist/src/sandbox/sandbox-backend-macos.js +112 -0
  236. package/dist/src/sandbox/sandbox-backend-macos.js.map +1 -0
  237. package/dist/src/sandbox/sandbox-backend-windows.d.ts +6 -0
  238. package/dist/src/sandbox/sandbox-backend-windows.d.ts.map +1 -0
  239. package/dist/src/sandbox/sandbox-backend-windows.js +30 -0
  240. package/dist/src/sandbox/sandbox-backend-windows.js.map +1 -0
  241. package/dist/src/sandbox/sandbox-profile.d.ts +58 -0
  242. package/dist/src/sandbox/sandbox-profile.d.ts.map +1 -0
  243. package/dist/src/sandbox/sandbox-profile.js +69 -0
  244. package/dist/src/sandbox/sandbox-profile.js.map +1 -0
  245. package/dist/src/schemas/index.d.ts +2 -0
  246. package/dist/src/schemas/index.d.ts.map +1 -0
  247. package/dist/src/schemas/index.js +5 -0
  248. package/dist/src/schemas/index.js.map +1 -0
  249. package/dist/src/state/date-utils.d.ts +66 -0
  250. package/dist/src/state/date-utils.d.ts.map +1 -0
  251. package/dist/src/state/date-utils.js +143 -0
  252. package/dist/src/state/date-utils.js.map +1 -0
  253. package/dist/src/state/index.d.ts +8 -0
  254. package/dist/src/state/index.d.ts.map +1 -0
  255. package/dist/src/state/index.js +15 -0
  256. package/dist/src/state/index.js.map +1 -0
  257. package/dist/src/state/state-machine.d.ts +14 -0
  258. package/dist/src/state/state-machine.d.ts.map +1 -0
  259. package/dist/src/state/state-machine.js +92 -0
  260. package/dist/src/state/state-machine.js.map +1 -0
  261. package/dist/src/state/wu-doc-types.d.ts +48 -0
  262. package/dist/src/state/wu-doc-types.d.ts.map +1 -0
  263. package/dist/src/state/wu-doc-types.js +4 -0
  264. package/dist/src/state/wu-doc-types.js.map +1 -0
  265. package/dist/src/state/wu-paths.d.ts +275 -0
  266. package/dist/src/state/wu-paths.d.ts.map +1 -0
  267. package/dist/src/state/wu-paths.js +335 -0
  268. package/dist/src/state/wu-paths.js.map +1 -0
  269. package/dist/src/state/wu-schema.d.ts +831 -0
  270. package/dist/src/state/wu-schema.d.ts.map +1 -0
  271. package/dist/src/state/wu-schema.js +934 -0
  272. package/dist/src/state/wu-schema.js.map +1 -0
  273. package/dist/src/state/wu-state-schema.d.ts +292 -0
  274. package/dist/src/state/wu-state-schema.d.ts.map +1 -0
  275. package/dist/src/state/wu-state-schema.js +215 -0
  276. package/dist/src/state/wu-state-schema.js.map +1 -0
  277. package/dist/src/state/wu-yaml.d.ts +113 -0
  278. package/dist/src/state/wu-yaml.d.ts.map +1 -0
  279. package/dist/src/state/wu-yaml.js +307 -0
  280. package/dist/src/state/wu-yaml.js.map +1 -0
  281. package/dist/tool-impl/wu-lifecycle-tools.d.ts +11 -0
  282. package/dist/tool-impl/wu-lifecycle-tools.d.ts.map +1 -1
  283. package/dist/tool-impl/wu-lifecycle-tools.js +17 -0
  284. package/dist/tool-impl/wu-lifecycle-tools.js.map +1 -1
  285. package/manifest.yaml +46 -0
  286. package/package.json +88 -3
@@ -0,0 +1,427 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Signal-Based Work Classifier
5
+ *
6
+ * WU-1899: Determines work domain (ui/backend/docs/infra/mixed) from
7
+ * multiple weighted signals: code_paths patterns (weight 1.0), lane hints
8
+ * (0.6), type (0.3), description keywords (0.2).
9
+ *
10
+ * Returns abstract capability tags (not client skill names) for
11
+ * vendor-agnostic design. Configurable via methodology.work_classification
12
+ * in workspace.yaml with sensible built-in defaults.
13
+ *
14
+ * @module work-classifier
15
+ */
16
+ import { minimatch } from 'minimatch';
17
+ // ─── Constants ───────────────────────────────────────────────────────
18
+ /**
19
+ * Work domain enum-style constants
20
+ */
21
+ export const WORK_DOMAINS = {
22
+ UI: 'ui',
23
+ BACKEND: 'backend',
24
+ DOCS: 'docs',
25
+ INFRA: 'infra',
26
+ MIXED: 'mixed',
27
+ };
28
+ /**
29
+ * Classifier-produced methodology hints consumed by prompt guidance builders.
30
+ */
31
+ export const TEST_METHODOLOGY_HINTS = {
32
+ SMOKE_TEST: 'smoke-test',
33
+ STRUCTURED_CONTENT: 'structured-content',
34
+ };
35
+ /**
36
+ * Signal weights for each source type.
37
+ * Confidence = max(matched_signal_weights), not sum.
38
+ */
39
+ export const SIGNAL_WEIGHTS = {
40
+ CODE_PATHS: 1.0,
41
+ LANE: 0.6,
42
+ TYPE: 0.3,
43
+ DESCRIPTION: 0.2,
44
+ };
45
+ /**
46
+ * Confidence threshold: domain only assigned when max signal weight >= this.
47
+ */
48
+ const CONFIDENCE_THRESHOLD = 0.3;
49
+ /**
50
+ * Smoke-test hint threshold: testMethodologyHint only assigned when
51
+ * UI confidence >= this value.
52
+ */
53
+ const SMOKE_TEST_THRESHOLD = 0.5;
54
+ /**
55
+ * Structured-content patterns used to detect non-code work.
56
+ *
57
+ * When all code_paths match these patterns, classifier emits
58
+ * testMethodologyHint: 'structured-content' to avoid forcing TDD
59
+ * for content/config-only changes.
60
+ */
61
+ const STRUCTURED_CONTENT_CODE_PATH_PATTERNS = Object.freeze([
62
+ '**/*.yaml',
63
+ '**/*.yml',
64
+ '**/*.json',
65
+ '**/*.md',
66
+ '**/*.mdx',
67
+ ]);
68
+ // ─── Default Patterns ────────────────────────────────────────────────
69
+ /**
70
+ * Built-in default UI code path patterns (minimatch glob patterns).
71
+ * CSS/SCSS/LESS, components/pages directories, app page/layout files,
72
+ * module CSS, styled components.
73
+ */
74
+ export const DEFAULT_UI_CODE_PATH_PATTERNS = Object.freeze([
75
+ // Stylesheets
76
+ '**/*.css',
77
+ '**/*.scss',
78
+ '**/*.less',
79
+ '**/*.module.css',
80
+ '**/*.module.scss',
81
+ // Styled components
82
+ '**/*.styled.ts',
83
+ '**/*.styled.tsx',
84
+ '**/*.styled.js',
85
+ '**/*.styled.jsx',
86
+ // Component / page directories
87
+ '**/components/**',
88
+ '**/pages/**',
89
+ ]);
90
+ /**
91
+ * Built-in default UI lane hints.
92
+ * Matched against the lane parent (part before the colon).
93
+ */
94
+ export const DEFAULT_UI_LANE_HINTS = Object.freeze([
95
+ 'Experience',
96
+ 'Frontend',
97
+ 'UI',
98
+ 'Design',
99
+ ]);
100
+ /**
101
+ * Built-in docs code path patterns.
102
+ */
103
+ const DEFAULT_DOCS_CODE_PATH_PATTERNS = Object.freeze([
104
+ 'docs/**',
105
+ '**/*.md',
106
+ '**/*.mdx',
107
+ 'README*',
108
+ 'CHANGELOG*',
109
+ ]);
110
+ /**
111
+ * Built-in docs lane hints.
112
+ */
113
+ const DEFAULT_DOCS_LANE_HINTS = Object.freeze([
114
+ 'Content',
115
+ 'Documentation',
116
+ 'Docs',
117
+ ]);
118
+ /**
119
+ * Built-in infra code path patterns.
120
+ */
121
+ const DEFAULT_INFRA_CODE_PATH_PATTERNS = Object.freeze([
122
+ '.github/**',
123
+ 'Dockerfile*',
124
+ 'docker-compose*',
125
+ '**/terraform/**',
126
+ '**/k8s/**',
127
+ '**/kubernetes/**',
128
+ 'infrastructure/**',
129
+ ]);
130
+ /**
131
+ * Built-in infra lane hints.
132
+ */
133
+ const DEFAULT_INFRA_LANE_HINTS = Object.freeze([
134
+ 'Operations',
135
+ 'Infrastructure',
136
+ 'DevOps',
137
+ 'Platform',
138
+ ]);
139
+ /**
140
+ * UI-related description keywords (case-insensitive).
141
+ */
142
+ const UI_DESCRIPTION_KEYWORDS = Object.freeze([
143
+ 'css',
144
+ 'scss',
145
+ 'less',
146
+ 'stylesheet',
147
+ 'component',
148
+ 'layout',
149
+ 'responsive',
150
+ 'ui',
151
+ 'frontend',
152
+ 'styled',
153
+ 'animation',
154
+ 'theme',
155
+ ]);
156
+ /**
157
+ * Docs-related description keywords (case-insensitive).
158
+ */
159
+ const DOCS_DESCRIPTION_KEYWORDS = Object.freeze([
160
+ 'documentation',
161
+ 'readme',
162
+ 'changelog',
163
+ 'docs',
164
+ 'guide',
165
+ 'tutorial',
166
+ ]);
167
+ /**
168
+ * Infra-related description keywords (case-insensitive).
169
+ */
170
+ const INFRA_DESCRIPTION_KEYWORDS = Object.freeze([
171
+ 'docker',
172
+ 'kubernetes',
173
+ 'terraform',
174
+ 'ci/cd',
175
+ 'pipeline',
176
+ 'deploy',
177
+ 'infrastructure',
178
+ ]);
179
+ function createDomainSignals(domain) {
180
+ return { domain, maxWeight: 0, signals: [] };
181
+ }
182
+ function addSignal(ds, signal) {
183
+ ds.signals.push(signal);
184
+ if (signal.weight > ds.maxWeight) {
185
+ ds.maxWeight = signal.weight;
186
+ }
187
+ }
188
+ /**
189
+ * Check if any code_paths match a set of glob patterns.
190
+ */
191
+ function matchCodePaths(codePaths, patterns) {
192
+ for (const path of codePaths) {
193
+ for (const pattern of patterns) {
194
+ if (minimatch(path, pattern)) {
195
+ return pattern;
196
+ }
197
+ }
198
+ }
199
+ return undefined;
200
+ }
201
+ /**
202
+ * Check whether all code_paths are structured content (yaml/json/markdown).
203
+ */
204
+ function isStructuredContentOnly(codePaths) {
205
+ return (codePaths.length > 0 &&
206
+ codePaths.every((path) => STRUCTURED_CONTENT_CODE_PATH_PATTERNS.some((pattern) => minimatch(path, pattern, { nocase: true }))));
207
+ }
208
+ /**
209
+ * Check if the lane parent matches any hints (case-insensitive).
210
+ */
211
+ function matchLaneHint(lane, hints) {
212
+ const parts = lane.split(':');
213
+ const laneParent = (parts[0] ?? '').trim().toLowerCase();
214
+ const laneSublane = parts.length > 1 ? (parts[1] ?? '').trim().toLowerCase() : '';
215
+ for (const hint of hints) {
216
+ const hintLower = hint.toLowerCase();
217
+ if (laneParent === hintLower || laneSublane === hintLower) {
218
+ return hint;
219
+ }
220
+ }
221
+ return undefined;
222
+ }
223
+ /**
224
+ * Check if description contains any keywords (case-insensitive, word boundary).
225
+ */
226
+ function matchDescriptionKeywords(description, keywords) {
227
+ const descLower = description.toLowerCase();
228
+ for (const keyword of keywords) {
229
+ if (descLower.includes(keyword.toLowerCase())) {
230
+ return keyword;
231
+ }
232
+ }
233
+ return undefined;
234
+ }
235
+ /**
236
+ * Domain-to-capabilities data map (OCP-compliant).
237
+ * Add new domains by extending the record, no switch modification needed.
238
+ */
239
+ const DOMAIN_CAPABILITIES = {
240
+ [WORK_DOMAINS.UI]: ['ui-design-awareness', 'component-reuse-check'],
241
+ [WORK_DOMAINS.DOCS]: ['documentation-structure', 'link-validation'],
242
+ [WORK_DOMAINS.INFRA]: ['infrastructure-review', 'security-check'],
243
+ [WORK_DOMAINS.MIXED]: ['cross-domain-awareness'],
244
+ [WORK_DOMAINS.BACKEND]: [],
245
+ };
246
+ /**
247
+ * Map work domain to capabilities (abstract, vendor-agnostic).
248
+ */
249
+ function getCapabilities(domain) {
250
+ return DOMAIN_CAPABILITIES[domain] ?? [];
251
+ }
252
+ // ─── Public API ──────────────────────────────────────────────────────
253
+ /**
254
+ * Classify work domain from multiple weighted signals.
255
+ *
256
+ * Signal weights:
257
+ * - code_paths patterns: 1.0
258
+ * - lane hints: 0.6
259
+ * - WU type: 0.3
260
+ * - description keywords: 0.2
261
+ *
262
+ * Confidence = max(matched signal weights for winning domain).
263
+ * Domain only assigned when confidence >= 0.3.
264
+ *
265
+ * @param doc - WU document (code_paths, lane, type, description)
266
+ * @param config - Optional config to extend default patterns
267
+ * @returns WorkClassification with domain, confidence, signals, capabilities, testMethodologyHint
268
+ */
269
+ export function classifyWork(doc, config) {
270
+ const codePaths = doc.code_paths ?? [];
271
+ const lane = doc.lane ?? '';
272
+ const type = doc.type ?? '';
273
+ const description = doc.description ?? '';
274
+ const structuredContentOnly = isStructuredContentOnly(codePaths);
275
+ // Merge config patterns with defaults (config extends, not replaces)
276
+ const uiCodePathPatterns = [
277
+ ...DEFAULT_UI_CODE_PATH_PATTERNS,
278
+ ...(config?.ui?.code_path_patterns ?? []),
279
+ ];
280
+ const uiLaneHints = [...DEFAULT_UI_LANE_HINTS, ...(config?.ui?.lane_hints ?? [])];
281
+ // Collect signals per domain
282
+ const ui = createDomainSignals(WORK_DOMAINS.UI);
283
+ const docs = createDomainSignals(WORK_DOMAINS.DOCS);
284
+ const infra = createDomainSignals(WORK_DOMAINS.INFRA);
285
+ // ── Signal 1: code_paths (weight 1.0) ──
286
+ if (codePaths.length > 0) {
287
+ const uiMatch = matchCodePaths(codePaths, uiCodePathPatterns);
288
+ if (uiMatch) {
289
+ addSignal(ui, {
290
+ source: 'code_paths',
291
+ domain: WORK_DOMAINS.UI,
292
+ weight: SIGNAL_WEIGHTS.CODE_PATHS,
293
+ match: uiMatch,
294
+ });
295
+ }
296
+ const docsMatch = matchCodePaths(codePaths, DEFAULT_DOCS_CODE_PATH_PATTERNS);
297
+ if (docsMatch) {
298
+ addSignal(docs, {
299
+ source: 'code_paths',
300
+ domain: WORK_DOMAINS.DOCS,
301
+ weight: SIGNAL_WEIGHTS.CODE_PATHS,
302
+ match: docsMatch,
303
+ });
304
+ }
305
+ const infraMatch = matchCodePaths(codePaths, DEFAULT_INFRA_CODE_PATH_PATTERNS);
306
+ if (infraMatch) {
307
+ addSignal(infra, {
308
+ source: 'code_paths',
309
+ domain: WORK_DOMAINS.INFRA,
310
+ weight: SIGNAL_WEIGHTS.CODE_PATHS,
311
+ match: infraMatch,
312
+ });
313
+ }
314
+ }
315
+ // ── Signal 2: lane hints (weight 0.6) ──
316
+ if (lane) {
317
+ const uiLaneMatch = matchLaneHint(lane, uiLaneHints);
318
+ if (uiLaneMatch) {
319
+ addSignal(ui, {
320
+ source: 'lane',
321
+ domain: WORK_DOMAINS.UI,
322
+ weight: SIGNAL_WEIGHTS.LANE,
323
+ match: uiLaneMatch,
324
+ });
325
+ }
326
+ const docsLaneMatch = matchLaneHint(lane, DEFAULT_DOCS_LANE_HINTS);
327
+ if (docsLaneMatch) {
328
+ addSignal(docs, {
329
+ source: 'lane',
330
+ domain: WORK_DOMAINS.DOCS,
331
+ weight: SIGNAL_WEIGHTS.LANE,
332
+ match: docsLaneMatch,
333
+ });
334
+ }
335
+ const infraLaneMatch = matchLaneHint(lane, DEFAULT_INFRA_LANE_HINTS);
336
+ if (infraLaneMatch) {
337
+ addSignal(infra, {
338
+ source: 'lane',
339
+ domain: WORK_DOMAINS.INFRA,
340
+ weight: SIGNAL_WEIGHTS.LANE,
341
+ match: infraLaneMatch,
342
+ });
343
+ }
344
+ }
345
+ // ── Signal 3: WU type (weight 0.3) ──
346
+ if (type === 'documentation') {
347
+ addSignal(docs, {
348
+ source: 'type',
349
+ domain: WORK_DOMAINS.DOCS,
350
+ weight: SIGNAL_WEIGHTS.TYPE,
351
+ match: 'documentation',
352
+ });
353
+ }
354
+ // ── Signal 4: description keywords (weight 0.2) ──
355
+ if (description) {
356
+ const uiKeywordMatch = matchDescriptionKeywords(description, UI_DESCRIPTION_KEYWORDS);
357
+ if (uiKeywordMatch) {
358
+ addSignal(ui, {
359
+ source: 'description',
360
+ domain: WORK_DOMAINS.UI,
361
+ weight: SIGNAL_WEIGHTS.DESCRIPTION,
362
+ match: uiKeywordMatch,
363
+ });
364
+ }
365
+ const docsKeywordMatch = matchDescriptionKeywords(description, DOCS_DESCRIPTION_KEYWORDS);
366
+ if (docsKeywordMatch) {
367
+ addSignal(docs, {
368
+ source: 'description',
369
+ domain: WORK_DOMAINS.DOCS,
370
+ weight: SIGNAL_WEIGHTS.DESCRIPTION,
371
+ match: docsKeywordMatch,
372
+ });
373
+ }
374
+ const infraKeywordMatch = matchDescriptionKeywords(description, INFRA_DESCRIPTION_KEYWORDS);
375
+ if (infraKeywordMatch) {
376
+ addSignal(infra, {
377
+ source: 'description',
378
+ domain: WORK_DOMAINS.INFRA,
379
+ weight: SIGNAL_WEIGHTS.DESCRIPTION,
380
+ match: infraKeywordMatch,
381
+ });
382
+ }
383
+ }
384
+ // ── Determine winning domain ──
385
+ const candidates = [ui, docs, infra].filter((d) => d.maxWeight >= CONFIDENCE_THRESHOLD);
386
+ // Check for mixed: multiple domains with strong code_paths signals
387
+ const strongCodePathDomains = [ui, docs, infra].filter((d) => d.signals.some((s) => s.source === 'code_paths'));
388
+ if (strongCodePathDomains.length > 1) {
389
+ // Multiple code_paths domains detected - classify as mixed
390
+ const allSignals = strongCodePathDomains.flatMap((d) => d.signals);
391
+ return {
392
+ domain: WORK_DOMAINS.MIXED,
393
+ confidence: Math.max(...strongCodePathDomains.map((d) => d.maxWeight)),
394
+ signals: allSignals,
395
+ capabilities: getCapabilities(WORK_DOMAINS.MIXED),
396
+ testMethodologyHint: undefined,
397
+ };
398
+ }
399
+ if (candidates.length === 0) {
400
+ // No signals above threshold - default to backend
401
+ return {
402
+ domain: WORK_DOMAINS.BACKEND,
403
+ confidence: 0,
404
+ signals: [],
405
+ capabilities: [],
406
+ testMethodologyHint: structuredContentOnly
407
+ ? TEST_METHODOLOGY_HINTS.STRUCTURED_CONTENT
408
+ : undefined,
409
+ };
410
+ }
411
+ // Pick the domain with highest max weight
412
+ candidates.sort((a, b) => b.maxWeight - a.maxWeight);
413
+ const winner = candidates[0];
414
+ const testMethodologyHint = winner.domain === WORK_DOMAINS.UI && winner.maxWeight >= SMOKE_TEST_THRESHOLD
415
+ ? TEST_METHODOLOGY_HINTS.SMOKE_TEST
416
+ : structuredContentOnly
417
+ ? TEST_METHODOLOGY_HINTS.STRUCTURED_CONTENT
418
+ : undefined;
419
+ return {
420
+ domain: winner.domain,
421
+ confidence: winner.maxWeight,
422
+ signals: winner.signals,
423
+ capabilities: getCapabilities(winner.domain),
424
+ testMethodologyHint,
425
+ };
426
+ }
427
+ //# sourceMappingURL=work-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-classifier.js","sourceRoot":"","sources":["../../../src/runtime/work-classifier.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,wEAAwE;AAExE;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,EAAE,EAAE,IAAI;IACR,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;CACN,CAAC;AAIX;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,UAAU,EAAE,YAAY;IACxB,kBAAkB,EAAE,oBAAoB;CAChC,CAAC;AAKX;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU,EAAE,GAAG;IACf,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,GAAG;IACT,WAAW,EAAE,GAAG;CACR,CAAC;AAEX;;GAEG;AACH,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAEjC;;;GAGG;AACH,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAEjC;;;;;;GAMG;AACH,MAAM,qCAAqC,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC7E,WAAW;IACX,UAAU;IACV,WAAW;IACX,SAAS;IACT,UAAU;CACX,CAAC,CAAC;AAEH,wEAAwE;AAExE;;;;GAIG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC5E,cAAc;IACd,UAAU;IACV,WAAW;IACX,WAAW;IACX,iBAAiB;IACjB,kBAAkB;IAClB,oBAAoB;IACpB,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;IACjB,+BAA+B;IAC/B,kBAAkB;IAClB,aAAa;CACd,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAsB,MAAM,CAAC,MAAM,CAAC;IACpE,YAAY;IACZ,UAAU;IACV,IAAI;IACJ,QAAQ;CACT,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,+BAA+B,GAAsB,MAAM,CAAC,MAAM,CAAC;IACvE,SAAS;IACT,SAAS;IACT,UAAU;IACV,SAAS;IACT,YAAY;CACb,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,uBAAuB,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC/D,SAAS;IACT,eAAe;IACf,MAAM;CACP,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,gCAAgC,GAAsB,MAAM,CAAC,MAAM,CAAC;IACxE,YAAY;IACZ,aAAa;IACb,iBAAiB;IACjB,iBAAiB;IACjB,WAAW;IACX,kBAAkB;IAClB,mBAAmB;CACpB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,wBAAwB,GAAsB,MAAM,CAAC,MAAM,CAAC;IAChE,YAAY;IACZ,gBAAgB;IAChB,QAAQ;IACR,UAAU;CACX,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,uBAAuB,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC/D,KAAK;IACL,MAAM;IACN,MAAM;IACN,YAAY;IACZ,WAAW;IACX,QAAQ;IACR,YAAY;IACZ,IAAI;IACJ,UAAU;IACV,QAAQ;IACR,WAAW;IACX,OAAO;CACR,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,yBAAyB,GAAsB,MAAM,CAAC,MAAM,CAAC;IACjE,eAAe;IACf,QAAQ;IACR,WAAW;IACX,MAAM;IACN,OAAO;IACP,UAAU;CACX,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,0BAA0B,GAAsB,MAAM,CAAC,MAAM,CAAC;IAClE,QAAQ;IACR,YAAY;IACZ,WAAW;IACX,OAAO;IACP,UAAU;IACV,QAAQ;IACR,gBAAgB;CACjB,CAAC,CAAC;AA0DH,SAAS,mBAAmB,CAAC,MAAkB;IAC7C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,SAAS,CAAC,EAAiB,EAAE,MAAkB;IACtD,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;QACjC,EAAE,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,SAAmB,EAAE,QAA2B;IACtE,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC7B,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,SAAmB;IAClD,OAAO,CACL,SAAS,CAAC,MAAM,GAAG,CAAC;QACpB,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CACvB,qCAAqC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CACrD,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAC3C,CACF,CACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,IAAY,EAAE,KAAwB;IAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,UAAU,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzD,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAElF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,UAAU,KAAK,SAAS,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAC/B,WAAmB,EACnB,QAA2B;IAE3B,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IAC5C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC9C,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,mBAAmB,GAAiC;IACxD,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,EAAE,uBAAuB,CAAC;IACnE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,yBAAyB,EAAE,iBAAiB,CAAC;IACnE,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,uBAAuB,EAAE,gBAAgB,CAAC;IACjE,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAAC;IAChD,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,EAAE;CAC3B,CAAC;AAEF;;GAEG;AACH,SAAS,eAAe,CAAC,MAAkB;IACzC,OAAO,mBAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;AAC3C,CAAC;AAED,wEAAwE;AAExE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,YAAY,CAC1B,GAKC,EACD,MAAiC;IAEjC,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;IAC1C,MAAM,qBAAqB,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAEjE,qEAAqE;IACrE,MAAM,kBAAkB,GAAG;QACzB,GAAG,6BAA6B;QAChC,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,kBAAkB,IAAI,EAAE,CAAC;KAC1C,CAAC;IACF,MAAM,WAAW,GAAG,CAAC,GAAG,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC;IAElF,6BAA6B;IAC7B,MAAM,EAAE,GAAG,mBAAmB,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,mBAAmB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,mBAAmB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAEtD,0CAA0C;IAE1C,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,cAAc,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAC9D,IAAI,OAAO,EAAE,CAAC;YACZ,SAAS,CAAC,EAAE,EAAE;gBACZ,MAAM,EAAE,YAAY;gBACpB,MAAM,EAAE,YAAY,CAAC,EAAE;gBACvB,MAAM,EAAE,cAAc,CAAC,UAAU;gBACjC,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;QACL,CAAC;QAED,MAAM,SAAS,GAAG,cAAc,CAAC,SAAS,EAAE,+BAA+B,CAAC,CAAC;QAC7E,IAAI,SAAS,EAAE,CAAC;YACd,SAAS,CAAC,IAAI,EAAE;gBACd,MAAM,EAAE,YAAY;gBACpB,MAAM,EAAE,YAAY,CAAC,IAAI;gBACzB,MAAM,EAAE,cAAc,CAAC,UAAU;gBACjC,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,UAAU,GAAG,cAAc,CAAC,SAAS,EAAE,gCAAgC,CAAC,CAAC;QAC/E,IAAI,UAAU,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,EAAE;gBACf,MAAM,EAAE,YAAY;gBACpB,MAAM,EAAE,YAAY,CAAC,KAAK;gBAC1B,MAAM,EAAE,cAAc,CAAC,UAAU;gBACjC,KAAK,EAAE,UAAU;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,0CAA0C;IAE1C,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACrD,IAAI,WAAW,EAAE,CAAC;YAChB,SAAS,CAAC,EAAE,EAAE;gBACZ,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,YAAY,CAAC,EAAE;gBACvB,MAAM,EAAE,cAAc,CAAC,IAAI;gBAC3B,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;QACnE,IAAI,aAAa,EAAE,CAAC;YAClB,SAAS,CAAC,IAAI,EAAE;gBACd,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,YAAY,CAAC,IAAI;gBACzB,MAAM,EAAE,cAAc,CAAC,IAAI;gBAC3B,KAAK,EAAE,aAAa;aACrB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;QACrE,IAAI,cAAc,EAAE,CAAC;YACnB,SAAS,CAAC,KAAK,EAAE;gBACf,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,YAAY,CAAC,KAAK;gBAC1B,MAAM,EAAE,cAAc,CAAC,IAAI;gBAC3B,KAAK,EAAE,cAAc;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,uCAAuC;IAEvC,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;QAC7B,SAAS,CAAC,IAAI,EAAE;YACd,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,YAAY,CAAC,IAAI;YACzB,MAAM,EAAE,cAAc,CAAC,IAAI;YAC3B,KAAK,EAAE,eAAe;SACvB,CAAC,CAAC;IACL,CAAC;IAED,oDAAoD;IAEpD,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,cAAc,GAAG,wBAAwB,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC;QACtF,IAAI,cAAc,EAAE,CAAC;YACnB,SAAS,CAAC,EAAE,EAAE;gBACZ,MAAM,EAAE,aAAa;gBACrB,MAAM,EAAE,YAAY,CAAC,EAAE;gBACvB,MAAM,EAAE,cAAc,CAAC,WAAW;gBAClC,KAAK,EAAE,cAAc;aACtB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,gBAAgB,GAAG,wBAAwB,CAAC,WAAW,EAAE,yBAAyB,CAAC,CAAC;QAC1F,IAAI,gBAAgB,EAAE,CAAC;YACrB,SAAS,CAAC,IAAI,EAAE;gBACd,MAAM,EAAE,aAAa;gBACrB,MAAM,EAAE,YAAY,CAAC,IAAI;gBACzB,MAAM,EAAE,cAAc,CAAC,WAAW;gBAClC,KAAK,EAAE,gBAAgB;aACxB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,WAAW,EAAE,0BAA0B,CAAC,CAAC;QAC5F,IAAI,iBAAiB,EAAE,CAAC;YACtB,SAAS,CAAC,KAAK,EAAE;gBACf,MAAM,EAAE,aAAa;gBACrB,MAAM,EAAE,YAAY,CAAC,KAAK;gBAC1B,MAAM,EAAE,cAAc,CAAC,WAAW;gBAClC,KAAK,EAAE,iBAAiB;aACzB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,iCAAiC;IAEjC,MAAM,UAAU,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,oBAAoB,CAAC,CAAC;IAExF,mEAAmE;IACnE,MAAM,qBAAqB,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3D,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CACjD,CAAC;IAEF,IAAI,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,2DAA2D;QAC3D,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACnE,OAAO;YACL,MAAM,EAAE,YAAY,CAAC,KAAK;YAC1B,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACtE,OAAO,EAAE,UAAU;YACnB,YAAY,EAAE,eAAe,CAAC,YAAY,CAAC,KAAK,CAAC;YACjD,mBAAmB,EAAE,SAAS;SAC/B,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,kDAAkD;QAClD,OAAO;YACL,MAAM,EAAE,YAAY,CAAC,OAAO;YAC5B,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,EAAE;YACX,YAAY,EAAE,EAAE;YAChB,mBAAmB,EAAE,qBAAqB;gBACxC,CAAC,CAAC,sBAAsB,CAAC,kBAAkB;gBAC3C,CAAC,CAAC,SAAS;SACd,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAkB,CAAC;IAE9C,MAAM,mBAAmB,GACvB,MAAM,CAAC,MAAM,KAAK,YAAY,CAAC,EAAE,IAAI,MAAM,CAAC,SAAS,IAAI,oBAAoB;QAC3E,CAAC,CAAC,sBAAsB,CAAC,UAAU;QACnC,CAAC,CAAC,qBAAqB;YACrB,CAAC,CAAC,sBAAsB,CAAC,kBAAkB;YAC3C,CAAC,CAAC,SAAS,CAAC;IAElB,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,UAAU,EAAE,MAAM,CAAC,SAAS;QAC5B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,YAAY,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC;QAC5C,mBAAmB;KACpB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './sandbox-allowlist.js';
2
+ export * from './sandbox-profile.js';
3
+ export * from './sandbox-backend-linux.js';
4
+ export * from './sandbox-backend-macos.js';
5
+ export * from './sandbox-backend-windows.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sandbox/index.ts"],"names":[],"mappings":"AAKA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC"}
@@ -0,0 +1,10 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ // Barrel for pack-local sandbox modules. Populated by Layer 4 of INIT-058.
4
+ // WU-2678: moved sandbox-profile, sandbox-allowlist, sandbox-backend-{linux,macos,windows} from @lumenflow/core.
5
+ export * from './sandbox-allowlist.js';
6
+ export * from './sandbox-profile.js';
7
+ export * from './sandbox-backend-linux.js';
8
+ export * from './sandbox-backend-macos.js';
9
+ export * from './sandbox-backend-windows.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sandbox/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC,2EAA2E;AAC3E,iHAAiH;AACjH,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface SandboxAllowlistEntry {
2
+ originalPath: string;
3
+ normalizedPath: string;
4
+ canonicalPath: string;
5
+ }
6
+ export interface SandboxAllowlist {
7
+ projectRoot: string;
8
+ writableRoots: SandboxAllowlistEntry[];
9
+ }
10
+ export interface BuildSandboxAllowlistInput {
11
+ projectRoot: string;
12
+ writableRoots: string[];
13
+ }
14
+ export declare function buildSandboxAllowlist(input: BuildSandboxAllowlistInput): SandboxAllowlist;
15
+ export declare function isWritePathAllowed(allowlist: SandboxAllowlist, targetPath: string): boolean;
16
+ //# sourceMappingURL=sandbox-allowlist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-allowlist.d.ts","sourceRoot":"","sources":["../../../src/sandbox/sandbox-allowlist.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,qBAAqB,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAkED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,GAAG,gBAAgB,CAgBzF;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAa3F"}
@@ -0,0 +1,77 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ function normalizeAbsolutePath(targetPath) {
6
+ const normalized = path.resolve(targetPath);
7
+ if (normalized.length > 1 && normalized.endsWith(path.sep)) {
8
+ return normalized.slice(0, -1);
9
+ }
10
+ return normalized;
11
+ }
12
+ function toComparisonKey(targetPath) {
13
+ return process.platform === 'win32' ? targetPath.toLowerCase() : targetPath;
14
+ }
15
+ function findNearestExistingAncestor(targetPath) {
16
+ let cursor = normalizeAbsolutePath(targetPath);
17
+ const suffixParts = [];
18
+ while (!fs.existsSync(cursor)) {
19
+ const parent = path.dirname(cursor);
20
+ if (parent === cursor) {
21
+ break;
22
+ }
23
+ suffixParts.unshift(path.basename(cursor));
24
+ cursor = parent;
25
+ }
26
+ return { ancestor: cursor, suffixParts };
27
+ }
28
+ function resolveCanonicalPathForWrite(targetPath) {
29
+ const normalized = normalizeAbsolutePath(targetPath);
30
+ if (fs.existsSync(normalized)) {
31
+ return normalizeAbsolutePath(fs.realpathSync.native(normalized));
32
+ }
33
+ const { ancestor, suffixParts } = findNearestExistingAncestor(normalized);
34
+ const canonicalAncestor = fs.existsSync(ancestor)
35
+ ? normalizeAbsolutePath(fs.realpathSync.native(ancestor))
36
+ : normalizeAbsolutePath(ancestor);
37
+ return normalizeAbsolutePath(path.join(canonicalAncestor, ...suffixParts));
38
+ }
39
+ function resolveRoot(projectRoot, writableRoot) {
40
+ if (path.isAbsolute(writableRoot)) {
41
+ return normalizeAbsolutePath(writableRoot);
42
+ }
43
+ return normalizeAbsolutePath(path.resolve(projectRoot, writableRoot));
44
+ }
45
+ function isWithinRoot(candidatePath, rootPath) {
46
+ const candidateKey = toComparisonKey(candidatePath);
47
+ const rootKey = toComparisonKey(rootPath);
48
+ return candidateKey === rootKey || candidateKey.startsWith(`${rootKey}${path.sep}`);
49
+ }
50
+ export function buildSandboxAllowlist(input) {
51
+ const projectRoot = normalizeAbsolutePath(input.projectRoot);
52
+ const writableRoots = input.writableRoots.map((writableRoot) => {
53
+ const normalizedPath = resolveRoot(projectRoot, writableRoot);
54
+ return {
55
+ originalPath: writableRoot,
56
+ normalizedPath,
57
+ canonicalPath: resolveCanonicalPathForWrite(normalizedPath),
58
+ };
59
+ });
60
+ return {
61
+ projectRoot,
62
+ writableRoots,
63
+ };
64
+ }
65
+ export function isWritePathAllowed(allowlist, targetPath) {
66
+ const normalizedTargetPath = normalizeAbsolutePath(targetPath);
67
+ const canonicalTargetPath = resolveCanonicalPathForWrite(normalizedTargetPath);
68
+ return allowlist.writableRoots.some((entry) => {
69
+ const normalizedMatch = isWithinRoot(normalizedTargetPath, entry.normalizedPath);
70
+ const canonicalMatch = isWithinRoot(canonicalTargetPath, entry.canonicalPath);
71
+ // Require both checks:
72
+ // - normalized path guards lexical traversal tricks (../)
73
+ // - canonical path guards symlink escapes to outside the allowed root
74
+ return normalizedMatch && canonicalMatch;
75
+ });
76
+ }
77
+ //# sourceMappingURL=sandbox-allowlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-allowlist.js","sourceRoot":"","sources":["../../../src/sandbox/sandbox-allowlist.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type SandboxBackend } from './sandbox-profile.js';
2
+ export interface LinuxSandboxBackendOptions {
3
+ commandExists?: (binary: string) => boolean;
4
+ }
5
+ export declare function createLinuxSandboxBackend(options?: LinuxSandboxBackendOptions): SandboxBackend;
6
+ //# sourceMappingURL=sandbox-backend-linux.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-backend-linux.d.ts","sourceRoot":"","sources":["../../../src/sandbox/sandbox-backend-linux.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,cAAc,EAGpB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,0BAA0B;IACzC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;CAC7C;AAsDD,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,0BAA+B,GACvC,cAAc,CAkBhB"}
@@ -0,0 +1,67 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { spawnSync } from 'node:child_process';
4
+ import { SANDBOX_BACKEND_IDS, } from './sandbox-profile.js';
5
+ const LINUX_SANDBOX_BINARY = 'bwrap';
6
+ function defaultCommandExists(binary) {
7
+ const probe = spawnSync(binary, ['--help'], { stdio: 'ignore' });
8
+ return !probe.error;
9
+ }
10
+ function buildUnavailablePlan(request) {
11
+ if (request.allowUnsandboxedFallback) {
12
+ return {
13
+ backendId: SANDBOX_BACKEND_IDS.LINUX,
14
+ enforced: false,
15
+ failClosed: false,
16
+ warning: 'Running unsandboxed because bwrap is unavailable and fallback was explicitly enabled.',
17
+ };
18
+ }
19
+ return {
20
+ backendId: SANDBOX_BACKEND_IDS.LINUX,
21
+ enforced: false,
22
+ failClosed: true,
23
+ reason: 'Linux sandbox backend unavailable: required binary "bwrap" was not found.',
24
+ };
25
+ }
26
+ function buildInvocation(request) {
27
+ const writableBinds = request.profile.allowlist.writableRoots.flatMap((entry) => [
28
+ '--bind',
29
+ entry.normalizedPath,
30
+ entry.normalizedPath,
31
+ ]);
32
+ return {
33
+ command: LINUX_SANDBOX_BINARY,
34
+ args: [
35
+ '--die-with-parent',
36
+ '--new-session',
37
+ '--ro-bind',
38
+ '/',
39
+ '/',
40
+ ...writableBinds,
41
+ '--proc',
42
+ '/proc',
43
+ '--dev',
44
+ '/dev',
45
+ '--',
46
+ ...request.command,
47
+ ],
48
+ };
49
+ }
50
+ export function createLinuxSandboxBackend(options = {}) {
51
+ const commandExists = options.commandExists || defaultCommandExists;
52
+ return {
53
+ id: SANDBOX_BACKEND_IDS.LINUX,
54
+ resolveExecution(request) {
55
+ if (!commandExists(LINUX_SANDBOX_BINARY)) {
56
+ return buildUnavailablePlan(request);
57
+ }
58
+ return {
59
+ backendId: SANDBOX_BACKEND_IDS.LINUX,
60
+ enforced: true,
61
+ failClosed: false,
62
+ invocation: buildInvocation(request),
63
+ };
64
+ },
65
+ };
66
+ }
67
+ //# sourceMappingURL=sandbox-backend-linux.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-backend-linux.js","sourceRoot":"","sources":["../../../src/sandbox/sandbox-backend-linux.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACL,mBAAmB,GAIpB,MAAM,sBAAsB,CAAC;AAM9B,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAErC,SAAS,oBAAoB,CAAC,MAAc;IAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AACtB,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAgC;IAC5D,IAAI,OAAO,CAAC,wBAAwB,EAAE,CAAC;QACrC,OAAO;YACL,SAAS,EAAE,mBAAmB,CAAC,KAAK;YACpC,QAAQ,EAAE,KAAK;YACf,UAAU,EAAE,KAAK;YACjB,OAAO,EACL,uFAAuF;SAC1F,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,mBAAmB,CAAC,KAAK;QACpC,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,2EAA2E;KACpF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,OAAgC;IACvD,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/E,QAAQ;QACR,KAAK,CAAC,cAAc;QACpB,KAAK,CAAC,cAAc;KACrB,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,oBAAoB;QAC7B,IAAI,EAAE;YACJ,mBAAmB;YACnB,eAAe;YACf,WAAW;YACX,GAAG;YACH,GAAG;YACH,GAAG,aAAa;YAChB,QAAQ;YACR,OAAO;YACP,OAAO;YACP,MAAM;YACN,IAAI;YACJ,GAAG,OAAO,CAAC,OAAO;SACnB;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,UAAsC,EAAE;IAExC,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,oBAAoB,CAAC;IAEpE,OAAO;QACL,EAAE,EAAE,mBAAmB,CAAC,KAAK;QAC7B,gBAAgB,CAAC,OAAgC;YAC/C,IAAI,CAAC,aAAa,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBACzC,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAC;YACvC,CAAC;YAED,OAAO;gBACL,SAAS,EAAE,mBAAmB,CAAC,KAAK;gBACpC,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,KAAK;gBACjB,UAAU,EAAE,eAAe,CAAC,OAAO,CAAC;aACrC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { type SandboxBackend } from './sandbox-profile.js';
2
+ export interface MacosSandboxBackendOptions {
3
+ commandExists?: (binary: string) => boolean;
4
+ }
5
+ export declare function createMacosSandboxBackend(options?: MacosSandboxBackendOptions): SandboxBackend;
6
+ //# sourceMappingURL=sandbox-backend-macos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-backend-macos.d.ts","sourceRoot":"","sources":["../../../src/sandbox/sandbox-backend-macos.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,cAAc,EAGpB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,0BAA0B;IACzC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;CAC7C;AAuHD,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,0BAA+B,GACvC,cAAc,CAkBhB"}