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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (560) hide show
  1. package/CHANGELOG.md +1005 -0
  2. package/README.md +149 -9
  3. package/contracts/atelier-adoption-policy.v2.schema.json +55 -0
  4. package/contracts/atelier-architecture.v1.schema.json +258 -0
  5. package/contracts/atelier-boundary-delegations.v1.schema.json +161 -0
  6. package/contracts/atelier-boundary-owner-keys.v1.schema.json +98 -0
  7. package/contracts/atelier-build.v1.schema.json +1076 -0
  8. package/contracts/atelier-capability.v1.schema.json +1252 -0
  9. package/contracts/atelier-coordination.v1.schema.json +1050 -0
  10. package/contracts/atelier-evidence-navigation.v1.schema.json +603 -0
  11. package/contracts/atelier-harness.v1.schema.json +234 -0
  12. package/contracts/atelier-ingestion.v1.schema.json +806 -0
  13. package/contracts/atelier-inquiry.v1.schema.json +1772 -0
  14. package/contracts/atelier-instruction-adoption.v1.schema.json +490 -0
  15. package/contracts/atelier-interaction.v1.schema.json +553 -0
  16. package/contracts/atelier-judgment.v1.schema.json +690 -0
  17. package/contracts/atelier-knowledge.v1.schema.json +1512 -0
  18. package/contracts/atelier-learning.v1.schema.json +1095 -0
  19. package/contracts/atelier-migration.v3.schema.json +64 -0
  20. package/contracts/atelier-obsidian-generation-manifest.v2.schema.json +372 -0
  21. package/contracts/atelier-personal-workspace-manifest.v1.schema.json +87 -0
  22. package/contracts/atelier-personal-workspace-overlay.v1.schema.json +299 -0
  23. package/contracts/atelier-template-adoption.v1.schema.json +223 -0
  24. package/contracts/atelier-template-profile.v1.schema.json +1168 -0
  25. package/contracts/atelier-trackable.v1.schema.json +781 -0
  26. package/contracts/atelier-upgrade-plan.v3.schema.json +532 -0
  27. package/contracts/compat-baseline.json +1 -1
  28. package/docs/architecture.md +89 -0
  29. package/docs/assurance-controls.md +4 -3
  30. package/docs/blocks/capability-stewardship.md +17 -0
  31. package/docs/blocks/claims.md +16 -3
  32. package/docs/blocks/inquiry-harnesses.md +19 -0
  33. package/docs/blocks/learning-harnesses.md +17 -0
  34. package/docs/capability-stewardship.md +269 -0
  35. package/docs/coordination.md +51 -0
  36. package/docs/decision-practices.md +111 -0
  37. package/docs/decisions.md +29 -0
  38. package/docs/evidence-navigation.md +237 -0
  39. package/docs/exact-upgrades.md +3 -2
  40. package/docs/ingestion.md +181 -0
  41. package/docs/inquiry-harnesses.md +211 -0
  42. package/docs/install.md +80 -3
  43. package/docs/intake-and-guides.md +5 -0
  44. package/docs/integration-contract-decisions.md +24 -2
  45. package/docs/interaction-and-reflection.md +72 -0
  46. package/docs/knowledge-graph.md +20 -0
  47. package/docs/knowledge-health/api.md +30 -0
  48. package/docs/knowledge-health/assessment/api.md +96 -0
  49. package/docs/knowledge-health/assessment/capabilities.md +40 -0
  50. package/docs/knowledge-health/assessment/evaluation.md +27 -0
  51. package/docs/knowledge-health/assessment/facilitator.md +30 -0
  52. package/docs/knowledge-health/assessment/quickstart.md +61 -0
  53. package/docs/knowledge-health/assessment/troubleshooting.md +23 -0
  54. package/docs/knowledge-health/devday/facilitator.md +16 -0
  55. package/docs/knowledge-health/devday/participant-response.md +22 -0
  56. package/docs/knowledge-health/devday/public-default.md +107 -0
  57. package/docs/knowledge-health/devday/quickstart.md +18 -0
  58. package/docs/knowledge-health/devday/support.md +22 -0
  59. package/docs/knowledge-health/exercise.md +17 -0
  60. package/docs/knowledge-health/facilitator.md +20 -0
  61. package/docs/knowledge-health/quickstart.md +94 -0
  62. package/docs/knowledge-health/readme.md +15 -0
  63. package/docs/knowledge-health/support.md +34 -0
  64. package/docs/knowledge-setup.md +248 -0
  65. package/docs/knowledge-workspace.md +264 -0
  66. package/docs/learning-harnesses.md +238 -0
  67. package/docs/learning.md +215 -0
  68. package/docs/local-services.md +242 -26
  69. package/docs/obsidian-contract.md +878 -36
  70. package/docs/obsidian-plugin.md +619 -0
  71. package/docs/obsidian.md +809 -64
  72. package/docs/optional-ingestion.md +83 -0
  73. package/docs/personal-workspace.md +257 -0
  74. package/docs/practical-judgment.md +92 -0
  75. package/docs/progressive-ingestion-acceptance.md +89 -0
  76. package/docs/progressive-ingestion.md +235 -0
  77. package/docs/project-command-inventory.md +1 -0
  78. package/docs/release-engineering.md +56 -1
  79. package/docs/repo-boundary-guard.md +94 -0
  80. package/docs/research-starter-quickstart.md +66 -0
  81. package/docs/research-starter.md +114 -0
  82. package/docs/semantic-ingestion.md +198 -0
  83. package/docs/semantic-operation.md +317 -0
  84. package/docs/skill-steward.md +6 -0
  85. package/docs/template-profile.md +164 -0
  86. package/docs/template-upgrades.md +114 -0
  87. package/docs/trackables.md +111 -0
  88. package/docs/upgrade.md +68 -3
  89. package/fixtures/atelier-architecture/binding/invalid/document.json +19 -0
  90. package/fixtures/atelier-architecture/binding/valid/document.json +19 -0
  91. package/fixtures/atelier-architecture/catalog/invalid/document.json +290 -0
  92. package/fixtures/atelier-architecture/catalog/valid/document.json +343 -0
  93. package/fixtures/atelier-build-contract/attempt/invalid/document.json +20 -0
  94. package/fixtures/atelier-build-contract/attempt/valid/document.json +19 -0
  95. package/fixtures/atelier-build-contract/candidate/invalid/document.json +24 -0
  96. package/fixtures/atelier-build-contract/candidate/valid/document.json +23 -0
  97. package/fixtures/atelier-build-contract/decision/invalid/document.json +31 -0
  98. package/fixtures/atelier-build-contract/decision/valid/document.json +30 -0
  99. package/fixtures/atelier-build-contract/delivery/invalid/document.json +18 -0
  100. package/fixtures/atelier-build-contract/delivery/valid/document.json +17 -0
  101. package/fixtures/atelier-build-contract/gate/invalid/document.json +22 -0
  102. package/fixtures/atelier-build-contract/gate/valid/document.json +21 -0
  103. package/fixtures/atelier-build-contract/ledger/invalid/document.json +270 -0
  104. package/fixtures/atelier-build-contract/ledger/valid/document.json +269 -0
  105. package/fixtures/atelier-build-contract/objective/invalid/document.json +73 -0
  106. package/fixtures/atelier-build-contract/objective/valid/document.json +72 -0
  107. package/fixtures/atelier-build-contract/progress/invalid/document.json +18 -0
  108. package/fixtures/atelier-build-contract/progress/valid/document.json +17 -0
  109. package/fixtures/atelier-capability-contract/adoption/invalid/document.json +71 -0
  110. package/fixtures/atelier-capability-contract/adoption/valid/document.json +70 -0
  111. package/fixtures/atelier-capability-contract/event/invalid/document.json +18 -0
  112. package/fixtures/atelier-capability-contract/event/valid/document.json +17 -0
  113. package/fixtures/atelier-capability-contract/journal/invalid/document.json +382 -0
  114. package/fixtures/atelier-capability-contract/journal/valid/document.json +381 -0
  115. package/fixtures/atelier-capability-contract/notice/invalid/document.json +8 -0
  116. package/fixtures/atelier-capability-contract/notice/valid/document.json +7 -0
  117. package/fixtures/atelier-capability-contract/package/invalid/document.json +59 -0
  118. package/fixtures/atelier-capability-contract/package/valid/document.json +58 -0
  119. package/fixtures/atelier-capability-contract/plan/invalid/document.json +107 -0
  120. package/fixtures/atelier-capability-contract/plan/valid/document.json +106 -0
  121. package/fixtures/atelier-capability-contract/release/invalid/document.json +85 -0
  122. package/fixtures/atelier-capability-contract/release/valid/document.json +84 -0
  123. package/fixtures/atelier-capability-contract/state/invalid/document.json +316 -0
  124. package/fixtures/atelier-capability-contract/state/valid/document.json +315 -0
  125. package/fixtures/atelier-coordination/dependency/invalid/document.json +37 -0
  126. package/fixtures/atelier-coordination/dependency/valid/document.json +36 -0
  127. package/fixtures/atelier-coordination/directive/invalid/document.json +25 -0
  128. package/fixtures/atelier-coordination/directive/valid/document.json +24 -0
  129. package/fixtures/atelier-coordination/disposition/invalid/document.json +34 -0
  130. package/fixtures/atelier-coordination/disposition/valid/document.json +33 -0
  131. package/fixtures/atelier-coordination/outcome/invalid/document.json +39 -0
  132. package/fixtures/atelier-coordination/outcome/valid/document.json +38 -0
  133. package/fixtures/atelier-coordination/recovery/invalid/document.json +34 -0
  134. package/fixtures/atelier-coordination/recovery/valid/document.json +33 -0
  135. package/fixtures/atelier-harness-contract/handoff/invalid/document.json +25 -0
  136. package/fixtures/atelier-harness-contract/handoff/valid/document.json +24 -0
  137. package/fixtures/atelier-ingestion/invalid/authority.json +19 -0
  138. package/fixtures/atelier-ingestion/semantic-baseline.json +26 -0
  139. package/fixtures/atelier-ingestion/semantic-operation.json +75 -0
  140. package/fixtures/atelier-ingestion/valid/plan-input.json +18 -0
  141. package/fixtures/atelier-inquiry-contract/assessment/invalid/document.json +41 -0
  142. package/fixtures/atelier-inquiry-contract/assessment/valid/document.json +40 -0
  143. package/fixtures/atelier-inquiry-contract/bundle/invalid/document.json +51 -0
  144. package/fixtures/atelier-inquiry-contract/bundle/valid/document.json +50 -0
  145. package/fixtures/atelier-inquiry-contract/campaign/invalid/document.json +17 -0
  146. package/fixtures/atelier-inquiry-contract/campaign/valid/document.json +16 -0
  147. package/fixtures/atelier-inquiry-contract/decision/invalid/document.json +22 -0
  148. package/fixtures/atelier-inquiry-contract/decision/valid/document.json +21 -0
  149. package/fixtures/atelier-inquiry-contract/feedback/invalid/document.json +19 -0
  150. package/fixtures/atelier-inquiry-contract/feedback/valid/document.json +18 -0
  151. package/fixtures/atelier-inquiry-contract/handoff/invalid/document.json +92 -0
  152. package/fixtures/atelier-inquiry-contract/handoff/valid/document.json +91 -0
  153. package/fixtures/atelier-inquiry-contract/hypothesis/invalid/document.json +20 -0
  154. package/fixtures/atelier-inquiry-contract/hypothesis/valid/document.json +19 -0
  155. package/fixtures/atelier-inquiry-contract/ledger/invalid/document.json +680 -0
  156. package/fixtures/atelier-inquiry-contract/ledger/valid/document.json +679 -0
  157. package/fixtures/atelier-inquiry-contract/legacy-assessment/invalid/document.json +19 -0
  158. package/fixtures/atelier-inquiry-contract/legacy-assessment/valid/document.json +18 -0
  159. package/fixtures/atelier-inquiry-contract/request/invalid/document.json +50 -0
  160. package/fixtures/atelier-inquiry-contract/request/valid/document.json +49 -0
  161. package/fixtures/atelier-inquiry-contract/source/invalid/document.json +18 -0
  162. package/fixtures/atelier-inquiry-contract/source/valid/document.json +17 -0
  163. package/fixtures/atelier-inquiry-contract/withdrawal/invalid/document.json +16 -0
  164. package/fixtures/atelier-inquiry-contract/withdrawal/valid/document.json +15 -0
  165. package/fixtures/atelier-instruction-adoption/context-receipt/invalid/document.json +18 -0
  166. package/fixtures/atelier-instruction-adoption/context-receipt/valid/document.json +17 -0
  167. package/fixtures/atelier-instruction-adoption/plan/invalid/document.json +63 -0
  168. package/fixtures/atelier-instruction-adoption/plan/valid/document.json +62 -0
  169. package/fixtures/atelier-instruction-adoption/receipt/invalid/document.json +22 -0
  170. package/fixtures/atelier-instruction-adoption/receipt/valid/document.json +21 -0
  171. package/fixtures/atelier-instruction-adoption/state/invalid/document.json +30 -0
  172. package/fixtures/atelier-instruction-adoption/state/valid/document.json +29 -0
  173. package/fixtures/atelier-interaction/act/invalid/document.json +25 -0
  174. package/fixtures/atelier-interaction/act/valid/document.json +24 -0
  175. package/fixtures/atelier-interaction/assessment/invalid/document.json +32 -0
  176. package/fixtures/atelier-interaction/assessment/valid/document.json +31 -0
  177. package/fixtures/atelier-interaction/observation/invalid/document.json +22 -0
  178. package/fixtures/atelier-interaction/observation/valid/document.json +21 -0
  179. package/fixtures/atelier-interaction/policy/invalid/document.json +20 -0
  180. package/fixtures/atelier-interaction/policy/valid/document.json +19 -0
  181. package/fixtures/atelier-judgment/case/invalid/document.json +76 -0
  182. package/fixtures/atelier-judgment/case/valid/document.json +75 -0
  183. package/fixtures/atelier-judgment/decision/invalid/document.json +38 -0
  184. package/fixtures/atelier-judgment/decision/valid/document.json +37 -0
  185. package/fixtures/atelier-judgment/native-decision.md +3 -0
  186. package/fixtures/atelier-judgment/practice-reconsideration/definition.json +92 -0
  187. package/fixtures/atelier-judgment/practice-reconsideration/scenario.json +435 -0
  188. package/fixtures/atelier-knowledge-contract/activation/invalid/document.json +26 -0
  189. package/fixtures/atelier-knowledge-contract/activation/valid/document.json +25 -0
  190. package/fixtures/atelier-knowledge-contract/contribution/invalid/document.json +34 -0
  191. package/fixtures/atelier-knowledge-contract/contribution/valid/document.json +33 -0
  192. package/fixtures/atelier-knowledge-contract/domain/invalid/document.json +41 -0
  193. package/fixtures/atelier-knowledge-contract/domain/valid/document.json +40 -0
  194. package/fixtures/atelier-knowledge-contract/domain-revision/invalid/document.json +46 -0
  195. package/fixtures/atelier-knowledge-contract/domain-revision/valid/document.json +45 -0
  196. package/fixtures/atelier-knowledge-contract/evaluation/invalid/document.json +21 -0
  197. package/fixtures/atelier-knowledge-contract/evaluation/valid/document.json +20 -0
  198. package/fixtures/atelier-knowledge-contract/ledger/invalid/document.json +318 -0
  199. package/fixtures/atelier-knowledge-contract/ledger/valid/document.json +317 -0
  200. package/fixtures/atelier-knowledge-contract/relation/invalid/document.json +25 -0
  201. package/fixtures/atelier-knowledge-contract/relation/valid/document.json +24 -0
  202. package/fixtures/atelier-knowledge-contract/review/invalid/document.json +18 -0
  203. package/fixtures/atelier-knowledge-contract/review/valid/document.json +17 -0
  204. package/fixtures/atelier-knowledge-contract/withdrawal/invalid/document.json +16 -0
  205. package/fixtures/atelier-knowledge-contract/withdrawal/valid/document.json +15 -0
  206. package/fixtures/atelier-learning/invalid/authority.json +14 -0
  207. package/fixtures/atelier-learning/valid/capture.json +13 -0
  208. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/authority-key.json +17 -0
  209. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/nonempty-ext.json +25 -0
  210. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/wrong-schema.json +22 -0
  211. package/fixtures/atelier-personal-workspace-contract/manifest/valid/manifest.json +22 -0
  212. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/authority-key.json +25 -0
  213. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/unknown-top-level-field.json +27 -0
  214. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/wrong-schema.json +24 -0
  215. package/fixtures/atelier-trackable/definition/invalid/document.json +15 -0
  216. package/fixtures/atelier-trackable/definition/valid/document.json +14 -0
  217. package/fixtures/atelier-trackable/request/invalid/document.json +23 -0
  218. package/fixtures/atelier-trackable/request/valid/document.json +22 -0
  219. package/fixtures/boundary-delegations/invalid/authority-key.v1.json +30 -0
  220. package/fixtures/boundary-delegations/invalid/push-operation.v1.json +28 -0
  221. package/fixtures/boundary-delegations/invalid/unsigned.v1.json +25 -0
  222. package/fixtures/boundary-delegations/valid/empty.v1.json +4 -0
  223. package/fixtures/boundary-delegations/valid/signed-operator.v1.json +30 -0
  224. package/fixtures/boundary-owner-keys/invalid/wrong-algorithm.v1.json +15 -0
  225. package/fixtures/boundary-owner-keys/invalid/wrong-curve.v1.json +15 -0
  226. package/fixtures/boundary-owner-keys/valid/one-owner.v1.json +17 -0
  227. package/fixtures/capability-packages/adoption.example.json +70 -0
  228. package/fixtures/capability-packages/evidence-review/capability-package.json +58 -0
  229. package/fixtures/capability-packages/evidence-review/capability-release.json +84 -0
  230. package/fixtures/capability-packages/evidence-review/evaluation.md +15 -0
  231. package/fixtures/capability-packages/evidence-review/skills/evidence-review/SKILL.md +22 -0
  232. package/fixtures/capability-packages/evidence-review/skills/evidence-review/references/ledger.md +7 -0
  233. package/fixtures/capability-packages/research/capability-package.json +88 -0
  234. package/fixtures/capability-packages/research/capability-release.json +134 -0
  235. package/fixtures/capability-packages/research/evaluation.md +15 -0
  236. package/fixtures/capability-packages/research/skills/research-integrate/SKILL.md +29 -0
  237. package/fixtures/capability-packages/research/skills/research-integrate/references/integration.md +10 -0
  238. package/fixtures/capability-packages/research/skills/research-plan/SKILL.md +27 -0
  239. package/fixtures/capability-packages/research/skills/research-plan/references/inquiries.md +26 -0
  240. package/fixtures/capability-packages/research/skills/research-synthesize/SKILL.md +23 -0
  241. package/fixtures/capability-packages/research/skills/research-synthesize/references/synthesis.md +12 -0
  242. package/fixtures/evidence-navigation/invalid/duplicate-operation.json +16 -0
  243. package/fixtures/evidence-navigation/invalid/instruction-kind.json +36 -0
  244. package/fixtures/evidence-navigation/invalid/invalid-digest.json +36 -0
  245. package/fixtures/evidence-navigation/invalid/invalid-time.json +36 -0
  246. package/fixtures/evidence-navigation/invalid/missing-attribution.json +35 -0
  247. package/fixtures/evidence-navigation/invalid/reserved-extension.json +19 -0
  248. package/fixtures/evidence-navigation/invalid/unattributed-acceptance.json +36 -0
  249. package/fixtures/evidence-navigation/invalid/uncoerced-version.json +16 -0
  250. package/fixtures/evidence-navigation/invalid/unknown-currency.json +17 -0
  251. package/fixtures/evidence-navigation/invalid/unknown-selector-field.json +37 -0
  252. package/fixtures/evidence-navigation/invalid/unsupported-operation.json +15 -0
  253. package/fixtures/evidence-navigation/valid/claim.json +36 -0
  254. package/fixtures/evidence-navigation/valid/host.json +16 -0
  255. package/fixtures/evidence-navigation/valid/profile.json +16 -0
  256. package/fixtures/evidence-navigation/valid/snapshot.json +17 -0
  257. package/fixtures/harness-packages/build-harness/capability-package.json +61 -0
  258. package/fixtures/harness-packages/build-harness/capability-release.json +82 -0
  259. package/fixtures/harness-packages/build-harness/evaluation.md +3 -0
  260. package/fixtures/harness-packages/build-harness/skills/atelier-build-harness/SKILL.md +59 -0
  261. package/fixtures/harness-packages/knowledge-harness/capability-package.json +61 -0
  262. package/fixtures/harness-packages/knowledge-harness/capability-release.json +82 -0
  263. package/fixtures/harness-packages/knowledge-harness/evaluation.md +3 -0
  264. package/fixtures/harness-packages/knowledge-harness/skills/atelier-knowledge-harness/SKILL.md +60 -0
  265. package/fixtures/harnesses/learning-cycle.json +780 -0
  266. package/fixtures/inquiry/workshop.json +675 -0
  267. package/fixtures/inquiry-packages/discovery-harness/capability-package.json +61 -0
  268. package/fixtures/inquiry-packages/discovery-harness/capability-release.json +82 -0
  269. package/fixtures/inquiry-packages/discovery-harness/evaluation.md +3 -0
  270. package/fixtures/inquiry-packages/discovery-harness/skills/atelier-discovery-harness/SKILL.md +48 -0
  271. package/fixtures/inquiry-packages/research-harness/capability-package.json +61 -0
  272. package/fixtures/inquiry-packages/research-harness/capability-release.json +82 -0
  273. package/fixtures/inquiry-packages/research-harness/evaluation.md +3 -0
  274. package/fixtures/inquiry-packages/research-harness/skills/atelier-research-harness/SKILL.md +43 -0
  275. package/fixtures/knowledge-health/calibration-suite.json +26 -0
  276. package/fixtures/knowledge-health/calibration-trial.json +37 -0
  277. package/fixtures/knowledge-health/corrected/checklist.md +18 -0
  278. package/fixtures/knowledge-health/devday/participant-record.json +19 -0
  279. package/fixtures/knowledge-health/expected-summary.json +27 -0
  280. package/fixtures/knowledge-health/workshop/README.md +20 -0
  281. package/fixtures/knowledge-health/workshop/atelier.project.json +7 -0
  282. package/fixtures/knowledge-health/workshop/knowledge-plan.json +65 -0
  283. package/fixtures/knowledge-health/workshop/records/checklist.md +18 -0
  284. package/fixtures/knowledge-health/workshop/records/workshop.md +18 -0
  285. package/fixtures/knowledge-health/workshop/repo-access.v1.json +5 -0
  286. package/fixtures/knowledge-health/workspace/atelier.project.json +18 -0
  287. package/fixtures/knowledge-health/workspace/knowledge-plan.json +74 -0
  288. package/fixtures/knowledge-health/workspace/records/checklist.md +18 -0
  289. package/fixtures/knowledge-health/workspace/records/pilot.md +16 -0
  290. package/fixtures/knowledge-health/workspace/repo-access.v1.json +9 -0
  291. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/case-only-collision.v2.json +160 -0
  292. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/flat-note-path.v2.json +160 -0
  293. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/hidden-folder.v2.json +160 -0
  294. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/identity-in-the-body.v2.json +160 -0
  295. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/link-breaking-name.v2.json +160 -0
  296. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/missing-identity-region.v2.json +156 -0
  297. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/missing-layout-version.v2.json +159 -0
  298. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/note-named-like-a-folder.v2.json +160 -0
  299. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/unknown-region-kind.v2.json +160 -0
  300. package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/v1-contract-version.v2.json +161 -0
  301. package/fixtures/obsidian/contracts/generation-manifest-v2/valid/three-notes.v2.json +160 -0
  302. package/fixtures/obsidian/edits/workspace.json +1 -1
  303. package/fixtures/obsidian/materialization/expected-full.json +21 -21
  304. package/fixtures/obsidian/materialization/expected-full.layout-1.json +99 -0
  305. package/fixtures/obsidian/materialization/expected-scoped.json +7 -7
  306. package/fixtures/obsidian/materialization/expected-scoped.layout-1.json +39 -0
  307. package/fixtures/personal-workspace/overlay.json +24 -0
  308. package/fixtures/templates/local-library.v1.json +75 -0
  309. package/fixtures/templates/upgrade-contracts/adoption-policy.v2/invalid.json +16 -0
  310. package/fixtures/templates/upgrade-contracts/adoption-policy.v2/valid.json +13 -0
  311. package/fixtures/templates/upgrade-contracts/migration.v3/invalid.json +24 -0
  312. package/fixtures/templates/upgrade-contracts/migration.v3/valid.json +21 -0
  313. package/fixtures/templates/upgrade-contracts/template-adoption.v1/invalid.json +60 -0
  314. package/fixtures/templates/upgrade-contracts/template-adoption.v1/valid.json +57 -0
  315. package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/invalid.json +85 -0
  316. package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/valid.json +82 -0
  317. package/package.json +64 -6
  318. package/plugins/obsidian/main.js +444 -0
  319. package/plugins/obsidian/manifest.json +9 -0
  320. package/plugins/obsidian/styles.css +22 -0
  321. package/skills/claude/atelier-build-harness/SKILL.md +59 -0
  322. package/skills/claude/atelier-coordination/SKILL.md +32 -0
  323. package/skills/claude/atelier-discovery-harness/SKILL.md +48 -0
  324. package/skills/claude/atelier-guided-upgrade/SKILL.md +29 -0
  325. package/skills/claude/atelier-interaction/SKILL.md +34 -0
  326. package/skills/claude/atelier-knowledge-harness/SKILL.md +60 -0
  327. package/skills/claude/atelier-knowledge-setup/SKILL.md +72 -0
  328. package/skills/claude/atelier-practical-judgment/SKILL.md +64 -0
  329. package/skills/claude/atelier-research-harness/SKILL.md +43 -0
  330. package/skills/claude/atelier-skill-steward/SKILL.md +53 -0
  331. package/skills/claude/atelier-trackables/SKILL.md +40 -0
  332. package/skills/codex/atelier-build-harness/SKILL.md +59 -0
  333. package/skills/codex/atelier-coordination/SKILL.md +32 -0
  334. package/skills/codex/atelier-discovery-harness/SKILL.md +48 -0
  335. package/skills/codex/atelier-guided-upgrade/SKILL.md +29 -0
  336. package/skills/codex/atelier-interaction/SKILL.md +34 -0
  337. package/skills/codex/atelier-knowledge-harness/SKILL.md +60 -0
  338. package/skills/codex/atelier-knowledge-setup/SKILL.md +72 -0
  339. package/skills/codex/atelier-practical-judgment/SKILL.md +64 -0
  340. package/skills/codex/atelier-research-harness/SKILL.md +43 -0
  341. package/skills/codex/atelier-skill-steward/SKILL.md +53 -0
  342. package/skills/codex/atelier-trackables/SKILL.md +40 -0
  343. package/src/architecture/catalog.mjs +355 -0
  344. package/src/architecture/index.mjs +93 -0
  345. package/src/boundary/content-rules.mjs +4 -2
  346. package/src/boundary/delegation-command.mjs +158 -0
  347. package/src/boundary/delegation.mjs +396 -0
  348. package/src/boundary/policy.mjs +52 -10
  349. package/src/build/git.mjs +18 -0
  350. package/src/build/index.mjs +3 -0
  351. package/src/build/ledger.mjs +88 -0
  352. package/src/capabilities/adoption.mjs +381 -0
  353. package/src/capabilities/evidence.mjs +140 -0
  354. package/src/capabilities/files.mjs +124 -0
  355. package/src/capabilities/index.mjs +4 -0
  356. package/src/capabilities/instructions.mjs +250 -0
  357. package/src/capabilities/package.mjs +136 -0
  358. package/src/cli/command-failure.mjs +36 -0
  359. package/src/cli/execute-command.mjs +16 -2
  360. package/src/cli/run.mjs +65 -9
  361. package/src/coauthor/store.mjs +43 -2
  362. package/src/collaboration/proposals.mjs +189 -0
  363. package/src/commands/architecture.mjs +27 -0
  364. package/src/commands/boundary.mjs +3 -0
  365. package/src/commands/capability.mjs +73 -0
  366. package/src/commands/enroll.mjs +3 -0
  367. package/src/commands/harness.mjs +79 -0
  368. package/src/commands/ingest.mjs +39 -0
  369. package/src/commands/init.mjs +4 -1
  370. package/src/commands/inquiry.mjs +66 -0
  371. package/src/commands/knowledge-semantic.mjs +128 -0
  372. package/src/commands/knowledge.mjs +119 -0
  373. package/src/commands/learn.mjs +61 -0
  374. package/src/commands/obsidian.mjs +832 -62
  375. package/src/commands/practice.mjs +24 -0
  376. package/src/commands/setup.mjs +22 -2
  377. package/src/commands/trackable.mjs +19 -0
  378. package/src/contracts/corpus.mjs +36 -0
  379. package/src/coordination/index.mjs +110 -0
  380. package/src/egress/forbidden-egress.mjs +2 -0
  381. package/src/evidence-navigation/contracts.mjs +60 -0
  382. package/src/evidence-navigation/evaluate.mjs +69 -0
  383. package/src/evidence-navigation/generation.mjs +22 -0
  384. package/src/evidence-navigation/index.mjs +2 -0
  385. package/src/evidence-navigation/local.mjs +167 -0
  386. package/src/evidence-navigation/schema.generated.mjs +604 -0
  387. package/src/evidence-navigation/types.mjs +12 -0
  388. package/src/export/atelier-export-contract.mjs +35 -8
  389. package/src/graph/enroll.mjs +248 -0
  390. package/src/graph/graph.mjs +17 -1
  391. package/src/graph/knowledge-graph.mjs +58 -8
  392. package/src/harnesses/contracts.mjs +41 -0
  393. package/src/harnesses/exchange.mjs +154 -0
  394. package/src/harnesses/feedback.mjs +16 -0
  395. package/src/harnesses/history.mjs +37 -0
  396. package/src/harnesses/index.mjs +4 -0
  397. package/src/harnesses/store.mjs +29 -0
  398. package/src/ingestion/contracts.mjs +41 -0
  399. package/src/ingestion/evaluation.mjs +119 -0
  400. package/src/ingestion/optional/composition/index.mjs +171 -0
  401. package/src/ingestion/optional/evaluation/index.mjs +219 -0
  402. package/src/ingestion/optional/graphify/composition-binding.mjs +60 -0
  403. package/src/ingestion/optional/graphify/composition_receiving.py +185 -0
  404. package/src/ingestion/optional/graphify/graphify_supplier.py +933 -0
  405. package/src/ingestion/optional/graphify/json_bridge.py +163 -0
  406. package/src/ingestion/optional/graphify/query_receiving.py +209 -0
  407. package/src/ingestion/optional/index.mjs +9 -0
  408. package/src/ingestion/optional/jev/bridge.mjs +166 -0
  409. package/src/ingestion/optional/jev/composition-binding.mjs +116 -0
  410. package/src/ingestion/optional/jev/judgments.mjs +174 -0
  411. package/src/ingestion/optional/jev/native-translation.mjs +32 -0
  412. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/__init__.py +7 -0
  413. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/adapter.py +966 -0
  414. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/artifacts.py +101 -0
  415. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/projection.py +146 -0
  416. package/src/ingestion/optional/lightrag/composition-binding.mjs +67 -0
  417. package/src/ingestion/optional/vanilla/composition-binding.mjs +102 -0
  418. package/src/ingestion/optional/vanilla/index.mjs +218 -0
  419. package/src/ingestion/optional/vanilla/native-normalization.mjs +187 -0
  420. package/src/ingestion/processors.mjs +218 -0
  421. package/src/ingestion/semantic.mjs +203 -0
  422. package/src/ingestion/store.mjs +372 -0
  423. package/src/inquiry/beliefs.mjs +32 -0
  424. package/src/inquiry/contracts.mjs +23 -0
  425. package/src/inquiry/index.mjs +5 -0
  426. package/src/inquiry/ledger.mjs +135 -0
  427. package/src/inquiry/lenses.mjs +15 -0
  428. package/src/inquiry/projection.mjs +77 -0
  429. package/src/inquiry/store.mjs +35 -0
  430. package/src/intake/read-scope.mjs +12 -0
  431. package/src/intake/store.mjs +69 -6
  432. package/src/interaction/index.mjs +91 -0
  433. package/src/judgment/index.mjs +82 -0
  434. package/src/judgment/practice-evaluation.mjs +70 -0
  435. package/src/judgment/practice.mjs +144 -0
  436. package/src/knowledge/context.mjs +217 -0
  437. package/src/knowledge/index.mjs +5 -0
  438. package/src/knowledge/ingestion.mjs +79 -0
  439. package/src/knowledge/intake.mjs +33 -0
  440. package/src/knowledge/ledger.mjs +110 -0
  441. package/src/knowledge/participatory/guidance.mjs +36 -0
  442. package/src/knowledge/participatory/guided-contribution.mjs +44 -0
  443. package/src/knowledge/participatory/index.mjs +2 -0
  444. package/src/knowledge/participatory/installed-workshop.mjs +108 -0
  445. package/src/knowledge/plan.mjs +67 -0
  446. package/src/knowledge/projection.mjs +43 -0
  447. package/src/knowledge/semantic-operation.mjs +567 -0
  448. package/src/knowledge/sessions.mjs +467 -0
  449. package/src/knowledge/workspace.mjs +295 -0
  450. package/src/knowledge-health/assessment.mjs +165 -0
  451. package/src/knowledge-health/capabilities.mjs +350 -0
  452. package/src/knowledge-health/context.mjs +62 -0
  453. package/src/knowledge-health/example.mjs +47 -0
  454. package/src/knowledge-health/index.mjs +10 -0
  455. package/src/knowledge-health/owner-join.mjs +88 -0
  456. package/src/knowledge-health/proof/common.mjs +24 -0
  457. package/src/knowledge-health/proof/installed-check.mjs +100 -0
  458. package/src/knowledge-health/proof/native-readback.mjs +37 -0
  459. package/src/knowledge-health/proof/rehearse.mjs +68 -0
  460. package/src/knowledge-health/proof/validate-participant.mjs +17 -0
  461. package/src/knowledge-health/proof/verify-native-capture.mjs +14 -0
  462. package/src/knowledge-health/proof/workshop-check.mjs +36 -0
  463. package/src/knowledge-health/rule-identity.mjs +44 -0
  464. package/src/knowledge-health/workshop-composition.mjs +19 -0
  465. package/src/knowledge-health/workshop-profile.mjs +176 -0
  466. package/src/knowledge-health/workshop.mjs +99 -0
  467. package/src/learning/adapters.mjs +68 -0
  468. package/src/learning/assistance.mjs +127 -0
  469. package/src/learning/contracts.mjs +65 -0
  470. package/src/learning/store.mjs +272 -0
  471. package/src/personal-workspace/index.mjs +391 -0
  472. package/src/personal-workspace/selection.mjs +385 -0
  473. package/src/project/config.mjs +8 -0
  474. package/src/project/durable-state.mjs +3 -1
  475. package/src/project/file-class.mjs +1 -1
  476. package/src/project/private-state.mjs +10 -1
  477. package/src/projection/obsidian/contracts.mjs +224 -18
  478. package/src/projection/obsidian/edits/apply.mjs +63 -19
  479. package/src/projection/obsidian/edits/regions.mjs +137 -42
  480. package/src/projection/obsidian/materialize/index.mjs +6 -3
  481. package/src/projection/obsidian/materialize/path-registry.mjs +443 -57
  482. package/src/projection/obsidian/materialize/prepare-view.mjs +382 -131
  483. package/src/projection/obsidian/materialize/redaction.mjs +327 -0
  484. package/src/projection/obsidian/materialize/settings.mjs +113 -34
  485. package/src/projection/obsidian/personal-workspace.mjs +436 -0
  486. package/src/projection/obsidian/plugin-bridge/bundle.mjs +50 -0
  487. package/src/projection/obsidian/plugin-bridge/channel.mjs +174 -0
  488. package/src/projection/obsidian/plugin-bridge/index.mjs +10 -0
  489. package/src/projection/obsidian/proposals/adapter.mjs +47 -8
  490. package/src/projection/obsidian/proposals/observation.mjs +20 -7
  491. package/src/projection/obsidian/publication/bridge-script.mjs +11 -5
  492. package/src/projection/obsidian/publication/index.mjs +2 -1
  493. package/src/projection/obsidian/publication/publisher.mjs +312 -36
  494. package/src/projection/obsidian/publication/transport.mjs +63 -8
  495. package/src/projection/obsidian/publication/vault-list.mjs +200 -0
  496. package/src/projection/obsidian/recovery/index.mjs +4 -1
  497. package/src/projection/obsidian/recovery/restart.mjs +3 -1
  498. package/src/projection/obsidian/recovery/store.mjs +168 -8
  499. package/src/projection/obsidian/selection-ui/contribution.mjs +6 -5
  500. package/src/projection/obsidian/selection-ui/focus.mjs +14 -7
  501. package/src/projection/obsidian/selection-ui/selection-state.mjs +2 -2
  502. package/src/projection/obsidian/selection-ui/selection.mjs +8 -3
  503. package/src/readiness/readiness.mjs +10 -3
  504. package/src/reflection/index.mjs +56 -0
  505. package/src/runtime/obsidian/app-capability.mjs +104 -12
  506. package/src/runtime/obsidian/app-production-seams.mjs +161 -42
  507. package/src/runtime/obsidian/app-registration.mjs +313 -0
  508. package/src/runtime/obsidian/app-restart.mjs +154 -0
  509. package/src/runtime/obsidian/engine.mjs +288 -29
  510. package/src/runtime/obsidian/extension-points.mjs +1 -1
  511. package/src/runtime/obsidian/index.mjs +15 -8
  512. package/src/runtime/obsidian/launch-plan.mjs +91 -0
  513. package/src/runtime/obsidian/lifecycle.mjs +193 -22
  514. package/src/runtime/obsidian/login-item.mjs +332 -0
  515. package/src/runtime/obsidian/machine-settings.mjs +119 -12
  516. package/src/runtime/obsidian/opening.mjs +369 -63
  517. package/src/runtime/obsidian/pending-edits.mjs +10 -0
  518. package/src/runtime/obsidian/pipeline.mjs +71 -3
  519. package/src/runtime/obsidian/plugin-channel.mjs +289 -0
  520. package/src/runtime/obsidian/plugin-choice.mjs +182 -0
  521. package/src/runtime/obsidian/plugin-drift.mjs +124 -0
  522. package/src/runtime/obsidian/plugin-presence.mjs +61 -0
  523. package/src/runtime/obsidian/process-identity.mjs +20 -10
  524. package/src/runtime/obsidian/project-views.mjs +282 -0
  525. package/src/runtime/obsidian/questions.mjs +48 -0
  526. package/src/runtime/obsidian/release-watch.mjs +56 -0
  527. package/src/runtime/obsidian/service-main.mjs +113 -17
  528. package/src/runtime/obsidian/service-manager-production.mjs +61 -0
  529. package/src/runtime/obsidian/service-managers.mjs +275 -0
  530. package/src/runtime/obsidian/service-record.mjs +105 -5
  531. package/src/runtime/obsidian/service-server.mjs +50 -12
  532. package/src/runtime/obsidian/service.mjs +134 -7
  533. package/src/runtime/obsidian/startup-adapters.mjs +59 -21
  534. package/src/runtime/obsidian/state-store.mjs +13 -1
  535. package/src/runtime/obsidian/unheld-evidence.mjs +84 -0
  536. package/src/runtime/obsidian/vault-location.mjs +300 -0
  537. package/src/runtime/obsidian/view-counts.mjs +34 -0
  538. package/src/server/local-sidecar.mjs +193 -7
  539. package/src/server/server.mjs +45 -6
  540. package/src/template-bindings/project.mjs +92 -0
  541. package/src/templates/profile.mjs +225 -0
  542. package/src/trackables/domain.mjs +175 -0
  543. package/src/trackables/store.mjs +114 -0
  544. package/src/ui/knowledge-page.mjs +1388 -0
  545. package/src/upgrade/explanation.mjs +1 -1
  546. package/src/upgrade/template-participant.mjs +171 -0
  547. package/src/upgrade/transaction.mjs +72 -25
  548. package/src/upgrade/upgrade.mjs +2 -1
  549. package/templates/external-project-workspace/pack-lifecycle.json +6 -1
  550. package/templates/knowledge-workspace/.gitattributes +2 -0
  551. package/templates/knowledge-workspace/AGENTS.md +27 -0
  552. package/templates/knowledge-workspace/README.md +44 -0
  553. package/templates/knowledge-workspace/atelier.project.json +22 -0
  554. package/templates/knowledge-workspace/gitignore +6 -0
  555. package/templates/knowledge-workspace/knowledge-plan.json +111 -0
  556. package/templates/knowledge-workspace/knowledge-plan.schema.json +281 -0
  557. package/templates/knowledge-workspace/records/forecast.md +22 -0
  558. package/templates/knowledge-workspace/records/inspection.md +25 -0
  559. package/templates/knowledge-workspace/records/telescope.md +24 -0
  560. package/templates/knowledge-workspace/repo-access.v1.json +9 -0
