@mnstry/atelier 0.2.0-alpha.11 → 0.2.0-alpha.13

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 (560) hide show
  1. package/CHANGELOG.md +1005 -0
  2. package/README.md +149 -9
  3. package/contracts/atelier-adoption-policy.v2.schema.json +55 -0
  4. package/contracts/atelier-architecture.v1.schema.json +258 -0
  5. package/contracts/atelier-boundary-delegations.v1.schema.json +161 -0
  6. package/contracts/atelier-boundary-owner-keys.v1.schema.json +98 -0
  7. package/contracts/atelier-build.v1.schema.json +1076 -0
  8. package/contracts/atelier-capability.v1.schema.json +1252 -0
  9. package/contracts/atelier-coordination.v1.schema.json +1050 -0
  10. package/contracts/atelier-evidence-navigation.v1.schema.json +603 -0
  11. package/contracts/atelier-harness.v1.schema.json +234 -0
  12. package/contracts/atelier-ingestion.v1.schema.json +806 -0
  13. package/contracts/atelier-inquiry.v1.schema.json +1772 -0
  14. package/contracts/atelier-instruction-adoption.v1.schema.json +490 -0
  15. package/contracts/atelier-interaction.v1.schema.json +553 -0
  16. package/contracts/atelier-judgment.v1.schema.json +690 -0
  17. package/contracts/atelier-knowledge.v1.schema.json +1512 -0
  18. package/contracts/atelier-learning.v1.schema.json +1095 -0
  19. package/contracts/atelier-migration.v3.schema.json +64 -0
  20. package/contracts/atelier-obsidian-generation-manifest.v2.schema.json +372 -0
  21. package/contracts/atelier-personal-workspace-manifest.v1.schema.json +87 -0
  22. package/contracts/atelier-personal-workspace-overlay.v1.schema.json +299 -0
  23. package/contracts/atelier-template-adoption.v1.schema.json +223 -0
  24. package/contracts/atelier-template-profile.v1.schema.json +1168 -0
  25. package/contracts/atelier-trackable.v1.schema.json +781 -0
  26. package/contracts/atelier-upgrade-plan.v3.schema.json +532 -0
  27. package/contracts/compat-baseline.json +1 -1
  28. package/docs/architecture.md +89 -0
  29. package/docs/assurance-controls.md +4 -3
  30. package/docs/blocks/capability-stewardship.md +17 -0
  31. package/docs/blocks/claims.md +16 -3
  32. package/docs/blocks/inquiry-harnesses.md +19 -0
  33. package/docs/blocks/learning-harnesses.md +17 -0
  34. package/docs/capability-stewardship.md +269 -0
  35. package/docs/coordination.md +51 -0
  36. package/docs/decision-practices.md +111 -0
  37. package/docs/decisions.md +29 -0
  38. package/docs/evidence-navigation.md +237 -0
  39. package/docs/exact-upgrades.md +3 -2
  40. package/docs/ingestion.md +181 -0
  41. package/docs/inquiry-harnesses.md +211 -0
  42. package/docs/install.md +80 -3
  43. package/docs/intake-and-guides.md +5 -0
  44. package/docs/integration-contract-decisions.md +24 -2
  45. package/docs/interaction-and-reflection.md +72 -0
  46. package/docs/knowledge-graph.md +20 -0
  47. package/docs/knowledge-health/api.md +30 -0
  48. package/docs/knowledge-health/assessment/api.md +96 -0
  49. package/docs/knowledge-health/assessment/capabilities.md +40 -0
  50. package/docs/knowledge-health/assessment/evaluation.md +27 -0
  51. package/docs/knowledge-health/assessment/facilitator.md +30 -0
  52. package/docs/knowledge-health/assessment/quickstart.md +61 -0
  53. package/docs/knowledge-health/assessment/troubleshooting.md +23 -0
  54. package/docs/knowledge-health/devday/facilitator.md +16 -0
  55. package/docs/knowledge-health/devday/participant-response.md +22 -0
  56. package/docs/knowledge-health/devday/public-default.md +107 -0
  57. package/docs/knowledge-health/devday/quickstart.md +18 -0
  58. package/docs/knowledge-health/devday/support.md +22 -0
  59. package/docs/knowledge-health/exercise.md +17 -0
  60. package/docs/knowledge-health/facilitator.md +20 -0
  61. package/docs/knowledge-health/quickstart.md +94 -0
  62. package/docs/knowledge-health/readme.md +15 -0
  63. package/docs/knowledge-health/support.md +34 -0
  64. package/docs/knowledge-setup.md +248 -0
  65. package/docs/knowledge-workspace.md +264 -0
  66. package/docs/learning-harnesses.md +238 -0
  67. package/docs/learning.md +215 -0
  68. package/docs/local-services.md +242 -26
  69. package/docs/obsidian-contract.md +878 -36
  70. package/docs/obsidian-plugin.md +619 -0
  71. package/docs/obsidian.md +809 -64
  72. package/docs/optional-ingestion.md +83 -0
  73. package/docs/personal-workspace.md +257 -0
  74. package/docs/practical-judgment.md +92 -0
  75. package/docs/progressive-ingestion-acceptance.md +89 -0
  76. package/docs/progressive-ingestion.md +235 -0
  77. package/docs/project-command-inventory.md +1 -0
  78. package/docs/release-engineering.md +56 -1
  79. package/docs/repo-boundary-guard.md +94 -0
  80. package/docs/research-starter-quickstart.md +66 -0
  81. package/docs/research-starter.md +114 -0
  82. package/docs/semantic-ingestion.md +198 -0
  83. package/docs/semantic-operation.md +317 -0
  84. package/docs/skill-steward.md +6 -0
  85. package/docs/template-profile.md +164 -0
  86. package/docs/template-upgrades.md +114 -0
  87. package/docs/trackables.md +111 -0
  88. package/docs/upgrade.md +68 -3
  89. package/fixtures/atelier-architecture/binding/invalid/document.json +19 -0
  90. package/fixtures/atelier-architecture/binding/valid/document.json +19 -0
  91. package/fixtures/atelier-architecture/catalog/invalid/document.json +290 -0
  92. package/fixtures/atelier-architecture/catalog/valid/document.json +343 -0
  93. package/fixtures/atelier-build-contract/attempt/invalid/document.json +20 -0
  94. package/fixtures/atelier-build-contract/attempt/valid/document.json +19 -0
  95. package/fixtures/atelier-build-contract/candidate/invalid/document.json +24 -0
  96. package/fixtures/atelier-build-contract/candidate/valid/document.json +23 -0
  97. package/fixtures/atelier-build-contract/decision/invalid/document.json +31 -0
  98. package/fixtures/atelier-build-contract/decision/valid/document.json +30 -0
  99. package/fixtures/atelier-build-contract/delivery/invalid/document.json +18 -0
  100. package/fixtures/atelier-build-contract/delivery/valid/document.json +17 -0
  101. package/fixtures/atelier-build-contract/gate/invalid/document.json +22 -0
  102. package/fixtures/atelier-build-contract/gate/valid/document.json +21 -0
  103. package/fixtures/atelier-build-contract/ledger/invalid/document.json +270 -0
  104. package/fixtures/atelier-build-contract/ledger/valid/document.json +269 -0
  105. package/fixtures/atelier-build-contract/objective/invalid/document.json +73 -0
  106. package/fixtures/atelier-build-contract/objective/valid/document.json +72 -0
  107. package/fixtures/atelier-build-contract/progress/invalid/document.json +18 -0
  108. package/fixtures/atelier-build-contract/progress/valid/document.json +17 -0
  109. package/fixtures/atelier-capability-contract/adoption/invalid/document.json +71 -0
  110. package/fixtures/atelier-capability-contract/adoption/valid/document.json +70 -0
  111. package/fixtures/atelier-capability-contract/event/invalid/document.json +18 -0
  112. package/fixtures/atelier-capability-contract/event/valid/document.json +17 -0
  113. package/fixtures/atelier-capability-contract/journal/invalid/document.json +382 -0
  114. package/fixtures/atelier-capability-contract/journal/valid/document.json +381 -0
  115. package/fixtures/atelier-capability-contract/notice/invalid/document.json +8 -0
  116. package/fixtures/atelier-capability-contract/notice/valid/document.json +7 -0
  117. package/fixtures/atelier-capability-contract/package/invalid/document.json +59 -0
  118. package/fixtures/atelier-capability-contract/package/valid/document.json +58 -0
  119. package/fixtures/atelier-capability-contract/plan/invalid/document.json +107 -0
  120. package/fixtures/atelier-capability-contract/plan/valid/document.json +106 -0
  121. package/fixtures/atelier-capability-contract/release/invalid/document.json +85 -0
  122. package/fixtures/atelier-capability-contract/release/valid/document.json +84 -0
  123. package/fixtures/atelier-capability-contract/state/invalid/document.json +316 -0
  124. package/fixtures/atelier-capability-contract/state/valid/document.json +315 -0
  125. package/fixtures/atelier-coordination/dependency/invalid/document.json +37 -0
  126. package/fixtures/atelier-coordination/dependency/valid/document.json +36 -0
  127. package/fixtures/atelier-coordination/directive/invalid/document.json +25 -0
  128. package/fixtures/atelier-coordination/directive/valid/document.json +24 -0
  129. package/fixtures/atelier-coordination/disposition/invalid/document.json +34 -0
  130. package/fixtures/atelier-coordination/disposition/valid/document.json +33 -0
  131. package/fixtures/atelier-coordination/outcome/invalid/document.json +39 -0
  132. package/fixtures/atelier-coordination/outcome/valid/document.json +38 -0
  133. package/fixtures/atelier-coordination/recovery/invalid/document.json +34 -0
  134. package/fixtures/atelier-coordination/recovery/valid/document.json +33 -0
  135. package/fixtures/atelier-harness-contract/handoff/invalid/document.json +25 -0
  136. package/fixtures/atelier-harness-contract/handoff/valid/document.json +24 -0
  137. package/fixtures/atelier-ingestion/invalid/authority.json +19 -0
  138. package/fixtures/atelier-ingestion/semantic-baseline.json +26 -0
  139. package/fixtures/atelier-ingestion/semantic-operation.json +75 -0
  140. package/fixtures/atelier-ingestion/valid/plan-input.json +18 -0
  141. package/fixtures/atelier-inquiry-contract/assessment/invalid/document.json +41 -0
  142. package/fixtures/atelier-inquiry-contract/assessment/valid/document.json +40 -0
  143. package/fixtures/atelier-inquiry-contract/bundle/invalid/document.json +51 -0
  144. package/fixtures/atelier-inquiry-contract/bundle/valid/document.json +50 -0
  145. package/fixtures/atelier-inquiry-contract/campaign/invalid/document.json +17 -0
  146. package/fixtures/atelier-inquiry-contract/campaign/valid/document.json +16 -0
  147. package/fixtures/atelier-inquiry-contract/decision/invalid/document.json +22 -0
  148. package/fixtures/atelier-inquiry-contract/decision/valid/document.json +21 -0
  149. package/fixtures/atelier-inquiry-contract/feedback/invalid/document.json +19 -0
  150. package/fixtures/atelier-inquiry-contract/feedback/valid/document.json +18 -0
  151. package/fixtures/atelier-inquiry-contract/handoff/invalid/document.json +92 -0
  152. package/fixtures/atelier-inquiry-contract/handoff/valid/document.json +91 -0
  153. package/fixtures/atelier-inquiry-contract/hypothesis/invalid/document.json +20 -0
  154. package/fixtures/atelier-inquiry-contract/hypothesis/valid/document.json +19 -0
  155. package/fixtures/atelier-inquiry-contract/ledger/invalid/document.json +680 -0
  156. package/fixtures/atelier-inquiry-contract/ledger/valid/document.json +679 -0
  157. package/fixtures/atelier-inquiry-contract/legacy-assessment/invalid/document.json +19 -0
  158. package/fixtures/atelier-inquiry-contract/legacy-assessment/valid/document.json +18 -0
  159. package/fixtures/atelier-inquiry-contract/request/invalid/document.json +50 -0
  160. package/fixtures/atelier-inquiry-contract/request/valid/document.json +49 -0
  161. package/fixtures/atelier-inquiry-contract/source/invalid/document.json +18 -0
  162. package/fixtures/atelier-inquiry-contract/source/valid/document.json +17 -0
  163. package/fixtures/atelier-inquiry-contract/withdrawal/invalid/document.json +16 -0
  164. package/fixtures/atelier-inquiry-contract/withdrawal/valid/document.json +15 -0
  165. package/fixtures/atelier-instruction-adoption/context-receipt/invalid/document.json +18 -0
  166. package/fixtures/atelier-instruction-adoption/context-receipt/valid/document.json +17 -0
  167. package/fixtures/atelier-instruction-adoption/plan/invalid/document.json +63 -0
  168. package/fixtures/atelier-instruction-adoption/plan/valid/document.json +62 -0
  169. package/fixtures/atelier-instruction-adoption/receipt/invalid/document.json +22 -0
  170. package/fixtures/atelier-instruction-adoption/receipt/valid/document.json +21 -0
  171. package/fixtures/atelier-instruction-adoption/state/invalid/document.json +30 -0
  172. package/fixtures/atelier-instruction-adoption/state/valid/document.json +29 -0
  173. package/fixtures/atelier-interaction/act/invalid/document.json +25 -0
  174. package/fixtures/atelier-interaction/act/valid/document.json +24 -0
  175. package/fixtures/atelier-interaction/assessment/invalid/document.json +32 -0
  176. package/fixtures/atelier-interaction/assessment/valid/document.json +31 -0
  177. package/fixtures/atelier-interaction/observation/invalid/document.json +22 -0
  178. package/fixtures/atelier-interaction/observation/valid/document.json +21 -0
  179. package/fixtures/atelier-interaction/policy/invalid/document.json +20 -0
  180. package/fixtures/atelier-interaction/policy/valid/document.json +19 -0
  181. package/fixtures/atelier-judgment/case/invalid/document.json +76 -0
  182. package/fixtures/atelier-judgment/case/valid/document.json +75 -0
  183. package/fixtures/atelier-judgment/decision/invalid/document.json +38 -0
  184. package/fixtures/atelier-judgment/decision/valid/document.json +37 -0
  185. package/fixtures/atelier-judgment/native-decision.md +3 -0
  186. package/fixtures/atelier-judgment/practice-reconsideration/definition.json +92 -0
  187. package/fixtures/atelier-judgment/practice-reconsideration/scenario.json +435 -0
  188. package/fixtures/atelier-knowledge-contract/activation/invalid/document.json +26 -0
  189. package/fixtures/atelier-knowledge-contract/activation/valid/document.json +25 -0
  190. package/fixtures/atelier-knowledge-contract/contribution/invalid/document.json +34 -0
  191. package/fixtures/atelier-knowledge-contract/contribution/valid/document.json +33 -0
  192. package/fixtures/atelier-knowledge-contract/domain/invalid/document.json +41 -0
  193. package/fixtures/atelier-knowledge-contract/domain/valid/document.json +40 -0
  194. package/fixtures/atelier-knowledge-contract/domain-revision/invalid/document.json +46 -0
  195. package/fixtures/atelier-knowledge-contract/domain-revision/valid/document.json +45 -0
  196. package/fixtures/atelier-knowledge-contract/evaluation/invalid/document.json +21 -0
  197. package/fixtures/atelier-knowledge-contract/evaluation/valid/document.json +20 -0
  198. package/fixtures/atelier-knowledge-contract/ledger/invalid/document.json +318 -0
  199. package/fixtures/atelier-knowledge-contract/ledger/valid/document.json +317 -0
  200. package/fixtures/atelier-knowledge-contract/relation/invalid/document.json +25 -0
  201. package/fixtures/atelier-knowledge-contract/relation/valid/document.json +24 -0
  202. package/fixtures/atelier-knowledge-contract/review/invalid/document.json +18 -0
  203. package/fixtures/atelier-knowledge-contract/review/valid/document.json +17 -0
  204. package/fixtures/atelier-knowledge-contract/withdrawal/invalid/document.json +16 -0
  205. package/fixtures/atelier-knowledge-contract/withdrawal/valid/document.json +15 -0
  206. package/fixtures/atelier-learning/invalid/authority.json +14 -0
  207. package/fixtures/atelier-learning/valid/capture.json +13 -0
  208. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/authority-key.json +17 -0
  209. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/nonempty-ext.json +25 -0
  210. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/wrong-schema.json +22 -0
  211. package/fixtures/atelier-personal-workspace-contract/manifest/valid/manifest.json +22 -0
  212. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/authority-key.json +25 -0
  213. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/unknown-top-level-field.json +27 -0
  214. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/wrong-schema.json +24 -0
  215. package/fixtures/atelier-trackable/definition/invalid/document.json +15 -0
  216. package/fixtures/atelier-trackable/definition/valid/document.json +14 -0
  217. package/fixtures/atelier-trackable/request/invalid/document.json +23 -0
  218. package/fixtures/atelier-trackable/request/valid/document.json +22 -0
  219. package/fixtures/boundary-delegations/invalid/authority-key.v1.json +30 -0
  220. package/fixtures/boundary-delegations/invalid/push-operation.v1.json +28 -0
  221. package/fixtures/boundary-delegations/invalid/unsigned.v1.json +25 -0
  222. package/fixtures/boundary-delegations/valid/empty.v1.json +4 -0
  223. package/fixtures/boundary-delegations/valid/signed-operator.v1.json +30 -0
  224. package/fixtures/boundary-owner-keys/invalid/wrong-algorithm.v1.json +15 -0
  225. package/fixtures/boundary-owner-keys/invalid/wrong-curve.v1.json +15 -0
  226. package/fixtures/boundary-owner-keys/valid/one-owner.v1.json +17 -0
  227. package/fixtures/capability-packages/adoption.example.json +70 -0
  228. package/fixtures/capability-packages/evidence-review/capability-package.json +58 -0
  229. package/fixtures/capability-packages/evidence-review/capability-release.json +84 -0
  230. package/fixtures/capability-packages/evidence-review/evaluation.md +15 -0
  231. package/fixtures/capability-packages/evidence-review/skills/evidence-review/SKILL.md +22 -0
  232. package/fixtures/capability-packages/evidence-review/skills/evidence-review/references/ledger.md +7 -0
  233. package/fixtures/capability-packages/research/capability-package.json +88 -0
  234. package/fixtures/capability-packages/research/capability-release.json +134 -0
  235. package/fixtures/capability-packages/research/evaluation.md +15 -0
  236. package/fixtures/capability-packages/research/skills/research-integrate/SKILL.md +29 -0
  237. package/fixtures/capability-packages/research/skills/research-integrate/references/integration.md +10 -0
  238. package/fixtures/capability-packages/research/skills/research-plan/SKILL.md +27 -0
  239. package/fixtures/capability-packages/research/skills/research-plan/references/inquiries.md +26 -0
  240. package/fixtures/capability-packages/research/skills/research-synthesize/SKILL.md +23 -0
  241. package/fixtures/capability-packages/research/skills/research-synthesize/references/synthesis.md +12 -0
  242. package/fixtures/evidence-navigation/invalid/duplicate-operation.json +16 -0
  243. package/fixtures/evidence-navigation/invalid/instruction-kind.json +36 -0
  244. package/fixtures/evidence-navigation/invalid/invalid-digest.json +36 -0
  245. package/fixtures/evidence-navigation/invalid/invalid-time.json +36 -0
  246. package/fixtures/evidence-navigation/invalid/missing-attribution.json +35 -0
  247. package/fixtures/evidence-navigation/invalid/reserved-extension.json +19 -0
  248. package/fixtures/evidence-navigation/invalid/unattributed-acceptance.json +36 -0
  249. package/fixtures/evidence-navigation/invalid/uncoerced-version.json +16 -0
  250. package/fixtures/evidence-navigation/invalid/unknown-currency.json +17 -0
  251. package/fixtures/evidence-navigation/invalid/unknown-selector-field.json +37 -0
  252. package/fixtures/evidence-navigation/invalid/unsupported-operation.json +15 -0
  253. package/fixtures/evidence-navigation/valid/claim.json +36 -0
  254. package/fixtures/evidence-navigation/valid/host.json +16 -0
  255. package/fixtures/evidence-navigation/valid/profile.json +16 -0
  256. package/fixtures/evidence-navigation/valid/snapshot.json +17 -0
  257. package/fixtures/harness-packages/build-harness/capability-package.json +61 -0
  258. package/fixtures/harness-packages/build-harness/capability-release.json +82 -0
  259. package/fixtures/harness-packages/build-harness/evaluation.md +3 -0
  260. package/fixtures/harness-packages/build-harness/skills/atelier-build-harness/SKILL.md +59 -0
  261. package/fixtures/harness-packages/knowledge-harness/capability-package.json +61 -0
  262. package/fixtures/harness-packages/knowledge-harness/capability-release.json +82 -0
  263. package/fixtures/harness-packages/knowledge-harness/evaluation.md +3 -0
  264. package/fixtures/harness-packages/knowledge-harness/skills/atelier-knowledge-harness/SKILL.md +60 -0
  265. package/fixtures/harnesses/learning-cycle.json +780 -0
  266. package/fixtures/inquiry/workshop.json +675 -0
  267. package/fixtures/inquiry-packages/discovery-harness/capability-package.json +61 -0
  268. package/fixtures/inquiry-packages/discovery-harness/capability-release.json +82 -0
  269. package/fixtures/inquiry-packages/discovery-harness/evaluation.md +3 -0
  270. package/fixtures/inquiry-packages/discovery-harness/skills/atelier-discovery-harness/SKILL.md +48 -0
  271. package/fixtures/inquiry-packages/research-harness/capability-package.json +61 -0
  272. package/fixtures/inquiry-packages/research-harness/capability-release.json +82 -0
  273. package/fixtures/inquiry-packages/research-harness/evaluation.md +3 -0
  274. package/fixtures/inquiry-packages/research-harness/skills/atelier-research-harness/SKILL.md +43 -0
  275. package/fixtures/knowledge-health/calibration-suite.json +26 -0
  276. package/fixtures/knowledge-health/calibration-trial.json +37 -0
  277. package/fixtures/knowledge-health/corrected/checklist.md +18 -0
  278. package/fixtures/knowledge-health/devday/participant-record.json +19 -0
  279. package/fixtures/knowledge-health/expected-summary.json +27 -0
  280. package/fixtures/knowledge-health/workshop/README.md +20 -0
  281. package/fixtures/knowledge-health/workshop/atelier.project.json +7 -0
  282. package/fixtures/knowledge-health/workshop/knowledge-plan.json +65 -0
  283. package/fixtures/knowledge-health/workshop/records/checklist.md +18 -0
  284. package/fixtures/knowledge-health/workshop/records/workshop.md +18 -0
  285. package/fixtures/knowledge-health/workshop/repo-access.v1.json +5 -0
  286. package/fixtures/knowledge-health/workspace/atelier.project.json +18 -0
  287. package/fixtures/knowledge-health/workspace/knowledge-plan.json +74 -0
  288. package/fixtures/knowledge-health/workspace/records/checklist.md +18 -0
  289. package/fixtures/knowledge-health/workspace/records/pilot.md +16 -0
  290. package/fixtures/knowledge-health/workspace/repo-access.v1.json +9 -0
  291. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/case-only-collision.v2.json +160 -0
  292. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/flat-note-path.v2.json +160 -0
  293. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/hidden-folder.v2.json +160 -0
  294. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/identity-in-the-body.v2.json +160 -0
  295. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/link-breaking-name.v2.json +160 -0
  296. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/missing-identity-region.v2.json +156 -0
  297. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/missing-layout-version.v2.json +159 -0
  298. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/note-named-like-a-folder.v2.json +160 -0
  299. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/unknown-region-kind.v2.json +160 -0
  300. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/v1-contract-version.v2.json +161 -0
  301. package/fixtures/obsidian/contracts/generation-manifest-v2/valid/three-notes.v2.json +160 -0
  302. package/fixtures/obsidian/edits/workspace.json +1 -1
  303. package/fixtures/obsidian/materialization/expected-full.json +21 -21
  304. package/fixtures/obsidian/materialization/expected-full.layout-1.json +99 -0
  305. package/fixtures/obsidian/materialization/expected-scoped.json +7 -7
  306. package/fixtures/obsidian/materialization/expected-scoped.layout-1.json +39 -0
  307. package/fixtures/personal-workspace/overlay.json +24 -0
  308. package/fixtures/templates/local-library.v1.json +75 -0
  309. package/fixtures/templates/upgrade-contracts/adoption-policy.v2/invalid.json +16 -0
  310. package/fixtures/templates/upgrade-contracts/adoption-policy.v2/valid.json +13 -0
  311. package/fixtures/templates/upgrade-contracts/migration.v3/invalid.json +24 -0
  312. package/fixtures/templates/upgrade-contracts/migration.v3/valid.json +21 -0
  313. package/fixtures/templates/upgrade-contracts/template-adoption.v1/invalid.json +60 -0
  314. package/fixtures/templates/upgrade-contracts/template-adoption.v1/valid.json +57 -0
  315. package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/invalid.json +85 -0
  316. package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/valid.json +82 -0
  317. package/package.json +64 -6
  318. package/plugins/obsidian/main.js +444 -0
  319. package/plugins/obsidian/manifest.json +9 -0
  320. package/plugins/obsidian/styles.css +22 -0
  321. package/skills/claude/atelier-build-harness/SKILL.md +59 -0
  322. package/skills/claude/atelier-coordination/SKILL.md +32 -0
  323. package/skills/claude/atelier-discovery-harness/SKILL.md +48 -0
  324. package/skills/claude/atelier-guided-upgrade/SKILL.md +29 -0
  325. package/skills/claude/atelier-interaction/SKILL.md +34 -0
  326. package/skills/claude/atelier-knowledge-harness/SKILL.md +60 -0
  327. package/skills/claude/atelier-knowledge-setup/SKILL.md +72 -0
  328. package/skills/claude/atelier-practical-judgment/SKILL.md +64 -0
  329. package/skills/claude/atelier-research-harness/SKILL.md +43 -0
  330. package/skills/claude/atelier-skill-steward/SKILL.md +53 -0
  331. package/skills/claude/atelier-trackables/SKILL.md +40 -0
  332. package/skills/codex/atelier-build-harness/SKILL.md +59 -0
  333. package/skills/codex/atelier-coordination/SKILL.md +32 -0
  334. package/skills/codex/atelier-discovery-harness/SKILL.md +48 -0
  335. package/skills/codex/atelier-guided-upgrade/SKILL.md +29 -0
  336. package/skills/codex/atelier-interaction/SKILL.md +34 -0
  337. package/skills/codex/atelier-knowledge-harness/SKILL.md +60 -0
  338. package/skills/codex/atelier-knowledge-setup/SKILL.md +72 -0
  339. package/skills/codex/atelier-practical-judgment/SKILL.md +64 -0
  340. package/skills/codex/atelier-research-harness/SKILL.md +43 -0
  341. package/skills/codex/atelier-skill-steward/SKILL.md +53 -0
  342. package/skills/codex/atelier-trackables/SKILL.md +40 -0
  343. package/src/architecture/catalog.mjs +355 -0
  344. package/src/architecture/index.mjs +93 -0
  345. package/src/boundary/content-rules.mjs +4 -2
  346. package/src/boundary/delegation-command.mjs +158 -0
  347. package/src/boundary/delegation.mjs +396 -0
  348. package/src/boundary/policy.mjs +52 -10
  349. package/src/build/git.mjs +18 -0
  350. package/src/build/index.mjs +3 -0
  351. package/src/build/ledger.mjs +88 -0
  352. package/src/capabilities/adoption.mjs +381 -0
  353. package/src/capabilities/evidence.mjs +140 -0
  354. package/src/capabilities/files.mjs +124 -0
  355. package/src/capabilities/index.mjs +4 -0
  356. package/src/capabilities/instructions.mjs +250 -0
  357. package/src/capabilities/package.mjs +136 -0
  358. package/src/cli/command-failure.mjs +36 -0
  359. package/src/cli/execute-command.mjs +16 -2
  360. package/src/cli/run.mjs +65 -9
  361. package/src/coauthor/store.mjs +43 -2
  362. package/src/collaboration/proposals.mjs +189 -0
  363. package/src/commands/architecture.mjs +27 -0
  364. package/src/commands/boundary.mjs +3 -0
  365. package/src/commands/capability.mjs +73 -0
  366. package/src/commands/enroll.mjs +3 -0
  367. package/src/commands/harness.mjs +79 -0
  368. package/src/commands/ingest.mjs +39 -0
  369. package/src/commands/init.mjs +4 -1
  370. package/src/commands/inquiry.mjs +66 -0
  371. package/src/commands/knowledge-semantic.mjs +128 -0
  372. package/src/commands/knowledge.mjs +119 -0
  373. package/src/commands/learn.mjs +61 -0
  374. package/src/commands/obsidian.mjs +832 -62
  375. package/src/commands/practice.mjs +24 -0
  376. package/src/commands/setup.mjs +22 -2
  377. package/src/commands/trackable.mjs +19 -0
  378. package/src/contracts/corpus.mjs +36 -0
  379. package/src/coordination/index.mjs +110 -0
  380. package/src/egress/forbidden-egress.mjs +2 -0
  381. package/src/evidence-navigation/contracts.mjs +60 -0
  382. package/src/evidence-navigation/evaluate.mjs +69 -0
  383. package/src/evidence-navigation/generation.mjs +22 -0
  384. package/src/evidence-navigation/index.mjs +2 -0
  385. package/src/evidence-navigation/local.mjs +167 -0
  386. package/src/evidence-navigation/schema.generated.mjs +604 -0
  387. package/src/evidence-navigation/types.mjs +12 -0
  388. package/src/export/atelier-export-contract.mjs +35 -8
  389. package/src/graph/enroll.mjs +248 -0
  390. package/src/graph/graph.mjs +17 -1
  391. package/src/graph/knowledge-graph.mjs +58 -8
  392. package/src/harnesses/contracts.mjs +41 -0
  393. package/src/harnesses/exchange.mjs +154 -0
  394. package/src/harnesses/feedback.mjs +16 -0
  395. package/src/harnesses/history.mjs +37 -0
  396. package/src/harnesses/index.mjs +4 -0
  397. package/src/harnesses/store.mjs +29 -0
  398. package/src/ingestion/contracts.mjs +41 -0
  399. package/src/ingestion/evaluation.mjs +119 -0
  400. package/src/ingestion/optional/composition/index.mjs +171 -0
  401. package/src/ingestion/optional/evaluation/index.mjs +219 -0
  402. package/src/ingestion/optional/graphify/composition-binding.mjs +60 -0
  403. package/src/ingestion/optional/graphify/composition_receiving.py +185 -0
  404. package/src/ingestion/optional/graphify/graphify_supplier.py +933 -0
  405. package/src/ingestion/optional/graphify/json_bridge.py +163 -0
  406. package/src/ingestion/optional/graphify/query_receiving.py +209 -0
  407. package/src/ingestion/optional/index.mjs +9 -0
  408. package/src/ingestion/optional/jev/bridge.mjs +166 -0
  409. package/src/ingestion/optional/jev/composition-binding.mjs +116 -0
  410. package/src/ingestion/optional/jev/judgments.mjs +174 -0
  411. package/src/ingestion/optional/jev/native-translation.mjs +32 -0
  412. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/__init__.py +7 -0
  413. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/adapter.py +966 -0
  414. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/artifacts.py +101 -0
  415. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/projection.py +146 -0
  416. package/src/ingestion/optional/lightrag/composition-binding.mjs +67 -0
  417. package/src/ingestion/optional/vanilla/composition-binding.mjs +102 -0
  418. package/src/ingestion/optional/vanilla/index.mjs +218 -0
  419. package/src/ingestion/optional/vanilla/native-normalization.mjs +187 -0
  420. package/src/ingestion/processors.mjs +218 -0
  421. package/src/ingestion/semantic.mjs +203 -0
  422. package/src/ingestion/store.mjs +372 -0
  423. package/src/inquiry/beliefs.mjs +32 -0
  424. package/src/inquiry/contracts.mjs +23 -0
  425. package/src/inquiry/index.mjs +5 -0
  426. package/src/inquiry/ledger.mjs +135 -0
  427. package/src/inquiry/lenses.mjs +15 -0
  428. package/src/inquiry/projection.mjs +77 -0
  429. package/src/inquiry/store.mjs +35 -0
  430. package/src/intake/read-scope.mjs +12 -0
  431. package/src/intake/store.mjs +69 -6
  432. package/src/interaction/index.mjs +91 -0
  433. package/src/judgment/index.mjs +82 -0
  434. package/src/judgment/practice-evaluation.mjs +70 -0
  435. package/src/judgment/practice.mjs +144 -0
  436. package/src/knowledge/context.mjs +217 -0
  437. package/src/knowledge/index.mjs +5 -0
  438. package/src/knowledge/ingestion.mjs +79 -0
  439. package/src/knowledge/intake.mjs +33 -0
  440. package/src/knowledge/ledger.mjs +110 -0
  441. package/src/knowledge/participatory/guidance.mjs +36 -0
  442. package/src/knowledge/participatory/guided-contribution.mjs +44 -0
  443. package/src/knowledge/participatory/index.mjs +2 -0
  444. package/src/knowledge/participatory/installed-workshop.mjs +108 -0
  445. package/src/knowledge/plan.mjs +67 -0
  446. package/src/knowledge/projection.mjs +43 -0
  447. package/src/knowledge/semantic-operation.mjs +567 -0
  448. package/src/knowledge/sessions.mjs +467 -0
  449. package/src/knowledge/workspace.mjs +295 -0
  450. package/src/knowledge-health/assessment.mjs +165 -0
  451. package/src/knowledge-health/capabilities.mjs +350 -0
  452. package/src/knowledge-health/context.mjs +62 -0
  453. package/src/knowledge-health/example.mjs +47 -0
  454. package/src/knowledge-health/index.mjs +10 -0
  455. package/src/knowledge-health/owner-join.mjs +88 -0
  456. package/src/knowledge-health/proof/common.mjs +24 -0
  457. package/src/knowledge-health/proof/installed-check.mjs +100 -0
  458. package/src/knowledge-health/proof/native-readback.mjs +37 -0
  459. package/src/knowledge-health/proof/rehearse.mjs +68 -0
  460. package/src/knowledge-health/proof/validate-participant.mjs +17 -0
  461. package/src/knowledge-health/proof/verify-native-capture.mjs +14 -0
  462. package/src/knowledge-health/proof/workshop-check.mjs +36 -0
  463. package/src/knowledge-health/rule-identity.mjs +44 -0
  464. package/src/knowledge-health/workshop-composition.mjs +19 -0
  465. package/src/knowledge-health/workshop-profile.mjs +176 -0
  466. package/src/knowledge-health/workshop.mjs +99 -0
  467. package/src/learning/adapters.mjs +68 -0
  468. package/src/learning/assistance.mjs +127 -0
  469. package/src/learning/contracts.mjs +65 -0
  470. package/src/learning/store.mjs +272 -0
  471. package/src/personal-workspace/index.mjs +391 -0
  472. package/src/personal-workspace/selection.mjs +385 -0
  473. package/src/project/config.mjs +8 -0
  474. package/src/project/durable-state.mjs +3 -1
  475. package/src/project/file-class.mjs +1 -1
  476. package/src/project/private-state.mjs +10 -1
  477. package/src/projection/obsidian/contracts.mjs +224 -18
  478. package/src/projection/obsidian/edits/apply.mjs +63 -19
  479. package/src/projection/obsidian/edits/regions.mjs +137 -42
  480. package/src/projection/obsidian/materialize/index.mjs +6 -3
  481. package/src/projection/obsidian/materialize/path-registry.mjs +443 -57
  482. package/src/projection/obsidian/materialize/prepare-view.mjs +382 -131
  483. package/src/projection/obsidian/materialize/redaction.mjs +327 -0
  484. package/src/projection/obsidian/materialize/settings.mjs +113 -34
  485. package/src/projection/obsidian/personal-workspace.mjs +436 -0
  486. package/src/projection/obsidian/plugin-bridge/bundle.mjs +50 -0
  487. package/src/projection/obsidian/plugin-bridge/channel.mjs +174 -0
  488. package/src/projection/obsidian/plugin-bridge/index.mjs +10 -0
  489. package/src/projection/obsidian/proposals/adapter.mjs +47 -8
  490. package/src/projection/obsidian/proposals/observation.mjs +20 -7
  491. package/src/projection/obsidian/publication/bridge-script.mjs +11 -5
  492. package/src/projection/obsidian/publication/index.mjs +2 -1
  493. package/src/projection/obsidian/publication/publisher.mjs +312 -36
  494. package/src/projection/obsidian/publication/transport.mjs +63 -8
  495. package/src/projection/obsidian/publication/vault-list.mjs +200 -0
  496. package/src/projection/obsidian/recovery/index.mjs +4 -1
  497. package/src/projection/obsidian/recovery/restart.mjs +3 -1
  498. package/src/projection/obsidian/recovery/store.mjs +168 -8
  499. package/src/projection/obsidian/selection-ui/contribution.mjs +6 -5
  500. package/src/projection/obsidian/selection-ui/focus.mjs +14 -7
  501. package/src/projection/obsidian/selection-ui/selection-state.mjs +2 -2
  502. package/src/projection/obsidian/selection-ui/selection.mjs +8 -3
  503. package/src/readiness/readiness.mjs +10 -3
  504. package/src/reflection/index.mjs +56 -0
  505. package/src/runtime/obsidian/app-capability.mjs +104 -12
  506. package/src/runtime/obsidian/app-production-seams.mjs +161 -42
  507. package/src/runtime/obsidian/app-registration.mjs +313 -0
  508. package/src/runtime/obsidian/app-restart.mjs +154 -0
  509. package/src/runtime/obsidian/engine.mjs +288 -29
  510. package/src/runtime/obsidian/extension-points.mjs +1 -1
  511. package/src/runtime/obsidian/index.mjs +15 -8
  512. package/src/runtime/obsidian/launch-plan.mjs +91 -0
  513. package/src/runtime/obsidian/lifecycle.mjs +193 -22
  514. package/src/runtime/obsidian/login-item.mjs +332 -0
  515. package/src/runtime/obsidian/machine-settings.mjs +119 -12
  516. package/src/runtime/obsidian/opening.mjs +369 -63
  517. package/src/runtime/obsidian/pending-edits.mjs +10 -0
  518. package/src/runtime/obsidian/pipeline.mjs +71 -3
  519. package/src/runtime/obsidian/plugin-channel.mjs +289 -0
  520. package/src/runtime/obsidian/plugin-choice.mjs +182 -0
  521. package/src/runtime/obsidian/plugin-drift.mjs +124 -0
  522. package/src/runtime/obsidian/plugin-presence.mjs +61 -0
  523. package/src/runtime/obsidian/process-identity.mjs +20 -10
  524. package/src/runtime/obsidian/project-views.mjs +282 -0
  525. package/src/runtime/obsidian/questions.mjs +48 -0
  526. package/src/runtime/obsidian/release-watch.mjs +56 -0
  527. package/src/runtime/obsidian/service-main.mjs +113 -17
  528. package/src/runtime/obsidian/service-manager-production.mjs +61 -0
  529. package/src/runtime/obsidian/service-managers.mjs +275 -0
  530. package/src/runtime/obsidian/service-record.mjs +105 -5
  531. package/src/runtime/obsidian/service-server.mjs +50 -12
  532. package/src/runtime/obsidian/service.mjs +134 -7
  533. package/src/runtime/obsidian/startup-adapters.mjs +59 -21
  534. package/src/runtime/obsidian/state-store.mjs +13 -1
  535. package/src/runtime/obsidian/unheld-evidence.mjs +84 -0
  536. package/src/runtime/obsidian/vault-location.mjs +300 -0
  537. package/src/runtime/obsidian/view-counts.mjs +34 -0
  538. package/src/server/local-sidecar.mjs +193 -7
  539. package/src/server/server.mjs +45 -6
  540. package/src/template-bindings/project.mjs +92 -0
  541. package/src/templates/profile.mjs +225 -0
  542. package/src/trackables/domain.mjs +175 -0
  543. package/src/trackables/store.mjs +114 -0
  544. package/src/ui/knowledge-page.mjs +1388 -0
  545. package/src/upgrade/explanation.mjs +1 -1
  546. package/src/upgrade/template-participant.mjs +171 -0
  547. package/src/upgrade/transaction.mjs +72 -25
  548. package/src/upgrade/upgrade.mjs +2 -1
  549. package/templates/external-project-workspace/pack-lifecycle.json +6 -1
  550. package/templates/knowledge-workspace/.gitattributes +2 -0
  551. package/templates/knowledge-workspace/AGENTS.md +27 -0
  552. package/templates/knowledge-workspace/README.md +44 -0
  553. package/templates/knowledge-workspace/atelier.project.json +22 -0
  554. package/templates/knowledge-workspace/gitignore +6 -0
  555. package/templates/knowledge-workspace/knowledge-plan.json +111 -0
  556. package/templates/knowledge-workspace/knowledge-plan.schema.json +281 -0
  557. package/templates/knowledge-workspace/records/forecast.md +22 -0
  558. package/templates/knowledge-workspace/records/inspection.md +25 -0
  559. package/templates/knowledge-workspace/records/telescope.md +24 -0
  560. package/templates/knowledge-workspace/repo-access.v1.json +9 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,1010 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0-alpha.13
