@mnstry/atelier 0.2.0-alpha.1 → 0.2.0-alpha.10

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 (414) hide show
  1. package/CHANGELOG.md +372 -0
  2. package/README.md +402 -205
  3. package/SECURITY.md +6 -1
  4. package/contracts/atelier-adoption-policy.v1.schema.json +49 -0
  5. package/contracts/atelier-coauthor.v1.schema.json +163 -0
  6. package/contracts/atelier-decision-request.v1.schema.json +476 -0
  7. package/contracts/atelier-decision-result.v1.schema.json +500 -0
  8. package/contracts/atelier-guide.v1.schema.json +227 -0
  9. package/contracts/atelier-intake.v1.schema.json +151 -0
  10. package/contracts/atelier-migration.v2.schema.json +61 -0
  11. package/contracts/atelier-obsidian-acceptance-receipt.v1.schema.json +211 -0
  12. package/contracts/atelier-obsidian-apply-policy.v1.schema.json +298 -0
  13. package/contracts/atelier-obsidian-corpus-profile.v1.schema.json +98 -0
  14. package/contracts/atelier-obsidian-edit-operation.v1.schema.json +138 -0
  15. package/contracts/atelier-obsidian-ext-settings.v1.schema.json +287 -0
  16. package/contracts/atelier-obsidian-generation-manifest.v1.schema.json +353 -0
  17. package/contracts/atelier-obsidian-proposal-receipt.v1.schema.json +110 -0
  18. package/contracts/atelier-obsidian-publication-journal.v1.schema.json +167 -0
  19. package/contracts/atelier-obsidian-scope.v1.schema.json +264 -0
  20. package/contracts/atelier-obsidian-service-state.v1.schema.json +149 -0
  21. package/contracts/atelier-obsidian-source-snapshot.v1.schema.json +179 -0
  22. package/contracts/atelier-pane-presentation.v1.schema.json +76 -0
  23. package/contracts/atelier-presentation.v1.schema.json +1293 -0
  24. package/contracts/atelier-repository-observation.v1.schema.json +163 -0
  25. package/contracts/atelier-review.v1.schema.json +1601 -0
  26. package/contracts/atelier-skill-steward.v1.schema.json +692 -0
  27. package/contracts/atelier-upgrade-plan.v2.schema.json +398 -0
  28. package/contracts/atelier-upgrade-receipt.v1.schema.json +99 -0
  29. package/contracts/atelier-vault-publication.v1.schema.json +58 -0
  30. package/contracts/public-api-baseline.json +57 -0
  31. package/docs/assurance-controls.md +49 -0
  32. package/docs/atelier-runtime.md +28 -2
  33. package/docs/atelier-sync.md +172 -0
  34. package/docs/blocks/audience-visibility.md +9 -0
  35. package/docs/blocks/claims.md +61 -0
  36. package/docs/blocks/conformance-admission.md +15 -0
  37. package/docs/blocks/will-not-do.md +18 -0
  38. package/docs/coauthor-session.md +57 -0
  39. package/docs/connected-composition.md +75 -0
  40. package/docs/continuity.md +3 -4
  41. package/docs/decisions.md +167 -0
  42. package/docs/design.md +167 -0
  43. package/docs/exact-upgrades.md +159 -0
  44. package/docs/extension-pack-lifecycle.md +33 -0
  45. package/docs/guided-upgrades.md +99 -0
  46. package/docs/install.md +99 -16
  47. package/docs/intake-and-guides.md +65 -0
  48. package/docs/integration-and-review-plan.md +409 -0
  49. package/docs/integration-contract-decisions.md +22 -0
  50. package/docs/knowledge-graph.md +8 -4
  51. package/docs/local-review.md +84 -0
  52. package/docs/local-services.md +328 -0
  53. package/docs/local-state.md +107 -0
  54. package/docs/obsidian-contract.md +690 -0
  55. package/docs/obsidian.md +423 -0
  56. package/docs/portable-presentation.md +328 -0
  57. package/docs/presentation-consumer-boundaries.md +75 -0
  58. package/docs/presentation-review-disposition.md +47 -0
  59. package/docs/project-command-inventory.md +38 -0
  60. package/docs/project-options.md +53 -0
  61. package/docs/release-engineering.md +174 -12
  62. package/docs/repo-boundary-guard.md +12 -2
  63. package/docs/review-portability.md +55 -0
  64. package/docs/skill-steward.md +156 -0
  65. package/docs/upgrade.md +146 -5
  66. package/docs/vault-service.md +292 -0
  67. package/fixtures/atelier-coauthor/invalid/authority.v1.json +5 -0
  68. package/fixtures/atelier-coauthor/valid/config.v1.json +12 -0
  69. package/fixtures/atelier-guide/invalid/authority.v1.json +11 -0
  70. package/fixtures/atelier-guide/valid/capability.v1.json +10 -0
  71. package/fixtures/atelier-guide/valid/consent.v1.json +11 -0
  72. package/fixtures/atelier-guide/valid/engagement.v1.json +7 -0
  73. package/fixtures/atelier-guide/valid/offer.v1.json +10 -0
  74. package/fixtures/atelier-intake/invalid/authority.v1.json +9 -0
  75. package/fixtures/atelier-intake/valid/attempt.v1.json +8 -0
  76. package/fixtures/atelier-intake/valid/completion.v1.json +9 -0
  77. package/fixtures/atelier-intake/valid/source.v1.json +7 -0
  78. package/fixtures/atelier-repository-observation/invalid/complete-with-blocker.v1.json +18 -0
  79. package/fixtures/atelier-repository-observation/valid/complete-local.v1.json +48 -0
  80. package/fixtures/atelier-review/invalid/authenticated-identity.v1.json +22 -0
  81. package/fixtures/atelier-review/valid/bound.v1.json +229 -0
  82. package/fixtures/atelier-review/valid/bundle.v1.json +267 -0
  83. package/fixtures/atelier-review/valid/contribution.v1.json +22 -0
  84. package/fixtures/atelier-review/valid/lifecycle.v1.json +14 -0
  85. package/fixtures/atelier-skill-steward/audit/invalid/source-mutation.v1.json +26 -0
  86. package/fixtures/atelier-skill-steward/audit/valid/clean.v1.json +26 -0
  87. package/fixtures/atelier-skill-steward/candidates/invalid/workflow-key.v1.json +37 -0
  88. package/fixtures/atelier-skill-steward/candidates/valid/create.v1.json +37 -0
  89. package/fixtures/atelier-skill-steward/lock/invalid/bad-digest.v1.json +18 -0
  90. package/fixtures/atelier-skill-steward/lock/valid/installed.v1.json +23 -0
  91. package/fixtures/atelier-skill-steward/plan/invalid/delete-action.v1.json +33 -0
  92. package/fixtures/atelier-skill-steward/plan/valid/add.v1.json +33 -0
  93. package/fixtures/atelier-upgrade-transaction/adoption-policy/invalid/example.json +12 -0
  94. package/fixtures/atelier-upgrade-transaction/adoption-policy/valid/example.json +11 -0
  95. package/fixtures/atelier-upgrade-transaction/migration/invalid/example.json +20 -0
  96. package/fixtures/atelier-upgrade-transaction/migration/valid/example.json +19 -0
  97. package/fixtures/atelier-upgrade-transaction/upgrade-plan/invalid/example.json +58 -0
  98. package/fixtures/atelier-upgrade-transaction/upgrade-plan/valid/example.json +57 -0
  99. package/fixtures/atelier-upgrade-transaction/upgrade-receipt/invalid/example.json +15 -0
  100. package/fixtures/atelier-upgrade-transaction/upgrade-receipt/valid/example.json +14 -0
  101. package/fixtures/atelier-vault-publication/invalid/publication.json +5 -0
  102. package/fixtures/atelier-vault-publication/valid/publication.json +11 -0
  103. package/fixtures/decisions/request/invalid/unknown-authority.v1.json +61 -0
  104. package/fixtures/decisions/request/valid/triage.v1.json +60 -0
  105. package/fixtures/decisions/result/invalid/execution-authority.v1.json +50 -0
  106. package/fixtures/decisions/result/valid/abstained.v1.json +23 -0
  107. package/fixtures/decisions/result/valid/assessed.v1.json +50 -0
  108. package/fixtures/obsidian/acceptance/ap05-extra-notes.json +14 -0
  109. package/fixtures/obsidian/acceptance/receipts/G07.valid.v1.json +63 -0
  110. package/fixtures/obsidian/acceptance/receipts/G13.valid.v1.json +69 -0
  111. package/fixtures/obsidian/acceptance/receipts/G14.valid.v1.json +62 -0
  112. package/fixtures/obsidian/acceptance/receipts/G15.valid.v1.json +56 -0
  113. package/fixtures/obsidian/acceptance/receipts/G16.valid.v1.json +73 -0
  114. package/fixtures/obsidian/acceptance/receipts/G17.valid.v1.json +75 -0
  115. package/fixtures/obsidian/acceptance/receipts/G18.valid.v1.json +64 -0
  116. package/fixtures/obsidian/acceptance/service-sentinels.json +10 -0
  117. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/duplicate-evidence-name.v1.json +39 -0
  118. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/evidence-by-absolute-path.v1.json +34 -0
  119. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/missing-candidate-tree.v1.json +33 -0
  120. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/no-evidence.v1.json +28 -0
  121. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/unknown-outcome.v1.json +34 -0
  122. package/fixtures/obsidian/contracts/acceptance-receipt/invalid/unknown-top-level-field.v1.json +35 -0
  123. package/fixtures/obsidian/contracts/acceptance-receipt/valid/node-gate.v1.json +34 -0
  124. package/fixtures/obsidian/contracts/apply-policy/invalid/automatic-without-edit-class.v1.json +27 -0
  125. package/fixtures/obsidian/contracts/apply-policy/invalid/conflict-overwrite.v1.json +29 -0
  126. package/fixtures/obsidian/contracts/apply-policy/invalid/missing-policy-digest.v1.json +28 -0
  127. package/fixtures/obsidian/contracts/apply-policy/invalid/unbounded-batch.v1.json +29 -0
  128. package/fixtures/obsidian/contracts/apply-policy/invalid/unimplemented-edit-class.v1.json +30 -0
  129. package/fixtures/obsidian/contracts/apply-policy/invalid/unknown-mode.v1.json +29 -0
  130. package/fixtures/obsidian/contracts/apply-policy/invalid/unknown-selector-operator.v1.json +22 -0
  131. package/fixtures/obsidian/contracts/apply-policy/invalid/unknown-top-level-field.v1.json +30 -0
  132. package/fixtures/obsidian/contracts/apply-policy/valid/automatic-scoped.v1.json +29 -0
  133. package/fixtures/obsidian/contracts/apply-policy/valid/manual-default.v1.json +20 -0
  134. package/fixtures/obsidian/contracts/corpus-profile/invalid/absolute-path-in-ext.v1.json +30 -0
  135. package/fixtures/obsidian/contracts/corpus-profile/invalid/absolute-repository-root.v1.json +27 -0
  136. package/fixtures/obsidian/contracts/corpus-profile/invalid/duplicate-repository-id.v1.json +27 -0
  137. package/fixtures/obsidian/contracts/corpus-profile/invalid/overlapping-managed-roots.v1.json +27 -0
  138. package/fixtures/obsidian/contracts/corpus-profile/invalid/unknown-enrollment.v1.json +27 -0
  139. package/fixtures/obsidian/contracts/corpus-profile/invalid/unknown-top-level-field.v1.json +28 -0
  140. package/fixtures/obsidian/contracts/corpus-profile/valid/three-repositories.v1.json +27 -0
  141. package/fixtures/obsidian/contracts/edit-operation/invalid/absolute-recovery-ref.v1.json +21 -0
  142. package/fixtures/obsidian/contracts/edit-operation/invalid/inline-observed-bytes.v1.json +22 -0
  143. package/fixtures/obsidian/contracts/edit-operation/invalid/missing-base-digest.v1.json +20 -0
  144. package/fixtures/obsidian/contracts/edit-operation/invalid/short-idempotency-key.v1.json +21 -0
  145. package/fixtures/obsidian/contracts/edit-operation/invalid/unknown-kind.v1.json +21 -0
  146. package/fixtures/obsidian/contracts/edit-operation/valid/pending-body-replacement.v1.json +21 -0
  147. package/fixtures/obsidian/contracts/ext-settings/invalid/absolute-path-prefix.v1.json +28 -0
  148. package/fixtures/obsidian/contracts/ext-settings/invalid/apply-policy-in-portable-settings.v1.json +30 -0
  149. package/fixtures/obsidian/contracts/ext-settings/invalid/duplicate-scope-id.v1.json +27 -0
  150. package/fixtures/obsidian/contracts/ext-settings/invalid/machine-local-vault-path.v1.json +28 -0
  151. package/fixtures/obsidian/contracts/ext-settings/invalid/service-port-in-portable-settings.v1.json +28 -0
  152. package/fixtures/obsidian/contracts/ext-settings/invalid/unknown-default-scope.v1.json +27 -0
  153. package/fixtures/obsidian/contracts/ext-settings/valid/disabled.v1.json +5 -0
  154. package/fixtures/obsidian/contracts/ext-settings/valid/enabled-with-scopes.v1.json +27 -0
  155. package/fixtures/obsidian/contracts/generation-manifest/invalid/absolute-note-path.v1.json +114 -0
  156. package/fixtures/obsidian/contracts/generation-manifest/invalid/complete-with-unwritten-notes.v1.json +114 -0
  157. package/fixtures/obsidian/contracts/generation-manifest/invalid/derived-link-claimed-declared.v1.json +114 -0
  158. package/fixtures/obsidian/contracts/generation-manifest/invalid/duplicate-note-identity.v1.json +114 -0
  159. package/fixtures/obsidian/contracts/generation-manifest/invalid/in-scope-endpoint-missing.v1.json +114 -0
  160. package/fixtures/obsidian/contracts/generation-manifest/invalid/title-only-note-path.v1.json +114 -0
  161. package/fixtures/obsidian/contracts/generation-manifest/invalid/unknown-note-field.v1.json +115 -0
  162. package/fixtures/obsidian/contracts/generation-manifest/invalid/unknown-relation-type.v1.json +114 -0
  163. package/fixtures/obsidian/contracts/generation-manifest/invalid/withheld-endpoint.v1.json +114 -0
  164. package/fixtures/obsidian/contracts/generation-manifest/valid/two-notes.v1.json +114 -0
  165. package/fixtures/obsidian/contracts/oracles/scope-cases.json +412 -0
  166. package/fixtures/obsidian/contracts/proposal-receipt/invalid/accepted-without-proposal-id.v1.json +12 -0
  167. package/fixtures/obsidian/contracts/proposal-receipt/invalid/missing-adapter-operation-id.v1.json +11 -0
  168. package/fixtures/obsidian/contracts/proposal-receipt/invalid/unknown-backpressure-outcome.v1.json +12 -0
  169. package/fixtures/obsidian/contracts/proposal-receipt/invalid/unknown-top-level-field.v1.json +13 -0
  170. package/fixtures/obsidian/contracts/proposal-receipt/valid/accepted-new.v1.json +12 -0
  171. package/fixtures/obsidian/contracts/proposal-receipt/valid/deferred.v1.json +12 -0
  172. package/fixtures/obsidian/contracts/publication-journal/invalid/absolute-recovery-ref.v1.json +47 -0
  173. package/fixtures/obsidian/contracts/publication-journal/invalid/duplicate-sequence.v1.json +47 -0
  174. package/fixtures/obsidian/contracts/publication-journal/invalid/empty-protocol-id.v1.json +47 -0
  175. package/fixtures/obsidian/contracts/publication-journal/invalid/missing-protocol-id.v1.json +46 -0
  176. package/fixtures/obsidian/contracts/publication-journal/invalid/unknown-entry-field.v1.json +48 -0
  177. package/fixtures/obsidian/contracts/publication-journal/invalid/unknown-state.v1.json +47 -0
  178. package/fixtures/obsidian/contracts/publication-journal/valid/committed.v1.json +47 -0
  179. package/fixtures/obsidian/contracts/publication-journal/valid/updating-after-restart.v1.json +22 -0
  180. package/fixtures/obsidian/contracts/scope/invalid/absolute-path-prefix.v1.json +15 -0
  181. package/fixtures/obsidian/contracts/scope/invalid/duplicate-ids.v1.json +18 -0
  182. package/fixtures/obsidian/contracts/scope/invalid/expansion-without-node-budget.v1.json +40 -0
  183. package/fixtures/obsidian/contracts/scope/invalid/full-mode-with-subset.v1.json +8 -0
  184. package/fixtures/obsidian/contracts/scope/invalid/unknown-mode.v1.json +41 -0
  185. package/fixtures/obsidian/contracts/scope/invalid/unknown-selector-key.v1.json +15 -0
  186. package/fixtures/obsidian/contracts/scope/invalid/unknown-selector-operator.v1.json +14 -0
  187. package/fixtures/obsidian/contracts/scope/invalid/unknown-top-level-field.v1.json +42 -0
  188. package/fixtures/obsidian/contracts/scope/valid/explicit-empty.v1.json +8 -0
  189. package/fixtures/obsidian/contracts/scope/valid/focus.v1.json +11 -0
  190. package/fixtures/obsidian/contracts/scope/valid/full.v1.json +8 -0
  191. package/fixtures/obsidian/contracts/scope/valid/scoped-set-expression.v1.json +41 -0
  192. package/fixtures/obsidian/contracts/service-state/invalid/hostname-instead-of-literal-loopback.v1.json +23 -0
  193. package/fixtures/obsidian/contracts/service-state/invalid/missing-consent.v1.json +18 -0
  194. package/fixtures/obsidian/contracts/service-state/invalid/privileged-port.v1.json +23 -0
  195. package/fixtures/obsidian/contracts/service-state/invalid/unknown-top-level-field.v1.json +24 -0
  196. package/fixtures/obsidian/contracts/service-state/invalid/wildcard-bind.v1.json +23 -0
  197. package/fixtures/obsidian/contracts/service-state/valid/healthy.v1.json +23 -0
  198. package/fixtures/obsidian/contracts/source-snapshot/invalid/absolute-file-path.v1.json +48 -0
  199. package/fixtures/obsidian/contracts/source-snapshot/invalid/duplicate-repository-id.v1.json +48 -0
  200. package/fixtures/obsidian/contracts/source-snapshot/invalid/mixed-read.v1.json +48 -0
  201. package/fixtures/obsidian/contracts/source-snapshot/invalid/parent-traversal-path.v1.json +48 -0
  202. package/fixtures/obsidian/contracts/source-snapshot/invalid/unknown-file-field.v1.json +49 -0
  203. package/fixtures/obsidian/contracts/source-snapshot/valid/two-repositories.v1.json +48 -0
  204. package/fixtures/obsidian/edits/workspace.json +65 -0
  205. package/fixtures/obsidian/materialization/expected-full.json +99 -0
  206. package/fixtures/obsidian/materialization/expected-scoped.json +39 -0
  207. package/fixtures/obsidian/materialization/workspace.json +54 -0
  208. package/fixtures/obsidian/proposals/expected-shapes.json +11 -0
  209. package/fixtures/projects/sample-workspace/content/source.html.kg.json +4 -1
  210. package/fixtures/projects/source-formats-workspace/content/data.json.kg.json +4 -1
  211. package/fixtures/projects/source-formats-workspace/content/logo.png.kg.json +4 -1
  212. package/fixtures/projects/source-formats-workspace/content/metrics.csv.kg.json +4 -1
  213. package/fixtures/projects/source-formats-workspace/content/pipeline.yaml.kg.json +4 -1
  214. package/fixtures/ui/presentation/pane.v1.json +7 -0
  215. package/fixtures/ui/presentation/reference.v1.json +293 -0
  216. package/package.json +86 -10
  217. package/skills/claude/atelier-guided-coauthor/SKILL.md +49 -0
  218. package/skills/claude/atelier-guided-upgrade/SKILL.md +97 -0
  219. package/skills/claude/atelier-local-service/SKILL.md +47 -0
  220. package/skills/claude/atelier-open/SKILL.md +11 -5
  221. package/skills/claude/atelier-public-boundary/SKILL.md +31 -0
  222. package/skills/claude/atelier-skill-steward/SKILL.md +62 -0
  223. package/skills/claude/mnstry-readiness/SKILL.md +5 -0
  224. package/skills/codex/atelier-guided-coauthor/SKILL.md +49 -0
  225. package/skills/codex/atelier-guided-upgrade/SKILL.md +97 -0
  226. package/skills/codex/atelier-local-service/SKILL.md +47 -0
  227. package/skills/codex/atelier-open/SKILL.md +11 -5
  228. package/skills/codex/atelier-public-boundary/SKILL.md +31 -0
  229. package/skills/codex/atelier-skill-steward/SKILL.md +62 -0
  230. package/skills/codex/mnstry-readiness/SKILL.md +5 -0
  231. package/src/access/preview-enforcer.mjs +84 -0
  232. package/src/boundary/content-rules.mjs +283 -20
  233. package/src/boundary/policy.mjs +213 -91
  234. package/src/cli/execute-command.mjs +36 -0
  235. package/src/cli/project-options.mjs +58 -0
  236. package/src/cli/run.mjs +78 -10
  237. package/src/coauthor/session.mjs +161 -0
  238. package/src/coauthor/store.mjs +173 -0
  239. package/src/collaboration/event-ledger.mjs +348 -0
  240. package/src/collaboration/index.mjs +17 -0
  241. package/src/collaboration/inspection-bundle.mjs +223 -0
  242. package/src/collaboration/proposals.mjs +265 -65
  243. package/src/collaboration/review-contracts.mjs +25 -0
  244. package/src/collaboration/review-store.mjs +305 -0
  245. package/src/commands/attestation.mjs +20 -6
  246. package/src/commands/coauthor.mjs +26 -0
  247. package/src/commands/config.mjs +6 -1
  248. package/src/commands/disclosure.mjs +133 -0
  249. package/src/commands/distribution.mjs +2 -1
  250. package/src/commands/extension-pack.mjs +17 -9
  251. package/src/commands/init.mjs +46 -6
  252. package/src/commands/obsidian.mjs +371 -0
  253. package/src/commands/review.mjs +147 -0
  254. package/src/commands/server.mjs +1 -4
  255. package/src/commands/setup.mjs +51 -14
  256. package/src/commands/skills.mjs +199 -0
  257. package/src/commands/sync.mjs +107 -0
  258. package/src/composition/registry.mjs +27 -0
  259. package/src/composition/wire.mjs +122 -0
  260. package/src/contracts/corpus.mjs +35 -0
  261. package/src/decisions/contracts.d.mts +96 -0
  262. package/src/decisions/contracts.mjs +321 -0
  263. package/src/disclosure/content-scan.mjs +206 -0
  264. package/src/egress/check.mjs +7 -38
  265. package/src/egress/forbidden-egress.mjs +32 -18
  266. package/src/export/atelier-export-contract.mjs +16 -1
  267. package/src/extension-packs/lifecycle.mjs +154 -0
  268. package/src/graph/graph.mjs +176 -316
  269. package/src/graph/knowledge-graph.mjs +643 -43
  270. package/src/guides/contracts.mjs +54 -0
  271. package/src/harness/context-client.mjs +9 -1
  272. package/src/index.mjs +41 -0
  273. package/src/intake/store.mjs +119 -0
  274. package/src/preview/channel.mjs +89 -0
  275. package/src/project/config.mjs +112 -52
  276. package/src/project/durable-state.mjs +161 -0
  277. package/src/project/file-class.mjs +180 -0
  278. package/src/project/package-root.mjs +10 -0
  279. package/src/project/path-match.mjs +38 -15
  280. package/src/project/private-state.mjs +120 -0
  281. package/src/projection/obsidian/contracts.mjs +571 -0
  282. package/src/projection/obsidian/edits/align.mjs +169 -0
  283. package/src/projection/obsidian/edits/apply.mjs +889 -0
  284. package/src/projection/obsidian/edits/arbitrate.mjs +414 -0
  285. package/src/projection/obsidian/edits/contribution.mjs +108 -0
  286. package/src/projection/obsidian/edits/index.mjs +19 -0
  287. package/src/projection/obsidian/edits/object-identity.mjs +61 -0
  288. package/src/projection/obsidian/edits/object-store.mjs +517 -0
  289. package/src/projection/obsidian/edits/observe.mjs +123 -0
  290. package/src/projection/obsidian/edits/policy.mjs +123 -0
  291. package/src/projection/obsidian/edits/regions.mjs +648 -0
  292. package/src/projection/obsidian/materialize/byte-lens.mjs +98 -0
  293. package/src/projection/obsidian/materialize/index.mjs +7 -0
  294. package/src/projection/obsidian/materialize/path-registry.mjs +105 -0
  295. package/src/projection/obsidian/materialize/prepare-view.mjs +746 -0
  296. package/src/projection/obsidian/materialize/settings.mjs +57 -0
  297. package/src/projection/obsidian/materialize/stage.mjs +27 -0
  298. package/src/projection/obsidian/proposals/adapter.mjs +572 -0
  299. package/src/projection/obsidian/proposals/backpressure.mjs +113 -0
  300. package/src/projection/obsidian/proposals/contribution.mjs +55 -0
  301. package/src/projection/obsidian/proposals/index.mjs +23 -0
  302. package/src/projection/obsidian/proposals/observation.mjs +216 -0
  303. package/src/projection/obsidian/proposals/queue.mjs +277 -0
  304. package/src/projection/obsidian/proposals/router.mjs +168 -0
  305. package/src/projection/obsidian/publication/bridge-script.mjs +266 -0
  306. package/src/projection/obsidian/publication/exchange.mjs +117 -0
  307. package/src/projection/obsidian/publication/index.mjs +5 -0
  308. package/src/projection/obsidian/publication/publisher.mjs +588 -0
  309. package/src/projection/obsidian/publication/test-seam.mjs +16 -0
  310. package/src/projection/obsidian/publication/transport.mjs +160 -0
  311. package/src/projection/obsidian/recovery/index.mjs +6 -0
  312. package/src/projection/obsidian/recovery/journal.mjs +134 -0
  313. package/src/projection/obsidian/recovery/late-writer.mjs +46 -0
  314. package/src/projection/obsidian/recovery/restart.mjs +316 -0
  315. package/src/projection/obsidian/recovery/store.mjs +234 -0
  316. package/src/projection/obsidian/selection-ui/conflict-view.mjs +91 -0
  317. package/src/projection/obsidian/selection-ui/contribution.mjs +141 -0
  318. package/src/projection/obsidian/selection-ui/focus.mjs +82 -0
  319. package/src/projection/obsidian/selection-ui/index.mjs +12 -0
  320. package/src/projection/obsidian/selection-ui/policy-setup.mjs +107 -0
  321. package/src/projection/obsidian/selection-ui/receipt.mjs +173 -0
  322. package/src/projection/obsidian/selection-ui/selection-state.mjs +122 -0
  323. package/src/projection/obsidian/selection-ui/selection.mjs +109 -0
  324. package/src/projection/project.mjs +28 -19
  325. package/src/readiness-protocols/evidence.mjs +282 -0
  326. package/src/readiness-protocols/runtime.mjs +4 -3
  327. package/src/readiness-protocols/source-read.mjs +39 -0
  328. package/src/runtime/git-adapter.mjs +189 -0
  329. package/src/runtime/local-state.mjs +439 -0
  330. package/src/runtime/obsidian/app-capability.mjs +129 -0
  331. package/src/runtime/obsidian/app-production-seams.mjs +105 -0
  332. package/src/runtime/obsidian/contributions/proposal-adapter.mjs +4 -0
  333. package/src/runtime/obsidian/contributions/selection-ui.mjs +4 -0
  334. package/src/runtime/obsidian/contributions/source-apply.mjs +4 -0
  335. package/src/runtime/obsidian/contributions.mjs +27 -0
  336. package/src/runtime/obsidian/documents.mjs +37 -0
  337. package/src/runtime/obsidian/enablement.mjs +53 -0
  338. package/src/runtime/obsidian/engine.mjs +532 -0
  339. package/src/runtime/obsidian/errors.mjs +14 -0
  340. package/src/runtime/obsidian/extension-points.mjs +103 -0
  341. package/src/runtime/obsidian/index.mjs +34 -0
  342. package/src/runtime/obsidian/lifecycle.mjs +258 -0
  343. package/src/runtime/obsidian/machine-settings.mjs +260 -0
  344. package/src/runtime/obsidian/observation.mjs +158 -0
  345. package/src/runtime/obsidian/opening.mjs +263 -0
  346. package/src/runtime/obsidian/pending-edits.mjs +141 -0
  347. package/src/runtime/obsidian/pipeline.mjs +122 -0
  348. package/src/runtime/obsidian/private-lock.mjs +156 -0
  349. package/src/runtime/obsidian/process-identity.mjs +58 -0
  350. package/src/runtime/obsidian/service-client.mjs +66 -0
  351. package/src/runtime/obsidian/service-entry-path.mjs +9 -0
  352. package/src/runtime/obsidian/service-main.mjs +91 -0
  353. package/src/runtime/obsidian/service-record.mjs +169 -0
  354. package/src/runtime/obsidian/service-server.mjs +121 -0
  355. package/src/runtime/obsidian/service.mjs +216 -0
  356. package/src/runtime/obsidian/startup-adapters.mjs +87 -0
  357. package/src/runtime/obsidian/state-store.mjs +180 -0
  358. package/src/runtime/obsidian/sync-notice.mjs +33 -0
  359. package/src/runtime/obsidian/tick-loop.mjs +84 -0
  360. package/src/runtime/obsidian/watchers.mjs +36 -0
  361. package/src/runtime/repository-observation.mjs +491 -0
  362. package/src/runtime/supervisor.mjs +803 -0
  363. package/src/server/local-sidecar.mjs +125 -59
  364. package/src/server/security.mjs +89 -4
  365. package/src/server/server.mjs +4 -2
  366. package/src/skills/steward.mjs +780 -0
  367. package/src/support/feedback-report.mjs +4 -3
  368. package/src/ui/presentation/browser.mjs +278 -0
  369. package/src/ui/presentation/contract.mjs +116 -0
  370. package/src/ui/presentation/index.mjs +7 -0
  371. package/src/ui/presentation/native.mjs +153 -0
  372. package/src/ui/presentation/proof.mjs +57 -0
  373. package/src/ui/presentation/schema-check.mjs +30 -0
  374. package/src/ui/presentation/schema.generated.mjs +1371 -0
  375. package/src/ui/presentation/state.mjs +43 -0
  376. package/src/ui/presentation/styles.mjs +67 -0
  377. package/src/ui/presentation/tokens.mjs +74 -0
  378. package/src/ui/presentation/web.mjs +85 -0
  379. package/src/ui/review-page.mjs +32 -0
  380. package/src/upgrade/explanation.mjs +33 -0
  381. package/src/upgrade/provenance.mjs +338 -0
  382. package/src/upgrade/transaction-files.mjs +103 -0
  383. package/src/upgrade/transaction.mjs +475 -0
  384. package/src/upgrade/upgrade.mjs +65 -29
  385. package/src/vault/hosts.mjs +21 -0
  386. package/src/vault/identity.mjs +19 -0
  387. package/src/vault/index.mjs +7 -0
  388. package/src/vault/interface.mjs +11 -0
  389. package/src/vault/metadata.mjs +31 -0
  390. package/src/vault/privacy.mjs +148 -0
  391. package/src/vault/probe.mjs +89 -0
  392. package/src/vault/service.mjs +131 -0
  393. package/src/vault/source.mjs +45 -0
  394. package/src/vault/storage.mjs +23 -0
  395. package/templates/distribution-workspace/.claude/launch.json +6 -2
  396. package/templates/distribution-workspace/gitignore +1 -0
  397. package/templates/distribution-workspace/project/README.md +2 -2
  398. package/templates/external-project-workspace/README.md +45 -0
  399. package/templates/external-project-workspace/answers.example.json +4 -0
  400. package/templates/external-project-workspace/atelier.project.json +40 -0
  401. package/templates/external-project-workspace/boundary-policy.v1.json +60 -0
  402. package/templates/external-project-workspace/gitignore +8 -0
  403. package/templates/external-project-workspace/pack-lifecycle.json +14 -0
  404. package/templates/external-project-workspace/packs/protocols/contract-gate.v1.json +109 -0
  405. package/templates/external-project-workspace/packs/sample-pack.v1.json +48 -0
  406. package/templates/external-project-workspace/repo-access.v1.json +9 -0
  407. package/templates/external-project-workspace/source/README.md +11 -0
  408. package/templates/launch.json +6 -2
  409. package/templates/private-domain-workspace/.claude/launch.json +6 -2
  410. package/templates/private-domain-workspace/domain/README.md +2 -2
  411. package/templates/private-domain-workspace/gitignore +1 -0
  412. package/templates/shared-project-workspace/.claude/launch.json +6 -2
  413. package/templates/shared-project-workspace/gitignore +1 -0
  414. package/templates/shared-project-workspace/project/README.md +2 -2
