@mnstry/atelier 0.2.0-alpha.12 → 0.2.0-alpha.14

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 (531) hide show
  1. package/CHANGELOG.md +894 -0
  2. package/README.md +159 -6
  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-personal-workspace-manifest.v1.schema.json +87 -0
  21. package/contracts/atelier-personal-workspace-overlay.v1.schema.json +299 -0
  22. package/contracts/atelier-template-adoption.v1.schema.json +223 -0
  23. package/contracts/atelier-template-profile.v1.schema.json +1168 -0
  24. package/contracts/atelier-trackable.v1.schema.json +781 -0
  25. package/contracts/atelier-upgrade-plan.v3.schema.json +532 -0
  26. package/docs/architecture.md +89 -0
  27. package/docs/assurance-controls.md +2 -2
  28. package/docs/blocks/capability-stewardship.md +17 -0
  29. package/docs/blocks/claims.md +16 -3
  30. package/docs/blocks/inquiry-harnesses.md +19 -0
  31. package/docs/blocks/learning-harnesses.md +17 -0
  32. package/docs/capability-stewardship.md +267 -0
  33. package/docs/coordination.md +51 -0
  34. package/docs/decision-practices.md +111 -0
  35. package/docs/decisions.md +29 -0
  36. package/docs/evidence-navigation.md +237 -0
  37. package/docs/exact-upgrades.md +3 -2
  38. package/docs/ingestion.md +181 -0
  39. package/docs/inquiry-harnesses.md +210 -0
  40. package/docs/install.md +80 -3
  41. package/docs/intake-and-guides.md +5 -0
  42. package/docs/integration-contract-decisions.md +24 -2
  43. package/docs/interaction-and-reflection.md +72 -0
  44. package/docs/knowledge-graph.md +20 -0
  45. package/docs/knowledge-health/api.md +30 -0
  46. package/docs/knowledge-health/assessment/api.md +96 -0
  47. package/docs/knowledge-health/assessment/capabilities.md +40 -0
  48. package/docs/knowledge-health/assessment/evaluation.md +27 -0
  49. package/docs/knowledge-health/assessment/facilitator.md +30 -0
  50. package/docs/knowledge-health/assessment/quickstart.md +61 -0
  51. package/docs/knowledge-health/assessment/troubleshooting.md +23 -0
  52. package/docs/knowledge-health/devday/facilitator.md +16 -0
  53. package/docs/knowledge-health/devday/participant-response.md +22 -0
  54. package/docs/knowledge-health/devday/public-default.md +107 -0
  55. package/docs/knowledge-health/devday/quickstart.md +18 -0
  56. package/docs/knowledge-health/devday/support.md +22 -0
  57. package/docs/knowledge-health/exercise.md +17 -0
  58. package/docs/knowledge-health/facilitator.md +20 -0
  59. package/docs/knowledge-health/quickstart.md +94 -0
  60. package/docs/knowledge-health/readme.md +15 -0
  61. package/docs/knowledge-health/support.md +34 -0
  62. package/docs/knowledge-setup.md +248 -0
  63. package/docs/knowledge-workspace.md +264 -0
  64. package/docs/learning-harnesses.md +237 -0
  65. package/docs/learning.md +215 -0
  66. package/docs/local-services.md +223 -19
  67. package/docs/obsidian-contract.md +246 -15
  68. package/docs/obsidian-plugin.md +252 -7
  69. package/docs/obsidian.md +874 -52
  70. package/docs/optional-ingestion.md +83 -0
  71. package/docs/personal-workspace.md +266 -0
  72. package/docs/practical-judgment.md +92 -0
  73. package/docs/progressive-ingestion-acceptance.md +89 -0
  74. package/docs/progressive-ingestion.md +235 -0
  75. package/docs/project-command-inventory.md +1 -0
  76. package/docs/release-engineering.md +50 -0
  77. package/docs/repo-boundary-guard.md +120 -3
  78. package/docs/research-starter-quickstart.md +66 -0
  79. package/docs/research-starter.md +114 -0
  80. package/docs/semantic-ingestion.md +198 -0
  81. package/docs/semantic-operation.md +318 -0
  82. package/docs/skill-steward.md +6 -0
  83. package/docs/template-profile.md +164 -0
  84. package/docs/template-upgrades.md +114 -0
  85. package/docs/trackables.md +111 -0
  86. package/docs/upgrade.md +219 -2
  87. package/fixtures/atelier-architecture/binding/invalid/document.json +19 -0
  88. package/fixtures/atelier-architecture/binding/valid/document.json +19 -0
  89. package/fixtures/atelier-architecture/catalog/invalid/document.json +290 -0
  90. package/fixtures/atelier-architecture/catalog/valid/document.json +343 -0
  91. package/fixtures/atelier-build-contract/attempt/invalid/document.json +20 -0
  92. package/fixtures/atelier-build-contract/attempt/valid/document.json +19 -0
  93. package/fixtures/atelier-build-contract/candidate/invalid/document.json +24 -0
  94. package/fixtures/atelier-build-contract/candidate/valid/document.json +23 -0
  95. package/fixtures/atelier-build-contract/decision/invalid/document.json +31 -0
  96. package/fixtures/atelier-build-contract/decision/valid/document.json +30 -0
  97. package/fixtures/atelier-build-contract/delivery/invalid/document.json +18 -0
  98. package/fixtures/atelier-build-contract/delivery/valid/document.json +17 -0
  99. package/fixtures/atelier-build-contract/gate/invalid/document.json +22 -0
  100. package/fixtures/atelier-build-contract/gate/valid/document.json +21 -0
  101. package/fixtures/atelier-build-contract/ledger/invalid/document.json +270 -0
  102. package/fixtures/atelier-build-contract/ledger/valid/document.json +269 -0
  103. package/fixtures/atelier-build-contract/objective/invalid/document.json +73 -0
  104. package/fixtures/atelier-build-contract/objective/valid/document.json +72 -0
  105. package/fixtures/atelier-build-contract/progress/invalid/document.json +18 -0
  106. package/fixtures/atelier-build-contract/progress/valid/document.json +17 -0
  107. package/fixtures/atelier-capability-contract/adoption/invalid/document.json +71 -0
  108. package/fixtures/atelier-capability-contract/adoption/valid/document.json +70 -0
  109. package/fixtures/atelier-capability-contract/event/invalid/document.json +18 -0
  110. package/fixtures/atelier-capability-contract/event/valid/document.json +17 -0
  111. package/fixtures/atelier-capability-contract/journal/invalid/document.json +382 -0
  112. package/fixtures/atelier-capability-contract/journal/valid/document.json +381 -0
  113. package/fixtures/atelier-capability-contract/notice/invalid/document.json +8 -0
  114. package/fixtures/atelier-capability-contract/notice/valid/document.json +7 -0
  115. package/fixtures/atelier-capability-contract/package/invalid/document.json +59 -0
  116. package/fixtures/atelier-capability-contract/package/valid/document.json +58 -0
  117. package/fixtures/atelier-capability-contract/plan/invalid/document.json +107 -0
  118. package/fixtures/atelier-capability-contract/plan/valid/document.json +106 -0
  119. package/fixtures/atelier-capability-contract/release/invalid/document.json +85 -0
  120. package/fixtures/atelier-capability-contract/release/valid/document.json +84 -0
  121. package/fixtures/atelier-capability-contract/state/invalid/document.json +316 -0
  122. package/fixtures/atelier-capability-contract/state/valid/document.json +315 -0
  123. package/fixtures/atelier-coordination/dependency/invalid/document.json +37 -0
  124. package/fixtures/atelier-coordination/dependency/valid/document.json +36 -0
  125. package/fixtures/atelier-coordination/directive/invalid/document.json +25 -0
  126. package/fixtures/atelier-coordination/directive/valid/document.json +24 -0
  127. package/fixtures/atelier-coordination/disposition/invalid/document.json +34 -0
  128. package/fixtures/atelier-coordination/disposition/valid/document.json +33 -0
  129. package/fixtures/atelier-coordination/outcome/invalid/document.json +39 -0
  130. package/fixtures/atelier-coordination/outcome/valid/document.json +38 -0
  131. package/fixtures/atelier-coordination/recovery/invalid/document.json +34 -0
  132. package/fixtures/atelier-coordination/recovery/valid/document.json +33 -0
  133. package/fixtures/atelier-harness-contract/handoff/invalid/document.json +25 -0
  134. package/fixtures/atelier-harness-contract/handoff/valid/document.json +24 -0
  135. package/fixtures/atelier-ingestion/invalid/authority.json +19 -0
  136. package/fixtures/atelier-ingestion/semantic-baseline.json +26 -0
  137. package/fixtures/atelier-ingestion/semantic-operation.json +75 -0
  138. package/fixtures/atelier-ingestion/valid/plan-input.json +18 -0
  139. package/fixtures/atelier-inquiry-contract/assessment/invalid/document.json +41 -0
  140. package/fixtures/atelier-inquiry-contract/assessment/valid/document.json +40 -0
  141. package/fixtures/atelier-inquiry-contract/bundle/invalid/document.json +51 -0
  142. package/fixtures/atelier-inquiry-contract/bundle/valid/document.json +50 -0
  143. package/fixtures/atelier-inquiry-contract/campaign/invalid/document.json +17 -0
  144. package/fixtures/atelier-inquiry-contract/campaign/valid/document.json +16 -0
  145. package/fixtures/atelier-inquiry-contract/decision/invalid/document.json +22 -0
  146. package/fixtures/atelier-inquiry-contract/decision/valid/document.json +21 -0
  147. package/fixtures/atelier-inquiry-contract/feedback/invalid/document.json +19 -0
  148. package/fixtures/atelier-inquiry-contract/feedback/valid/document.json +18 -0
  149. package/fixtures/atelier-inquiry-contract/handoff/invalid/document.json +92 -0
  150. package/fixtures/atelier-inquiry-contract/handoff/valid/document.json +91 -0
  151. package/fixtures/atelier-inquiry-contract/hypothesis/invalid/document.json +20 -0
  152. package/fixtures/atelier-inquiry-contract/hypothesis/valid/document.json +19 -0
  153. package/fixtures/atelier-inquiry-contract/ledger/invalid/document.json +680 -0
  154. package/fixtures/atelier-inquiry-contract/ledger/valid/document.json +679 -0
  155. package/fixtures/atelier-inquiry-contract/legacy-assessment/invalid/document.json +19 -0
  156. package/fixtures/atelier-inquiry-contract/legacy-assessment/valid/document.json +18 -0
  157. package/fixtures/atelier-inquiry-contract/request/invalid/document.json +50 -0
  158. package/fixtures/atelier-inquiry-contract/request/valid/document.json +49 -0
  159. package/fixtures/atelier-inquiry-contract/source/invalid/document.json +18 -0
  160. package/fixtures/atelier-inquiry-contract/source/valid/document.json +17 -0
  161. package/fixtures/atelier-inquiry-contract/withdrawal/invalid/document.json +16 -0
  162. package/fixtures/atelier-inquiry-contract/withdrawal/valid/document.json +15 -0
  163. package/fixtures/atelier-instruction-adoption/context-receipt/invalid/document.json +18 -0
  164. package/fixtures/atelier-instruction-adoption/context-receipt/valid/document.json +17 -0
  165. package/fixtures/atelier-instruction-adoption/plan/invalid/document.json +63 -0
  166. package/fixtures/atelier-instruction-adoption/plan/valid/document.json +62 -0
  167. package/fixtures/atelier-instruction-adoption/receipt/invalid/document.json +22 -0
  168. package/fixtures/atelier-instruction-adoption/receipt/valid/document.json +21 -0
  169. package/fixtures/atelier-instruction-adoption/state/invalid/document.json +30 -0
  170. package/fixtures/atelier-instruction-adoption/state/valid/document.json +29 -0
  171. package/fixtures/atelier-interaction/act/invalid/document.json +25 -0
  172. package/fixtures/atelier-interaction/act/valid/document.json +24 -0
  173. package/fixtures/atelier-interaction/assessment/invalid/document.json +32 -0
  174. package/fixtures/atelier-interaction/assessment/valid/document.json +31 -0
  175. package/fixtures/atelier-interaction/observation/invalid/document.json +22 -0
  176. package/fixtures/atelier-interaction/observation/valid/document.json +21 -0
  177. package/fixtures/atelier-interaction/policy/invalid/document.json +20 -0
  178. package/fixtures/atelier-interaction/policy/valid/document.json +19 -0
  179. package/fixtures/atelier-judgment/case/invalid/document.json +76 -0
  180. package/fixtures/atelier-judgment/case/valid/document.json +75 -0
  181. package/fixtures/atelier-judgment/decision/invalid/document.json +38 -0
  182. package/fixtures/atelier-judgment/decision/valid/document.json +37 -0
  183. package/fixtures/atelier-judgment/native-decision.md +3 -0
  184. package/fixtures/atelier-judgment/practice-reconsideration/definition.json +92 -0
  185. package/fixtures/atelier-judgment/practice-reconsideration/scenario.json +435 -0
  186. package/fixtures/atelier-knowledge-contract/activation/invalid/document.json +26 -0
  187. package/fixtures/atelier-knowledge-contract/activation/valid/document.json +25 -0
  188. package/fixtures/atelier-knowledge-contract/contribution/invalid/document.json +34 -0
  189. package/fixtures/atelier-knowledge-contract/contribution/valid/document.json +33 -0
  190. package/fixtures/atelier-knowledge-contract/domain/invalid/document.json +41 -0
  191. package/fixtures/atelier-knowledge-contract/domain/valid/document.json +40 -0
  192. package/fixtures/atelier-knowledge-contract/domain-revision/invalid/document.json +46 -0
  193. package/fixtures/atelier-knowledge-contract/domain-revision/valid/document.json +45 -0
  194. package/fixtures/atelier-knowledge-contract/evaluation/invalid/document.json +21 -0
  195. package/fixtures/atelier-knowledge-contract/evaluation/valid/document.json +20 -0
  196. package/fixtures/atelier-knowledge-contract/ledger/invalid/document.json +318 -0
  197. package/fixtures/atelier-knowledge-contract/ledger/valid/document.json +317 -0
  198. package/fixtures/atelier-knowledge-contract/relation/invalid/document.json +25 -0
  199. package/fixtures/atelier-knowledge-contract/relation/valid/document.json +24 -0
  200. package/fixtures/atelier-knowledge-contract/review/invalid/document.json +18 -0
  201. package/fixtures/atelier-knowledge-contract/review/valid/document.json +17 -0
  202. package/fixtures/atelier-knowledge-contract/withdrawal/invalid/document.json +16 -0
  203. package/fixtures/atelier-knowledge-contract/withdrawal/valid/document.json +15 -0
  204. package/fixtures/atelier-learning/invalid/authority.json +14 -0
  205. package/fixtures/atelier-learning/valid/capture.json +13 -0
  206. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/authority-key.json +17 -0
  207. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/nonempty-ext.json +25 -0
  208. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/wrong-schema.json +22 -0
  209. package/fixtures/atelier-personal-workspace-contract/manifest/valid/manifest.json +22 -0
  210. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/authority-key.json +25 -0
  211. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/unknown-top-level-field.json +27 -0
  212. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/wrong-schema.json +24 -0
  213. package/fixtures/atelier-trackable/definition/invalid/document.json +15 -0
  214. package/fixtures/atelier-trackable/definition/valid/document.json +14 -0
  215. package/fixtures/atelier-trackable/request/invalid/document.json +23 -0
  216. package/fixtures/atelier-trackable/request/valid/document.json +22 -0
  217. package/fixtures/boundary-delegations/invalid/authority-key.v1.json +30 -0
  218. package/fixtures/boundary-delegations/invalid/push-operation.v1.json +28 -0
  219. package/fixtures/boundary-delegations/invalid/unsigned.v1.json +25 -0
  220. package/fixtures/boundary-delegations/valid/empty.v1.json +4 -0
  221. package/fixtures/boundary-delegations/valid/signed-operator.v1.json +30 -0
  222. package/fixtures/boundary-owner-keys/invalid/wrong-algorithm.v1.json +15 -0
  223. package/fixtures/boundary-owner-keys/invalid/wrong-curve.v1.json +15 -0
  224. package/fixtures/boundary-owner-keys/valid/one-owner.v1.json +17 -0
  225. package/fixtures/capability-packages/adoption.example.json +70 -0
  226. package/fixtures/capability-packages/evidence-review/capability-package.json +58 -0
  227. package/fixtures/capability-packages/evidence-review/capability-release.json +84 -0
  228. package/fixtures/capability-packages/evidence-review/evaluation.md +15 -0
  229. package/fixtures/capability-packages/evidence-review/skills/evidence-review/SKILL.md +22 -0
  230. package/fixtures/capability-packages/evidence-review/skills/evidence-review/references/ledger.md +7 -0
  231. package/fixtures/capability-packages/research/capability-package.json +88 -0
  232. package/fixtures/capability-packages/research/capability-release.json +134 -0
  233. package/fixtures/capability-packages/research/evaluation.md +15 -0
  234. package/fixtures/capability-packages/research/skills/research-integrate/SKILL.md +29 -0
  235. package/fixtures/capability-packages/research/skills/research-integrate/references/integration.md +10 -0
  236. package/fixtures/capability-packages/research/skills/research-plan/SKILL.md +27 -0
  237. package/fixtures/capability-packages/research/skills/research-plan/references/inquiries.md +26 -0
  238. package/fixtures/capability-packages/research/skills/research-synthesize/SKILL.md +23 -0
  239. package/fixtures/capability-packages/research/skills/research-synthesize/references/synthesis.md +12 -0
  240. package/fixtures/evidence-navigation/invalid/duplicate-operation.json +16 -0
  241. package/fixtures/evidence-navigation/invalid/instruction-kind.json +36 -0
  242. package/fixtures/evidence-navigation/invalid/invalid-digest.json +36 -0
  243. package/fixtures/evidence-navigation/invalid/invalid-time.json +36 -0
  244. package/fixtures/evidence-navigation/invalid/missing-attribution.json +35 -0
  245. package/fixtures/evidence-navigation/invalid/reserved-extension.json +19 -0
  246. package/fixtures/evidence-navigation/invalid/unattributed-acceptance.json +36 -0
  247. package/fixtures/evidence-navigation/invalid/uncoerced-version.json +16 -0
  248. package/fixtures/evidence-navigation/invalid/unknown-currency.json +17 -0
  249. package/fixtures/evidence-navigation/invalid/unknown-selector-field.json +37 -0
  250. package/fixtures/evidence-navigation/invalid/unsupported-operation.json +15 -0
  251. package/fixtures/evidence-navigation/valid/claim.json +36 -0
  252. package/fixtures/evidence-navigation/valid/host.json +16 -0
  253. package/fixtures/evidence-navigation/valid/profile.json +16 -0
  254. package/fixtures/evidence-navigation/valid/snapshot.json +17 -0
  255. package/fixtures/harness-packages/build-harness/capability-package.json +61 -0
  256. package/fixtures/harness-packages/build-harness/capability-release.json +82 -0
  257. package/fixtures/harness-packages/build-harness/evaluation.md +3 -0
  258. package/fixtures/harness-packages/build-harness/skills/atelier-build-harness/SKILL.md +59 -0
  259. package/fixtures/harness-packages/knowledge-harness/capability-package.json +61 -0
  260. package/fixtures/harness-packages/knowledge-harness/capability-release.json +82 -0
  261. package/fixtures/harness-packages/knowledge-harness/evaluation.md +3 -0
  262. package/fixtures/harness-packages/knowledge-harness/skills/atelier-knowledge-harness/SKILL.md +60 -0
  263. package/fixtures/harnesses/learning-cycle.json +780 -0
  264. package/fixtures/inquiry/workshop.json +675 -0
  265. package/fixtures/inquiry-packages/discovery-harness/capability-package.json +61 -0
  266. package/fixtures/inquiry-packages/discovery-harness/capability-release.json +82 -0
  267. package/fixtures/inquiry-packages/discovery-harness/evaluation.md +3 -0
  268. package/fixtures/inquiry-packages/discovery-harness/skills/atelier-discovery-harness/SKILL.md +48 -0
  269. package/fixtures/inquiry-packages/research-harness/capability-package.json +61 -0
  270. package/fixtures/inquiry-packages/research-harness/capability-release.json +82 -0
  271. package/fixtures/inquiry-packages/research-harness/evaluation.md +3 -0
  272. package/fixtures/inquiry-packages/research-harness/skills/atelier-research-harness/SKILL.md +43 -0
  273. package/fixtures/knowledge-health/calibration-suite.json +26 -0
  274. package/fixtures/knowledge-health/calibration-trial.json +37 -0
  275. package/fixtures/knowledge-health/corrected/checklist.md +18 -0
  276. package/fixtures/knowledge-health/devday/participant-record.json +19 -0
  277. package/fixtures/knowledge-health/expected-summary.json +27 -0
  278. package/fixtures/knowledge-health/workshop/README.md +20 -0
  279. package/fixtures/knowledge-health/workshop/atelier.project.json +7 -0
  280. package/fixtures/knowledge-health/workshop/knowledge-plan.json +65 -0
  281. package/fixtures/knowledge-health/workshop/records/checklist.md +18 -0
  282. package/fixtures/knowledge-health/workshop/records/workshop.md +18 -0
  283. package/fixtures/knowledge-health/workshop/repo-access.v1.json +5 -0
  284. package/fixtures/knowledge-health/workspace/atelier.project.json +18 -0
  285. package/fixtures/knowledge-health/workspace/knowledge-plan.json +74 -0
  286. package/fixtures/knowledge-health/workspace/records/checklist.md +18 -0
  287. package/fixtures/knowledge-health/workspace/records/pilot.md +16 -0
  288. package/fixtures/knowledge-health/workspace/repo-access.v1.json +9 -0
  289. package/fixtures/personal-workspace/overlay.json +24 -0
  290. package/fixtures/templates/local-library.v1.json +76 -0
  291. package/fixtures/templates/upgrade-contracts/adoption-policy.v2/invalid.json +16 -0
  292. package/fixtures/templates/upgrade-contracts/adoption-policy.v2/valid.json +13 -0
  293. package/fixtures/templates/upgrade-contracts/migration.v3/invalid.json +24 -0
  294. package/fixtures/templates/upgrade-contracts/migration.v3/valid.json +21 -0
  295. package/fixtures/templates/upgrade-contracts/template-adoption.v1/invalid.json +60 -0
  296. package/fixtures/templates/upgrade-contracts/template-adoption.v1/valid.json +57 -0
  297. package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/invalid.json +85 -0
  298. package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/valid.json +82 -0
  299. package/package.json +60 -5
  300. package/plugins/obsidian/main.js +57 -8
  301. package/plugins/obsidian/manifest.json +1 -1
  302. package/skills/claude/atelier-build-harness/SKILL.md +59 -0
  303. package/skills/claude/atelier-coordination/SKILL.md +32 -0
  304. package/skills/claude/atelier-discovery-harness/SKILL.md +48 -0
  305. package/skills/claude/atelier-guided-upgrade/SKILL.md +29 -0
  306. package/skills/claude/atelier-interaction/SKILL.md +34 -0
  307. package/skills/claude/atelier-knowledge-harness/SKILL.md +60 -0
  308. package/skills/claude/atelier-knowledge-setup/SKILL.md +72 -0
  309. package/skills/claude/atelier-practical-judgment/SKILL.md +64 -0
  310. package/skills/claude/atelier-research-harness/SKILL.md +43 -0
  311. package/skills/claude/atelier-skill-steward/SKILL.md +53 -0
  312. package/skills/claude/atelier-trackables/SKILL.md +40 -0
  313. package/skills/codex/atelier-build-harness/SKILL.md +59 -0
  314. package/skills/codex/atelier-coordination/SKILL.md +32 -0
  315. package/skills/codex/atelier-discovery-harness/SKILL.md +48 -0
  316. package/skills/codex/atelier-guided-upgrade/SKILL.md +29 -0
  317. package/skills/codex/atelier-interaction/SKILL.md +34 -0
  318. package/skills/codex/atelier-knowledge-harness/SKILL.md +60 -0
  319. package/skills/codex/atelier-knowledge-setup/SKILL.md +72 -0
  320. package/skills/codex/atelier-practical-judgment/SKILL.md +64 -0
  321. package/skills/codex/atelier-research-harness/SKILL.md +43 -0
  322. package/skills/codex/atelier-skill-steward/SKILL.md +53 -0
  323. package/skills/codex/atelier-trackables/SKILL.md +40 -0
  324. package/src/architecture/catalog.mjs +355 -0
  325. package/src/architecture/index.mjs +93 -0
  326. package/src/boundary/content-rules.mjs +536 -69
  327. package/src/boundary/delegation-command.mjs +158 -0
  328. package/src/boundary/delegation.mjs +396 -0
  329. package/src/boundary/policy.mjs +185 -64
  330. package/src/build/git.mjs +18 -0
  331. package/src/build/index.mjs +3 -0
  332. package/src/build/ledger.mjs +88 -0
  333. package/src/capabilities/adoption.mjs +381 -0
  334. package/src/capabilities/evidence.mjs +140 -0
  335. package/src/capabilities/files.mjs +124 -0
  336. package/src/capabilities/index.mjs +4 -0
  337. package/src/capabilities/instructions.mjs +250 -0
  338. package/src/capabilities/package.mjs +136 -0
  339. package/src/cli/command-failure.mjs +36 -0
  340. package/src/cli/execute-command.mjs +16 -2
  341. package/src/cli/run.mjs +66 -9
  342. package/src/coauthor/store.mjs +43 -2
  343. package/src/collaboration/proposals.mjs +189 -0
  344. package/src/commands/architecture.mjs +27 -0
  345. package/src/commands/boundary.mjs +3 -0
  346. package/src/commands/capability.mjs +73 -0
  347. package/src/commands/enroll.mjs +3 -0
  348. package/src/commands/harness.mjs +79 -0
  349. package/src/commands/ingest.mjs +39 -0
  350. package/src/commands/init.mjs +4 -1
  351. package/src/commands/inquiry.mjs +66 -0
  352. package/src/commands/knowledge-semantic.mjs +128 -0
  353. package/src/commands/knowledge.mjs +119 -0
  354. package/src/commands/learn.mjs +61 -0
  355. package/src/commands/obsidian.mjs +772 -65
  356. package/src/commands/practice.mjs +24 -0
  357. package/src/commands/setup.mjs +22 -2
  358. package/src/commands/trackable.mjs +19 -0
  359. package/src/contracts/corpus.mjs +30 -0
  360. package/src/coordination/index.mjs +110 -0
  361. package/src/evidence-navigation/contracts.mjs +60 -0
  362. package/src/evidence-navigation/evaluate.mjs +69 -0
  363. package/src/evidence-navigation/generation.mjs +22 -0
  364. package/src/evidence-navigation/index.mjs +2 -0
  365. package/src/evidence-navigation/local.mjs +167 -0
  366. package/src/evidence-navigation/schema.generated.mjs +604 -0
  367. package/src/evidence-navigation/types.mjs +12 -0
  368. package/src/export/atelier-export-contract.mjs +35 -8
  369. package/src/graph/enroll.mjs +248 -0
  370. package/src/graph/graph.mjs +30 -6
  371. package/src/graph/knowledge-graph.mjs +77 -9
  372. package/src/harnesses/contracts.mjs +41 -0
  373. package/src/harnesses/exchange.mjs +154 -0
  374. package/src/harnesses/feedback.mjs +16 -0
  375. package/src/harnesses/history.mjs +37 -0
  376. package/src/harnesses/index.mjs +4 -0
  377. package/src/harnesses/store.mjs +29 -0
  378. package/src/ingestion/contracts.mjs +41 -0
  379. package/src/ingestion/evaluation.mjs +119 -0
  380. package/src/ingestion/optional/composition/index.mjs +171 -0
  381. package/src/ingestion/optional/evaluation/index.mjs +219 -0
  382. package/src/ingestion/optional/graphify/composition-binding.mjs +60 -0
  383. package/src/ingestion/optional/graphify/composition_receiving.py +185 -0
  384. package/src/ingestion/optional/graphify/graphify_supplier.py +938 -0
  385. package/src/ingestion/optional/graphify/json_bridge.py +163 -0
  386. package/src/ingestion/optional/graphify/native-closure-pins.json +275 -0
  387. package/src/ingestion/optional/graphify/native-pins.json +306 -0
  388. package/src/ingestion/optional/graphify/query_receiving.py +209 -0
  389. package/src/ingestion/optional/index.mjs +9 -0
  390. package/src/ingestion/optional/jev/bridge.mjs +166 -0
  391. package/src/ingestion/optional/jev/composition-binding.mjs +116 -0
  392. package/src/ingestion/optional/jev/judgments.mjs +174 -0
  393. package/src/ingestion/optional/jev/native-translation.mjs +32 -0
  394. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/__init__.py +7 -0
  395. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/adapter.py +966 -0
  396. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/artifacts.py +101 -0
  397. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/projection.py +146 -0
  398. package/src/ingestion/optional/lightrag/composition-binding.mjs +67 -0
  399. package/src/ingestion/optional/vanilla/composition-binding.mjs +102 -0
  400. package/src/ingestion/optional/vanilla/index.mjs +218 -0
  401. package/src/ingestion/optional/vanilla/native-normalization.mjs +187 -0
  402. package/src/ingestion/processors.mjs +218 -0
  403. package/src/ingestion/semantic.mjs +203 -0
  404. package/src/ingestion/store.mjs +372 -0
  405. package/src/inquiry/beliefs.mjs +32 -0
  406. package/src/inquiry/contracts.mjs +23 -0
  407. package/src/inquiry/index.mjs +5 -0
  408. package/src/inquiry/ledger.mjs +135 -0
  409. package/src/inquiry/lenses.mjs +15 -0
  410. package/src/inquiry/projection.mjs +77 -0
  411. package/src/inquiry/store.mjs +35 -0
  412. package/src/intake/read-scope.mjs +12 -0
  413. package/src/intake/store.mjs +69 -6
  414. package/src/interaction/index.mjs +91 -0
  415. package/src/judgment/index.mjs +82 -0
  416. package/src/judgment/practice-evaluation.mjs +70 -0
  417. package/src/judgment/practice.mjs +144 -0
  418. package/src/knowledge/context.mjs +217 -0
  419. package/src/knowledge/index.mjs +5 -0
  420. package/src/knowledge/ingestion.mjs +79 -0
  421. package/src/knowledge/intake.mjs +33 -0
  422. package/src/knowledge/ledger.mjs +110 -0
  423. package/src/knowledge/participatory/guidance.mjs +36 -0
  424. package/src/knowledge/participatory/guided-contribution.mjs +44 -0
  425. package/src/knowledge/participatory/index.mjs +2 -0
  426. package/src/knowledge/participatory/installed-workshop.mjs +108 -0
  427. package/src/knowledge/plan.mjs +67 -0
  428. package/src/knowledge/projection.mjs +43 -0
  429. package/src/knowledge/semantic-operation.mjs +567 -0
  430. package/src/knowledge/sessions.mjs +467 -0
  431. package/src/knowledge/workspace.mjs +295 -0
  432. package/src/knowledge-health/assessment.mjs +165 -0
  433. package/src/knowledge-health/capabilities.mjs +350 -0
  434. package/src/knowledge-health/context.mjs +62 -0
  435. package/src/knowledge-health/example.mjs +47 -0
  436. package/src/knowledge-health/index.mjs +10 -0
  437. package/src/knowledge-health/owner-join.mjs +88 -0
  438. package/src/knowledge-health/proof/common.mjs +24 -0
  439. package/src/knowledge-health/proof/installed-check.mjs +100 -0
  440. package/src/knowledge-health/proof/native-readback.mjs +37 -0
  441. package/src/knowledge-health/proof/rehearse.mjs +68 -0
  442. package/src/knowledge-health/proof/validate-participant.mjs +17 -0
  443. package/src/knowledge-health/proof/verify-native-capture.mjs +14 -0
  444. package/src/knowledge-health/proof/workshop-check.mjs +36 -0
  445. package/src/knowledge-health/rule-identity.mjs +49 -0
  446. package/src/knowledge-health/workshop-composition.mjs +19 -0
  447. package/src/knowledge-health/workshop-profile.mjs +176 -0
  448. package/src/knowledge-health/workshop.mjs +99 -0
  449. package/src/learning/adapters.mjs +68 -0
  450. package/src/learning/assistance.mjs +127 -0
  451. package/src/learning/contracts.mjs +65 -0
  452. package/src/learning/store.mjs +272 -0
  453. package/src/personal-workspace/index.mjs +391 -0
  454. package/src/personal-workspace/selection.mjs +401 -0
  455. package/src/project/config.mjs +8 -0
  456. package/src/project/durable-state.mjs +3 -1
  457. package/src/project/file-class.mjs +1 -1
  458. package/src/project/path-match.mjs +2 -1
  459. package/src/projection/obsidian/edits/apply.mjs +55 -16
  460. package/src/projection/obsidian/materialize/prepare-view.mjs +87 -5
  461. package/src/projection/obsidian/personal-workspace.mjs +519 -0
  462. package/src/projection/obsidian/proposals/adapter.mjs +79 -17
  463. package/src/projection/obsidian/proposals/observation.mjs +50 -4
  464. package/src/projection/obsidian/publication/publisher.mjs +214 -18
  465. package/src/projection/obsidian/publication/vault-list.mjs +4 -3
  466. package/src/projection/obsidian/recovery/index.mjs +4 -1
  467. package/src/projection/obsidian/recovery/store.mjs +160 -7
  468. package/src/projection/obsidian/selection-ui/contribution.mjs +6 -5
  469. package/src/projection/project.mjs +3 -2
  470. package/src/readiness/readiness.mjs +10 -3
  471. package/src/reflection/index.mjs +56 -0
  472. package/src/runtime/obsidian/app-production-seams.mjs +48 -16
  473. package/src/runtime/obsidian/app-registration.mjs +175 -28
  474. package/src/runtime/obsidian/app-restart.mjs +154 -0
  475. package/src/runtime/obsidian/engine.mjs +437 -56
  476. package/src/runtime/obsidian/extension-points.mjs +1 -1
  477. package/src/runtime/obsidian/index.mjs +10 -7
  478. package/src/runtime/obsidian/launch-plan.mjs +7 -4
  479. package/src/runtime/obsidian/lifecycle.mjs +108 -23
  480. package/src/runtime/obsidian/login-item.mjs +335 -0
  481. package/src/runtime/obsidian/machine-settings.mjs +119 -12
  482. package/src/runtime/obsidian/observation.mjs +36 -4
  483. package/src/runtime/obsidian/opening.mjs +173 -38
  484. package/src/runtime/obsidian/personal-selection.mjs +125 -0
  485. package/src/runtime/obsidian/pipeline.mjs +115 -6
  486. package/src/runtime/obsidian/plugin-channel.mjs +11 -3
  487. package/src/runtime/obsidian/plugin-choice.mjs +16 -4
  488. package/src/runtime/obsidian/plugin-drift.mjs +59 -11
  489. package/src/runtime/obsidian/plugin-presence.mjs +14 -1
  490. package/src/runtime/obsidian/private-lock.mjs +39 -4
  491. package/src/runtime/obsidian/process-identity.mjs +20 -10
  492. package/src/runtime/obsidian/project-views.mjs +282 -0
  493. package/src/runtime/obsidian/questions.mjs +48 -0
  494. package/src/runtime/obsidian/release-watch.mjs +56 -0
  495. package/src/runtime/obsidian/service-main.mjs +148 -19
  496. package/src/runtime/obsidian/service-manager-production.mjs +61 -0
  497. package/src/runtime/obsidian/service-managers.mjs +275 -0
  498. package/src/runtime/obsidian/service-record.mjs +87 -23
  499. package/src/runtime/obsidian/service.mjs +102 -9
  500. package/src/runtime/obsidian/startup-adapters.mjs +59 -21
  501. package/src/runtime/obsidian/unheld-evidence.mjs +84 -0
  502. package/src/runtime/obsidian/vault-location.mjs +300 -0
  503. package/src/runtime/obsidian/view-counts.mjs +34 -0
  504. package/src/runtime/obsidian/view-permission.mjs +334 -0
  505. package/src/server/local-sidecar.mjs +169 -2
  506. package/src/server/server.mjs +28 -2
  507. package/src/template-bindings/project.mjs +92 -0
  508. package/src/templates/profile.mjs +225 -0
  509. package/src/trackables/domain.mjs +175 -0
  510. package/src/trackables/store.mjs +114 -0
  511. package/src/ui/control-system.mjs +201 -0
  512. package/src/ui/html-primitives.mjs +3 -0
  513. package/src/ui/knowledge-page.mjs +1388 -0
  514. package/src/upgrade/closure-diagnostics.mjs +135 -0
  515. package/src/upgrade/closure.mjs +649 -0
  516. package/src/upgrade/explanation.mjs +1 -1
  517. package/src/upgrade/template-participant.mjs +171 -0
  518. package/src/upgrade/transaction.mjs +72 -25
  519. package/src/upgrade/upgrade.mjs +20 -7
  520. package/templates/external-project-workspace/pack-lifecycle.json +7 -1
  521. package/templates/knowledge-workspace/.gitattributes +2 -0
  522. package/templates/knowledge-workspace/AGENTS.md +27 -0
  523. package/templates/knowledge-workspace/README.md +44 -0
  524. package/templates/knowledge-workspace/atelier.project.json +22 -0
  525. package/templates/knowledge-workspace/gitignore +6 -0
  526. package/templates/knowledge-workspace/knowledge-plan.json +111 -0
  527. package/templates/knowledge-workspace/knowledge-plan.schema.json +281 -0
  528. package/templates/knowledge-workspace/records/forecast.md +22 -0
  529. package/templates/knowledge-workspace/records/inspection.md +25 -0
  530. package/templates/knowledge-workspace/records/telescope.md +24 -0
  531. package/templates/knowledge-workspace/repo-access.v1.json +9 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,899 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0-alpha.14
