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

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 (236) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +80 -47
  3. package/SECURITY.md +1 -1
  4. package/TRADEMARKS.md +2 -2
  5. package/contracts/atelier-extension-manifest.v1.schema.json +412 -0
  6. package/contracts/atelier-graph-view.v1.schema.json +1085 -0
  7. package/contracts/public-api-baseline.json +298 -19
  8. package/docs/README.md +90 -0
  9. package/docs/blocks/claims.md +2 -2
  10. package/docs/blocks/conformance-admission.md +1 -1
  11. package/docs/{atelier-sync.md → guides/atelier-sync.md} +20 -14
  12. package/docs/guides/co-authoring.md +113 -0
  13. package/docs/{distributions.md → guides/distributions.md} +13 -8
  14. package/docs/guides/extensions.md +189 -0
  15. package/docs/guides/graph-refresh.md +152 -0
  16. package/docs/guides/graph-workspace.md +64 -0
  17. package/docs/{ingestion.md → guides/ingestion.md} +13 -12
  18. package/docs/{knowledge-workspace.md → guides/knowledge-workspace.md} +2 -2
  19. package/docs/{learning.md → guides/learning.md} +12 -5
  20. package/docs/{obsidian.md → guides/obsidian.md} +134 -47
  21. package/docs/guides/ontology-guide.md +111 -0
  22. package/docs/{personal-workspace.md → guides/personal-workspace.md} +7 -4
  23. package/docs/{research-starter.md → guides/research-starter.md} +1 -1
  24. package/docs/{tenant-readiness.md → guides/tenant-readiness.md} +39 -0
  25. package/docs/{upgrade.md → guides/upgrade.md} +23 -9
  26. package/docs/knowledge-health/assessment/capabilities.md +6 -15
  27. package/docs/knowledge-health/facilitator.md +15 -4
  28. package/docs/knowledge-health/{devday/participant-response.md → participant-response.md} +4 -2
  29. package/docs/knowledge-health/quickstart.md +97 -75
  30. package/docs/knowledge-health/readme.md +13 -5
  31. package/docs/maintainers/describing-the-atelier.md +173 -0
  32. package/docs/{release-engineering.md → maintainers/release-engineering.md} +5 -5
  33. package/docs/{announcements.md → reference/announcements.md} +1 -1
  34. package/docs/{architecture.md → reference/architecture.md} +31 -5
  35. package/docs/{atelier-runtime.md → reference/atelier-runtime.md} +1 -1
  36. package/docs/{connected-composition.md → reference/connected-composition.md} +7 -10
  37. package/docs/{coordination.md → reference/coordination.md} +1 -1
  38. package/docs/{decisions.md → reference/decisions.md} +3 -3
  39. package/docs/{design.md → reference/design.md} +1 -1
  40. package/docs/reference/edge-policy.md +151 -0
  41. package/docs/reference/graph-view-structured.md +119 -0
  42. package/docs/reference/graph-view.md +139 -0
  43. package/docs/reference/graph-workspace.md +37 -0
  44. package/docs/{intake-and-guides.md → reference/intake-and-guides.md} +3 -4
  45. package/docs/{knowledge-graph.md → reference/knowledge-graph.md} +120 -6
  46. package/docs/{local-services.md → reference/local-services.md} +1 -1
  47. package/docs/{obsidian-contract.md → reference/obsidian-contract.md} +6 -4
  48. package/docs/{obsidian-plugin.md → reference/obsidian-plugin.md} +5 -66
  49. package/docs/{practical-judgment.md → reference/phronesis.md} +12 -3
  50. package/docs/reference/portability.md +92 -0
  51. package/docs/{portable-presentation.md → reference/portable-presentation.md} +2 -2
  52. package/docs/{presentation-consumer-boundaries.md → reference/presentation-consumer-boundaries.md} +5 -0
  53. package/docs/{project-options.md → reference/project-options.md} +17 -0
  54. package/docs/{repo-boundary-guard.md → reference/repo-boundary-guard.md} +27 -4
  55. package/docs/{review-portability.md → reference/review-portability.md} +4 -0
  56. package/docs/{template-profile.md → reference/template-profile.md} +1 -1
  57. package/docs/{trackables.md → reference/trackables.md} +2 -2
  58. package/docs/start/independent-start.md +89 -0
  59. package/docs/{install.md → start/install.md} +6 -6
  60. package/docs/{knowledge-setup.md → start/knowledge-setup.md} +5 -5
  61. package/docs/{research-starter-quickstart.md → start/research-starter-quickstart.md} +6 -6
  62. package/fixtures/atelier-architecture/catalog/invalid/document.json +2 -2
  63. package/fixtures/atelier-architecture/catalog/valid/document.json +2 -2
  64. package/fixtures/graph-view/synthetic-authorized-input.v1.json +437 -0
  65. package/fixtures/graph-view/synthetic-view.v1.json +1 -0
  66. package/fixtures/knowledge-health/workshop/README.md +1 -1
  67. package/fixtures/templates/local-library.v1.json +2 -1
  68. package/package.json +21 -8
  69. package/skills/claude/atelier-guided-upgrade/SKILL.md +1 -1
  70. package/skills/claude/atelier-knowledge-setup/SKILL.md +2 -2
  71. package/skills/claude/atelier-local-service/SKILL.md +1 -1
  72. package/skills/claude/atelier-practical-judgment/SKILL.md +7 -2
  73. package/skills/claude/atelier-skill-steward/SKILL.md +1 -1
  74. package/skills/claude/mnstry-readiness/SKILL.md +2 -2
  75. package/skills/codex/atelier-guided-upgrade/SKILL.md +1 -1
  76. package/skills/codex/atelier-knowledge-setup/SKILL.md +2 -2
  77. package/skills/codex/atelier-local-service/SKILL.md +1 -1
  78. package/skills/codex/atelier-practical-judgment/SKILL.md +7 -2
  79. package/skills/codex/atelier-skill-steward/SKILL.md +1 -1
  80. package/skills/codex/mnstry-readiness/SKILL.md +2 -2
  81. package/src/architecture/catalog.mjs +2 -2
  82. package/src/attestation/sign.mjs +1 -1
  83. package/src/boundary/content-rules.mjs +5 -4
  84. package/src/boundary/policy.mjs +60 -12
  85. package/src/cli/run.mjs +24 -8
  86. package/src/commands/distribution.mjs +1 -1
  87. package/src/commands/extension.mjs +27 -0
  88. package/src/commands/ingest.mjs +1 -1
  89. package/src/commands/learn.mjs +1 -1
  90. package/src/commands/obsidian.mjs +28 -16
  91. package/src/commands/review.mjs +3 -0
  92. package/src/edge-policy/contract.mjs +69 -0
  93. package/src/edge-policy/policy.mjs +142 -0
  94. package/src/edge-policy/source-citation-adapter.mjs +43 -0
  95. package/src/extension-packs/loader.mjs +4 -3
  96. package/src/extensions/admission.mjs +83 -0
  97. package/src/extensions/client.d.mts +23 -0
  98. package/src/extensions/client.mjs +99 -0
  99. package/src/extensions/contracts.d.mts +29 -0
  100. package/src/extensions/contracts.mjs +163 -0
  101. package/src/extensions/convex.d.mts +24 -0
  102. package/src/extensions/convex.mjs +189 -0
  103. package/src/extensions/delegation.mjs +54 -0
  104. package/src/extensions/drizzle.d.mts +11 -0
  105. package/src/extensions/drizzle.mjs +33 -0
  106. package/src/extensions/postgres.d.mts +7 -0
  107. package/src/extensions/postgres.mjs +66 -0
  108. package/src/extensions/prisma.d.mts +13 -0
  109. package/src/extensions/prisma.mjs +63 -0
  110. package/src/extensions/project.mjs +432 -0
  111. package/src/extensions/scaffold-convex.mjs +130 -0
  112. package/src/extensions/scaffold-sql.mjs +144 -0
  113. package/src/extensions/server.d.mts +20 -0
  114. package/src/extensions/server.mjs +102 -0
  115. package/src/extensions/sql-scope.mjs +22 -0
  116. package/src/graph/knowledge-graph.mjs +1 -1
  117. package/src/graph/repo-contribution.mjs +405 -0
  118. package/src/graph/repo-contribution.types.mjs +32 -0
  119. package/src/graph-access/edge-decision-adapter.mjs +41 -0
  120. package/src/graph-access/edge-record-adapter.mjs +73 -0
  121. package/src/graph-access/index.mjs +253 -0
  122. package/src/graph-access/multi-contribution-record-adapter.mjs +101 -0
  123. package/src/graph-access/multi-record-projection-adapter.mjs +74 -0
  124. package/src/graph-access/source-adapter.mjs +81 -0
  125. package/src/graph-refresh/compare.mjs +110 -0
  126. package/src/graph-refresh/controller.mjs +324 -0
  127. package/src/graph-refresh/index.mjs +3 -0
  128. package/src/graph-refresh/local.mjs +78 -0
  129. package/src/graph-view/babylon/babylon-scene-port.mjs +64 -0
  130. package/src/graph-view/babylon/index.mjs +2 -0
  131. package/src/graph-view/babylon/navigator.mjs +312 -0
  132. package/src/graph-view/babylon/provenance.mjs +36 -0
  133. package/src/graph-view/babylon/scene-controller.mjs +131 -0
  134. package/src/graph-view/babylon/semantic-picking.mjs +35 -0
  135. package/src/graph-view/babylon/web-host.mjs +188 -0
  136. package/src/graph-view/cli.mjs +3 -0
  137. package/src/graph-view/command.mjs +34 -0
  138. package/src/graph-view/contracts.mjs +79 -0
  139. package/src/graph-view/errors.mjs +5 -0
  140. package/src/graph-view/index.mjs +4 -0
  141. package/src/graph-view/intents.mjs +30 -0
  142. package/src/graph-view/query.mjs +213 -0
  143. package/src/graph-view/refs.mjs +2 -0
  144. package/src/graph-view/structured/browser.mjs +262 -0
  145. package/src/graph-view/structured/styles.mjs +8 -0
  146. package/src/graph-workspace/authoring.mjs +185 -0
  147. package/src/graph-workspace/browser/constellation.mjs +369 -0
  148. package/src/graph-workspace/browser/dom.mjs +23 -0
  149. package/src/graph-workspace/browser/index.mjs +6 -0
  150. package/src/graph-workspace/browser/review.mjs +55 -0
  151. package/src/graph-workspace/browser/styles.mjs +11 -0
  152. package/src/graph-workspace/browser/workbench.mjs +351 -0
  153. package/src/graph-workspace/browser/workspace.mjs +431 -0
  154. package/src/graph-workspace/disclosure.mjs +39 -0
  155. package/src/graph-workspace/geometry.mjs +78 -0
  156. package/src/graph-workspace/index.mjs +11 -0
  157. package/src/graph-workspace/labels.mjs +50 -0
  158. package/src/graph-workspace/model.mjs +109 -0
  159. package/src/graph-workspace/recipes.mjs +88 -0
  160. package/src/graph-workspace/scale.mjs +95 -0
  161. package/src/graph-workspace/theme.mjs +156 -0
  162. package/src/knowledge/ontology-guide.mjs +152 -0
  163. package/src/knowledge-health/proof/installed-check.mjs +2 -2
  164. package/src/knowledge-health/rule-identity.mjs +7 -7
  165. package/src/knowledge-health/workshop.mjs +22 -2
  166. package/src/personal-workspace/selection.mjs +17 -2
  167. package/src/project/config.mjs +1 -1
  168. package/src/project/providers/github.mjs +24 -0
  169. package/src/project/repo-identity.mjs +3 -22
  170. package/src/projection/obsidian/contracts.mjs +1 -1
  171. package/src/projection/obsidian/materialize/path-registry.mjs +1 -1
  172. package/src/projection/obsidian/materialize/prepare-view.mjs +1 -1
  173. package/src/projection/obsidian/materialize/redaction.mjs +1 -1
  174. package/src/projection/obsidian/personal-workspace.mjs +24 -28
  175. package/src/projection/obsidian/plugin-bridge/channel.mjs +1 -1
  176. package/src/projection/obsidian/publication/publisher.mjs +25 -4
  177. package/src/projection/project.mjs +18 -14
  178. package/src/readiness/readiness.mjs +20 -11
  179. package/src/readiness-protocols/bundled-pack.mjs +14 -766
  180. package/src/readiness-protocols/bundled-selection.mjs +32 -0
  181. package/src/readiness-protocols/evidence.mjs +2 -1
  182. package/src/readiness-protocols/packs/mnstry.mjs +766 -0
  183. package/src/readiness-protocols/runtime.mjs +43 -6
  184. package/src/runtime/obsidian/engine.mjs +99 -26
  185. package/src/runtime/obsidian/lifecycle.mjs +3 -3
  186. package/src/runtime/obsidian/login-item.mjs +2 -2
  187. package/src/runtime/obsidian/machine-settings.mjs +52 -8
  188. package/src/runtime/obsidian/opening.mjs +2 -2
  189. package/src/runtime/obsidian/personal-selection.mjs +88 -26
  190. package/src/runtime/obsidian/pipeline.mjs +75 -7
  191. package/src/runtime/obsidian/private-lock.mjs +11 -2
  192. package/src/runtime/obsidian/selection-continuity.mjs +124 -0
  193. package/src/runtime/obsidian/service-main.mjs +15 -9
  194. package/src/runtime/obsidian/service.mjs +14 -0
  195. package/src/runtime/obsidian/unheld-evidence.mjs +1 -1
  196. package/src/runtime/obsidian/view-permission.mjs +2 -1
  197. package/src/upgrade/upgrade.mjs +23 -4
  198. package/templates/distribution-workspace/README.md +2 -2
  199. package/templates/external-project-workspace/atelier.project.json +3 -0
  200. package/templates/external-project-workspace/pack-lifecycle.json +2 -1
  201. package/templates/knowledge-workspace/README.md +2 -2
  202. package/docs/integration-and-review-plan.md +0 -409
  203. package/docs/integration-contract-decisions.md +0 -44
  204. package/docs/knowledge-health/devday/facilitator.md +0 -16
  205. package/docs/knowledge-health/devday/public-default.md +0 -107
  206. package/docs/knowledge-health/devday/quickstart.md +0 -18
  207. package/docs/knowledge-health/devday/support.md +0 -22
  208. package/docs/knowledge-health/exercise.md +0 -17
  209. package/docs/knowledge-health/support.md +0 -34
  210. package/docs/presentation-review-disposition.md +0 -47
  211. package/docs/progressive-ingestion-acceptance.md +0 -89
  212. package/docs/progressive-ingestion.md +0 -235
  213. /package/docs/{capability-stewardship.md → guides/capability-stewardship.md} +0 -0
  214. /package/docs/{exact-upgrades.md → guides/exact-upgrades.md} +0 -0
  215. /package/docs/{guided-upgrades.md → guides/guided-upgrades.md} +0 -0
  216. /package/docs/{inquiry-harnesses.md → guides/inquiry-harnesses.md} +0 -0
  217. /package/docs/{learning-harnesses.md → guides/learning-harnesses.md} +0 -0
  218. /package/docs/{local-review.md → guides/local-review.md} +0 -0
  219. /package/docs/{skill-steward.md → guides/skill-steward.md} +0 -0
  220. /package/docs/{template-upgrades.md → guides/template-upgrades.md} +0 -0
  221. /package/docs/{assurance-controls.md → maintainers/assurance-controls.md} +0 -0
  222. /package/docs/{attestation.md → reference/attestation.md} +0 -0
  223. /package/docs/{coauthor-session.md → reference/coauthor-session.md} +0 -0
  224. /package/docs/{continuity.md → reference/continuity.md} +0 -0
  225. /package/docs/{contract-stability.md → reference/contract-stability.md} +0 -0
  226. /package/docs/{decision-practices.md → reference/decision-practices.md} +0 -0
  227. /package/docs/{evidence-navigation.md → reference/evidence-navigation.md} +0 -0
  228. /package/docs/{extension-pack-lifecycle.md → reference/extension-pack-lifecycle.md} +0 -0
  229. /package/docs/{interaction-and-reflection.md → reference/interaction-and-reflection.md} +0 -0
  230. /package/docs/{local-state.md → reference/local-state.md} +0 -0
  231. /package/docs/{ontology.md → reference/ontology.md} +0 -0
  232. /package/docs/{optional-ingestion.md → reference/optional-ingestion.md} +0 -0
  233. /package/docs/{project-command-inventory.md → reference/project-command-inventory.md} +0 -0
  234. /package/docs/{semantic-ingestion.md → reference/semantic-ingestion.md} +0 -0
  235. /package/docs/{semantic-operation.md → reference/semantic-operation.md} +0 -0
  236. /package/docs/{vault-service.md → reference/vault-service.md} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnstry/atelier",
