@warpgogol/forge 4.2.4 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/AGENTS.md +14 -6
  2. package/CHANGELOG.md +72 -0
  3. package/README.md +8 -8
  4. package/README.uk.md +5 -5
  5. package/dist/os/adr/handlers/list-create.d.ts.map +1 -1
  6. package/dist/os/adr/handlers/list-create.js +4 -1
  7. package/dist/os/adr/handlers/list-create.js.map +1 -1
  8. package/dist/os/adr/handlers/validate.d.ts.map +1 -1
  9. package/dist/os/adr/handlers/validate.js +6 -1
  10. package/dist/os/adr/handlers/validate.js.map +1 -1
  11. package/dist/os/adr/types.d.ts.map +1 -1
  12. package/dist/os/adr/types.js +7 -3
  13. package/dist/os/adr/types.js.map +1 -1
  14. package/dist/os/compass/compass.module.d.ts.map +1 -1
  15. package/dist/os/compass/compass.module.js +76 -10
  16. package/dist/os/compass/compass.module.js.map +1 -1
  17. package/dist/os/compass/handlers/compass-audit-handler.d.ts.map +1 -1
  18. package/dist/os/compass/handlers/compass-audit-handler.js +7 -3
  19. package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
  20. package/dist/os/compass/handlers/compass-change-summary-handler.d.ts +1 -9
  21. package/dist/os/compass/handlers/compass-change-summary-handler.d.ts.map +1 -1
  22. package/dist/os/compass/handlers/compass-change-summary-handler.js +44 -186
  23. package/dist/os/compass/handlers/compass-change-summary-handler.js.map +1 -1
  24. package/dist/os/compass/handlers/compass-inventory-handler.d.ts +2 -0
  25. package/dist/os/compass/handlers/compass-inventory-handler.d.ts.map +1 -1
  26. package/dist/os/compass/handlers/compass-inventory-handler.js +24 -12
  27. package/dist/os/compass/handlers/compass-inventory-handler.js.map +1 -1
  28. package/dist/os/compass/handlers/compass-inventory.d.ts +7 -5
  29. package/dist/os/compass/handlers/compass-inventory.d.ts.map +1 -1
  30. package/dist/os/compass/handlers/compass-inventory.js +84 -241
  31. package/dist/os/compass/handlers/compass-inventory.js.map +1 -1
  32. package/dist/os/compass/handlers/compass-migrate-handler.d.ts +4 -0
  33. package/dist/os/compass/handlers/compass-migrate-handler.d.ts.map +1 -0
  34. package/dist/os/compass/handlers/compass-migrate-handler.js +100 -0
  35. package/dist/os/compass/handlers/compass-migrate-handler.js.map +1 -0
  36. package/dist/os/compass/handlers/compass-migrate.d.ts +34 -0
  37. package/dist/os/compass/handlers/compass-migrate.d.ts.map +1 -0
  38. package/dist/os/compass/handlers/compass-migrate.js +273 -0
  39. package/dist/os/compass/handlers/compass-migrate.js.map +1 -0
  40. package/dist/os/compass/handlers/resolve-scan-root.d.ts.map +1 -1
  41. package/dist/os/compass/handlers/resolve-scan-root.js +15 -8
  42. package/dist/os/compass/handlers/resolve-scan-root.js.map +1 -1
  43. package/dist/os/compass/handlers/summary-record.d.ts +46 -0
  44. package/dist/os/compass/handlers/summary-record.d.ts.map +1 -0
  45. package/dist/os/compass/handlers/summary-record.js +233 -0
  46. package/dist/os/compass/handlers/summary-record.js.map +1 -0
  47. package/dist/os/compass/index.d.ts +4 -1
  48. package/dist/os/compass/index.d.ts.map +1 -1
  49. package/dist/os/compass/index.js +9 -1
  50. package/dist/os/compass/index.js.map +1 -1
  51. package/dist/os/compass/policy.d.ts +65 -0
  52. package/dist/os/compass/policy.d.ts.map +1 -0
  53. package/dist/os/compass/policy.js +241 -0
  54. package/dist/os/compass/policy.js.map +1 -0
  55. package/dist/os/core/core.module.d.ts.map +1 -1
  56. package/dist/os/core/core.module.js +11 -23
  57. package/dist/os/core/core.module.js.map +1 -1
  58. package/dist/os/core/handlers/forge-autonomy-validate.d.ts.map +1 -1
  59. package/dist/os/core/handlers/forge-autonomy-validate.js +7 -1
  60. package/dist/os/core/handlers/forge-autonomy-validate.js.map +1 -1
  61. package/dist/os/core/handlers/package-health.d.ts.map +1 -1
  62. package/dist/os/core/handlers/package-health.js +6 -1
  63. package/dist/os/core/handlers/package-health.js.map +1 -1
  64. package/dist/os/core/handlers/pinned-check.d.ts.map +1 -1
  65. package/dist/os/core/handlers/pinned-check.js +6 -1
  66. package/dist/os/core/handlers/pinned-check.js.map +1 -1
  67. package/dist/os/core/handlers/pinned-validate.d.ts.map +1 -1
  68. package/dist/os/core/handlers/pinned-validate.js +6 -1
  69. package/dist/os/core/handlers/pinned-validate.js.map +1 -1
  70. package/dist/os/core/handlers/validate.d.ts.map +1 -1
  71. package/dist/os/core/handlers/validate.js +6 -1
  72. package/dist/os/core/handlers/validate.js.map +1 -1
  73. package/dist/os/exploration/exploration.module.d.ts.map +1 -1
  74. package/dist/os/exploration/exploration.module.js +6 -4
  75. package/dist/os/exploration/exploration.module.js.map +1 -1
  76. package/dist/os/exploration/handlers/list.d.ts.map +1 -1
  77. package/dist/os/exploration/handlers/list.js +4 -1
  78. package/dist/os/exploration/handlers/list.js.map +1 -1
  79. package/dist/os/mission/handlers/archive.d.ts.map +1 -1
  80. package/dist/os/mission/handlers/archive.js +7 -3
  81. package/dist/os/mission/handlers/archive.js.map +1 -1
  82. package/dist/os/mission/index.d.ts.map +1 -1
  83. package/dist/os/mission/index.js +13 -0
  84. package/dist/os/mission/index.js.map +1 -1
  85. package/dist/os/notes/index.d.ts.map +1 -1
  86. package/dist/os/notes/index.js +7 -1
  87. package/dist/os/notes/index.js.map +1 -1
  88. package/dist/os/rfc/frontmatter-io.d.ts.map +1 -1
  89. package/dist/os/rfc/frontmatter-io.js +6 -1
  90. package/dist/os/rfc/frontmatter-io.js.map +1 -1
  91. package/dist/os/rfc/handlers/archive.d.ts.map +1 -1
  92. package/dist/os/rfc/handlers/archive.js +6 -1
  93. package/dist/os/rfc/handlers/archive.js.map +1 -1
  94. package/dist/os/rfc/handlers/implement-stamp.d.ts.map +1 -1
  95. package/dist/os/rfc/handlers/implement-stamp.js +7 -3
  96. package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
  97. package/dist/os/rfc/handlers/index-graph.d.ts.map +1 -1
  98. package/dist/os/rfc/handlers/index-graph.js +6 -1
  99. package/dist/os/rfc/handlers/index-graph.js.map +1 -1
  100. package/dist/os/rfc/handlers/lifecycle.d.ts.map +1 -1
  101. package/dist/os/rfc/handlers/lifecycle.js +6 -1
  102. package/dist/os/rfc/handlers/lifecycle.js.map +1 -1
  103. package/dist/os/rfc/handlers/list-create.d.ts.map +1 -1
  104. package/dist/os/rfc/handlers/list-create.js +6 -1
  105. package/dist/os/rfc/handlers/list-create.js.map +1 -1
  106. package/dist/os/rfc/handlers/pipeline-status.d.ts.map +1 -1
  107. package/dist/os/rfc/handlers/pipeline-status.js +6 -1
  108. package/dist/os/rfc/handlers/pipeline-status.js.map +1 -1
  109. package/dist/os/rfc/handlers/supersede-propose.d.ts.map +1 -1
  110. package/dist/os/rfc/handlers/supersede-propose.js +6 -1
  111. package/dist/os/rfc/handlers/supersede-propose.js.map +1 -1
  112. package/dist/os/rfc/handlers/validate-rules.d.ts.map +1 -1
  113. package/dist/os/rfc/handlers/validate-rules.js +7 -3
  114. package/dist/os/rfc/handlers/validate-rules.js.map +1 -1
  115. package/dist/os/rfc/handlers/validate.d.ts.map +1 -1
  116. package/dist/os/rfc/handlers/validate.js +6 -1
  117. package/dist/os/rfc/handlers/validate.js.map +1 -1
  118. package/dist/os/rfc/index.d.ts.map +1 -1
  119. package/dist/os/rfc/index.js +6 -1
  120. package/dist/os/rfc/index.js.map +1 -1
  121. package/dist/os/rfc/rfc.module.d.ts.map +1 -1
  122. package/dist/os/rfc/rfc.module.js +6 -1
  123. package/dist/os/rfc/rfc.module.js.map +1 -1
  124. package/dist/os/rfc/types.d.ts +7 -4
  125. package/dist/os/rfc/types.d.ts.map +1 -1
  126. package/dist/os/rfc/types.js +7 -4
  127. package/dist/os/rfc/types.js.map +1 -1
  128. package/dist/os/session/handlers/save.d.ts.map +1 -1
  129. package/dist/os/session/handlers/save.js +6 -1
  130. package/dist/os/session/handlers/save.js.map +1 -1
  131. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.d.ts.map +1 -1
  132. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js +6 -1
  133. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js.map +1 -1
  134. package/dist/os/werkstatt/handlers/workspace-deps.js +3 -3
  135. package/dist/os/werkstatt/handlers/workspace-deps.js.map +1 -1
  136. package/dist/os/workflow/index.d.ts.map +1 -1
  137. package/dist/os/workflow/index.js +6 -1
  138. package/dist/os/workflow/index.js.map +1 -1
  139. package/dist/src/config/forge-config.d.ts +62 -4
  140. package/dist/src/config/forge-config.d.ts.map +1 -1
  141. package/dist/src/config/forge-config.js +35 -19
  142. package/dist/src/config/forge-config.js.map +1 -1
  143. package/dist/src/forge-module.d.ts.map +1 -1
  144. package/dist/src/forge-module.js +6 -1
  145. package/dist/src/forge-module.js.map +1 -1
  146. package/dist/src/index.d.ts.map +1 -1
  147. package/dist/src/index.js +10 -2
  148. package/dist/src/index.js.map +1 -1
  149. package/dist/src/migration-adapters/git-utils.d.ts.map +1 -1
  150. package/dist/src/migration-adapters/git-utils.js +6 -2
  151. package/dist/src/migration-adapters/git-utils.js.map +1 -1
  152. package/dist/src/migration-adapters/ignored-files.d.ts.map +1 -1
  153. package/dist/src/migration-adapters/ignored-files.js +6 -1
  154. package/dist/src/migration-adapters/ignored-files.js.map +1 -1
  155. package/dist/src/migration-adapters/index.d.ts.map +1 -1
  156. package/dist/src/migration-adapters/index.js +4 -1
  157. package/dist/src/migration-adapters/index.js.map +1 -1
  158. package/dist/src/migration-adapters/types.d.ts.map +1 -1
  159. package/dist/src/migration-adapters/types.js +6 -2
  160. package/dist/src/migration-adapters/types.js.map +1 -1
  161. package/dist/src/onboarding/agents-generate.d.ts.map +1 -1
  162. package/dist/src/onboarding/agents-generate.js +18 -14
  163. package/dist/src/onboarding/agents-generate.js.map +1 -1
  164. package/dist/src/onboarding/create.d.ts.map +1 -1
  165. package/dist/src/onboarding/create.js +7 -6
  166. package/dist/src/onboarding/create.js.map +1 -1
  167. package/dist/src/onboarding/doctor.d.ts.map +1 -1
  168. package/dist/src/onboarding/doctor.js +7 -13
  169. package/dist/src/onboarding/doctor.js.map +1 -1
  170. package/dist/src/onboarding/init.d.ts.map +1 -1
  171. package/dist/src/onboarding/init.js +7 -12
  172. package/dist/src/onboarding/init.js.map +1 -1
  173. package/dist/src/onboarding/invariant-engine.d.ts.map +1 -1
  174. package/dist/src/onboarding/invariant-engine.js +7 -2
  175. package/dist/src/onboarding/invariant-engine.js.map +1 -1
  176. package/dist/src/onboarding/nested-agents-generate.d.ts.map +1 -1
  177. package/dist/src/onboarding/nested-agents-generate.js +7 -2
  178. package/dist/src/onboarding/nested-agents-generate.js.map +1 -1
  179. package/dist/src/onboarding/nested-agents-templates.d.ts.map +1 -1
  180. package/dist/src/onboarding/nested-agents-templates.js +11 -3
  181. package/dist/src/onboarding/nested-agents-templates.js.map +1 -1
  182. package/dist/src/onboarding/scaffold-project.d.ts.map +1 -1
  183. package/dist/src/onboarding/scaffold-project.js +6 -1
  184. package/dist/src/onboarding/scaffold-project.js.map +1 -1
  185. package/dist/src/onboarding/upgrade.d.ts.map +1 -1
  186. package/dist/src/onboarding/upgrade.js +7 -3
  187. package/dist/src/onboarding/upgrade.js.map +1 -1
  188. package/dist/src/profiles/profile-schema.d.ts +54 -4
  189. package/dist/src/profiles/profile-schema.d.ts.map +1 -1
  190. package/dist/src/profiles/profile-schema.js +34 -14
  191. package/dist/src/profiles/profile-schema.js.map +1 -1
  192. package/dist/src/profiles/stack-profile.d.ts +24 -0
  193. package/dist/src/profiles/stack-profile.d.ts.map +1 -1
  194. package/dist/src/profiles/stack-profile.js +7 -3
  195. package/dist/src/profiles/stack-profile.js.map +1 -1
  196. package/dist/src/registry.d.ts.map +1 -1
  197. package/dist/src/registry.js +7 -9
  198. package/dist/src/registry.js.map +1 -1
  199. package/dist/src/types.d.ts.map +1 -1
  200. package/dist/src/types.js +6 -1
  201. package/dist/src/types.js.map +1 -1
  202. package/dist/src/utils/fs-atomic.d.ts.map +1 -1
  203. package/dist/src/utils/fs-atomic.js +13 -1
  204. package/dist/src/utils/fs-atomic.js.map +1 -1
  205. package/dist/src/utils/fs-idempotent.d.ts.map +1 -1
  206. package/dist/src/utils/fs-idempotent.js +13 -0
  207. package/dist/src/utils/fs-idempotent.js.map +1 -1
  208. package/dist/src/utils/fs-trash-sync.d.ts.map +1 -1
  209. package/dist/src/utils/fs-trash-sync.js +13 -1
  210. package/dist/src/utils/fs-trash-sync.js.map +1 -1
  211. package/dist/src/utils/fs-trash.d.ts.map +1 -1
  212. package/dist/src/utils/fs-trash.js +13 -1
  213. package/dist/src/utils/fs-trash.js.map +1 -1
  214. package/dist/src/utils/fs.d.ts.map +1 -1
  215. package/dist/src/utils/fs.js +14 -3
  216. package/dist/src/utils/fs.js.map +1 -1
  217. package/dist/src/utils/hash.d.ts.map +1 -1
  218. package/dist/src/utils/hash.js +12 -1
  219. package/dist/src/utils/hash.js.map +1 -1
  220. package/dist/src/utils/index.d.ts.map +1 -1
  221. package/dist/src/utils/index.js +13 -2
  222. package/dist/src/utils/index.js.map +1 -1
  223. package/dist/src/utils/string-utils.d.ts.map +1 -1
  224. package/dist/src/utils/string-utils.js +12 -1
  225. package/dist/src/utils/string-utils.js.map +1 -1
  226. package/dist/src/validators/port-validate.js +1 -1
  227. package/dist/src/validators/port-validate.js.map +1 -1
  228. package/dist/src/validators/skill-validate.d.ts.map +1 -1
  229. package/dist/src/validators/skill-validate.js +7 -8
  230. package/dist/src/validators/skill-validate.js.map +1 -1
  231. package/docs/getting-started.md +1 -1
  232. package/docs/reference/forge-yaml.md +38 -9
  233. package/docs/reference/profiles.md +8 -8
  234. package/os/adr/handlers/list-create.ts +4 -1
  235. package/os/adr/handlers/validate.ts +6 -1
  236. package/os/adr/types.ts +7 -3
  237. package/os/compass/compass.module.ts +79 -13
  238. package/os/compass/handlers/compass-audit-handler.ts +22 -3
  239. package/os/compass/handlers/compass-change-summary-handler.ts +55 -227
  240. package/os/compass/handlers/compass-inventory-handler.ts +30 -12
  241. package/os/compass/handlers/compass-inventory.ts +103 -240
  242. package/os/compass/handlers/compass-migrate-handler.ts +122 -0
  243. package/os/compass/handlers/compass-migrate.ts +361 -0
  244. package/os/compass/handlers/resolve-scan-root-package.test.ts +70 -0
  245. package/os/compass/handlers/resolve-scan-root.ts +15 -8
  246. package/os/compass/handlers/summary-record.ts +313 -0
  247. package/os/compass/handlers/tests/compass-migrate.test.ts +291 -0
  248. package/os/compass/handlers/tests/compass-policy.test.ts +249 -0
  249. package/os/compass/handlers/tests/compass-v2-contract.test.ts +9 -9
  250. package/os/compass/handlers/tests/summary-record.test.ts +224 -0
  251. package/os/compass/index.ts +23 -5
  252. package/os/compass/policy.ts +350 -0
  253. package/os/core/core.module.ts +11 -23
  254. package/os/core/handlers/forge-autonomy-validate.ts +7 -1
  255. package/os/core/handlers/package-health.ts +6 -1
  256. package/os/core/handlers/pinned-check.ts +6 -1
  257. package/os/core/handlers/pinned-validate.ts +6 -1
  258. package/os/core/handlers/validate.ts +6 -1
  259. package/os/exploration/exploration.module.ts +72 -71
  260. package/os/exploration/handlers/list.ts +4 -1
  261. package/os/mission/handlers/archive.ts +7 -3
  262. package/os/mission/index.ts +14 -0
  263. package/os/notes/index.ts +7 -1
  264. package/os/rfc/frontmatter-io.ts +6 -1
  265. package/os/rfc/handlers/archive.ts +6 -1
  266. package/os/rfc/handlers/implement-stamp.ts +7 -3
  267. package/os/rfc/handlers/index-graph.ts +6 -1
  268. package/os/rfc/handlers/lifecycle.ts +6 -1
  269. package/os/rfc/handlers/list-create.ts +6 -1
  270. package/os/rfc/handlers/pipeline-status.ts +6 -1
  271. package/os/rfc/handlers/supersede-propose.ts +6 -1
  272. package/os/rfc/handlers/validate-rules.ts +7 -3
  273. package/os/rfc/handlers/validate.ts +6 -1
  274. package/os/rfc/index.ts +6 -1
  275. package/os/rfc/rfc.module.ts +6 -1
  276. package/os/rfc/types.ts +7 -4
  277. package/os/session/handlers/save.ts +6 -1
  278. package/os/werkstatt/handlers/werkstatt-lock-recover.ts +6 -1
  279. package/os/werkstatt/handlers/workspace-deps.ts +3 -3
  280. package/os/workflow/index.ts +6 -1
  281. package/package.json +1 -1
  282. package/profiles/{godot-csharp.yaml → godot-game.yaml} +2 -2
  283. package/profiles/{knowledge-typescript-turborepo.yaml → knowledge.yaml} +1 -1
  284. package/profiles/{phaser-turborepo.yaml → phaser-game.yaml} +2 -2
  285. package/profiles/{typescript-turborepo.yaml → typescript.yaml} +2 -2
  286. package/skills/fo/fo-add-tests/SKILL.md +14 -0
  287. package/skills/fo/fo-architecture/SKILL.md +14 -0
  288. package/skills/fo/fo-compass-annotate/SKILL.md +14 -0
  289. package/skills/fo/fo-design-summit/SKILL.md +14 -0
  290. package/skills/fo/fo-doc-audit/SKILL.md +14 -0
  291. package/skills/fo/fo-explore/SKILL.md +14 -0
  292. package/skills/fo/fo-extract-dna/SKILL.md +14 -0
  293. package/skills/fo/fo-fix/SKILL.md +14 -0
  294. package/skills/fo/fo-handoff/SKILL.md +14 -0
  295. package/skills/fo/fo-harvest/SKILL.md +14 -0
  296. package/skills/fo/fo-idea/SKILL.md +14 -0
  297. package/skills/fo/fo-idea-audit/SKILL.md +14 -0
  298. package/skills/fo/fo-idea-create-adr/SKILL.md +14 -0
  299. package/skills/fo/fo-idea-create-rfc/SKILL.md +14 -0
  300. package/skills/fo/fo-idea-enhance/SKILL.md +14 -0
  301. package/skills/fo/fo-idea-i-just-want-to-see-the-plan/SKILL.md +14 -0
  302. package/skills/fo/fo-idea-i-just-want-to-see-the-result/SKILL.md +14 -0
  303. package/skills/fo/fo-idea-implement/SKILL.md +14 -0
  304. package/skills/fo/fo-idea-plan/SKILL.md +14 -0
  305. package/skills/fo/fo-idea-status/SKILL.md +14 -0
  306. package/skills/fo/fo-knowledge-distill/SKILL.md +14 -0
  307. package/skills/fo/fo-memory-sync/SKILL.md +14 -0
  308. package/skills/fo/fo-qa/SKILL.md +14 -0
  309. package/skills/fo/fo-review/SKILL.md +14 -0
  310. package/skills/fo/fo-session-retro/SKILL.md +14 -0
  311. package/skills/fo/fo-session-save/SKILL.md +14 -0
  312. package/skills/fo/fo-spec-ingest/SKILL.md +14 -0
  313. package/skills/fo/fo-step-commit/SKILL.md +14 -0
  314. package/skills/fo/fo-triage/SKILL.md +14 -0
  315. package/skills/meta/forge-bootstrap/SKILL.md +14 -0
  316. package/skills/meta/port-to-forge/SKILL.md +14 -0
  317. package/skills/meta/skill-create/SKILL.md +14 -0
  318. package/skills/shared/grilling/SKILL.md +14 -0
  319. package/skills/shared/my-preferences/SKILL.md +14 -0
  320. package/skills/shared/windows-ai-tooling/SKILL.md +14 -0
  321. package/skills/shared/writing-great-skills/SKILL.md +14 -0
  322. package/src/config/forge-config.ts +40 -23
  323. package/src/forge-module.ts +6 -1
  324. package/src/index.ts +10 -2
  325. package/src/migration-adapters/git-utils.ts +6 -2
  326. package/src/migration-adapters/ignored-files.ts +6 -1
  327. package/src/migration-adapters/index.ts +4 -1
  328. package/src/migration-adapters/types.ts +6 -2
  329. package/src/onboarding/agents-generate.ts +23 -14
  330. package/src/onboarding/create.ts +7 -6
  331. package/src/onboarding/doctor.ts +7 -13
  332. package/src/onboarding/init.ts +7 -12
  333. package/src/onboarding/invariant-engine.ts +7 -2
  334. package/src/onboarding/nested-agents-generate.ts +7 -2
  335. package/src/onboarding/nested-agents-templates.ts +11 -3
  336. package/src/onboarding/scaffold-project.ts +6 -1
  337. package/src/onboarding/upgrade.ts +7 -3
  338. package/src/profiles/profile-schema.ts +42 -18
  339. package/src/profiles/stack-profile.ts +7 -3
  340. package/src/registry.ts +7 -9
  341. package/src/tests/agents-generate-domain.test.ts +3 -3
  342. package/src/tests/agents-generate.test.ts +2 -2
  343. package/src/tests/create.test.ts +4 -4
  344. package/src/tests/forge-autonomy-validate.test.ts +1 -1
  345. package/src/tests/package-files.test.ts +53 -1
  346. package/src/tests/profile-schema.test.ts +4 -4
  347. package/src/tests/scaffold-project.test.ts +3 -3
  348. package/src/tests/stack-profile.test.ts +12 -12
  349. package/src/types.ts +6 -1
  350. package/src/utils/fs-atomic.ts +13 -1
  351. package/src/utils/fs-idempotent.ts +13 -0
  352. package/src/utils/fs-trash-sync.ts +13 -1
  353. package/src/utils/fs-trash.ts +13 -1
  354. package/src/utils/fs.ts +14 -3
  355. package/src/utils/hash.ts +12 -1
  356. package/src/utils/index.ts +13 -2
  357. package/src/utils/string-utils.ts +12 -1
  358. package/src/validators/port-validate.ts +1 -1
  359. package/src/validators/skill-validate.ts +7 -8
  360. package/skills/shared/extension-e2e-mitm/SKILL.md +0 -53
  361. package/skills/shared/extension-e2e-mitm/fixture-proxy.ts +0 -113
  362. package/src/types/werkstatt-engine-shims.d.ts +0 -1416
  363. package/src/types/werkstatt-shared-shims.d.ts +0 -5686
