forge-workflow 0.0.10 → 0.1.0-beta.3

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 (468) hide show
  1. package/.claude/rules/{greptile-review-process.md → review-process.md} +56 -41
  2. package/.claude/scripts/{greptile-resolve.sh → review-resolve.sh} +13 -3
  3. package/.cursor/rules/permissions-guidance.mdc +2 -2
  4. package/.forge/hooks/check-tdd.js +82 -5
  5. package/.forge/hooks/forge-native-hook.js +431 -0
  6. package/.forge/protected-paths.yaml +157 -0
  7. package/AGENTS.md +151 -61
  8. package/CHANGELOG.md +709 -0
  9. package/CLAUDE.md +9 -118
  10. package/QUICKSTART.md +175 -0
  11. package/README.md +275 -365
  12. package/bin/forge-cmd.js +120 -9
  13. package/bin/forge-preflight.js +26 -5
  14. package/bin/forge.js +532 -489
  15. package/docs/INDEX.md +93 -0
  16. package/docs/PROJECT_DESIGN.md +685 -0
  17. package/docs/architecture/index.md +66 -0
  18. package/docs/architecture/notes/README.md +35 -0
  19. package/docs/architecture/subsystems/README.md +46 -0
  20. package/docs/forge/TOOLCHAIN.md +670 -0
  21. package/docs/forge/VALIDATION.md +82 -0
  22. package/docs/{AGENT_INSTALL_PROMPT.md → guides/AGENT_INSTALL_PROMPT.md} +3 -3
  23. package/docs/guides/BEADS_GITHUB_SYNC.md +32 -0
  24. package/docs/{ENHANCED_ONBOARDING.md → guides/ENHANCED_ONBOARDING.md} +16 -12
  25. package/docs/guides/GREPTILE_SETUP.md +46 -0
  26. package/docs/guides/MANUAL_REVIEW_GUIDE.md +58 -0
  27. package/docs/guides/MIGRATION.md +56 -0
  28. package/docs/guides/SETUP.md +121 -0
  29. package/docs/guides/SUPPORT.md +190 -0
  30. package/docs/guides/WORKFLOW_TEMPLATES.md +74 -0
  31. package/docs/guides/memory-backends.md +183 -0
  32. package/docs/reference/ADAPTERS.md +128 -0
  33. package/docs/reference/AGENT_SKILL_PARITY.md +175 -0
  34. package/docs/reference/COMMANDS.md +214 -0
  35. package/docs/reference/DECISION_DRIFT_GUARDS.md +97 -0
  36. package/docs/{EXAMPLES.md → reference/EXAMPLES.md} +7 -5
  37. package/docs/reference/FORGE_KERNEL_STORAGE_MODEL.md +135 -0
  38. package/docs/reference/HERMES_INTEGRATION.md +118 -0
  39. package/docs/reference/INSIGHTS_RECAP.md +63 -0
  40. package/docs/reference/INSTALL.md +164 -0
  41. package/docs/reference/KERNEL_TAXONOMY_VALIDATION.md +161 -0
  42. package/docs/reference/PROTECTED_PATH_MANIFEST.md +25 -0
  43. package/docs/reference/RELEASE.md +68 -0
  44. package/docs/reference/RESEARCH_TEMPLATE.md +292 -0
  45. package/docs/{ROADMAP.md → reference/ROADMAP.md} +12 -9
  46. package/docs/reference/SKILLS.md +35 -0
  47. package/docs/reference/STATUS_BOARD.md +80 -0
  48. package/docs/reference/TEMPLATES.md +106 -0
  49. package/docs/{TOOLCHAIN.md → reference/TOOLCHAIN.md} +62 -47
  50. package/docs/reference/VALIDATION.md +82 -0
  51. package/docs/reference/agent-permissions.md +169 -0
  52. package/docs/reference/beads-to-kernel-migration-ux.md +61 -0
  53. package/docs/reference/control-plane-guarantees.md +125 -0
  54. package/docs/reference/dependency-chain.md +331 -0
  55. package/docs/reference/forge-kernel-issue-command-contract.md +161 -0
  56. package/docs/reference/forge-kernel-schema.md +72 -0
  57. package/docs/reference/kernel-conflict-evaluators.md +27 -0
  58. package/docs/reference/patch-md-format.md +77 -0
  59. package/docs/reference/protected-state-surfaces.md +59 -0
  60. package/docs/reference/shepherd.md +155 -0
  61. package/docs/reference/superpowers-analysis.md +320 -0
  62. package/docs/reference/superpowers-integration-options.md +404 -0
  63. package/docs/reference/test-environment.md +519 -0
  64. package/docs/reference/upgrade-safety.md +59 -0
  65. package/lefthook.yml +18 -0
  66. package/lib/activation/ensure-forge-home.js +135 -0
  67. package/lib/adapter-cli.js +307 -0
  68. package/lib/adapters/beads-issue-adapter.js +127 -0
  69. package/lib/adapters/beads-kernel-compat.js +1109 -0
  70. package/lib/adapters/greptile-review-adapter.js +141 -0
  71. package/lib/adapters/kernel-issue-adapter.js +101 -0
  72. package/lib/adapters/pr-state-adapter.js +484 -0
  73. package/lib/adoption-profiles.js +139 -0
  74. package/lib/agents/README.md +2 -6
  75. package/lib/agents/claude.plugin.json +3 -8
  76. package/lib/agents/codex.plugin.json +9 -1
  77. package/lib/agents/cursor.plugin.json +2 -6
  78. package/lib/agents/hermes.plugin.json +22 -0
  79. package/lib/agents-config.js +39 -1236
  80. package/lib/audit-evidence.js +282 -0
  81. package/lib/beads-detect.js +60 -0
  82. package/lib/beads-nudge.js +91 -0
  83. package/lib/beads-setup.js +121 -0
  84. package/lib/beads-sync-scaffold.js +25 -101
  85. package/lib/codex-skills.js +51 -1
  86. package/lib/commands/_aliases.js +248 -0
  87. package/lib/commands/_issue.js +780 -77
  88. package/lib/commands/_manifest.js +93 -0
  89. package/lib/commands/_registry.js +99 -34
  90. package/lib/commands/_resolve-command-opts.js +230 -0
  91. package/lib/commands/_serve-security.js +270 -0
  92. package/lib/commands/adapter.js +12 -0
  93. package/lib/commands/add.js +118 -0
  94. package/lib/commands/audit.js +70 -0
  95. package/lib/commands/blocked.js +5 -0
  96. package/lib/commands/board.js +64 -0
  97. package/lib/commands/claim.js +21 -2
  98. package/lib/commands/claims.js +7 -0
  99. package/lib/commands/clean.js +485 -75
  100. package/lib/commands/close.js +2 -2
  101. package/lib/commands/comment.js +5 -0
  102. package/lib/commands/control.js +148 -0
  103. package/lib/commands/create.js +2 -2
  104. package/lib/commands/dev.js +185 -7
  105. package/lib/commands/doc-gate.js +336 -0
  106. package/lib/commands/doctor.js +156 -0
  107. package/lib/commands/explain.js +15 -0
  108. package/lib/commands/export.js +237 -0
  109. package/lib/commands/gate.js +209 -0
  110. package/lib/commands/hooks.js +377 -0
  111. package/lib/commands/inbox.js +118 -0
  112. package/lib/commands/init.js +604 -0
  113. package/lib/commands/insights.js +79 -0
  114. package/lib/commands/issue.js +12 -1
  115. package/lib/commands/issues.js +17 -0
  116. package/lib/commands/lint.js +5 -0
  117. package/lib/commands/list.js +2 -2
  118. package/lib/commands/memory.js +81 -0
  119. package/lib/commands/merge.js +312 -0
  120. package/lib/commands/migrate.js +362 -0
  121. package/lib/commands/new.js +12 -0
  122. package/lib/commands/options.js +241 -0
  123. package/lib/commands/orient.js +13 -0
  124. package/lib/commands/orphans.js +5 -0
  125. package/lib/commands/patch.js +67 -0
  126. package/lib/commands/plan.js +481 -29
  127. package/lib/commands/pr.js +88 -0
  128. package/lib/commands/preflight.js +211 -0
  129. package/lib/commands/prime.js +13 -0
  130. package/lib/commands/push.js +135 -2
  131. package/lib/commands/ready.js +2 -2
  132. package/lib/commands/recall.js +171 -0
  133. package/lib/commands/recap.js +75 -0
  134. package/lib/commands/recommend.js +0 -1
  135. package/lib/commands/release.js +104 -0
  136. package/lib/commands/remember.js +140 -0
  137. package/lib/commands/role.js +99 -0
  138. package/lib/commands/serve.js +581 -0
  139. package/lib/commands/setup.js +900 -971
  140. package/lib/commands/shepherd.js +501 -0
  141. package/lib/commands/ship.js +59 -1
  142. package/lib/commands/show.js +2 -2
  143. package/lib/commands/stage.js +192 -0
  144. package/lib/commands/stale.js +5 -0
  145. package/lib/commands/status.js +158 -21
  146. package/lib/commands/sync.js +34 -46
  147. package/lib/commands/team.js +4 -1
  148. package/lib/commands/test.js +43 -27
  149. package/lib/commands/update.js +2 -2
  150. package/lib/commands/upgrade.js +47 -0
  151. package/lib/commands/validate.js +43 -18
  152. package/lib/commands/worktree.js +362 -99
  153. package/lib/config-writer.js +202 -0
  154. package/lib/control-plane.js +236 -0
  155. package/lib/core/runtime-graph.js +977 -0
  156. package/lib/dep-guard/keyword-ripple.js +2 -2
  157. package/lib/deprecated-sync-cleanup.js +362 -0
  158. package/lib/detect-agent.js +2 -28
  159. package/lib/detect-worktree.js +35 -9
  160. package/lib/doc-gate/declaration.js +177 -0
  161. package/lib/doc-gate/detect.js +289 -0
  162. package/lib/doc-gate/gate.js +375 -0
  163. package/lib/doc-gate/okf-config.js +128 -0
  164. package/lib/doc-gate/okf.js +429 -0
  165. package/lib/docs-command.js +1161 -6
  166. package/lib/forge-issues.js +382 -11
  167. package/lib/forge-lock.js +262 -0
  168. package/lib/gate-events.js +192 -0
  169. package/lib/global-flags.js +104 -0
  170. package/lib/greptile-match.js +7 -63
  171. package/lib/grounding/context-events.js +230 -0
  172. package/lib/grounding/read-first.js +112 -0
  173. package/lib/harness-capability-matrix.js +380 -0
  174. package/lib/hook-global-installer.js +347 -0
  175. package/lib/hook-renderer.js +541 -0
  176. package/lib/inbox.js +391 -0
  177. package/lib/insights.js +397 -0
  178. package/lib/issue-adapter.js +156 -0
  179. package/lib/issue-backend.js +145 -0
  180. package/lib/issue-render.js +220 -0
  181. package/lib/kernel/backing-issue.js +311 -0
  182. package/lib/kernel/broker.js +1218 -0
  183. package/lib/kernel/cli-broker-factory.js +130 -0
  184. package/lib/kernel/conflict-signal.js +82 -0
  185. package/lib/kernel/evaluators.js +195 -0
  186. package/lib/kernel/fs-class.js +495 -0
  187. package/lib/kernel/issue-command-contract.js +559 -0
  188. package/lib/kernel/issue-id-resolver.js +186 -0
  189. package/lib/kernel/lease-enforcer.js +158 -0
  190. package/lib/kernel/migrations.js +333 -0
  191. package/lib/kernel/owned-kernel.js +43 -0
  192. package/lib/kernel/planning-buckets-schema.js +109 -0
  193. package/lib/kernel/projection-jsonl-writer.js +450 -0
  194. package/lib/kernel/readiness-model.js +329 -0
  195. package/lib/kernel/schema.js +356 -0
  196. package/lib/kernel/sqlite-driver.js +2540 -0
  197. package/lib/kernel/taxonomy-validator.js +394 -0
  198. package/lib/lefthook-check.js +3 -2
  199. package/lib/lefthook-wiring.js +413 -0
  200. package/lib/mcp-config-renderer.js +288 -0
  201. package/lib/memory/graphiti-mcp.js +106 -0
  202. package/lib/memory/router.js +387 -0
  203. package/lib/memory/typed-api.js +102 -0
  204. package/lib/memory-digest.js +195 -0
  205. package/lib/merge-rules.js +395 -0
  206. package/lib/migrate-dry-run.js +466 -0
  207. package/lib/orientation.js +863 -0
  208. package/lib/package-manager-remediation.js +103 -0
  209. package/lib/package-root.js +381 -0
  210. package/lib/patch-intent.js +890 -0
  211. package/lib/plugin-catalog.js +3 -4
  212. package/lib/plugin-manager.js +0 -5
  213. package/lib/pr-bundle.js +186 -0
  214. package/lib/pr-monitor/auto-actions.js +175 -0
  215. package/lib/pr-monitor/differ.js +195 -0
  216. package/lib/pr-monitor/digest.js +206 -0
  217. package/lib/pr-monitor/events.js +0 -0
  218. package/lib/pr-monitor/gather.js +124 -0
  219. package/lib/pr-monitor/journal.js +299 -0
  220. package/lib/pr-monitor/monitor.js +146 -0
  221. package/lib/pr-monitor/render-sticky.js +192 -0
  222. package/lib/pr-monitor/upsert-sticky.js +169 -0
  223. package/lib/pr-monitor/watch-lifecycle.js +95 -0
  224. package/lib/pr-monitor/watch.js +247 -0
  225. package/lib/pr-pull.js +1314 -0
  226. package/lib/pr-shepherd.js +494 -0
  227. package/lib/pr-state-validator.js +59 -0
  228. package/lib/preflight/gates.js +237 -0
  229. package/lib/preflight/runner.js +116 -0
  230. package/lib/project-discovery.js +0 -53
  231. package/lib/project-memory.js +99 -497
  232. package/lib/protected-path-manifest.js +281 -0
  233. package/lib/protected-state-surfaces.js +387 -0
  234. package/lib/release-readiness.js +2105 -0
  235. package/lib/reset.js +59 -45
  236. package/lib/review-adapter.js +68 -0
  237. package/lib/rules-sync.js +260 -0
  238. package/lib/runtime-health.js +241 -20
  239. package/lib/safety-config-renderer.js +268 -0
  240. package/lib/setup-action-log.js +1 -7
  241. package/lib/setup.js +27 -65
  242. package/lib/shell-utils.js +76 -6
  243. package/lib/skills-sync.js +330 -0
  244. package/lib/smart-status/scoring.js +17 -3
  245. package/lib/status/beads-snapshot.js +45 -2
  246. package/lib/status/presenter.js +169 -18
  247. package/lib/status/snapshot.js +186 -0
  248. package/lib/sync-backend.js +202 -0
  249. package/lib/untrusted-content.js +52 -0
  250. package/lib/upgrade-safety.js +251 -0
  251. package/lib/workflow/enforce-stage.js +351 -45
  252. package/lib/workflow/stage-transition.js +115 -0
  253. package/lib/workflow/stages.js +30 -6
  254. package/lib/workflow/state-manager.js +11 -22
  255. package/lib/workflow/state.js +23 -1
  256. package/lib/workflow-profiles.js +17 -5
  257. package/package.json +37 -35
  258. package/rules/documentation.md +19 -0
  259. package/rules/kernel-tracking.md +26 -0
  260. package/rules/security.md +22 -0
  261. package/rules/tdd.md +20 -0
  262. package/rules/workflow.md +27 -0
  263. package/scripts/auto-backing-issue.js +47 -0
  264. package/scripts/beads-context.sh +81 -57
  265. package/scripts/beads-upgrade-smoke.sh +24 -3
  266. package/scripts/bootstrap-windows-tools.sh +78 -0
  267. package/scripts/branch-protection.js +2 -3
  268. package/scripts/check-agents.js +34 -137
  269. package/scripts/commitlint.js +3 -1
  270. package/scripts/conflict-detect.sh +3 -0
  271. package/scripts/dep-guard.sh +22 -3
  272. package/scripts/file-index.sh +3 -0
  273. package/scripts/forge-team/lib/claim.sh +34 -18
  274. package/scripts/forge-team/lib/dashboard.sh +61 -86
  275. package/scripts/forge-team/lib/epic.sh +99 -263
  276. package/scripts/forge-team/lib/hooks.sh +26 -28
  277. package/scripts/forge-team/lib/identity.sh +4 -4
  278. package/scripts/forge-team/lib/sync-github.sh +49 -84
  279. package/scripts/forge-team/lib/verify.sh +93 -83
  280. package/scripts/forge-team/lib/workload.sh +41 -65
  281. package/scripts/forge-team/tests/claim.test.sh +25 -19
  282. package/scripts/forge-team/tests/dashboard.test.sh +31 -46
  283. package/scripts/forge-team/tests/epic.test.sh +52 -71
  284. package/scripts/forge-team/tests/hooks.test.sh +38 -50
  285. package/scripts/forge-team/tests/identity.test.sh +3 -3
  286. package/scripts/forge-team/tests/integration.test.sh +44 -66
  287. package/scripts/forge-team/tests/sync-github.test.sh +50 -83
  288. package/scripts/forge-team/tests/verify.test.sh +37 -46
  289. package/scripts/forge-team/tests/workflow-integration.test.sh +4 -4
  290. package/scripts/forge-team/tests/workload.test.sh +32 -66
  291. package/scripts/gen-command-manifest.js +153 -0
  292. package/scripts/gen-embedded-assets.mjs +129 -0
  293. package/scripts/install.ps1 +139 -0
  294. package/scripts/install.sh +268 -0
  295. package/scripts/lib/release-asset.mjs +84 -0
  296. package/scripts/parity-check.mjs +145 -0
  297. package/scripts/parity-check.test.mjs +58 -0
  298. package/scripts/pin-agentic-workflow-images.js +112 -0
  299. package/scripts/pr-auto-actions.js +93 -0
  300. package/scripts/pr-coordinator.sh +3 -0
  301. package/scripts/pr-verdict-label.js +50 -0
  302. package/scripts/preflight-sonar.eslint.config.mjs +44 -0
  303. package/scripts/preflight.sh +21 -94
  304. package/scripts/protected-state-check.js +104 -0
  305. package/scripts/smart-status.sh +60 -57
  306. package/scripts/spikes/config-race-bench.js +111 -0
  307. package/scripts/spikes/harness-capability-matrix.js +13 -0
  308. package/scripts/spikes/patch-anchor-stability-bench.js +125 -0
  309. package/scripts/spikes/protected-path-manifest.js +20 -0
  310. package/scripts/spikes/skill-auto-invoke-parity.js +292 -0
  311. package/scripts/sync-agent-skills.js +62 -0
  312. package/scripts/sync-utils.sh +3 -0
  313. package/scripts/test-ci-shard.js +13 -6
  314. package/scripts/test.js +95 -12
  315. package/skills/claim-safety/SKILL.md +102 -0
  316. package/skills/claim-safety/evals/evals.json +46 -0
  317. package/{.github/prompts/dev.prompt.md → skills/dev/SKILL.md} +44 -50
  318. package/skills/dev/evals/evals.json +50 -0
  319. package/skills/hermes-forge/SKILL.md +185 -0
  320. package/skills/hermes-forge/evals/evals.json +46 -0
  321. package/skills/issue-basics/SKILL.md +111 -0
  322. package/skills/issue-basics/evals/evals.json +46 -0
  323. package/skills/kernel/SKILL.md +166 -0
  324. package/skills/kernel/evals/evals.json +50 -0
  325. package/skills/memory/SKILL.md +102 -0
  326. package/skills/parallel-deep-research/SKILL.md +14 -11
  327. package/skills/parallel-deep-research/evals/evals.json +11 -27
  328. package/{.github/prompts/plan.prompt.md → skills/plan/SKILL.md} +132 -157
  329. package/skills/plan/evals/evals.json +42 -0
  330. package/skills/research/SKILL.md +195 -0
  331. package/skills/research/evals/evals.json +42 -0
  332. package/{.github/prompts/review.prompt.md → skills/review/SKILL.md} +98 -62
  333. package/skills/review/evals/evals.json +42 -0
  334. package/skills/rollback/SKILL.md +110 -0
  335. package/skills/rollback/evals/evals.json +46 -0
  336. package/skills/rollback/references/methods.md +204 -0
  337. package/{.cursor/commands/rollback.md → skills/rollback/references/workflow-integration.md} +10 -284
  338. package/skills/shepherd/SKILL.md +66 -0
  339. package/skills/shepherd/evals/evals.json +42 -0
  340. package/{.github/prompts/ship.prompt.md → skills/ship/SKILL.md} +81 -45
  341. package/skills/ship/evals/evals.json +42 -0
  342. package/skills/smith/SKILL.md +142 -0
  343. package/skills/smith/evals/evals.json +46 -0
  344. package/skills/smith/references/autonomy-and-gates.md +94 -0
  345. package/{.github/prompts/sonarcloud.prompt.md → skills/sonarcloud/SKILL.md} +14 -3
  346. package/skills/sonarcloud/evals/evals.json +46 -0
  347. package/skills/sonarcloud-analysis/SKILL.md +18 -13
  348. package/skills/sonarcloud-analysis/evals/evals.json +11 -15
  349. package/{.github/prompts/status.prompt.md → skills/status/SKILL.md} +20 -10
  350. package/skills/status/evals/evals.json +50 -0
  351. package/skills/triage-ready/SKILL.md +121 -0
  352. package/skills/triage-ready/evals/evals.json +42 -0
  353. package/{.github/prompts/validate.prompt.md → skills/validate/SKILL.md} +52 -29
  354. package/skills/validate/evals/evals.json +42 -0
  355. package/skills/verify/SKILL.md +299 -0
  356. package/skills/verify/evals/evals.json +50 -0
  357. package/.claude/commands/dev.md +0 -345
  358. package/.claude/commands/plan.md +0 -566
  359. package/.claude/commands/premerge.md +0 -186
  360. package/.claude/commands/research.md +0 -42
  361. package/.claude/commands/review.md +0 -451
  362. package/.claude/commands/rollback.md +0 -721
  363. package/.claude/commands/ship.md +0 -213
  364. package/.claude/commands/sonarcloud.md +0 -152
  365. package/.claude/commands/status.md +0 -90
  366. package/.claude/commands/validate.md +0 -288
  367. package/.claude/commands/verify.md +0 -269
  368. package/.claude/rules/workflow.md +0 -121
  369. package/.cline/workflows/dev.md +0 -342
  370. package/.cline/workflows/plan.md +0 -563
  371. package/.cline/workflows/premerge.md +0 -183
  372. package/.cline/workflows/research.md +0 -39
  373. package/.cline/workflows/review.md +0 -448
  374. package/.cline/workflows/rollback.md +0 -718
  375. package/.cline/workflows/ship.md +0 -210
  376. package/.cline/workflows/sonarcloud.md +0 -146
  377. package/.cline/workflows/status.md +0 -87
  378. package/.cline/workflows/validate.md +0 -285
  379. package/.cline/workflows/verify.md +0 -266
  380. package/.codex/config.toml +0 -11
  381. package/.codex/skills/dev/SKILL.md +0 -345
  382. package/.codex/skills/plan/SKILL.md +0 -566
  383. package/.codex/skills/premerge/SKILL.md +0 -186
  384. package/.codex/skills/research/SKILL.md +0 -42
  385. package/.codex/skills/review/SKILL.md +0 -451
  386. package/.codex/skills/rollback/SKILL.md +0 -721
  387. package/.codex/skills/ship/SKILL.md +0 -213
  388. package/.codex/skills/sonarcloud/SKILL.md +0 -149
  389. package/.codex/skills/status/SKILL.md +0 -90
  390. package/.codex/skills/validate/SKILL.md +0 -288
  391. package/.codex/skills/verify/SKILL.md +0 -269
  392. package/.cursor/commands/dev.md +0 -342
  393. package/.cursor/commands/plan.md +0 -563
  394. package/.cursor/commands/premerge.md +0 -183
  395. package/.cursor/commands/research.md +0 -39
  396. package/.cursor/commands/review.md +0 -448
  397. package/.cursor/commands/ship.md +0 -210
  398. package/.cursor/commands/sonarcloud.md +0 -146
  399. package/.cursor/commands/status.md +0 -87
  400. package/.cursor/commands/validate.md +0 -285
  401. package/.cursor/commands/verify.md +0 -266
  402. package/.cursorrules +0 -149
  403. package/.github/prompts/premerge.prompt.md +0 -188
  404. package/.github/prompts/research.prompt.md +0 -44
  405. package/.github/prompts/rollback.prompt.md +0 -723
  406. package/.github/prompts/verify.prompt.md +0 -271
  407. package/.github/workflows/beads-to-github.yml +0 -89
  408. package/.github/workflows/github-to-beads.yml +0 -100
  409. package/.kilocode/workflows/dev.md +0 -346
  410. package/.kilocode/workflows/plan.md +0 -567
  411. package/.kilocode/workflows/premerge.md +0 -187
  412. package/.kilocode/workflows/research.md +0 -43
  413. package/.kilocode/workflows/review.md +0 -452
  414. package/.kilocode/workflows/rollback.md +0 -722
  415. package/.kilocode/workflows/ship.md +0 -214
  416. package/.kilocode/workflows/sonarcloud.md +0 -150
  417. package/.kilocode/workflows/status.md +0 -91
  418. package/.kilocode/workflows/validate.md +0 -289
  419. package/.kilocode/workflows/verify.md +0 -270
  420. package/.opencode/commands/dev.md +0 -345
  421. package/.opencode/commands/plan.md +0 -566
  422. package/.opencode/commands/premerge.md +0 -186
  423. package/.opencode/commands/research.md +0 -42
  424. package/.opencode/commands/review.md +0 -451
  425. package/.opencode/commands/rollback.md +0 -721
  426. package/.opencode/commands/ship.md +0 -213
  427. package/.opencode/commands/sonarcloud.md +0 -149
  428. package/.opencode/commands/status.md +0 -90
  429. package/.opencode/commands/validate.md +0 -288
  430. package/.opencode/commands/verify.md +0 -269
  431. package/.roo/commands/dev.md +0 -346
  432. package/.roo/commands/plan.md +0 -567
  433. package/.roo/commands/premerge.md +0 -187
  434. package/.roo/commands/research.md +0 -43
  435. package/.roo/commands/review.md +0 -452
  436. package/.roo/commands/rollback.md +0 -722
  437. package/.roo/commands/ship.md +0 -214
  438. package/.roo/commands/sonarcloud.md +0 -150
  439. package/.roo/commands/status.md +0 -91
  440. package/.roo/commands/validate.md +0 -289
  441. package/.roo/commands/verify.md +0 -270
  442. package/docs/BEADS_GITHUB_SYNC.md +0 -281
  443. package/docs/GREPTILE_SETUP.md +0 -400
  444. package/docs/MANUAL_REVIEW_GUIDE.md +0 -106
  445. package/docs/SETUP.md +0 -663
  446. package/docs/VALIDATION.md +0 -363
  447. package/lib/agents/cline.plugin.json +0 -29
  448. package/lib/agents/copilot.plugin.json +0 -24
  449. package/lib/agents/kilocode.plugin.json +0 -22
  450. package/lib/agents/opencode.plugin.json +0 -23
  451. package/lib/agents/roo.plugin.json +0 -30
  452. package/lib/beads-bootstrap.js +0 -225
  453. package/lib/beads-health-check.js +0 -188
  454. package/lib/commands/commands-reset.js +0 -147
  455. package/opencode.json +0 -67
  456. package/scripts/beads-context.test.js +0 -584
  457. package/scripts/github-beads-sync/comment.mjs +0 -64
  458. package/scripts/github-beads-sync/config.mjs +0 -148
  459. package/scripts/github-beads-sync/github-api.mjs +0 -131
  460. package/scripts/github-beads-sync/index.mjs +0 -356
  461. package/scripts/github-beads-sync/label-mapper.mjs +0 -54
  462. package/scripts/github-beads-sync/mapping.mjs +0 -132
  463. package/scripts/github-beads-sync/reverse-sync-cli.mjs +0 -31
  464. package/scripts/github-beads-sync/reverse-sync.mjs +0 -162
  465. package/scripts/github-beads-sync/run-bd.mjs +0 -161
  466. package/scripts/github-beads-sync/sanitize.mjs +0 -121
  467. package/scripts/github-beads-sync.config.json +0 -26
  468. package/scripts/sync-commands.js +0 -600