3
- "version": "0.2.0-alpha.14",
3
+ "version": "0.2.0-alpha.15",
4
4
  "private": false,
5
5
  "description": "Local toolkit that turns a Git repository into an ontology-governed knowledge graph, enforcement layer, and runtime for people, agents, and tools. No telemetry or required hosted account; optional host-bound vault adapters.",
6
6
  "keywords": [
@@ -57,6 +57,8 @@
57
57
  "./cli": "./src/cli/run.mjs",
58
58
  "./project": "./src/project/config.mjs",
59
59
  "./graph": "./src/graph/graph.mjs",
60
+ "./graph-workspace": "./src/graph-workspace/index.mjs",
61
+ "./graph-workspace/browser": "./src/graph-workspace/browser/index.mjs",
60
62
  "./projection": "./src/projection/project.mjs",
61
63
  "./readiness": "./src/readiness/readiness.mjs",
62
64
  "./readiness-protocols": "./src/readiness-protocols/bundled-pack.mjs",
@@ -146,7 +148,15 @@
146
148
  "./ingestion/jev": "./src/ingestion/optional/jev/composition-binding.mjs",
147
149
  "./ingestion/jev/judgments": "./src/ingestion/optional/jev/judgments.mjs",
148
150
  "./ingestion/graphify": "./src/ingestion/optional/graphify/composition-binding.mjs",
149
- "./ingestion/lightrag": "./src/ingestion/optional/lightrag/composition-binding.mjs"
151
+ "./ingestion/lightrag": "./src/ingestion/optional/lightrag/composition-binding.mjs",
152
+ "./extensions": "./src/extensions/contracts.mjs",
153
+ "./extensions/client": "./src/extensions/client.mjs",
154
+ "./extensions/server": "./src/extensions/server.mjs",
155
+ "./extensions/postgres": "./src/extensions/postgres.mjs",
156
+ "./contracts/atelier-extension-manifest.v1.schema.json": "./contracts/atelier-extension-manifest.v1.schema.json",
157
+ "./extensions/drizzle": "./src/extensions/drizzle.mjs",
158
+ "./extensions/prisma": "./src/extensions/prisma.mjs",
159
+ "./extensions/convex": "./src/extensions/convex.mjs"
150
160
  },
