@mnstry/atelier 0.2.0-alpha.6 → 0.2.0-alpha.8

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 (374) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/README.md +59 -15
  3. package/SECURITY.md +6 -1
  4. package/contracts/atelier-adoption-policy.v1.schema.json +49 -0
  5. package/contracts/atelier-coauthor.v1.schema.json +163 -0
  6. package/contracts/atelier-decision-request.v1.schema.json +476 -0
  7. package/contracts/atelier-decision-result.v1.schema.json +500 -0
  8. package/contracts/atelier-guide.v1.schema.json +227 -0
  9. package/contracts/atelier-intake.v1.schema.json +151 -0
  10. package/contracts/atelier-migration.v2.schema.json +61 -0
  11. package/contracts/atelier-obsidian-acceptance-receipt.v1.schema.json +211 -0
  12. package/contracts/atelier-obsidian-apply-policy.v1.schema.json +298 -0
  13. package/contracts/atelier-obsidian-corpus-profile.v1.schema.json +98 -0
  14. package/contracts/atelier-obsidian-edit-operation.v1.schema.json +138 -0
  15. package/contracts/atelier-obsidian-ext-settings.v1.schema.json +287 -0
  16. package/contracts/atelier-obsidian-generation-manifest.v1.schema.json +353 -0
  17. package/contracts/atelier-obsidian-proposal-receipt.v1.schema.json +110 -0
  18. package/contracts/atelier-obsidian-publication-journal.v1.schema.json +167 -0
  19. package/contracts/atelier-obsidian-scope.v1.schema.json +264 -0
  20. package/contracts/atelier-obsidian-service-state.v1.schema.json +149 -0
  21. package/contracts/atelier-obsidian-source-snapshot.v1.schema.json +179 -0
  22. package/contracts/atelier-pane-presentation.v1.schema.json +76 -0
  23. package/contracts/atelier-presentation.v1.schema.json +1293 -0
  24. package/contracts/atelier-review.v1.schema.json +1601 -0
  25. package/contracts/atelier-skill-steward.v1.schema.json +692 -0
  26. package/contracts/atelier-upgrade-plan.v2.schema.json +398 -0
  27. package/contracts/atelier-upgrade-receipt.v1.schema.json +99 -0
  28. package/contracts/atelier-vault-publication.v1.schema.json +58 -0
  29. package/docs/assurance-controls.md +9 -1
  30. package/docs/atelier-sync.md +5 -4
  31. package/docs/blocks/claims.md +15 -10
  32. package/docs/blocks/will-not-do.md +4 -1
  33. package/docs/coauthor-session.md +57 -0
  34. package/docs/connected-composition.md +75 -0
  35. package/docs/decisions.md +167 -0
  36. package/docs/exact-upgrades.md +159 -0
  37. package/docs/extension-pack-lifecycle.md +33 -0
  38. package/docs/guided-upgrades.md +99 -0
  39. package/docs/install.md +65 -9
  40. package/docs/intake-and-guides.md +65 -0
  41. package/docs/integration-and-review-plan.md +409 -0
  42. package/docs/integration-contract-decisions.md +22 -0
  43. package/docs/local-review.md +84 -0
  44. package/docs/local-services.md +227 -0
  45. package/docs/local-state.md +107 -0
  46. package/docs/obsidian-contract.md +687 -0
  47. package/docs/obsidian.md +387 -0
  48. package/docs/portable-presentation.md +328 -0
  49. package/docs/presentation-consumer-boundaries.md +75 -0
  50. package/docs/presentation-review-disposition.md +47 -0
  51. package/docs/project-command-inventory.md +38 -0
  52. package/docs/project-options.md +53 -0
  53. package/docs/release-engineering.md +88 -0
  54. package/docs/review-portability.md +55 -0
  55. package/docs/skill-steward.md +156 -0
  56. package/docs/upgrade.md +55 -2
  57. package/docs/vault-service.md +292 -0
  58. package/fixtures/atelier-coauthor/invalid/authority.v1.json +5 -0
  59. package/fixtures/atelier-coauthor/valid/config.v1.json +12 -0
  60. package/fixtures/atelier-guide/invalid/authority.v1.json +11 -0
  61. package/fixtures/atelier-guide/valid/capability.v1.json +10 -0
  62. package/fixtures/atelier-guide/valid/consent.v1.json +11 -0
  63. package/fixtures/atelier-guide/valid/engagement.v1.json +7 -0
  64. package/fixtures/atelier-guide/valid/offer.v1.json +10 -0
  65. package/fixtures/atelier-intake/invalid/authority.v1.json +9 -0
  66. package/fixtures/atelier-intake/valid/attempt.v1.json +8 -0
  67. package/fixtures/atelier-intake/valid/completion.v1.json +9 -0
  68. package/fixtures/atelier-intake/valid/source.v1.json +7 -0
  69. package/fixtures/atelier-review/invalid/authenticated-identity.v1.json +22 -0
  70. package/fixtures/atelier-review/valid/bound.v1.json +229 -0
  71. package/fixtures/atelier-review/valid/bundle.v1.json +267 -0
  72. package/fixtures/atelier-review/valid/contribution.v1.json +22 -0
  73. package/fixtures/atelier-review/valid/lifecycle.v1.json +14 -0
  74. package/fixtures/atelier-skill-steward/audit/invalid/source-mutation.v1.json +26 -0
  75. package/fixtures/atelier-skill-steward/audit/valid/clean.v1.json +26 -0
  76. package/fixtures/atelier-skill-steward/candidates/invalid/workflow-key.v1.json +37 -0
  77. package/fixtures/atelier-skill-steward/candidates/valid/create.v1.json +37 -0
  78. package/fixtures/atelier-skill-steward/lock/invalid/bad-digest.v1.json +18 -0
  79. package/fixtures/atelier-skill-steward/lock/valid/installed.v1.json +23 -0
  80. package/fixtures/atelier-skill-steward/plan/invalid/delete-action.v1.json +33 -0
  81. package/fixtures/atelier-skill-steward/plan/valid/add.v1.json +33 -0
  82. package/fixtures/atelier-upgrade-transaction/adoption-policy/invalid/example.json +12 -0
  83. package/fixtures/atelier-upgrade-transaction/adoption-policy/valid/example.json +11 -0
  84. package/fixtures/atelier-upgrade-transaction/migration/invalid/example.json +20 -0
  85. package/fixtures/atelier-upgrade-transaction/migration/valid/example.json +19 -0
  86. package/fixtures/atelier-upgrade-transaction/upgrade-plan/invalid/example.json +58 -0
  87. package/fixtures/atelier-upgrade-transaction/upgrade-plan/valid/example.json +57 -0
  88. package/fixtures/atelier-upgrade-transaction/upgrade-receipt/invalid/example.json +15 -0
  89. package/fixtures/atelier-upgrade-transaction/upgrade-receipt/valid/example.json +14 -0
  90. package/fixtures/atelier-vault-publication/invalid/publication.json +5 -0
  91. package/fixtures/atelier-vault-publication/valid/publication.json +11 -0
  92. package/fixtures/decisions/request/invalid/unknown-authority.v1.json +61 -0
  93. package/fixtures/decisions/request/valid/triage.v1.json +60 -0
  94. package/fixtures/decisions/result/invalid/execution-authority.v1.json +50 -0
  95. package/fixtures/decisions/result/valid/abstained.v1.json +23 -0
  96. package/fixtures/decisions/result/valid/assessed.v1.json +50 -0
  97. package/fixtures/obsidian/acceptance/ap05-extra-notes.json +14 -0
  98. package/fixtures/obsidian/acceptance/receipts/G07.valid.v1.json +63 -0
  99. package/fixtures/obsidian/acceptance/receipts/G13.valid.v1.json +69 -0
  100. package/fixtures/obsidian/acceptance/receipts/G14.valid.v1.json +62 -0
  101. package/fixtures/obsidian/acceptance/receipts/G15.valid.v1.json +56 -0
  102. package/fixtures/obsidian/acceptance/receipts/G16.valid.v1.json +73 -0
  103. package/fixtures/obsidian/acceptance/receipts/G17.valid.v1.json +75 -0
  104. package/fixtures/obsidian/acceptance/receipts/G18.valid.v1.json +64 -0
  105. package/fixtures/obsidian/acceptance/service-sentinels.json +10 -0
  106. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/duplicate-evidence-name.v1.json +39 -0
  107. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/evidence-by-absolute-path.v1.json +34 -0
  108. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/missing-candidate-tree.v1.json +33 -0
  109. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/no-evidence.v1.json +28 -0
  110. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/unknown-outcome.v1.json +34 -0
  111. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/unknown-top-level-field.v1.json +35 -0
  112. package/fixtures/obsidian/contracts/acceptance-receipt/valid/node-gate.v1.json +34 -0
  113. package/fixtures/obsidian/contracts/apply-policy/invalid/automatic-without-edit-class.v1.json +27 -0
  114. package/fixtures/obsidian/contracts/apply-policy/invalid/conflict-overwrite.v1.json +29 -0
  115. package/fixtures/obsidian/contracts/apply-policy/invalid/missing-policy-digest.v1.json +28 -0
  116. package/fixtures/obsidian/contracts/apply-policy/invalid/unbounded-batch.v1.json +29 -0
  117. package/fixtures/obsidian/contracts/apply-policy/invalid/unimplemented-edit-class.v1.json +30 -0
  118. package/fixtures/obsidian/contracts/apply-policy/invalid/unknown-mode.v1.json +29 -0
  119. package/fixtures/obsidian/contracts/apply-policy/invalid/unknown-selector-operator.v1.json +22 -0
  120. package/fixtures/obsidian/contracts/apply-policy/invalid/unknown-top-level-field.v1.json +30 -0
  121. package/fixtures/obsidian/contracts/apply-policy/valid/automatic-scoped.v1.json +29 -0
  122. package/fixtures/obsidian/contracts/apply-policy/valid/manual-default.v1.json +20 -0
  123. package/fixtures/obsidian/contracts/corpus-profile/invalid/absolute-path-in-ext.v1.json +30 -0
  124. package/fixtures/obsidian/contracts/corpus-profile/invalid/absolute-repository-root.v1.json +27 -0
  125. package/fixtures/obsidian/contracts/corpus-profile/invalid/duplicate-repository-id.v1.json +27 -0
  126. package/fixtures/obsidian/contracts/corpus-profile/invalid/overlapping-managed-roots.v1.json +27 -0
  127. package/fixtures/obsidian/contracts/corpus-profile/invalid/unknown-enrollment.v1.json +27 -0
  128. package/fixtures/obsidian/contracts/corpus-profile/invalid/unknown-top-level-field.v1.json +28 -0
  129. package/fixtures/obsidian/contracts/corpus-profile/valid/three-repositories.v1.json +27 -0
  130. package/fixtures/obsidian/contracts/edit-operation/invalid/absolute-recovery-ref.v1.json +21 -0
  131. package/fixtures/obsidian/contracts/edit-operation/invalid/inline-observed-bytes.v1.json +22 -0
  132. package/fixtures/obsidian/contracts/edit-operation/invalid/missing-base-digest.v1.json +20 -0
  133. package/fixtures/obsidian/contracts/edit-operation/invalid/short-idempotency-key.v1.json +21 -0
  134. package/fixtures/obsidian/contracts/edit-operation/invalid/unknown-kind.v1.json +21 -0
  135. package/fixtures/obsidian/contracts/edit-operation/valid/pending-body-replacement.v1.json +21 -0
  136. package/fixtures/obsidian/contracts/ext-settings/invalid/absolute-path-prefix.v1.json +28 -0
  137. package/fixtures/obsidian/contracts/ext-settings/invalid/apply-policy-in-portable-settings.v1.json +30 -0
  138. package/fixtures/obsidian/contracts/ext-settings/invalid/duplicate-scope-id.v1.json +27 -0
  139. package/fixtures/obsidian/contracts/ext-settings/invalid/machine-local-vault-path.v1.json +28 -0
  140. package/fixtures/obsidian/contracts/ext-settings/invalid/service-port-in-portable-settings.v1.json +28 -0
  141. package/fixtures/obsidian/contracts/ext-settings/invalid/unknown-default-scope.v1.json +27 -0
  142. package/fixtures/obsidian/contracts/ext-settings/valid/disabled.v1.json +5 -0
  143. package/fixtures/obsidian/contracts/ext-settings/valid/enabled-with-scopes.v1.json +27 -0
  144. package/fixtures/obsidian/contracts/generation-manifest/invalid/absolute-note-path.v1.json +114 -0
  145. package/fixtures/obsidian/contracts/generation-manifest/invalid/complete-with-unwritten-notes.v1.json +114 -0
  146. package/fixtures/obsidian/contracts/generation-manifest/invalid/derived-link-claimed-declared.v1.json +114 -0
  147. package/fixtures/obsidian/contracts/generation-manifest/invalid/duplicate-note-identity.v1.json +114 -0
  148. package/fixtures/obsidian/contracts/generation-manifest/invalid/in-scope-endpoint-missing.v1.json +114 -0
  149. package/fixtures/obsidian/contracts/generation-manifest/invalid/title-only-note-path.v1.json +114 -0
  150. package/fixtures/obsidian/contracts/generation-manifest/invalid/unknown-note-field.v1.json +115 -0
  151. package/fixtures/obsidian/contracts/generation-manifest/invalid/unknown-relation-type.v1.json +114 -0
  152. package/fixtures/obsidian/contracts/generation-manifest/invalid/withheld-endpoint.v1.json +114 -0
  153. package/fixtures/obsidian/contracts/generation-manifest/valid/two-notes.v1.json +114 -0
  154. package/fixtures/obsidian/contracts/oracles/scope-cases.json +412 -0
  155. package/fixtures/obsidian/contracts/proposal-receipt/invalid/accepted-without-proposal-id.v1.json +12 -0
  156. package/fixtures/obsidian/contracts/proposal-receipt/invalid/missing-adapter-operation-id.v1.json +11 -0
  157. package/fixtures/obsidian/contracts/proposal-receipt/invalid/unknown-backpressure-outcome.v1.json +12 -0
  158. package/fixtures/obsidian/contracts/proposal-receipt/invalid/unknown-top-level-field.v1.json +13 -0
  159. package/fixtures/obsidian/contracts/proposal-receipt/valid/accepted-new.v1.json +12 -0
  160. package/fixtures/obsidian/contracts/proposal-receipt/valid/deferred.v1.json +12 -0
  161. package/fixtures/obsidian/contracts/publication-journal/invalid/absolute-recovery-ref.v1.json +47 -0
  162. package/fixtures/obsidian/contracts/publication-journal/invalid/duplicate-sequence.v1.json +47 -0
  163. package/fixtures/obsidian/contracts/publication-journal/invalid/empty-protocol-id.v1.json +47 -0
  164. package/fixtures/obsidian/contracts/publication-journal/invalid/missing-protocol-id.v1.json +46 -0
  165. package/fixtures/obsidian/contracts/publication-journal/invalid/unknown-entry-field.v1.json +48 -0
  166. package/fixtures/obsidian/contracts/publication-journal/invalid/unknown-state.v1.json +47 -0
  167. package/fixtures/obsidian/contracts/publication-journal/valid/committed.v1.json +47 -0
  168. package/fixtures/obsidian/contracts/publication-journal/valid/updating-after-restart.v1.json +22 -0
  169. package/fixtures/obsidian/contracts/scope/invalid/absolute-path-prefix.v1.json +15 -0
  170. package/fixtures/obsidian/contracts/scope/invalid/duplicate-ids.v1.json +18 -0
  171. package/fixtures/obsidian/contracts/scope/invalid/expansion-without-node-budget.v1.json +40 -0
  172. package/fixtures/obsidian/contracts/scope/invalid/full-mode-with-subset.v1.json +8 -0
  173. package/fixtures/obsidian/contracts/scope/invalid/unknown-mode.v1.json +41 -0
  174. package/fixtures/obsidian/contracts/scope/invalid/unknown-selector-key.v1.json +15 -0
  175. package/fixtures/obsidian/contracts/scope/invalid/unknown-selector-operator.v1.json +14 -0
  176. package/fixtures/obsidian/contracts/scope/invalid/unknown-top-level-field.v1.json +42 -0
  177. package/fixtures/obsidian/contracts/scope/valid/explicit-empty.v1.json +8 -0
  178. package/fixtures/obsidian/contracts/scope/valid/focus.v1.json +11 -0
  179. package/fixtures/obsidian/contracts/scope/valid/full.v1.json +8 -0
  180. package/fixtures/obsidian/contracts/scope/valid/scoped-set-expression.v1.json +41 -0
  181. package/fixtures/obsidian/contracts/service-state/invalid/hostname-instead-of-literal-loopback.v1.json +23 -0
  182. package/fixtures/obsidian/contracts/service-state/invalid/missing-consent.v1.json +18 -0
  183. package/fixtures/obsidian/contracts/service-state/invalid/privileged-port.v1.json +23 -0
  184. package/fixtures/obsidian/contracts/service-state/invalid/unknown-top-level-field.v1.json +24 -0
  185. package/fixtures/obsidian/contracts/service-state/invalid/wildcard-bind.v1.json +23 -0
  186. package/fixtures/obsidian/contracts/service-state/valid/healthy.v1.json +23 -0
  187. package/fixtures/obsidian/contracts/source-snapshot/invalid/absolute-file-path.v1.json +48 -0
  188. package/fixtures/obsidian/contracts/source-snapshot/invalid/duplicate-repository-id.v1.json +48 -0
  189. package/fixtures/obsidian/contracts/source-snapshot/invalid/mixed-read.v1.json +48 -0
  190. package/fixtures/obsidian/contracts/source-snapshot/invalid/parent-traversal-path.v1.json +48 -0
  191. package/fixtures/obsidian/contracts/source-snapshot/invalid/unknown-file-field.v1.json +49 -0
  192. package/fixtures/obsidian/contracts/source-snapshot/valid/two-repositories.v1.json +48 -0
  193. package/fixtures/obsidian/edits/workspace.json +65 -0
  194. package/fixtures/obsidian/materialization/expected-full.json +99 -0
  195. package/fixtures/obsidian/materialization/expected-scoped.json +39 -0
  196. package/fixtures/obsidian/materialization/workspace.json +54 -0
  197. package/fixtures/obsidian/proposals/expected-shapes.json +11 -0
  198. package/fixtures/ui/presentation/pane.v1.json +7 -0
  199. package/fixtures/ui/presentation/reference.v1.json +293 -0
  200. package/package.json +57 -6
  201. package/skills/claude/atelier-guided-coauthor/SKILL.md +49 -0
  202. package/skills/claude/atelier-guided-upgrade/SKILL.md +97 -0
  203. package/skills/claude/atelier-open/SKILL.md +5 -0
  204. package/skills/claude/atelier-skill-steward/SKILL.md +62 -0
  205. package/skills/claude/mnstry-readiness/SKILL.md +5 -0
  206. package/skills/codex/atelier-guided-coauthor/SKILL.md +49 -0
  207. package/skills/codex/atelier-guided-upgrade/SKILL.md +97 -0
  208. package/skills/codex/atelier-open/SKILL.md +5 -0
  209. package/skills/codex/atelier-skill-steward/SKILL.md +62 -0
  210. package/skills/codex/mnstry-readiness/SKILL.md +5 -0
  211. package/src/access/preview-enforcer.mjs +84 -0
  212. package/src/boundary/policy.mjs +57 -25
  213. package/src/cli/project-options.mjs +58 -0
  214. package/src/cli/run.mjs +43 -3
  215. package/src/coauthor/session.mjs +161 -0
  216. package/src/coauthor/store.mjs +173 -0
  217. package/src/collaboration/event-ledger.mjs +16 -33
  218. package/src/collaboration/inspection-bundle.mjs +223 -0
  219. package/src/collaboration/review-contracts.mjs +25 -0
  220. package/src/collaboration/review-store.mjs +305 -0
  221. package/src/commands/coauthor.mjs +26 -0
  222. package/src/commands/config.mjs +6 -1
  223. package/src/commands/extension-pack.mjs +15 -8
  224. package/src/commands/init.mjs +44 -5
  225. package/src/commands/obsidian.mjs +368 -0
  226. package/src/commands/review.mjs +147 -0
  227. package/src/commands/setup.mjs +51 -14
  228. package/src/commands/skills.mjs +199 -0
  229. package/src/commands/sync.mjs +8 -1
  230. package/src/composition/registry.mjs +27 -0
  231. package/src/composition/wire.mjs +122 -0
  232. package/src/contracts/corpus.mjs +29 -0
  233. package/src/decisions/contracts.d.mts +96 -0
  234. package/src/decisions/contracts.mjs +321 -0
  235. package/src/disclosure/content-scan.mjs +13 -0
  236. package/src/export/atelier-export-contract.mjs +16 -1
  237. package/src/extension-packs/lifecycle.mjs +154 -0
  238. package/src/graph/graph.mjs +64 -2
  239. package/src/graph/knowledge-graph.mjs +548 -24
  240. package/src/guides/contracts.mjs +54 -0
  241. package/src/intake/store.mjs +119 -0
  242. package/src/preview/channel.mjs +89 -0
  243. package/src/project/config.mjs +26 -27
  244. package/src/project/durable-state.mjs +161 -0
  245. package/src/project/file-class.mjs +166 -0
  246. package/src/project/private-state.mjs +11 -1
  247. package/src/projection/obsidian/contracts.mjs +571 -0
  248. package/src/projection/obsidian/edits/align.mjs +169 -0
  249. package/src/projection/obsidian/edits/apply.mjs +889 -0
  250. package/src/projection/obsidian/edits/arbitrate.mjs +414 -0
  251. package/src/projection/obsidian/edits/contribution.mjs +108 -0
  252. package/src/projection/obsidian/edits/index.mjs +19 -0
  253. package/src/projection/obsidian/edits/object-identity.mjs +61 -0
  254. package/src/projection/obsidian/edits/object-store.mjs +517 -0
  255. package/src/projection/obsidian/edits/observe.mjs +123 -0
  256. package/src/projection/obsidian/edits/policy.mjs +123 -0
  257. package/src/projection/obsidian/edits/regions.mjs +648 -0
  258. package/src/projection/obsidian/materialize/byte-lens.mjs +98 -0
  259. package/src/projection/obsidian/materialize/index.mjs +7 -0
  260. package/src/projection/obsidian/materialize/path-registry.mjs +105 -0
  261. package/src/projection/obsidian/materialize/prepare-view.mjs +746 -0
  262. package/src/projection/obsidian/materialize/settings.mjs +57 -0
  263. package/src/projection/obsidian/materialize/stage.mjs +27 -0
  264. package/src/projection/obsidian/proposals/adapter.mjs +572 -0
  265. package/src/projection/obsidian/proposals/backpressure.mjs +113 -0
  266. package/src/projection/obsidian/proposals/contribution.mjs +55 -0
  267. package/src/projection/obsidian/proposals/index.mjs +23 -0
  268. package/src/projection/obsidian/proposals/observation.mjs +216 -0
  269. package/src/projection/obsidian/proposals/queue.mjs +277 -0
  270. package/src/projection/obsidian/proposals/router.mjs +168 -0
  271. package/src/projection/obsidian/publication/bridge-script.mjs +266 -0
  272. package/src/projection/obsidian/publication/exchange.mjs +117 -0
  273. package/src/projection/obsidian/publication/index.mjs +5 -0
  274. package/src/projection/obsidian/publication/publisher.mjs +588 -0
  275. package/src/projection/obsidian/publication/test-seam.mjs +16 -0
  276. package/src/projection/obsidian/publication/transport.mjs +139 -0
  277. package/src/projection/obsidian/recovery/index.mjs +6 -0
  278. package/src/projection/obsidian/recovery/journal.mjs +134 -0
  279. package/src/projection/obsidian/recovery/late-writer.mjs +46 -0
  280. package/src/projection/obsidian/recovery/restart.mjs +316 -0
  281. package/src/projection/obsidian/recovery/store.mjs +234 -0
  282. package/src/projection/obsidian/selection-ui/conflict-view.mjs +91 -0
  283. package/src/projection/obsidian/selection-ui/contribution.mjs +141 -0
  284. package/src/projection/obsidian/selection-ui/focus.mjs +82 -0
  285. package/src/projection/obsidian/selection-ui/index.mjs +12 -0
  286. package/src/projection/obsidian/selection-ui/policy-setup.mjs +107 -0
  287. package/src/projection/obsidian/selection-ui/receipt.mjs +173 -0
  288. package/src/projection/obsidian/selection-ui/selection-state.mjs +122 -0
  289. package/src/projection/obsidian/selection-ui/selection.mjs +109 -0
  290. package/src/projection/project.mjs +28 -19
  291. package/src/readiness-protocols/evidence.mjs +282 -0
  292. package/src/readiness-protocols/runtime.mjs +4 -3
  293. package/src/readiness-protocols/source-read.mjs +39 -0
  294. package/src/runtime/obsidian/app-capability.mjs +110 -0
  295. package/src/runtime/obsidian/app-production-seams.mjs +96 -0
  296. package/src/runtime/obsidian/contributions/proposal-adapter.mjs +4 -0
  297. package/src/runtime/obsidian/contributions/selection-ui.mjs +4 -0
  298. package/src/runtime/obsidian/contributions/source-apply.mjs +4 -0
  299. package/src/runtime/obsidian/contributions.mjs +27 -0
  300. package/src/runtime/obsidian/documents.mjs +37 -0
  301. package/src/runtime/obsidian/enablement.mjs +53 -0
  302. package/src/runtime/obsidian/engine.mjs +532 -0
  303. package/src/runtime/obsidian/errors.mjs +14 -0
  304. package/src/runtime/obsidian/extension-points.mjs +103 -0
  305. package/src/runtime/obsidian/index.mjs +34 -0
  306. package/src/runtime/obsidian/lifecycle.mjs +258 -0
  307. package/src/runtime/obsidian/machine-settings.mjs +260 -0
  308. package/src/runtime/obsidian/observation.mjs +158 -0
  309. package/src/runtime/obsidian/opening.mjs +243 -0
  310. package/src/runtime/obsidian/pending-edits.mjs +141 -0
  311. package/src/runtime/obsidian/pipeline.mjs +122 -0
  312. package/src/runtime/obsidian/private-lock.mjs +156 -0
  313. package/src/runtime/obsidian/process-identity.mjs +58 -0
  314. package/src/runtime/obsidian/service-client.mjs +66 -0
  315. package/src/runtime/obsidian/service-main.mjs +89 -0
  316. package/src/runtime/obsidian/service-record.mjs +169 -0
  317. package/src/runtime/obsidian/service-server.mjs +121 -0
  318. package/src/runtime/obsidian/service.mjs +216 -0
  319. package/src/runtime/obsidian/startup-adapters.mjs +87 -0
  320. package/src/runtime/obsidian/state-store.mjs +180 -0
  321. package/src/runtime/obsidian/sync-notice.mjs +33 -0
  322. package/src/runtime/obsidian/tick-loop.mjs +84 -0
  323. package/src/runtime/obsidian/watchers.mjs +36 -0
  324. package/src/runtime/supervisor.mjs +16 -1
  325. package/src/server/local-sidecar.mjs +44 -0
  326. package/src/server/server.mjs +1 -0
  327. package/src/skills/steward.mjs +780 -0
  328. package/src/ui/presentation/browser.mjs +278 -0
  329. package/src/ui/presentation/contract.mjs +116 -0
  330. package/src/ui/presentation/index.mjs +7 -0
  331. package/src/ui/presentation/native.mjs +153 -0
  332. package/src/ui/presentation/proof.mjs +57 -0
  333. package/src/ui/presentation/schema-check.mjs +30 -0
  334. package/src/ui/presentation/schema.generated.mjs +1371 -0
  335. package/src/ui/presentation/state.mjs +43 -0
  336. package/src/ui/presentation/styles.mjs +67 -0
  337. package/src/ui/presentation/tokens.mjs +74 -0
  338. package/src/ui/presentation/web.mjs +85 -0
  339. package/src/ui/review-page.mjs +32 -0
  340. package/src/upgrade/explanation.mjs +33 -0
  341. package/src/upgrade/provenance.mjs +338 -0
  342. package/src/upgrade/transaction-files.mjs +103 -0
  343. package/src/upgrade/transaction.mjs +475 -0
  344. package/src/upgrade/upgrade.mjs +63 -28
  345. package/src/vault/hosts.mjs +21 -0
  346. package/src/vault/identity.mjs +19 -0
  347. package/src/vault/index.mjs +7 -0
  348. package/src/vault/interface.mjs +11 -0
  349. package/src/vault/metadata.mjs +31 -0
  350. package/src/vault/privacy.mjs +148 -0
  351. package/src/vault/probe.mjs +89 -0
  352. package/src/vault/service.mjs +131 -0
  353. package/src/vault/source.mjs +45 -0
  354. package/src/vault/storage.mjs +23 -0
  355. package/templates/distribution-workspace/.claude/launch.json +6 -2
  356. package/templates/distribution-workspace/gitignore +1 -0
  357. package/templates/distribution-workspace/project/README.md +2 -2
  358. package/templates/external-project-workspace/README.md +45 -0
  359. package/templates/external-project-workspace/answers.example.json +4 -0
  360. package/templates/external-project-workspace/atelier.project.json +40 -0
  361. package/templates/external-project-workspace/boundary-policy.v1.json +60 -0
  362. package/templates/external-project-workspace/gitignore +8 -0
  363. package/templates/external-project-workspace/pack-lifecycle.json +14 -0
  364. package/templates/external-project-workspace/packs/protocols/contract-gate.v1.json +109 -0
  365. package/templates/external-project-workspace/packs/sample-pack.v1.json +48 -0
  366. package/templates/external-project-workspace/repo-access.v1.json +9 -0
  367. package/templates/external-project-workspace/source/README.md +11 -0
  368. package/templates/launch.json +6 -2
  369. package/templates/private-domain-workspace/.claude/launch.json +6 -2
  370. package/templates/private-domain-workspace/domain/README.md +2 -2
  371. package/templates/private-domain-workspace/gitignore +1 -0
  372. package/templates/shared-project-workspace/.claude/launch.json +6 -2
  373. package/templates/shared-project-workspace/gitignore +1 -0
  374. package/templates/shared-project-workspace/project/README.md +2 -2