@@ -0,0 +1,131 @@
1
+ import { verifyVaultPrivacy, createVaultContext } from './privacy.mjs'
2
+ import { renderVaultHome, vaultHomePolicy } from './interface.mjs'
3
+ /** Optional hosted artifact service. No default network, storage, or identity provider. */
4
+ const TYPES = Object.freeze({ html: 'text/html; charset=utf-8', css: 'text/css; charset=utf-8', txt: 'text/plain; charset=utf-8', png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', webp: 'image/webp', pdf: 'application/pdf' })
5
+ const LIMIT = 4 * 1024 * 1024
6
+ const encoder = new TextEncoder()
7
+ const validId = value => typeof value === 'string' && /^[a-z][a-z0-9-]{0,62}$/.test(value)
8
+ const validPath = value => typeof value === 'string' && value.length <= 512 && value.split('/').every(p => /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(p) && p !== '.' && p !== '..')
9
+ const validExt = value => value === undefined || (value !== null && typeof value === 'object' && !Array.isArray(value))
10
+ const sameOwner = (a, b) => a && b && typeof a.issuer === 'string' && a.issuer.length > 0 && typeof a.subject === 'string' && a.subject.length > 0 && a.issuer === b.issuer && a.subject === b.subject
11
+ const headers = {
12
+ 'Cache-Control': 'private, no-store',
13
+ 'Content-Security-Policy': "sandbox; default-src 'none'; img-src 'self'; style-src 'self' 'unsafe-inline'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'",
14
+ 'X-Content-Type-Options': 'nosniff',
15
+ 'Referrer-Policy': 'no-referrer',
16
+ 'X-Robots-Tag': 'noindex, nofollow',
17
+ }
18
+ export async function digest(bytes) {
19
+ return Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256', bytes)), b => b.toString(16).padStart(2, '0')).join('')
20
+ }
21
+ function reply(status, text = '', extra = {}) { return new Response(text, { status, headers: { ...headers, 'Content-Type': 'text/plain; charset=utf-8', ...extra } }) }
22
+ async function boundedBody(request) {
23
+ if (!request.body) throw new Error('invalid')
24
+ const reader = request.body.getReader()
25
+ let size = 0
26
+ const chunks = []
27
+ try {
28
+ while (true) {
29
+ const { done, value } = await reader.read()
30
+ if (done) break
31
+ size += value.byteLength
32
+ if (size > LIMIT) { await reader.cancel(); throw new Error('too-large') }
33
+ chunks.push(value)
34
+ }
35
+ } finally { reader.releaseLock() }
36
+ const bytes = new Uint8Array(size)
37
+ let offset = 0
38
+ for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length }
39
+ return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes))
40
+ }
41
+ export async function preparePublication(input) {
42
+ if (!input || input.schema !== 'atelier-vault-publication/v1' || (input.contractVersion !== undefined && (typeof input.contractVersion !== 'string' || !/^1\.[0-9]+\.[0-9]+$/.test(input.contractVersion))) || !validExt(input.ext) || !Number.isSafeInteger(input.expectedRevision) || input.expectedRevision < 0 || input.expectedRevision >= Number.MAX_SAFE_INTEGER || Object.keys(input).some(key => !['schema', 'contractVersion', 'expectedRevision', 'files', 'ext'].includes(key)) || !Array.isArray(input.files) || !input.files.length || input.files.length > 100) throw new Error('invalid')
43
+ if (encoder.encode(JSON.stringify(input)).length > LIMIT) throw new Error('too-large')
44
+ const seen = new Set()
45
+ const files = []
46
+ let total = 0
47
+ for (const file of input.files) {
48
+ if (!file || !validExt(file.ext) || Object.keys(file).some(key => !['path', 'base64', 'ext'].includes(key)) || !validPath(file.path) || seen.has(file.path) || typeof file.base64 !== 'string' || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(file.base64)) throw new Error('invalid')
49
+ const type = TYPES[file.path.split('.').at(-1)]
50
+ if (typeof type !== 'string') throw new Error('invalid')
51
+ seen.add(file.path)
52
+ const bytes = Uint8Array.from(atob(file.base64), c => c.charCodeAt(0))
53
+ total += bytes.length
54
+ if (total > LIMIT) throw new Error('too-large')
55
+ files.push({ path: file.path, type, size: bytes.length, sha256: await digest(bytes), bytes })
56
+ }
57
+ files.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0)
58
+ const manifest = files.map(({ bytes, ...record }) => record)
59
+ return { files, manifest, publication: await digest(encoder.encode(JSON.stringify(manifest))) }
60
+ }
61
+ /**
62
+ * identity.read(request) -> verified {issuer,subject}, or null (revocation checked).
63
+ * identity.publish(request,vault) -> verified owner identity, or null; MUST use
64
+ * a revocable vault-scoped machine credential, never browser cookies.
65
+ * metadata.get(vault) -> {owner, revision, manifest}, or null.
66
+ * metadata.commit(vault,{owner,expectedRevision,manifest,publication}) -> boolean;
67
+ * MUST atomically compare both owner and revision before replacing manifest.
68
+ * storage.get/put accepts service-generated keys only and uses private storage.
69
+ */
70
+ export function createVaultService({ identity, metadata, storage, privacy, deployment }) {
71
+ for (const [object, methods] of [[identity, ['read', 'publish']], [metadata, ['get', 'commit']], [storage, ['get', 'put']]]) {
72
+ if (!object || methods.some(method => typeof object[method] !== 'function')) throw new TypeError('Incomplete vault adapter')
73
+ }
74
+ return async function handle(request) {
75
+ try {
76
+ const url = new URL(request.url)
77
+ if (/%|\\/.test(url.pathname)) return reply(400)
78
+ const parts = url.pathname.slice(1).split('/')
79
+ const publishing = parts[0] === '_publish'
80
+ const vault = publishing ? parts[1] : parts[0]
81
+ if (!validId(vault)) return reply(404)
82
+ const home = !publishing && (parts.length === 1 || (parts.length === 2 && parts[1] === ''))
83
+ if (url.search && (publishing || (home && ( [...url.searchParams.keys()].some(key => key !== 'q') || url.searchParams.getAll('q').length > 1 || (url.searchParams.get('q') || '').length > 200)))) return reply(400)
84
+ if (publishing) {
85
+ if (parts.length !== 2 || !['GET', 'POST'].includes(request.method)) return reply(405, '', { Allow: 'GET, POST' })
86
+ // Browser-originated writes are not a machine publication channel.
87
+ if (request.headers.has('origin') || request.headers.has('cookie')) return reply(403)
88
+ const principal = await identity.publish(request, vault)
89
+ if (!principal) return reply(401, '', { 'WWW-Authenticate': 'Bearer realm="vault-publication"' })
90
+ const record = await metadata.get(vault)
91
+ if (!sameOwner(principal, record?.owner)) return reply(404)
92
+ if (request.method === 'GET') {
93
+ return new Response(JSON.stringify({ schema: 'atelier-vault-status/v1', vault, revision: record.revision, publication: record.publication ?? null }), { headers: { ...headers, 'Content-Type': 'application/json' } })
94
+ }
95
+ if (request.headers.get('content-type')?.split(';')[0].trim().toLowerCase() !== 'application/json') return reply(415)
96
+ let input, prepared
97
+ try { input = await boundedBody(request); prepared = await preparePublication(input) }
98
+ catch (error) { return reply(error.message === 'too-large' ? 413 : 400) }
99
+ if (input.expectedRevision !== record.revision) return reply(409)
100
+ const context = createVaultContext({ vault, record: { owner: record.owner, publication: prepared.publication, revision: input.expectedRevision + 1, manifest: prepared.manifest }, deployment, request: { origin: url.origin, path: url.pathname } })
101
+ const before = await verifyVaultPrivacy(privacy, { ...context, phase: 'before-upload' })
102
+ if (before.status !== 'verified') return reply(503, before.reason)
103
+ for (const file of prepared.files) await storage.put(`${vault}/${file.sha256}`, file.bytes)
104
+ const after = await verifyVaultPrivacy(privacy, { ...context, phase: 'before-activation' })
105
+ if (after.status !== 'verified' || after.policyRevision !== before.policyRevision) return reply(503, 'Protection changed or could not be verified. Publication was not activated.')
106
+ // Revalidate the credential after uploads and activation checks, immediately before commit.
107
+ const current = await identity.publish(request, vault)
108
+ if (!sameOwner(principal, current)) return reply(401, '', { 'WWW-Authenticate': 'Bearer realm="vault-publication"' })
109
+ const committed = await metadata.commit(vault, { owner: principal, expectedRevision: input.expectedRevision, manifest: prepared.manifest, publication: prepared.publication })
110
+ if (!committed) return reply(409)
111
+ return new Response(JSON.stringify({ schema: 'atelier-vault-receipt/v1', vault, revision: input.expectedRevision + 1, publication: prepared.publication }), { status: 201, headers: { ...headers, 'Content-Type': 'application/json' } })
112
+ }
113
+ if (!['GET', 'HEAD'].includes(request.method)) return reply(405, '', { Allow: 'GET, HEAD' })
114
+ const principal = await identity.read(request)
115
+ if (!principal) return reply(401)
116
+ const record = await metadata.get(vault)
117
+ if (!sameOwner(principal, record?.owner)) return reply(404)
118
+ if (!home && !record.manifest.some(file => file.path === parts.slice(1).join('/'))) return reply(404)
119
+ const protection = await verifyVaultPrivacy(privacy, createVaultContext({ vault, record, deployment, request: { origin: url.origin, path: url.pathname } }))
120
+ if (home) return new Response(request.method === 'HEAD' ? null : renderVaultHome({ vault, revision: record.revision, manifest: record.manifest, privacy: protection, query: url.searchParams.get('q') || '' }), { headers: { ...headers, 'Content-Type': 'text/html; charset=utf-8', 'Content-Security-Policy': vaultHomePolicy } })
121
+ if (protection.status !== 'verified') return reply(503, protection.reason)
122
+ const path = parts.slice(1).join('/')
123
+ if (!validPath(path)) return reply(404)
124
+ const file = record.manifest.find(entry => entry.path === path)
125
+ if (!file || !/^[a-f0-9]{64}$/.test(file.sha256) || !Object.values(TYPES).includes(file.type)) return reply(404)
126
+ const bytes = await storage.get(`${vault}/${file.sha256}`)
127
+ if (!bytes || bytes.length !== file.size || await digest(bytes) !== file.sha256) return reply(503)
128
+ return new Response(request.method === 'HEAD' ? null : bytes, { headers: { ...headers, 'Content-Type': file.type, 'Content-Length': String(bytes.length), ...(file.type === 'application/pdf' ? { 'Content-Disposition': 'attachment' } : {}) } })
129
+ } catch { return reply(503) }
130
+ }
131
+ }
@@ -0,0 +1,45 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { preparePublication } from './service.mjs'
4
+ const LIMIT = 4 * 1024 * 1024
5
+ /** Node-only bundle preparation. Select paths explicitly; never scan a repo. */
6
+ export async function prepareVaultSource({ root, paths, expectedRevision }) {
7
+ if (typeof root !== 'string' || !path.isAbsolute(root) || !Array.isArray(paths) || !paths.length || paths.length > 100) throw new TypeError('Absolute artifact root and explicit paths required')
8
+ if (fs.lstatSync(root).isSymbolicLink()) throw new Error('Artifact root must not be a symlink')
9
+ const realRoot = fs.realpathSync(root)
10
+ if (!fs.statSync(realRoot).isDirectory()) throw new Error('Artifact root must be a directory')
11
+ let total = 0
12
+ const files = []
13
+ for (const name of paths) {
14
+ if (typeof name !== 'string' || name.length > 512 || !name.split('/').every(part => /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(part))) throw new Error('Invalid selected artifact path')
15
+ let file = realRoot
16
+ for (const part of name.split('/')) {
17
+ file = path.join(file, part)
18
+ if (fs.lstatSync(file).isSymbolicLink()) throw new Error('Selected artifacts must not traverse symlinks')
19
+ }
20
+ const before = fs.lstatSync(file)
21
+ if (!before.isFile() || before.nlink !== 1 || before.size > LIMIT) throw new Error('Selected artifact must be a bounded, unlinked regular file')
22
+ const fd = fs.openSync(file, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0))
23
+ try {
24
+ const opened = fs.fstatSync(fd)
25
+ const resolved = fs.realpathSync(file)
26
+ if ((path.relative(realRoot, resolved).startsWith('..' + path.sep) || path.isAbsolute(path.relative(realRoot, resolved))) || opened.ino !== before.ino || opened.dev !== before.dev || !opened.isFile() || opened.nlink !== 1 || opened.size > LIMIT) throw new Error('Artifact changed during selection')
27
+ const data = Buffer.alloc(opened.size)
28
+ let offset = 0
29
+ while (offset < data.length) {
30
+ const count = fs.readSync(fd, data, offset, data.length - offset, offset)
31
+ if (!count) throw new Error('Artifact changed during read')
32
+ offset += count
33
+ }
34
+ const after = fs.fstatSync(fd)
35
+ const current = fs.lstatSync(file)
36
+ if (after.nlink !== 1 || current.nlink !== 1 || after.size !== opened.size || after.mtimeMs !== opened.mtimeMs || after.ctimeMs !== opened.ctimeMs || current.ino !== opened.ino || current.dev !== opened.dev || fs.realpathSync(file) !== resolved) throw new Error('Artifact changed during read')
37
+ total += data.length
38
+ if (total > LIMIT) throw new Error('Artifact bundle too large')
39
+ files.push({ path: name, base64: data.toString('base64') })
40
+ } finally { fs.closeSync(fd) }
41
+ }
42
+ const request = { schema: 'atelier-vault-publication/v1', contractVersion: '1.0.0', expectedRevision, files }
43
+ const prepared = await preparePublication(request)
44
+ return { request, publication: prepared.publication, manifest: prepared.manifest }
45
+ }
@@ -0,0 +1,23 @@
1
+ /** Provider SDKs/bindings are explicitly supplied by the host, never auto-loaded. */
2
+ export function r2PrivateStorage(bucket) {
3
+ return {
4
+ async put(key, bytes) { await bucket.put(key, bytes) },
5
+ async get(key) {
6
+ const object = await bucket.get(key)
7
+ return object ? new Uint8Array(await object.arrayBuffer()) : null
8
+ },
9
+ }
10
+ }
11
+ export function vercelPrivateStorage(blob) {
12
+ return {
13
+ async put(key, bytes) {
14
+ await blob.put(key, bytes, { access: 'private', addRandomSuffix: false, allowOverwrite: true, contentType: 'application/octet-stream' })
15
+ },
16
+ async get(key) {
17
+ const object = await blob.get(key, { access: 'private', useCache: false })
18
+ if (!object) return null
19
+ if (object.statusCode !== 200 || !object.stream) throw new Error('Private storage unavailable')
20
+ return new Uint8Array(await new Response(object.stream).arrayBuffer())
21
+ },
22
+ }
23
+ }
@@ -3,8 +3,12 @@
3
3
  "configurations": [
4
4
  {
5
5
  "name": "atelier",
6
- "runtimeExecutable": "npx",
7
- "runtimeArgs": ["atelier", "server"],
6
+ "runtimeExecutable": "node",
7
+ "runtimeArgs": [
8
+ "--input-type=module",
9
+ "--eval",
10
+ "import { runCli } from '@mnstry/atelier/cli'; process.exit(await runCli({ argv: ['server', ...process.argv.slice(1)] }));"
11
+ ],
8
12
  "port": 8137,
9
13
  "autoPort": true
10
14
  }
@@ -1,4 +1,5 @@
1
1
  .atelier-local/
2
+ .atelier-local/obsidian.json
2
3
  atelier.local.json
3
4
  atelier.workspace.local.json
4
5
  atelier-attestation-key.local.json
@@ -2,10 +2,10 @@
2
2
  title: "Shared Project Seed"
3
3
  kg:
4
4
  id: "project-alpha:seed"
5
- type: "project-note"
5
+ type: "document"
6
6
  domain: "project"
7
7
  lifecycle: "draft"
8
- status: "seed"
8
+ status: "draft"
9
9
  audience: "team"
10
10
  relations: []
11
11
  ---
@@ -0,0 +1,45 @@
1
+ # External-project adapter starter
2
+
3
+ This invented example uses MNSTRY Atelier. The adapter owns configuration and
4
+ a sample extension pack; the separate source repository owns canonical text.
5
+ Runs, answers and review history remain ignored local state. Public audience
6
+ labels do not grant publication, consent or runtime access.
7
+
8
+ Create this scaffold with `atelier init --template external-project --target DIR`.
9
+ The target must not exist. No Git repository, hook or remote is created.
10
+ Initialize the adapter and its source directory as separate repositories when
11
+ ready; the adapter ignores `source/`. To connect an existing repository instead,
12
+ pass `--repo-path source=PATH` consistently, or use an ignored local overlay.
13
+ Keep domain vocabulary and methods in your own adapter and source repositories.
14
+ Replace the synthetic actor in the boundary policy with your actual policy.
15
+
16
+ Using the installed package's CLI, from the adapter directory:
17
+
18
+ ```sh
19
+ atelier lock provenance
20
+ atelier config check --explain
21
+ atelier extension-pack validate
22
+ atelier graph
23
+ atelier project
24
+ atelier readiness
25
+ atelier review packs
26
+ atelier review run sample.readiness:contract-gate --answers answers.example.json
27
+ atelier dev --review
28
+ ```
29
+
30
+ Open `/review` on the displayed local address. Use repository `source` and
31
+ `README.md` to leave a question. Use the returned run ID to review its claims.
32
+ The evaluator measures answer completeness only. Read and judge the evidence;
33
+ acceptance creates a handoff, never a canonical edit. Use `atelier review history`
34
+ and `atelier review handoff REQUEST_ID` to inspect records locally.
35
+
36
+ Real answers and responses belong in ignored local state, not the tracked
37
+ example answer file. Reopening recovers saved contributions; missing or failed
38
+ saves remain visible. Stop/start the foreground sidecar with the same project
39
+ and reopen the same document. This does not establish cross-computer access.
40
+
41
+ For CI, compose the root's existing consumer, portability, boundary and
42
+ private-disclosure checks. No new CI run or provider is triggered by this template.
43
+ Before changing the pack, run `atelier upgrade --dry-run`, retain historical
44
+ pack content, update its lifecycle declaration and lock through your reviewed
45
+ migration process, and run the checks again. Never reinterpret old run evidence.
@@ -0,0 +1,4 @@
1
+ {
2
+ "scope.name": "Sample observation",
3
+ "scope.sourceRef": "sample-source:observation"
4
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "schema": "mnstry.atelier-project-config@v1",
3
+ "name": "sample-adapter",
4
+ "roots": {
5
+ "workspace": ".",
6
+ "repoOps": "."
7
+ },
8
+ "graph": {
9
+ "repoAccessPath": "repo-access.v1.json",
10
+ "outputPath": "atelier-output/knowledge.graph.json"
11
+ },
12
+ "projection": {
13
+ "outputRoot": "atelier-output",
14
+ "readinessPath": "atelier-output/atelier-readiness.json"
15
+ },
16
+ "boundaries": {
17
+ "policyPath": "boundary-policy.v1.json",
18
+ "strictNewRepos": true
19
+ },
20
+ "repos": [
21
+ {
22
+ "name": "source",
23
+ "path": "source",
24
+ "readBoundary": "private"
25
+ }
26
+ ],
27
+ "ext": {
28
+ "mnstry.atelier": {
29
+ "extensionPacks": [
30
+ {
31
+ "id": "sample.readiness",
32
+ "version": "v1",
33
+ "path": "packs/sample-pack.v1.json",
34
+ "enabled": true
35
+ }
36
+ ],
37
+ "extensionPackLifecycle": "pack-lifecycle.json"
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "schema": "mnstry.atelier-boundary-policy@v1",
3
+ "mode": "strict",
4
+ "actors": {
5
+ "sample-author": {
6
+ "githubLogin": "sample-author",
7
+ "gitEmails": [
8
+ "sample@example.invalid"
9
+ ],
10
+ "privateDomainRepo": "source"
11
+ }
12
+ },
13
+ "repos": {
14
+ "source": {
15
+ "kind": "private_domain",
16
+ "ownerActor": "sample-author",
17
+ "readBoundary": "private",
18
+ "allowedAudiences": [
19
+ "private"
20
+ ],
21
+ "forbiddenAudiences": [
22
+ "public"
23
+ ],
24
+ "autoCommit": "guarded"
25
+ }
26
+ },
27
+ "forbiddenPaths": [
28
+ ".atelier-local/**",
29
+ "atelier.local.json",
30
+ "atelier.workspace.local.json",
31
+ ".mnstry-local/**",
32
+ ".atelier-proposals/**",
33
+ ".atelier-current",
34
+ ".atelier-current.json",
35
+ ".atelier-presence.json",
36
+ ".atelier-nonce",
37
+ ".atelier-capability-grants.json",
38
+ ".atelier-grants/**",
39
+ ".atelier-events.jsonl",
40
+ ".atelier-audit.jsonl",
41
+ ".atelier-audit/**",
42
+ ".atelier-session.json",
43
+ ".atelier-session.jsonl",
44
+ ".atelier-session/**",
45
+ ".atelier-sessions/**",
46
+ ".atelier-support/**",
47
+ ".atelier-support.json",
48
+ "support-bundle*",
49
+ "support-bundles/**",
50
+ "prompts/**",
51
+ "transcripts/**",
52
+ "node_modules/**",
53
+ ".DS_Store"
54
+ ],
55
+ "promotion": {
56
+ "requiresGitPromote": true,
57
+ "recordsPath": "governance/git-promote-events.jsonl"
58
+ },
59
+ "governanceLedgerPath": "governance/repo-boundary-ledger.md"
60
+ }
@@ -0,0 +1,8 @@
1
+ node_modules/
2
+ .atelier-local/
3
+ .atelier-local/obsidian.json
4
+ atelier-output/
5
+ atelier.local.json
6
+ atelier.workspace.local.json
7
+ source/
8
+ .claude/
@@ -0,0 +1,14 @@
1
+ {
2
+ "schema": "atelier-pack-lifecycle@v1",
3
+ "packs": [
4
+ {
5
+ "id": "sample.readiness",
6
+ "version": "v1",
7
+ "digest": "sha256:0eff795765e0bbd4c2510acda2e492201c23bc870df6c354eef623484643ab11",
8
+ "compatibleRootVersions": [
9
+ "0.2.0-alpha.10"
10
+ ],
11
+ "status": "active"
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,109 @@
1
+ {
2
+ "schema": "atelier-readiness-protocol@v1",
3
+ "id": "sample.readiness:contract-gate",
4
+ "slug": "contract-gate",
5
+ "version": "v1",
6
+ "stage": "formation",
7
+ "title": "Sample contract gate",
8
+ "purpose": "Verify neutral protocol inputs before a readiness run is accepted.",
9
+ "questions": [
10
+ {
11
+ "id": "scope",
12
+ "prompt": "What neutral scope is being prepared?",
13
+ "inputFields": ["scope.name", "scope.sourceRef"],
14
+ "required": true
15
+ }
16
+ ],
17
+ "inputFields": [
18
+ {
19
+ "id": "scope.name",
20
+ "type": "string",
21
+ "required": true,
22
+ "description": "Neutral scope name."
23
+ },
24
+ {
25
+ "id": "scope.sourceRef",
26
+ "type": "string",
27
+ "required": true,
28
+ "description": "Evidence reference for the scope."
29
+ }
30
+ ],
31
+ "outputHints": [
32
+ {
33
+ "id": "contract-gate.summary",
34
+ "text": "Render scope and evidence before review."
35
+ }
36
+ ],
37
+ "outputs": {
38
+ "runSchema": "atelier-readiness-run@v1",
39
+ "artifacts": [
40
+ {
41
+ "id": "sample.readiness:contract-gate.summary",
42
+ "kind": "draft",
43
+ "schema": "atelier-readiness-run@v1",
44
+ "description": "Draft readiness summary."
45
+ }
46
+ ]
47
+ },
48
+ "claimMappings": [
49
+ {
50
+ "id": "sample.readiness:contract-gate.scope-supports-review",
51
+ "claimPredicate": "supports",
52
+ "sourceFields": ["scope.name"],
53
+ "target": "atelier-claim@v1",
54
+ "evidence": "scope.sourceRef"
55
+ }
56
+ ],
57
+ "readinessRules": [
58
+ {
59
+ "id": "sample.readiness:contract-gate.scope-present",
60
+ "severity": "blocker",
61
+ "condition": "Scope name and evidence are present.",
62
+ "remediation": "Add scope.name and scope.sourceRef.",
63
+ "failClosed": true
64
+ }
65
+ ],
66
+ "graphLenses": [
67
+ {
68
+ "id": "sample.readiness:contract-gate.lens",
69
+ "title": "Sample contract gate lens",
70
+ "query": { "protocolId": "sample.readiness:contract-gate" }
71
+ }
72
+ ],
73
+ "exportMappings": [
74
+ {
75
+ "id": "sample.readiness:contract-gate.export",
76
+ "sourceField": "scope",
77
+ "sourceTerm": "sample.readiness:contract-gate.scope",
78
+ "target": "core.artifact",
79
+ "runtimeOwner": "audit",
80
+ "targetCollection": "staffPrep"
81
+ }
82
+ ],
83
+ "ui": {
84
+ "section": "readiness-journey",
85
+ "title": "Sample contract gate",
86
+ "description": "Neutral protocol fixture.",
87
+ "agentPrompt": "Run atelier readiness run sample.readiness:contract-gate --project ./atelier.project.json."
88
+ },
89
+ "safety": {
90
+ "runtimeMutation": false,
91
+ "runtimeImport": false,
92
+ "canonicalWrites": false,
93
+ "claimOnly": true,
94
+ "telemetry": false,
95
+ "egress": false,
96
+ "sendPath": false,
97
+ "browserApply": false,
98
+ "dryRunOnly": true
99
+ },
100
+ "safetyPosture": {
101
+ "runtimeMutation": false,
102
+ "externalEgress": false,
103
+ "defaultVisibility": "private",
104
+ "authority": "proposal-only",
105
+ "reviewMode": "static-inspection",
106
+ "failClosedOnMissingEvidence": true,
107
+ "refuses": ["runtime writes"]
108
+ }
109
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "schema": "mnstry-atelier-extension-pack@v1",
3
+ "id": "sample.readiness",
4
+ "namespace": "sample",
5
+ "version": "v1",
6
+ "terms": [
7
+ {
8
+ "id": "sample.readiness:scope",
9
+ "label": "Sample scope",
10
+ "kind": "concept"
11
+ }
12
+ ],
13
+ "migrations": [],
14
+ "fixtures": [],
15
+ "protocols": [
16
+ {
17
+ "id": "sample.readiness:contract-gate",
18
+ "schema": "atelier-readiness-protocol@v1",
19
+ "path": "protocols/contract-gate.v1.json",
20
+ "gate": "required",
21
+ "title": "Sample contract gate"
22
+ }
23
+ ],
24
+ "lenses": [
25
+ {
26
+ "id": "sample.readiness:contract-gate-lens",
27
+ "title": "Sample contract gate lens",
28
+ "query": {
29
+ "protocolId": "sample.readiness:contract-gate"
30
+ }
31
+ }
32
+ ],
33
+ "readinessRules": [
34
+ {
35
+ "id": "sample.readiness:scope-present",
36
+ "severity": "blocker",
37
+ "condition": "Scope name and evidence are present."
38
+ }
39
+ ],
40
+ "actionRules": [],
41
+ "exportMappings": [
42
+ {
43
+ "id": "sample.readiness:scope-export",
44
+ "sourceTerm": "sample.readiness:scope",
45
+ "target": "core.artifact"
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "schema": "mnstry.atelier-repo-access@v1",
3
+ "defaultReadBoundary": "private",
4
+ "repos": {
5
+ "source": {
6
+ "readBoundary": "private"
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,11 @@
1
+ ---
2
+ title: Sample observation
3
+ kg:
4
+ id: "sample-source:observation"
5
+ type: "document"
6
+ status: "active"
7
+ audience: "private"
8
+ ---
9
+ # Sample observation
10
+
11
+ The sample observation needs an owner to confirm its interpretation.
@@ -3,8 +3,12 @@
3
3
  "configurations": [
4
4
  {
5
5
  "name": "atelier",
6
- "runtimeExecutable": "npx",
7
- "runtimeArgs": ["atelier", "server"],
6
+ "runtimeExecutable": "node",
7
+ "runtimeArgs": [
8
+ "--input-type=module",
9
+ "--eval",
10
+ "import { runCli } from '@mnstry/atelier/cli'; process.exit(await runCli({ argv: ['server', ...process.argv.slice(1)] }));"
11
+ ],
8
12
  "port": 8137,
9
13
  "autoPort": true
10
14
  }
@@ -3,8 +3,12 @@
3
3
  "configurations": [
4
4
  {
5
5
  "name": "atelier",
6
- "runtimeExecutable": "npx",
7
- "runtimeArgs": ["atelier", "server"],
6
+ "runtimeExecutable": "node",
7
+ "runtimeArgs": [
8
+ "--input-type=module",
9
+ "--eval",
10
+ "import { runCli } from '@mnstry/atelier/cli'; process.exit(await runCli({ argv: ['server', ...process.argv.slice(1)] }));"
11
+ ],
8
12
  "port": 8137,
9
13
  "autoPort": true
10
14
  }
@@ -2,10 +2,10 @@
2
2
  title: "Private Domain Seed"
3
3
  kg:
4
4
  id: "tenant-private-domain:seed"
5
- type: "domain-note"
5
+ type: "document"
6
6
  domain: "example-domain"
7
7
  lifecycle: "draft"
8
- status: "seed"
8
+ status: "draft"
9
9
  audience: "private"
10
10
  relations: []
11
11
  ---
@@ -1,4 +1,5 @@
1
1
  .atelier-local/
2
+ .atelier-local/obsidian.json
2
3
  atelier.local.json
3
4
  atelier.workspace.local.json
4
5
  atelier-attestation-key.local.json