@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
|
@@ -30,7 +30,7 @@ sources, concepts, relations, and questions before operational use.
|
|
|
30
30
|
|
|
31
31
|
An existing enrolled project needs a valid `knowledge-plan.json` beside its
|
|
32
32
|
project configuration. Use the schema and guide in
|
|
33
|
-
[knowledge setup](knowledge-setup.md). Rebuild the projection when its source
|
|
33
|
+
[knowledge setup](../start/knowledge-setup.md). Rebuild the projection when its source
|
|
34
34
|
changes. The knowledge panels read the current enrolled graph on request; the
|
|
35
35
|
ordinary projection remains the last explicitly built projection.
|
|
36
36
|
|
|
@@ -216,7 +216,7 @@ Start takes `requestId` (a fresh UUID, retained for exact retry), `flow`
|
|
|
216
216
|
and `author`. Read/recover take only `sessionId`. Event takes `sessionId` and
|
|
217
217
|
an `event` with a unique `id`, current `expectedRevision`, and reducer `type`.
|
|
218
218
|
An `answer` or `propose` also carries `text`. All other event behavior follows
|
|
219
|
-
[coauthor sessions](coauthor-session.md). Clients cannot submit receipts or
|
|
219
|
+
[coauthor sessions](../reference/coauthor-session.md). Clients cannot submit receipts or
|
|
220
220
|
failure events. Stale versions never silently overwrite an intervening answer.
|
|
221
221
|
|
|
222
222
|
Ask one useful question at a time. Record the person's exact answer. For
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# Knowledge development and the learning cycle
|
|
2
2
|
|
|
3
|
-
Status:
|
|
4
|
-
|
|
5
|
-
checkout, or `atelier harness help` from a package built from this candidate.
|
|
3
|
+
Status: shipped since 0.2.0-alpha.13. Run `atelier harness help` for the
|
|
4
|
+
commands.
|
|
6
5
|
|
|
7
6
|
Knowledge Harness helps people establish, develop, use and revise what they know.
|
|
8
7
|
Ingestion is one capability within that larger purpose. Sources can also originate
|
|
@@ -5,6 +5,11 @@ decisions, and supplies explicitly activated lessons to a named harness. It is
|
|
|
5
5
|
an experimental local source capability. It requires consumer integration and
|
|
6
6
|
does not establish availability in a published package or installed desktop.
|
|
7
7
|
|
|
8
|
+
Here, `capture` means recording the observation explicitly supplied by a caller
|
|
9
|
+
or on stdin. It does not monitor an editor, microphone, conversation or desktop.
|
|
10
|
+
The [independent local start](../start/independent-start.md) needs no desktop or MNSTRY
|
|
11
|
+
account; integrated capture is a separate host capability.
|
|
12
|
+
|
|
8
13
|
A person defines the task and scope, an agent can propose a lesson, and the
|
|
9
14
|
person reviews its wording and consequences. Evidence can be represented before
|
|
10
15
|
acceptance. Only accepted, activated content is eligible for task context.
|
|
@@ -202,11 +207,13 @@ Campaigns may stay in their own workspaces; selected references do not change
|
|
|
202
207
|
their writer ownership. Private evidence projections stay outside committed
|
|
203
208
|
canonical graphs unless an owner explicitly authors an appropriate source.
|
|
204
209
|
|
|
205
|
-
A
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
+
A consuming host owns integrated capture, authenticating its caller, background
|
|
211
|
+
jobs, provider access, budgets, review controls and actual harness integration.
|
|
212
|
+
MNSTRY's desktop utility is a separate proprietary consumer of this public
|
|
213
|
+
foundation. Other hosts can use the same portable APIs and optional public
|
|
214
|
+
startup, editor and native-presentation bindings. Private feedback, preferences,
|
|
215
|
+
methods and authored skills remain in their owning workspace. Basic local
|
|
216
|
+
learning and export require no MNSTRY account or service.
|
|
210
217
|
|
|
211
218
|
Run `node --test test/learning-*.test.mjs` on the supported Node version for
|
|
212
219
|
the local acceptance cases. They cover terminal capture through withdrawal
|
|
@@ -4,7 +4,7 @@ This document describes the selection binding, the apply policy setup, the
|
|
|
4
4
|
conflict-state view and the acceptance receipt validator under
|
|
5
5
|
`src/projection/obsidian/selection-ui/`. It states what each one does on this
|
|
6
6
|
machine and what it does not. The contract itself is in
|
|
7
|
-
[obsidian-contract.md](obsidian-contract.md).
|
|
7
|
+
[obsidian-contract.md](../reference/obsidian-contract.md).
|
|
8
8
|
|
|
9
9
|
Nothing in this module starts the app, runs `obsidian-cli`, publishes a vault
|
|
10
10
|
or writes a source file. The test suite installs a spawn guard that throws if
|
|
@@ -273,7 +273,7 @@ path. The package root (`@mnstry/atelier`) exports nothing of the projection.
|
|
|
273
273
|
Names ending `ForOracleTests` are mutation controls for the test suite, not a
|
|
274
274
|
supported API. The whole surface is alpha and may change between prereleases.
|
|
275
275
|
What the tarball must and must not carry, and the package proof, are in
|
|
276
|
-
[release-engineering.md](release-engineering.md#obsidian-package-contents).
|
|
276
|
+
[release-engineering.md](../maintainers/release-engineering.md#obsidian-package-contents).
|
|
277
277
|
|
|
278
278
|
## First vault: what to expect
|
|
279
279
|
|
|
@@ -538,9 +538,19 @@ earlier one, so two installations used on one workspace (a global and a
|
|
|
538
538
|
project-local one, say) do not replace each other's service on every open:
|
|
539
539
|
`open` answers `service-unavailable` / `service-other-release`, and `service
|
|
540
540
|
start` answers that it runs, with `release: later`; run `atelier obsidian
|
|
541
|
-
service stop`, then open again, or open with the later release. A service
|
|
542
|
-
|
|
543
|
-
|
|
541
|
+
service stop`, then open again, or open with the later release. A service that
|
|
542
|
+
does not answer health in time, in a stretch of a tick that does not yield, is
|
|
543
|
+
not stopped (`open` answers `busy`), and a listener that does not prove itself
|
|
544
|
+
this workspace's service is never touched. While a view is being prepared and
|
|
545
|
+
published the service does answer: `open` asks it for a tick that starts after
|
|
546
|
+
the one in flight and waits for that tick, two minutes at most unless
|
|
547
|
+
`atelier obsidian open --wait-ms MS` sets another bound, before it reports the
|
|
548
|
+
view as it is (one that read `current` is reported `updating`, with the reason
|
|
549
|
+
`tick-still-running`, while that tick has not ended); and `service stop` is
|
|
550
|
+
accepted and ends the
|
|
551
|
+
service after the tick in flight or after its shutdown grace, whichever comes
|
|
552
|
+
first. A publication cut short that way is settled by the publisher's restart
|
|
553
|
+
recovery at the next one.
|
|
544
554
|
|
|
545
555
|
The first time Obsidian opens a view's vault it asks "Do you trust the author
|
|
546
556
|
of this vault?", because every vault Atelier publishes carries Atelier's own
|
|
@@ -554,7 +564,7 @@ its own storage and asks again the next time until the vault is trusted or
|
|
|
554
564
|
restricted mode is switched on for good in its settings. Turning the plugin
|
|
555
565
|
off in a vault, or uninstalling it there, is respected from then on;
|
|
556
566
|
`atelier obsidian plugin on --scope ID` brings it back. What the plugin does
|
|
557
|
-
and never does is in [obsidian-plugin.md](obsidian-plugin.md).
|
|
567
|
+
and never does is in [obsidian-plugin.md](../reference/obsidian-plugin.md).
|
|
558
568
|
|
|
559
569
|
`open` and `status` answer with a freshness state, not a promise. `current`
|
|
560
570
|
means the vault is the present generation, verified by read-back, and the app
|
|
@@ -679,7 +689,7 @@ exactly because the folder is listed.
|
|
|
679
689
|
Obsidian does not have to be quit.
|
|
680
690
|
- **Obsidian is not running.** The view is published on the path with no app,
|
|
681
691
|
as before. `open` then adds the vault to the app's settings file (see
|
|
682
|
-
[Obsidian's vault list](obsidian-contract.md#obsidians-vault-list) for
|
|
692
|
+
[Obsidian's vault list](../reference/obsidian-contract.md#obsidians-vault-list) for
|
|
683
693
|
exactly when and how that one file is written, marked to reopen) and starts
|
|
684
694
|
Obsidian plainly, with no link: an Obsidian started with a link opens only
|
|
685
695
|
that vault and drops the reopen flag of every other one, so your other
|
|
@@ -815,7 +825,7 @@ names the folder meanwhile, a settings file with other bytes is already
|
|
|
815
825
|
there, or an interrupted run left a replacement or a removal. `open` may then
|
|
816
826
|
add and open the vault before it is complete, and the app publishes the rest.
|
|
817
827
|
Anything that would replace or remove a file waits for the app. See "First publication into a vault no Obsidian lists" in
|
|
818
|
-
[obsidian-contract.md](obsidian-contract.md). The plugin's entry written this
|
|
828
|
+
[obsidian-contract.md](../reference/obsidian-contract.md). The plugin's entry written this
|
|
819
829
|
way counts as offered until the plugin says hello from the vault.
|
|
820
830
|
|
|
821
831
|
The publisher still writes into a vault only when it can coordinate with every
|
|
@@ -862,8 +872,9 @@ generationId })` in `src/projection/obsidian/personal-workspace.mjs`. Both
|
|
|
862
872
|
arguments are explicit; neither is discovered from the environment or the
|
|
863
873
|
working directory. A loader uses `loadBoundProject` with the same arguments,
|
|
864
874
|
or `loadBoundProjectOffThread`, which composes in a worker thread; the engine
|
|
865
|
-
awaits its loader.
|
|
866
|
-
|
|
875
|
+
awaits its loader. The command, the service and the login item bind a personal
|
|
876
|
+
home through `--personal-home`, which follows the generation the person
|
|
877
|
+
confirmed there (see "A confirmed selection", below).
|
|
867
878
|
|
|
868
879
|
- **One graph.** The binding is attached to the generation's resolved
|
|
869
880
|
`atelier.project.json` under one symbol key. When a project carries it, the
|
|
@@ -960,9 +971,12 @@ keeps one projection configuration per person.
|
|
|
960
971
|
(`personal-views-exceed-settings-limit`), within the Obsidian settings
|
|
961
972
|
contract. The preferred view, when it names a saved one, is the default. No
|
|
962
973
|
generation file is written. `view add` refuses `views-from-personal-overlay`;
|
|
963
|
-
`audience set
|
|
964
|
-
`
|
|
965
|
-
|
|
974
|
+
`audience set me` records owner-only visibility in the machine settings, and
|
|
975
|
+
`audience clear` withholds every audience. Custom audience lists refuse
|
|
976
|
+
`personal-binding-owner-only`; `location set` still refuses
|
|
977
|
+
`personal-binding-decision-unavailable`. Refused operations do not change
|
|
978
|
+
audience, view or location settings. Following a selection may still keep
|
|
979
|
+
machine-private continuity evidence before the setting operation refuses.
|
|
966
980
|
- **Preferences and coverage.** `preferences` are returned read only. A theme
|
|
967
981
|
is reported and never written: `appearance.json` stays the person's.
|
|
968
982
|
`coverage` is passed through untouched. No Obsidian code reads it: it states
|
|
@@ -984,6 +998,173 @@ keeps one projection configuration per person.
|
|
|
984
998
|
in memory. A project configuration that declares it itself is refused at
|
|
985
999
|
every build (`personal-binding-lost`, naming the key).
|
|
986
1000
|
|
|
1001
|
+
### A confirmed selection
|
|
1002
|
+
|
|
1003
|
+
`--personal-home DIR`, given instead of `--project` to `atelier obsidian`, to
|
|
1004
|
+
the service entry and in a login item's unit, binds the personal home DIR
|
|
1005
|
+
(`src/runtime/obsidian/personal-selection.mjs`). Without it, every argument,
|
|
1006
|
+
unit and loader is what it was.
|
|
1007
|
+
|
|
1008
|
+
- **What is loaded.** The generation the person last confirmed with
|
|
1009
|
+
`selectPersonalGeneration` (see [personal-workspace.md](personal-workspace.md)),
|
|
1010
|
+
and nothing else. The loader reads the head of the selection history from
|
|
1011
|
+
the history alone (`readPersonalSelectionHead`), loads the generation it
|
|
1012
|
+
names through the route above (in a worker for the service, in the
|
|
1013
|
+
command's thread for a command), then reads the head again. A head that
|
|
1014
|
+
moved meanwhile refuses `personal-selection-changed`. Nothing here confirms
|
|
1015
|
+
a selection or chooses one for the person.
|
|
1016
|
+
- **Nothing confirmed publishes nothing.** No record refuses
|
|
1017
|
+
`nothing-selected`; a confirmed generation whose inputs were edited and not
|
|
1018
|
+
confirmed again refuses `stale-generation`; a history whose hash chain does
|
|
1019
|
+
not hold refuses `selection-history-corrupt`; a history that ends at an
|
|
1020
|
+
earlier record than the running service has read refuses
|
|
1021
|
+
`selection-history-shortened`; a home whose history cannot be read refuses
|
|
1022
|
+
`personal-home-unavailable`, and a home that is gone or not
|
|
1023
|
+
private refuses with the module's own code (`root-missing`,
|
|
1024
|
+
`not-private-location`, `root-symlinked`). Every other refusal of the
|
|
1025
|
+
composition keeps its code. Nothing falls back to another generation or to
|
|
1026
|
+
the project without a binding. The vault keeps what it last published from
|
|
1027
|
+
a confirmed generation. `status`, `open` and `service start` load the
|
|
1028
|
+
selection and refuse with its code; the service's freshness shows every view
|
|
1029
|
+
`stale` with it, and its status document has it as the last tick's reason.
|
|
1030
|
+
The command and service read the same machine-private continuity state, so a
|
|
1031
|
+
restart or a separate command does not accept a shortened history. An invalid
|
|
1032
|
+
checkpoint refuses `invalid-selection-continuity`; a checkpoint that cannot be
|
|
1033
|
+
kept refuses `selection-continuity-unavailable`. No project is returned in either case.
|
|
1034
|
+
A confirmed selection is reported by `status` (`selection`: the generation
|
|
1035
|
+
and the number of its record).
|
|
1036
|
+
- **The service starts from an initialized home whatever the selection.** A bound
|
|
1037
|
+
project's folder is its private home. The home must contain its caller-authored
|
|
1038
|
+
`atelier.personal.json`, even when its enrollment is explicitly empty and no
|
|
1039
|
+
generation is confirmed. A bare directory or a missing/unreadable manifest
|
|
1040
|
+
refuses before startup; the locator cannot infer that no repositories were
|
|
1041
|
+
enrolled from missing evidence. This tightens the former lower-level API
|
|
1042
|
+
behavior that could start from a bare home. The locator reads the home and the
|
|
1043
|
+
current manifest's repository roots for exclusion, without composing or
|
|
1044
|
+
selecting a generation. A data root
|
|
1045
|
+
inside a declared repository is refused before private state is created or a
|
|
1046
|
+
login item is removed for a restart, including when nothing is confirmed.
|
|
1047
|
+
The service resolves its workspace from that at once and starts, and its
|
|
1048
|
+
engine awaits the loader at each tick. `atelier obsidian --personal-home`
|
|
1049
|
+
does this for a bound home. A
|
|
1050
|
+
program that runs the service itself (`runMaintenanceService` from
|
|
1051
|
+
`@mnstry/atelier/obsidian`) gives it the same through `locateProject`, a
|
|
1052
|
+
synchronous function that answers, without loading anything, a project whose
|
|
1053
|
+
`configDir` is the folder the workspace is resolved from. The workspace is
|
|
1054
|
+
then resolved from that answer alone: a data root named only in the loaded
|
|
1055
|
+
project's local overlay, and not in the answer, is not seen, so the service's
|
|
1056
|
+
state can lie under another data root than the loaded project's. Name the data
|
|
1057
|
+
root through the `dataRoot` option or the workspace pointer instead, which
|
|
1058
|
+
both see. Started by a login item, the service asks the home, not the loader,
|
|
1059
|
+
for its workspace and log. `service status` and `stop`, the ticks `open` asks
|
|
1060
|
+
for, `service unit --remove` and `uninstall` locate the service the same way.
|
|
1061
|
+
When no project loaded (a restart while nothing is confirmed), the engine
|
|
1062
|
+
locates the workspace too, so each view published before says why nothing is
|
|
1063
|
+
published now instead of keeping the previous run's `current`. A service given
|
|
1064
|
+
a loader that answers a promise and no locator is still refused at start with
|
|
1065
|
+
`service-loader-not-synchronous`, and so is one whose locator answers a
|
|
1066
|
+
promise; a located value that names no folder refuses
|
|
1067
|
+
`service-locator-invalid`. The workspace pointer is under the home, so a home
|
|
1068
|
+
that is gone when the service starts leaves it no workspace to find
|
|
1069
|
+
(`service-workspace-not-prepared`).
|
|
1070
|
+
- **Cleanup with nothing confirmed.** `service unit --remove` and `uninstall`
|
|
1071
|
+
locate the existing protected workspace without a generation, and remember
|
|
1072
|
+
the machine's login-item decision as `off` there. They do not change the
|
|
1073
|
+
audience or confirm anything. Uninstall reports the actual kept workspace
|
|
1074
|
+
pointer under the personal home, and leaves its bytes, private state,
|
|
1075
|
+
generations and selection history in place.
|
|
1076
|
+
- **Following the history.** A loaded project is pinned to the record it was
|
|
1077
|
+
loaded under, and the engine observes that record and the place of the next
|
|
1078
|
+
one as configuration. A confirmation is therefore loaded at the next tick. A
|
|
1079
|
+
history cut short is seen at the next tick too, and a running service does
|
|
1080
|
+
not follow it back. Selections are only ever appended, so a history that
|
|
1081
|
+
ends at an earlier record than the service has read it ending at was cut by
|
|
1082
|
+
something other than a confirmation, and following it back could publish
|
|
1083
|
+
what nobody confirmed after the records removed: cut after a restore nobody
|
|
1084
|
+
confirmed, it would publish that restore. The service notes the highest
|
|
1085
|
+
record number at every read of the history's end (a load's first read, its
|
|
1086
|
+
read once the generation is loaded, the recheck at a full reconciliation,
|
|
1087
|
+
and a read made when a tick stops a view as `mixed-read` because the tick's
|
|
1088
|
+
settings changed or could not be read, once for views stopped one after
|
|
1089
|
+
another), whether or not the
|
|
1090
|
+
record's generation could be used, and whichever part of the service read
|
|
1091
|
+
it. A history that ends earlier refuses `selection-history-shortened` at a
|
|
1092
|
+
load and at a recheck until a fresh confirmation accepts it; at
|
|
1093
|
+
the read made when a tick stops a view, the view says `mixed-read` at that
|
|
1094
|
+
tick and the code at the next. A project already loaded is loaded again at
|
|
1095
|
+
the next tick once any part of the service has read the history ending at a
|
|
1096
|
+
later record than the one the project was loaded under, so a confirmation
|
|
1097
|
+
read elsewhere in the service and removed before the engine looked refuses at
|
|
1098
|
+
that tick; otherwise a project already loaded is held to this at its next
|
|
1099
|
+
recheck, at the latest the next full reconciliation, and until then it
|
|
1100
|
+
publishes nothing new under another record, and a change at its sources
|
|
1101
|
+
brings the recheck forward. A record added and removed between two of those
|
|
1102
|
+
reads was never read, and does not count: while a load of its own is under
|
|
1103
|
+
way, the plugin's status read compares the files that decide its views and
|
|
1104
|
+
reads no history, so a record it sees then only as a changed file is not
|
|
1105
|
+
noted. The views say why (`open` and
|
|
1106
|
+
`status --json` name the ways out), and the vault keeps what it last
|
|
1107
|
+
published.
|
|
1108
|
+
- **What ends that refusal.** Put the removed records back, or explicitly confirm
|
|
1109
|
+
the currently eligible generation through `selectPersonalGeneration` again.
|
|
1110
|
+
That existing confirmation operation is the accepting act; no new command is
|
|
1111
|
+
needed. One fresh confirmation accepts a shorter history even when its record
|
|
1112
|
+
number remains below the highest ever observed. Its unique confirmation
|
|
1113
|
+
identity distinguishes it from a previously observed record restored to the
|
|
1114
|
+
same position. Replaying a previously observed prefix refuses, including after
|
|
1115
|
+
a shorter history was accepted. Composition still decides whether the chosen
|
|
1116
|
+
generation is eligible.
|
|
1117
|
+
- **Continuity across starts.** The highest observed number, accepted head and
|
|
1118
|
+
previously observed record digests live in
|
|
1119
|
+
`state/maintenance/selection-continuity.json` under the existing private
|
|
1120
|
+
workspace. Reads validate its closed schema, workspace and personal-home
|
|
1121
|
+
identities; changed writes are serialized through the existing private-state
|
|
1122
|
+
lock, owner-only and atomic. State is bounded at 1 MiB and 8,192 observed record
|
|
1123
|
+
identities; exhausting the identity budget refuses `selection-continuity-capacity`.
|
|
1124
|
+
First use initializes from the current valid history, including historical v1
|
|
1125
|
+
records without a confirmation identity. Retain this private state: deleting
|
|
1126
|
+
all of it removes the evidence that distinguishes prior observation from a first
|
|
1127
|
+
installation. Damaged existing state is never treated as a new installation.
|
|
1128
|
+
- **What the history is checked for besides.** At every full reconciliation the
|
|
1129
|
+
history is read again, so a record before the last that no longer links, or
|
|
1130
|
+
a confirmation that landed before the engine first looked at the record,
|
|
1131
|
+
refuses with its code within the reconciliation interval. A confirmation
|
|
1132
|
+
during a tick changes an observed file: the view being prepared or published
|
|
1133
|
+
refuses `mixed-read` at its next wait, before its generation commits (one
|
|
1134
|
+
already committed stays), so do the views after it, and the next tick
|
|
1135
|
+
publishes under the new record. While the last load was refused, every tick
|
|
1136
|
+
loads again: with nothing confirmed the manifest, history and private continuity
|
|
1137
|
+
state are read without composition, and with a
|
|
1138
|
+
confirmed generation that no longer holds, one composition runs in a worker
|
|
1139
|
+
per tick.
|
|
1140
|
+
- **A narrowing.** When the newly confirmed generation drops a source (a
|
|
1141
|
+
repository withdrawn, a view narrowed), each view follows the publisher's
|
|
1142
|
+
rule for notes that leave a view; this binding adds no rule. At the view's
|
|
1143
|
+
next publication a generated note of the dropped source leaves the vault and
|
|
1144
|
+
its bytes are moved to private recovery. A note the person edited, once the
|
|
1145
|
+
engine has queued the edit, holds the whole view at the generation it last
|
|
1146
|
+
published (`held-for-your-edit`, `publication-withheld-for-your-edit`): the
|
|
1147
|
+
note is neither removed nor overwritten. A note edited during the
|
|
1148
|
+
publication itself stays in the vault (`retained-edit`).
|
|
1149
|
+
- **Who may see.** The existing machine audience setting owns this decision.
|
|
1150
|
+
For a personal binding, an undecided empty audience initializes to `only-you`
|
|
1151
|
+
with notes without a classification shown, recorded with `defaults` provenance.
|
|
1152
|
+
Existing explicit `only-you` lists and unclassified choices retain their exact
|
|
1153
|
+
meaning. An explicit `audience clear` stays empty across ticks and restarts.
|
|
1154
|
+
A nonempty custom setting refuses `personal-binding-owner-only` until
|
|
1155
|
+
`audience set me` or `audience clear` is recorded. Nothing is written into a
|
|
1156
|
+
generation or the personal overlay.
|
|
1157
|
+
- **Reading the history on the service's event loop.** The head is one
|
|
1158
|
+
directory listing and one bounded read per record. A record that is not a
|
|
1159
|
+
regular file (a FIFO, a device) refuses `selection-history-corrupt` without
|
|
1160
|
+
being waited on. A home that becomes unreadable while the engine holds a
|
|
1161
|
+
project (its permissions changed, not removed) fails the tick when the
|
|
1162
|
+
engine observes its files, as an unreadable configuration file does: nothing
|
|
1163
|
+
is published, and the service reports the failed tick.
|
|
1164
|
+
After a worker composes a generation, the caller still reads generation
|
|
1165
|
+
files, resolves the generation's project configuration and assembles the
|
|
1166
|
+
bound project on its own thread. Composition itself remains in the worker.
|
|
1167
|
+
|
|
987
1168
|
Measured once on 2,156 notes in three repositories, with 50 annotations and five
|
|
988
1169
|
saved views (six views in all). The production contributions were loaded, as
|
|
989
1170
|
the service loads them, so the proposal adapter was registered. The host's load
|
|
@@ -1011,16 +1192,133 @@ again. While an edit stays open and shared sources are quiet, the adapter
|
|
|
1011
1192
|
builds nothing more; under continuous change it builds once per tick until a
|
|
1012
1193
|
quiet tick.
|
|
1013
1194
|
|
|
1014
|
-
**What
|
|
1015
|
-
|
|
1016
|
-
|
|
1195
|
+
**What a service binding needed.** The first publication blocked the event
|
|
1196
|
+
loop far longer than the service's five-second health probe: about ten minutes
|
|
1197
|
+
here. That is the
|
|
1017
1198
|
publication path every project takes, not this route: an ordinary project of
|
|
1018
1199
|
450 notes, measured the same way, blocked as long as a bound one. Preparing six
|
|
1019
1200
|
views again blocked 4.5 s, under the probe. The proposal adapter's build of a
|
|
1020
1201
|
newly observed edit, without the engine's file cache, blocked 2.0 s, at a
|
|
1021
|
-
two-second target, as for an ordinary project. A service binding
|
|
1022
|
-
first publication to yield to the event loop
|
|
1023
|
-
|
|
1202
|
+
two-second target, as for an ordinary project. A service binding needed the
|
|
1203
|
+
first publication to yield to the event loop, which it now does (see "Since
|
|
1204
|
+
that measurement"), and a start that does not wait for its loader. The service
|
|
1205
|
+
resolves its workspace from the project its loader answers when it starts, and refuses a loader that answers a promise or any
|
|
1206
|
+
other thenable, such as `loadBoundProjectOffThread`, with
|
|
1207
|
+
`service-loader-not-synchronous`, before it reads anything from it, listens or
|
|
1208
|
+
records anything; a promise it was handed is let go, and its refusal, if it
|
|
1209
|
+
is refused, does not go unhandled. Started by a login item (`--startup`), the
|
|
1210
|
+
service asks its loader (or, under `--personal-home`, its locator) once for both
|
|
1211
|
+
the lookup of its workspace and its own start. One that answers a promise there
|
|
1212
|
+
is never handed to the workspace resolution: a promise whose `constructor`
|
|
1213
|
+
reads as this realm's `Promise` is let go without calling a `then` of its
|
|
1214
|
+
own, any other thenable (as a rule another realm's promise or a subclass's)
|
|
1215
|
+
is adopted once (its `then` is called once in all), the refusal is recorded
|
|
1216
|
+
in the workspace the unit names, when that exists, and the process ends with
|
|
1217
|
+
0, so the service manager does not start it again at once. One that throws
|
|
1218
|
+
there, whatever it throws (`undefined` too, a value with no prototype, or one
|
|
1219
|
+
whose `code` cannot be read), or answers a project whose `then` cannot be
|
|
1220
|
+
read, ends the start as a failure of the loader does anywhere else: it is
|
|
1221
|
+
logged, and what carries no code is a crash.
|
|
1222
|
+
A service bound through `--personal-home` is given a locator as well, and starts
|
|
1223
|
+
from it (see "A confirmed selection"). The plugin's status read allows for such
|
|
1224
|
+
a loader without waiting for it (see "The channel" in
|
|
1225
|
+
[obsidian-plugin.md](../reference/obsidian-plugin.md)).
|
|
1226
|
+
|
|
1227
|
+
**Since that measurement.** The engine prepares each view cooperatively and
|
|
1228
|
+
the publisher yields between complete units, so the service answers health and
|
|
1229
|
+
status while notes are emitted, staged and published. The first-tick figures
|
|
1230
|
+
in the table are from before that change and have not been taken again on that
|
|
1231
|
+
corpus. Building the canonical graph gives the event loop a turn between the
|
|
1232
|
+
Markdown sources it reads, hashes and parses (the census): a first tick reads
|
|
1233
|
+
every source, and on a heavily loaded host the build of one view of 10,000
|
|
1234
|
+
invented notes held the listener for 8 s in one stretch. The other sources
|
|
1235
|
+
(HTML files and the sidecars of PDF and Word documents) are read without a turn
|
|
1236
|
+
between them, and a project bound to a personal workspace is built by its own
|
|
1237
|
+
route in one stretch. Walking the directories, resolving the links and
|
|
1238
|
+
assembling the graph still run through.
|
|
1239
|
+
So do capturing the source snapshot, the publisher's restart recovery,
|
|
1240
|
+
validating a prepared view and planning its units, the exchange probe, writing
|
|
1241
|
+
and syncing the journal before the candidates move, and the look again at
|
|
1242
|
+
displaced files after the units (`recheckDisplacedFiles`).
|
|
1243
|
+
The read-back after a commit waits between
|
|
1244
|
+
notes: on a loaded host it took 16.8 s for one view of 10,000 invented notes
|
|
1245
|
+
and held the listener for all of it, and now a request is answered between two
|
|
1246
|
+
notes. Nothing is checked at those waits, since the generation is committed. A
|
|
1247
|
+
note edited in the vault while the read-back is under way is read as edited
|
|
1248
|
+
when the walk has not reached it, and is seen by the next tick when it has, as
|
|
1249
|
+
an edit made just after a read-back is. A stop whose grace runs out while a
|
|
1250
|
+
read-back waits ends the process after the commit and before the view is
|
|
1251
|
+
recorded as current, as a crash there does: the next start's first tick reads
|
|
1252
|
+
the committed generation back. Before a view is prepared, a tick looks at
|
|
1253
|
+
every view's notes and then at the sources, and both walks wait between files.
|
|
1254
|
+
They matter after a publication, when the watcher has named the notes it
|
|
1255
|
+
wrote, and at every full reconciliation, when every note and every source is
|
|
1256
|
+
hashed: on one view of 10,000 invented notes on a loaded host such a tick held
|
|
1257
|
+
the listener for 5.5 s when the walks ran through. Nothing is checked at their
|
|
1258
|
+
waits and nothing is written. Within Atelier only the engine commits a
|
|
1259
|
+
manifest or writes the pending edits, under the lock the tick holds, so the
|
|
1260
|
+
pending edits are read, compared and written in one stretch after the walk
|
|
1261
|
+
over the vault, and the bytes an edit keeps are read there. A file changed
|
|
1262
|
+
after its turn in a walk is seen by the next tick, by its stat hint or the
|
|
1263
|
+
watcher (one that keeps its size and times and draws no event, at the latest
|
|
1264
|
+
by the next full reconciliation), as one changed just after a walk that ran
|
|
1265
|
+
through is; when the tick builds the graph, the look again at the sources
|
|
1266
|
+
after the build refuses such a change as `mixed-read`. A source this tick
|
|
1267
|
+
observed, removed before the build read it (or its folder), is refused the
|
|
1268
|
+
same way. So is a selected source removed before a view's preparation, or the
|
|
1269
|
+
look again before its commit, read it: that view is refused, and the tick goes
|
|
1270
|
+
on to its other views. Either way the next tick reads everything again; a path
|
|
1271
|
+
that can never be read still fails the tick. A note gone from a
|
|
1272
|
+
vault, a source that changed, or a configuration file that changed is a change
|
|
1273
|
+
once: a tick that sees it and then fails without a typed reason (a file it
|
|
1274
|
+
cannot read, a disk that is full, a project loader that fails) has recorded it
|
|
1275
|
+
without acting on it. The next tick therefore starts as the first tick of a
|
|
1276
|
+
process does: it loads the project again and looks at every view, so a view
|
|
1277
|
+
whose note is missing reads `vault-note-missing` instead of staying `current`,
|
|
1278
|
+
and a changed source or view is published.
|
|
1279
|
+
The comparison of kept notes with their candidates reads asynchronously,
|
|
1280
|
+
sixteen at a time, and does not hold the listener. Observing pending edits
|
|
1281
|
+
and routing proposals wait between two edits and between two operations, so
|
|
1282
|
+
a burst of edits does not hold the listener for its whole length. One edit,
|
|
1283
|
+
or one operation, is still one stretch. The first edit an observation looks
|
|
1284
|
+
at that the object store does not hold yet builds the canonical graph in its
|
|
1285
|
+
stretch, and the first operation routed builds it again while the lock of
|
|
1286
|
+
its repository is held. An edit whose published note
|
|
1287
|
+
is not retained has its whole view prepared again in its stretch: once for a
|
|
1288
|
+
view and generation in an observation when the preparation succeeds, and for
|
|
1289
|
+
every such edit when it fails. A stop whose grace runs out while proposals
|
|
1290
|
+
are routed can end the process between two operations of a repository with
|
|
1291
|
+
that repository's proposal lock still held, as a crash can. A service in one
|
|
1292
|
+
of those stretches does not answer until it ends, and is `busy` if that
|
|
1293
|
+
outlasts the probe. A request can
|
|
1294
|
+
hold the listener too: the plugin's status read loads the project on the event
|
|
1295
|
+
loop at its first requests after the service starts (until two loads agree),
|
|
1296
|
+
when a configuration file changed, every two and a half minutes, again two to
|
|
1297
|
+
thirty seconds after a load that failed, and at every request while one of
|
|
1298
|
+
those files vouches for nothing or while its loads never agree. For a project
|
|
1299
|
+
named by `--project` none of those loads is taken off the loop. For a bound
|
|
1300
|
+
personal home they compose in a worker, as the engine's loads do, and the read
|
|
1301
|
+
starts each one on the loop by reading the selection history. A load that holds the loop
|
|
1302
|
+
for a second or more is logged (`status-project-loaded`), and so is a load at
|
|
1303
|
+
every request that names the files it started over (see "What the service
|
|
1304
|
+
shows of these loads" in [obsidian-plugin.md](../reference/obsidian-plugin.md)).
|
|
1305
|
+
|
|
1306
|
+
What the waits cost. The waits of observation and routing are taken at
|
|
1307
|
+
every boundary between two edits or two operations and before each
|
|
1308
|
+
repository, whatever time was spent; while routing describes its operations
|
|
1309
|
+
a wait comes after about 8 ms of work or 32 units. Nothing is checked around
|
|
1310
|
+
any of them. In preparation and publication a wait
|
|
1311
|
+
comes after about 8 ms of work or 32 units,
|
|
1312
|
+
whichever is first, and around each one the engine checks that the tick's
|
|
1313
|
+
settings still hold: it reads and hashes every configuration file it observes
|
|
1314
|
+
(the project configuration, the repository access file, local overlays and,
|
|
1315
|
+
for a bound personal workspace, its inputs), reads and validates the machine
|
|
1316
|
+
settings, and asks the eligibility revision. Measured on six configuration
|
|
1317
|
+
files, that check took about 0.2 ms, twice per wait; a first publication of
|
|
1318
|
+
200 invented notes waited 463 times, so roughly 0.2 s of a 64 s tick, on a
|
|
1319
|
+
host with a load average above 200 (indicative only). The selected sources
|
|
1320
|
+
cost one stat call each after the preparation and one before the commit; a
|
|
1321
|
+
note reused from the preparation cache is still not read.
|
|
1024
1322
|
|
|
1025
1323
|
## Known limits
|
|
1026
1324
|
|
|
@@ -1047,7 +1345,7 @@ test reported as a pass.
|
|
|
1047
1345
|
is admitted although the protocol depends on the view's undocumented
|
|
1048
1346
|
`lastSavedData` field, and the protocol cases have not been re-run on any
|
|
1049
1347
|
later release. See the "App capability floor" row of
|
|
1050
|
-
[obsidian-contract.md](obsidian-contract.md). An app that was not running
|
|
1348
|
+
[obsidian-contract.md](../reference/obsidian-contract.md). An app that was not running
|
|
1051
1349
|
when an adapter was qualified had no version to check, and neither had an
|
|
1052
1350
|
app that was not found. Such an answer is never reused, and the adapter
|
|
1053
1351
|
built on it does not coordinate with any app it then finds running, and
|
|
@@ -1087,6 +1385,50 @@ test reported as a pass.
|
|
|
1087
1385
|
first allocation or when a vault is made again. Every other check runs
|
|
1088
1386
|
again at both, and a vault made again, or published into, through a link on
|
|
1089
1387
|
the way is refused (`vault-allocation-moved`).
|
|
1388
|
+
- Private state after a wait: that the private state is outside every
|
|
1389
|
+
repository the workspace declares now is proven when a project loads, around
|
|
1390
|
+
each engine phase, inside the engine and selection locks, and after each wait
|
|
1391
|
+
the publisher makes for the app, its list of vaults, its comparison of kept
|
|
1392
|
+
notes or its quiet period. "Declares now" differs by binding. For a project
|
|
1393
|
+
bound to a personal home, each proof reads the home's manifest again, so a
|
|
1394
|
+
repository enrolled while a tick waits is seen at the next proof. For an
|
|
1395
|
+
ordinary project, each proof uses the repositories of the project as it was
|
|
1396
|
+
last loaded. A change to its configuration or overlay that declares a
|
|
1397
|
+
repository enclosing the data root is not seen until the project is loaded
|
|
1398
|
+
again, and the writes of the tick in flight (preserved edits, pending edits
|
|
1399
|
+
and freshness, say) can land under it meanwhile. The proof is not made again
|
|
1400
|
+
at every write, and it is not made at all for writes made outside the
|
|
1401
|
+
engine's phases and the publisher. Those are:
|
|
1402
|
+
- the built-in proposal store's writes for pending edits to shared notes
|
|
1403
|
+
(kept bytes, arbitration records and its queue) while it works through
|
|
1404
|
+
several of them;
|
|
1405
|
+
- everything the service process itself keeps: its log, service settings,
|
|
1406
|
+
runtime record (with its bearer), service-start lock, startup record,
|
|
1407
|
+
error record and login-item record, including those written after it waits
|
|
1408
|
+
for a free port, for its server to listen or for the service manager, and
|
|
1409
|
+
those a login item's start writes in the workspace the unit names when the
|
|
1410
|
+
project's loader fails;
|
|
1411
|
+
- the plugin channel's bearer and the plugin choices it records, including a
|
|
1412
|
+
first-use bearer minted while a view is prepared and the confirmation
|
|
1413
|
+
written when a plugin session opens;
|
|
1414
|
+
- lock cleanup when a proof fails: any private lock that is held, or whose
|
|
1415
|
+
ticket was just published, when its proof refuses is still released or
|
|
1416
|
+
withdrawn, so that ownership is never left behind. This covers the engine
|
|
1417
|
+
lock (a release record, or the withdrawal of a ticket published before
|
|
1418
|
+
the last check of its acquisition), the selection continuity lock and the
|
|
1419
|
+
publication locks, including a release retried at the next acquisition.
|
|
1420
|
+
Lock cleanup and removing staged candidates are the only changes the
|
|
1421
|
+
engine and the publisher make after one of their proofs refuses.
|
|
1422
|
+
|
|
1423
|
+
Each of these writers keeps its file inside the workspace's private state,
|
|
1424
|
+
but none checks the roots declared now. A manifest that comes to enclose the
|
|
1425
|
+
data root, or that cannot be read, while the service runs can therefore
|
|
1426
|
+
receive these writes. A refusal of the private state's own location
|
|
1427
|
+
(`managed-root-unproven`) stops the whole tick, whichever view it is found
|
|
1428
|
+
in: no later view is prepared, given a store or published, and no view is
|
|
1429
|
+
reported current after it. A view whose own vault is in a bad place is still
|
|
1430
|
+
refused alone. A single check of the declared
|
|
1431
|
+
roots at every private-state write is planned as a separate change.
|
|
1090
1432
|
- Replacing a vault during a publication: the allocated folder is checked
|
|
1091
1433
|
before the vault lock is taken and again once its folder is made, after the
|
|
1092
1434
|
app is asked about the vault, before each note and before the generation is
|
|
@@ -1111,7 +1453,7 @@ test reported as a pass.
|
|
|
1111
1453
|
`~/.config/obsidian`) on Linux. It is written only while the process table
|
|
1112
1454
|
shows, positively, that no Obsidian runs, only when Obsidian created it
|
|
1113
1455
|
before, and with a backup beside it; see
|
|
1114
|
-
[Obsidian's vault list](obsidian-contract.md#obsidians-vault-list). A
|
|
1456
|
+
[Obsidian's vault list](../reference/obsidian-contract.md#obsidians-vault-list). A
|
|
1115
1457
|
Flatpak or snap build keeps its list inside its sandbox and never reads that
|
|
1116
1458
|
file. Which build is in use is read from which vault list was written last
|
|
1117
1459
|
(every build rewrites its own when a vault window opens or closes), and only
|
|
@@ -1166,7 +1508,7 @@ test reported as a pass.
|
|
|
1166
1508
|
- The command-line tool (`obsidian-cli`) is a client of the app and is not
|
|
1167
1509
|
counted. An app packaged under another executable name, an app on
|
|
1168
1510
|
another machine and an app that starts after a reading are not seen; see
|
|
1169
|
-
"The path with no app" in [obsidian-contract.md](obsidian-contract.md).
|
|
1511
|
+
"The path with no app" in [obsidian-contract.md](../reference/obsidian-contract.md).
|
|
1170
1512
|
- The app-free path is live: before 0.2.0-alpha.10 the probe always found
|
|
1171
1513
|
Atelier's own service, so publication never took the path with no app.
|
|
1172
1514
|
From 0.2.0-alpha.10 it does, whenever the process table shows, positively,
|
|
@@ -1196,7 +1538,7 @@ test reported as a pass.
|
|
|
1196
1538
|
back and a deleted folder is not made again until the person turns it on
|
|
1197
1539
|
in Obsidian's settings or runs
|
|
1198
1540
|
`atelier obsidian plugin on --scope ID`. Plugin files are never removed from
|
|
1199
|
-
a vault. See [obsidian-plugin.md](obsidian-plugin.md).
|
|
1541
|
+
a vault. See [obsidian-plugin.md](../reference/obsidian-plugin.md).
|
|
1200
1542
|
- Login items: the tests run the launchd and systemd managers' own code
|
|
1201
1543
|
against stand-ins that answer as launchctl and systemctl do, and never
|
|
1202
1544
|
against a real session. What `launchctl print-disabled` says for an item
|
|
@@ -1227,3 +1569,8 @@ The test suite proves each oracle can fail:
|
|
|
1227
1569
|
- `createMaintenanceEngineForOracleTests` with an
|
|
1228
1570
|
`ENGINE_PRIMITIVES.isRetryDue` that never holds: a refused view waits for
|
|
1229
1571
|
the full reconciliation, and the retry oracle fails.
|
|
1572
|
+
- `createMaintenanceEngineForOracleTests` with
|
|
1573
|
+
`ENGINE_PRIMITIVES.rechecksEveryViewAfterFailure` false: a note removed, a
|
|
1574
|
+
source changed or a view added in a tick that then fails without a typed
|
|
1575
|
+
reason is lost, the view stays `current` with the note gone or the old
|
|
1576
|
+
content, the new view is never published, and the oracle fails.
|