@@ -0,0 +1,103 @@
1
+ /**
2
+ * package-manager-remediation.js — Detect the caller's package manager from
3
+ * lockfile presence so remediation messages (e.g. "lefthook is missing, run
4
+ * X") give the correct install command instead of hard-coding a single tool.
5
+ *
6
+ * This is deliberately separate from lib/detection-utils.js#detectPackageManager,
7
+ * which shells out to probe installed binaries and prints setup-wizard output.
8
+ * Remediation messages need a fast, side-effect-free, synchronous lookup that
9
+ * never spawns a process — it runs on every stage-gate health check.
10
+ *
11
+ * @module lib/package-manager-remediation
12
+ */
13
+
14
+ const fs = require('node:fs');
15
+ const path = require('node:path');
16
+
17
+ /**
18
+ * Ordered lockfile → package manager mapping. First match wins.
19
+ * `install` is the command to fetch already-declared dependencies.
20
+ * `addDev(pkg)` is the command to add a new dev dependency and install it.
21
+ */
22
+ const PACKAGE_MANAGERS = [
23
+ {
24
+ name: 'bun',
25
+ lockFiles: ['bun.lockb', 'bun.lock'],
26
+ install: 'bun install',
27
+ addDev: pkg => `bun add -D ${pkg} && bun install`
28
+ },
29
+ {
30
+ name: 'pnpm',
31
+ lockFiles: ['pnpm-lock.yaml'],
32
+ install: 'pnpm install',
33
+ addDev: pkg => `pnpm add -D ${pkg}`
34
+ },
35
+ {
36
+ name: 'yarn',
37
+ lockFiles: ['yarn.lock'],
38
+ install: 'yarn install',
39
+ addDev: pkg => `yarn add -D ${pkg}`
40
+ },
41
+ {
42
+ name: 'npm',
43
+ lockFiles: ['package-lock.json'],
44
+ install: 'npm install',
45
+ addDev: pkg => `npm install -D ${pkg}`
46
+ }
47
+ ];
48
+
49
+ // npm is the safest universal fallback when no lockfile is present or
50
+ // recognized — it ships with Node itself, so it is always a documented,
51
+ // reasonable default rather than assuming any particular toolchain.
52
+ const DEFAULT_MANAGER = PACKAGE_MANAGERS[PACKAGE_MANAGERS.length - 1];
53
+
54
+ /**
55
+ * Detect the package manager in use for a project from lockfile presence.
56
+ *
57
+ * @param {string} [projectRoot] - Absolute path to the project root. Falls
58
+ * back to process.cwd() when omitted or not a non-empty string.
59
+ * @returns {{ name: string, install: string, addDev: (pkg: string) => string }}
60
+ * The detected (or default) package manager descriptor.
61
+ */
62
+ function detectPackageManagerForRemediation(projectRoot) {
63
+ const root = typeof projectRoot === 'string' && projectRoot.trim()
64
+ ? projectRoot
65
+ : process.cwd();
66
+
67
+ for (const manager of PACKAGE_MANAGERS) {
68
+ const hasLockFile = manager.lockFiles.some(file =>
69
+ fs.existsSync(path.join(root, file))
70
+ );
71
+ if (hasLockFile) return manager;
72
+ }
73
+
74
+ return DEFAULT_MANAGER;
75
+ }
76
+
77
+ /**
78
+ * Get the install command for the detected package manager (e.g. when a
79
+ * dependency is already declared but not installed).
80
+ *
81
+ * @param {string} [projectRoot] - Absolute path to the project root.
82
+ * @returns {string} Install command, e.g. "npm install".
83
+ */
84
+ function getInstallCommand(projectRoot) {
85
+ return detectPackageManagerForRemediation(projectRoot).install;
86
+ }
87
+
88
+ /**
89
+ * Get the "add as dev dependency" command for the detected package manager.
90
+ *
91
+ * @param {string} [projectRoot] - Absolute path to the project root.
92
+ * @param {string} pkg - Package name to add, e.g. "lefthook".
93
+ * @returns {string} Add-dev-dependency command, e.g. "npm install -D lefthook".
94
+ */
95
+ function getAddDevCommand(projectRoot, pkg) {
96
+ return detectPackageManagerForRemediation(projectRoot).addDev(pkg);
97
+ }
98
+
99
+ module.exports = {
100
+ detectPackageManagerForRemediation,
101
+ getInstallCommand,
102
+ getAddDevCommand
103
+ };
@@ -0,0 +1,381 @@
1
+ 'use strict';
2
+
3
+ /* global FORGE_COMPILED */
4
+
5
+ /**
6
+ * @module package-root
7
+ *
8
+ * Dual-channel resolution of the Forge "package root" — the directory that ships
9
+ * the runtime assets `forge setup` (and a few runtime commands) copy into a
10
+ * target project (`skills/`, `rules/`, essential docs, `AGENTS.md`, hook scripts,
11
+ * workflow runtime scripts).
12
+ *
13
+ * Two distribution channels must both work:
14
+ *
15
+ * 1. npm / npx install → the package is a real directory on disk. The root is
16
+ * the Forge repo/package root (`lib/` → `..`). Historical path; unchanged.
17
+ *
18
+ * 2. `bun build --compile` single-file binary → there is NO package directory
19
+ * on disk. The runtime assets are embedded at compile time (Bun import
20
+ * attributes, see `scripts/gen-embedded-assets.mjs`) and this module
21
+ * materializes them into a temp directory on first use, then hands that
22
+ * directory to the existing (unchanged) copy logic. This "extract then
23
+ * delegate" keeps every downstream asset consumer working without a rewrite.
24
+ *
25
+ * Every consumer that READS a packaged asset off the package root goes through
26
+ * `getPackageRoot(diskFallback)`:
27
+ * - npm/dev: returns `diskFallback` (verified to actually contain assets).
28
+ * - compiled: returns the memoized, sentinel-guarded extraction directory.
29
+ *
30
+ * Module `require()`s that resolve code (`require(path.join(packageDir,'lib',…))`)
31
+ * are NOT asset reads and are intentionally left alone — those are handled by the
32
+ * bundler when compiling, not by this helper.
33
+ */
34
+
35
+ const fs = require('node:fs');
36
+ const path = require('node:path');
37
+ const os = require('node:os');
38
+
39
+ /** On-disk package root for the npm/dev channel: `lib/` → repo root. */
40
+ const DISK_PACKAGE_ROOT = path.resolve(__dirname, '..');
41
+
42
+ /** Filename written into the extraction dir after a fully-successful extraction. */
43
+ const SENTINEL_FILE = '.forge-assets-complete';
44
+
45
+ /**
46
+ * Asset roots that Forge reads from the package root. Directory entries are
47
+ * embedded recursively; file entries individually. The generator
48
+ * (`scripts/gen-embedded-assets.mjs`) walks exactly this list, so it is the
49
+ * single source of truth for "what ships inside the compiled binary".
50
+ *
51
+ * Kept in sync with the setup/runtime consumers (asserted by
52
+ * test/embedded-assets-drift.test.js):
53
+ * - skills/** → populateAgentSkills, listCanonicalSkills, codex skills, reset
54
+ * - rules/** → renderRulesForHarness (agents-config)
55
+ * - AGENTS.md → workflow contract copied into the project
56
+ * - .claude/scripts/** → load-env.sh, review-resolve.sh
57
+ * - .forge/hooks/** → check-tdd.js, forge-native-hook.js
58
+ * - scripts/** → WORKFLOW_RUNTIME_ASSETS (team + workflow scripts), `forge team`
59
+ *
60
+ * NOTE: the essential docs (TOOLCHAIN.md / VALIDATION.md) are intentionally NOT
61
+ * embedded — copyEssentialDocs reads `docs/<doc>` which does not exist (the files
62
+ * live under docs/reference/ + docs/forge/), so it is a no-op in BOTH channels
63
+ * today. Embedding follows the copyEssentialDocs source-path fix (deferred). Every
64
+ * root listed here MUST exist on disk — the generator fails closed if one is absent.
65
+ */
66
+ const ASSET_ROOTS = Object.freeze([
67
+ 'skills',
68
+ 'rules',
69
+ 'AGENTS.md',
70
+ '.claude/scripts',
71
+ '.forge/hooks',
72
+ 'scripts',
73
+ ]);
74
+
75
+ /**
76
+ * Compile-time signal injected by `build:binary` via `--define FORGE_COMPILED=true`.
77
+ * The `global` directive above tells ESLint the identifier exists; the `typeof`
78
+ * guard prevents a ReferenceError under node where it is never defined.
79
+ */
80
+ function isCompiledByDefine() {
81
+ try {
82
+ return typeof FORGE_COMPILED !== 'undefined' && FORGE_COMPILED === true;
83
+ } catch {
84
+ return false;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * True when running inside a `bun build --compile` single-file executable that
90
+ * carries embedded assets. Primary signal is the injected `FORGE_COMPILED`
91
+ * constant; `Bun.embeddedFiles` is a runtime FALLBACK. Under `node` (npm) and a
92
+ * plain `bun test` (not compiled) both are false → the on-disk path is used.
93
+ *
94
+ * @param {*} [bun] - Bun runtime object; injectable for tests (the real
95
+ * `globalThis.Bun` is a read-only property and cannot be mocked by assignment).
96
+ */
97
+ function isCompiledBinary(bun = globalThis.Bun) {
98
+ if (isCompiledByDefine()) return true;
99
+ try {
100
+ if (!bun || bun.embeddedFiles == null) return false;
101
+ return Array.from(bun.embeddedFiles).length > 0;
102
+ } catch {
103
+ return false;
104
+ }
105
+ }
106
+
107
+ /** A directory qualifies as a real on-disk package root if it carries the core assets. */
108
+ function hasDiskAssets(dir) {
109
+ return (
110
+ !!dir &&
111
+ fs.existsSync(path.join(dir, 'skills')) &&
112
+ fs.existsSync(path.join(dir, 'AGENTS.md'))
113
+ );
114
+ }
115
+
116
+ /** Resolve a stable version tag for the extraction directory + sentinel. */
117
+ function resolveVersion() {
118
+ try {
119
+ // Literal path so the bundler embeds package.json into the binary too.
120
+ return require('../package.json').version || 'dev';
121
+ } catch {
122
+ return 'dev';
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Load the compile-time embedded-asset manifest. Only ever reached inside a
128
+ * compiled binary, where the generated module is bundled at build time. The
129
+ * literal specifier lets Bun's compiler discover and embed it; the guard in
130
+ * `getPackageRoot` ensures node/npm never executes this line (the generated
131
+ * file is gitignored and absent there).
132
+ *
133
+ * @returns {{ EMBEDDED_ASSETS: Record<string,string>, EXECUTABLE_ASSETS: string[] }}
134
+ */
135
+ function loadEmbeddedManifest() {
136
+ return require('./embedded-assets.generated.mjs');
137
+ }
138
+
139
+ /**
140
+ * Split a relative path into segments for platform-correct joining. Splits on
141
+ * BOTH `/` and `\` so a backslash-separated key cannot smuggle a `..` segment
142
+ * past the traversal guard on Windows.
143
+ */
144
+ function relSegments(relPosix) {
145
+ return relPosix.split(/[/\\]/).filter(Boolean);
146
+ }
147
+
148
+ /**
149
+ * Extract every embedded asset into `destDir`, preserving relative paths and
150
+ * restoring the executable bit on scripts/hooks (files-only embedding drops
151
+ * mode). Node `fs` reads the `/$bunfs/…` embedded paths directly. Returns the
152
+ * number of files written so the caller can assert completeness.
153
+ *
154
+ * @param {string} destDir
155
+ * @param {Record<string,string>} [assets] - relPath → source path map. Defaults
156
+ * to the compile-time embedded manifest; injectable for unit tests.
157
+ * @param {string[]} [executable] - relPaths needing chmod +x. Defaults to manifest.
158
+ * @returns {number} count of files written
159
+ */
160
+ function extractEmbeddedAssets(destDir, assets, executable) {
161
+ if (!assets) {
162
+ const manifest = loadEmbeddedManifest();
163
+ assets = manifest.EMBEDDED_ASSETS;
164
+ executable = manifest.EXECUTABLE_ASSETS || [];
165
+ }
166
+ const execSet = new Set(executable || []);
167
+ let count = 0;
168
+ for (const [relPath, embeddedPath] of Object.entries(assets)) {
169
+ // Defense-in-depth: the manifest is compile-time-trusted, but never let a
170
+ // key escape destDir via traversal or an absolute path.
171
+ const segs = relSegments(relPath);
172
+ if (path.isAbsolute(relPath) || segs.includes('..') || segs.length === 0) {
173
+ throw new Error(`Refusing to extract unsafe embedded asset path: ${JSON.stringify(relPath)}`);
174
+ }
175
+ const outPath = path.join(destDir, ...segs);
176
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
177
+ // read+write (not copyFileSync): Bun's embedded `/$bunfs/…` source paths
178
+ // support readFileSync but NOT the copyfile syscall. Binary buffer copy — no
179
+ // encoding/line-ending translation. Works identically for real disk files.
180
+ fs.writeFileSync(outPath, fs.readFileSync(embeddedPath));
181
+ if (execSet.has(relPath)) {
182
+ try {
183
+ // Owner-only rwx (0o700) — this is a per-user cache dir; no group/other
184
+ // needs access. chmod is a no-op on Windows.
185
+ fs.chmodSync(outPath, 0o700);
186
+ } catch {
187
+ // Non-fatal: mode restore best-effort; the copy already succeeded.
188
+ }
189
+ }
190
+ count += 1;
191
+ }
192
+ return count;
193
+ }
194
+
195
+ /**
196
+ * Per-USER cache root for extracted assets. NOT `os.tmpdir()` — a world-writable
197
+ * shared tmp lets a local attacker pre-plant `forge-assets-<version>/` with a
198
+ * valid sentinel + malicious hook scripts that `forge setup` would then install.
199
+ * Windows: `%LOCALAPPDATA%`; POSIX: `$XDG_CACHE_HOME` or `~/.cache`. The `forge`
200
+ * dir is created `0o700` on POSIX so only the owner can populate it.
201
+ */
202
+ function userCacheRoot() {
203
+ let base;
204
+ if (process.platform === 'win32') {
205
+ base = process.env.LOCALAPPDATA || process.env.APPDATA || os.tmpdir();
206
+ } else {
207
+ base = process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache');
208
+ }
209
+ const root = path.join(base, 'forge');
210
+ fs.mkdirSync(root, { recursive: true });
211
+ if (process.platform !== 'win32') {
212
+ try {
213
+ fs.chmodSync(root, 0o700);
214
+ } catch {
215
+ // Best-effort ownership hardening; not fatal.
216
+ }
217
+ }
218
+ return root;
219
+ }
220
+
221
+ /** True iff `dir` holds a completion sentinel matching this version. */
222
+ function isCompleteExtraction(dir, version) {
223
+ try {
224
+ const sentinel = path.join(dir, SENTINEL_FILE);
225
+ return fs.existsSync(sentinel) && fs.readFileSync(sentinel, 'utf8').trim() === version;
226
+ } catch {
227
+ return false;
228
+ }
229
+ }
230
+
231
+ /** Assert every expected relpath exists on disk under `dir` and is non-empty. */
232
+ function assertAllPresent(dir, assets) {
233
+ const missing = [];
234
+ for (const rel of Object.keys(assets)) {
235
+ const p = path.join(dir, ...relSegments(rel));
236
+ let ok = false;
237
+ try {
238
+ ok = fs.statSync(p).size > 0;
239
+ } catch {
240
+ // Missing or unreadable → counts as absent below.
241
+ }
242
+ if (!ok) missing.push(rel);
243
+ }
244
+ if (missing.length > 0) {
245
+ const sample = missing.slice(0, 10).join(', ');
246
+ throw new Error(
247
+ `Forge embedded-asset extraction incomplete: ${missing.length} file(s) missing or empty in ${dir} ` +
248
+ `(e.g. ${sample}${missing.length > 10 ? ', …' : ''}). Rebuild with \`bun run build:binary\`.`
249
+ );
250
+ }
251
+ }
252
+
253
+ let _extractedRoot = null;
254
+
255
+ /**
256
+ * Materialize embedded assets, atomically and concurrency-safely.
257
+ *
258
+ * Extraction writes into a PRIVATE `mkdtempSync` sibling dir (all files + the
259
+ * completion sentinel), then `renameSync`s it into the final version-stamped
260
+ * path in ONE atomic step. A half-written temp NEVER acquires the final name, so
261
+ * a crash mid-extraction or a second process racing us can never observe (or
262
+ * bless) a partially-populated dir — and no process ever `rmSync`es a dir another
263
+ * process is reading. If the final path already exists (another process won),
264
+ * we discard our temp and adopt theirs.
265
+ */
266
+ function ensureExtracted() {
267
+ if (_extractedRoot) return _extractedRoot;
268
+ const version = resolveVersion();
269
+ const manifest = loadEmbeddedManifest();
270
+ const cacheRoot = userCacheRoot();
271
+
272
+ // Cache identity = version + an asset-content FINGERPRINT (emitted by the
273
+ // generator). Same-version rebuilds with a changed asset set therefore land in
274
+ // a DIFFERENT dir, so a stale extraction is never silently reused.
275
+ const fp = String(manifest.ASSET_FINGERPRINT || 'nofp').slice(0, 16);
276
+ const finalDir = path.join(cacheRoot, `assets-${version}-${fp}`);
277
+
278
+ // Fast path: a completed extraction already exists — but do NOT trust the
279
+ // sentinel alone; verify the expected files are actually present + non-empty
280
+ // (a truncated/partly-deleted cache must re-extract, not be adopted).
281
+ if (isCompleteExtraction(finalDir, version)) {
282
+ try {
283
+ assertAllPresent(finalDir, manifest.EMBEDDED_ASSETS);
284
+ _extractedRoot = finalDir;
285
+ return finalDir;
286
+ } catch {
287
+ // Cache incomplete/corrupt — fall through to a fresh extraction.
288
+ }
289
+ }
290
+
291
+ const tmpDir = fs.mkdtempSync(path.join(cacheRoot, `.assets-${version}-`));
292
+ try {
293
+ extractEmbeddedAssets(tmpDir, manifest.EMBEDDED_ASSETS, manifest.EXECUTABLE_ASSETS || []);
294
+ assertAllPresent(tmpDir, manifest.EMBEDDED_ASSETS);
295
+ fs.writeFileSync(path.join(tmpDir, SENTINEL_FILE), version, 'utf8');
296
+ try {
297
+ fs.renameSync(tmpDir, finalDir);
298
+ } catch (err) {
299
+ // Another process already materialized finalDir (rename onto a non-empty
300
+ // dir fails) — discard ours and adopt theirs if it is complete.
301
+ fs.rmSync(tmpDir, { recursive: true, force: true });
302
+ if (isCompleteExtraction(finalDir, version)) {
303
+ _extractedRoot = finalDir;
304
+ return finalDir;
305
+ }
306
+ throw err;
307
+ }
308
+ } catch (err) {
309
+ try {
310
+ fs.rmSync(tmpDir, { recursive: true, force: true });
311
+ } catch {
312
+ // Best-effort cleanup of the private temp dir.
313
+ }
314
+ throw err;
315
+ }
316
+ _extractedRoot = finalDir;
317
+ return finalDir;
318
+ }
319
+
320
+ /**
321
+ * The directory to read packaged assets from, for BOTH channels.
322
+ *
323
+ * Resolution order (safe-default): a real on-disk package (npm/npx/dev) wins;
324
+ * otherwise a compiled binary extracts its embedded assets; otherwise BOTH
325
+ * channels failed and we throw loudly listing both attempts — never silently
326
+ * return an empty dir that lets setup "succeed" with nothing.
327
+ *
328
+ * @param {string} [diskFallback] - The caller's own on-disk package root.
329
+ * @returns {string}
330
+ */
331
+ function getPackageRoot(diskFallback = DISK_PACKAGE_ROOT) {
332
+ // 1. Disk channel — a real package dir that actually carries assets.
333
+ if (hasDiskAssets(diskFallback)) {
334
+ return diskFallback;
335
+ }
336
+ // 2. Embedded channel — compiled binary (or disk assets simply absent).
337
+ if (isCompiledBinary()) {
338
+ return ensureExtracted();
339
+ }
340
+ // 3. Both channels failed — fail loud, never return an asset-less dir.
341
+ throw new Error(
342
+ 'Cannot resolve Forge runtime assets. Tried:\n' +
343
+ ` 1. on-disk package root: ${diskFallback} (missing skills/ or AGENTS.md)\n` +
344
+ ' 2. embedded assets: not a compiled binary (no FORGE_COMPILED / Bun.embeddedFiles)\n' +
345
+ 'A published npm install should always satisfy (1); a single-file binary should satisfy (2).'
346
+ );
347
+ }
348
+
349
+ /**
350
+ * List the relative POSIX paths of all embedded assets (compiled binary only).
351
+ * Minimal read surface for steps 3/4; returns [] outside a compiled binary.
352
+ */
353
+ function listAssets() {
354
+ if (!isCompiledBinary()) return [];
355
+ try {
356
+ // Deterministic, locale-INDEPENDENT codepoint order (must match the generator
357
+ // so the embed set is byte-identical across cross-compile targets).
358
+ return Object.keys(loadEmbeddedManifest().EMBEDDED_ASSETS).sort((a, b) =>
359
+ a < b ? -1 : a > b ? 1 : 0
360
+ );
361
+ } catch {
362
+ return [];
363
+ }
364
+ }
365
+
366
+ /** Test-only: reset the memoized extraction directory. */
367
+ function _resetForTests() {
368
+ _extractedRoot = null;
369
+ }
370
+
371
+ module.exports = {
372
+ getPackageRoot,
373
+ isCompiledBinary,
374
+ extractEmbeddedAssets,
375
+ listAssets,
376
+ hasDiskAssets,
377
+ ASSET_ROOTS,
378
+ DISK_PACKAGE_ROOT,
379
+ SENTINEL_FILE,
380
+ _resetForTests,
381
+ };