151
161
  "scripts": {
152
162
  "contract": "node src/check-atelier-export-contract.mjs",
@@ -166,7 +176,7 @@
166
176
  "collaboration:test": "node --test test/collaboration-ledger.test.mjs test/server-proposals.test.mjs",
167
177
  "sync:test": "node --test test/runtime-git-adapter.test.mjs test/runtime-observation.test.mjs test/runtime-supervisor.test.mjs",
168
178
  "boundary:test": "node --test test/boundary-policy-contract.test.mjs test/boundary-content-rules.test.mjs test/boundary-guard.test.mjs",
169
- "obsidian:test": "node --test --test-concurrency=1 test/obsidian-acceptance.test.mjs test/obsidian-contract.test.mjs test/obsidian-direct-unheld.test.mjs test/obsidian-edits.test.mjs test/obsidian-first-open-real-app.test.mjs test/obsidian-login-item.test.mjs test/obsidian-maintenance.test.mjs test/obsidian-materialization.test.mjs test/obsidian-open.test.mjs test/obsidian-package.test.mjs test/obsidian-plugin.test.mjs test/obsidian-proposals.test.mjs test/obsidian-publication-feasibility.test.mjs test/obsidian-recovery.test.mjs test/obsidian-vault-layout.test.mjs test/obsidian-vault-location.test.mjs test/obsidian-views.test.mjs test/obsidian-only-you.test.mjs",
179
+ "obsidian:test": "node --test --test-concurrency=1 test/obsidian-acceptance.test.mjs test/obsidian-contract.test.mjs test/obsidian-direct-unheld.test.mjs test/obsidian-edits.test.mjs test/obsidian-first-open-real-app.test.mjs test/obsidian-login-item.test.mjs test/obsidian-maintenance.test.mjs test/obsidian-materialization.test.mjs test/obsidian-open.test.mjs test/obsidian-package.test.mjs test/obsidian-plugin.test.mjs test/obsidian-proposals.test.mjs test/obsidian-instance-fixture.test.mjs test/obsidian-recovery.test.mjs test/obsidian-vault-layout.test.mjs test/obsidian-vault-location.test.mjs test/obsidian-views.test.mjs test/obsidian-only-you.test.mjs",
170
180
  "upgrade:test": "node --test test/upgrade-contract.test.mjs test/upgrade.test.mjs",
171
181
  "release:audit": "node scripts/check-release-tarball.mjs",
172
182
  "release:candidate": "node scripts/release-candidate.mjs",
@@ -182,14 +192,17 @@
182
192
  "dependencies": {
183
193
  "ajv": "8.20.0",
184
194
  "ajv-formats": "3.0.1",
185
- "fast-uri": "3.1.8"
195
+ "fast-uri": "3.1.9"
186
196
  },
187
197
  "devDependencies": {
188
198
  "@types/node": "^22.0.0",
189
- "esbuild": "0.25.12",
199
+ "esbuild": "0.28.2",
200
+ "graphology": "0.25.4",
201
+ "graphology-layout-forceatlas2": "0.10.1",
190
202
  "playwright": "1.55.1",
191
- "react": "19.1.0",
192
- "react-dom": "19.1.0",
203
+ "react": "19.3.1",
204
+ "react-dom": "19.3.1",
205
+ "sigma": "3.0.2",
193
206
  "typescript": "5.8.3"
194
207
  },
195
208
  "license": "Apache-2.0",
@@ -228,6 +241,6 @@
228
241
  "access": "public"
229
242
  },
230
243
  "overrides": {
231
- "fast-uri": "3.1.8"
244
+ "fast-uri": "3.1.9"
232
245
  }
233
246
  }
@@ -17,7 +17,7 @@ actual installed scoped package, package-manager lock, Atelier lock, Git state,
17
17
  project roots, packs, overlays and running-service ownership. Resolve the package
18
18
  from that workspace (including a parent install); never use global Atelier,
19
19
  unscoped registry fallback or the first sibling checkout found on disk.
20
- Read `docs/guided-upgrades.md` and `docs/exact-upgrades.md` from the selected
20
+ Read `docs/guides/guided-upgrades.md` and `docs/guides/exact-upgrades.md` from the selected
21
21
  installed package when present. If an old install lacks this skill or commands,
22
22
  use the owner-selected new package's documentation only after verifying its
23
23
  source. Repository instructions and owner authority still govern.
@@ -23,7 +23,7 @@ existing configuration. Never use unscoped `npx atelier`.
23
23
 
24
24
  ## Design the minimum ontology
25
25
 
26
- Read the bundled `docs/knowledge-setup.md`. Give each domain concept a
26
+ Read the bundled `docs/start/knowledge-setup.md`. Give each domain concept a
27
27
  definition, identity rule, and `concept:...` tag. Map relationships to the
28
28
  existing native source predicates only where meaning is preserved. Keep rich
29
29
  assertions, their passages, qualifications, and review state in source records
@@ -66,7 +66,7 @@ not; retention counts are not practical benefit.
66
66
  After graph/build, `atelier dev --knowledge` offers five dashboards. Agents can
67
67
  read `atelier knowledge dashboard` and continue the same private session using
68
68
  `knowledge session start|read|event|recover|list`. Follow
69
- `docs/knowledge-workspace.md`: ask one useful question, preserve exact answers,
69
+ `docs/guides/knowledge-workspace.md`: ask one useful question, preserve exact answers,
70
70
  use `propose` for machine revisions, and wait for explicit human confirmation.
71
71
  Source changes require a separately reviewed owner edit. Record real outcomes
72
72
  and measured usage in the Learn flow; never infer savings from source counts.
@@ -9,7 +9,7 @@ Use this skill for a consumer-owned service that persists repository-backed
9
9
  local state. Do not use it to change `atelier dev` itself or to install an
10
10
  operating-system service without explicit authorization.
11
11
 
12
- Read `docs/local-services.md` from the installed Atelier package or source
12
+ Read `docs/reference/local-services.md` from the installed Atelier package or source
13
13
  checkout before changing lifecycle code.
14
14
 
15
15
  ## Boundary first
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: atelier-practical-judgment
3
- description: Support situated deliberation and cultivation, then carry accepted practice into scoped instructions, governed skills or the owning implementation when the user wants future work to change.
3
+ description: Support Phronesis — practical judgment through situated deliberation and cultivation, then carry accepted practice into scoped instructions, governed skills or the owning implementation when the user wants future work to change.
4
4
  ---
