agentera 3.0.0-dev.25 → 3.0.0-dev.27

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 (495) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +29 -23
  3. package/bundle/CHANGELOG.md +18 -25
  4. package/bundle/README.md +13 -34
  5. package/bundle/UPGRADE.md +71 -165
  6. package/bundle/references/adapters/package-manifest-interface-model.yaml +40 -241
  7. package/bundle/references/adapters/package-registry.yaml +0 -145
  8. package/bundle/references/adapters/package-surface-characterization.md +22 -42
  9. package/bundle/references/adapters/runtime-lifecycle-adapters.yaml +5 -219
  10. package/bundle/references/adapters/runtime-lifecycle-authority.yaml +2 -29
  11. package/bundle/references/adapters/runtime-lifecycle-operation-contract.yaml +1 -1
  12. package/bundle/references/analysis/analytics-boundary-proportional-2026-07-20.yaml +74 -0
  13. package/bundle/references/analysis/benchmark.md +11 -0
  14. package/bundle/references/analysis/evidence/analytics-boundary-proportional-2026-07-20/source-focused-1.json.gz +0 -0
  15. package/bundle/references/analysis/evidence/analytics-boundary-proportional-2026-07-20/source-focused-2.json.gz +0 -0
  16. package/bundle/references/analysis/evidence/analytics-boundary-proportional-2026-07-20/source-focused-3.json.gz +0 -0
  17. package/bundle/references/analysis/evidence/migration-pagination-proportional-2026-07-20/source-focused-1.json.gz +0 -0
  18. package/bundle/references/analysis/evidence/migration-pagination-proportional-2026-07-20/source-focused-2.json.gz +0 -0
  19. package/bundle/references/analysis/evidence/migration-pagination-proportional-2026-07-20/source-focused-3.json.gz +0 -0
  20. package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/precommit-cli-route.log.gz +0 -0
  21. package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/precommit-cli.log.gz +0 -0
  22. package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/precommit-documentation.log.gz +0 -0
  23. package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/recompute.mjs +98 -0
  24. package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/source-1.json.gz +0 -0
  25. package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/source-2.json.gz +0 -0
  26. package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/source-3.json.gz +0 -0
  27. package/bundle/references/analysis/migration-pagination-proportional-2026-07-20.yaml +64 -0
  28. package/bundle/references/analysis/verification-baseline-2026-07-20.yaml +313 -0
  29. package/bundle/references/analysis/verification-final-proof-2026-07-21.yaml +340 -0
  30. package/bundle/references/analysis/verification-policy.yaml +142 -0
  31. package/bundle/references/analysis/worker-policy-2026-07-21.yaml +207 -0
  32. package/bundle/references/artifacts/state-storage-authority.yaml +48 -448
  33. package/bundle/references/cli/agent-ready-state-contract.yaml +9 -9
  34. package/bundle/references/cli/app-lifecycle-vocabulary.yaml +3 -4
  35. package/bundle/references/cli/bundle-skill-vocabulary.yaml +9 -18
  36. package/bundle/references/cli/capability-tool-classification.yaml +2 -2
  37. package/bundle/references/cli/prime-consumer-compatibility.yaml +86 -112
  38. package/bundle/references/cli/routing-execution-vocabulary.yaml +4 -22
  39. package/bundle/references/cli/upgrade-repair-wording.md +8 -28
  40. package/bundle/references/cli/v3-handoff-manifest.schema.yaml +2 -3
  41. package/bundle/references/cli/vocabulary.md +18 -23
  42. package/bundle/references/meta/documentation-inventory.md +3 -1
  43. package/bundle/skills/agentera/capabilities/orchestrate/schemas/artifacts.yaml +3 -2
  44. package/bundle/skills/agentera/capabilities/orchestrate/schemas/exit.yaml +1 -1
  45. package/bundle/skills/agentera/schemas/artifacts/docs.yaml +3 -11
  46. package/bundle/skills/agentera/schemas/artifacts/plan.yaml +23 -5
  47. package/dist/analytics/extractCorpus/cli.js.map +1 -1
  48. package/dist/analytics/extractCorpus/copilotSessions.js.map +1 -1
  49. package/dist/analytics/extractCorpus/core.js.map +1 -1
  50. package/dist/analytics/extractCorpus/corpus.js.map +1 -1
  51. package/dist/analytics/extractCorpus/coverageAudit.js.map +1 -1
  52. package/dist/analytics/extractCorpus/cursorSessions.js.map +1 -1
  53. package/dist/analytics/extractCorpus/evidenceTiers.js.map +1 -1
  54. package/dist/analytics/extractCorpus/extractCorpusParity.js +1 -1
  55. package/dist/analytics/extractCorpus/extractCorpusParity.js.map +1 -1
  56. package/dist/analytics/extractCorpus/filesystemSources.js.map +1 -1
  57. package/dist/analytics/extractCorpus/index.js.map +1 -1
  58. package/dist/analytics/extractCorpus/jsonlSessions.js.map +1 -1
  59. package/dist/analytics/extractCorpus/sqliteCaps.js.map +1 -1
  60. package/dist/analytics/extractCorpus/sqliteSessions.js.map +1 -1
  61. package/dist/analytics/extractCorpus/tierReader.js.map +1 -1
  62. package/dist/analytics/extractCorpus.js.map +1 -1
  63. package/dist/analytics/profileSignals.js.map +1 -1
  64. package/dist/analytics/usageStats.js.map +1 -1
  65. package/dist/bin/agentera.js.map +1 -1
  66. package/dist/capabilities/audit/instructions.js.map +1 -1
  67. package/dist/capabilities/build/instructions.js.map +1 -1
  68. package/dist/capabilities/design/instructions.js.map +1 -1
  69. package/dist/capabilities/discuss/instructions.js.map +1 -1
  70. package/dist/capabilities/document/instructions.js.map +1 -1
  71. package/dist/capabilities/index.js.map +1 -1
  72. package/dist/capabilities/optimize/instructions.js.map +1 -1
  73. package/dist/capabilities/orchestrate/instructions.js +1 -1
  74. package/dist/capabilities/orchestrate/instructions.js.map +1 -1
  75. package/dist/capabilities/plan/instructions.js.map +1 -1
  76. package/dist/capabilities/profile/instructions.js.map +1 -1
  77. package/dist/capabilities/research/instructions.js.map +1 -1
  78. package/dist/capabilities/status/instructions.js.map +1 -1
  79. package/dist/capabilities/status/startupInstructions.js.map +1 -1
  80. package/dist/capabilities/vision/instructions.js.map +1 -1
  81. package/dist/cli/appContext.js.map +1 -1
  82. package/dist/cli/argvalidate.js.map +1 -1
  83. package/dist/cli/capabilityContext/benchmark.js.map +1 -1
  84. package/dist/cli/capabilityContext/bespoke.js +8 -2
  85. package/dist/cli/capabilityContext/bespoke.js.map +1 -1
  86. package/dist/cli/capabilityContext/build.js.map +1 -1
  87. package/dist/cli/capabilityContext/closeout.js +3 -3
  88. package/dist/cli/capabilityContext/closeout.js.map +1 -1
  89. package/dist/cli/capabilityContext/contract.js.map +1 -1
  90. package/dist/cli/capabilityContext/evidence.js +52 -40
  91. package/dist/cli/capabilityContext/evidence.js.map +1 -1
  92. package/dist/cli/capabilityContext/index.js.map +1 -1
  93. package/dist/cli/capabilityContext/orchestration.js +15 -5
  94. package/dist/cli/capabilityContext/orchestration.js.map +1 -1
  95. package/dist/cli/capabilityContext/planState.js +1 -1
  96. package/dist/cli/capabilityContext/planState.js.map +1 -1
  97. package/dist/cli/capabilityContext/progress.js.map +1 -1
  98. package/dist/cli/capabilityContext/shared.js.map +1 -1
  99. package/dist/cli/capabilityContext/slim.js +16 -3
  100. package/dist/cli/capabilityContext/slim.js.map +1 -1
  101. package/dist/cli/capabilityContext/startup.js +4 -1
  102. package/dist/cli/capabilityContext/startup.js.map +1 -1
  103. package/dist/cli/capabilityContext/types.js.map +1 -1
  104. package/dist/cli/capabilityContext.js.map +1 -1
  105. package/dist/cli/commands/appHome.js.map +1 -1
  106. package/dist/cli/commands/capability.js.map +1 -1
  107. package/dist/cli/commands/compact.js.map +1 -1
  108. package/dist/cli/commands/doctor.js +6 -64
  109. package/dist/cli/commands/doctor.js.map +1 -1
  110. package/dist/cli/commands/durability.js +12 -48
  111. package/dist/cli/commands/durability.js.map +1 -1
  112. package/dist/cli/commands/entityMigrate.js.map +1 -1
  113. package/dist/cli/commands/lint.js.map +1 -1
  114. package/dist/cli/commands/prime/briefOrientation.js +25 -24
  115. package/dist/cli/commands/prime/briefOrientation.js.map +1 -1
  116. package/dist/cli/commands/prime/bundleStatus.js +8 -2
  117. package/dist/cli/commands/prime/bundleStatus.js.map +1 -1
  118. package/dist/cli/commands/prime/collectEntityOrientation.js +76 -24
  119. package/dist/cli/commands/prime/collectEntityOrientation.js.map +1 -1
  120. package/dist/cli/commands/prime/collectOrientationState.js +34 -53
  121. package/dist/cli/commands/prime/collectOrientationState.js.map +1 -1
  122. package/dist/cli/commands/prime/orientationOutput.js +9 -14
  123. package/dist/cli/commands/prime/orientationOutput.js.map +1 -1
  124. package/dist/cli/commands/prime/types.js.map +1 -1
  125. package/dist/cli/commands/prime/v1Migration.js.map +1 -1
  126. package/dist/cli/commands/prime.js +43 -25
  127. package/dist/cli/commands/prime.js.map +1 -1
  128. package/dist/cli/commands/query.js +17 -49
  129. package/dist/cli/commands/query.js.map +1 -1
  130. package/dist/cli/commands/report.js.map +1 -1
  131. package/dist/cli/commands/schema.js +19 -78
  132. package/dist/cli/commands/schema.js.map +1 -1
  133. package/dist/cli/commands/state/decisions.js +11 -57
  134. package/dist/cli/commands/state/decisions.js.map +1 -1
  135. package/dist/cli/commands/state/docs.js +56 -120
  136. package/dist/cli/commands/state/docs.js.map +1 -1
  137. package/dist/cli/commands/state/experimentRecords.js +22 -121
  138. package/dist/cli/commands/state/experimentRecords.js.map +1 -1
  139. package/dist/cli/commands/state/experiments.js +9 -75
  140. package/dist/cli/commands/state/experiments.js.map +1 -1
  141. package/dist/cli/commands/state/get.js +62 -143
  142. package/dist/cli/commands/state/get.js.map +1 -1
  143. package/dist/cli/commands/state/health.js +9 -123
  144. package/dist/cli/commands/state/health.js.map +1 -1
  145. package/dist/cli/commands/state/index.js +2 -2
  146. package/dist/cli/commands/state/index.js.map +1 -1
  147. package/dist/cli/commands/state/list.js +20 -36
  148. package/dist/cli/commands/state/list.js.map +1 -1
  149. package/dist/cli/commands/state/objective.js +19 -86
  150. package/dist/cli/commands/state/objective.js.map +1 -1
  151. package/dist/cli/commands/state/plan.js +9 -388
  152. package/dist/cli/commands/state/plan.js.map +1 -1
  153. package/dist/cli/commands/state/planTasks.js +58 -93
  154. package/dist/cli/commands/state/planTasks.js.map +1 -1
  155. package/dist/cli/commands/state/plans.js +13 -40
  156. package/dist/cli/commands/state/plans.js.map +1 -1
  157. package/dist/cli/commands/state/progress.js +10 -55
  158. package/dist/cli/commands/state/progress.js.map +1 -1
  159. package/dist/cli/commands/state/shared.js.map +1 -1
  160. package/dist/cli/commands/state/todo.js +24 -133
  161. package/dist/cli/commands/state/todo.js.map +1 -1
  162. package/dist/cli/commands/state/write.js +13 -35
  163. package/dist/cli/commands/state/write.js.map +1 -1
  164. package/dist/cli/commands/upgrade.js +48 -18
  165. package/dist/cli/commands/upgrade.js.map +1 -1
  166. package/dist/cli/commands/upgradeVerify.js +21 -15
  167. package/dist/cli/commands/upgradeVerify.js.map +1 -1
  168. package/dist/cli/commands/validate.js +1 -9
  169. package/dist/cli/commands/validate.js.map +1 -1
  170. package/dist/cli/commands/verify.js.map +1 -1
  171. package/dist/cli/contracts/bundleStatus.js.map +1 -1
  172. package/dist/cli/contracts/orientationState.js.map +1 -1
  173. package/dist/cli/dispatch/argvParser.js.map +1 -1
  174. package/dist/cli/dispatch/check.js +5 -12
  175. package/dist/cli/dispatch/check.js.map +1 -1
  176. package/dist/cli/dispatch/commands.js.map +1 -1
  177. package/dist/cli/dispatch/index.js +30 -29
  178. package/dist/cli/dispatch/index.js.map +1 -1
  179. package/dist/cli/dispatch/lifecycle.js +23 -40
  180. package/dist/cli/dispatch/lifecycle.js.map +1 -1
  181. package/dist/cli/dispatch/prime.js.map +1 -1
  182. package/dist/cli/dispatch/shared.js.map +1 -1
  183. package/dist/cli/dispatch/state.js.map +1 -1
  184. package/dist/cli/dispatch.js.map +1 -1
  185. package/dist/cli/errors.js.map +1 -1
  186. package/dist/cli/help.js +20 -100
  187. package/dist/cli/help.js.map +1 -1
  188. package/dist/cli/migrationRequired.js +22 -19
  189. package/dist/cli/migrationRequired.js.map +1 -1
  190. package/dist/cli/orientation/attention.js +1 -97
  191. package/dist/cli/orientation/attention.js.map +1 -1
  192. package/dist/cli/orientation/corpusCoverage.js.map +1 -1
  193. package/dist/cli/orientation.js +18 -4
  194. package/dist/cli/orientation.js.map +1 -1
  195. package/dist/cli/planArtifacts.js.map +1 -1
  196. package/dist/cli/planEvidence.js.map +1 -1
  197. package/dist/cli/planLifecycleState.js.map +1 -1
  198. package/dist/cli/planTaskIndex.js +12 -0
  199. package/dist/cli/planTaskIndex.js.map +1 -0
  200. package/dist/cli/prime-blob.js +1 -1
  201. package/dist/cli/prime-blob.js.map +1 -1
  202. package/dist/cli/startupCompletenessContract.js.map +1 -1
  203. package/dist/cli/stateQuery.js +1 -2
  204. package/dist/cli/stateQuery.js.map +1 -1
  205. package/dist/cli/structured.js.map +1 -1
  206. package/dist/cli/todoMarkdown.js.map +1 -1
  207. package/dist/cli/todoSeverity.js.map +1 -1
  208. package/dist/core/atomicWriter.js.map +1 -1
  209. package/dist/core/difflib.js.map +1 -1
  210. package/dist/core/envPaths.js.map +1 -1
  211. package/dist/core/jsonValue.js.map +1 -1
  212. package/dist/core/paths.js.map +1 -1
  213. package/dist/core/pyjson.js.map +1 -1
  214. package/dist/core/skillIdentity.js +24 -0
  215. package/dist/core/skillIdentity.js.map +1 -0
  216. package/dist/core/sourceRoot.js.map +1 -1
  217. package/dist/core/text.js.map +1 -1
  218. package/dist/core/toml.js.map +1 -1
  219. package/dist/core/yaml.js.map +1 -1
  220. package/dist/eval/evalSkills.js.map +1 -1
  221. package/dist/eval/semanticEval.js.map +1 -1
  222. package/dist/eval/semanticFixtures.js.map +1 -1
  223. package/dist/hooks/common.js +1 -1
  224. package/dist/hooks/common.js.map +1 -1
  225. package/dist/hooks/compaction/apply.js.map +1 -1
  226. package/dist/hooks/compaction/dryRun.js.map +1 -1
  227. package/dist/hooks/compaction/index.js.map +1 -1
  228. package/dist/hooks/compaction/parse.js.map +1 -1
  229. package/dist/hooks/compaction/retention.js.map +1 -1
  230. package/dist/hooks/compaction/status.js +2 -1
  231. package/dist/hooks/compaction/status.js.map +1 -1
  232. package/dist/hooks/compaction/types.js.map +1 -1
  233. package/dist/hooks/cursorPreToolUse.js.map +1 -1
  234. package/dist/hooks/cursorSessionStart.js +4 -25
  235. package/dist/hooks/cursorSessionStart.js.map +1 -1
  236. package/dist/hooks/projectHookInput.js +26 -0
  237. package/dist/hooks/projectHookInput.js.map +1 -0
  238. package/dist/hooks/sessionStart.js +23 -239
  239. package/dist/hooks/sessionStart.js.map +1 -1
  240. package/dist/hooks/sessionStop.js +4 -12
  241. package/dist/hooks/sessionStop.js.map +1 -1
  242. package/dist/hooks/validateArtifact/agentFacing.js.map +1 -1
  243. package/dist/hooks/validateArtifact/index.js.map +1 -1
  244. package/dist/hooks/validateArtifact/markdown.js.map +1 -1
  245. package/dist/hooks/validateArtifact/runtime.js.map +1 -1
  246. package/dist/hooks/validateArtifact/schema.js.map +1 -1
  247. package/dist/hooks/validateArtifact/traversal.js +1 -1
  248. package/dist/hooks/validateArtifact/traversal.js.map +1 -1
  249. package/dist/hooks/validateArtifact/violations.js.map +1 -1
  250. package/dist/migrate/v2HandoffManifest.js.map +1 -1
  251. package/dist/registries/artifactProtocolIds.js.map +1 -1
  252. package/dist/registries/artifactRegistry.js +2 -1
  253. package/dist/registries/artifactRegistry.js.map +1 -1
  254. package/dist/registries/capabilityContract.js.map +1 -1
  255. package/dist/registries/evaluatorHandoffContract.js.map +1 -1
  256. package/dist/registries/evidenceTierContract.js.map +1 -1
  257. package/dist/registries/packageRegistry.js +57 -231
  258. package/dist/registries/packageRegistry.js.map +1 -1
  259. package/dist/registries/triggerLoader.js.map +1 -1
  260. package/dist/registries/verbosityBudgetContract.js.map +1 -1
  261. package/dist/release/releaseMetadata.js +1 -13
  262. package/dist/release/releaseMetadata.js.map +1 -1
  263. package/dist/runtime/lifecycleAdapterContract.js +4 -4
  264. package/dist/runtime/lifecycleAdapterContract.js.map +1 -1
  265. package/dist/runtime/lifecycleAdapters.js +14 -2
  266. package/dist/runtime/lifecycleAdapters.js.map +1 -1
  267. package/dist/runtime/lifecycleAuthority.js +5 -43
  268. package/dist/runtime/lifecycleAuthority.js.map +1 -1
  269. package/dist/runtime/lifecycleOperationContract.js +3 -2
  270. package/dist/runtime/lifecycleOperationContract.js.map +1 -1
  271. package/dist/runtime/lifecycleOperations.js.map +1 -1
  272. package/dist/runtime/lifecycleOwnershipJournal.js.map +1 -1
  273. package/dist/runtime/lifecyclePublication.js +21 -0
  274. package/dist/runtime/lifecyclePublication.js.map +1 -1
  275. package/dist/runtime/lifecycleSnapshot.js.map +1 -1
  276. package/dist/runtime/retiredRuntimeCleanup.js.map +1 -1
  277. package/dist/setup/codex/agents.js.map +1 -1
  278. package/dist/setup/codex/cli.js.map +1 -1
  279. package/dist/setup/codex/configToml.js.map +1 -1
  280. package/dist/setup/codex/constants.js.map +1 -1
  281. package/dist/setup/codex/installRoot.js.map +1 -1
  282. package/dist/setup/codex/state.js.map +1 -1
  283. package/dist/setup/codex.js.map +1 -1
  284. package/dist/setup/opencode.js +20 -12
  285. package/dist/setup/opencode.js.map +1 -1
  286. package/dist/setup/opencodeConstants.js.map +1 -1
  287. package/dist/setup/sharedSkill.js +46 -0
  288. package/dist/setup/sharedSkill.js.map +1 -0
  289. package/dist/setup/smokeChecks.js +16 -43
  290. package/dist/setup/smokeChecks.js.map +1 -1
  291. package/dist/state/archiveDiscovery.js.map +1 -1
  292. package/dist/state/archivePublication.js.map +1 -1
  293. package/dist/state/archiveRecovery.js.map +1 -1
  294. package/dist/state/archiveReplay.js.map +1 -1
  295. package/dist/state/decisionEntities.js +7 -4
  296. package/dist/state/decisionEntities.js.map +1 -1
  297. package/dist/state/decisionLegacyValidation.js.map +1 -1
  298. package/dist/state/decisionOverlay.js.map +1 -1
  299. package/dist/state/decisionRevision.js.map +1 -1
  300. package/dist/state/decisionRevisionPublication.js.map +1 -1
  301. package/dist/state/directRetrieval.js.map +1 -1
  302. package/dist/state/durability.js +4 -240
  303. package/dist/state/durability.js.map +1 -1
  304. package/dist/state/entityCutover.js +90 -186
  305. package/dist/state/entityCutover.js.map +1 -1
  306. package/dist/state/entityCutoverGit.js.map +1 -1
  307. package/dist/state/entityMigrationPreview.js +3 -3
  308. package/dist/state/entityMigrationPreview.js.map +1 -1
  309. package/dist/state/entityPublicationContext.js.map +1 -1
  310. package/dist/state/entityStorage.js +49 -10
  311. package/dist/state/entityStorage.js.map +1 -1
  312. package/dist/state/experimentArchive.js.map +1 -1
  313. package/dist/state/experimentIdentity.js.map +1 -1
  314. package/dist/state/experimentRetrieval.js.map +1 -1
  315. package/dist/state/healthEntities.js +7 -4
  316. package/dist/state/healthEntities.js.map +1 -1
  317. package/dist/state/healthEntityValidation.js.map +1 -1
  318. package/dist/state/healthRepair.js.map +1 -1
  319. package/dist/state/installRoot.js.map +1 -1
  320. package/dist/state/legacyEntityCutoverEvidence.js.map +1 -1
  321. package/dist/state/legacyIdentity.js.map +1 -1
  322. package/dist/state/listAccounting.js.map +1 -1
  323. package/dist/state/listClassification.js.map +1 -1
  324. package/dist/state/listRetrieval.js.map +1 -1
  325. package/dist/state/objectiveExperimentEntities.js +7 -5
  326. package/dist/state/objectiveExperimentEntities.js.map +1 -1
  327. package/dist/state/planEntities.js +60 -12
  328. package/dist/state/planEntities.js.map +1 -1
  329. package/dist/state/planIdentity.js.map +1 -1
  330. package/dist/state/planRetrieval.js.map +1 -1
  331. package/dist/state/planTaskRetrieval.js.map +1 -1
  332. package/dist/state/progressEntities.js +4 -2
  333. package/dist/state/progressEntities.js.map +1 -1
  334. package/dist/state/projectRoot.js.map +1 -1
  335. package/dist/state/projectionPolicy.js.map +1 -1
  336. package/dist/state/retrievalAuthority.js.map +1 -1
  337. package/dist/state/safeProjectFile.js.map +1 -1
  338. package/dist/state/startupAnalysis/benchmark.js.map +1 -1
  339. package/dist/state/startupAnalysis/contract.js.map +1 -1
  340. package/dist/state/startupAnalysis/helpers.js.map +1 -1
  341. package/dist/state/startupAnalysis/index.js.map +1 -1
  342. package/dist/state/startupAnalysis/metrics.js.map +1 -1
  343. package/dist/state/startupAnalysis/records.js.map +1 -1
  344. package/dist/state/startupAnalysis/report.js.map +1 -1
  345. package/dist/state/startupAnalysis/threshold.js.map +1 -1
  346. package/dist/state/startupAnalysis.js.map +1 -1
  347. package/dist/state/startupProjection.js +5 -3
  348. package/dist/state/startupProjection.js.map +1 -1
  349. package/dist/state/stateMode.js +7 -0
  350. package/dist/state/stateMode.js.map +1 -1
  351. package/dist/state/todoDocsEntities.js +6 -4
  352. package/dist/state/todoDocsEntities.js.map +1 -1
  353. package/dist/state/todoDocsEntityValidation.js.map +1 -1
  354. package/dist/state/write/assign.js.map +1 -1
  355. package/dist/state/write/candidateMutation.js.map +1 -1
  356. package/dist/state/write/errors.js.map +1 -1
  357. package/dist/state/write/experimentPublication.js.map +1 -1
  358. package/dist/state/write/explain.js +10 -12
  359. package/dist/state/write/explain.js.map +1 -1
  360. package/dist/state/write/fields.js.map +1 -1
  361. package/dist/state/write/helpers.js.map +1 -1
  362. package/dist/state/write/index.js.map +1 -1
  363. package/dist/state/write/input.js.map +1 -1
  364. package/dist/state/write/lock.js.map +1 -1
  365. package/dist/state/write/mutation.js.map +1 -1
  366. package/dist/state/write/operations.js +6 -0
  367. package/dist/state/write/operations.js.map +1 -1
  368. package/dist/state/write/planEvaluation.js +19 -5
  369. package/dist/state/write/planEvaluation.js.map +1 -1
  370. package/dist/state/write/planPublication.js +7 -0
  371. package/dist/state/write/planPublication.js.map +1 -1
  372. package/dist/state/write/serialize.js.map +1 -1
  373. package/dist/state/write/transaction.js +23 -532
  374. package/dist/state/write/transaction.js.map +1 -1
  375. package/dist/state/write/validate.js.map +1 -1
  376. package/dist/upgrade/appContentRefresh.js +54 -44
  377. package/dist/upgrade/appContentRefresh.js.map +1 -1
  378. package/dist/upgrade/appModel.js.map +1 -1
  379. package/dist/upgrade/atomicWriter.js.map +1 -1
  380. package/dist/upgrade/bundleEvidence.js.map +1 -1
  381. package/dist/upgrade/channels.js.map +1 -1
  382. package/dist/upgrade/coexistenceProbe.js.map +1 -1
  383. package/dist/upgrade/compatibility.js.map +1 -1
  384. package/dist/upgrade/doctor.js +5 -1
  385. package/dist/upgrade/doctor.js.map +1 -1
  386. package/dist/upgrade/doctorClassifier.js.map +1 -1
  387. package/dist/upgrade/installedHooksRetirement.js +46 -39
  388. package/dist/upgrade/installedHooksRetirement.js.map +1 -1
  389. package/dist/upgrade/legacyAgentCleanup.js +132 -32
  390. package/dist/upgrade/legacyAgentCleanup.js.map +1 -1
  391. package/dist/upgrade/lifecycleUpgrade.js +65 -378
  392. package/dist/upgrade/lifecycleUpgrade.js.map +1 -1
  393. package/dist/upgrade/migrateArtifactsV2ToV3.js +151 -52
  394. package/dist/upgrade/migrateArtifactsV2ToV3.js.map +1 -1
  395. package/dist/upgrade/migrationPublication.js +123 -0
  396. package/dist/upgrade/migrationPublication.js.map +1 -0
  397. package/dist/upgrade/nextMajorDoctor.js.map +1 -1
  398. package/dist/upgrade/npxPlatformStatus.js.map +1 -1
  399. package/dist/upgrade/projectIntegration.js +46 -113
  400. package/dist/upgrade/projectIntegration.js.map +1 -1
  401. package/dist/upgrade/projectIntegrationDecision.js +6 -96
  402. package/dist/upgrade/projectIntegrationDecision.js.map +1 -1
  403. package/dist/upgrade/runtimeMigration.js +222 -402
  404. package/dist/upgrade/runtimeMigration.js.map +1 -1
  405. package/dist/upgrade/upgradeCommands.js +5 -4
  406. package/dist/upgrade/upgradeCommands.js.map +1 -1
  407. package/dist/upgrade/upgradeLock.js +73 -41
  408. package/dist/upgrade/upgradeLock.js.map +1 -1
  409. package/dist/upgrade/upgradeOrchestrator.js +91 -158
  410. package/dist/upgrade/upgradeOrchestrator.js.map +1 -1
  411. package/dist/upgrade/v3CapabilitySurface.js +2 -2
  412. package/dist/upgrade/v3CapabilitySurface.js.map +1 -1
  413. package/dist/upgrade/versionResolution.js.map +1 -1
  414. package/dist/validate/appHomeContract.js +0 -4
  415. package/dist/validate/appHomeContract.js.map +1 -1
  416. package/dist/validate/capability.js.map +1 -1
  417. package/dist/validate/crossCapability.js.map +1 -1
  418. package/dist/validate/selfAudit.js.map +1 -1
  419. package/dist/validate/vocabularyAuthority.js.map +1 -1
  420. package/package.json +23 -8
  421. package/bundle/.codex-plugin/plugin.json +0 -92
  422. package/bundle/.cursor/agents/agentera.md +0 -7
  423. package/bundle/.cursor/hooks.json +0 -32
  424. package/bundle/.cursor-plugin/plugin.json +0 -34
  425. package/bundle/.github/hooks/postToolUse.json +0 -9
  426. package/bundle/.github/hooks/preToolUse.json +0 -8
  427. package/bundle/.github/hooks/sessionEnd.json +0 -8
  428. package/bundle/.github/hooks/sessionStart.json +0 -8
  429. package/bundle/.github/plugin/plugin.json +0 -7
  430. package/bundle/.opencode/agents/agentera.md +0 -12
  431. package/bundle/.opencode/commands/agentera.md +0 -5
  432. package/bundle/.opencode/package.json +0 -31
  433. package/bundle/.opencode/plugins/agentera.js +0 -820
  434. package/bundle/agents/openai.yaml +0 -87
  435. package/bundle/hooks/codex-hooks.json +0 -31
  436. package/bundle/hooks/codex-plugin-hooks.json +0 -31
  437. package/bundle/plugin.json +0 -13
  438. package/bundle/references/adapters/cursor.md +0 -224
  439. package/bundle/references/adapters/opencode.md +0 -529
  440. package/bundle/references/adapters/runtime-adapter-characterization.md +0 -44
  441. package/bundle/references/adapters/runtime-adapter-interface-model.yaml +0 -200
  442. package/bundle/references/adapters/runtime-adapter-registry.yaml +0 -387
  443. package/bundle/references/adapters/runtime-feature-parity.md +0 -129
  444. package/dist/cli/commands/backfill.js +0 -231
  445. package/dist/cli/commands/backfill.js.map +0 -1
  446. package/dist/cli/commands/migrate.js +0 -681
  447. package/dist/cli/commands/migrate.js.map +0 -1
  448. package/dist/registries/runtimeAdapterRegistry.js +0 -324
  449. package/dist/registries/runtimeAdapterRegistry.js.map +0 -1
  450. package/dist/setup/copilot.js +0 -227
  451. package/dist/setup/copilot.js.map +0 -1
  452. package/dist/setup/cursor.js +0 -129
  453. package/dist/setup/cursor.js.map +0 -1
  454. package/dist/setup/cursorSurfaces.js +0 -67
  455. package/dist/setup/cursorSurfaces.js.map +0 -1
  456. package/dist/setup/doctor/core.js +0 -296
  457. package/dist/setup/doctor/core.js.map +0 -1
  458. package/dist/setup/doctor/diagnostics.js +0 -201
  459. package/dist/setup/doctor/diagnostics.js.map +0 -1
  460. package/dist/setup/doctor/opencode.js +0 -301
  461. package/dist/setup/doctor/opencode.js.map +0 -1
  462. package/dist/setup/doctor/report.js +0 -425
  463. package/dist/setup/doctor/report.js.map +0 -1
  464. package/dist/setup/doctor.js +0 -10
  465. package/dist/setup/doctor.js.map +0 -1
  466. package/dist/state/gitBackfill.js +0 -561
  467. package/dist/state/gitBackfill.js.map +0 -1
  468. package/dist/state/gitBackfillAuthority.js +0 -141
  469. package/dist/state/gitBackfillAuthority.js.map +0 -1
  470. package/dist/state/gitBackfillHistory.js +0 -278
  471. package/dist/state/gitBackfillHistory.js.map +0 -1
  472. package/dist/state/gitBackfillOutput.js +0 -209
  473. package/dist/state/gitBackfillOutput.js.map +0 -1
  474. package/dist/state/legacyMigration.js +0 -516
  475. package/dist/state/legacyMigration.js.map +0 -1
  476. package/dist/state/legacyMigrationParser.js +0 -489
  477. package/dist/state/legacyMigrationParser.js.map +0 -1
  478. package/dist/state/migrationAuthority.js +0 -413
  479. package/dist/state/migrationAuthority.js.map +0 -1
  480. package/dist/state/migrationEnrichment.js +0 -35
  481. package/dist/state/migrationEnrichment.js.map +0 -1
  482. package/dist/state/projectionRecovery.js +0 -458
  483. package/dist/state/projectionRecovery.js.map +0 -1
  484. package/dist/upgrade/migrateArtifactsV1ToV2.js +0 -568
  485. package/dist/upgrade/migrateArtifactsV1ToV2.js.map +0 -1
  486. package/dist/validate/lifecycleAdapters/legacyPythonParity.js +0 -93
  487. package/dist/validate/lifecycleAdapters/legacyPythonParity.js.map +0 -1
  488. package/dist/validate/lifecycleAdapters/lifecycleMain.js +0 -154
  489. package/dist/validate/lifecycleAdapters/lifecycleMain.js.map +0 -1
  490. package/dist/validate/lifecycleAdapters/nodeFormChecks.js +0 -481
  491. package/dist/validate/lifecycleAdapters/nodeFormChecks.js.map +0 -1
  492. package/dist/validate/lifecycleAdapters/shared.js +0 -198
  493. package/dist/validate/lifecycleAdapters/shared.js.map +0 -1
  494. package/dist/validate/lifecycleAdapters.js +0 -10
  495. package/dist/validate/lifecycleAdapters.js.map +0 -1
