@aperant/framework 0.8.1 → 0.8.6

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 (308) hide show
  1. package/CHANGELOG.md +443 -1
  2. package/agents/apt-planner.md +39 -7
  3. package/dist/cli/commands/adr.mjs +1 -1
  4. package/dist/cli/commands/audit-branch-current.d.mts +25 -0
  5. package/dist/cli/commands/audit-branch-current.d.mts.map +1 -0
  6. package/dist/cli/commands/audit-branch-current.mjs +252 -0
  7. package/dist/cli/commands/audit-branch-current.mjs.map +1 -0
  8. package/dist/cli/commands/audit.d.mts.map +1 -1
  9. package/dist/cli/commands/audit.mjs +13 -2
  10. package/dist/cli/commands/audit.mjs.map +1 -1
  11. package/dist/cli/commands/check-version.d.mts.map +1 -1
  12. package/dist/cli/commands/check-version.mjs +19 -1
  13. package/dist/cli/commands/check-version.mjs.map +1 -1
  14. package/dist/cli/commands/context.mjs +3 -3
  15. package/dist/cli/commands/context.mjs.map +1 -1
  16. package/dist/cli/commands/coverage-check.d.mts.map +1 -1
  17. package/dist/cli/commands/coverage-check.mjs +74 -7
  18. package/dist/cli/commands/coverage-check.mjs.map +1 -1
  19. package/dist/cli/commands/detect-runtime.d.mts +6 -0
  20. package/dist/cli/commands/detect-runtime.d.mts.map +1 -0
  21. package/dist/cli/commands/detect-runtime.mjs +142 -0
  22. package/dist/cli/commands/detect-runtime.mjs.map +1 -0
  23. package/dist/cli/commands/driver-doctor.d.mts +29 -0
  24. package/dist/cli/commands/driver-doctor.d.mts.map +1 -0
  25. package/dist/cli/commands/driver-doctor.mjs +291 -0
  26. package/dist/cli/commands/driver-doctor.mjs.map +1 -0
  27. package/dist/cli/commands/gate.mjs +14 -0
  28. package/dist/cli/commands/gate.mjs.map +1 -1
  29. package/dist/cli/commands/init.d.mts.map +1 -1
  30. package/dist/cli/commands/init.mjs +9 -6
  31. package/dist/cli/commands/init.mjs.map +1 -1
  32. package/dist/cli/commands/install-from-source.d.mts +2 -0
  33. package/dist/cli/commands/install-from-source.d.mts.map +1 -0
  34. package/dist/cli/commands/install-from-source.mjs +2 -0
  35. package/dist/cli/commands/install-from-source.mjs.map +1 -0
  36. package/dist/cli/commands/modes.mjs +1 -1
  37. package/dist/cli/commands/route.d.mts.map +1 -1
  38. package/dist/cli/commands/route.mjs +38 -1
  39. package/dist/cli/commands/route.mjs.map +1 -1
  40. package/dist/cli/commands/triage.mjs +1 -1
  41. package/dist/cli/config/load.d.mts.map +1 -1
  42. package/dist/cli/config/load.mjs +9 -3
  43. package/dist/cli/config/load.mjs.map +1 -1
  44. package/dist/cli/coordination/auto-emit-artifact-ready.mjs +1 -1
  45. package/dist/cli/coordination/event-schema.d.mts.map +1 -1
  46. package/dist/cli/coordination/event-schema.mjs +18 -0
  47. package/dist/cli/coordination/event-schema.mjs.map +1 -1
  48. package/dist/cli/coverage-check/user-outcomes.d.mts +84 -0
  49. package/dist/cli/coverage-check/user-outcomes.d.mts.map +1 -0
  50. package/dist/cli/coverage-check/user-outcomes.mjs +265 -0
  51. package/dist/cli/coverage-check/user-outcomes.mjs.map +1 -0
  52. package/dist/cli/dispatch.d.mts.map +1 -1
  53. package/dist/cli/dispatch.mjs +18 -1
  54. package/dist/cli/dispatch.mjs.map +1 -1
  55. package/dist/cli/gate/context.d.mts +1 -0
  56. package/dist/cli/gate/context.d.mts.map +1 -1
  57. package/dist/cli/gate/context.mjs +14 -1
  58. package/dist/cli/gate/context.mjs.map +1 -1
  59. package/dist/cli/gate/gates/consistency-check.d.mts +1 -0
  60. package/dist/cli/gate/gates/consistency-check.d.mts.map +1 -1
  61. package/dist/cli/gate/gates/consistency-check.mjs +1 -0
  62. package/dist/cli/gate/gates/consistency-check.mjs.map +1 -1
  63. package/dist/cli/gate/gates/review-clean.d.mts +1 -0
  64. package/dist/cli/gate/gates/review-clean.d.mts.map +1 -1
  65. package/dist/cli/gate/gates/review-clean.mjs +1 -0
  66. package/dist/cli/gate/gates/review-clean.mjs.map +1 -1
  67. package/dist/cli/gate/gates/verify-approved.d.mts +1 -0
  68. package/dist/cli/gate/gates/verify-approved.d.mts.map +1 -1
  69. package/dist/cli/gate/gates/verify-approved.mjs +1 -0
  70. package/dist/cli/gate/gates/verify-approved.mjs.map +1 -1
  71. package/dist/cli/gate/registry.d.mts.map +1 -1
  72. package/dist/cli/gate/registry.mjs +9 -1
  73. package/dist/cli/gate/registry.mjs.map +1 -1
  74. package/dist/cli/host/detect.mjs +1 -1
  75. package/dist/cli/host/detect.mjs.map +1 -1
  76. package/dist/cli/install/find-workspace-framework-version.d.mts +16 -0
  77. package/dist/cli/install/find-workspace-framework-version.d.mts.map +1 -0
  78. package/dist/cli/install/find-workspace-framework-version.mjs +85 -0
  79. package/dist/cli/install/find-workspace-framework-version.mjs.map +1 -0
  80. package/dist/cli/install/install-from-source.d.mts +10 -0
  81. package/dist/cli/install/install-from-source.d.mts.map +1 -0
  82. package/dist/cli/install/install-from-source.mjs +271 -0
  83. package/dist/cli/install/install-from-source.mjs.map +1 -0
  84. package/dist/cli/install/install-kernel.d.mts.map +1 -1
  85. package/dist/cli/install/install-kernel.mjs +24 -0
  86. package/dist/cli/install/install-kernel.mjs.map +1 -1
  87. package/dist/cli/install/legacy-paths.d.mts +33 -11
  88. package/dist/cli/install/legacy-paths.d.mts.map +1 -1
  89. package/dist/cli/install/legacy-paths.mjs +163 -39
  90. package/dist/cli/install/legacy-paths.mjs.map +1 -1
  91. package/dist/cli/install/runtime-detect.mjs +1 -1
  92. package/dist/cli/install/runtime-detect.mjs.map +1 -1
  93. package/dist/cli/install/runtime-migrate.d.mts +34 -14
  94. package/dist/cli/install/runtime-migrate.d.mts.map +1 -1
  95. package/dist/cli/install/runtime-migrate.mjs +63 -30
  96. package/dist/cli/install/runtime-migrate.mjs.map +1 -1
  97. package/dist/cli/install/transforms/codex.d.mts.map +1 -1
  98. package/dist/cli/install/transforms/codex.mjs +28 -17
  99. package/dist/cli/install/transforms/codex.mjs.map +1 -1
  100. package/dist/cli/skill-author/contract.mjs +2 -2
  101. package/dist/cli/skill-author/contract.mjs.map +1 -1
  102. package/dist/cli/verify-proof/audit.d.mts +34 -0
  103. package/dist/cli/verify-proof/audit.d.mts.map +1 -0
  104. package/dist/cli/verify-proof/audit.mjs +53 -0
  105. package/dist/cli/verify-proof/audit.mjs.map +1 -0
  106. package/dist/cli/verify-proof/exec.d.mts +20 -0
  107. package/dist/cli/verify-proof/exec.d.mts.map +1 -0
  108. package/dist/cli/verify-proof/exec.mjs +74 -0
  109. package/dist/cli/verify-proof/exec.mjs.map +1 -0
  110. package/dist/cli/verify-proof/idl/index.d.mts +2 -0
  111. package/dist/cli/verify-proof/idl/index.d.mts.map +1 -0
  112. package/dist/cli/verify-proof/idl/index.mjs +13 -0
  113. package/dist/cli/verify-proof/idl/index.mjs.map +1 -0
  114. package/dist/cli/verify-proof/idl/types.d.ts +10 -0
  115. package/dist/cli/verify-proof/idl/types.d.ts.map +1 -0
  116. package/dist/cli/verify-proof/idl/types.js +10 -0
  117. package/dist/cli/verify-proof/idl/types.js.map +1 -0
  118. package/dist/cli/verify-proof/manifest-validator.d.mts +19 -0
  119. package/dist/cli/verify-proof/manifest-validator.d.mts.map +1 -0
  120. package/dist/cli/verify-proof/manifest-validator.mjs +182 -0
  121. package/dist/cli/verify-proof/manifest-validator.mjs.map +1 -0
  122. package/dist/cli/verify-proof/resolver.d.mts +105 -0
  123. package/dist/cli/verify-proof/resolver.d.mts.map +1 -0
  124. package/dist/cli/verify-proof/resolver.mjs +320 -0
  125. package/dist/cli/verify-proof/resolver.mjs.map +1 -0
  126. package/dist/cli/verify-proof/runtime-detect.d.mts +30 -0
  127. package/dist/cli/verify-proof/runtime-detect.d.mts.map +1 -0
  128. package/dist/cli/verify-proof/runtime-detect.mjs +209 -0
  129. package/dist/cli/verify-proof/runtime-detect.mjs.map +1 -0
  130. package/dist/cli/verify-proof/trust.d.mts +70 -0
  131. package/dist/cli/verify-proof/trust.d.mts.map +1 -0
  132. package/dist/cli/verify-proof/trust.mjs +174 -0
  133. package/dist/cli/verify-proof/trust.mjs.map +1 -0
  134. package/dist/driver-sdk/conformance.d.ts +41 -0
  135. package/dist/driver-sdk/conformance.d.ts.map +1 -0
  136. package/dist/driver-sdk/conformance.js +123 -0
  137. package/dist/driver-sdk/conformance.js.map +1 -0
  138. package/dist/driver-sdk/errors.d.ts +75 -0
  139. package/dist/driver-sdk/errors.d.ts.map +1 -0
  140. package/dist/driver-sdk/errors.js +80 -0
  141. package/dist/driver-sdk/errors.js.map +1 -0
  142. package/dist/driver-sdk/idl.d.ts +221 -0
  143. package/dist/driver-sdk/idl.d.ts.map +1 -0
  144. package/dist/driver-sdk/idl.js +140 -0
  145. package/dist/driver-sdk/idl.js.map +1 -0
  146. package/dist/driver-sdk/index.d.ts +28 -0
  147. package/dist/driver-sdk/index.d.ts.map +1 -0
  148. package/dist/driver-sdk/index.js +28 -0
  149. package/dist/driver-sdk/index.js.map +1 -0
  150. package/dist/driver-sdk/manifest.d.ts +93 -0
  151. package/dist/driver-sdk/manifest.d.ts.map +1 -0
  152. package/dist/driver-sdk/manifest.js +12 -0
  153. package/dist/driver-sdk/manifest.js.map +1 -0
  154. package/dist/driver-sdk/retry.d.ts +33 -0
  155. package/dist/driver-sdk/retry.d.ts.map +1 -0
  156. package/dist/driver-sdk/retry.js +50 -0
  157. package/dist/driver-sdk/retry.js.map +1 -0
  158. package/dist/plugin/.claude-plugin/plugin.json +4 -1
  159. package/dist/plugin/agents/apt-planner.md +39 -7
  160. package/dist/plugin/skills/apt/SKILL.md +75 -6
  161. package/dist/plugin/skills/apt-caveman/SKILL.md +64 -0
  162. package/dist/plugin/skills/apt-debug/SKILL.md +36 -4
  163. package/dist/plugin/skills/apt-debug/appendices/diagnose-discipline.md +2 -11
  164. package/dist/plugin/skills/apt-discuss/SKILL.md +4 -4
  165. package/dist/plugin/skills/apt-discuss/appendices/grill-discipline.md +2 -11
  166. package/dist/plugin/skills/apt-discuss/appendices/zoom-out-helper.md +0 -8
  167. package/dist/plugin/skills/apt-execute/SKILL.md +27 -4
  168. package/dist/plugin/skills/apt-execute/appendices/tdd-mode.md +2 -10
  169. package/dist/plugin/skills/apt-fan-out/SKILL.md +36 -1
  170. package/dist/plugin/skills/apt-handoff/SKILL.md +228 -0
  171. package/dist/plugin/skills/apt-improve/DEEPENING.md +0 -8
  172. package/dist/plugin/skills/apt-improve/INTERFACE-DESIGN.md +0 -8
  173. package/dist/plugin/skills/apt-improve/LANGUAGE.md +0 -8
  174. package/dist/plugin/skills/apt-improve/SKILL.md +4 -4
  175. package/dist/plugin/skills/apt-plan/SKILL.md +73 -5
  176. package/dist/plugin/skills/apt-plan/adapters/conductor.md +1 -1
  177. package/dist/plugin/skills/apt-pr-review/SKILL.md +1 -1
  178. package/dist/plugin/skills/apt-prototype/LOGIC.md +0 -8
  179. package/dist/plugin/skills/apt-prototype/SKILL.md +4 -4
  180. package/dist/plugin/skills/apt-prototype/UI.md +0 -8
  181. package/dist/plugin/skills/apt-quick/SKILL.md +31 -1
  182. package/dist/plugin/skills/apt-research/SKILL.md +526 -0
  183. package/dist/plugin/skills/apt-research/appendices/budget-loop.md +397 -0
  184. package/dist/plugin/skills/apt-research/appendices/claim-graph-schema.md +206 -0
  185. package/dist/plugin/skills/apt-research/appendices/domain-tools.md +236 -0
  186. package/dist/plugin/skills/apt-resume/SKILL.md +54 -31
  187. package/dist/plugin/skills/apt-run/SKILL.md +114 -16
  188. package/dist/plugin/skills/apt-setup/SKILL.md +97 -8
  189. package/dist/plugin/skills/apt-ship/SKILL.md +165 -9
  190. package/dist/plugin/skills/apt-spar/SKILL.md +84 -23
  191. package/dist/plugin/skills/apt-triage/AGENT-BRIEF.md +0 -8
  192. package/dist/plugin/skills/apt-triage/OUT-OF-SCOPE.md +0 -7
  193. package/dist/plugin/skills/apt-triage/SKILL.md +2 -2
  194. package/dist/plugin/skills/apt-update/SKILL.md +74 -17
  195. package/dist/plugin/skills/apt-verify-proof/SKILL.md +87 -1
  196. package/dist/plugin/skills/apt-zoom-out/SKILL.md +3 -3
  197. package/dist/schemas/quick-task.d.ts +17 -17
  198. package/dist/schemas/quick-task.d.ts.map +1 -1
  199. package/dist/schemas/quick-task.js +2 -2
  200. package/dist/schemas/quick-task.js.map +1 -1
  201. package/dist/types/config.d.ts +33 -0
  202. package/dist/types/config.d.ts.map +1 -1
  203. package/dist/types/state.d.ts +1 -1
  204. package/dist/types/state.d.ts.map +1 -1
  205. package/dist/types/task-record.d.ts +1 -1
  206. package/dist/types/task-record.d.ts.map +1 -1
  207. package/drivers/.gitkeep +0 -0
  208. package/drivers/api/README.md +40 -0
  209. package/drivers/api/driver.mjs +59 -0
  210. package/drivers/api/manifest.json +26 -0
  211. package/drivers/browser/README.md +105 -0
  212. package/drivers/browser/driver.mjs +134 -0
  213. package/drivers/browser/manifest.json +35 -0
  214. package/drivers/cli/README.md +44 -0
  215. package/drivers/cli/driver.mjs +62 -0
  216. package/drivers/cli/manifest.json +28 -0
  217. package/drivers/electron/README.md +64 -0
  218. package/drivers/electron/driver.mjs +87 -0
  219. package/drivers/electron/manifest.json +37 -0
  220. package/package.json +138 -133
  221. package/prompts/planner.md +1 -1
  222. package/prompts/spec_writer.md +1 -1
  223. package/skills/apt/SKILL.md +75 -6
  224. package/skills/apt-caveman/SKILL.md +64 -0
  225. package/skills/apt-debug/SKILL.md +36 -4
  226. package/skills/apt-debug/appendices/diagnose-discipline.md +2 -11
  227. package/skills/apt-discuss/SKILL.md +4 -4
  228. package/skills/apt-discuss/appendices/grill-discipline.md +2 -11
  229. package/skills/apt-discuss/appendices/zoom-out-helper.md +0 -8
  230. package/skills/apt-execute/SKILL.md +27 -4
  231. package/skills/apt-execute/appendices/tdd-mode.md +2 -10
  232. package/skills/apt-fan-out/SKILL.md +36 -1
  233. package/skills/apt-handoff/SKILL.md +228 -0
  234. package/skills/apt-improve/DEEPENING.md +0 -8
  235. package/skills/apt-improve/INTERFACE-DESIGN.md +0 -8
  236. package/skills/apt-improve/LANGUAGE.md +0 -8
  237. package/skills/apt-improve/SKILL.md +4 -4
  238. package/skills/apt-plan/SKILL.md +73 -5
  239. package/skills/apt-plan/adapters/conductor.md +1 -1
  240. package/skills/apt-planner.md +17 -1
  241. package/skills/apt-pr-review/SKILL.md +1 -1
  242. package/skills/apt-prototype/LOGIC.md +0 -8
  243. package/skills/apt-prototype/SKILL.md +4 -4
  244. package/skills/apt-prototype/UI.md +0 -8
  245. package/skills/apt-quick/SKILL.md +31 -1
  246. package/skills/apt-research/SKILL.md +526 -0
  247. package/skills/apt-research/appendices/budget-loop.md +397 -0
  248. package/skills/apt-research/appendices/claim-graph-schema.md +206 -0
  249. package/skills/apt-research/appendices/domain-tools.md +236 -0
  250. package/skills/apt-resume/SKILL.md +54 -31
  251. package/skills/apt-run/SKILL.md +114 -16
  252. package/skills/apt-setup/SKILL.md +97 -8
  253. package/skills/apt-ship/SKILL.md +165 -9
  254. package/skills/apt-spar/SKILL.md +84 -23
  255. package/skills/apt-triage/AGENT-BRIEF.md +0 -8
  256. package/skills/apt-triage/OUT-OF-SCOPE.md +0 -7
  257. package/skills/apt-triage/SKILL.md +2 -2
  258. package/skills/apt-update/SKILL.md +74 -17
  259. package/skills/apt-verify-proof/SKILL.md +87 -1
  260. package/skills/apt-zoom-out/SKILL.md +3 -3
  261. package/src/cli/commands/adr.mjs +1 -1
  262. package/src/cli/commands/audit-branch-current.mjs +250 -0
  263. package/src/cli/commands/audit.mjs +13 -2
  264. package/src/cli/commands/check-version.mjs +20 -1
  265. package/src/cli/commands/context.mjs +3 -3
  266. package/src/cli/commands/coverage-check.mjs +126 -44
  267. package/src/cli/commands/detect-runtime.mjs +143 -0
  268. package/src/cli/commands/driver-doctor.mjs +294 -0
  269. package/src/cli/commands/gate.mjs +15 -0
  270. package/src/cli/commands/init.mjs +9 -6
  271. package/src/cli/commands/install-from-source.mjs +1 -0
  272. package/src/cli/commands/modes.mjs +1 -1
  273. package/src/cli/commands/route.mjs +42 -1
  274. package/src/cli/commands/triage.mjs +1 -1
  275. package/src/cli/config/load.mjs +9 -3
  276. package/src/cli/coordination/auto-emit-artifact-ready.mjs +1 -1
  277. package/src/cli/coordination/event-schema.mjs +19 -0
  278. package/src/cli/coverage-check/user-outcomes.mjs +273 -0
  279. package/src/cli/dispatch.mjs +17 -1
  280. package/src/cli/gate/context.mjs +20 -1
  281. package/src/cli/gate/gates/consistency-check.mjs +1 -0
  282. package/src/cli/gate/gates/review-clean.mjs +1 -0
  283. package/src/cli/gate/gates/verify-approved.mjs +1 -0
  284. package/src/cli/gate/registry.mjs +11 -1
  285. package/src/cli/host/detect.mjs +1 -1
  286. package/src/cli/install/find-workspace-framework-version.mjs +88 -0
  287. package/src/cli/install/install-from-source.mjs +276 -0
  288. package/src/cli/install/install-kernel.mjs +24 -0
  289. package/src/cli/install/legacy-paths.mjs +164 -39
  290. package/src/cli/install/runtime-detect.mjs +1 -1
  291. package/src/cli/install/runtime-migrate.mjs +63 -30
  292. package/src/cli/install/transforms/codex.mjs +26 -17
  293. package/src/cli/skill-author/contract.mjs +2 -2
  294. package/src/cli/verify-proof/.gitkeep +0 -0
  295. package/src/cli/verify-proof/audit.mjs +55 -0
  296. package/src/cli/verify-proof/exec.mjs +74 -0
  297. package/src/cli/verify-proof/idl/index.mjs +23 -0
  298. package/src/cli/verify-proof/idl/types.ts +42 -0
  299. package/src/cli/verify-proof/manifest-schema.json +212 -0
  300. package/src/cli/verify-proof/manifest-validator.mjs +184 -0
  301. package/src/cli/verify-proof/resolver.mjs +330 -0
  302. package/src/cli/verify-proof/runtime-detect.mjs +211 -0
  303. package/src/cli/verify-proof/trust.mjs +187 -0
  304. package/templates/adr-format.md +0 -8
  305. package/templates/aperant-claude-md-appendix.md +1 -1
  306. package/templates/context-format.md +1 -9
  307. package/templates/proof-verification.md +51 -8
  308. package/workflows/verify-proof.md +130 -19