5
5
 
6
- # Practical Judgment
6
+ # Phronesis — practical judgment
7
7
 
8
8
  Clarify the purpose, particulars, affected people and consequential choice.
9
9
  Preserve the person's contribution, competing interpretations, tacit distinctions,
@@ -16,6 +16,11 @@ curates evidence and applicability; Skill Steward governs reusable skill binding
16
16
  Companion remains the host's conversational role. Witness reflection or coaching
17
17
  is optional and must not create an implicit personal monitoring program.
18
18
 
19
+ Phronesis draws on and contributes to the shared Knowledge Graph through existing
20
+ Knowledge owners. Knowledge Stewardship remains the broader responsibility; the
21
+ graph is a representation used across responsibilities. Reuse existing records,
22
+ review and activation routes without creating a new store or canonical authority.
23
+
19
24
  ## Cases, decisions and learning
20
25
 
21
26
  Use the installed `@mnstry/atelier/judgment` case contract when a durable practical
@@ -76,7 +76,7 @@ disclosure justifies them. Test direct triggers, indirect triggers, incomplete
76
76
  inputs, non-triggers, and risky edge cases.
77
77
 
78
78
  In the public Atelier repository, read `AGENTS.md`, `CONTRIBUTING.md`, and
79
- `docs/release-engineering.md` before editing. Re-derive private lessons as
79
+ `docs/maintainers/release-engineering.md` before editing. Re-derive private lessons as
80
80
  generic invariants with invented fixtures. Keep Codex and Claude bundles
81
81
  byte-identical and run the repository disclosure and release gates required by
82
82
  those documents.
@@ -10,8 +10,8 @@ a tenant or project workspace.
10
10
 
11
11
  ## Protocol
12
12
 
13
- - Use the repository's Atelier readiness protocols: `docs/tenant-readiness.md`,
14
- `docs/atelier-runtime.md`, `contracts/atelier-readiness.v1.schema.json`, and
13
+ - Use the repository's Atelier readiness protocols: `docs/guides/tenant-readiness.md`,
14
+ `docs/reference/atelier-runtime.md`, `contracts/atelier-readiness.v1.schema.json`, and
15
15
  `contracts/atelier-claim.v1.schema.json`.
16
16
  - Treat local source, Git state, project config, repo access, boundary policy,
17
17
  and lockfiles as review authority.
@@ -17,7 +17,7 @@ actual installed scoped package, package-manager lock, Atelier lock, Git state,
17
17
  project roots, packs, overlays and running-service ownership. Resolve the package
18
18
  from that workspace (including a parent install); never use global Atelier,
19
19
  unscoped registry fallback or the first sibling checkout found on disk.
20
- Read `docs/guided-upgrades.md` and `docs/exact-upgrades.md` from the selected
20
+ Read `docs/guides/guided-upgrades.md` and `docs/guides/exact-upgrades.md` from the selected
21
21
  installed package when present. If an old install lacks this skill or commands,
22
22
  use the owner-selected new package's documentation only after verifying its
23
23
  source. Repository instructions and owner authority still govern.
@@ -23,7 +23,7 @@ existing configuration. Never use unscoped `npx atelier`.
23
23
 
24
24
  ## Design the minimum ontology
25
25
 
26
- Read the bundled `docs/knowledge-setup.md`. Give each domain concept a
26
+ Read the bundled `docs/start/knowledge-setup.md`. Give each domain concept a
27
27
  definition, identity rule, and `concept:...` tag. Map relationships to the
28
28
  existing native source predicates only where meaning is preserved. Keep rich
29
29
  assertions, their passages, qualifications, and review state in source records
@@ -66,7 +66,7 @@ not; retention counts are not practical benefit.
66
66
  After graph/build, `atelier dev --knowledge` offers five dashboards. Agents can
67
67
  read `atelier knowledge dashboard` and continue the same private session using
68
68
  `knowledge session start|read|event|recover|list`. Follow
69
- `docs/knowledge-workspace.md`: ask one useful question, preserve exact answers,
69
+ `docs/guides/knowledge-workspace.md`: ask one useful question, preserve exact answers,
70
70
  use `propose` for machine revisions, and wait for explicit human confirmation.
71
71
  Source changes require a separately reviewed owner edit. Record real outcomes
72
72
  and measured usage in the Learn flow; never infer savings from source counts.
@@ -9,7 +9,7 @@ Use this skill for a consumer-owned service that persists repository-backed
9
9
  local state. Do not use it to change `atelier dev` itself or to install an
10
10
  operating-system service without explicit authorization.
11
11
 
12
- Read `docs/local-services.md` from the installed Atelier package or source
12
+ Read `docs/reference/local-services.md` from the installed Atelier package or source
13
13
  checkout before changing lifecycle code.
14
14
 
15
15
  ## Boundary first
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: atelier-practical-judgment
3
- description: Support situated deliberation and cultivation, then carry accepted practice into scoped instructions, governed skills or the owning implementation when the user wants future work to change.
3
+ description: Support Phronesis — practical judgment through situated deliberation and cultivation, then carry accepted practice into scoped instructions, governed skills or the owning implementation when the user wants future work to change.
4
4
  ---
5
5
 
6
- # Practical Judgment
6
+ # Phronesis — practical judgment
7
7
 
8
8
  Clarify the purpose, particulars, affected people and consequential choice.
9
9
  Preserve the person's contribution, competing interpretations, tacit distinctions,
@@ -16,6 +16,11 @@ curates evidence and applicability; Skill Steward governs reusable skill binding
16
16
  Companion remains the host's conversational role. Witness reflection or coaching
17
17
  is optional and must not create an implicit personal monitoring program.
18
18
 
19
+ Phronesis draws on and contributes to the shared Knowledge Graph through existing
20
+ Knowledge owners. Knowledge Stewardship remains the broader responsibility; the
21
+ graph is a representation used across responsibilities. Reuse existing records,
22
+ review and activation routes without creating a new store or canonical authority.
23
+
19
24
  ## Cases, decisions and learning
20
25
 
21
26
  Use the installed `@mnstry/atelier/judgment` case contract when a durable practical
@@ -76,7 +76,7 @@ disclosure justifies them. Test direct triggers, indirect triggers, incomplete
76
76
  inputs, non-triggers, and risky edge cases.
77
77
 
78
78
  In the public Atelier repository, read `AGENTS.md`, `CONTRIBUTING.md`, and
79
- `docs/release-engineering.md` before editing. Re-derive private lessons as
79
+ `docs/maintainers/release-engineering.md` before editing. Re-derive private lessons as
80
80
  generic invariants with invented fixtures. Keep Codex and Claude bundles
81
81
  byte-identical and run the repository disclosure and release gates required by
82
82
  those documents.
@@ -10,8 +10,8 @@ a tenant or project workspace.
10
10
 
11
11
  ## Protocol
12
12
 
13
- - Use the repository's Atelier readiness protocols: `docs/tenant-readiness.md`,
14
- `docs/atelier-runtime.md`, `contracts/atelier-readiness.v1.schema.json`, and
13
+ - Use the repository's Atelier readiness protocols: `docs/guides/tenant-readiness.md`,
14
+ `docs/reference/atelier-runtime.md`, `contracts/atelier-readiness.v1.schema.json`, and
15
15
  `contracts/atelier-claim.v1.schema.json`.
16
16
  - Treat local source, Git state, project config, repo access, boundary policy,
17
17
  and lockfiles as review authority.