@@ -1,16 +1,15 @@
1
1
  import fs from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
+ import { createHash } from "node:crypto";
4
5
  import { isFile, pathExists, resolvePath } from "../core/paths.js";
5
6
  import { resolveSourceRoot } from "../core/sourceRoot.js";
6
- import { loadRegistry } from "../registries/runtimeAdapterRegistry.js";
7
7
  import { codexCopiedHooksAreAgenteraOnly, codexPluginHooksEnabled, retireCodexCopiedHookTrust, } from "../setup/codex.js";
8
8
  import { hasManagedMarker, opencodeConfigDir, } from "../setup/opencode.js";
9
9
  import { OPENCODE_SKILL_NAMES } from "../setup/opencodeConstants.js";
10
10
  import { resolveInvokedUpdateChannel } from "./channels.js";
11
- import { writeFileAtomic } from "./atomicWriter.js";
12
- import { applyInstalledHooksRetirementItems, planInstalledHooksRetirementItems, textReferencesV2InstalledHooks, } from "./installedHooksRetirement.js";
13
- import { projectUsesV3CapabilityInstructionModules } from "./v3CapabilitySurface.js";
11
+ import { doctorRoots } from "./appModel.js";
12
+ import { bindMigrationResource, removeBoundMigrationResource, updateBoundMigrationFile, verifyBoundMigrationResource, } from "./migrationPublication.js";
14
13
  const PYTHON_MANAGED_PATTERNS = [
15
14
  /hooks\/validate_artifact\.py/,
16
15
  /hooks\/cursor_session_start\.py/,
@@ -37,12 +36,11 @@ export function projectHasProjectLevelRuntimeHooks(project) {
37
36
  return candidates.some((candidate) => isFile(candidate) || pathExists(candidate));
38
37
  }
39
38
  const OPENCODE_COMMAND_NAMES = ["agentera"];
40
- const CURSOR_AGENT_MARKER = "<!-- agentera: managed -->";
41
- export function resolveNpxHookCommands(ctx) {
39
+ export function resolveNpxHookCommands(ctx, resolvedChannel) {
42
40
  const env = ctx.env ?? process.env;
43
41
  const home = ctx.home ?? env.HOME ?? os.homedir();
44
42
  const sourceRoot = ctx.sourceRoot ?? resolveSourceRoot(env);
45
- const channel = resolveInvokedUpdateChannel({
43
+ const channel = resolvedChannel ?? resolveInvokedUpdateChannel({
46
44
  channel: ctx.channel ?? null,
47
45
  env,
48
46
  home,
@@ -72,15 +70,9 @@ export function rewireRuntimeText(text, runtime, commands) {
72
70
  next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/hooks\/validate_artifact\.py\\?"?/g, commands.validate);
73
71
  next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/app\/hooks\/validate_artifact\.py\\?"?/g, commands.validate);
74
72
  next = next.replace(/uv run\s+\\?"?\$\{PLUGIN_ROOT\}\/hooks\/validate_artifact\.py\\?"?/g, commands.validate);
75
- next = next.replace(/uv run\s+hooks\/validate_artifact\.py/g, commands.validate);
76
- if (next.includes("validate_artifact.py")) {
77
- next = next.replace(/["']?[^"'\n]*hooks\/validate_artifact\.py[^"'\n]*["']?/g, `"${commands.validate}"`);
78
- }
79
- next = next.replace(/["']?[^"'\n]*cursor_session_start\.py[^"'\n]*["']?/g, `"${commands.cursorSessionStart}"`);
80
- next = next.replace(/["']?[^"'\n]*cursor_pre_tool_use\.py[^"'\n]*["']?/g, `"${commands.cursorPreTool}"`);
81
- next = next.replace(/["']?[^"'\n]*cursor_session_stop\.py[^"'\n]*["']?/g, `"${commands.cursorSessionStop}"`);
82
- next = next.replace(/["']?[^"'\n]*\/app\/scripts\/agentera[^"'\n]*["']?/g, `"${commands.cliEntrypoint}"`);
83
- next = next.replace(/["']?[^"'\n]*scripts\/agentera[^"'\n]*["']?/g, `"${commands.cliEntrypoint}"`);
73
+ next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/(?:app\/scripts|(?:app\/)?hooks)\/cursor_session_start\.py\\?"?/g, `"${commands.cursorSessionStart}"`);
74
+ next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/(?:app\/)?hooks\/cursor_pre_tool_use\.py\\?"?/g, `"${commands.cursorPreTool}"`);
75
+ next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/(?:app\/)?hooks\/cursor_session_stop\.py\\?"?/g, `"${commands.cursorSessionStop}"`);
84
76
  next = next.replace(/npx -y agentera hook /g, `${commands.cliEntrypoint} hook `);
85
77
  next = next.replace(/npx -y agentera@latest hook /g, `${commands.cliEntrypoint} hook `);
86
78
  if (runtime === "codex") {
@@ -102,10 +94,23 @@ function needsChannelNpxRewire(text, cliEntrypoint) {
102
94
  }
103
95
  return false;
104
96
  }
105
- function pushRewireItem(items, runtime, filePath, commands) {
97
+ function textHasAuthoritativeV2AgenteraEvidence(text) {
98
+ const variableReference = /\$\{AGENTERA_HOME\}\/(?:app\/scripts\/(?:agentera|cursor_session_start\.py)|(?:app\/)?hooks\/(?:validate_artifact|cursor_session_start|cursor_pre_tool_use|cursor_session_stop|session_start|session_stop)\.py)/;
99
+ if (variableReference.test(text))
100
+ return true;
101
+ if (/AGENTERA_HOME\s*=/.test(text))
102
+ return true;
103
+ if (/\[plugins\."agentera@agentera"\]/.test(text) && /AGENTERA_HOME\s*=/.test(text))
104
+ return true;
105
+ return false;
106
+ }
107
+ function pushRewireItem(items, runtime, filePath, commands, allowedRoot) {
106
108
  const text = fs.readFileSync(filePath, "utf8");
107
109
  const needsBare = needsChannelNpxRewire(text, commands.cliEntrypoint);
108
- if (!textUsesPythonManagedEntrypoint(text) && !textReferencesV2InstalledHooks(text) && !needsBare) {
110
+ const authoritative = hasManagedMarker(text)
111
+ || textHasAuthoritativeV2AgenteraEvidence(text)
112
+ || needsBare;
113
+ if (!authoritative) {
109
114
  if (textUsesV3NpmEntrypoint(text)) {
110
115
  items.push({
111
116
  status: "noop",
@@ -121,7 +126,7 @@ function pushRewireItem(items, runtime, filePath, commands) {
121
126
  }
122
127
  const newText = rewireRuntimeText(text, runtime, commands);
123
128
  const status = newText === text ? "blocked" : "pending";
124
- items.push({
129
+ const item = {
125
130
  status,
126
131
  action: "rewire-runtime",
127
132
  runtime,
@@ -131,36 +136,19 @@ function pushRewireItem(items, runtime, filePath, commands) {
131
136
  message: status === "pending"
132
137
  ? "will rewire runtime config from Python managed app-home to npm self-contained entrypoint"
133
138
  : "runtime config uses Python managed paths but could not be rewritten safely",
134
- });
135
- }
136
- function hasCursorManagedAgentMarker(text) {
137
- return text.includes(CURSOR_AGENT_MARKER);
138
- }
139
- function copyIfChanged(source, target) {
140
- if (!isFile(source)) {
141
- return false;
142
- }
143
- if (isFile(target)) {
144
- const before = fs.readFileSync(source);
145
- const after = fs.readFileSync(target);
146
- if (before.equals(after)) {
147
- return false;
148
- }
139
+ };
140
+ const evidenceError = bindMigrationResource(item, "target", filePath, [allowedRoot], "file");
141
+ if (evidenceError) {
142
+ item.status = "blocked";
143
+ item.message = `runtime config preserved: ${evidenceError}; review the unsafe path manually`;
149
144
  }
150
- fs.mkdirSync(path.dirname(target), { recursive: true });
151
- const sourceBytes = fs.readFileSync(source);
152
- writeFileAtomic(target, sourceBytes);
153
- return true;
145
+ items.push(item);
154
146
  }
155
- function planCodexItems(items, home, project, commands, force) {
147
+ function planCodexItems(items, home, project, commands) {
156
148
  for (const root of [project, home]) {
157
149
  const hooksPath = path.join(root, ".codex", "hooks", "codex-hooks.json");
158
150
  const configPath = path.join(root, ".codex", "config.toml");
159
- if (isFile(hooksPath)) {
160
- pushRewireItem(items, "codex", hooksPath, commands);
161
- }
162
151
  if (isFile(configPath)) {
163
- pushRewireItem(items, "codex", configPath, commands);
164
152
  const configText = fs.readFileSync(configPath, "utf8");
165
153
  const pluginHooks = codexPluginHooksEnabled(configText);
166
154
  if (pluginHooks && isFile(hooksPath)) {
@@ -172,292 +160,88 @@ function planCodexItems(items, home, project, commands, force) {
172
160
  hooksText = "";
173
161
  }
174
162
  if (codexCopiedHooksAreAgenteraOnly(hooksText)) {
175
- items.push({
163
+ const rewiredConfig = rewireRuntimeText(configText, "codex", commands);
164
+ const item = {
176
165
  status: "pending",
177
166
  action: "retire-hooks",
178
167
  runtime: "codex",
179
168
  source: hooksPath,
180
169
  target: configPath,
170
+ newText: retireCodexCopiedHookTrust(rewiredConfig, hooksPath),
181
171
  message: "will remove Agentera-owned copied Codex hooks because plugin hooks are enabled",
182
- });
172
+ };
173
+ const sourceError = bindMigrationResource(item, "source", hooksPath, [root], "file");
174
+ const targetError = bindMigrationResource(item, "target", configPath, [root], "file");
175
+ if (sourceError || targetError) {
176
+ item.status = "blocked";
177
+ item.message = `copied Codex hooks preserved: ${sourceError ?? targetError}; review the unsafe path manually`;
178
+ }
179
+ items.push(item);
180
+ continue;
183
181
  }
184
182
  else if (hooksText.includes("validate_artifact") || hooksText.includes("hook validate-artifact")) {
185
183
  items.push({
186
- status: force ? "pending" : "blocked",
184
+ status: "blocked",
187
185
  action: "retire-hooks",
188
186
  runtime: "codex",
189
187
  source: hooksPath,
190
188
  target: configPath,
191
189
  message: "plugin hooks are enabled, but copied hook target needs manual review before retirement",
192
190
  });
191
+ continue;
193
192
  }
194
193
  }
194
+ pushRewireItem(items, "codex", configPath, commands, root);
195
+ }
196
+ if (isFile(hooksPath)) {
197
+ pushRewireItem(items, "codex", hooksPath, commands, root);
195
198
  }
196
199
  }
197
200
  }
198
- function planCursorItems(items, home, project, sourceRoot, commands) {
199
- for (const hooksPath of [
200
- path.join(project, ".cursor", "hooks.json"),
201
- path.join(home, ".cursor", "hooks.json"),
201
+ function planCursorItems(items, home, project, commands) {
202
+ for (const [root, hooksPath] of [
203
+ [project, path.join(project, ".cursor", "hooks.json")],
204
+ [home, path.join(home, ".cursor", "hooks.json")],
202
205
  ]) {
203
206
  if (isFile(hooksPath)) {
204
- pushRewireItem(items, "cursor", hooksPath, commands);
205
- }
206
- }
207
- const agentsSource = path.join(sourceRoot, ".cursor", "agents");
208
- const pluginSource = path.join(sourceRoot, ".cursor-plugin", "plugin.json");
209
- for (const root of [project]) {
210
- const agentsDir = path.join(root, ".cursor", "agents");
211
- if (isFile(pluginSource) && root === project) {
212
- const pluginTarget = path.join(root, ".cursor-plugin", "plugin.json");
213
- if (!isFile(pluginTarget)) {
214
- items.push({
215
- status: "pending",
216
- action: "copy-plugin",
217
- runtime: "cursor",
218
- source: pluginSource,
219
- target: pluginTarget,
220
- message: "will copy managed Cursor plugin manifest",
221
- });
222
- }
223
- else if (!fs.readFileSync(pluginSource).equals(fs.readFileSync(pluginTarget))) {
224
- items.push({
225
- status: "pending",
226
- action: "copy-plugin",
227
- runtime: "cursor",
228
- source: pluginSource,
229
- target: pluginTarget,
230
- message: "will refresh managed Cursor plugin manifest",
231
- });
232
- }
233
- }
234
- const skipInTreeCursorAgents = root === project && projectUsesV3CapabilityInstructionModules(project);
235
- if (skipInTreeCursorAgents) {
236
- items.push({
237
- status: "noop",
238
- action: "copy-agent",
239
- runtime: "cursor",
240
- target: agentsDir,
241
- message: "v3 capability instruction modules present; in-tree .cursor/agents/ uses prime --context and is not overwritten",
242
- });
243
- }
244
- else if (pathExists(agentsSource)) {
245
- const CURSOR_MANAGED_AGENT = "agentera.md";
246
- const src = path.join(agentsSource, CURSOR_MANAGED_AGENT);
247
- if (isFile(src)) {
248
- const dst = path.join(agentsDir, CURSOR_MANAGED_AGENT);
249
- if (!isFile(dst)) {
250
- items.push({
251
- status: "pending",
252
- action: "copy-agent",
253
- runtime: "cursor",
254
- source: src,
255
- target: dst,
256
- message: "will copy managed Cursor Agentera agent",
257
- });
258
- }
259
- else {
260
- const dstText = fs.readFileSync(dst, "utf8");
261
- const srcText = fs.readFileSync(src, "utf8");
262
- if (hasCursorManagedAgentMarker(dstText) && dstText !== srcText) {
263
- items.push({
264
- status: "pending",
265
- action: "copy-agent",
266
- runtime: "cursor",
267
- source: src,
268
- target: dst,
269
- message: "will refresh stale managed Cursor Agentera agent",
270
- });
271
- }
272
- }
273
- }
207
+ pushRewireItem(items, "cursor", hooksPath, commands, root);
274
208
  }
275
209
  }
276
210
  }
277
- function planOpencodeItems(items, home, sourceRoot, env, commands) {
211
+ function planOpencodeItems(items, home, env, commands) {
278
212
  const configDir = opencodeConfigDir(home, env);
279
- const pluginSource = path.join(sourceRoot, ".opencode", "plugins", "agentera.js");
280
- const pluginTarget = path.join(configDir, "plugins", "agentera.js");
281
- if (isFile(pluginSource)) {
282
- const targetContent = isFile(pluginTarget) ? fs.readFileSync(pluginTarget, "utf8") : "";
283
- const sourceContent = fs.readFileSync(pluginSource, "utf8");
284
- const needsCopy = !isFile(pluginTarget) ||
285
- (targetContent !== sourceContent &&
286
- (textUsesPythonManagedEntrypoint(targetContent) ||
287
- needsChannelNpxRewire(targetContent, commands.cliEntrypoint)));
288
- items.push({
289
- status: needsCopy ? "pending" : "noop",
290
- action: "copy-plugin",
291
- runtime: "opencode",
292
- source: pluginSource,
293
- target: pluginTarget,
294
- message: needsCopy
295
- ? "will copy current Agentera OpenCode plugin to native plugin path"
296
- : "OpenCode plugin already current at native plugin path",
297
- });
298
- }
299
- const commandsSourceDir = path.join(sourceRoot, ".opencode", "commands");
300
- const commandsTargetDir = path.join(configDir, "commands");
301
- for (const name of OPENCODE_COMMAND_NAMES) {
302
- const src = path.join(commandsSourceDir, `${name}.md`);
303
- const dst = path.join(commandsTargetDir, `${name}.md`);
304
- if (isFile(src)) {
305
- const needsCopy = !isFile(dst) || (hasManagedMarker(fs.readFileSync(dst, "utf8")) && !fs.readFileSync(src).equals(fs.readFileSync(dst)));
306
- items.push({
307
- status: needsCopy ? "pending" : "noop",
308
- action: "copy-command",
309
- runtime: "opencode",
310
- source: src,
311
- target: dst,
312
- message: needsCopy ? "will sync managed OpenCode command" : "OpenCode managed command already current",
313
- });
314
- }
213
+ const existingResources = [
214
+ path.join(configDir, "plugins", "agentera.js"),
215
+ ...OPENCODE_COMMAND_NAMES.map((name) => path.join(configDir, "commands", `${name}.md`)),
216
+ path.join(configDir, "agents", "agentera.md"),
217
+ ];
218
+ for (const resource of existingResources) {
219
+ if (isFile(resource))
220
+ pushRewireItem(items, "opencode", resource, commands, configDir);
315
221
  }
316
- const agentsSourceDir = path.join(sourceRoot, ".opencode", "agents");
317
- const agentsTargetDir = path.join(configDir, "agents");
318
- const OPENCODE_MANAGED_AGENT = "agentera.md";
319
- if (pathExists(agentsSourceDir)) {
320
- const src = path.join(agentsSourceDir, OPENCODE_MANAGED_AGENT);
321
- if (isFile(src)) {
322
- const dst = path.join(agentsTargetDir, OPENCODE_MANAGED_AGENT);
323
- const needsCopy = !isFile(dst) || !fs.readFileSync(src).equals(fs.readFileSync(dst));
324
- items.push({
325
- status: needsCopy ? "pending" : "noop",
326
- action: "copy-agent",
327
- runtime: "opencode",
328
- source: src,
329
- target: dst,
330
- message: needsCopy ? "will copy managed OpenCode Agentera agent" : "OpenCode Agentera agent already current",
331
- });
332
- }
222
+ }
223
+ function symlinkOwnership(linkPath, managedSkillsRoot) {
224
+ let stat;
225
+ let target;
226
+ try {
227
+ stat = fs.lstatSync(linkPath);
228
+ if (!stat.isSymbolicLink())
229
+ return null;
230
+ target = fs.readlinkSync(linkPath);
333
231
  }
334
- const skillsSourceRoot = path.join(sourceRoot, "skills");
335
- // D78: ~/.agents/skills is the canonical agent-compatible root (opencode loads
336
- // from both ~/.config/opencode/skills and ~/.agents/skills and requires skill
337
- // names unique across locations — opencode.ai/docs/skills). Maintain the link
338
- // here; the legacy ~/.config/opencode/skills entry is retired below.
339
- const skillsTargetDir = path.join(home, ".agents", "skills");
340
- for (const name of OPENCODE_SKILL_NAMES) {
341
- const src = path.join(skillsSourceRoot, name);
342
- const dst = path.join(skillsTargetDir, name);
343
- if (!isFile(path.join(src, "SKILL.md"))) {
344
- continue;
345
- }
346
- if (!pathExists(dst)) {
347
- items.push({
348
- status: "pending",
349
- action: "link-skill",
350
- runtime: "opencode",
351
- source: src,
352
- target: dst,
353
- message: "will create OpenCode skill link",
354
- });
355
- continue;
356
- }
357
- try {
358
- const linkTarget = fs.readlinkSync(dst);
359
- if (!linkTarget.includes("agentera") && path.basename(linkTarget) !== name) {
360
- items.push({
361
- status: "blocked",
362
- action: "link-skill",
363
- runtime: "opencode",
364
- source: src,
365
- target: dst,
366
- message: "OpenCode skill path is user-owned; manual review required",
367
- });
368
- }
369
- else if (path.resolve(path.dirname(dst), linkTarget) !== path.resolve(src)) {
370
- items.push({
371
- status: "pending",
372
- action: "link-skill",
373
- runtime: "opencode",
374
- source: src,
375
- target: dst,
376
- message: "will update stale Agentera-managed OpenCode skill link",
377
- });
378
- }
379
- }
380
- catch {
381
- items.push({
382
- status: "pending",
383
- action: "link-skill",
384
- runtime: "opencode",
385
- source: src,
386
- target: dst,
387
- message: "will replace non-symlink OpenCode skill path with managed link",
388
- });
389
- }
390
- }
391
- // D78: retire the legacy opencode-specific skill symlinks now that
392
- // ~/.agents/skills is canonical. The opencode doc requires skill names
393
- // unique across its discovery locations; a skill present in both
394
- // ~/.config/opencode/skills and ~/.agents/skills is the duplicate-name error
395
- // that let a stale copy load.
396
- const legacySkillsDir = path.join(configDir, "skills");
397
- if (pathExists(legacySkillsDir) && fs.statSync(legacySkillsDir).isDirectory()) {
398
- for (const name of OPENCODE_SKILL_NAMES) {
399
- const legacy = path.join(legacySkillsDir, name);
400
- let linkTarget = null;
401
- try {
402
- linkTarget = fs.readlinkSync(legacy);
403
- }
404
- catch {
405
- linkTarget = null;
406
- }
407
- if (linkTarget !== null) {
408
- if (linkTarget.toLowerCase().includes("agentera") || path.basename(linkTarget) === name) {
409
- items.push({
410
- status: "pending",
411
- action: "remove-stale-skill",
412
- runtime: "opencode",
413
- source: legacy,
414
- message: `will retire duplicate OpenCode skill symlink ${name} (agent-compatible root ~/.agents/skills is canonical; D78)`,
415
- });
416
- }
417
- else {
418
- items.push({
419
- status: "blocked",
420
- action: "remove-stale-skill",
421
- runtime: "opencode",
422
- source: legacy,
423
- message: `legacy OpenCode skill symlink ${name} targets a non-agentera path; manual review required`,
424
- });
425
- }
426
- }
427
- else if (pathExists(legacy)) {
428
- try {
429
- const dirEntries = fs.readdirSync(legacy);
430
- if (dirEntries.length === 0) {
431
- items.push({
432
- status: "pending",
433
- action: "remove-stale-skill",
434
- runtime: "opencode",
435
- source: legacy,
436
- message: `will retire empty legacy OpenCode skill directory ${name} (agent-compatible root ~/.agents/skills is canonical; D78)`,
437
- });
438
- }
439
- else {
440
- items.push({
441
- status: "blocked",
442
- action: "remove-stale-skill",
443
- runtime: "opencode",
444
- source: legacy,
445
- message: `legacy OpenCode skill path ${name} is a non-empty real directory (entries: ${dirEntries.length}); manual review required (D78 retires agentera-managed symlinks and empty dirs only)`,
446
- });
447
- }
448
- }
449
- catch {
450
- items.push({
451
- status: "blocked",
452
- action: "remove-stale-skill",
453
- runtime: "opencode",
454
- source: legacy,
455
- message: `legacy OpenCode skill path ${name} could not be inspected; manual review required`,
456
- });
457
- }
458
- }
459
- }
232
+ catch {
233
+ return null;
460
234
  }
235
+ const resolvedTarget = path.resolve(path.dirname(linkPath), target);
236
+ const relative = path.relative(managedSkillsRoot, resolvedTarget);
237
+ if (relative === "" || relative.startsWith("..") || path.isAbsolute(relative))
238
+ return null;
239
+ return {
240
+ kind: "managed-app-symlink",
241
+ identity: `${stat.dev}:${stat.ino}`,
242
+ fingerprint: `sha256:${createHash("sha256").update(target).digest("hex")}`,
243
+ root: managedSkillsRoot,
244
+ };
461
245
  }
462
246
  export function planStaleCommandCleanupItems(ctx, items) {
463
247
  const env = ctx.env ?? process.env;
@@ -483,48 +267,99 @@ export function planStaleCommandCleanupItems(ctx, items) {
483
267
  if (currentNames.has(name)) {
484
268
  continue;
485
269
  }
486
- items.push({
270
+ const item = {
487
271
  status: "pending",
488
272
  action: "remove-stale-command",
489
273
  runtime: "opencode",
490
274
  source: filePath,
491
275
  message: `will remove stale managed command ${path.basename(filePath)}`,
492
- });
276
+ };
277
+ const evidenceError = bindMigrationResource(item, "source", filePath, [home], "file");
278
+ if (evidenceError) {
279
+ item.status = "blocked";
280
+ item.message = `stale command preserved: ${evidenceError}; review the unsafe path manually`;
281
+ }
282
+ items.push(item);
493
283
  }
494
284
  }
495
285
  export function planStaleSkillCleanupItems(ctx, items) {
496
286
  const env = ctx.env ?? process.env;
497
287
  const home = resolvePath(ctx.home);
498
288
  const skillsDir = path.join(opencodeConfigDir(home, env), "skills");
499
- if (!pathExists(skillsDir) || !fs.statSync(skillsDir).isDirectory()) {
289
+ let skillsDirectory;
290
+ try {
291
+ skillsDirectory = fs.lstatSync(skillsDir);
292
+ }
293
+ catch {
294
+ return;
295
+ }
296
+ if (!skillsDirectory.isDirectory()) {
297
+ items.push({
298
+ status: "blocked",
299
+ action: "remove-stale-skill",
300
+ runtime: "opencode",
301
+ source: skillsDir,
302
+ message: `preserved ${skillsDir}: the legacy skills path is not a real directory; replace the unsafe path or review it manually`,
303
+ });
500
304
  return;
501
305
  }
502
306
  const requiredNames = new Set(OPENCODE_SKILL_NAMES);
307
+ const managedSkillsRoot = path.join(doctorRoots(resolvePath(ctx.appHome)).activeBundleRoot, "skills");
503
308
  for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
309
+ const linkPath = path.join(skillsDir, entry.name);
504
310
  if (!entry.isSymbolicLink()) {
311
+ if (requiredNames.has(entry.name)) {
312
+ items.push({
313
+ status: "blocked",
314
+ action: "remove-stale-skill",
315
+ runtime: "opencode",
316
+ source: linkPath,
317
+ message: `preserved ${linkPath}: name and directory shape do not prove Agentera ownership; review and remove it manually if appropriate`,
318
+ });
319
+ }
505
320
  continue;
506
321
  }
507
- const linkPath = path.join(skillsDir, entry.name);
508
322
  let linkTarget;
509
323
  try {
510
324
  linkTarget = fs.readlinkSync(linkPath);
511
325
  }
512
326
  catch {
327
+ items.push({
328
+ status: "blocked",
329
+ action: "remove-stale-skill",
330
+ runtime: "opencode",
331
+ source: linkPath,
332
+ message: `preserved ${linkPath}: the symlink target could not be inspected; review the unsafe resource manually`,
333
+ });
513
334
  continue;
514
335
  }
515
- if (!linkTarget.toLowerCase().includes("agentera")) {
516
- continue;
517
- }
518
- if (requiredNames.has(entry.name)) {
336
+ const ownership = symlinkOwnership(linkPath, managedSkillsRoot);
337
+ if (!ownership) {
338
+ if (requiredNames.has(entry.name) || linkTarget.toLowerCase().includes("agentera")) {
339
+ items.push({
340
+ status: "blocked",
341
+ action: "remove-stale-skill",
342
+ runtime: "opencode",
343
+ source: linkPath,
344
+ message: `preserved ${linkPath}: skill name or target text does not prove Agentera ownership; confirm ownership and remove it manually if appropriate`,
345
+ });
346
+ }
519
347
  continue;
520
348
  }
521
- items.push({
349
+ const item = {
522
350
  status: "pending",
523
351
  action: "remove-stale-skill",
524
352
  runtime: "opencode",
525
353
  source: linkPath,
526
- message: `will remove stale Agentera skill symlink ${entry.name}`,
527
- });
354
+ ownership,
355
+ message: `will remove v2 app-owned OpenCode skill symlink ${entry.name}`,
356
+ };
357
+ const evidenceError = bindMigrationResource(item, "source", linkPath, [home], "symlink");
358
+ if (evidenceError) {
359
+ item.status = "blocked";
360
+ item.message = `legacy skill preserved: ${evidenceError}; review the unsafe path manually`;
361
+ }
362
+ items.push(item);
528
363
  }
529
364
  }
530
365
  function walkJsonHookFiles(dir) {
@@ -550,7 +385,7 @@ function walkJsonHookFiles(dir) {
550
385
  function planCopilotItems(items, project, commands) {
551
386
  const hooksDir = path.join(project, ".github", "hooks");
552
387
  for (const hookFile of walkJsonHookFiles(hooksDir)) {
553
- pushRewireItem(items, "copilot", hookFile, commands);
388
+ pushRewireItem(items, "copilot", hookFile, commands, project);
554
389
  }
555
390
  if (!items.some((item) => item.runtime === "copilot")) {
556
391
  items.push({
@@ -561,7 +396,7 @@ function planCopilotItems(items, project, commands) {
561
396
  });
562
397
  }
563
398
  }
564
- export function planRuntimeMigrationItems(ctx) {
399
+ export function planRuntimeMigrationItems(ctx, resolvedChannel) {
565
400
  if (!ctx.env) {
566
401
  throw new Error("MigrationContext.env is required for runtime migration planning; pass sandboxMigrationEnv(home, sourceRoot) in tests or an explicit env in callers.");
567
402
  }
@@ -569,21 +404,25 @@ export function planRuntimeMigrationItems(ctx) {
569
404
  const project = resolvePath(ctx.project);
570
405
  const env = ctx.env;
571
406
  const sourceRoot = resolvePath(ctx.sourceRoot ?? resolveSourceRoot(env));
572
- const commands = resolveNpxHookCommands({ ...ctx, home, env, sourceRoot });
407
+ const commands = resolveNpxHookCommands({ ...ctx, home, env, sourceRoot }, resolvedChannel);
573
408
  const items = [];
574
- planCodexItems(items, home, project, commands, ctx.force);
575
- planCursorItems(items, home, project, sourceRoot, commands);
576
- planOpencodeItems(items, home, sourceRoot, env, commands);
409
+ planCodexItems(items, home, project, commands);
410
+ planCursorItems(items, home, project, commands);
411
+ planOpencodeItems(items, home, env, commands);
577
412
  planStaleCommandCleanupItems(ctx, items);
578
413
  planStaleSkillCleanupItems(ctx, items);
579
414
  planCopilotItems(items, project, commands);
580
- const hookRetirement = planInstalledHooksRetirementItems(ctx).filter((item) => item.status === "pending");
581
- if (hookRetirement.length > 0 && items.some((item) => item.action === "rewire-runtime" && item.status === "pending")) {
582
- items.push(...hookRetirement);
583
- }
584
- void loadRegistry();
585
415
  return items;
586
416
  }
417
+ const RUNTIME_MIGRATION_ACTIONS = new Set([
418
+ "rewire-runtime",
419
+ "retire-hooks",
420
+ "remove-stale-command",
421
+ "remove-stale-skill",
422
+ ]);
423
+ function isRuntimeMigrationAction(action) {
424
+ return RUNTIME_MIGRATION_ACTIONS.has(action);
425
+ }
587
426
  export function applyRuntimeMigrationItem(item, _commands) {
588
427
  if (item.status !== "pending") {
589
428
  return;
@@ -596,71 +435,31 @@ export function applyRuntimeMigrationItem(item, _commands) {
596
435
  item.message = "rewire-runtime missing target or newText";
597
436
  return;
598
437
  }
599
- writeFileAtomic(item.target, item.newText, "utf8");
438
+ updateBoundMigrationFile(item, "target", item.newText);
600
439
  item.status = "applied";
601
440
  item.message = "runtime config rewired to npm self-contained entrypoint";
602
441
  break;
603
442
  }
604
- case "copy-plugin":
605
- case "copy-agent":
606
- case "copy-command": {
607
- if (!item.source || !item.target) {
608
- item.status = "failed";
609
- item.message = `${item.action} missing source or target`;
610
- return;
611
- }
612
- copyIfChanged(item.source, item.target);
613
- item.status = "applied";
614
- item.message = `applied ${item.action}`;
615
- break;
616
- }
617
- case "link-skill": {
618
- if (!item.source || !item.target) {
443
+ case "retire-hooks": {
444
+ if (!item.source) {
619
445
  item.status = "failed";
620
- item.message = "link-skill missing source or target";
446
+ item.message = "retire-hooks missing source";
621
447
  return;
622
448
  }
623
- if (!pathExists(item.source)) {
449
+ if (!item.target) {
624
450
  item.status = "failed";
625
- item.message = `link-skill source disappeared between plan and apply: ${item.source}`;
451
+ item.message = "retire-hooks missing target";
626
452
  return;
627
453
  }
628
- fs.mkdirSync(path.dirname(item.target), { recursive: true });
629
- // lstat (not stat): stat follows symlinks and ENOENTs on dangling links; rmSync then fails.
630
- let targetStat = null;
631
- try {
632
- targetStat = fs.lstatSync(item.target);
633
- }
634
- catch {
635
- /* target absent */
636
- }
637
- if (targetStat) {
638
- if (targetStat.isSymbolicLink()) {
639
- fs.unlinkSync(item.target);
640
- }
641
- else {
642
- fs.rmSync(item.target, { recursive: true, force: true });
643
- }
644
- }
645
- fs.symlinkSync(item.source, item.target);
646
- item.status = "applied";
647
- item.message = "OpenCode skill link created";
648
- break;
649
- }
650
- case "retire-hooks": {
651
- if (!item.source) {
454
+ verifyBoundMigrationResource(item, "source");
455
+ verifyBoundMigrationResource(item, "target");
456
+ if (item.newText === undefined) {
652
457
  item.status = "failed";
653
- item.message = "retire-hooks missing source";
458
+ item.message = "retire-hooks missing newText";
654
459
  return;
655
460
  }
656
- if (isFile(item.source)) {
657
- fs.rmSync(item.source, { force: true });
658
- }
659
- if (item.target && isFile(item.target)) {
660
- const configText = fs.readFileSync(item.target, "utf8");
661
- const next = retireCodexCopiedHookTrust(configText, item.source);
662
- writeFileAtomic(item.target, next, "utf8");
663
- }
461
+ updateBoundMigrationFile(item, "target", item.newText);
462
+ removeBoundMigrationResource(item, "source");
664
463
  item.status = "applied";
665
464
  item.message = "retired Agentera-owned copied Codex hooks";
666
465
  break;
@@ -671,15 +470,15 @@ export function applyRuntimeMigrationItem(item, _commands) {
671
470
  item.message = "remove-stale-command missing source";
672
471
  return;
673
472
  }
674
- if (isFile(item.source)) {
675
- fs.rmSync(item.source, { force: true });
676
- item.status = "applied";
677
- item.message = `removed stale managed command ${path.basename(item.source)}`;
678
- }
679
- else {
473
+ if (!pathExists(item.source)) {
680
474
  item.status = "noop";
681
475
  item.message = `stale command already absent at ${item.source}`;
682
476
  }
477
+ else {
478
+ removeBoundMigrationResource(item, "source");
479
+ item.status = "applied";
480
+ item.message = `removed stale managed command ${path.basename(item.source)}`;
481
+ }
683
482
  break;
684
483
  }
685
484
  case "remove-stale-skill": {
@@ -691,47 +490,68 @@ export function applyRuntimeMigrationItem(item, _commands) {
691
490
  try {
692
491
  const stat = fs.lstatSync(item.source);
693
492
  if (stat.isSymbolicLink()) {
694
- fs.unlinkSync(item.source);
695
- item.status = "applied";
696
- item.message = `removed stale skill symlink ${path.basename(item.source)}`;
697
- }
698
- else if (stat.isDirectory()) {
699
- const entries = fs.readdirSync(item.source);
700
- if (entries.length === 0) {
701
- fs.rmdirSync(item.source);
702
- item.status = "applied";
703
- item.message = `removed empty skill directory ${path.basename(item.source)}`;
704
- }
705
- else {
493
+ const target = fs.readlinkSync(item.source);
494
+ const identity = `${stat.dev}:${stat.ino}`;
495
+ const fingerprint = `sha256:${createHash("sha256").update(target).digest("hex")}`;
496
+ const resolvedTarget = path.resolve(path.dirname(item.source), target);
497
+ const relative = item.ownership?.root
498
+ ? path.relative(item.ownership.root, resolvedTarget)
499
+ : "..";
500
+ if (item.ownership?.kind !== "managed-app-symlink"
501
+ || item.ownership.identity !== identity
502
+ || item.ownership.fingerprint !== fingerprint
503
+ || relative === ""
504
+ || relative.startsWith("..")
505
+ || path.isAbsolute(relative)) {
706
506
  item.status = "blocked";
707
- item.message = `skill directory ${path.basename(item.source)} is non-empty (entries: ${entries.length}); manual review required`;
507
+ item.message = `preserved ${item.source}: authoritative symlink ownership changed or is missing; rerun migration and review the resource`;
508
+ break;
708
509
  }
510
+ removeBoundMigrationResource(item, "source");
511
+ item.status = "applied";
512
+ item.message = `removed stale skill symlink ${path.basename(item.source)}`;
709
513
  }
710
514
  else {
711
- item.status = "noop";
712
- item.message = "skill path is not a symlink or directory; skipped";
515
+ item.status = "blocked";
516
+ item.message = `preserved ${item.source}: only a fingerprinted v2 app-owned symlink is eligible; review it manually`;
713
517
  }
714
518
  }
715
- catch {
716
- item.status = "noop";
717
- item.message = "stale skill already absent";
519
+ catch (error) {
520
+ if (error.code === "ENOENT") {
521
+ item.status = "noop";
522
+ item.message = "stale skill already absent";
523
+ }
524
+ else {
525
+ item.status = "failed";
526
+ item.message = `remove-stale-skill failed: ${error.message}`;
527
+ }
718
528
  }
719
529
  break;
720
530
  }
721
531
  default:
532
+ item.status = "failed";
533
+ item.message = `unsupported runtime migration action: ${item.action}`;
722
534
  break;
723
535
  }
724
536
  }
725
537
  catch (exc) {
726
- item.status = "failed";
727
- item.message = `${item.action} failed: ${exc.message}`;
538
+ item.status = "blocked";
539
+ item.message = `${item.action} preserved the resource: ${exc.message}; rerun migration and review it manually`;
728
540
  }
729
541
  }
730
542
  export function applyRuntimeMigrationItems(items, ctx) {
731
543
  const commands = resolveNpxHookCommands(ctx);
732
544
  for (const item of items) {
733
- applyRuntimeMigrationItem(item, commands);
545
+ if (item.status !== "pending") {
546
+ continue;
547
+ }
548
+ if (isRuntimeMigrationAction(item.action)) {
549
+ applyRuntimeMigrationItem(item, commands);
550
+ }
551
+ else {
552
+ item.status = "failed";
553
+ item.message = `unsupported runtime migration action: ${item.action}`;
554
+ }
734
555
  }
735
- applyInstalledHooksRetirementItems(items, ctx);
736
556
  }
737
557
  //# sourceMappingURL=runtimeMigration.js.map