agentera 3.0.0-dev.6 → 3.0.0-dev.69

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 (696) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +118 -22
  3. package/bundle/CHANGELOG.md +1361 -0
  4. package/bundle/DESIGN.md +229 -0
  5. package/bundle/LICENSE +201 -0
  6. package/bundle/README.md +143 -0
  7. package/bundle/UPGRADE.md +252 -0
  8. package/bundle/extract-corpus-parity.json +21 -0
  9. package/bundle/fixtures/routing/hybrid-corpus.yaml +154 -0
  10. package/bundle/references/adapters/package-publication.json +488 -0
  11. package/bundle/references/adapters/package-registry.yaml +435 -188
  12. package/bundle/references/adapters/package-surface-characterization.md +66 -34
  13. package/bundle/references/adapters/runtime-lifecycle-adapters.yaml +74 -0
  14. package/bundle/references/adapters/runtime-lifecycle-authority.yaml +62 -0
  15. package/bundle/references/adapters/runtime-lifecycle-operation-contract.yaml +84 -0
  16. package/bundle/references/adapters/runtime-retired-resources.yaml +333 -0
  17. package/bundle/references/analysis/evidence-tier-authority.yaml +518 -0
  18. package/bundle/references/analysis/verification-policy.yaml +266 -0
  19. package/bundle/references/artifacts/artifact-registry-interface-model.yaml +20 -10
  20. package/bundle/references/artifacts/glossary-entry-contract.yaml +1254 -0
  21. package/bundle/references/artifacts/state-storage-authority.yaml +3061 -0
  22. package/bundle/references/artifacts/verbosity-budget-authority.yaml +42 -0
  23. package/bundle/references/cli/app-lifecycle-vocabulary.yaml +7 -8
  24. package/bundle/references/cli/capability-instruction-contract.yaml +11 -14
  25. package/bundle/references/cli/hybrid-route-contract.yaml +438 -0
  26. package/bundle/references/cli/routing-model.md +155 -0
  27. package/bundle/references/cli/trigger-schema-enrichment.md +147 -0
  28. package/bundle/references/cli/update-channels.yaml +19 -2
  29. package/bundle/references/cli/vocabulary-index.yaml +20 -17
  30. package/bundle/references/cli/vocabulary.md +325 -362
  31. package/bundle/references/meta/retained-reference-authority.yaml +151 -0
  32. package/bundle/registry.json +13 -13
  33. package/bundle/skills/agentera/SKILL.md +226 -422
  34. package/bundle/skills/agentera/capabilities/audit/schemas/artifacts.yaml +84 -0
  35. package/bundle/skills/agentera/capabilities/{inspektera → audit}/schemas/exit.yaml +2 -2
  36. package/bundle/skills/agentera/capabilities/audit/schemas/triggers.yaml +25 -0
  37. package/bundle/skills/agentera/capabilities/{inspektera → audit}/schemas/validation.yaml +37 -18
  38. package/bundle/skills/agentera/capabilities/build/schemas/artifacts.yaml +103 -0
  39. package/bundle/skills/agentera/capabilities/{realisera → build}/schemas/exit.yaml +8 -6
  40. package/bundle/skills/agentera/capabilities/build/schemas/triggers.yaml +27 -0
  41. package/bundle/skills/agentera/capabilities/build/schemas/validation.yaml +184 -0
  42. package/bundle/skills/agentera/capabilities/{visualisera → design}/schemas/artifacts.yaml +12 -12
  43. package/bundle/skills/agentera/capabilities/{visualisera → design}/schemas/exit.yaml +5 -5
  44. package/bundle/skills/agentera/capabilities/design/schemas/triggers.yaml +16 -0
  45. package/bundle/skills/agentera/capabilities/{visualisera → design}/schemas/validation.yaml +7 -7
  46. package/bundle/skills/agentera/capabilities/discuss/schemas/artifacts.yaml +51 -0
  47. package/bundle/skills/agentera/capabilities/{resonera → discuss}/schemas/exit.yaml +2 -2
  48. package/bundle/skills/agentera/capabilities/discuss/schemas/triggers.yaml +20 -0
  49. package/bundle/skills/agentera/capabilities/discuss/schemas/validation.yaml +144 -0
  50. package/bundle/skills/agentera/capabilities/document/schemas/artifacts.yaml +80 -0
  51. package/bundle/skills/agentera/capabilities/document/schemas/triggers.yaml +16 -0
  52. package/bundle/skills/agentera/capabilities/{dokumentera → document}/schemas/validation.yaml +18 -18
  53. package/bundle/skills/agentera/capabilities/{optimera → optimize}/schemas/artifacts.yaml +18 -18
  54. package/bundle/skills/agentera/capabilities/{optimera → optimize}/schemas/exit.yaml +2 -2
  55. package/bundle/skills/agentera/capabilities/optimize/schemas/triggers.yaml +16 -0
  56. package/bundle/skills/agentera/capabilities/{optimera → optimize}/schemas/validation.yaml +9 -9
  57. package/bundle/skills/agentera/capabilities/orchestrate/schemas/artifacts.yaml +76 -0
  58. package/bundle/skills/agentera/capabilities/{orkestrera → orchestrate}/schemas/exit.yaml +9 -7
  59. package/bundle/skills/agentera/capabilities/orchestrate/schemas/triggers.yaml +23 -0
  60. package/bundle/skills/agentera/capabilities/orchestrate/schemas/validation.yaml +121 -0
  61. package/bundle/skills/agentera/capabilities/plan/schemas/artifacts.yaml +66 -0
  62. package/bundle/skills/agentera/capabilities/{planera → plan}/schemas/exit.yaml +2 -2
  63. package/bundle/skills/agentera/capabilities/plan/schemas/triggers.yaml +23 -0
  64. package/bundle/skills/agentera/capabilities/plan/schemas/validation.yaml +121 -0
  65. package/bundle/skills/agentera/capabilities/profile/schemas/artifacts.yaml +23 -0
  66. package/bundle/skills/agentera/capabilities/{profilera → profile}/schemas/exit.yaml +6 -5
  67. package/bundle/skills/agentera/capabilities/profile/schemas/triggers.yaml +20 -0
  68. package/bundle/skills/agentera/capabilities/profile/schemas/validation.yaml +115 -0
  69. package/bundle/skills/agentera/capabilities/research/schemas/artifacts.yaml +24 -0
  70. package/bundle/skills/agentera/capabilities/research/schemas/triggers.yaml +16 -0
  71. package/bundle/skills/agentera/capabilities/{inspirera → research}/schemas/validation.yaml +2 -2
  72. package/bundle/skills/agentera/capabilities/status/schemas/artifacts.yaml +73 -0
  73. package/bundle/skills/agentera/capabilities/status/schemas/triggers.yaml +22 -0
  74. package/bundle/skills/agentera/capabilities/{hej → status}/schemas/validation.yaml +5 -5
  75. package/bundle/skills/agentera/capabilities/{visionera → vision}/schemas/artifacts.yaml +16 -16
  76. package/bundle/skills/agentera/capabilities/{visionera → vision}/schemas/exit.yaml +7 -6
  77. package/bundle/skills/agentera/capabilities/vision/schemas/triggers.yaml +23 -0
  78. package/bundle/skills/agentera/capabilities/{visionera → vision}/schemas/validation.yaml +18 -20
  79. package/bundle/skills/agentera/capability_schema_contract.yaml +178 -34
  80. package/bundle/skills/agentera/protocol.yaml +31 -31
  81. package/bundle/skills/agentera/route-phrases.yaml +81 -0
  82. package/bundle/skills/agentera/schemas/artifacts/changelog.yaml +5 -4
  83. package/bundle/skills/agentera/schemas/artifacts/decisions.yaml +39 -21
  84. package/bundle/skills/agentera/schemas/artifacts/design.yaml +5 -4
  85. package/bundle/skills/agentera/schemas/artifacts/docs.yaml +15 -19
  86. package/bundle/skills/agentera/schemas/artifacts/experiments.yaml +145 -14
  87. package/bundle/skills/agentera/schemas/artifacts/glossary.yaml +82 -0
  88. package/bundle/skills/agentera/schemas/artifacts/health.yaml +58 -21
  89. package/bundle/skills/agentera/schemas/artifacts/objective.yaml +22 -8
  90. package/bundle/skills/agentera/schemas/artifacts/plan.yaml +461 -36
  91. package/bundle/skills/agentera/schemas/artifacts/progress.yaml +133 -20
  92. package/bundle/skills/agentera/schemas/artifacts/todo.yaml +342 -42
  93. package/bundle/skills/agentera/schemas/artifacts/vision.yaml +3 -3
  94. package/dist/analytics/extractCorpus/cli.js +101 -12
  95. package/dist/analytics/extractCorpus/copilotSessions.js +53 -9
  96. package/dist/analytics/extractCorpus/core.js +59 -24
  97. package/dist/analytics/extractCorpus/corpus.js +58 -23
  98. package/dist/analytics/extractCorpus/coverageAudit.js +260 -0
  99. package/dist/analytics/extractCorpus/cursorSessions.js +12 -7
  100. package/dist/analytics/extractCorpus/evidenceTiers.js +603 -0
  101. package/dist/analytics/extractCorpus/extractCorpusParity.js +105 -0
  102. package/dist/analytics/extractCorpus/filesystemSources.js +1 -5
  103. package/dist/analytics/extractCorpus/index.js +6 -1
  104. package/dist/analytics/extractCorpus/jsonlSessions.js +24 -5
  105. package/dist/analytics/extractCorpus/sqliteCaps.js +43 -0
  106. package/dist/analytics/extractCorpus/sqliteSessions.js +98 -6
  107. package/dist/analytics/extractCorpus/tierReader.js +108 -0
  108. package/dist/analytics/extractCorpus.js +0 -1
  109. package/dist/analytics/glossaryAdviceResolution.js +166 -0
  110. package/dist/analytics/glossaryInputAcquisition.js +319 -0
  111. package/dist/analytics/personalGlossaryAdmission.js +133 -0
  112. package/dist/analytics/personalGlossaryProfile.js +219 -0
  113. package/dist/analytics/profileSignals.js +211 -0
  114. package/dist/analytics/usageStats.js +169 -42
  115. package/dist/audit/terminologyDrift.js +281 -0
  116. package/dist/bin/agentera.js +3 -2
  117. package/dist/capabilities/audit/instructions.js +16 -0
  118. package/dist/capabilities/build/instructions.js +59 -0
  119. package/dist/capabilities/design/instructions.js +4 -0
  120. package/dist/capabilities/discuss/instructions.js +29 -0
  121. package/dist/capabilities/document/instructions.js +11 -0
  122. package/dist/capabilities/index.js +29 -27
  123. package/dist/capabilities/optimize/instructions.js +14 -0
  124. package/dist/capabilities/orchestrate/instructions.js +42 -0
  125. package/dist/capabilities/plan/instructions.js +33 -0
  126. package/dist/capabilities/profile/instructions.js +70 -0
  127. package/dist/capabilities/research/instructions.js +5 -0
  128. package/dist/capabilities/status/instructions.js +15 -0
  129. package/dist/capabilities/status/startupInstructions.js +34 -0
  130. package/dist/capabilities/vision/instructions.js +4 -0
  131. package/dist/cli/appContext.js +30 -24
  132. package/dist/cli/argvalidate.js +0 -1
  133. package/dist/cli/capabilityContext/benchmark.js +25 -17
  134. package/dist/cli/capabilityContext/bespoke.js +31 -12
  135. package/dist/cli/capabilityContext/build.js +251 -0
  136. package/dist/cli/capabilityContext/closeout.js +33 -30
  137. package/dist/cli/capabilityContext/contract.js +39 -46
  138. package/dist/cli/capabilityContext/evidence.js +90 -73
  139. package/dist/cli/capabilityContext/index.js +1 -2
  140. package/dist/cli/capabilityContext/orchestration.js +45 -21
  141. package/dist/cli/capabilityContext/planState.js +93 -100
  142. package/dist/cli/capabilityContext/progress.js +60 -14
  143. package/dist/cli/capabilityContext/projectVerification.js +409 -0
  144. package/dist/cli/capabilityContext/shared.js +9 -20
  145. package/dist/cli/capabilityContext/slim.js +56 -10
  146. package/dist/cli/capabilityContext/startup.js +57 -115
  147. package/dist/cli/capabilityContext/startupAggregation.js +68 -0
  148. package/dist/cli/capabilityContext/types.js +37 -24
  149. package/dist/cli/capabilityContext.js +1 -2
  150. package/dist/cli/commands/appHome.js +22 -0
  151. package/dist/cli/commands/capability.js +4 -4
  152. package/dist/cli/commands/compact.js +163 -13
  153. package/dist/cli/commands/doctor.js +122 -114
  154. package/dist/cli/commands/durability.js +81 -0
  155. package/dist/cli/commands/glossaryAdvice.js +138 -0
  156. package/dist/cli/commands/lint.js +22 -8
  157. package/dist/cli/commands/personalGlossary.js +176 -0
  158. package/dist/cli/commands/prime/briefOrientation.js +746 -0
  159. package/dist/cli/commands/prime/buildExecutionRequest.js +165 -0
  160. package/dist/cli/commands/prime/bundleStatus.js +190 -0
  161. package/dist/cli/commands/prime/collectEntityOrientation.js +326 -0
  162. package/dist/cli/commands/prime/collectOrientationState.js +219 -0
  163. package/dist/cli/commands/prime/orientationOutput.js +421 -0
  164. package/dist/cli/commands/prime/types.js +1 -0
  165. package/dist/cli/commands/prime/v1Migration.js +38 -0
  166. package/dist/cli/commands/prime.js +80 -558
  167. package/dist/cli/commands/profileGrounding.js +55 -0
  168. package/dist/cli/commands/query.js +77 -52
  169. package/dist/cli/commands/report.js +88 -26
  170. package/dist/cli/commands/route.js +142 -0
  171. package/dist/cli/commands/schema.js +266 -142
  172. package/dist/cli/commands/state/decisions.js +51 -61
  173. package/dist/cli/commands/state/docs.js +63 -86
  174. package/dist/cli/commands/state/experimentRecords.js +151 -0
  175. package/dist/cli/commands/state/experiments.js +11 -64
  176. package/dist/cli/commands/state/get.js +129 -0
  177. package/dist/cli/commands/state/health.js +11 -111
  178. package/dist/cli/commands/state/index.js +6 -41
  179. package/dist/cli/commands/state/list.js +194 -0
  180. package/dist/cli/commands/state/objective.js +21 -64
  181. package/dist/cli/commands/state/plan.js +11 -169
  182. package/dist/cli/commands/state/planTasks.js +154 -0
  183. package/dist/cli/commands/state/plans.js +154 -0
  184. package/dist/cli/commands/state/progress.js +11 -45
  185. package/dist/cli/commands/state/shared.js +0 -1
  186. package/dist/cli/commands/state/todo.js +29 -108
  187. package/dist/cli/commands/state/write.js +433 -0
  188. package/dist/cli/commands/upgrade.js +146 -5
  189. package/dist/cli/commands/upgradeVerify.js +118 -0
  190. package/dist/cli/commands/validate.js +246 -211
  191. package/dist/cli/commands/verify.js +24 -9
  192. package/dist/cli/contracts/bundleStatus.js +1 -0
  193. package/dist/cli/contracts/orientationState.js +1 -0
  194. package/dist/cli/dispatch/argvParser.js +32 -0
  195. package/dist/cli/dispatch/check.js +94 -50
  196. package/dist/cli/dispatch/commands.js +27 -0
  197. package/dist/cli/dispatch/index.js +82 -52
  198. package/dist/cli/dispatch/lifecycle.js +268 -108
  199. package/dist/cli/dispatch/prime.js +68 -29
  200. package/dist/cli/dispatch/projections.js +17 -0
  201. package/dist/cli/dispatch/shared.js +1 -2
  202. package/dist/cli/dispatch/state.js +68 -77
  203. package/dist/cli/dispatch.js +0 -1
  204. package/dist/cli/errors.js +16 -17
  205. package/dist/cli/help.js +395 -41
  206. package/dist/cli/migrationRequired.js +122 -0
  207. package/dist/cli/orientation/attention.js +61 -0
  208. package/dist/cli/orientation/corpusCoverage.js +102 -0
  209. package/dist/cli/orientation.js +438 -170
  210. package/dist/cli/planArtifacts.js +350 -0
  211. package/dist/cli/planEvidence.js +157 -0
  212. package/dist/cli/planLifecycleState.js +36 -0
  213. package/dist/cli/planTaskIndex.js +11 -0
  214. package/dist/cli/preCutoverCommand.js +32 -0
  215. package/dist/cli/prime-blob.js +71 -3
  216. package/dist/cli/profileAcquisition.js +167 -0
  217. package/dist/cli/startupCompletenessContract.js +59 -0
  218. package/dist/cli/stateQuery.js +56 -14
  219. package/dist/cli/structured.js +0 -1
  220. package/dist/cli/todoMarkdown.js +25 -12
  221. package/dist/cli/todoReadinessSelection.js +192 -0
  222. package/dist/cli/todoSeverity.js +18 -0
  223. package/dist/core/atomicWriter.js +20 -0
  224. package/dist/core/developmentChannel.js +1 -0
  225. package/dist/core/developmentInvocation.js +374 -0
  226. package/dist/core/difflib.js +0 -1
  227. package/dist/core/envPaths.js +20 -0
  228. package/dist/core/jsonValue.js +5 -0
  229. package/dist/core/paths.js +0 -1
  230. package/dist/core/pyjson.js +67 -3
  231. package/dist/core/shell.js +4 -0
  232. package/dist/core/skillIdentity.js +23 -0
  233. package/dist/core/sourceRoot.js +9 -12
  234. package/dist/core/text.js +10 -0
  235. package/dist/core/toml.js +0 -1
  236. package/dist/core/yaml.js +8 -1
  237. package/dist/eval/evalSkills.js +30 -26
  238. package/dist/eval/hybridRouteEvaluation.js +155 -0
  239. package/dist/eval/semanticEval.js +43 -20
  240. package/dist/eval/semanticFixtures.js +16 -5
  241. package/dist/hooks/common.js +3 -56
  242. package/dist/hooks/compaction/apply.js +252 -50
  243. package/dist/hooks/compaction/dryRun.js +7 -4
  244. package/dist/hooks/compaction/index.js +5 -6
  245. package/dist/hooks/compaction/parse.js +201 -5
  246. package/dist/hooks/compaction/retention.js +30 -25
  247. package/dist/hooks/compaction/status.js +149 -32
  248. package/dist/hooks/compaction/types.js +0 -1
  249. package/dist/hooks/validateArtifact/agentFacing.js +0 -1
  250. package/dist/hooks/validateArtifact/index.js +7 -64
  251. package/dist/hooks/validateArtifact/markdown.js +57 -7
  252. package/dist/hooks/validateArtifact/schema.js +110 -19
  253. package/dist/hooks/validateArtifact/traversal.js +13 -11
  254. package/dist/hooks/validateArtifact/violations.js +7 -5
  255. package/dist/migrate/v2HandoffManifest.js +127 -8
  256. package/dist/registries/activationContract.js +2 -0
  257. package/dist/registries/activationTuples.js +108 -0
  258. package/dist/registries/artifactProtocolIds.js +2 -1
  259. package/dist/registries/artifactRegistry.js +224 -63
  260. package/dist/registries/artifactSchemaProjection.js +45 -0
  261. package/dist/registries/capabilityContract.js +129 -2
  262. package/dist/registries/evaluatorHandoffContract.js +2 -3
  263. package/dist/registries/evidenceTierContract.js +371 -0
  264. package/dist/registries/glossaryAdviceContract.js +79 -0
  265. package/dist/registries/glossaryCaveatContract.js +67 -0
  266. package/dist/registries/glossaryConsumerContractValidation.js +787 -0
  267. package/dist/registries/glossaryEntryContract.js +757 -0
  268. package/dist/registries/glossaryTermIdentity.js +17 -0
  269. package/dist/registries/glossaryTermOccurrence.js +20 -0
  270. package/dist/registries/hybridRoute.js +274 -0
  271. package/dist/registries/hybridRouteReceipt.js +221 -0
  272. package/dist/registries/packagePublication.js +273 -0
  273. package/dist/registries/packageRegistry.js +187 -211
  274. package/dist/registries/todoReadinessContract.js +448 -0
  275. package/dist/registries/triggerLoader.js +174 -0
  276. package/dist/registries/verbosityBudgetContract.js +205 -0
  277. package/dist/release/releaseMetadata.js +156 -6
  278. package/dist/runtime/lifecycleAdapterContract.js +457 -0
  279. package/dist/runtime/lifecycleAdapters.js +777 -0
  280. package/dist/runtime/lifecycleAuthority.js +453 -0
  281. package/dist/runtime/lifecycleOperationContract.js +123 -0
  282. package/dist/runtime/lifecycleOperations.js +634 -0
  283. package/dist/runtime/lifecycleOwnershipJournal.js +622 -0
  284. package/dist/runtime/lifecyclePublication.js +415 -0
  285. package/dist/runtime/lifecycleSnapshot.js +438 -0
  286. package/dist/runtime/nativeResourceCleanup.js +502 -0
  287. package/dist/setup/opencode.js +20 -13
  288. package/dist/setup/opencodeConstants.js +1 -0
  289. package/dist/setup/sharedSkill.js +45 -0
  290. package/dist/setup/smokeChecks.js +21 -82
  291. package/dist/state/archiveDiscovery.js +580 -0
  292. package/dist/state/archivePublication.js +225 -0
  293. package/dist/state/archiveRecovery.js +237 -0
  294. package/dist/state/archiveReplay.js +53 -0
  295. package/dist/state/canonicalMigrationRecord.js +36 -0
  296. package/dist/state/changelog.js +221 -0
  297. package/dist/state/decisionEntities.js +367 -0
  298. package/dist/state/decisionLegacyValidation.js +215 -0
  299. package/dist/state/decisionMigrationProvenance.js +199 -0
  300. package/dist/state/decisionOverlay.js +254 -0
  301. package/dist/state/decisionRevision.js +256 -0
  302. package/dist/state/decisionRevisionMigration.js +89 -0
  303. package/dist/state/directRetrieval.js +323 -0
  304. package/dist/state/durability.js +324 -0
  305. package/dist/state/entityCutover.js +459 -0
  306. package/dist/state/entityCutoverGit.js +127 -0
  307. package/dist/state/entityGlossaryAuthority.js +13 -0
  308. package/dist/state/entityListProjection.js +187 -0
  309. package/dist/state/entityListRuntimeRegistry.js +85 -0
  310. package/dist/state/entityMigrationCausality.js +97 -0
  311. package/dist/state/entityMigrationIdentity.js +5 -0
  312. package/dist/state/entityMigrationPreview.js +840 -0
  313. package/dist/state/entityMigrationTodo.js +133 -0
  314. package/dist/state/entityPublicationContext.js +859 -0
  315. package/dist/state/entityRetrievalHelp.js +506 -0
  316. package/dist/state/entityStorage.js +899 -0
  317. package/dist/state/exactReplacementRecovery.js +18 -0
  318. package/dist/state/experimentArchive.js +63 -0
  319. package/dist/state/experimentIdentity.js +202 -0
  320. package/dist/state/healthEntities.js +262 -0
  321. package/dist/state/healthEntityValidation.js +18 -0
  322. package/dist/state/healthRepair.js +69 -0
  323. package/dist/state/installRoot.js +64 -25
  324. package/dist/state/legacyEntityCutoverEvidence.js +65 -0
  325. package/dist/state/legacyIdentity.js +47 -0
  326. package/dist/state/legacySummaryRecord.js +6 -0
  327. package/dist/state/listAccounting.js +54 -0
  328. package/dist/state/listClassification.js +17 -0
  329. package/dist/state/listCursor.js +42 -0
  330. package/dist/state/listRetrieval.js +781 -0
  331. package/dist/state/migrationSourceBinding.js +30 -0
  332. package/dist/state/objectiveExperimentEntities.js +322 -0
  333. package/dist/state/planEntities.js +1027 -0
  334. package/dist/state/planIdentity.js +47 -0
  335. package/dist/state/planLineageValidation.js +52 -0
  336. package/dist/state/planReplacementTransaction.js +475 -0
  337. package/dist/state/planRetrieval.js +313 -0
  338. package/dist/state/planTaskRetrieval.js +294 -0
  339. package/dist/state/progressEntities.js +512 -0
  340. package/dist/state/progressGlossaryCaveat.js +168 -0
  341. package/dist/state/progressPublicationOrder.js +19 -0
  342. package/dist/state/progressWritePolicy.js +33 -0
  343. package/dist/state/projectRoot.js +62 -0
  344. package/dist/state/projectionPolicy.js +190 -0
  345. package/dist/state/retrievalAuthority.js +156 -0
  346. package/dist/state/safeProjectFile.js +155 -0
  347. package/dist/state/startupAnalysis/benchmark.js +92 -27
  348. package/dist/state/startupAnalysis/contract.js +48 -10
  349. package/dist/state/startupAnalysis/helpers.js +27 -73
  350. package/dist/state/startupAnalysis/index.js +0 -1
  351. package/dist/state/startupAnalysis/metrics.js +25 -19
  352. package/dist/state/startupAnalysis/records.js +13 -10
  353. package/dist/state/startupAnalysis/report.js +26 -38
  354. package/dist/state/startupAnalysis/threshold.js +19 -7
  355. package/dist/state/startupAnalysis.js +0 -1
  356. package/dist/state/startupProjection.js +499 -0
  357. package/dist/state/stateMode.js +222 -0
  358. package/dist/state/stateStorageAuthority.js +47 -0
  359. package/dist/state/summaryEntityRead.js +25 -0
  360. package/dist/state/summaryMigrationProvenance.js +66 -0
  361. package/dist/state/summarySourceRowAuthority.js +36 -0
  362. package/dist/state/todoActivationSafety.js +58 -0
  363. package/dist/state/todoDocsEntities.js +1124 -0
  364. package/dist/state/todoDocsEntityValidation.js +158 -0
  365. package/dist/state/todoMarkdownProjection.js +51 -0
  366. package/dist/state/todoReconciliationActivation.js +182 -0
  367. package/dist/state/todoReconciliationInspection.js +171 -0
  368. package/dist/state/todoReconciliationRepair.js +318 -0
  369. package/dist/state/todoReconciliationTransaction.js +595 -0
  370. package/dist/state/write/assign.js +20 -0
  371. package/dist/state/write/candidateMutation.js +269 -0
  372. package/dist/state/write/errors.js +11 -0
  373. package/dist/state/write/experimentPublication.js +192 -0
  374. package/dist/state/write/explain.js +377 -0
  375. package/dist/state/write/fields.js +61 -0
  376. package/dist/state/write/glossaryPublication.js +263 -0
  377. package/dist/state/write/grammar.js +285 -0
  378. package/dist/state/write/helpers.js +29 -0
  379. package/dist/state/write/index.js +12 -0
  380. package/dist/state/write/input.js +391 -0
  381. package/dist/state/write/lock.js +837 -0
  382. package/dist/state/write/mutation.js +234 -0
  383. package/dist/state/write/operations.js +170 -0
  384. package/dist/state/write/planEvaluation.js +128 -0
  385. package/dist/state/write/planPublication.js +179 -0
  386. package/dist/state/write/runtimeOperations.js +146 -0
  387. package/dist/state/write/serialize.js +1 -0
  388. package/dist/state/write/transaction.js +57 -0
  389. package/dist/state/write/validate.js +7 -0
  390. package/dist/upgrade/appContentRefresh.js +383 -0
  391. package/dist/upgrade/appModel.js +8 -7
  392. package/dist/upgrade/atomicWriter.js +1 -0
  393. package/dist/upgrade/bundleEvidence.js +33 -0
  394. package/dist/upgrade/channels.js +12 -8
  395. package/dist/upgrade/compatibility.js +56 -21
  396. package/dist/upgrade/doctor.js +165 -199
  397. package/dist/upgrade/doctorClassifier.js +187 -0
  398. package/dist/upgrade/installedHooksRetirement.js +196 -0
  399. package/dist/upgrade/legacyAgentCleanup.js +282 -0
  400. package/dist/upgrade/lifecycleUpgrade.js +113 -0
  401. package/dist/upgrade/migrateArtifactsV2ToV3.js +375 -79
  402. package/dist/upgrade/migrationPublication.js +122 -0
  403. package/dist/upgrade/nextMajorDoctor.js +29 -10
  404. package/dist/upgrade/npxPlatformStatus.js +22 -0
  405. package/dist/upgrade/projectIntegration.js +145 -189
  406. package/dist/upgrade/projectIntegrationDecision.js +50 -0
  407. package/dist/upgrade/retiredResourceDiagnostics.js +117 -0
  408. package/dist/upgrade/runtimeMigration.js +272 -373
  409. package/dist/upgrade/upgradeCommands.js +14 -1
  410. package/dist/upgrade/upgradeLock.js +85 -0
  411. package/dist/upgrade/upgradeOrchestrator.js +263 -59
  412. package/dist/upgrade/v3CapabilitySurface.js +2 -3
  413. package/dist/upgrade/versionResolution.js +2 -3
  414. package/dist/validate/activationArtifactEvidence.js +852 -0
  415. package/dist/validate/activationArtifactEvidenceTypes.js +12 -0
  416. package/dist/validate/activationConjunction.js +816 -0
  417. package/dist/validate/activationEvidenceManifest.js +531 -0
  418. package/dist/validate/activationPackageSemantics.js +29 -0
  419. package/dist/validate/appHomeContract.js +2 -8
  420. package/dist/validate/bootstrapAuthority.js +44 -0
  421. package/dist/validate/capability.js +133 -12
  422. package/dist/validate/crossCapability.js +15 -10
  423. package/dist/validate/retainedReferenceAuthority.js +879 -0
  424. package/dist/validate/selfAudit.js +39 -45
  425. package/dist/validate/v1LegacyCruft.js +131 -0
  426. package/dist/validate/vocabularyAuthority.js +18 -13
  427. package/package.json +60 -29
  428. package/bundle/references/adapters/cursor.md +0 -213
  429. package/bundle/references/adapters/opencode.md +0 -530
  430. package/bundle/references/adapters/package-manifest-interface-model.yaml +0 -337
  431. package/bundle/references/adapters/runtime-adapter-characterization.md +0 -79
  432. package/bundle/references/adapters/runtime-adapter-interface-model.yaml +0 -200
  433. package/bundle/references/adapters/runtime-adapter-registry.yaml +0 -548
  434. package/bundle/references/adapters/runtime-feature-parity.md +0 -189
  435. package/bundle/references/analysis/benchmark.md +0 -267
  436. package/bundle/references/analysis/startup-measurement-contract.yaml +0 -424
  437. package/bundle/references/cli/agent-ready-state-contract.yaml +0 -953
  438. package/bundle/references/cli/audience-namespace-cli-migration.yaml +0 -369
  439. package/bundle/references/cli/bundle-skill-vocabulary.yaml +0 -250
  440. package/bundle/references/cli/capability-tool-classification.yaml +0 -53
  441. package/bundle/references/cli/coexistence-probe.yaml +0 -9
  442. package/bundle/references/cli/routing-execution-vocabulary.yaml +0 -281
  443. package/bundle/references/cli/single-name-protocol.yaml +0 -42
  444. package/bundle/references/cli/upgrade-repair-wording.md +0 -31
  445. package/bundle/references/cli/v3-handoff-manifest.schema.yaml +0 -98
  446. package/bundle/references/meta/documentation-inventory.md +0 -49
  447. package/bundle/skills/agentera/.claude-plugin/plugin.json +0 -27
  448. package/bundle/skills/agentera/agents/dokumentera.toml +0 -6
  449. package/bundle/skills/agentera/agents/hej.toml +0 -6
  450. package/bundle/skills/agentera/agents/inspektera.toml +0 -6
  451. package/bundle/skills/agentera/agents/inspirera.toml +0 -6
  452. package/bundle/skills/agentera/agents/optimera.toml +0 -6
  453. package/bundle/skills/agentera/agents/orkestrera.toml +0 -6
  454. package/bundle/skills/agentera/agents/planera.toml +0 -6
  455. package/bundle/skills/agentera/agents/profilera.toml +0 -6
  456. package/bundle/skills/agentera/agents/realisera.toml +0 -6
  457. package/bundle/skills/agentera/agents/resonera.toml +0 -6
  458. package/bundle/skills/agentera/agents/visionera.toml +0 -6
  459. package/bundle/skills/agentera/agents/visualisera.toml +0 -6
  460. package/bundle/skills/agentera/capabilities/dokumentera/schemas/artifacts.yaml +0 -73
  461. package/bundle/skills/agentera/capabilities/dokumentera/schemas/triggers.yaml +0 -35
  462. package/bundle/skills/agentera/capabilities/hej/schemas/artifacts.yaml +0 -69
  463. package/bundle/skills/agentera/capabilities/hej/schemas/triggers.yaml +0 -58
  464. package/bundle/skills/agentera/capabilities/inspektera/schemas/artifacts.yaml +0 -76
  465. package/bundle/skills/agentera/capabilities/inspektera/schemas/triggers.yaml +0 -38
  466. package/bundle/skills/agentera/capabilities/inspirera/schemas/artifacts.yaml +0 -24
  467. package/bundle/skills/agentera/capabilities/inspirera/schemas/triggers.yaml +0 -34
  468. package/bundle/skills/agentera/capabilities/optimera/schemas/triggers.yaml +0 -39
  469. package/bundle/skills/agentera/capabilities/orkestrera/schemas/artifacts.yaml +0 -64
  470. package/bundle/skills/agentera/capabilities/orkestrera/schemas/triggers.yaml +0 -42
  471. package/bundle/skills/agentera/capabilities/orkestrera/schemas/validation.yaml +0 -120
  472. package/bundle/skills/agentera/capabilities/planera/schemas/artifacts.yaml +0 -62
  473. package/bundle/skills/agentera/capabilities/planera/schemas/triggers.yaml +0 -34
  474. package/bundle/skills/agentera/capabilities/planera/schemas/validation.yaml +0 -61
  475. package/bundle/skills/agentera/capabilities/profilera/schemas/artifacts.yaml +0 -18
  476. package/bundle/skills/agentera/capabilities/profilera/schemas/triggers.yaml +0 -45
  477. package/bundle/skills/agentera/capabilities/profilera/schemas/validation.yaml +0 -57
  478. package/bundle/skills/agentera/capabilities/realisera/schemas/artifacts.yaml +0 -80
  479. package/bundle/skills/agentera/capabilities/realisera/schemas/triggers.yaml +0 -39
  480. package/bundle/skills/agentera/capabilities/realisera/schemas/validation.yaml +0 -110
  481. package/bundle/skills/agentera/capabilities/resonera/schemas/artifacts.yaml +0 -47
  482. package/bundle/skills/agentera/capabilities/resonera/schemas/triggers.yaml +0 -46
  483. package/bundle/skills/agentera/capabilities/resonera/schemas/validation.yaml +0 -77
  484. package/bundle/skills/agentera/capabilities/visionera/schemas/triggers.yaml +0 -41
  485. package/bundle/skills/agentera/capabilities/visualisera/schemas/triggers.yaml +0 -33
  486. package/bundle/skills/agentera/references/contract.md +0 -1039
  487. package/dist/analytics/extractCorpus/cli.js.map +0 -1
  488. package/dist/analytics/extractCorpus/copilotSessions.js.map +0 -1
  489. package/dist/analytics/extractCorpus/core.js.map +0 -1
  490. package/dist/analytics/extractCorpus/corpus.js.map +0 -1
  491. package/dist/analytics/extractCorpus/cursorSessions.js.map +0 -1
  492. package/dist/analytics/extractCorpus/filesystemSources.js.map +0 -1
  493. package/dist/analytics/extractCorpus/index.js.map +0 -1
  494. package/dist/analytics/extractCorpus/jsonlSessions.js.map +0 -1
  495. package/dist/analytics/extractCorpus/sqliteSessions.js.map +0 -1
  496. package/dist/analytics/extractCorpus.js.map +0 -1
  497. package/dist/analytics/usageStats.js.map +0 -1
  498. package/dist/bin/agentera.js.map +0 -1
  499. package/dist/capabilities/dokumentera/instructions.js +0 -6
  500. package/dist/capabilities/dokumentera/instructions.js.map +0 -1
  501. package/dist/capabilities/hej/instructions.js +0 -6
  502. package/dist/capabilities/hej/instructions.js.map +0 -1
  503. package/dist/capabilities/index.js.map +0 -1
  504. package/dist/capabilities/inspektera/instructions.js +0 -6
  505. package/dist/capabilities/inspektera/instructions.js.map +0 -1
  506. package/dist/capabilities/inspirera/instructions.js +0 -6
  507. package/dist/capabilities/inspirera/instructions.js.map +0 -1
  508. package/dist/capabilities/optimera/instructions.js +0 -6
  509. package/dist/capabilities/optimera/instructions.js.map +0 -1
  510. package/dist/capabilities/orkestrera/instructions.js +0 -6
  511. package/dist/capabilities/orkestrera/instructions.js.map +0 -1
  512. package/dist/capabilities/planera/instructions.js +0 -6
  513. package/dist/capabilities/planera/instructions.js.map +0 -1
  514. package/dist/capabilities/profilera/instructions.js +0 -6
  515. package/dist/capabilities/profilera/instructions.js.map +0 -1
  516. package/dist/capabilities/realisera/instructions.js +0 -6
  517. package/dist/capabilities/realisera/instructions.js.map +0 -1
  518. package/dist/capabilities/resonera/instructions.js +0 -6
  519. package/dist/capabilities/resonera/instructions.js.map +0 -1
  520. package/dist/capabilities/visionera/instructions.js +0 -6
  521. package/dist/capabilities/visionera/instructions.js.map +0 -1
  522. package/dist/capabilities/visualisera/instructions.js +0 -6
  523. package/dist/capabilities/visualisera/instructions.js.map +0 -1
  524. package/dist/cli/appContext.js.map +0 -1
  525. package/dist/cli/argvalidate.js.map +0 -1
  526. package/dist/cli/capabilityContext/benchmark.js.map +0 -1
  527. package/dist/cli/capabilityContext/bespoke.js.map +0 -1
  528. package/dist/cli/capabilityContext/closeout.js.map +0 -1
  529. package/dist/cli/capabilityContext/contract.js.map +0 -1
  530. package/dist/cli/capabilityContext/evidence.js.map +0 -1
  531. package/dist/cli/capabilityContext/index.js.map +0 -1
  532. package/dist/cli/capabilityContext/orchestration.js.map +0 -1
  533. package/dist/cli/capabilityContext/planState.js.map +0 -1
  534. package/dist/cli/capabilityContext/progress.js.map +0 -1
  535. package/dist/cli/capabilityContext/realisera.js +0 -174
  536. package/dist/cli/capabilityContext/realisera.js.map +0 -1
  537. package/dist/cli/capabilityContext/shared.js.map +0 -1
  538. package/dist/cli/capabilityContext/slim.js.map +0 -1
  539. package/dist/cli/capabilityContext/startup.js.map +0 -1
  540. package/dist/cli/capabilityContext/types.js.map +0 -1
  541. package/dist/cli/capabilityContext.js.map +0 -1
  542. package/dist/cli/commands/backfill.js +0 -84
  543. package/dist/cli/commands/backfill.js.map +0 -1
  544. package/dist/cli/commands/capability.js.map +0 -1
  545. package/dist/cli/commands/compact.js.map +0 -1
  546. package/dist/cli/commands/doctor.js.map +0 -1
  547. package/dist/cli/commands/lint.js.map +0 -1
  548. package/dist/cli/commands/prime.js.map +0 -1
  549. package/dist/cli/commands/query.js.map +0 -1
  550. package/dist/cli/commands/report.js.map +0 -1
  551. package/dist/cli/commands/schema.js.map +0 -1
  552. package/dist/cli/commands/state/decisions.js.map +0 -1
  553. package/dist/cli/commands/state/docs.js.map +0 -1
  554. package/dist/cli/commands/state/experiments.js.map +0 -1
  555. package/dist/cli/commands/state/health.js.map +0 -1
  556. package/dist/cli/commands/state/index.js.map +0 -1
  557. package/dist/cli/commands/state/objective.js.map +0 -1
  558. package/dist/cli/commands/state/plan.js.map +0 -1
  559. package/dist/cli/commands/state/progress.js.map +0 -1
  560. package/dist/cli/commands/state/shared.js.map +0 -1
  561. package/dist/cli/commands/state/todo.js.map +0 -1
  562. package/dist/cli/commands/state.js +0 -1023
  563. package/dist/cli/commands/state.js.map +0 -1
  564. package/dist/cli/commands/upgrade.js.map +0 -1
  565. package/dist/cli/commands/validate.js.map +0 -1
  566. package/dist/cli/commands/verify.js.map +0 -1
  567. package/dist/cli/dispatch/check.js.map +0 -1
  568. package/dist/cli/dispatch/index.js.map +0 -1
  569. package/dist/cli/dispatch/lifecycle.js.map +0 -1
  570. package/dist/cli/dispatch/prime.js.map +0 -1
  571. package/dist/cli/dispatch/shared.js.map +0 -1
  572. package/dist/cli/dispatch/state.js.map +0 -1
  573. package/dist/cli/dispatch.js.map +0 -1
  574. package/dist/cli/errors.js.map +0 -1
  575. package/dist/cli/help.js.map +0 -1
  576. package/dist/cli/orientation.js.map +0 -1
  577. package/dist/cli/prime-blob.js.map +0 -1
  578. package/dist/cli/stateQuery.js.map +0 -1
  579. package/dist/cli/structured.js.map +0 -1
  580. package/dist/cli/todoMarkdown.js.map +0 -1
  581. package/dist/core/difflib.js.map +0 -1
  582. package/dist/core/git.js +0 -43
  583. package/dist/core/git.js.map +0 -1
  584. package/dist/core/paths.js.map +0 -1
  585. package/dist/core/pyjson.js.map +0 -1
  586. package/dist/core/sourceRoot.js.map +0 -1
  587. package/dist/core/toml.js.map +0 -1
  588. package/dist/core/yaml.js.map +0 -1
  589. package/dist/eval/evalSkills.js.map +0 -1
  590. package/dist/eval/semanticEval.js.map +0 -1
  591. package/dist/eval/semanticFixtures.js.map +0 -1
  592. package/dist/hooks/common.js.map +0 -1
  593. package/dist/hooks/compaction/apply.js.map +0 -1
  594. package/dist/hooks/compaction/dryRun.js.map +0 -1
  595. package/dist/hooks/compaction/index.js.map +0 -1
  596. package/dist/hooks/compaction/parse.js.map +0 -1
  597. package/dist/hooks/compaction/retention.js.map +0 -1
  598. package/dist/hooks/compaction/status.js.map +0 -1
  599. package/dist/hooks/compaction/types.js.map +0 -1
  600. package/dist/hooks/compaction.js +0 -935
  601. package/dist/hooks/compaction.js.map +0 -1
  602. package/dist/hooks/cursorPreToolUse.js +0 -19
  603. package/dist/hooks/cursorPreToolUse.js.map +0 -1
  604. package/dist/hooks/cursorSessionStart.js +0 -71
  605. package/dist/hooks/cursorSessionStart.js.map +0 -1
  606. package/dist/hooks/sessionStart.js +0 -209
  607. package/dist/hooks/sessionStart.js.map +0 -1
  608. package/dist/hooks/sessionStop.js +0 -203
  609. package/dist/hooks/sessionStop.js.map +0 -1
  610. package/dist/hooks/validateArtifact/agentFacing.js.map +0 -1
  611. package/dist/hooks/validateArtifact/index.js.map +0 -1
  612. package/dist/hooks/validateArtifact/markdown.js.map +0 -1
  613. package/dist/hooks/validateArtifact/runtime.js +0 -83
  614. package/dist/hooks/validateArtifact/runtime.js.map +0 -1
  615. package/dist/hooks/validateArtifact/schema.js.map +0 -1
  616. package/dist/hooks/validateArtifact/traversal.js.map +0 -1
  617. package/dist/hooks/validateArtifact/violations.js.map +0 -1
  618. package/dist/hooks/validateArtifact.js +0 -924
  619. package/dist/hooks/validateArtifact.js.map +0 -1
  620. package/dist/migrate/v2HandoffManifest.js.map +0 -1
  621. package/dist/registries/artifactProtocolIds.js.map +0 -1
  622. package/dist/registries/artifactRegistry.js.map +0 -1
  623. package/dist/registries/capabilityContract.js.map +0 -1
  624. package/dist/registries/evaluatorHandoffContract.js.map +0 -1
  625. package/dist/registries/packageRegistry.js.map +0 -1
  626. package/dist/registries/runtimeAdapterRegistry.js +0 -315
  627. package/dist/registries/runtimeAdapterRegistry.js.map +0 -1
  628. package/dist/release/releaseMetadata.js.map +0 -1
  629. package/dist/setup/codex/agents.js +0 -96
  630. package/dist/setup/codex/agents.js.map +0 -1
  631. package/dist/setup/codex/cli.js +0 -161
  632. package/dist/setup/codex/cli.js.map +0 -1
  633. package/dist/setup/codex/configToml.js +0 -644
  634. package/dist/setup/codex/configToml.js.map +0 -1
  635. package/dist/setup/codex/constants.js +0 -29
  636. package/dist/setup/codex/constants.js.map +0 -1
  637. package/dist/setup/codex/installRoot.js +0 -64
  638. package/dist/setup/codex/installRoot.js.map +0 -1
  639. package/dist/setup/codex/state.js +0 -270
  640. package/dist/setup/codex/state.js.map +0 -1
  641. package/dist/setup/codex.js +0 -12
  642. package/dist/setup/codex.js.map +0 -1
  643. package/dist/setup/copilot.js +0 -227
  644. package/dist/setup/copilot.js.map +0 -1
  645. package/dist/setup/cursor.js +0 -127
  646. package/dist/setup/cursor.js.map +0 -1
  647. package/dist/setup/doctor/core.js +0 -300
  648. package/dist/setup/doctor/core.js.map +0 -1
  649. package/dist/setup/doctor/diagnostics.js +0 -247
  650. package/dist/setup/doctor/diagnostics.js.map +0 -1
  651. package/dist/setup/doctor/opencode.js +0 -281
  652. package/dist/setup/doctor/opencode.js.map +0 -1
  653. package/dist/setup/doctor/report.js +0 -474
  654. package/dist/setup/doctor/report.js.map +0 -1
  655. package/dist/setup/doctor.js +0 -10
  656. package/dist/setup/doctor.js.map +0 -1
  657. package/dist/setup/opencode.js.map +0 -1
  658. package/dist/setup/smokeChecks.js.map +0 -1
  659. package/dist/state/installRoot.js.map +0 -1
  660. package/dist/state/progressCommit.js +0 -289
  661. package/dist/state/progressCommit.js.map +0 -1
  662. package/dist/state/startupAnalysis/benchmark.js.map +0 -1
  663. package/dist/state/startupAnalysis/contract.js.map +0 -1
  664. package/dist/state/startupAnalysis/helpers.js.map +0 -1
  665. package/dist/state/startupAnalysis/index.js.map +0 -1
  666. package/dist/state/startupAnalysis/metrics.js.map +0 -1
  667. package/dist/state/startupAnalysis/records.js.map +0 -1
  668. package/dist/state/startupAnalysis/report.js.map +0 -1
  669. package/dist/state/startupAnalysis/threshold.js.map +0 -1
  670. package/dist/state/startupAnalysis.js.map +0 -1
  671. package/dist/upgrade/appModel.js.map +0 -1
  672. package/dist/upgrade/channels.js.map +0 -1
  673. package/dist/upgrade/coexistenceProbe.js +0 -83
  674. package/dist/upgrade/coexistenceProbe.js.map +0 -1
  675. package/dist/upgrade/compatibility.js.map +0 -1
  676. package/dist/upgrade/doctor.js.map +0 -1
  677. package/dist/upgrade/migrateArtifactsV1ToV2.js +0 -570
  678. package/dist/upgrade/migrateArtifactsV1ToV2.js.map +0 -1
  679. package/dist/upgrade/migrateArtifactsV2ToV3.js.map +0 -1
  680. package/dist/upgrade/nextMajorDoctor.js.map +0 -1
  681. package/dist/upgrade/projectIntegration.js.map +0 -1
  682. package/dist/upgrade/runtimeMigration.js.map +0 -1
  683. package/dist/upgrade/upgradeCommands.js.map +0 -1
  684. package/dist/upgrade/upgradeOrchestrator.js.map +0 -1
  685. package/dist/upgrade/v3CapabilitySurface.js.map +0 -1
  686. package/dist/upgrade/versionResolution.js.map +0 -1
  687. package/dist/validate/appHomeContract.js.map +0 -1
  688. package/dist/validate/capability.js.map +0 -1
  689. package/dist/validate/crossCapability.js.map +0 -1
  690. package/dist/validate/lifecycleAdapters.js +0 -772
  691. package/dist/validate/lifecycleAdapters.js.map +0 -1
  692. package/dist/validate/selfAudit.js.map +0 -1
  693. package/dist/validate/vocabularyAuthority.js.map +0 -1
  694. /package/bundle/skills/agentera/capabilities/{dokumentera → document}/schemas/exit.yaml +0 -0
  695. /package/bundle/skills/agentera/capabilities/{inspirera → research}/schemas/exit.yaml +0 -0
  696. /package/bundle/skills/agentera/capabilities/{hej → status}/schemas/exit.yaml +0 -0
