@latysh-development/monolith 0.0.0-stage → 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (345) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +179 -2
  3. package/dist/brief/cli.d.ts +30 -0
  4. package/dist/brief/cli.d.ts.map +1 -0
  5. package/dist/brief/cli.js +85 -0
  6. package/dist/brief/collect.d.ts +17 -0
  7. package/dist/brief/collect.d.ts.map +1 -0
  8. package/dist/brief/collect.js +342 -0
  9. package/dist/brief/config.d.ts +40 -0
  10. package/dist/brief/config.d.ts.map +1 -0
  11. package/dist/brief/config.js +85 -0
  12. package/dist/brief/constants.d.ts +12 -0
  13. package/dist/brief/constants.d.ts.map +1 -0
  14. package/dist/brief/constants.js +11 -0
  15. package/dist/brief/docs.d.ts +53 -0
  16. package/dist/brief/docs.d.ts.map +1 -0
  17. package/dist/brief/docs.js +229 -0
  18. package/dist/brief/freshness.d.ts +104 -0
  19. package/dist/brief/freshness.d.ts.map +1 -0
  20. package/dist/brief/freshness.js +263 -0
  21. package/dist/brief/git-signals.d.ts +17 -0
  22. package/dist/brief/git-signals.d.ts.map +1 -0
  23. package/dist/brief/git-signals.js +101 -0
  24. package/dist/brief/index.d.ts +11 -0
  25. package/dist/brief/index.d.ts.map +1 -0
  26. package/dist/brief/index.js +5 -0
  27. package/dist/brief/reconcile.d.ts +75 -0
  28. package/dist/brief/reconcile.d.ts.map +1 -0
  29. package/dist/brief/reconcile.js +259 -0
  30. package/dist/brief/render.d.ts +67 -0
  31. package/dist/brief/render.d.ts.map +1 -0
  32. package/dist/brief/render.js +458 -0
  33. package/dist/brief/sanitize.d.ts +38 -0
  34. package/dist/brief/sanitize.d.ts.map +1 -0
  35. package/dist/brief/sanitize.js +48 -0
  36. package/dist/brief/selectors.d.ts +36 -0
  37. package/dist/brief/selectors.d.ts.map +1 -0
  38. package/dist/brief/selectors.js +75 -0
  39. package/dist/brief/story.d.ts +18 -0
  40. package/dist/brief/story.d.ts.map +1 -0
  41. package/dist/brief/story.js +59 -0
  42. package/dist/brief/types.d.ts +126 -0
  43. package/dist/brief/types.d.ts.map +1 -0
  44. package/dist/brief/types.js +11 -0
  45. package/dist/cli/index.d.ts +3 -0
  46. package/dist/cli/index.d.ts.map +1 -0
  47. package/dist/cli/index.js +199 -0
  48. package/dist/cli/init-args.d.ts +16 -0
  49. package/dist/cli/init-args.d.ts.map +1 -0
  50. package/dist/cli/init-args.js +24 -0
  51. package/dist/cli/ui-args.d.ts +23 -0
  52. package/dist/cli/ui-args.d.ts.map +1 -0
  53. package/dist/cli/ui-args.js +66 -0
  54. package/dist/cli/ui.d.ts +40 -0
  55. package/dist/cli/ui.d.ts.map +1 -0
  56. package/dist/cli/ui.js +180 -0
  57. package/dist/coordinatorium/checkpoint.d.ts +44 -0
  58. package/dist/coordinatorium/checkpoint.d.ts.map +1 -0
  59. package/dist/coordinatorium/checkpoint.js +124 -0
  60. package/dist/coordinatorium/cli.d.ts +39 -0
  61. package/dist/coordinatorium/cli.d.ts.map +1 -0
  62. package/dist/coordinatorium/cli.js +203 -0
  63. package/dist/coordinatorium/errors.d.ts +112 -0
  64. package/dist/coordinatorium/errors.d.ts.map +1 -0
  65. package/dist/coordinatorium/errors.js +145 -0
  66. package/dist/coordinatorium/index.d.ts +11 -0
  67. package/dist/coordinatorium/index.d.ts.map +1 -0
  68. package/dist/coordinatorium/index.js +5 -0
  69. package/dist/coordinatorium/lock.d.ts +187 -0
  70. package/dist/coordinatorium/lock.d.ts.map +1 -0
  71. package/dist/coordinatorium/lock.js +659 -0
  72. package/dist/coordinatorium/mission.d.ts +32 -0
  73. package/dist/coordinatorium/mission.d.ts.map +1 -0
  74. package/dist/coordinatorium/mission.js +87 -0
  75. package/dist/coordinatorium/state-keeper.d.ts +115 -0
  76. package/dist/coordinatorium/state-keeper.d.ts.map +1 -0
  77. package/dist/coordinatorium/state-keeper.js +396 -0
  78. package/dist/coordinatorium/types.d.ts +69 -0
  79. package/dist/coordinatorium/types.d.ts.map +1 -0
  80. package/dist/coordinatorium/types.js +27 -0
  81. package/dist/discovery/compose.d.ts +28 -0
  82. package/dist/discovery/compose.d.ts.map +1 -0
  83. package/dist/discovery/compose.js +159 -0
  84. package/dist/discovery/contracts.d.ts +211 -0
  85. package/dist/discovery/contracts.d.ts.map +1 -0
  86. package/dist/discovery/contracts.js +555 -0
  87. package/dist/discovery/docs.d.ts +278 -0
  88. package/dist/discovery/docs.d.ts.map +1 -0
  89. package/dist/discovery/docs.js +1182 -0
  90. package/dist/discovery/facts.d.ts +49 -0
  91. package/dist/discovery/facts.d.ts.map +1 -0
  92. package/dist/discovery/facts.js +541 -0
  93. package/dist/discovery/index.d.ts +8 -0
  94. package/dist/discovery/index.d.ts.map +1 -0
  95. package/dist/discovery/index.js +9 -0
  96. package/dist/discovery/orchestrate.d.ts +35 -0
  97. package/dist/discovery/orchestrate.d.ts.map +1 -0
  98. package/dist/discovery/orchestrate.js +32 -0
  99. package/dist/discovery/render.d.ts +36 -0
  100. package/dist/discovery/render.d.ts.map +1 -0
  101. package/dist/discovery/render.js +278 -0
  102. package/dist/discovery/traverse.d.ts +197 -0
  103. package/dist/discovery/traverse.d.ts.map +1 -0
  104. package/dist/discovery/traverse.js +510 -0
  105. package/dist/durable/assess.d.ts +105 -0
  106. package/dist/durable/assess.d.ts.map +1 -0
  107. package/dist/durable/assess.js +239 -0
  108. package/dist/durable/canonical.d.ts +25 -0
  109. package/dist/durable/canonical.d.ts.map +1 -0
  110. package/dist/durable/canonical.js +78 -0
  111. package/dist/durable/cli.d.ts +37 -0
  112. package/dist/durable/cli.d.ts.map +1 -0
  113. package/dist/durable/cli.js +141 -0
  114. package/dist/durable/errors.d.ts +192 -0
  115. package/dist/durable/errors.d.ts.map +1 -0
  116. package/dist/durable/errors.js +323 -0
  117. package/dist/durable/fs-store.d.ts +254 -0
  118. package/dist/durable/fs-store.d.ts.map +1 -0
  119. package/dist/durable/fs-store.js +1493 -0
  120. package/dist/durable/index.d.ts +20 -0
  121. package/dist/durable/index.d.ts.map +1 -0
  122. package/dist/durable/index.js +13 -0
  123. package/dist/durable/log.d.ts +33 -0
  124. package/dist/durable/log.d.ts.map +1 -0
  125. package/dist/durable/log.js +157 -0
  126. package/dist/durable/memory-store.d.ts +51 -0
  127. package/dist/durable/memory-store.d.ts.map +1 -0
  128. package/dist/durable/memory-store.js +302 -0
  129. package/dist/durable/projection.d.ts +35 -0
  130. package/dist/durable/projection.d.ts.map +1 -0
  131. package/dist/durable/projection.js +328 -0
  132. package/dist/durable/prune-check.d.ts +34 -0
  133. package/dist/durable/prune-check.d.ts.map +1 -0
  134. package/dist/durable/prune-check.js +72 -0
  135. package/dist/durable/register.d.ts +100 -0
  136. package/dist/durable/register.d.ts.map +1 -0
  137. package/dist/durable/register.js +532 -0
  138. package/dist/durable/retention.d.ts +49 -0
  139. package/dist/durable/retention.d.ts.map +1 -0
  140. package/dist/durable/retention.js +59 -0
  141. package/dist/durable/runtime.d.ts +499 -0
  142. package/dist/durable/runtime.d.ts.map +1 -0
  143. package/dist/durable/runtime.js +1288 -0
  144. package/dist/durable/seams.d.ts +44 -0
  145. package/dist/durable/seams.d.ts.map +1 -0
  146. package/dist/durable/seams.js +21 -0
  147. package/dist/durable/testing.d.ts +11 -0
  148. package/dist/durable/testing.d.ts.map +1 -0
  149. package/dist/durable/testing.js +25 -0
  150. package/dist/durable/types.d.ts +442 -0
  151. package/dist/durable/types.d.ts.map +1 -0
  152. package/dist/durable/types.js +75 -0
  153. package/dist/graph/builder.d.ts +11 -0
  154. package/dist/graph/builder.d.ts.map +1 -0
  155. package/dist/graph/builder.js +153 -0
  156. package/dist/graph/identity.d.ts +37 -0
  157. package/dist/graph/identity.d.ts.map +1 -0
  158. package/dist/graph/identity.js +46 -0
  159. package/dist/graph/index.d.ts +7 -0
  160. package/dist/graph/index.d.ts.map +1 -0
  161. package/dist/graph/index.js +3 -0
  162. package/dist/graph/resolver.d.ts +41 -0
  163. package/dist/graph/resolver.d.ts.map +1 -0
  164. package/dist/graph/resolver.js +36 -0
  165. package/dist/graph/types.d.ts +42 -0
  166. package/dist/graph/types.d.ts.map +1 -0
  167. package/dist/graph/types.js +1 -0
  168. package/dist/http/index.d.ts +5 -0
  169. package/dist/http/index.d.ts.map +1 -0
  170. package/dist/http/index.js +2 -0
  171. package/dist/http/server.d.ts +76 -0
  172. package/dist/http/server.d.ts.map +1 -0
  173. package/dist/http/server.js +195 -0
  174. package/dist/http/ui-assets.d.ts +22 -0
  175. package/dist/http/ui-assets.d.ts.map +1 -0
  176. package/dist/http/ui-assets.js +100 -0
  177. package/dist/ideas/cli.d.ts +33 -0
  178. package/dist/ideas/cli.d.ts.map +1 -0
  179. package/dist/ideas/cli.js +158 -0
  180. package/dist/ideas/format.d.ts +38 -0
  181. package/dist/ideas/format.d.ts.map +1 -0
  182. package/dist/ideas/format.js +194 -0
  183. package/dist/ideas/index.d.ts +6 -0
  184. package/dist/ideas/index.d.ts.map +1 -0
  185. package/dist/ideas/index.js +3 -0
  186. package/dist/ideas/store.d.ts +55 -0
  187. package/dist/ideas/store.d.ts.map +1 -0
  188. package/dist/ideas/store.js +262 -0
  189. package/dist/ideas/types.d.ts +54 -0
  190. package/dist/ideas/types.d.ts.map +1 -0
  191. package/dist/ideas/types.js +26 -0
  192. package/dist/index.d.ts +32 -0
  193. package/dist/index.d.ts.map +1 -0
  194. package/dist/index.js +28 -0
  195. package/dist/init/index.d.ts +12 -0
  196. package/dist/init/index.d.ts.map +1 -0
  197. package/dist/init/index.js +90 -0
  198. package/dist/init/prompts.d.ts +3 -0
  199. package/dist/init/prompts.d.ts.map +1 -0
  200. package/dist/init/prompts.js +47 -0
  201. package/dist/init/scaffold.d.ts +29 -0
  202. package/dist/init/scaffold.d.ts.map +1 -0
  203. package/dist/init/scaffold.js +208 -0
  204. package/dist/init/types.d.ts +14 -0
  205. package/dist/init/types.d.ts.map +1 -0
  206. package/dist/init/types.js +1 -0
  207. package/dist/managed/index.d.ts +73 -0
  208. package/dist/managed/index.d.ts.map +1 -0
  209. package/dist/managed/index.js +222 -0
  210. package/dist/readmodel/dashboard.d.ts +40 -0
  211. package/dist/readmodel/dashboard.d.ts.map +1 -0
  212. package/dist/readmodel/dashboard.js +236 -0
  213. package/dist/readmodel/index.d.ts +3 -0
  214. package/dist/readmodel/index.d.ts.map +1 -0
  215. package/dist/readmodel/index.js +1 -0
  216. package/dist/readmodel/types.d.ts +104 -0
  217. package/dist/readmodel/types.d.ts.map +1 -0
  218. package/dist/readmodel/types.js +15 -0
  219. package/dist/root/index.d.ts +186 -0
  220. package/dist/root/index.d.ts.map +1 -0
  221. package/dist/root/index.js +430 -0
  222. package/dist/root/safe-write.d.ts +268 -0
  223. package/dist/root/safe-write.d.ts.map +1 -0
  224. package/dist/root/safe-write.js +966 -0
  225. package/dist/root/write-artifacts.d.ts +20 -0
  226. package/dist/root/write-artifacts.d.ts.map +1 -0
  227. package/dist/root/write-artifacts.js +42 -0
  228. package/dist/scriptorium/compile.d.ts +4 -0
  229. package/dist/scriptorium/compile.d.ts.map +1 -0
  230. package/dist/scriptorium/compile.js +185 -0
  231. package/dist/scriptorium/frontmatter.d.ts +13 -0
  232. package/dist/scriptorium/frontmatter.d.ts.map +1 -0
  233. package/dist/scriptorium/frontmatter.js +90 -0
  234. package/dist/scriptorium/index.d.ts +3 -0
  235. package/dist/scriptorium/index.d.ts.map +1 -0
  236. package/dist/scriptorium/index.js +1 -0
  237. package/dist/scriptorium/markdown.d.ts +31 -0
  238. package/dist/scriptorium/markdown.d.ts.map +1 -0
  239. package/dist/scriptorium/markdown.js +88 -0
  240. package/dist/scriptorium/types.d.ts +78 -0
  241. package/dist/scriptorium/types.d.ts.map +1 -0
  242. package/dist/scriptorium/types.js +1 -0
  243. package/dist/types/enforcement.d.ts +11 -0
  244. package/dist/types/enforcement.d.ts.map +1 -0
  245. package/dist/types/enforcement.js +1 -0
  246. package/dist/types/integrity.d.ts +33 -0
  247. package/dist/types/integrity.d.ts.map +1 -0
  248. package/dist/types/integrity.js +1 -0
  249. package/dist/types/project-definition.d.ts +30 -0
  250. package/dist/types/project-definition.d.ts.map +1 -0
  251. package/dist/types/project-definition.js +1 -0
  252. package/dist/ui/assets/cosmic-glass-bg-Dwx47zPu.webp +0 -0
  253. package/dist/ui/assets/index-C4NhMaq7.js +28 -0
  254. package/dist/ui/assets/index-DMZ7ZvZY.css +1 -0
  255. package/dist/ui/index.html +13 -0
  256. package/dist/update/cli.d.ts +8 -0
  257. package/dist/update/cli.d.ts.map +1 -0
  258. package/dist/update/cli.js +115 -0
  259. package/dist/update/index.d.ts +78 -0
  260. package/dist/update/index.d.ts.map +1 -0
  261. package/dist/update/index.js +285 -0
  262. package/dist/validate/index.d.ts +6 -0
  263. package/dist/validate/index.d.ts.map +1 -0
  264. package/dist/validate/index.js +214 -0
  265. package/dist/version.d.ts +2 -0
  266. package/dist/version.d.ts.map +1 -0
  267. package/dist/version.js +1 -0
  268. package/package.json +67 -4
  269. package/templates/.gitkeep +0 -0
  270. package/templates/default-instance/instruction/.cursorrules +59 -0
  271. package/templates/default-instance/instruction/.windsurfrules +59 -0
  272. package/templates/default-instance/instruction/CLAUDE.md +57 -0
  273. package/templates/default-instance/managed/agent.md +20 -0
  274. package/templates/default-instance/managed/bootstrap.md +7 -0
  275. package/templates/default-instance/managed/index-idea.md +5 -0
  276. package/templates/default-instance/managed/routing-idea.md +14 -0
  277. package/templates/default-instance/monolith/AGENT.md +1 -0
  278. package/templates/default-instance/monolith/context/boot/HANDOFF.md +49 -0
  279. package/templates/default-instance/monolith/context/boot/WORK_SESSION.md +30 -0
  280. package/templates/default-instance/monolith/context/execution/current-state.md +30 -0
  281. package/templates/default-instance/monolith/context/maps/dependency-map.md +38 -0
  282. package/templates/default-instance/monolith/context/maps/project-map.md +85 -0
  283. package/templates/default-instance/monolith/context/maps/roadmap-index.md +41 -0
  284. package/templates/default-instance/monolith/context/maps/routing-map.md +151 -0
  285. package/templates/default-instance/monolith/context/maps/semantic-map.md +75 -0
  286. package/templates/default-instance/monolith/context/models/model-registry.md +37 -0
  287. package/templates/default-instance/monolith/context/models/privacy-classification.md +35 -0
  288. package/templates/default-instance/monolith/context/templates/plan-template.md +56 -0
  289. package/templates/default-instance/monolith/governance/README.md +29 -0
  290. package/templates/default-instance/monolith/governance/RULE_SCHEMA.md +58 -0
  291. package/templates/default-instance/monolith/learning/INDEX.md +48 -0
  292. package/templates/default-instance/monolith/learning/injection-map.md +49 -0
  293. package/templates/default-instance/monolith/learning/taxonomy.md +30 -0
  294. package/templates/default-instance/monolith/memory/errors/README.md +26 -0
  295. package/templates/default-instance/monolith/memory/errors/SCHEMA.md +47 -0
  296. package/templates/default-instance/monolith/memory/errors/TAXONOMY.md +27 -0
  297. package/templates/default-instance/monolith/memory/long-term/architecture-principles.md +31 -0
  298. package/templates/default-instance/monolith/memory/long-term/decisions.md +36 -0
  299. package/templates/default-instance/monolith/memory/long-term/execution-history.md +20 -0
  300. package/templates/default-instance/monolith/memory/long-term/tech-debt.md +25 -0
  301. package/templates/default-instance/monolith/memory/working/active.md +41 -0
  302. package/templates/default-instance/monolith/memory/working/governance-result.md +0 -0
  303. package/templates/default-instance/monolith/memory/working/integrity-result.md +0 -0
  304. package/templates/default-instance/monolith/memory/working/story-index.md +28 -0
  305. package/templates/default-instance/monolith/protocols/boot/boot-sequence.md +59 -0
  306. package/templates/default-instance/monolith/protocols/cognition/cognitive-modes.md +90 -0
  307. package/templates/default-instance/monolith/protocols/cognition/dry-run.md +56 -0
  308. package/templates/default-instance/monolith/protocols/cognition/execution-trace-format.md +52 -0
  309. package/templates/default-instance/monolith/protocols/cognition/semantic-planning.md +51 -0
  310. package/templates/default-instance/monolith/protocols/execution/hybrid-execution.md +37 -0
  311. package/templates/default-instance/monolith/protocols/execution/local-llm-governance.md +42 -0
  312. package/templates/default-instance/monolith/protocols/governance/command-policy.md +51 -0
  313. package/templates/default-instance/monolith/protocols/governance/core-invariants.md +40 -0
  314. package/templates/default-instance/monolith/protocols/governance/memory-governance.md +54 -0
  315. package/templates/default-instance/monolith/protocols/governance/metadata-schema.md +62 -0
  316. package/templates/default-instance/monolith/protocols/governance/skills.md +53 -0
  317. package/templates/default-instance/monolith/protocols/governance/work-session.md +46 -0
  318. package/templates/default-instance/monolith/skills/INDEX.md +32 -0
  319. package/templates/default-instance/monolith/skills/current-status/SKILL.md +47 -0
  320. package/templates/default-instance/monolith/skills/finalize-story/SKILL.md +86 -0
  321. package/templates/default-instance/monolith/skills/global-status/SKILL.md +56 -0
  322. package/templates/default-instance/monolith/skills/idea-capture/SKILL.md +157 -0
  323. package/templates/default-instance/monolith/skills/self-improvement/SKILL.md +77 -0
  324. package/templates/default-instance/monolith/state.json +11 -0
  325. package/templates/default-instance/monolith/tests/INDEX.md +57 -0
  326. package/templates/default-instance/monolith/tests/scenarios/architecture-review.md +32 -0
  327. package/templates/default-instance/monolith/tests/scenarios/debug-failure.md +32 -0
  328. package/templates/default-instance/monolith/tests/scenarios/dry-run-activation.md +33 -0
  329. package/templates/default-instance/monolith/tests/scenarios/execution-trace-verification.md +31 -0
  330. package/templates/default-instance/monolith/tests/scenarios/finalize-story.md +35 -0
  331. package/templates/default-instance/monolith/tests/scenarios/implement-feature.md +36 -0
  332. package/templates/default-instance/monolith/tests/scenarios/local-llm-delegation.md +31 -0
  333. package/templates/default-instance/monolith/tests/scenarios/planning-request.md +32 -0
  334. package/templates/default-instance/monolith/tests/scenarios/sensitive-context-task.md +30 -0
  335. package/templates/default-instance/monolith/tests/scenarios/validator-verification.md +33 -0
  336. package/templates/default-instance/monolith/tests/validation/expected-behavior.md +70 -0
  337. package/templates/default-instance/monolith/tests/validators/INDEX.md +17 -0
  338. package/templates/default-instance/monolith/tests/validators/delegation-semantics.md +22 -0
  339. package/templates/default-instance/monolith/tests/validators/mode-consistency.md +25 -0
  340. package/templates/default-instance/monolith/tests/validators/privacy-routing.md +23 -0
  341. package/templates/default-instance/monolith/tests/validators/protocol-references.md +27 -0
  342. package/templates/default-instance/monolith/tests/validators/routing-integrity.md +30 -0
  343. package/templates/default-instance/projectroot/AGENTS.md +111 -0
  344. package/templates/default-instance/projectroot/monolith.config.json +32 -0
  345. package/templates/default-instance/projectroot/project.definition.mjs.template +41 -0
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Error taxonomy for the Coordinatorium State Keeper.
3
+ *
4
+ * Every error the state keeper or mission layer can throw is one of these.
5
+ * The CLI maps all of them to a non-zero exit code; `code` exists so a
6
+ * future caller (or a test) can distinguish failure classes without
7
+ * string-matching messages.
8
+ */
9
+ import type { ProjectFileErrorCode } from '../root/index.js';
10
+ export type CoordinatoriumErrorCode = 'STATE_CORRUPTED' | 'STATE_SCHEMA_INVALID' | 'LOCK_TIMEOUT' | 'LOCK_CREATION_FAILED' | 'LOCK_UNSAFE' | 'STATE_FILE_UNSAFE' | 'MISSION_NOT_FOUND' | 'INVALID_TRANSITION' | 'VALIDATION_ERROR' | 'MISSION_NOT_ACTIVE' | 'CHECKPOINT_NOT_FOUND';
11
+ export declare class CoordinatoriumError extends Error {
12
+ readonly code: CoordinatoriumErrorCode;
13
+ constructor(code: CoordinatoriumErrorCode, message: string);
14
+ }
15
+ export declare class StateCorruptedError extends CoordinatoriumError {
16
+ constructor(message: string);
17
+ }
18
+ export declare class StateSchemaError extends CoordinatoriumError {
19
+ constructor(message: string);
20
+ }
21
+ /**
22
+ * Thrown when `state.json` cannot be read or written within the bounded-file
23
+ * contract (SEC-001B.1): a FIFO or other special file, a file over its size
24
+ * limit (`FILE_TOO_LARGE`, also raised before a write would produce an
25
+ * oversized file), or an unreadable file. `fileCode` is the machine-readable
26
+ * reason. Nothing is modified, truncated or compacted when this is thrown.
27
+ */
28
+ export declare class StateFileError extends CoordinatoriumError {
29
+ readonly fileCode: ProjectFileErrorCode;
30
+ constructor(fileCode: ProjectFileErrorCode, detail: string);
31
+ }
32
+ /**
33
+ * Thrown when the lock file exists but cannot be safely inspected (a FIFO or
34
+ * other special file, over the lock size limit, or unreadable). The lock is
35
+ * NOT acquired, and the file is never deleted: a human has to look at it.
36
+ */
37
+ export declare class LockUnsafeError extends CoordinatoriumError {
38
+ readonly fileCode: ProjectFileErrorCode;
39
+ constructor(lockPath: string, fileCode: ProjectFileErrorCode, detail: string);
40
+ }
41
+ export declare class LockTimeoutError extends CoordinatoriumError {
42
+ /** The last failure that prevented acquisition (e.g. a stale-lock `unlink`
43
+ * error), kept so a timeout never hides why the lock could not be taken.
44
+ * Also set as the standard `cause`. */
45
+ readonly lastFailure?: unknown;
46
+ constructor(message: string, options?: {
47
+ lastFailure?: unknown;
48
+ });
49
+ }
50
+ /**
51
+ * The phase of the create/publish protocol (`lock.ts`'s `createAndPublish`)
52
+ * that failed. `staging-cleanup` is reported only via `cleanedUp: false` on
53
+ * whichever phase actually failed (cleanup is always best-effort and never
54
+ * itself the primary reason for a throw); it is listed here so the taxonomy
55
+ * names every step of the protocol, not because it is a distinct throw site.
56
+ */
57
+ export type LockCreationPhase = 'staging-open' | 'metadata-write' | 'metadata-fsync' | 'publish-link' | 'staging-cleanup';
58
+ export interface LockCreationErrorParams {
59
+ lockPath: string;
60
+ phase: LockCreationPhase;
61
+ pid: number;
62
+ nonce: string;
63
+ /** Whether this process's own staging file was successfully removed
64
+ * (or was already gone) after the failure. */
65
+ cleanedUp: boolean;
66
+ /** The original fs error (e.g. ENOSPC/EIO), or whatever else was thrown. */
67
+ cause: unknown;
68
+ /** `UNKNOWN`: the publish step may or may not have created the lock (SEC-001B.2).
69
+ * Default `NOT_PUBLISHED`. */
70
+ publication?: 'NOT_PUBLISHED' | 'UNKNOWN';
71
+ }
72
+ /**
73
+ * Thrown when a lock (the primary `state.json.lock` or the internal
74
+ * recovery mutex) could not be created — a staging-file open, metadata
75
+ * write/fsync, or publish-link step failed. Never thrown for ordinary lock
76
+ * contention (an already-existing canonical lock is not a failure, just a
77
+ * reason to wait). The original fs error is preserved as `cause`/`causeCode`,
78
+ * never masked.
79
+ */
80
+ export declare class LockCreationError extends CoordinatoriumError {
81
+ readonly lockPath: string;
82
+ readonly phase: LockCreationPhase;
83
+ readonly pid: number;
84
+ readonly nonce: string;
85
+ readonly timestamp: string;
86
+ readonly cleanedUp: boolean;
87
+ readonly publication: 'NOT_PUBLISHED' | 'UNKNOWN';
88
+ readonly cause: unknown;
89
+ readonly causeCode: string | undefined;
90
+ constructor(params: LockCreationErrorParams);
91
+ }
92
+ export declare class MissionNotFoundError extends CoordinatoriumError {
93
+ constructor(id: string);
94
+ }
95
+ export declare class InvalidTransitionError extends CoordinatoriumError {
96
+ constructor(message: string);
97
+ }
98
+ export declare class ValidationError extends CoordinatoriumError {
99
+ constructor(message: string);
100
+ }
101
+ /**
102
+ * Thrown when a checkpoint is requested to be created against a mission
103
+ * that exists but is not `in_progress` (COORDINATORIUM-002). Reading
104
+ * checkpoints for such a mission is unaffected — only creation is blocked.
105
+ */
106
+ export declare class MissionNotActiveError extends CoordinatoriumError {
107
+ constructor(id: string, status: string);
108
+ }
109
+ export declare class CheckpointNotFoundError extends CoordinatoriumError {
110
+ constructor(id: string);
111
+ }
112
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/coordinatorium/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Error taxonomy for the Coordinatorium State Keeper.
3
+ *
4
+ * Every error the state keeper or mission layer can throw is one of these.
5
+ * The CLI maps all of them to a non-zero exit code; `code` exists so a
6
+ * future caller (or a test) can distinguish failure classes without
7
+ * string-matching messages.
8
+ */
9
+ export class CoordinatoriumError extends Error {
10
+ code;
11
+ constructor(code, message) {
12
+ super(message);
13
+ this.name = 'CoordinatoriumError';
14
+ this.code = code;
15
+ }
16
+ }
17
+ export class StateCorruptedError extends CoordinatoriumError {
18
+ constructor(message) {
19
+ super('STATE_CORRUPTED', message);
20
+ this.name = 'StateCorruptedError';
21
+ }
22
+ }
23
+ export class StateSchemaError extends CoordinatoriumError {
24
+ constructor(message) {
25
+ super('STATE_SCHEMA_INVALID', message);
26
+ this.name = 'StateSchemaError';
27
+ }
28
+ }
29
+ /**
30
+ * Thrown when `state.json` cannot be read or written within the bounded-file
31
+ * contract (SEC-001B.1): a FIFO or other special file, a file over its size
32
+ * limit (`FILE_TOO_LARGE`, also raised before a write would produce an
33
+ * oversized file), or an unreadable file. `fileCode` is the machine-readable
34
+ * reason. Nothing is modified, truncated or compacted when this is thrown.
35
+ */
36
+ export class StateFileError extends CoordinatoriumError {
37
+ fileCode;
38
+ constructor(fileCode, detail) {
39
+ super('STATE_FILE_UNSAFE', `${fileCode}: ${detail}`);
40
+ this.name = 'StateFileError';
41
+ this.fileCode = fileCode;
42
+ }
43
+ }
44
+ /**
45
+ * Thrown when the lock file exists but cannot be safely inspected (a FIFO or
46
+ * other special file, over the lock size limit, or unreadable). The lock is
47
+ * NOT acquired, and the file is never deleted: a human has to look at it.
48
+ */
49
+ export class LockUnsafeError extends CoordinatoriumError {
50
+ fileCode;
51
+ constructor(lockPath, fileCode, detail) {
52
+ super('LOCK_UNSAFE', `Lock at "${lockPath}" cannot be safely read (${fileCode}): ${detail}`);
53
+ this.name = 'LockUnsafeError';
54
+ this.fileCode = fileCode;
55
+ }
56
+ }
57
+ export class LockTimeoutError extends CoordinatoriumError {
58
+ /** The last failure that prevented acquisition (e.g. a stale-lock `unlink`
59
+ * error), kept so a timeout never hides why the lock could not be taken.
60
+ * Also set as the standard `cause`. */
61
+ lastFailure;
62
+ constructor(message, options = {}) {
63
+ super('LOCK_TIMEOUT', message);
64
+ this.name = 'LockTimeoutError';
65
+ if (options.lastFailure !== undefined) {
66
+ this.lastFailure = options.lastFailure;
67
+ this.cause = options.lastFailure;
68
+ }
69
+ }
70
+ }
71
+ /**
72
+ * Thrown when a lock (the primary `state.json.lock` or the internal
73
+ * recovery mutex) could not be created — a staging-file open, metadata
74
+ * write/fsync, or publish-link step failed. Never thrown for ordinary lock
75
+ * contention (an already-existing canonical lock is not a failure, just a
76
+ * reason to wait). The original fs error is preserved as `cause`/`causeCode`,
77
+ * never masked.
78
+ */
79
+ export class LockCreationError extends CoordinatoriumError {
80
+ lockPath;
81
+ phase;
82
+ pid;
83
+ nonce;
84
+ timestamp;
85
+ cleanedUp;
86
+ publication;
87
+ cause;
88
+ causeCode;
89
+ constructor(params) {
90
+ const causeCode = params.cause?.code;
91
+ const causeMessage = params.cause instanceof Error ? params.cause.message : String(params.cause);
92
+ const timestamp = new Date().toISOString();
93
+ super('LOCK_CREATION_FAILED', `Failed to create lock at "${params.lockPath}" (phase: ${params.phase}` +
94
+ `${causeCode ? `, cause: ${causeCode}` : ''}): ${causeMessage} ` +
95
+ `[pid=${params.pid} nonce=${params.nonce} at=${timestamp} cleanedUp=${params.cleanedUp}]` +
96
+ (params.publication === 'UNKNOWN'
97
+ ? ` Whether the lock was created is UNKNOWN: inspect "${params.lockPath}" before retrying; nothing was retried or removed.`
98
+ : ''));
99
+ this.name = 'LockCreationError';
100
+ this.lockPath = params.lockPath;
101
+ this.phase = params.phase;
102
+ this.pid = params.pid;
103
+ this.nonce = params.nonce;
104
+ this.timestamp = timestamp;
105
+ this.cleanedUp = params.cleanedUp;
106
+ this.publication = params.publication ?? 'NOT_PUBLISHED';
107
+ this.cause = params.cause;
108
+ this.causeCode = causeCode;
109
+ }
110
+ }
111
+ export class MissionNotFoundError extends CoordinatoriumError {
112
+ constructor(id) {
113
+ super('MISSION_NOT_FOUND', `No mission found with id "${id}"`);
114
+ this.name = 'MissionNotFoundError';
115
+ }
116
+ }
117
+ export class InvalidTransitionError extends CoordinatoriumError {
118
+ constructor(message) {
119
+ super('INVALID_TRANSITION', message);
120
+ this.name = 'InvalidTransitionError';
121
+ }
122
+ }
123
+ export class ValidationError extends CoordinatoriumError {
124
+ constructor(message) {
125
+ super('VALIDATION_ERROR', message);
126
+ this.name = 'ValidationError';
127
+ }
128
+ }
129
+ /**
130
+ * Thrown when a checkpoint is requested to be created against a mission
131
+ * that exists but is not `in_progress` (COORDINATORIUM-002). Reading
132
+ * checkpoints for such a mission is unaffected — only creation is blocked.
133
+ */
134
+ export class MissionNotActiveError extends CoordinatoriumError {
135
+ constructor(id, status) {
136
+ super('MISSION_NOT_ACTIVE', `Mission "${id}" is not active (status: "${status}") — cannot create a checkpoint`);
137
+ this.name = 'MissionNotActiveError';
138
+ }
139
+ }
140
+ export class CheckpointNotFoundError extends CoordinatoriumError {
141
+ constructor(id) {
142
+ super('CHECKPOINT_NOT_FOUND', `No checkpoint found with id "${id}"`);
143
+ this.name = 'CheckpointNotFoundError';
144
+ }
145
+ }
@@ -0,0 +1,11 @@
1
+ export type { CoordinatoriumState, StrategicState, TacticalState, Mission, MissionStatus, MissionResult, Checkpoint, } from './types.js';
2
+ export { STATE_SCHEMA_VERSION, createInitialState } from './types.js';
3
+ export { CoordinatoriumError, StateCorruptedError, StateSchemaError, LockTimeoutError, LockUnsafeError, StateFileError, MissionNotFoundError, InvalidTransitionError, ValidationError, MissionNotActiveError, CheckpointNotFoundError, } from './errors.js';
4
+ export type { CoordinatoriumErrorCode } from './errors.js';
5
+ export { readState, mutateState, validateState, stateFilePath, STATE_FILE_NAME, MAX_STATE_BYTES, projectTarget, trustedDirectoryTarget, } from './state-keeper.js';
6
+ export type { StateWriteTarget, StateReadTarget } from './state-keeper.js';
7
+ export { startMission, listMissions, getMission, finishMission } from './mission.js';
8
+ export type { StartMissionInput, FinishMissionInput } from './mission.js';
9
+ export { createCheckpoint, listCheckpoints, getCheckpoint } from './checkpoint.js';
10
+ export type { CreateCheckpointInput } from './checkpoint.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/coordinatorium/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,OAAO,EACP,aAAa,EACb,aAAa,EACb,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EACL,SAAS,EACT,WAAW,EACX,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,aAAa,EACb,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACrF,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnF,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { STATE_SCHEMA_VERSION, createInitialState } from './types.js';
2
+ export { CoordinatoriumError, StateCorruptedError, StateSchemaError, LockTimeoutError, LockUnsafeError, StateFileError, MissionNotFoundError, InvalidTransitionError, ValidationError, MissionNotActiveError, CheckpointNotFoundError, } from './errors.js';
3
+ export { readState, mutateState, validateState, stateFilePath, STATE_FILE_NAME, MAX_STATE_BYTES, projectTarget, trustedDirectoryTarget, } from './state-keeper.js';
4
+ export { startMission, listMissions, getMission, finishMission } from './mission.js';
5
+ export { createCheckpoint, listCheckpoints, getCheckpoint } from './checkpoint.js';
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Minimal cross-process file lock.
3
+ *
4
+ * Acquisition is a single `open(path, 'wx')` syscall — it either creates the
5
+ * file or fails with EEXIST, atomically, on every platform Node supports.
6
+ * That atomicity is what actually prevents two processes from both believing
7
+ * they own the lock at once; the lock file's body (a JSON owner record) exists only
8
+ * to support crash recovery.
9
+ *
10
+ * Three invariants govern every decision in this module:
11
+ *
12
+ * 1. Lock ownership is not time-based.
13
+ * The age of the lock file is never, by itself, a reason to take it.
14
+ * 2. Uncertainty never grants ownership.
15
+ * If we cannot reliably establish that the recorded owner has exited,
16
+ * the lock is treated as held — we wait, we do not recover it.
17
+ * 3. Timeout ends waiting, not ownership.
18
+ * `timeoutMs` bounds how long a *challenger* will wait to acquire the
19
+ * lock. It says nothing about how long the current owner may hold it.
20
+ *
21
+ * A fourth, narrower rule governs recovery specifically:
22
+ *
23
+ * 4. Recovering a dead owner's lock is itself serialized.
24
+ * "Read the lock, confirm its owner is dead, re-read it, and delete it
25
+ * if unchanged" is NOT one atomic operation — the re-read and the
26
+ * delete are two separate syscalls, and another process can complete
27
+ * an entire recovery (delete the stale lock, create its own) in the
28
+ * gap between them. A recovery mutex (`<lockPath>.recovery`, itself
29
+ * just another `open(..., 'wx')`-guarded file) makes "verify and then
30
+ * delete a specific stale lock" exclusive, so at most one process is
31
+ * ever in a position to delete a given dead owner's record.
32
+ *
33
+ * Known limitation: this is a local-filesystem lock built on POSIX rename/
34
+ * open semantics. It does not claim to provide distributed coordination,
35
+ * and its guarantees are not evaluated on network filesystems (NFS, SMB,
36
+ * etc.) where `open(..., 'wx')` atomicity is not always dependable.
37
+ *
38
+ * A fifth invariant governs *creating* a lock (primary or recovery mutex)
39
+ * specifically:
40
+ *
41
+ * 5. A lock is never published in a partially-written state.
42
+ * Metadata is written in full to a private staging file
43
+ * (`<lockPath>.creating.<pid>.<nonce>`, a name no other acquirer can
44
+ * ever guess or collide with; created `O_EXCL|O_NOFOLLOW` at mode `0600`
45
+ * through the shared safe-write primitive, SEC-001B.2) and only
46
+ * published — via `link()`,
47
+ * which is exactly as exclusive a create-if-absent primitive as
48
+ * `open(path, 'wx')` — once that write (and, if requested, an fsync)
49
+ * has fully succeeded. If anything fails first, the canonical path
50
+ * never existed because of this attempt; only this process's own
51
+ * uniquely-named staging file is ever touched by its own cleanup. See
52
+ * `createAndPublish` below and ADR-008 for the full argument.
53
+ */
54
+ import { type FsOps, type ParentRef } from '../root/index.js';
55
+ /** A well-formed record (see `LockRecord`) is under 200 bytes; 256 B is generous. */
56
+ export declare const MAX_LOCK_BYTES = 256;
57
+ export interface LockOptions {
58
+ /** How long a challenger will wait to acquire the lock before giving up. */
59
+ timeoutMs?: number;
60
+ /** Delay between acquisition attempts while waiting. */
61
+ retryDelayMs?: number;
62
+ /** Fsync the staged metadata file before publishing it as the canonical
63
+ * lock. A durability option, not a correctness requirement: mutual
64
+ * exclusion comes entirely from `linkSync`/`open(path, 'wx')` atomicity,
65
+ * with or without this. Default `false` — without it, metadata for a
66
+ * lock acquired just before a hard crash/power loss may not have reached
67
+ * disk yet, though the lock's atomicity and exclusivity guarantees are
68
+ * unaffected either way; this never claims power-loss durability when
69
+ * left at its default. */
70
+ fsyncMetadata?: boolean;
71
+ }
72
+ /**
73
+ * Test-only hooks for forcing specific, otherwise-timing-dependent
74
+ * interleavings deterministically. Every hook defaults to a no-op; no
75
+ * production code path (in particular, `state-keeper.ts`) ever supplies
76
+ * one. Do not use this outside tests.
77
+ */
78
+ export interface LockTestHooks {
79
+ /** Invoked right after an owner is confirmed dead, before attempting to
80
+ * acquire the recovery mutex. */
81
+ beforeRecoveryAttempt?: () => void | Promise<void>;
82
+ /** Invoked immediately before the confirmed-dead owner's lock file is
83
+ * actually unlinked, while still holding the recovery mutex. */
84
+ beforeStaleUnlink?: () => void | Promise<void>;
85
+ /** Replaces the low-level write call used while writing a lock's staged
86
+ * metadata, so tests can force a deterministic fault (e.g. throw ENOSPC
87
+ * before any byte is written, or write a short chunk and then throw) —
88
+ * never supplied by production code. */
89
+ writeMetadata?: (fd: number, buffer: Buffer, offset: number, length: number) => number;
90
+ /** Invoked after a staging-write/fsync failure is detected (and the fd
91
+ * closed) but before the best-effort cleanup of this process's own
92
+ * staging file — lets tests pause a failed creator at exactly the point
93
+ * where only its own staging file exists on disk. */
94
+ beforeStagingCleanupOnFailure?: () => void | Promise<void>;
95
+ /** Replaces the `unlink` of a confirmed-dead owner's lock during stale
96
+ * recovery, so tests can force a persistent failure (EACCES/EROFS/EIO). */
97
+ unlinkLock?: (path: string) => void;
98
+ /** Replaces the `/proc` and `kill(pid, 0)` probes used to identify this
99
+ * process and to judge a recorded owner — lets tests simulate another PID
100
+ * namespace or boot without real namespace support. */
101
+ procOps?: Partial<ProcOps>;
102
+ /** Replaces individual filesystem calls made by the safe-write primitive
103
+ * while creating, publishing and removing staging files — fault injection
104
+ * for publication states. Never supplied by production code. */
105
+ fsOps?: Partial<FsOps>;
106
+ /** Replaces the monotonic clock (milliseconds) that drives the deadline. */
107
+ now?: () => number;
108
+ /** Replaces the jitter source: a value in `[0, 1)`. */
109
+ random?: () => number;
110
+ /** Replaces the wait between attempts; receives the requested milliseconds. */
111
+ sleep?: (ms: number) => Promise<void>;
112
+ }
113
+ export type LivenessVerdict = 'alive' | 'dead' | 'unknown';
114
+ /** What identifies a process beyond its PID. A PID is only meaningful inside
115
+ * one PID namespace of one boot, and may be reused after its owner exits. Any
116
+ * field is `null` when the platform cannot provide it. */
117
+ export interface OwnerIdentity {
118
+ /** Kernel boot id (`/proc/sys/kernel/random/boot_id`): distinguishes boots and hosts. */
119
+ boot: string | null;
120
+ /** PID namespace (`readlink /proc/self/ns/pid`, `pid:[inode]`). */
121
+ pidns: string | null;
122
+ /** Process start time in clock ticks since boot (`/proc/<pid>/stat`, field 22): detects PID reuse. */
123
+ start: string | null;
124
+ }
125
+ /** The OS probes liveness decisions rest on; injectable for tests only. */
126
+ export interface ProcOps {
127
+ platform: NodeJS.Platform;
128
+ pid: number;
129
+ readText(path: string): string;
130
+ readlink(path: string): string;
131
+ kill(pid: number, signal: 0): void;
132
+ }
133
+ /** This process's identity, or all-`null` when it cannot be established
134
+ * (non-Linux, or `/proc` that does not belong to our PID namespace). */
135
+ export declare function captureIdentity(ops?: ProcOps): OwnerIdentity;
136
+ /**
137
+ * Decide whether the owner named by `record` is alive, from verifiable
138
+ * identity rather than from `kill(pid, 0)` alone (H1, LOCK-FIX-001).
139
+ *
140
+ * A PID is only meaningful inside the PID namespace and boot that issued it, so
141
+ * `ESRCH` is NOT proof of death by itself: a process in another namespace
142
+ * sharing the filesystem would see a live owner's PID as "no such process".
143
+ * `dead` therefore requires the record's boot and PID namespace to equal ours,
144
+ * and either a different start time for that PID (it was reused) or two
145
+ * independent probes agreeing it does not exist (`/proc/<pid>` absent AND
146
+ * `ESRCH`). Everything else is `unknown`, which — like `alive` — forbids
147
+ * recovery. Rules are checked top to bottom; the first match decides. The age
148
+ * of the lock plays no part.
149
+ */
150
+ export declare function judgeOwner(record: LockRecord, ours: OwnerIdentity, ops?: ProcOps): {
151
+ verdict: LivenessVerdict;
152
+ reason: string;
153
+ };
154
+ /**
155
+ * The lock file's body: one line of strict JSON. `pid` and `nonce` identify the
156
+ * attempt; `boot`, `pidns` and `start` identify the owning process well enough
157
+ * for another process to judge whether it is dead (H1). There is no support for
158
+ * the earlier `pid:nonce` format: such a file is "unrecognised", never judged
159
+ * and never deleted.
160
+ */
161
+ export interface LockRecord extends OwnerIdentity {
162
+ pid: number;
163
+ nonce: string;
164
+ }
165
+ /** The exact bytes written as a lock file's body. */
166
+ export declare function formatLockRecord(r: LockRecord): string;
167
+ /**
168
+ * Acquire `lockPath` exclusively. Waits up to `timeoutMs` for the current
169
+ * owner (if any) to release it, attempting liveness-gated, mutex-serialized
170
+ * recovery only when the owner is provably dead (`judgeOwner`). Returns a
171
+ * release function. `testHooks` exists solely to let tests force specific
172
+ * interleavings deterministically — production callers must never pass it.
173
+ *
174
+ * One monotonic deadline governs the whole call and is checked at the top of
175
+ * EVERY iteration, and the only `continue` sits at the tail after all
176
+ * bookkeeping, so no branch (recovery progress, aborted recovery, a failing
177
+ * `unlink`) can skip the check or the wait. Waits are a bounded exponential backoff with jitter in `[d/2, d]`,
178
+ * never longer than the time remaining. After a recovery the lock path is
179
+ * observed again rather than assumed free; at most
180
+ * `MAX_PROGRESS_WITHOUT_SLEEP` iterations in a row may run without waiting.
181
+ *
182
+ * The deadline bounds the waiting loop and the number of retries. It does not
183
+ * bound a single synchronous filesystem call that hangs inside the kernel
184
+ * (e.g. a stuck mount): no timer can run while it blocks.
185
+ */
186
+ export declare function acquireLock(lockPath: string, options?: LockOptions, testHooks?: LockTestHooks, parent?: ParentRef): Promise<() => void>;
187
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/coordinatorium/lock.ts"],"names":[],"mappings":"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"}