@mnstry/atelier 0.2.0-alpha.13 → 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 (253) hide show
  1. package/CHANGELOG.md +283 -0
  2. package/README.md +102 -52
  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/capability-stewardship.md +1 -1
  10. package/docs/blocks/claims.md +2 -2
  11. package/docs/blocks/conformance-admission.md +1 -1
  12. package/docs/blocks/learning-harnesses.md +1 -1
  13. package/docs/{atelier-sync.md → guides/atelier-sync.md} +20 -14
  14. package/docs/{capability-stewardship.md → guides/capability-stewardship.md} +2 -4
  15. package/docs/guides/co-authoring.md +113 -0
  16. package/docs/{distributions.md → guides/distributions.md} +13 -8
  17. package/docs/guides/extensions.md +189 -0
  18. package/docs/guides/graph-refresh.md +152 -0
  19. package/docs/guides/graph-workspace.md +64 -0
  20. package/docs/{ingestion.md → guides/ingestion.md} +16 -15
  21. package/docs/{inquiry-harnesses.md → guides/inquiry-harnesses.md} +2 -3
  22. package/docs/{knowledge-workspace.md → guides/knowledge-workspace.md} +2 -2
  23. package/docs/{learning-harnesses.md → guides/learning-harnesses.md} +2 -3
  24. package/docs/{learning.md → guides/learning.md} +12 -5
  25. package/docs/{obsidian.md → guides/obsidian.md} +370 -23
  26. package/docs/guides/ontology-guide.md +111 -0
  27. package/docs/{personal-workspace.md → guides/personal-workspace.md} +17 -5
  28. package/docs/{research-starter.md → guides/research-starter.md} +1 -1
  29. package/docs/{tenant-readiness.md → guides/tenant-readiness.md} +39 -0
  30. package/docs/{upgrade.md → guides/upgrade.md} +197 -11
  31. package/docs/knowledge-health/assessment/capabilities.md +6 -15
  32. package/docs/knowledge-health/facilitator.md +15 -4
  33. package/docs/knowledge-health/{devday/participant-response.md → participant-response.md} +4 -2
  34. package/docs/knowledge-health/quickstart.md +97 -75
  35. package/docs/knowledge-health/readme.md +13 -5
  36. package/docs/maintainers/describing-the-atelier.md +173 -0
  37. package/docs/{release-engineering.md → maintainers/release-engineering.md} +5 -4
  38. package/docs/{announcements.md → reference/announcements.md} +1 -1
  39. package/docs/{architecture.md → reference/architecture.md} +31 -5
  40. package/docs/{atelier-runtime.md → reference/atelier-runtime.md} +1 -1
  41. package/docs/{connected-composition.md → reference/connected-composition.md} +7 -10
  42. package/docs/{coordination.md → reference/coordination.md} +1 -1
  43. package/docs/{decisions.md → reference/decisions.md} +3 -3
  44. package/docs/{design.md → reference/design.md} +1 -1
  45. package/docs/reference/edge-policy.md +151 -0
  46. package/docs/reference/graph-view-structured.md +119 -0
  47. package/docs/reference/graph-view.md +139 -0
  48. package/docs/reference/graph-workspace.md +37 -0
  49. package/docs/{intake-and-guides.md → reference/intake-and-guides.md} +3 -4
  50. package/docs/{knowledge-graph.md → reference/knowledge-graph.md} +120 -6
  51. package/docs/{local-services.md → reference/local-services.md} +43 -4
  52. package/docs/{obsidian-contract.md → reference/obsidian-contract.md} +29 -4
  53. package/docs/{obsidian-plugin.md → reference/obsidian-plugin.md} +218 -68
  54. package/docs/{practical-judgment.md → reference/phronesis.md} +12 -3
  55. package/docs/reference/portability.md +92 -0
  56. package/docs/{portable-presentation.md → reference/portable-presentation.md} +2 -2
  57. package/docs/{presentation-consumer-boundaries.md → reference/presentation-consumer-boundaries.md} +5 -0
  58. package/docs/{project-options.md → reference/project-options.md} +17 -0
  59. package/docs/{repo-boundary-guard.md → reference/repo-boundary-guard.md} +50 -4
  60. package/docs/{review-portability.md → reference/review-portability.md} +4 -0
  61. package/docs/{semantic-operation.md → reference/semantic-operation.md} +4 -3
  62. package/docs/{template-profile.md → reference/template-profile.md} +1 -1
  63. package/docs/{trackables.md → reference/trackables.md} +2 -2
  64. package/docs/start/independent-start.md +89 -0
  65. package/docs/{install.md → start/install.md} +9 -9
  66. package/docs/{knowledge-setup.md → start/knowledge-setup.md} +5 -5
  67. package/docs/{research-starter-quickstart.md → start/research-starter-quickstart.md} +6 -6
  68. package/fixtures/atelier-architecture/catalog/invalid/document.json +2 -2
  69. package/fixtures/atelier-architecture/catalog/valid/document.json +2 -2
  70. package/fixtures/graph-view/synthetic-authorized-input.v1.json +437 -0
  71. package/fixtures/graph-view/synthetic-view.v1.json +1 -0
  72. package/fixtures/knowledge-health/workshop/README.md +1 -1
  73. package/fixtures/templates/local-library.v1.json +3 -1
  74. package/package.json +22 -8
  75. package/plugins/obsidian/main.js +57 -8
  76. package/plugins/obsidian/manifest.json +1 -1
  77. package/skills/claude/atelier-guided-upgrade/SKILL.md +1 -1
  78. package/skills/claude/atelier-knowledge-setup/SKILL.md +2 -2
  79. package/skills/claude/atelier-local-service/SKILL.md +1 -1
  80. package/skills/claude/atelier-practical-judgment/SKILL.md +7 -2
  81. package/skills/claude/atelier-skill-steward/SKILL.md +1 -1
  82. package/skills/claude/mnstry-readiness/SKILL.md +2 -2
  83. package/skills/codex/atelier-guided-upgrade/SKILL.md +1 -1
  84. package/skills/codex/atelier-knowledge-setup/SKILL.md +2 -2
  85. package/skills/codex/atelier-local-service/SKILL.md +1 -1
  86. package/skills/codex/atelier-practical-judgment/SKILL.md +7 -2
  87. package/skills/codex/atelier-skill-steward/SKILL.md +1 -1
  88. package/skills/codex/mnstry-readiness/SKILL.md +2 -2
  89. package/src/architecture/catalog.mjs +2 -2
  90. package/src/attestation/sign.mjs +1 -1
  91. package/src/boundary/content-rules.mjs +534 -68
  92. package/src/boundary/policy.mjs +187 -60
  93. package/src/cli/run.mjs +26 -9
  94. package/src/commands/distribution.mjs +1 -1
  95. package/src/commands/extension.mjs +27 -0
  96. package/src/commands/ingest.mjs +1 -1
  97. package/src/commands/learn.mjs +1 -1
  98. package/src/commands/obsidian.mjs +49 -21
  99. package/src/commands/review.mjs +3 -0
  100. package/src/edge-policy/contract.mjs +69 -0
  101. package/src/edge-policy/policy.mjs +142 -0
  102. package/src/edge-policy/source-citation-adapter.mjs +43 -0
  103. package/src/extension-packs/loader.mjs +4 -3
  104. package/src/extensions/admission.mjs +83 -0
  105. package/src/extensions/client.d.mts +23 -0
  106. package/src/extensions/client.mjs +99 -0
  107. package/src/extensions/contracts.d.mts +29 -0
  108. package/src/extensions/contracts.mjs +163 -0
  109. package/src/extensions/convex.d.mts +24 -0
  110. package/src/extensions/convex.mjs +189 -0
  111. package/src/extensions/delegation.mjs +54 -0
  112. package/src/extensions/drizzle.d.mts +11 -0
  113. package/src/extensions/drizzle.mjs +33 -0
  114. package/src/extensions/postgres.d.mts +7 -0
  115. package/src/extensions/postgres.mjs +66 -0
  116. package/src/extensions/prisma.d.mts +13 -0
  117. package/src/extensions/prisma.mjs +63 -0
  118. package/src/extensions/project.mjs +432 -0
  119. package/src/extensions/scaffold-convex.mjs +130 -0
  120. package/src/extensions/scaffold-sql.mjs +144 -0
  121. package/src/extensions/server.d.mts +20 -0
  122. package/src/extensions/server.mjs +102 -0
  123. package/src/extensions/sql-scope.mjs +22 -0
  124. package/src/graph/graph.mjs +13 -5
  125. package/src/graph/knowledge-graph.mjs +20 -2
  126. package/src/graph/repo-contribution.mjs +405 -0
  127. package/src/graph/repo-contribution.types.mjs +32 -0
  128. package/src/graph-access/edge-decision-adapter.mjs +41 -0
  129. package/src/graph-access/edge-record-adapter.mjs +73 -0
  130. package/src/graph-access/index.mjs +253 -0
  131. package/src/graph-access/multi-contribution-record-adapter.mjs +101 -0
  132. package/src/graph-access/multi-record-projection-adapter.mjs +74 -0
  133. package/src/graph-access/source-adapter.mjs +81 -0
  134. package/src/graph-refresh/compare.mjs +110 -0
  135. package/src/graph-refresh/controller.mjs +324 -0
  136. package/src/graph-refresh/index.mjs +3 -0
  137. package/src/graph-refresh/local.mjs +78 -0
  138. package/src/graph-view/babylon/babylon-scene-port.mjs +64 -0
  139. package/src/graph-view/babylon/index.mjs +2 -0
  140. package/src/graph-view/babylon/navigator.mjs +312 -0
  141. package/src/graph-view/babylon/provenance.mjs +36 -0
  142. package/src/graph-view/babylon/scene-controller.mjs +131 -0
  143. package/src/graph-view/babylon/semantic-picking.mjs +35 -0
  144. package/src/graph-view/babylon/web-host.mjs +188 -0
  145. package/src/graph-view/cli.mjs +3 -0
  146. package/src/graph-view/command.mjs +34 -0
  147. package/src/graph-view/contracts.mjs +79 -0
  148. package/src/graph-view/errors.mjs +5 -0
  149. package/src/graph-view/index.mjs +4 -0
  150. package/src/graph-view/intents.mjs +30 -0
  151. package/src/graph-view/query.mjs +213 -0
  152. package/src/graph-view/refs.mjs +2 -0
  153. package/src/graph-view/structured/browser.mjs +262 -0
  154. package/src/graph-view/structured/styles.mjs +8 -0
  155. package/src/graph-workspace/authoring.mjs +185 -0
  156. package/src/graph-workspace/browser/constellation.mjs +369 -0
  157. package/src/graph-workspace/browser/dom.mjs +23 -0
  158. package/src/graph-workspace/browser/index.mjs +6 -0
  159. package/src/graph-workspace/browser/review.mjs +55 -0
  160. package/src/graph-workspace/browser/styles.mjs +11 -0
  161. package/src/graph-workspace/browser/workbench.mjs +351 -0
  162. package/src/graph-workspace/browser/workspace.mjs +431 -0
  163. package/src/graph-workspace/disclosure.mjs +39 -0
  164. package/src/graph-workspace/geometry.mjs +78 -0
  165. package/src/graph-workspace/index.mjs +11 -0
  166. package/src/graph-workspace/labels.mjs +50 -0
  167. package/src/graph-workspace/model.mjs +109 -0
  168. package/src/graph-workspace/recipes.mjs +88 -0
  169. package/src/graph-workspace/scale.mjs +95 -0
  170. package/src/graph-workspace/theme.mjs +156 -0
  171. package/src/ingestion/optional/graphify/graphify_supplier.py +5 -0
  172. package/src/ingestion/optional/graphify/native-closure-pins.json +275 -0
  173. package/src/ingestion/optional/graphify/native-pins.json +306 -0
  174. package/src/knowledge/ontology-guide.mjs +152 -0
  175. package/src/knowledge-health/proof/installed-check.mjs +2 -2
  176. package/src/knowledge-health/rule-identity.mjs +14 -9
  177. package/src/knowledge-health/workshop.mjs +22 -2
  178. package/src/personal-workspace/index.mjs +1 -1
  179. package/src/personal-workspace/selection.mjs +34 -3
  180. package/src/project/config.mjs +1 -1
  181. package/src/project/path-match.mjs +2 -1
  182. package/src/project/providers/github.mjs +24 -0
  183. package/src/project/repo-identity.mjs +3 -22
  184. package/src/projection/obsidian/contracts.mjs +1 -1
  185. package/src/projection/obsidian/materialize/path-registry.mjs +1 -1
  186. package/src/projection/obsidian/materialize/prepare-view.mjs +88 -6
  187. package/src/projection/obsidian/materialize/redaction.mjs +1 -1
  188. package/src/projection/obsidian/personal-workspace.mjs +84 -5
  189. package/src/projection/obsidian/plugin-bridge/channel.mjs +1 -1
  190. package/src/projection/obsidian/proposals/adapter.mjs +46 -23
  191. package/src/projection/obsidian/proposals/observation.mjs +40 -2
  192. package/src/projection/obsidian/publication/publisher.mjs +96 -8
  193. package/src/projection/project.mjs +21 -16
  194. package/src/readiness/readiness.mjs +20 -11
  195. package/src/readiness-protocols/bundled-pack.mjs +14 -766
  196. package/src/readiness-protocols/bundled-selection.mjs +32 -0
  197. package/src/readiness-protocols/evidence.mjs +2 -1
  198. package/src/readiness-protocols/packs/mnstry.mjs +766 -0
  199. package/src/readiness-protocols/runtime.mjs +43 -6
  200. package/src/runtime/obsidian/engine.mjs +387 -76
  201. package/src/runtime/obsidian/lifecycle.mjs +20 -15
  202. package/src/runtime/obsidian/login-item.mjs +6 -3
  203. package/src/runtime/obsidian/machine-settings.mjs +52 -8
  204. package/src/runtime/obsidian/observation.mjs +36 -4
  205. package/src/runtime/obsidian/opening.mjs +4 -3
  206. package/src/runtime/obsidian/personal-selection.mjs +187 -0
  207. package/src/runtime/obsidian/pipeline.mjs +115 -6
  208. package/src/runtime/obsidian/private-lock.mjs +50 -6
  209. package/src/runtime/obsidian/selection-continuity.mjs +124 -0
  210. package/src/runtime/obsidian/service-main.mjs +68 -16
  211. package/src/runtime/obsidian/service.mjs +80 -6
  212. package/src/runtime/obsidian/unheld-evidence.mjs +1 -1
  213. package/src/runtime/obsidian/view-permission.mjs +335 -0
  214. package/src/ui/control-system.mjs +201 -0
  215. package/src/ui/html-primitives.mjs +3 -0
  216. package/src/upgrade/closure-diagnostics.mjs +135 -0
  217. package/src/upgrade/closure.mjs +649 -0
  218. package/src/upgrade/upgrade.mjs +42 -11
  219. package/templates/distribution-workspace/README.md +2 -2
  220. package/templates/external-project-workspace/atelier.project.json +3 -0
  221. package/templates/external-project-workspace/pack-lifecycle.json +3 -1
  222. package/templates/knowledge-workspace/README.md +2 -2
  223. package/docs/integration-and-review-plan.md +0 -409
  224. package/docs/integration-contract-decisions.md +0 -44
  225. package/docs/knowledge-health/devday/facilitator.md +0 -16
  226. package/docs/knowledge-health/devday/public-default.md +0 -107
  227. package/docs/knowledge-health/devday/quickstart.md +0 -18
  228. package/docs/knowledge-health/devday/support.md +0 -22
  229. package/docs/knowledge-health/exercise.md +0 -17
  230. package/docs/knowledge-health/support.md +0 -34
  231. package/docs/presentation-review-disposition.md +0 -47
  232. package/docs/progressive-ingestion-acceptance.md +0 -89
  233. package/docs/progressive-ingestion.md +0 -235
  234. /package/docs/{exact-upgrades.md → guides/exact-upgrades.md} +0 -0
  235. /package/docs/{guided-upgrades.md → guides/guided-upgrades.md} +0 -0
  236. /package/docs/{local-review.md → guides/local-review.md} +0 -0
  237. /package/docs/{skill-steward.md → guides/skill-steward.md} +0 -0
  238. /package/docs/{template-upgrades.md → guides/template-upgrades.md} +0 -0
  239. /package/docs/{assurance-controls.md → maintainers/assurance-controls.md} +0 -0
  240. /package/docs/{attestation.md → reference/attestation.md} +0 -0
  241. /package/docs/{coauthor-session.md → reference/coauthor-session.md} +0 -0
  242. /package/docs/{continuity.md → reference/continuity.md} +0 -0
  243. /package/docs/{contract-stability.md → reference/contract-stability.md} +0 -0
  244. /package/docs/{decision-practices.md → reference/decision-practices.md} +0 -0
  245. /package/docs/{evidence-navigation.md → reference/evidence-navigation.md} +0 -0
  246. /package/docs/{extension-pack-lifecycle.md → reference/extension-pack-lifecycle.md} +0 -0
  247. /package/docs/{interaction-and-reflection.md → reference/interaction-and-reflection.md} +0 -0
  248. /package/docs/{local-state.md → reference/local-state.md} +0 -0
  249. /package/docs/{ontology.md → reference/ontology.md} +0 -0
  250. /package/docs/{optional-ingestion.md → reference/optional-ingestion.md} +0 -0
  251. /package/docs/{project-command-inventory.md → reference/project-command-inventory.md} +0 -0
  252. /package/docs/{semantic-ingestion.md → reference/semantic-ingestion.md} +0 -0
  253. /package/docs/{vault-service.md → reference/vault-service.md} +0 -0