@@ -0,0 +1,859 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { ExactReplacementConflictError, FileReplacementError } from "./exactReplacementRecovery.js";
5
+ import { assertValidatedProjectRoot } from "./projectRoot.js";
6
+ import { reject, StateWriteInputError } from "./write/errors.js";
7
+ const RECOVERY_IGNORE_BYTES = "*\n!.gitignore\n";
8
+ export const FILE_REPLACEMENT_RECOVERY_VERSION = "agentera.fileReplacementRecovery.v1";
9
+ export const FILE_REPLACEMENT_METADATA_NAME = "replacement.json";
10
+ function identity(stat) {
11
+ return {
12
+ dev: stat.dev,
13
+ ino: stat.ino,
14
+ type: stat.mode & BigInt(fs.constants.S_IFMT),
15
+ size: stat.size,
16
+ mtimeNs: stat.mtimeNs,
17
+ ctimeNs: stat.ctimeNs,
18
+ nlink: stat.nlink,
19
+ mode: stat.mode,
20
+ };
21
+ }
22
+ function sameIdentity(left, right) {
23
+ return left.dev === right.dev
24
+ && left.ino === right.ino
25
+ && left.type === right.type
26
+ && left.size === right.size
27
+ && left.mtimeNs === right.mtimeNs
28
+ && left.ctimeNs === right.ctimeNs
29
+ && left.nlink === right.nlink;
30
+ }
31
+ function sameDirectory(left, right) {
32
+ return right.isDirectory()
33
+ && !right.isSymbolicLink()
34
+ && left.dev === right.dev
35
+ && left.ino === right.ino;
36
+ }
37
+ function sha256(bytes) {
38
+ return createHash("sha256").update(bytes).digest("hex");
39
+ }
40
+ function publishedIdentity(file) {
41
+ return {
42
+ dev: file.identity.dev,
43
+ ino: file.identity.ino,
44
+ type: file.identity.type,
45
+ size: file.identity.size,
46
+ sha256: sha256(file.bytes),
47
+ };
48
+ }
49
+ function matchesPublished(file, expected) {
50
+ const observed = publishedIdentity(file);
51
+ return observed.dev === expected.dev
52
+ && observed.ino === expected.ino
53
+ && observed.type === expected.type
54
+ && observed.size === expected.size
55
+ && observed.sha256 === expected.sha256;
56
+ }
57
+ function matchesExpected(file, expected) {
58
+ return Buffer.isBuffer(expected) ? file.bytes.equals(expected) : matchesPublished(file, expected);
59
+ }
60
+ function sameStableFile(left, right) {
61
+ return sameIdentity(left.identity, right.identity) && left.bytes.equals(right.bytes);
62
+ }
63
+ function readStableFile(absolute, label) {
64
+ let before;
65
+ try {
66
+ before = fs.lstatSync(absolute, { bigint: true });
67
+ }
68
+ catch (error) {
69
+ throw new Error(`${label} is unavailable: ${error.message}`, { cause: error });
70
+ }
71
+ if (!before.isFile() || before.isSymbolicLink()) {
72
+ throw new Error(`${label} is not a safe regular file`);
73
+ }
74
+ let descriptor;
75
+ try {
76
+ descriptor = fs.openSync(absolute, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0));
77
+ const opened = fs.fstatSync(descriptor, { bigint: true });
78
+ if (!opened.isFile() || opened.isSymbolicLink() || opened.dev !== before.dev || opened.ino !== before.ino) {
79
+ throw new Error(`${label} changed while it was opened`);
80
+ }
81
+ const bytes = fs.readFileSync(descriptor);
82
+ const after = fs.fstatSync(descriptor, { bigint: true });
83
+ const pathname = fs.lstatSync(absolute, { bigint: true });
84
+ const openedIdentity = identity(opened);
85
+ if (!sameIdentity(openedIdentity, identity(after))
86
+ || !sameIdentity(openedIdentity, identity(pathname))
87
+ || BigInt(bytes.length) !== opened.size)
88
+ throw new Error(`${label} changed while its exact bytes were read`);
89
+ return { absolute, identity: identity(after), bytes };
90
+ }
91
+ finally {
92
+ if (descriptor !== undefined)
93
+ fs.closeSync(descriptor);
94
+ }
95
+ }
96
+ function readFileIfPresent(absolute, label) {
97
+ try {
98
+ fs.lstatSync(absolute);
99
+ }
100
+ catch (error) {
101
+ if (error.code === "ENOENT")
102
+ return null;
103
+ throw error;
104
+ }
105
+ return readStableFile(absolute, label);
106
+ }
107
+ function readStableDirectory(absolute, created = false) {
108
+ const stat = fs.lstatSync(absolute, { bigint: true });
109
+ if (!stat.isDirectory() || stat.isSymbolicLink()) {
110
+ throw new Error(`publication directory '${absolute}' is not a safe real directory`);
111
+ }
112
+ return { absolute, dev: stat.dev, ino: stat.ino, created };
113
+ }
114
+ function projectLocalPath(root, absolute, allowRoot = false) {
115
+ const resolved = path.resolve(absolute);
116
+ const relative = path.relative(root.path, resolved);
117
+ return resolved === absolute
118
+ && (allowRoot || relative.length > 0)
119
+ && relative !== ".."
120
+ && !relative.startsWith(`..${path.sep}`)
121
+ && !path.isAbsolute(relative);
122
+ }
123
+ /** Validate a recovery directory before listing or mutating anything through it. */
124
+ export function validateEntityRecoveryDirectory(root, absolute, targetDirectory, label, expected) {
125
+ assertValidatedProjectRoot(root);
126
+ if (!projectLocalPath(root, absolute) || !projectLocalPath(root, targetDirectory, true)) {
127
+ throw new FileReplacementError(`${label} must be a real project-local directory under the validated project root`);
128
+ }
129
+ let directory;
130
+ let target;
131
+ try {
132
+ directory = readStableDirectory(absolute);
133
+ target = readStableDirectory(targetDirectory);
134
+ if (fs.realpathSync(absolute) !== absolute || fs.realpathSync(targetDirectory) !== targetDirectory) {
135
+ throw new Error("a directory path traverses a symbolic link");
136
+ }
137
+ }
138
+ catch (error) {
139
+ throw new FileReplacementError(`${label} must be a real project-local non-symlink directory: ${error.message}`, error);
140
+ }
141
+ if (typeof process.getuid === "function") {
142
+ const stat = fs.lstatSync(directory.absolute, { bigint: true });
143
+ if ((stat.mode & 18n) !== 0n || stat.uid !== BigInt(process.getuid())) {
144
+ throw new FileReplacementError(`${label} must be owned by the current user and not group/world-writable`);
145
+ }
146
+ }
147
+ if (directory.dev !== target.dev) {
148
+ throw new FileReplacementError(`${label} must share the replacement target filesystem`);
149
+ }
150
+ if (expected && (directory.absolute !== expected.absolute
151
+ || directory.dev !== expected.dev
152
+ || directory.ino !== expected.ino)) {
153
+ throw new FileReplacementError(`${label} changed after its recovery boundary was validated`);
154
+ }
155
+ return { absolute: directory.absolute, dev: directory.dev, ino: directory.ino };
156
+ }
157
+ function syncDirectory(absolute) {
158
+ if (process.platform === "win32")
159
+ return;
160
+ let descriptor;
161
+ try {
162
+ descriptor = fs.openSync(absolute, fs.constants.O_RDONLY | (fs.constants.O_DIRECTORY ?? 0));
163
+ fs.fsyncSync(descriptor);
164
+ }
165
+ catch (error) {
166
+ if (!["EINVAL", "ENOTSUP", "ENOSYS"].includes(error.code ?? ""))
167
+ throw error;
168
+ }
169
+ finally {
170
+ if (descriptor !== undefined)
171
+ fs.closeSync(descriptor);
172
+ }
173
+ }
174
+ function syncDirectoryBestEffort(absolute) {
175
+ try {
176
+ syncDirectory(absolute);
177
+ }
178
+ catch { /* The canonical rename already linearized. */ }
179
+ }
180
+ function safeSegments(relativeTarget, label) {
181
+ const segments = relativeTarget.split(/[\\/]/).filter(Boolean);
182
+ if (segments.length < 1
183
+ || path.posix.isAbsolute(relativeTarget)
184
+ || path.win32.isAbsolute(relativeTarget)
185
+ || relativeTarget.includes("\0")
186
+ || segments.includes("..")
187
+ || segments.includes("."))
188
+ reject({
189
+ class: "unsupported_target",
190
+ message: `${label} '${relativeTarget}' is outside the validated project path grammar`,
191
+ recovery: "Use one project-relative path without symbolic, dot, parent, drive, UNC, or absolute segments; no state was changed.",
192
+ });
193
+ return segments;
194
+ }
195
+ function relativeDisplay(root, absolute) {
196
+ return path.relative(root, absolute).split(path.sep).join("/");
197
+ }
198
+ function removeExactFile(file) {
199
+ const current = readFileIfPresent(file.absolute, `attempt-owned file '${file.absolute}'`);
200
+ if (!current || !sameStableFile(file, current))
201
+ return false;
202
+ fs.unlinkSync(file.absolute);
203
+ return true;
204
+ }
205
+ function createDurableFile(absolute, bytes, mode = 0o600) {
206
+ let descriptor;
207
+ let opened;
208
+ try {
209
+ descriptor = fs.openSync(absolute, fs.constants.O_RDWR | fs.constants.O_CREAT | fs.constants.O_EXCL | (fs.constants.O_NOFOLLOW ?? 0), mode);
210
+ opened = identity(fs.fstatSync(descriptor, { bigint: true }));
211
+ fs.writeFileSync(descriptor, bytes);
212
+ if (typeof process.getuid === "function")
213
+ fs.fchmodSync(descriptor, mode);
214
+ fs.fsyncSync(descriptor);
215
+ }
216
+ catch (error) {
217
+ if (descriptor !== undefined) {
218
+ try {
219
+ fs.closeSync(descriptor);
220
+ }
221
+ catch { /* Preserve the primary failure. */ }
222
+ descriptor = undefined;
223
+ }
224
+ if (opened) {
225
+ try {
226
+ const current = readFileIfPresent(absolute, `failed stage '${absolute}'`);
227
+ if (current && sameIdentity(opened, current.identity))
228
+ fs.unlinkSync(absolute);
229
+ }
230
+ catch { /* Preserve changed or partially inspectable attempt state. */ }
231
+ }
232
+ throw error;
233
+ }
234
+ finally {
235
+ if (descriptor !== undefined)
236
+ fs.closeSync(descriptor);
237
+ }
238
+ return readStableFile(absolute, `durable stage '${absolute}'`);
239
+ }
240
+ function publicationConflict(markerPath) {
241
+ reject({
242
+ class: "conflict",
243
+ message: `state mode marker '${markerPath}' changed after entity mode detection; this is a conflict and cannot fall back to legacy state`,
244
+ syntax: "agentera state <artifact-id> <verb> ... --format json",
245
+ example: `restore the exact '${markerPath}' marker selected at command start and retry`,
246
+ });
247
+ }
248
+ function initializationConflict(markerPath) {
249
+ reject({
250
+ class: "conflict",
251
+ message: `state mode marker '${markerPath}' appeared during fresh plan initialization`,
252
+ syntax: "agentera state plan create --input PLAN.yaml --format json",
253
+ example: "remove no files; inspect the competing state publication and retry",
254
+ });
255
+ }
256
+ /**
257
+ * Binds mutations to a validated project and exact entity-mode marker. Every
258
+ * pathname and byte identity is checked at declared boundaries. Publication
259
+ * linearizes through standard complete-file link or rename operations; a
260
+ * non-cooperating writer that races after the final successful check is outside
261
+ * the contract and is not represented as a cross-process compare-and-swap.
262
+ */
263
+ export class EntityPublicationContext {
264
+ projectRoot;
265
+ validatedRoot;
266
+ markerPath;
267
+ marker;
268
+ createdDirectories = new Map();
269
+ closed = false;
270
+ constructor(root, markerPath, expectedBytes) {
271
+ this.projectRoot = root.path;
272
+ this.validatedRoot = root;
273
+ this.markerPath = markerPath;
274
+ const markerAbsolute = path.join(root.path, ...safeSegments(markerPath, "state mode marker"));
275
+ if (expectedBytes === null) {
276
+ if (readFileIfPresent(markerAbsolute, `state mode marker '${markerPath}'`))
277
+ initializationConflict(markerPath);
278
+ this.marker = null;
279
+ }
280
+ else {
281
+ this.marker = readStableFile(markerAbsolute, `state mode marker '${markerPath}'`);
282
+ if (!this.marker.bytes.equals(expectedBytes))
283
+ publicationConflict(markerPath);
284
+ }
285
+ this.assertValid();
286
+ }
287
+ static open(root, markerPath, expectedBytes) {
288
+ return new EntityPublicationContext(root, markerPath, expectedBytes);
289
+ }
290
+ static beginInitialization(root, markerPath) {
291
+ return new EntityPublicationContext(root, markerPath, null);
292
+ }
293
+ pinnedPath(relativePath = "") {
294
+ if (this.closed)
295
+ throw new Error("entity publication context is closed");
296
+ if (!relativePath)
297
+ return this.projectRoot;
298
+ return path.join(this.projectRoot, ...safeSegments(relativePath, "entity publication path"));
299
+ }
300
+ assertValid() {
301
+ if (this.closed)
302
+ throw new Error("entity publication context is closed");
303
+ assertValidatedProjectRoot(this.validatedRoot);
304
+ if (this.marker === null) {
305
+ try {
306
+ if (readFileIfPresent(path.join(this.projectRoot, ...safeSegments(this.markerPath, "state mode marker")), `state mode marker '${this.markerPath}'`)) {
307
+ initializationConflict(this.markerPath);
308
+ }
309
+ }
310
+ catch {
311
+ initializationConflict(this.markerPath);
312
+ }
313
+ return;
314
+ }
315
+ let current;
316
+ try {
317
+ current = readStableFile(this.marker.absolute, `state mode marker '${this.markerPath}'`);
318
+ }
319
+ catch {
320
+ publicationConflict(this.markerPath);
321
+ }
322
+ if (!sameStableFile(this.marker, current))
323
+ publicationConflict(this.markerPath);
324
+ }
325
+ publishImmutable(relativeTarget, bytes) {
326
+ return this.publishImmutableInternal(relativeTarget, bytes, false);
327
+ }
328
+ isInitializing() {
329
+ return this.marker === null;
330
+ }
331
+ publishStateMarker(bytes) {
332
+ if (this.marker !== null)
333
+ throw new Error("entity state marker is already active");
334
+ const published = this.publishImmutableInternal(this.markerPath, bytes, true);
335
+ if (!published)
336
+ initializationConflict(this.markerPath);
337
+ return published;
338
+ }
339
+ publishImmutableInternal(relativeTarget, bytes, activateMarker) {
340
+ const segments = safeSegments(relativeTarget, "immutable entity target");
341
+ if (segments.length < 2)
342
+ throw new Error(`unsafe immutable entity target '${relativeTarget}'`);
343
+ if (activateMarker && relativeTarget !== this.markerPath)
344
+ throw new Error("only the state mode marker can activate fresh entity state");
345
+ const directories = [];
346
+ const target = path.join(this.projectRoot, ...segments);
347
+ let stage;
348
+ let published;
349
+ let publicationOwned = false;
350
+ try {
351
+ directories.push(...this.openDirectories(segments.slice(0, -1), true));
352
+ const directory = directories.at(-1)?.absolute ?? this.projectRoot;
353
+ const existing = readFileIfPresent(target, `immutable entity target '${relativeTarget}'`);
354
+ if (existing) {
355
+ this.removeCreatedDirectories(directories);
356
+ return null;
357
+ }
358
+ const stagePath = path.join(directory, `.${segments.at(-1)}.${process.pid}.${randomUUID()}.tmp`);
359
+ stage = createDurableFile(stagePath, bytes);
360
+ this.assertBoundary(directories, undefined, [stage]);
361
+ if (readFileIfPresent(target, `immutable entity target '${relativeTarget}'`)) {
362
+ removeExactFile(stage);
363
+ stage = undefined;
364
+ this.removeCreatedDirectories(directories);
365
+ return null;
366
+ }
367
+ try {
368
+ fs.linkSync(stage.absolute, target);
369
+ }
370
+ catch (error) {
371
+ if (error.code === "EEXIST") {
372
+ removeExactFile(stage);
373
+ stage = undefined;
374
+ this.removeCreatedDirectories(directories);
375
+ return null;
376
+ }
377
+ throw new FileReplacementError(`immutable publication for '${relativeTarget}' failed before effects`, error);
378
+ }
379
+ syncDirectory(directory);
380
+ stage = readStableFile(stage.absolute, `immutable publication stage '${relativeTarget}'`);
381
+ published = readStableFile(target, `published entity '${relativeTarget}'`);
382
+ if (!published.bytes.equals(Buffer.from(bytes)) || published.identity.ino !== stage.identity.ino || published.identity.dev !== stage.identity.dev) {
383
+ throw new ExactReplacementConflictError(`immutable entity target '${relativeTarget}' changed at its publication boundary`);
384
+ }
385
+ publicationOwned = true;
386
+ if (activateMarker)
387
+ this.marker = published;
388
+ this.assertBoundary(directories, published, [stage]);
389
+ removeExactFile(stage);
390
+ stage = undefined;
391
+ syncDirectory(directory);
392
+ published = readStableFile(target, `published entity '${relativeTarget}'`);
393
+ if (activateMarker)
394
+ this.marker = published;
395
+ this.assertBoundary(directories, published);
396
+ for (const entry of directories.filter(({ created }) => created)) {
397
+ this.createdDirectories.set(relativeDisplay(this.projectRoot, entry.absolute), entry);
398
+ }
399
+ return publishedIdentity(published);
400
+ }
401
+ catch (error) {
402
+ if (activateMarker)
403
+ this.marker = null;
404
+ if (publicationOwned && published) {
405
+ if (stage) {
406
+ try {
407
+ if (removeExactFile(stage))
408
+ stage = undefined;
409
+ }
410
+ catch { /* Preserve changed attempt bytes. */ }
411
+ }
412
+ if (!stage) {
413
+ try {
414
+ const current = readFileIfPresent(target, `failed immutable publication '${relativeTarget}'`);
415
+ if (current && matchesPublished(current, publishedIdentity(published)))
416
+ removeExactFile(current);
417
+ }
418
+ catch { /* Preserve a changed successor. */ }
419
+ }
420
+ }
421
+ if (stage) {
422
+ try {
423
+ removeExactFile(stage);
424
+ }
425
+ catch { /* Preserve changed attempt bytes. */ }
426
+ }
427
+ this.removeCreatedDirectories(directories);
428
+ throw error;
429
+ }
430
+ }
431
+ publishPreowned(relativeTarget, relativeReceipt, expected) {
432
+ const targetSegments = safeSegments(relativeTarget, "preowned target");
433
+ const receiptSegments = safeSegments(relativeReceipt, "preowned receipt");
434
+ if (targetSegments.length < 2 || receiptSegments.length < 2)
435
+ throw new Error("unsafe preowned publication path");
436
+ this.assertValid();
437
+ const receipt = readStableFile(path.join(this.projectRoot, ...receiptSegments), `preowned receipt '${relativeReceipt}'`);
438
+ if (!matchesPublished(receipt, expected))
439
+ throw new Error(`preowned receipt '${relativeReceipt}' changed before publication`);
440
+ const directories = this.openDirectories(targetSegments.slice(0, -1), true);
441
+ const directory = directories.at(-1)?.absolute ?? this.projectRoot;
442
+ const target = path.join(directory, targetSegments.at(-1));
443
+ try {
444
+ this.assertBoundary(directories, undefined, [receipt]);
445
+ if (!readFileIfPresent(target, `preowned target '${relativeTarget}'`)) {
446
+ try {
447
+ fs.linkSync(receipt.absolute, target);
448
+ syncDirectory(directory);
449
+ }
450
+ catch (error) {
451
+ if (error.code !== "EEXIST")
452
+ throw error;
453
+ }
454
+ }
455
+ const published = readStableFile(target, `preowned target '${relativeTarget}'`);
456
+ if (!matchesPublished(published, expected) || published.identity.dev !== receipt.identity.dev || published.identity.ino !== receipt.identity.ino) {
457
+ throw new Error(`canonical target '${relativeTarget}' collides with migration ownership receipt; byte-identical replacement inodes are never adopted`);
458
+ }
459
+ this.assertBoundary(directories, published, [receipt]);
460
+ for (const entry of directories.filter(({ created }) => created)) {
461
+ this.createdDirectories.set(relativeDisplay(this.projectRoot, entry.absolute), entry);
462
+ }
463
+ return publishedIdentity(published);
464
+ }
465
+ catch (error) {
466
+ this.removeCreatedDirectories(directories);
467
+ throw error;
468
+ }
469
+ }
470
+ removeExact(relativeTarget, expected, verifyContext = true) {
471
+ const segments = safeSegments(relativeTarget, "exact removal target");
472
+ const directories = this.openDirectories(segments.slice(0, -1), false, true, verifyContext);
473
+ if (!directories)
474
+ return "absent";
475
+ const directory = directories.at(-1)?.absolute ?? this.projectRoot;
476
+ const target = path.join(directory, segments.at(-1));
477
+ const current = readFileIfPresent(target, `exact removal target '${relativeTarget}'`);
478
+ if (!current)
479
+ return "absent";
480
+ if (!matchesPublished(current, expected))
481
+ return "identity_mismatch";
482
+ this.assertBoundary(directories, current, [], verifyContext);
483
+ const confirmed = readStableFile(target, `exact removal target '${relativeTarget}'`);
484
+ if (!sameStableFile(current, confirmed))
485
+ return "identity_mismatch";
486
+ fs.unlinkSync(target);
487
+ syncDirectory(directory);
488
+ if (relativeTarget === this.markerPath)
489
+ this.marker = null;
490
+ this.removeAttemptDirectories();
491
+ return "removed";
492
+ }
493
+ replaceExisting(relativeTarget, expectedBytes, bytes, maxEntityBytes) {
494
+ return this.replaceOwned(relativeTarget, expectedBytes, bytes, maxEntityBytes);
495
+ }
496
+ replaceVisible(relativeTarget, expectedBytes, bytes, maxEntityBytes) {
497
+ return this.replaceOwned(relativeTarget, expectedBytes, bytes, maxEntityBytes);
498
+ }
499
+ restoreExact(relativeTarget, expected, bytes, maxEntityBytes) {
500
+ return this.replaceOwned(relativeTarget, expected, bytes, maxEntityBytes, false);
501
+ }
502
+ restoreVisible(relativeTarget, expected, bytes, maxEntityBytes) {
503
+ return this.replaceOwned(relativeTarget, expected, bytes, maxEntityBytes, false);
504
+ }
505
+ close() {
506
+ this.closed = true;
507
+ }
508
+ replaceOwned(relativeTarget, expected, bytes, maxEntityBytes, verifyContext = true) {
509
+ const segments = safeSegments(relativeTarget, "recoverable replacement target");
510
+ const directories = this.openDirectories(segments.slice(0, -1), false, false, verifyContext);
511
+ if (!directories)
512
+ throw new FileReplacementError(`replacement target '${relativeTarget}' is absent before publication`);
513
+ const directory = directories.at(-1)?.absolute ?? this.projectRoot;
514
+ const target = path.join(directory, segments.at(-1));
515
+ const baseline = readStableFile(target, `replacement target '${relativeTarget}'`);
516
+ if (!matchesExpected(baseline, expected)) {
517
+ throw new ExactReplacementConflictError(`target '${relativeTarget}' ownership or bytes changed before replacement; the detected change was preserved`);
518
+ }
519
+ if (!Number.isSafeInteger(maxEntityBytes) || maxEntityBytes < 1 || baseline.bytes.length > maxEntityBytes) {
520
+ throw new FileReplacementError(`target '${relativeTarget}' exact ${baseline.bytes.length}-byte baseline exceeds the authority-owned ${maxEntityBytes}-byte recovery limit`);
521
+ }
522
+ const after = Buffer.from(bytes);
523
+ let recovery;
524
+ let backup;
525
+ let stage;
526
+ let metadata;
527
+ let committed;
528
+ let renameCompleted = false;
529
+ try {
530
+ recovery = this.createRecoveryAttempt(directory);
531
+ backup = createDurableFile(path.join(recovery.attempt.absolute, "original.previous"), baseline.bytes);
532
+ stage = createDurableFile(path.join(recovery.attempt.absolute, "replacement.tmp"), after, Number(baseline.identity.mode & 4095n));
533
+ metadata = createDurableFile(path.join(recovery.attempt.absolute, FILE_REPLACEMENT_METADATA_NAME), `${JSON.stringify({
534
+ schema_version: FILE_REPLACEMENT_RECOVERY_VERSION,
535
+ target_path: segments.join("/"),
536
+ before_sha256: sha256(baseline.bytes),
537
+ after_sha256: sha256(after),
538
+ })}\n`);
539
+ syncDirectory(recovery.attempt.absolute);
540
+ this.assertBoundary(directories, baseline, [backup, stage, metadata], verifyContext);
541
+ const boundaryTarget = readStableFile(target, `replacement target '${relativeTarget}'`);
542
+ if (!sameStableFile(boundaryTarget, baseline)) {
543
+ throw new ExactReplacementConflictError(`target '${relativeTarget}' changed at the final validation boundary; the detected change was preserved`);
544
+ }
545
+ try {
546
+ fs.renameSync(stage.absolute, target);
547
+ renameCompleted = true;
548
+ }
549
+ catch (error) {
550
+ throw new FileReplacementError(`complete-file replacement for '${relativeTarget}' failed before publication${error.code ? ` (${error.code})` : ""}`, error);
551
+ }
552
+ syncDirectory(directory);
553
+ syncDirectory(recovery.attempt.absolute);
554
+ const published = readStableFile(target, `published replacement '${relativeTarget}'`);
555
+ if (!published.bytes.equals(after)) {
556
+ throw new ExactReplacementConflictError(`target '${relativeTarget}' changed through the publication boundary`);
557
+ }
558
+ this.assertBoundary(directories, published, [backup, metadata], verifyContext);
559
+ committed = { previousBytes: baseline.bytes.toString("utf8"), publishedIdentity: publishedIdentity(published) };
560
+ this.cleanupCommittedReplacement(recovery.attempt.absolute, [backup, metadata]);
561
+ backup = undefined;
562
+ metadata = undefined;
563
+ stage = undefined;
564
+ return committed;
565
+ }
566
+ catch (error) {
567
+ if (committed)
568
+ return committed;
569
+ let current = null;
570
+ try {
571
+ current = readFileIfPresent(target, `replacement target '${relativeTarget}'`);
572
+ }
573
+ catch { /* Preserve all recovery evidence. */ }
574
+ if (!renameCompleted && error instanceof ExactReplacementConflictError) {
575
+ const retained = this.cleanupAttemptFiles([stage, backup, metadata]);
576
+ stage = undefined;
577
+ backup = undefined;
578
+ metadata = undefined;
579
+ if (retained.length) {
580
+ throw new ExactReplacementConflictError(`${error.message}; cleanup retained changed recovery roles`, retained);
581
+ }
582
+ throw error;
583
+ }
584
+ if (renameCompleted && current?.bytes.equals(after) && backup) {
585
+ try {
586
+ this.assertBoundary(directories, current, [backup], false);
587
+ fs.renameSync(backup.absolute, target);
588
+ backup = undefined;
589
+ syncDirectory(directory);
590
+ const restored = readStableFile(target, `restored replacement target '${relativeTarget}'`);
591
+ if (!restored.bytes.equals(baseline.bytes))
592
+ throw new Error("restored bytes do not match the exact baseline");
593
+ if (stage) {
594
+ try {
595
+ removeExactFile(stage);
596
+ }
597
+ catch { /* Preserve changed stage. */ }
598
+ stage = undefined;
599
+ }
600
+ if (metadata) {
601
+ try {
602
+ removeExactFile(metadata);
603
+ }
604
+ catch { /* Preserve changed metadata. */ }
605
+ metadata = undefined;
606
+ }
607
+ syncDirectoryBestEffort(recovery?.attempt.absolute ?? directory);
608
+ throw new FileReplacementError(`${error.message}; restored exact prior bytes at '${relativeTarget}'`, error);
609
+ }
610
+ catch (restoreError) {
611
+ if (restoreError instanceof FileReplacementError && restoreError.cause === error)
612
+ throw restoreError;
613
+ }
614
+ }
615
+ if (!renameCompleted && current && sameStableFile(current, baseline)) {
616
+ const retained = this.cleanupAttemptFiles([stage, backup, metadata]);
617
+ stage = undefined;
618
+ backup = undefined;
619
+ metadata = undefined;
620
+ if (retained.length) {
621
+ throw new ExactReplacementConflictError(`${error.message}; cleanup retained changed recovery roles`, retained);
622
+ }
623
+ if (error instanceof ExactReplacementConflictError || error instanceof FileReplacementError || error instanceof StateWriteInputError)
624
+ throw error;
625
+ throw new FileReplacementError(`${error.message}; target bytes remained unchanged`, error);
626
+ }
627
+ const retained = [backup, stage, metadata]
628
+ .filter((file) => Boolean(file && fs.existsSync(file.absolute)))
629
+ .map((file) => relativeDisplay(this.projectRoot, file.absolute));
630
+ throw new ExactReplacementConflictError(`${error.message}; recoverable publication did not report success and preserved the canonical target plus ${retained.length} bounded recovery role${retained.length === 1 ? "" : "s"}`, retained);
631
+ }
632
+ finally {
633
+ if (recovery)
634
+ this.closeRecoveryAttempt(recovery);
635
+ }
636
+ }
637
+ openDirectories(segments, create, missingIsAbsent = false, verifyContext = true) {
638
+ const directories = [];
639
+ let parent = this.projectRoot;
640
+ for (const segment of segments) {
641
+ if (verifyContext)
642
+ this.assertValid();
643
+ else
644
+ assertValidatedProjectRoot(this.validatedRoot);
645
+ const absolute = path.join(parent, segment);
646
+ let entry;
647
+ try {
648
+ entry = readStableDirectory(absolute);
649
+ }
650
+ catch (error) {
651
+ if (error.code === "ENOENT" || error.message.includes("ENOENT")) {
652
+ if (missingIsAbsent)
653
+ return null;
654
+ if (!create)
655
+ throw error;
656
+ this.assertBoundary(directories, undefined, [], verifyContext);
657
+ fs.mkdirSync(absolute, 0o700);
658
+ syncDirectory(parent);
659
+ entry = readStableDirectory(absolute, true);
660
+ }
661
+ else
662
+ throw error;
663
+ }
664
+ directories.push(entry);
665
+ parent = absolute;
666
+ }
667
+ return directories;
668
+ }
669
+ assertBoundary(directories, target, roles = [], verifyContext = true) {
670
+ if (verifyContext)
671
+ this.assertValid();
672
+ else
673
+ assertValidatedProjectRoot(this.validatedRoot);
674
+ for (const directory of directories) {
675
+ let current;
676
+ try {
677
+ current = fs.lstatSync(directory.absolute, { bigint: true });
678
+ }
679
+ catch {
680
+ throw new ExactReplacementConflictError(`publication directory '${relativeDisplay(this.projectRoot, directory.absolute)}' changed at a validation boundary`);
681
+ }
682
+ if (!sameDirectory(directory, current)) {
683
+ throw new ExactReplacementConflictError(`publication directory '${relativeDisplay(this.projectRoot, directory.absolute)}' changed at a validation boundary`);
684
+ }
685
+ }
686
+ if (target) {
687
+ const current = readFileIfPresent(target.absolute, `publication target '${relativeDisplay(this.projectRoot, target.absolute)}'`);
688
+ if (!current || !sameStableFile(target, current)) {
689
+ throw new ExactReplacementConflictError(`publication target '${relativeDisplay(this.projectRoot, target.absolute)}' changed at a validation boundary`);
690
+ }
691
+ }
692
+ for (const role of roles) {
693
+ const current = readFileIfPresent(role.absolute, `publication role '${relativeDisplay(this.projectRoot, role.absolute)}'`);
694
+ if (!current || !sameStableFile(role, current)) {
695
+ throw new ExactReplacementConflictError(`publication recovery role '${relativeDisplay(this.projectRoot, role.absolute)}' changed at a validation boundary`);
696
+ }
697
+ }
698
+ }
699
+ createRecoveryAttempt(targetDirectory) {
700
+ const agentera = readStableDirectory(path.join(this.projectRoot, ".agentera"));
701
+ const rootPath = path.join(agentera.absolute, ".entity-recovery");
702
+ let rootCreated = false;
703
+ let ignoreCreated = false;
704
+ let root;
705
+ let ignore;
706
+ let attempt;
707
+ try {
708
+ try {
709
+ root = readStableDirectory(rootPath);
710
+ }
711
+ catch (error) {
712
+ if (!error.message.includes("ENOENT")) {
713
+ throw new FileReplacementError(`private entity recovery root '.agentera/.entity-recovery' cannot be opened safely: ${error.message}`, error);
714
+ }
715
+ fs.mkdirSync(rootPath, 0o700);
716
+ rootCreated = true;
717
+ syncDirectory(agentera.absolute);
718
+ root = readStableDirectory(rootPath, true);
719
+ }
720
+ const trustedRoot = validateEntityRecoveryDirectory(this.validatedRoot, root.absolute, targetDirectory, "private entity recovery root '.agentera/.entity-recovery'", root);
721
+ root = { ...trustedRoot, created: rootCreated };
722
+ const ignorePath = path.join(root.absolute, ".gitignore");
723
+ const existingIgnore = readFileIfPresent(ignorePath, "private entity recovery ignore marker");
724
+ if (existingIgnore)
725
+ ignore = existingIgnore;
726
+ else {
727
+ ignore = createDurableFile(ignorePath, RECOVERY_IGNORE_BYTES);
728
+ ignoreCreated = true;
729
+ }
730
+ if (!ignore.bytes.equals(Buffer.from(RECOVERY_IGNORE_BYTES))) {
731
+ throw new FileReplacementError("private entity recovery ignore marker must contain the authoritative rules");
732
+ }
733
+ const ignoreStat = fs.lstatSync(ignore.absolute, { bigint: true });
734
+ if (typeof process.getuid === "function" && ((ignoreStat.mode & 18n) !== 0n || ignoreStat.uid !== BigInt(process.getuid()))) {
735
+ throw new FileReplacementError("private entity recovery ignore marker must be owner-controlled and not group/world-writable");
736
+ }
737
+ syncDirectory(root.absolute);
738
+ for (let index = 0; index < 8; index += 1) {
739
+ const attemptPath = path.join(root.absolute, `entity-${process.pid}-${randomUUID()}`);
740
+ try {
741
+ fs.mkdirSync(attemptPath, 0o700);
742
+ const opened = readStableDirectory(attemptPath, true);
743
+ attempt = opened;
744
+ const trusted = validateEntityRecoveryDirectory(this.validatedRoot, attemptPath, targetDirectory, `private entity recovery attempt '${relativeDisplay(this.projectRoot, attemptPath)}'`, opened);
745
+ attempt = { ...trusted, created: true };
746
+ break;
747
+ }
748
+ catch (error) {
749
+ if (error.code !== "EEXIST")
750
+ throw error;
751
+ }
752
+ }
753
+ if (!attempt)
754
+ throw new FileReplacementError("could not allocate a unique private entity recovery attempt after 8 tries");
755
+ syncDirectory(root.absolute);
756
+ return { root, attempt, ignore, relativePath: relativeDisplay(this.projectRoot, attempt.absolute) };
757
+ }
758
+ catch (error) {
759
+ if (attempt) {
760
+ try {
761
+ fs.rmdirSync(attempt.absolute);
762
+ }
763
+ catch { /* Preserve unexpected contents. */ }
764
+ }
765
+ if (ignore && ignoreCreated) {
766
+ try {
767
+ removeExactFile(ignore);
768
+ }
769
+ catch { /* Preserve changed marker. */ }
770
+ }
771
+ if (root && rootCreated) {
772
+ try {
773
+ fs.rmdirSync(root.absolute);
774
+ }
775
+ catch { /* Preserve non-empty root. */ }
776
+ }
777
+ throw error;
778
+ }
779
+ }
780
+ cleanupAttemptFiles(files) {
781
+ const retained = [];
782
+ for (const file of files) {
783
+ if (!file)
784
+ continue;
785
+ try {
786
+ if (!removeExactFile(file) && fs.existsSync(file.absolute))
787
+ retained.push(relativeDisplay(this.projectRoot, file.absolute));
788
+ }
789
+ catch {
790
+ retained.push(relativeDisplay(this.projectRoot, file.absolute));
791
+ }
792
+ }
793
+ return retained;
794
+ }
795
+ cleanupCommittedReplacement(directory, files) {
796
+ this.cleanupAttemptFiles(files);
797
+ syncDirectoryBestEffort(directory);
798
+ }
799
+ closeRecoveryAttempt(recovery) {
800
+ try {
801
+ fs.rmdirSync(recovery.attempt.absolute);
802
+ syncDirectoryBestEffort(recovery.root.absolute);
803
+ }
804
+ catch {
805
+ return;
806
+ }
807
+ try {
808
+ const names = fs.readdirSync(recovery.root.absolute);
809
+ if (names.length === 1 && names[0] === ".gitignore") {
810
+ removeExactFile(recovery.ignore);
811
+ syncDirectoryBestEffort(recovery.root.absolute);
812
+ }
813
+ if (fs.readdirSync(recovery.root.absolute).length === 0) {
814
+ fs.rmdirSync(recovery.root.absolute);
815
+ syncDirectoryBestEffort(path.dirname(recovery.root.absolute));
816
+ }
817
+ }
818
+ catch { /* Preserve non-empty or changed recovery authority. */ }
819
+ }
820
+ removeCreatedDirectories(directories) {
821
+ for (const directory of [...directories].reverse()) {
822
+ if (!directory.created)
823
+ continue;
824
+ try {
825
+ const current = fs.lstatSync(directory.absolute, { bigint: true });
826
+ if (!sameDirectory(directory, current))
827
+ continue;
828
+ fs.rmdirSync(directory.absolute);
829
+ syncDirectoryBestEffort(path.dirname(directory.absolute));
830
+ }
831
+ catch (error) {
832
+ if (!["ENOTEMPTY", "EEXIST", "ENOENT"].includes(error.code ?? ""))
833
+ throw error;
834
+ }
835
+ }
836
+ }
837
+ removeAttemptDirectories() {
838
+ const paths = [...this.createdDirectories].sort((left, right) => right[0].split("/").length - left[0].split("/").length);
839
+ for (const [relativePath, expected] of paths) {
840
+ try {
841
+ const current = fs.lstatSync(expected.absolute, { bigint: true });
842
+ if (!sameDirectory(expected, current)) {
843
+ this.createdDirectories.delete(relativePath);
844
+ continue;
845
+ }
846
+ fs.rmdirSync(expected.absolute);
847
+ syncDirectoryBestEffort(path.dirname(expected.absolute));
848
+ this.createdDirectories.delete(relativePath);
849
+ }
850
+ catch (error) {
851
+ const code = error.code ?? "";
852
+ if (code === "ENOENT")
853
+ this.createdDirectories.delete(relativePath);
854
+ else if (!["ENOTEMPTY", "EEXIST"].includes(code))
855
+ throw error;
856
+ }
857
+ }
858
+ }
859
+ }