@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.
- package/CHANGELOG.md +283 -0
- package/README.md +102 -52
- package/SECURITY.md +1 -1
- package/TRADEMARKS.md +2 -2
- package/contracts/atelier-extension-manifest.v1.schema.json +412 -0
- package/contracts/atelier-graph-view.v1.schema.json +1085 -0
- package/contracts/public-api-baseline.json +298 -19
- package/docs/README.md +90 -0
- package/docs/blocks/capability-stewardship.md +1 -1
- package/docs/blocks/claims.md +2 -2
- package/docs/blocks/conformance-admission.md +1 -1
- package/docs/blocks/learning-harnesses.md +1 -1
- package/docs/{atelier-sync.md → guides/atelier-sync.md} +20 -14
- package/docs/{capability-stewardship.md → guides/capability-stewardship.md} +2 -4
- package/docs/guides/co-authoring.md +113 -0
- package/docs/{distributions.md → guides/distributions.md} +13 -8
- package/docs/guides/extensions.md +189 -0
- package/docs/guides/graph-refresh.md +152 -0
- package/docs/guides/graph-workspace.md +64 -0
- package/docs/{ingestion.md → guides/ingestion.md} +16 -15
- package/docs/{inquiry-harnesses.md → guides/inquiry-harnesses.md} +2 -3
- package/docs/{knowledge-workspace.md → guides/knowledge-workspace.md} +2 -2
- package/docs/{learning-harnesses.md → guides/learning-harnesses.md} +2 -3
- package/docs/{learning.md → guides/learning.md} +12 -5
- package/docs/{obsidian.md → guides/obsidian.md} +370 -23
- package/docs/guides/ontology-guide.md +111 -0
- package/docs/{personal-workspace.md → guides/personal-workspace.md} +17 -5
- package/docs/{research-starter.md → guides/research-starter.md} +1 -1
- package/docs/{tenant-readiness.md → guides/tenant-readiness.md} +39 -0
- package/docs/{upgrade.md → guides/upgrade.md} +197 -11
- package/docs/knowledge-health/assessment/capabilities.md +6 -15
- package/docs/knowledge-health/facilitator.md +15 -4
- package/docs/knowledge-health/{devday/participant-response.md → participant-response.md} +4 -2
- package/docs/knowledge-health/quickstart.md +97 -75
- package/docs/knowledge-health/readme.md +13 -5
- package/docs/maintainers/describing-the-atelier.md +173 -0
- package/docs/{release-engineering.md → maintainers/release-engineering.md} +5 -4
- package/docs/{announcements.md → reference/announcements.md} +1 -1
- package/docs/{architecture.md → reference/architecture.md} +31 -5
- package/docs/{atelier-runtime.md → reference/atelier-runtime.md} +1 -1
- package/docs/{connected-composition.md → reference/connected-composition.md} +7 -10
- package/docs/{coordination.md → reference/coordination.md} +1 -1
- package/docs/{decisions.md → reference/decisions.md} +3 -3
- package/docs/{design.md → reference/design.md} +1 -1
- package/docs/reference/edge-policy.md +151 -0
- package/docs/reference/graph-view-structured.md +119 -0
- package/docs/reference/graph-view.md +139 -0
- package/docs/reference/graph-workspace.md +37 -0
- package/docs/{intake-and-guides.md → reference/intake-and-guides.md} +3 -4
- package/docs/{knowledge-graph.md → reference/knowledge-graph.md} +120 -6
- package/docs/{local-services.md → reference/local-services.md} +43 -4
- package/docs/{obsidian-contract.md → reference/obsidian-contract.md} +29 -4
- package/docs/{obsidian-plugin.md → reference/obsidian-plugin.md} +218 -68
- package/docs/{practical-judgment.md → reference/phronesis.md} +12 -3
- package/docs/reference/portability.md +92 -0
- package/docs/{portable-presentation.md → reference/portable-presentation.md} +2 -2
- package/docs/{presentation-consumer-boundaries.md → reference/presentation-consumer-boundaries.md} +5 -0
- package/docs/{project-options.md → reference/project-options.md} +17 -0
- package/docs/{repo-boundary-guard.md → reference/repo-boundary-guard.md} +50 -4
- package/docs/{review-portability.md → reference/review-portability.md} +4 -0
- package/docs/{semantic-operation.md → reference/semantic-operation.md} +4 -3
- package/docs/{template-profile.md → reference/template-profile.md} +1 -1
- package/docs/{trackables.md → reference/trackables.md} +2 -2
- package/docs/start/independent-start.md +89 -0
- package/docs/{install.md → start/install.md} +9 -9
- package/docs/{knowledge-setup.md → start/knowledge-setup.md} +5 -5
- package/docs/{research-starter-quickstart.md → start/research-starter-quickstart.md} +6 -6
- package/fixtures/atelier-architecture/catalog/invalid/document.json +2 -2
- package/fixtures/atelier-architecture/catalog/valid/document.json +2 -2
- package/fixtures/graph-view/synthetic-authorized-input.v1.json +437 -0
- package/fixtures/graph-view/synthetic-view.v1.json +1 -0
- package/fixtures/knowledge-health/workshop/README.md +1 -1
- package/fixtures/templates/local-library.v1.json +3 -1
- package/package.json +22 -8
- package/plugins/obsidian/main.js +57 -8
- package/plugins/obsidian/manifest.json +1 -1
- package/skills/claude/atelier-guided-upgrade/SKILL.md +1 -1
- package/skills/claude/atelier-knowledge-setup/SKILL.md +2 -2
- package/skills/claude/atelier-local-service/SKILL.md +1 -1
- package/skills/claude/atelier-practical-judgment/SKILL.md +7 -2
- package/skills/claude/atelier-skill-steward/SKILL.md +1 -1
- package/skills/claude/mnstry-readiness/SKILL.md +2 -2
- package/skills/codex/atelier-guided-upgrade/SKILL.md +1 -1
- package/skills/codex/atelier-knowledge-setup/SKILL.md +2 -2
- package/skills/codex/atelier-local-service/SKILL.md +1 -1
- package/skills/codex/atelier-practical-judgment/SKILL.md +7 -2
- package/skills/codex/atelier-skill-steward/SKILL.md +1 -1
- package/skills/codex/mnstry-readiness/SKILL.md +2 -2
- package/src/architecture/catalog.mjs +2 -2
- package/src/attestation/sign.mjs +1 -1
- package/src/boundary/content-rules.mjs +534 -68
- package/src/boundary/policy.mjs +187 -60
- package/src/cli/run.mjs +26 -9
- package/src/commands/distribution.mjs +1 -1
- package/src/commands/extension.mjs +27 -0
- package/src/commands/ingest.mjs +1 -1
- package/src/commands/learn.mjs +1 -1
- package/src/commands/obsidian.mjs +49 -21
- package/src/commands/review.mjs +3 -0
- package/src/edge-policy/contract.mjs +69 -0
- package/src/edge-policy/policy.mjs +142 -0
- package/src/edge-policy/source-citation-adapter.mjs +43 -0
- package/src/extension-packs/loader.mjs +4 -3
- package/src/extensions/admission.mjs +83 -0
- package/src/extensions/client.d.mts +23 -0
- package/src/extensions/client.mjs +99 -0
- package/src/extensions/contracts.d.mts +29 -0
- package/src/extensions/contracts.mjs +163 -0
- package/src/extensions/convex.d.mts +24 -0
- package/src/extensions/convex.mjs +189 -0
- package/src/extensions/delegation.mjs +54 -0
- package/src/extensions/drizzle.d.mts +11 -0
- package/src/extensions/drizzle.mjs +33 -0
- package/src/extensions/postgres.d.mts +7 -0
- package/src/extensions/postgres.mjs +66 -0
- package/src/extensions/prisma.d.mts +13 -0
- package/src/extensions/prisma.mjs +63 -0
- package/src/extensions/project.mjs +432 -0
- package/src/extensions/scaffold-convex.mjs +130 -0
- package/src/extensions/scaffold-sql.mjs +144 -0
- package/src/extensions/server.d.mts +20 -0
- package/src/extensions/server.mjs +102 -0
- package/src/extensions/sql-scope.mjs +22 -0
- package/src/graph/graph.mjs +13 -5
- package/src/graph/knowledge-graph.mjs +20 -2
- package/src/graph/repo-contribution.mjs +405 -0
- package/src/graph/repo-contribution.types.mjs +32 -0
- package/src/graph-access/edge-decision-adapter.mjs +41 -0
- package/src/graph-access/edge-record-adapter.mjs +73 -0
- package/src/graph-access/index.mjs +253 -0
- package/src/graph-access/multi-contribution-record-adapter.mjs +101 -0
- package/src/graph-access/multi-record-projection-adapter.mjs +74 -0
- package/src/graph-access/source-adapter.mjs +81 -0
- package/src/graph-refresh/compare.mjs +110 -0
- package/src/graph-refresh/controller.mjs +324 -0
- package/src/graph-refresh/index.mjs +3 -0
- package/src/graph-refresh/local.mjs +78 -0
- package/src/graph-view/babylon/babylon-scene-port.mjs +64 -0
- package/src/graph-view/babylon/index.mjs +2 -0
- package/src/graph-view/babylon/navigator.mjs +312 -0
- package/src/graph-view/babylon/provenance.mjs +36 -0
- package/src/graph-view/babylon/scene-controller.mjs +131 -0
- package/src/graph-view/babylon/semantic-picking.mjs +35 -0
- package/src/graph-view/babylon/web-host.mjs +188 -0
- package/src/graph-view/cli.mjs +3 -0
- package/src/graph-view/command.mjs +34 -0
- package/src/graph-view/contracts.mjs +79 -0
- package/src/graph-view/errors.mjs +5 -0
- package/src/graph-view/index.mjs +4 -0
- package/src/graph-view/intents.mjs +30 -0
- package/src/graph-view/query.mjs +213 -0
- package/src/graph-view/refs.mjs +2 -0
- package/src/graph-view/structured/browser.mjs +262 -0
- package/src/graph-view/structured/styles.mjs +8 -0
- package/src/graph-workspace/authoring.mjs +185 -0
- package/src/graph-workspace/browser/constellation.mjs +369 -0
- package/src/graph-workspace/browser/dom.mjs +23 -0
- package/src/graph-workspace/browser/index.mjs +6 -0
- package/src/graph-workspace/browser/review.mjs +55 -0
- package/src/graph-workspace/browser/styles.mjs +11 -0
- package/src/graph-workspace/browser/workbench.mjs +351 -0
- package/src/graph-workspace/browser/workspace.mjs +431 -0
- package/src/graph-workspace/disclosure.mjs +39 -0
- package/src/graph-workspace/geometry.mjs +78 -0
- package/src/graph-workspace/index.mjs +11 -0
- package/src/graph-workspace/labels.mjs +50 -0
- package/src/graph-workspace/model.mjs +109 -0
- package/src/graph-workspace/recipes.mjs +88 -0
- package/src/graph-workspace/scale.mjs +95 -0
- package/src/graph-workspace/theme.mjs +156 -0
- package/src/ingestion/optional/graphify/graphify_supplier.py +5 -0
- package/src/ingestion/optional/graphify/native-closure-pins.json +275 -0
- package/src/ingestion/optional/graphify/native-pins.json +306 -0
- package/src/knowledge/ontology-guide.mjs +152 -0
- package/src/knowledge-health/proof/installed-check.mjs +2 -2
- package/src/knowledge-health/rule-identity.mjs +14 -9
- package/src/knowledge-health/workshop.mjs +22 -2
- package/src/personal-workspace/index.mjs +1 -1
- package/src/personal-workspace/selection.mjs +34 -3
- package/src/project/config.mjs +1 -1
- package/src/project/path-match.mjs +2 -1
- package/src/project/providers/github.mjs +24 -0
- package/src/project/repo-identity.mjs +3 -22
- package/src/projection/obsidian/contracts.mjs +1 -1
- package/src/projection/obsidian/materialize/path-registry.mjs +1 -1
- package/src/projection/obsidian/materialize/prepare-view.mjs +88 -6
- package/src/projection/obsidian/materialize/redaction.mjs +1 -1
- package/src/projection/obsidian/personal-workspace.mjs +84 -5
- package/src/projection/obsidian/plugin-bridge/channel.mjs +1 -1
- package/src/projection/obsidian/proposals/adapter.mjs +46 -23
- package/src/projection/obsidian/proposals/observation.mjs +40 -2
- package/src/projection/obsidian/publication/publisher.mjs +96 -8
- package/src/projection/project.mjs +21 -16
- package/src/readiness/readiness.mjs +20 -11
- package/src/readiness-protocols/bundled-pack.mjs +14 -766
- package/src/readiness-protocols/bundled-selection.mjs +32 -0
- package/src/readiness-protocols/evidence.mjs +2 -1
- package/src/readiness-protocols/packs/mnstry.mjs +766 -0
- package/src/readiness-protocols/runtime.mjs +43 -6
- package/src/runtime/obsidian/engine.mjs +387 -76
- package/src/runtime/obsidian/lifecycle.mjs +20 -15
- package/src/runtime/obsidian/login-item.mjs +6 -3
- package/src/runtime/obsidian/machine-settings.mjs +52 -8
- package/src/runtime/obsidian/observation.mjs +36 -4
- package/src/runtime/obsidian/opening.mjs +4 -3
- package/src/runtime/obsidian/personal-selection.mjs +187 -0
- package/src/runtime/obsidian/pipeline.mjs +115 -6
- package/src/runtime/obsidian/private-lock.mjs +50 -6
- package/src/runtime/obsidian/selection-continuity.mjs +124 -0
- package/src/runtime/obsidian/service-main.mjs +68 -16
- package/src/runtime/obsidian/service.mjs +80 -6
- package/src/runtime/obsidian/unheld-evidence.mjs +1 -1
- package/src/runtime/obsidian/view-permission.mjs +335 -0
- package/src/ui/control-system.mjs +201 -0
- package/src/ui/html-primitives.mjs +3 -0
- package/src/upgrade/closure-diagnostics.mjs +135 -0
- package/src/upgrade/closure.mjs +649 -0
- package/src/upgrade/upgrade.mjs +42 -11
- package/templates/distribution-workspace/README.md +2 -2
- package/templates/external-project-workspace/atelier.project.json +3 -0
- package/templates/external-project-workspace/pack-lifecycle.json +3 -1
- package/templates/knowledge-workspace/README.md +2 -2
- package/docs/integration-and-review-plan.md +0 -409
- package/docs/integration-contract-decisions.md +0 -44
- package/docs/knowledge-health/devday/facilitator.md +0 -16
- package/docs/knowledge-health/devday/public-default.md +0 -107
- package/docs/knowledge-health/devday/quickstart.md +0 -18
- package/docs/knowledge-health/devday/support.md +0 -22
- package/docs/knowledge-health/exercise.md +0 -17
- package/docs/knowledge-health/support.md +0 -34
- package/docs/presentation-review-disposition.md +0 -47
- package/docs/progressive-ingestion-acceptance.md +0 -89
- package/docs/progressive-ingestion.md +0 -235
- /package/docs/{exact-upgrades.md → guides/exact-upgrades.md} +0 -0
- /package/docs/{guided-upgrades.md → guides/guided-upgrades.md} +0 -0
- /package/docs/{local-review.md → guides/local-review.md} +0 -0
- /package/docs/{skill-steward.md → guides/skill-steward.md} +0 -0
- /package/docs/{template-upgrades.md → guides/template-upgrades.md} +0 -0
- /package/docs/{assurance-controls.md → maintainers/assurance-controls.md} +0 -0
- /package/docs/{attestation.md → reference/attestation.md} +0 -0
- /package/docs/{coauthor-session.md → reference/coauthor-session.md} +0 -0
- /package/docs/{continuity.md → reference/continuity.md} +0 -0
- /package/docs/{contract-stability.md → reference/contract-stability.md} +0 -0
- /package/docs/{decision-practices.md → reference/decision-practices.md} +0 -0
- /package/docs/{evidence-navigation.md → reference/evidence-navigation.md} +0 -0
- /package/docs/{extension-pack-lifecycle.md → reference/extension-pack-lifecycle.md} +0 -0
- /package/docs/{interaction-and-reflection.md → reference/interaction-and-reflection.md} +0 -0
- /package/docs/{local-state.md → reference/local-state.md} +0 -0
- /package/docs/{ontology.md → reference/ontology.md} +0 -0
- /package/docs/{optional-ingestion.md → reference/optional-ingestion.md} +0 -0
- /package/docs/{project-command-inventory.md → reference/project-command-inventory.md} +0 -0
- /package/docs/{semantic-ingestion.md → reference/semantic-ingestion.md} +0 -0
- /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
|
-
|
|
207
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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;
|
|
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
|
-
#
|
|
1
|
+
# Phronesis — practical judgment
|
|
2
2
|
|
|
3
|
-
|
|
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
|
|
6
|
-
[
|
|
5
|
+
Current compatibility and adoption conditions are in
|
|
6
|
+
[consumer boundaries](presentation-consumer-boundaries.md).
|
|
7
7
|
|
|
8
8
|
## Placement and authority
|
|
9
9
|
|
package/docs/{presentation-consumer-boundaries.md → reference/presentation-consumer-boundaries.md}
RENAMED
|
@@ -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 |
|