@@ -0,0 +1,387 @@
1
+ # Obsidian projection: selection, apply policy and acceptance receipts
2
+
3
+ This document describes the selection binding, the apply policy setup, the
4
+ conflict-state view and the acceptance receipt validator under
5
+ `src/projection/obsidian/selection-ui/`. It states what each one does on this
6
+ machine and what it does not. The contract itself is in
7
+ [obsidian-contract.md](obsidian-contract.md).
8
+
9
+ Nothing in this module starts the app, runs `obsidian-cli`, publishes a vault
10
+ or writes a source file. The test suite installs a spawn guard that throws if
11
+ anything tries.
12
+
13
+ ## What is real and what is not
14
+
15
+ Real, on this machine, today:
16
+
17
+ - A declared view (`full`, `scoped` or `focus`, with an optional bounded
18
+ expansion) resolves to an exact scope document, the exact selected set, and
19
+ the note paths a vault of this workspace gives those notes.
20
+ - A focus resolves to a Graph "Search files" query naming every selected note
21
+ by its exact path, plus the payload of a core Bookmark that retains the
22
+ query.
23
+ - The resolved selection persists in Atelier's private workspace state and
24
+ reads back exactly.
25
+ - A manual or automatic apply policy is built, digested, validated and
26
+ installed through the runtime's installer; revocation is durable and is
27
+ re-read before every queued dispatch.
28
+ - A read-only view of the arbitration state answers which objects are
29
+ conflicted, pending, settled or unreadable and what a person does next.
30
+ - A receipt document for one of the gates G07 and G13 to G18 is checked for
31
+ shape and required fields.
32
+
33
+ Not real, and not claimed:
34
+
35
+ - Whether the installed app applies the focus query as built, indexes the
36
+ vault, or shows the graph the way the receipt says. That is acceptance
37
+ evidence from a running app (AP-01, AP-02), and nothing here produces it.
38
+ - Whether any gate is closed. `validateAcceptanceReceipt` answers
39
+ `gateClosed: false` on every input; its result is labelled
40
+ `schema-validation-only`.
41
+ - Any change to the files the app's UI owns under `.obsidian/`. Atelier never
42
+ writes `workspace.json`, `graph.json` or `bookmarks.json`.
43
+
44
+ ## Selection
45
+
46
+ `resolveSelection({ canonicalSnapshot, profile, scope, allowEmpty, pathRegistry })`
47
+ calls the contract's `selectScope` unchanged and adds no selector, default or
48
+ fallback. The answer carries:
49
+
50
+ - `scope`: the exact scope document (`atelier-obsidian-scope/v1`). The only
51
+ members filled in are the two expansion defaults the contract allows,
52
+ `direction: outgoing` and `order: canonical-id`. A budget is never
53
+ defaulted; an expansion without `depth` and `maxNodes` refuses with
54
+ `missing-expansion-budget`, and a budget out of range refuses with
55
+ `invalid-expansion`.
56
+ - `nodes`, `edges`, `outsideSelectionEdges`, `vaultNodes`, `vaultEdges`,
57
+ `truncated`, `unresolvedIds`, `diagnostics`: `selectScope`'s answer as is.
58
+ - `notePaths`: one vault-relative path per selected node, allocated by the
59
+ workspace path registry when the caller passes the persisted one, or by a
60
+ fresh allocation otherwise. Both are deterministic for the same inputs.
61
+ - `empty` and `emptyReason` (`explicit-empty` or `no-visible-members`). An
62
+ empty selection is refused with `selection-empty` unless the caller passes
63
+ `allowEmpty: true`; it is then reported empty, never widened.
64
+ - `focus`: `null` unless the mode is `focus`.
65
+
66
+ A withheld identity and an absent one are one answer, `unresolvedIds`, and
67
+ neither falls back to the whole corpus.
68
+
69
+ ### Focus
70
+
71
+ A focus keeps the full vault on disk and filters the native Graph view. The
72
+ query is
73
+
74
+ ```
75
+ path:"<note path>" OR path:"<note path>" ...
76
+ ```
77
+
78
+ in the order of the selected set (canonical-id order). Inside the quoted term
79
+ a backslash and a double quote are escaped with a backslash; nothing else is
80
+ changed, so a path that itself contains search operators (`tag:`, `-`, `OR`,
81
+ parentheses) stays text. Paths are NFC-normalized before they are quoted. A
82
+ path that carries a control character, a C1 control, or the U+2028 or U+2029
83
+ line separator cannot be a search term and refuses with
84
+ `focus-path-unrepresentable`; so does an absolute path, a backslash path or a
85
+ `..` segment. A focus with no selected note refuses with
86
+ `focus-selection-empty` even when the caller allows empty results: a filter
87
+ naming nothing would show the whole vault or nothing, and neither was asked
88
+ for.
89
+
90
+ The bookmark payload is `{ type: "graph", title: "Atelier focus <scope-id>",
91
+ options: { search: <query> } }`, the shape of a core-Bookmark graph entry.
92
+ The app assigns the creation time when the bookmark is made there. Only the
93
+ `graph` type is produced: core Bookmarks retain graph views, not local-graph
94
+ views.
95
+
96
+ Both values are applied by a person, an agent or the acceptance procedure in
97
+ the app. Atelier hands them over and writes nothing under `.obsidian/`.
98
+
99
+ ### Where the selector persists
100
+
101
+ `writeSelectionState` keeps the resolved selection at
102
+
103
+ ```
104
+ <data>/obsidian/<workspace-id>/state/selection/<scope-id>.json
105
+ ```
106
+
107
+ beside the maintenance and settings documents the runtime keeps there,
108
+ through the same private-state primitives (owner-only mode, atomic replace,
109
+ no symlink following) and the same guard that refuses private state inside an
110
+ enrolled repository. `assertWritableSelectionPath` refuses any target outside
111
+ `state/selection`, any target under `vaults/`, and any path with a `.obsidian`
112
+ segment. A rewrite that would change only the timestamp is not a change and
113
+ is not written. A stored document of another workspace, or one with a member
114
+ the shape does not know, refuses on read with `invalid-selection-state`.
115
+
116
+ ## Apply policy setup
117
+
118
+ `runPolicySetup({ action, input, workspace, repositoryRoots, now })` takes a
119
+ structured request and answers a structured document
120
+ (`atelier-obsidian-policy-setup/v1`, `ok: true|false`; a refusal is carried
121
+ as `refusal: { code, message, detail }`).
122
+
123
+ - `create`: builds `atelier-obsidian-apply-policy/v1` from
124
+ `{ policyId, mode, actor, selector, allowedEditClasses?, maxBatchSize?,
125
+ retryBudget?, version? }`, computes the canonical digest, validates the
126
+ document against the frozen contract and installs it through the runtime's
127
+ installer. `mode` is `manual` or `automatic`. Only an edit class with an
128
+ apply implementation can be allowed (`body-replacement` today); any other
129
+ refuses with `unimplemented-edit-class`. The conflict disposition is `hold`,
130
+ the only one that exists. Without an explicit `version`, the next revision
131
+ of an installed identity is one above it; an equal or lower version refuses
132
+ with `policy-version-not-newer` and installs nothing.
133
+ - `show`: the installed policy, the reference to it in the machine settings,
134
+ the maintenance mode, and whether an automatic apply would be authorized
135
+ right now.
136
+ - `revoke`: the stored policy is rewritten `revoked` first, then the
137
+ maintenance mode goes back to `manual`. Every later authorization read
138
+ denies with `apply-policy-revoked`, even when the mode is switched back to
139
+ automatic by hand.
140
+
141
+ Installing a policy never switches the maintenance mode. That is the person's
142
+ separate `mode set automatic`, which itself checks that an active automatic
143
+ policy is installed.
144
+
145
+ ### Revocation wins
146
+
147
+ The dispatch loop reads authorization from disk immediately before each
148
+ queued edit. A revocation that lands while one edit is being applied stops
149
+ the next one in the same batch: it is never dispatched, it stays `queued`,
150
+ and after a restart nothing is dispatched at all because the revocation is on
151
+ disk. `dispatchGate(workspace)` exposes that read in the form a caller sees.
152
+
153
+ ## Conflict view
154
+
155
+ `conflictView({ objects, edits, scopeId })` is a pure function of the object
156
+ entries (the object store's `list()`) and the pending edit records.
157
+ `readConflictView` reads both from the workspace's private state. The answer
158
+ (`atelier-obsidian-conflict-view/v1`) lists, per object, its identity, state
159
+ (`conflicted`, `pending`, `settled`, `empty`, `inconsistent`, `unreadable`),
160
+ source digest, whether a lease is held, whether an apply was started whose
161
+ outcome is not recorded, its operations with their states and reasons, the
162
+ conflicted operation keys, the open edits of the views that feed it, whether
163
+ a person is needed, and what happens next. No note text, title or path leaves
164
+ the view. The view decides nothing, chooses no winner and appends no event: a
165
+ conflict is resolved by a new operation that names the ones it resolves.
166
+
167
+ ## Acceptance receipt validation
168
+
169
+ `validateAcceptanceReceipt(receipt, { gate })` checks a document against the
170
+ `acceptance-receipt` schema and then against the rules of the named gate. The
171
+ answer carries `label: "schema-validation-only"`, `schemaValid`,
172
+ `requirementsMet`, `valid`, `outcome`, `evidenceType`, the list of
173
+ `missing` entries (`{ code, pointer, message }`), and always
174
+ `gateClosed: false` with `closes: "nothing"`. A failed or blocked receipt is
175
+ a valid receipt of its outcome; validity is not a pass.
176
+
177
+ A gate is closed by its owner inspecting the actual app, host or adopter
178
+ evidence and recording that in the parent matrix. A document that passes here
179
+ is an input to that inspection, never its result.
180
+
181
+ ### Required fields per gate
182
+
183
+ Every gate requires: `candidate.commit` (not the zero placeholder),
184
+ `candidate.treeDigest`, exact `environment.os.{name,version}`,
185
+ `environment.app.{name,version}` and `environment.cli.version` (a placeholder
186
+ such as `latest`, `unknown`, `n/a` or a blank refuses), every `evidence[]`
187
+ entry hashed with a positive `byteLength`, and `host.id` and `operator.id`
188
+ under `ext["mnstry.atelier.obsidian"]`. The extension is a closed shape:
189
+ `host`, `operator`, `evidenceRoles`, `acceptance`, `wallClock`, `dataset`.
190
+
191
+ | Gate | Procedure | Evidence type | Evidence roles (each names a hashed entry) | Also required |
192
+ | --- | --- | --- | --- | --- |
193
+ | G07 | AP-01 | `real-app` | `cli-link-inspection`, `app-observation` | human acceptance |
194
+ | G13 | AP-02 | `real-app` | `on-disk-membership`, `app-index-membership`, `graph-filter-observation` | human acceptance |
195
+ | G14 | AP-03 | `host` | `source-refresh-trace`, `dropped-event-recovery`, `sleep-wake-clock` | wall clock; no acceptance |
196
+ | G15 | AP-03 | `host` | `ownership-health`, `terminal-closure` | wall clock; no acceptance |
197
+ | G16 | AP-04 | `real-app` | `dataset-manifest`, `resource-samples`, `app-indexing-timings`, `warm-update-latencies` | wall clock; dataset (nodes, edges, fixture digest); no acceptance |
198
+ | G17 | AP-05 | `real-app` | `multi-vault-edit-trace`, `manual-apply-trace`, `automatic-apply-trace`, `uninstall-retention` | human acceptance |
199
+ | G18 | AP-06 | `human` | `tarball-audit`, `adopter-acceptance` | `candidate.tarballDigest`; adopter acceptance |
200
+
201
+ `procedureId` is the gate's procedure or a variant of it (`AP-02:run-3`); a
202
+ bare name of another procedure refuses. An acceptance is
203
+ `{ kind: human|adopter, actor, recordedAt, evidenceName }` and names its own
204
+ hashed evidence entry; an adopter acceptance recorded by the operator refuses
205
+ with `acceptance-not-separate`. A gate that records automation and host
206
+ evidence (G14, G15, G16) refuses an acceptance with
207
+ `acceptance-not-expected`. `receiptRequirementsFor(gate)` answers this table
208
+ as data.
209
+
210
+ Synthetic, schema-valid receipts for each gate are under
211
+ `fixtures/obsidian/acceptance/receipts/`. They name no real host, person or
212
+ machine path, and validating them closes nothing.
213
+
214
+ ## The command operations
215
+
216
+ `createSelectionContribution()` is a contribution `{ id, register({ operations }) }`
217
+ for the `obsidian` command's operation registry, the extension point the
218
+ runtime lays out. It registers:
219
+
220
+ - `selection resolve ID | persist ID [allow-empty] | show ID | list`
221
+ - `conflicts [ID]`
222
+ - `apply-policy create FILE | show | revoke`
223
+
224
+ The built-in `scope`, `policy` and `mode` names are reserved and untouched.
225
+ The production loader reads regular `.mjs` modules from
226
+ `src/runtime/obsidian/contributions/`, and that directory ships three one-line
227
+ modules: `source-apply.mjs` (`apply`), `proposal-adapter.mjs` (`proposals`)
228
+ and `selection-ui.mjs` (`selection`, `conflicts`, `apply-policy`). The shipped
229
+ `atelier obsidian` command loads them and dispatches every registered
230
+ operation with the discipline of the built-ins: noninteractive, one JSON
231
+ document under `--json`, exit 2 with a typed code for a refusal or a usage
232
+ error, exit 3 when the operation ran and its answer is not success.
233
+ `atelier obsidian status` lists the registered operations under
234
+ `operations`; `atelier obsidian --help` names them.
235
+
236
+ A manual apply on a real workspace, from the shipped command:
237
+
238
+ ```sh
239
+ atelier obsidian apply list --project atelier.project.json --json
240
+ atelier obsidian apply show EDIT --project atelier.project.json --json
241
+ atelier obsidian apply run EDIT --actor ID --project atelier.project.json --json
242
+ ```
243
+
244
+ `--actor` is an option of `apply run` only; every other operation refuses it
245
+ as a usage error. `apply run` exits 0 when the edit was applied and 3 when it
246
+ ran and the answer is anything else; nothing is staged or committed either
247
+ way. A contribution registers which shared options it takes by naming them
248
+ under `options`; one that names none refuses `--actor` before it runs.
249
+
250
+ ## Package entry points
251
+
252
+ The published package declares these subpaths. Each is the module named, and
253
+ nothing under `scripts/obsidian/` ships.
254
+
255
+ | Subpath | Module |
256
+ | --- | --- |
257
+ | `@mnstry/atelier/obsidian` | `src/runtime/obsidian/index.mjs`: enablement, machine settings, engine, service lifecycle, production seams, app qualification |
258
+ | `@mnstry/atelier/obsidian/contracts` | `src/projection/obsidian/contracts.mjs`: contract validation, `selectScope`, note paths |
259
+ | `@mnstry/atelier/obsidian/materialize` | `prepareView`, settings, path registry |
260
+ | `@mnstry/atelier/obsidian/publication` | `publishView`, editor adapters, the exchange |
261
+ | `@mnstry/atelier/obsidian/recovery` | recovery store, journals, late-writer recheck |
262
+ | `@mnstry/atelier/obsidian/edits` | edit observation, arbitration, apply policy, source apply |
263
+ | `@mnstry/atelier/obsidian/proposals` | proposal queue, router and adapter |
264
+ | `@mnstry/atelier/obsidian/selection` | this document's module, `src/projection/obsidian/selection-ui/index.mjs` |
265
+
266
+ Every `contracts/atelier-obsidian-*.v1.schema.json` is exported under its own
267
+ path. The package root (`@mnstry/atelier`) exports nothing of the projection.
268
+ Names ending `ForOracleTests` are mutation controls for the test suite, not a
269
+ supported API. The whole surface is alpha and may change between prereleases.
270
+ What the tarball must and must not carry, and the package proof, are in
271
+ [release-engineering.md](release-engineering.md#obsidian-package-contents).
272
+
273
+ ## First vault: what to expect
274
+
275
+ This is the path an adopter walks on one machine, in the order the command
276
+ requires it. Every operation and flag below is the shipped `atelier obsidian`
277
+ usage text; `atelier obsidian --help` prints it.
278
+
279
+ 1. Enable the projection in the project configuration. The member
280
+ `ext["mnstry.atelier.obsidian"]` is an `atelier-obsidian-ext-settings/v1`
281
+ document: `enabled: true`, `scopes` (each with a `scopeId`, a `mode` of
282
+ `full`, `scoped` or `focus`, a `selector`, and for an expansion an explicit
283
+ `depth` and `maxNodes`), and optionally `defaultScopeId`. A project without
284
+ this member is `disabled (not-configured)` and nothing is published.
285
+ `atelier obsidian scope list` shows what was declared.
286
+ 2. Set the private machine settings. They live outside every repository and
287
+ are never committed:
288
+ - `atelier obsidian audience set A,B` names the audiences this machine lets
289
+ into a view. No audience is admitted by default, so a view is empty until
290
+ one is set; `audience clear` empties it again.
291
+ - `atelier obsidian mode set manual` keeps every queued edit waiting for a
292
+ person. `mode set automatic` is refused until an active automatic policy
293
+ is installed.
294
+ - `atelier obsidian policy digest FILE` prints the digest the policy file
295
+ has to carry; `policy install FILE` installs it and leaves the mode
296
+ unchanged; `policy revoke` returns the mode to `manual` and stops every
297
+ later apply.
298
+ 3. Start the maintenance service:
299
+ `atelier obsidian service start --consent-actor ID --adapter=obsidian-cli`.
300
+ Reaching the installed app is never a default, so `--adapter=obsidian-cli`
301
+ is required, and the consent actor records who allowed the service to run.
302
+ `service status` and `service stop` manage it; `service unit --print
303
+ --adapter=obsidian-cli` prints a startup unit and installs nothing.
304
+ 4. Open a view: `atelier obsidian open --scope ID --adapter=obsidian-cli`.
305
+ The command starts or reconnects maintenance, verifies the vault by reading
306
+ it back, and asks the app (version 1.13.7 or later) to open it.
307
+
308
+ `open` and `status` answer with a freshness state, not a promise. `current`
309
+ means the vault is the present generation, verified by read-back, and the app
310
+ has it open. `updating` means maintenance is publishing or has not finished.
311
+ `stale-readable` means a last good vault exists but is not proven current;
312
+ `open --allow-stale` opens it as it is. `not-prepared` means no generation has
313
+ been published yet. `held-for-your-edit` means a note you edited is preserved
314
+ and the view is not republished over it. The remaining outcomes (`indexing`,
315
+ `publisher-conflict`, `app-missing`, `app-version-unsupported`,
316
+ `app-cli-unavailable`, `launch-failed`, `service-unavailable`, `busy`,
317
+ `disabled`) each name what to do next, and exit code 3 says the answer is not
318
+ success.
319
+
320
+ Edits made in the vault are preserved before anything is republished. A body
321
+ replacement is held as a pending edit; under manual mode it reaches its source
322
+ file only through `atelier obsidian apply run EDIT [--actor ID]`, after
323
+ `apply list` and `apply show EDIT` named it. An applied edit changes the source
324
+ file and nothing is staged or committed. Under automatic mode the engine
325
+ applies body replacements itself under the installed policy, and revocation is
326
+ read again before every one. An edit that is not a body replacement, such as a
327
+ new or changed link to another note or an edited front matter, becomes a
328
+ copy-only proposal in the owning repository's proposal store; `atelier obsidian
329
+ proposals list` and `proposals show OPERATION` read them, and nothing applies
330
+ one. A body edit to a note whose source uses CRLF line endings is also a
331
+ proposal, never an apply, because the app normalizes line endings on save.
332
+
333
+ The vault itself lives under the private data root, outside every repository:
334
+ `~/Library/Application Support/Atelier` on macOS, `$XDG_DATA_HOME/atelier`
335
+ (else `~/.local/share/atelier`) on Linux and `%LOCALAPPDATA%\Atelier` on
336
+ Windows, under `obsidian/<workspace-id>/`. `--data-root DIR` names another
337
+ absolute directory. Private state inside an enrolled repository is refused.
338
+ Publication is proven on macOS arm64 only and is refused on Windows; see
339
+ [Known limits](#known-limits).
340
+
341
+ ## Known limits
342
+
343
+ These are the limits known at this release. None is hidden behind a skipped
344
+ test reported as a pass.
345
+
346
+ - Windows: no atomic file exchange is known, so the publisher refuses with
347
+ `exchange-unsupported-platform` and publishes nothing, and source apply
348
+ refuses for the same reason. Selection, policy setup, `prepareView` and
349
+ receipt validation work. The tests that publish are skipped there and say
350
+ why.
351
+ - Linux: the exchange primitive was proven in a container on aarch64. The
352
+ real-app suite (the publication interleavings and procedures AP-01 to AP-05)
353
+ has not been run on Linux. x86_64 has not been run on any system.
354
+ - macOS: the exchange is a raw system call reached through the system perl. The
355
+ perl binary is used only when uid 0 owns it and neither group nor others can
356
+ write it; otherwise publication refuses with
357
+ `exchange-interpreter-untrusted`. A machine without the stock perl cannot
358
+ publish.
359
+ - App version: `MINIMUM_APP_VERSION` in
360
+ `src/runtime/obsidian/app-capability.mjs` is 1.13.7, the only version the
361
+ publication protocol was proven on. An older, unreadable or unknown version
362
+ is `app-version-unsupported`. There is a floor and no ceiling: a newer app
363
+ is admitted although the protocol depends on the view's undocumented
364
+ `lastSavedData` field, and the protocol cases have not been re-run on any
365
+ later release. See the "App capability floor" row of
366
+ [obsidian-contract.md](obsidian-contract.md).
367
+ - CRLF sources: the editor normalizes line endings when it saves, so a body
368
+ edit made in the vault to a note whose source uses CRLF is more than a body
369
+ replacement to the edit lens. It is preserved and becomes a proposal; it is
370
+ never applied to the source, in manual or automatic mode. Edit such a note
371
+ in its repository.
372
+ - An edit the byte lens cannot turn into source bytes (a new or changed link
373
+ to another note of the vault, an edited front matter) becomes a copy-only
374
+ proposal. No operation applies one.
375
+ - Acceptance: a schema-valid receipt closes no gate, the package proof closes
376
+ no gate, and no adopter acceptance is recorded in this repository.
377
+
378
+ ## Mutation controls
379
+
380
+ The test suite proves each oracle can fail:
381
+
382
+ - `createFocusQueryBuilderForOracleTests` accepts a builder with escaping,
383
+ quoting or joining switched off; the escaping oracle fails on exactly the
384
+ cases that depend on the switched-off step.
385
+ - `createReceiptValidatorForOracleTests` accepts a rule table with one rule
386
+ switched off; every negative case that depends on that rule then passes,
387
+ and even that closes nothing.