@amalgm/shell 0.1.164-main.40070365614 → 0.1.164-main.40795482467

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 (319) hide show
  1. package/dist/accepted-fold.d.ts +24 -46
  2. package/dist/accepted-fold.js +62 -140
  3. package/dist/accepted-fold.js.map +1 -1
  4. package/dist/accepted-tail.d.ts +3 -3
  5. package/dist/accepted-tail.js +6 -6
  6. package/dist/accepted-tail.js.map +1 -1
  7. package/dist/apply-control.d.ts +9 -4
  8. package/dist/apply-control.js +18 -5
  9. package/dist/apply-control.js.map +1 -1
  10. package/dist/apply-enter-build.d.ts +6 -7
  11. package/dist/apply-enter-build.js +4 -10
  12. package/dist/apply-enter-build.js.map +1 -1
  13. package/dist/apply-enter-plan.d.ts +9 -7
  14. package/dist/apply-enter-plan.js +40 -27
  15. package/dist/apply-enter-plan.js.map +1 -1
  16. package/dist/apply-local-work.d.ts +8 -20
  17. package/dist/apply-local-work.js +18 -95
  18. package/dist/apply-local-work.js.map +1 -1
  19. package/dist/apply-showing.d.ts +15 -1
  20. package/dist/apply-showing.js +26 -4
  21. package/dist/apply-showing.js.map +1 -1
  22. package/dist/apply-window-ground.d.ts +7 -9
  23. package/dist/apply-window-ground.js +16 -11
  24. package/dist/apply-window-ground.js.map +1 -1
  25. package/dist/apply-window-host.d.ts +29 -4
  26. package/dist/apply-window-host.js +212 -280
  27. package/dist/apply-window-host.js.map +1 -1
  28. package/dist/apply-window-line.d.ts +2 -1
  29. package/dist/apply-window-line.js +5 -4
  30. package/dist/apply-window-line.js.map +1 -1
  31. package/dist/apply-window-recovery.js +18 -30
  32. package/dist/apply-window-recovery.js.map +1 -1
  33. package/dist/apply-window-reveal.d.ts +0 -7
  34. package/dist/apply-window-reveal.js +5 -48
  35. package/dist/apply-window-reveal.js.map +1 -1
  36. package/dist/apply-window-rows.d.ts +1 -24
  37. package/dist/apply-window-rows.js.map +1 -1
  38. package/dist/apply-window-saves.d.ts +16 -9
  39. package/dist/apply-window-saves.js +65 -19
  40. package/dist/apply-window-saves.js.map +1 -1
  41. package/dist/apply-window-store.d.ts +6 -6
  42. package/dist/apply-window-store.js +7 -4
  43. package/dist/apply-window-store.js.map +1 -1
  44. package/dist/apply-window-verify.d.ts +4 -7
  45. package/dist/apply-window-verify.js +4 -23
  46. package/dist/apply-window-verify.js.map +1 -1
  47. package/dist/baseline-content.d.ts +3 -5
  48. package/dist/baseline-content.js +7 -44
  49. package/dist/baseline-content.js.map +1 -1
  50. package/dist/content-cache-retention.d.ts +3 -2
  51. package/dist/content-cache-retention.js +11 -11
  52. package/dist/content-cache-retention.js.map +1 -1
  53. package/dist/content-capture-pool.d.ts +4 -47
  54. package/dist/content-capture-pool.js +3 -42
  55. package/dist/content-capture-pool.js.map +1 -1
  56. package/dist/content-capture-worker.d.ts +2 -3
  57. package/dist/content-capture-worker.js +2 -19
  58. package/dist/content-capture-worker.js.map +1 -1
  59. package/dist/declaration-absorption.d.ts +9 -15
  60. package/dist/declaration-absorption.js +14 -32
  61. package/dist/declaration-absorption.js.map +1 -1
  62. package/dist/declaration-commit.d.ts +0 -5
  63. package/dist/declaration-commit.js +1 -6
  64. package/dist/declaration-commit.js.map +1 -1
  65. package/dist/declaration-save.d.ts +0 -4
  66. package/dist/declaration-save.js +0 -4
  67. package/dist/declaration-save.js.map +1 -1
  68. package/dist/detection/accepted-result.js +1 -1
  69. package/dist/detection/accepted-result.js.map +1 -1
  70. package/dist/detection/admission-save.d.ts +7 -17
  71. package/dist/detection/admission-save.js +4 -11
  72. package/dist/detection/admission-save.js.map +1 -1
  73. package/dist/detection/admission-units.d.ts +10 -26
  74. package/dist/detection/admission-units.js +12 -50
  75. package/dist/detection/admission-units.js.map +1 -1
  76. package/dist/detection/apply-ownership.d.ts +2 -2
  77. package/dist/detection/apply-ownership.js +2 -7
  78. package/dist/detection/apply-ownership.js.map +1 -1
  79. package/dist/detection/capture-outcome.js +12 -19
  80. package/dist/detection/capture-outcome.js.map +1 -1
  81. package/dist/detection/dispositions.d.ts +1 -1
  82. package/dist/detection/dispositions.js +3 -4
  83. package/dist/detection/dispositions.js.map +1 -1
  84. package/dist/detection/ground-proof.d.ts +1 -3
  85. package/dist/detection/ground-proof.js +0 -9
  86. package/dist/detection/ground-proof.js.map +1 -1
  87. package/dist/detection/ground-reader.d.ts +1 -5
  88. package/dist/detection/ground-reader.js +1 -31
  89. package/dist/detection/ground-reader.js.map +1 -1
  90. package/dist/detection/notebook-basis.d.ts +1 -2
  91. package/dist/detection/notebook-basis.js +2 -4
  92. package/dist/detection/notebook-basis.js.map +1 -1
  93. package/dist/detection/owed-selection.d.ts +2 -3
  94. package/dist/detection/owed-selection.js +3 -6
  95. package/dist/detection/owed-selection.js.map +1 -1
  96. package/dist/detection/portable.d.ts +7 -48
  97. package/dist/detection/portable.js +46 -155
  98. package/dist/detection/portable.js.map +1 -1
  99. package/dist/detection/repository-state.d.ts +35 -0
  100. package/dist/detection/repository-state.js +51 -0
  101. package/dist/detection/repository-state.js.map +1 -0
  102. package/dist/detection/root-examination.d.ts +1 -11
  103. package/dist/detection/root-examination.js +69 -127
  104. package/dist/detection/root-examination.js.map +1 -1
  105. package/dist/detection/runtime.d.ts +8 -32
  106. package/dist/detection/runtime.js +36 -140
  107. package/dist/detection/runtime.js.map +1 -1
  108. package/dist/detection/scope-frame.d.ts +32 -62
  109. package/dist/detection/scope-frame.js +139 -214
  110. package/dist/detection/scope-frame.js.map +1 -1
  111. package/dist/detection/scoped-identity-port.d.ts +1 -1
  112. package/dist/detection/scoped-identity-port.js +3 -4
  113. package/dist/detection/scoped-identity-port.js.map +1 -1
  114. package/dist/detection/walk-law.d.ts +3 -11
  115. package/dist/detection/walk-law.js +5 -9
  116. package/dist/detection/walk-law.js.map +1 -1
  117. package/dist/git/ground-owners.d.ts +8 -0
  118. package/dist/git/ground-owners.js +25 -0
  119. package/dist/git/ground-owners.js.map +1 -0
  120. package/dist/git/home.d.ts +39 -0
  121. package/dist/git/home.js +81 -0
  122. package/dist/git/home.js.map +1 -0
  123. package/dist/git/marker.d.ts +21 -0
  124. package/dist/git/marker.js +30 -0
  125. package/dist/git/marker.js.map +1 -0
  126. package/dist/git/objects.d.ts +42 -0
  127. package/dist/git/objects.js +144 -0
  128. package/dist/git/objects.js.map +1 -0
  129. package/dist/git/rail.d.ts +90 -0
  130. package/dist/git/rail.js +341 -0
  131. package/dist/git/rail.js.map +1 -0
  132. package/dist/git/read-state.d.ts +21 -0
  133. package/dist/git/read-state.js +143 -0
  134. package/dist/git/read-state.js.map +1 -0
  135. package/dist/git/repository.d.ts +48 -0
  136. package/dist/git/repository.js +110 -0
  137. package/dist/git/repository.js.map +1 -0
  138. package/dist/git/write-files.d.ts +9 -0
  139. package/dist/git/write-files.js +125 -0
  140. package/dist/git/write-files.js.map +1 -0
  141. package/dist/git-binding.d.ts +0 -53
  142. package/dist/git-binding.js +3 -114
  143. package/dist/git-binding.js.map +1 -1
  144. package/dist/git-command.js +11 -2
  145. package/dist/git-command.js.map +1 -1
  146. package/dist/git-index-entries.d.ts +7 -15
  147. package/dist/git-index-entries.js +3 -41
  148. package/dist/git-index-entries.js.map +1 -1
  149. package/dist/git-index-format.d.ts +4 -7
  150. package/dist/git-index-format.js +41 -106
  151. package/dist/git-index-format.js.map +1 -1
  152. package/dist/graph-publication.d.ts +6 -7
  153. package/dist/graph-publication.js +9 -21
  154. package/dist/graph-publication.js.map +1 -1
  155. package/dist/ground-basis.d.ts +1 -37
  156. package/dist/ground-basis.js +5 -162
  157. package/dist/ground-basis.js.map +1 -1
  158. package/dist/ground-database.js +0 -22
  159. package/dist/ground-database.js.map +1 -1
  160. package/dist/ground-install-saves.d.ts +0 -4
  161. package/dist/ground-install-saves.js +0 -4
  162. package/dist/ground-install-saves.js.map +1 -1
  163. package/dist/ground-inventory-schema.js +0 -3
  164. package/dist/ground-inventory-schema.js.map +1 -1
  165. package/dist/ground-marks.d.ts +7 -33
  166. package/dist/ground-marks.js +8 -55
  167. package/dist/ground-marks.js.map +1 -1
  168. package/dist/ground-relations.d.ts +2 -2
  169. package/dist/ground-relations.js +5 -10
  170. package/dist/ground-relations.js.map +1 -1
  171. package/dist/ground-row.d.ts +0 -7
  172. package/dist/ground-row.js +7 -12
  173. package/dist/ground-row.js.map +1 -1
  174. package/dist/ground-save-ops.d.ts +2 -1
  175. package/dist/ground-save-ops.js +2 -1
  176. package/dist/ground-save-ops.js.map +1 -1
  177. package/dist/ground-store.d.ts +0 -10
  178. package/dist/ground-store.js +19 -131
  179. package/dist/ground-store.js.map +1 -1
  180. package/dist/materialize-records.d.ts +19 -20
  181. package/dist/materialize-records.js +123 -244
  182. package/dist/materialize-records.js.map +1 -1
  183. package/dist/materialized-graph.d.ts +3 -22
  184. package/dist/materialized-graph.js +1 -142
  185. package/dist/materialized-graph.js.map +1 -1
  186. package/dist/received-state.d.ts +4 -6
  187. package/dist/received-state.js +6 -11
  188. package/dist/received-state.js.map +1 -1
  189. package/dist/root-install.d.ts +1 -2
  190. package/dist/root-install.js +2 -11
  191. package/dist/root-install.js.map +1 -1
  192. package/dist/sharing-admission.d.ts +1 -2
  193. package/dist/sharing-admission.js +8 -77
  194. package/dist/sharing-admission.js.map +1 -1
  195. package/dist/source-witness.d.ts +1 -7
  196. package/dist/source-witness.js +0 -12
  197. package/dist/source-witness.js.map +1 -1
  198. package/dist/user-ground-host.d.ts +21 -35
  199. package/dist/user-ground-host.js +423 -1484
  200. package/dist/user-ground-host.js.map +1 -1
  201. package/npm-shrinkwrap.json +24 -24
  202. package/package.json +5 -5
  203. package/dist/apply-window-repository.d.ts +0 -97
  204. package/dist/apply-window-repository.js +0 -464
  205. package/dist/apply-window-repository.js.map +0 -1
  206. package/dist/detection/codec-standing.d.ts +0 -27
  207. package/dist/detection/codec-standing.js +0 -86
  208. package/dist/detection/codec-standing.js.map +0 -1
  209. package/dist/detection/git-notice.d.ts +0 -104
  210. package/dist/detection/git-notice.js +0 -483
  211. package/dist/detection/git-notice.js.map +0 -1
  212. package/dist/detection/held-survey.d.ts +0 -39
  213. package/dist/detection/held-survey.js +0 -105
  214. package/dist/detection/held-survey.js.map +0 -1
  215. package/dist/detection/held-territory.d.ts +0 -73
  216. package/dist/detection/held-territory.js +0 -266
  217. package/dist/detection/held-territory.js.map +0 -1
  218. package/dist/detection/name-reach.d.ts +0 -12
  219. package/dist/detection/name-reach.js +0 -28
  220. package/dist/detection/name-reach.js.map +0 -1
  221. package/dist/detection/own-channel.d.ts +0 -17
  222. package/dist/detection/own-channel.js +0 -31
  223. package/dist/detection/own-channel.js.map +0 -1
  224. package/dist/detection/repository-publication.d.ts +0 -22
  225. package/dist/detection/repository-publication.js +0 -81
  226. package/dist/detection/repository-publication.js.map +0 -1
  227. package/dist/detection/repository-routes.d.ts +0 -50
  228. package/dist/detection/repository-routes.js +0 -118
  229. package/dist/detection/repository-routes.js.map +0 -1
  230. package/dist/detection/repository-seals.d.ts +0 -98
  231. package/dist/detection/repository-seals.js +0 -145
  232. package/dist/detection/repository-seals.js.map +0 -1
  233. package/dist/detection/seal-law.d.ts +0 -59
  234. package/dist/detection/seal-law.js +0 -103
  235. package/dist/detection/seal-law.js.map +0 -1
  236. package/dist/git-capture.d.ts +0 -47
  237. package/dist/git-capture.js +0 -153
  238. package/dist/git-capture.js.map +0 -1
  239. package/dist/git-card.d.ts +0 -30
  240. package/dist/git-card.js +0 -136
  241. package/dist/git-card.js.map +0 -1
  242. package/dist/git-checkpoint-construction.d.ts +0 -54
  243. package/dist/git-checkpoint-construction.js +0 -126
  244. package/dist/git-checkpoint-construction.js.map +0 -1
  245. package/dist/git-checkpoint-preparation.d.ts +0 -47
  246. package/dist/git-checkpoint-preparation.js +0 -201
  247. package/dist/git-checkpoint-preparation.js.map +0 -1
  248. package/dist/git-configuration.d.ts +0 -53
  249. package/dist/git-configuration.js +0 -238
  250. package/dist/git-configuration.js.map +0 -1
  251. package/dist/git-evidence.d.ts +0 -50
  252. package/dist/git-evidence.js +0 -114
  253. package/dist/git-evidence.js.map +0 -1
  254. package/dist/git-facts.d.ts +0 -2
  255. package/dist/git-facts.js +0 -35
  256. package/dist/git-facts.js.map +0 -1
  257. package/dist/git-index-witness.d.ts +0 -34
  258. package/dist/git-index-witness.js +0 -85
  259. package/dist/git-index-witness.js.map +0 -1
  260. package/dist/git-literal-batch.d.ts +0 -82
  261. package/dist/git-literal-batch.js +0 -152
  262. package/dist/git-literal-batch.js.map +0 -1
  263. package/dist/git-literal-host.d.ts +0 -76
  264. package/dist/git-literal-host.js +0 -185
  265. package/dist/git-literal-host.js.map +0 -1
  266. package/dist/git-literal-read.d.ts +0 -74
  267. package/dist/git-literal-read.js +0 -186
  268. package/dist/git-literal-read.js.map +0 -1
  269. package/dist/git-literal-replay.d.ts +0 -83
  270. package/dist/git-literal-replay.js +0 -393
  271. package/dist/git-literal-replay.js.map +0 -1
  272. package/dist/git-native-file.d.ts +0 -42
  273. package/dist/git-native-file.js +0 -145
  274. package/dist/git-native-file.js.map +0 -1
  275. package/dist/git-native-index.d.ts +0 -27
  276. package/dist/git-native-index.js +0 -44
  277. package/dist/git-native-index.js.map +0 -1
  278. package/dist/git-operation-host.d.ts +0 -42
  279. package/dist/git-operation-host.js +0 -115
  280. package/dist/git-operation-host.js.map +0 -1
  281. package/dist/git-private-repository.d.ts +0 -4
  282. package/dist/git-private-repository.js +0 -66
  283. package/dist/git-private-repository.js.map +0 -1
  284. package/dist/git-private-view.d.ts +0 -72
  285. package/dist/git-private-view.js +0 -318
  286. package/dist/git-private-view.js.map +0 -1
  287. package/dist/git-records.d.ts +0 -29
  288. package/dist/git-records.js +0 -119
  289. package/dist/git-records.js.map +0 -1
  290. package/dist/git-ref-store.d.ts +0 -12
  291. package/dist/git-ref-store.js +0 -68
  292. package/dist/git-ref-store.js.map +0 -1
  293. package/dist/git-registration-host.d.ts +0 -42
  294. package/dist/git-registration-host.js +0 -98
  295. package/dist/git-registration-host.js.map +0 -1
  296. package/dist/git-repository-host.d.ts +0 -291
  297. package/dist/git-repository-host.js +0 -1291
  298. package/dist/git-repository-host.js.map +0 -1
  299. package/dist/git-spelling.d.ts +0 -41
  300. package/dist/git-spelling.js +0 -233
  301. package/dist/git-spelling.js.map +0 -1
  302. package/dist/git-tree-objects.d.ts +0 -22
  303. package/dist/git-tree-objects.js +0 -205
  304. package/dist/git-tree-objects.js.map +0 -1
  305. package/dist/git-worktree-host.d.ts +0 -2
  306. package/dist/git-worktree-host.js +0 -16
  307. package/dist/git-worktree-host.js.map +0 -1
  308. package/dist/ground-territory.d.ts +0 -106
  309. package/dist/ground-territory.js +0 -340
  310. package/dist/ground-territory.js.map +0 -1
  311. package/dist/repository-checkpoint-file.d.ts +0 -20
  312. package/dist/repository-checkpoint-file.js +0 -129
  313. package/dist/repository-checkpoint-file.js.map +0 -1
  314. package/dist/repository-statement.d.ts +0 -21
  315. package/dist/repository-statement.js +0 -33
  316. package/dist/repository-statement.js.map +0 -1
  317. package/dist/reveal-owner.d.ts +0 -16
  318. package/dist/reveal-owner.js +0 -74
  319. package/dist/reveal-owner.js.map +0 -1
