@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
@@ -0,0 +1,567 @@
1
+ import { canonicalize } from '../attestation/jcs.mjs'
2
+ import { createIntakeStore, intakeDigest } from '../intake/store.mjs'
3
+ import { createIngestionStore } from '../ingestion/store.mjs'
4
+ import { ingestionJson, ingestionDigest } from '../ingestion/contracts.mjs'
5
+ import { prepareSemanticInput, prepareSemanticProposals, readSemanticProposals } from '../ingestion/semantic.mjs'
6
+ import { appendHarness, readHarness } from '../harnesses/store.mjs'
7
+ import { harnessRef, contentDigest } from '../harnesses/contracts.mjs'
8
+ import { inspectKnowledge } from './ledger.mjs'
9
+ import { prepareIngestionContribution, localKnowledgeContext } from './ingestion.mjs'
10
+ import { knowledgeGraphProposal } from './projection.mjs'
11
+ import { learningDigest } from '../learning/contracts.mjs'
12
+
13
+ const OPERATION = 'atelier.semantic-operation/v0'
14
+ export const SEMANTIC_OPERATION_PROFILE = 'atelier.semantic-operation-profile/v0'
15
+ export class SemanticOperationError extends Error {
16
+ constructor(code, message) { super(message); this.name = 'SemanticOperationError'; this.code = code }
17
+ }
18
+ function withSavedReceipts(error, receipts) {
19
+ if (Object.keys(receipts).length === 0) return error
20
+ let code
21
+ if (error !== null && ['object', 'function'].includes(typeof error)) {
22
+ try {
23
+ const codeProperty = Object.getOwnPropertyDescriptor(error, 'code')
24
+ if (typeof codeProperty?.value === 'string' && /^SEMANTIC_[A-Z_]+$/.test(codeProperty.value)) code = codeProperty.value
25
+ const descriptors = {}, extensible = Object.isExtensible(error)
26
+ let writable = true
27
+ for (const [key, value] of Object.entries(receipts)) {
28
+ const existing = Object.getOwnPropertyDescriptor(error, key)
29
+ if (existing ? !Object.hasOwn(existing, 'value') || !existing.writable : !extensible) { writable = false; break }
30
+ descriptors[key] = existing ? { value } : { value, writable: true, configurable: true, enumerable: true }
31
+ }
32
+ if (writable) { Object.defineProperties(error, descriptors); return error }
33
+ } catch { /* Reflection/decoration failure must not erase the original cause. */ }
34
+ }
35
+ const failure = new SemanticOperationError(code ?? 'SEMANTIC_OPERATION_INTERRUPTED', 'Semantic operation was interrupted after saving recoverable receipts')
36
+ Object.defineProperty(failure, 'cause', { value: error, writable: true, configurable: true })
37
+ Object.assign(failure, receipts)
38
+ return failure
39
+ }
40
+ function check(condition, code, message) { if (!condition) throw new SemanticOperationError(code, message) }
41
+ function identifier(value) { check(typeof value === 'string' && /^[a-z][a-z0-9-]{0,63}$/.test(value), 'SEMANTIC_OPERATION_INVALID', 'A bounded operation identifier is required'); return value }
42
+ function json(value) {
43
+ try { return ingestionJson(value) }
44
+ catch (error) {
45
+ const limit = ['ingestion JSON depth exceeded', 'ingestion member ceiling exceeded', 'ingestion document byte ceiling exceeded'].includes(error?.message)
46
+ throw new SemanticOperationError(limit ? 'SEMANTIC_OPERATION_LIMIT' : 'SEMANTIC_OPERATION_INVALID', limit ? 'Operation JSON limit exceeded' : 'Bounded plain operation JSON is required')
47
+ }
48
+ }
49
+ function closed(value, fields) {
50
+ check(value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === fields.length && fields.every(key => Object.hasOwn(value, key)), 'SEMANTIC_OPERATION_INVALID', 'The declared operation shape is required')
51
+ }
52
+ const eventId = (operationId, phase) => `semantic-${intakeDigest(`${operationId}:${phase}`).slice(0, 40)}`
53
+ function extractorPins(value, inputDigest) {
54
+ const pins = json(value)
55
+ closed(pins, ['id', 'version', 'route', 'model', 'promptDigest', 'parameters'])
56
+ identifier(pins.id)
57
+ check(typeof pins.version === 'string' && /^[a-zA-Z0-9._-]{1,64}$/.test(pins.version), 'SEMANTIC_OPERATION_INVALID', 'A bounded extractor version is required')
58
+ check(['model', 'deterministic', 'authored'].includes(pins.route), 'SEMANTIC_OPERATION_INVALID', 'Declare the extraction route')
59
+ check(pins.route === 'model' ? typeof pins.model === 'string' && pins.model.length > 0 && pins.model.length <= 256 : pins.model === null, 'SEMANTIC_OPERATION_INVALID', 'Model routes need a model pin; other routes use null')
60
+ check(typeof pins.promptDigest === 'string' && /^[a-f0-9]{64}$/.test(pins.promptDigest), 'SEMANTIC_OPERATION_INVALID', 'A prompt or configuration digest is required')
61
+ check(pins.parameters && typeof pins.parameters === 'object' && !Array.isArray(pins.parameters), 'SEMANTIC_OPERATION_INVALID', 'Plain extractor parameters are required')
62
+ return { ...pins, configurationDigest: intakeDigest(canonicalize({ ...pins, inputDigest })) }
63
+ }
64
+
65
+ // Called only after the proposal validator has checked the complete assertion.
66
+ // Omission is explicit: the qualified contribution remains available for review.
67
+ export function plainAssertionEligibility(assertion, domain) {
68
+ check(assertion && assertion.time && Array.isArray(assertion.time.unknowns) && domain?.data &&
69
+ ['from', 'until', 'expression'].every(key => Object.hasOwn(assertion.time, key)), 'SEMANTIC_PROJECTION_SUPPORT', 'An explicitly qualified assertion and domain are required')
70
+ const reasons = []
71
+ if (assertion.objectId === null || assertion.direction !== 'subject-to-object') reasons.push('unary')
72
+ if (assertion.negated !== false) reasons.push('negated')
73
+ if (assertion.modality !== 'asserted') reasons.push('modal')
74
+ if (assertion.time.from !== null || assertion.time.until !== null || assertion.time.expression !== null || assertion.time.unknowns.length) reasons.push('temporal')
75
+ if (assertion.scope !== domain.data.scope) reasons.push('scope')
76
+ return { eligible: reasons.length === 0, reasons }
77
+ }
78
+
79
+ export const semanticRelationId = assertionId => `relation-${intakeDigest(identifier(assertionId)).slice(0, 40)}`
80
+ export function assertSemanticOperationProfile({ references = [], candidates = null }) {
81
+ if (Array.isArray(references)) for (const reference of references) {
82
+ check(!reference?.locator || ['line', 'csv-cell', 'json-pointer'].includes(reference.locator.kind), 'SEMANTIC_UNSUPPORTED_LOCATOR', 'unsupported-locator')
83
+ }
84
+ if (Array.isArray(candidates?.assertions)) for (const assertion of candidates.assertions) {
85
+ if (!assertion || typeof assertion !== 'object' || Array.isArray(assertion)) continue
86
+ check(assertion.scope === undefined || typeof assertion.scope === 'string', 'SEMANTIC_UNSUPPORTED_SCOPE', 'unsupported-scope')
87
+ check(!Object.hasOwn(assertion, 'literalObject') && (assertion.objectId === undefined || assertion.objectId === null || typeof assertion.objectId === 'string'), 'SEMANTIC_UNSUPPORTED_LITERAL_OBJECT', 'unsupported-literal-object')
88
+ if (Array.isArray(assertion.evidence)) for (const support of assertion.evidence) {
89
+ check(typeof support?.quote !== 'string' || !/[\r\n]/u.test(support.quote), 'SEMANTIC_UNSUPPORTED_LOCATOR', 'unsupported-locator: multiline quote')
90
+ }
91
+ }
92
+ }
93
+ export function semanticDependencyWitnesses({ citations, sources, endpoints = [] }) {
94
+ const basedOn = [], sourceWitness = []
95
+ function witness(record, quote, dependency = 'source') {
96
+ check(typeof quote === 'string' && quote.length > 0, 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'A source quote is required for a dependency witness')
97
+ let encoded = ''
98
+ for (const point of quote) {
99
+ const encodedPoint = JSON.stringify(point).slice(1, -1)
100
+ if (encoded.length + encodedPoint.length > 8192) break
101
+ encoded += encodedPoint
102
+ }
103
+ check(encoded.length > 0 && record.data.body.includes(encoded), 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'The encoded dependency witness is absent from the stored contribution body')
104
+ if (basedOn.some(item => item.contribution.id === record.id)) return
105
+ check(basedOn.length < 64, 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'Sources and endpoints exceed the existing dependency limit')
106
+ basedOn.push({ contribution: harnessRef(record), quote: encoded })
107
+ sourceWitness.push({ contributionId: record.id, encoding: 'json-string-substring', purpose: 'ledger-dependency-only', dependency })
108
+ }
109
+ for (const citation of citations) {
110
+ const matches = sources.filter(record => record.data.origin.method === 'extracted' && record.data.origin.attemptId === citation.attemptId && record.data.origin.blobDigest === `sha256:${citation.sourceDigest}`)
111
+ check(matches.length === 1, 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'Each citation needs one exact current structural source contribution')
112
+ witness(matches[0], citation.quote)
113
+ }
114
+ for (const endpoint of endpoints) witness(endpoint.record, endpoint.quote, endpoint.dependency)
115
+ return { basedOn, sourceWitness }
116
+ }
117
+ // Relation support is not a ledger dependency in harness v1. This guard is
118
+ // stateless and fails closed even when withdrawal cleanup has not run.
119
+ export function assertSemanticProjection({ records, activationId, reconsider = [] }) {
120
+ const state = inspectKnowledge(records), byId = new Map(records.map(record => [record.id, record]))
121
+ const stale = new Set([...state.reconsider, ...reconsider].map(item => item.id))
122
+ const accepted = new Set(state.accepted), active = new Set(), selected = new Set()
123
+ const activation = byId.get(activationId)
124
+ check(activation?.kind === 'activation' && !stale.has(activationId), 'SEMANTIC_PROJECTION_STALE', 'A current activation is required')
125
+ for (const record of records) if (record.kind === 'activation' && !stale.has(record.id)) {
126
+ for (const pin of record.data.reviews) active.add(byId.get(pin.id).data.target.id)
127
+ }
128
+ function include(id) {
129
+ if (selected.has(id)) return
130
+ check(accepted.has(id) && !stale.has(id), 'SEMANTIC_PROJECTION_STALE', 'Every projected dependency must have current acceptance')
131
+ selected.add(id)
132
+ const record = byId.get(id)
133
+ if (record.kind === 'relation') {
134
+ const support = /(?:^|\n)semantic-support: ([a-z][a-z0-9-]{0,63}) (sha256:[a-f0-9]{64})$/.exec(record.data.rationale)
135
+ check(support && record.id === semanticRelationId(support[1]), 'SEMANTIC_PROJECTION_SUPPORT', 'A semantic relation needs its unique exact assertion support pin')
136
+ const assertion = byId.get(support[1])
137
+ check(assertion?.kind === 'contribution' && harnessRef(assertion).digest === support[2], 'SEMANTIC_PROJECTION_SUPPORT', 'Relation assertion support digest differs')
138
+ check(accepted.has(assertion.id) && active.has(assertion.id) && !stale.has(assertion.id), 'SEMANTIC_PROJECTION_SUPPORT', 'Relation support must be currently accepted, active and not withdrawn or superseded')
139
+ let body
140
+ try { body = JSON.parse(assertion.data.body) } catch { throw new SemanticOperationError('SEMANTIC_PROJECTION_SUPPORT', 'A qualified assertion body is required') }
141
+ check(body?.schema === SEMANTIC_OPERATION_PROFILE && body.kind === 'assertion', 'SEMANTIC_PROJECTION_SUPPORT', 'A semantic assertion contribution is required')
142
+ check(plainAssertionEligibility(body.candidate, state.domain).eligible, 'SEMANTIC_PROJECTION_QUALIFIED', 'A qualified assertion cannot become a plain edge')
143
+ check(body.candidate.predicate === record.data.predicate && body.endpoints?.subject?.id === record.data.subject.id && body.endpoints?.object?.id === record.data.object.id,
144
+ 'SEMANTIC_PROJECTION_SUPPORT', 'Relation participants differ from its reviewed assertion')
145
+ include(assertion.id)
146
+ include(record.data.subject.id); include(record.data.object.id)
147
+ } else for (const pin of record.data.basedOn) include(pin.contribution.id)
148
+ }
149
+ for (const pin of activation.data.reviews) include(byId.get(pin.id).data.target.id)
150
+ return { selected: [...selected], activation: harnessRef(activation), authority: 'none' }
151
+ }
152
+
153
+ // Existing intake owns bytes; the existing harness owns all durable metadata.
154
+ // This runner never invokes an extractor or infers a receiver decision.
155
+ export function createSemanticOperation({ workspaceRoot, workspaceId, run }) {
156
+ identifier(run)
157
+ const intake = createIntakeStore({ workspaceRoot })
158
+ const store = createIngestionStore({ workspaceRoot, workspaceId })
159
+ const readHistory = () => readHarness({ workspaceRoot, profile: 'knowledge', run })
160
+ let verification = null
161
+ const history = () => verification?.state ?? readHistory()
162
+ function verified(read) {
163
+ if (verification) return read()
164
+ const state = readHistory()
165
+ verification = { state, completed: new Map(), sources: new Map() }
166
+ let result
167
+ try {
168
+ result = read()
169
+ for (const current of verification.completed.values()) {
170
+ const input = current.initial.value.input
171
+ const refreshed = prepareSemanticInput({ store, plan: input.plan, domain: state.domain, references: input.evidence.map(span => span.reference), identityCandidates: input.identityCandidates })
172
+ check(refreshed.digest === input.digest, 'SEMANTIC_OPERATION_STALE', 'Semantic evidence changed during the operation')
173
+ }
174
+ check(readHistory().head === (result.head ?? state.head), 'SEMANTIC_OPERATION_HEAD', 'Knowledge history changed during the operation')
175
+ return result
176
+ } catch (error) {
177
+ const receipts = result?.record && result.head
178
+ ? { recorded: { record: harnessRef(result.record), head: result.head, nextAction: 'reopen-recorded-write' } } : {}
179
+ throw withSavedReceipts(error, receipts)
180
+ } finally { verification = null }
181
+ }
182
+ function events(state) {
183
+ const result = []
184
+ for (const record of state.records) {
185
+ if (record.kind !== 'contribution') continue
186
+ let value
187
+ try { value = JSON.parse(record.data.body) } catch { continue }
188
+ if (value?.schema !== OPERATION) continue
189
+ check(record.data.origin.method === 'captured' && record.data.origin.contentDigest === contentDigest(record.data.body) && record.id === eventId(value.operationId, value.phase), 'SEMANTIC_OPERATION_INTEGRITY', 'Operation record identity differs')
190
+ result.push({ record, value })
191
+ }
192
+ return result
193
+ }
194
+ function operation(operationId, state = history()) {
195
+ identifier(operationId)
196
+ const matching = events(state).filter(event => event.value.operationId === operationId)
197
+ check(matching.length > 0 && matching[0].value.phase === 'reserved', 'SEMANTIC_OPERATION_MISSING', 'No reserved semantic operation exists')
198
+ return { initial: matching[0], latest: matching.at(-1), state }
199
+ }
200
+ function append(value, { term, at, by, confirm, basedOn = [] }) {
201
+ const state = history(), domain = state.domain
202
+ check(domain && state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'The current knowledge history digest is required')
203
+ const body = canonicalize(json(value))
204
+ const record = { schema: 'atelier-knowledge-record@v1', id: eventId(value.operationId, value.phase), run, at, by, kind: 'contribution', data: {
205
+ domain: harnessRef(domain), category: 'decision-rationale', term, title: `Semantic operation ${value.operationId}: ${value.phase}`, body,
206
+ audience: domain.data.audience, scope: domain.data.scope,
207
+ origin: { method: 'captured', locator: `semantic-operation:${value.operationId}`, contentDigest: contentDigest(body), rightsBasis: 'Host-declared operation metadata; integrity is not semantic acceptance.' }, basedOn,
208
+ } }
209
+ return { ...appendHarness({ workspaceRoot, profile: 'knowledge', record, confirm }), record }
210
+ }
211
+ function expectedAttempt(initial) {
212
+ const value = initial.value
213
+ return { schema: 'mnstry.atelier-intake-attempt@v1', attemptId: value.attemptId, blobId: value.source.digest,
214
+ extractorId: value.extractor.id, extractorVersion: value.extractor.version, configurationDigest: value.extractor.configurationDigest }
215
+ }
216
+ function foreignAttempt(initial, result) {
217
+ return result.status !== 'absent' && ingestionDigest(result.attempt) !== ingestionDigest(expectedAttempt(initial))
218
+ }
219
+ function inspected(initial) {
220
+ const value = initial.value, result = intake.readAttempt(value.attemptId)
221
+ check(!foreignAttempt(initial, result), 'SEMANTIC_OPERATION_INTEGRITY', 'Raw attempt differs from its operation pins')
222
+ if (result.status === 'complete') {
223
+ check(ingestionDigest(intake.readCompletion(value.attemptId)) === ingestionDigest(result.completion), 'SEMANTIC_OPERATION_INTEGRITY', 'Completion readback differs')
224
+ }
225
+ return result
226
+ }
227
+ function assertNoReconciledCapture(initial, attempt, state) {
228
+ if (!foreignAttempt(initial, attempt) && ['partial', 'complete'].includes(attempt.status)) {
229
+ const error = new SemanticOperationError('SEMANTIC_RECONCILE_REQUIRED', 'Own output contradicts the host reconciliation; do not start another execution')
230
+ error.captured = { attemptId: initial.value.attemptId, completion: attempt.completion, head: state.head, nextAction: 'reopen-captured-output' }
231
+ throw error
232
+ }
233
+ }
234
+ function status({ operationId }) {
235
+ const { initial, latest, state } = operation(operationId), value = initial.value
236
+ let attempt
237
+ if (latest.value.phase === 'reconciled' && latest.value.recovery) {
238
+ const actual = intake.readAttempt(value.attemptId), recovery = latest.value.recovery
239
+ closed(recovery, ['kind', 'attemptId', 'manifestDigest'])
240
+ check(recovery.kind === 'foreign-manifest-before-readiness' && recovery.attemptId === value.attemptId &&
241
+ latest.value.outcome === 'not-executed' && foreignAttempt(initial, actual) && recovery.manifestDigest === ingestionDigest(actual.attempt),
242
+ 'SEMANTIC_OPERATION_INTEGRITY', 'Reconciled foreign manifest readback differs')
243
+ attempt = { status: 'foreign-manifest', attemptId: value.attemptId, manifestDigest: recovery.manifestDigest }
244
+ } else {
245
+ attempt = inspected(initial)
246
+ if (latest.value.phase === 'reconciled') assertNoReconciledCapture(initial, attempt, state)
247
+ }
248
+ let freshness = 'current'
249
+ try {
250
+ intake.readSource({ ref: value.source.ref, expectedDigest: value.source.digest })
251
+ const refreshed = prepareSemanticInput({ store, plan: value.input.plan, domain: state.domain, references: value.input.evidence.map(span => span.reference), identityCandidates: value.input.identityCandidates })
252
+ check(refreshed.digest === value.input.digest, 'SEMANTIC_OPERATION_STALE', 'Current semantic input differs')
253
+ } catch { freshness = 'stale' }
254
+ if (latest.value.phase === 'completed') {
255
+ check(attempt.status === 'complete' && ingestionDigest(attempt.completion) === ingestionDigest(latest.value.completion), 'SEMANTIC_OPERATION_INTEGRITY', 'Saved completion differs from intake')
256
+ }
257
+ return { schema: 'atelier.semantic-operation-status/v0', operationId, phase: latest.value.phase, head: state.head, input: value.input, extractor: value.extractor,
258
+ attempt, freshness, execution: latest.value.phase === 'reconciled' ? 'reconciled' : attempt.status === 'complete' ? 'complete' : 'unknown',
259
+ usage: latest.value.usage ?? null, authority: 'none', semanticAcceptance: 'pending' }
260
+ }
261
+ function begin(request) {
262
+ const selected = json(request)
263
+ closed(selected, ['operationId', 'attemptId', 'at', 'term', 'plan', 'references', 'identityCandidates', 'extractor', 'confirm'])
264
+ const { operationId, attemptId, at, term, confirm } = selected
265
+ assertSemanticOperationProfile({ references: selected.references })
266
+ identifier(operationId); identifier(attemptId)
267
+ const state = history()
268
+ check(state.domain && state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'The current knowledge history digest is required')
269
+ check(!events(state).some(event => event.value.operationId === operationId), 'SEMANTIC_OPERATION_EXISTS', 'Reopen the existing operation; do not execute it again')
270
+ const input = prepareSemanticInput({ store, domain: state.domain, ...selected })
271
+ const extractor = extractorPins(selected.extractor, input.digest), source = { ref: input.evidence[0].receipt.ref, digest: input.evidence[0].reference.sourceDigest }
272
+ const starts = events(state).filter(event => event.value.phase === 'reserved')
273
+ for (const prior of starts) {
274
+ if (prior.value.source.digest !== source.digest || prior.value.source.ref !== source.ref || prior.value.extractor.configurationDigest !== extractor.configurationDigest) continue
275
+ const known = operation(prior.value.operationId, state)
276
+ if (known.latest.value.phase === 'reconciled') {
277
+ assertNoReconciledCapture(known.initial, intake.readAttempt(prior.value.attemptId), state)
278
+ continue
279
+ }
280
+ const attempt = inspected(known.initial)
281
+ check(attempt.status === 'complete', 'SEMANTIC_EXECUTION_UNKNOWN', 'Reconcile the prior source/configuration execution before a new attempt')
282
+ check(known.latest.value.phase === 'completed', 'SEMANTIC_RECONCILE_REQUIRED', 'Finish recording the existing completed attempt before reuse')
283
+ const cached = status({ operationId: prior.value.operationId })
284
+ check(cached.freshness === 'current', 'SEMANTIC_OPERATION_STALE', 'Cached semantic input is stale')
285
+ return { ...cached, cacheReuse: true }
286
+ }
287
+ check(!starts.some(prior => prior.value.attemptId === attemptId), 'SEMANTIC_OPERATION_EXISTS', 'Attempt identity is already reserved')
288
+ check(intake.readAttempt(attemptId).status === 'absent', 'SEMANTIC_OPERATION_EXISTS', 'Attempt identity is already in use')
289
+ intake.ingest({ ref: source.ref, expectedDigest: source.digest })
290
+ const value = { schema: OPERATION, operationId, phase: 'reserved', attemptId, source, input, extractor }
291
+ const recorded = append(value, { term, at, by: `host-model:${extractor.id}@${extractor.version}`, confirm })
292
+ try {
293
+ intake.beginAttempt({ attemptId, blobId: source.digest, extractorId: extractor.id, extractorVersion: extractor.version, configurationDigest: extractor.configurationDigest })
294
+ const ready = status({ operationId })
295
+ check(ready.phase === 'reserved' && ready.head === recorded.head && ready.attempt.status === 'begun', 'SEMANTIC_RECONCILE_REQUIRED', 'Reservation changed before host execution')
296
+ check(ready.freshness === 'current', 'SEMANTIC_OPERATION_STALE', 'Source or domain changed during reservation')
297
+ return { ...ready, execution: 'ready-for-host', cacheReuse: false }
298
+ } catch (error) {
299
+ throw withSavedReceipts(error, { recorded: { record: harnessRef(recorded.record), head: recorded.head, nextAction: 'reopen-recorded-write' } })
300
+ }
301
+ }
302
+ function reconcile({ operationId, at, by, reason, outcome, confirm }) {
303
+ const { initial, latest } = operation(operationId), attempt = intake.readAttempt(initial.value.attemptId)
304
+ const foreign = foreignAttempt(initial, attempt)
305
+ check(latest.value.phase === 'reserved' && (foreign && outcome === 'not-executed' || !foreign && ['absent', 'begun'].includes(attempt.status)),
306
+ 'SEMANTIC_RECONCILE_REQUIRED', 'Partial own output must be completed; a foreign manifest permits only explicit not-executed reconciliation')
307
+ check(['not-executed', 'failed-no-output'].includes(outcome) && typeof reason === 'string' && reason.trim().length > 0 && reason.length <= 8192, 'SEMANTIC_OPERATION_INVALID', 'An explicit host reconciliation outcome and reason are required')
308
+ const recovery = foreign ? { recovery: { kind: 'foreign-manifest-before-readiness', attemptId: initial.value.attemptId, manifestDigest: ingestionDigest(attempt.attempt) } } : {}
309
+ const recorded = append({ schema: OPERATION, operationId, phase: 'reconciled', reserved: harnessRef(initial.record), outcome, reason, assurance: 'host-declared-not-independently-verified', ...recovery }, { term: initial.record.data.term, at, by, confirm })
310
+ try { return { ...status({ operationId }), head: recorded.head } }
311
+ catch (error) {
312
+ throw withSavedReceipts(error, { recorded: { record: harnessRef(recorded.record), head: recorded.head, nextAction: 'reopen-recorded-write' } })
313
+ }
314
+ }
315
+ function complete({ operationId, output, expectedOutputDigest, candidates, usage, at, confirm }) {
316
+ const { initial, latest, state } = operation(operationId), value = initial.value
317
+ check(state.head === confirm && latest.value.phase === 'reserved', 'SEMANTIC_OPERATION_HEAD', 'Complete the reserved operation against current history')
318
+ // Verify byte custody before publication; never write into another run's attempt.
319
+ const before = inspected(initial)
320
+ check(before.status !== 'absent', 'SEMANTIC_RECONCILE_REQUIRED', 'Reconcile the absent own manifest before completing output')
321
+ // Store owned executed bytes before interpreting even an oversized/malformed envelope.
322
+ const completion = intake.completeAttempt({ attemptId: value.attemptId, output, expectedOutputDigest })
323
+ let recorded
324
+ try {
325
+ const attempt = inspected(initial)
326
+ check(status({ operationId }).freshness === 'current', 'SEMANTIC_OPERATION_STALE', 'The source or adopted domain changed before completion')
327
+ const declared = json({ candidates, usage })
328
+ closed(declared.usage, ['inputTokens', 'outputTokens', 'cost', 'currency', 'elapsedMs', 'retries'])
329
+ for (const key of ['inputTokens', 'outputTokens', 'elapsedMs', 'retries']) check(declared.usage[key] === null || Number.isSafeInteger(declared.usage[key]) && declared.usage[key] >= 0, 'SEMANTIC_OPERATION_INVALID', 'Usage counts are nonnegative integers or unknown')
330
+ check(declared.usage.cost === null || typeof declared.usage.cost === 'number' && Number.isFinite(declared.usage.cost) && declared.usage.cost >= 0, 'SEMANTIC_OPERATION_INVALID', 'Cost is nonnegative or unknown')
331
+ check(declared.usage.currency === null || typeof declared.usage.currency === 'string' && /^[A-Z]{3}$/.test(declared.usage.currency), 'SEMANTIC_OPERATION_INVALID', 'Currency is explicit or unknown')
332
+ assertSemanticOperationProfile({ candidates: declared.candidates })
333
+ // Preserve executed raw bytes even when their interpretation is refused.
334
+ // Resuming interpretation reuses this completion; it never runs the host.
335
+ const proposals = prepareSemanticProposals({ store, input: value.input, candidates: declared.candidates })
336
+ recorded = append({ schema: OPERATION, operationId, phase: 'completed', reserved: harnessRef(initial.record), completion: attempt.completion,
337
+ candidates: declared.candidates, usage: declared.usage, usageAssurance: 'host-reported', inputDigest: value.input.digest }, { term: initial.record.data.term, at, by: `host-model:${value.extractor.id}@${value.extractor.version}`, confirm })
338
+ const ready = status({ operationId })
339
+ if (ready.freshness !== 'current') {
340
+ const error = new SemanticOperationError('SEMANTIC_OPERATION_STALE', 'Source or domain changed after recording completion')
341
+ throw error
342
+ }
343
+ return { ...ready, head: recorded.head, proposals }
344
+ } catch (error) {
345
+ const receipts = { captured: { attemptId: value.attemptId, completion, head: recorded?.head ?? state.head, nextAction: 'reopen-captured-output' } }
346
+ if (recorded) receipts.recorded = { record: harnessRef(recorded.record), head: recorded.head, nextAction: 'reopen-recorded-write' }
347
+ throw withSavedReceipts(error, receipts)
348
+ }
349
+ }
350
+ function completed(operationId) {
351
+ if (verification?.completed.has(operationId)) return verification.completed.get(operationId)
352
+ const value = operation(operationId), inspectedStatus = status({ operationId })
353
+ check(value.latest.value.phase === 'completed' && inspectedStatus.attempt.status === 'complete', 'SEMANTIC_RECONCILE_REQUIRED', 'Record the completed raw attempt before preparing interpretations')
354
+ check(inspectedStatus.freshness === 'current', 'SEMANTIC_OPERATION_STALE', 'Current source and adopted domain are required')
355
+ const proposals = prepareSemanticProposals({ store, input: value.initial.value.input, candidates: value.latest.value.candidates })
356
+ const receipt = inspectedStatus.attempt.completion
357
+ const result = { ...value, proposals, raw: { attemptId: value.initial.value.attemptId, attemptDigest: receipt.attemptDigest, outputDigest: receipt.outputDigest, completionDigest: intakeDigest(JSON.stringify(receipt)) } }
358
+ verification?.completed.set(operationId, result)
359
+ return result
360
+ }
361
+ function proposals({ operationId, query, limit = 64 }) {
362
+ const current = completed(operationId)
363
+ return { answerClass: 'pending-proposals', ...readSemanticProposals({ store, input: current.initial.value.input, proposals: current.proposals, query, limit }) }
364
+ }
365
+ function semanticBody(record) {
366
+ if (record?.kind !== 'contribution') return null
367
+ let body
368
+ try { body = JSON.parse(record.data.body) } catch { return null }
369
+ return body?.schema === SEMANTIC_OPERATION_PROFILE ? body : null
370
+ }
371
+ function endpointWitnessQuote(record) {
372
+ const candidateId = semanticBody(record)?.candidate?.id
373
+ if (typeof candidateId === 'string' && record.data.body.includes(JSON.stringify(candidateId).slice(1, -1))) return candidateId
374
+ // An ordinary accepted concept need not repeat its record identifier.
375
+ // Choose actual body text whose JSON encoding is also a body substring.
376
+ let quote = ''
377
+ for (const point of record.data.body) {
378
+ if (JSON.stringify(point).slice(1, -1) !== point) {
379
+ if (quote.trim()) return quote.trim()
380
+ quote = ''; continue
381
+ }
382
+ if (!quote && !point.trim()) continue
383
+ if (quote.length + point.length > 8192) break
384
+ quote += point
385
+ }
386
+ check(quote.trim().length > 0, 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'The accepted endpoint body has no representable dependency witness')
387
+ return quote.trim()
388
+ }
389
+ function verifySemantic(record) {
390
+ const body = semanticBody(record)
391
+ check(body && ['entity', 'assertion', 'unknown'].includes(body.kind), 'SEMANTIC_OPERATION_INTEGRITY', 'An operation interpretation is required')
392
+ const current = completed(body.operationId), collection = { entity: 'entities', assertion: 'assertions', unknown: 'unknowns' }[body.kind]
393
+ const candidate = current.proposals[collection].find(value => value.id === body.candidate?.id)
394
+ check(candidate && ingestionDigest(candidate) === ingestionDigest(body.candidate) && ingestionDigest(current.raw) === ingestionDigest(body.raw) &&
395
+ body.inputDigest === current.proposals.inputDigest && ingestionDigest(body.usage) === ingestionDigest(current.latest.value.usage), 'SEMANTIC_OPERATION_INTEGRITY', 'Interpretation differs from current candidate or raw capture pins')
396
+ closed(body, ['schema', 'operationId', 'kind', 'candidate', 'endpoints', 'raw', 'inputDigest', 'usage', 'sourceBinding', 'source', 'sourceWitness'])
397
+ const sourceRecord = sourceFor(body.source, body.sourceBinding, current), endpoints = {}, endpointWitnesses = []
398
+ if (body.kind === 'assertion') for (const role of ['subject', 'object']) {
399
+ const id = candidate[`${role}Id`]
400
+ if (id === null) { endpoints[role] = null; continue }
401
+ const { target: resolved, interpretation } = endpoint(current.proposals.entities.find(entity => entity.id === id), current)
402
+ endpoints[role] = harnessRef(resolved)
403
+ endpointWitnesses.push({ record: interpretation, quote: endpointWitnessQuote(interpretation), dependency: 'identity-choice' })
404
+ if (resolved.id !== interpretation.id) endpointWitnesses.push({ record: resolved, quote: endpointWitnessQuote(resolved), dependency: 'resolved-identity' })
405
+ }
406
+ const witnesses = semanticDependencyWitnesses({ citations: candidate.evidence, sources: [sourceRecord], endpoints: endpointWitnesses })
407
+ check(ingestionDigest(body.endpoints) === ingestionDigest(endpoints) && ingestionDigest(record.data.basedOn) === ingestionDigest(witnesses.basedOn) && ingestionDigest(body.sourceWitness) === ingestionDigest(witnesses.sourceWitness), 'SEMANTIC_OPERATION_INTEGRITY', 'Interpretation dependency, witness or endpoint pins differ')
408
+ const value = current.initial.value
409
+ check(record.by === `host-model:${value.extractor.id}@${value.extractor.version}` && record.data.origin.method === 'authored' &&
410
+ record.data.category === (body.kind === 'entity' ? 'concept' : body.kind === 'assertion' ? 'claim' : 'interpretation') &&
411
+ (body.kind !== 'entity' || record.data.term === candidate.type), 'SEMANTIC_OPERATION_INTEGRITY', 'Interpretation author, category or entity type differs')
412
+ return body
413
+ }
414
+ function sourceFor(source, binding, current) {
415
+ const record = current.state.records.find(record => record.id === source.id)
416
+ check(record?.kind === 'contribution' && harnessRef(record).digest === source.digest, 'SEMANTIC_OPERATION_INTEGRITY', 'The exact structural source contribution is required')
417
+ check(!current.state.reconsider.some(item => item.id === record.id), 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'The structural source contribution requires reconsideration')
418
+ const key = ingestionDigest({ source, binding })
419
+ if (verification?.sources.has(key)) return verification.sources.get(key)
420
+ const value = current.initial.value, selected = prepareIngestionContribution({ workspaceRoot, workspaceId, records: current.state.records, ...value.input.plan,
421
+ sourceId: value.input.evidence[0].reference.sourceId, title: record.data.title, term: record.data.term })
422
+ const expected = { ...selected.sourceBinding, contributionDataDigest: learningDigest(record.data) }
423
+ check(ingestionDigest(expected) === ingestionDigest(binding) && record.data.body === selected.data.body && ingestionDigest(record.data.origin) === ingestionDigest(selected.data.origin), 'SEMANTIC_OPERATION_INTEGRITY', 'Structural source provenance or binding differs')
424
+ verification?.sources.set(key, record)
425
+ return record
426
+ }
427
+ function endpoint(entity, current) {
428
+ const record = current.state.records.findLast(record => {
429
+ const body = semanticBody(record)
430
+ return body?.operationId === current.initial.value.operationId && body.kind === 'entity' && body.candidate?.id === entity.id
431
+ })
432
+ check(record && current.state.accepted.includes(record.id), 'SEMANTIC_IDENTITY_PENDING', 'The receiver must review each endpoint entity first')
433
+ verifySemantic(record)
434
+ if (entity.identity.status === 'source-local') return { target: record, interpretation: record }
435
+ // The ordinary review record carries the explicit receiver identity choice.
436
+ const acceptedReview = current.state.records.findLast(item => item.kind === 'review' && item.data.target.id === record.id)
437
+ let decision
438
+ try { decision = JSON.parse(acceptedReview.data.basis) } catch { /* A prose acceptance does not resolve a canonical identity. */ }
439
+ check(decision?.schema === 'atelier.semantic-identity-decision/v0' && decision.operationId === current.initial.value.operationId && decision.candidateId === entity.id && ['existing', 'source-local'].includes(decision.resolution?.status), 'SEMANTIC_IDENTITY_PENDING', 'An explicit receiver identity review is required')
440
+ if (decision.resolution.status === 'source-local') return { target: record, interpretation: record }
441
+ const target = current.state.records.find(item => item.id === decision.resolution.contribution?.id)
442
+ check(target?.kind === 'contribution' && entity.identity.candidateIds.includes(target.id) && target.data.term === entity.type && current.state.accepted.includes(target.id) && harnessRef(target).digest === decision.resolution.contribution.digest,
443
+ 'SEMANTIC_IDENTITY_PENDING', 'Canonical identity must be a supplied currently accepted matching contribution')
444
+ return { target, interpretation: record }
445
+ }
446
+ function prepareContribution({ operationId, id, kind, candidateId, source, sourceBinding, term, at, confirm, supersedes = null, revisionReason = null }) {
447
+ identifier(id)
448
+ const current = completed(operationId), collection = { entity: 'entities', assertion: 'assertions', unknown: 'unknowns' }[kind]
449
+ check(collection && current.state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'A declared interpretation kind and current history are required')
450
+ const candidate = current.proposals[collection].find(value => value.id === candidateId)
451
+ check(candidate, 'SEMANTIC_OPERATION_INVALID', 'The candidate is absent from the completed operation')
452
+ check(kind !== 'entity' || term === candidate.type, 'SEMANTIC_OPERATION_INVALID', 'Entity contributions must retain their proposed vocabulary type')
453
+ const sourceRecord = sourceFor(source, sourceBinding, current), endpoints = {}, endpointWitnesses = []
454
+ if (kind === 'assertion') for (const role of ['subject', 'object']) {
455
+ const candidateId = candidate[`${role}Id`]
456
+ if (candidateId === null) { endpoints[role] = null; continue }
457
+ const entity = current.proposals.entities.find(entity => entity.id === candidateId), { target: resolved, interpretation } = endpoint(entity, current)
458
+ endpoints[role] = harnessRef(resolved)
459
+ endpointWitnesses.push({ record: interpretation, quote: endpointWitnessQuote(interpretation), dependency: 'identity-choice' })
460
+ if (resolved.id !== interpretation.id) endpointWitnesses.push({ record: resolved, quote: endpointWitnessQuote(resolved), dependency: 'resolved-identity' })
461
+ }
462
+ const witnesses = semanticDependencyWitnesses({ citations: candidate.evidence, sources: [sourceRecord], endpoints: endpointWitnesses })
463
+ const value = current.initial.value, body = canonicalize(json({ schema: SEMANTIC_OPERATION_PROFILE, operationId, kind, candidate, endpoints, raw: current.raw,
464
+ inputDigest: current.proposals.inputDigest, usage: current.latest.value.usage, sourceBinding, source: harnessRef(sourceRecord), sourceWitness: witnesses.sourceWitness }))
465
+ const record = { schema: 'atelier-knowledge-record@v1', id, run, at, by: `host-model:${value.extractor.id}@${value.extractor.version}`, kind: 'contribution', data: {
466
+ domain: current.proposals.domainRef, category: kind === 'entity' ? 'concept' : kind === 'assertion' ? 'claim' : 'interpretation', term,
467
+ title: kind === 'entity' ? candidate.label : kind === 'assertion' ? `${candidate.subjectId} ${candidate.predicate} ${candidate.objectId ?? ''}`.trim() : candidate.reason,
468
+ body, audience: current.state.domain.data.audience, scope: current.state.domain.data.scope,
469
+ origin: { method: 'authored', reason: `Machine-authored interpretation by ${value.extractor.id}@${value.extractor.version} in operation ${operationId}; pending receiver review.` }, basedOn: witnesses.basedOn,
470
+ } }
471
+ const prior = current.state.records.filter(item => semanticBody(item)?.operationId === operationId && semanticBody(item)?.kind === kind && semanticBody(item)?.candidate?.id === candidateId)
472
+ if (supersedes !== null) {
473
+ const old = prior.at(-1)
474
+ check(old && ingestionDigest(harnessRef(old)) === ingestionDigest(supersedes) && typeof revisionReason === 'string' && revisionReason.trim().length > 0 && revisionReason.length <= 8192,
475
+ 'SEMANTIC_OPERATION_INVALID', 'A revision must explicitly supersede the latest exact interpretation with a reason')
476
+ record.data.supersedes = supersedes; record.data.revisionReason = revisionReason
477
+ } else check(prior.length === 0 && revisionReason === null, 'SEMANTIC_OPERATION_EXISTS', 'A candidate already has its immutable contribution; an explicit revision is required')
478
+ return { ...appendHarness({ workspaceRoot, profile: 'knowledge', record, confirm }), record, semanticAcceptance: 'pending' }
479
+ }
480
+ function record({ record, confirm }) {
481
+ check(record.run === run && ['evaluation', 'review', 'withdrawal', 'activation'].includes(record.kind), 'SEMANTIC_OPERATION_INVALID', 'Supply an actual receiver evaluation, review, withdrawal or activation')
482
+ return appendHarness({ workspaceRoot, profile: 'knowledge', record, confirm })
483
+ }
484
+ function prepareRelation({ assertion, at, confirm }) {
485
+ const state = history(), contribution = state.records.find(record => record.id === assertion.id)
486
+ check(contribution && harnessRef(contribution).digest === assertion.digest && state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'The exact assertion and current history are required')
487
+ const body = verifySemantic(contribution)
488
+ check(body.kind === 'assertion' && state.accepted.includes(contribution.id), 'SEMANTIC_IDENTITY_PENDING', 'The receiver must accept the assertion before its relation')
489
+ const eligibility = plainAssertionEligibility(body.candidate, state.domain)
490
+ if (!eligibility.eligible) return { head: state.head, record: null, projectionOmission: { assertion, ...eligibility }, authority: 'none' }
491
+ const relation = { schema: 'atelier-knowledge-record@v1', run, id: semanticRelationId(contribution.id), at, by: contribution.by, kind: 'relation', data: {
492
+ domain: contribution.data.domain, subject: body.endpoints.subject, object: body.endpoints.object, predicate: body.candidate.predicate,
493
+ rationale: `Machine-prepared plain relation; pending receiver review.\nsemantic-support: ${contribution.id} ${assertion.digest}`,
494
+ } }
495
+ return { ...appendHarness({ workspaceRoot, profile: 'knowledge', record: relation, confirm }), record: relation, semanticAcceptance: 'pending' }
496
+ }
497
+ function cascade({ withdrawalId, at, confirm }) {
498
+ let state = history(), head = confirm
499
+ check(state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'Resume cleanup against current history')
500
+ const withdrawal = state.records.find(record => record.id === withdrawalId && record.kind === 'withdrawal')
501
+ check(withdrawal, 'SEMANTIC_OPERATION_INVALID', 'An existing explicit receiver withdrawal is required')
502
+ const cleaned = []
503
+ for (const relation of state.records.filter(record => record.kind === 'relation')) {
504
+ const support = /(?:^|\n)semantic-support: ([a-z][a-z0-9-]{0,63}) (sha256:[a-f0-9]{64})$/.exec(relation.data.rationale)
505
+ if (support?.[1] !== withdrawal.data.target.id || support[2] !== withdrawal.data.target.digest || relation.id !== semanticRelationId(support[1])) continue
506
+ state = history()
507
+ if (state.records.some(record => record.kind === 'withdrawal' && record.data.target.id === relation.id)) continue
508
+ const cleanup = { schema: 'atelier-knowledge-record@v1', id: `cleanup-${intakeDigest(`${withdrawalId}:${relation.id}`).slice(0, 40)}`, run, at, by: 'semantic-operation:withdrawal-cleanup', kind: 'withdrawal', data: {
509
+ target: harnessRef(relation), reason: `Consequential cleanup of explicit receiver withdrawal ${withdrawalId}; supporting assertion is withdrawn.`,
510
+ } }
511
+ head = appendHarness({ workspaceRoot, profile: 'knowledge', record: cleanup, confirm: head }).head
512
+ cleaned.push(relation.id)
513
+ }
514
+ return { head, cleaned, authority: 'none' }
515
+ }
516
+ function context({ query }) {
517
+ const state = history(), bindings = [], failures = []
518
+ for (const record of state.records) {
519
+ const body = semanticBody(record)
520
+ if (!body) continue
521
+ try { if (state.accepted.includes(record.id)) verifySemantic(record) }
522
+ catch (error) {
523
+ if (!(error instanceof SemanticOperationError) || !['SEMANTIC_OPERATION_STALE', 'SEMANTIC_OPERATION_INTEGRITY', 'SEMANTIC_IDENTITY_PENDING', 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION'].includes(error.code)) throw error
524
+ failures.push({ id: record.id, reason: 'semantic-record-requires-reconsideration', code: error.code })
525
+ }
526
+ if (!bindings.some(binding => ingestionDigest(binding) === ingestionDigest(body.sourceBinding))) bindings.push(body.sourceBinding)
527
+ }
528
+ const view = localKnowledgeContext({ workspaceRoot, workspaceId, records: state.records, sourceBindings: bindings, query })
529
+ const reconsider = new Map(view.reconsider.map(item => [item.id, [...item.reasons]]))
530
+ for (const failure of failures) reconsider.set(failure.id, [...new Set([...(reconsider.get(failure.id) ?? []), failure.reason])])
531
+ // Preserve the full immutable ledger. Withhold failed interpretations and
532
+ // their dependents from this view without changing receiver decisions.
533
+ for (const record of state.records) {
534
+ const d = record.data
535
+ const refs = record.kind === 'contribution' ? [d.domain, ...d.basedOn.map(pin => pin.contribution)]
536
+ : record.kind === 'evaluation' ? [d.contribution]
537
+ : record.kind === 'relation' ? [d.domain, d.subject, d.object]
538
+ : record.kind === 'review' ? [d.target, ...d.evaluations]
539
+ : record.kind === 'activation' ? d.reviews : []
540
+ const reasons = refs.flatMap(pin => reconsider.get(pin.id) ?? [])
541
+ if (reasons.length) reconsider.set(record.id, [...new Set([...(reconsider.get(record.id) ?? []), ...reasons])])
542
+ }
543
+ const active = new Set()
544
+ for (const record of state.records) if (record.kind === 'activation' && !reconsider.has(record.id)) {
545
+ for (const pin of record.data.reviews) active.add(state.records.find(item => item.id === pin.id).data.target.id)
546
+ }
547
+ return { answerClass: 'accepted-knowledge', ...view,
548
+ hits: view.hits.filter(hit => active.has(hit.reference.id) && !reconsider.has(hit.reference.id)),
549
+ reconsider: [...reconsider].map(([id, reasons]) => ({ id, reasons })),
550
+ diagnostics: [...view.diagnostics, ...failures] }
551
+
552
+ }
553
+ function project({ activationId, namespace }) {
554
+ const state = history(), view = context({ query: 'semantic' })
555
+ const selected = assertSemanticProjection({ records: state.records, activationId, reconsider: view.reconsider }).selected
556
+ const typed = selected.map(id => ({ record: state.records.find(record => record.id === id), body: semanticBody(state.records.find(record => record.id === id)) })).filter(item => item.body)
557
+ for (const item of typed) verifySemantic(item.record)
558
+ return { ...knowledgeGraphProposal(state.records, { activationId, namespace }), semanticProfile: SEMANTIC_OPERATION_PROFILE,
559
+ semanticEntities: typed.filter(item => item.body.kind === 'entity').map(item => ({ record: harnessRef(item.record), candidate: item.body.candidate })),
560
+ semanticAssertions: typed.filter(item => item.body.kind === 'assertion').map(item => ({ record: harnessRef(item.record), candidate: item.body.candidate, endpoints: item.body.endpoints })),
561
+ dependencyWitnesses: typed.map(item => ({ record: harnessRef(item.record), witnesses: item.body.sourceWitness })),
562
+ projectionOmissions: typed.filter(item => item.body.kind === 'assertion').map(item => ({ assertion: harnessRef(item.record), ...plainAssertionEligibility(item.body.candidate, state.domain) })).filter(item => !item.eligible) }
563
+ }
564
+ return Object.freeze({ begin, status, reconcile, complete, proposals: request => verified(() => proposals(request)),
565
+ prepareContribution: request => verified(() => prepareContribution(request)), prepareRelation: request => verified(() => prepareRelation(request)),
566
+ record, cascade, context: request => verified(() => context(request)), project: request => verified(() => project(request)) })
567
+ }