@@ -203,8 +203,19 @@ the child it created. If that proof never arrives it stops only that child, by
203
203
  its process handle, and reports the private operational log,
204
204
  `state/service/service.log`.
205
205
 
206
- A tick is largely synchronous, so a healthy service in a long tick may not
207
- answer health within the deadline. That is `busy`, not `occupied`: it is
206
+ Stretches of a tick are synchronous (walking the directories, reading the
207
+ HTML sources and the sidecars of PDF and Word documents, resolving links and
208
+ assembling the canonical graph, building the whole graph of a project bound to
209
+ a personal workspace, capturing the source snapshot, the
210
+ publisher's restart recovery, its exchange probe, writing the journal, the
211
+ look again at displaced files), so a healthy service in a long one may not
212
+ answer health within the deadline; observing the vault and source files before
213
+ a view is prepared, reading the Markdown sources into the canonical graph,
214
+ preparing
215
+ and publishing a view, and reading it back after a commit yield between files
216
+ and between publication units, and health is answered meanwhile. A service
217
+ that does not answer in time is `busy`, not
218
+ `occupied`: it is
208
219
  never adopted, never stopped and never started over, and a `start` whose own
209
220
  child went straight into a long first tick reports it as started and busy
210
221
  instead of ending it. The command line of another process is read from