@@ -0,0 +1,88 @@
1
+ /**
2
+ * install/find-workspace-framework-version.mjs — Bundle A.
3
+ *
4
+ * Locates the workspace `packages/framework/package.json` above `targetDir`
5
+ * so the SessionStart worker and `apt-tools check-version` can detect the
6
+ * "self-host contributor's workspace is ahead of the installed kernel" case
7
+ * WITHOUT requiring the user to remember the `--from-source` flag.
8
+ *
9
+ * Mirrors the bounded-walk + semver-validation contract of the route-side
10
+ * `detectSourceWorkspaceDrift` (route/drift-detect.mjs:32-107), but returns
11
+ * just the source workspace metadata — the caller decides whether to flip
12
+ * `update_available` (worker / check-version branch on the comparison).
13
+ *
14
+ * Safe for hot paths: synchronous, file-existence + JSON parse only,
15
+ * bounded walk (6 segments max), no network, no spawn.
16
+ *
17
+ * Security: workspace `package.json:version` is validated against the same
18
+ * `SEMVER_RE` as `update-chips.mjs` so a poisoned `package.json` cannot
19
+ * propagate a non-semver value into downstream envelopes.
20
+ */
21
+
22
+ import { existsSync, readFileSync } from 'node:fs'
23
+ import { dirname, join } from 'node:path'
24
+ import { SEMVER_RE } from '../util/semver.mjs'
25
+
26
+ /** Max directory frames to walk before giving up. Mirrors route/drift-detect.mjs:32. */
27
+ const MAX_WALK_DEPTH = 6
28
+
29
+ /**
30
+ * Walk up from `start`, returning every directory frame including `start`
31
+ * itself. Stops at the filesystem root or at depth `MAX_WALK_DEPTH`
32
+ * (whichever comes first).
33
+ *
34
+ * @param {string} start
35
+ * @returns {string[]}
36
+ */
37
+ function walkUp(start) {
38
+ const frames = []
39
+ let cur = start
40
+ for (let i = 0; i < MAX_WALK_DEPTH; i++) {
41
+ frames.push(cur)
42
+ const parent = dirname(cur)
43
+ if (parent === cur) break
44
+ cur = parent
45
+ }
46
+ return frames
47
+ }
48
+
49
+ /**
50
+ * Find the workspace `@aperant/framework` package above `targetDir`.
51
+ *
52
+ * @param {string} targetDir Absolute path to start the walk from.
53
+ * @returns {null | { source_path: string, source_version: string }}
54
+ * `source_path` is the absolute path to `packages/framework/package.json`.
55
+ * `source_version` is the semver-validated `version` field. Returns null
56
+ * when no workspace package is found, when the workspace package name is
57
+ * not `@aperant/framework`, or when the workspace version fails the
58
+ * semver-shape check.
59
+ */
60
+ export function findWorkspaceFrameworkVersion(targetDir) {
61
+ if (!targetDir || typeof targetDir !== 'string') return null
62
+
63
+ for (const dir of walkUp(targetDir)) {
64
+ const candidate = join(dir, 'packages', 'framework', 'package.json')
65
+ if (!existsSync(candidate)) continue
66
+
67
+ let pkg
68
+ try {
69
+ pkg = JSON.parse(readFileSync(candidate, 'utf-8'))
70
+ } catch {
71
+ continue
72
+ }
73
+
74
+ // Guard against false matches on unrelated monorepos that happen to
75
+ // have a `packages/framework/` directory.
76
+ if (pkg?.name !== '@aperant/framework') continue
77
+
78
+ const sourceVersion = pkg?.version
79
+ if (typeof sourceVersion !== 'string' || !SEMVER_RE.test(sourceVersion)) continue
80
+
81
+ return {
82
+ source_path: candidate,
83
+ source_version: sourceVersion,
84
+ }
85
+ }
86
+
87
+ return null
88
+ }
@@ -0,0 +1,276 @@
1
+ /**
2
+ * install/install-from-source.mjs — Bundle D part 1.
3
+ *
4
+ * `apt-tools install-from-source <project-dir>` for the Aperant-contributor
5
+ * self-host case. Resolves the workspace `@aperant/framework` chain — packs
6
+ * the framework itself AND every `workspace:*` dependency (none today after
7
+ * the 0.8.5 driver-sdk inline, but the walker is general). Hands the full
8
+ * tarball list to a single `npm install --prefix` invocation so any future
9
+ * unpublished-pair case stops blowing up with `EUNSUPPORTEDPROTOCOL`.
10
+ *
11
+ * Stable envelope:
12
+ * { status: 'ok', tarballs: string[], kernel_path: string }
13
+ * { status: 'error', error: string, ...optional context }
14
+ *
15
+ * Test seams: `APT_PNPM_BIN` + `APT_NPM_BIN` mirror the existing
16
+ * `install-kernel.mjs` + worker patterns.
17
+ */
18
+
19
+ import { spawnSync } from 'node:child_process'
20
+ import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync } from 'node:fs'
21
+ import { tmpdir } from 'node:os'
22
+ import { dirname, isAbsolute, join, resolve } from 'node:path'
23
+ import { err, ok } from '../util/result.mjs'
24
+ import { findWorkspaceFrameworkVersion } from './find-workspace-framework-version.mjs'
25
+ import { KERNEL_BIN_REL_PATH } from './install-kernel.mjs'
26
+
27
+ /**
28
+ * Locate the monorepo root given the workspace framework package.json path.
29
+ * `<root>/packages/framework/package.json` → `<root>`.
30
+ *
31
+ * @param {string} frameworkPkgPath
32
+ * @returns {string}
33
+ */
34
+ function monorepoRootFrom(frameworkPkgPath) {
35
+ // `<root>/packages/framework/package.json` — go up THREE levels.
36
+ return dirname(dirname(dirname(frameworkPkgPath)))
37
+ }
38
+
39
+ /**
40
+ * Scan `<monorepoRoot>/packages/` for a directory whose `package.json:name`
41
+ * matches `pkgName`. Returns the directory path (containing package.json),
42
+ * or null if no match.
43
+ *
44
+ * @param {string} monorepoRoot
45
+ * @param {string} pkgName
46
+ * @returns {string|null}
47
+ */
48
+ function findWorkspacePackage(monorepoRoot, pkgName) {
49
+ const packagesDir = join(monorepoRoot, 'packages')
50
+ if (!existsSync(packagesDir)) return null
51
+ let entries
52
+ try {
53
+ entries = readdirSync(packagesDir, { withFileTypes: true })
54
+ } catch {
55
+ return null
56
+ }
57
+ for (const entry of entries) {
58
+ if (!entry.isDirectory()) continue
59
+ const candidate = join(packagesDir, entry.name, 'package.json')
60
+ if (!existsSync(candidate)) continue
61
+ try {
62
+ const pkg = JSON.parse(readFileSync(candidate, 'utf-8'))
63
+ if (pkg?.name === pkgName) return join(packagesDir, entry.name)
64
+ } catch {
65
+ // Skip unreadable package.json files.
66
+ }
67
+ }
68
+ return null
69
+ }
70
+
71
+ /**
72
+ * pnpm-pack a workspace package into `tmpDir` and return the resulting
73
+ * tarball path. Uses `pnpm --filter <name> pack --pack-destination <tmp>`
74
+ * so workspace protocols resolve to concrete versions inside the tarball.
75
+ *
76
+ * `knownBefore` is the set of .tgz filenames already present in `tmpDir`
77
+ * before this call; the mtime fallback uses it to find only the NEW file,
78
+ * avoiding coarse-timestamp ambiguity when multiple packs land in the same
79
+ * directory.
80
+ *
81
+ * @param {string} monorepoRoot
82
+ * @param {string} pkgName
83
+ * @param {string} tmpDir
84
+ * @param {Set<string>} knownBefore Filenames (not paths) present before this pack.
85
+ * @returns {{ tarball: string } | { error: string }}
86
+ */
87
+ function packWorkspace(monorepoRoot, pkgName, tmpDir, knownBefore) {
88
+ const pnpmBin = process.env.APT_PNPM_BIN || 'pnpm'
89
+ const result = spawnSync(pnpmBin, ['--filter', pkgName, 'pack', '--pack-destination', tmpDir], {
90
+ cwd: monorepoRoot,
91
+ stdio: ['ignore', 'pipe', 'pipe'],
92
+ encoding: 'utf-8',
93
+ timeout: 120_000,
94
+ })
95
+ if (result.error) {
96
+ return { error: `pnpm spawn failed for ${pkgName}: ${result.error.message}` }
97
+ }
98
+ if (result.status !== 0) {
99
+ const stderr = (result.stderr || '').trim().slice(-600)
100
+ return { error: `pnpm pack ${pkgName} exited with ${result.status}: ${stderr || 'no stderr'}` }
101
+ }
102
+ // pnpm pack prints the resulting tarball path on stdout. Take the last
103
+ // `.tgz` line (pnpm sometimes emits warnings above the path line).
104
+ const tarballLine = (result.stdout || '')
105
+ .split('\n')
106
+ .map((s) => s.trim())
107
+ .reverse()
108
+ .find((s) => s.endsWith('.tgz'))
109
+ if (tarballLine) {
110
+ // `tarballLine` may be a bare filename (older pnpm) or an absolute path.
111
+ // Use `isAbsolute` so Windows backslash + drive-letter paths are also
112
+ // recognized — `startsWith('/')` was POSIX-only.
113
+ const tarball = isAbsolute(tarballLine) ? tarballLine : join(tmpDir, tarballLine)
114
+ // SEC-001: containment check — tarball must resolve to a child of tmpDir.
115
+ const resolvedTmpDir = resolve(tmpDir)
116
+ const resolvedTarball = resolve(tarball)
117
+ if (!resolvedTarball.startsWith(`${resolvedTmpDir}/`) && resolvedTarball !== resolvedTmpDir) {
118
+ return { error: `pnpm pack ${pkgName}: tarball path escapes tmpDir: ${tarball}` }
119
+ }
120
+ return { tarball }
121
+ }
122
+ // Fall back to scanning tmpDir for the NEW tgz when stdout was
123
+ // uninformative (some pnpm builds print only progress to stderr).
124
+ // Use `knownBefore` to find only files added by this pack, avoiding
125
+ // mtime coarse-timestamp ambiguity on FAT32/network filesystems.
126
+ try {
127
+ for (const f of readdirSync(tmpDir)) {
128
+ if (!f.endsWith('.tgz')) continue
129
+ if (knownBefore.has(f)) continue
130
+ return { tarball: join(tmpDir, f) }
131
+ }
132
+ } catch {
133
+ // fall through
134
+ }
135
+ return {
136
+ error: `pnpm pack ${pkgName}: no .tgz produced (stdout: ${result.stdout?.slice(-200)})`,
137
+ }
138
+ }
139
+
140
+ /**
141
+ * `apt-tools install-from-source <project-dir>` — pack the workspace
142
+ * framework + every `workspace:*` dep, then npm-install the full tarball
143
+ * list into `<project-dir>/.aperant/deps/`.
144
+ *
145
+ * @param {string} projectDir
146
+ * @returns {import('../util/result.mjs').CommandResult}
147
+ */
148
+ export function cmdInstallFromSource(projectDir) {
149
+ if (!projectDir) {
150
+ return err('Usage: apt-tools install-from-source <project-dir>')
151
+ }
152
+ const targetDir = resolve(projectDir)
153
+
154
+ const workspace = findWorkspaceFrameworkVersion(targetDir)
155
+ if (!workspace) {
156
+ return err('install-from-source: no @aperant/framework workspace found above project-dir')
157
+ }
158
+ const monorepoRoot = monorepoRootFrom(workspace.source_path)
159
+
160
+ // QUA-001: re-read the workspace package.json with a try/catch — the file
161
+ // was validated by findWorkspaceFrameworkVersion but could change between
162
+ // the two reads (active monorepo, contributor machine).
163
+ let frameworkPkg
164
+ try {
165
+ frameworkPkg = JSON.parse(readFileSync(workspace.source_path, 'utf-8'))
166
+ } catch (e) {
167
+ return err(
168
+ `install-from-source: failed to read ${workspace.source_path}: ${e instanceof Error ? e.message : String(e)}`,
169
+ )
170
+ }
171
+
172
+ // Enumerate workspace:* deps from dependencies + peerDependencies.
173
+ const depSources = [frameworkPkg.dependencies, frameworkPkg.peerDependencies]
174
+ const workspaceDeps = []
175
+ for (const block of depSources) {
176
+ if (!block || typeof block !== 'object') continue
177
+ for (const [name, spec] of Object.entries(block)) {
178
+ if (typeof spec === 'string' && spec.startsWith('workspace:')) {
179
+ if (!workspaceDeps.includes(name)) workspaceDeps.push(name)
180
+ }
181
+ }
182
+ }
183
+
184
+ // Resolve each workspace dep to its `packages/<dir>` path. Reject hard
185
+ // when any dep cannot be located — we cannot pack what we cannot find.
186
+ const missingDeps = []
187
+ const resolvedDeps = []
188
+ for (const depName of workspaceDeps) {
189
+ const pkgDir = findWorkspacePackage(monorepoRoot, depName)
190
+ if (!pkgDir) {
191
+ missingDeps.push(depName)
192
+ continue
193
+ }
194
+ resolvedDeps.push({ name: depName, dir: pkgDir })
195
+ }
196
+ if (missingDeps.length > 0) {
197
+ return err(
198
+ `install-from-source: workspace:* dep(s) not found in packages/: ${missingDeps.join(', ')}`,
199
+ )
200
+ }
201
+
202
+ // PRF-001: include framework in the same pack loop — eliminates structural
203
+ // duplication and ensures per-pack knownBefore snapshots work uniformly.
204
+ const packTargets = [...resolvedDeps.map((d) => d.name), '@aperant/framework']
205
+
206
+ // Pack everything into a fresh tmp dir so accumulated stale tarballs
207
+ // from prior runs don't sneak in.
208
+ const tmpDir = mkdtempSync(join(tmpdir(), 'apt-install-from-source-'))
209
+ const tarballs = []
210
+
211
+ // QUA-002: wrap pack+install in try/finally so tmpDir is always removed.
212
+ try {
213
+ for (const pkgName of packTargets) {
214
+ // LOG-003: snapshot existing tgz filenames before each pack so the
215
+ // fallback can identify exactly the new file, even on coarse-timestamp
216
+ // filesystems (FAT32, some network mounts).
217
+ const knownBefore = new Set()
218
+ try {
219
+ for (const f of readdirSync(tmpDir)) {
220
+ if (f.endsWith('.tgz')) knownBefore.add(f)
221
+ }
222
+ } catch {
223
+ // tmpDir unreadable — proceed with empty set; fallback will still work.
224
+ }
225
+ const packResult = packWorkspace(monorepoRoot, pkgName, tmpDir, knownBefore)
226
+ if ('error' in packResult) return err(packResult.error)
227
+ tarballs.push(packResult.tarball)
228
+ }
229
+
230
+ // npm install --prefix .aperant/deps <tarball1> <tarball2> ...
231
+ const depsDir = join(targetDir, '.aperant', 'deps')
232
+ mkdirSync(depsDir, { recursive: true })
233
+
234
+ const npmBin = process.env.APT_NPM_BIN || 'npm'
235
+ const args = [
236
+ 'install',
237
+ '--prefix',
238
+ depsDir,
239
+ ...tarballs,
240
+ '--no-save',
241
+ '--no-package-lock',
242
+ '--no-audit',
243
+ '--no-fund',
244
+ '--silent',
245
+ ]
246
+ const npmResult = spawnSync(npmBin, args, {
247
+ cwd: targetDir,
248
+ stdio: ['ignore', 'pipe', 'pipe'],
249
+ encoding: 'utf-8',
250
+ timeout: 180_000,
251
+ })
252
+ if (npmResult.error) {
253
+ return err(`install-from-source: npm spawn failed: ${npmResult.error.message}`)
254
+ }
255
+ if (npmResult.status !== 0) {
256
+ const stderr = (npmResult.stderr || '').trim().slice(-600)
257
+ return err(
258
+ `install-from-source: npm install --prefix exited with ${npmResult.status}: ${stderr || 'no stderr'}`,
259
+ )
260
+ }
261
+
262
+ const kernelPath = join(targetDir, KERNEL_BIN_REL_PATH)
263
+ if (!existsSync(kernelPath)) {
264
+ return err(`install-from-source: npm reported success but kernel not found at ${kernelPath}`)
265
+ }
266
+
267
+ return ok({
268
+ status: 'ok',
269
+ command: 'install-from-source',
270
+ tarballs,
271
+ kernel_path: kernelPath,
272
+ })
273
+ } finally {
274
+ rmSync(tmpDir, { recursive: true, force: true })
275
+ }
276
+ }
@@ -120,6 +120,30 @@ export function installKernel(targetDir, version, opts = {}) {
120
120
  const kernelPath = join(targetDir, KERNEL_BIN_REL_PATH)
121
121
  const npmBin = resolveNpmBin()
122
122
 
123
+ // Bundle B — idempotency short-circuit. When the kernel package.json
124
+ // already reports the requested version AND the kernel binary exists,
125
+ // skip the npm spawn entirely. Returns the same `status: 'installed'`
126
+ // envelope shape that downstream consumers branch on (init.mjs:1441,
127
+ // init.mjs:1735, apt-update/SKILL.md Scenario D) — no new enum value
128
+ // per D-02.
129
+ const installedPkgPath = join(depsDir, 'node_modules', '@aperant', 'framework', 'package.json')
130
+ if (existsSync(installedPkgPath) && existsSync(kernelPath)) {
131
+ try {
132
+ const installedPkg = JSON.parse(readFileSync(installedPkgPath, 'utf-8'))
133
+ if (installedPkg?.version === version) {
134
+ return {
135
+ status: 'installed',
136
+ kernelPath,
137
+ reason: 'already at target version',
138
+ durationMs: 0,
139
+ }
140
+ }
141
+ } catch {
142
+ // Malformed package.json — fall through to the npm install path
143
+ // (npm will reconcile / repair).
144
+ }
145
+ }
146
+
123
147
  const t0 = Date.now()
124
148
  const args = [
125
149
  'install',
@@ -11,18 +11,28 @@
11
11
  * pre-manifest install still surfaces as "installed" rather than
12
12
  * "missing-skills".
13
13
  *
14
- * Derivation: the codex `framework_files` list was extracted from
15
- * `git show 1a8dd8a8 --stat` (the original "make Codex a first-class
16
- * skill install surface" commit) every `.agents/skills/…` path the
17
- * installer once wrote, including the `.apt-version` stamp and the
18
- * apt-pr-review / apt-discuss / apt-verify-proof sub-files. When the
19
- * codex installer was retargeted to `.codex/`, that entire tree became
20
- * orphaned on upgrading projects.
14
+ * Codex evolution: v0.7/v0.8 retargeted the codex transform to write
15
+ * markdown skills under `.codex/agents/` + `.codex/commands/` (with the
16
+ * apt-file-manifest.json next to them). Codex CLI 0.132.0 does not
17
+ * discover skills at either path its documented surface is
18
+ * `.agents/skills/<folder>/SKILL.md` (per
19
+ * https://developers.openai.com/codex/skills). The v0.8.2 fix inverts
20
+ * this registry: the dead `.codex/` markdown tree becomes the legacy
21
+ * target so `runLegacyCleanup` GCs it on the next `apt-tools init`.
21
22
  *
22
23
  * Schema:
23
24
  * { [runtimeId]: {
24
25
  * install_root: relative path the runtime once wrote into,
25
- * version_file: relative path of the legacy `.apt-version` stamp,
26
+ * version_file: relative path of the legacy `.apt-version` stamp
27
+ * (or a path known to never exist, when no version
28
+ * stamp was ever written for the legacy topology),
29
+ * honor_manifest: when true (default), a present apt-file-manifest.json
30
+ * at install_root signals a managed install and the
31
+ * cleanup no-ops (`reason: 'managed'`). When false,
32
+ * the legacy root is known-dead so the manifest is
33
+ * removed alongside framework files (used for surfaces
34
+ * like the v0.7/v0.8 codex misdirect that will never
35
+ * again be a managed install root).
26
36
  * framework_files: array of relative paths the installer once owned
27
37
  * (under install_root).
28
38
  * } }
@@ -30,40 +40,155 @@
30
40
  * Frozen via Object.freeze so callers cannot mutate the shared registry.
31
41
  */
32
42
 
33
- /** @type {Record<string, { install_root: string, version_file: string, framework_files: ReadonlyArray<string> }>} */
43
+ /**
44
+ * @typedef {Object} LegacyInstallPath
45
+ * @property {string} install_root
46
+ * @property {string} version_file
47
+ * @property {boolean} [honor_manifest] default true; false for known-dead surfaces
48
+ * @property {ReadonlyArray<string>} framework_files
49
+ */
50
+
51
+ /** @type {Record<string, LegacyInstallPath>} */
34
52
  export const LEGACY_INSTALL_PATHS = Object.freeze({
35
53
  codex: Object.freeze({
36
- install_root: '.agents/skills',
37
- version_file: '.agents/skills/.apt-version',
54
+ // The v0.7/v0.8 misdirect lived under `.codex/agents/` + `.codex/commands/`
55
+ // (with the orphan apt-file-manifest.json at `.codex/apt-file-manifest.json`).
56
+ // Codex CLI 0.132.0 does not consume any of those paths — see header.
57
+ install_root: '.codex',
58
+ // No `.apt-version` was ever written under `.codex/`; point at a path
59
+ // that doesn't exist so `existsSync` returns false in
60
+ // skill-installs.mjs:67-68 (legacy version_file fallback). The bare
61
+ // apt-file-manifest.json (handled by framework_files) is enough to
62
+ // signal the legacy install.
63
+ version_file: '.codex/.apt-version',
64
+ // Known-dead surface: this `.codex/` topology will never again be
65
+ // a managed Aperant install root, so a manifest sitting here is
66
+ // always stale. Skip the no-op-on-manifest safety and remove the
67
+ // manifest alongside framework_files. Default-true elsewhere
68
+ // preserves the safety for legacy roots that could legitimately
69
+ // re-host a managed install.
70
+ honor_manifest: false,
71
+ // Enumerated from BOTH canonical sources (drift-checked at test time
72
+ // by legacy-cleanup-codex.test.ts):
73
+ // - For each `packages/framework/skills/apt-*/` directory: the v0.7/v0.8
74
+ // transform emitted BOTH `agents/<dir>.md` AND `commands/<dir>.md`.
75
+ // - For each top-level `packages/framework/skills/apt-*.md` file
76
+ // (fileType=agent in the pipeline): the transform emitted
77
+ // `agents/<basename>.md`.
78
+ // - For each `packages/framework/agents/apt-*.md` file: the transform
79
+ // emitted `agents/<basename>.md` (last-write-wins de-dupe applied
80
+ // by the pipeline for overlapping outputs).
81
+ // - Plus the orphan apt-file-manifest.json the install pipeline
82
+ // stamps at install_root.
83
+ // TODO: follow-up — derive this programmatically per spec ID-06 so
84
+ // new apt-* skills auto-extend the legacy set without an edit here.
38
85
  framework_files: Object.freeze([
39
- '.apt-version',
40
- 'apt/SKILL.md',
41
- 'apt-debug/SKILL.md',
42
- 'apt-discuss/SKILL.md',
43
- 'apt-discuss/examples/rationalization-example.md',
44
- 'apt-docs/SKILL.md',
45
- 'apt-execute/SKILL.md',
46
- 'apt-pause/SKILL.md',
47
- 'apt-plan/SKILL.md',
48
- 'apt-pr-review/SCHEMA.md',
49
- 'apt-pr-review/SKILL.md',
50
- 'apt-pr-review/prompts/fp-gate-codex.md',
51
- 'apt-pr-review/templates/external-comment.md',
52
- 'apt-quick/SKILL.md',
53
- 'apt-resume/SKILL.md',
54
- 'apt-review/SKILL.md',
55
- 'apt-roadmap/SKILL.md',
56
- 'apt-roundtable/SKILL.md',
57
- 'apt-run/SKILL.md',
58
- 'apt-scan/SKILL.md',
59
- 'apt-setup/SKILL.md',
60
- 'apt-ship/SKILL.md',
61
- 'apt-stress-test/SKILL.md',
62
- 'apt-verify/SKILL.md',
63
- 'apt-verify-proof/SKILL.md',
64
- 'apt-verify-proof/references/multi-model-setup.md',
65
- 'apt-verify-proof/references/multi-model-verification.md',
66
- 'apt-verify-proof/references/proof-capture.md',
86
+ 'apt-file-manifest.json',
87
+ // agents/<dir>.md — one per skill directory (39 dirs)
88
+ 'agents/apt.md',
89
+ 'agents/apt-author-skill.md',
90
+ 'agents/apt-bootstrap.md',
91
+ 'agents/apt-caveman.md',
92
+ 'agents/apt-classify.md',
93
+ 'agents/apt-close-task.md',
94
+ 'agents/apt-create-docs.md',
95
+ 'agents/apt-debug.md',
96
+ 'agents/apt-design.md',
97
+ 'agents/apt-diagram.md',
98
+ 'agents/apt-discuss.md',
99
+ 'agents/apt-docs.md',
100
+ 'agents/apt-execute.md',
101
+ 'agents/apt-fan-out.md',
102
+ 'agents/apt-handoff.md',
103
+ 'agents/apt-improve.md',
104
+ 'agents/apt-mockup.md',
105
+ 'agents/apt-pause.md',
106
+ 'agents/apt-personas.md',
107
+ 'agents/apt-plan.md',
108
+ 'agents/apt-pr-review.md',
109
+ 'agents/apt-prototype.md',
110
+ 'agents/apt-quick.md',
111
+ 'agents/apt-release-notes.md',
112
+ 'agents/apt-research.md',
113
+ 'agents/apt-resume.md',
114
+ 'agents/apt-review.md',
115
+ 'agents/apt-roadmap.md',
116
+ 'agents/apt-roundtable.md',
117
+ 'agents/apt-run.md',
118
+ 'agents/apt-scan.md',
119
+ 'agents/apt-setup.md',
120
+ 'agents/apt-ship.md',
121
+ 'agents/apt-spar.md',
122
+ 'agents/apt-stress-test.md',
123
+ 'agents/apt-terminal.md',
124
+ 'agents/apt-triage.md',
125
+ 'agents/apt-update.md',
126
+ 'agents/apt-verify.md',
127
+ 'agents/apt-verify-proof.md',
128
+ 'agents/apt-watch-ci.md',
129
+ 'agents/apt-zoom-out.md',
130
+ // commands/<dir>.md — one per skill directory (mirrors agents/)
131
+ 'commands/apt.md',
132
+ 'commands/apt-author-skill.md',
133
+ 'commands/apt-bootstrap.md',
134
+ 'commands/apt-caveman.md',
135
+ 'commands/apt-classify.md',
136
+ 'commands/apt-close-task.md',
137
+ 'commands/apt-create-docs.md',
138
+ 'commands/apt-debug.md',
139
+ 'commands/apt-design.md',
140
+ 'commands/apt-diagram.md',
141
+ 'commands/apt-discuss.md',
142
+ 'commands/apt-docs.md',
143
+ 'commands/apt-execute.md',
144
+ 'commands/apt-fan-out.md',
145
+ 'commands/apt-handoff.md',
146
+ 'commands/apt-improve.md',
147
+ 'commands/apt-mockup.md',
148
+ 'commands/apt-pause.md',
149
+ 'commands/apt-personas.md',
150
+ 'commands/apt-plan.md',
151
+ 'commands/apt-pr-review.md',
152
+ 'commands/apt-prototype.md',
153
+ 'commands/apt-quick.md',
154
+ 'commands/apt-release-notes.md',
155
+ 'commands/apt-research.md',
156
+ 'commands/apt-resume.md',
157
+ 'commands/apt-review.md',
158
+ 'commands/apt-roadmap.md',
159
+ 'commands/apt-roundtable.md',
160
+ 'commands/apt-run.md',
161
+ 'commands/apt-scan.md',
162
+ 'commands/apt-setup.md',
163
+ 'commands/apt-ship.md',
164
+ 'commands/apt-spar.md',
165
+ 'commands/apt-stress-test.md',
166
+ 'commands/apt-terminal.md',
167
+ 'commands/apt-triage.md',
168
+ 'commands/apt-update.md',
169
+ 'commands/apt-verify.md',
170
+ 'commands/apt-verify-proof.md',
171
+ 'commands/apt-watch-ci.md',
172
+ 'commands/apt-zoom-out.md',
173
+ // agents/<basename>.md — packages/framework/agents/apt-*.md (17 files)
174
+ // (overlap with skills/apt-*.md top-level — same outputPath, de-dupe)
175
+ 'agents/apt-docs-author.md',
176
+ 'agents/apt-executor.md',
177
+ 'agents/apt-improver.md',
178
+ 'agents/apt-planner.md',
179
+ 'agents/apt-pr-review-codebase-fit.md',
180
+ 'agents/apt-pr-review-fixer.md',
181
+ 'agents/apt-pr-review-logic.md',
182
+ 'agents/apt-pr-review-performance.md',
183
+ 'agents/apt-pr-review-quality.md',
184
+ 'agents/apt-pr-review-security.md',
185
+ 'agents/apt-pr-review-self-reviewer.md',
186
+ 'agents/apt-pr-review-test-integrity.md',
187
+ 'agents/apt-pr-review-validator.md',
188
+ 'agents/apt-researcher.md',
189
+ 'agents/apt-reviewer.md',
190
+ 'agents/apt-team-docs-narrator.md',
191
+ 'agents/apt-verifier.md',
67
192
  ]),
68
193
  }),
69
194
  })
@@ -50,7 +50,7 @@ export const RUNTIMES = Object.freeze([
50
50
  {
51
51
  id: 'codex',
52
52
  flag: '--codex',
53
- installRoot: '.codex',
53
+ installRoot: '.agents',
54
54
  markers: ['.codex/config.toml'],
55
55
  cliId: 'codex',
56
56
  },