@@ -0,0 +1,361 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>compass.migrate domain logic — the v1 to v2 Compass header codemod
4
+ (RFC-1097). Rewrites authored file headers in place: collapses CHANGE_SUMMARY
5
+ windows into history, strips forbidden v1 blocks, seeds KEY_DECISIONS from
6
+ ai-invariant comments, reorders blocks to canonical order, and reports a
7
+ closed action union per file. Pure per-file transform plus a workspace
8
+ walker; the kernel handler lives in compass-migrate-handler.ts.</purpose>
9
+ <non-goals>
10
+ <item>Do not author headers from scratch — files with no Compass header are reported no-header and skipped; the agent sweep writes them.</item>
11
+ <item>Do not rewrite purpose text — boilerplate purposes are flagged for the sweep, not auto-fixed.</item>
12
+ <item>Do not import @warpgogol/* packages — this module is autonomous (FORGE-AUTONOMY-01).</item>
13
+ </non-goals>
14
+ </MODULE_CONTRACT>
15
+ <KEY_DECISIONS>
16
+ <item>migrateFile is a pure source-to-source function so every action is unit-testable without I/O.</item>
17
+ <item>Collapse reuses the summary.trim repair semantics — ID-less items dropped, overflow IDs merged into history.</item>
18
+ <item>Seeded KEY_DECISIONS strip the leading governance-ID prefix so items satisfy COMPASS-KD-05 immediately.</item>
19
+ <item>Reorder only fires when the inter-block region is whitespace — interleaved content is left for the sweep.</item>
20
+ </KEY_DECISIONS>
21
+ <CHANGE_SUMMARY>
22
+ <item>RFC-1097: initial codemod — migrateFile pure transform, migrateWorkspace walker, closed action union.</item>
23
+ <item>RFC-1097: steps 1-4 — compass.migrate codemod
24
+
25
+ Add the v1 to v2 Compass header codemod: migrateFile pure transform (collapse, strip, seed, reorder, purpose-flag actions), migrateWorkspace walker, runCompassMigrate handler with dirty-tree refusal and --force/--files/--dry-run flags, module registration, and 15 unit tests.</item>
26
+ </CHANGE_SUMMARY>
27
+ */
28
+
29
+ import { readFile } from "node:fs/promises";
30
+ import { relative, resolve } from "node:path";
31
+ import {
32
+ createCompassInventoryEntries,
33
+ detectRiskClass,
34
+ getEntrySource,
35
+ getRelativeSegments,
36
+ getWorkspaceRelativeSegments,
37
+ } from "./compass-inventory.ts";
38
+ import {
39
+ buildChangeSummaryBlock,
40
+ CHANGE_SUMMARY_WINDOW,
41
+ getLineCommentPrefix,
42
+ mergeHistoryIds,
43
+ parseChangeSummary,
44
+ } from "./summary-record.ts";
45
+ import { writeFileIfChanged } from "../../../src/utils/fs-idempotent.ts";
46
+ import type { CompassPolicy } from "../policy.ts";
47
+ import type { ForgeCommandInput } from "../../../src/types.ts";
48
+
49
+ export type MigrateAction =
50
+ | "collapsed"
51
+ | "stripped"
52
+ | "seeded"
53
+ | "todo"
54
+ | "purpose-flagged"
55
+ | "reordered"
56
+ | "unparseable"
57
+ | "no-header"
58
+ | "unchanged";
59
+
60
+ export interface MigrateFileResult {
61
+ source: string;
62
+ actions: MigrateAction[];
63
+ }
64
+
65
+ export interface MigrateResult {
66
+ scanned: number;
67
+ files: Array<{ path: string; actions: MigrateAction[] }>;
68
+ }
69
+
70
+ export interface MigrateOptions {
71
+ /** Explicit root-relative file list — bypasses scan-root filtering entirely. */
72
+ files?: string[];
73
+ /** Compute actions without writing. */
74
+ dryRun?: boolean;
75
+ }
76
+
77
+ const HEADER_SCAN_LINES = 120;
78
+ const KEY_DECISIONS_MAX_ITEMS = 7;
79
+ const TODO_ITEM = "TODO: record current design decisions";
80
+
81
+ const COMPASS_TAGS = ["MODULE_CONTRACT", "KEY_DECISIONS", "CHANGE_SUMMARY"] as const;
82
+ type CompassTag = (typeof COMPASS_TAGS)[number];
83
+
84
+ const FORBIDDEN_BLOCK_TAGS = ["MODULE_MAP", "keywords", "responsibilities"] as const;
85
+ const COMPASS_BLOCK_ANCHOR_RE = /[ \t]*<\/?COMPASS_BLOCK\b[^>]*>[ \t]*/g;
86
+
87
+ function blockSpan(source: string, tag: string): { start: number; end: number } | null {
88
+ const open = source.indexOf(`<${tag}>`);
89
+ if (open < 0) return null;
90
+ const closeTag = `</${tag}>`;
91
+ const close = source.indexOf(closeTag, open);
92
+ if (close < 0) return null;
93
+ return { start: open, end: close + closeTag.length };
94
+ }
95
+
96
+ function hasUnclosedTag(source: string, tag: string): boolean {
97
+ return source.includes(`<${tag}>`) && !source.includes(`</${tag}>`);
98
+ }
99
+
100
+ function inHeaderRegion(source: string, index: number): boolean {
101
+ return source.slice(0, index).split("\n").length <= HEADER_SCAN_LINES;
102
+ }
103
+
104
+ /** Collect ai-invariant comment texts, deduped, capped, ID-prefix stripped. */
105
+ export function collectAiInvariants(source: string, policy: CompassPolicy): string[] {
106
+ const items: string[] = [];
107
+ const seen = new Set<string>();
108
+ const re = /@ai-invariant:?\s+([^\n*]+)/g;
109
+ let m: RegExpExecArray | null;
110
+ while ((m = re.exec(source)) !== null) {
111
+ let text = m[1]!.replace(/(-->|\*\/)\s*$/, "").trim();
112
+ // KD-05: seeded items must not lead with a governance-ID prefix.
113
+ const idMatch = text.match(policy.idPatternPrefix);
114
+ if (idMatch) {
115
+ text = text
116
+ .slice(idMatch[0].length)
117
+ .replace(/^\s*[:—-]\s*/, "")
118
+ .trim();
119
+ }
120
+ if (text.length === 0 || seen.has(text)) continue;
121
+ seen.add(text);
122
+ items.push(text);
123
+ if (items.length >= KEY_DECISIONS_MAX_ITEMS) break;
124
+ }
125
+ return items;
126
+ }
127
+
128
+ function buildKeyDecisionsBlock(items: string[], filePath: string): string {
129
+ const lines = ["<KEY_DECISIONS>"];
130
+ for (const item of items) {
131
+ lines.push(` <item>${item}</item>`);
132
+ }
133
+ lines.push("</KEY_DECISIONS>");
134
+ const prefix = getLineCommentPrefix(filePath);
135
+ if (prefix) {
136
+ // New block: every line needs the line-comment prefix (unlike block
137
+ // replacement where the first line already carries one).
138
+ return lines.map((line) => prefix + line).join("\n");
139
+ }
140
+ return lines.join("\n");
141
+ }
142
+
143
+ function extractPurposeText(source: string): string {
144
+ const contract = blockSpan(source, "MODULE_CONTRACT");
145
+ if (!contract) return "";
146
+ const contractText = source.slice(contract.start, contract.end);
147
+ const purposeMatch = contractText.match(/<purpose>([\s\S]*?)<\/purpose>/);
148
+ return purposeMatch ? purposeMatch[1]!.replace(/<[^>]+>/g, " ").trim() : "";
149
+ }
150
+
151
+ /**
152
+ * Pure v1 to v2 transform of one file's source. Returns the rewritten source
153
+ * and the closed action union. `unchanged` is exclusive; every other action
154
+ * may combine. Never throws on malformed input — reports `unparseable`.
155
+ */
156
+ export function migrateFile(
157
+ source: string,
158
+ policy: CompassPolicy,
159
+ pathFromRoot: string,
160
+ workspaceRelativePath: string,
161
+ ): MigrateFileResult {
162
+ const actions: MigrateAction[] = [];
163
+
164
+ // 1. Header detection — a Compass header lives in the header region only.
165
+ const mcIndex = source.indexOf("<MODULE_CONTRACT>");
166
+ const csIndex = source.indexOf("<CHANGE_SUMMARY>");
167
+ const hasHeader =
168
+ (mcIndex >= 0 && inHeaderRegion(source, mcIndex)) ||
169
+ (csIndex >= 0 && inHeaderRegion(source, csIndex));
170
+ if (!hasHeader) {
171
+ return { source, actions: ["no-header"] };
172
+ }
173
+
174
+ // 2. Parseability — an open tag without its close is a broken header.
175
+ for (const tag of COMPASS_TAGS) {
176
+ if (hasUnclosedTag(source, tag)) {
177
+ return { source, actions: ["unparseable"] };
178
+ }
179
+ }
180
+
181
+ let next = source;
182
+
183
+ // 3. Collapse CHANGE_SUMMARY — same repair semantics as compass.summary.trim.
184
+ const csSpan = blockSpan(next, "CHANGE_SUMMARY");
185
+ if (csSpan) {
186
+ const block = next.slice(csSpan.start, csSpan.end);
187
+ const { items, historyIds } = parseChangeSummary(block);
188
+ const idItems = items.filter((item) => policy.idPatternPrefix.test(item));
189
+ const collapsedIds: string[] = [];
190
+ while (idItems.length > CHANGE_SUMMARY_WINDOW) {
191
+ const oldest = idItems.shift()!;
192
+ const idMatch = oldest.match(policy.idPatternPrefix);
193
+ if (idMatch) collapsedIds.push(idMatch[0]);
194
+ }
195
+ const nextHistory = mergeHistoryIds(historyIds, collapsedIds, policy);
196
+ const changed =
197
+ idItems.length !== items.length ||
198
+ collapsedIds.length > 0 ||
199
+ nextHistory.length !== historyIds.length ||
200
+ nextHistory.some((id, i) => id !== historyIds[i]);
201
+ if (changed) {
202
+ const newBlock = buildChangeSummaryBlock(idItems, nextHistory, pathFromRoot);
203
+ next = next.slice(0, csSpan.start) + newBlock + next.slice(csSpan.end);
204
+ actions.push("collapsed");
205
+ }
206
+ }
207
+
208
+ // 4. Strip forbidden v1 blocks and COMPASS_BLOCK anchors.
209
+ let stripped = next;
210
+ for (const tag of FORBIDDEN_BLOCK_TAGS) {
211
+ const tagRe = new RegExp(`[ \\t]*<${tag}>[\\s\\S]*?</${tag}>[ \\t]*`, "g");
212
+ stripped = stripped.replace(tagRe, "");
213
+ }
214
+ stripped = stripped.replace(COMPASS_BLOCK_ANCHOR_RE, "");
215
+ if (stripped !== next) {
216
+ next = stripped;
217
+ actions.push("stripped");
218
+ }
219
+
220
+ // 5. Seed KEY_DECISIONS on medium/high-risk files that lack the block.
221
+ const riskClass = detectRiskClass(pathFromRoot, workspaceRelativePath, policy);
222
+ const kdRequired = riskClass === "medium" || riskClass === "high";
223
+ if (kdRequired && !next.includes("<KEY_DECISIONS>")) {
224
+ const invariants = collectAiInvariants(next, policy);
225
+ const items = invariants.length > 0 ? invariants : [TODO_ITEM];
226
+ const kdBlock = buildKeyDecisionsBlock(items, pathFromRoot);
227
+ const mcSpan = blockSpan(next, "MODULE_CONTRACT");
228
+ if (mcSpan) {
229
+ next = next.slice(0, mcSpan.end) + "\n" + kdBlock + next.slice(mcSpan.end);
230
+ } else {
231
+ const csSpan2 = blockSpan(next, "CHANGE_SUMMARY");
232
+ if (csSpan2) {
233
+ next = next.slice(0, csSpan2.start) + kdBlock + "\n" + next.slice(csSpan2.start);
234
+ }
235
+ }
236
+ actions.push(invariants.length > 0 ? "seeded" : "todo");
237
+ }
238
+
239
+ // 6. Reorder blocks to canonical order — only when the region between the
240
+ // outermost blocks is whitespace and the blocks themselves.
241
+ const spans = COMPASS_TAGS.map((tag) => ({ tag, span: blockSpan(next, tag) }))
242
+ .filter(
243
+ (entry): entry is { tag: CompassTag; span: { start: number; end: number } } =>
244
+ entry.span !== null,
245
+ )
246
+ .sort((a, b) => a.span.start - b.span.start);
247
+ if (spans.length >= 2) {
248
+ const canonicalOrder = spans
249
+ .slice()
250
+ .sort((a, b) => COMPASS_TAGS.indexOf(a.tag) - COMPASS_TAGS.indexOf(b.tag))
251
+ .map((entry) => entry.tag);
252
+ const currentOrder = spans.map((entry) => entry.tag);
253
+ const outOfOrder = currentOrder.some((tag, i) => tag !== canonicalOrder[i]);
254
+ if (outOfOrder) {
255
+ const minStart = Math.min(...spans.map((entry) => entry.span.start));
256
+ const maxEnd = Math.max(...spans.map((entry) => entry.span.end));
257
+ const region = next.slice(minStart, maxEnd);
258
+ const residue = region
259
+ .replace(/<MODULE_CONTRACT>[\s\S]*?<\/MODULE_CONTRACT>/, "")
260
+ .replace(/<KEY_DECISIONS>[\s\S]*?<\/KEY_DECISIONS>/, "")
261
+ .replace(/<CHANGE_SUMMARY>[\s\S]*?<\/CHANGE_SUMMARY>/, "");
262
+ if (residue.trim().length === 0) {
263
+ const ordered = canonicalOrder.map((tag) => {
264
+ const span = spans.find((entry) => entry.tag === tag)!.span;
265
+ return next.slice(span.start, span.end);
266
+ });
267
+ next = next.slice(0, minStart) + ordered.join("\n") + next.slice(maxEnd);
268
+ actions.push("reordered");
269
+ }
270
+ }
271
+ }
272
+
273
+ // 7. Flag boilerplate purpose — report only, the sweep rewrites the text.
274
+ const purposeText = extractPurposeText(next);
275
+ if (
276
+ purposeText.length > 0 &&
277
+ policy.purposeBoilerplatePatterns.some((pattern) => pattern.test(purposeText))
278
+ ) {
279
+ actions.push("purpose-flagged");
280
+ }
281
+
282
+ if (actions.length === 0 || next === source) {
283
+ const reportOnly = actions.filter((a) => a === "purpose-flagged");
284
+ return {
285
+ source,
286
+ actions: reportOnly.length > 0 ? reportOnly : ["unchanged"],
287
+ };
288
+ }
289
+
290
+ return { source: next, actions };
291
+ }
292
+
293
+ interface MigrateTarget {
294
+ absPath: string;
295
+ pathFromRoot: string;
296
+ workspaceRelativePath: string;
297
+ }
298
+
299
+ function toTarget(workspaceRoot: string, absPath: string, policy: CompassPolicy): MigrateTarget {
300
+ const pathFromRoot = relative(workspaceRoot, absPath).replace(/\\/g, "/");
301
+ const segments = getRelativeSegments(absPath, workspaceRoot);
302
+ const workspaceRelativePath = getWorkspaceRelativeSegments(segments, policy).join("/");
303
+ return { absPath, pathFromRoot, workspaceRelativePath };
304
+ }
305
+
306
+ /**
307
+ * Walk the workspace (or an explicit file list) and apply migrateFile to every
308
+ * authored file. Writes via writeFileIfChanged unless dryRun.
309
+ */
310
+ export async function migrateWorkspace(
311
+ workspaceRoot: string,
312
+ input: ForgeCommandInput,
313
+ scanRoot: string | undefined,
314
+ policy: CompassPolicy,
315
+ options: MigrateOptions,
316
+ ): Promise<MigrateResult> {
317
+ const result: MigrateResult = { scanned: 0, files: [] };
318
+
319
+ if (options.files && options.files.length > 0) {
320
+ for (const file of options.files) {
321
+ const absPath = resolve(scanRoot ?? workspaceRoot, file);
322
+ const target = toTarget(workspaceRoot, absPath, policy);
323
+ let source: string;
324
+ try {
325
+ source = await readFile(absPath, "utf8");
326
+ } catch {
327
+ result.files.push({ path: file, actions: ["unparseable"] });
328
+ continue;
329
+ }
330
+ result.scanned += 1;
331
+ const migrated = migrateFile(
332
+ source,
333
+ policy,
334
+ target.pathFromRoot,
335
+ target.workspaceRelativePath,
336
+ );
337
+ result.files.push({ path: target.pathFromRoot, actions: migrated.actions });
338
+ if (!options.dryRun && migrated.source !== source) {
339
+ await writeFileIfChanged(absPath, migrated.source);
340
+ }
341
+ }
342
+ return result;
343
+ }
344
+
345
+ const entries = await createCompassInventoryEntries(workspaceRoot, input, scanRoot, policy);
346
+ for (const entry of entries) {
347
+ if (entry.authoringStatus !== "authored") continue;
348
+ result.scanned += 1;
349
+ const absPath = resolve(workspaceRoot, entry.path);
350
+ const source = getEntrySource(entry) ?? (await readFile(absPath, "utf8"));
351
+ const segments = getRelativeSegments(absPath, workspaceRoot);
352
+ const workspaceRelativePath = getWorkspaceRelativeSegments(segments, policy).join("/");
353
+ const migrated = migrateFile(source, policy, entry.path, workspaceRelativePath);
354
+ result.files.push({ path: entry.path, actions: migrated.actions });
355
+ if (!options.dryRun && migrated.source !== source) {
356
+ await writeFileIfChanged(absPath, migrated.source);
357
+ }
358
+ }
359
+
360
+ return result;
361
+ }
@@ -0,0 +1,70 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtempSync, mkdirSync, rmSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { resolveCompassScanRoot } from "./resolve-scan-root.ts";
6
+ import type { ForgeCommandInput, ForgeRuntimeContext } from "../../../src/types.ts";
7
+
8
+ function makeContext(workspaceRoot: string, siteExplicit = false): ForgeRuntimeContext {
9
+ return {
10
+ workspaceRoot,
11
+ site: undefined,
12
+ siteExplicit,
13
+ dryRun: false,
14
+ logger: { info: () => {}, warn: () => {}, error: () => {} },
15
+ } as unknown as ForgeRuntimeContext;
16
+ }
17
+
18
+ function makeInput(flags: Record<string, unknown> = {}): ForgeCommandInput {
19
+ return { flags } as ForgeCommandInput;
20
+ }
21
+
22
+ describe("resolveCompassScanRoot --package", () => {
23
+ let tempDir: string;
24
+
25
+ beforeEach(() => {
26
+ tempDir = mkdtempSync(join(tmpdir(), "compass-package-test-"));
27
+ });
28
+
29
+ afterEach(() => {
30
+ rmSync(tempDir, { recursive: true, force: true });
31
+ });
32
+
33
+ it("implies --packages scope: resolves to packages/<name>/src when src exists", () => {
34
+ mkdirSync(join(tempDir, "packages", "my-pkg", "src"), { recursive: true });
35
+ const result = resolveCompassScanRoot(makeInput({ package: "my-pkg" }), makeContext(tempDir));
36
+ expect(result).toBe(join(tempDir, "packages", "my-pkg", "src"));
37
+ });
38
+
39
+ it("implies --packages scope: resolves to packages/<name> when no src dir", () => {
40
+ mkdirSync(join(tempDir, "packages", "my-pkg"), { recursive: true });
41
+ const result = resolveCompassScanRoot(makeInput({ package: "my-pkg" }), makeContext(tempDir));
42
+ expect(result).toBe(join(tempDir, "packages", "my-pkg"));
43
+ });
44
+
45
+ it("throws when --package and --workpiece are both set", () => {
46
+ expect(() =>
47
+ resolveCompassScanRoot(
48
+ makeInput({ package: "my-pkg", workpiece: "some/path" }),
49
+ makeContext(tempDir),
50
+ ),
51
+ ).toThrow("--workpiece and --packages are mutually exclusive");
52
+ });
53
+
54
+ it("throws when --package and --site are both set", () => {
55
+ expect(() =>
56
+ resolveCompassScanRoot(makeInput({ package: "my-pkg" }), makeContext(tempDir, true)),
57
+ ).toThrow("--site and --packages are mutually exclusive");
58
+ });
59
+
60
+ it("throws when the package does not exist", () => {
61
+ expect(() =>
62
+ resolveCompassScanRoot(makeInput({ package: "nonexistent" }), makeContext(tempDir)),
63
+ ).toThrow('Package "nonexistent" not found');
64
+ });
65
+
66
+ it("--packages without --package still scans the packages/ root", () => {
67
+ const result = resolveCompassScanRoot(makeInput({ packages: true }), makeContext(tempDir));
68
+ expect(result).toBe(join(tempDir, "packages"));
69
+ });
70
+ });
@@ -8,9 +8,18 @@ Moved from @warpgogol/site-kernel to @warpgogol/forge for full autonomous mode (
8
8
  </non-goals>
9
9
  </MODULE_CONTRACT>
10
10
  <CHANGE_SUMMARY>
11
- <item>Introduced as part of RFC-0015 to extend Compass commands to packages/.</item>
12
11
  <item>RFC-0556: moved canonical implementation from @warpgogol/site-kernel to @warpgogol/forge for autonomous mode.</item>
13
12
  <item>RFC-0617: added --workpiece flag for mission workpiece directory scanning.</item>
13
+ <item>RFC-1097: step 6 — compass.migrate codemod run
14
+
15
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
16
+ <item>RFC-1097: sweep — engine package clean
17
+
18
+ Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. engine package now 0 diagnostics.</item>
19
+ <item>RFC-1097: AC-4 banned literal in os/compass handlers
20
+
21
+ compass-migrate-handler hint used a consumer-specific run command — switched to generic 'pnpm exec forge run' convention. Reworded recorded CHANGE_SUMMARY items in 3 handlers to drop the consumer-specific literal. compass-policy AC-4 test green (65/65).</item>
22
+ <item>RFC-0617: fix — --package alone now implies --packages scope (was a silent no-op falling through to full-repo scan).</item>
14
23
  </CHANGE_SUMMARY>
15
24
  */
16
25
 
@@ -22,7 +31,9 @@ export function resolveCompassScanRoot(
22
31
  input: ForgeCommandInput,
23
32
  context: ForgeRuntimeContext,
24
33
  ): string | undefined {
25
- const hasPackages = input.flags["packages"] === true;
34
+ const packageName = input.flags["package"];
35
+ const hasPackage = typeof packageName === "string" && packageName.length > 0;
36
+ const hasPackages = input.flags["packages"] === true || hasPackage;
26
37
  const workpiecePath = input.flags["workpiece"];
27
38
  const hasWorkpiece = typeof workpiecePath === "string" && workpiecePath.length > 0;
28
39
 
@@ -56,15 +67,11 @@ export function resolveCompassScanRoot(
56
67
  return context.site ? context.site.directory : undefined;
57
68
  }
58
69
 
59
- const packageName = input.flags["package"];
60
- if (!packageName || typeof packageName !== "string") {
70
+ if (!hasPackage) {
61
71
  return resolve(context.workspaceRoot, "packages");
62
72
  }
63
73
 
64
- const candidates = [
65
- resolve(context.workspaceRoot, "packages", "os", packageName),
66
- resolve(context.workspaceRoot, "packages", packageName),
67
- ];
74
+ const candidates = [resolve(context.workspaceRoot, "packages", packageName)];
68
75
 
69
76
  for (const candidate of candidates) {
70
77
  if (existsSync(candidate)) {