@@ -14,12 +14,12 @@
14
14
  * - Verify (#verify): one reread of real ground, its rows staged for the end;
15
15
  * - the durability point (apply-durability.ts), owed where the window placed
16
16
  * its results, runs at idle or at the cap. */
17
- import { chmodSync, copyFileSync, lstatSync, readFileSync, readdirSync, readlinkSync, rmSync } from "node:fs";
18
- import { rm } from "node:fs/promises";
17
+ import { chmodSync, copyFileSync, lstatSync, readFileSync, readdirSync, readlinkSync, rmSync, writeFileSync } from "node:fs";
18
+ import { readFile, rm } from "node:fs/promises";
19
19
  import { basename, dirname, join, relative } from "node:path";
20
- import { CONTAINERS, buildEntityApplyEffects, isRefusal, portableFileMode, repositoryPayloadVersion, repositoryApplyTerritory, repositorySharesWorktreeStorage, resolvedPrefix, revealOrder } from "@amalgm/live";
20
+ import { CONTAINERS, buildEntityApplyEffects, classifyFile, isRefusal, portableFileMode, resolvedPrefix, revealOrder } from "@amalgm/live";
21
21
  import { LOCAL_DIR_NAME } from "@amalgm/core/identity";
22
- import { applyControlRoot, displacedGitPath, displacedPath, enterControl, ensureApplyPrivate, judgeBoundRoot, stagedPath, windowControl } from "./apply-control.js";
22
+ import { applyControlRoot, displacedGitPath, displacedPath, enterControl, ensureApplyPrivate, gitPartPath, judgeBoundRoot, readGitPart, stagedPath, windowControl } from "./apply-control.js";
23
23
  import { ApplyDurability } from "./apply-durability.js";
24
24
  import { keepRemainder, returnKept, topmostRemainder, vacateKept } from "./apply-kept.js";
25
25
  import { flushEach } from "./flush.js";
@@ -27,41 +27,46 @@ import { WindowCargo } from "./apply-window-cargo.js";
27
27
  import { boundEnter, enterStaging, prepareEnter, sealShows } from "./apply-enter-build.js";
28
28
  import { divideEnter, entersContainer, readEnterClosure } from "./apply-enter-plan.js";
29
29
  import { captureGitStorage, displaceGitStorage, keptStorageIsO } from "./apply-git-storage.js";
30
- import { GitCapture } from "./git-capture.js";
31
- import { ShownGround } from "./apply-showing.js";
30
+ import { NOTHING_ON_DEMAND, ShownGround } from "./apply-showing.js";
32
31
  import { holds, moveWithoutReplacing, occupiedByOther, standing } from "./apply-spelling.js";
33
32
  import { ApplyWindowStore } from "./apply-window-store.js";
34
33
  import { heldCovers, isContainerType, meetsAny, placedByBinding, tryLstat, WindowGround } from "./apply-window-ground.js";
35
34
  import { containerGround, enterGround, leaveGround, receiptStats, readVerificationFacts, roomRows, verifiedRow } from "./apply-window-verify.js";
36
- import { RepositoryGround, repositoryArtifact, repositoryMembers } from "./apply-window-repository.js";
37
35
  import { boundAttempts, readEndedWindows, readWindow } from "./apply-window-rows.js";
38
36
  import { recoveryVerdict } from "./apply-window-recovery.js";
39
- import { relocateGroups, replaceAt, stageDirectory, takeSource } from "./apply-window-reveal.js";
37
+ import { replaceAt, stageDirectory, takeSource } from "./apply-window-reveal.js";
40
38
  import { constructApplyAdapters } from "./construct-apply-host.js";
41
39
  import { ConstructLedger } from "./construct-ledger.js";
42
40
  import { contentCacheOwnership } from "./content-cache-ownership.js";
41
+ import { captureContent } from "./content-capture-pool.js";
43
42
  import { stampAfterWrites } from "./content-clock.js";
44
43
  import { DerivedRelocationCycle, relocateDerived } from "./derived-relocation.js";
45
44
  import { ApplyOwnershipSnapshot, ownedObject, ownershipWait, sqliteApplyOwnership, windowFootprint } from "./detection/apply-ownership.js";
46
45
  import { settledCaptureOutcome } from "./detection/capture-outcome.js";
46
+ import { cachedNotebook } from "./detection/repository-state.js";
47
47
  import { ensureDirBeneath } from "./filesystem.js";
48
48
  import { reflogKeys, repositoryGroundCones } from "./git-binding.js";
49
- import { observeLiteralPath } from "./git-literal-host.js";
50
- import { leafPayload, payloadFormat, sameCodec } from "./git-literal-read.js";
51
- import { planWorkingReveal, RepositoryGroundObstructed } from "./git-literal-replay.js";
52
- import { unsupportedGitOperation, UnsupportedGitOperationError } from "./git-operation-host.js";
53
- import { applyRepositoryFiles, hasGitMarker, cachedRepositoryIdentity, repositoryRevealRefusal } from "./git-repository-host.js";
54
- import { inspectGitWorktreeStorage } from "./git-worktree-host.js";
49
+ import { hasGitMarker } from "./git/marker.js";
50
+ import { groundGitOwners } from "./git/ground-owners.js";
51
+ import { applyGit, GitApplyWait, gitStateIdOf } from "./git/rail.js";
55
52
  import { openGroundConnection } from "./ground-database.js";
56
53
  import { portableGroundRecord as portable } from "./ground-row.js";
57
- import { writeLinkTarget } from "./link-target.js";
54
+ import { readLinkTarget, writeLinkTarget } from "./link-target.js";
58
55
  import { addressWitness, optionalLstat, PhysicalPathWitnesses } from "./physical-path-witness.js";
59
56
  import { HeldHeads, ReceivedStateUnavailableError } from "./received-state.js";
60
- import { revealStorageOf, revealStoragePhysical } from "./reveal-owner.js";
61
57
  import { sha256Hex } from "./sha256.js";
62
58
  import { closePhysically, closeSource, sourceProofs, witnessProof } from "./source-proof.js";
63
59
  import { physicalKey, sourceReusable, sourceSignature } from "./source-signature.js";
64
60
  import { awaitTurn } from "./turns.js";
61
+ /** The immutable artifact a repository or structural result names, if any. */
62
+ const resultArtifact = (plan) => plan.kind === "repo.git" ? plan.artifact : plan.kind === "structure" ? plan.resultArtifact : null;
63
+ /** Apply cannot act on a repository yet (src/git/rail.ts). A worktree or
64
+ * submodule waits on the repository whose Git directory holds its own, whose
65
+ * Apply releases it; any other wait, on a change there, which Detect
66
+ * observes. */
67
+ const gitWait = (intent, error) => ({ kind: "dependency", reason: error.message, waitFor: error.owner
68
+ ? { producer: "apply", entityIds: [error.owner] }
69
+ : { producer: "capability", entityIds: [intent.entityId] } });
65
70
  const objectOf = (path, stats) => ({ path, physicalKey: physicalKey(stats), signature: sourceSignature(stats) });
66
71
  /** The member's kind, from its plan. */
67
72
  const kindOf = (plan) => {
@@ -85,7 +90,6 @@ const kindOf = (plan) => {
85
90
  const declined = (reason) => ({ kind: "declined", reason });
86
91
  /** The receipts whose reveal can take a container from its address. */
87
92
  const DISPLACING = new Set(["leave", "leaf", "link", "reference"]);
88
- const isWait = (value) => "kind" in value && value.kind === "dependency";
89
93
  /** One persistent machine-effect owner for the Apply rail lifetime. */
90
94
  export class ApplyWindowHost {
91
95
  store;
@@ -103,14 +107,20 @@ export class ApplyWindowHost {
103
107
  #acquireGround;
104
108
  #onStage;
105
109
  #onWindowEnded;
110
+ #onDemand;
111
+ /** The units something opened, each answered once its line ends it, and
112
+ * the wake that rings that line. */
113
+ #opening = new Map();
106
114
  #now;
107
115
  #ground;
116
+ /** The repositories this machine holds, where worktrees and submodules
117
+ * find the Git directory that holds their own (src/git/home.ts). */
118
+ #gitOwners;
108
119
  #onDerivedRelocationStage;
109
120
  #prepared = new Map();
110
121
  #enterClosures = new Map();
111
122
  /** The ground the window in flight holds. */
112
123
  #held = null;
113
- #repository;
114
124
  /** The Git storage manifest a final guard took before proving a repository
115
125
  * is O, for the receipt the same pass freezes. */
116
126
  #gitStorage = new Map();
@@ -123,10 +133,12 @@ export class ApplyWindowHost {
123
133
  // Read-only: the file's saver thread makes every write this host posts.
124
134
  this.#database = openGroundConnection(options.databaseFile);
125
135
  this.#now = options.now ?? Date.now;
136
+ this.#onDemand = { root: options.onDemand ?? NOTHING_ON_DEMAND.root, opened: uuid => this.#opening.has(uuid) };
126
137
  this.durability = new ApplyDurability({ databaseFile: options.databaseFile,
127
138
  ...(options.onBackgroundError ? { onError: options.onBackgroundError } : {}) });
128
139
  this.store = new ApplyWindowStore(this.#database, {
129
140
  now: this.#now,
141
+ onDemand: this.#onDemand,
130
142
  onEnded: (intent, members) => this.#ended(intent, members),
131
143
  // Not a failure: the line proves again at its next fair turn.
132
144
  onStale: (members, reason) => {
@@ -144,18 +156,12 @@ export class ApplyWindowHost {
144
156
  readAhead: (authorityId, after, limit) => this.store.readApplyAhead(authorityId, after, limit),
145
157
  fetch: async (wants) => { await this.#cargo.read(wants); },
146
158
  };
147
- this.#heads = new HeldHeads(options.readGraphPage, cachedRepositoryIdentity(this.#cacheDir, artifacts => this.#cargo.read(artifacts.map(artifact => ({ artifact })))));
159
+ this.#heads = new HeldHeads(options.readGraphPage);
148
160
  this.#acquireGround = options.acquireGround;
149
161
  this.#onStage = options.onStage;
150
162
  this.#onWindowEnded = options.onWindowEnded;
151
163
  this.#ground = new WindowGround(this.#database);
152
- this.#repository = new RepositoryGround(this.#ground, options.cacheDir, {
153
- matches: (intent, record, path, plan) => this.#matches(intent, record, path, plan),
154
- prepared: (intent, plan) => this.#ensurePrepared(intent, plan),
155
- receiptOf: intent => this.#receiptOf(intent),
156
- readOne: artifact => this.#cargo.readOne(artifact),
157
- key: intent => this.#key(intent),
158
- });
164
+ this.#gitOwners = groundGitOwners(this.#database);
159
165
  this.#onDerivedRelocationStage = options.onDerivedRelocationStage;
160
166
  // Every type in Live's alphabet binds both sockets or the registry
161
167
  // refuses to build. Filesystem entities reread their native ground;
@@ -255,11 +261,21 @@ export class ApplyWindowHost {
255
261
  });
256
262
  }
257
263
  // ---------------------------------------------------------------- prepare
264
+ /** A repository in an Enter that cannot be built yet, such as a linked
265
+ * worktree whose main checkout's Apply has yet to bring its objects,
266
+ * waits on it, so the window ends before it (journey.ts). */
258
267
  async #prepare(intent, plan) {
259
- if (entersContainer(plan))
260
- await this.#prepareEnter(intent, plan);
261
- else
262
- await this.#ensurePrepared(intent, plan);
268
+ try {
269
+ if (entersContainer(plan))
270
+ await this.#prepareEnter(intent, plan);
271
+ else
272
+ await this.#ensurePrepared(intent, plan);
273
+ }
274
+ catch (error) {
275
+ if (error instanceof GitApplyWait)
276
+ return gitWait(intent, error);
277
+ throw error;
278
+ }
263
279
  }
264
280
  async #ensurePrepared(intent, plan) {
265
281
  const key = this.#key(intent);
@@ -274,24 +290,12 @@ export class ApplyWindowHost {
274
290
  }
275
291
  this.#emit(intent, plan, "preparation-started");
276
292
  let prepared = {};
277
- const repository = repositoryArtifact(plan);
278
- if (repository) {
279
- const chain = await this.#repository.chain(repository);
280
- const latest = chain.links.at(-1).layout;
281
- if (repositoryPayloadVersion(latest, sha256Hex) !== plan.target.payloadVersion
282
- || (plan.kind === "repo.git" && (latest.stateId !== plan.stateId
283
- || latest.cardId !== plan.cardId || latest.checkpointId !== plan.checkpointId
284
- || latest.identityHash !== plan.identityHash
285
- || latest.parentTransportVersion !== plan.parentTransportVersion))) {
286
- throw new Error("repository package does not describe the accepted complete result");
287
- }
288
- prepared = { repository: { ...chain, objectFormat: latest.card.objectFormat } };
289
- }
290
- else if (plan.kind === "file.text" || plan.kind === "file.binary" || plan.kind === "link") {
293
+ const artifact = resultArtifact(plan);
294
+ if (plan.kind === "file.text" || plan.kind === "file.binary" || plan.kind === "link") {
291
295
  prepared = { artifact: await this.#cargo.prepare(plan) };
292
296
  }
293
- else if (plan.kind === "structure" && plan.resultArtifact) {
294
- prepared = { artifact: await this.#cargo.sealed(plan.resultArtifact.contentHash) ?? await this.#cargo.readOne(plan.resultArtifact) };
297
+ else if (artifact) {
298
+ prepared = { artifact: await this.#cargo.sealed(artifact.contentHash) ?? await this.#cargo.readOne(artifact) };
295
299
  }
296
300
  this.#prepared.set(key, prepared);
297
301
  this.#emit(intent, plan, "cargo-verified");
@@ -329,8 +333,8 @@ export class ApplyWindowHost {
329
333
  targetPath: context.targetPath },
330
334
  clockRoot: this.#ground.bindingRoot(context),
331
335
  databaseFile: this.#database.name,
332
- cacheDir: this.#cacheDir,
333
336
  bindingDir: this.#bindingDir,
337
+ held: this.#gitOwners,
334
338
  readContent: artifacts => this.#cargo.read(artifacts.map(artifact => ({ artifact }))),
335
339
  });
336
340
  this.#emit(intent, plan, "cargo-verified");
@@ -342,7 +346,8 @@ export class ApplyWindowHost {
342
346
  const key = this.#key(intent);
343
347
  let closure = this.#enterClosures.get(key);
344
348
  if (!closure) {
345
- closure = await readEnterClosure({ database: this.#database, intent, target: plan.target, heads: this.#heads });
349
+ closure = await readEnterClosure({ database: this.#database, intent, target: plan.target, heads: this.#heads,
350
+ unit: new ShownGround(this.#database, this.#onDemand).beneathOnDemand(plan.target) });
346
351
  this.#enterClosures.set(key, closure);
347
352
  }
348
353
  const division = await divideEnter(closure.records, plan.target.uuid, uuid => this.#ground.current(uuid) !== null);
@@ -353,7 +358,6 @@ export class ApplyWindowHost {
353
358
  this.#prepared.delete(key);
354
359
  this.#enterClosures.delete(key);
355
360
  this.#gitStorage.delete(key);
356
- this.#repository.forget(key);
357
361
  }
358
362
  // ------------------------------------------------------------------ guard
359
363
  /** Only a final safe or already-target guard keeps its member in the window. */
@@ -373,7 +377,6 @@ export class ApplyWindowHost {
373
377
  async #inspectGround(intent, plan, stage) {
374
378
  const finalGuard = stage === "final";
375
379
  const key = this.#key(intent);
376
- this.#repository.forget(key);
377
380
  this.#gitStorage.delete(key);
378
381
  try {
379
382
  if (finalGuard) {
@@ -387,7 +390,7 @@ export class ApplyWindowHost {
387
390
  }
388
391
  // The line judged this play from the tables, and Detect may have
389
392
  // changed them since: a play that no longer holds is judged again.
390
- const judged = new ShownGround(this.#database).judge(plan.target);
393
+ const judged = new ShownGround(this.#database, this.#onDemand).judge(plan.target);
391
394
  if (judged !== plan.play) {
392
395
  return { kind: "rejudge", reason: `The accepted result now plays ${judged} on this computer, not ${plan.play}.` };
393
396
  }
@@ -417,9 +420,6 @@ export class ApplyWindowHost {
417
420
  .every(row => row === null || row === undefined || this.#ground.directoryAncestorsMatch(row, directories))) {
418
421
  return replacedParent;
419
422
  }
420
- let repositoryTargetMatches = false;
421
- let repositoryRelocationsPending = false;
422
- let repositoryIdentityMatches = true;
423
423
  // A reveal installs the repository's own `.git` where the entity
424
424
  // stands. A `.git` there that names no repository exists only on this
425
425
  // computer, so the reveal waits until the person removes or repairs it.
@@ -429,68 +429,18 @@ export class ApplyWindowHost {
429
429
  blocker: { code: "local-ground-would-be-displaced", effect: "repository-reveal" },
430
430
  reason: `${current.absolutePath} holds Git metadata that names no repository; only this computer has it.` };
431
431
  }
432
- if (plan.target.type === "repo.git" || current?.type === "repo.git") {
433
- for (const path of new Set([context.targetPath, current?.absolutePath].filter((path) => path !== undefined))) {
434
- if (!hasGitMarker(path))
435
- continue;
436
- const storage = await inspectGitWorktreeStorage(path);
437
- const unsupported = unsupportedGitOperation(storage.privateDirectory);
438
- if (unsupported) {
439
- return { kind: "dependency", reason: new UnsupportedGitOperationError(unsupported).message,
440
- waitFor: { producer: "capability", entityIds: [intent.entityId] } };
441
- }
442
- if (repositorySharesWorktreeStorage(storage)) {
443
- return { kind: "dependency",
444
- reason: "This checkout shares Git storage with another worktree. Apply requires an independent checkout.",
445
- waitFor: { producer: "capability", entityIds: [intent.entityId] },
446
- };
447
- }
448
- }
449
- }
450
- if (entersContainer(plan)) {
432
+ if (entersContainer(plan) && finalGuard) {
433
+ // The build assumed the ground's division and its address. A build
434
+ // that no longer shows them is dropped and built again by the next
435
+ // attempt.
451
436
  const { closure, division } = await this.#enterDivision(intent, plan);
452
- if (finalGuard) {
453
- // The build assumed the ground's division, its address and its
454
- // relocation sources. A build that no longer shows them is dropped
455
- // and built again by the next attempt.
456
- const enter = this.#prepared.get(key)?.enter;
457
- if (!enter || !holds(enter.tree, enter.seal.root) || !sealShows(enter.seal, { target: plan.target,
458
- position: closure.position, leftOut: division.leftOut, targetPath: context.targetPath })) {
459
- this.#prepared.delete(key);
460
- return { kind: "retry", reason: "The entering tree no longer shows this computer's ground; it is built again." };
461
- }
462
- for (const group of this.#repository.enterRelocations(context.targetPath, enter)) {
463
- for (const row of group.rows) {
464
- if (!await this.#matches(intent, portable(row), row.absolutePath, plan)) {
465
- return { kind: "retry", reason: `repository relocation ${row.uuid} changed before Apply` };
466
- }
467
- }
468
- }
437
+ const enter = this.#prepared.get(key)?.enter;
438
+ if (!enter || !holds(enter.tree, enter.seal.root) || !sealShows(enter.seal, { target: plan.target,
439
+ position: closure.position, leftOut: division.leftOut, targetPath: context.targetPath })) {
440
+ this.#prepared.delete(key);
441
+ return { kind: "retry", reason: "The entering tree no longer shows this computer's ground; it is built again." };
469
442
  }
470
443
  }
471
- else if (plan.target.type === "repo.git" && !leaving) {
472
- const repository = (await this.#ensurePrepared(intent, plan)).repository;
473
- if (!repository)
474
- throw new Error("repository Apply has no prepared transport identity");
475
- // The result acts only on its territory, so ground another rail owns
476
- // here never waits on that rail's later record (docs/entity-apply.md).
477
- const territory = this.#repository.territory(intent, repository.identity, context.current);
478
- const ground = current && tryLstat(current.absolutePath) ? current.absolutePath : context.targetPath;
479
- const refused = await repositoryRevealRefusal(ground, root, repository.objectFormat, !hasGitMarker(ground));
480
- if (refused)
481
- return { kind: "dependency", reason: refused, waitFor: { producer: "capability", entityIds: [intent.entityId] } };
482
- const groups = this.#repository.relocations(context, territory.identity);
483
- for (const group of groups) {
484
- for (const row of group.rows) {
485
- if (!await this.#matches(intent, portable(row), row.absolutePath, plan)) {
486
- return { kind: "retry", reason: `repository relocation ${row.uuid} changed before Apply` };
487
- }
488
- }
489
- }
490
- repositoryRelocationsPending = groups.length > 0;
491
- repositoryIdentityMatches = this.#repository.identityMatches(intent, context.targetPath, repository.identity);
492
- repositoryTargetMatches = current !== null && await this.#matches(intent, plan.target, context.targetPath, plan);
493
- }
494
444
  // Identity comes from O, never a historical sharing address or byte
495
445
  // equality. A same-identity complete target can be adopted even when B
496
446
  // lags, provided no other physical effect remains. A Leave's target
@@ -501,10 +451,8 @@ export class ApplyWindowHost {
501
451
  && physical.absolutePath === context.targetPath
502
452
  && targetStats !== null && physicalKey(targetStats) === physical.physicalKey;
503
453
  if (targetIdentity
504
- && repositoryIdentityMatches
505
- && !repositoryRelocationsPending
506
454
  && context.room.length === 0
507
- && (repositoryTargetMatches || await this.#matches(intent, plan.target, context.targetPath, plan))
455
+ && await this.#matches(intent, plan.target, context.targetPath, plan)
508
456
  && this.#ground.physicalDirectoriesMatch(physical, directories)) {
509
457
  if (!this.#ground.directoriesStand(directories))
510
458
  return replacedParent;
@@ -512,8 +460,6 @@ export class ApplyWindowHost {
512
460
  const receipt = await this.#receipt(intent, plan, context, "already-target");
513
461
  if (receipt === null)
514
462
  return { kind: "local-change", reason: "The ground this member stands on changed after its guard." };
515
- if (isWait(receipt))
516
- return receipt;
517
463
  this.store.stageReceipt(receipt);
518
464
  }
519
465
  return { kind: "already-target" };
@@ -532,13 +478,13 @@ export class ApplyWindowHost {
532
478
  // effect waits for Detect to see that ground leave or become shared.
533
479
  if (current && isContainerType(current.type) && tryLstat(current.absolutePath)
534
480
  && (leaving || !isContainerType(plan.target.type))) {
535
- const named = this.#repository.unsharedGitMetadata(current);
481
+ const named = this.#ground.unsharedGitWithin(current.absolutePath);
536
482
  if (named.length > 0) {
537
483
  return { kind: "dependency", waitFor: { producer: "detect", entityIds: named },
538
484
  blocker: { code: "local-ground-would-be-displaced", effect: leaving ? "leave" : "replace-container" },
539
485
  reason: `${current.absolutePath} holds local ground sharing never held; removing it would destroy that ground.` };
540
486
  }
541
- const publishing = this.#repository.pendingPublication(intent.authorityId, current);
487
+ const publishing = this.#ground.pendingWithin(intent.authorityId, current);
542
488
  if (publishing.length > 0) {
543
489
  return { kind: "dependency", waitFor: { producer: "send", entityIds: publishing },
544
490
  reason: `${current.absolutePath} holds local results not yet sequenced; removing it would hide them.` };
@@ -548,9 +494,6 @@ export class ApplyWindowHost {
548
494
  return { kind: "local-change", reason: "A required sibling relocation has unproved ground." };
549
495
  }
550
496
  let safe;
551
- // The source already shows the target's exact package, every member
552
- // where its map places it.
553
- let showsTarget = false;
554
497
  if (!current) {
555
498
  safe = !tryLstat(context.targetPath) ? { kind: "safe" } : await this.#occupiedDestination(intent, plan, context);
556
499
  }
@@ -575,58 +518,43 @@ export class ApplyWindowHost {
575
518
  && (plan.target.type === "workspace" || plan.target.type === "folder") && hasGitMarker(current.absolutePath)) {
576
519
  this.#gitStorage.set(key, await captureGitStorage(current.absolutePath));
577
520
  }
578
- // A repository's ground is safe when it shows what this computer
579
- // expects of it (#showsExpected); anything else is a person's change.
580
- const shared = current.type === "repo.git" ? this.#ground.shared(current.uuid) : undefined;
581
- let shows;
582
- if (shared?.status === "active" && shared.type === "repo.git") {
583
- const showing = await this.#repository.showsExpected(intent, plan, current, shared);
584
- shows = showing !== null;
585
- showsTarget = showing === "package" && plan.target.type === "repo.git"
586
- && shared.payloadVersion === plan.target.payloadVersion && shared.transportVersion === plan.target.transportVersion;
587
- }
588
- else {
589
- shows = await this.#matches(intent, portable(shared?.status === "active" ? shared : current), current.absolutePath, plan);
590
- }
591
- safe = shows && this.#ground.physicalDirectoriesMatch(current, directories) ? { kind: "safe" } : { kind: "local-change" };
521
+ // The ground is safe while it shows what this computer last observed
522
+ // there, its O row; anything else is a person's change, which Detect
523
+ // records before Apply looks again.
524
+ safe = await this.#matches(intent, portable(current), current.absolutePath, plan)
525
+ && this.#ground.physicalDirectoriesMatch(current, directories) ? { kind: "safe" } : { kind: "local-change" };
592
526
  }
593
527
  if (safe.kind === "safe" && !this.#ground.directoriesStand(directories))
594
528
  return replacedParent;
595
529
  if (safe.kind === "safe" && finalGuard) {
596
- const receipt = await this.#receipt(intent, plan, context, "safe", showsTarget);
530
+ const receipt = await this.#receipt(intent, plan, context, "safe");
597
531
  if (receipt === null)
598
532
  return { kind: "local-change", reason: "The ground this member would reveal over changed after its guard." };
599
- if (isWait(receipt))
600
- return receipt;
601
533
  this.store.stageReceipt(receipt);
602
534
  }
603
535
  return safe;
604
536
  }
605
537
  catch (error) {
606
- if (error instanceof UnsupportedGitOperationError) {
607
- return { kind: "dependency", reason: error.message, waitFor: { producer: "capability", entityIds: [intent.entityId] } };
608
- }
538
+ if (error instanceof GitApplyWait)
539
+ return gitWait(intent, error);
609
540
  // No kept graph head reaches the Enter's position yet: the line holds.
610
541
  if (error instanceof ReceivedStateUnavailableError)
611
542
  return { kind: "dependency", reason: error.message };
612
543
  throw error;
613
544
  }
614
545
  finally {
615
- if (!finalGuard) {
616
- this.#repository.forget(key);
546
+ if (!finalGuard)
617
547
  this.#emit(intent, plan, "preflight-finished");
618
- }
619
548
  }
620
549
  }
621
550
  /**
622
551
  * The member's receipt, frozen from the ground its final guard proved:
623
552
  * its address, its binding root, the object it reveals over, the object it
624
- * stages, the sibling moves that free its address, the ground a parcel or
625
- * an Enter relocates, a repository reveal's plan, and where its history
626
- * stood. Null when the source a person replaced since the guard: nothing
627
- * binds for it. A dependency is a repository obstruction.
553
+ * stages, the sibling moves that free its address, and a former
554
+ * repository's Git storage. Null when a person replaced the source since
555
+ * the guard: nothing binds for it.
628
556
  */
629
- async #receipt(intent, plan, context, look, showsTarget = false) {
557
+ async #receipt(intent, plan, context, look) {
630
558
  const key = this.#key(intent);
631
559
  const anchor = context.current ?? context.parent;
632
560
  if (!anchor)
@@ -645,11 +573,7 @@ export class ApplyWindowHost {
645
573
  throw new Error("Apply room move has no physical identity");
646
574
  return { uuid: physical.uuid, source: from, destination, physicalKey: physical.physicalKey };
647
575
  });
648
- const relocation = (group) => ({ uuid: group.sourceRoot.uuid,
649
- source: group.sourceRoot.absolutePath, physicalKey: group.sourceRoot.physicalKey });
650
576
  let staged = null;
651
- let repository = null;
652
- let relocated = [];
653
577
  if (look === "safe") {
654
578
  if (kind === "leaf" || kind === "link" || kind === "reference") {
655
579
  const path = await this.#stageResult(intent, plan, context, control);
@@ -660,43 +584,12 @@ export class ApplyWindowHost {
660
584
  if (!enter)
661
585
  throw new Error("container Enter binds without its prepared tree");
662
586
  staged = objectOf(enter.tree, lstatSync(enter.tree, { bigint: true }));
663
- relocated = this.#repository.enterRelocations(context.targetPath, enter).map(relocation);
664
- }
665
- else if (kind === "repository") {
666
- const chain = prepared?.repository;
667
- if (!chain)
668
- throw new Error("repository Apply has no prepared transport chain");
669
- const basis = await this.#repository.revealBasis(context);
670
- const kept = basis?.unstated ?? [];
671
- let removals = { leaves: [], directories: [] }, standing = [];
672
- if (context.current && sourceStats) {
673
- standing = this.#repository.elsewhere(context.current, chain.identity);
674
- try {
675
- removals = planWorkingReveal(context.current.absolutePath, repositoryApplyTerritory(chain.identity, standing), basis?.held ?? [], new Set(kept.map(entry => entry.path)));
676
- }
677
- catch (error) {
678
- if (!(error instanceof RepositoryGroundObstructed))
679
- throw error;
680
- return this.#repository.obstructed(context.current, error);
681
- }
682
- }
683
- const sourcePath = source?.path ?? null;
684
- const storage = sourcePath === null || !hasGitMarker(sourcePath) ? null : revealStorageOf(sourcePath);
685
- // Only a self-contained checkout moves whole: its own `.git`
686
- // directory, nothing to remove around the package it shows, and no
687
- // configured worktree, which would leave Git reading the old place.
688
- const shown = showsTarget && sourcePath !== null && tryLstat(join(sourcePath, ".git"))?.isDirectory() === true
689
- && removals.leaves.length === 0 && removals.directories.length === 0
690
- && !(await new GitCapture(sourcePath).configuration()).has("core.worktree");
691
- repository = { removals, standing, remainder: kept, storage: storage === null ? null : revealStoragePhysical(storage), shown };
692
- relocated = this.#repository.relocations(context, repositoryApplyTerritory(chain.identity, standing).identity).map(relocation);
693
587
  }
694
588
  }
695
589
  return {
696
590
  intent, target: plan.target, kind, look, address: context.targetPath,
697
591
  root: { path: root.absolutePath, physicalKey: root.physicalKey }, control,
698
- source, staged, room, relocated, repository,
699
- gitStorage: this.#gitStorage.get(key) ?? null,
592
+ source, staged, room, gitStorage: this.#gitStorage.get(key) ?? null,
700
593
  };
701
594
  }
702
595
  /** A file or link result staged at its vacant private address, with its
@@ -769,12 +662,6 @@ export class ApplyWindowHost {
769
662
  * cones discovered after acquisition without proving them again. */
770
663
  async #hold(intent, plans) {
771
664
  const members = intent.members.map((member, index) => ({ intent: member, plan: plans[index] }));
772
- // Immutable identity determines a repository's relocation cones. Load it
773
- // before acquiring ground, including after restart with an empty cache.
774
- for (const { intent: member, plan } of members) {
775
- if (plan.target.type === "repo.git" && plan.kind !== "leave" && !entersContainer(plan))
776
- await this.#ensurePrepared(member, plan);
777
- }
778
665
  const cones = () => [...new Set(members.flatMap(({ intent: member, plan }) => this.#groundCones(member, plan)))];
779
666
  const reflogs = members.some(({ plan }) => plan.target.type === "repo.git" && !entersContainer(plan))
780
667
  ? () => members.flatMap(({ intent: member, plan }) => plan.target.type === "repo.git" && !entersContainer(plan)
@@ -812,9 +699,7 @@ export class ApplyWindowHost {
812
699
  /**
813
700
  * The visible addresses one member may read or replace: its target
814
701
  * address, the entity's current address when it moves, its room chain's
815
- * sources and destinations, and for a repository or an Enter every
816
- * materialized address its identity map relocates. A bound member's are
817
- * its receipt's. A member current rows no longer place holds only its O
702
+ * sources and destinations. A bound member's are its receipt's. A member current rows no longer place holds only its O
818
703
  * address, and its guard then finds its play changed.
819
704
  */
820
705
  applyAddresses(intent, plan) {
@@ -837,12 +722,6 @@ export class ApplyWindowHost {
837
722
  addresses.add(source);
838
723
  addresses.add(destination);
839
724
  }
840
- const prepared = this.#prepared.get(this.#key(intent));
841
- const groups = prepared?.enter ? this.#repository.enterRelocations(context.targetPath, prepared.enter)
842
- : plan.target.type === "repo.git" && prepared?.repository
843
- ? this.#repository.relocations(context, this.#repository.territory(intent, prepared.repository.identity, context.current).identity) : [];
844
- for (const group of groups)
845
- addresses.add(group.sourceRoot.absolutePath);
846
725
  return [...addresses];
847
726
  }
848
727
  /** Called only after the requesting Watch cutoff settles. Outbox protection
@@ -872,9 +751,6 @@ export class ApplyWindowHost {
872
751
  const root = judgeBoundRoot(receipt.root);
873
752
  if (root !== "present")
874
753
  return declined(`Materialized root ${receipt.root.path} is ${root}.`);
875
- const key = this.#key(intent);
876
- // The guard's readings describe ground this reveal is about to change.
877
- this.#repository.forget(key);
878
754
  const { address, control, source } = receipt;
879
755
  await this.#makeRoom(receipt);
880
756
  const remainder = this.#remainder(intent, receipt);
@@ -894,7 +770,7 @@ export class ApplyWindowHost {
894
770
  if (!moveWithoutReplacing(source.path, address))
895
771
  return declined(`${address} holds another object.`);
896
772
  }
897
- if (receipt.kind === "container") {
773
+ if (receipt.kind === "container" || receipt.kind === "repository") {
898
774
  const at = standing(address);
899
775
  if (at && (!at.isDirectory() || at.isSymbolicLink())) {
900
776
  if (!replaceAt(receipt, stageDirectory(control, intent.entityId)))
@@ -911,30 +787,8 @@ export class ApplyWindowHost {
911
787
  displaceGitStorage(displaced, address, receipt.gitStorage);
912
788
  }
913
789
  await this.#return(receipt.root.path, [{ uuid: intent.entityId, path: address }]);
914
- return;
915
- }
916
- if (receipt.kind === "repository") {
917
- if (!receipt.repository)
918
- throw new Error("repository Apply binds without its reveal plan");
919
- // Optimistic equality: the source already showed this exact package,
920
- // so the move above was the whole reveal. Verify reads it afresh.
921
- if (receipt.repository.shown) {
922
- relocateGroups(receipt);
923
- return;
924
- }
925
- const chain = (await this.#ensurePrepared(intent, plan)).repository;
926
- if (!chain)
927
- throw new Error("repository Apply has no prepared transport chain");
928
- ensureDirBeneath(receipt.root.path, address, 0o755);
929
- const staging = stagedPath(control, intent.entityId);
930
- ensureApplyPrivate(control, dirname(staging));
931
- const applied = await applyRepositoryFiles(address, chain, { kind: "working", root: receipt.root.path,
932
- removals: receipt.repository.removals, staging, standing: receipt.repository.standing,
933
- reveal: { attempt: intent.attemptId, storage: receipt.repository.storage },
934
- proven: this.#repository.proofs(address) });
935
- // The reveal's readback is the reading Verify inherits.
936
- this.#repository.remember(key, address, applied.reading);
937
- relocateGroups(receipt);
790
+ if (receipt.kind === "repository")
791
+ return await this.#revealGit(intent, plan, receipt);
938
792
  return;
939
793
  }
940
794
  if (receipt.kind === "enter") {
@@ -947,7 +801,6 @@ export class ApplyWindowHost {
947
801
  if (!replaceAt(receipt, staged.path))
948
802
  return declined(`${address} holds another object.`);
949
803
  }
950
- relocateGroups(receipt);
951
804
  const { seal } = (await this.#ensurePrepared(intent, plan)).enter;
952
805
  await this.#return(receipt.root.path, seal.rows.filter(row => CONTAINERS.has(row.record.type))
953
806
  .map(row => ({ uuid: row.record.uuid, path: join(address, ...row.relativePath.split("/").filter(Boolean)) })));
@@ -973,6 +826,46 @@ export class ApplyWindowHost {
973
826
  this.#emit(intent, plan, "reveal-finished");
974
827
  }
975
828
  }
829
+ /**
830
+ * A repository's Git part: its folder stands, and Git's own files are
831
+ * made to hold the target's state (src/git/rail.ts). The part marker says
832
+ * `started`, durably, before Git writes anything, so recovery knows a torn
833
+ * install is Apply's own; `ended` follows Git's read of the result. A
834
+ * folder that already shows the state, as a move or rename leaves it, is
835
+ * read and left alone. Its working-tree files are their own members.
836
+ */
837
+ async #revealGit(intent, plan, receipt) {
838
+ const target = plan.target.transportVersion, artifact = resultArtifact(plan);
839
+ if (!target || !artifact)
840
+ throw new Error(`repository ${intent.entityId} Apply names no Git artifact`);
841
+ const marker = gitPartPath(receipt.control, intent.entityId);
842
+ const before = this.#ground.current(intent.entityId);
843
+ const known = async () => before?.type === "repo.git" ? cachedNotebook(this.#cacheDir, before.transportVersion) : null;
844
+ try {
845
+ if (readGitPart(receipt.control, intent.entityId) === null) {
846
+ if (hasGitMarker(receipt.address)) {
847
+ const shown = await gitStateIdOf(receipt.address, this.#gitOwners, async () => (await known())?.state ?? null);
848
+ if ("stateId" in shown && shown.stateId === plan.target.payloadVersion)
849
+ return;
850
+ }
851
+ ensureApplyPrivate(receipt.control, dirname(marker));
852
+ writeFileSync(marker, "started");
853
+ await flushEach([marker], [dirname(marker)]);
854
+ }
855
+ // The target and its parents, from the cache when its bytes prove
856
+ // their name, else the wire.
857
+ const source = async (version) => readFile((await this.#cargo.sealed(version)
858
+ ?? await this.#cargo.readOne({ ...artifact, contentHash: version })).file);
859
+ await applyGit(receipt.address, target, source, await known(), this.#gitOwners);
860
+ }
861
+ catch (error) {
862
+ if (error instanceof GitApplyWait)
863
+ return gitWait(intent, error);
864
+ throw error;
865
+ }
866
+ // Unflushed: a lost `ended` only runs the same install again.
867
+ writeFileSync(marker, "ended");
868
+ }
976
869
  /** The topmost local remainder beneath a container this Leave or leaf
977
870
  * displaces, before the reveal or after it; null when that ground is no
978
871
  * longer settled. */
@@ -1050,15 +943,14 @@ export class ApplyWindowHost {
1050
943
  && !await keptStorageIsO(displacedGitPath(receipt.control, intent.entityId), receipt.address, receipt.gitStorage)) {
1051
944
  return { kind: "local-change" };
1052
945
  }
1053
- const judged = new ShownGround(this.#database).judge(plan.target);
946
+ const judged = new ShownGround(this.#database, this.#onDemand).judge(plan.target);
1054
947
  if (judged !== plan.play) {
1055
948
  return { kind: "rejudge", reason: `The accepted result now plays ${judged} on this computer, not ${plan.play}.` };
1056
949
  }
1057
950
  const enter = receipt.kind === "enter" ? (await this.#ensurePrepared(intent, plan)).enter : undefined;
1058
- const identity = receipt.kind === "repository" ? (await this.#ensurePrepared(intent, plan)).repository?.identity : undefined;
1059
951
  const [members, containers] = enter
1060
952
  ? [enter.seal.rows.map(row => row.record.uuid), enter.seal.rows.filter(row => CONTAINERS.has(row.record.type)).map(row => row.record.uuid)]
1061
- : repositoryMembers(identity ?? []);
953
+ : [[], []];
1062
954
  const moved = receipt.room.map(move => move.uuid);
1063
955
  const read = this.store.verificationRead(intent.attemptId, reader => {
1064
956
  readVerificationFacts(reader, plan.target, members, containers, moved);
@@ -1070,7 +962,6 @@ export class ApplyWindowHost {
1070
962
  const context = this.#boundContext(receipt);
1071
963
  // Every read Verify proves follows its root's content clock.
1072
964
  const clock = await this.#clock(intent.attemptId, receipt.root.path);
1073
- await this.#repository.closeInherited(intent);
1074
965
  let proof;
1075
966
  let ground;
1076
967
  if (receipt.kind === "leave") {
@@ -1087,8 +978,7 @@ export class ApplyWindowHost {
1087
978
  const matches = await this.#matches(intent, plan.target, receipt.address, plan, receipt.address, found => { proof = found; });
1088
979
  if (!matches)
1089
980
  return { kind: "local-change" };
1090
- ground = receipt.kind === "repository" ? await this.#repository.rows(intent, plan, context, proof, clock)
1091
- : containerGround(this.#ground, plan.target, context, verifiedRow(this.#ground, plan.target, context, proof, clock));
981
+ ground = containerGround(this.#ground, plan.target, context, verifiedRow(this.#ground, plan.target, context, proof, clock));
1092
982
  }
1093
983
  const verification = proof.proof;
1094
984
  const closed = { semantic: () => verification.semantic(), witnesses: [],
@@ -1098,6 +988,11 @@ export class ApplyWindowHost {
1098
988
  shared: [...ground.shared, ...room.shared] }, closed);
1099
989
  return { kind: "match" };
1100
990
  }
991
+ catch (error) {
992
+ if (error instanceof GitApplyWait)
993
+ return gitWait(intent, error);
994
+ throw error;
995
+ }
1101
996
  finally {
1102
997
  this.#emit(intent, plan, "verify-finished");
1103
998
  }
@@ -1214,10 +1109,6 @@ export class ApplyWindowHost {
1214
1109
  }
1215
1110
  }
1216
1111
  const verification = await adapter.verify.verify(member, plan);
1217
- // An ended Git part lets go of the ground its parcel recreated only
1218
- // once its result is proven; that ground lies outside the repository.
1219
- if (verification.kind === "match" && verdict === "revealed")
1220
- relocateGroups(receipt);
1221
1112
  if (verification.kind === "match")
1222
1113
  outcomes.set(entityId, { kind: "materialized" });
1223
1114
  else
@@ -1232,17 +1123,20 @@ export class ApplyWindowHost {
1232
1123
  return intent.members.map(member => outcomes.get(member.entityId) ?? { kind: "owed", reason: "not reached" });
1233
1124
  }
1234
1125
  /** Whether the ground at `at` shows what the member's final guard proved
1235
- * of its source (#guard), read the same way: the source's O row, and a
1236
- * repository's shared expectation. Its O row stands until the window ends. */
1126
+ * of its source (#guard), read the same way: the source's O row, which
1127
+ * stands until the window ends. A repository Git refuses shows nothing. */
1237
1128
  async #showsGuarded(intent, plan, at) {
1238
1129
  const current = this.#ground.current(intent.entityId);
1239
1130
  if (!current)
1240
1131
  return false;
1241
- const shared = current.type === "repo.git" ? this.#ground.shared(current.uuid) : undefined;
1242
- if (shared?.status === "active" && shared.type === "repo.git") {
1243
- return await this.#repository.showsExpected(intent, plan, current, shared, at) !== null;
1132
+ try {
1133
+ return await this.#matches(intent, portable(current), at, plan);
1134
+ }
1135
+ catch (error) {
1136
+ if (error instanceof GitApplyWait)
1137
+ return false;
1138
+ throw error;
1244
1139
  }
1245
- return this.#matches(intent, portable(shared?.status === "active" ? shared : current), at, plan);
1246
1140
  }
1247
1141
  /** A window that never bound leaves nothing anyone owns: its preparation
1248
1142
  * and its control trees go. A bound window keeps both for #recover. */
@@ -1265,6 +1159,41 @@ export class ApplyWindowHost {
1265
1159
  await rm(control, { recursive: true, force: true });
1266
1160
  }
1267
1161
  }
1162
+ /**
1163
+ * Place one unit its root on demand lists (src/drive/): its line plays it
1164
+ * as one ordinary Enter of that unit, through intent, guard, reveal and
1165
+ * Verify, and the answer comes when the window holding it ends. `wake`
1166
+ * rings the line once the unit is owed. One placement per unit is in
1167
+ * flight: a second ask joins the first.
1168
+ */
1169
+ place(entityId, wake) {
1170
+ return new Promise(answer => {
1171
+ const joined = this.#opening.get(entityId);
1172
+ this.#opening.set(entityId, joined
1173
+ ? { answer: placement => { joined.answer(placement); answer(placement); }, wake: joined.wake }
1174
+ : { answer, wake });
1175
+ if (!joined)
1176
+ this.#open(entityId);
1177
+ });
1178
+ }
1179
+ /** Owe an opened unit to its line and ring it; answer at once when O
1180
+ * already shows the unit or this computer never received it. */
1181
+ #open(entityId) {
1182
+ void this.store.openUnit(entityId).then(opened => {
1183
+ if (opened === "owed")
1184
+ return this.#opening.get(entityId)?.wake();
1185
+ this.#answer(entityId, opened === "shown" ? { kind: "placed" } : { kind: "unknown" });
1186
+ }, (error) => this.#answer(entityId, { kind: "failed", error }));
1187
+ }
1188
+ /** Stop placing a unit: its line lists it again unless its window bound. */
1189
+ abandon(entityId) {
1190
+ this.#opening.delete(entityId);
1191
+ }
1192
+ #answer(entityId, placement) {
1193
+ const opening = this.#opening.get(entityId);
1194
+ this.#opening.delete(entityId);
1195
+ opening?.answer(placement);
1196
+ }
1268
1197
  /** The end commit landed: the window's ground is no longer owned, and
1269
1198
  * every byte it revealed is owed to the durability point. */
1270
1199
  #ended(intent, members) {
@@ -1285,9 +1214,15 @@ export class ApplyWindowHost {
1285
1214
  }
1286
1215
  else if (member.outcome.kind === "settled") {
1287
1216
  this.#onStage?.({ ...common, stage: "settled", settlement: member.outcome.settlement });
1217
+ // A window judged before the unit opened listed it: owe it again.
1218
+ if (member.outcome.settlement === "listed" && this.#opening.has(member.entityId))
1219
+ this.#open(member.entityId);
1220
+ else
1221
+ this.#answer(member.entityId, { kind: "settled", settlement: member.outcome.settlement });
1288
1222
  }
1289
1223
  else {
1290
1224
  this.#onStage?.({ ...common, stage: "retired", completion: "materialized" });
1225
+ this.#answer(member.entityId, { kind: "placed" });
1291
1226
  }
1292
1227
  if (receipt)
1293
1228
  this.#forgetPreparation(receipt.intent);
@@ -1316,8 +1251,6 @@ export class ApplyWindowHost {
1316
1251
  directories.add(dirname(move.source));
1317
1252
  directories.add(dirname(move.destination));
1318
1253
  }
1319
- for (const entry of receipt.relocated)
1320
- directories.add(dirname(entry.source));
1321
1254
  switch (receipt.kind) {
1322
1255
  case "leaf":
1323
1256
  files.add(receipt.address);
@@ -1373,35 +1306,36 @@ export class ApplyWindowHost {
1373
1306
  };
1374
1307
  if (!stats)
1375
1308
  return false;
1376
- if (["file.text", "file.binary", "link"].includes(record.type)) {
1377
- const expected = record.payloadVersion, format = expected ? payloadFormat(expected) : null;
1378
- if (!expected || (format !== "sha1" && format !== "sha256"))
1379
- throw new Error(`Apply matched ${record.uuid} with no literal payload`);
1380
- // A leaf this computer proved keeps its proof while the slot shows its
1381
- // exact signature, by the rule Detect reuses it (source-signature.ts):
1382
- // its bytes are not read again, and they answer for every payload
1383
- // their codec names. An object Apply just placed carries the change
1384
- // time of its rename, past every earlier stamp, so it is always read
1385
- // once, and that read becomes its row's proof.
1386
- const proven = this.#ground.atPath(path);
1387
- if (proven?.payloadVersion && sameCodec(proven.payloadVersion, expected) && sourceReusable(proven, stats)) {
1388
- if (proven.type !== record.type || proven.payloadVersion !== expected)
1389
- return false;
1309
+ if (record.type === "file.text" || record.type === "file.binary" || record.type === "link") {
1310
+ const expected = record.payloadVersion;
1311
+ if (!expected)
1312
+ throw new Error(`Apply matched ${record.uuid} with no payload`);
1313
+ const modeShown = record.type === "link" || record.fileMode === portableFileMode(record.type, Number(stats.mode));
1314
+ const shown = async () => {
1390
1315
  const witnesses = new PhysicalPathWitnesses();
1391
1316
  witnesses.remember(dirname(path), optionalLstat(dirname(path)));
1392
1317
  witnesses.remember(path, stats);
1393
- return (record.type === "link" || record.fileMode === portableFileMode(record.type, Number(stats.mode)))
1394
- && await retain(stats, witnessProof([witnesses.seal()]));
1318
+ return modeShown && retain(stats, witnessProof([witnesses.seal()]));
1319
+ };
1320
+ // A leaf this computer proved keeps its proof while the slot shows its
1321
+ // exact signature, by the rule Detect reuses it (source-signature.ts):
1322
+ // its bytes are not read again. An object Apply just placed carries
1323
+ // the change time of its rename, past every earlier stamp, so it is
1324
+ // always read once, and that read becomes its row's proof.
1325
+ const proven = this.#ground.atPath(path);
1326
+ if (proven?.payloadVersion && sourceReusable(proven, stats)) {
1327
+ return proven.type === record.type && proven.payloadVersion === expected && shown();
1395
1328
  }
1396
1329
  const key = this.#key(intent);
1397
1330
  this.#contentReads.set(key, (this.#contentReads.get(key) ?? 0) + 1);
1398
- const { observation, witness } = await observeLiteralPath(dirname(path), basename(path), format, "apply");
1399
- if (observation.kind !== "leaf" || observation.leaf.type !== record.type)
1331
+ // Read the way Detect reads it (src/detection/runtime.ts).
1332
+ if (record.type === "link") {
1333
+ return stats.isSymbolicLink() && sha256Hex(Buffer.from(readLinkTarget(path), "utf8")) === expected && shown();
1334
+ }
1335
+ if (!stats.isFile())
1400
1336
  return false;
1401
- const leaf = observation.leaf;
1402
- return leafPayload(expected, format, leaf) === expected && (record.type === "link"
1403
- || record.fileMode === portableFileMode(record.type, Number(leaf.stats.mode)))
1404
- && await retain(leaf.stats, witnessProof([witness]));
1337
+ const content = await captureContent(path, stats, null, { lane: "named" });
1338
+ return classifyFile({ binary: content.binary }) === record.type && content.contentHash === expected && shown();
1405
1339
  }
1406
1340
  if (record.type === "reference") {
1407
1341
  if (!record.payloadVersion)
@@ -1415,16 +1349,14 @@ export class ApplyWindowHost {
1415
1349
  }
1416
1350
  const addressProof = witnessProof([addressWitness(path, stats)]);
1417
1351
  if (record.type === "repo.git") {
1418
- if (!stats.isDirectory() || !hasGitMarker(path))
1419
- return false;
1420
- const repository = await this.#repository.package(intent, plan, record);
1421
- const own = record.uuid === intent.entityId;
1422
- const territory = own ? this.#repository.territory(intent, repository.identity) : repositoryApplyTerritory(repository.identity, []);
1423
- const remainder = own ? this.#repository.allowance(intent, repository.identity) : [];
1424
- if (!remainder)
1352
+ // A repository is its folder plus its Git directory's state, read
1353
+ // without a Git process; its working-tree files are their own entities.
1354
+ if (!stats.isDirectory() || stats.isSymbolicLink() || !hasGitMarker(path))
1425
1355
  return false;
1426
- const observed = await this.#repository.showsPackage(intent, path, repository, territory, remainder);
1427
- return observed !== null && await retain(stats, addressProof, observed.proof);
1356
+ const read = await gitStateIdOf(path, this.#gitOwners, async () => (await cachedNotebook(this.#cacheDir, record.transportVersion))?.state ?? null);
1357
+ if ("unsupported" in read)
1358
+ throw new GitApplyWait(`${path} holds ${read.unsupported}; Apply waits for it to change`);
1359
+ return read.stateId === record.payloadVersion && retain(stats, addressProof);
1428
1360
  }
1429
1361
  if (!stats.isDirectory() || stats.isSymbolicLink())
1430
1362
  return false;