@@ -5,6 +5,7 @@ import fs from 'node:fs'
5
5
  import http from 'node:http'
6
6
  import path from 'node:path'
7
7
  import { fileURLToPath } from 'node:url'
8
+ import { AtelierDiagnosticError } from '../project/config.mjs'
8
9
  import {
9
10
  atomicReplacePrivateText,
10
11
  ensureContainedPrivateDirectory,
@@ -24,6 +25,7 @@ import {
24
25
  trustedMutationRequest,
25
26
  trustedReadRequest,
26
27
  } from './security.mjs'
28
+ import { canonicalize } from '../attestation/jcs.mjs'
27
29
  import { createProposalStore } from '../collaboration/proposals.mjs'
28
30
  import {
29
31
  renderProposalDetailPageHtml,
@@ -33,6 +35,9 @@ import {
33
35
  import { createReviewStore } from '../collaboration/review-store.mjs'
34
36
  import { loadBoundRun, currentRunEligibility } from '../readiness-protocols/evidence.mjs'
35
37
  import { renderReviewPage } from '../ui/review-page.mjs'
38
+ import { renderKnowledgePage } from '../ui/knowledge-page.mjs'
39
+ import { knowledgeDashboard, knowledgeQuestionContext, loadKnowledgeWorkspace } from '../knowledge/workspace.mjs'
40
+ import { createKnowledgeSessions } from '../knowledge/sessions.mjs'
36
41
 
37
42
  export const ATELIER_CONTEXT_SCHEMA = 'atelier-context@v1'
38
43
  export const ATELIER_PRESENCE_SCHEMA = 'atelier-presence@v1'
@@ -196,6 +201,47 @@ function capabilityContract() {
196
201
  }
197
202
  }
198
203
 
204
+ // A listen failure a person can fix by choosing another port becomes a typed
205
+ // diagnostic the CLI prints with that remedy. Any other failure is returned
206
+ // unchanged, so the CLI's own rule for unknown errors still decides what shows.
207
+ function listenFailure(error, port) {
208
+ if (error?.code === 'EADDRINUSE') {
209
+ return new AtelierDiagnosticError('port-in-use', `port ${port} is already in use`, {
210
+ hint: 'Pass --port=<free port> to choose another.',
211
+ cause: error,
212
+ })
213
+ }
214
+ if (error?.code === 'EACCES') {
215
+ return new AtelierDiagnosticError('port-permission-denied', `permission to listen on port ${port} was denied`, {
216
+ hint: 'Pass --port=<free port from 1024 to 65535> to choose another; lower ports need elevated privileges.',
217
+ cause: error,
218
+ })
219
+ }
220
+ return error
221
+ }
222
+
223
+ function knowledgeError(error) {
224
+ const message = error instanceof Error ? error.message : ''
225
+ if (message === 'coauthor requires a Git workspace with untracked, ignored .atelier-local/ state')
226
+ return 'coauthor requires a Git workspace with untracked, ignored local state. Initialize Git and ignore the .atelier-local directory.'
227
+ if (/^collaboration (ledger|event).*ceiling/.test(message))
228
+ return 'knowledge history capacity reached. Preserve the ledger and saved values for operator inspection; do not compact active session chains.'
229
+ if (message.startsWith('EEXIST: private state is locked'))
230
+ return 'knowledge writer is busy. Preserve the request and retry after the active writer finishes.'
231
+ const safe = [
232
+ 'workspace changed', 'stale revision', 'event id conflict', 'source changed',
233
+ 'coauthor session not found', 'coauthor requires', 'unknown knowledge',
234
+ 'invalid knowledge', 'request UUID', 'retry budget exhausted',
235
+ 'receipt and failure events are store-owned', 'event refused in',
236
+ 'coauthor plan must', 'knowledge session configuration mismatch',
237
+ 'knowledge session identity mismatch', 'knowledge session exceeds',
238
+ 'knowledge session list exceeds',
239
+ 'knowledge history unavailable', 'knowledge start marker mismatch',
240
+ ]
241
+ return safe.some(prefix => message.startsWith(prefix)) && !message.includes('/')
242
+ ? message : 'Knowledge operation unavailable. Preserve your draft and inspect the local workspace or active writer.'
243
+ }
244
+
199
245
  function doctorEnvelope() {
200
246
  return {
201
247
  ok: true,
@@ -211,6 +257,7 @@ export function createAtelierSidecarServer({
211
257
  workspaceRoot = process.cwd(),
212
258
  stateDir = workspaceRoot,
213
259
  reviewProject = null,
260
+ knowledgeProject = null,
214
261
  port = 0,
215
262
  presenceTtlMs = Number(process.env.ATELIER_PRESENCE_TTL_MS || 5 * 60 * 1000),
216
263
  } = {}) {
@@ -223,6 +270,7 @@ export function createAtelierSidecarServer({
223
270
  })
224
271
  const publication = loadPublishedWorkspaceManifest(root)
225
272
  const review = reviewProject ? createReviewStore(reviewProject) : null
273
+ const knowledge = knowledgeProject ? createKnowledgeSessions(knowledgeProject) : null
226
274
  const workspaceId = workspaceIdForRoot(root)
227
275
  const noncePath = path.join(stateDirReal, '.atelier-nonce')
228
276
  const presencePath = path.join(stateDirReal, '.atelier-presence.json')
@@ -233,6 +281,95 @@ export function createAtelierSidecarServer({
233
281
  workspaceId,
234
282
  })
235
283
 
284
+ // One copy-only declaration is retained from the workshop: this path, this
285
+ // action, from this view. The request stays `{ sessionId }`; everything
286
+ // retained is derived here from fresh owning readbacks, and the generic
287
+ // /api/proposals route keeps its published-HTML fence.
288
+ const WORKSHOP_HANDOFF_TARGET = Object.freeze({ path: 'records/checklist.md', action: 'copy.repoPath', viewId: 'knowledge-workshop' })
289
+ const sameJson = (left, right) => canonicalize(left) === canonicalize(right)
290
+ const refusedRetention = (error, status = 'refused') => ({ status: 409, body: { ok: false, error, retention: { status } } })
291
+ const retentionSummary = (record, outcome, sourceCurrent) => ({
292
+ status: 'retained',
293
+ outcome,
294
+ sourceCurrent,
295
+ proposalId: record.proposal.id,
296
+ readback: `/api/proposals/${record.proposal.id}`,
297
+ receipt: {
298
+ sessionId: record.retention.sessionId,
299
+ requestId: record.retention.requestId,
300
+ valueDigest: record.retention.valueDigest,
301
+ },
302
+ payloadDigest: record.retention.payloadDigest,
303
+ proposalStatus: record.proposal.status,
304
+ eventVersion: record.proposal.eventVersion,
305
+ })
306
+
307
+ function retainWorkshopHandoff(body) {
308
+ if (!body || Array.isArray(body) || Object.keys(body).join(',') !== 'sessionId' || typeof body.sessionId !== 'string') {
309
+ return refusedRetention('workshop handoff accepts a session id only')
310
+ }
311
+ // A fresh owning readback: this throws when the session, its ledger or a
312
+ // saved value is missing, redirected or altered.
313
+ const session = knowledge.read(body.sessionId)
314
+ const selected = session.record.flow === 'workshop-review'
315
+ ? session.state.saved.find((value) => value.fieldId === 'authored-revision')
316
+ : null
317
+ if (!selected) {
318
+ // No separately selected draft receipt: prepared only, as before. An
319
+ // incomplete Review or a response that selects nothing is refused by
320
+ // the existing preparation.
321
+ return { status: 200, body: { ...knowledge.workshopHandoff(body), retention: { status: 'not-retained', reason: 'no separately selected draft receipt' } } }
322
+ }
323
+ const own = session.owningReadbacks?.verified === true
324
+ ? session.owningReadbacks.immutableValues.find((value) => sameJson(value.receipt, selected.receipt))
325
+ : null
326
+ if (!own || own.text !== selected.text || selected.receipt.sessionId !== session.record.id) {
327
+ return refusedRetention('the selected draft receipt is not confirmed by its owning readback')
328
+ }
329
+ if (!session.current) {
330
+ // Reopen after a source change: read back what was retained, never append.
331
+ const known = proposals.lookupRetainedProposal(selected.receipt)
332
+ if (known.outcome === 'retained') {
333
+ return {
334
+ status: 200,
335
+ body: {
336
+ ok: true,
337
+ handoff: proposals.retainedHandoff(known.record),
338
+ sourceEditsApplied: false,
339
+ directWrite: false,
340
+ retention: retentionSummary(known.record, 'existing', false),
341
+ },
342
+ }
343
+ }
344
+ return known.outcome === 'not-found'
345
+ ? refusedRetention('the source changed before this draft was retained; nothing is retained for this receipt', 'not-retained')
346
+ : refusedRetention(known.error, known.outcome === 'conflict' ? 'refused' : 'unknown')
347
+ }
348
+ const prepared = knowledge.workshopHandoff(body)
349
+ const handoff = prepared.handoff
350
+ if (
351
+ !sameJson(handoff.proposal.selectedDraftReceipt, selected.receipt) || handoff.sessionId !== session.record.id ||
352
+ handoff.path !== WORKSHOP_HANDOFF_TARGET.path || handoff.action !== WORKSHOP_HANDOFF_TARGET.action ||
353
+ handoff.viewId !== WORKSHOP_HANDOFF_TARGET.viewId || handoff.directWrite !== false ||
354
+ handoff.applyEndpoint !== null || handoff.diff?.replacement !== selected.text
355
+ ) {
356
+ return refusedRetention('the prepared handoff does not match the selected draft readback')
357
+ }
358
+ // The original contribution is read back from its own session as well.
359
+ const original = knowledge.read(handoff.proposal.contributionSessionId)
360
+ const values = original.owningReadbacks?.verified === true ? original.owningReadbacks.immutableValues : null
361
+ if (
362
+ !values ||
363
+ !sameJson([...values.map((value) => value.receipt), selected.receipt], handoff.proposal.savedDraftReceipts) ||
364
+ values.find((value) => value.receipt.fieldId === 'original-words')?.text !== handoff.proposal.originalWords
365
+ ) {
366
+ return refusedRetention('the original contribution is not confirmed by its owning readback')
367
+ }
368
+ const result = proposals.retainProposal(handoff)
369
+ if (!result.ok) return refusedRetention(result.error, result.outcome === 'unknown' ? 'unknown' : 'refused')
370
+ return { status: 200, body: { ...prepared, retention: retentionSummary(result.record, result.outcome, true) } }
371
+ }
372
+
236
373
  function resolvePublishedPath({ rel, requireFile = false, requireHtml = false } = {}) {
237
374
  const resolved = resolveWorkspacePath({
238
375
  workspaceRoot: root,
@@ -375,8 +512,8 @@ export function createAtelierSidecarServer({
375
512
  // Browsers send Origin on POST; same-origin GET normally omits it. Keep
376
513
  // the strict origin gate for nonce disclosure instead of relaxing the
377
514
  // existing session-auth GET contract or accepting unclassified reads.
378
- if (review && url.pathname === '/api/review/session') {
379
- if (!trustedMutationRequest(req.headers) || !body || Array.isArray(body) || Object.keys(body).length) {
515
+ if ((review && url.pathname === '/api/review/session') || (knowledge && url.pathname === '/api/knowledge/session')) {
516
+ if (!trustedMutationRequest(req.headers) || !body || Array.isArray(body) || Object.keys(body).length || (url.pathname === '/api/knowledge/session' && url.search)) {
380
517
  json(res, 403, { ok: false, error: 'review session requires a same-origin empty request' })
381
518
  return
382
519
  }
@@ -391,6 +528,22 @@ export function createAtelierSidecarServer({
391
528
  return
392
529
  }
393
530
 
531
+ if (knowledge && url.pathname.startsWith('/api/knowledge/')) {
532
+ const operation = url.pathname.slice('/api/knowledge/'.length)
533
+ if (!['start', 'event', 'recover', 'lookup', 'workshop-handoff', 'workshop-review'].includes(operation) || url.search) {
534
+ json(res, 404, { ok: false, error: 'unknown knowledge action' }); return
535
+ }
536
+ try {
537
+ if (operation === 'workshop-handoff') {
538
+ const retained = retainWorkshopHandoff(body)
539
+ json(res, retained.status, retained.body)
540
+ } else {
541
+ json(res, 200, knowledge[operation === 'workshop-review' ? 'workshopReview' : operation](body))
542
+ }
543
+ } catch (error) { json(res, 409, { ok: false, error: knowledgeError(error) }) }
544
+ return
545
+ }
546
+
394
547
  if (review && url.pathname === '/api/review/contributions') {
395
548
  const result = review.contribute(body)
396
549
  json(res, result.status, result)
@@ -508,6 +661,38 @@ export function createAtelierSidecarServer({
508
661
  return
509
662
  }
510
663
 
664
+ if (knowledge && url.pathname === '/knowledge' && !url.search) {
665
+ const body = renderKnowledgePage()
666
+ res.writeHead(200, htmlDocumentHeaders(Buffer.byteLength(body)))
667
+ res.end(body)
668
+ return
669
+ }
670
+ if (knowledge && url.pathname.startsWith('/api/knowledge/')) {
671
+ try {
672
+ let result
673
+ const operation = url.pathname.slice('/api/knowledge/'.length)
674
+ const parameters = operation === 'context' ? ['id', 'mode'] : operation === 'read' ? ['id'] : []
675
+ if ([...url.searchParams.keys()].some(k => !parameters.includes(k)) || [...url.searchParams.keys()].length !== new Set(url.searchParams.keys()).size) throw new Error('invalid knowledge query')
676
+ if (operation === 'dashboard') {
677
+ const dashboard = knowledgeDashboard(loadKnowledgeWorkspace(knowledgeProject))
678
+ try {
679
+ const profile = knowledge.workshopProfile()
680
+ dashboard.flows = [profile.flow, ...dashboard.flows]
681
+ dashboard.workshop = { available: true, context: profile.context }
682
+ } catch {
683
+ dashboard.workshop = { available: false, reason: 'No current actionable public workshop finding.' }
684
+ }
685
+ result = { dashboard }
686
+ }
687
+ else if (operation === 'context') result = { context: knowledgeQuestionContext(loadKnowledgeWorkspace(knowledgeProject), url.searchParams.get('id'), url.searchParams.get('mode') || 'graph') }
688
+ else if (operation === 'sessions') result = knowledge.list()
689
+ else if (operation === 'read') result = knowledge.read(url.searchParams.get('id'))
690
+ else { json(res, 404, { ok: false, error: 'unknown knowledge action' }); return }
691
+ json(res, 200, { ok: true, ...result })
692
+ } catch (error) { json(res, 409, { ok: false, error: knowledgeError(error) }) }
693
+ return
694
+ }
695
+
511
696
  if (review && url.pathname === '/review') {
512
697
  const body = renderReviewPage()
513
698
  res.writeHead(200, htmlDocumentHeaders(Buffer.byteLength(body)))
@@ -606,6 +791,8 @@ export function createAtelierSidecarServer({
606
791
  proposal: record.proposal,
607
792
  diff: record.diff,
608
793
  copyable: record.copyable,
794
+ // A retained workshop handoff is read back whole; other proposals are unchanged.
795
+ ...(record.retention ? { payload: record.payload, retention: record.retention } : {}),
609
796
  } : { ok: false, error: result.error, diagnostics: result.diagnostics })
610
797
  return
611
798
  }
@@ -662,14 +849,13 @@ export function createAtelierSidecarServer({
662
849
  if (!isLoopbackHost(host)) {
663
850
  return Promise.reject(new Error(`non-loopback listen host refused: ${host}`))
664
851
  }
665
- // A busy port is an ordinary condition, not a crash: surface it as a
666
- // rejection the CLI can print, instead of an unhandled 'error' event.
852
+ // A busy or refused port is an ordinary condition, not a crash: surface
853
+ // it as a typed rejection the CLI prints with its remedy, instead of an
854
+ // unhandled 'error' event or a redacted internal error.
667
855
  return new Promise((resolve, reject) => {
668
856
  const onError = (error) => {
669
857
  server.removeListener('listening', onListening)
670
- reject(error.code === 'EADDRINUSE'
671
- ? new Error(`port ${listenPort} is already in use — pass --port=<free port> to choose another`)
672
- : error)
858
+ reject(listenFailure(error, listenPort))
673
859
  }
674
860
  const onListening = () => {
675
861
  server.removeListener('error', onError)
@@ -1,6 +1,27 @@
1
- import { resolveProjectConfig } from '../project/config.mjs'
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { AtelierDiagnosticError, resolveProjectConfig } from '../project/config.mjs'
2
4
  import { createAtelierSidecarServer } from './local-sidecar.mjs'
3
5
 
6
+ // dev serves what build wrote and builds nothing itself. Before build, the
7
+ // output folder (or, after graph alone, its manifest) is absent, and the
8
+ // sidecar failed with a raw ENOENT carrying an absolute path or a redacted
9
+ // internal error. Name the missing steps instead, and name the folder only
10
+ // relative to the project config. A non-directory is left to the sidecar.
11
+ function assertProjectionBuilt(project) {
12
+ const stat = fs.statSync(project.outputRoot, { throwIfNoEntry: false })
13
+ if (stat && !stat.isDirectory()) return
14
+ const manifestMissing = stat && !fs.existsSync(path.join(project.outputRoot, 'atelier.manifest.json'))
15
+ if (stat && !manifestMissing) return
16
+ const rel = path.relative(project.configDir, project.outputRoot)
17
+ const contained = rel !== '' && rel !== '..' && !rel.startsWith(`..${path.sep}`) && !path.isAbsolute(rel)
18
+ const folder = contained ? `projection output folder ${rel}` : 'the projection output folder'
19
+ const state = manifestMissing ? 'has no atelier.manifest.json' : 'does not exist'
20
+ throw new AtelierDiagnosticError('projection-output-missing', `${folder} ${state}; this project has not been built yet`, {
21
+ hint: 'Run atelier graph, then atelier build, with the same --project path, then retry.',
22
+ })
23
+ }
24
+
4
25
  function parseServerArgs(argv = []) {
5
26
  const args = { projectArgs: [] }
6
27
  for (const arg of argv) {
@@ -11,17 +32,35 @@ function parseServerArgs(argv = []) {
11
32
  return args
12
33
  }
13
34
 
35
+ // argv > PORT env > default. Supervisors that assign a free port (preview
36
+ // panes, dev harnesses) pass it via PORT, and an Atelier that ignores that
37
+ // fights whatever already holds the canonical port instead of coexisting.
38
+ // A value listen would refuse is refused here, naming where it came from;
39
+ // Node's own range error names neither the flag nor the variable.
40
+ function resolvePort(args, env = process.env) {
41
+ const [source, raw] = args.port ? ['--port', args.port] : env.PORT ? ['PORT', env.PORT] : [null, '8137']
42
+ const port = Number(raw)
43
+ if (Number.isInteger(port) && port >= 0 && port <= 65535) return port
44
+ throw new AtelierDiagnosticError('port-invalid', `${source} must be a whole number from 0 to 65535, got ${JSON.stringify(raw)}`, {
45
+ hint: source === 'PORT'
46
+ ? 'Set PORT to a free port or unset it, or pass --port=<free port> to override it.'
47
+ : 'Pass a free port, for example --port=8138.',
48
+ })
49
+ }
50
+
14
51
  export async function runServerCommand(argv = process.argv.slice(2)) {
15
52
  const args = parseServerArgs(argv)
16
53
  const project = resolveProjectConfig({ argv: args.projectArgs })
54
+ // An unusable --port or PORT is refused before the project's build state,
55
+ // so a mistyped argument is named even in a project not built yet.
56
+ const port = args.smoke ? 0 : resolvePort(args)
57
+ assertProjectionBuilt(project)
17
58
  const sidecar = createAtelierSidecarServer({
18
59
  workspaceRoot: project.outputRoot,
19
60
  stateDir: project.outputRoot,
20
61
  reviewProject: argv.includes('--review') ? project : null,
21
- // argv > PORT env > default. Supervisors that assign a free port (preview
22
- // panes, dev harnesses) pass it via PORT, and an Atelier that ignores that
23
- // fights whatever already holds the canonical port instead of coexisting.
24
- port: args.smoke ? 0 : Number(args.port || process.env.PORT || 8137),
62
+ knowledgeProject: argv.includes('--knowledge') ? project : null,
63
+ port,
25
64
  })
26
65
 
27
66
  if (args.smoke) {
@@ -40,5 +79,5 @@ export async function runServerCommand(argv = process.argv.slice(2)) {
40
79
  }
41
80
 
42
81
  const address = await sidecar.listen()
43
- console.log(`MNSTRY Atelier listening on http://127.0.0.1:${address.port}/`)
82
+ console.log(`MNSTRY Atelier listening on http://127.0.0.1:${address.port}/${argv.includes('--knowledge') ? 'knowledge' : ''}`)
44
83
  }
@@ -0,0 +1,92 @@
1
+ import fs from 'node:fs'
2
+ import { buildCanonicalGraph, createGraphFileCache } from '../graph/graph.mjs'
3
+ import { projectGraph, PROJECTION_TARGETS } from '../projection/policy.mjs'
4
+ import { renderReadOnlyDocument, validatePresentation } from '../ui/presentation/index.mjs'
5
+ import { templateReference, validateTemplateDefinition, validateTemplateBinding, validateTemplateHost } from '../templates/profile.mjs'
6
+
7
+ const packageVersion = JSON.parse(fs.readFileSync(new URL('../../package.json', import.meta.url), 'utf8')).version
8
+ const identity = value => templateReference('PayloadRef', 'identity', '1', value).digest.slice(7, 39)
9
+ const outcome = (ok, errors, rest = {}) => ({ ok, errors, authority: 'structural-only', executionAuthority: false, publicationAuthority: false, conformanceClaim: 'none', ...rest })
10
+
11
+ /** Read-only composition over a loaded project, not a graph or source writer.
12
+ * The request is bounded JSON text: {profile, projectRef, roleNodeIds, target,
13
+ * theme?}. This initial binding supports classified active Markdown resources,
14
+ * Resource bindings and CollectionView/StatusView. Other requirements
15
+ * refuse instead of being converted to a superficially similar surface.
16
+ */
17
+ export function createTemplateProjectView(project, requestJson) {
18
+ try {
19
+ if (typeof requestJson !== 'string' || Buffer.byteLength(requestJson) > 1048576) return outcome(false, ['invalid request'])
20
+ const request = JSON.parse(requestJson)
21
+ // The profile reference validator also enforces bounded plain JSON before
22
+ // the request is used; no caller-supplied accessors enter this adapter.
23
+ templateReference('PayloadRef', 'request', '1', request)
24
+ if (!request || Array.isArray(request) || Object.keys(request).some(key => !['profile', 'projectRef', 'roleNodeIds', 'target', 'theme'].includes(key))) return outcome(false, ['invalid request'])
25
+ const { profile, projectRef, roleNodeIds, target, theme = 'light' } = request
26
+ const definition = validateTemplateDefinition(profile)
27
+ if (!definition.ok) return outcome(false, definition.errors)
28
+ if (!Object.hasOwn(PROJECTION_TARGETS, target)) return outcome(false, ['unknown projection target'])
29
+ if (!roleNodeIds || Array.isArray(roleNodeIds) || typeof roleNodeIds !== 'object') return outcome(false, ['invalid role selection'])
30
+ if (profile.runtimeProfileRef !== null) return outcome(false, ['runtime profile requires its owning adapter'])
31
+ const templateRef = templateReference('TemplateRef', profile.id, profile.version, profile)
32
+ const host = validateTemplateHost(profile, {
33
+ schema: 'atelier-template-host@v1', templateRef, carrier: 'web', atelierVersion: packageVersion,
34
+ packRefs: [], semanticPrimitives: ['Resource'], surfacePrimitives: ['CollectionView', 'StatusView'],
35
+ runtimeProfileRef: null, optionalDecisions: [],
36
+ })
37
+ if (!host.ok) return outcome(false, host.errors)
38
+ const cache = createGraphFileCache()
39
+ const graph = buildCanonicalGraph(project, { fileCache: cache })
40
+ if (!graph.ok) return outcome(false, ['canonical graph invalid'])
41
+ const projected = projectGraph(graph, { target })
42
+ const visible = new Map(projected.nodes.filter(node => node.classification === 'classified' && node.status === 'active').map(node => [node.id, node]))
43
+ const records = [], sources = new Map(), roles = []
44
+ for (const [roleRef, ids] of Object.entries(roleNodeIds)) {
45
+ if (!profile.semanticRoles.some(role => role.id === roleRef) || !Array.isArray(ids) || !ids.length || ids.length > 256 || ids.some(id => typeof id !== 'string') || new Set(ids).size !== ids.length) return outcome(false, ['invalid role selection'])
46
+ if (profile.semanticRoles.find(role => role.id === roleRef).primitive !== 'Resource') return outcome(false, ['semantic role has no canonical binding'])
47
+ const refs = []
48
+ for (const id of ids) {
49
+ const node = visible.get(id)
50
+ // A node's audience cannot widen its repository's read boundary.
51
+ if (!node || !PROJECTION_TARGETS[target].has(node.repoAccess?.readBoundary)) return outcome(false, ['selected source unavailable for this view'])
52
+ const source = cache.files.get(`${node.repo}\u0000${node.path}`)
53
+ if (!source || !/^[a-f0-9]{64}$/.test(source.digest)) return outcome(false, ['source byte pin unavailable'])
54
+ if (!sources.has(id)) {
55
+ const document = { nodeId: id, repository: node.repo, path: node.path, rawDigest: `sha256:${source.digest}`, title: node.title, summary: node.summary }
56
+ const ref = templateReference('SourceRef', `source.${identity(id)}`, document.rawDigest, document)
57
+ sources.set(id, { ref, document }); records.push({ ref, document })
58
+ }
59
+ refs.push(sources.get(id).ref)
60
+ }
61
+ roles.push({ roleRef, sourceRefs: refs })
62
+ }
63
+ const binding = { schema: 'atelier-template-binding@v1', id: `binding.${identity(projectRef)}`, version: '1.0.0', templateRef, projectRef, roles }
64
+ const checked = validateTemplateBinding(profile, binding, records)
65
+ if (!checked.ok) return outcome(false, checked.errors)
66
+ const bindingRef = templateReference('BindingRef', binding.id, binding.version, binding)
67
+ const nodes = profile.surfaceRoles.map((view, index) => {
68
+ const id = `view-${index}`
69
+ if (view.primitive === 'StatusView') return { id, type: 'status', label: view.id, text: 'Read-only local projection. Runtime actions and publication are unavailable.', tone: 'neutral', details: host.diagnostics.map(item => ({ label: item.id, value: item.kind === 'semantic-role' ? 'Optional role unsupported; binding unavailable' : `${item.status}; deterministic or manual fallback` })), actions: [] }
70
+ const sourceIds = [...new Set(view.semanticRoleRefs.flatMap(role => roleNodeIds[role] ?? []))]
71
+ return { id, type: 'collection', label: view.id, items: sourceIds.map(sourceId => ({ id: `item-${identity(sourceId)}`, label: sources.get(sourceId).document.title, detail: sources.get(sourceId).document.summary })) }
72
+ })
73
+ nodes.unshift({ id: 'description', type: 'text', label: 'Inputs and limits', text: `Inputs: ${profile.inputs.join('; ')}. Limits: ${profile.limitations.join('; ')}` })
74
+ nodes.push({ id: 'identity', type: 'text', label: 'Template and binding identity', text: `Template: ${templateRef.id}@${templateRef.version}; ${templateRef.digest}. Binding: ${bindingRef.id}@${bindingRef.version}; ${bindingRef.digest}. Release: none (local preview). Structural references only; not verified authorship, release acceptance or rights.` })
75
+ // Provenance travels with readable exports, not only the API envelope.
76
+ // Use opaque refs and byte pins; never expose local repository paths here.
77
+ for (let offset = 0; offset < records.length; offset += 128) nodes.push({
78
+ id: `provenance-${offset}`, type: 'collection', label: 'Source provenance',
79
+ items: records.slice(offset, offset + 128).map(({ ref, document }) => ({ id: `source-${identity(ref.id)}`, label: document.title, detail: `SourceRef: ${ref.id}; ${ref.digest}. Source bytes: ${document.rawDigest}.` })),
80
+ })
81
+ const model = { schema: 'atelier.presentation/v1', version: '1.0.0', id: `template-${identity(profile.id)}`, title: profile.purpose, lang: 'en', direction: 'ltr', theme, density: 'comfortable', navigation: [], panes: [{ id: 'content', label: 'Template preview', role: 'primary', blocks: nodes.map(node => node.id) }], nodes }
82
+ if (validatePresentation(model).length) return outcome(false, ['presentation binding invalid'])
83
+ // Reuse the exact same non-interactive renderer for local web and document
84
+ // preview. This creates bytes only; it does not publish or erase old copies.
85
+ const html = renderReadOnlyDocument(model)
86
+ const textPreview = [model.title, ...nodes.flatMap(node => [node.label, ...(node.items ? node.items.flatMap(item => [item.label, item.detail]) : [node.text]), ...(node.details ?? []).map(item => `${item.label}: ${item.value}`)])].join('\n\n')
87
+ return outcome(true, [], { templateRef, bindingRef, binding, records, model, html, textPreview, capabilityDiagnostics: host.diagnostics, optionalDecisions: host.diagnostics.filter(item => item.kind !== 'semantic-role'), target, lifecycle: 'active-only', artifacts: { web: html, documents: html } })
88
+ } catch {
89
+ // Do not disclose source paths or source text through exception messages.
90
+ return outcome(false, ['template project composition refused'])
91
+ }
92
+ }