4
+
5
+ - Add the public Knowledge Health workshop on the existing local Knowledge
6
+ host: original wording, separate interpretation and four distinct responses;
7
+ optional Review in a separate session; a selected-draft copy-only handoff
8
+ retained with its original receipt. Exact retries do not append duplicates,
9
+ and reopening after restart reads the same proposal. The source owner edits
10
+ through ordinary repository tooling and reassesses; no browser source-apply
11
+ endpoint is added. Include the installed workshop kit and receiving guidance.
12
+ - `atelier knowledge semantic` exposes the internal semantic operation runner
13
+ (`docs/semantic-operation.md`) as eleven operations: `begin`, `status`,
14
+ `reconcile`, `complete`, `proposals`, `contribution`, `relation`, `record`,
15
+ `cascade`, `context` and `project`. Each reads one JSON object
16
+ `{workspaceId, run, request}` from stdin, at most 256 KiB, in the workspace
17
+ `atelier ingest` uses. Each operation accepts exactly its documented request
18
+ fields, each of a declared kind; an unknown or missing field, a null
19
+ required field or a value of the wrong kind refuses as
20
+ `SEMANTIC_OPERATION_INVALID` before any store is opened, so nothing is
21
+ written. Formats such as timestamps are checked by the runner. Atelier calls no model: the host supplies its raw output, candidates
22
+ and usage (`null` when unknown), and interpretations stay pending until
23
+ receiver records, which are caller assertions, accept them. Failures print
24
+ `{ok:false, code, error}` with the runner's own `SEMANTIC_*` code,
25
+ `SEMANTIC_OPERATION_INTERRUPTED` for an uncoded error, or
26
+ `SEMANTIC_OPERATION_REFUSED` for Atelier's other refusals; `recorded` or
27
+ `captured` details are included whenever the runner attached them. No package export
28
+ or schema changes.
29
+
30
+ ## Unreleased
31
+
32
+ - Patch the fast-uri dependency and override from 3.1.7 to 3.1.8, the patched
33
+ 3.x release for GHSA-hrr3-gc8f-f4qj (3.1.7 is in the affected range; whether
34
+ Atelier's use was exploitable is not established). The direct dependency
35
+ keeps packed consumers on one deduplicated copy: Ajv's own `^3.0.1` range
36
+ resolves to it, so a bare consumer installs 3.1.8 only.
37
+ - Personal workspaces gain an explicit selection record, a read-only inventory of
38
+ the private home, and a restore of authored inputs from an earlier generation:
39
+ `selectPersonalGeneration`, `selectionConfirmDigest`, `readPersonalSelection`,
40
+ `inventoryPersonalHome`, `planPersonalRestore` and `restorePersonalInputs`. A
41
+ selection is a confirmed, hash-chained choice of the eligible generation. A
42
+ restore accepts only a plan from `planPersonalRestore`, re-checks the exact
43
+ current bytes, keeps them, and never widens enrollment or bindings:
44
+ re-admitting a withdrawn repository, a changed repository identity, or a
45
+ re-added binding refuses before any write. Each file is replaced by
46
+ compare-and-swap, so a write that replaces or recreates the file by path
47
+ during the restore is kept and the restore refuses; an interrupted swap
48
+ refuses `restore-interrupted` until the listed moved copy is put back.
49
+ Authored inputs, generations and records are never deleted; only temporary
50
+ files are removed.
51
+ - A private-domain repository owner can let one named operator pass the local
52
+ boundary actor check by signing a delegation
53
+ (`docs/repo-boundary-guard.md`). It covers only `atelier boundary check` and
54
+ the `pre-commit` path, for listed repositories, for at most 90 days. It never
55
+ changes ownership, audiences, paths, content rules, promotion, push-content
56
+ checks or publication. It applies only when all of these hold:
57
+ - its ed25519 signature verifies against the owner's key in the host file
58
+ `/etc/atelier/boundary-owner-keys.json`, owned by root in root-owned
59
+ directories (Windows is not supported yet);
60
+ - it is current and not revoked in that file;
61
+ - the whole boundary policy, the managed repository set and each repository's
62
+ root commit match what the owner signed.
63
+
64
+ It records consent for a cooperating operator; the actor check stays
65
+ attribution, not authentication. Delegations live in
66
+ `boundary-delegations.v1.json` beside the policy, under the new
67
+ `atelier-boundary-delegations@v1` and `atelier-boundary-owner-keys@v1`
68
+ contracts; the boundary policy contract is unchanged.
69
+ `atelier boundary delegation draft|sign|verify` prepares, signs (after
70
+ recomputing the bindings) and inspects them. The policy validator now accepts
71
+ the `contractVersion` and `ext` members its schema already declared; `ext` is
72
+ ignored.
73
+ - A capability operation that has committed no longer reports `EEXIST` ("not
74
+ entered") when its lock is removed or replaced while cleanup inspects it.
75
+ Cleanup preserves the other file and returns the operation's result. Lock
76
+ races in reclamation, readback and cleanup are each covered by a test.
77
+ - `src/judgment/practice.mjs` and `src/judgment/practice-evaluation.mjs` keep a
78
+ reusable decision practice inside an ordinary Knowledge contribution
79
+ (`docs/decision-practices.md`). They are internal: the
80
+ `atelier.decision-practice/v0` format is experimental, not a registered public
81
+ contract, and has no package export, CLI command, adoption store, scheduler or
82
+ model route. A definition is prepared as a captured contribution for the
83
+ existing Knowledge review path, and is read as adopted only from an exact
84
+ contribution digest with a current accepted review and activation in the
85
+ supplied history. `evaluateDecisionPractice` returns `proceed`, `stop`,
86
+ `escalate` or `refuse` with a typed reason from declared prerequisites, count
87
+ budgets, exact current evidence and an existing decision request and result.
88
+ It calls no provider, and an abstention escalates. A proceeding outcome
89
+ prepares an unaccepted reconsideration draft; nothing is appended, accepted or
90
+ activated by the module. Inputs are bounded to a portable profile, and a
91
+ larger history refuses `practice-input-exceeds-bounds`. The instruction
92
+ adoption command `atelier practice` is a separate concept.
93
+ `atelier architecture entry practical-judgment` lists both modules.
94
+ - `src/ingestion/semantic.mjs` prepares source-bound entity and assertion
95
+ proposals from a host's extractor output, one source per input
96
+ (`docs/semantic-ingestion.md`). It is an internal module: its `v0` formats are
97
+ not public contracts, and it has no package export or CLI command. The host
98
+ must already hold whole-plan read permission, which the module does not grant,
99
+ and chooses and runs its extractor. The module makes no provider call, durable
100
+ write or graph change, and claims no extraction quality. `readSemanticProposals`
101
+ gives a search view that rereads the cited evidence. Proposals and identity
102
+ mappings stay pending and carry no authority: identity, semantic acceptance and
103
+ activation remain separate decisions of the existing knowledge review owner, and
104
+ this release maps nothing into knowledge review or activation records.
105
+ `atelier architecture entry knowledge-stewardship` lists the module.
106
+ - A personal workspace bound to the Obsidian projection is served from the
107
+ canonical build, with the composition's link-target rule and the engine's file
108
+ cache. A graph is used only under a validity key the composition confirmed.
109
+ Its inputs are read before the composition runs. The engine, and the
110
+ proposal adapter it runs, compose in a worker with a two-minute deadline: at
111
+ load (`loadBoundProjectOffThread`), after a change, and at every full
112
+ reconciliation, which prepares nothing again when nothing changed. A bound
113
+ project is loaded once. Authored and generation files the key reads are
114
+ opened without following links or waiting on them. The adapter builds only
115
+ when it looks at a newly observed edit. The proposal adapter answers a vault edit to a private
116
+ note with `personal-overlay-not-proposed`, and `personal-binding-lost` now
117
+ names the reserved settings key.
118
+
119
+ - Evidence navigation is exported as `@mnstry/atelier/evidence-navigation`
120
+ (the pure contract checks and currency assessments) and
121
+ `@mnstry/atelier/evidence-navigation/local` (the Node local reader, kept
122
+ separate), with its schema at
123
+ `@mnstry/atelier/contracts/atelier-evidence-navigation.v1.schema.json`. The
124
+ schema and its fixtures join the contract corpus. There is no CLI command:
125
+ search and get need a host to construct the reader with its exact plan,
126
+ workspace and current whole-plan admission, and Atelier ships no issuer of that
127
+ authority.
128
+ - The Obsidian projection has one route for a personal workspace. A binding
129
+ names a private home and a generation explicitly. Every caller that builds
130
+ the graph (the engine, view counts, source apply, the proposal adapter and the
131
+ selection operation) then reads the composed graph, which composition checks
132
+ again at every build. The overlay's saved views become scopes, plus an
133
+ `everything` view. Composition refusals keep their codes, at load and at
134
+ every build, and no view is current under one. The engine observes the
135
+ person's manifest and overlay, so a generation that stops holding is refused
136
+ at the next tick. A copy of a bound project that lost its binding is refused.
137
+ `view add`, `audience` and `location` refuse on a bound project and write
138
+ nothing, and a vault edit to a private note is refused, never applied. A
139
+ theme is never written, and coverage is passed through unread. No command or
140
+ service binds a personal workspace yet.
141
+
142
+ - The knowledge workspace states its supported interfaces
143
+ (`docs/knowledge-workspace.md`).
144
+ - Two outputs are versioned contracts: the context packet
145
+ (`atelier-knowledge-context@v1`) and the evaluation report
146
+ (`atelier-knowledge-evaluation@v1`).
147
+ - The other CLI outputs, the browser routes and the sidecar's `knowledgeProject`
148
+ option are experimental.
149
+ - The workspace modules have no library export. `@mnstry/atelier/knowledge`
150
+ keeps its existing exports.
151
+ - `atelier architecture entry knowledge-stewardship` lists the workspace modules
152
+ and the `knowledge` command.
153
+ - `npm run knowledge:consumer-proof` installs a packed tarball into a clean
154
+ consumer and checks the documented CLI paths, writing a receipt bound to the
155
+ tarball SHA-256.
156
+ - Personal workspaces are exported as `@mnstry/atelier/personal-workspace`,
157
+ with their manifest and overlay schemas under `@mnstry/atelier/contracts/`. The
158
+ public API is these nine exports: `MANIFEST_SCHEMA`, `OVERLAY_SCHEMA`,
159
+ `PersonalWorkspaceRefusal`, `loadPersonalManifest`, `loadPersonalOverlay`,
160
+ `resolvePersonalWorkspace`, `planPersonalGeneration`,
161
+ `materializePersonalGeneration` and `composePersonalWorkspace`. The composition
162
+ is manifest-only, with enforcement `none`: filesystem access, disclosure,
163
+ effects and the host sandbox are reported as uncovered, and no consent or
164
+ effect enforcement is claimed. The manifest and overlay schemas join the
165
+ contract corpus.
166
+
167
+ - The ingestion store adds `getEvidence`, which returns one exact evidence span
168
+ after rechecking only that source and its stored attempt. Query and
169
+ `getEvidence` both report `readScope: "all-plan"`: they read at the scope of
170
+ the whole plan and grant or narrow no permission.
171
+ - Preserve workspace template lineage during profile adoption and updates.
172
+ Keep profile identity in its typed adoption manifest, and refuse saved plans
173
+ that replace the workspace lineage before installing any managed content.
174
+ - Verify exact upgrades from a real 0.2.0-alpha.12 lock as well as the
175
+ alpha.10 lock, and check that the upgraded lock records the installed version.
176
+ - A long-lived reader of verified history (learning and ingestion stores) no
177
+ longer wedges after one refused read; it replays from a clean copy.
178
+ - Ingestion reads take no lock and bind no workspace identity; only `plan`
179
+ binds it, so reads work during a run and a mistyped id is not recorded.
180
+ - Inquiry graph proposals label each file, and the proposal, with the most
181
+ restrictive audience of the sources whose material they carry.
182
+ - Coordination reports every dependency cycle regardless of record order, and a
183
+ superseded directive stays superseded when its replacement goes stale.
184
+ - Reflective and coaching acts require Reflection, an assessment and a request
185
+ whatever their origin.
186
+ - The responsibility commands print only their own refusals; Node, git and
187
+ parser errors go through the typed-code rule and never show paths or input.
188
+
189
+ - Preserve the bundled readiness pack's immutable v1 content and digest so
190
+ previous release locks can use both exact upgrade participants without a
191
+ separate lock rewrite. Keep Discovery Harness naming in the architecture
192
+ catalog; retain Discovery Engine in the persisted readiness pack. Add a
193
+ real alpha.10 lock fixture, plan/application regressions and digest refusal
194
+ controls.
195
+
196
+ - Add portable template profiles, digest-bound project bindings, staged structural
197
+ validation and canonical read-only presentation through installed package APIs.
198
+ - Add explicit local template adoption and updates through the existing exact-plan
199
+ upgrade engine, preserving source, local customization and adoption history.
200
+ - Reuse Git placement checks within synchronous ingestion read operations;
201
+ recheck at operation boundaries and around writes without caching source bytes
202
+ or integrity verdicts.
203
+
204
+ - Preserve recorded Trackable calendar resolutions across host timezone-data changes; retain verified-chain export when legacy replay cannot reconstruct state.
205
+
206
+ - Correct unchanged instruction re-adoption and preserve literal replacement text during revisions; add recovery and neighboring-slot regressions.
207
+ - Recover recognized dead capability operation locks without requiring an adoption journal; preserve live, uncertain and replacement owners.
208
+ - Add portable Trackable definitions, shared preview/runtime rules, durable scoped reference storage and correction.
209
+ - Add evidence-qualified Reflection, one-authority Interaction delivery, and bounded cross-repository Coordination views.
210
+
211
+ - Reconcile eight responsibility names and typed consumer bindings; preserve historical aliases.
212
+ - Connect durable ingestion to source-current knowledge context and graph proposals.
213
+ - Add situated judgment and native ADR adapters, capability feedback, and recoverable scoped instruction adoption.
214
+ - Include a provider-agnostic research starter and Practical Judgment operating skill.
215
+
216
+ - Add Knowledge Harness, Fabric-derived Build Harness and shared typed handoffs, with immutable local history, intake and inquiry bridges, graph activation, correction propagation and version-bound skill feedback.
217
+
218
+ - Add local Discovery and Research Harnesses with versioned inquiry records,
219
+ portable research handoffs, reproducible basic belief calculations, evidence
220
+ dependence and withdrawal checks, and reviewable graph proposals. Add separate
221
+ capability packages and version-bound Skill Steward feedback. Rename the
222
+ discovery workflow through the architecture catalog while retaining the
223
+ bundled readiness pack's persisted title, identifiers and digest.
224
+ - Add an experimental progressive local ingestion runner with exact plans,
225
+ bounded deterministic text/CSV/JSON extraction, immutable intake reuse,
226
+ resumable attempt accounting and source-verified lexical queries. Add a
227
+ JSON stdin CLI and structural evaluation that retains missing cases and
228
+ unknown costs. No model dispatch, automatic semantic acceptance or native
229
+ desktop admission is provided by the portable runner.
230
+
231
+ - Add a portable local learning lifecycle: Evidence, proposals, exact decisions,
232
+ explicit harness activation, withdrawal and retained history. Include a JSON
233
+ stdin CLI, private graph/export projections, bounded proposal-assistance
234
+ adapters and compatibility with existing skill observations. Local actor
235
+ assertions do not authenticate users; check artifacts remain inert and hosts
236
+ retain execution and access authority.
237
+
238
+ - Recompile cached JSON Schema validators when caller-owned schemas change; preserve unchanged-schema reuse and fresh compilation for non-JSON schemas.
239
+
240
+ ### Added
241
+
242
+ - Add opt-in knowledge dashboards and source-bound coauthor flows, sharing private drafts between the local browser and CLI, with evidence comparison and restart recovery.
243
+
244
+ - A `knowledge-workspace` starter, mirrored `atelier-knowledge-setup` agent
245
+ skills, and `atelier knowledge check|context|evaluate`: question-led ontology
246
+ coverage, complete source context within an exact byte budget, and a lexical
247
+ versus graph comparison with source-digest and directed-relation checks.
248
+ Local operator output carries no expression or execution permission. Token
249
+ estimates remain distinct from measured usage and accepted work.
250
+
251
+ - `atelier enroll documents [--audience private] [--dry-run] [--json]` writes
252
+ a minimal `<file>.kg.json` sidecar next to every `.html`, `.pdf` and
253
+ `.docx` document the knowledge graph reads that has none, so an adopted
254
+ vault with attachments, a static website or a folder of documents can pass
255
+ `atelier graph` without hand-written sidecars. Each sidecar carries the
256
+ document's title, the domain, lifecycle and status the graph infers, the id
257
+ `<repo>:asset:<path>` (with a short digest when two paths fold to one id)
258
+ and the audience `private`. `--audience` picks another, which the
259
+ repository's boundary policy must allow; a refusal is typed
260
+ (`enroll-audience-not-allowed`) and names the allowed audiences before
261
+ anything is written. An existing sidecar, including one Git ignores or a
262
+ link with the sidecar's name, is never changed, and sources are never
263
+ changed. See `docs/install.md`.
264
+ - `atelier adopt --enroll-documents [--audience AUDIENCE]` adopts and enrolls
265
+ in one step, checking the audience against the policy before adoption
266
+ writes anything.
267
+ - A login item keeps a workspace's vaults fresh after you log in:
268
+ `atelier obsidian service unit --install [--consent-actor ID]
269
+ [--adapter=obsidian-cli]` installs a launchd agent on macOS
270
+ (`~/Library/LaunchAgents/ai.mnstry.atelier.<project>.<workspace-id>.plist`)
271
+ or a systemd user unit on Linux
272
+ (`~/.config/systemd/user/atelier-obsidian-<workspace-id>.service`), after
273
+ recording a consent that covers startup (`--consent-actor ID`; at a
274
+ terminal, the actor already recorded or else the account's name). A
275
+ service of an earlier release still running is stopped just before the
276
+ unit is loaded, so the unit's first start runs the installed release.
277
+ `service unit --remove` lowers the consent to the service alone, removes
278
+ the item and starts the service again at once for this session only;
279
+ `service unit --print` shows what `--install` writes. The answer is
280
+ remembered as the machine settings' `loginItem` decision (`on`, `off`), and
281
+ `atelier obsidian settings` names these commands as the way to change it. The unit runs the package installed in the project,
282
+ by its path, with the Node that installed it (its real path), the search
283
+ path you had (absolute, non-temporary entries), in `/`, and names the data
284
+ root the workspace was resolved under and the workspace
285
+ (`--data-root`, `--workspace-id`), so the service at login finds that
286
+ workspace whatever its manager's environment carries, and records a refusal
287
+ there when the project no longer leads to it. launchd: `Standard`
288
+ process type, `RunAtLoad`, `KeepAlive` `SuccessfulExit` false,
289
+ `ThrottleInterval` 60, `ExitTimeOut` 60, output to
290
+ `state/service/login-item.log`. From `npx` without a package installed in
291
+ the project it refuses (`login-item-needs-installed-package`); Windows is not
292
+ offered (`startup-platform-unqualified`); without a user systemd the answer
293
+ is `login-item-unavailable`. The installed item is recorded in
294
+ `state/service/login-item.json` (`atelier-obsidian-login-item/v1`).
295
+ - Once a login item is installed, `service start`, `open` and the replacement
296
+ of an outdated service start the service through launchd or systemd
297
+ (`kickstart -p`, `systemctl --user start`) instead of as a child, and accept
298
+ the service that proves itself with the entry the item runs. A unit that
299
+ differs from what would be written now is written again and reloaded, and
300
+ `open` says `login item refreshed`. An item switched off in System Settings
301
+ or with `systemctl --user disable` is not forced: it is neither written
302
+ again nor started through its manager, and the service is started for that
303
+ command only.
304
+ - A service started by a login item (`--startup`) keeps its own bounded
305
+ `service.log`, exits 0 on a refusal as well, so it is not restarted every
306
+ minute, and records how its start ended in `state/service/last-startup.json`
307
+ (`atelier-obsidian-last-startup/v1`); `status` shows the login item and
308
+ `the login item did not start the service: <code>` with the next step. After
309
+ each tick it compares its package on disk with the release it started with
310
+ (file status first, then a digest of `src/`, `contracts/` and `plugins/`
311
+ and the version) and exits 75 after the tick when it changed, which its
312
+ manager restarts on the new release.
313
+ - `atelier obsidian uninstall` removes the login item and stops the proven
314
+ service, and starts nothing. Vaults, private state, the project file and
315
+ Obsidian's vault list are kept, and it prints where each is.
316
+ - `readReleaseIdentity({ root })` reads a package's release identity now,
317
+ uncached; `releaseIdentity()` stays its cached form.
318
+ - The production service manager refuses under the Node test runner
319
+ (`real-login-item-under-test`) and when HOME is not the account's own home
320
+ directory (`login-item-home-mismatch`), since launchd and systemd register a
321
+ unit in the account's real session whatever HOME says.
322
+ - `atelier obsidian open` gets through the Obsidian states it used to stop
323
+ at. For an Obsidian that is installed and never started (no
324
+ `obsidian.json`), and only while the process table shows that no Obsidian
325
+ runs, it creates the settings file with the view's vault flagged open and
326
+ the command line on, exclusively (a file the app wrote first is kept), in a
327
+ settings folder made private to you when it is missing; Obsidian then opens
328
+ the vault at a plain start (`registration.how: created-settings`). Whenever
329
+ it writes Obsidian's vault list with the app quit, it also turns the
330
+ command line on (`cli: true`) in the same guarded write, with the backup of
331
+ the file as it was; a listed vault whose switch is off is written for the
332
+ switch alone. With `--restart-obsidian`, a running Obsidian that cannot be
333
+ reached (its command line off, or no vault open and the view's vault not in
334
+ its list) is quit with SIGTERM to its proven main process only, the vault
335
+ and the switch are written once it has gone, and it is started again
336
+ plainly, reopening the vaults it had open (macOS only). Without the flag,
337
+ those states answer `app-cli-unavailable` / `cli-turned-off` and
338
+ `app-version-unsupported` / `no-vault-open`, naming it. The flag is never
339
+ implied and every other operation refuses it. Every write and the restart
340
+ are shown in the answer (`obsidianSettings`, `restart`). Before any signal,
341
+ `open` checks, reading only, that the write can succeed (otherwise it
342
+ answers that refusal and leaves Obsidian running; an Obsidian at its
343
+ starter window with no `obsidian.json` yet is the create case) and, right
344
+ before the first signal, keeps a copy of `obsidian.json` that the same
345
+ run's write does not prune. On macOS the main process can stay after the first
346
+ SIGTERM, with its windows closed; Electron handles only the first SIGTERM as
347
+ a quit, and a second one ends the process at once, without its quit
348
+ handlers. `open` sends that second one only when the same process has
349
+ stayed alone, with no window or helper, at two readings at least 5 seconds
350
+ apart; never a third, and never another kind. `atelier obsidian --help` names every option of the
351
+ command, `--wait-ms` included. See "What `open` does in each state of
352
+ Obsidian" in `docs/obsidian.md` and "Obsidian's vault list" in
353
+ `docs/obsidian-contract.md`.
354
+ - Views can be declared without editing JSON:
355
+ `atelier obsidian view add ID (--all | --folder PATH [--folder PATH ...] [--repo R] | --tag T) [--expand DEPTH:MAX] [--default]`
356
+ adds a view to `atelier.project.json` (and `.atelier-local/` to
357
+ `.gitignore` when that folder is not ignored), and never commits. It shows
358
+ the change as a diff and how many notes the view would show on this machine,
359
+ with how many of the notes it selects are withheld for carrying no
360
+ classification or an audience that is not admitted. A view that would show
361
+ no note is refused with `view-would-be-empty` unless `--allow-empty`. A
362
+ person at a terminal is asked before anything is written (`--yes` answers
363
+ beforehand; no answer within 10 minutes writes nothing); for anyone else the
364
+ command is the consent. The file is rewritten only when it is in the form
365
+ Atelier writes JSON in, so the change is the view and nothing else
366
+ (`project-config-format-unknown` names the member to add by hand
367
+ otherwise), atomically, keeping its mode, and only over the bytes it read
368
+ (`project-config-changed`). A file that is not UTF-8 is never rewritten
369
+ (`gitignore-not-utf8`, or `project-config-format-unknown`). Every new text
370
+ is written and synced to disk before any file is replaced; a failure after
371
+ that says which files changed (`project-files-partly-written`), and no
372
+ temporary file is left beside them. The first view is the default. `view list` and
373
+ `view show ID` are `scope list` and `scope show ID`.
374
+
375
+ ### Changed
376
+
377
+ - Where a workspace's vaults live can be decided, and a visible folder can
378
+ hold them: `atelier obsidian location set DIR` (`~/Atelier`, say) records
379
+ the `location` decision. Each view not published yet is then given its own
380
+ folder there at its first publication, `<project> (<view>)`, which is also
381
+ the vault's name in Obsidian (`harbor-notes (everything)`; a number inside the
382
+ parentheses when that name is taken on the disk or by a vault the app lists).
383
+ The folder is created exclusively and private to this user, and its
384
+ allocation is recorded once in the workspace's private state
385
+ (`atelier-obsidian-vault-allocation/v1`, `state/allocations/<view>.json`,
386
+ with the folder's real path, device and inode, which the maintenance service
387
+ checks at every tick and the publisher before it writes, before each note
388
+ and before its commit: another folder put
389
+ where the one made was is not published into, `vault-allocation-replaced`,
390
+ nor is the same folder reached through a link put on the way since,
391
+ `vault-allocation-moved`; on Linux a folder made after the original was
392
+ removed can be given its inode number, see Known limits in
393
+ `docs/obsidian.md`. A folder that has gone is made again by the next tick,
394
+ only where its recorded real path leads and only where a location would be
395
+ accepted: never inside a repository, the project, the private state, a vault
396
+ Atelier publishes or one the app lists; a vault removed, moved or replaced
397
+ while it was being published stops that publication (`vault-root-moved` for
398
+ a vault under the data root), and the running service, without a restart,
399
+ publishes into it again once it is put back or made again: at once, or, for
400
+ a folder made again after a publication stopped just before its commit, at
401
+ the next change at its sources (`vault-note-missing` until then). A published view whose vault cannot
402
+ be found (its record was lost, or a view published under the data root lost
403
+ its `vaults/<view>` folder, which was made again before) is refused,
404
+ `vault-allocation-lost`, never published again into a new, empty vault;
405
+ `status` and `open` name the way back),
406
+ which the recovery store reads: the engine, source apply, the proposal
407
+ adapter, `open` and the plugin's service paths (its hello, the person's
408
+ choice to turn it off, drift) all find the same vault. So does
409
+ `viewVaultRoot` of `@mnstry/atelier/obsidian`, which answers the allocated
410
+ folder now, and may refuse, typed (a record that cannot be read, or was
411
+ lost); pass the workspace id as its third argument: without it the name of
412
+ the workspace's private-state folder is taken as the id, as before, and a
413
+ record that does not match it is refused. A vault published before stays
414
+ under the data root, and a workspace that decides nothing publishes there as
415
+ before. A folder inside a repository or the project, inside a vault Atelier
416
+ publishes or one the app lists, or on another volume than the data root is
417
+ refused, through links and in any letter case; a synced one needs
418
+ `--allow-synced-location`; a macOS-protected one is warned about. The app's
419
+ list is read through the app when it answers, else from its settings file;
420
+ while it cannot be read, no folder is allocated (`app-vault-list-unreadable`,
421
+ tried again at the next tick). A view whose folder cannot be allocated is not published
422
+ and its freshness says why, while the other views go on: a folder that
423
+ cannot be made (`vault-location-unusable`: a file in the way, no
424
+ permission), one inside Atelier's private state
425
+ (`vault-location-inside-private-state`, refused by `location set` too), an
426
+ allocation record that cannot be read or names a folder inside a
427
+ repository, each stops its own view only. `location show`
428
+ and `status` (`scopes[].vault`) say where each view's vault is, or why it
429
+ cannot be read. Consent to a synced folder is not recorded, so it is not
430
+ checked again when a folder is allocated or made again; a link on the way is
431
+ followed only at a view's first allocation (Known limits).
432
+ - A vault that is only yours shows the notes that carry no classification:
433
+ `atelier obsidian audience set me` now records `unclassified: shown` with
434
+ "only you", and every path that builds a view (the engine, source apply,
435
+ the proposal adapter, `selection`) admits them through one rule,
436
+ `eligibilityFor`. A list of audiences never shows them, even one that names
437
+ every audience "only you" stands for. Such a note is shown only when its
438
+ bytes read as a note the way the emitter reads every note, so a file that
439
+ cannot be published stays withheld instead of stopping the vault. Deciding
440
+ it changes the eligibility revision, so every view is rebuilt at the next
441
+ tick. A decision recorded as "only you" with them withheld keeps them
442
+ withheld until `audience set me` is run again. `view add` counts what a
443
+ view would show the same way, as "only you" while nobody decided. Since
444
+ the maintenance service publishes no note until someone decides who may
445
+ see, `view add` then names `atelier obsidian audience set me` as the next
446
+ step, before `open`; and a view refused as empty because no audience is
447
+ admitted (`audience clear`) is told to decide who may see, not to classify
448
+ notes. A note whose labels cannot be known is never shown: front matter
449
+ Atelier cannot read, or a top-level `kg` key that is not a block, may say
450
+ `sensitive`.
451
+ - A view's first publication into its allocated folder no longer waits for an
452
+ Obsidian that runs and cannot be coordinated with (a vault open, its command
453
+ line off, no vault open, or a version below the floor). While the app's own
454
+ settings file names neither the folder, a folder above it nor one inside it
455
+ (read, not guessed: a missing or unreadable file, an entry with a `..`
456
+ segment, or a Flatpak or snap build, gives no such evidence), the publisher fills the vault in its own process by
457
+ creating files only (journal `mode: 'direct-unheld'`). Anything that would
458
+ replace or remove a file, or write a settings file over one that is there,
459
+ refuses as `editor-uncoordinated` and writes nothing. The evidence is read
460
+ again before the first file and every two seconds, and once it is gone
461
+ nothing more is written or committed. A run that completes is committed
462
+ before `open` adds the vault to Obsidian and opens it. A run that stops
463
+ partway commits nothing: the list names the folder meanwhile, a settings
464
+ file with other bytes is already there, or an interrupted run left a
465
+ replacement or a removal. The view then falls back to the coordinated path,
466
+ so `open` may add the vault to Obsidian and open it before it is complete,
467
+ and the rest, every replacement and removal included, is published through
468
+ the app with its usual checks. While the app does not qualify, a run stopped
469
+ that way reports the app's own refusal (`app-cli-unavailable`, say), and
470
+ `open` answers it without adding the vault unless asked to restart
471
+ Obsidian; with the app running and no vault open, a vault the app already
472
+ lists is still opened by its path, as before. The plugin's entry written this way counts as offered until the
473
+ plugin says hello. A later generation, a vault under the data root, and
474
+ every other case publish and refuse as before.
475
+ - The Obsidian machine settings of a workspace remember what a person decided
476
+ once, so no later run has to ask again or be told again: who may see the
477
+ vaults, where they live, whether maintenance starts at login, and that the
478
+ installed app may be reached. The document is now
479
+ `atelier-obsidian-machine-settings/v2`, with a closed `decisions` member,
480
+ one entry per decision (`audience`, `location`, `loginItem`, `adapter`),
481
+ each null until decided and otherwise stamped with when, by whom when known,
482
+ and how (`question`, `command`, `defaults`, `v1`). The audience decision
483
+ also says whether notes that carry no classification are `shown` or
484
+ `withheld`: only an "only you" decision may show them, and every decision
485
+ made today withholds them. A v1 document is read as the v2 document it
486
+ stands for and stays v1 on disk until the next write, which writes v2; an
487
+ audience list set before is carried over as that person's decision, with
488
+ unclassified notes withheld as they were. A release up to 0.2.0-alpha.12 refuses a v2 document
489
+ (`invalid-machine-settings`), so after an upgrade a maintenance service
490
+ still running the earlier release fails its ticks until it is replaced:
491
+ `atelier obsidian open` and `service start` replace it. `atelier obsidian settings` shows what is remembered and
492
+ how each answer is changed; `status` carries the decisions and a one-line
493
+ summary.
494
+ - `--adapter=obsidian-cli` is needed once per workspace. Given to `open` or
495
+ `service start` of an enabled project, it is remembered before anything
496
+ starts, and later runs of the real command-line entry reach the app without
497
+ it (`service unit --print` too). A remembered adapter is never used under
498
+ the Node test runner (`remembered-adapter-under-test`), and never by a
499
+ caller that passes its own seams; the decision is one pure rule,
500
+ `selectAdapter`.
501
+ - The first start of the maintenance service records who allowed it: still
502
+ `--consent-actor ID`, or now, for a person at a terminal, the name of the
503
+ account the command runs as, which the command says it recorded. A person
504
+ is at a terminal when standard input and output are both terminals and
505
+ nothing says otherwise: `--json`, the new `--no-input`, a `CI` environment
506
+ or `ATELIER_NONINTERACTIVE=1` mean nobody is (`isInteractive`). A consent
507
+ recorded already is never replaced by a derived one, and a program still
508
+ names its actor.
509
+ - `atelier obsidian audience set me` admits "only you": every audience of a
510
+ note (`public`, `team`, `operator`, `staff`, `private`) except `sensitive`,
511
+ which a vault takes only when it is named (`audience set me,sensitive`).
512
+ Any other list is the person's own; either is remembered as their decision.
513
+ Notes without a classification are still withheld from every vault,
514
+ "only you" included; a later change lets an "only you" vault show them.
515
+
516
+ - `setup.include` and `setup.exclude` in `atelier.project.json` now scope
517
+ what the knowledge graph reads. `adopt --include` and `--exclude` recorded
518
+ them, and the `monorepo` profile required `--include`, but nothing read
519
+ them, so a tracked build folder could not be left out and every tracked
520
+ page needed a sidecar. Each is a path pattern relative to the project
521
+ config's folder, in the boundary policy's `forbiddenPaths` dialect; a path
522
+ outside the scope is treated exactly like a Git-ignored one, and a sidecar
523
+ follows its source. A project that already sets either field gets a graph
524
+ over that scope from this release: run `atelier graph` and commit the
525
+ result. Both values must now be relative (the contract's `pathString`), and
526
+ `adopt` no longer writes them as `null`. The decision is recorded in
527
+ `docs/install.md`.
528
+ - `atelier graph` ends its error list with a `Next:` line naming
529
+ `atelier enroll documents` when a document has no sidecar.
530
+ - `service unit --print` prints the unit `--install` writes: on macOS under
531
+ the label `ai.mnstry.atelier.<project>.<workspace-id>`, with process type
532
+ `Standard` instead of `Background`, the search path, `WorkingDirectory` `/`
533
+ and output to `login-item.log` instead of `service.log`; on Linux with
534
+ `Environment="PATH=…"`, `WorkingDirectory=/` and `TimeoutStopSec=60`.
535
+ `buildStartupAdapter` takes `searchPath`, and its working directory is `/`
536
+ unless one is given. A service records the path it was started by beside its
537
+ real path (`executable.ext.invokedAs`), and the busy proof accepts a process
538
+ table that names the entry through it.
539
+ - Whether a running maintenance service is of an earlier, the same or a
540
+ later release is measured against the entry that would be started: its
541
+ digest and the release of the package that entry's path names, read now.
542
+ With a login item that is the project's own package, whatever package the
543
+ command runs from, and a re-pointed link or `file:` install is read where
544
+ it leads.
545
+
546
+ ### Fixed
547
+
548
+ - `atelier obsidian open` with a view the maintenance service did not publish
549
+ because Obsidian's command line is off now answers `app-cli-unavailable` /
550
+ `cli-turned-off` with its next step, instead of the view's own
551
+ `not-prepared` or `stale-readable`: such a view counts as one the app kept
552
+ from publication, which `open` publishes once the app holds the vault.
553
+ - `atelier obsidian service start` replaces a maintenance service of an
554
+ earlier release still running after an upgrade, as `open` does (stopped
555
+ through its own listener, the installed release started under the consent
556
+ already recorded, `replaced: 'outdated'`), instead of answering that it is
557
+ already running while that service fails every tick on the new machine
558
+ settings. A service of a later release is left running (`release:
559
+ 'later'`).
560
+ - `atelier obsidian open` no longer answers `app-cli-unavailable` /
561
+ `vault-open-cli-silent` on the first silent round after it launched the
562
+ vault. A version only Atelier's plugin gave, with no answer for the vault,
563
+ now has to be seen in two rounds in a row: one version call that timed out
564
+ while Obsidian was busy opening its window made `open` report a command
565
+ line that was only slow as switched off. A wait that ends right after one
566
+ such round still gives that answer, not `launch-failed`.
567
+ - A view kept `current` while a plugin file it pins waits for Obsidian (a
568
+ drifted `data.json`, say, while the app cannot be coordinated with) now
569
+ says so. Its reason is `verified-by-read-back-plugin-waits-for-app`
570
+ instead of the `verified-by-read-back` of a view whose plugin files are all
571
+ there, and `status` and `open` add `plugin files wait for the app` to the
572
+ plugin line, with a next step (`files: "waits-for-app"` and `next` on
573
+ `plugin` in `--json`). A drift that publishing would only leave for the
574
+ person again (the data file of a vault root that is a link or not private,
575
+ a folder where a file goes) is no longer a reason to publish a committed
576
+ generation again, so it never waits for the app and never gets that
577
+ reason; the path is left as it is (nothing names it in `status` yet, and
578
+ the plugin shows as not present).
579
+ - A view held because a plugin file (`plugin-file-changed`) or a settings
580
+ file (`settings-changed`) changed while it was published, by another
581
+ program or by the person, is still `publisher-conflict`, but its next step
582
+ no longer tells the person to close another publisher: it names the file
583
+ that stopped the publication and says that the view is retried
584
+ automatically.
585
+ - A plugin-file drift that publishing cannot repair (the data file of a vault
586
+ root that is a link, say) was published twice whenever the maintenance
587
+ service started: once by the start's own tick and once more when the
588
+ service first compared the plugin files with the disk, or when that tick's
589
+ publication changed the pinned files. What that publication could not
590
+ change (a file as pinned, or one that holds what it held before the tick
591
+ under the same pin and vault root) is now taken as seen, and such a drift
592
+ is no longer a reason to publish a committed generation again, so asking
593
+ about it at most once more writes no vault file. A plugin file another
594
+ writer removes or changes after the publication, even during the same tick
595
+ (brought back to its old bytes after a publication that changed its pin,
596
+ say), unless it holds again what it held before the tick under the same
597
+ pin and vault root, and a path the person repairs before the tick ends,
598
+ are still written at the next tick.
599
+ - `atelier obsidian open` with Obsidian quit and the view's vault already in
600
+ Obsidian's list but closed: Obsidian started plainly does not reopen such a
601
+ vault, so a link it refused just after starting left `open` to wait and
602
+ answer `launch-failed` / `app-did-not-answer-for-this-vault`. `open` now
603
+ hands the link once more to the Obsidian that now runs, through its
604
+ command-line tool only (never the operating system, since this `open`
605
+ started it), before it answers that. A vault the list flags open is not
606
+ asked twice.
607
+ - `atelier obsidian --help` lists `plugin show | on` and `policy digest`, which
608
+ 0.2.0-alpha.12 ships but left out of that help (the operations themselves
609
+ worked, and `atelier obsidian help` showed them). A test now fails when a
610
+ built-in obsidian operation is missing from it.
611
+ - The project readiness artifact (`atelier-output/atelier-readiness.json` by
612
+ default) records `graph.path`, `projection.outputRoot` and
613
+ `projection.entry` relative to the project configuration directory, in POSIX
614
+ form, instead of as absolute paths. `atelier readiness --check` and
615
+ `atelier generated check` now accept an artifact written in another checkout
616
+ of the same project, and the artifact no longer names the machine's
617
+ directories (which could include the account name). An exact upgrade
618
+ candidate's readiness bytes now match what `atelier readiness` regenerates
619
+ there; before, when the path to the candidate passed through a symlink (as
620
+ macOS temporary directories do), the check reported the new candidate
621
+ stale. `atelier upgrade explain` no longer warns that readiness bytes can
622
+ contain absolute host paths. An artifact written by an earlier version is
623
+ reported stale once; run `atelier readiness` to rewrite it and review the
624
+ difference.
625
+ - `atelier dev` run before `atelier build` (straight after `atelier init`,
626
+ for example) printed Node's raw `[ENOENT] ... lstat '<absolute path>'`
627
+ with no next step, and after `atelier graph` alone a redacted
628
+ `[internal-error]`. Both are now `projection-output-missing`, naming the
629
+ output folder relative to the project config (never as an absolute path)
630
+ and the next step: run `atelier graph`, then `atelier build`, with the same
631
+ `--project` path. `atelier dev --help` (and `server --help`) now documents
632
+ `--port=PORT`, the `PORT` variable, the 8137 default, and `--review`.
633
+ - The CLI printed any error that carried a string code verbatim, so Node's own
634
+ errors (`ENOENT`, `EACCES`, `ERR_*`) reached the terminal with the absolute
635
+ path Node puts in their message, no next step, and exit 2. Only Atelier's
636
+ typed codes (lowercase words joined by hyphens) are now printed verbatim.
637
+ Any other error is `[internal-error]` with exit 1, naming only Node's code
638
+ and system call, for example `(ENOENT from lstat)`. `ATELIER_DEBUG=1` still
639
+ prints the full error.
640
+ - Obsidian source apply could reject with an untyped `ELEAFCHANGED` error. This
641
+ happened when another program renamed a new file over the source while the
642
+ published note was being prepared again, between the look at the path and its
643
+ open. That is a source being written: the apply now refuses `stale-source`
644
+ (cause `changed-while-reading`) and writes nothing. A preparation that fails
645
+ for any tolerated reason is no longer kept for its scope and generation; only
646
+ one that succeeded is reused.
647
+ - Obsidian source apply answers three more races with another program typed.
648
+ An enrolled source removed while apply builds the graph used to reject with
649
+ an untyped `ENOENT`; it now refuses `corpus-unreadable`, with the system code
650
+ as the cause, and writes nothing. When a publication replaced the pointer to
651
+ the current manifest during an apply, the read used to reject with an untyped
652
+ `ELEAFCHANGED`. The pointer is now read again, up to five times, and one that
653
+ keeps changing refuses `manifest-unavailable` (cause `changed-while-reading`).
654
+ A source replaced while the published note is prepared again now leads to a
655
+ fresh preparation, up to three in all. If the source was saved with the same
656
+ bytes, or another source of the scope was replaced, the edit applies instead
657
+ of refusing `published-note-unavailable`. Observation of pending edits on a
658
+ tick had the same gap: a source replaced while its note was prepared again
659
+ raised an untyped `ELEAFCHANGED` from the tick. It now refuses that edit
660
+ `stale-source` when its own source bytes changed, and otherwise refuses
661
+ `published-note-unavailable`. The failed preparation is no longer kept, so the
662
+ other edits of that generation in the tick are still observed.
663
+
664
+ ## 0.2.0-alpha.12
665
+
666
+ ### Added
667
+
668
+ - Atelier's own Obsidian plugin (phase 1: presence and status). Every vault
669
+ the maintenance service publishes now carries it under
670
+ `.obsidian/plugins/atelier-projection/` with its entry in
671
+ `.obsidian/community-plugins.json`; the person never installs anything, and
672
+ Obsidian asks once per vault whether to trust the vault's plugins. Once
673
+ trusted, a status bar item says whether the view is current, updating, held
674
+ for an edit, stale or out of reach of the service, and "Atelier: show
675
+ status" says why. The plugin writes nothing, runs nothing it is sent and
676
+ reaches only the workspace's maintenance service on its literal loopback
677
+ address. Without it (restricted mode, an app older than 1.13.7, before the
678
+ prompt is answered, or turned off in the vault) everything works as before.
679
+ See `docs/obsidian-plugin.md`.
680
+ - A person who turns Atelier's plugin off in a vault, or uninstalls it there,
681
+ is followed. Once the app has the plugin's entry in
682
+ `community-plugins.json` (it was in place before an app opened the vault,
683
+ or the plugin ran there), a list without it is recorded as the person's
684
+ decision (private state, `state/plugin/choices/`): the entry is not added
685
+ back, a deleted plugin folder is not made again, and the plugin files still
686
+ there are kept current. An entry published while an app held the vault is
687
+ only offered until then, since that app may write back the list it read
688
+ before, and a list without it is no decision of the person's. `status`, `open` and the new
689
+ `atelier obsidian plugin show` report `turned-off-in-this-vault`. Turning the
690
+ plugin on again in Obsidian's settings is followed the same way;
691
+ `atelier obsidian plugin on --scope ID` brings the entry and the files back
692
+ (the way back after an uninstall): at once, on a tick that names the view,
693
+ while the maintenance service runs (with `--adapter=obsidian-cli`, one of
694
+ an earlier release is replaced by the installed one first, as `open` does),
695
+ and otherwise at the view's next publication.
696
+ - The maintenance service answers five plugin commands (`/plugin/challenge`,
697
+ `/plugin/hello`, `/plugin/lease`, `/plugin/release`, `/plugin/status`,
698
+ protocol `atelier-obsidian-plugin-channel/v2`) and grants presence and
699
+ read-only status of one view to a plugin that proves it holds that vault's
700
+ key. The key is random per vault, kept owner-only in private state and in
701
+ that vault's plugin data file, and never crosses the wire: the service
702
+ proves it holds the key over its own exact address before the plugin sends
703
+ anything that names the vault, and every later request and answer is sealed
704
+ with a key for that session and a counter that only goes up. A program that
705
+ takes the service's port while the service is down learns nothing it can
706
+ use: an answer the session's key does not seal ends the session in the
707
+ plugin, so such a program receives one command of a session at most; a
708
+ challenge is answered once and only within thirty seconds of the time it
709
+ names, and at most four handshakes wait per view. `status` reports which
710
+ views a plugin holds open, and so do `atelier obsidian status` and `open`.
711
+ - While one launch of the plugin holds a view open and the command-line
712
+ tool gives no version (no vault open yet, or no answer in time), the app
713
+ version the plugin reports counts as checked (reason `plugin-reported`), in
714
+ the service's adapter factory and in `open`, unless the process table shows
715
+ no app running (a lease outlives a crashed app by a few seconds, and then
716
+ vouches for no version). A version the tool does give
717
+ decides, since the tool may reach another app holding the same vault, and
718
+ whether the app and its tool are installed is still the probe's answer.
719
+
720
+ ### Changed
721
+
722
+ - Node.js 24 is supported alongside Node.js 22. The engines range is now
723
+ `>=22.18.0 <23 || >=24.13.1 <25`, so an install on Node 24 no longer warns.
724
+ Graph and projection files come out byte-identical on either major: CI runs
725
+ the complete suite on 24.13.1 and on the newest 24, and a new
726
+ `cross-node-bytes` job builds one workspace on 22 and on 24 and compares
727
+ every file written. The byte-determinism test names the supported majors
728
+ and checks them against `package.json`. The floor is 24.13.1, not the
729
+ first 24 LTS, because earlier 24 releases have an `fs.rmSync` defect
730
+ (nodejs/node#61020): removing a symbolic link to a directory throws
731
+ `EISDIR`, and a broken symbolic link is silently left in place. The
732
+ complete suite fails on 24.11.0 for that reason.
733
+ - **Breaking:** Obsidian generation manifests of the new vault layout are
734
+ `atelier-obsidian-generation-manifest/v2`, a new contract major that records
735
+ `layoutVersion: 2` and each note's identity region, and a vault an earlier
736
+ release published is laid out again once (below). The v1 contract is
737
+ unchanged and still validates every generation an earlier release wrote; a
738
+ reader of generation manifests must accept both majors.
739
+ - Obsidian views are laid out in vault layout 2, so a file name reads as the
740
+ note's title and the vault reads as the repositories. Folders mirror each
741
+ repository under a folder named after it, so a view's folders show the
742
+ repository identity and source directory chain of its notes, as its notes'
743
+ `atelier-repo` and `atelier-source` properties do; this is acceptable for
744
+ every vault, scoped ones included. A note's file name is its title (the
745
+ front-matter `title`, else its first H1, else the file stem as written),
746
+ with a trailing source extension dropped and made safe for macOS, Linux,
747
+ Windows and Obsidian links. Two notes of a view that would share a name in
748
+ one folder, compared case- and normalization-insensitively, are told apart
749
+ by the source file stem and then by a short stable id; a name that collides
750
+ with nothing carries no hash. A wrapped file keeps its own name beside its
751
+ note (`<file name>.md`), and an embedded file is copied to its mirrored
752
+ path. Links name their target by its full vault path. A repository folder
753
+ that would be `notes` or `attachments` spelled another way is told apart by
754
+ a short id, since an upgraded vault keeps those two folders of the earlier
755
+ layout.
756
+ - Each view allocates its paths among its own notes, seeded from what its
757
+ prior generation published: a path does not change on retitle or when
758
+ other files come and go, a note that leaves the view releases its path
759
+ there (a renamed source takes its name back), a note of another view never
760
+ causes a qualifier, and a lost path registry costs no view its paths. One
761
+ identity may have different paths in different views. The registry keeps
762
+ each view's allocation in a section of its own, and drops the sections of
763
+ views the engine no longer maintains. `@mnstry/atelier/obsidian/materialize`
764
+ adds `allocateViewPaths`; `allocateWorkspacePaths` is deprecated: it still
765
+ allocates the earlier layout's paths for a whole workspace, exactly as
766
+ before, and Atelier no longer calls it.
767
+ - A source that does not fit is laid out anyway and reported, never a reason
768
+ to refuse the workspace: a folder chain too long for the path budget keeps a
769
+ readable prefix and a short stable id, or, when not even that fits, the note
770
+ sits directly in its repository's folder; a source folder that meets a file
771
+ of the same name is qualified with an id. Only a name that does not fit even
772
+ in its repository's folder refuses the view. What is worth a look (these, an
773
+ author's own identity keys shadowing the generated ones, generated text that
774
+ names a note outside the view without refusing it) is recorded in the
775
+ manifest and the view's freshness entry, and shown by
776
+ `atelier obsidian status`, naming the note.
777
+ - Every note names its identity in three generated front-matter properties,
778
+ `atelier-id`, `atelier-repo` and `atelier-source`, or, when its own front
779
+ matter could not take them unchanged in meaning, in a generated block at
780
+ its end. An edit to them is never applied to a source.
781
+ - A vault published by an earlier release is laid out again once. Every
782
+ earlier path is retired through the publisher's remove units: moved to the
783
+ recovery area, or kept where it is when somebody edited it. The app's
784
+ bookmarks, open tabs and graph positions of the earlier paths are lost once.
785
+ A view that holds a note for an open edit keeps its earlier layout until the
786
+ edit is applied or withdrawn, and such an edit still applies; an edit that
787
+ closes on a tick (automatic mode applies on the tick it observes) keeps it
788
+ for that tick, so the file the person edited becomes the published note and
789
+ is retired like any other. See "Vault layout" in `docs/obsidian-contract.md`.
790
+ - The redaction guard is re-based on the readable layout. Atelier never
791
+ generates a reference to a note outside a view: every path the emitter
792
+ writes must be one allocated to the view, and every identity block names
793
+ its own note. Generated prose repeats author text (the titles, summaries
794
+ and tags of in-view notes), which is carried as authored; the deny-list over
795
+ it, read as a reader sees it with the emitter's escapes removed and in NFC,
796
+ follows the audience, as defence in depth. For a note the audience may not
797
+ see it refuses an unambiguous identifier (an identity qualified by any
798
+ repository, a repository-qualified path, a repository-relative path with a
799
+ folder, a vault path) and reports a bare-word identity or a file name at a
800
+ repository's root (`README.md`); for a note the audience may see but the
801
+ view does not select it only reports. A view may newly refuse with
802
+ `redaction-failure`; the refusal names the rule and the in-view note, never
803
+ the value. Both rules run over every note, cached ones included. The deny
804
+ matcher is one automaton: building it takes time and memory linear in the
805
+ values it holds, on every preparation, and it reads each text once, however
806
+ many there are.
807
+ - A focus query names each note by an anchored regular-expression path term
808
+ (`path:/^…$/`, query version `obsidian-graph-search-paths/v2`), so it matches
809
+ exactly the selected notes; a focus persisted with the earlier version is
810
+ still read.
811
+ - `atelier obsidian open` makes the first open of a view automatic: Obsidian
812
+ no longer has to be quit, and no vault folder has to be opened by hand. It
813
+ makes the app know the view's vault as one of its vaults before it opens
814
+ it. With Obsidian running and
815
+ answering its command line, the vault is added through the app itself
816
+ (`vault-open` through `obsidian-cli eval`, a constant script with the folder
817
+ as a base64 JSON payload), verified in the app's own vault list by real
818
+ path, and opened; `open` waits until the app answers for exactly that vault
819
+ and then asks for the view again, so the first publication runs through the
820
+ app with every editor check. Quitting Obsidian is no longer needed. With
821
+ Obsidian not running, the view is published on the path with no app, and
822
+ the vault is added to the app's `obsidian.json` before the app is started
823
+ on it: only while the process table shows, positively, that no Obsidian
824
+ runs (read again immediately before the rename), only a file Obsidian
825
+ created, owned by this user and not a link, atomically (a temporary file in
826
+ the same directory, fsynced, renamed), keeping every other key and entry,
827
+ and with a timestamped backup beside it; a write that fails at any step
828
+ leaves the file as it was and nothing beside it; an Obsidian that never ran
829
+ on the account (no such file) is asked to be started once. With Obsidian running
830
+ and no vault open, a vault the app already lists is opened by path; one it
831
+ does not list is answered as `app-version-unsupported` / `no-vault-open`
832
+ (open any vault, or quit Obsidian, then open again) and nothing is
833
+ written. Every failure is typed and names its next step. See "What `open`
834
+ does in each state of Obsidian" in docs/obsidian.md and "Obsidian's vault
835
+ list" in docs/obsidian-contract.md.
836
+ - A tick requested over the service's listener may name one view
837
+ (`POST /tick` with `scopeId`; `requestServiceTick({ scopeId })`), which the
838
+ engine then prepares and publishes once more, whatever its state
839
+ (`engine.requestPreparation(scopeId)`, a one-shot request consumed at the
840
+ next tick), with the app's qualification asked again. `open` names its view
841
+ on both ticks it requests. A view whose last publication did not settle is
842
+ also tried again without a request: as soon as the app looks different (it
843
+ quit or started, or opened or closed a vault in its list), and otherwise
844
+ after a delay that starts at 30 seconds (`DEFAULT_PUBLICATION_RETRY_MS`) and
845
+ doubles, up to the full reconciliation interval. Before, it waited for a
846
+ change or the five-minute reconciliation. What the app looks like is read
847
+ from the process table and its vault list alone (`appStateSignature({
848
+ processes, settings })`), so nothing runs in Obsidian to find out; the app
849
+ is asked for its version only when a view is about to be published, and
850
+ the service's adapter factory asks it without blocking
851
+ (`createQualifiedAdapterFactory` answers a promise for an app probe with
852
+ `inspect()`). `engine.requestPreparation` takes a request only for a view
853
+ the project declared at the last tick (at most 64 before the first), and
854
+ answers whether it did. The service listener answers a POST member it does
855
+ not know, or a view on a stop, with 400 `request-member-unknown` instead of
856
+ 409, and checks a view against the scope contract's own identifier.
857
+ - Command-line calls to the app reach only the vault they are about. A call
858
+ about a vault names it first (`vault=<id>`), so it reaches that vault's
859
+ window whichever window has focus; only when that id would name another
860
+ vault first does it run in the vault's folder, and not at all when a vault
861
+ the app lists before it at a folder above it (a home folder, say) would take
862
+ a call run there. The vault root, the settings entry, the vault check and
863
+ the publication bridge's check that the app holds this vault use the path as
864
+ the file system stores it, so on macOS a data root given in another letter
865
+ case neither hides a vault listed above it nor routes a call there, and a
866
+ store written before, or an app that holds the vault under another spelling
867
+ or through a link, keeps working: publication through the app, and `open`'s
868
+ check that the app answers for the vault. Publication calls do so only while the app's list
869
+ shows the view's vault open; every other call runs in a directory that is
870
+ no vault. Maintenance never reopens a vault window that was closed and never
871
+ reaches another vault, and the directory a command or service was started
872
+ in no longer picks, or opens, a vault. `open` never adds a view's vault
873
+ inside a folder Obsidian already lists as a vault, which would show the
874
+ view's notes too: it answers `launch-failed` / `vault-inside-another-vault`.
875
+ A listed folder is compared as written first; its real path is read only
876
+ when its last component is the vault root's, so a vault on a mount that
877
+ does not answer is never waited on. The maintenance service is started in
878
+ the root directory.
879
+ - A view's vault that Obsidian has open in more than one window, one per
880
+ entry of its vault list that names the folder (under another letter case,
881
+ or through a link), is not published: a publication would coordinate with
882
+ one window only. The view reports `publisher-conflict` /
883
+ `vault-open-in-several-windows` (removing the extra entries from Obsidian's
884
+ vault list clears it; closing a window may not, since Obsidian keeps the last
885
+ window it closed marked open), and `open` answers the same, names the entries (`open in Obsidian
886
+ as: …`, `duplicates` in JSON) and launches nothing. While one entry of the
887
+ folder has a window, calls and `open` reach only that entry, so a closed
888
+ entry of the same folder is never opened beside it.
889
+ - Obsidian's settings file is not written larger than 4 MiB
890
+ (`obsidian-settings-too-large`), nor through a second name (a hard link,
891
+ `obsidian-settings-unsafe`). Of Atelier's backups beside it, the first (the
892
+ list as it was before Atelier wrote it) and the latest are kept. A write
893
+ that cannot be read back is `registration-not-read-back`, no longer
894
+ `app-started-during-registration`. A Flatpak or snap build of Obsidian on
895
+ Linux, which never reads that file, is recognised (the build whose vault
896
+ list was written last; its installation only when no build wrote one), and
897
+ the file is neither read nor written for it (`obsidian-sandboxed`); the
898
+ vault is added through the running app. An addition the running app did not answer is looked up in
899
+ its list, and is `addition-not-answered` when it is not there, no longer
900
+ `app-did-not-list-its-vaults`. Adding a vault through the app also puts its
901
+ folder in the operating system's recent documents (Recent Items on macOS),
902
+ as Obsidian's own "open folder as vault" does.
903
+ - A maintenance service still running an earlier release after an upgrade
904
+ is replaced by `open`. Every service records the release it runs, the
905
+ package version and a digest of every runtime module it ships (`src/`,
906
+ `contracts/`), in its record's `executable.ext.release`
907
+ (`releaseIdentity()`). A service of the workspace that proves itself ours
908
+ but runs an earlier version than the installed one, the same version with
909
+ another entry module or other modules, records no release, or refuses a
910
+ tick that names a view (as 0.2.0-alpha.11 and earlier do), is stopped
911
+ through its own listener and the installed release is started under the
912
+ consent already recorded; `open` shows `service: restarted (outdated)`
913
+ (`service.restarted` in JSON). A service of a later version (versions
914
+ ordered as semantic versions, 0.2.0-alpha.11 < 0.2.0-alpha.12 < 0.2.0), or
915
+ of one that cannot be ordered, is never replaced by an earlier release, so
916
+ two installations used on one workspace do not replace each other's service
917
+ on every open: `open` answers `service-unavailable` /
918
+ `service-other-release`, whose next step is `atelier obsidian service stop`,
919
+ then open again. The same version string on both sides is compared by
920
+ content even when it cannot be ordered (a fork's `dev`), so that next step
921
+ cannot loop. A tick refused because a concurrent command replaced the
922
+ runtime just before is asked of the runtime that took its place, and
923
+ nothing is restarted. A busy service is not stopped, and nothing that does
924
+ not prove itself ours is touched. `requestServiceTick` takes the start
925
+ options of the installed entry as `service` for this (`runtimeRelease`,
926
+ `releaseStanding`).
927
+ - The `status` next step for `publisher-conflict` / `editor-uncoordinated`
928
+ names `atelier obsidian open` (which adds the vault to Obsidian and
929
+ publishes through it) or quitting Obsidian; after `open` itself tried, it
930
+ names quitting Obsidian. `launch-failed` no longer asks for a vault folder
931
+ to be opened by hand.
932
+ - The settings unit owns two more things in a vault: the `atelier-projection`
933
+ entry of `community-plugins.json` (appended while the person wants the
934
+ plugin there; every other entry kept in order; written only over the exact
935
+ bytes the decision was made on, so a change the person makes meanwhile
936
+ stops that unit as `settings-changed` and the view is tried again) and the
937
+ plugin's four files, whose digests are pinned in the generation manifest
938
+ under `ext["mnstry.atelier.obsidian"].settings`.
939
+ Whatever occupies a plugin path is displaced to recovery, never lost; a
940
+ plugin path a person has to repair (a link, a folder where a file goes, a
941
+ file nobody may read, a folder nobody may write) never holds a view back; a
942
+ generation whose plugin files the person repaired, changed or removed is
943
+ published again as it is at the maintenance service's next tick; and
944
+ another writer racing a plugin file makes the view try again.
945
+ `isUserOwnedSettingsPath` answers `false` for these paths.
946
+ - Vault roots that Atelier places under its data root are created private
947
+ (`0700`), and an existing one is made private before the plugin's key is
948
+ written into it. A vault root Atelier did not place never receives the key
949
+ unless it is already private, and a vault path under the data root that is
950
+ a link to another folder never receives it, and its mode is never changed.
951
+ - A settings file nobody may read (`core-plugins.json`, say) is reported as
952
+ `path-unsafe` and left for the person instead of failing the publication.
953
+ - `plugins/` is part of the egress scan, and the release audit requires the
954
+ plugin's three files in the package.
955
+
956
+ ### Fixed
957
+
958
+ - A publication no longer stops with an untyped `state leaf changed while
959
+ opening` when another program replaces a note by rename at the instant the
960
+ publisher opens it (an editor or sync tool saving the note). The note is
961
+ read again, since every rename leaves a complete file; a note that keeps
962
+ being replaced is reported as `disk-changed` for that note only, and the
963
+ other notes are published. No bytes were ever lost: the publication threw
964
+ before writing.
965
+ - `open` no longer makes Obsidian forget which of your vaults to reopen. A
966
+ quit Obsidian started with an `obsidian://` link opens only that vault and
967
+ drops the reopen flag of every other one; `open` now starts it plainly on
968
+ macOS (it reopens every vault it had open, and the view's vault, which `open`
969
+ added flagged to reopen) and hands it the vault's link through its command
970
+ line once the app itself answers there, never through the operating system.
971
+ On Linux a quit Obsidian is still started with the link (a known limit).
972
+ - `open` names the vault by its id (`obsidian://open?vault=<id>`) where the id
973
+ reaches it first, instead of its path, which Obsidian matches against its
974
+ vault list by string prefix.
975
+ - Obsidian with its command line turned off (the default of a new
976
+ installation) answers every command with "Command line interface is not
977
+ enabled"; that answer was read as an unreadable version. It is now
978
+ `app-cli-unavailable` / `cli-turned-off`, whose next step names the setting
979
+ (Settings > General > Advanced > Command line interface).
980
+ - A view whose prepared generation was already the committed one (on the
981
+ first tick of a service, or prepared again on request) was marked `stale`
982
+ when the app could not be qualified, for example while it ran with no vault
983
+ open: the editor adapter was built before the publisher found nothing to
984
+ publish. That adapter is now built only when the publisher needs one.
985
+ - After a refused publication, the tick `open` asked for did not try the view
986
+ again (the engine attempted only views with changes), so `open` reported the
987
+ old conflict until the five-minute reconciliation.
988
+ - `open` launched `obsidian://open?path=` for a vault the app did not know,
989
+ and Obsidian showed "Vault not found. Unable to find a vault for the URL";
990
+ `open` then answered `launch-failed` / `app-did-not-answer-for-this-vault`.
991
+ - The production check that the app answers for a vault parsed the app's
992
+ answer twice and so never saw an answer; it now reads it once (twice only
993
+ for a quoted string), compares real paths, and asks from inside the vault
994
+ folder.
995
+ - An app whose vault window is still loading answers a command with `Error:
996
+ Command "version" not found`; that was read as an unreadable version and
997
+ ended `open` as `app-version-unsupported`. It is now read as not up yet.
998
+ - `atelier dev` on a port that was already taken (8137 by default) printed
999
+ only `[internal-error] command failed without a safe diagnostic`, and the
1000
+ message that says what to do appeared only with `ATELIER_DEBUG=1`. It is now
1001
+ `port-in-use`, naming the port, with `--port=<free port>` as the next step.
1002
+ A port the operating system refuses (EACCES, usually one below 1024) is
1003
+ `port-permission-denied` with the same remedy, and a `--port` or `PORT`
1004
+ value that is not a port from 0 to 65535 is `port-invalid`, naming which
1005
+ one, instead of Node's `ERR_SOCKET_BAD_PORT`. Other failures without a
1006
+ typed code are still redacted.
1007
+
3
1008
  ## 0.2.0-alpha.11
4
1009
 
5
1010
  ### Fixed