@telora/daemon 0.22.187 → 0.22.208

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 (278) hide show
  1. package/build-info.json +6 -3
  2. package/dist/backends/index.d.ts.map +1 -1
  3. package/dist/backends/index.js +2 -0
  4. package/dist/backends/index.js.map +1 -1
  5. package/dist/completion/completion-fact-readers.d.ts +35 -0
  6. package/dist/completion/completion-fact-readers.d.ts.map +1 -0
  7. package/dist/completion/completion-fact-readers.js +70 -0
  8. package/dist/completion/completion-fact-readers.js.map +1 -0
  9. package/dist/completion/escalations.d.ts.map +1 -1
  10. package/dist/completion/escalations.js +2 -1
  11. package/dist/completion/escalations.js.map +1 -1
  12. package/dist/completion/event-dep-defaults.d.ts +27 -0
  13. package/dist/completion/event-dep-defaults.d.ts.map +1 -0
  14. package/dist/completion/event-dep-defaults.js +30 -0
  15. package/dist/completion/event-dep-defaults.js.map +1 -0
  16. package/dist/completion/event-phases.d.ts.map +1 -1
  17. package/dist/completion/event-phases.js +5 -13
  18. package/dist/completion/event-phases.js.map +1 -1
  19. package/dist/completion/event.d.ts +32 -0
  20. package/dist/completion/event.d.ts.map +1 -1
  21. package/dist/completion/event.js +31 -25
  22. package/dist/completion/event.js.map +1 -1
  23. package/dist/completion/review-exit-phase.d.ts.map +1 -1
  24. package/dist/completion/review-exit-phase.js +11 -4
  25. package/dist/completion/review-exit-phase.js.map +1 -1
  26. package/dist/completion/session-hold.d.ts +13 -1
  27. package/dist/completion/session-hold.d.ts.map +1 -1
  28. package/dist/completion/session-hold.js +18 -0
  29. package/dist/completion/session-hold.js.map +1 -1
  30. package/dist/completion/standing-approval-convergence.d.ts.map +1 -1
  31. package/dist/completion/standing-approval-convergence.js +2 -1
  32. package/dist/completion/standing-approval-convergence.js.map +1 -1
  33. package/dist/completion/team-phase.d.ts.map +1 -1
  34. package/dist/completion/team-phase.js +1 -0
  35. package/dist/completion/team-phase.js.map +1 -1
  36. package/dist/completion/unclaimed-migration-notice-phase.d.ts +97 -0
  37. package/dist/completion/unclaimed-migration-notice-phase.d.ts.map +1 -0
  38. package/dist/completion/unclaimed-migration-notice-phase.js +270 -0
  39. package/dist/completion/unclaimed-migration-notice-phase.js.map +1 -0
  40. package/dist/directive/directive-executor.d.ts.map +1 -1
  41. package/dist/directive/directive-executor.js +1 -20
  42. package/dist/directive/directive-executor.js.map +1 -1
  43. package/dist/focus/focus-executor.d.ts +1 -0
  44. package/dist/focus/focus-executor.d.ts.map +1 -1
  45. package/dist/focus/focus-executor.js +18 -17
  46. package/dist/focus/focus-executor.js.map +1 -1
  47. package/dist/focus/focus-loop-registry.js +2 -2
  48. package/dist/focus/focus-loop-registry.js.map +1 -1
  49. package/dist/focus/focus-team-state.js +1 -1
  50. package/dist/focus/listener-spawn.d.ts.map +1 -1
  51. package/dist/focus/listener-spawn.js +5 -20
  52. package/dist/focus/listener-spawn.js.map +1 -1
  53. package/dist/focus/listener-state.d.ts.map +1 -1
  54. package/dist/focus/listener-state.js +1 -0
  55. package/dist/focus/listener-state.js.map +1 -1
  56. package/dist/focus/listener.d.ts +1 -0
  57. package/dist/focus/listener.d.ts.map +1 -1
  58. package/dist/focus/listener.js +9 -0
  59. package/dist/focus/listener.js.map +1 -1
  60. package/dist/focus/migration-claim-pass.d.ts +50 -0
  61. package/dist/focus/migration-claim-pass.d.ts.map +1 -0
  62. package/dist/focus/migration-claim-pass.js +234 -0
  63. package/dist/focus/migration-claim-pass.js.map +1 -0
  64. package/dist/focus/pending-spawn-pass-deps.d.ts.map +1 -1
  65. package/dist/focus/pending-spawn-pass-deps.js +2 -1
  66. package/dist/focus/pending-spawn-pass-deps.js.map +1 -1
  67. package/dist/focus/team-actionable-work.d.ts +21 -0
  68. package/dist/focus/team-actionable-work.d.ts.map +1 -1
  69. package/dist/focus/team-actionable-work.js +3 -0
  70. package/dist/focus/team-actionable-work.js.map +1 -1
  71. package/dist/git/types.d.ts.map +1 -1
  72. package/dist/git/types.js +2 -1
  73. package/dist/git/types.js.map +1 -1
  74. package/dist/loops/llm-client.d.ts +1 -1
  75. package/dist/loops/llm-client.d.ts.map +1 -1
  76. package/dist/loops/llm-client.js +29 -106
  77. package/dist/loops/llm-client.js.map +1 -1
  78. package/dist/migrations/migration-claim-lifecycle.d.ts +166 -0
  79. package/dist/migrations/migration-claim-lifecycle.d.ts.map +1 -0
  80. package/dist/migrations/migration-claim-lifecycle.js +198 -0
  81. package/dist/migrations/migration-claim-lifecycle.js.map +1 -0
  82. package/dist/migrations/migration-held-set.d.ts +171 -0
  83. package/dist/migrations/migration-held-set.d.ts.map +1 -0
  84. package/dist/migrations/migration-held-set.js +295 -0
  85. package/dist/migrations/migration-held-set.js.map +1 -0
  86. package/dist/migrations/migration-inventory.d.ts +187 -0
  87. package/dist/migrations/migration-inventory.d.ts.map +1 -0
  88. package/dist/migrations/migration-inventory.js +253 -0
  89. package/dist/migrations/migration-inventory.js.map +1 -0
  90. package/dist/migrations/migration-manifest.d.ts +114 -0
  91. package/dist/migrations/migration-manifest.d.ts.map +1 -0
  92. package/dist/migrations/migration-manifest.js +295 -0
  93. package/dist/migrations/migration-manifest.js.map +1 -0
  94. package/dist/prompt/team-prompt-base.js +1 -1
  95. package/dist/prompt-sections/migration-numbering-section.d.ts +58 -0
  96. package/dist/prompt-sections/migration-numbering-section.d.ts.map +1 -0
  97. package/dist/prompt-sections/migration-numbering-section.js +70 -0
  98. package/dist/prompt-sections/migration-numbering-section.js.map +1 -0
  99. package/dist/prompt-sections/migration-numbering-state.d.ts +30 -0
  100. package/dist/prompt-sections/migration-numbering-state.d.ts.map +1 -0
  101. package/dist/prompt-sections/migration-numbering-state.js +24 -0
  102. package/dist/prompt-sections/migration-numbering-state.js.map +1 -0
  103. package/dist/prompt-sections/unclaimed-migration-section.d.ts +38 -0
  104. package/dist/prompt-sections/unclaimed-migration-section.d.ts.map +1 -0
  105. package/dist/prompt-sections/unclaimed-migration-section.js +57 -0
  106. package/dist/prompt-sections/unclaimed-migration-section.js.map +1 -0
  107. package/dist/queries/agent-resolvable-promotion.d.ts +12 -0
  108. package/dist/queries/agent-resolvable-promotion.d.ts.map +1 -1
  109. package/dist/queries/agent-resolvable-promotion.js +17 -6
  110. package/dist/queries/agent-resolvable-promotion.js.map +1 -1
  111. package/dist/queries/claim-pass-focuses.d.ts +19 -0
  112. package/dist/queries/claim-pass-focuses.d.ts.map +1 -0
  113. package/dist/queries/claim-pass-focuses.js +72 -0
  114. package/dist/queries/claim-pass-focuses.js.map +1 -0
  115. package/dist/queries/daemon-connection.d.ts.map +1 -1
  116. package/dist/queries/daemon-connection.js +1 -0
  117. package/dist/queries/daemon-connection.js.map +1 -1
  118. package/dist/queries/delivery-gate-state.d.ts +3 -0
  119. package/dist/queries/delivery-gate-state.d.ts.map +1 -1
  120. package/dist/queries/delivery-gate-state.js +1 -1
  121. package/dist/queries/delivery-gate-state.js.map +1 -1
  122. package/dist/queries/focus-discovery.d.ts +25 -2
  123. package/dist/queries/focus-discovery.d.ts.map +1 -1
  124. package/dist/queries/focus-discovery.js +16 -9
  125. package/dist/queries/focus-discovery.js.map +1 -1
  126. package/dist/queries/focus-unclaimed-migration.d.ts +146 -0
  127. package/dist/queries/focus-unclaimed-migration.d.ts.map +1 -0
  128. package/dist/queries/focus-unclaimed-migration.js +266 -0
  129. package/dist/queries/focus-unclaimed-migration.js.map +1 -0
  130. package/dist/queries/live-focus-branches.d.ts +32 -0
  131. package/dist/queries/live-focus-branches.d.ts.map +1 -0
  132. package/dist/queries/live-focus-branches.js +66 -0
  133. package/dist/queries/live-focus-branches.js.map +1 -0
  134. package/dist/queries/migration-claims.d.ts +25 -0
  135. package/dist/queries/migration-claims.d.ts.map +1 -0
  136. package/dist/queries/migration-claims.js +79 -0
  137. package/dist/queries/migration-claims.js.map +1 -0
  138. package/dist/queries/schemas.d.ts +2 -0
  139. package/dist/queries/schemas.d.ts.map +1 -1
  140. package/dist/queries/schemas.js +6 -0
  141. package/dist/queries/schemas.js.map +1 -1
  142. package/dist/queries/shared.js +1 -1
  143. package/dist/queries/verify-own-holds.d.ts +89 -0
  144. package/dist/queries/verify-own-holds.d.ts.map +1 -0
  145. package/dist/queries/verify-own-holds.js +93 -0
  146. package/dist/queries/verify-own-holds.js.map +1 -0
  147. package/dist/session/session-lineage.d.ts.map +1 -1
  148. package/dist/session/session-lineage.js +3 -0
  149. package/dist/session/session-lineage.js.map +1 -1
  150. package/dist/shell/heartbeat-metadata.d.ts +48 -2
  151. package/dist/shell/heartbeat-metadata.d.ts.map +1 -1
  152. package/dist/shell/heartbeat-metadata.js +80 -3
  153. package/dist/shell/heartbeat-metadata.js.map +1 -1
  154. package/dist/shell/heartbeat.d.ts +13 -0
  155. package/dist/shell/heartbeat.d.ts.map +1 -1
  156. package/dist/shell/heartbeat.js +31 -10
  157. package/dist/shell/heartbeat.js.map +1 -1
  158. package/dist/shell/mcp-resolution.js +1 -1
  159. package/dist/shell/mcp-resolution.js.map +1 -1
  160. package/dist/shell/migration-held-set-publish.d.ts +170 -0
  161. package/dist/shell/migration-held-set-publish.d.ts.map +1 -0
  162. package/dist/shell/migration-held-set-publish.js +172 -0
  163. package/dist/shell/migration-held-set-publish.js.map +1 -0
  164. package/dist/shell/worker-pidfile.d.ts.map +1 -1
  165. package/dist/shell/worker-pidfile.js +1 -0
  166. package/dist/shell/worker-pidfile.js.map +1 -1
  167. package/dist/spawn/helpers.d.ts.map +1 -1
  168. package/dist/spawn/helpers.js +1 -0
  169. package/dist/spawn/helpers.js.map +1 -1
  170. package/dist/spawn/lead-launch.d.ts.map +1 -1
  171. package/dist/spawn/lead-launch.js +1 -0
  172. package/dist/spawn/lead-launch.js.map +1 -1
  173. package/dist/spawn/lead-process-ownership.d.ts.map +1 -1
  174. package/dist/spawn/lead-process-ownership.js +1 -0
  175. package/dist/spawn/lead-process-ownership.js.map +1 -1
  176. package/dist/spawn/one-shot-model.d.ts +145 -0
  177. package/dist/spawn/one-shot-model.d.ts.map +1 -0
  178. package/dist/spawn/one-shot-model.js +329 -0
  179. package/dist/spawn/one-shot-model.js.map +1 -0
  180. package/dist/spawn/process-group-kill.d.ts.map +1 -1
  181. package/dist/spawn/process-group-kill.js +1 -0
  182. package/dist/spawn/process-group-kill.js.map +1 -1
  183. package/dist/spawn/process-spawn.d.ts +18 -1
  184. package/dist/spawn/process-spawn.d.ts.map +1 -1
  185. package/dist/spawn/process-spawn.js +11 -6
  186. package/dist/spawn/process-spawn.js.map +1 -1
  187. package/dist/spawn/prompt-assembly.d.ts +115 -18
  188. package/dist/spawn/prompt-assembly.d.ts.map +1 -1
  189. package/dist/spawn/prompt-assembly.js +121 -2
  190. package/dist/spawn/prompt-assembly.js.map +1 -1
  191. package/dist/spawn/review-hold-park.d.ts.map +1 -1
  192. package/dist/spawn/review-hold-park.js +7 -3
  193. package/dist/spawn/review-hold-park.js.map +1 -1
  194. package/dist/spawn/routing-decider-spawn.d.ts +30 -0
  195. package/dist/spawn/routing-decider-spawn.d.ts.map +1 -1
  196. package/dist/spawn/routing-decider-spawn.js +84 -2
  197. package/dist/spawn/routing-decider-spawn.js.map +1 -1
  198. package/dist/spawn/routing-decider.d.ts.map +1 -1
  199. package/dist/spawn/routing-decider.js +22 -0
  200. package/dist/spawn/routing-decider.js.map +1 -1
  201. package/dist/spawn/spawn-and-acknowledge.d.ts +61 -0
  202. package/dist/spawn/spawn-and-acknowledge.d.ts.map +1 -0
  203. package/dist/spawn/spawn-and-acknowledge.js +117 -0
  204. package/dist/spawn/spawn-and-acknowledge.js.map +1 -0
  205. package/dist/spawn/spawn-cooldown.d.ts +15 -1
  206. package/dist/spawn/spawn-cooldown.d.ts.map +1 -1
  207. package/dist/spawn/spawn-cooldown.js +67 -19
  208. package/dist/spawn/spawn-cooldown.js.map +1 -1
  209. package/dist/spawn/spawn-decision.d.ts +10 -10
  210. package/dist/spawn/spawn-decision.d.ts.map +1 -1
  211. package/dist/spawn/spawn-decision.js +33 -5
  212. package/dist/spawn/spawn-decision.js.map +1 -1
  213. package/dist/templates/claude-md.d.ts +1 -1
  214. package/dist/templates/claude-md.d.ts.map +1 -1
  215. package/dist/templates/claude-md.js +24 -0
  216. package/dist/templates/claude-md.js.map +1 -1
  217. package/dist/testing/fixtures/index.js +1 -1
  218. package/dist/testing/fixtures/migration-namespace-repo.d.ts +63 -0
  219. package/dist/testing/fixtures/migration-namespace-repo.d.ts.map +1 -0
  220. package/dist/testing/fixtures/migration-namespace-repo.js +164 -0
  221. package/dist/testing/fixtures/migration-namespace-repo.js.map +1 -0
  222. package/dist/testing/fixtures/stubborn-lead-process.d.ts.map +1 -1
  223. package/dist/testing/fixtures/stubborn-lead-process.js +1 -0
  224. package/dist/testing/fixtures/stubborn-lead-process.js.map +1 -1
  225. package/dist/types/index.js +1 -1
  226. package/dist/verify/ai-inspection-runner.d.ts.map +1 -1
  227. package/dist/verify/ai-inspection-runner.js +26 -7
  228. package/dist/verify/ai-inspection-runner.js.map +1 -1
  229. package/dist/verify/de-restatement.d.ts +9 -2
  230. package/dist/verify/de-restatement.d.ts.map +1 -1
  231. package/dist/verify/de-restatement.js +14 -76
  232. package/dist/verify/de-restatement.js.map +1 -1
  233. package/dist/verify/default-on-guards.d.ts +5 -2
  234. package/dist/verify/default-on-guards.d.ts.map +1 -1
  235. package/dist/verify/default-on-guards.js +5 -3
  236. package/dist/verify/default-on-guards.js.map +1 -1
  237. package/dist/verify/no-own-delta-verdict.d.ts +16 -2
  238. package/dist/verify/no-own-delta-verdict.d.ts.map +1 -1
  239. package/dist/verify/no-own-delta-verdict.js +18 -2
  240. package/dist/verify/no-own-delta-verdict.js.map +1 -1
  241. package/dist/verify/verification-deps-default.d.ts.map +1 -1
  242. package/dist/verify/verification-deps-default.js +6 -0
  243. package/dist/verify/verification-deps-default.js.map +1 -1
  244. package/dist/verify/verification-deps.d.ts +10 -0
  245. package/dist/verify/verification-deps.d.ts.map +1 -1
  246. package/dist/verify/verification-deterministic.d.ts +7 -0
  247. package/dist/verify/verification-deterministic.d.ts.map +1 -1
  248. package/dist/verify/verification-deterministic.js.map +1 -1
  249. package/dist/verify/verification-engine.d.ts +1 -20
  250. package/dist/verify/verification-engine.d.ts.map +1 -1
  251. package/dist/verify/verification-engine.js +24 -55
  252. package/dist/verify/verification-engine.js.map +1 -1
  253. package/dist/verify/verification-evidence-unavailable-feedback.d.ts +3 -1
  254. package/dist/verify/verification-evidence-unavailable-feedback.d.ts.map +1 -1
  255. package/dist/verify/verification-evidence-unavailable-feedback.js +3 -1
  256. package/dist/verify/verification-evidence-unavailable-feedback.js.map +1 -1
  257. package/dist/verify/verification-feedback.d.ts +4 -12
  258. package/dist/verify/verification-feedback.d.ts.map +1 -1
  259. package/dist/verify/verification-feedback.js +7 -12
  260. package/dist/verify/verification-feedback.js.map +1 -1
  261. package/dist/verify/verification-history-reset.d.ts.map +1 -1
  262. package/dist/verify/verification-history-reset.js +11 -3
  263. package/dist/verify/verification-history-reset.js.map +1 -1
  264. package/dist/verify/verification-model-unavailable-hold.d.ts +92 -0
  265. package/dist/verify/verification-model-unavailable-hold.d.ts.map +1 -0
  266. package/dist/verify/verification-model-unavailable-hold.js +207 -0
  267. package/dist/verify/verification-model-unavailable-hold.js.map +1 -0
  268. package/dist/verify/verification-strategies.d.ts +32 -0
  269. package/dist/verify/verification-strategies.d.ts.map +1 -0
  270. package/dist/verify/verification-strategies.js +47 -0
  271. package/dist/verify/verification-strategies.js.map +1 -0
  272. package/dist/verify/verify-reconciliation.d.ts.map +1 -1
  273. package/dist/verify/verify-reconciliation.js +2 -1
  274. package/dist/verify/verify-reconciliation.js.map +1 -1
  275. package/dist/verify/verify-restatement.d.ts.map +1 -1
  276. package/dist/verify/verify-restatement.js +21 -8
  277. package/dist/verify/verify-restatement.js.map +1 -1
  278. package/package.json +2 -2