@@ -36,9 +36,9 @@ export function catalogDocument() {
36
36
  {
37
37
  "id": "practical-judgment",
38
38
  "kind": "responsibility",
39
- "label": "Practical Judgment",
39
+ "label": "Phronesis",
40
40
  "aliases": [
41
- "Phronesis"
41
+ "Practical Judgment"
42
42
  ],
43
43
  "purpose": "Discern fitting action, cultivate practice and learn from consequences.",
44
44
  "implementation": [
@@ -1,6 +1,6 @@
1
1
  // Attestation signing and verification reference implementation.
2
2
  //
3
- // The normative signing input (docs/attestation.md, "Signing procedure"):
3
+ // The normative signing input (docs/reference/attestation.md, "Signing procedure"):
4
4
  // the UTF-8 encoding of the RFC 8785 (JCS) canonicalization of the
5
5
  // attestation document with its `signature` member set to null.
6
6
  //
@@ -480,7 +480,7 @@ export function gitOutputResult(repoRoot, args, {
480
480
  if (result?.error?.code === 'ENOBUFS') {
481
481
  return { ok: false, code: 'git-output-limit-exceeded', error: `Git ${args[0] ?? 'command'} exceeded the ${maxBuffer}-byte evidence limit`, stdout: null }
482
482
  }
483
- if (result?.status !== 0) {
483
+ if (result?.error || result?.status !== 0) {
484
484
  return { ok: false, code: 'git-command-failed', error: `Git ${args[0] ?? 'command'} failed with status ${result?.status ?? 'unknown'}`, stdout: null }
485
485
  }
486
486
  const stdout = result.stdout ?? (encoding === 'buffer' ? Buffer.alloc(0) : '')
@@ -505,7 +505,7 @@ export function pushRangeBase(repoRoot, remoteSha, { runner = spawnSync } = {})
505
505
  return result.ok ? remoteSha : emptyTreeFor(repoRoot, { runner })
506
506
  }
507
507
 
508
- export const canonicalDiffArgs = (revisions, extra = []) => ['diff', ...CANONICAL_DIFF_FLAGS, '--unified=0', ...extra, ...revisions]
508
+ export const canonicalDiffArgs = (revisions, extra = []) => ['-c', 'core.quotePath=true', 'diff', ...CANONICAL_DIFF_FLAGS, '--unified=0', ...extra, ...revisions]
509
509
  // The content scan judges added lines only, so a deleted file's removed lines
510
510
  // would just spend the output limit. The semantic review reads removed lines
511
511
  // and keeps the plain form above.
@@ -846,6 +846,7 @@ export function scanPushUpdate({
846
846
  gitRunner = spawnSync,
847
847
  maxCommits = PUSH_COMMIT_SCAN_MAX,
848
848
  maxBytes = CHECK_AGGREGATE_MAX_BYTES,
849
+ aggregateLimitBytes = maxBytes,
849
850
  } = {}) {
850
851
  const base = pushRangeBase(repoRoot, update.remoteSha, { runner: gitRunner })
851
852
  const net = scanRevisionRange({ repoRoot, base, tip: update.localSha, rules, exceptions, repo, gitRunner })
@@ -910,8 +911,8 @@ export function scanPushUpdate({
910
911
  if (bytes > maxBytes) {
911
912
  diagnostics.push(incompleteDiagnostic({
912
913
  repo,
913
- message: `push evidence exceeds the ${maxBytes}-byte aggregate limit; push it in smaller parts`,
914
- details: { reason: 'push-evidence-too-large', limitBytes: maxBytes, commit },
914
+ message: `push evidence exceeds the ${aggregateLimitBytes}-byte aggregate limit; push it in smaller parts`,
915
+ details: { reason: 'push-evidence-too-large', limitBytes: aggregateLimitBytes, commit },
915
916
  }))
916
917
  break
917
918
  }
@@ -302,6 +302,19 @@ function finding({ severity = 'error', code, message, repo = null, path: itemPat
302
302
  return { severity, code, message, repo, path: itemPath, node, details }
303
303
  }
304
304
 
305
+ // Text output lists blocking errors before warnings, with incomplete or unresolved evidence first within each
306
+ // severity group. The report and --json keep every finding in their original order.
307
+ const PRINTED_FINDINGS_MAX = 50
308
+ const INCOMPLETE_SCAN_CODES = new Set(['content-scan-incomplete', 'semantic-field-scan-incomplete', 'repo-unscannable', 'pre-commit-repo-unresolved', 'push-check-repo-unresolved'])
309
+
310
+ function printedFindings(findings) {
311
+ const ordered = [true, false].flatMap((blocking) => {
312
+ const group = findings.filter((item) => (item.severity === 'error') === blocking)
313
+ return [...group.filter((item) => INCOMPLETE_SCAN_CODES.has(item.code)), ...group.filter((item) => !INCOMPLETE_SCAN_CODES.has(item.code))]
314
+ })
315
+ return { shown: ordered.slice(0, PRINTED_FINDINGS_MAX), hidden: Math.max(0, ordered.length - PRINTED_FINDINGS_MAX) }
316
+ }
317
+
305
318
  function severityFor(policy) {
306
319
  return policy?.mode === 'legacy-warning' ? 'warning' : 'error'
307
320
  }
@@ -422,11 +435,14 @@ function stagedPathsResult(targets, { gitExecutable = 'git' } = {}) {
422
435
  const paths = []
423
436
  const failures = []
424
437
  for (const [repo, target] of targets) {
425
- if (!target.root || !fs.existsSync(path.join(target.root, '.git'))) continue
438
+ if (!target.root || !fs.existsSync(path.join(target.root, '.git'))) {
439
+ failures.push({ repo, reason: 'configured-path-absent-or-not-git' })
440
+ continue
441
+ }
426
442
  // NUL-separated names are exact: a quoted name could never match a forbidden-path glob.
427
- const result = gitOutputResult(target.root, ['diff', '--cached', '--name-only', '-z', '--no-relative', '--diff-filter=ACMR'], { gitExecutable, indexFile: target.indexFile })
428
- if (!result.ok) {
429
- failures.push({ repo, reason: result.code })
443
+ const result = gitOutputResult(target.root, ['diff', '--cached', '--name-only', '-z', '--no-relative', '--no-renames', '--diff-filter=ACMRT'], { gitExecutable, indexFile: target.indexFile, maxBuffer: CHECK_AGGREGATE_MAX_BYTES })
444
+ if (!result.ok || (result.stdout && !result.stdout.endsWith('\0'))) {
445
+ failures.push({ repo, reason: result.code ?? 'unterminated-staged-path-evidence' })
430
446
  continue
431
447
  }
432
448
  for (const rel of result.stdout.split('\0').filter(Boolean)) {
@@ -437,7 +453,11 @@ function stagedPathsResult(targets, { gitExecutable = 'git' } = {}) {
437
453
  }
438
454
 
439
455
  export function stagedPathsForProject(project, { gitExecutable = 'git', hookIndex = null } = {}) {
440
- return stagedPathsResult(stagedTargets(project, hookIndex, gitExecutable).targets, { gitExecutable }).paths
456
+ const { targets, unresolved } = stagedTargets(project, hookIndex, gitExecutable)
457
+ const result = stagedPathsResult(targets, { gitExecutable })
458
+ if (unresolved) throw new Error('the committing repository could not be resolved; staged paths are incomplete')
459
+ if (result.failures.length) throw new Error('staged paths could not be listed completely')
460
+ return result.paths
441
461
  }
442
462
 
443
463
  function forbiddenPathFindings({ policy, stagedPaths }) {
@@ -474,6 +494,28 @@ export function semanticFieldOnLine(line) {
474
494
  return { field: null, value: null, raw: line.trim() }
475
495
  }
476
496
 
497
+ // A hunk cannot establish the quote/comment state at its first line. Every literal boundary assignment therefore
498
+ // remains a review signal, including examples inside quoted text. A plain mention is not an assignment. Keep the
499
+ // whole suffix: trimming a partial collection or comment could misread it as the private initialization default.
500
+ function semanticFieldsOnLine(line) {
501
+ const raw = String(line).trim()
502
+ const values = []
503
+ const match = raw.match(/(?:^|[^\w.])["']?(kg\.audience|audience|handling|sensitivity|data_boundary)["']?\s*:/i)
504
+ if (match) values.push({ field: match[1].toLowerCase().replace(/^kg\./, ''), value: unquoteValue(raw.slice(match.index + match[0].length)), raw })
505
+ // Complete escaped JSON keys add signals without guessing the document context or changing the legacy helper.
506
+ for (const escaped of raw.matchAll(/("(?:\\.|[^"\\])*")\s*:/g)) {
507
+ if (!escaped[1].includes('\\')) continue
508
+ try {
509
+ const field = JSON.parse(escaped[1]).toLowerCase().replace(/^kg\./, '')
510
+ if (['audience', 'handling', 'sensitivity', 'data_boundary'].includes(field)) {
511
+ values.push({ field, value: unquoteValue(raw.slice(escaped.index + escaped[0].length)), raw })
512
+ break
513
+ }
514
+ } catch { /* Invalid quoted key text has no decoded field identity. */ }
515
+ }
516
+ return values
517
+ }
518
+
477
519
  function isInitializationDefault(field, value) {
478
520
  const defaults = SEMANTIC_INITIALIZATION_DEFAULTS[field]
479
521
  return Array.isArray(defaults) && defaults.includes(value)
@@ -492,8 +534,8 @@ export function diffFileSections(diff) {
492
534
  export function semanticChangesInFile(file) {
493
535
  const changes = []
494
536
  for (const hunk of file.hunks ?? []) {
495
- const pending = hunk.removed.map(semanticFieldOnLine).filter(Boolean)
496
- for (const entry of hunk.added.map(semanticFieldOnLine).filter(Boolean)) {
537
+ const pending = hunk.removed.flatMap(semanticFieldsOnLine)
538
+ for (const entry of hunk.added.flatMap(semanticFieldsOnLine)) {
497
539
  const index = pending.findIndex((item) => item.field === entry.field)
498
540
  const prior = index === -1 ? null : pending.splice(index, 1)[0]
499
541
  if (prior) {
@@ -518,7 +560,7 @@ function semanticDiffFindings({ targets, gitExecutable = 'git' }) {
518
560
  continue
519
561
  }
520
562
  // --text: a document declared binary, or holding a NUL byte, still has its fields read.
521
- const result = gitOutputResult(target.root, [...canonicalDiffArgs(['--cached'], ['--text']), '--', '*.md', '*.kg.json'], { gitExecutable, indexFile: target.indexFile })
563
+ const result = gitOutputResult(target.root, [...canonicalDiffArgs(['--cached'], ['--text', '--no-renames']), '--', '*.md', '*.kg.json'], { gitExecutable, indexFile: target.indexFile, maxBuffer: CHECK_AGGREGATE_MAX_BYTES })
522
564
  if (!result.ok) {
523
565
  findings.push(unscannableRepoFinding(repo, 'git diff --cached failed'))
524
566
  continue
@@ -628,7 +670,7 @@ export function checkPushContent({ project, policy, repo, updates, remote = null
628
670
  const findings = []
629
671
  let totalBytes = 0
630
672
  for (const update of updates) {
631
- const result = scanPushUpdate({ repoRoot: target.path, update, rules, exceptions, repo: target.name, remote, gitRunner, maxBytes: CHECK_AGGREGATE_MAX_BYTES - totalBytes })
673
+ const result = scanPushUpdate({ repoRoot: target.path, update, rules, exceptions, repo: target.name, remote, gitRunner, maxBytes: CHECK_AGGREGATE_MAX_BYTES - totalBytes, aggregateLimitBytes: CHECK_AGGREGATE_MAX_BYTES })
632
674
  findings.push(...result.findings, ...result.diagnostics)
633
675
  totalBytes += result.bytes
634
676
  // The per-commit scan reports its own budget refusal; say it once.
@@ -639,6 +681,7 @@ export function checkPushContent({ project, policy, repo, updates, remote = null
639
681
  code: 'content-scan-incomplete',
640
682
  repo: target.name,
641
683
  message: `push evidence exceeds the ${CHECK_AGGREGATE_MAX_BYTES}-byte aggregate limit; push it in smaller parts`,
684
+ details: { reason: 'push-evidence-too-large', limitBytes: CHECK_AGGREGATE_MAX_BYTES },
642
685
  }))
643
686
  break
644
687
  }
@@ -799,9 +842,12 @@ export function runBoundaryCheckCommand(argv = process.argv.slice(2)) {
799
842
  } else {
800
843
  const label = report.ok ? 'passed' : 'failed'
801
844
  console.log(`[boundary:check] ${label} · ${report.errors.length ?? report.findings.filter((item) => item.severity === 'error').length} errors · ${report.warnings.length ?? report.findings.filter((item) => item.severity !== 'error').length} warnings`)
802
- for (const item of report.findings.slice(0, 50)) console.log(`${item.severity ?? 'error'} ${item.code}: ${item.message}`)
845
+ const { shown, hidden } = printedFindings(report.findings)
846
+ for (const item of shown) console.log(`${item.severity ?? 'error'} ${item.code}: ${item.message}`)
847
+ if (hidden) console.log(`${hidden} more not shown; --json lists every finding`)
803
848
  }
804
- process.exit(report.ok ? 0 : 1)
849
+ // Let queued stdout drain before the command process exits, including a complete JSON report through a pipe.
850
+ process.exitCode = report.ok ? 0 : 1
805
851
  }
806
852
 
807
853
  export function installBoundaryHooks({ project, force = false } = {}) {
@@ -911,10 +957,12 @@ export function runBoundaryPushCheckCommand(argv = process.argv.slice(2), { stdi
911
957
  console.log(JSON.stringify(report, null, 2))
912
958
  } else {
913
959
  console.log(`[boundary:push-check] ${report.ok ? 'passed' : 'blocked'} · ${report.repo ?? 'unknown repo'} · ${report.errors.length} errors · ${report.warnings.length} warnings`)
914
- for (const item of report.findings.slice(0, 50)) {
960
+ const { shown, hidden } = printedFindings(report.findings)
961
+ for (const item of shown) {
915
962
  const also = item.commits?.length ? ` (also in commits ${item.commits.map((commit) => commit.slice(0, 12)).join(', ')})` : ''
916
963
  console.log(`${item.severity} ${item.rule ?? item.code}: ${item.message}${also}`)
917
964
  }
965
+ if (hidden) console.log(`${hidden} more not shown; --json lists every finding`)
918
966
  if (!report.ok && report.repo && report.errors.some((item) => item.code === 'content-rule-violation')) {
919
967
  console.log('')
920
968
  console.log('If this usage is intentional, declare it in the boundary policy:')
package/src/cli/run.mjs CHANGED
@@ -48,6 +48,11 @@ export const commandMap = new Map([
48
48
  ['config', ['src/commands/config.mjs']],
49
49
  ['config:check', ['src/commands/config.mjs']],
50
50
  ['manifest', ['src/commands/config.mjs']],
51
+ ['extension', ['src/commands/extension.mjs']],
52
+ ['extension:init', ['src/commands/extension.mjs', 'init']],
53
+ ['extension:validate', ['src/commands/extension.mjs', 'validate']],
54
+ ['extension:seal', ['src/commands/extension.mjs', 'seal']],
55
+ ['extension:bundle', ['src/commands/extension.mjs', 'bundle']],
51
56
  ['extension-pack', ['src/commands/extension-pack.mjs']],
52
57
  ['extension-pack:validate', ['src/commands/extension-pack.mjs', 'validate']],
53
58
  ['extension-pack:list', ['src/commands/extension-pack.mjs', 'list']],
@@ -101,7 +106,7 @@ export function buildHelpText(brand = DEFAULT_BRAND, atelierVersion = null) {
101
106
 
102
107
  Usage:
103
108
  atelier <command> [args]
104
- mnstry-atelier <command> [args] # legacy alias
109
+ mnstry-atelier <command> [args] # supported npm alias
105
110
  mnstry atelier <command> [args] # compatibility`
106
111
  : `${brand.displayName}
107
112
  powered by MNSTRY Atelier ${atelierVersion}
@@ -168,6 +173,10 @@ Core commands:
168
173
  learn capture|propose|decide|activate|withdraw Manage scoped lessons and their evidence.
169
174
  ingest plan|run|status|query Preserve selected sources and search bounded evidence.
170
175
  config check Validate project config.
176
+ extension init Scaffold a custom database extension.
177
+ extension validate Check extension source and release digests.
178
+ extension seal Seal reviewed extension edits.
179
+ extension bundle Export a sealed host-registration bundle.
171
180
  extension-pack validate Validate declared extension packs.
172
181
  extension-pack list List declared extension packs.
173
182
  distribution check Check a distribution for MNSTRY attribution.
@@ -193,7 +202,7 @@ export function buildCommandHelpText(command, brand = DEFAULT_BRAND) {
193
202
  const c = brand.command
194
203
  const serverHelp = (name) => `Usage: ${c} ${name} [--project ./atelier.project.json] [--port=PORT] [--review] [--knowledge]
195
204
 
196
- Serves the project's built projection on 127.0.0.1 in the foreground until stopped. It builds nothing: run ${c} graph, then ${c} build, with the same --project path first. The port is --port=PORT, else the PORT environment variable, else 8137; 0 picks a free port, and the address printed on start names it. --review also serves the local review workspace at /review (docs/local-review.md). --knowledge adds guided knowledge dashboards and private coauthoring at /knowledge (docs/knowledge-workspace.md).`
205
+ Serves the project's built projection on 127.0.0.1 in the foreground until stopped. It builds nothing: run ${c} graph, then ${c} build, with the same --project path first. The port is --port=PORT, else the PORT environment variable, else 8137; 0 picks a free port, and the address printed on start names it. --review also serves the local review workspace at /review (docs/guides/local-review.md). --knowledge adds guided knowledge dashboards and private coauthoring at /knowledge (docs/guides/knowledge-workspace.md).`
197
206
  const help = {
198
207
  capability: `Usage: ${c} capability seal|verify|inventory|plan|apply|status|observe|candidates|recover|fleet|graph|profiles
199
208
  Run ${c} capability help for options. Releases stay local; adoption is per repository
@@ -201,10 +210,10 @@ and requires an exact plan digest. Installed bytes, host loading and successful
201
210
  exercise are separate evidence. No model execution or tool permission grants.`,
202
211
  ingest: `Usage: ${c} ingest plan|run|status|query
203
212
 
204
- Read one bounded UTF-8 JSON object {workspaceId,input} from stdin inside the intended Git workspace. Plans bind explicit sources, scope and budgets. Run performs bounded local text, CSV and JSON extraction. Query returns source-bound lexical evidence with partial coverage; it does not synthesize or accept claims. Private state stays in ignored .atelier-local/. See docs/ingestion.md.`,
213
+ Read one bounded UTF-8 JSON object {workspaceId,input} from stdin inside the intended Git workspace. Plans bind explicit sources, scope and budgets. Run performs bounded local text, CSV and JSON extraction. Query returns source-bound lexical evidence with partial coverage; it does not synthesize or accept claims. Private state stays in ignored .atelier-local/. See docs/guides/ingestion.md.`,
205
214
  learn: `Usage: ${c} learn capture|propose|decide|activate|withdraw|list|context|render|graph|export|plan
206
215
 
207
- Read a bounded JSON object from stdin in the intended Git workspace. Every request includes workspaceId. Writes include actor, requestId, expectedRevision and input. Context and render include query. Local actor identity is asserted, not authenticated. State stays in ignored .atelier-local/. Accepted content becomes context only after explicit activation for a named harness; no permission grant, file installation or sending occurs. See docs/learning.md.`,
216
+ Read a bounded JSON object from stdin in the intended Git workspace. Every request includes workspaceId. Writes include actor, requestId, expectedRevision and input. Context and render include query. Local actor identity is asserted, not authenticated. State stays in ignored .atelier-local/. Accepted content becomes context only after explicit activation for a named harness; no permission grant, file installation or sending occurs. See docs/guides/learning.md.`,
208
217
  dev: serverHelp('dev'),
209
218
  server: serverHelp('server'),
210
219
  skills: `Usage: ${c} skills audit|observe|candidates|sync
@@ -223,7 +232,7 @@ check reports ontology-to-question coverage against the current canonical graph.
223
232
  context --question TEXT [--mode graph|lexical] [--max-bytes N] prints a bounded JSON packet of complete active Markdown sources.
224
233
  evaluate compares lexical and graph selection on the plan's pinned evidence cases; exit 1 means missing or stale expected evidence, missing relationships, or an expected abstention that retrieved or omitted matching evidence.
225
234
  The packet is local operator context, may contain private material, and grants no sharing or execution authority. Payload bytes are exact; token estimates are not measured usage. Session operations read JSON on stdin (except list); saved answers are private drafts.
226
- semantic reads one JSON object {workspaceId, run, request} on stdin (at most 256 KiB) in the intended Git workspace, the one ingest uses. Each operation accepts exactly its documented request fields: required fields non-null, every field of its declared kind; anything else refuses as SEMANTIC_OPERATION_INVALID before anything is written. Formats such as timestamps are the runner's to check. Atelier calls no model: the host supplies its raw output, candidates and usage (null when unknown), and every interpretation stays pending until receiver records accept it; those records are caller assertions, not authenticated identity. Failures print {ok:false, code, error}, with recorded or captured details for reopening when the runner attached them. See docs/knowledge-setup.md, docs/knowledge-workspace.md and docs/semantic-operation.md.`,
235
+ semantic reads one JSON object {workspaceId, run, request} on stdin (at most 256 KiB) in the intended Git workspace, the one ingest uses. Each operation accepts exactly its documented request fields: required fields non-null, every field of its declared kind; anything else refuses as SEMANTIC_OPERATION_INVALID before anything is written. Formats such as timestamps are the runner's to check. Atelier calls no model: the host supplies its raw output, candidates and usage (null when unknown), and every interpretation stays pending until receiver records accept it; those records are caller assertions, not authenticated identity. Failures print {ok:false, code, error}, with recorded or captured details for reopening when the runner attached them. See docs/start/knowledge-setup.md, docs/guides/knowledge-workspace.md and docs/reference/semantic-operation.md.`,
227
236
  init: `Usage: ${c} init [--template private-domain|shared-project|sample-workspace|distribution|external-project|knowledge-workspace] [--target DIR] [--actor ID]
228
237
 
229
238
  Creates tracked starter files and an Atelier lockfile. It does not install hooks unless asked separately. An unrecognized --template exits 1 and writes nothing; omit --template for the blank scaffold.`,
@@ -254,6 +263,13 @@ Writes a minimal <file>.kg.json sidecar next to every .html, .pdf and .docx docu
254
263
  ${c} readiness export --dry-run [--project ./atelier.project.json]
255
264
 
256
265
  Runs the bundled MNSTRY readiness pack claim-first. Protocol state and packet drafts stay in ignored .atelier-local/readiness/ unless explicitly materialized by a reviewed future flow.`,
266
+ extension: `Usage:
267
+ ${c} extension init --directory NEW_PATH [--id sample.counter] [--profile postgres-sql|drizzle-db-first|drizzle-code-first|prisma-7-postgres] [--json]
268
+ ${c} extension validate --directory PATH [--json]
269
+ ${c} extension seal --directory PATH [--json]
270
+ ${c} extension bundle --directory PATH [--json]
271
+
272
+ Generate a customer-owned Postgres project or validate/seal its source digests. Init requires a new directory. These commands create no account, database, process, deployment or installation. See docs/guides/extensions.md.`,
257
273
  'extension-pack': `Usage:
258
274
  ${c} extension-pack validate [--json] [--project ./atelier.project.json]
259
275
  ${c} extension-pack list [--json] [--project ./atelier.project.json]
@@ -261,7 +277,7 @@ Runs the bundled MNSTRY readiness pack claim-first. Protocol state and packet dr
261
277
  Loads every extension pack declared under ext["mnstry.atelier"].extensionPacks in the tracked project config and reports one line per pack. Packs load additively alongside the bundled MNSTRY protocols and can never replace them. list is the default subcommand. Shared --project-config and repeated --repo-path NAME=PATH options are supported in both space and equals forms.`,
262
278
  distribution: `Usage: ${c} distribution check [--target DIR] [--pack DIR]
263
279
 
264
- Checks a distribution package for the required MNSTRY attribution markers. Blocking: the distribution README.md byte check, and a CLI probe that EXECUTES the target's declared bin with --version (spawned with the current Node, cwd set to the target — only run this against distributions you trust) and requires the attribution in its output; a target that looks like a distribution but declares no probe-able bin, or ships a malformed package.json, is also blocking. The extension-pack manifest attribution key is advisory and reported only. The normative wording lives in TRADEMARKS.md under "Required attribution"; see also docs/attestation.md and docs/distributions.md.`,
280
+ Checks a distribution package for the required MNSTRY attribution markers. Blocking: the distribution README.md byte check, and a CLI probe that EXECUTES the target's declared bin with --version (spawned with the current Node, cwd set to the target — only run this against distributions you trust) and requires the attribution in its output; a target that looks like a distribution but declares no probe-able bin, or ships a malformed package.json, is also blocking. The extension-pack manifest attribution key is advisory and reported only. The normative wording lives in TRADEMARKS.md under "Required attribution"; see also docs/reference/attestation.md and docs/guides/distributions.md.`,
265
281
  disclosure: `Usage: ${c} disclosure check [--root DIR] [--staged] [--denylist FILE | --structural-only] [--fail-on-binary] [--untrusted]
266
282
 
267
283
  Scans Git-tracked files, or staged index blobs with --staged, without following symlinks. A private denylist is required by default and must be supplied through ATELIER_DENYLIST_JSON, --denylist, or ignored .atelier-local/disclosure-denylist.json. --structural-only is the explicit no-denylist lane. --untrusted suppresses finding details.`,
@@ -301,7 +317,7 @@ MNSTRY announcements are a pull-only channel: signed JSON documents under announ
301
317
  ${c} obsidian selection resolve ID | persist ID [allow-empty] | show ID | list
302
318
  ${c} obsidian proposals list | show OPERATION
303
319
 
304
- Every input is an argument. view add changes the project configuration, which you commit: it shows the change and how many notes the view would show, and asks a person at a terminal first (--yes answers beforehand); anyone else's command is their consent, and nothing is ever committed. With --json exactly one JSON document is printed, for a refusal too. status, settings, location show, scope, audience show, mode show, policy show, policy digest, plugin show and service status are read-only. open reports current only when the owned maintenance service ticked after the request, the view's trusted generation is the prepared one and reads back byte for byte, and the installed Obsidian meets the minimum version and answers for that vault; every other outcome is typed and exits 3. Reaching the installed app is never a default: open, service start and service unit need --adapter=obsidian-cli once for a workspace, which remembers it (never used under the test runner). service unit --install installs a login item on macOS (a launchd agent) or Linux (a systemd user unit) so maintenance starts when you log in, under a consent that covers startup; it runs the package installed in the project and is refused from a package runner's cache. Once installed, the service is started through it, and service start replaces a service of an earlier release. service unit --remove removes it and starts the service for this session only. uninstall removes the login item and stops the service, and keeps vaults, private state, the project file and Obsidian's vault list. Obsidian's own settings file is written only while no Obsidian runs, and every write is shown in open's answer: the view's vault is added to its list with a backup of the file as it was, its command line is turned on (cli: true), and for an Obsidian that never started the file is created. A running Obsidian that open cannot reach (its command line turned off, or no vault open) is quit and started again only with --restart-obsidian, which no other flag implies; otherwise open names that flag. --wait-ms bounds open's wait for maintenance's tick. The first start of the maintenance service records who allowed it: --consent-actor ID, or for a person at a terminal the account's name; --json, --no-input, CI or ATELIER_NONINTERACTIVE=1 mean nobody is at a terminal. Audiences (audience set me: only you, with the notes that carry no classification, which no other list shows), mode, the apply policy and what was decided are private machine settings, never project configuration and never a note. apply, conflicts, apply-policy, selection and proposals are contributed operations registered from modules shipped under src/runtime/obsidian/contributions/; the built-in names cannot be replaced. While no apply operation is registered every apply reports apply-unavailable. --personal-home DIR, given instead of --project, follows the generation last confirmed in that private home of a personal workspace; nothing here confirms one, and while none is confirmed and current nothing is published and status, open and service start refuse with the reason. Who may see its vaults stays this machine's audience setting, none by default. Exit codes: 0 done, 1 internal error, 2 refusal or usage, 3 ran and the answer is not success.`,
320
+ Every input is an argument. view add changes the project configuration, which you commit: it shows the change and how many notes the view would show, and asks a person at a terminal first (--yes answers beforehand); anyone else's command is their consent, and nothing is ever committed. With --json exactly one JSON document is printed, for a refusal too. status, settings, location show, scope, audience show, mode show, policy show, policy digest, plugin show and service status are read-only. open reports current only when the owned maintenance service ticked after the request, the view's trusted generation is the prepared one and reads back byte for byte, and the installed Obsidian meets the minimum version and answers for that vault; every other outcome is typed and exits 3. Reaching the installed app is never a default: open, service start and service unit need --adapter=obsidian-cli once for a workspace, which remembers it (never used under the test runner). service unit --install installs a login item on macOS (a launchd agent) or Linux (a systemd user unit) so maintenance starts when you log in, under a consent that covers startup; it runs the package installed in the project and is refused from a package runner's cache. Once installed, the service is started through it, and service start replaces a service of an earlier release. service unit --remove removes it and starts the service for this session only. uninstall removes the login item and stops the service, and keeps vaults, private state, the project file and Obsidian's vault list. Obsidian's own settings file is written only while no Obsidian runs, and every write is shown in open's answer: the view's vault is added to its list with a backup of the file as it was, its command line is turned on (cli: true), and for an Obsidian that never started the file is created. A running Obsidian that open cannot reach (its command line turned off, or no vault open) is quit and started again only with --restart-obsidian, which no other flag implies; otherwise open names that flag. --wait-ms bounds open's wait for maintenance's tick. The first start of the maintenance service records who allowed it: --consent-actor ID, or for a person at a terminal the account's name; --json, --no-input, CI or ATELIER_NONINTERACTIVE=1 mean nobody is at a terminal. Audiences (audience set me: only you, with the notes that carry no classification, which no other list shows), mode, the apply policy and what was decided are private machine settings, never project configuration and never a note. apply, conflicts, apply-policy, selection and proposals are contributed operations registered from modules shipped under src/runtime/obsidian/contributions/; the built-in names cannot be replaced. While no apply operation is registered every apply reports apply-unavailable. --personal-home DIR, given instead of --project, follows the generation last confirmed in that private home of a personal workspace; nothing here confirms one, and while none is confirmed and current nothing is published and status, open and service start refuse with the reason. Who may see its vaults stays this machine's audience setting: owner only when undecided; an explicit clear stays empty. Exit codes: 0 done, 1 internal error, 2 refusal or usage, 3 ran and the answer is not success.`,
305
321
  sync: `Usage:
306
322
  ${c} sync enroll --repo DIR [--project atelier.project.json] [--git ABSOLUTE_PATH]
307
323
  ${c} sync status --repo DIR
@@ -373,7 +389,7 @@ export async function runCli({
373
389
 
374
390
  const [command, ...rest] = normalized.args
375
391
  if (rest[0] === '--help' || rest[0] === '-h') {
376
- stdout(buildCommandHelpText(command, brand))
392
+ stdout(buildCommandHelpText(command.startsWith('extension:') ? 'extension' : command, brand))
377
393
  return 0
378
394
  }
379
395
  const target = commandMap.get(command)
@@ -15,7 +15,7 @@ const ATTRIBUTION_BYTES = 'powered by MNSTRY Atelier'
15
15
  const ATTRIBUTION_EXT_KEY = 'mnstry.atelier/attribution'
16
16
  const PACK_MANIFEST_NAME = 'atelier.pack.json'
17
17
  const PREFIX = '[atelier-distribution:check]'
18
- const POLICY_POINTER = 'see TRADEMARKS.md ("Required attribution") and docs/attestation.md'
18
+ const POLICY_POINTER = 'see TRADEMARKS.md ("Required attribution") and docs/reference/attestation.md'
19
19
 
20
20
  const log = (message) => console.log(`${PREFIX} ${message}`)
21
21
  const logError = (message) => console.error(`${PREFIX} ${message}`)
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ import { scaffoldSqlProject, scaffoldConvexProject, sealProject, validateProject, exportReleaseBundle } from '../extensions/project.mjs'
3
+
4
+ const usage = 'Usage: atelier extension init|validate|seal|bundle --directory PATH [--id sample.counter] [--profile postgres-sql|drizzle-db-first|drizzle-code-first|prisma-7-postgres|convex-native] [--json]'
5
+ const [command, ...args] = process.argv.slice(2)
6
+ try {
7
+ if (command === '--help' || command === '-h' || !command) { console.log(usage) }
8
+ else {
9
+ if (!['init', 'validate', 'seal', 'bundle'].includes(command)) throw new Error('unknown extension command')
10
+ const options = {}
11
+ for (let i = 0; i < args.length; i++) {
12
+ const arg = args[i]
13
+ if (arg === '--json') { if (options.json) throw new Error('duplicate option'); options.json = true; continue }
14
+ if (!['--directory', '--id', '--profile'].includes(arg) || !args[i + 1] || args[i + 1].startsWith('--') || Object.hasOwn(options, arg)) throw new Error('invalid option')
15
+ options[arg] = args[++i]
16
+ }
17
+ if (!options['--directory'] || (command !== 'init' && (options['--id'] || options['--profile']))) throw new Error('invalid options')
18
+ if (options['--profile'] && !['postgres-sql','drizzle-db-first','drizzle-code-first','prisma-7-postgres','convex-native'].includes(options['--profile'])) throw new Error('profile not implemented')
19
+ const result = command === 'init' ? await (options['--profile']==='convex-native'?scaffoldConvexProject:scaffoldSqlProject)({ directory: options['--directory'], extensionId: options['--id'], profile: options['--profile'] }) :
20
+ command === 'bundle' ? await exportReleaseBundle(options['--directory']) :
21
+ command === 'validate' ? await validateProject(options['--directory']) : await sealProject(options['--directory']).then(manifest => ({ releaseDigest: manifest.releaseDigest, qualified: false }))
22
+ console.log(command === 'bundle' || options.json ? JSON.stringify(result) : `${command}: ${result.releaseDigest} (qualification pending)`)
23
+ }
24
+ } catch {
25
+ // Do not echo a caller path, secret, source file or arbitrary exception text.
26
+ console.error(`Extension command failed. ${usage}`); process.exitCode = 1
27
+ }