@mnstry/atelier 0.2.0-alpha.12 → 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 (516) hide show
  1. package/CHANGELOG.md +661 -0
  2. package/README.md +142 -6
  3. package/contracts/atelier-adoption-policy.v2.schema.json +55 -0
  4. package/contracts/atelier-architecture.v1.schema.json +258 -0
  5. package/contracts/atelier-boundary-delegations.v1.schema.json +161 -0
  6. package/contracts/atelier-boundary-owner-keys.v1.schema.json +98 -0
  7. package/contracts/atelier-build.v1.schema.json +1076 -0
  8. package/contracts/atelier-capability.v1.schema.json +1252 -0
  9. package/contracts/atelier-coordination.v1.schema.json +1050 -0
  10. package/contracts/atelier-evidence-navigation.v1.schema.json +603 -0
  11. package/contracts/atelier-harness.v1.schema.json +234 -0
  12. package/contracts/atelier-ingestion.v1.schema.json +806 -0
  13. package/contracts/atelier-inquiry.v1.schema.json +1772 -0
  14. package/contracts/atelier-instruction-adoption.v1.schema.json +490 -0
  15. package/contracts/atelier-interaction.v1.schema.json +553 -0
  16. package/contracts/atelier-judgment.v1.schema.json +690 -0
  17. package/contracts/atelier-knowledge.v1.schema.json +1512 -0
  18. package/contracts/atelier-learning.v1.schema.json +1095 -0
  19. package/contracts/atelier-migration.v3.schema.json +64 -0
  20. package/contracts/atelier-personal-workspace-manifest.v1.schema.json +87 -0
  21. package/contracts/atelier-personal-workspace-overlay.v1.schema.json +299 -0
  22. package/contracts/atelier-template-adoption.v1.schema.json +223 -0
  23. package/contracts/atelier-template-profile.v1.schema.json +1168 -0
  24. package/contracts/atelier-trackable.v1.schema.json +781 -0
  25. package/contracts/atelier-upgrade-plan.v3.schema.json +532 -0
  26. package/docs/architecture.md +89 -0
  27. package/docs/assurance-controls.md +2 -2
  28. package/docs/blocks/capability-stewardship.md +17 -0
  29. package/docs/blocks/claims.md +16 -3
  30. package/docs/blocks/inquiry-harnesses.md +19 -0
  31. package/docs/blocks/learning-harnesses.md +17 -0
  32. package/docs/capability-stewardship.md +269 -0
  33. package/docs/coordination.md +51 -0
  34. package/docs/decision-practices.md +111 -0
  35. package/docs/decisions.md +29 -0
  36. package/docs/evidence-navigation.md +237 -0
  37. package/docs/exact-upgrades.md +3 -2
  38. package/docs/ingestion.md +181 -0
  39. package/docs/inquiry-harnesses.md +211 -0
  40. package/docs/install.md +80 -3
  41. package/docs/intake-and-guides.md +5 -0
  42. package/docs/integration-contract-decisions.md +24 -2
  43. package/docs/interaction-and-reflection.md +72 -0
  44. package/docs/knowledge-graph.md +20 -0
  45. package/docs/knowledge-health/api.md +30 -0
  46. package/docs/knowledge-health/assessment/api.md +96 -0
  47. package/docs/knowledge-health/assessment/capabilities.md +40 -0
  48. package/docs/knowledge-health/assessment/evaluation.md +27 -0
  49. package/docs/knowledge-health/assessment/facilitator.md +30 -0
  50. package/docs/knowledge-health/assessment/quickstart.md +61 -0
  51. package/docs/knowledge-health/assessment/troubleshooting.md +23 -0
  52. package/docs/knowledge-health/devday/facilitator.md +16 -0
  53. package/docs/knowledge-health/devday/participant-response.md +22 -0
  54. package/docs/knowledge-health/devday/public-default.md +107 -0
  55. package/docs/knowledge-health/devday/quickstart.md +18 -0
  56. package/docs/knowledge-health/devday/support.md +22 -0
  57. package/docs/knowledge-health/exercise.md +17 -0
  58. package/docs/knowledge-health/facilitator.md +20 -0
  59. package/docs/knowledge-health/quickstart.md +94 -0
  60. package/docs/knowledge-health/readme.md +15 -0
  61. package/docs/knowledge-health/support.md +34 -0
  62. package/docs/knowledge-setup.md +248 -0
  63. package/docs/knowledge-workspace.md +264 -0
  64. package/docs/learning-harnesses.md +238 -0
  65. package/docs/learning.md +215 -0
  66. package/docs/local-services.md +181 -16
  67. package/docs/obsidian-contract.md +223 -15
  68. package/docs/obsidian-plugin.md +38 -4
  69. package/docs/obsidian.md +613 -51
  70. package/docs/optional-ingestion.md +83 -0
  71. package/docs/personal-workspace.md +257 -0
  72. package/docs/practical-judgment.md +92 -0
  73. package/docs/progressive-ingestion-acceptance.md +89 -0
  74. package/docs/progressive-ingestion.md +235 -0
  75. package/docs/project-command-inventory.md +1 -0
  76. package/docs/release-engineering.md +49 -0
  77. package/docs/repo-boundary-guard.md +94 -0
  78. package/docs/research-starter-quickstart.md +66 -0
  79. package/docs/research-starter.md +114 -0
  80. package/docs/semantic-ingestion.md +198 -0
  81. package/docs/semantic-operation.md +317 -0
  82. package/docs/skill-steward.md +6 -0
  83. package/docs/template-profile.md +164 -0
  84. package/docs/template-upgrades.md +114 -0
  85. package/docs/trackables.md +111 -0
  86. package/docs/upgrade.md +47 -2
  87. package/fixtures/atelier-architecture/binding/invalid/document.json +19 -0
  88. package/fixtures/atelier-architecture/binding/valid/document.json +19 -0
  89. package/fixtures/atelier-architecture/catalog/invalid/document.json +290 -0
  90. package/fixtures/atelier-architecture/catalog/valid/document.json +343 -0
  91. package/fixtures/atelier-build-contract/attempt/invalid/document.json +20 -0
  92. package/fixtures/atelier-build-contract/attempt/valid/document.json +19 -0
  93. package/fixtures/atelier-build-contract/candidate/invalid/document.json +24 -0
  94. package/fixtures/atelier-build-contract/candidate/valid/document.json +23 -0
  95. package/fixtures/atelier-build-contract/decision/invalid/document.json +31 -0
  96. package/fixtures/atelier-build-contract/decision/valid/document.json +30 -0
  97. package/fixtures/atelier-build-contract/delivery/invalid/document.json +18 -0
  98. package/fixtures/atelier-build-contract/delivery/valid/document.json +17 -0
  99. package/fixtures/atelier-build-contract/gate/invalid/document.json +22 -0
  100. package/fixtures/atelier-build-contract/gate/valid/document.json +21 -0
  101. package/fixtures/atelier-build-contract/ledger/invalid/document.json +270 -0
  102. package/fixtures/atelier-build-contract/ledger/valid/document.json +269 -0
  103. package/fixtures/atelier-build-contract/objective/invalid/document.json +73 -0
  104. package/fixtures/atelier-build-contract/objective/valid/document.json +72 -0
  105. package/fixtures/atelier-build-contract/progress/invalid/document.json +18 -0
  106. package/fixtures/atelier-build-contract/progress/valid/document.json +17 -0
  107. package/fixtures/atelier-capability-contract/adoption/invalid/document.json +71 -0
  108. package/fixtures/atelier-capability-contract/adoption/valid/document.json +70 -0
  109. package/fixtures/atelier-capability-contract/event/invalid/document.json +18 -0
  110. package/fixtures/atelier-capability-contract/event/valid/document.json +17 -0
  111. package/fixtures/atelier-capability-contract/journal/invalid/document.json +382 -0
  112. package/fixtures/atelier-capability-contract/journal/valid/document.json +381 -0
  113. package/fixtures/atelier-capability-contract/notice/invalid/document.json +8 -0
  114. package/fixtures/atelier-capability-contract/notice/valid/document.json +7 -0
  115. package/fixtures/atelier-capability-contract/package/invalid/document.json +59 -0
  116. package/fixtures/atelier-capability-contract/package/valid/document.json +58 -0
  117. package/fixtures/atelier-capability-contract/plan/invalid/document.json +107 -0
  118. package/fixtures/atelier-capability-contract/plan/valid/document.json +106 -0
  119. package/fixtures/atelier-capability-contract/release/invalid/document.json +85 -0
  120. package/fixtures/atelier-capability-contract/release/valid/document.json +84 -0
  121. package/fixtures/atelier-capability-contract/state/invalid/document.json +316 -0
  122. package/fixtures/atelier-capability-contract/state/valid/document.json +315 -0
  123. package/fixtures/atelier-coordination/dependency/invalid/document.json +37 -0
  124. package/fixtures/atelier-coordination/dependency/valid/document.json +36 -0
  125. package/fixtures/atelier-coordination/directive/invalid/document.json +25 -0
  126. package/fixtures/atelier-coordination/directive/valid/document.json +24 -0
  127. package/fixtures/atelier-coordination/disposition/invalid/document.json +34 -0
  128. package/fixtures/atelier-coordination/disposition/valid/document.json +33 -0
  129. package/fixtures/atelier-coordination/outcome/invalid/document.json +39 -0
  130. package/fixtures/atelier-coordination/outcome/valid/document.json +38 -0
  131. package/fixtures/atelier-coordination/recovery/invalid/document.json +34 -0
  132. package/fixtures/atelier-coordination/recovery/valid/document.json +33 -0
  133. package/fixtures/atelier-harness-contract/handoff/invalid/document.json +25 -0
  134. package/fixtures/atelier-harness-contract/handoff/valid/document.json +24 -0
  135. package/fixtures/atelier-ingestion/invalid/authority.json +19 -0
  136. package/fixtures/atelier-ingestion/semantic-baseline.json +26 -0
  137. package/fixtures/atelier-ingestion/semantic-operation.json +75 -0
  138. package/fixtures/atelier-ingestion/valid/plan-input.json +18 -0
  139. package/fixtures/atelier-inquiry-contract/assessment/invalid/document.json +41 -0
  140. package/fixtures/atelier-inquiry-contract/assessment/valid/document.json +40 -0
  141. package/fixtures/atelier-inquiry-contract/bundle/invalid/document.json +51 -0
  142. package/fixtures/atelier-inquiry-contract/bundle/valid/document.json +50 -0
  143. package/fixtures/atelier-inquiry-contract/campaign/invalid/document.json +17 -0
  144. package/fixtures/atelier-inquiry-contract/campaign/valid/document.json +16 -0
  145. package/fixtures/atelier-inquiry-contract/decision/invalid/document.json +22 -0
  146. package/fixtures/atelier-inquiry-contract/decision/valid/document.json +21 -0
  147. package/fixtures/atelier-inquiry-contract/feedback/invalid/document.json +19 -0
  148. package/fixtures/atelier-inquiry-contract/feedback/valid/document.json +18 -0
  149. package/fixtures/atelier-inquiry-contract/handoff/invalid/document.json +92 -0
  150. package/fixtures/atelier-inquiry-contract/handoff/valid/document.json +91 -0
  151. package/fixtures/atelier-inquiry-contract/hypothesis/invalid/document.json +20 -0
  152. package/fixtures/atelier-inquiry-contract/hypothesis/valid/document.json +19 -0
  153. package/fixtures/atelier-inquiry-contract/ledger/invalid/document.json +680 -0
  154. package/fixtures/atelier-inquiry-contract/ledger/valid/document.json +679 -0
  155. package/fixtures/atelier-inquiry-contract/legacy-assessment/invalid/document.json +19 -0
  156. package/fixtures/atelier-inquiry-contract/legacy-assessment/valid/document.json +18 -0
  157. package/fixtures/atelier-inquiry-contract/request/invalid/document.json +50 -0
  158. package/fixtures/atelier-inquiry-contract/request/valid/document.json +49 -0
  159. package/fixtures/atelier-inquiry-contract/source/invalid/document.json +18 -0
  160. package/fixtures/atelier-inquiry-contract/source/valid/document.json +17 -0
  161. package/fixtures/atelier-inquiry-contract/withdrawal/invalid/document.json +16 -0
  162. package/fixtures/atelier-inquiry-contract/withdrawal/valid/document.json +15 -0
  163. package/fixtures/atelier-instruction-adoption/context-receipt/invalid/document.json +18 -0
  164. package/fixtures/atelier-instruction-adoption/context-receipt/valid/document.json +17 -0
  165. package/fixtures/atelier-instruction-adoption/plan/invalid/document.json +63 -0
  166. package/fixtures/atelier-instruction-adoption/plan/valid/document.json +62 -0
  167. package/fixtures/atelier-instruction-adoption/receipt/invalid/document.json +22 -0
  168. package/fixtures/atelier-instruction-adoption/receipt/valid/document.json +21 -0
  169. package/fixtures/atelier-instruction-adoption/state/invalid/document.json +30 -0
  170. package/fixtures/atelier-instruction-adoption/state/valid/document.json +29 -0
  171. package/fixtures/atelier-interaction/act/invalid/document.json +25 -0
  172. package/fixtures/atelier-interaction/act/valid/document.json +24 -0
  173. package/fixtures/atelier-interaction/assessment/invalid/document.json +32 -0
  174. package/fixtures/atelier-interaction/assessment/valid/document.json +31 -0
  175. package/fixtures/atelier-interaction/observation/invalid/document.json +22 -0
  176. package/fixtures/atelier-interaction/observation/valid/document.json +21 -0
  177. package/fixtures/atelier-interaction/policy/invalid/document.json +20 -0
  178. package/fixtures/atelier-interaction/policy/valid/document.json +19 -0
  179. package/fixtures/atelier-judgment/case/invalid/document.json +76 -0
  180. package/fixtures/atelier-judgment/case/valid/document.json +75 -0
  181. package/fixtures/atelier-judgment/decision/invalid/document.json +38 -0
  182. package/fixtures/atelier-judgment/decision/valid/document.json +37 -0
  183. package/fixtures/atelier-judgment/native-decision.md +3 -0
  184. package/fixtures/atelier-judgment/practice-reconsideration/definition.json +92 -0
  185. package/fixtures/atelier-judgment/practice-reconsideration/scenario.json +435 -0
  186. package/fixtures/atelier-knowledge-contract/activation/invalid/document.json +26 -0
  187. package/fixtures/atelier-knowledge-contract/activation/valid/document.json +25 -0
  188. package/fixtures/atelier-knowledge-contract/contribution/invalid/document.json +34 -0
  189. package/fixtures/atelier-knowledge-contract/contribution/valid/document.json +33 -0
  190. package/fixtures/atelier-knowledge-contract/domain/invalid/document.json +41 -0
  191. package/fixtures/atelier-knowledge-contract/domain/valid/document.json +40 -0
  192. package/fixtures/atelier-knowledge-contract/domain-revision/invalid/document.json +46 -0
  193. package/fixtures/atelier-knowledge-contract/domain-revision/valid/document.json +45 -0
  194. package/fixtures/atelier-knowledge-contract/evaluation/invalid/document.json +21 -0
  195. package/fixtures/atelier-knowledge-contract/evaluation/valid/document.json +20 -0
  196. package/fixtures/atelier-knowledge-contract/ledger/invalid/document.json +318 -0
  197. package/fixtures/atelier-knowledge-contract/ledger/valid/document.json +317 -0
  198. package/fixtures/atelier-knowledge-contract/relation/invalid/document.json +25 -0
  199. package/fixtures/atelier-knowledge-contract/relation/valid/document.json +24 -0
  200. package/fixtures/atelier-knowledge-contract/review/invalid/document.json +18 -0
  201. package/fixtures/atelier-knowledge-contract/review/valid/document.json +17 -0
  202. package/fixtures/atelier-knowledge-contract/withdrawal/invalid/document.json +16 -0
  203. package/fixtures/atelier-knowledge-contract/withdrawal/valid/document.json +15 -0
  204. package/fixtures/atelier-learning/invalid/authority.json +14 -0
  205. package/fixtures/atelier-learning/valid/capture.json +13 -0
  206. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/authority-key.json +17 -0
  207. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/nonempty-ext.json +25 -0
  208. package/fixtures/atelier-personal-workspace-contract/manifest/invalid/wrong-schema.json +22 -0
  209. package/fixtures/atelier-personal-workspace-contract/manifest/valid/manifest.json +22 -0
  210. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/authority-key.json +25 -0
  211. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/unknown-top-level-field.json +27 -0
  212. package/fixtures/atelier-personal-workspace-contract/overlay/invalid/wrong-schema.json +24 -0
  213. package/fixtures/atelier-trackable/definition/invalid/document.json +15 -0
  214. package/fixtures/atelier-trackable/definition/valid/document.json +14 -0
  215. package/fixtures/atelier-trackable/request/invalid/document.json +23 -0
  216. package/fixtures/atelier-trackable/request/valid/document.json +22 -0
  217. package/fixtures/boundary-delegations/invalid/authority-key.v1.json +30 -0
  218. package/fixtures/boundary-delegations/invalid/push-operation.v1.json +28 -0
  219. package/fixtures/boundary-delegations/invalid/unsigned.v1.json +25 -0
  220. package/fixtures/boundary-delegations/valid/empty.v1.json +4 -0
  221. package/fixtures/boundary-delegations/valid/signed-operator.v1.json +30 -0
  222. package/fixtures/boundary-owner-keys/invalid/wrong-algorithm.v1.json +15 -0
  223. package/fixtures/boundary-owner-keys/invalid/wrong-curve.v1.json +15 -0
  224. package/fixtures/boundary-owner-keys/valid/one-owner.v1.json +17 -0
  225. package/fixtures/capability-packages/adoption.example.json +70 -0
  226. package/fixtures/capability-packages/evidence-review/capability-package.json +58 -0
  227. package/fixtures/capability-packages/evidence-review/capability-release.json +84 -0
  228. package/fixtures/capability-packages/evidence-review/evaluation.md +15 -0
  229. package/fixtures/capability-packages/evidence-review/skills/evidence-review/SKILL.md +22 -0
  230. package/fixtures/capability-packages/evidence-review/skills/evidence-review/references/ledger.md +7 -0
  231. package/fixtures/capability-packages/research/capability-package.json +88 -0
  232. package/fixtures/capability-packages/research/capability-release.json +134 -0
  233. package/fixtures/capability-packages/research/evaluation.md +15 -0
  234. package/fixtures/capability-packages/research/skills/research-integrate/SKILL.md +29 -0
  235. package/fixtures/capability-packages/research/skills/research-integrate/references/integration.md +10 -0
  236. package/fixtures/capability-packages/research/skills/research-plan/SKILL.md +27 -0
  237. package/fixtures/capability-packages/research/skills/research-plan/references/inquiries.md +26 -0
  238. package/fixtures/capability-packages/research/skills/research-synthesize/SKILL.md +23 -0
  239. package/fixtures/capability-packages/research/skills/research-synthesize/references/synthesis.md +12 -0
  240. package/fixtures/evidence-navigation/invalid/duplicate-operation.json +16 -0
  241. package/fixtures/evidence-navigation/invalid/instruction-kind.json +36 -0
  242. package/fixtures/evidence-navigation/invalid/invalid-digest.json +36 -0
  243. package/fixtures/evidence-navigation/invalid/invalid-time.json +36 -0
  244. package/fixtures/evidence-navigation/invalid/missing-attribution.json +35 -0
  245. package/fixtures/evidence-navigation/invalid/reserved-extension.json +19 -0
  246. package/fixtures/evidence-navigation/invalid/unattributed-acceptance.json +36 -0
  247. package/fixtures/evidence-navigation/invalid/uncoerced-version.json +16 -0
  248. package/fixtures/evidence-navigation/invalid/unknown-currency.json +17 -0
  249. package/fixtures/evidence-navigation/invalid/unknown-selector-field.json +37 -0
  250. package/fixtures/evidence-navigation/invalid/unsupported-operation.json +15 -0
  251. package/fixtures/evidence-navigation/valid/claim.json +36 -0
  252. package/fixtures/evidence-navigation/valid/host.json +16 -0
  253. package/fixtures/evidence-navigation/valid/profile.json +16 -0
  254. package/fixtures/evidence-navigation/valid/snapshot.json +17 -0
  255. package/fixtures/harness-packages/build-harness/capability-package.json +61 -0
  256. package/fixtures/harness-packages/build-harness/capability-release.json +82 -0
  257. package/fixtures/harness-packages/build-harness/evaluation.md +3 -0
  258. package/fixtures/harness-packages/build-harness/skills/atelier-build-harness/SKILL.md +59 -0
  259. package/fixtures/harness-packages/knowledge-harness/capability-package.json +61 -0
  260. package/fixtures/harness-packages/knowledge-harness/capability-release.json +82 -0
  261. package/fixtures/harness-packages/knowledge-harness/evaluation.md +3 -0
  262. package/fixtures/harness-packages/knowledge-harness/skills/atelier-knowledge-harness/SKILL.md +60 -0
  263. package/fixtures/harnesses/learning-cycle.json +780 -0
  264. package/fixtures/inquiry/workshop.json +675 -0
  265. package/fixtures/inquiry-packages/discovery-harness/capability-package.json +61 -0
  266. package/fixtures/inquiry-packages/discovery-harness/capability-release.json +82 -0
  267. package/fixtures/inquiry-packages/discovery-harness/evaluation.md +3 -0
  268. package/fixtures/inquiry-packages/discovery-harness/skills/atelier-discovery-harness/SKILL.md +48 -0
  269. package/fixtures/inquiry-packages/research-harness/capability-package.json +61 -0
  270. package/fixtures/inquiry-packages/research-harness/capability-release.json +82 -0
  271. package/fixtures/inquiry-packages/research-harness/evaluation.md +3 -0
  272. package/fixtures/inquiry-packages/research-harness/skills/atelier-research-harness/SKILL.md +43 -0
  273. package/fixtures/knowledge-health/calibration-suite.json +26 -0
  274. package/fixtures/knowledge-health/calibration-trial.json +37 -0
  275. package/fixtures/knowledge-health/corrected/checklist.md +18 -0
  276. package/fixtures/knowledge-health/devday/participant-record.json +19 -0
  277. package/fixtures/knowledge-health/expected-summary.json +27 -0
  278. package/fixtures/knowledge-health/workshop/README.md +20 -0
  279. package/fixtures/knowledge-health/workshop/atelier.project.json +7 -0
  280. package/fixtures/knowledge-health/workshop/knowledge-plan.json +65 -0
  281. package/fixtures/knowledge-health/workshop/records/checklist.md +18 -0
  282. package/fixtures/knowledge-health/workshop/records/workshop.md +18 -0
  283. package/fixtures/knowledge-health/workshop/repo-access.v1.json +5 -0
  284. package/fixtures/knowledge-health/workspace/atelier.project.json +18 -0
  285. package/fixtures/knowledge-health/workspace/knowledge-plan.json +74 -0
  286. package/fixtures/knowledge-health/workspace/records/checklist.md +18 -0
  287. package/fixtures/knowledge-health/workspace/records/pilot.md +16 -0
  288. package/fixtures/knowledge-health/workspace/repo-access.v1.json +9 -0
  289. package/fixtures/personal-workspace/overlay.json +24 -0
  290. package/fixtures/templates/local-library.v1.json +75 -0
  291. package/fixtures/templates/upgrade-contracts/adoption-policy.v2/invalid.json +16 -0
  292. package/fixtures/templates/upgrade-contracts/adoption-policy.v2/valid.json +13 -0
  293. package/fixtures/templates/upgrade-contracts/migration.v3/invalid.json +24 -0
  294. package/fixtures/templates/upgrade-contracts/migration.v3/valid.json +21 -0
  295. package/fixtures/templates/upgrade-contracts/template-adoption.v1/invalid.json +60 -0
  296. package/fixtures/templates/upgrade-contracts/template-adoption.v1/valid.json +57 -0
  297. package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/invalid.json +85 -0
  298. package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/valid.json +82 -0
  299. package/package.json +59 -5
  300. package/skills/claude/atelier-build-harness/SKILL.md +59 -0
  301. package/skills/claude/atelier-coordination/SKILL.md +32 -0
  302. package/skills/claude/atelier-discovery-harness/SKILL.md +48 -0
  303. package/skills/claude/atelier-guided-upgrade/SKILL.md +29 -0
  304. package/skills/claude/atelier-interaction/SKILL.md +34 -0
  305. package/skills/claude/atelier-knowledge-harness/SKILL.md +60 -0
  306. package/skills/claude/atelier-knowledge-setup/SKILL.md +72 -0
  307. package/skills/claude/atelier-practical-judgment/SKILL.md +64 -0
  308. package/skills/claude/atelier-research-harness/SKILL.md +43 -0
  309. package/skills/claude/atelier-skill-steward/SKILL.md +53 -0
  310. package/skills/claude/atelier-trackables/SKILL.md +40 -0
  311. package/skills/codex/atelier-build-harness/SKILL.md +59 -0
  312. package/skills/codex/atelier-coordination/SKILL.md +32 -0
  313. package/skills/codex/atelier-discovery-harness/SKILL.md +48 -0
  314. package/skills/codex/atelier-guided-upgrade/SKILL.md +29 -0
  315. package/skills/codex/atelier-interaction/SKILL.md +34 -0
  316. package/skills/codex/atelier-knowledge-harness/SKILL.md +60 -0
  317. package/skills/codex/atelier-knowledge-setup/SKILL.md +72 -0
  318. package/skills/codex/atelier-practical-judgment/SKILL.md +64 -0
  319. package/skills/codex/atelier-research-harness/SKILL.md +43 -0
  320. package/skills/codex/atelier-skill-steward/SKILL.md +53 -0
  321. package/skills/codex/atelier-trackables/SKILL.md +40 -0
  322. package/src/architecture/catalog.mjs +355 -0
  323. package/src/architecture/index.mjs +93 -0
  324. package/src/boundary/content-rules.mjs +4 -2
  325. package/src/boundary/delegation-command.mjs +158 -0
  326. package/src/boundary/delegation.mjs +396 -0
  327. package/src/boundary/policy.mjs +52 -10
  328. package/src/build/git.mjs +18 -0
  329. package/src/build/index.mjs +3 -0
  330. package/src/build/ledger.mjs +88 -0
  331. package/src/capabilities/adoption.mjs +381 -0
  332. package/src/capabilities/evidence.mjs +140 -0
  333. package/src/capabilities/files.mjs +124 -0
  334. package/src/capabilities/index.mjs +4 -0
  335. package/src/capabilities/instructions.mjs +250 -0
  336. package/src/capabilities/package.mjs +136 -0
  337. package/src/cli/command-failure.mjs +36 -0
  338. package/src/cli/execute-command.mjs +16 -2
  339. package/src/cli/run.mjs +65 -9
  340. package/src/coauthor/store.mjs +43 -2
  341. package/src/collaboration/proposals.mjs +189 -0
  342. package/src/commands/architecture.mjs +27 -0
  343. package/src/commands/boundary.mjs +3 -0
  344. package/src/commands/capability.mjs +73 -0
  345. package/src/commands/enroll.mjs +3 -0
  346. package/src/commands/harness.mjs +79 -0
  347. package/src/commands/ingest.mjs +39 -0
  348. package/src/commands/init.mjs +4 -1
  349. package/src/commands/inquiry.mjs +66 -0
  350. package/src/commands/knowledge-semantic.mjs +128 -0
  351. package/src/commands/knowledge.mjs +119 -0
  352. package/src/commands/learn.mjs +61 -0
  353. package/src/commands/obsidian.mjs +754 -63
  354. package/src/commands/practice.mjs +24 -0
  355. package/src/commands/setup.mjs +22 -2
  356. package/src/commands/trackable.mjs +19 -0
  357. package/src/contracts/corpus.mjs +30 -0
  358. package/src/coordination/index.mjs +110 -0
  359. package/src/evidence-navigation/contracts.mjs +60 -0
  360. package/src/evidence-navigation/evaluate.mjs +69 -0
  361. package/src/evidence-navigation/generation.mjs +22 -0
  362. package/src/evidence-navigation/index.mjs +2 -0
  363. package/src/evidence-navigation/local.mjs +167 -0
  364. package/src/evidence-navigation/schema.generated.mjs +604 -0
  365. package/src/evidence-navigation/types.mjs +12 -0
  366. package/src/export/atelier-export-contract.mjs +35 -8
  367. package/src/graph/enroll.mjs +248 -0
  368. package/src/graph/graph.mjs +17 -1
  369. package/src/graph/knowledge-graph.mjs +58 -8
  370. package/src/harnesses/contracts.mjs +41 -0
  371. package/src/harnesses/exchange.mjs +154 -0
  372. package/src/harnesses/feedback.mjs +16 -0
  373. package/src/harnesses/history.mjs +37 -0
  374. package/src/harnesses/index.mjs +4 -0
  375. package/src/harnesses/store.mjs +29 -0
  376. package/src/ingestion/contracts.mjs +41 -0
  377. package/src/ingestion/evaluation.mjs +119 -0
  378. package/src/ingestion/optional/composition/index.mjs +171 -0
  379. package/src/ingestion/optional/evaluation/index.mjs +219 -0
  380. package/src/ingestion/optional/graphify/composition-binding.mjs +60 -0
  381. package/src/ingestion/optional/graphify/composition_receiving.py +185 -0
  382. package/src/ingestion/optional/graphify/graphify_supplier.py +933 -0
  383. package/src/ingestion/optional/graphify/json_bridge.py +163 -0
  384. package/src/ingestion/optional/graphify/query_receiving.py +209 -0
  385. package/src/ingestion/optional/index.mjs +9 -0
  386. package/src/ingestion/optional/jev/bridge.mjs +166 -0
  387. package/src/ingestion/optional/jev/composition-binding.mjs +116 -0
  388. package/src/ingestion/optional/jev/judgments.mjs +174 -0
  389. package/src/ingestion/optional/jev/native-translation.mjs +32 -0
  390. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/__init__.py +7 -0
  391. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/adapter.py +966 -0
  392. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/artifacts.py +101 -0
  393. package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/projection.py +146 -0
  394. package/src/ingestion/optional/lightrag/composition-binding.mjs +67 -0
  395. package/src/ingestion/optional/vanilla/composition-binding.mjs +102 -0
  396. package/src/ingestion/optional/vanilla/index.mjs +218 -0
  397. package/src/ingestion/optional/vanilla/native-normalization.mjs +187 -0
  398. package/src/ingestion/processors.mjs +218 -0
  399. package/src/ingestion/semantic.mjs +203 -0
  400. package/src/ingestion/store.mjs +372 -0
  401. package/src/inquiry/beliefs.mjs +32 -0
  402. package/src/inquiry/contracts.mjs +23 -0
  403. package/src/inquiry/index.mjs +5 -0
  404. package/src/inquiry/ledger.mjs +135 -0
  405. package/src/inquiry/lenses.mjs +15 -0
  406. package/src/inquiry/projection.mjs +77 -0
  407. package/src/inquiry/store.mjs +35 -0
  408. package/src/intake/read-scope.mjs +12 -0
  409. package/src/intake/store.mjs +69 -6
  410. package/src/interaction/index.mjs +91 -0
  411. package/src/judgment/index.mjs +82 -0
  412. package/src/judgment/practice-evaluation.mjs +70 -0
  413. package/src/judgment/practice.mjs +144 -0
  414. package/src/knowledge/context.mjs +217 -0
  415. package/src/knowledge/index.mjs +5 -0
  416. package/src/knowledge/ingestion.mjs +79 -0
  417. package/src/knowledge/intake.mjs +33 -0
  418. package/src/knowledge/ledger.mjs +110 -0
  419. package/src/knowledge/participatory/guidance.mjs +36 -0
  420. package/src/knowledge/participatory/guided-contribution.mjs +44 -0
  421. package/src/knowledge/participatory/index.mjs +2 -0
  422. package/src/knowledge/participatory/installed-workshop.mjs +108 -0
  423. package/src/knowledge/plan.mjs +67 -0
  424. package/src/knowledge/projection.mjs +43 -0
  425. package/src/knowledge/semantic-operation.mjs +567 -0
  426. package/src/knowledge/sessions.mjs +467 -0
  427. package/src/knowledge/workspace.mjs +295 -0
  428. package/src/knowledge-health/assessment.mjs +165 -0
  429. package/src/knowledge-health/capabilities.mjs +350 -0
  430. package/src/knowledge-health/context.mjs +62 -0
  431. package/src/knowledge-health/example.mjs +47 -0
  432. package/src/knowledge-health/index.mjs +10 -0
  433. package/src/knowledge-health/owner-join.mjs +88 -0
  434. package/src/knowledge-health/proof/common.mjs +24 -0
  435. package/src/knowledge-health/proof/installed-check.mjs +100 -0
  436. package/src/knowledge-health/proof/native-readback.mjs +37 -0
  437. package/src/knowledge-health/proof/rehearse.mjs +68 -0
  438. package/src/knowledge-health/proof/validate-participant.mjs +17 -0
  439. package/src/knowledge-health/proof/verify-native-capture.mjs +14 -0
  440. package/src/knowledge-health/proof/workshop-check.mjs +36 -0
  441. package/src/knowledge-health/rule-identity.mjs +44 -0
  442. package/src/knowledge-health/workshop-composition.mjs +19 -0
  443. package/src/knowledge-health/workshop-profile.mjs +176 -0
  444. package/src/knowledge-health/workshop.mjs +99 -0
  445. package/src/learning/adapters.mjs +68 -0
  446. package/src/learning/assistance.mjs +127 -0
  447. package/src/learning/contracts.mjs +65 -0
  448. package/src/learning/store.mjs +272 -0
  449. package/src/personal-workspace/index.mjs +391 -0
  450. package/src/personal-workspace/selection.mjs +385 -0
  451. package/src/project/config.mjs +8 -0
  452. package/src/project/durable-state.mjs +3 -1
  453. package/src/project/file-class.mjs +1 -1
  454. package/src/projection/obsidian/edits/apply.mjs +55 -16
  455. package/src/projection/obsidian/personal-workspace.mjs +436 -0
  456. package/src/projection/obsidian/proposals/adapter.mjs +47 -8
  457. package/src/projection/obsidian/proposals/observation.mjs +10 -2
  458. package/src/projection/obsidian/publication/publisher.mjs +142 -13
  459. package/src/projection/obsidian/publication/vault-list.mjs +4 -3
  460. package/src/projection/obsidian/recovery/index.mjs +4 -1
  461. package/src/projection/obsidian/recovery/store.mjs +160 -7
  462. package/src/projection/obsidian/selection-ui/contribution.mjs +6 -5
  463. package/src/readiness/readiness.mjs +10 -3
  464. package/src/reflection/index.mjs +56 -0
  465. package/src/runtime/obsidian/app-production-seams.mjs +48 -16
  466. package/src/runtime/obsidian/app-registration.mjs +175 -28
  467. package/src/runtime/obsidian/app-restart.mjs +154 -0
  468. package/src/runtime/obsidian/engine.mjs +163 -20
  469. package/src/runtime/obsidian/extension-points.mjs +1 -1
  470. package/src/runtime/obsidian/index.mjs +10 -7
  471. package/src/runtime/obsidian/launch-plan.mjs +7 -4
  472. package/src/runtime/obsidian/lifecycle.mjs +92 -12
  473. package/src/runtime/obsidian/login-item.mjs +332 -0
  474. package/src/runtime/obsidian/machine-settings.mjs +119 -12
  475. package/src/runtime/obsidian/opening.mjs +171 -37
  476. package/src/runtime/obsidian/pipeline.mjs +71 -3
  477. package/src/runtime/obsidian/plugin-channel.mjs +11 -3
  478. package/src/runtime/obsidian/plugin-choice.mjs +16 -4
  479. package/src/runtime/obsidian/plugin-drift.mjs +59 -11
  480. package/src/runtime/obsidian/plugin-presence.mjs +14 -1
  481. package/src/runtime/obsidian/process-identity.mjs +20 -10
  482. package/src/runtime/obsidian/project-views.mjs +282 -0
  483. package/src/runtime/obsidian/questions.mjs +48 -0
  484. package/src/runtime/obsidian/release-watch.mjs +56 -0
  485. package/src/runtime/obsidian/service-main.mjs +99 -16
  486. package/src/runtime/obsidian/service-manager-production.mjs +61 -0
  487. package/src/runtime/obsidian/service-managers.mjs +275 -0
  488. package/src/runtime/obsidian/service-record.mjs +87 -23
  489. package/src/runtime/obsidian/service.mjs +36 -3
  490. package/src/runtime/obsidian/startup-adapters.mjs +59 -21
  491. package/src/runtime/obsidian/unheld-evidence.mjs +84 -0
  492. package/src/runtime/obsidian/vault-location.mjs +300 -0
  493. package/src/runtime/obsidian/view-counts.mjs +34 -0
  494. package/src/server/local-sidecar.mjs +169 -2
  495. package/src/server/server.mjs +28 -2
  496. package/src/template-bindings/project.mjs +92 -0
  497. package/src/templates/profile.mjs +225 -0
  498. package/src/trackables/domain.mjs +175 -0
  499. package/src/trackables/store.mjs +114 -0
  500. package/src/ui/knowledge-page.mjs +1388 -0
  501. package/src/upgrade/explanation.mjs +1 -1
  502. package/src/upgrade/template-participant.mjs +171 -0
  503. package/src/upgrade/transaction.mjs +72 -25
  504. package/src/upgrade/upgrade.mjs +1 -0
  505. package/templates/external-project-workspace/pack-lifecycle.json +6 -1
  506. package/templates/knowledge-workspace/.gitattributes +2 -0
  507. package/templates/knowledge-workspace/AGENTS.md +27 -0
  508. package/templates/knowledge-workspace/README.md +44 -0
  509. package/templates/knowledge-workspace/atelier.project.json +22 -0
  510. package/templates/knowledge-workspace/gitignore +6 -0
  511. package/templates/knowledge-workspace/knowledge-plan.json +111 -0
  512. package/templates/knowledge-workspace/knowledge-plan.schema.json +281 -0
  513. package/templates/knowledge-workspace/records/forecast.md +22 -0
  514. package/templates/knowledge-workspace/records/inspection.md +25 -0
  515. package/templates/knowledge-workspace/records/telescope.md +24 -0
  516. package/templates/knowledge-workspace/repo-access.v1.json +9 -0