@@ -268,7 +279,35 @@ A tick that fails for a reason nobody typed (a full disk, a crash inside a
268
279
  step) does not end the service. Its error code is kept in
269
280
  `state/service/last-error.json`, its message only in the private log; the
270
281
  delay before the next attempt doubles up to a ceiling, and the next tick
271
- proceeds.
282
+ proceeds. It starts as the first tick of the service does, loading the project
283
+ again and looking at every view, so nothing the failed tick saw and did not
284
+ act on is lost. A tick whose engine lock could not be given back at its end
285
+ (its released ticket could not be written) fails too: its error is recorded
286
+ and the loop backs off, and its work was already recorded before the release.
287
+ The lock stays this service's, and the next tick gives it back before it takes
288
+ it again, instead of finding its own ticket and answering `busy` until the
289
+ service is started again.
290
+
291
+ A view refused for a file-system error does not fail the tick. Examples are
292
+ a vault folder that could not be allocated or placed (`vault-location-unusable`),
293
+ a configuration file that could not be read again during the tick, a source
294
+ removed while it was read (both `mixed-read`) and candidates that could not be
295
+ staged (`staging-failed`). The view's freshness names only the refusal, so the
296
+ service writes a `view-refused` line to its private log for each such view
297
+ whose refusal carries a file-system error's code, at most 64 a tick: the view,
298
+ the refusal's code and the error's code (`EACCES`, `EIO`, `ENOENT`, `ENOSPC`).
299
+ Only codes shaped as a file-system error's are written, never a message. A view
300
+ the next tick names for the same reason is not written again, so a folder that
301
+ stays unwritable (tried at every tick) is written once. It is written again when
302
+ its reason changes, or after a tick that failed or did not name it: a tick that
303
+ did not refuse it, refused it for no file-system error, had named 64 other
304
+ views first, or was refused as a whole. When removing the staged candidates
305
+ afterwards fails too, the line also names that error's code as `cleanupCause`,
306
+ and a line is written for that alone when the refusal names no error of its
307
+ own. That failure does not replace the refusal. What could not be removed
308
+ stays where it was: in `staging/`, or at its exchange path under `recovery/`
309
+ once the publication's journal is written. The restart recovery of the next
310
+ publication removes the latter.
272
311
 
273
312
  ### Cases that need a person
274
313
 