@@ -0,0 +1,198 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/focus/migration-claim-pass.test.ts,
3
+ // packages/daemon/src/migrations/migration-claim-lifecycle.test.ts,
4
+ // packages/daemon/src/queries/focus-unclaimed-migration.test.ts
5
+ // PINNED-BY-END
6
+ /** The empty decision: what an unreadable branch produces. */
7
+ function nothing(readable) {
8
+ return { confirm: [], release: [], unclaimed: [], clearUnclaimed: false, readable };
9
+ }
10
+ /**
11
+ * The tag a recorded path implies.
12
+ *
13
+ * The record stores the number and the file, not the tag -- one text serves
14
+ * both the human reading it and the lifecycle reasoning over it, and a second
15
+ * stored field is a second thing to keep in step. Reading it back off the
16
+ * filename is exact for every file the declaration's own pattern matched.
17
+ */
18
+ function tagFromRecordedPath(ordinal, path) {
19
+ const base = path.slice(path.lastIndexOf('/') + 1);
20
+ const withoutOrdinal = base.startsWith(`${ordinal}_`) ? base.slice(ordinal.length + 1) : base;
21
+ return withoutOrdinal.replace(/\.[^.]+$/, '');
22
+ }
23
+ /** Confirm every claim whose file is on the branch; release the ended ones. */
24
+ function decideClaims(claims, onBranch, onIntegration, focus, decision) {
25
+ for (const claim of claims) {
26
+ const file = onBranch.get(claim.ordinal);
27
+ if (file) {
28
+ // The file landed. Confirm with the tag the FILE carries -- a team is
29
+ // free to rename as it writes, and the file is the reality.
30
+ //
31
+ // Re-confirm only when what was RECORDED differs from what is there now.
32
+ // Comparing against `tag` (frozen intent) instead would differ forever
33
+ // for any team that renamed as it wrote, rewriting the row every tick.
34
+ if (claim.confirmedAt === null || claim.confirmedTag !== file.tag) {
35
+ decision.confirm.push({
36
+ migrationClaimId: claim.migrationClaimId,
37
+ ordinal: claim.ordinal,
38
+ confirmedTag: file.tag,
39
+ });
40
+ }
41
+ continue;
42
+ }
43
+ // No file on the branch. Only a focus that has ENDED releases anything: a
44
+ // live focus simply has not written it yet.
45
+ if (focus.endedBecause === null)
46
+ continue;
47
+ // RELEASE REQUIRES ESTABLISHED ABSENCE FROM BOTH PLACES A FILE CAN BE.
48
+ // Absence from the branch is established above. Absence from INTEGRATION
49
+ // has to be established too, and for every claim -- not only confirmed
50
+ // ones. A claim can be unconfirmed simply because the confirm pass never
51
+ // ran before the branch merged: its file is on integration, and releasing
52
+ // it would hand a landed migration's number out a second time, which is
53
+ // the cleanup re-creating the failure it cleans up after.
54
+ if (onIntegration === null)
55
+ continue; // cannot prove it is gone -- hold
56
+ if (onIntegration.has(claim.ordinal))
57
+ continue; // it merged; the number stands
58
+ decision.release.push({
59
+ migrationClaimId: claim.migrationClaimId,
60
+ ordinal: claim.ordinal,
61
+ reason: focus.endedBecause,
62
+ });
63
+ }
64
+ }
65
+ /**
66
+ * Migrations on the branch that no claim accounts for, and whether an existing
67
+ * record may be cleared.
68
+ *
69
+ * DETECTING one is judged against the UNRELEASED claims and only against files
70
+ * the branch adds beyond integration -- a migration inherited from integration
71
+ * is someone else's already-landed work, and naming it would put the whole of
72
+ * history in front of the team on every tick.
73
+ *
74
+ * KEEPING one named is a different question, and conflating the two is how the
75
+ * record used to disappear without anyone resolving it. TWO WAYS IT VANISHED:
76
+ * the branch MERGES, so the file reads as "inherited" and the detection goes
77
+ * quiet; or the branch is PRUNED after merging (crash-recovery's merged-orphan
78
+ * cleanup deletes it), so there is no branch to see the file on at all. In both
79
+ * the team neither claimed the number nor removed the file, and in both the
80
+ * file is sitting on integration.
81
+ *
82
+ * So resolution is stated positively and is the ONLY thing that clears a
83
+ * record: a live claim now covers the ordinal, or the file is gone from the
84
+ * branch AND from integration -- really removed, not merely moved. Where
85
+ * integration cannot be read, nothing is resolved, because removal cannot be
86
+ * told from a merge.
87
+ */
88
+ function decideUnclaimed(claims, onBranch, onIntegration, recorded, decision) {
89
+ const claimed = new Set(claims.map((c) => c.ordinal));
90
+ const named = new Set();
91
+ const alreadyRecorded = new Set(recorded.map((e) => e.ordinal));
92
+ for (const migration of onBranch.values()) {
93
+ if (claimed.has(migration.ordinal))
94
+ continue;
95
+ if (!alreadyRecorded.has(migration.ordinal)) {
96
+ // A NEW detection: inherited history is not this team's file.
97
+ if (onIntegration === null)
98
+ continue; // cannot tell inherited from new
99
+ if (onIntegration.has(migration.ordinal))
100
+ continue;
101
+ }
102
+ named.add(migration.ordinal);
103
+ decision.unclaimed.push({
104
+ ordinal: migration.ordinal,
105
+ tag: migration.tag,
106
+ path: migration.path,
107
+ });
108
+ }
109
+ if (recorded.length === 0)
110
+ return;
111
+ // A RECORDED ORDINAL THE BRANCH NO LONGER SHOWS IS NOT AUTOMATICALLY GONE.
112
+ // The common case is that it MERGED: the file is on integration, reads as
113
+ // inherited, and drops out of the walk above. If the caller re-renders the
114
+ // record from `unclaimed` alone, that ordinal is silently dropped from it --
115
+ // so with [0352, 0353] recorded, 0352 merged and 0353 still on the branch,
116
+ // re-recording leaves only 0353, and claiming 0353 then clears the record
117
+ // although 0352 was never claimed or removed. Unresolved state must survive
118
+ // a re-render, so it is carried here, sourced from integration (which is
119
+ // where the file now is).
120
+ for (const entry of recorded) {
121
+ const { ordinal } = entry;
122
+ if (claimed.has(ordinal) || named.has(ordinal))
123
+ continue;
124
+ const merged = onIntegration?.get(ordinal);
125
+ if (merged) {
126
+ // It MERGED. Sourced from integration, which is where the file now is.
127
+ named.add(ordinal);
128
+ decision.unclaimed.push({ ordinal: merged.ordinal, tag: merged.tag, path: merged.path });
129
+ continue;
130
+ }
131
+ if (onIntegration === null) {
132
+ // UNRESOLVABLE, and that is precisely when it must be kept. Integration
133
+ // could not be read, so "this merged" and "this was removed" are the same
134
+ // observation from here. `clearUnclaimed` already refuses to clear the
135
+ // record on this evidence -- but the caller RE-RENDERS the record from
136
+ // `unclaimed`, so an ordinal missing from that list is dropped from the
137
+ // record just the same, quietly, and only for the ordinals an outage made
138
+ // unknowable. Carried forward verbatim instead, from what the record
139
+ // itself said.
140
+ named.add(ordinal);
141
+ decision.unclaimed.push({
142
+ ordinal,
143
+ tag: tagFromRecordedPath(ordinal, entry.path),
144
+ path: entry.path,
145
+ });
146
+ continue;
147
+ }
148
+ // Integration WAS read and does not have it, and the branch does not
149
+ // either: really removed. It leaves the record.
150
+ }
151
+ decision.clearUnclaimed = recorded.every(({ ordinal }) => {
152
+ if (claimed.has(ordinal))
153
+ return true; // the team claimed it
154
+ if (named.has(ordinal))
155
+ return false; // still unresolved, still named
156
+ if (onIntegration === null)
157
+ return false; // removal cannot be told from a merge
158
+ return !onIntegration.has(ordinal); // gone from both: really removed
159
+ });
160
+ }
161
+ /**
162
+ * Decide what this focus's claims and files call for.
163
+ *
164
+ * @param claims The focus's UNRELEASED claims.
165
+ * @param branch What its branch holds (the reader's result).
166
+ * @param integration What integration holds. Used to keep a confirmed claim
167
+ * whose file has merged and left the branch, and to tell a
168
+ * removed migration from a merged one.
169
+ * @param focus The focus, and whether it has ended.
170
+ * @param recorded Ordinals an existing unclaimed record already names.
171
+ * Once named, an ordinal stays named until the team
172
+ * RESOLVES it; see `decideUnclaimed`.
173
+ */
174
+ export function decideClaimLifecycle(claims, branch, integration, focus, recorded = []) {
175
+ // A declaration problem is not a branch fact: nothing can be decided at all.
176
+ if (branch.kind === 'declarationUnreadable')
177
+ return nothing(false);
178
+ if (branch.kind === 'undeclared')
179
+ return nothing(true);
180
+ // A branch that could not be READ proves nothing about what it holds.
181
+ if (branch.kind === 'refUnreadable')
182
+ return nothing(false);
183
+ // The file is absent from the branch either because the branch was read and
184
+ // does not have it, or because there IS no branch -- a deleted one, or a
185
+ // focus that never got one. Both are established absence FROM THE BRANCH;
186
+ // neither is absence from INTEGRATION, which is asked separately.
187
+ const onBranch = branch.kind === 'read'
188
+ ? new Map(branch.inventory.migrations.map((m) => [m.ordinal, m]))
189
+ : new Map();
190
+ const onIntegration = integration.kind === 'read'
191
+ ? new Map(integration.inventory.migrations.map((m) => [m.ordinal, m]))
192
+ : null;
193
+ const decision = nothing(true);
194
+ decideClaims(claims, onBranch, onIntegration, focus, decision);
195
+ decideUnclaimed(claims, onBranch, onIntegration, recorded, decision);
196
+ return decision;
197
+ }
198
+ //# sourceMappingURL=migration-claim-lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-claim-lifecycle.js","sourceRoot":"","sources":["../../src/migrations/migration-claim-lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * What a product's migration numbers are CURRENTLY held by, across every ref
3
+ * that matters -- integration and every live focus branch.
4
+ *
5
+ * WHY THIS LIVES IN THE DAEMON AND THE GRANT DOES NOT
6
+ * ---------------------------------------------------
7
+ * The two halves of claiming a number sit on opposite sides of a boundary, and
8
+ * neither half can move:
9
+ *
10
+ * - Seeing what is held needs the REPO. It is a git-tree read across several
11
+ * refs, and only the daemon has the repository on disk. The product-api
12
+ * edge function has no git (`sessionStateHandler` says as much: "the server
13
+ * has no git access").
14
+ * - Granting a number needs the DATABASE, atomically. Two teams claiming at
15
+ * once must be separated by a constraint, not by timing, and the constraint
16
+ * is the partial unique index on `product_migration_claims`.
17
+ *
18
+ * So the held set has to cross the gap. The daemon PUBLISHES it -- per product,
19
+ * on the heartbeat, the way `metadata.verificationPostures` is published for
20
+ * the same reason ("posture is workstation-local config the API cannot itself
21
+ * derive; the daemon is the single source") -- and the edge handler grants
22
+ * against the published set plus the live claims it can see itself.
23
+ *
24
+ * THE OTHER SHAPE, AND WHY NOT IT. Serving the whole claim from the daemon was
25
+ * the alternative. It collapses: either the daemon reads-then-inserts, which is
26
+ * the two-worktrees race reborn one altitude up, or it still calls an edge
27
+ * handler to do the atomic insert -- in which case that handler exists anyway
28
+ * and the daemon is an extra hop in front of it. The decision is recorded on
29
+ * the delivery.
30
+ *
31
+ * WHY A STALE SNAPSHOT IS SAFE, AND WHERE IT IS NOT
32
+ * -------------------------------------------------
33
+ * The published set is only ever an INPUT TO THE CANDIDATE. It never decides
34
+ * anything: the unique index decides. A snapshot read a minute ago can make the
35
+ * handler propose a number that a concurrent claim just took -- and the insert
36
+ * fails, and the handler recomputes. A stale snapshot costs a retry; it cannot
37
+ * cost a collision.
38
+ *
39
+ * What it CAN cost is a number granted against branch tips that have since
40
+ * moved -- a migration landed on a sibling branch after the snapshot was taken,
41
+ * and no claim was recorded for it (a team that skipped the rule). That is why
42
+ * every reading carries `tips`: the exact sha each ref was at when it was read.
43
+ * The confirm pass re-checks a claim whose snapshot predates the tips its branch
44
+ * actually had. A snapshot with no recorded staleness is a silent read-then-write
45
+ * race wearing a different hat, so the tips are not optional decoration.
46
+ *
47
+ * WHAT AN UNREADABLE REF DOES
48
+ * ---------------------------
49
+ * It makes the whole reading INCOMPLETE, and the reading says so. A ref that
50
+ * could not be read proves nothing about what it holds, and a held set quietly
51
+ * missing one branch's numbers tells the allocator those numbers are free --
52
+ * failing open on exactly the question being asked. An incomplete reading is
53
+ * published as incomplete and the handler refuses to grant against it.
54
+ *
55
+ * A ref that does not EXIST is different and is not incompleteness: a deleted
56
+ * branch holds nothing. That distinction is the reader's (`migration-inventory`)
57
+ * and is simply carried through here.
58
+ *
59
+ * @module migration-held-set
60
+ */
61
+ import { type MigrationInventoryDeps, type JournalEntry } from './migration-inventory.js';
62
+ import { type MigrationScheme } from './migration-manifest.js';
63
+ /** A ref to read, and the tip it was at when it was read. */
64
+ export interface HeldRefReading {
65
+ /** The ref as asked for (a branch name). */
66
+ ref: string;
67
+ /** The commit the ref was at, or null when it does not exist / was unreadable. */
68
+ tip: string | null;
69
+ /** What happened: read / absent / unreadable. */
70
+ outcome: 'read' | 'absent' | 'unreadable';
71
+ /** Ordinals this ref holds. Empty for absent or unreadable. */
72
+ ordinals: string[];
73
+ /** Why it could not be read, when `outcome` is 'unreadable'. */
74
+ reason?: string;
75
+ }
76
+ /** Every number a product's refs currently hold, and how completely it is known. */
77
+ export interface MigrationHeldSet {
78
+ /** The declared scheme, carried so the grant need not re-read the declaration. */
79
+ scheme: MigrationScheme;
80
+ /**
81
+ * Every ordinal held by any ref that was read, de-duplicated and sorted.
82
+ * String sort IS ordinal sort: both schemes are zero-padded fixed width.
83
+ */
84
+ held: string[];
85
+ /** Per-ref detail, including the tip each reading was taken at. */
86
+ readings: HeldRefReading[];
87
+ /**
88
+ * False when ANY ref was unreadable. An incomplete held set must not be
89
+ * granted against: the numbers of the ref that failed would read as free.
90
+ */
91
+ complete: boolean;
92
+ /** When this reading was taken (epoch ms). */
93
+ readAt: number;
94
+ }
95
+ /** A product that declares no migration numbering, or one whose declaration is broken. */
96
+ export type MigrationHeldSetResult = {
97
+ kind: 'undeclared';
98
+ } | {
99
+ kind: 'declarationUnreadable';
100
+ reason: string;
101
+ } | {
102
+ kind: 'held';
103
+ heldSet: MigrationHeldSet;
104
+ };
105
+ /** Seams: the inventory reader's, plus the clock (so a test can pin `readAt`). */
106
+ export interface MigrationHeldSetDeps extends MigrationInventoryDeps {
107
+ now: () => number;
108
+ }
109
+ /** Real git, real declaration reader, real clock. */
110
+ export declare function defaultMigrationHeldSetDeps(): MigrationHeldSetDeps;
111
+ /**
112
+ * The ordinals a ref's JOURNAL registers, normalised to the product's width.
113
+ *
114
+ * WHY THE JOURNAL COUNTS AT ALL. On a hand-registered product the journal is
115
+ * half the record: a migration is its numbered filename AND its `idx` entry. A
116
+ * ref can register an idx whose file is not visible -- mid-rename, a file
117
+ * removed but the entry left, a journal edited ahead of the file -- and a held
118
+ * set built from filenames alone reports that number free. The allocator then
119
+ * grants it, and the product ends with two migrations at one position, which is
120
+ * the failure this whole mechanism exists to remove.
121
+ *
122
+ * WHY NORMALISATION IS REQUIRED, NOT COSMETIC. The journal records `idx` as a
123
+ * NUMBER (352) while the filename carries it zero-padded (`0352`). Unioning the
124
+ * two raw would put both `352` and `0352` in the held set -- two widths -- and
125
+ * the candidate rule refuses a product whose ordinals are not one fixed width.
126
+ * A naive union would therefore break every claim on exactly the products this
127
+ * fixes. So a journal idx is padded to the width the product uses.
128
+ *
129
+ * WHEN IT CANNOT BE NORMALISED, THE READING IS INCOMPLETE. An idx wider than
130
+ * the width, one that is not a plain number, and -- the case this argument was
131
+ * missing -- ANY idx at all when no width is established. Dropping such an
132
+ * entry silently is the fail-open; guessing a placement is worse; and using the
133
+ * raw value is worst, because it is neither dropped nor refused but published
134
+ * as though it were a number on this product. It is reported instead, and the
135
+ * caller refuses to grant against the reading rather than granting around the
136
+ * part it could not read.
137
+ *
138
+ * @param width The product's ordinal width, or null when none is established.
139
+ * See `resolveOrdinalWidth`.
140
+ */
141
+ export declare function journalOrdinals(journal: readonly JournalEntry[] | undefined, width: number | null): {
142
+ ordinals: string[];
143
+ unnormalisable: string[];
144
+ };
145
+ /**
146
+ * The width this product's ordinals are padded to, across the WHOLE reading.
147
+ *
148
+ * A PROPERTY OF THE PRODUCT, NOT OF ONE REF. It used to be derived per ref,
149
+ * from that ref's own filenames -- so a ref holding only a journal entry had no
150
+ * width, and a ref holding files a moment before the reading had one. The width
151
+ * a number is padded to cannot depend on which branch you happen to be looking
152
+ * at; it is the product's numbering convention, and it is read once for the
153
+ * whole reading.
154
+ *
155
+ * Declaration first (it fixes the width authoritatively -- no inventoried file
156
+ * can disagree with a pattern it had to match), then the files, which must all
157
+ * agree. Null when neither establishes one: a product with no declared width
158
+ * and no files. Every journal entry is then unnormalisable and the reading is
159
+ * incomplete, which is the honest answer -- the alternative was publishing a
160
+ * bare `351` and granting `352` into a four-digit namespace.
161
+ */
162
+ export declare function resolveOrdinalWidth(declaredWidth: number | null, fileOrdinals: readonly string[]): number | null;
163
+ /**
164
+ * Read every ref and fold what they hold into one set.
165
+ *
166
+ * @param repoPath The product's repo root.
167
+ * @param refs Integration plus every live focus branch. Duplicates are fine
168
+ * (a focus whose branch IS integration reads once).
169
+ */
170
+ export declare function computeMigrationHeldSet(repoPath: string, refs: readonly string[], deps?: MigrationHeldSetDeps): MigrationHeldSetResult;
171
+ //# sourceMappingURL=migration-held-set.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-held-set.d.ts","sourceRoot":"","sources":["../../src/migrations/migration-held-set.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AAEH,OAAO,EAGL,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EAElB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAErF,6DAA6D;AAC7D,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,kFAAkF;IAClF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,iDAAiD;IACjD,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC1C,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,oFAAoF;AACpF,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,MAAM,EAAE,eAAe,CAAC;IACxB;;;OAGG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,mEAAmE;IACnE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0FAA0F;AAC1F,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,uBAAuB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEhD,kFAAkF;AAClF,MAAM,WAAW,oBAAqB,SAAQ,sBAAsB;IAClE,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB;AAED,qDAAqD;AACrD,wBAAgB,2BAA2B,IAAI,oBAAoB,CAElE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,SAAS,EAC5C,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CAgBlD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,MAAM,GAAG,IAAI,CAIf;AA2ID;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,GAAE,oBAAoD,GACzD,sBAAsB,CA4CxB"}