@mnstry/atelier 0.2.0-alpha.6 → 0.2.0-alpha.8
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 +176 -0
- package/README.md +59 -15
- package/SECURITY.md +6 -1
- package/contracts/atelier-adoption-policy.v1.schema.json +49 -0
- package/contracts/atelier-coauthor.v1.schema.json +163 -0
- package/contracts/atelier-decision-request.v1.schema.json +476 -0
- package/contracts/atelier-decision-result.v1.schema.json +500 -0
- package/contracts/atelier-guide.v1.schema.json +227 -0
- package/contracts/atelier-intake.v1.schema.json +151 -0
- package/contracts/atelier-migration.v2.schema.json +61 -0
- package/contracts/atelier-obsidian-acceptance-receipt.v1.schema.json +211 -0
- package/contracts/atelier-obsidian-apply-policy.v1.schema.json +298 -0
- package/contracts/atelier-obsidian-corpus-profile.v1.schema.json +98 -0
- package/contracts/atelier-obsidian-edit-operation.v1.schema.json +138 -0
- package/contracts/atelier-obsidian-ext-settings.v1.schema.json +287 -0
- package/contracts/atelier-obsidian-generation-manifest.v1.schema.json +353 -0
- package/contracts/atelier-obsidian-proposal-receipt.v1.schema.json +110 -0
- package/contracts/atelier-obsidian-publication-journal.v1.schema.json +167 -0
- package/contracts/atelier-obsidian-scope.v1.schema.json +264 -0
- package/contracts/atelier-obsidian-service-state.v1.schema.json +149 -0
- package/contracts/atelier-obsidian-source-snapshot.v1.schema.json +179 -0
- package/contracts/atelier-pane-presentation.v1.schema.json +76 -0
- package/contracts/atelier-presentation.v1.schema.json +1293 -0
- package/contracts/atelier-review.v1.schema.json +1601 -0
- package/contracts/atelier-skill-steward.v1.schema.json +692 -0
- package/contracts/atelier-upgrade-plan.v2.schema.json +398 -0
- package/contracts/atelier-upgrade-receipt.v1.schema.json +99 -0
- package/contracts/atelier-vault-publication.v1.schema.json +58 -0
- package/docs/assurance-controls.md +9 -1
- package/docs/atelier-sync.md +5 -4
- package/docs/blocks/claims.md +15 -10
- package/docs/blocks/will-not-do.md +4 -1
- package/docs/coauthor-session.md +57 -0
- package/docs/connected-composition.md +75 -0
- package/docs/decisions.md +167 -0
- package/docs/exact-upgrades.md +159 -0
- package/docs/extension-pack-lifecycle.md +33 -0
- package/docs/guided-upgrades.md +99 -0
- package/docs/install.md +65 -9
- package/docs/intake-and-guides.md +65 -0
- package/docs/integration-and-review-plan.md +409 -0
- package/docs/integration-contract-decisions.md +22 -0
- package/docs/local-review.md +84 -0
- package/docs/local-services.md +227 -0
- package/docs/local-state.md +107 -0
- package/docs/obsidian-contract.md +687 -0
- package/docs/obsidian.md +387 -0
- package/docs/portable-presentation.md +328 -0
- package/docs/presentation-consumer-boundaries.md +75 -0
- package/docs/presentation-review-disposition.md +47 -0
- package/docs/project-command-inventory.md +38 -0
- package/docs/project-options.md +53 -0
- package/docs/release-engineering.md +88 -0
- package/docs/review-portability.md +55 -0
- package/docs/skill-steward.md +156 -0
- package/docs/upgrade.md +55 -2
- package/docs/vault-service.md +292 -0
- package/fixtures/atelier-coauthor/invalid/authority.v1.json +5 -0
- package/fixtures/atelier-coauthor/valid/config.v1.json +12 -0
- package/fixtures/atelier-guide/invalid/authority.v1.json +11 -0
- package/fixtures/atelier-guide/valid/capability.v1.json +10 -0
- package/fixtures/atelier-guide/valid/consent.v1.json +11 -0
- package/fixtures/atelier-guide/valid/engagement.v1.json +7 -0
- package/fixtures/atelier-guide/valid/offer.v1.json +10 -0
- package/fixtures/atelier-intake/invalid/authority.v1.json +9 -0
- package/fixtures/atelier-intake/valid/attempt.v1.json +8 -0
- package/fixtures/atelier-intake/valid/completion.v1.json +9 -0
- package/fixtures/atelier-intake/valid/source.v1.json +7 -0
- package/fixtures/atelier-review/invalid/authenticated-identity.v1.json +22 -0
- package/fixtures/atelier-review/valid/bound.v1.json +229 -0
- package/fixtures/atelier-review/valid/bundle.v1.json +267 -0
- package/fixtures/atelier-review/valid/contribution.v1.json +22 -0
- package/fixtures/atelier-review/valid/lifecycle.v1.json +14 -0
- package/fixtures/atelier-skill-steward/audit/invalid/source-mutation.v1.json +26 -0
- package/fixtures/atelier-skill-steward/audit/valid/clean.v1.json +26 -0
- package/fixtures/atelier-skill-steward/candidates/invalid/workflow-key.v1.json +37 -0
- package/fixtures/atelier-skill-steward/candidates/valid/create.v1.json +37 -0
- package/fixtures/atelier-skill-steward/lock/invalid/bad-digest.v1.json +18 -0
- package/fixtures/atelier-skill-steward/lock/valid/installed.v1.json +23 -0
- package/fixtures/atelier-skill-steward/plan/invalid/delete-action.v1.json +33 -0
- package/fixtures/atelier-skill-steward/plan/valid/add.v1.json +33 -0
- package/fixtures/atelier-upgrade-transaction/adoption-policy/invalid/example.json +12 -0
- package/fixtures/atelier-upgrade-transaction/adoption-policy/valid/example.json +11 -0
- package/fixtures/atelier-upgrade-transaction/migration/invalid/example.json +20 -0
- package/fixtures/atelier-upgrade-transaction/migration/valid/example.json +19 -0
- package/fixtures/atelier-upgrade-transaction/upgrade-plan/invalid/example.json +58 -0
- package/fixtures/atelier-upgrade-transaction/upgrade-plan/valid/example.json +57 -0
- package/fixtures/atelier-upgrade-transaction/upgrade-receipt/invalid/example.json +15 -0
- package/fixtures/atelier-upgrade-transaction/upgrade-receipt/valid/example.json +14 -0
- package/fixtures/atelier-vault-publication/invalid/publication.json +5 -0
- package/fixtures/atelier-vault-publication/valid/publication.json +11 -0
- package/fixtures/decisions/request/invalid/unknown-authority.v1.json +61 -0
- package/fixtures/decisions/request/valid/triage.v1.json +60 -0
- package/fixtures/decisions/result/invalid/execution-authority.v1.json +50 -0
- package/fixtures/decisions/result/valid/abstained.v1.json +23 -0
- package/fixtures/decisions/result/valid/assessed.v1.json +50 -0
- package/fixtures/obsidian/acceptance/ap05-extra-notes.json +14 -0
- package/fixtures/obsidian/acceptance/receipts/G07.valid.v1.json +63 -0
- package/fixtures/obsidian/acceptance/receipts/G13.valid.v1.json +69 -0
- package/fixtures/obsidian/acceptance/receipts/G14.valid.v1.json +62 -0
- package/fixtures/obsidian/acceptance/receipts/G15.valid.v1.json +56 -0
- package/fixtures/obsidian/acceptance/receipts/G16.valid.v1.json +73 -0
- package/fixtures/obsidian/acceptance/receipts/G17.valid.v1.json +75 -0
- package/fixtures/obsidian/acceptance/receipts/G18.valid.v1.json +64 -0
- package/fixtures/obsidian/acceptance/service-sentinels.json +10 -0
- package/fixtures/obsidian/contracts/acceptance-receipt/invalid/duplicate-evidence-name.v1.json +39 -0
- package/fixtures/obsidian/contracts/acceptance-receipt/invalid/evidence-by-absolute-path.v1.json +34 -0
- package/fixtures/obsidian/contracts/acceptance-receipt/invalid/missing-candidate-tree.v1.json +33 -0
- package/fixtures/obsidian/contracts/acceptance-receipt/invalid/no-evidence.v1.json +28 -0
- package/fixtures/obsidian/contracts/acceptance-receipt/invalid/unknown-outcome.v1.json +34 -0
- package/fixtures/obsidian/contracts/acceptance-receipt/invalid/unknown-top-level-field.v1.json +35 -0
- package/fixtures/obsidian/contracts/acceptance-receipt/valid/node-gate.v1.json +34 -0
- package/fixtures/obsidian/contracts/apply-policy/invalid/automatic-without-edit-class.v1.json +27 -0
- package/fixtures/obsidian/contracts/apply-policy/invalid/conflict-overwrite.v1.json +29 -0
- package/fixtures/obsidian/contracts/apply-policy/invalid/missing-policy-digest.v1.json +28 -0
- package/fixtures/obsidian/contracts/apply-policy/invalid/unbounded-batch.v1.json +29 -0
- package/fixtures/obsidian/contracts/apply-policy/invalid/unimplemented-edit-class.v1.json +30 -0
- package/fixtures/obsidian/contracts/apply-policy/invalid/unknown-mode.v1.json +29 -0
- package/fixtures/obsidian/contracts/apply-policy/invalid/unknown-selector-operator.v1.json +22 -0
- package/fixtures/obsidian/contracts/apply-policy/invalid/unknown-top-level-field.v1.json +30 -0
- package/fixtures/obsidian/contracts/apply-policy/valid/automatic-scoped.v1.json +29 -0
- package/fixtures/obsidian/contracts/apply-policy/valid/manual-default.v1.json +20 -0
- package/fixtures/obsidian/contracts/corpus-profile/invalid/absolute-path-in-ext.v1.json +30 -0
- package/fixtures/obsidian/contracts/corpus-profile/invalid/absolute-repository-root.v1.json +27 -0
- package/fixtures/obsidian/contracts/corpus-profile/invalid/duplicate-repository-id.v1.json +27 -0
- package/fixtures/obsidian/contracts/corpus-profile/invalid/overlapping-managed-roots.v1.json +27 -0
- package/fixtures/obsidian/contracts/corpus-profile/invalid/unknown-enrollment.v1.json +27 -0
- package/fixtures/obsidian/contracts/corpus-profile/invalid/unknown-top-level-field.v1.json +28 -0
- package/fixtures/obsidian/contracts/corpus-profile/valid/three-repositories.v1.json +27 -0
- package/fixtures/obsidian/contracts/edit-operation/invalid/absolute-recovery-ref.v1.json +21 -0
- package/fixtures/obsidian/contracts/edit-operation/invalid/inline-observed-bytes.v1.json +22 -0
- package/fixtures/obsidian/contracts/edit-operation/invalid/missing-base-digest.v1.json +20 -0
- package/fixtures/obsidian/contracts/edit-operation/invalid/short-idempotency-key.v1.json +21 -0
- package/fixtures/obsidian/contracts/edit-operation/invalid/unknown-kind.v1.json +21 -0
- package/fixtures/obsidian/contracts/edit-operation/valid/pending-body-replacement.v1.json +21 -0
- package/fixtures/obsidian/contracts/ext-settings/invalid/absolute-path-prefix.v1.json +28 -0
- package/fixtures/obsidian/contracts/ext-settings/invalid/apply-policy-in-portable-settings.v1.json +30 -0
- package/fixtures/obsidian/contracts/ext-settings/invalid/duplicate-scope-id.v1.json +27 -0
- package/fixtures/obsidian/contracts/ext-settings/invalid/machine-local-vault-path.v1.json +28 -0
- package/fixtures/obsidian/contracts/ext-settings/invalid/service-port-in-portable-settings.v1.json +28 -0
- package/fixtures/obsidian/contracts/ext-settings/invalid/unknown-default-scope.v1.json +27 -0
- package/fixtures/obsidian/contracts/ext-settings/valid/disabled.v1.json +5 -0
- package/fixtures/obsidian/contracts/ext-settings/valid/enabled-with-scopes.v1.json +27 -0
- package/fixtures/obsidian/contracts/generation-manifest/invalid/absolute-note-path.v1.json +114 -0
- package/fixtures/obsidian/contracts/generation-manifest/invalid/complete-with-unwritten-notes.v1.json +114 -0
- package/fixtures/obsidian/contracts/generation-manifest/invalid/derived-link-claimed-declared.v1.json +114 -0
- package/fixtures/obsidian/contracts/generation-manifest/invalid/duplicate-note-identity.v1.json +114 -0
- package/fixtures/obsidian/contracts/generation-manifest/invalid/in-scope-endpoint-missing.v1.json +114 -0
- package/fixtures/obsidian/contracts/generation-manifest/invalid/title-only-note-path.v1.json +114 -0
- package/fixtures/obsidian/contracts/generation-manifest/invalid/unknown-note-field.v1.json +115 -0
- package/fixtures/obsidian/contracts/generation-manifest/invalid/unknown-relation-type.v1.json +114 -0
- package/fixtures/obsidian/contracts/generation-manifest/invalid/withheld-endpoint.v1.json +114 -0
- package/fixtures/obsidian/contracts/generation-manifest/valid/two-notes.v1.json +114 -0
- package/fixtures/obsidian/contracts/oracles/scope-cases.json +412 -0
- package/fixtures/obsidian/contracts/proposal-receipt/invalid/accepted-without-proposal-id.v1.json +12 -0
- package/fixtures/obsidian/contracts/proposal-receipt/invalid/missing-adapter-operation-id.v1.json +11 -0
- package/fixtures/obsidian/contracts/proposal-receipt/invalid/unknown-backpressure-outcome.v1.json +12 -0
- package/fixtures/obsidian/contracts/proposal-receipt/invalid/unknown-top-level-field.v1.json +13 -0
- package/fixtures/obsidian/contracts/proposal-receipt/valid/accepted-new.v1.json +12 -0
- package/fixtures/obsidian/contracts/proposal-receipt/valid/deferred.v1.json +12 -0
- package/fixtures/obsidian/contracts/publication-journal/invalid/absolute-recovery-ref.v1.json +47 -0
- package/fixtures/obsidian/contracts/publication-journal/invalid/duplicate-sequence.v1.json +47 -0
- package/fixtures/obsidian/contracts/publication-journal/invalid/empty-protocol-id.v1.json +47 -0
- package/fixtures/obsidian/contracts/publication-journal/invalid/missing-protocol-id.v1.json +46 -0
- package/fixtures/obsidian/contracts/publication-journal/invalid/unknown-entry-field.v1.json +48 -0
- package/fixtures/obsidian/contracts/publication-journal/invalid/unknown-state.v1.json +47 -0
- package/fixtures/obsidian/contracts/publication-journal/valid/committed.v1.json +47 -0
- package/fixtures/obsidian/contracts/publication-journal/valid/updating-after-restart.v1.json +22 -0
- package/fixtures/obsidian/contracts/scope/invalid/absolute-path-prefix.v1.json +15 -0
- package/fixtures/obsidian/contracts/scope/invalid/duplicate-ids.v1.json +18 -0
- package/fixtures/obsidian/contracts/scope/invalid/expansion-without-node-budget.v1.json +40 -0
- package/fixtures/obsidian/contracts/scope/invalid/full-mode-with-subset.v1.json +8 -0
- package/fixtures/obsidian/contracts/scope/invalid/unknown-mode.v1.json +41 -0
- package/fixtures/obsidian/contracts/scope/invalid/unknown-selector-key.v1.json +15 -0
- package/fixtures/obsidian/contracts/scope/invalid/unknown-selector-operator.v1.json +14 -0
- package/fixtures/obsidian/contracts/scope/invalid/unknown-top-level-field.v1.json +42 -0
- package/fixtures/obsidian/contracts/scope/valid/explicit-empty.v1.json +8 -0
- package/fixtures/obsidian/contracts/scope/valid/focus.v1.json +11 -0
- package/fixtures/obsidian/contracts/scope/valid/full.v1.json +8 -0
- package/fixtures/obsidian/contracts/scope/valid/scoped-set-expression.v1.json +41 -0
- package/fixtures/obsidian/contracts/service-state/invalid/hostname-instead-of-literal-loopback.v1.json +23 -0
- package/fixtures/obsidian/contracts/service-state/invalid/missing-consent.v1.json +18 -0
- package/fixtures/obsidian/contracts/service-state/invalid/privileged-port.v1.json +23 -0
- package/fixtures/obsidian/contracts/service-state/invalid/unknown-top-level-field.v1.json +24 -0
- package/fixtures/obsidian/contracts/service-state/invalid/wildcard-bind.v1.json +23 -0
- package/fixtures/obsidian/contracts/service-state/valid/healthy.v1.json +23 -0
- package/fixtures/obsidian/contracts/source-snapshot/invalid/absolute-file-path.v1.json +48 -0
- package/fixtures/obsidian/contracts/source-snapshot/invalid/duplicate-repository-id.v1.json +48 -0
- package/fixtures/obsidian/contracts/source-snapshot/invalid/mixed-read.v1.json +48 -0
- package/fixtures/obsidian/contracts/source-snapshot/invalid/parent-traversal-path.v1.json +48 -0
- package/fixtures/obsidian/contracts/source-snapshot/invalid/unknown-file-field.v1.json +49 -0
- package/fixtures/obsidian/contracts/source-snapshot/valid/two-repositories.v1.json +48 -0
- package/fixtures/obsidian/edits/workspace.json +65 -0
- package/fixtures/obsidian/materialization/expected-full.json +99 -0
- package/fixtures/obsidian/materialization/expected-scoped.json +39 -0
- package/fixtures/obsidian/materialization/workspace.json +54 -0
- package/fixtures/obsidian/proposals/expected-shapes.json +11 -0
- package/fixtures/ui/presentation/pane.v1.json +7 -0
- package/fixtures/ui/presentation/reference.v1.json +293 -0
- package/package.json +57 -6
- package/skills/claude/atelier-guided-coauthor/SKILL.md +49 -0
- package/skills/claude/atelier-guided-upgrade/SKILL.md +97 -0
- package/skills/claude/atelier-open/SKILL.md +5 -0
- package/skills/claude/atelier-skill-steward/SKILL.md +62 -0
- package/skills/claude/mnstry-readiness/SKILL.md +5 -0
- package/skills/codex/atelier-guided-coauthor/SKILL.md +49 -0
- package/skills/codex/atelier-guided-upgrade/SKILL.md +97 -0
- package/skills/codex/atelier-open/SKILL.md +5 -0
- package/skills/codex/atelier-skill-steward/SKILL.md +62 -0
- package/skills/codex/mnstry-readiness/SKILL.md +5 -0
- package/src/access/preview-enforcer.mjs +84 -0
- package/src/boundary/policy.mjs +57 -25
- package/src/cli/project-options.mjs +58 -0
- package/src/cli/run.mjs +43 -3
- package/src/coauthor/session.mjs +161 -0
- package/src/coauthor/store.mjs +173 -0
- package/src/collaboration/event-ledger.mjs +16 -33
- package/src/collaboration/inspection-bundle.mjs +223 -0
- package/src/collaboration/review-contracts.mjs +25 -0
- package/src/collaboration/review-store.mjs +305 -0
- package/src/commands/coauthor.mjs +26 -0
- package/src/commands/config.mjs +6 -1
- package/src/commands/extension-pack.mjs +15 -8
- package/src/commands/init.mjs +44 -5
- package/src/commands/obsidian.mjs +368 -0
- package/src/commands/review.mjs +147 -0
- package/src/commands/setup.mjs +51 -14
- package/src/commands/skills.mjs +199 -0
- package/src/commands/sync.mjs +8 -1
- package/src/composition/registry.mjs +27 -0
- package/src/composition/wire.mjs +122 -0
- package/src/contracts/corpus.mjs +29 -0
- package/src/decisions/contracts.d.mts +96 -0
- package/src/decisions/contracts.mjs +321 -0
- package/src/disclosure/content-scan.mjs +13 -0
- package/src/export/atelier-export-contract.mjs +16 -1
- package/src/extension-packs/lifecycle.mjs +154 -0
- package/src/graph/graph.mjs +64 -2
- package/src/graph/knowledge-graph.mjs +548 -24
- package/src/guides/contracts.mjs +54 -0
- package/src/intake/store.mjs +119 -0
- package/src/preview/channel.mjs +89 -0
- package/src/project/config.mjs +26 -27
- package/src/project/durable-state.mjs +161 -0
- package/src/project/file-class.mjs +166 -0
- package/src/project/private-state.mjs +11 -1
- package/src/projection/obsidian/contracts.mjs +571 -0
- package/src/projection/obsidian/edits/align.mjs +169 -0
- package/src/projection/obsidian/edits/apply.mjs +889 -0
- package/src/projection/obsidian/edits/arbitrate.mjs +414 -0
- package/src/projection/obsidian/edits/contribution.mjs +108 -0
- package/src/projection/obsidian/edits/index.mjs +19 -0
- package/src/projection/obsidian/edits/object-identity.mjs +61 -0
- package/src/projection/obsidian/edits/object-store.mjs +517 -0
- package/src/projection/obsidian/edits/observe.mjs +123 -0
- package/src/projection/obsidian/edits/policy.mjs +123 -0
- package/src/projection/obsidian/edits/regions.mjs +648 -0
- package/src/projection/obsidian/materialize/byte-lens.mjs +98 -0
- package/src/projection/obsidian/materialize/index.mjs +7 -0
- package/src/projection/obsidian/materialize/path-registry.mjs +105 -0
- package/src/projection/obsidian/materialize/prepare-view.mjs +746 -0
- package/src/projection/obsidian/materialize/settings.mjs +57 -0
- package/src/projection/obsidian/materialize/stage.mjs +27 -0
- package/src/projection/obsidian/proposals/adapter.mjs +572 -0
- package/src/projection/obsidian/proposals/backpressure.mjs +113 -0
- package/src/projection/obsidian/proposals/contribution.mjs +55 -0
- package/src/projection/obsidian/proposals/index.mjs +23 -0
- package/src/projection/obsidian/proposals/observation.mjs +216 -0
- package/src/projection/obsidian/proposals/queue.mjs +277 -0
- package/src/projection/obsidian/proposals/router.mjs +168 -0
- package/src/projection/obsidian/publication/bridge-script.mjs +266 -0
- package/src/projection/obsidian/publication/exchange.mjs +117 -0
- package/src/projection/obsidian/publication/index.mjs +5 -0
- package/src/projection/obsidian/publication/publisher.mjs +588 -0
- package/src/projection/obsidian/publication/test-seam.mjs +16 -0
- package/src/projection/obsidian/publication/transport.mjs +139 -0
- package/src/projection/obsidian/recovery/index.mjs +6 -0
- package/src/projection/obsidian/recovery/journal.mjs +134 -0
- package/src/projection/obsidian/recovery/late-writer.mjs +46 -0
- package/src/projection/obsidian/recovery/restart.mjs +316 -0
- package/src/projection/obsidian/recovery/store.mjs +234 -0
- package/src/projection/obsidian/selection-ui/conflict-view.mjs +91 -0
- package/src/projection/obsidian/selection-ui/contribution.mjs +141 -0
- package/src/projection/obsidian/selection-ui/focus.mjs +82 -0
- package/src/projection/obsidian/selection-ui/index.mjs +12 -0
- package/src/projection/obsidian/selection-ui/policy-setup.mjs +107 -0
- package/src/projection/obsidian/selection-ui/receipt.mjs +173 -0
- package/src/projection/obsidian/selection-ui/selection-state.mjs +122 -0
- package/src/projection/obsidian/selection-ui/selection.mjs +109 -0
- package/src/projection/project.mjs +28 -19
- package/src/readiness-protocols/evidence.mjs +282 -0
- package/src/readiness-protocols/runtime.mjs +4 -3
- package/src/readiness-protocols/source-read.mjs +39 -0
- package/src/runtime/obsidian/app-capability.mjs +110 -0
- package/src/runtime/obsidian/app-production-seams.mjs +96 -0
- package/src/runtime/obsidian/contributions/proposal-adapter.mjs +4 -0
- package/src/runtime/obsidian/contributions/selection-ui.mjs +4 -0
- package/src/runtime/obsidian/contributions/source-apply.mjs +4 -0
- package/src/runtime/obsidian/contributions.mjs +27 -0
- package/src/runtime/obsidian/documents.mjs +37 -0
- package/src/runtime/obsidian/enablement.mjs +53 -0
- package/src/runtime/obsidian/engine.mjs +532 -0
- package/src/runtime/obsidian/errors.mjs +14 -0
- package/src/runtime/obsidian/extension-points.mjs +103 -0
- package/src/runtime/obsidian/index.mjs +34 -0
- package/src/runtime/obsidian/lifecycle.mjs +258 -0
- package/src/runtime/obsidian/machine-settings.mjs +260 -0
- package/src/runtime/obsidian/observation.mjs +158 -0
- package/src/runtime/obsidian/opening.mjs +243 -0
- package/src/runtime/obsidian/pending-edits.mjs +141 -0
- package/src/runtime/obsidian/pipeline.mjs +122 -0
- package/src/runtime/obsidian/private-lock.mjs +156 -0
- package/src/runtime/obsidian/process-identity.mjs +58 -0
- package/src/runtime/obsidian/service-client.mjs +66 -0
- package/src/runtime/obsidian/service-main.mjs +89 -0
- package/src/runtime/obsidian/service-record.mjs +169 -0
- package/src/runtime/obsidian/service-server.mjs +121 -0
- package/src/runtime/obsidian/service.mjs +216 -0
- package/src/runtime/obsidian/startup-adapters.mjs +87 -0
- package/src/runtime/obsidian/state-store.mjs +180 -0
- package/src/runtime/obsidian/sync-notice.mjs +33 -0
- package/src/runtime/obsidian/tick-loop.mjs +84 -0
- package/src/runtime/obsidian/watchers.mjs +36 -0
- package/src/runtime/supervisor.mjs +16 -1
- package/src/server/local-sidecar.mjs +44 -0
- package/src/server/server.mjs +1 -0
- package/src/skills/steward.mjs +780 -0
- package/src/ui/presentation/browser.mjs +278 -0
- package/src/ui/presentation/contract.mjs +116 -0
- package/src/ui/presentation/index.mjs +7 -0
- package/src/ui/presentation/native.mjs +153 -0
- package/src/ui/presentation/proof.mjs +57 -0
- package/src/ui/presentation/schema-check.mjs +30 -0
- package/src/ui/presentation/schema.generated.mjs +1371 -0
- package/src/ui/presentation/state.mjs +43 -0
- package/src/ui/presentation/styles.mjs +67 -0
- package/src/ui/presentation/tokens.mjs +74 -0
- package/src/ui/presentation/web.mjs +85 -0
- package/src/ui/review-page.mjs +32 -0
- package/src/upgrade/explanation.mjs +33 -0
- package/src/upgrade/provenance.mjs +338 -0
- package/src/upgrade/transaction-files.mjs +103 -0
- package/src/upgrade/transaction.mjs +475 -0
- package/src/upgrade/upgrade.mjs +63 -28
- package/src/vault/hosts.mjs +21 -0
- package/src/vault/identity.mjs +19 -0
- package/src/vault/index.mjs +7 -0
- package/src/vault/interface.mjs +11 -0
- package/src/vault/metadata.mjs +31 -0
- package/src/vault/privacy.mjs +148 -0
- package/src/vault/probe.mjs +89 -0
- package/src/vault/service.mjs +131 -0
- package/src/vault/source.mjs +45 -0
- package/src/vault/storage.mjs +23 -0
- package/templates/distribution-workspace/.claude/launch.json +6 -2
- package/templates/distribution-workspace/gitignore +1 -0
- package/templates/distribution-workspace/project/README.md +2 -2
- package/templates/external-project-workspace/README.md +45 -0
- package/templates/external-project-workspace/answers.example.json +4 -0
- package/templates/external-project-workspace/atelier.project.json +40 -0
- package/templates/external-project-workspace/boundary-policy.v1.json +60 -0
- package/templates/external-project-workspace/gitignore +8 -0
- package/templates/external-project-workspace/pack-lifecycle.json +14 -0
- package/templates/external-project-workspace/packs/protocols/contract-gate.v1.json +109 -0
- package/templates/external-project-workspace/packs/sample-pack.v1.json +48 -0
- package/templates/external-project-workspace/repo-access.v1.json +9 -0
- package/templates/external-project-workspace/source/README.md +11 -0
- package/templates/launch.json +6 -2
- package/templates/private-domain-workspace/.claude/launch.json +6 -2
- package/templates/private-domain-workspace/domain/README.md +2 -2
- package/templates/private-domain-workspace/gitignore +1 -0
- package/templates/shared-project-workspace/.claude/launch.json +6 -2
- package/templates/shared-project-workspace/gitignore +1 -0
- package/templates/shared-project-workspace/project/README.md +2 -2
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { ObsidianContractRefusal } from '../contracts.mjs'
|
|
3
|
+
|
|
4
|
+
// Raw byte lens: where the front matter and the body of one Markdown source
|
|
5
|
+
// sit, as byte offsets into the Buffer exactly as read. Nothing is decoded into
|
|
6
|
+
// a working string, no newline is normalized and no byte is dropped. A source
|
|
7
|
+
// the lens cannot delimit with certainty refuses; it is never guessed at.
|
|
8
|
+
|
|
9
|
+
const UTF8_BOM = Buffer.from([0xef, 0xbb, 0xbf])
|
|
10
|
+
const LF = 0x0a
|
|
11
|
+
const CR = 0x0d
|
|
12
|
+
const DASH = 0x2d
|
|
13
|
+
const SPACE = 0x20
|
|
14
|
+
const TAB = 0x09
|
|
15
|
+
|
|
16
|
+
export function refuse(code, message, detail = {}) {
|
|
17
|
+
throw new ObsidianContractRefusal(code, message, detail)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function sha256Digest(bytes) {
|
|
21
|
+
return `sha256:${createHash('sha256').update(bytes).digest('hex')}`
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function assertStrictUtf8(buffer, detail = {}) {
|
|
25
|
+
if (!Buffer.isBuffer(buffer)) refuse('invalid-source', 'a source must be read as a Buffer', detail)
|
|
26
|
+
try {
|
|
27
|
+
new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(buffer)
|
|
28
|
+
} catch {
|
|
29
|
+
refuse('malformed-utf8', 'source is not valid UTF-8; it is not emitted', detail)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// One line starting at `offset`: [contentEnd, nextOffset, eol]. `eol` is
|
|
34
|
+
// 'lf', 'crlf' or 'none' (end of buffer).
|
|
35
|
+
function lineAt(buffer, offset) {
|
|
36
|
+
const newline = buffer.indexOf(LF, offset)
|
|
37
|
+
if (newline === -1) return { contentEnd: buffer.length, next: buffer.length, eol: 'none' }
|
|
38
|
+
const crlf = newline > offset && buffer[newline - 1] === CR
|
|
39
|
+
return { contentEnd: crlf ? newline - 1 : newline, next: newline + 1, eol: crlf ? 'crlf' : 'lf' }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isDelimiterLine(buffer, start, contentEnd) {
|
|
43
|
+
if (contentEnd - start < 3) return null
|
|
44
|
+
for (let index = start; index < start + 3; index += 1) if (buffer[index] !== DASH) return null
|
|
45
|
+
let trailing = 0
|
|
46
|
+
for (let index = start + 3; index < contentEnd; index += 1) {
|
|
47
|
+
if (buffer[index] !== SPACE && buffer[index] !== TAB) return null
|
|
48
|
+
trailing += 1
|
|
49
|
+
}
|
|
50
|
+
return { trailing }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function finalNewlineState(buffer) {
|
|
54
|
+
if (buffer.length === 0 || buffer[buffer.length - 1] !== LF) return 'none'
|
|
55
|
+
return buffer.length > 1 && buffer[buffer.length - 2] === CR ? 'crlf' : 'lf'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Returns { bom, frontmatter, body, finalNewline } with half-open byte ranges.
|
|
59
|
+
// `bom` and `frontmatter` are null when absent.
|
|
60
|
+
export function readMarkdownLens(buffer, detail = {}) {
|
|
61
|
+
assertStrictUtf8(buffer, detail)
|
|
62
|
+
const hasBom = buffer.length >= 3 && buffer.subarray(0, 3).equals(UTF8_BOM)
|
|
63
|
+
const start = hasBom ? 3 : 0
|
|
64
|
+
const bom = hasBom ? { start: 0, end: 3 } : null
|
|
65
|
+
const whole = { bom, frontmatter: null, body: { start, end: buffer.length }, finalNewline: finalNewlineState(buffer) }
|
|
66
|
+
|
|
67
|
+
// A bare carriage return after the opening dashes is a line ending to some
|
|
68
|
+
// readers and ordinary text to others.
|
|
69
|
+
if (buffer.subarray(start, start + 3).equals(Buffer.from('---')) && buffer[start + 3] === CR && buffer[start + 4] !== LF) {
|
|
70
|
+
refuse('ambiguous-frontmatter', 'the opening front matter delimiter ends in a bare carriage return', detail)
|
|
71
|
+
}
|
|
72
|
+
const first = lineAt(buffer, start)
|
|
73
|
+
const opening = isDelimiterLine(buffer, start, first.contentEnd)
|
|
74
|
+
if (!opening) return whole
|
|
75
|
+
// The canonical graph reads a delimiter only as the exact first bytes of the
|
|
76
|
+
// text. Any opening it would read differently from an editor is ambiguous.
|
|
77
|
+
if (hasBom) refuse('ambiguous-frontmatter', 'a byte order prefix precedes a front matter delimiter', detail)
|
|
78
|
+
if (opening.trailing > 0) refuse('ambiguous-frontmatter', 'the opening front matter delimiter carries trailing whitespace', detail)
|
|
79
|
+
if (first.eol === 'none') refuse('ambiguous-frontmatter', 'the source is a lone front matter delimiter', detail)
|
|
80
|
+
|
|
81
|
+
let offset = first.next
|
|
82
|
+
let lines = 0
|
|
83
|
+
while (offset < buffer.length) {
|
|
84
|
+
const line = lineAt(buffer, offset)
|
|
85
|
+
if (isDelimiterLine(buffer, offset, line.contentEnd)) {
|
|
86
|
+
if (lines === 0) refuse('ambiguous-frontmatter', 'front matter closes immediately after it opens', detail)
|
|
87
|
+
if (line.eol === 'none') refuse('ambiguous-frontmatter', 'the closing front matter delimiter has no line ending', detail)
|
|
88
|
+
const region = buffer.subarray(start, line.next)
|
|
89
|
+
for (let index = 0; index < region.length; index += 1) {
|
|
90
|
+
if (region[index] === CR && region[index + 1] !== LF) refuse('ambiguous-frontmatter', 'front matter uses a bare carriage return as a line ending', detail)
|
|
91
|
+
}
|
|
92
|
+
return { ...whole, frontmatter: { start, end: line.next }, body: { start: line.next, end: buffer.length } }
|
|
93
|
+
}
|
|
94
|
+
lines += 1
|
|
95
|
+
offset = line.next
|
|
96
|
+
}
|
|
97
|
+
return refuse('ambiguous-frontmatter', 'front matter opens and never closes', detail)
|
|
98
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Materialization: the pure preparation layer for an Obsidian view. Nothing
|
|
2
|
+
// here writes into a vault; publication is a separate protocol.
|
|
3
|
+
export { EMITTER_VERSION, createPreparationCache, prepareView, withEligibility } from './prepare-view.mjs'
|
|
4
|
+
export { readMarkdownLens, assertStrictUtf8, sha256Digest } from './byte-lens.mjs'
|
|
5
|
+
export { PATH_REGISTRY_SCHEMA, allocateWorkspacePaths, collisionKey, emptyPathRegistry } from './path-registry.mjs'
|
|
6
|
+
export { POLICY_DISABLED_CORE_PLUGINS, POLICY_SETTINGS_PATH, SETTINGS_ROOT, isPolicySettingsPath, isUserOwnedSettingsPath, prepareSettings } from './settings.mjs'
|
|
7
|
+
export { stagePreparedView } from './stage.mjs'
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { identitySuffix, notePath } from '../contracts.mjs'
|
|
2
|
+
import { refuse } from './byte-lens.mjs'
|
|
3
|
+
|
|
4
|
+
// The persistent path registry: one readable note path per canonical identity,
|
|
5
|
+
// allocated once per workspace and reused by every scope and generation. A
|
|
6
|
+
// path, once allocated, never changes because a source title changed.
|
|
7
|
+
//
|
|
8
|
+
// The registry is workspace-wide, not view-wide: preparing any view allocates
|
|
9
|
+
// for every visible node of the workspace and returns the whole grown registry
|
|
10
|
+
// to the caller, which holds it as machine-private trusted state. It therefore
|
|
11
|
+
// names visible nodes outside the view's selection. It never includes a
|
|
12
|
+
// withheld node: allocation runs over the visible nodes only. A view's
|
|
13
|
+
// manifest and notes carry only the paths of the notes the view holds.
|
|
14
|
+
|
|
15
|
+
export const PATH_REGISTRY_SCHEMA = 'atelier-obsidian-path-registry/v1'
|
|
16
|
+
|
|
17
|
+
const NOTE_PATH = /^notes\/([^/\\\u0000]+)--([0-9a-f]{12,64})\.md$/
|
|
18
|
+
const MAX_COMPONENT_BYTES = 255
|
|
19
|
+
const MAX_SUFFIX = 64
|
|
20
|
+
// Bytes left for the readable title once the longest suffix, the separator and
|
|
21
|
+
// the extension are reserved, so lengthening a suffix never overflows a name.
|
|
22
|
+
const TITLE_BYTE_BUDGET = MAX_COMPONENT_BYTES - '--'.length - MAX_SUFFIX - '.md'.length
|
|
23
|
+
export const DEFAULT_MAX_FULL_PATH_BYTES = 1024
|
|
24
|
+
|
|
25
|
+
const compare = (left, right) => (left < right ? -1 : left > right ? 1 : 0)
|
|
26
|
+
export const identityKey = (repoId, nodeId) => `${repoId}\u0000${nodeId}`
|
|
27
|
+
|
|
28
|
+
// Two paths that a case-insensitive or normalization-insensitive filesystem
|
|
29
|
+
// would treat as one share a collision key.
|
|
30
|
+
export function collisionKey(value) {
|
|
31
|
+
return value.normalize('NFKC').toUpperCase().toLowerCase().normalize('NFKC')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function titleWithinBudget(title, budget = TITLE_BYTE_BUDGET) {
|
|
35
|
+
let kept = ''
|
|
36
|
+
let bytes = 0
|
|
37
|
+
for (const character of String(title ?? '').normalize('NFC')) {
|
|
38
|
+
bytes += Buffer.byteLength(character, 'utf8')
|
|
39
|
+
if (bytes > budget) break
|
|
40
|
+
kept += character
|
|
41
|
+
}
|
|
42
|
+
return kept
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function emptyPathRegistry(workspaceId) {
|
|
46
|
+
return { schema: PATH_REGISTRY_SCHEMA, workspaceId, entries: [] }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function indexRegistry(registry, workspaceId) {
|
|
50
|
+
if (registry === undefined || registry === null) return { byIdentity: new Map(), taken: new Map() }
|
|
51
|
+
if (registry.schema !== PATH_REGISTRY_SCHEMA || !Array.isArray(registry.entries)) refuse('invalid-path-registry', 'path registry has an unknown shape')
|
|
52
|
+
if (registry.workspaceId !== workspaceId) refuse('invalid-path-registry', 'path registry belongs to another workspace')
|
|
53
|
+
const byIdentity = new Map()
|
|
54
|
+
const taken = new Map()
|
|
55
|
+
for (const entry of registry.entries) {
|
|
56
|
+
const match = typeof entry?.path === 'string' ? entry.path.match(NOTE_PATH) : null
|
|
57
|
+
if (!match || typeof entry.repoId !== 'string' || typeof entry.nodeId !== 'string') refuse('invalid-path-registry', 'path registry entry is malformed')
|
|
58
|
+
if (identitySuffix(entry.repoId, entry.nodeId, 64).slice(0, match[2].length) !== match[2]) {
|
|
59
|
+
refuse('invalid-path-registry', 'path registry entry carries a suffix that is not derived from its identity')
|
|
60
|
+
}
|
|
61
|
+
const key = identityKey(entry.repoId, entry.nodeId)
|
|
62
|
+
if (byIdentity.has(key)) refuse('duplicate-identity', 'path registry repeats a canonical identity')
|
|
63
|
+
if (taken.has(collisionKey(entry.path))) refuse('path-collision', 'path registry allocates one path to more than one identity')
|
|
64
|
+
byIdentity.set(key, entry.path)
|
|
65
|
+
taken.set(collisionKey(entry.path), key)
|
|
66
|
+
}
|
|
67
|
+
return { byIdentity, taken }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Allocates a path for every node that lacks one and returns the grown
|
|
71
|
+
// registry. `nodes` are canonical nodes ({ repo, id, title }); allocation order
|
|
72
|
+
// is canonical-identity order, so the result depends on the inputs alone.
|
|
73
|
+
export function allocateWorkspacePaths({ registry, workspaceId, nodes, vaultRootBytes = 0, maxFullPathBytes = DEFAULT_MAX_FULL_PATH_BYTES }) {
|
|
74
|
+
const { byIdentity, taken } = indexRegistry(registry, workspaceId)
|
|
75
|
+
const seen = new Set()
|
|
76
|
+
const ordered = [...nodes].sort((left, right) => compare(left.repo, right.repo) || compare(left.id, right.id))
|
|
77
|
+
for (const node of ordered) {
|
|
78
|
+
const key = identityKey(node.repo, node.id)
|
|
79
|
+
if (seen.has(key)) refuse('duplicate-identity', 'more than one node carries the same canonical identity')
|
|
80
|
+
seen.add(key)
|
|
81
|
+
if (byIdentity.has(key)) continue
|
|
82
|
+
const titled = { repo: node.repo, id: node.id, title: titleWithinBudget(node.title) }
|
|
83
|
+
let length = 12
|
|
84
|
+
let candidate = notePath(titled, length)
|
|
85
|
+
while (taken.has(collisionKey(candidate))) {
|
|
86
|
+
length += 4
|
|
87
|
+
if (length > MAX_SUFFIX) refuse('path-collision', 'unable to allocate a distinct note path')
|
|
88
|
+
candidate = notePath(titled, length)
|
|
89
|
+
}
|
|
90
|
+
byIdentity.set(key, candidate)
|
|
91
|
+
taken.set(collisionKey(candidate), key)
|
|
92
|
+
}
|
|
93
|
+
for (const candidate of byIdentity.values()) {
|
|
94
|
+
const name = candidate.slice('notes/'.length)
|
|
95
|
+
if (Buffer.byteLength(name, 'utf8') > MAX_COMPONENT_BYTES || vaultRootBytes + 1 + Buffer.byteLength(candidate, 'utf8') > maxFullPathBytes) {
|
|
96
|
+
refuse('path-too-long', 'an allocated note path exceeds the supported path length')
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const entries = [...byIdentity].map(([key, allocated]) => {
|
|
100
|
+
const [repoId, nodeId] = key.split('\u0000')
|
|
101
|
+
return { repoId, nodeId, path: allocated }
|
|
102
|
+
})
|
|
103
|
+
entries.sort((left, right) => compare(left.repoId, right.repoId) || compare(left.nodeId, right.nodeId))
|
|
104
|
+
return { registry: { schema: PATH_REGISTRY_SCHEMA, workspaceId, entries }, pathOf: (repoId, nodeId) => byIdentity.get(identityKey(repoId, nodeId)) ?? null }
|
|
105
|
+
}
|