@@ -0,0 +1,24 @@
1
+ import { planInstructionAdoption, applyInstructionAdoption, recoverInstructionAdoption, abandonInstructionAdoption, inspectInstructionAdoption, consumeInstructionContext } from '../capabilities/instructions.mjs'
2
+ import { reportCommandFailure, parseJsonRequest } from '../cli/command-failure.mjs'
3
+
4
+ const methods = { plan: planInstructionAdoption, apply: applyInstructionAdoption, recover: recoverInstructionAdoption, abandon: abandonInstructionAdoption, status: inspectInstructionAdoption, context: consumeInstructionContext }
5
+ const fields = {
6
+ plan: ['workspaceId', 'scope', 'harnessId', 'lessonId', 'target', 'slot', 'mode'],
7
+ apply: ['workspaceId', 'scope', 'harnessId', 'lessonId', 'target', 'slot', 'mode', 'confirm'],
8
+ recover: ['confirm'], abandon: ['confirm', 'destinationDigest'], status: [], context: ['target', 'slot', 'session', 'scope', 'harnessId'],
9
+ }
10
+ try {
11
+ const [command, ...rest] = process.argv.slice(2)
12
+ if (!methods[command] || rest.length) throw new Error('Usage: atelier practice plan|apply|recover|abandon|status|context (JSON stdin)')
13
+ const chunks = []; let bytes = 0
14
+ for await (const chunk of process.stdin) {
15
+ bytes += chunk.length
16
+ if (bytes > 256 * 1024) throw new Error('practice request exceeds limit')
17
+ chunks.push(chunk)
18
+ }
19
+ const body = parseJsonRequest(Buffer.concat(chunks), 'practice request')
20
+ if (!body || Array.isArray(body) || typeof body !== 'object' || Object.keys(body).some(k => !fields[command].includes(k))) throw new Error('invalid practice request fields')
21
+ console.log(JSON.stringify(methods[command]({ ...body, workspaceRoot: process.cwd() }), null, 2))
22
+ } catch (error) {
23
+ reportCommandFailure(error)
24
+ }
@@ -15,6 +15,14 @@ import {
15
15
  import { writeAtelierLock, loadAtelierLock, checkAtelierLock } from '../upgrade/upgrade.mjs'
16
16
  import { loadBoundaryPolicy, validateBoundaryPolicy } from '../boundary/policy.mjs'
17
17
  import { auditRepoIdentities } from '../project/repo-identity.mjs'
18
+ import {
19
+ DEFAULT_ENROLLMENT_AUDIENCE,
20
+ assertAudienceAllowed,
21
+ assertEnrollmentAudience,
22
+ enrollmentReport,
23
+ planDocumentEnrollment,
24
+ writeDocumentEnrollment,
25
+ } from '../graph/enroll.mjs'
18
26
 
19
27
  const PROFILE_SET = new Set(['single-repo', 'private-domain', 'shared-project', 'multi-repo', 'monorepo', 'control-workspace'])
20
28
  const IGNORE_LINES = [
@@ -190,6 +198,13 @@ function runAdopt(argv) {
190
198
  }
191
199
  const repoName = slug(firstString(args.name) || path.basename(target))
192
200
  const actor = slug(firstString(args.actor) || process.env.USER || 'owner')
201
+ if (typeof args['enroll-documents'] === 'string') throw new Error('--enroll-documents takes no value')
202
+ const enrollDocuments = args['enroll-documents'] === true
203
+ const audience = args.audience === undefined ? DEFAULT_ENROLLMENT_AUDIENCE : args.audience
204
+ if (args.audience !== undefined && !enrollDocuments) throw new Error('--audience applies only with --enroll-documents')
205
+ if (enrollDocuments) assertEnrollmentAudience(audience)
206
+ const include = firstString(args.include, args.includes)
207
+ const exclude = firstString(args.exclude, args.excludes)
193
208
  const projectPath = path.join(target, 'atelier.project.json')
194
209
  const existingProject = fs.existsSync(projectPath)
195
210
  ? resolveProjectConfig({ cwd: target, argv: ['--project', projectPath], writeLocalState: false }) : null
@@ -200,7 +215,7 @@ function runAdopt(argv) {
200
215
  graph: { repoAccessPath: 'repo-access.v1.json', outputPath: 'atelier-output/knowledge.graph.json' },
201
216
  projection: { outputRoot: 'atelier-output', readinessPath: 'atelier-output/atelier-readiness.json' },
202
217
  boundaries: { policyPath: 'boundary-policy.v1.json', governanceLedgerPath: 'governance/repo-boundary-ledger.md', strictNewRepos: true },
203
- setup: { profile, include: firstString(args.include, args.includes) || null, exclude: firstString(args.exclude, args.excludes) || null },
218
+ setup: { profile, ...(include ? { include } : {}), ...(exclude ? { exclude } : {}) },
204
219
  repos: [{ name: repoName, path: '.', readBoundary: profile === 'shared-project' ? 'team' : 'private', role: profile }],
205
220
  }
206
221
  const configErrors = validateProjectConfigDoc(proposedConfig)
@@ -217,6 +232,10 @@ function runAdopt(argv) {
217
232
  const proposedPolicy = priorPolicy.ok ? priorPolicy.policy : cleanUndefined(baseBoundaryPolicy({ repoName, profile, actor }))
218
233
  const proposedPolicyErrors = validateBoundaryPolicy(proposedPolicy, proposedProject)
219
234
  if (proposedPolicyErrors.length) throw new Error(`adopt requires a valid boundary policy: ${proposedPolicyErrors.join('; ')}`)
235
+ // An audience the policy would refuse is refused before any scaffold write.
236
+ if (enrollDocuments) {
237
+ assertAudienceAllowed({ policy: proposedPolicy, repoNames: (proposedProject.repos ?? []).map((repo) => repo.name), audience })
238
+ }
220
239
  if (prior.lock) {
221
240
  const report = checkAtelierLock(existingProject)
222
241
  if (!report.ok) throw new Error(`adopt cannot accept existing lock drift: ${report.errors.join('; ')}`)
@@ -245,7 +264,8 @@ function runAdopt(argv) {
245
264
  if (!fs.existsSync(lockPath)) writeAtelierLock({ project, templateId: `adopt:${profile}` })
246
265
  const lockReport = checkAtelierLock(project)
247
266
  if (!lockReport.ok) throw new Error(`adopt lock check failed: ${lockReport.errors.join('; ')}`)
248
- console.log(JSON.stringify({ ok: true, command: 'adopt', profile, target, projectPath }, null, 2))
267
+ const enrollment = enrollDocuments ? enrollmentReport(writeDocumentEnrollment(planDocumentEnrollment(project, { audience }))) : null
268
+ console.log(JSON.stringify({ ok: true, command: 'adopt', profile, target, projectPath, ...(enrollment ? { enrollment } : {}) }, null, 2))
249
269
  }
250
270
 
251
271
  function runDoctor(argv) {
@@ -0,0 +1,19 @@
1
+ import { createTrackableStore, previewTrackable, releaseTrackable } from '../trackables/store.mjs'
2
+ import { reportCommandFailure, parseJsonRequest } from '../cli/command-failure.mjs'
3
+ try {
4
+ const [command, ...rest] = process.argv.slice(2)
5
+ if (!['preview', 'release', 'execute', 'snapshot', 'view', 'export'].includes(command) || rest.length) throw new Error('Usage: atelier trackable preview|release|execute|snapshot|view|export (JSON stdin)')
6
+ const chunks = []; let length = 0
7
+ for await (const chunk of process.stdin) { length += chunk.length; if (length > 256 * 1024) throw new Error('request exceeds limit'); chunks.push(chunk) }
8
+ const input = parseJsonRequest(Buffer.concat(chunks), 'trackable request')
9
+ const fields = command === 'preview' ? ['definition', 'subject', 'at', 'effectiveAt', 'evidence'] : command === 'release' ? ['definition'] : ['scope', 'actor', ...(command === 'execute' ? ['command'] : command === 'view' ? ['instanceId', 'at'] : [])]
10
+ if (!input || Array.isArray(input) || typeof input !== 'object' || Object.keys(input).some(k => !fields.includes(k))) throw new Error('invalid trackable request fields')
11
+ let result
12
+ if (command === 'preview') result = previewTrackable(input)
13
+ else if (command === 'release') result = releaseTrackable(input.definition)
14
+ else {
15
+ const store = createTrackableStore({ workspaceRoot: process.cwd(), scope: input.scope, actor: input.actor })
16
+ result = command === 'execute' ? store.execute(input.command) : command === 'view' ? store.view({ instanceId: input.instanceId, at: input.at }) : command === 'export' ? store.exportHistory() : store.snapshot()
17
+ }
18
+ console.log(JSON.stringify(result, null, 2))
19
+ } catch (error) { reportCommandFailure(error) }
@@ -26,8 +26,36 @@ import { fileURLToPath } from 'node:url'
26
26
  // document, not a schema, and is deliberately absent.
27
27
 
28
28
  export const CONTRACT_CORPUS = [
29
+ { name: 'atelier-evidence-navigation', contractFile: 'contracts/atelier-evidence-navigation.v1.schema.json', fixtureRoot: 'fixtures/evidence-navigation', registry: false },
30
+ { name: 'atelier-personal-workspace-manifest', contractFile: 'contracts/atelier-personal-workspace-manifest.v1.schema.json', fixtureRoot: 'fixtures/atelier-personal-workspace-contract/manifest', registry: true },
31
+ { name: 'atelier-personal-workspace-overlay', contractFile: 'contracts/atelier-personal-workspace-overlay.v1.schema.json', validFiles: ['fixtures/personal-workspace/overlay.json'], invalidFiles: ['authority-key.json', 'unknown-top-level-field.json', 'wrong-schema.json'].map((file) => `fixtures/atelier-personal-workspace-contract/overlay/invalid/${file}`), registry: true },
32
+ { name: 'atelier-template-profile', contractFile: 'contracts/atelier-template-profile.v1.schema.json', validFiles: ['fixtures/templates/local-library.v1.json'], registry: false },
33
+ ...['adoption-policy.v2', 'migration.v3', 'template-adoption.v1', 'upgrade-plan.v3'].map(shape => ({
34
+ name: `atelier-template-${shape}`, contractFile: `contracts/atelier-${shape}.schema.json`,
35
+ validFiles: [`fixtures/templates/upgrade-contracts/${shape}/valid.json`],
36
+ invalidFiles: [`fixtures/templates/upgrade-contracts/${shape}/invalid.json`], registry: false,
37
+ })),
29
38
  { name: 'atelier-decision-request', contractFile: 'contracts/atelier-decision-request.v1.schema.json', fixtureRoot: 'fixtures/decisions/request', registry: false },
30
39
  { name: 'atelier-decision-result', contractFile: 'contracts/atelier-decision-result.v1.schema.json', fixtureRoot: 'fixtures/decisions/result', registry: false },
40
+ ...Object.entries({ interaction: ['observation', 'assessment', 'act', 'policy'], coordination: ['outcome', 'dependency', 'directive', 'disposition', 'recovery'] }).flatMap(([profile, shapes]) => shapes.map(shape => ({ name: `atelier-${profile}-${shape}`, contractFile: `contracts/atelier-${profile}.v1.schema.json`, docPointer: `#/$defs/${shape}`, fixtureRoot: `fixtures/atelier-${profile}/${shape}`, registry: true }))),
41
+ ...['definition', 'request'].map(shape => ({ name: `atelier-trackable-${shape}`, contractFile: 'contracts/atelier-trackable.v1.schema.json', docPointer: `#/$defs/${shape}`, fixtureRoot: `fixtures/atelier-trackable/${shape}`, registry: true })),
42
+ ...['case', 'decision'].map(shape => ({ name: `atelier-judgment-${shape}`, contractFile: 'contracts/atelier-judgment.v1.schema.json', docPointer: `#/$defs/${shape}`, fixtureRoot: `fixtures/atelier-judgment/${shape}`, registry: false })),
43
+ ...['state', 'plan', 'receipt', 'context-receipt'].map(shape => ({ name: `atelier-instruction-${shape}`, contractFile: 'contracts/atelier-instruction-adoption.v1.schema.json', docPointer: `#/$defs/${shape}`, fixtureRoot: `fixtures/atelier-instruction-adoption/${shape}`, registry: false })),
44
+ ...['catalog', 'binding'].map(shape => ({ name: `atelier-architecture-${shape}`, contractFile: 'contracts/atelier-architecture.v1.schema.json', docPointer: `#/$defs/${shape}`, fixtureRoot: `fixtures/atelier-architecture/${shape}`, registry: false })),
45
+ ...Object.entries({ knowledge: ['domain', 'domain-revision', 'contribution', 'evaluation', 'relation', 'review', 'withdrawal', 'activation', 'ledger'], build: ['objective', 'candidate', 'attempt', 'progress', 'gate', 'decision', 'delivery', 'ledger'], harness: ['handoff'] }).flatMap(([profile, shapes]) => shapes.map(shape => ({
46
+ name: `atelier-${profile}-${shape}`, contractFile: `contracts/atelier-${profile}.v1.schema.json`,
47
+ docPointer: `#/$defs/${shape}`, fixtureRoot: `fixtures/atelier-${profile}-contract/${shape}`, registry: false,
48
+ }))),
49
+ ...['campaign', 'hypothesis', 'request', 'source', 'bundle', 'assessment', 'decision', 'withdrawal', 'feedback', 'legacy-assessment', 'ledger', 'handoff'].map(shape => ({
50
+ name: `atelier-inquiry-${shape}`, contractFile: 'contracts/atelier-inquiry.v1.schema.json',
51
+ docPointer: `#/$defs/${shape}`, fixtureRoot: `fixtures/atelier-inquiry-contract/${shape}`, registry: true,
52
+ })),
53
+ ...['package', 'release', 'adoption', 'state', 'plan', 'event', 'journal', 'notice'].map(shape => ({
54
+ name: `atelier-capability-${shape}`, contractFile: 'contracts/atelier-capability.v1.schema.json',
55
+ docPointer: `#/$defs/${shape}`, fixtureRoot: `fixtures/atelier-capability-contract/${shape}`, registry: false,
56
+ })),
57
+ { name: 'atelier-ingestion', contractFile: 'contracts/atelier-ingestion.v1.schema.json', fixtureRoot: 'fixtures/atelier-ingestion', registry: true },
58
+ { name: 'atelier-learning', contractFile: 'contracts/atelier-learning.v1.schema.json', fixtureRoot: 'fixtures/atelier-learning', registry: true },
31
59
  { name: 'atelier-adoption-policy-v1', contractFile: 'contracts/atelier-adoption-policy.v1.schema.json', fixtureRoot: 'fixtures/atelier-upgrade-transaction/adoption-policy', registry: false },
32
60
  { name: 'atelier-migration-v2', contractFile: 'contracts/atelier-migration.v2.schema.json', fixtureRoot: 'fixtures/atelier-upgrade-transaction/migration', registry: false },
33
61
  { name: 'atelier-upgrade-plan-v2', contractFile: 'contracts/atelier-upgrade-plan.v2.schema.json', fixtureRoot: 'fixtures/atelier-upgrade-transaction/upgrade-plan', registry: false },
@@ -69,6 +97,8 @@ export const CONTRACT_CORPUS = [
69
97
  fixtureRoot: 'fixtures/boundary-policy',
70
98
  registry: false,
71
99
  },
100
+ { name: 'atelier-boundary-delegations', contractFile: 'contracts/atelier-boundary-delegations.v1.schema.json', fixtureRoot: 'fixtures/boundary-delegations', registry: true },
101
+ { name: 'atelier-boundary-owner-keys', contractFile: 'contracts/atelier-boundary-owner-keys.v1.schema.json', fixtureRoot: 'fixtures/boundary-owner-keys', registry: true },
72
102
  {
73
103
  name: 'atelier-export',
74
104
  contractFile: 'contracts/atelier-export.v1.schema.json',
@@ -0,0 +1,110 @@
1
+ import fs from 'node:fs'
2
+ import Ajv from 'ajv/dist/2020.js'
3
+ import addFormats from 'ajv-formats'
4
+ import { boundedLearningValue, learningDigest as digest } from '../learning/contracts.mjs'
5
+ import { buildCoordinationProposal } from '../build/index.mjs'
6
+ const schema = JSON.parse(fs.readFileSync(new URL('../../contracts/atelier-coordination.v1.schema.json', import.meta.url)))
7
+ const ajv = new Ajv({ strict: true, allErrors: true }); addFormats(ajv)
8
+ const validate = ajv.compile(schema)
9
+ const key = r => `${r.repository}/${r.id}`
10
+ export function validateCoordination(record) {
11
+ try { boundedLearningValue(record) } catch (error) { return [error.message] }
12
+ if (!validate(record)) return validate.errors.map(e => `${e.instancePath || '/'}: ${e.message}`)
13
+ const errors = []
14
+ if (Date.parse(record.expiresAt) <= Date.parse(record.observedAt)) errors.push('expiry must follow observation')
15
+ if (new Set(record.scope).size !== record.scope.length || !record.scope.length) errors.push('nonempty distinct scope required')
16
+ if (record.kind === 'dependency' && record.body.receiving.status !== 'missing' && record.body.receiving.receipt === null) errors.push('reported receipt or acceptance needs native receipt reference')
17
+ if (record.kind === 'outcome') {
18
+ if (new Set(record.body.gates.map(g => g.id)).size !== record.body.gates.length) errors.push('duplicate gate identity')
19
+ if (record.body.gates.some(g => ['passed', 'waived'].includes(g.status) && g.evidence === null)) errors.push('reported passed/waived gate needs evidence')
20
+ }
21
+ if (record.kind === 'disposition' && ['sent', 'read', 'applied', 'verified'].includes(record.body.stage) && record.body.evidence === null) errors.push('reported disposition needs native evidence')
22
+ return errors
23
+ }
24
+ export function coordinationReference(record) {
25
+ const errors = validateCoordination(record)
26
+ if (errors.length) throw new Error(errors.join('; '))
27
+ return { repository: record.repository, id: record.id, digest: digest(record) }
28
+ }
29
+ export function coordinationView({ records, at, maxAgeMs = 86400000 }) {
30
+ if (!Array.isArray(records) || records.length > 256 || !Number.isFinite(Date.parse(at)) || !Number.isSafeInteger(maxAgeMs) || maxAgeMs < 1 || maxAgeMs > 30 * 86400000) throw new Error('bounded coordination snapshot and time required')
31
+ const map = new Map(), freshness = new Map()
32
+ for (const record of records) {
33
+ coordinationReference(record)
34
+ if (map.has(key(record))) throw new Error('ambiguous repository record identity; select an exact snapshot')
35
+ map.set(key(record), record)
36
+ const age = Date.parse(at) - Date.parse(record.observedAt)
37
+ freshness.set(key(record), age < 0 ? 'unknown' : Date.parse(at) >= Date.parse(record.expiresAt) || age > maxAgeMs ? 'stale' : 'current-reported')
38
+ }
39
+ const resolves = (pin, kind) => {
40
+ const record = map.get(key(pin))
41
+ return record?.kind === kind && digest(record) === pin.digest && freshness.get(key(pin)) === 'current-reported' ? record : null
42
+ }
43
+ const dependencies = [], adjacency = new Map()
44
+ for (const record of records.filter(r => r.kind === 'dependency')) {
45
+ const { producer: pin, consumer, artifactDigest, receiving } = record.body
46
+ const producer = resolves(pin, 'outcome'), target = map.get(key(consumer)), reasons = []
47
+ if (freshness.get(key(record)) !== 'current-reported') reasons.push('dependency-report-not-current')
48
+ if (!producer) reasons.push('producer-missing-stale-or-changed')
49
+ if (!target || target.kind !== 'outcome' || freshness.get(key(consumer)) !== 'current-reported') reasons.push('consumer-missing-or-stale')
50
+ if (producer && (producer.body.lifecycle !== 'active' || producer.body.candidate?.artifactDigest !== artifactDigest)) reasons.push('producer-artifact-unavailable')
51
+ if (record.repository !== consumer.repository) reasons.push('receiving-report-outside-consumer-repository')
52
+ if (target && (!record.scope.every(s => target.scope.includes(s)) || (producer && !record.scope.every(s => producer.scope.includes(s))))) reasons.push('dependency-scope-differs')
53
+ if (receiving.status !== 'accepted') reasons.push(`receiving-${receiving.status}`)
54
+ if (!adjacency.has(key(consumer))) adjacency.set(key(consumer), [])
55
+ adjacency.get(key(consumer)).push(key(pin))
56
+ dependencies.push({ reference: coordinationReference(record), producer: pin, consumer, receiving, reasons, nativeReceiptVerified: false })
57
+ }
58
+ // Strongly connected components (Tarjan): every dependency inside one lies on
59
+ // a cycle, whatever order the records arrive in.
60
+ const cycles = [], component = new Map(), index = new Map(), low = new Map(), stack = [], onStack = new Set()
61
+ let counter = 0
62
+ function connect(node) {
63
+ index.set(node, counter); low.set(node, counter++); stack.push(node); onStack.add(node)
64
+ for (const next of adjacency.get(node) ?? []) {
65
+ if (!index.has(next)) { connect(next); low.set(node, Math.min(low.get(node), low.get(next))) }
66
+ else if (onStack.has(next)) low.set(node, Math.min(low.get(node), index.get(next)))
67
+ }
68
+ if (low.get(node) !== index.get(node)) return
69
+ const members = []
70
+ let member
71
+ do { member = stack.pop(); onStack.delete(member); members.push(member) } while (member !== node)
72
+ if (members.length > 1 || (adjacency.get(node) ?? []).includes(node)) {
73
+ members.sort()
74
+ for (const m of members) component.set(m, cycles.length)
75
+ cycles.push(members)
76
+ }
77
+ }
78
+ for (const node of [...adjacency.keys()].sort()) if (!index.has(node)) connect(node)
79
+ for (const dependency of dependencies) {
80
+ const group = component.get(key(dependency.consumer))
81
+ if (group !== undefined && group === component.get(key(dependency.producer))) dependency.reasons.push('dependency-cycle')
82
+ }
83
+ const directives = records.filter(r => r.kind === 'directive').map(directive => {
84
+ const pin = coordinationReference(directive)
85
+ const replacements = records.filter(r => r.kind === 'directive' && r.body.supersedes && digest(r.body.supersedes) === digest(pin) &&
86
+ r.repository === directive.repository && key(r.body.target) === key(directive.body.target) && digest([...r.scope].sort()) === digest([...directive.scope].sort()))
87
+ // Supersession is permanent: a replacement going stale withdraws its own
88
+ // report, never revives the directive it replaced.
89
+ const superseded = replacements.length > 0
90
+ const reports = records.filter(r => r.kind === 'disposition' && digest(r.body.directive) === digest(pin))
91
+ return { reference: pin, target: directive.body.target, freshness: freshness.get(key(directive)), supersedes: directive.body.supersedes,
92
+ supersededBy: replacements.map(coordinationReference), activeReported: !superseded && freshness.get(key(directive)) === 'current-reported',
93
+ reports: reports.map(r => ({ reference: coordinationReference(r), stage: r.body.stage, evidence: r.body.evidence,
94
+ applicable: !superseded && freshness.get(key(r)) === 'current-reported' && freshness.get(key(directive)) === 'current-reported' && key(r.body.recipient) === key(directive.body.target) && r.repository === directive.body.target.repository && r.scope.every(s => directive.scope.includes(s)),
95
+ nativeReceiptVerified: false })), executionAuthorized: false }
96
+ })
97
+ const outcomes = records.filter(r => r.kind === 'outcome').map(record => ({ reference: coordinationReference(record), owner: record.body.owner, purpose: record.body.purpose,
98
+ priority: record.body.priority, freshness: freshness.get(key(record)), lifecycle: record.body.lifecycle, candidate: record.body.candidate,
99
+ gates: record.body.gates.map(g => ({ ...g, candidateCurrent: record.body.candidate !== null && g.candidateDigest === digest(record.body.candidate), nativeEvidenceVerified: false })),
100
+ blockers: dependencies.filter(d => key(d.consumer) === key(record)).flatMap(d => d.reasons) }))
101
+ const recovery = records.filter(r => r.kind === 'recovery').map(record => ({ reference: coordinationReference(record), ...record.body,
102
+ freshness: freshness.get(key(record)), priorPresent: !!resolves(record.body.prior, 'outcome'), successorPresent: map.get(key(record.body.successor ?? {}))?.kind === 'outcome', owningRepository: record.repository === record.body.prior.repository, executionAuthorized: false }))
103
+ return { schema: 'atelier-coordination-view@v1', at, maxAgeMs, coverage: records.map(coordinationReference), outcomes, dependencies, directives, recovery, cycles,
104
+ freshness: 'relative-to-supplied-observations', completionVerified: false, authorityTransferred: false, executionAuthorized: false }
105
+ }
106
+ // Retain the native Build history and its own dependency/gate qualification.
107
+ // Additional portfolio records cannot change this result or waive its blockers.
108
+ export function coordinatedBuild({ records, buildRecords, dependencySnapshots = [], at, maxAgeMs }) {
109
+ return { coordination: coordinationView({ records, at, maxAgeMs }), build: buildCoordinationProposal(buildRecords, { dependencySnapshots }), authorityTransferred: false }
110
+ }
@@ -0,0 +1,60 @@
1
+ import Ajv from 'ajv/dist/2020.js'
2
+ import addFormats from 'ajv-formats'
3
+ import { evidenceSchema } from './schema.generated.mjs'
4
+
5
+ const ajv = new Ajv({ strict: true, allErrors: true, ownProperties: true,
6
+ coerceTypes: false, useDefaults: false, removeAdditional: false, validateFormats: true })
7
+ addFormats(ajv, { mode: 'full' })
8
+ ajv.addSchema(evidenceSchema)
9
+ const validators = new Map(Object.keys(evidenceSchema.$defs).map(name =>
10
+ [name, ajv.getSchema(`${evidenceSchema.$id}#/$defs/${name}`)]))
11
+
12
+ export const EVIDENCE_PROTOCOL = 'atelier-evidence-navigation@v1'
13
+ export const EVIDENCE_LIMITS = Object.freeze({ bytes: 262144, depth: 24, members: 8192, snapshots: 256, dependencyDepth: 12 })
14
+
15
+ // Public functions consume JSON, never getters, cyclic graphs, or custom objects.
16
+ // Copy before validation so no validator can mutate the caller's input.
17
+ export function evidenceJson(value) {
18
+ const active = new Set()
19
+ let remaining = EVIDENCE_LIMITS.members
20
+ function copy(item, depth) {
21
+ if (--remaining < 0 || depth > EVIDENCE_LIMITS.depth) throw new Error('evidence value exceeds bounds')
22
+ if (item === null || typeof item === 'boolean') return item
23
+ if (typeof item === 'string' && item.length <= EVIDENCE_LIMITS.bytes && !item.includes('\u0000')) return item
24
+ if (typeof item === 'number' && Number.isFinite(item)) return item
25
+ if (typeof item !== 'object' || active.has(item)) throw new Error('evidence value must be JSON')
26
+ const array = Array.isArray(item)
27
+ const prototype = Object.getPrototypeOf(item)
28
+ if (array ? prototype !== Array.prototype : ![Object.prototype, null].includes(prototype)) throw new Error('evidence value must be JSON')
29
+ active.add(item)
30
+ const entries = []
31
+ for (const key of Reflect.ownKeys(item)) {
32
+ if (array && key === 'length') continue
33
+ const descriptor = Object.getOwnPropertyDescriptor(item, key)
34
+ if (typeof key !== 'string' || !descriptor.enumerable || !Object.hasOwn(descriptor, 'value')) throw new Error('evidence value must be JSON')
35
+ entries.push([key, copy(descriptor.value, depth + 1)])
36
+ }
37
+ let result
38
+ if (array) {
39
+ const length = Object.getOwnPropertyDescriptor(item, 'length')?.value
40
+ if (entries.length !== length || entries.some(([key], index) => key !== String(index))) throw new Error('evidence array must be dense')
41
+ result = entries.map(([, value]) => value)
42
+ } else result = Object.fromEntries(entries)
43
+ active.delete(item)
44
+ return result
45
+ }
46
+ const result = copy(value, 0)
47
+ if (new TextEncoder().encode(JSON.stringify(result)).byteLength > EVIDENCE_LIMITS.bytes) throw new Error('evidence value exceeds bounds')
48
+ return result
49
+ }
50
+
51
+ export function validateEvidenceDocument(shape, value) {
52
+ if (typeof shape !== 'string') return { valid: false, reason: 'unsupported-shape' }
53
+ const validate = validators.get(shape)
54
+ if (typeof validate !== 'function') return { valid: false, reason: 'unsupported-shape' }
55
+ try {
56
+ return validate(evidenceJson(value))
57
+ ? { valid: true, reason: null }
58
+ : { valid: false, reason: 'invalid-document' }
59
+ } catch { return { valid: false, reason: 'invalid-document' } }
60
+ }
@@ -0,0 +1,69 @@
1
+ import { EVIDENCE_LIMITS, evidenceJson, validateEvidenceDocument } from './contracts.mjs'
2
+
3
+ const result = (status, reasons = []) => ({ status, reasons: [...new Set(reasons)], executionAuthorized: false, authorityTransferred: false, semanticTruthVerified: false })
4
+ const valid = (shape, value) => validateEvidenceDocument(shape, value).valid
5
+ const logicalKey = ref => JSON.stringify([ref.owner, ref.objectId, ref.selector.type, ref.selector.version, ref.selector.value])
6
+ const exactRef = (a, b) => logicalKey(a) === logicalKey(b) && a.revision === b.revision && a.contentDigest === b.contentDigest
7
+ const canonical = value => JSON.stringify(value, function (_key, item) {
8
+ return item && !Array.isArray(item) && typeof item === 'object'
9
+ ? Object.fromEntries(Object.keys(item).sort().map(key => [key, item[key]])) : item
10
+ })
11
+
12
+ /** Compare declared support. This assesses compatibility, never host qualification. */
13
+ export function assessEvidenceCompatibility(profile, host) {
14
+ let input
15
+ try { input = evidenceJson({ profile, host }) } catch { return result('unsupported', ['invalid-document']) }
16
+ if (!valid('profile', input.profile) || !valid('hostCapabilities', input.host)) return result('unsupported', ['invalid-document'])
17
+ const reasons = []
18
+ if (!input.host.protocols.includes(input.profile.protocol)) reasons.push('unsupported-protocol')
19
+ if (input.profile.operations.some(operation => !input.host.operations.includes(operation))) reasons.push('unsupported-operation')
20
+ if (input.profile.requiredCapabilities.some(required => !input.host.capabilities.some(capability => capability.id === required.id && capability.version === required.version))) reasons.push('unsupported-capability')
21
+ return result(reasons.length ? 'unsupported' : 'compatible', reasons)
22
+ }
23
+
24
+ /** Check exact supplied snapshots. Their authenticity and read permission stay with the host. */
25
+ export function assessEvidenceCurrency(reference, snapshots, options = {}) {
26
+ let input
27
+ try { input = evidenceJson({ reference, snapshots, options }) } catch { return result('unknown', ['invalid-document']) }
28
+ if (!input.options || typeof input.options !== 'object' || Array.isArray(input.options)) return result('unknown', ['invalid-document'])
29
+ const { at, maxDepth = EVIDENCE_LIMITS.dependencyDepth, maxNodes = EVIDENCE_LIMITS.snapshots } = input.options
30
+ if (!valid('evidenceRef', input.reference) || !Array.isArray(input.snapshots) || input.snapshots.length > EVIDENCE_LIMITS.snapshots ||
31
+ !input.snapshots.every(snapshot => valid('snapshot', snapshot)) || typeof at !== 'string' ||
32
+ !valid('validInterval', { from: at, until: null }) || !Number.isFinite(Date.parse(at)) ||
33
+ !Number.isSafeInteger(maxDepth) || maxDepth < 0 || maxDepth > EVIDENCE_LIMITS.dependencyDepth ||
34
+ !Number.isSafeInteger(maxNodes) || maxNodes < 1 || maxNodes > EVIDENCE_LIMITS.snapshots) return result('unknown', ['invalid-document'])
35
+ const index = new Map()
36
+ for (const snapshot of input.snapshots) {
37
+ const key = logicalKey(snapshot.reference)
38
+ index.set(key, [...(index.get(key) ?? []), snapshot])
39
+ }
40
+ let visited = 0
41
+ const reasons = new Set()
42
+ function visit(ref, path, depth) {
43
+ if (++visited > maxNodes || depth > maxDepth) { reasons.add('verification-bound'); return false }
44
+ const key = logicalKey(ref)
45
+ if (path.has(key)) { reasons.add('cyclic-dependency'); return false }
46
+ const matches = index.get(key) ?? []
47
+ if (matches.length !== 1) { reasons.add(matches.length ? 'ambiguous-snapshot' : 'missing-snapshot'); return false }
48
+ const snapshot = matches[0]
49
+ if (snapshot.currency !== 'current') { reasons.add(snapshot.currency === 'withdrawn-from-use' ? 'withdrawn' : 'not-current'); return false }
50
+ if (!exactRef(ref, snapshot.reference)) { reasons.add('changed-reference'); return false }
51
+ if (snapshot.validUntil !== null && !Number.isFinite(Date.parse(snapshot.validUntil))) { reasons.add('unrepresentable-expiry'); return false }
52
+ if (snapshot.validUntil !== null && Date.parse(at) >= Date.parse(snapshot.validUntil)) { reasons.add('expired'); return false }
53
+ const next = new Set(path).add(key)
54
+ return snapshot.dependencies.map(dependency => visit(dependency, next, depth + 1)).every(Boolean)
55
+ }
56
+ const current = visit(input.reference, new Set(), 0)
57
+ return result(current ? 'current' : 'not-current', [...reasons])
58
+ }
59
+
60
+ /** A later acceptance cannot change what kind of claim was recorded. */
61
+ export function assessClaimContinuity(previous, next) {
62
+ let input
63
+ try { input = evidenceJson({ previous, next }) } catch { return result('unsupported', ['invalid-document']) }
64
+ if (!valid('claim', input.previous) || !valid('claim', input.next)) return result('unsupported', ['invalid-document'])
65
+ if (input.previous.claimId !== input.next.claimId || input.previous.ownerRecordRef.owner !== input.next.ownerRecordRef.owner || input.previous.ownerRecordRef.objectId !== input.next.ownerRecordRef.objectId) return result('unsupported', ['different-claim-identity'])
66
+ if (input.previous.kind !== input.next.kind) return result('unsupported', ['immutable-claim-kind'])
67
+ if (input.previous.revision === input.next.revision && canonical(input.previous) !== canonical(input.next)) return result('unsupported', ['unchanged-claim-revision'])
68
+ return result('compatible')
69
+ }
@@ -0,0 +1,22 @@
1
+ // Generated from contracts. Run node scripts/generate-evidence-navigation.mjs.
2
+ export const evidenceGeneration = {
3
+ "schema": "atelier-evidence-navigation-generation@v1",
4
+ "contract": "https://mnstry.ai/schemas/atelier/atelier-evidence-navigation.v1.schema.json",
5
+ "contractDigest": "sha256:738a93062065af4dd3f3df70ca12a6ef87b9496893e9f3df68e3bdab0fb37930",
6
+ "generatorVersion": 2,
7
+ "validator": {
8
+ "name": "ajv",
9
+ "version": "8.20.0",
10
+ "schemaDraft": "2020-12"
11
+ },
12
+ "formats": {
13
+ "name": "ajv-formats",
14
+ "version": "3.0.1",
15
+ "mode": "full"
16
+ },
17
+ "distribution": "schema-and-types-with-package-validator",
18
+ "files": {
19
+ "src/evidence-navigation/schema.generated.mjs": "sha256:553f800381b92cef8550a80a6c0f4f95d310e0a744effb7a1a45e21b31bed46c",
20
+ "src/evidence-navigation/types.mjs": "sha256:5b4b771657a91e739de779bae00f002feafae917b4ce73ed1d8b27efa0052e5d"
21
+ }
22
+ }
@@ -0,0 +1,2 @@
1
+ export { EVIDENCE_PROTOCOL, EVIDENCE_LIMITS, validateEvidenceDocument } from './contracts.mjs'
2
+ export { assessEvidenceCompatibility, assessEvidenceCurrency, assessClaimContinuity } from './evaluate.mjs'
@@ -0,0 +1,167 @@
1
+ import { createHash, randomUUID } from 'node:crypto'
2
+ import { performance } from 'node:perf_hooks'
3
+ import { createIngestionStore } from '../ingestion/store.mjs'
4
+ import { evidenceJson } from './contracts.mjs'
5
+
6
+ const schema = 'atelier-local-evidence-result@v1'
7
+ const flags = { executionAuthorized: false, authorityTransferred: false, semanticTruthVerified: false }
8
+ const digest = text => createHash('sha256').update(text, 'utf8').digest('hex')
9
+ const bytes = text => Buffer.byteLength(text, 'utf8')
10
+ const refusal = reason => ({ schema, status: 'refused', reason, ...flags })
11
+ function fail(reason = 'not-available') { throw { reason } }
12
+ function record(input, keys) {
13
+ const value = evidenceJson(input)
14
+ if (!value || Array.isArray(value) || typeof value !== 'object' || Object.keys(value).some(key => !keys.includes(key))) fail('invalid-request')
15
+ return value
16
+ }
17
+ function positive(value, ceiling) { return Number.isSafeInteger(value) && value > 0 && value <= ceiling }
18
+ function clip(text, ceiling) {
19
+ if (bytes(text) <= ceiling) return { text, truncated: false }
20
+ let result = '', used = 0
21
+ for (const character of text) {
22
+ const size = bytes(character)
23
+ if (used + size > ceiling) break
24
+ result += character; used += size
25
+ }
26
+ return { text: result, truncated: true }
27
+ }
28
+
29
+ /**
30
+ * One host-owned session over one exact, whole-plan admission. Construction
31
+ * options and callbacks are trusted code, never model arguments. No writes,
32
+ * providers, or persisted handles. A separate host must qualify actual authority.
33
+ */
34
+ export function createLocalEvidenceReader({ workspaceRoot, workspaceId, plan,
35
+ admit, openStore = createIngestionStore, now = () => performance.now(), limits = {} } = {}) {
36
+ let binding, bounds, started
37
+ try {
38
+ binding = record(plan, ['planId', 'planDigest'])
39
+ bounds = { maxReads: 32, maxHandles: 32, maxTextBytes: 16384, maxTotalTextBytes: 65536, lifetimeMs: 60000,
40
+ ...record(limits, ['maxReads', 'maxHandles', 'maxTextBytes', 'maxTotalTextBytes', 'lifetimeMs']) }
41
+ if (!/^plan-[a-f0-9]{40}$/.test(binding.planId) || !/^sha256:[a-f0-9]{64}$/.test(binding.planDigest) ||
42
+ typeof workspaceRoot !== 'string' || typeof workspaceId !== 'string' ||
43
+ typeof admit !== 'function' || typeof openStore !== 'function' || typeof now !== 'function' ||
44
+ !positive(bounds.maxReads, 128) || !positive(bounds.maxHandles, 128) ||
45
+ !positive(bounds.maxTextBytes, 65536) || !positive(bounds.maxTotalTextBytes, 262144) ||
46
+ !positive(bounds.lifetimeMs, 600000)) throw new Error()
47
+ started = now()
48
+ if (!Number.isFinite(started)) throw new Error()
49
+ } catch { throw new Error('Invalid local evidence reader configuration') }
50
+ Object.freeze(binding)
51
+ const handles = new Map()
52
+ let reads = 0, releasedBytes = 0, closed = false, busy = false, lastTime = started
53
+ function live() {
54
+ const time = now()
55
+ if (closed || !Number.isFinite(time) || time < lastTime || time - started >= bounds.lifetimeMs) {
56
+ closed = true; handles.clear(); fail()
57
+ }
58
+ lastTime = time
59
+ }
60
+ function permission(operation, expected) {
61
+ live()
62
+ let decision
63
+ try {
64
+ const response = admit(Object.freeze({ operation, ...binding, readScope: 'all-plan' }))
65
+ let asynchronous = false
66
+ // Contain native Promise rejection without invoking an untrusted then getter.
67
+ try { Promise.prototype.then.call(response, undefined, () => {}); asynchronous = true } catch {}
68
+ if (asynchronous) fail()
69
+ decision = record(response, ['disposition', 'revision', 'readScope'])
70
+ }
71
+ catch { fail() }
72
+ if (decision.disposition !== 'permit' || decision.readScope !== 'all-plan' ||
73
+ typeof decision.revision !== 'string' || !decision.revision || decision.revision.length > 256 ||
74
+ (expected !== undefined && decision.revision !== expected)) fail()
75
+ live()
76
+ return decision.revision
77
+ }
78
+ function reserve(count) {
79
+ if (reads + count > bounds.maxReads || releasedBytes >= bounds.maxTotalTextBytes) fail('budget-exhausted')
80
+ reads += count // Failed reads retain their reservation; no free retries.
81
+ }
82
+ function exact(store, reference) {
83
+ live()
84
+ const value = store.getEvidence({ ...binding, ...reference })
85
+ if (!value || value.schema !== 'mnstry.atelier-ingestion-evidence@v1' || value.readScope !== 'all-plan' ||
86
+ value.planId !== binding.planId || value.planDigest !== binding.planDigest ||
87
+ value.sourceId !== reference.sourceId || value.sourceDigest !== reference.sourceDigest ||
88
+ value.attemptId !== reference.attemptId || value.locator?.kind !== reference.locator.kind ||
89
+ value.locator?.value !== reference.locator.value || value.freshness !== 'current' ||
90
+ value.integrity !== 'verified' || value.semanticAcceptance !== 'pending' || value.synthesized !== false ||
91
+ typeof value.text !== 'string' || bytes(value.text) > 262144) fail()
92
+ live()
93
+ return value.text
94
+ }
95
+ function execute(input, operation, body) {
96
+ if (busy) return refusal('not-available')
97
+ busy = true
98
+ try {
99
+ live()
100
+ let request
101
+ try { request = record(input, operation === 'search' ? ['query', 'limit', 'readScope'] : ['handle', 'readScope']) }
102
+ catch { fail('invalid-request') }
103
+ if (request.readScope !== undefined && request.readScope !== 'all-plan') fail('unsupported-scope')
104
+ return body(request)
105
+ } catch (error) {
106
+ // Never forward backend errors, path-bearing messages, or denied counts.
107
+ return refusal(['invalid-request', 'unsupported-scope', 'budget-exhausted'].includes(error?.reason) ? error.reason : 'not-available')
108
+ } finally { busy = false }
109
+ }
110
+ return Object.freeze({
111
+ search(input) {
112
+ return execute(input, 'search', request => {
113
+ const limit = request.limit ?? 5
114
+ if (typeof request.query !== 'string' || !request.query.trim() || request.query.length > 512 ||
115
+ bytes(request.query) > 2048 || request.query.toLowerCase().trim().split(/\s+/u).length > 32 || !positive(limit, 5)) fail('invalid-request')
116
+ const revision = permission('search')
117
+ if (handles.size + limit > bounds.maxHandles) fail('budget-exhausted')
118
+ reserve(1 + limit)
119
+ const store = openStore({ workspaceRoot, workspaceId })
120
+ permission('search', revision)
121
+ const found = store.query({ ...binding, query: request.query, limit })
122
+ if (!found || found.schema !== 'mnstry.atelier-ingestion-query@v1' || found.readScope !== 'all-plan' ||
123
+ found.planId !== binding.planId || found.planDigest !== binding.planDigest ||
124
+ !Array.isArray(found.hits) || found.hits.length > limit) fail()
125
+ const pending = [], items = []
126
+ let outputBytes = 0
127
+ for (const hit of found.hits) {
128
+ permission('search', revision)
129
+ const reference = evidenceJson({ sourceId: hit.sourceId, sourceDigest: hit.sourceDigest,
130
+ attemptId: hit.attemptId, locator: hit.locator })
131
+ // Query text is only a pointer. Exact fetch supplies every released byte.
132
+ const text = exact(store, reference)
133
+ const remaining = bounds.maxTotalTextBytes - releasedBytes - outputBytes
134
+ if (remaining <= 0) fail('budget-exhausted')
135
+ const projected = clip(text, Math.min(bounds.maxTextBytes, remaining))
136
+ outputBytes += bytes(projected.text)
137
+ const handle = randomUUID()
138
+ pending.push([handle, { reference, textDigest: digest(text), revision }])
139
+ items.push({ handle, ...projected, kind: 'source-evidence', semanticAcceptance: 'pending' })
140
+ }
141
+ permission('search', revision)
142
+ for (const [key, value] of pending) handles.set(key, value)
143
+ releasedBytes += outputBytes
144
+ return { schema, status: 'ok', items, coverage: 'partial', readScope: 'all-plan', ...flags }
145
+ })
146
+ },
147
+ get(input) {
148
+ return execute(input, 'get', request => {
149
+ if (typeof request.handle !== 'string' || request.handle.length > 64) fail('invalid-request')
150
+ const revision = permission('get')
151
+ const held = handles.get(request.handle)
152
+ if (!held || held.revision !== revision) fail()
153
+ reserve(1)
154
+ const store = openStore({ workspaceRoot, workspaceId })
155
+ permission('get', revision)
156
+ const text = exact(store, held.reference)
157
+ if (digest(text) !== held.textDigest) fail()
158
+ const projected = clip(text, Math.min(bounds.maxTextBytes, bounds.maxTotalTextBytes - releasedBytes))
159
+ permission('get', revision)
160
+ releasedBytes += bytes(projected.text)
161
+ return { schema, status: 'ok', item: { handle: request.handle, ...projected, kind: 'source-evidence', semanticAcceptance: 'pending' },
162
+ coverage: 'partial', readScope: 'all-plan', ...flags }
163
+ })
164
+ },
165
+ close() { closed = true; handles.clear() },
166
+ })
167
+ }