4
+
5
+ - The Obsidian maintenance service's log no longer gets a `status-project-loaded` line for every failure and recovery, or every slow load, of the plugin's status read while its loads come less than a minute apart and fail, or are slow, every other load or every third. Before, any load that answered ended a row of failures, and any load in time a row of slow loads. Now a row of failures ends only at a load that answers a minute or more after its last failure, with a line that names how many failures it held, and a row of slow loads only at a load in time a minute or more after the last slow one. Such a loader writes one row, less and less often. While a project is kept, it is loaded again every two and a half minutes, so there a row of failures ends at the next reload that answers. A loader that answers at least one reload between two failures still writes each failure and the load that ends its row, and one that fails at every reload and answers only at its retry keeps one row. Each slow load is still written there. A load at every request is now written too, when each load names the files it started over. That happens while a file that decides the views vouches for nothing, or while loads never agree, and before it showed only as a growing count. A load after which nothing is kept, though it named the files it started over, is written from the second in a row, on the same doubling row (`notKept`, with `vouched`); a load that named other files, as after a new confirmed selection, neither counts nor ends that row. `statusLoads` in the status document counts these loads as `notKept`, one at a start and one after each change on a healthy service.
6
+ - An Obsidian maintenance service started by a login item asks its project loader once (under `--personal-home`, its locator), and now hands its first answer on faithfully. A thenable that is no promise is adopted once as a native promise that settles as it does, so its `then` is called once in all. Before, it was called twice: once where the process let the answer go, and again at the service's own start. A promise whose `constructor` reads as this realm's `Promise` is let go without calling a `then` of its own, which may throw; any other, as a rule another realm's promise or a subclass's, is adopted as any other thenable is. A service started any other way that is handed a promise with a `then` of its own that throws now refuses it typed as well. Before, that start ended untyped. Anything thrown, `undefined` included, and a project whose `then` cannot be read, ends the start as a failure of the loader does. Before, `undefined` was taken as an answer of nothing: the start went on to resolve a workspace from it, and for a locator it was refused as `service-locator-invalid`. An unreadable `then` ended the process with an error the service never logged. The service also logs what was thrown when it has no prototype, or a `code` or `message` that cannot be read, where before that logging itself threw. A start ended by an error without a code is still a crash that the service manager restarts.
7
+ - A view the Obsidian maintenance service refuses for a file-system error is now named in its private log. The view's freshness names only the refusal's code, and such a tick is no failure, so nothing recorded the error before. Examples are `vault-location-unusable` for a vault folder that could not be allocated or placed, `mixed-read` for a configuration file that could not be read again during the tick or a source removed while it was read, and `staging-failed` for candidates that could not be staged. The service now writes a `view-refused` line for each such view whose refusal carries a file-system error's code, at most 64 a tick. The line names the view, the refusal's code and the error's code (`EACCES`, `EIO`, `ENOENT`, `ENOSPC`), and `cleanupCause` when a cleanup after it failed too. Only codes shaped as a file-system error's are written, never a message. A view the next tick names for the same reason is not written again, so a vault folder that stays unwritable, tried at every tick, is written once. The engine's tick report carries the same entries as `refusalCauses`, only when there are any.
8
+ - A failure while the publisher cleans up the candidates of a staging that did not complete no longer replaces what ended the staging. Before, a removal or a read that failed (`EBUSY`, `EPERM`, `EIO`, a volume gone) was thrown in place of the refusal or stop, and the tick failed without a typed reason. Now each candidate is cleaned up on its own, so one that cannot be removed leaves the others removed. What ended the staging is handed on unchanged: a caller's stop, a refusal such as `vault-root-moved`, or `staging-failed`. The code of the first such failure is added to a copy of its detail as `cleanupCause`. A candidate that could not be removed stays where it was, as before. That is in staging, or at its exchange path once the publication's journal is written, where the restart recovery of the next publication removes it.
9
+ - A selected source removed while the Obsidian maintenance service prepares or publishes a view, after the tick observed it and before the preparation, or the look again at the sources before the commit, read it, now refuses that view as `mixed-read`, as a source removed during the graph build does: no generation is committed for the view, the tick goes on to its other views, and the next tick reads everything again and publishes without the source. A generation already committed and prepared again is not reported current. Before, the tick failed without a typed reason: the view read `publisher-error`, the views after it were not prepared in that tick, and the service read degraded and recorded the error until the next tick. The rule is the build's: only a source the tick observed and that is gone when it is read (or its folder) is refused this way, and a file that cannot be read for another reason, or a path still there, still stops the tick. The engine primitive that decides it is now named `sourceRemovedSinceObserved`.
10
+ - A running Obsidian maintenance service whose loaded project is pinned to a selection record below the highest record any part of the service has read the selection history ending at loads the project again at its next tick, with no read of its own to trigger it. A confirmation read by another part of the service (the plugin's status read) and removed before the engine looked therefore refuses `selection-history-shortened` at that tick. Before, the engine went on publishing under its record until its next recheck, at the latest the next full reconciliation. Views that a change stops one after another have the history's end read once, not once a view, and it is read also when a file that decides the views could not be read.
11
+ - A source removed while the Obsidian maintenance service builds the canonical graph, after the build listed it and before it read it, now refuses the views of that tick as `mixed-read`, as a source changed during the build is: nothing is prepared from the build, and the next tick reads everything again and publishes without it. Before, the tick failed without a typed reason, and the service read degraded and recorded the error until the next tick. Only a source this tick observed, gone when the build reads it (or its folder), is refused this way. Anything else still stops the tick: a file that cannot be read for another reason, a path still there, one the walk over the sources listed and could not read, or one it never observed, so a path that can never be read fails every tick as before.
12
+ - AP-03 cleanup joins owned child handles even when the runtime status record is missing or malformed, and retains disposable roots when cleanup cannot be proven.
13
+ - The Obsidian maintenance service goes on answering health and status while a tick observes and routes pending edits. Observation gives the event loop a turn between two edits, and proposal routing gives it one before each repository and between two operations. Each edit and each operation is still handled in one stretch, and what is observed, recorded and proposed is unchanged. Before, a tick with a burst of edits held the listener for the whole observation. An observation asked for while another is under way now waits for it.
14
+ - The event-loop benchmark (`scripts/obsidian/benchmark-event-loop.mjs`) waits for the health request in flight at the end of the first tick, and of a transition, before it judges the window. A stretch at the end that holds the listener is then measured by that request's latency, under the same five-second rule as any other, instead of being read as a gap in the sampling; the 250 ms edge rule is about whether the sampling reached the edge, as it already was at the start of a tick. A request in flight at the end that is never answered now fails the run, where before it was left out. The rules a request is judged by are unchanged. The result's `health` and `transitionHealth` say whether such a request was waited for (`awaitedProbeInFlightAtEnd`; `false` also when it was answered at once). `--timeout-ms` may now be up to four hours, so a first publication of ten thousand notes in six views can be run; the window is judged without a limit on how many requests it holds.
15
+ - A running Obsidian maintenance service no longer follows a selection history back when it is cut short. It notes the highest record number at every read of the history's end, and a history that ends earlier refuses `selection-history-shortened`: nothing is loaded from it, a project already loaded is refused at its next recheck, the views say why and the vault keeps what it last published, until the removed records are back or the history is as long again. Before, the service loaded whatever record the history then ended with, so a history cut after a restore nobody confirmed published that restore. The number is kept in the process only: a service started after the cut, by the person or at login, after an upgrade or a failure, reads the history as it then stands and follows what it ends with, as each command run once does. Keeping it across a start is not part of this change.
16
+ - The Obsidian maintenance service goes on answering health and status while a published view is read back. The read-back after a commit gives the event loop a turn between notes, as preparation and publication do. It ran through before: for one view of 10,000 notes it held the listener for 1.9 s on a quiet host and 16.8 s on a loaded one, long enough for three health requests in a row to time out. Each note of the committed generation is still read once, and a view is reported current only after its read-back. `reconcileCooperatively` beside `reconcile` in `src/runtime/obsidian/observation.mjs` is the walk that waits.
17
+ - The event-loop benchmark (`scripts/obsidian/benchmark-event-loop.mjs`) has two more scenarios, which ask the service for one more tick after the first publication, with nothing changed, and judge that tick: by what it did, by how long it held the event loop, and by the health requests across it. `--scenario=next-tick` keeps the watcher a service runs with, so that tick is told of the notes the publication wrote, as the tick after a publication is; when the publication took five minutes or more it is also a full reconciliation, as it is in a service. `--scenario=full-reconciliation` makes it a full reconciliation whatever the publication took. The result records the tick, whether it was full, its longest event-loop delay, and what the watcher had reported before it. Until now no stage ran a tick that a watcher had told of anything, and the one full reconciliation a stage ran (in `observe-16`) was over the small corpus that stage is run with.
18
+ - The Obsidian maintenance service goes on answering health and status while a tick looks at the vault and at the sources. Before a view is prepared, the walk over every view's notes and the walk over the sources give the event loop a turn between files, as the read-back does. They ran through before: on one view of 10,000 notes the tick after a publication (told by the watcher of every note it wrote, and a full reconciliation as well after a long publication) held the listener for 5.5 s on a loaded host, and a health request timed out; at every full reconciliation, every five minutes, each walk reads every file. The pending edits are still read, compared and written in one stretch, after the walk over the vault. A file changed after its turn in a walk is seen by the next tick, by its stat hint or the watcher, or at the latest by the next full reconciliation. The tick reports two more phases to a caller that asks for them, `vault-observation` and `late-writer-recheck`. In the event-loop benchmark, a second-tick stage's ending is one tested function, and its delay test samples the stretch it means to leave out.
19
+ - A note removed from a vault is no longer lost when the tick that saw it fails without a typed reason (a source or a note it cannot read, a full disk while an edit is kept). The removal is a change once, and such a tick had recorded it without acting on it, so the view stayed `current` with the note gone, through every later full reconciliation. The tick after a failure without a typed reason now starts as the first tick of a process does: it loads the project again and looks at every view, and the view reads `vault-note-missing`. A source changed in such a tick, or a view added to the configuration in a tick whose project loader failed, is published by the next one for the same reason. The phase `late-writer-recheck` is reported when the look again at displaced files fails too.
20
+ - An Obsidian maintenance service whose engine lock could not be given back at the end of a tick (its released ticket could not be written: a full disk, an I/O error) goes on maintaining once the write succeeds. Before, every later tick found the service's own unreleased ticket and answered `busy`, which the service counts as a success: health read healthy, the views stayed `current`, and nothing was maintained until the service was started again. The tick whose release failed still fails; the lock stays held, and the next tick gives it back before it takes it again. A release of a private generation lock that throws now settles nothing, so calling it again tries again.
21
+ - A private generation lock whose acquisition fails after its ticket was put in place (the directory sync or the read-back of the ticket, or the listing that confirms it) removes that ticket again, while it still holds its own bytes, before the failure is reported; a removal that fails too is made at that process's next acquisition in the same directory. Before, the ticket stayed on disk unreleased and nobody held it to release it: every later acquisition by the same process found it held by that process, so an Obsidian maintenance service answered `busy` at every tick until it was started again, with health reading healthy. The engine lock, the start lock of `service start` and the proposal adapter's lock all take this path.
22
+ - The Obsidian maintenance service goes on answering health and status while a tick builds the canonical graph. The census (each Markdown source read, hashed and parsed, or reused from the graph file cache) gives the event loop a turn between sources; a first tick reads every source, and on a heavily loaded host the build for one view of 10,000 invented notes held the listener for 8 s in one stretch. The settings that select the views are checked at each wait, as during a preparation. `buildKnowledgeGraphSteps` and `buildCanonicalGraphSteps` are the builds as steps; `buildKnowledgeGraph` and `buildCanonicalGraph` run them through, unchanged for their callers. A project bound to a personal workspace is built by its own route in one stretch, as before, and the other sources (HTML files, the sidecars of PDF and Word documents) are read without a turn between them. Walking the directories, resolving links and assembling the graph still run through. `createProductionSeams()` has one more member, `buildGraphCooperatively`, which the engine uses for every project not bound to a personal workspace; a caller that replaces `buildGraph` and leaves `buildGraphCooperatively` as it ships builds every graph through its own `buildGraph`, as a replaced `prepareView` already prepares every view. Knowledge Health pins the bytes of the two graph files, so its rule identity is regenerated for them: the `check` each assessment carries names a new `version`, `sourceTree` and `graphBlob`, and the rule it applies is unchanged.
23
+ - Pages that still called shipped commands unreleased now say they shipped in 0.2.0-alpha.13: `atelier knowledge semantic`, `atelier ingest` (with the `./ingestion` export), `atelier inquiry`, `atelier harness` and `atelier capability`. Each was checked against the published 0.2.0-alpha.12 and 0.2.0-alpha.13 packages.
24
+ - A staged or pushed deletion of a tracked binary file no longer blocks the boundary check. A deleted path has nothing to read at the revision being scanned, yet the check tried to read it and reported `content-scan-incomplete` ("binary content could not be read within the 8388608-byte per-file limit"), which refused the commit or the push. A binary added or changed in the same change is still read and scanned, and only the extended header of the diff can say a path was deleted, so a content line cannot skip a file. A binary rename that git shows as a deletion and an addition is unblocked the same way.
25
+ - The optional Graphify supplier loads again. `graphify_supplier.py` reads `native-pins.json` and `native-closure-pins.json` beside it when it is imported, and neither file was in the package, so importing it (and the JSON bridge, query and composition receivers that import it) failed with a missing file in 0.2.0-alpha.13. Both pin files ship now, admitted by the release tarball audit, pinning Graphify 0.9.72 at upstream commit `1cd9a36c`: 30 operations and 67 closure modules. Of the 30, `extract-semantic` is pinned but cannot run, because its `graphify.llm` module is outside the admitted closure, so 29 are usable. `extract-structure` now refuses `parallel: true` with `NATIVE_WORKERS_UNATTESTED`: parallel extraction starts worker processes that import Graphify outside the pinned source loader, so only in-process extraction is admitted.
26
+ - `atelier upgrade closure` says what to do in two more cases and refuses one more flag. A refused linked `--npm-root` prints the directory's `realPath`, and the docs say why macOS `/tmp` and `$TMPDIR` are refused until it is given. A tarball URL with no readable host no longer suggests `--registry-host`, which cannot clear it. The `prefix-mismatch` message no longer claims npm would use another root, since the plan refuses any parent that declares workspaces. `--__proto__`, which the shared argument parser dropped, is refused as an unsupported flag. The upgrade guide now matches the code on an empty `--npm-root=` (`npm-root-required`), on `http` and `https` (counted separately in `registrySchemes`) and on when Atelier's own `package.json` is read.
27
+ - The practice-consumer reconsideration tool (`scripts/practice-consumer/reconsider.mjs measure`) can keep the full context of one measurement with `--capture NEWFILE`: the records and definition the evaluator was given, each evaluation's input and outcome as received, the citations that were not evaluated and why, and the decisions with no citation. It is written once, to a file that must not exist yet and must not be the measurements file under another name (checked by real path before measuring and by the file itself after writing), only when the measurement line can be appended, and before that line, so a refused capture appends nothing and the run removes the capture it wrote; only a run interrupted between writing the capture and appending its line can leave one standing. Without `--capture` nothing changes.
28
+ - The boundary content scan reads every changed file under its own name. Its diffs now pin their format (`--no-ext-diff --no-textconv --no-color --src-prefix=a/ --dst-prefix=b/ --no-relative --inter-hunk-context=0 --submodule=short --full-index`), so `diff.noprefix`, `diff.mnemonicPrefix`, changed prefixes, forced colour, an external diff or a textconv driver no longer leave a staged or pushed change unscanned, and fused hunks or submodule summaries do not stop clean work. Quoted paths (non-ASCII, quotes, tabs) and paths containing ` b/` are read correctly instead of being skipped or read as another file; a name holding a backslash is reported as it is, never inherits a sibling path's exception, and is in scope of every path-scoped rule. Changed binaries are read by object id, so a name shaped like an index stage (`0:name`) is read as itself. Added lines are taken from each hunk by its own line counts, so an added line that itself begins with `+`, such as a Markdown bullet, is scanned. Text that the repository's attributes declare binary (UTF-8 without a NUL byte in its first 8 KiB) was not scanned at all; it is now judged by its added lines like any other text, with renames and copies paired as in the main diff, and other content declared binary is scanned as a binary, as before. A changed file the scan cannot read from the diff is reported as `content-scan-incomplete` and blocks, where before it was skipped; a Git setting not pinned here can therefore stop a commit but cannot hide content.
29
+ - The boundary pre-commit check judges what is being committed. `git commit -a` and `git commit <paths>` hand the hook a temporary index, and a commit from a linked worktree its own index; the check dropped it with the rest of the Git environment, read the configured checkout's index and saw nothing staged. It now reads the index and work tree Git names, for the managed repository being committed, found by Git even from a hook chained into a subdirectory, and blocks when no single declared repository is being committed (`pre-commit-repo-unresolved`), as the push check does. Staged paths are listed NUL-separated, so a quoted name (non-ASCII, quotes) is matched against forbidden-path patterns, and a repository whose staged paths cannot be listed blocks. The semantic-field review reads the staged diff with the same pinned format and parser as the content scan, reads a document Git would call binary as text, blocks on a diff it cannot read, and takes only an added review marker as approval: a removed marker, or one in a file name, approves nothing; `atelier upgrade` applies the same marker rule. A forbidden-path pattern's `**` now also matches across a newline in a name.
30
+ - In the boundary content scan, a file that takes the name of a directory, or moves into a directory of its own name, in text that Git reports as binary, is judged as the main diff pairs it instead of blocking the commit. When such text is still unreadable the message says Git reports it as binary, which also covers text replacing binary content.
31
+ - The boundary push check judges the commits a push carries that the remote's tracking refs do not hold, each against its parent, binaries included, so a key added in one commit and removed in the next is no longer published unscanned; such a finding names its commit, and a key that reaches the pushed tip is reported once, listing the commits that carry it. A merge is judged only for what is new against all its parents, so a pull merge into the branch you push is not refused for what the remote already holds. The pre-push hook now passes the remote Git names (a configured remote, or a URL matched to one); reinstall hooks (`atelier boundary install-hooks`) so history held only by another remote is judged on its way to a new one. A push carrying more than 1000 such commits or more than the evidence budget is refused with `content-scan-incomplete`; push it in smaller parts. The content scan's diffs omit a deleted file's removed lines, which it never judges (the semantic-field review still reads them), so deleting a large file no longer exhausts the output limit. A new branch in a SHA-256 repository is diffed against that format's empty tree instead of failing.
32
+
33
+ - `atelier upgrade closure --npm-root ABSOLUTE_NPM_ROOT` plans a check of a staged
34
+ candidate's own dependency closure, and `planConsumerClosure` is exported from
35
+ `@mnstry/atelier/upgrade`. The plan reads the candidate's `package.json` and
36
+ `package-lock.json`, the installed manifest of every lockfile copy of the
37
+ selected package, `package.json` in each directory above the npm root (to
38
+ refuse a parent that declares workspaces) and, for the default package name,
39
+ Atelier's own `package.json`. It runs no npm command, uses no network, reads
40
+ no npm configuration and writes nothing. It reports the lockfile's sources,
41
+ registry hosts and schemes, and platform exclusions. It checks the selected
42
+ package's exact `overrides` against every installed copy, only after binding
43
+ each installed manifest to the name and version of its lockfile entry, and
44
+ lists selector, nested and non-exact overrides, and overrides for packages a
45
+ link provides, as unchecked. The npm root must be the directory's real path.
46
+ Refusals reuse `usage`, `consumer-closure-incomplete` and
47
+ `override-not-inherited`, each with one bounded reason. Every run prints one
48
+ JSON document, including a run whose arguments are refused. A completed plan
49
+ exits 3 with `"proof": "not-run"` and a refusal exits 2; the command never
50
+ exits 0 and does not prove an offline reinstall. The consumer-closure
51
+ classifiers moved to `src/upgrade/closure-diagnostics.mjs`, and
52
+ `scripts/consumer-closure-diagnostics.mjs` re-exports them. Two of them
53
+ changed: a project folder entry in a lockfile is never counted as an
54
+ installed copy, and a lockfile entry that is not an object is reported as
55
+ missing by `capturedClosure` instead of raising a `TypeError`.
56
+
57
+ - Add a tenant-neutral HTML control system at `@mnstry/atelier/ui`. The shared
58
+ geometry, variants, focus treatment, motion, action-group layouts, and safe
59
+ renderers are used by Atelier's generated project UI and are available to
60
+ downstream publication kits without importing publication semantics into
61
+ Atelier.
62
+ - The Obsidian service test suites reserve the loopback ports they choose, so
63
+ another test cannot take a port between its selection and its use.
64
+ - The Obsidian plugin (1.1.2) keeps the last authenticated status in view
65
+ through a transport interruption. After a connection refusal or timeout on
66
+ the same channel, the status window shows the last observed state, reason,
67
+ generation and check under "Last observed" labels. Those rows are historical
68
+ and never establish current freshness, service health or permission. The
69
+ history stays in memory and is cleared on a channel change, an
70
+ authentication refusal, an untrusted or malformed answer, a report for
71
+ another scope, or unload. A republish that names a different channel resets
72
+ the display to `connecting` without repeating an unchanged notice, and the
73
+ plugin opens no channel before startup admits it or after unload.
74
+ - The Obsidian maintenance service tells a plugin a view's stored freshness
75
+ and pending-edit count only while the project allows that view at the moment
76
+ of the request: its Obsidian settings are enabled and declare the view, and
77
+ its workspace pointer still names the workspace the service runs for.
78
+ Before, a view that was turned off or taken out of the settings was still
79
+ told what the service had stored, until the next tick and, for its
80
+ generations and counts, after it. The answer is now sealed as before with
81
+ `view` and `pendingEdits` null, so the plugin shows `Atelier: stale`, keeps
82
+ its session and asks again; anything that cannot be established (settings
83
+ that refuse, a project that does not load) is answered the same way. The
84
+ project is loaded again only when a file that decides it changed, compared
85
+ by content at every request. A loader that answers a promise is never
86
+ waited for: its view is told nothing until the load has answered.
87
+ - The real-app acceptance run of the small-fixture desktop procedure
88
+ (`scripts/obsidian/desktop-receipts.mjs`, maintainer tooling that is not
89
+ shipped) ends the processes it started, removes the temporary directories it
90
+ created, and bounds the receipt and console output it keeps. It signals only
91
+ a process it spawned or a recorded child of one, and removes a directory only
92
+ while the path still names the one it created; otherwise it keeps the
93
+ directories and names them.
94
+ - A project configuration file that is a link (one kept in a dotfiles
95
+ repository, say) no longer makes the Obsidian maintenance service load the
96
+ project, and run Git, at every status request a plugin makes. The service
97
+ compares what the loader reads through the link: the file it leads to and
98
+ that file's bytes, so a link pointed elsewhere is a change. A folder in a
99
+ file's place, or a link that leads nowhere or to a folder, still vouches for
100
+ nothing. The project the service keeps for those requests is taken only from
101
+ two loads in a row that agree over the same bytes, is loaded again every two
102
+ and a half minutes and never used past five. A loader that answers a promise
103
+ is given up after two and a half minutes, and a load that fails is asked for
104
+ again after two seconds, then four, up to thirty, unless a file changed.
105
+ - The Obsidian maintenance service refuses to start on a project loader that
106
+ answers a promise (or any other thenable), with
107
+ `service-loader-not-synchronous`, before it reads anything from it, listens
108
+ or records anything. Before, it handed the promise to its workspace
109
+ resolution, which then read the workspace pointer of the working directory
110
+ and protected no repository. For the status read of a plugin: a load whose
111
+ answer comes after its deadline is given up even when no request saw the
112
+ deadline pass; a link is resolved as the system resolves it, a `..` after a
113
+ link included, and a link to a folder above a configuration file pointed
114
+ elsewhere is a change; two loads agree when what the decision reads of the
115
+ project is the same, so a field that differs between loads (a time, a
116
+ binding under a symbol key) no longer stops a project from being kept; and
117
+ a load that fails, is given up or holds the event loop is logged with how
118
+ long it took.
119
+ - The Obsidian maintenance service stays responsive while it prepares and
120
+ publishes a view. The engine prepares each view cooperatively and the
121
+ publisher yields between complete units, so the loopback listener answers
122
+ health and status while notes are emitted, staged and published, instead of
123
+ being `busy` for the length of a large first publication. `open` and
124
+ `service stop` therefore reach a service in the middle of a publication:
125
+ `open` waits for a tick that starts after the one in flight, and `service
126
+ stop` ends the service after the tick in flight or its shutdown grace,
127
+ leaving a publication cut short to the publisher's restart recovery.
128
+ Walking the directories, resolving links and assembling the canonical
129
+ graph, capturing the source snapshot, the
130
+ publisher's restart recovery, validating a prepared view and planning its
131
+ units, the exchange probe, writing and syncing the journal before the
132
+ candidates move and the look again at displaced files after the units
133
+ still run without yielding. So did reading the sources into the canonical
134
+ graph, observing the source and vault files and the read-back after a
135
+ commit, until later changes made them wait between files (for the graph,
136
+ between Markdown sources, outside a personal workspace).
137
+ `prepareView` stays synchronous
138
+ and returns the same bytes. Across each wait of preparation and publication
139
+ the configuration files, the machine settings and the eligibility revision
140
+ are checked again, and after
141
+ a view is prepared and before its generation commits every selected source
142
+ is checked as observation checks it: by its stat hint, and by digest where
143
+ the hint moved. A change during the tick refuses the generation as
144
+ `mixed-read`; neither that tick nor a later restart recovery commits it,
145
+ and the next tick prepares the view again. A source that drifts under an
146
+ unchanged stat hint is still seen by the next full reconciliation, and a
147
+ note reused from the preparation cache is still not read. A cancelled
148
+ preparation leaves the preparation cache as it was, and publication keeps
149
+ its locks, journal and conditional writes.
150
+ - Started by a login item, the Obsidian maintenance service asks its project
151
+ loader once, and a loader that answers a promise there is refused and
152
+ recorded as at any other start, ending with 0. Before, the promise reached
153
+ the workspace resolution, and a refused one ended the process with an error
154
+ that the service manager answered by starting it again. The loads behind a
155
+ plugin's status requests are counted in the service's status document
156
+ (`statusLoads`), and the service log gets a `status-project-loaded` line
157
+ only for a load that failed or was given up (the first in a row, then when
158
+ the row is 2, 4, 8 and so on long), the first that answered after a failure,
159
+ and one that held the event loop for a second or more. A regular
160
+ configuration file the system resolves no path for (some Windows volumes)
161
+ is compared by its own path and bytes, instead of the project being loaded
162
+ at every request.
163
+ - A publication of the Obsidian maintenance service that is stopped or refused
164
+ on the way is recorded and cleaned up as what it was. A caller's stop after
165
+ the journal was opened (a setting that changed during the tick,
166
+ `mixed-read`, or a cancellation) is recorded in the journal's last entry
167
+ under that stop's own code instead of `publisher-error`; restart recovery
168
+ reads such a journal as before. A configuration file that cannot be read
169
+ again at a wait (no permission, an I/O error, no descriptor left) refuses
170
+ that view as `mixed-read` and has the next tick read everything again;
171
+ before, the raw error ended the tick, and the views after that one were not
172
+ prepared. A refusal raised while candidates are being staged (the vault's
173
+ folder replaced or gone) is still reported under its own code, now after
174
+ the candidates it staged are removed; before, those staged ahead of the
175
+ journal stayed in private staging, where restart recovery never looks. And
176
+ the service reads an explicit `prepareViewCooperatively: null` among its
177
+ engine seams as the engine does: there is no cooperative preparation, so a
178
+ replaced `prepareView` prepares the view.
179
+ - The desktop acceptance procedures (`scripts/obsidian/desktop-receipts.mjs`,
180
+ maintainer tooling that is not shipped) no longer signal the isolated app
181
+ by its process number outside the small-fixture run: quitting signals it
182
+ through the handle spawn returned and waits on that handle, a launch that
183
+ gives up signals the app's process group only while that handle still
184
+ holds the app, and a launch under the user's own HOME is refused before the
185
+ stale command-line socket there is removed. In the small-fixture run, a
186
+ process first recorded from a process table passes lineage on only from the
187
+ next read; a process the table shows, unrecorded, under a parent that
188
+ exited or changed during the read is remembered until it is seen gone, and
189
+ the directories are kept while it is there; and the app log copy's credit
190
+ is charged back when a directory is kept after all, with the excess over
191
+ the output bound's allowance reported.
192
+ - `atelier obsidian`, the Obsidian maintenance service and its login item take
193
+ `--personal-home DIR` instead of `--project`, and then follow the generation
194
+ last confirmed in that private home of a personal workspace. The head of the
195
+ selection history is read, that generation is loaded (composed in a worker
196
+ for the service), and the head is read again; a head that moved refuses
197
+ `personal-selection-changed`. Nothing confirmed publishes nothing, each with
198
+ its own code (`nothing-selected`, `stale-generation`,
199
+ `selection-history-corrupt`, `personal-home-unavailable`, or the module's own
200
+ code for a home that is gone), and nothing falls back to another project.
201
+ The service locates its workspace from the home alone through a new
202
+ `locateProject` option, so it starts whatever the selection; a service given
203
+ only a loader that answers a promise is still refused at start. The engine
204
+ observes the selection's record and the next one, so a confirmation or a
205
+ history cut short is loaded at the next tick, and reads the history again at
206
+ every full reconciliation. `status` reports the confirmed generation, and
207
+ nothing here confirms one. Who may see a bound vault is not decided: it stays
208
+ the machine's audience setting, none by default. `readPersonalSelectionHead`
209
+ is added to `@mnstry/atelier/personal-workspace`, and the selection history is
210
+ read without waiting on a record that is not a regular file. Without
211
+ `--personal-home` nothing changes.
212
+ - The desktop acceptance procedures (`scripts/obsidian/desktop-receipts.mjs`,
213
+ maintainer tooling that is not shipped) interrupt AP-03's service only
214
+ after a healthy status, and only through the handle of the service process
215
+ the run started; any other number is refused and the step fails. A launch
216
+ is refused unless the instance's HOME lies inside a layout root the run
217
+ made and is not the user's own home, however it is reached. In the
218
+ small-fixture run, cleanup reads the process table until a read records
219
+ nothing new before its first signal, and the run records how many
220
+ processes one command-line call becomes. The event-loop benchmark
221
+ (`scripts/obsidian/benchmark-event-loop.mjs`) signals its child's process
222
+ group only while it still holds the child.
223
+
224
+ - AP-03 reports a refused interruption without losing its failure evidence.
225
+ Separately, small-fixture cleanup remembers a child observed under a run-owned
226
+ process that exited or changed during the process-table read, then remembers
227
+ descendants of those children. It retains its temporary roots while those
228
+ remembered processes remain. It also reserves estimated time for SIGTERM
229
+ grace after reading the process tree.
230
+ - AP-03 test cleanup runs before temporary-workspace removal. It joins children
231
+ through retained handles even when the service record is missing or malformed
232
+ or graceful stop fails. Unheld launcher services use the existing forced-stop
233
+ fallback, which rechecks healthy runtime identity before signalling the PID.
234
+ A held child that does not exit within the cleanup bound fails the test.
235
+
236
+ ## 0.2.0-alpha.13
237
+
238
+ - Add the public Knowledge Health workshop on the existing local Knowledge
239
+ host: original wording, separate interpretation and four distinct responses;
240
+ optional Review in a separate session; a selected-draft copy-only handoff
241
+ retained with its original receipt. Exact retries do not append duplicates,
242
+ and reopening after restart reads the same proposal. The source owner edits
243
+ through ordinary repository tooling and reassesses; no browser source-apply
244
+ endpoint is added. Include the installed workshop kit and receiving guidance.
245
+ - `atelier knowledge semantic` exposes the internal semantic operation runner
246
+ (`docs/semantic-operation.md`) as eleven operations: `begin`, `status`,
247
+ `reconcile`, `complete`, `proposals`, `contribution`, `relation`, `record`,
248
+ `cascade`, `context` and `project`. Each reads one JSON object
249
+ `{workspaceId, run, request}` from stdin, at most 256 KiB, in the workspace
250
+ `atelier ingest` uses. Each operation accepts exactly its documented request
251
+ fields, each of a declared kind; an unknown or missing field, a null
252
+ required field or a value of the wrong kind refuses as
253
+ `SEMANTIC_OPERATION_INVALID` before any store is opened, so nothing is
254
+ written. Formats such as timestamps are checked by the runner. Atelier calls no model: the host supplies its raw output, candidates
255
+ and usage (`null` when unknown), and interpretations stay pending until
256
+ receiver records, which are caller assertions, accept them. Failures print
257
+ `{ok:false, code, error}` with the runner's own `SEMANTIC_*` code,
258
+ `SEMANTIC_OPERATION_INTERRUPTED` for an uncoded error, or
259
+ `SEMANTIC_OPERATION_REFUSED` for Atelier's other refusals; `recorded` or
260
+ `captured` details are included whenever the runner attached them. No package export
261
+ or schema changes.
262
+
263
+ ## Unreleased
264
+
265
+ - Patch the fast-uri dependency and override from 3.1.7 to 3.1.8, the patched
266
+ 3.x release for GHSA-hrr3-gc8f-f4qj (3.1.7 is in the affected range; whether
267
+ Atelier's use was exploitable is not established). The direct dependency
268
+ keeps packed consumers on one deduplicated copy: Ajv's own `^3.0.1` range
269
+ resolves to it, so a bare consumer installs 3.1.8 only.
270
+ - Personal workspaces gain an explicit selection record, a read-only inventory of
271
+ the private home, and a restore of authored inputs from an earlier generation:
272
+ `selectPersonalGeneration`, `selectionConfirmDigest`, `readPersonalSelection`,
273
+ `inventoryPersonalHome`, `planPersonalRestore` and `restorePersonalInputs`. A
274
+ selection is a confirmed, hash-chained choice of the eligible generation. A
275
+ restore accepts only a plan from `planPersonalRestore`, re-checks the exact
276
+ current bytes, keeps them, and never widens enrollment or bindings:
277
+ re-admitting a withdrawn repository, a changed repository identity, or a
278
+ re-added binding refuses before any write. Each file is replaced by
279
+ compare-and-swap, so a write that replaces or recreates the file by path
280
+ during the restore is kept and the restore refuses; an interrupted swap
281
+ refuses `restore-interrupted` until the listed moved copy is put back.
282
+ Authored inputs, generations and records are never deleted; only temporary
283
+ files are removed.
284
+ - A private-domain repository owner can let one named operator pass the local
285
+ boundary actor check by signing a delegation
286
+ (`docs/repo-boundary-guard.md`). It covers only `atelier boundary check` and
287
+ the `pre-commit` path, for listed repositories, for at most 90 days. It never
288
+ changes ownership, audiences, paths, content rules, promotion, push-content
289
+ checks or publication. It applies only when all of these hold:
290
+ - its ed25519 signature verifies against the owner's key in the host file
291
+ `/etc/atelier/boundary-owner-keys.json`, owned by root in root-owned
292
+ directories (Windows is not supported yet);
293
+ - it is current and not revoked in that file;
294
+ - the whole boundary policy, the managed repository set and each repository's
295
+ root commit match what the owner signed.
296
+
297
+ It records consent for a cooperating operator; the actor check stays
298
+ attribution, not authentication. Delegations live in
299
+ `boundary-delegations.v1.json` beside the policy, under the new
300
+ `atelier-boundary-delegations@v1` and `atelier-boundary-owner-keys@v1`
301
+ contracts; the boundary policy contract is unchanged.
302
+ `atelier boundary delegation draft|sign|verify` prepares, signs (after
303
+ recomputing the bindings) and inspects them. The policy validator now accepts
304
+ the `contractVersion` and `ext` members its schema already declared; `ext` is
305
+ ignored.
306
+ - A capability operation that has committed no longer reports `EEXIST` ("not
307
+ entered") when its lock is removed or replaced while cleanup inspects it.
308
+ Cleanup preserves the other file and returns the operation's result. Lock
309
+ races in reclamation, readback and cleanup are each covered by a test.
310
+ - `src/judgment/practice.mjs` and `src/judgment/practice-evaluation.mjs` keep a
311
+ reusable decision practice inside an ordinary Knowledge contribution
312
+ (`docs/decision-practices.md`). They are internal: the
313
+ `atelier.decision-practice/v0` format is experimental, not a registered public
314
+ contract, and has no package export, CLI command, adoption store, scheduler or
315
+ model route. A definition is prepared as a captured contribution for the
316
+ existing Knowledge review path, and is read as adopted only from an exact
317
+ contribution digest with a current accepted review and activation in the
318
+ supplied history. `evaluateDecisionPractice` returns `proceed`, `stop`,
319
+ `escalate` or `refuse` with a typed reason from declared prerequisites, count
320
+ budgets, exact current evidence and an existing decision request and result.
321
+ It calls no provider, and an abstention escalates. A proceeding outcome
322
+ prepares an unaccepted reconsideration draft; nothing is appended, accepted or
323
+ activated by the module. Inputs are bounded to a portable profile, and a
324
+ larger history refuses `practice-input-exceeds-bounds`. The instruction
325
+ adoption command `atelier practice` is a separate concept.
326
+ `atelier architecture entry practical-judgment` lists both modules.
327
+ - `src/ingestion/semantic.mjs` prepares source-bound entity and assertion
328
+ proposals from a host's extractor output, one source per input
329
+ (`docs/semantic-ingestion.md`). It is an internal module: its `v0` formats are
330
+ not public contracts, and it has no package export or CLI command. The host
331
+ must already hold whole-plan read permission, which the module does not grant,
332
+ and chooses and runs its extractor. The module makes no provider call, durable
333
+ write or graph change, and claims no extraction quality. `readSemanticProposals`
334
+ gives a search view that rereads the cited evidence. Proposals and identity
335
+ mappings stay pending and carry no authority: identity, semantic acceptance and
336
+ activation remain separate decisions of the existing knowledge review owner, and
337
+ this release maps nothing into knowledge review or activation records.
338
+ `atelier architecture entry knowledge-stewardship` lists the module.
339
+ - A personal workspace bound to the Obsidian projection is served from the
340
+ canonical build, with the composition's link-target rule and the engine's file
341
+ cache. A graph is used only under a validity key the composition confirmed.
342
+ Its inputs are read before the composition runs. The engine, and the
343
+ proposal adapter it runs, compose in a worker with a two-minute deadline: at
344
+ load (`loadBoundProjectOffThread`), after a change, and at every full
345
+ reconciliation, which prepares nothing again when nothing changed. A bound
346
+ project is loaded once. Authored and generation files the key reads are
347
+ opened without following links or waiting on them. The adapter builds only
348
+ when it looks at a newly observed edit. The proposal adapter answers a vault edit to a private
349
+ note with `personal-overlay-not-proposed`, and `personal-binding-lost` now
350
+ names the reserved settings key.
351
+
352
+ - Evidence navigation is exported as `@mnstry/atelier/evidence-navigation`
353
+ (the pure contract checks and currency assessments) and
354
+ `@mnstry/atelier/evidence-navigation/local` (the Node local reader, kept
355
+ separate), with its schema at
356
+ `@mnstry/atelier/contracts/atelier-evidence-navigation.v1.schema.json`. The
357
+ schema and its fixtures join the contract corpus. There is no CLI command:
358
+ search and get need a host to construct the reader with its exact plan,
359
+ workspace and current whole-plan admission, and Atelier ships no issuer of that
360
+ authority.
361
+ - The Obsidian projection has one route for a personal workspace. A binding
362
+ names a private home and a generation explicitly. Every caller that builds
363
+ the graph (the engine, view counts, source apply, the proposal adapter and the
364
+ selection operation) then reads the composed graph, which composition checks
365
+ again at every build. The overlay's saved views become scopes, plus an
366
+ `everything` view. Composition refusals keep their codes, at load and at
367
+ every build, and no view is current under one. The engine observes the
368
+ person's manifest and overlay, so a generation that stops holding is refused
369
+ at the next tick. A copy of a bound project that lost its binding is refused.
370
+ `view add`, `audience` and `location` refuse on a bound project and write
371
+ nothing, and a vault edit to a private note is refused, never applied. A
372
+ theme is never written, and coverage is passed through unread. No command or
373
+ service binds a personal workspace yet.
374
+
375
+ - The knowledge workspace states its supported interfaces
376
+ (`docs/knowledge-workspace.md`).
377
+ - Two outputs are versioned contracts: the context packet
378
+ (`atelier-knowledge-context@v1`) and the evaluation report
379
+ (`atelier-knowledge-evaluation@v1`).
380
+ - The other CLI outputs, the browser routes and the sidecar's `knowledgeProject`
381
+ option are experimental.
382
+ - The workspace modules have no library export. `@mnstry/atelier/knowledge`
383
+ keeps its existing exports.
384
+ - `atelier architecture entry knowledge-stewardship` lists the workspace modules
385
+ and the `knowledge` command.
386
+ - `npm run knowledge:consumer-proof` installs a packed tarball into a clean
387
+ consumer and checks the documented CLI paths, writing a receipt bound to the
388
+ tarball SHA-256.
389
+ - Personal workspaces are exported as `@mnstry/atelier/personal-workspace`,
390
+ with their manifest and overlay schemas under `@mnstry/atelier/contracts/`. The
391
+ public API is these nine exports: `MANIFEST_SCHEMA`, `OVERLAY_SCHEMA`,
392
+ `PersonalWorkspaceRefusal`, `loadPersonalManifest`, `loadPersonalOverlay`,
393
+ `resolvePersonalWorkspace`, `planPersonalGeneration`,
394
+ `materializePersonalGeneration` and `composePersonalWorkspace`. The composition
395
+ is manifest-only, with enforcement `none`: filesystem access, disclosure,
396
+ effects and the host sandbox are reported as uncovered, and no consent or
397
+ effect enforcement is claimed. The manifest and overlay schemas join the
398
+ contract corpus.
399
+
400
+ - The ingestion store adds `getEvidence`, which returns one exact evidence span
401
+ after rechecking only that source and its stored attempt. Query and
402
+ `getEvidence` both report `readScope: "all-plan"`: they read at the scope of
403
+ the whole plan and grant or narrow no permission.
404
+ - Preserve workspace template lineage during profile adoption and updates.
405
+ Keep profile identity in its typed adoption manifest, and refuse saved plans
406
+ that replace the workspace lineage before installing any managed content.
407
+ - Verify exact upgrades from a real 0.2.0-alpha.12 lock as well as the
408
+ alpha.10 lock, and check that the upgraded lock records the installed version.
409
+ - A long-lived reader of verified history (learning and ingestion stores) no
410
+ longer wedges after one refused read; it replays from a clean copy.
411
+ - Ingestion reads take no lock and bind no workspace identity; only `plan`
412
+ binds it, so reads work during a run and a mistyped id is not recorded.
413
+ - Inquiry graph proposals label each file, and the proposal, with the most
414
+ restrictive audience of the sources whose material they carry.
415
+ - Coordination reports every dependency cycle regardless of record order, and a
416
+ superseded directive stays superseded when its replacement goes stale.
417
+ - Reflective and coaching acts require Reflection, an assessment and a request
418
+ whatever their origin.
419
+ - The responsibility commands print only their own refusals; Node, git and
420
+ parser errors go through the typed-code rule and never show paths or input.
421
+
422
+ - Preserve the bundled readiness pack's immutable v1 content and digest so
423
+ previous release locks can use both exact upgrade participants without a
424
+ separate lock rewrite. Keep Discovery Harness naming in the architecture
425
+ catalog; retain Discovery Engine in the persisted readiness pack. Add a
426
+ real alpha.10 lock fixture, plan/application regressions and digest refusal
427
+ controls.
428
+
429
+ - Add portable template profiles, digest-bound project bindings, staged structural
430
+ validation and canonical read-only presentation through installed package APIs.
431
+ - Add explicit local template adoption and updates through the existing exact-plan
432
+ upgrade engine, preserving source, local customization and adoption history.
433
+ - Reuse Git placement checks within synchronous ingestion read operations;
434
+ recheck at operation boundaries and around writes without caching source bytes
435
+ or integrity verdicts.
436
+
437
+ - Preserve recorded Trackable calendar resolutions across host timezone-data changes; retain verified-chain export when legacy replay cannot reconstruct state.
438
+
439
+ - Correct unchanged instruction re-adoption and preserve literal replacement text during revisions; add recovery and neighboring-slot regressions.
440
+ - Recover recognized dead capability operation locks without requiring an adoption journal; preserve live, uncertain and replacement owners.
441
+ - Add portable Trackable definitions, shared preview/runtime rules, durable scoped reference storage and correction.
442
+ - Add evidence-qualified Reflection, one-authority Interaction delivery, and bounded cross-repository Coordination views.
443
+
444
+ - Reconcile eight responsibility names and typed consumer bindings; preserve historical aliases.
445
+ - Connect durable ingestion to source-current knowledge context and graph proposals.
446
+ - Add situated judgment and native ADR adapters, capability feedback, and recoverable scoped instruction adoption.
447
+ - Include a provider-agnostic research starter and Practical Judgment operating skill.
448
+
449
+ - 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.
450
+
451
+ - Add local Discovery and Research Harnesses with versioned inquiry records,
452
+ portable research handoffs, reproducible basic belief calculations, evidence
453
+ dependence and withdrawal checks, and reviewable graph proposals. Add separate
454
+ capability packages and version-bound Skill Steward feedback. Rename the
455
+ discovery workflow through the architecture catalog while retaining the
456
+ bundled readiness pack's persisted title, identifiers and digest.
457
+ - Add an experimental progressive local ingestion runner with exact plans,
458
+ bounded deterministic text/CSV/JSON extraction, immutable intake reuse,
459
+ resumable attempt accounting and source-verified lexical queries. Add a
460
+ JSON stdin CLI and structural evaluation that retains missing cases and
461
+ unknown costs. No model dispatch, automatic semantic acceptance or native
462
+ desktop admission is provided by the portable runner.
463
+
464
+ - Add a portable local learning lifecycle: Evidence, proposals, exact decisions,
465
+ explicit harness activation, withdrawal and retained history. Include a JSON
466
+ stdin CLI, private graph/export projections, bounded proposal-assistance
467
+ adapters and compatibility with existing skill observations. Local actor
468
+ assertions do not authenticate users; check artifacts remain inert and hosts
469
+ retain execution and access authority.
470
+
471
+ - Recompile cached JSON Schema validators when caller-owned schemas change; preserve unchanged-schema reuse and fresh compilation for non-JSON schemas.
472
+
473
+ ### Added
474
+
475
+ - 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.
476
+
477
+ - A `knowledge-workspace` starter, mirrored `atelier-knowledge-setup` agent
478
+ skills, and `atelier knowledge check|context|evaluate`: question-led ontology
479
+ coverage, complete source context within an exact byte budget, and a lexical
480
+ versus graph comparison with source-digest and directed-relation checks.
481
+ Local operator output carries no expression or execution permission. Token
482
+ estimates remain distinct from measured usage and accepted work.
483
+
484
+ - `atelier enroll documents [--audience private] [--dry-run] [--json]` writes
485
+ a minimal `<file>.kg.json` sidecar next to every `.html`, `.pdf` and
486
+ `.docx` document the knowledge graph reads that has none, so an adopted
487
+ vault with attachments, a static website or a folder of documents can pass
488
+ `atelier graph` without hand-written sidecars. Each sidecar carries the
489
+ document's title, the domain, lifecycle and status the graph infers, the id
490
+ `<repo>:asset:<path>` (with a short digest when two paths fold to one id)
491
+ and the audience `private`. `--audience` picks another, which the
492
+ repository's boundary policy must allow; a refusal is typed
493
+ (`enroll-audience-not-allowed`) and names the allowed audiences before
494
+ anything is written. An existing sidecar, including one Git ignores or a
495
+ link with the sidecar's name, is never changed, and sources are never
496
+ changed. See `docs/install.md`.
497
+ - `atelier adopt --enroll-documents [--audience AUDIENCE]` adopts and enrolls
498
+ in one step, checking the audience against the policy before adoption
499
+ writes anything.
500
+ - A login item keeps a workspace's vaults fresh after you log in:
501
+ `atelier obsidian service unit --install [--consent-actor ID]
502
+ [--adapter=obsidian-cli]` installs a launchd agent on macOS
503
+ (`~/Library/LaunchAgents/ai.mnstry.atelier.<project>.<workspace-id>.plist`)
504
+ or a systemd user unit on Linux
505
+ (`~/.config/systemd/user/atelier-obsidian-<workspace-id>.service`), after
506
+ recording a consent that covers startup (`--consent-actor ID`; at a
507
+ terminal, the actor already recorded or else the account's name). A
508
+ service of an earlier release still running is stopped just before the
509
+ unit is loaded, so the unit's first start runs the installed release.
510
+ `service unit --remove` lowers the consent to the service alone, removes
511
+ the item and starts the service again at once for this session only;
512
+ `service unit --print` shows what `--install` writes. The answer is
513
+ remembered as the machine settings' `loginItem` decision (`on`, `off`), and
514
+ `atelier obsidian settings` names these commands as the way to change it. The unit runs the package installed in the project,
515
+ by its path, with the Node that installed it (its real path), the search
516
+ path you had (absolute, non-temporary entries), in `/`, and names the data
517
+ root the workspace was resolved under and the workspace
518
+ (`--data-root`, `--workspace-id`), so the service at login finds that
519
+ workspace whatever its manager's environment carries, and records a refusal
520
+ there when the project no longer leads to it. launchd: `Standard`
521
+ process type, `RunAtLoad`, `KeepAlive` `SuccessfulExit` false,
522
+ `ThrottleInterval` 60, `ExitTimeOut` 60, output to
523
+ `state/service/login-item.log`. From `npx` without a package installed in
524
+ the project it refuses (`login-item-needs-installed-package`); Windows is not
525
+ offered (`startup-platform-unqualified`); without a user systemd the answer
526
+ is `login-item-unavailable`. The installed item is recorded in
527
+ `state/service/login-item.json` (`atelier-obsidian-login-item/v1`).
528
+ - Once a login item is installed, `service start`, `open` and the replacement
529
+ of an outdated service start the service through launchd or systemd
530
+ (`kickstart -p`, `systemctl --user start`) instead of as a child, and accept
531
+ the service that proves itself with the entry the item runs. A unit that
532
+ differs from what would be written now is written again and reloaded, and
533
+ `open` says `login item refreshed`. An item switched off in System Settings
534
+ or with `systemctl --user disable` is not forced: it is neither written
535
+ again nor started through its manager, and the service is started for that
536
+ command only.
537
+ - A service started by a login item (`--startup`) keeps its own bounded
538
+ `service.log`, exits 0 on a refusal as well, so it is not restarted every
539
+ minute, and records how its start ended in `state/service/last-startup.json`
540
+ (`atelier-obsidian-last-startup/v1`); `status` shows the login item and
541
+ `the login item did not start the service: <code>` with the next step. After
542
+ each tick it compares its package on disk with the release it started with
543
+ (file status first, then a digest of `src/`, `contracts/` and `plugins/`
544
+ and the version) and exits 75 after the tick when it changed, which its
545
+ manager restarts on the new release.
546
+ - `atelier obsidian uninstall` removes the login item and stops the proven
547
+ service, and starts nothing. Vaults, private state, the project file and
548
+ Obsidian's vault list are kept, and it prints where each is.
549
+ - `readReleaseIdentity({ root })` reads a package's release identity now,
550
+ uncached; `releaseIdentity()` stays its cached form.
551
+ - The production service manager refuses under the Node test runner
552
+ (`real-login-item-under-test`) and when HOME is not the account's own home
553
+ directory (`login-item-home-mismatch`), since launchd and systemd register a
554
+ unit in the account's real session whatever HOME says.
555
+ - `atelier obsidian open` gets through the Obsidian states it used to stop
556
+ at. For an Obsidian that is installed and never started (no
557
+ `obsidian.json`), and only while the process table shows that no Obsidian
558
+ runs, it creates the settings file with the view's vault flagged open and
559
+ the command line on, exclusively (a file the app wrote first is kept), in a
560
+ settings folder made private to you when it is missing; Obsidian then opens
561
+ the vault at a plain start (`registration.how: created-settings`). Whenever
562
+ it writes Obsidian's vault list with the app quit, it also turns the
563
+ command line on (`cli: true`) in the same guarded write, with the backup of
564
+ the file as it was; a listed vault whose switch is off is written for the
565
+ switch alone. With `--restart-obsidian`, a running Obsidian that cannot be
566
+ reached (its command line off, or no vault open and the view's vault not in
567
+ its list) is quit with SIGTERM to its proven main process only, the vault
568
+ and the switch are written once it has gone, and it is started again
569
+ plainly, reopening the vaults it had open (macOS only). Without the flag,
570
+ those states answer `app-cli-unavailable` / `cli-turned-off` and
571
+ `app-version-unsupported` / `no-vault-open`, naming it. The flag is never
572
+ implied and every other operation refuses it. Every write and the restart
573
+ are shown in the answer (`obsidianSettings`, `restart`). Before any signal,
574
+ `open` checks, reading only, that the write can succeed (otherwise it
575
+ answers that refusal and leaves Obsidian running; an Obsidian at its
576
+ starter window with no `obsidian.json` yet is the create case) and, right
577
+ before the first signal, keeps a copy of `obsidian.json` that the same
578
+ run's write does not prune. On macOS the main process can stay after the first
579
+ SIGTERM, with its windows closed; Electron handles only the first SIGTERM as
580
+ a quit, and a second one ends the process at once, without its quit
581
+ handlers. `open` sends that second one only when the same process has
582
+ stayed alone, with no window or helper, at two readings at least 5 seconds
583
+ apart; never a third, and never another kind. `atelier obsidian --help` names every option of the
584
+ command, `--wait-ms` included. See "What `open` does in each state of
585
+ Obsidian" in `docs/obsidian.md` and "Obsidian's vault list" in
586
+ `docs/obsidian-contract.md`.
587
+ - Views can be declared without editing JSON:
588
+ `atelier obsidian view add ID (--all | --folder PATH [--folder PATH ...] [--repo R] | --tag T) [--expand DEPTH:MAX] [--default]`
589
+ adds a view to `atelier.project.json` (and `.atelier-local/` to
590
+ `.gitignore` when that folder is not ignored), and never commits. It shows
591
+ the change as a diff and how many notes the view would show on this machine,
592
+ with how many of the notes it selects are withheld for carrying no
593
+ classification or an audience that is not admitted. A view that would show
594
+ no note is refused with `view-would-be-empty` unless `--allow-empty`. A
595
+ person at a terminal is asked before anything is written (`--yes` answers
596
+ beforehand; no answer within 10 minutes writes nothing); for anyone else the
597
+ command is the consent. The file is rewritten only when it is in the form
598
+ Atelier writes JSON in, so the change is the view and nothing else
599
+ (`project-config-format-unknown` names the member to add by hand
600
+ otherwise), atomically, keeping its mode, and only over the bytes it read
601
+ (`project-config-changed`). A file that is not UTF-8 is never rewritten
602
+ (`gitignore-not-utf8`, or `project-config-format-unknown`). Every new text
603
+ is written and synced to disk before any file is replaced; a failure after
604
+ that says which files changed (`project-files-partly-written`), and no
605
+ temporary file is left beside them. The first view is the default. `view list` and
606
+ `view show ID` are `scope list` and `scope show ID`.
607
+
608
+ ### Changed
609
+
610
+ - Where a workspace's vaults live can be decided, and a visible folder can
611
+ hold them: `atelier obsidian location set DIR` (`~/Atelier`, say) records
612
+ the `location` decision. Each view not published yet is then given its own
613
+ folder there at its first publication, `<project> (<view>)`, which is also
614
+ the vault's name in Obsidian (`harbor-notes (everything)`; a number inside the
615
+ parentheses when that name is taken on the disk or by a vault the app lists).
616
+ The folder is created exclusively and private to this user, and its
617
+ allocation is recorded once in the workspace's private state
618
+ (`atelier-obsidian-vault-allocation/v1`, `state/allocations/<view>.json`,
619
+ with the folder's real path, device and inode, which the maintenance service
620
+ checks at every tick and the publisher before it writes, before each note
621
+ and before its commit: another folder put
622
+ where the one made was is not published into, `vault-allocation-replaced`,
623
+ nor is the same folder reached through a link put on the way since,
624
+ `vault-allocation-moved`; on Linux a folder made after the original was
625
+ removed can be given its inode number, see Known limits in
626
+ `docs/obsidian.md`. A folder that has gone is made again by the next tick,
627
+ only where its recorded real path leads and only where a location would be
628
+ accepted: never inside a repository, the project, the private state, a vault
629
+ Atelier publishes or one the app lists; a vault removed, moved or replaced
630
+ while it was being published stops that publication (`vault-root-moved` for
631
+ a vault under the data root), and the running service, without a restart,
632
+ publishes into it again once it is put back or made again: at once, or, for
633
+ a folder made again after a publication stopped just before its commit, at
634
+ the next change at its sources (`vault-note-missing` until then). A published view whose vault cannot
635
+ be found (its record was lost, or a view published under the data root lost
636
+ its `vaults/<view>` folder, which was made again before) is refused,
637
+ `vault-allocation-lost`, never published again into a new, empty vault;
638
+ `status` and `open` name the way back),
639
+ which the recovery store reads: the engine, source apply, the proposal
640
+ adapter, `open` and the plugin's service paths (its hello, the person's
641
+ choice to turn it off, drift) all find the same vault. So does
642
+ `viewVaultRoot` of `@mnstry/atelier/obsidian`, which answers the allocated
643
+ folder now, and may refuse, typed (a record that cannot be read, or was
644
+ lost); pass the workspace id as its third argument: without it the name of
645
+ the workspace's private-state folder is taken as the id, as before, and a
646
+ record that does not match it is refused. A vault published before stays
647
+ under the data root, and a workspace that decides nothing publishes there as
648
+ before. A folder inside a repository or the project, inside a vault Atelier
649
+ publishes or one the app lists, or on another volume than the data root is
650
+ refused, through links and in any letter case; a synced one needs
651
+ `--allow-synced-location`; a macOS-protected one is warned about. The app's
652
+ list is read through the app when it answers, else from its settings file;
653
+ while it cannot be read, no folder is allocated (`app-vault-list-unreadable`,
654
+ tried again at the next tick). A view whose folder cannot be allocated is not published
655
+ and its freshness says why, while the other views go on: a folder that
656
+ cannot be made (`vault-location-unusable`: a file in the way, no
657
+ permission), one inside Atelier's private state
658
+ (`vault-location-inside-private-state`, refused by `location set` too), an
659
+ allocation record that cannot be read or names a folder inside a
660
+ repository, each stops its own view only. `location show`
661
+ and `status` (`scopes[].vault`) say where each view's vault is, or why it
662
+ cannot be read. Consent to a synced folder is not recorded, so it is not
663
+ checked again when a folder is allocated or made again; a link on the way is
664
+ followed only at a view's first allocation (Known limits).
665
+ - A vault that is only yours shows the notes that carry no classification:
666
+ `atelier obsidian audience set me` now records `unclassified: shown` with
667
+ "only you", and every path that builds a view (the engine, source apply,
668
+ the proposal adapter, `selection`) admits them through one rule,
669
+ `eligibilityFor`. A list of audiences never shows them, even one that names
670
+ every audience "only you" stands for. Such a note is shown only when its
671
+ bytes read as a note the way the emitter reads every note, so a file that
672
+ cannot be published stays withheld instead of stopping the vault. Deciding
673
+ it changes the eligibility revision, so every view is rebuilt at the next
674
+ tick. A decision recorded as "only you" with them withheld keeps them
675
+ withheld until `audience set me` is run again. `view add` counts what a
676
+ view would show the same way, as "only you" while nobody decided. Since
677
+ the maintenance service publishes no note until someone decides who may
678
+ see, `view add` then names `atelier obsidian audience set me` as the next
679
+ step, before `open`; and a view refused as empty because no audience is
680
+ admitted (`audience clear`) is told to decide who may see, not to classify
681
+ notes. A note whose labels cannot be known is never shown: front matter
682
+ Atelier cannot read, or a top-level `kg` key that is not a block, may say
683
+ `sensitive`.
684
+ - A view's first publication into its allocated folder no longer waits for an
685
+ Obsidian that runs and cannot be coordinated with (a vault open, its command
686
+ line off, no vault open, or a version below the floor). While the app's own
687
+ settings file names neither the folder, a folder above it nor one inside it
688
+ (read, not guessed: a missing or unreadable file, an entry with a `..`
689
+ segment, or a Flatpak or snap build, gives no such evidence), the publisher fills the vault in its own process by
690
+ creating files only (journal `mode: 'direct-unheld'`). Anything that would
691
+ replace or remove a file, or write a settings file over one that is there,
692
+ refuses as `editor-uncoordinated` and writes nothing. The evidence is read
693
+ again before the first file and every two seconds, and once it is gone
694
+ nothing more is written or committed. A run that completes is committed
695
+ before `open` adds the vault to Obsidian and opens it. A run that stops
696
+ partway commits nothing: the list names the folder meanwhile, a settings
697
+ file with other bytes is already there, or an interrupted run left a
698
+ replacement or a removal. The view then falls back to the coordinated path,
699
+ so `open` may add the vault to Obsidian and open it before it is complete,
700
+ and the rest, every replacement and removal included, is published through
701
+ the app with its usual checks. While the app does not qualify, a run stopped
702
+ that way reports the app's own refusal (`app-cli-unavailable`, say), and
703
+ `open` answers it without adding the vault unless asked to restart
704
+ Obsidian; with the app running and no vault open, a vault the app already
705
+ lists is still opened by its path, as before. The plugin's entry written this way counts as offered until the
706
+ plugin says hello. A later generation, a vault under the data root, and
707
+ every other case publish and refuse as before.
708
+ - The Obsidian machine settings of a workspace remember what a person decided
709
+ once, so no later run has to ask again or be told again: who may see the
710
+ vaults, where they live, whether maintenance starts at login, and that the
711
+ installed app may be reached. The document is now
712
+ `atelier-obsidian-machine-settings/v2`, with a closed `decisions` member,
713
+ one entry per decision (`audience`, `location`, `loginItem`, `adapter`),
714
+ each null until decided and otherwise stamped with when, by whom when known,
715
+ and how (`question`, `command`, `defaults`, `v1`). The audience decision
716
+ also says whether notes that carry no classification are `shown` or
717
+ `withheld`: only an "only you" decision may show them, and every decision
718
+ made today withholds them. A v1 document is read as the v2 document it
719
+ stands for and stays v1 on disk until the next write, which writes v2; an
720
+ audience list set before is carried over as that person's decision, with
721
+ unclassified notes withheld as they were. A release up to 0.2.0-alpha.12 refuses a v2 document
722
+ (`invalid-machine-settings`), so after an upgrade a maintenance service
723
+ still running the earlier release fails its ticks until it is replaced:
724
+ `atelier obsidian open` and `service start` replace it. `atelier obsidian settings` shows what is remembered and
725
+ how each answer is changed; `status` carries the decisions and a one-line
726
+ summary.
727
+ - `--adapter=obsidian-cli` is needed once per workspace. Given to `open` or
728
+ `service start` of an enabled project, it is remembered before anything
729
+ starts, and later runs of the real command-line entry reach the app without
730
+ it (`service unit --print` too). A remembered adapter is never used under
731
+ the Node test runner (`remembered-adapter-under-test`), and never by a
732
+ caller that passes its own seams; the decision is one pure rule,
733
+ `selectAdapter`.
734
+ - The first start of the maintenance service records who allowed it: still
735
+ `--consent-actor ID`, or now, for a person at a terminal, the name of the
736
+ account the command runs as, which the command says it recorded. A person
737
+ is at a terminal when standard input and output are both terminals and
738
+ nothing says otherwise: `--json`, the new `--no-input`, a `CI` environment
739
+ or `ATELIER_NONINTERACTIVE=1` mean nobody is (`isInteractive`). A consent
740
+ recorded already is never replaced by a derived one, and a program still
741
+ names its actor.
742
+ - `atelier obsidian audience set me` admits "only you": every audience of a
743
+ note (`public`, `team`, `operator`, `staff`, `private`) except `sensitive`,
744
+ which a vault takes only when it is named (`audience set me,sensitive`).
745
+ Any other list is the person's own; either is remembered as their decision.
746
+ Notes without a classification are still withheld from every vault,
747
+ "only you" included; a later change lets an "only you" vault show them.
748
+
749
+ - `setup.include` and `setup.exclude` in `atelier.project.json` now scope
750
+ what the knowledge graph reads. `adopt --include` and `--exclude` recorded
751
+ them, and the `monorepo` profile required `--include`, but nothing read
752
+ them, so a tracked build folder could not be left out and every tracked
753
+ page needed a sidecar. Each is a path pattern relative to the project
754
+ config's folder, in the boundary policy's `forbiddenPaths` dialect; a path
755
+ outside the scope is treated exactly like a Git-ignored one, and a sidecar
756
+ follows its source. A project that already sets either field gets a graph
757
+ over that scope from this release: run `atelier graph` and commit the
758
+ result. Both values must now be relative (the contract's `pathString`), and
759
+ `adopt` no longer writes them as `null`. The decision is recorded in
760
+ `docs/install.md`.
761
+ - `atelier graph` ends its error list with a `Next:` line naming
762
+ `atelier enroll documents` when a document has no sidecar.
763
+ - `service unit --print` prints the unit `--install` writes: on macOS under
764
+ the label `ai.mnstry.atelier.<project>.<workspace-id>`, with process type
765
+ `Standard` instead of `Background`, the search path, `WorkingDirectory` `/`
766
+ and output to `login-item.log` instead of `service.log`; on Linux with
767
+ `Environment="PATH=…"`, `WorkingDirectory=/` and `TimeoutStopSec=60`.
768
+ `buildStartupAdapter` takes `searchPath`, and its working directory is `/`
769
+ unless one is given. A service records the path it was started by beside its
770
+ real path (`executable.ext.invokedAs`), and the busy proof accepts a process
771
+ table that names the entry through it.
772
+ - Whether a running maintenance service is of an earlier, the same or a
773
+ later release is measured against the entry that would be started: its
774
+ digest and the release of the package that entry's path names, read now.
775
+ With a login item that is the project's own package, whatever package the
776
+ command runs from, and a re-pointed link or `file:` install is read where
777
+ it leads.
778
+
779
+ ### Fixed
780
+
781
+ - `atelier obsidian open` with a view the maintenance service did not publish
782
+ because Obsidian's command line is off now answers `app-cli-unavailable` /
783
+ `cli-turned-off` with its next step, instead of the view's own
784
+ `not-prepared` or `stale-readable`: such a view counts as one the app kept
785
+ from publication, which `open` publishes once the app holds the vault.
786
+ - `atelier obsidian service start` replaces a maintenance service of an
787
+ earlier release still running after an upgrade, as `open` does (stopped
788
+ through its own listener, the installed release started under the consent
789
+ already recorded, `replaced: 'outdated'`), instead of answering that it is
790
+ already running while that service fails every tick on the new machine
791
+ settings. A service of a later release is left running (`release:
792
+ 'later'`).
793
+ - `atelier obsidian open` no longer answers `app-cli-unavailable` /
794
+ `vault-open-cli-silent` on the first silent round after it launched the
795
+ vault. A version only Atelier's plugin gave, with no answer for the vault,
796
+ now has to be seen in two rounds in a row: one version call that timed out
797
+ while Obsidian was busy opening its window made `open` report a command
798
+ line that was only slow as switched off. A wait that ends right after one
799
+ such round still gives that answer, not `launch-failed`.
800
+ - A view kept `current` while a plugin file it pins waits for Obsidian (a
801
+ drifted `data.json`, say, while the app cannot be coordinated with) now
802
+ says so. Its reason is `verified-by-read-back-plugin-waits-for-app`
803
+ instead of the `verified-by-read-back` of a view whose plugin files are all
804
+ there, and `status` and `open` add `plugin files wait for the app` to the
805
+ plugin line, with a next step (`files: "waits-for-app"` and `next` on
806
+ `plugin` in `--json`). A drift that publishing would only leave for the
807
+ person again (the data file of a vault root that is a link or not private,
808
+ a folder where a file goes) is no longer a reason to publish a committed
809
+ generation again, so it never waits for the app and never gets that
810
+ reason; the path is left as it is (nothing names it in `status` yet, and
811
+ the plugin shows as not present).
812
+ - A view held because a plugin file (`plugin-file-changed`) or a settings
813
+ file (`settings-changed`) changed while it was published, by another
814
+ program or by the person, is still `publisher-conflict`, but its next step
815
+ no longer tells the person to close another publisher: it names the file
816
+ that stopped the publication and says that the view is retried
817
+ automatically.
818
+ - A plugin-file drift that publishing cannot repair (the data file of a vault
819
+ root that is a link, say) was published twice whenever the maintenance
820
+ service started: once by the start's own tick and once more when the
821
+ service first compared the plugin files with the disk, or when that tick's
822
+ publication changed the pinned files. What that publication could not
823
+ change (a file as pinned, or one that holds what it held before the tick
824
+ under the same pin and vault root) is now taken as seen, and such a drift
825
+ is no longer a reason to publish a committed generation again, so asking
826
+ about it at most once more writes no vault file. A plugin file another
827
+ writer removes or changes after the publication, even during the same tick
828
+ (brought back to its old bytes after a publication that changed its pin,
829
+ say), unless it holds again what it held before the tick under the same
830
+ pin and vault root, and a path the person repairs before the tick ends,
831
+ are still written at the next tick.
832
+ - `atelier obsidian open` with Obsidian quit and the view's vault already in
833
+ Obsidian's list but closed: Obsidian started plainly does not reopen such a
834
+ vault, so a link it refused just after starting left `open` to wait and
835
+ answer `launch-failed` / `app-did-not-answer-for-this-vault`. `open` now
836
+ hands the link once more to the Obsidian that now runs, through its
837
+ command-line tool only (never the operating system, since this `open`
838
+ started it), before it answers that. A vault the list flags open is not
839
+ asked twice.
840
+ - `atelier obsidian --help` lists `plugin show | on` and `policy digest`, which
841
+ 0.2.0-alpha.12 ships but left out of that help (the operations themselves
842
+ worked, and `atelier obsidian help` showed them). A test now fails when a
843
+ built-in obsidian operation is missing from it.
844
+ - The project readiness artifact (`atelier-output/atelier-readiness.json` by
845
+ default) records `graph.path`, `projection.outputRoot` and
846
+ `projection.entry` relative to the project configuration directory, in POSIX
847
+ form, instead of as absolute paths. `atelier readiness --check` and
848
+ `atelier generated check` now accept an artifact written in another checkout
849
+ of the same project, and the artifact no longer names the machine's
850
+ directories (which could include the account name). An exact upgrade
851
+ candidate's readiness bytes now match what `atelier readiness` regenerates
852
+ there; before, when the path to the candidate passed through a symlink (as
853
+ macOS temporary directories do), the check reported the new candidate
854
+ stale. `atelier upgrade explain` no longer warns that readiness bytes can
855
+ contain absolute host paths. An artifact written by an earlier version is
856
+ reported stale once; run `atelier readiness` to rewrite it and review the
857
+ difference.
858
+ - `atelier dev` run before `atelier build` (straight after `atelier init`,
859
+ for example) printed Node's raw `[ENOENT] ... lstat '<absolute path>'`
860
+ with no next step, and after `atelier graph` alone a redacted
861
+ `[internal-error]`. Both are now `projection-output-missing`, naming the
862
+ output folder relative to the project config (never as an absolute path)
863
+ and the next step: run `atelier graph`, then `atelier build`, with the same
864
+ `--project` path. `atelier dev --help` (and `server --help`) now documents
865
+ `--port=PORT`, the `PORT` variable, the 8137 default, and `--review`.
866
+ - The CLI printed any error that carried a string code verbatim, so Node's own
867
+ errors (`ENOENT`, `EACCES`, `ERR_*`) reached the terminal with the absolute
868
+ path Node puts in their message, no next step, and exit 2. Only Atelier's
869
+ typed codes (lowercase words joined by hyphens) are now printed verbatim.
870
+ Any other error is `[internal-error]` with exit 1, naming only Node's code
871
+ and system call, for example `(ENOENT from lstat)`. `ATELIER_DEBUG=1` still
872
+ prints the full error.
873
+ - Obsidian source apply could reject with an untyped `ELEAFCHANGED` error. This
874
+ happened when another program renamed a new file over the source while the
875
+ published note was being prepared again, between the look at the path and its
876
+ open. That is a source being written: the apply now refuses `stale-source`
877
+ (cause `changed-while-reading`) and writes nothing. A preparation that fails
878
+ for any tolerated reason is no longer kept for its scope and generation; only
879
+ one that succeeded is reused.
880
+ - Obsidian source apply answers three more races with another program typed.
881
+ An enrolled source removed while apply builds the graph used to reject with
882
+ an untyped `ENOENT`; it now refuses `corpus-unreadable`, with the system code
883
+ as the cause, and writes nothing. When a publication replaced the pointer to
884
+ the current manifest during an apply, the read used to reject with an untyped
885
+ `ELEAFCHANGED`. The pointer is now read again, up to five times, and one that
886
+ keeps changing refuses `manifest-unavailable` (cause `changed-while-reading`).
887
+ A source replaced while the published note is prepared again now leads to a
888
+ fresh preparation, up to three in all. If the source was saved with the same
889
+ bytes, or another source of the scope was replaced, the edit applies instead
890
+ of refusing `published-note-unavailable`. Observation of pending edits on a
891
+ tick had the same gap: a source replaced while its note was prepared again
892
+ raised an untyped `ELEAFCHANGED` from the tick. It now refuses that edit
893
+ `stale-source` when its own source bytes changed, and otherwise refuses
894
+ `published-note-unavailable`. The failed preparation is no longer kept, so the
895
+ other edits of that generation in the tick are still observed.
896
+
3
897
  ## 0.2.0-alpha.12
4
898
 
5
899
  ### Added