@@ -447,7 +486,7 @@ error, 3 the operation ran and its answer is not success.
447
486
  | `status` | enablement, machine settings, what was decided, proven service state, per-view freshness with its diagnostics (a code, the rule and the in-view note concerned, never a value; see [the Obsidian contract](obsidian-contract.md#notes-that-were-laid-out-anyway)), whether an apply operation exists | nothing |
448
487
  | `settings` | what this machine remembers for the workspace (who may see, where vaults live, start at login, the adapter), who allowed the service, and how each answer is changed | nothing |
449
488
  | `scope list`, `scope show ID` (also `view list`, `view show ID`) | the declared views | nothing |
450
- | `view add ID (--all \| --folder PATH [--folder PATH ...] [--repo R] \| --tag T) [--expand DEPTH:MAX] [--default] [--allow-empty] [--yes]` | adds a view to the project configuration, after showing the change and how many notes the view would show; refuses a view that would show no note unless `--allow-empty` (see [Adding a view](obsidian.md#adding-a-view)) | `atelier.project.json`, and `.gitignore` when `.atelier-local/` is not ignored. Never committed |
489
+ | `view add ID (--all \| --folder PATH [--folder PATH ...] [--repo R] \| --tag T) [--expand DEPTH:MAX] [--default] [--allow-empty] [--yes]` | adds a view to the project configuration, after showing the change and how many notes the view would show; refuses a view that would show no note unless `--allow-empty` (see [Adding a view](../guides/obsidian.md#adding-a-view)) | `atelier.project.json`, and `.gitignore` when `.atelier-local/` is not ignored. Never committed |
451
490
  | `audience show`, `audience set me\|A,B`, `audience clear` | the audiences this machine lets into a view; none by default, which publishes an empty view. `me` is only you: every audience but `sensitive`, which is added by name. The answer is remembered as the person's decision. A change invalidates every view at the next tick | private machine settings |
452
491
  | `location show`, `location set DIR [--allow-synced-location]` | where this workspace's vaults live; each view not published yet gets `<project> (<view>)` there at its first publication, and a vault published already stays where it is | private machine settings |
453
492
  | `mode show`, `mode set manual\|automatic` | `automatic` refuses without an installed, matching, active automatic policy | private machine settings |
@@ -5,7 +5,7 @@ feasibility track. It states what is proven, on what, and what is not. Nothing
5
5
  here enables a feature. The publisher under
6
6
  `src/projection/obsidian/publication/` is called by the maintenance service
7
7
  (`atelier obsidian service start`) and so by `atelier obsidian open`; see
8
- [obsidian.md](obsidian.md).
8
+ [obsidian.md](../guides/obsidian.md).
9
9
 
10
10
  ## Registered shapes
11
11
 
@@ -665,6 +665,29 @@ again, so bytes that drift under an unchanged pinned digest are not seen by
665
665
  describes, and the next observation by digest sees the drift. A note whose pin
666
666
  changed is read and verified against the pin as always.
667
667
 
668
+ The maintenance engine prepares a view cooperatively (the
669
+ `prepareViewCooperatively` production seam): it waits between notes so that
670
+ the service keeps answering. The bound above holds there too. After a
671
+ cooperative preparation, and again while the publisher holds its locks,
672
+ before the journal entry that says the publication settled and before the
673
+ commit, the engine checks every selected source as observation does: a source
674
+ that still has the stat hint it was indexed with is taken as unchanged and is
675
+ not opened, and one whose hint moved is read and must still be the pinned
676
+ bytes. A source that changed during the tick, or was removed, refuses the
677
+ generation as `mixed-read`: its manifest is not committed, at that tick or by the restart
678
+ recovery of a later one, and the next tick observes in full and prepares the
679
+ view again. The same waits check that the configuration files, the machine
680
+ settings and the eligibility revision are still the ones the tick read. A
681
+ configuration file that cannot be read at such a check (no permission, an I/O
682
+ error) refuses the view as `mixed-read` too, and the tick goes on to its
683
+ other views.
684
+
685
+ Called on its own, a cooperative preparation reads every selected source
686
+ against its pin once more before it returns, a reused note's included, unless
687
+ its caller says it checks them itself (`scheduling.recheckSources: false`, as
688
+ the engine does). A preparation refused or cancelled on the way leaves the
689
+ preparation cache as it was.
690
+
668
691
  The engine holds one graph file cache and one preparation cache per scope for
669
692
  its lifetime and hands them through the `createGraphCache` and
670
693
  `createPreparationCache` production seams; a test replaces either with
@@ -845,7 +868,7 @@ written meanwhile.
845
868
 
846
869
  macOS (Darwin 25, arm64) with Obsidian 1.13.7 (installer 1.12.7), CLI enabled,
847
870
  no community plugin. Sixteen interleavings, 25 rounds for each racing case, in
848
- four complete clean runs of the prototype in `experiments/obsidian-publication/`
871
+ four complete clean runs of the historical publication feasibility prototype
849
872
  at commits `34f5fab` and `c5142e7`. The receipts record those same trees under their
850
873
  pre-sign-off identities `5930f85` and `93303ff`; the branch was rewritten only to add
851
874
  sign-off trailers, with identical content. Receipt SHA-256 digests:
@@ -857,11 +880,13 @@ sign-off trailers, with identical content. Receipt SHA-256 digests:
857
880
 
858
881
  A fifth run aborted because the harness could not open a note after the
859
882
  second-window case; no bytes were involved. The receipts are maintainer-held
860
- and are not part of this repository.
883
+ and are not part of this repository. Current desktop qualification uses
884
+ `scripts/obsidian/desktop-receipts.mjs`. These historical receipts do not qualify
885
+ a later candidate or a different host.
861
886
 
862
887
  Every vault Atelier publishes now carries Atelier's own plugin
863
888
  ([obsidian-plugin.md](obsidian-plugin.md)), so a trusted vault runs one
864
- community plugin. In phase 1 it registers no editor extension, no vault event
889
+ community plugin. The current plugin registers no editor extension, no vault event
865
890
  handler and nothing that writes; it only talks to the maintenance service over
866
891
  loopback. The protocol cases above have not been re-run with it loaded; that
867
892
  run is gate G20, before the plugin carries any part of publication.
@@ -5,11 +5,11 @@ finds or installs it: the maintenance service puts it into the vault with the
5
5
  notes, and Obsidian asks once per vault whether to trust the vault's plugins.
6
6
  Until the person says yes, and whenever the plugin is absent, turned off or
7
7
  running in an app that is too old, everything works as it did before through
8
- the command-line path described in [obsidian.md](obsidian.md).
8
+ the command-line path described in [obsidian.md](../guides/obsidian.md).
9
9
 
10
- This is phase 1: the plugin is present, reports status and holds a channel to
11
- the service. It decides nothing and writes nothing. Phase 2, planned at the
12
- end of this document, moves the in-app part of publication into it.
10
+ The plugin reports status and holds a channel to the service. It decides
11
+ nothing and writes nothing. Publication uses the existing command-line or
12
+ app-free path; the plugin does not perform its critical section.
13
13
 
14
14
  The source is `plugins/obsidian/` in the package: `manifest.json`, `main.js`
15
15
  and `styles.css`, plain JavaScript with no build step. The channel it speaks
@@ -32,7 +32,24 @@ is `src/projection/obsidian/plugin-bridge/channel.mjs`; the service's half is
32
32
  a window with the view, its state and the reason in words, the committed and
33
33
  the prepared generation, when freshness was last checked, the held, retained
34
34
  and pending edits, the service address and state, and the plugin and app
35
- versions.
35
+ versions. While the service is unreachable, current generations, check time
36
+ and edit counts are unknown. After a connection refusal or timeout on the
37
+ same channel, the window also shows the last authenticated state, reason,
38
+ generation and check under "Last observed" labels. Those rows are historical
39
+ and never establish current freshness, service health or permission.
40
+ History stays only in memory. It is cleared on a channel change, missing or
41
+ unsupported setup, authentication refusal, an untrusted answer, a missing or
42
+ malformed view, a report for another scope, a disabled view or unload.
43
+ A connection reset or any other failure outside connection refusal and
44
+ timeout also clears it. Without a prior usable report, "Last observed
45
+ status" says "not available". After startup admits the channel, a republish
46
+ that names a different channel (host, port, scope or key) resets the display
47
+ to `connecting` before its next answer; this reset does not repeat an
48
+ unchanged notice or lose the transition back to current. A republish of the
49
+ same channel keeps the display and history, and unusable data shows
50
+ `not set up`.
51
+ Republish keeps an unsupported-app or unavailable-Node setup label and its
52
+ channel closed. Plugin 1.1.2 adds this status continuity.
36
53
  - A notice appears when the view moves into a state that needs a person (held,
37
54
  stale, service unreachable, app too old) and when it is current again.
38
55
  `updating` is not announced: it is what every change looks like.
@@ -336,6 +353,124 @@ the vault's key without sending it, and the service proves it first
336
353
  | `POST /plugin/release` | `sessionId`, `counter`, `mac` | sealed: whether the session was released |
337
354
  | `POST /plugin/status` | `sessionId`, `counter`, `mac` | sealed: the view's state, reason, verification, committed and prepared generation, held notes (counted, not named), retained edits, open pending edits, and the service's own state |
338
355
 
356
+ A status answer carries the view and its pending edits only while the project
357
+ allows that view at the moment of the request, not as of the last tick
358
+ (`src/runtime/obsidian/view-permission.mjs`): its Obsidian settings are
359
+ enabled and declare the view, and its workspace pointer still names the
360
+ workspace this service runs for, with its private state where the service
361
+ keeps it. Otherwise the answer is still sealed and still carries the service's
362
+ own state, but `view` and `pendingEdits` are `null`, which the plugin already
363
+ reads as nothing known about the view. That covers a view turned off or taken
364
+ out of the settings before the next tick, and the freshness a later tick
365
+ writes for it, which keeps its generations and counts. It also covers anything
366
+ that cannot be established: settings that refuse, a project that does not
367
+ load, a pointer that cannot be read. The plugin then shows `Atelier: stale`
368
+ with the reason "no freshness recorded", keeps its session and asks again at
369
+ its next round; it is not told why, and it remembers nothing of the view to
370
+ show later.
371
+
372
+ Loading the project runs Git in child processes, which would otherwise happen
373
+ every two seconds for every open vault, so the project is kept:
374
+
375
+ - **What decides it.** The files the engine observes as configuration,
376
+ compared at every request by a digest of what they hold, never by their
377
+ times. Each file holds where it really is and the bytes there: its path
378
+ resolved as the system resolves it when the loader opens it (`realpath(3)`,
379
+ through a link anywhere on the way, a `..` after a link included), so a
380
+ configuration kept in a dotfiles repository and linked into the project is
381
+ kept like any other, and a link pointed elsewhere, the file's own or one to
382
+ a folder above it, is a change even where every byte is the same. A folder
383
+ in a file's place, a link that leads nowhere or to a folder, and a file
384
+ that cannot be read vouch for nothing: then nothing is kept, and the
385
+ project is loaded at every request. Where the system resolves no path for a
386
+ regular file that is there and is not a link (some volumes on Windows
387
+ answer `EISDIR`; a C library that needs `/proc` and has none), the file is
388
+ compared by its own path as given and its bytes, so the project is still
389
+ kept; a link above such a file, pointed elsewhere, is not seen there. A
390
+ link the system does not resolve vouches for nothing. The pointer and the
391
+ place of the private state are read at every request.
392
+ - **When it is kept.** Two loads in a row, each started after those files
393
+ were read and found to hold the same, must return the same project as far
394
+ as the decision reads one: the views it enables, where its pointer is, the
395
+ data root its local overlay prefers and the roots it protects. A field that
396
+ differs from load to load, such as a time or a personal-workspace binding
397
+ kept under a symbol key, does not keep a project from being kept. One
398
+ load is not enough: a file changed and changed back while it ran leaves the
399
+ same bytes around a project read from other ones. So three loads keep the
400
+ project when the service has just started, and two after a change.
401
+ - **For how long.** A kept project is loaded again once it is two and a half
402
+ minutes old, and is never used once it is five, the interval of the
403
+ engine's full reconciliation. Whatever no file here names (an overlay named
404
+ by `MNSTRY_ATELIER_LOCAL_CONFIG` that did not exist at the last load, for
405
+ instance) is seen by then.
406
+ - **A loader that answers a promise** is never waited for, because the plugin
407
+ gives a request a second and a half. Its view is told nothing until two of
408
+ its loads have agreed; one load runs at a time, and a kept project goes on
409
+ deciding, within its time, while it is loaded again. A load that has not
410
+ answered within two and a half minutes is given up and its later answer
411
+ ignored, whether a request or that answer is the first to come after the
412
+ deadline. A service bound to a personal home (`--personal-home`) has such a
413
+ loader: it starts from the home alone, and its plugins are told about a view
414
+ once two of the loads that compose the confirmed generation have agreed. A
415
+ service given only a loader that answers a promise still refuses to start
416
+ (see "Personal workspaces" in [obsidian.md](../guides/obsidian.md)).
417
+ - **A load that fails** (it throws, it is refused, it is given up, or a file
418
+ vouches for nothing under a loader that answers a promise) ends whatever
419
+ was kept, and is asked for again after two seconds, then four, up to
420
+ thirty, while the files hold the same. A change to them is tried at once,
421
+ with two exceptions. Until a load has answered and named the files, a
422
+ corrected configuration waits for the next try. And while one of the files
423
+ vouches for nothing there is no digest to change, so after a load that
424
+ failed then (one that answers a promise, or one that answers at once and
425
+ threw) a change to another file waits for the next try as well.
426
+ - **What the service shows of these loads.** Its status document counts
427
+ them (`statusLoads`: `answered`, `failed`, `givenUp`, `slow`, `notKept` and
428
+ `longestMs`). Its log gets a `status-project-loaded` line, with the
429
+ milliseconds, the outcome, flags and counts and never a path, only for a
430
+ load somebody has to see, each kind on its own row, written when the row is
431
+ 1, 2, 4, 8 and so on long (from 2 for loads after which nothing is kept):
432
+ - a load that failed or was given up;
433
+ - a load that answered at once and took a second or more (`slow`). A second
434
+ is most of the second and a half the plugin gives a request, spent on the
435
+ listener's own event loop; a load that answers a promise holds nothing;
436
+ - a load after which nothing is kept although it named the files it
437
+ started over (`notKept`, from the second in a row, with `vouched` false
438
+ while a file vouches for nothing): a load at every request. A load that
439
+ named other files than it started over (the first, which started over
440
+ none, or the one after a change that names other files, such as a new
441
+ confirmed selection) neither counts nor ends that row, so loads that
442
+ each name other files than the one before are never counted. A start and
443
+ a change each have one load that names the files it started over and has
444
+ nothing to agree with yet, so neither writes such a line; each is
445
+ counted, so a healthy service shows one `notKept` at its start and one
446
+ after each change. A change that lands while a load reads the files,
447
+ names the same files, and changes the views or what the workspace is
448
+ resolved from, makes that load keep nothing as well, and so writes one
449
+ line and counts two. Any other change that lands then counts one, as a
450
+ change does, and writes nothing.
451
+
452
+ A row of failures goes on through loads that answer between them, and ends
453
+ at the first load that answers a minute or more after its last failure; a
454
+ line is written then (`afterFailures`). That line comes with the first load
455
+ after the minute, which under a kept project is the next reload, two and a
456
+ half minutes after the load that kept it, and none comes if no load
457
+ follows. A row of slow
458
+ loads ends the same way, at a load that answers in time a minute or more
459
+ after the last slow one. So, while loads come less than a minute apart (a
460
+ load at every request, or the retries after a failure), a loader that
461
+ fails, or is slow, every other load or every third keeps one row, written
462
+ less and less often, instead of a line per load. While a project is kept it
463
+ is loaded again every two and a half minutes, so there a row of failures
464
+ ends at the next reload that answers: a loader that answers at least one
465
+ reload between two failures writes each failure and the load that ends its
466
+ row, as before, and one that fails at every reload and answers only at its
467
+ retry keeps one row. Each slow load is written there, as before. A row
468
+ of loads after which nothing is kept ends at the next load that keeps the
469
+ project and named the files it started over. A healthy service writes none
470
+ of these lines. The log is cut over only when it is opened, so a line per
471
+ load, every two seconds while a file vouches for nothing, would have grown
472
+ it without bound.
473
+
339
474
  Refusals, before anything else is looked at: `Host` other than the listener's
340
475
  literal loopback authority, a cross-site `Origin` or `Sec-Fetch-Site`, a path
341
476
  other than one of the nine exactly (a query included), or another method (the
@@ -414,7 +549,11 @@ is authenticated, so they only ever decide what is shown.
414
549
  directory changed) and one HMAC per vault; at most four handshakes wait per
415
550
  view, and recorded challenges can keep them filled for at most about
416
551
  thirty seconds after a restart, since a challenge is answered only within
417
- thirty seconds of the time it names.
552
+ thirty seconds of the time it names. A status request of a session costs a
553
+ read of the project's configuration files and of its workspace pointer; the
554
+ project itself is loaded again when one of those files changed, every two
555
+ and a half minutes, or at every request while one of them vouches for
556
+ nothing (see "The channel").
418
557
  - Egress. `plugins/` is in the egress scan, which fails a request whose target
419
558
  is not a literal loopback address, and the release audit requires the three
420
559
  plugin files in the package and scans them in the tarball.
@@ -488,6 +627,72 @@ note open in the editor.
488
627
 
489
628
  ## Evidence
490
629
 
630
+ - `test/obsidian-plugin-status-continuity.test.mjs` exercises transient history
631
+ and the shipped request flow through a finite, socket-free `http.request`
632
+ stand-in. Canonical channel computations seal the invented replies. It
633
+ checks refused and timed-out lease/status requests, rejected leases followed
634
+ by interrupted handshakes, listener proof and answer authentication,
635
+ republished data, notice deduplication and recovery, and late answers after
636
+ a channel change or unload. It opens no service or app and writes no plugin
637
+ data. These tests complement the real-listener and real-app checks below.
638
+ - `test/obsidian-view-permission.test.mjs` asks whether the project allows a
639
+ view the way the service asks before a status answer, over real project
640
+ files, the real loader and the real workspace resolution, with no listener,
641
+ with time a number the test moves: every way a view or its
642
+ workspace is withdrawn and given back; the workspace's identity compared as
643
+ well as its place; two loads per change however often a view is asked
644
+ about; a change that keeps a file's size and modification time; a change
645
+ that lands during a load; a file the project comes to name; a configuration
646
+ file that is a link, retargeted, or a link to a link; a folder, a link that
647
+ leads nowhere and a link to a folder in a file's place; a kept project's
648
+ time; a loader that fails, with its backoff; and a loader that answers a
649
+ promise: one load at a time, a change undone and done again while it runs,
650
+ through a link, a load that never answers, one whose answer comes after its
651
+ deadline before any request, and one refused again and again; a link whose
652
+ target has a `..` after a link, and a link to a folder above a file pointed
653
+ at a byte-for-byte copy; two loads that differ in a time and a symbol-keyed
654
+ binding, or in a protected root; how long each load took and how it ended;
655
+ and the service refusing to start on a loader that answers a promise, a
656
+ refused promise or a thenable. Mutations of the module (a link that vouches
657
+ for nothing, a project kept from one load whose files are read again when
658
+ it answers, no deadline, no backoff, no identity check, the files not taken
659
+ from the load, no time limit, a late answer taken, JavaScript's realpath, no
660
+ real path for a regular file, the whole project compared, no protected
661
+ roots compared) and a service that does not refuse each fail at least one
662
+ of them. It also covers: a late refusal after the deadline; which loads the
663
+ log report writes (a row of failures or of slow loads kept through loads in
664
+ time between them until a minute without one, so a loader that fails every
665
+ other or every third load writes one row; loads after which nothing is
666
+ kept, from the second in a row, and loads that named other files, which
667
+ neither count nor end that row) and that a line holds no path; a load at
668
+ every request written while a file vouches for nothing and while loads
669
+ never agree, and none at a change that names other files; each input of the
670
+ workspace resolution (pointer folder, data-root preference, protected
671
+ repositories) keeping two loads apart; a system that resolves no path, for
672
+ a regular file and for a link; and, through the test service entry in a
673
+ child process, a start under `--startup` on a promise, a refused promise,
674
+ a thenable (its `then` called once) and a refused promise with a `then` of
675
+ its own that throws (never called), which asks the loader once, records the
676
+ refusal and ends with 0; and one on a loader that throws `undefined`, a
677
+ value with no prototype or one whose `code` cannot be read, or answers a
678
+ project whose `then` cannot be read, which logs `untyped-error` with the
679
+ text of what was thrown (its message, or the value itself, `undefined` for
680
+ `undefined`, and `unprintable` when it cannot be made text) and ends
681
+ with 1. `test/obsidian-personal-selection.test.mjs` covers a locator that
682
+ answers a thenable (its `then` called once) or throws `undefined`. Ten more
683
+ mutations (the loader asked twice at such a start, its
684
+ promise not let go, every load or every failure written, no fallback for a
685
+ regular file or one for a link too, a late refusal not given up, and each
686
+ of the three inputs dropped) each fail at least one case, and so do a row
687
+ of failures or of slow loads ended at any load in time, a load after which
688
+ nothing is kept written from the first in a row, the first load counted
689
+ among those, a kept project that does not end that row, a load that named
690
+ other files counted or ending it, and the files taken as vouching when they
691
+ did not.
692
+ `test/obsidian-personal-workspace.test.mjs` keeps a bound personal
693
+ workspace from the loader that composes in a worker: its views once two
694
+ compositions agree, nothing while its generation is refused, and the next
695
+ generation's views once that is bound.
491
696
  - `test/obsidian-plugin.test.mjs` runs the shipped `main.js` in a stand-in app
492
697
  against a real listener on an ephemeral loopback port: parity of the
493
698
  plugin's constants and of every proof and MAC with the channel contract (a
@@ -517,7 +722,13 @@ note open in the editor.
517
722
  drift left for the person asked about once),
518
723
  and an upgrade; the service publishing the plugin and the plugin it
519
724
  published holding the view; qualification from a plugin report, with one
520
- launch or two; and `status` and `open` reporting it. A spawn guard refuses
725
+ launch or two; `status` and `open` reporting it; a view the project turns
726
+ off or no longer declares, told nothing of what the service stored about
727
+ it, before the next tick and after it, and told as before once it is
728
+ allowed again; a project whose pointer is pointed at another workspace,
729
+ told nothing until it names this one again; and a loader that answers a
730
+ promise, never waited for, with the plugin keeping its session meanwhile.
731
+ A spawn guard refuses
521
732
  any child of the suite that could reach an Obsidian with the developer's
522
733
  own `HOME`.
523
734
  - The same file has three real-app tests, skipped unless
@@ -556,64 +767,3 @@ note open in the editor.
556
767
  storage. Writing the profile's local storage would mean editing a LevelDB
557
768
  database behind the app's back, and calling `app.plugins.setEnable(true)`
558
769
  would skip the prompt altogether.
559
-
560
- ## Phase 2 plan
561
-
562
- Phase 2 moves the in-app critical section of publication into the plugin, and
563
- closes gates G20 and G21 of the initiative. Nothing below is implemented.
564
-
565
- 1. Commands. The channel gains the publication protocol's three operations,
566
- `inspect`, `publish` (`replace` and `remove`) and `collect`, with the
567
- payloads the command-line path validates today (`validatePayload`), and a
568
- protocol variant, `obsidian-plugin-critical-section/v1`, recorded in every
569
- journal it writes. The service stays the only client that starts work; the
570
- plugin fetches work with a bounded long poll (`POST /plugin/work`) and
571
- answers with `POST /plugin/result`, both sealed under the session's key
572
- like every command of phase 1, so the plugin never listens on a port and
573
- takes work only from a service that proved it holds the vault's key.
574
- At most one operation per vault is in flight, every operation has an
575
- identity, a lost answer is recovered with `collect`, and a publish is never
576
- sent twice.
577
- 2. The critical section. The plugin runs the same synchronous body the
578
- command-line path sends through `eval` (`criticalSection` in
579
- `bridge-script.mjs`), shipped in `main.js` rather than sent: refuse on a
580
- dirty or differing editor in any window, refuse on changed bytes on disk,
581
- exchange atomically, update open editors in one transaction of minimal
582
- hunks and record `lastSavedData`, record the outcome, reply at once. The
583
- late-writer re-check and the manifest commit stay in the publisher.
584
- 3. Path selection. With a live lease from a plugin whose protocol matches, the
585
- publisher uses the plugin channel; otherwise the command-line path, and
586
- with no app running, the app-free path, exactly as today. A refusal is
587
- never relaxed by switching paths.
588
- 4. Live edit preservation. The plugin forwards the vault's `modify` events and
589
- the editor's dirty state for Atelier's notes to the service as they happen,
590
- so an edit is preserved in recovery before any maintenance tick looks for
591
- it. The service still decides what an edit is.
592
- 5. G20. The complete G00 interleaving suite (sixteen interleavings, racing
593
- cases repeated) and the G04 production-publisher suite run in plugin mode
594
- on a real isolated app, unchanged, with zero lost bytes. A case that passes
595
- on the command-line path and fails in plugin mode fails the gate; the suite
596
- is not narrowed.
597
- 6. G21. Apply and Discard in the status window for held edits, forwarded to
598
- the service's existing apply operation, which decides; then the procedure
599
- AP-08: enable, disable, uninstall and an app below the floor on one vault
600
- with pending edits and recovery bytes, comparing manifests, path
601
- allocations, pending edits and recovery digests with the command-line path
602
- after each step.
603
-
604
- Open questions for phase 2: when, if ever, plugin files are removed from a
605
- vault; and how an upgraded service answers an older `main.js` that the app
606
- keeps running until it reloads the plugin (the hello carries the plugin
607
- version and the protocol for that).
608
-
609
- ### Deviations from the track plan
610
-
611
- The obsidian-plugin track planned an optional enhanced mode. The owner's
612
- decision of 2026-09-24 made the plugin the primary in-app half, shipped in
613
- every managed vault, with the command-line path as the fallback. Phase 1 here
614
- therefore builds the plugin, its delivery and a presence and status channel
615
- before the publication commands the plan's first phase describes; the parity
616
- held today is between the plugin's constants and the channel contract, and the
617
- refusal parity with the command-line path belongs to phase 2, when the plugin
618
- carries publication commands. Fixtures are generated in temporary directories
619
- rather than kept under `fixtures/obsidian/plugin/`.
@@ -1,15 +1,24 @@
1
- # Practical Judgment and practice adoption
1
+ # Phronesis — practical judgment
2
2
 
3
- Practical Judgment supports deciding what matters and what is fitting in a
3
+ Phronesis supports deciding what matters and what is fitting in a
4
4
  particular situation. It also supports cultivation: contrasting cases, warranted
5
5
  exceptions, questions, distinct voices and reflection on consequences. A useful
6
6
  deliberation can remain open or produce an action without producing a rule.
7
7
 
8
+ Phronesis is a responsibility; the [Knowledge Graph](knowledge-graph.md) is a
9
+ shared representation. Knowledge Stewardship remains the broader responsibility
10
+ for knowledge inclusion and applicability. Phronesis draws on the shared graph
11
+ and contributes cases, decisions and learning through existing Knowledge records,
12
+ review and activation. It introduces no new store or canonical authority and
13
+ does not supply automatic wisdom or a universal score.
14
+
8
15
  `@mnstry/atelier/judgment` validates portable cases and native architecture
9
16
  decision snapshots. `inspectPracticalCase` preserves purpose, values, evidence,
10
17
  alternatives, dissent, cultivation exercises and reconsideration conditions.
11
18
  It does not score wisdom. The invented workshop fixtures demonstrate an open
12
19
  deliberation and a decision whose implementation is still planned.
20
+ The API and the `atelier-practical-judgment` skill identity retain their existing
21
+ names and compatibility obligations.
13
22
 
14
23
  ## Architecture decisions
15
24
 
@@ -31,7 +40,7 @@ review and dependency reconsideration. Do not change an old record in place.
31
40
 
32
41
  ## From feedback to intrinsic practice
33
42
 
34
- The [learning lifecycle](learning.md) captures an observation, proposes a scoped
43
+ The [learning lifecycle](../guides/learning.md) captures an observation, proposes a scoped
35
44
  lesson, records an exact decision, then activates the accepted version for a
36
45
  named harness. `capabilityEventToLearningInput` bridges version-bound capability
37
46
  metadata into that lifecycle. It retains the reported cause, binding, release,
@@ -0,0 +1,92 @@
1
+ # Portability: what a record holds and what the checks prove
2
+
3
+ An Atelier workspace is meant to be enough for another team to build from,
4
+ without rediscovering the work it describes. This page says what a complete
5
+ record holds, what each check proves about it, and where the line between the
6
+ record and a running product falls. `docs/reference/continuity.md` covers the
7
+ package's own continuity commitments; this page covers yours.
8
+
9
+ ## What a complete record holds
10
+
11
+ | What the record must hold | What another team needs from it |
12
+ | --- | --- |
13
+ | Rules and calculations | The rules the product applies, their inputs, how each result is computed and interpreted, exceptions and versions. |
14
+ | Agent behavior | Instructions, tone, context requirements, permitted actions and example exchanges. |
15
+ | Product and interface | Screens and flows, state changes, saved results, access rules, and what one person or a group can do. |
16
+ | Content and brand | Copy, published material, design references and assets, with ownership or license terms. |
17
+ | Business workflows | Processes, responsibilities, handoffs and approval rules. |
18
+ | Data and connections | Your systems' data formats, identifiers, relationships and export instructions, plus the service interfaces and dependencies a replacement would reconnect. |
19
+ | Tests and decisions | Representative inputs and expected results, quality criteria, accepted decisions and relevant revision history. |
20
+
21
+ **Every custom rule has a retained explanation.** If a rule determines a
22
+ result, a reply, access or a next step, its meaning belongs in the authored
23
+ record, including when software executes it.
24
+
25
+ ## How the record is checked
26
+
27
+ In three parts. The first two are package commands; the third is not.
28
+
29
+ The export validator checks conformance: the record is in the published
30
+ format and every reference resolves to a declared source. What it refuses
31
+ across a source's `audience` and an export's `visibility` is stated in the
32
+ README's audience-visibility block.
33
+
34
+ ```bash
35
+ atelier dry-run ./atelier-export.json
36
+ ```
37
+
38
+ The report says `accepted`, and separately whether the artifact is
39
+ `importable`. The validator resolves references to declared provenance
40
+ entries, not to packaged content, so it proves the artifact's shape and its
41
+ references, not that everything necessary was written down.
42
+
43
+ The readiness protocols check coverage inputs: a supplied answers file is
44
+ checked against each protocol's required inputs, and the missing ones are
45
+ listed. An answer being present is not evidence that it is right.
46
+
47
+ ```bash
48
+ atelier readiness run PROTOCOL_ID --answers answers.json --project ./atelier.project.json
49
+ ```
50
+
51
+ That run is an input-completeness check and is not evidence-bound. For a run
52
+ bound to its sources, `atelier review run PROTOCOL_ID --answers answers.json`
53
+ records that source-bound run. Accepting one of its claims in the review
54
+ workspace checks source linkage. A linked source establishes which
55
+ bytes were read, not whether they logically support the proposed claim
56
+ (`docs/guides/local-review.md`). The responsible people review coverage; an
57
+ issuer can record its admission decision in an attestation bound to the canonical form of the document it
58
+ judged (`docs/reference/attestation.md`).
59
+
60
+ The record also carries its own tests. A complete record gives every
61
+ documented rule representative inputs and expected results beside it. The
62
+ package keeps these cases and links them to their rules; it does not run them.
63
+ Whatever executes the rules runs them, so name that runner when you cite this
64
+ check.
65
+
66
+ Together the three show what has been delivered and what remains unresolved,
67
+ in the record rather than in someone's memory. A rebuild also needs the authored
68
+ rules, their representative tests, the data exports, the dependencies and the
69
+ operating instructions, reviewed together against the agreed scope. No
70
+ validator can supply that review.
71
+
72
+ ## The dividing line
73
+
74
+ If it describes how the work is done, it is a file in the Atelier. If it
75
+ records what happened to a particular person, or has to be enforced at the
76
+ moment of use, it lives in a product runtime. A folder of files cannot
77
+ decide, while two people are in a session, which of them may see what;
78
+ cannot hold a payment; and cannot be the consistent, recoverable record when
79
+ several parties write at once.
80
+
81
+ The Atelier holds how the work is done and the documentation of your systems'
82
+ data: formats, identifiers, relationships and export instructions. Records
83
+ about particular people live in the systems you run. What the package will
84
+ and will not do toward any runtime is stated once, in the README's
85
+ will-not-do block; this page adds nothing to it.
86
+
87
+ ## Copying the record
88
+
89
+ The repository is the store, Git is the history, and a copy of the folder is a
90
+ copy of the whole record. A copied folder carries the record and its history,
91
+ not remote data or assets stored elsewhere; the data-and-connections row above
92
+ is where those are described so a replacement knows where to look.
@@ -2,8 +2,8 @@
2
2
 
3
3
  Status: opt-in implementation candidate, not a published or adopted interface.
4
4
  Contract discussion: [issue 39](https://github.com/MNSTRY/atelier/issues/39).
5
- Current corrections and remaining adoption conditions:
6
- [review disposition](presentation-review-disposition.md).
5
+ Current compatibility and adoption conditions are in
6
+ [consumer boundaries](presentation-consumer-boundaries.md).
7
7
 
8
8
  ## Placement and authority
9
9
 
@@ -44,6 +44,11 @@ font loads; no-JavaScript readability and absence of motion are the baseline.
44
44
  5. Obtain the separate source, CI, maintainer and deployment authorities. The
45
45
  reference consumer neither allocates a product path nor activates a site.
46
46
 
47
+ Synthetic composition events and browser/React fixtures do not establish real
48
+ OS input, screen-reader behavior or native performance. Verify pending/busy
49
+ announcements with actual assistive technology and profile the receiving native
50
+ host before changing its confirmation guards.
51
+
47
52
  ## CI integration handoff
48
53
 
49
54
  The existing workflow does not yet execute either browser proof. A maintainer
@@ -31,6 +31,23 @@ Resolution may create ignored `.atelier-local/` directories; this diagnostic is
31
31
  not a promise of a write-free invocation. The ordinary config report retains
32
32
  its existing shape and local config path.
33
33
 
34
+ ## Bundled readiness selection
35
+
36
+ The tracked `atelier.project.json` may set
37
+ `ext["mnstry.atelier"].readiness.includeBundled` to `false` to deselect the bundled
38
+ MNSTRY readiness pack. An absent setting or explicit `true` preserves the
39
+ existing default. `readiness` must be an object and `includeBundled` a boolean;
40
+ invalid values fail with `readiness-selection-invalid`. This is a project
41
+ setting, not a CLI flag or local preference.
42
+
43
+ Project-aware protocol listing and runs then use only selected custom packs;
44
+ generic graph, projection and readiness checks remain available without the
45
+ MNSTRY tenant journey. A bare protocol listing without a project selection
46
+ retains its standalone bundled list. Review selection changes and run
47
+ `atelier lock write --project ./atelier.project.json`; see
48
+ [readiness pack selection](../guides/tenant-readiness.md#select-the-readiness-pack)
49
+ for lock checks and commands that require the bundle.
50
+
34
51
  ## Command inventory
35
52
 
36
53
  | Family | Project handling | Other effects |