@mnstry/atelier 0.2.0-alpha.1 → 0.2.0-alpha.10
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 +372 -0
- package/README.md +402 -205
- 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-repository-observation.v1.schema.json +163 -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/contracts/public-api-baseline.json +57 -0
- package/docs/assurance-controls.md +49 -0
- package/docs/atelier-runtime.md +28 -2
- package/docs/atelier-sync.md +172 -0
- package/docs/blocks/audience-visibility.md +9 -0
- package/docs/blocks/claims.md +61 -0
- package/docs/blocks/conformance-admission.md +15 -0
- package/docs/blocks/will-not-do.md +18 -0
- package/docs/coauthor-session.md +57 -0
- package/docs/connected-composition.md +75 -0
- package/docs/continuity.md +3 -4
- package/docs/decisions.md +167 -0
- package/docs/design.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 +99 -16
- 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/knowledge-graph.md +8 -4
- package/docs/local-review.md +84 -0
- package/docs/local-services.md +328 -0
- package/docs/local-state.md +107 -0
- package/docs/obsidian-contract.md +690 -0
- package/docs/obsidian.md +423 -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 +174 -12
- package/docs/repo-boundary-guard.md +12 -2
- package/docs/review-portability.md +55 -0
- package/docs/skill-steward.md +156 -0
- package/docs/upgrade.md +146 -5
- 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-repository-observation/invalid/complete-with-blocker.v1.json +18 -0
- package/fixtures/atelier-repository-observation/valid/complete-local.v1.json +48 -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/projects/sample-workspace/content/source.html.kg.json +4 -1
- package/fixtures/projects/source-formats-workspace/content/data.json.kg.json +4 -1
- package/fixtures/projects/source-formats-workspace/content/logo.png.kg.json +4 -1
- package/fixtures/projects/source-formats-workspace/content/metrics.csv.kg.json +4 -1
- package/fixtures/projects/source-formats-workspace/content/pipeline.yaml.kg.json +4 -1
- package/fixtures/ui/presentation/pane.v1.json +7 -0
- package/fixtures/ui/presentation/reference.v1.json +293 -0
- package/package.json +86 -10
- package/skills/claude/atelier-guided-coauthor/SKILL.md +49 -0
- package/skills/claude/atelier-guided-upgrade/SKILL.md +97 -0
- package/skills/claude/atelier-local-service/SKILL.md +47 -0
- package/skills/claude/atelier-open/SKILL.md +11 -5
- package/skills/claude/atelier-public-boundary/SKILL.md +31 -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-local-service/SKILL.md +47 -0
- package/skills/codex/atelier-open/SKILL.md +11 -5
- package/skills/codex/atelier-public-boundary/SKILL.md +31 -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/content-rules.mjs +283 -20
- package/src/boundary/policy.mjs +213 -91
- package/src/cli/execute-command.mjs +36 -0
- package/src/cli/project-options.mjs +58 -0
- package/src/cli/run.mjs +78 -10
- package/src/coauthor/session.mjs +161 -0
- package/src/coauthor/store.mjs +173 -0
- package/src/collaboration/event-ledger.mjs +348 -0
- package/src/collaboration/index.mjs +17 -0
- package/src/collaboration/inspection-bundle.mjs +223 -0
- package/src/collaboration/proposals.mjs +265 -65
- package/src/collaboration/review-contracts.mjs +25 -0
- package/src/collaboration/review-store.mjs +305 -0
- package/src/commands/attestation.mjs +20 -6
- package/src/commands/coauthor.mjs +26 -0
- package/src/commands/config.mjs +6 -1
- package/src/commands/disclosure.mjs +133 -0
- package/src/commands/distribution.mjs +2 -1
- package/src/commands/extension-pack.mjs +17 -9
- package/src/commands/init.mjs +46 -6
- package/src/commands/obsidian.mjs +371 -0
- package/src/commands/review.mjs +147 -0
- package/src/commands/server.mjs +1 -4
- package/src/commands/setup.mjs +51 -14
- package/src/commands/skills.mjs +199 -0
- package/src/commands/sync.mjs +107 -0
- package/src/composition/registry.mjs +27 -0
- package/src/composition/wire.mjs +122 -0
- package/src/contracts/corpus.mjs +35 -0
- package/src/decisions/contracts.d.mts +96 -0
- package/src/decisions/contracts.mjs +321 -0
- package/src/disclosure/content-scan.mjs +206 -0
- package/src/egress/check.mjs +7 -38
- package/src/egress/forbidden-egress.mjs +32 -18
- package/src/export/atelier-export-contract.mjs +16 -1
- package/src/extension-packs/lifecycle.mjs +154 -0
- package/src/graph/graph.mjs +176 -316
- package/src/graph/knowledge-graph.mjs +643 -43
- package/src/guides/contracts.mjs +54 -0
- package/src/harness/context-client.mjs +9 -1
- package/src/index.mjs +41 -0
- package/src/intake/store.mjs +119 -0
- package/src/preview/channel.mjs +89 -0
- package/src/project/config.mjs +112 -52
- package/src/project/durable-state.mjs +161 -0
- package/src/project/file-class.mjs +180 -0
- package/src/project/package-root.mjs +10 -0
- package/src/project/path-match.mjs +38 -15
- package/src/project/private-state.mjs +120 -0
- 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 +160 -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/git-adapter.mjs +189 -0
- package/src/runtime/local-state.mjs +439 -0
- package/src/runtime/obsidian/app-capability.mjs +129 -0
- package/src/runtime/obsidian/app-production-seams.mjs +105 -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 +263 -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-entry-path.mjs +9 -0
- package/src/runtime/obsidian/service-main.mjs +91 -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/repository-observation.mjs +491 -0
- package/src/runtime/supervisor.mjs +803 -0
- package/src/server/local-sidecar.mjs +125 -59
- package/src/server/security.mjs +89 -4
- package/src/server/server.mjs +4 -2
- package/src/skills/steward.mjs +780 -0
- package/src/support/feedback-report.mjs +4 -3
- 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 +65 -29
- 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,131 @@
|
|
|
1
|
+
import { verifyVaultPrivacy, createVaultContext } from './privacy.mjs'
|
|
2
|
+
import { renderVaultHome, vaultHomePolicy } from './interface.mjs'
|
|
3
|
+
/** Optional hosted artifact service. No default network, storage, or identity provider. */
|
|
4
|
+
const TYPES = Object.freeze({ html: 'text/html; charset=utf-8', css: 'text/css; charset=utf-8', txt: 'text/plain; charset=utf-8', png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', webp: 'image/webp', pdf: 'application/pdf' })
|
|
5
|
+
const LIMIT = 4 * 1024 * 1024
|
|
6
|
+
const encoder = new TextEncoder()
|
|
7
|
+
const validId = value => typeof value === 'string' && /^[a-z][a-z0-9-]{0,62}$/.test(value)
|
|
8
|
+
const validPath = value => typeof value === 'string' && value.length <= 512 && value.split('/').every(p => /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(p) && p !== '.' && p !== '..')
|
|
9
|
+
const validExt = value => value === undefined || (value !== null && typeof value === 'object' && !Array.isArray(value))
|
|
10
|
+
const sameOwner = (a, b) => a && b && typeof a.issuer === 'string' && a.issuer.length > 0 && typeof a.subject === 'string' && a.subject.length > 0 && a.issuer === b.issuer && a.subject === b.subject
|
|
11
|
+
const headers = {
|
|
12
|
+
'Cache-Control': 'private, no-store',
|
|
13
|
+
'Content-Security-Policy': "sandbox; default-src 'none'; img-src 'self'; style-src 'self' 'unsafe-inline'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'",
|
|
14
|
+
'X-Content-Type-Options': 'nosniff',
|
|
15
|
+
'Referrer-Policy': 'no-referrer',
|
|
16
|
+
'X-Robots-Tag': 'noindex, nofollow',
|
|
17
|
+
}
|
|
18
|
+
export async function digest(bytes) {
|
|
19
|
+
return Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256', bytes)), b => b.toString(16).padStart(2, '0')).join('')
|
|
20
|
+
}
|
|
21
|
+
function reply(status, text = '', extra = {}) { return new Response(text, { status, headers: { ...headers, 'Content-Type': 'text/plain; charset=utf-8', ...extra } }) }
|
|
22
|
+
async function boundedBody(request) {
|
|
23
|
+
if (!request.body) throw new Error('invalid')
|
|
24
|
+
const reader = request.body.getReader()
|
|
25
|
+
let size = 0
|
|
26
|
+
const chunks = []
|
|
27
|
+
try {
|
|
28
|
+
while (true) {
|
|
29
|
+
const { done, value } = await reader.read()
|
|
30
|
+
if (done) break
|
|
31
|
+
size += value.byteLength
|
|
32
|
+
if (size > LIMIT) { await reader.cancel(); throw new Error('too-large') }
|
|
33
|
+
chunks.push(value)
|
|
34
|
+
}
|
|
35
|
+
} finally { reader.releaseLock() }
|
|
36
|
+
const bytes = new Uint8Array(size)
|
|
37
|
+
let offset = 0
|
|
38
|
+
for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length }
|
|
39
|
+
return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes))
|
|
40
|
+
}
|
|
41
|
+
export async function preparePublication(input) {
|
|
42
|
+
if (!input || input.schema !== 'atelier-vault-publication/v1' || (input.contractVersion !== undefined && (typeof input.contractVersion !== 'string' || !/^1\.[0-9]+\.[0-9]+$/.test(input.contractVersion))) || !validExt(input.ext) || !Number.isSafeInteger(input.expectedRevision) || input.expectedRevision < 0 || input.expectedRevision >= Number.MAX_SAFE_INTEGER || Object.keys(input).some(key => !['schema', 'contractVersion', 'expectedRevision', 'files', 'ext'].includes(key)) || !Array.isArray(input.files) || !input.files.length || input.files.length > 100) throw new Error('invalid')
|
|
43
|
+
if (encoder.encode(JSON.stringify(input)).length > LIMIT) throw new Error('too-large')
|
|
44
|
+
const seen = new Set()
|
|
45
|
+
const files = []
|
|
46
|
+
let total = 0
|
|
47
|
+
for (const file of input.files) {
|
|
48
|
+
if (!file || !validExt(file.ext) || Object.keys(file).some(key => !['path', 'base64', 'ext'].includes(key)) || !validPath(file.path) || seen.has(file.path) || typeof file.base64 !== 'string' || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(file.base64)) throw new Error('invalid')
|
|
49
|
+
const type = TYPES[file.path.split('.').at(-1)]
|
|
50
|
+
if (typeof type !== 'string') throw new Error('invalid')
|
|
51
|
+
seen.add(file.path)
|
|
52
|
+
const bytes = Uint8Array.from(atob(file.base64), c => c.charCodeAt(0))
|
|
53
|
+
total += bytes.length
|
|
54
|
+
if (total > LIMIT) throw new Error('too-large')
|
|
55
|
+
files.push({ path: file.path, type, size: bytes.length, sha256: await digest(bytes), bytes })
|
|
56
|
+
}
|
|
57
|
+
files.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0)
|
|
58
|
+
const manifest = files.map(({ bytes, ...record }) => record)
|
|
59
|
+
return { files, manifest, publication: await digest(encoder.encode(JSON.stringify(manifest))) }
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* identity.read(request) -> verified {issuer,subject}, or null (revocation checked).
|
|
63
|
+
* identity.publish(request,vault) -> verified owner identity, or null; MUST use
|
|
64
|
+
* a revocable vault-scoped machine credential, never browser cookies.
|
|
65
|
+
* metadata.get(vault) -> {owner, revision, manifest}, or null.
|
|
66
|
+
* metadata.commit(vault,{owner,expectedRevision,manifest,publication}) -> boolean;
|
|
67
|
+
* MUST atomically compare both owner and revision before replacing manifest.
|
|
68
|
+
* storage.get/put accepts service-generated keys only and uses private storage.
|
|
69
|
+
*/
|
|
70
|
+
export function createVaultService({ identity, metadata, storage, privacy, deployment }) {
|
|
71
|
+
for (const [object, methods] of [[identity, ['read', 'publish']], [metadata, ['get', 'commit']], [storage, ['get', 'put']]]) {
|
|
72
|
+
if (!object || methods.some(method => typeof object[method] !== 'function')) throw new TypeError('Incomplete vault adapter')
|
|
73
|
+
}
|
|
74
|
+
return async function handle(request) {
|
|
75
|
+
try {
|
|
76
|
+
const url = new URL(request.url)
|
|
77
|
+
if (/%|\\/.test(url.pathname)) return reply(400)
|
|
78
|
+
const parts = url.pathname.slice(1).split('/')
|
|
79
|
+
const publishing = parts[0] === '_publish'
|
|
80
|
+
const vault = publishing ? parts[1] : parts[0]
|
|
81
|
+
if (!validId(vault)) return reply(404)
|
|
82
|
+
const home = !publishing && (parts.length === 1 || (parts.length === 2 && parts[1] === ''))
|
|
83
|
+
if (url.search && (publishing || (home && ( [...url.searchParams.keys()].some(key => key !== 'q') || url.searchParams.getAll('q').length > 1 || (url.searchParams.get('q') || '').length > 200)))) return reply(400)
|
|
84
|
+
if (publishing) {
|
|
85
|
+
if (parts.length !== 2 || !['GET', 'POST'].includes(request.method)) return reply(405, '', { Allow: 'GET, POST' })
|
|
86
|
+
// Browser-originated writes are not a machine publication channel.
|
|
87
|
+
if (request.headers.has('origin') || request.headers.has('cookie')) return reply(403)
|
|
88
|
+
const principal = await identity.publish(request, vault)
|
|
89
|
+
if (!principal) return reply(401, '', { 'WWW-Authenticate': 'Bearer realm="vault-publication"' })
|
|
90
|
+
const record = await metadata.get(vault)
|
|
91
|
+
if (!sameOwner(principal, record?.owner)) return reply(404)
|
|
92
|
+
if (request.method === 'GET') {
|
|
93
|
+
return new Response(JSON.stringify({ schema: 'atelier-vault-status/v1', vault, revision: record.revision, publication: record.publication ?? null }), { headers: { ...headers, 'Content-Type': 'application/json' } })
|
|
94
|
+
}
|
|
95
|
+
if (request.headers.get('content-type')?.split(';')[0].trim().toLowerCase() !== 'application/json') return reply(415)
|
|
96
|
+
let input, prepared
|
|
97
|
+
try { input = await boundedBody(request); prepared = await preparePublication(input) }
|
|
98
|
+
catch (error) { return reply(error.message === 'too-large' ? 413 : 400) }
|
|
99
|
+
if (input.expectedRevision !== record.revision) return reply(409)
|
|
100
|
+
const context = createVaultContext({ vault, record: { owner: record.owner, publication: prepared.publication, revision: input.expectedRevision + 1, manifest: prepared.manifest }, deployment, request: { origin: url.origin, path: url.pathname } })
|
|
101
|
+
const before = await verifyVaultPrivacy(privacy, { ...context, phase: 'before-upload' })
|
|
102
|
+
if (before.status !== 'verified') return reply(503, before.reason)
|
|
103
|
+
for (const file of prepared.files) await storage.put(`${vault}/${file.sha256}`, file.bytes)
|
|
104
|
+
const after = await verifyVaultPrivacy(privacy, { ...context, phase: 'before-activation' })
|
|
105
|
+
if (after.status !== 'verified' || after.policyRevision !== before.policyRevision) return reply(503, 'Protection changed or could not be verified. Publication was not activated.')
|
|
106
|
+
// Revalidate the credential after uploads and activation checks, immediately before commit.
|
|
107
|
+
const current = await identity.publish(request, vault)
|
|
108
|
+
if (!sameOwner(principal, current)) return reply(401, '', { 'WWW-Authenticate': 'Bearer realm="vault-publication"' })
|
|
109
|
+
const committed = await metadata.commit(vault, { owner: principal, expectedRevision: input.expectedRevision, manifest: prepared.manifest, publication: prepared.publication })
|
|
110
|
+
if (!committed) return reply(409)
|
|
111
|
+
return new Response(JSON.stringify({ schema: 'atelier-vault-receipt/v1', vault, revision: input.expectedRevision + 1, publication: prepared.publication }), { status: 201, headers: { ...headers, 'Content-Type': 'application/json' } })
|
|
112
|
+
}
|
|
113
|
+
if (!['GET', 'HEAD'].includes(request.method)) return reply(405, '', { Allow: 'GET, HEAD' })
|
|
114
|
+
const principal = await identity.read(request)
|
|
115
|
+
if (!principal) return reply(401)
|
|
116
|
+
const record = await metadata.get(vault)
|
|
117
|
+
if (!sameOwner(principal, record?.owner)) return reply(404)
|
|
118
|
+
if (!home && !record.manifest.some(file => file.path === parts.slice(1).join('/'))) return reply(404)
|
|
119
|
+
const protection = await verifyVaultPrivacy(privacy, createVaultContext({ vault, record, deployment, request: { origin: url.origin, path: url.pathname } }))
|
|
120
|
+
if (home) return new Response(request.method === 'HEAD' ? null : renderVaultHome({ vault, revision: record.revision, manifest: record.manifest, privacy: protection, query: url.searchParams.get('q') || '' }), { headers: { ...headers, 'Content-Type': 'text/html; charset=utf-8', 'Content-Security-Policy': vaultHomePolicy } })
|
|
121
|
+
if (protection.status !== 'verified') return reply(503, protection.reason)
|
|
122
|
+
const path = parts.slice(1).join('/')
|
|
123
|
+
if (!validPath(path)) return reply(404)
|
|
124
|
+
const file = record.manifest.find(entry => entry.path === path)
|
|
125
|
+
if (!file || !/^[a-f0-9]{64}$/.test(file.sha256) || !Object.values(TYPES).includes(file.type)) return reply(404)
|
|
126
|
+
const bytes = await storage.get(`${vault}/${file.sha256}`)
|
|
127
|
+
if (!bytes || bytes.length !== file.size || await digest(bytes) !== file.sha256) return reply(503)
|
|
128
|
+
return new Response(request.method === 'HEAD' ? null : bytes, { headers: { ...headers, 'Content-Type': file.type, 'Content-Length': String(bytes.length), ...(file.type === 'application/pdf' ? { 'Content-Disposition': 'attachment' } : {}) } })
|
|
129
|
+
} catch { return reply(503) }
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { preparePublication } from './service.mjs'
|
|
4
|
+
const LIMIT = 4 * 1024 * 1024
|
|
5
|
+
/** Node-only bundle preparation. Select paths explicitly; never scan a repo. */
|
|
6
|
+
export async function prepareVaultSource({ root, paths, expectedRevision }) {
|
|
7
|
+
if (typeof root !== 'string' || !path.isAbsolute(root) || !Array.isArray(paths) || !paths.length || paths.length > 100) throw new TypeError('Absolute artifact root and explicit paths required')
|
|
8
|
+
if (fs.lstatSync(root).isSymbolicLink()) throw new Error('Artifact root must not be a symlink')
|
|
9
|
+
const realRoot = fs.realpathSync(root)
|
|
10
|
+
if (!fs.statSync(realRoot).isDirectory()) throw new Error('Artifact root must be a directory')
|
|
11
|
+
let total = 0
|
|
12
|
+
const files = []
|
|
13
|
+
for (const name of paths) {
|
|
14
|
+
if (typeof name !== 'string' || name.length > 512 || !name.split('/').every(part => /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(part))) throw new Error('Invalid selected artifact path')
|
|
15
|
+
let file = realRoot
|
|
16
|
+
for (const part of name.split('/')) {
|
|
17
|
+
file = path.join(file, part)
|
|
18
|
+
if (fs.lstatSync(file).isSymbolicLink()) throw new Error('Selected artifacts must not traverse symlinks')
|
|
19
|
+
}
|
|
20
|
+
const before = fs.lstatSync(file)
|
|
21
|
+
if (!before.isFile() || before.nlink !== 1 || before.size > LIMIT) throw new Error('Selected artifact must be a bounded, unlinked regular file')
|
|
22
|
+
const fd = fs.openSync(file, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0))
|
|
23
|
+
try {
|
|
24
|
+
const opened = fs.fstatSync(fd)
|
|
25
|
+
const resolved = fs.realpathSync(file)
|
|
26
|
+
if ((path.relative(realRoot, resolved).startsWith('..' + path.sep) || path.isAbsolute(path.relative(realRoot, resolved))) || opened.ino !== before.ino || opened.dev !== before.dev || !opened.isFile() || opened.nlink !== 1 || opened.size > LIMIT) throw new Error('Artifact changed during selection')
|
|
27
|
+
const data = Buffer.alloc(opened.size)
|
|
28
|
+
let offset = 0
|
|
29
|
+
while (offset < data.length) {
|
|
30
|
+
const count = fs.readSync(fd, data, offset, data.length - offset, offset)
|
|
31
|
+
if (!count) throw new Error('Artifact changed during read')
|
|
32
|
+
offset += count
|
|
33
|
+
}
|
|
34
|
+
const after = fs.fstatSync(fd)
|
|
35
|
+
const current = fs.lstatSync(file)
|
|
36
|
+
if (after.nlink !== 1 || current.nlink !== 1 || after.size !== opened.size || after.mtimeMs !== opened.mtimeMs || after.ctimeMs !== opened.ctimeMs || current.ino !== opened.ino || current.dev !== opened.dev || fs.realpathSync(file) !== resolved) throw new Error('Artifact changed during read')
|
|
37
|
+
total += data.length
|
|
38
|
+
if (total > LIMIT) throw new Error('Artifact bundle too large')
|
|
39
|
+
files.push({ path: name, base64: data.toString('base64') })
|
|
40
|
+
} finally { fs.closeSync(fd) }
|
|
41
|
+
}
|
|
42
|
+
const request = { schema: 'atelier-vault-publication/v1', contractVersion: '1.0.0', expectedRevision, files }
|
|
43
|
+
const prepared = await preparePublication(request)
|
|
44
|
+
return { request, publication: prepared.publication, manifest: prepared.manifest }
|
|
45
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Provider SDKs/bindings are explicitly supplied by the host, never auto-loaded. */
|
|
2
|
+
export function r2PrivateStorage(bucket) {
|
|
3
|
+
return {
|
|
4
|
+
async put(key, bytes) { await bucket.put(key, bytes) },
|
|
5
|
+
async get(key) {
|
|
6
|
+
const object = await bucket.get(key)
|
|
7
|
+
return object ? new Uint8Array(await object.arrayBuffer()) : null
|
|
8
|
+
},
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function vercelPrivateStorage(blob) {
|
|
12
|
+
return {
|
|
13
|
+
async put(key, bytes) {
|
|
14
|
+
await blob.put(key, bytes, { access: 'private', addRandomSuffix: false, allowOverwrite: true, contentType: 'application/octet-stream' })
|
|
15
|
+
},
|
|
16
|
+
async get(key) {
|
|
17
|
+
const object = await blob.get(key, { access: 'private', useCache: false })
|
|
18
|
+
if (!object) return null
|
|
19
|
+
if (object.statusCode !== 200 || !object.stream) throw new Error('Private storage unavailable')
|
|
20
|
+
return new Uint8Array(await new Response(object.stream).arrayBuffer())
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
"configurations": [
|
|
4
4
|
{
|
|
5
5
|
"name": "atelier",
|
|
6
|
-
"runtimeExecutable": "
|
|
7
|
-
"runtimeArgs": [
|
|
6
|
+
"runtimeExecutable": "node",
|
|
7
|
+
"runtimeArgs": [
|
|
8
|
+
"--input-type=module",
|
|
9
|
+
"--eval",
|
|
10
|
+
"import { runCli } from '@mnstry/atelier/cli'; process.exit(await runCli({ argv: ['server', ...process.argv.slice(1)] }));"
|
|
11
|
+
],
|
|
8
12
|
"port": 8137,
|
|
9
13
|
"autoPort": true
|
|
10
14
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# External-project adapter starter
|
|
2
|
+
|
|
3
|
+
This invented example uses MNSTRY Atelier. The adapter owns configuration and
|
|
4
|
+
a sample extension pack; the separate source repository owns canonical text.
|
|
5
|
+
Runs, answers and review history remain ignored local state. Public audience
|
|
6
|
+
labels do not grant publication, consent or runtime access.
|
|
7
|
+
|
|
8
|
+
Create this scaffold with `atelier init --template external-project --target DIR`.
|
|
9
|
+
The target must not exist. No Git repository, hook or remote is created.
|
|
10
|
+
Initialize the adapter and its source directory as separate repositories when
|
|
11
|
+
ready; the adapter ignores `source/`. To connect an existing repository instead,
|
|
12
|
+
pass `--repo-path source=PATH` consistently, or use an ignored local overlay.
|
|
13
|
+
Keep domain vocabulary and methods in your own adapter and source repositories.
|
|
14
|
+
Replace the synthetic actor in the boundary policy with your actual policy.
|
|
15
|
+
|
|
16
|
+
Using the installed package's CLI, from the adapter directory:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
atelier lock provenance
|
|
20
|
+
atelier config check --explain
|
|
21
|
+
atelier extension-pack validate
|
|
22
|
+
atelier graph
|
|
23
|
+
atelier project
|
|
24
|
+
atelier readiness
|
|
25
|
+
atelier review packs
|
|
26
|
+
atelier review run sample.readiness:contract-gate --answers answers.example.json
|
|
27
|
+
atelier dev --review
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Open `/review` on the displayed local address. Use repository `source` and
|
|
31
|
+
`README.md` to leave a question. Use the returned run ID to review its claims.
|
|
32
|
+
The evaluator measures answer completeness only. Read and judge the evidence;
|
|
33
|
+
acceptance creates a handoff, never a canonical edit. Use `atelier review history`
|
|
34
|
+
and `atelier review handoff REQUEST_ID` to inspect records locally.
|
|
35
|
+
|
|
36
|
+
Real answers and responses belong in ignored local state, not the tracked
|
|
37
|
+
example answer file. Reopening recovers saved contributions; missing or failed
|
|
38
|
+
saves remain visible. Stop/start the foreground sidecar with the same project
|
|
39
|
+
and reopen the same document. This does not establish cross-computer access.
|
|
40
|
+
|
|
41
|
+
For CI, compose the root's existing consumer, portability, boundary and
|
|
42
|
+
private-disclosure checks. No new CI run or provider is triggered by this template.
|
|
43
|
+
Before changing the pack, run `atelier upgrade --dry-run`, retain historical
|
|
44
|
+
pack content, update its lifecycle declaration and lock through your reviewed
|
|
45
|
+
migration process, and run the checks again. Never reinterpret old run evidence.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "mnstry.atelier-project-config@v1",
|
|
3
|
+
"name": "sample-adapter",
|
|
4
|
+
"roots": {
|
|
5
|
+
"workspace": ".",
|
|
6
|
+
"repoOps": "."
|
|
7
|
+
},
|
|
8
|
+
"graph": {
|
|
9
|
+
"repoAccessPath": "repo-access.v1.json",
|
|
10
|
+
"outputPath": "atelier-output/knowledge.graph.json"
|
|
11
|
+
},
|
|
12
|
+
"projection": {
|
|
13
|
+
"outputRoot": "atelier-output",
|
|
14
|
+
"readinessPath": "atelier-output/atelier-readiness.json"
|
|
15
|
+
},
|
|
16
|
+
"boundaries": {
|
|
17
|
+
"policyPath": "boundary-policy.v1.json",
|
|
18
|
+
"strictNewRepos": true
|
|
19
|
+
},
|
|
20
|
+
"repos": [
|
|
21
|
+
{
|
|
22
|
+
"name": "source",
|
|
23
|
+
"path": "source",
|
|
24
|
+
"readBoundary": "private"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"ext": {
|
|
28
|
+
"mnstry.atelier": {
|
|
29
|
+
"extensionPacks": [
|
|
30
|
+
{
|
|
31
|
+
"id": "sample.readiness",
|
|
32
|
+
"version": "v1",
|
|
33
|
+
"path": "packs/sample-pack.v1.json",
|
|
34
|
+
"enabled": true
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"extensionPackLifecycle": "pack-lifecycle.json"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "mnstry.atelier-boundary-policy@v1",
|
|
3
|
+
"mode": "strict",
|
|
4
|
+
"actors": {
|
|
5
|
+
"sample-author": {
|
|
6
|
+
"githubLogin": "sample-author",
|
|
7
|
+
"gitEmails": [
|
|
8
|
+
"sample@example.invalid"
|
|
9
|
+
],
|
|
10
|
+
"privateDomainRepo": "source"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"repos": {
|
|
14
|
+
"source": {
|
|
15
|
+
"kind": "private_domain",
|
|
16
|
+
"ownerActor": "sample-author",
|
|
17
|
+
"readBoundary": "private",
|
|
18
|
+
"allowedAudiences": [
|
|
19
|
+
"private"
|
|
20
|
+
],
|
|
21
|
+
"forbiddenAudiences": [
|
|
22
|
+
"public"
|
|
23
|
+
],
|
|
24
|
+
"autoCommit": "guarded"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"forbiddenPaths": [
|
|
28
|
+
".atelier-local/**",
|
|
29
|
+
"atelier.local.json",
|
|
30
|
+
"atelier.workspace.local.json",
|
|
31
|
+
".mnstry-local/**",
|
|
32
|
+
".atelier-proposals/**",
|
|
33
|
+
".atelier-current",
|
|
34
|
+
".atelier-current.json",
|
|
35
|
+
".atelier-presence.json",
|
|
36
|
+
".atelier-nonce",
|
|
37
|
+
".atelier-capability-grants.json",
|
|
38
|
+
".atelier-grants/**",
|
|
39
|
+
".atelier-events.jsonl",
|
|
40
|
+
".atelier-audit.jsonl",
|
|
41
|
+
".atelier-audit/**",
|
|
42
|
+
".atelier-session.json",
|
|
43
|
+
".atelier-session.jsonl",
|
|
44
|
+
".atelier-session/**",
|
|
45
|
+
".atelier-sessions/**",
|
|
46
|
+
".atelier-support/**",
|
|
47
|
+
".atelier-support.json",
|
|
48
|
+
"support-bundle*",
|
|
49
|
+
"support-bundles/**",
|
|
50
|
+
"prompts/**",
|
|
51
|
+
"transcripts/**",
|
|
52
|
+
"node_modules/**",
|
|
53
|
+
".DS_Store"
|
|
54
|
+
],
|
|
55
|
+
"promotion": {
|
|
56
|
+
"requiresGitPromote": true,
|
|
57
|
+
"recordsPath": "governance/git-promote-events.jsonl"
|
|
58
|
+
},
|
|
59
|
+
"governanceLedgerPath": "governance/repo-boundary-ledger.md"
|
|
60
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "atelier-pack-lifecycle@v1",
|
|
3
|
+
"packs": [
|
|
4
|
+
{
|
|
5
|
+
"id": "sample.readiness",
|
|
6
|
+
"version": "v1",
|
|
7
|
+
"digest": "sha256:0eff795765e0bbd4c2510acda2e492201c23bc870df6c354eef623484643ab11",
|
|
8
|
+
"compatibleRootVersions": [
|
|
9
|
+
"0.2.0-alpha.10"
|
|
10
|
+
],
|
|
11
|
+
"status": "active"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "atelier-readiness-protocol@v1",
|
|
3
|
+
"id": "sample.readiness:contract-gate",
|
|
4
|
+
"slug": "contract-gate",
|
|
5
|
+
"version": "v1",
|
|
6
|
+
"stage": "formation",
|
|
7
|
+
"title": "Sample contract gate",
|
|
8
|
+
"purpose": "Verify neutral protocol inputs before a readiness run is accepted.",
|
|
9
|
+
"questions": [
|
|
10
|
+
{
|
|
11
|
+
"id": "scope",
|
|
12
|
+
"prompt": "What neutral scope is being prepared?",
|
|
13
|
+
"inputFields": ["scope.name", "scope.sourceRef"],
|
|
14
|
+
"required": true
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"inputFields": [
|
|
18
|
+
{
|
|
19
|
+
"id": "scope.name",
|
|
20
|
+
"type": "string",
|
|
21
|
+
"required": true,
|
|
22
|
+
"description": "Neutral scope name."
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "scope.sourceRef",
|
|
26
|
+
"type": "string",
|
|
27
|
+
"required": true,
|
|
28
|
+
"description": "Evidence reference for the scope."
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"outputHints": [
|
|
32
|
+
{
|
|
33
|
+
"id": "contract-gate.summary",
|
|
34
|
+
"text": "Render scope and evidence before review."
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"outputs": {
|
|
38
|
+
"runSchema": "atelier-readiness-run@v1",
|
|
39
|
+
"artifacts": [
|
|
40
|
+
{
|
|
41
|
+
"id": "sample.readiness:contract-gate.summary",
|
|
42
|
+
"kind": "draft",
|
|
43
|
+
"schema": "atelier-readiness-run@v1",
|
|
44
|
+
"description": "Draft readiness summary."
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"claimMappings": [
|
|
49
|
+
{
|
|
50
|
+
"id": "sample.readiness:contract-gate.scope-supports-review",
|
|
51
|
+
"claimPredicate": "supports",
|
|
52
|
+
"sourceFields": ["scope.name"],
|
|
53
|
+
"target": "atelier-claim@v1",
|
|
54
|
+
"evidence": "scope.sourceRef"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"readinessRules": [
|
|
58
|
+
{
|
|
59
|
+
"id": "sample.readiness:contract-gate.scope-present",
|
|
60
|
+
"severity": "blocker",
|
|
61
|
+
"condition": "Scope name and evidence are present.",
|
|
62
|
+
"remediation": "Add scope.name and scope.sourceRef.",
|
|
63
|
+
"failClosed": true
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"graphLenses": [
|
|
67
|
+
{
|
|
68
|
+
"id": "sample.readiness:contract-gate.lens",
|
|
69
|
+
"title": "Sample contract gate lens",
|
|
70
|
+
"query": { "protocolId": "sample.readiness:contract-gate" }
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"exportMappings": [
|
|
74
|
+
{
|
|
75
|
+
"id": "sample.readiness:contract-gate.export",
|
|
76
|
+
"sourceField": "scope",
|
|
77
|
+
"sourceTerm": "sample.readiness:contract-gate.scope",
|
|
78
|
+
"target": "core.artifact",
|
|
79
|
+
"runtimeOwner": "audit",
|
|
80
|
+
"targetCollection": "staffPrep"
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"ui": {
|
|
84
|
+
"section": "readiness-journey",
|
|
85
|
+
"title": "Sample contract gate",
|
|
86
|
+
"description": "Neutral protocol fixture.",
|
|
87
|
+
"agentPrompt": "Run atelier readiness run sample.readiness:contract-gate --project ./atelier.project.json."
|
|
88
|
+
},
|
|
89
|
+
"safety": {
|
|
90
|
+
"runtimeMutation": false,
|
|
91
|
+
"runtimeImport": false,
|
|
92
|
+
"canonicalWrites": false,
|
|
93
|
+
"claimOnly": true,
|
|
94
|
+
"telemetry": false,
|
|
95
|
+
"egress": false,
|
|
96
|
+
"sendPath": false,
|
|
97
|
+
"browserApply": false,
|
|
98
|
+
"dryRunOnly": true
|
|
99
|
+
},
|
|
100
|
+
"safetyPosture": {
|
|
101
|
+
"runtimeMutation": false,
|
|
102
|
+
"externalEgress": false,
|
|
103
|
+
"defaultVisibility": "private",
|
|
104
|
+
"authority": "proposal-only",
|
|
105
|
+
"reviewMode": "static-inspection",
|
|
106
|
+
"failClosedOnMissingEvidence": true,
|
|
107
|
+
"refuses": ["runtime writes"]
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "mnstry-atelier-extension-pack@v1",
|
|
3
|
+
"id": "sample.readiness",
|
|
4
|
+
"namespace": "sample",
|
|
5
|
+
"version": "v1",
|
|
6
|
+
"terms": [
|
|
7
|
+
{
|
|
8
|
+
"id": "sample.readiness:scope",
|
|
9
|
+
"label": "Sample scope",
|
|
10
|
+
"kind": "concept"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"migrations": [],
|
|
14
|
+
"fixtures": [],
|
|
15
|
+
"protocols": [
|
|
16
|
+
{
|
|
17
|
+
"id": "sample.readiness:contract-gate",
|
|
18
|
+
"schema": "atelier-readiness-protocol@v1",
|
|
19
|
+
"path": "protocols/contract-gate.v1.json",
|
|
20
|
+
"gate": "required",
|
|
21
|
+
"title": "Sample contract gate"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"lenses": [
|
|
25
|
+
{
|
|
26
|
+
"id": "sample.readiness:contract-gate-lens",
|
|
27
|
+
"title": "Sample contract gate lens",
|
|
28
|
+
"query": {
|
|
29
|
+
"protocolId": "sample.readiness:contract-gate"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"readinessRules": [
|
|
34
|
+
{
|
|
35
|
+
"id": "sample.readiness:scope-present",
|
|
36
|
+
"severity": "blocker",
|
|
37
|
+
"condition": "Scope name and evidence are present."
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"actionRules": [],
|
|
41
|
+
"exportMappings": [
|
|
42
|
+
{
|
|
43
|
+
"id": "sample.readiness:scope-export",
|
|
44
|
+
"sourceTerm": "sample.readiness:scope",
|
|
45
|
+
"target": "core.artifact"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
package/templates/launch.json
CHANGED
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
"configurations": [
|
|
4
4
|
{
|
|
5
5
|
"name": "atelier",
|
|
6
|
-
"runtimeExecutable": "
|
|
7
|
-
"runtimeArgs": [
|
|
6
|
+
"runtimeExecutable": "node",
|
|
7
|
+
"runtimeArgs": [
|
|
8
|
+
"--input-type=module",
|
|
9
|
+
"--eval",
|
|
10
|
+
"import { runCli } from '@mnstry/atelier/cli'; process.exit(await runCli({ argv: ['server', ...process.argv.slice(1)] }));"
|
|
11
|
+
],
|
|
8
12
|
"port": 8137,
|
|
9
13
|
"autoPort": true
|
|
10
14
|
}
|
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
"configurations": [
|
|
4
4
|
{
|
|
5
5
|
"name": "atelier",
|
|
6
|
-
"runtimeExecutable": "
|
|
7
|
-
"runtimeArgs": [
|
|
6
|
+
"runtimeExecutable": "node",
|
|
7
|
+
"runtimeArgs": [
|
|
8
|
+
"--input-type=module",
|
|
9
|
+
"--eval",
|
|
10
|
+
"import { runCli } from '@mnstry/atelier/cli'; process.exit(await runCli({ argv: ['server', ...process.argv.slice(1)] }));"
|
|
11
|
+
],
|
|
8
12
|
"port": 8137,
|
|
9
13
|
"autoPort": true
|
|
10
14
|
}
|