@mnstry/atelier 0.2.0-alpha.11 → 0.2.0-alpha.13
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 +1005 -0
- package/README.md +149 -9
- package/contracts/atelier-adoption-policy.v2.schema.json +55 -0
- package/contracts/atelier-architecture.v1.schema.json +258 -0
- package/contracts/atelier-boundary-delegations.v1.schema.json +161 -0
- package/contracts/atelier-boundary-owner-keys.v1.schema.json +98 -0
- package/contracts/atelier-build.v1.schema.json +1076 -0
- package/contracts/atelier-capability.v1.schema.json +1252 -0
- package/contracts/atelier-coordination.v1.schema.json +1050 -0
- package/contracts/atelier-evidence-navigation.v1.schema.json +603 -0
- package/contracts/atelier-harness.v1.schema.json +234 -0
- package/contracts/atelier-ingestion.v1.schema.json +806 -0
- package/contracts/atelier-inquiry.v1.schema.json +1772 -0
- package/contracts/atelier-instruction-adoption.v1.schema.json +490 -0
- package/contracts/atelier-interaction.v1.schema.json +553 -0
- package/contracts/atelier-judgment.v1.schema.json +690 -0
- package/contracts/atelier-knowledge.v1.schema.json +1512 -0
- package/contracts/atelier-learning.v1.schema.json +1095 -0
- package/contracts/atelier-migration.v3.schema.json +64 -0
- package/contracts/atelier-obsidian-generation-manifest.v2.schema.json +372 -0
- package/contracts/atelier-personal-workspace-manifest.v1.schema.json +87 -0
- package/contracts/atelier-personal-workspace-overlay.v1.schema.json +299 -0
- package/contracts/atelier-template-adoption.v1.schema.json +223 -0
- package/contracts/atelier-template-profile.v1.schema.json +1168 -0
- package/contracts/atelier-trackable.v1.schema.json +781 -0
- package/contracts/atelier-upgrade-plan.v3.schema.json +532 -0
- package/contracts/compat-baseline.json +1 -1
- package/docs/architecture.md +89 -0
- package/docs/assurance-controls.md +4 -3
- package/docs/blocks/capability-stewardship.md +17 -0
- package/docs/blocks/claims.md +16 -3
- package/docs/blocks/inquiry-harnesses.md +19 -0
- package/docs/blocks/learning-harnesses.md +17 -0
- package/docs/capability-stewardship.md +269 -0
- package/docs/coordination.md +51 -0
- package/docs/decision-practices.md +111 -0
- package/docs/decisions.md +29 -0
- package/docs/evidence-navigation.md +237 -0
- package/docs/exact-upgrades.md +3 -2
- package/docs/ingestion.md +181 -0
- package/docs/inquiry-harnesses.md +211 -0
- package/docs/install.md +80 -3
- package/docs/intake-and-guides.md +5 -0
- package/docs/integration-contract-decisions.md +24 -2
- package/docs/interaction-and-reflection.md +72 -0
- package/docs/knowledge-graph.md +20 -0
- package/docs/knowledge-health/api.md +30 -0
- package/docs/knowledge-health/assessment/api.md +96 -0
- package/docs/knowledge-health/assessment/capabilities.md +40 -0
- package/docs/knowledge-health/assessment/evaluation.md +27 -0
- package/docs/knowledge-health/assessment/facilitator.md +30 -0
- package/docs/knowledge-health/assessment/quickstart.md +61 -0
- package/docs/knowledge-health/assessment/troubleshooting.md +23 -0
- package/docs/knowledge-health/devday/facilitator.md +16 -0
- package/docs/knowledge-health/devday/participant-response.md +22 -0
- package/docs/knowledge-health/devday/public-default.md +107 -0
- package/docs/knowledge-health/devday/quickstart.md +18 -0
- package/docs/knowledge-health/devday/support.md +22 -0
- package/docs/knowledge-health/exercise.md +17 -0
- package/docs/knowledge-health/facilitator.md +20 -0
- package/docs/knowledge-health/quickstart.md +94 -0
- package/docs/knowledge-health/readme.md +15 -0
- package/docs/knowledge-health/support.md +34 -0
- package/docs/knowledge-setup.md +248 -0
- package/docs/knowledge-workspace.md +264 -0
- package/docs/learning-harnesses.md +238 -0
- package/docs/learning.md +215 -0
- package/docs/local-services.md +242 -26
- package/docs/obsidian-contract.md +878 -36
- package/docs/obsidian-plugin.md +619 -0
- package/docs/obsidian.md +809 -64
- package/docs/optional-ingestion.md +83 -0
- package/docs/personal-workspace.md +257 -0
- package/docs/practical-judgment.md +92 -0
- package/docs/progressive-ingestion-acceptance.md +89 -0
- package/docs/progressive-ingestion.md +235 -0
- package/docs/project-command-inventory.md +1 -0
- package/docs/release-engineering.md +56 -1
- package/docs/repo-boundary-guard.md +94 -0
- package/docs/research-starter-quickstart.md +66 -0
- package/docs/research-starter.md +114 -0
- package/docs/semantic-ingestion.md +198 -0
- package/docs/semantic-operation.md +317 -0
- package/docs/skill-steward.md +6 -0
- package/docs/template-profile.md +164 -0
- package/docs/template-upgrades.md +114 -0
- package/docs/trackables.md +111 -0
- package/docs/upgrade.md +68 -3
- package/fixtures/atelier-architecture/binding/invalid/document.json +19 -0
- package/fixtures/atelier-architecture/binding/valid/document.json +19 -0
- package/fixtures/atelier-architecture/catalog/invalid/document.json +290 -0
- package/fixtures/atelier-architecture/catalog/valid/document.json +343 -0
- package/fixtures/atelier-build-contract/attempt/invalid/document.json +20 -0
- package/fixtures/atelier-build-contract/attempt/valid/document.json +19 -0
- package/fixtures/atelier-build-contract/candidate/invalid/document.json +24 -0
- package/fixtures/atelier-build-contract/candidate/valid/document.json +23 -0
- package/fixtures/atelier-build-contract/decision/invalid/document.json +31 -0
- package/fixtures/atelier-build-contract/decision/valid/document.json +30 -0
- package/fixtures/atelier-build-contract/delivery/invalid/document.json +18 -0
- package/fixtures/atelier-build-contract/delivery/valid/document.json +17 -0
- package/fixtures/atelier-build-contract/gate/invalid/document.json +22 -0
- package/fixtures/atelier-build-contract/gate/valid/document.json +21 -0
- package/fixtures/atelier-build-contract/ledger/invalid/document.json +270 -0
- package/fixtures/atelier-build-contract/ledger/valid/document.json +269 -0
- package/fixtures/atelier-build-contract/objective/invalid/document.json +73 -0
- package/fixtures/atelier-build-contract/objective/valid/document.json +72 -0
- package/fixtures/atelier-build-contract/progress/invalid/document.json +18 -0
- package/fixtures/atelier-build-contract/progress/valid/document.json +17 -0
- package/fixtures/atelier-capability-contract/adoption/invalid/document.json +71 -0
- package/fixtures/atelier-capability-contract/adoption/valid/document.json +70 -0
- package/fixtures/atelier-capability-contract/event/invalid/document.json +18 -0
- package/fixtures/atelier-capability-contract/event/valid/document.json +17 -0
- package/fixtures/atelier-capability-contract/journal/invalid/document.json +382 -0
- package/fixtures/atelier-capability-contract/journal/valid/document.json +381 -0
- package/fixtures/atelier-capability-contract/notice/invalid/document.json +8 -0
- package/fixtures/atelier-capability-contract/notice/valid/document.json +7 -0
- package/fixtures/atelier-capability-contract/package/invalid/document.json +59 -0
- package/fixtures/atelier-capability-contract/package/valid/document.json +58 -0
- package/fixtures/atelier-capability-contract/plan/invalid/document.json +107 -0
- package/fixtures/atelier-capability-contract/plan/valid/document.json +106 -0
- package/fixtures/atelier-capability-contract/release/invalid/document.json +85 -0
- package/fixtures/atelier-capability-contract/release/valid/document.json +84 -0
- package/fixtures/atelier-capability-contract/state/invalid/document.json +316 -0
- package/fixtures/atelier-capability-contract/state/valid/document.json +315 -0
- package/fixtures/atelier-coordination/dependency/invalid/document.json +37 -0
- package/fixtures/atelier-coordination/dependency/valid/document.json +36 -0
- package/fixtures/atelier-coordination/directive/invalid/document.json +25 -0
- package/fixtures/atelier-coordination/directive/valid/document.json +24 -0
- package/fixtures/atelier-coordination/disposition/invalid/document.json +34 -0
- package/fixtures/atelier-coordination/disposition/valid/document.json +33 -0
- package/fixtures/atelier-coordination/outcome/invalid/document.json +39 -0
- package/fixtures/atelier-coordination/outcome/valid/document.json +38 -0
- package/fixtures/atelier-coordination/recovery/invalid/document.json +34 -0
- package/fixtures/atelier-coordination/recovery/valid/document.json +33 -0
- package/fixtures/atelier-harness-contract/handoff/invalid/document.json +25 -0
- package/fixtures/atelier-harness-contract/handoff/valid/document.json +24 -0
- package/fixtures/atelier-ingestion/invalid/authority.json +19 -0
- package/fixtures/atelier-ingestion/semantic-baseline.json +26 -0
- package/fixtures/atelier-ingestion/semantic-operation.json +75 -0
- package/fixtures/atelier-ingestion/valid/plan-input.json +18 -0
- package/fixtures/atelier-inquiry-contract/assessment/invalid/document.json +41 -0
- package/fixtures/atelier-inquiry-contract/assessment/valid/document.json +40 -0
- package/fixtures/atelier-inquiry-contract/bundle/invalid/document.json +51 -0
- package/fixtures/atelier-inquiry-contract/bundle/valid/document.json +50 -0
- package/fixtures/atelier-inquiry-contract/campaign/invalid/document.json +17 -0
- package/fixtures/atelier-inquiry-contract/campaign/valid/document.json +16 -0
- package/fixtures/atelier-inquiry-contract/decision/invalid/document.json +22 -0
- package/fixtures/atelier-inquiry-contract/decision/valid/document.json +21 -0
- package/fixtures/atelier-inquiry-contract/feedback/invalid/document.json +19 -0
- package/fixtures/atelier-inquiry-contract/feedback/valid/document.json +18 -0
- package/fixtures/atelier-inquiry-contract/handoff/invalid/document.json +92 -0
- package/fixtures/atelier-inquiry-contract/handoff/valid/document.json +91 -0
- package/fixtures/atelier-inquiry-contract/hypothesis/invalid/document.json +20 -0
- package/fixtures/atelier-inquiry-contract/hypothesis/valid/document.json +19 -0
- package/fixtures/atelier-inquiry-contract/ledger/invalid/document.json +680 -0
- package/fixtures/atelier-inquiry-contract/ledger/valid/document.json +679 -0
- package/fixtures/atelier-inquiry-contract/legacy-assessment/invalid/document.json +19 -0
- package/fixtures/atelier-inquiry-contract/legacy-assessment/valid/document.json +18 -0
- package/fixtures/atelier-inquiry-contract/request/invalid/document.json +50 -0
- package/fixtures/atelier-inquiry-contract/request/valid/document.json +49 -0
- package/fixtures/atelier-inquiry-contract/source/invalid/document.json +18 -0
- package/fixtures/atelier-inquiry-contract/source/valid/document.json +17 -0
- package/fixtures/atelier-inquiry-contract/withdrawal/invalid/document.json +16 -0
- package/fixtures/atelier-inquiry-contract/withdrawal/valid/document.json +15 -0
- package/fixtures/atelier-instruction-adoption/context-receipt/invalid/document.json +18 -0
- package/fixtures/atelier-instruction-adoption/context-receipt/valid/document.json +17 -0
- package/fixtures/atelier-instruction-adoption/plan/invalid/document.json +63 -0
- package/fixtures/atelier-instruction-adoption/plan/valid/document.json +62 -0
- package/fixtures/atelier-instruction-adoption/receipt/invalid/document.json +22 -0
- package/fixtures/atelier-instruction-adoption/receipt/valid/document.json +21 -0
- package/fixtures/atelier-instruction-adoption/state/invalid/document.json +30 -0
- package/fixtures/atelier-instruction-adoption/state/valid/document.json +29 -0
- package/fixtures/atelier-interaction/act/invalid/document.json +25 -0
- package/fixtures/atelier-interaction/act/valid/document.json +24 -0
- package/fixtures/atelier-interaction/assessment/invalid/document.json +32 -0
- package/fixtures/atelier-interaction/assessment/valid/document.json +31 -0
- package/fixtures/atelier-interaction/observation/invalid/document.json +22 -0
- package/fixtures/atelier-interaction/observation/valid/document.json +21 -0
- package/fixtures/atelier-interaction/policy/invalid/document.json +20 -0
- package/fixtures/atelier-interaction/policy/valid/document.json +19 -0
- package/fixtures/atelier-judgment/case/invalid/document.json +76 -0
- package/fixtures/atelier-judgment/case/valid/document.json +75 -0
- package/fixtures/atelier-judgment/decision/invalid/document.json +38 -0
- package/fixtures/atelier-judgment/decision/valid/document.json +37 -0
- package/fixtures/atelier-judgment/native-decision.md +3 -0
- package/fixtures/atelier-judgment/practice-reconsideration/definition.json +92 -0
- package/fixtures/atelier-judgment/practice-reconsideration/scenario.json +435 -0
- package/fixtures/atelier-knowledge-contract/activation/invalid/document.json +26 -0
- package/fixtures/atelier-knowledge-contract/activation/valid/document.json +25 -0
- package/fixtures/atelier-knowledge-contract/contribution/invalid/document.json +34 -0
- package/fixtures/atelier-knowledge-contract/contribution/valid/document.json +33 -0
- package/fixtures/atelier-knowledge-contract/domain/invalid/document.json +41 -0
- package/fixtures/atelier-knowledge-contract/domain/valid/document.json +40 -0
- package/fixtures/atelier-knowledge-contract/domain-revision/invalid/document.json +46 -0
- package/fixtures/atelier-knowledge-contract/domain-revision/valid/document.json +45 -0
- package/fixtures/atelier-knowledge-contract/evaluation/invalid/document.json +21 -0
- package/fixtures/atelier-knowledge-contract/evaluation/valid/document.json +20 -0
- package/fixtures/atelier-knowledge-contract/ledger/invalid/document.json +318 -0
- package/fixtures/atelier-knowledge-contract/ledger/valid/document.json +317 -0
- package/fixtures/atelier-knowledge-contract/relation/invalid/document.json +25 -0
- package/fixtures/atelier-knowledge-contract/relation/valid/document.json +24 -0
- package/fixtures/atelier-knowledge-contract/review/invalid/document.json +18 -0
- package/fixtures/atelier-knowledge-contract/review/valid/document.json +17 -0
- package/fixtures/atelier-knowledge-contract/withdrawal/invalid/document.json +16 -0
- package/fixtures/atelier-knowledge-contract/withdrawal/valid/document.json +15 -0
- package/fixtures/atelier-learning/invalid/authority.json +14 -0
- package/fixtures/atelier-learning/valid/capture.json +13 -0
- package/fixtures/atelier-personal-workspace-contract/manifest/invalid/authority-key.json +17 -0
- package/fixtures/atelier-personal-workspace-contract/manifest/invalid/nonempty-ext.json +25 -0
- package/fixtures/atelier-personal-workspace-contract/manifest/invalid/wrong-schema.json +22 -0
- package/fixtures/atelier-personal-workspace-contract/manifest/valid/manifest.json +22 -0
- package/fixtures/atelier-personal-workspace-contract/overlay/invalid/authority-key.json +25 -0
- package/fixtures/atelier-personal-workspace-contract/overlay/invalid/unknown-top-level-field.json +27 -0
- package/fixtures/atelier-personal-workspace-contract/overlay/invalid/wrong-schema.json +24 -0
- package/fixtures/atelier-trackable/definition/invalid/document.json +15 -0
- package/fixtures/atelier-trackable/definition/valid/document.json +14 -0
- package/fixtures/atelier-trackable/request/invalid/document.json +23 -0
- package/fixtures/atelier-trackable/request/valid/document.json +22 -0
- package/fixtures/boundary-delegations/invalid/authority-key.v1.json +30 -0
- package/fixtures/boundary-delegations/invalid/push-operation.v1.json +28 -0
- package/fixtures/boundary-delegations/invalid/unsigned.v1.json +25 -0
- package/fixtures/boundary-delegations/valid/empty.v1.json +4 -0
- package/fixtures/boundary-delegations/valid/signed-operator.v1.json +30 -0
- package/fixtures/boundary-owner-keys/invalid/wrong-algorithm.v1.json +15 -0
- package/fixtures/boundary-owner-keys/invalid/wrong-curve.v1.json +15 -0
- package/fixtures/boundary-owner-keys/valid/one-owner.v1.json +17 -0
- package/fixtures/capability-packages/adoption.example.json +70 -0
- package/fixtures/capability-packages/evidence-review/capability-package.json +58 -0
- package/fixtures/capability-packages/evidence-review/capability-release.json +84 -0
- package/fixtures/capability-packages/evidence-review/evaluation.md +15 -0
- package/fixtures/capability-packages/evidence-review/skills/evidence-review/SKILL.md +22 -0
- package/fixtures/capability-packages/evidence-review/skills/evidence-review/references/ledger.md +7 -0
- package/fixtures/capability-packages/research/capability-package.json +88 -0
- package/fixtures/capability-packages/research/capability-release.json +134 -0
- package/fixtures/capability-packages/research/evaluation.md +15 -0
- package/fixtures/capability-packages/research/skills/research-integrate/SKILL.md +29 -0
- package/fixtures/capability-packages/research/skills/research-integrate/references/integration.md +10 -0
- package/fixtures/capability-packages/research/skills/research-plan/SKILL.md +27 -0
- package/fixtures/capability-packages/research/skills/research-plan/references/inquiries.md +26 -0
- package/fixtures/capability-packages/research/skills/research-synthesize/SKILL.md +23 -0
- package/fixtures/capability-packages/research/skills/research-synthesize/references/synthesis.md +12 -0
- package/fixtures/evidence-navigation/invalid/duplicate-operation.json +16 -0
- package/fixtures/evidence-navigation/invalid/instruction-kind.json +36 -0
- package/fixtures/evidence-navigation/invalid/invalid-digest.json +36 -0
- package/fixtures/evidence-navigation/invalid/invalid-time.json +36 -0
- package/fixtures/evidence-navigation/invalid/missing-attribution.json +35 -0
- package/fixtures/evidence-navigation/invalid/reserved-extension.json +19 -0
- package/fixtures/evidence-navigation/invalid/unattributed-acceptance.json +36 -0
- package/fixtures/evidence-navigation/invalid/uncoerced-version.json +16 -0
- package/fixtures/evidence-navigation/invalid/unknown-currency.json +17 -0
- package/fixtures/evidence-navigation/invalid/unknown-selector-field.json +37 -0
- package/fixtures/evidence-navigation/invalid/unsupported-operation.json +15 -0
- package/fixtures/evidence-navigation/valid/claim.json +36 -0
- package/fixtures/evidence-navigation/valid/host.json +16 -0
- package/fixtures/evidence-navigation/valid/profile.json +16 -0
- package/fixtures/evidence-navigation/valid/snapshot.json +17 -0
- package/fixtures/harness-packages/build-harness/capability-package.json +61 -0
- package/fixtures/harness-packages/build-harness/capability-release.json +82 -0
- package/fixtures/harness-packages/build-harness/evaluation.md +3 -0
- package/fixtures/harness-packages/build-harness/skills/atelier-build-harness/SKILL.md +59 -0
- package/fixtures/harness-packages/knowledge-harness/capability-package.json +61 -0
- package/fixtures/harness-packages/knowledge-harness/capability-release.json +82 -0
- package/fixtures/harness-packages/knowledge-harness/evaluation.md +3 -0
- package/fixtures/harness-packages/knowledge-harness/skills/atelier-knowledge-harness/SKILL.md +60 -0
- package/fixtures/harnesses/learning-cycle.json +780 -0
- package/fixtures/inquiry/workshop.json +675 -0
- package/fixtures/inquiry-packages/discovery-harness/capability-package.json +61 -0
- package/fixtures/inquiry-packages/discovery-harness/capability-release.json +82 -0
- package/fixtures/inquiry-packages/discovery-harness/evaluation.md +3 -0
- package/fixtures/inquiry-packages/discovery-harness/skills/atelier-discovery-harness/SKILL.md +48 -0
- package/fixtures/inquiry-packages/research-harness/capability-package.json +61 -0
- package/fixtures/inquiry-packages/research-harness/capability-release.json +82 -0
- package/fixtures/inquiry-packages/research-harness/evaluation.md +3 -0
- package/fixtures/inquiry-packages/research-harness/skills/atelier-research-harness/SKILL.md +43 -0
- package/fixtures/knowledge-health/calibration-suite.json +26 -0
- package/fixtures/knowledge-health/calibration-trial.json +37 -0
- package/fixtures/knowledge-health/corrected/checklist.md +18 -0
- package/fixtures/knowledge-health/devday/participant-record.json +19 -0
- package/fixtures/knowledge-health/expected-summary.json +27 -0
- package/fixtures/knowledge-health/workshop/README.md +20 -0
- package/fixtures/knowledge-health/workshop/atelier.project.json +7 -0
- package/fixtures/knowledge-health/workshop/knowledge-plan.json +65 -0
- package/fixtures/knowledge-health/workshop/records/checklist.md +18 -0
- package/fixtures/knowledge-health/workshop/records/workshop.md +18 -0
- package/fixtures/knowledge-health/workshop/repo-access.v1.json +5 -0
- package/fixtures/knowledge-health/workspace/atelier.project.json +18 -0
- package/fixtures/knowledge-health/workspace/knowledge-plan.json +74 -0
- package/fixtures/knowledge-health/workspace/records/checklist.md +18 -0
- package/fixtures/knowledge-health/workspace/records/pilot.md +16 -0
- package/fixtures/knowledge-health/workspace/repo-access.v1.json +9 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/case-only-collision.v2.json +160 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/flat-note-path.v2.json +160 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/hidden-folder.v2.json +160 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/identity-in-the-body.v2.json +160 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/link-breaking-name.v2.json +160 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/missing-identity-region.v2.json +156 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/missing-layout-version.v2.json +159 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/note-named-like-a-folder.v2.json +160 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/unknown-region-kind.v2.json +160 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/invalid/v1-contract-version.v2.json +161 -0
- package/fixtures/obsidian/contracts/generation-manifest-v2/valid/three-notes.v2.json +160 -0
- package/fixtures/obsidian/edits/workspace.json +1 -1
- package/fixtures/obsidian/materialization/expected-full.json +21 -21
- package/fixtures/obsidian/materialization/expected-full.layout-1.json +99 -0
- package/fixtures/obsidian/materialization/expected-scoped.json +7 -7
- package/fixtures/obsidian/materialization/expected-scoped.layout-1.json +39 -0
- package/fixtures/personal-workspace/overlay.json +24 -0
- package/fixtures/templates/local-library.v1.json +75 -0
- package/fixtures/templates/upgrade-contracts/adoption-policy.v2/invalid.json +16 -0
- package/fixtures/templates/upgrade-contracts/adoption-policy.v2/valid.json +13 -0
- package/fixtures/templates/upgrade-contracts/migration.v3/invalid.json +24 -0
- package/fixtures/templates/upgrade-contracts/migration.v3/valid.json +21 -0
- package/fixtures/templates/upgrade-contracts/template-adoption.v1/invalid.json +60 -0
- package/fixtures/templates/upgrade-contracts/template-adoption.v1/valid.json +57 -0
- package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/invalid.json +85 -0
- package/fixtures/templates/upgrade-contracts/upgrade-plan.v3/valid.json +82 -0
- package/package.json +64 -6
- package/plugins/obsidian/main.js +444 -0
- package/plugins/obsidian/manifest.json +9 -0
- package/plugins/obsidian/styles.css +22 -0
- package/skills/claude/atelier-build-harness/SKILL.md +59 -0
- package/skills/claude/atelier-coordination/SKILL.md +32 -0
- package/skills/claude/atelier-discovery-harness/SKILL.md +48 -0
- package/skills/claude/atelier-guided-upgrade/SKILL.md +29 -0
- package/skills/claude/atelier-interaction/SKILL.md +34 -0
- package/skills/claude/atelier-knowledge-harness/SKILL.md +60 -0
- package/skills/claude/atelier-knowledge-setup/SKILL.md +72 -0
- package/skills/claude/atelier-practical-judgment/SKILL.md +64 -0
- package/skills/claude/atelier-research-harness/SKILL.md +43 -0
- package/skills/claude/atelier-skill-steward/SKILL.md +53 -0
- package/skills/claude/atelier-trackables/SKILL.md +40 -0
- package/skills/codex/atelier-build-harness/SKILL.md +59 -0
- package/skills/codex/atelier-coordination/SKILL.md +32 -0
- package/skills/codex/atelier-discovery-harness/SKILL.md +48 -0
- package/skills/codex/atelier-guided-upgrade/SKILL.md +29 -0
- package/skills/codex/atelier-interaction/SKILL.md +34 -0
- package/skills/codex/atelier-knowledge-harness/SKILL.md +60 -0
- package/skills/codex/atelier-knowledge-setup/SKILL.md +72 -0
- package/skills/codex/atelier-practical-judgment/SKILL.md +64 -0
- package/skills/codex/atelier-research-harness/SKILL.md +43 -0
- package/skills/codex/atelier-skill-steward/SKILL.md +53 -0
- package/skills/codex/atelier-trackables/SKILL.md +40 -0
- package/src/architecture/catalog.mjs +355 -0
- package/src/architecture/index.mjs +93 -0
- package/src/boundary/content-rules.mjs +4 -2
- package/src/boundary/delegation-command.mjs +158 -0
- package/src/boundary/delegation.mjs +396 -0
- package/src/boundary/policy.mjs +52 -10
- package/src/build/git.mjs +18 -0
- package/src/build/index.mjs +3 -0
- package/src/build/ledger.mjs +88 -0
- package/src/capabilities/adoption.mjs +381 -0
- package/src/capabilities/evidence.mjs +140 -0
- package/src/capabilities/files.mjs +124 -0
- package/src/capabilities/index.mjs +4 -0
- package/src/capabilities/instructions.mjs +250 -0
- package/src/capabilities/package.mjs +136 -0
- package/src/cli/command-failure.mjs +36 -0
- package/src/cli/execute-command.mjs +16 -2
- package/src/cli/run.mjs +65 -9
- package/src/coauthor/store.mjs +43 -2
- package/src/collaboration/proposals.mjs +189 -0
- package/src/commands/architecture.mjs +27 -0
- package/src/commands/boundary.mjs +3 -0
- package/src/commands/capability.mjs +73 -0
- package/src/commands/enroll.mjs +3 -0
- package/src/commands/harness.mjs +79 -0
- package/src/commands/ingest.mjs +39 -0
- package/src/commands/init.mjs +4 -1
- package/src/commands/inquiry.mjs +66 -0
- package/src/commands/knowledge-semantic.mjs +128 -0
- package/src/commands/knowledge.mjs +119 -0
- package/src/commands/learn.mjs +61 -0
- package/src/commands/obsidian.mjs +832 -62
- package/src/commands/practice.mjs +24 -0
- package/src/commands/setup.mjs +22 -2
- package/src/commands/trackable.mjs +19 -0
- package/src/contracts/corpus.mjs +36 -0
- package/src/coordination/index.mjs +110 -0
- package/src/egress/forbidden-egress.mjs +2 -0
- package/src/evidence-navigation/contracts.mjs +60 -0
- package/src/evidence-navigation/evaluate.mjs +69 -0
- package/src/evidence-navigation/generation.mjs +22 -0
- package/src/evidence-navigation/index.mjs +2 -0
- package/src/evidence-navigation/local.mjs +167 -0
- package/src/evidence-navigation/schema.generated.mjs +604 -0
- package/src/evidence-navigation/types.mjs +12 -0
- package/src/export/atelier-export-contract.mjs +35 -8
- package/src/graph/enroll.mjs +248 -0
- package/src/graph/graph.mjs +17 -1
- package/src/graph/knowledge-graph.mjs +58 -8
- package/src/harnesses/contracts.mjs +41 -0
- package/src/harnesses/exchange.mjs +154 -0
- package/src/harnesses/feedback.mjs +16 -0
- package/src/harnesses/history.mjs +37 -0
- package/src/harnesses/index.mjs +4 -0
- package/src/harnesses/store.mjs +29 -0
- package/src/ingestion/contracts.mjs +41 -0
- package/src/ingestion/evaluation.mjs +119 -0
- package/src/ingestion/optional/composition/index.mjs +171 -0
- package/src/ingestion/optional/evaluation/index.mjs +219 -0
- package/src/ingestion/optional/graphify/composition-binding.mjs +60 -0
- package/src/ingestion/optional/graphify/composition_receiving.py +185 -0
- package/src/ingestion/optional/graphify/graphify_supplier.py +933 -0
- package/src/ingestion/optional/graphify/json_bridge.py +163 -0
- package/src/ingestion/optional/graphify/query_receiving.py +209 -0
- package/src/ingestion/optional/index.mjs +9 -0
- package/src/ingestion/optional/jev/bridge.mjs +166 -0
- package/src/ingestion/optional/jev/composition-binding.mjs +116 -0
- package/src/ingestion/optional/jev/judgments.mjs +174 -0
- package/src/ingestion/optional/jev/native-translation.mjs +32 -0
- package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/__init__.py +7 -0
- package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/adapter.py +966 -0
- package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/artifacts.py +101 -0
- package/src/ingestion/optional/lightrag/atelier_lightrag_supplier/projection.py +146 -0
- package/src/ingestion/optional/lightrag/composition-binding.mjs +67 -0
- package/src/ingestion/optional/vanilla/composition-binding.mjs +102 -0
- package/src/ingestion/optional/vanilla/index.mjs +218 -0
- package/src/ingestion/optional/vanilla/native-normalization.mjs +187 -0
- package/src/ingestion/processors.mjs +218 -0
- package/src/ingestion/semantic.mjs +203 -0
- package/src/ingestion/store.mjs +372 -0
- package/src/inquiry/beliefs.mjs +32 -0
- package/src/inquiry/contracts.mjs +23 -0
- package/src/inquiry/index.mjs +5 -0
- package/src/inquiry/ledger.mjs +135 -0
- package/src/inquiry/lenses.mjs +15 -0
- package/src/inquiry/projection.mjs +77 -0
- package/src/inquiry/store.mjs +35 -0
- package/src/intake/read-scope.mjs +12 -0
- package/src/intake/store.mjs +69 -6
- package/src/interaction/index.mjs +91 -0
- package/src/judgment/index.mjs +82 -0
- package/src/judgment/practice-evaluation.mjs +70 -0
- package/src/judgment/practice.mjs +144 -0
- package/src/knowledge/context.mjs +217 -0
- package/src/knowledge/index.mjs +5 -0
- package/src/knowledge/ingestion.mjs +79 -0
- package/src/knowledge/intake.mjs +33 -0
- package/src/knowledge/ledger.mjs +110 -0
- package/src/knowledge/participatory/guidance.mjs +36 -0
- package/src/knowledge/participatory/guided-contribution.mjs +44 -0
- package/src/knowledge/participatory/index.mjs +2 -0
- package/src/knowledge/participatory/installed-workshop.mjs +108 -0
- package/src/knowledge/plan.mjs +67 -0
- package/src/knowledge/projection.mjs +43 -0
- package/src/knowledge/semantic-operation.mjs +567 -0
- package/src/knowledge/sessions.mjs +467 -0
- package/src/knowledge/workspace.mjs +295 -0
- package/src/knowledge-health/assessment.mjs +165 -0
- package/src/knowledge-health/capabilities.mjs +350 -0
- package/src/knowledge-health/context.mjs +62 -0
- package/src/knowledge-health/example.mjs +47 -0
- package/src/knowledge-health/index.mjs +10 -0
- package/src/knowledge-health/owner-join.mjs +88 -0
- package/src/knowledge-health/proof/common.mjs +24 -0
- package/src/knowledge-health/proof/installed-check.mjs +100 -0
- package/src/knowledge-health/proof/native-readback.mjs +37 -0
- package/src/knowledge-health/proof/rehearse.mjs +68 -0
- package/src/knowledge-health/proof/validate-participant.mjs +17 -0
- package/src/knowledge-health/proof/verify-native-capture.mjs +14 -0
- package/src/knowledge-health/proof/workshop-check.mjs +36 -0
- package/src/knowledge-health/rule-identity.mjs +44 -0
- package/src/knowledge-health/workshop-composition.mjs +19 -0
- package/src/knowledge-health/workshop-profile.mjs +176 -0
- package/src/knowledge-health/workshop.mjs +99 -0
- package/src/learning/adapters.mjs +68 -0
- package/src/learning/assistance.mjs +127 -0
- package/src/learning/contracts.mjs +65 -0
- package/src/learning/store.mjs +272 -0
- package/src/personal-workspace/index.mjs +391 -0
- package/src/personal-workspace/selection.mjs +385 -0
- package/src/project/config.mjs +8 -0
- package/src/project/durable-state.mjs +3 -1
- package/src/project/file-class.mjs +1 -1
- package/src/project/private-state.mjs +10 -1
- package/src/projection/obsidian/contracts.mjs +224 -18
- package/src/projection/obsidian/edits/apply.mjs +63 -19
- package/src/projection/obsidian/edits/regions.mjs +137 -42
- package/src/projection/obsidian/materialize/index.mjs +6 -3
- package/src/projection/obsidian/materialize/path-registry.mjs +443 -57
- package/src/projection/obsidian/materialize/prepare-view.mjs +382 -131
- package/src/projection/obsidian/materialize/redaction.mjs +327 -0
- package/src/projection/obsidian/materialize/settings.mjs +113 -34
- package/src/projection/obsidian/personal-workspace.mjs +436 -0
- package/src/projection/obsidian/plugin-bridge/bundle.mjs +50 -0
- package/src/projection/obsidian/plugin-bridge/channel.mjs +174 -0
- package/src/projection/obsidian/plugin-bridge/index.mjs +10 -0
- package/src/projection/obsidian/proposals/adapter.mjs +47 -8
- package/src/projection/obsidian/proposals/observation.mjs +20 -7
- package/src/projection/obsidian/publication/bridge-script.mjs +11 -5
- package/src/projection/obsidian/publication/index.mjs +2 -1
- package/src/projection/obsidian/publication/publisher.mjs +312 -36
- package/src/projection/obsidian/publication/transport.mjs +63 -8
- package/src/projection/obsidian/publication/vault-list.mjs +200 -0
- package/src/projection/obsidian/recovery/index.mjs +4 -1
- package/src/projection/obsidian/recovery/restart.mjs +3 -1
- package/src/projection/obsidian/recovery/store.mjs +168 -8
- package/src/projection/obsidian/selection-ui/contribution.mjs +6 -5
- package/src/projection/obsidian/selection-ui/focus.mjs +14 -7
- package/src/projection/obsidian/selection-ui/selection-state.mjs +2 -2
- package/src/projection/obsidian/selection-ui/selection.mjs +8 -3
- package/src/readiness/readiness.mjs +10 -3
- package/src/reflection/index.mjs +56 -0
- package/src/runtime/obsidian/app-capability.mjs +104 -12
- package/src/runtime/obsidian/app-production-seams.mjs +161 -42
- package/src/runtime/obsidian/app-registration.mjs +313 -0
- package/src/runtime/obsidian/app-restart.mjs +154 -0
- package/src/runtime/obsidian/engine.mjs +288 -29
- package/src/runtime/obsidian/extension-points.mjs +1 -1
- package/src/runtime/obsidian/index.mjs +15 -8
- package/src/runtime/obsidian/launch-plan.mjs +91 -0
- package/src/runtime/obsidian/lifecycle.mjs +193 -22
- package/src/runtime/obsidian/login-item.mjs +332 -0
- package/src/runtime/obsidian/machine-settings.mjs +119 -12
- package/src/runtime/obsidian/opening.mjs +369 -63
- package/src/runtime/obsidian/pending-edits.mjs +10 -0
- package/src/runtime/obsidian/pipeline.mjs +71 -3
- package/src/runtime/obsidian/plugin-channel.mjs +289 -0
- package/src/runtime/obsidian/plugin-choice.mjs +182 -0
- package/src/runtime/obsidian/plugin-drift.mjs +124 -0
- package/src/runtime/obsidian/plugin-presence.mjs +61 -0
- package/src/runtime/obsidian/process-identity.mjs +20 -10
- package/src/runtime/obsidian/project-views.mjs +282 -0
- package/src/runtime/obsidian/questions.mjs +48 -0
- package/src/runtime/obsidian/release-watch.mjs +56 -0
- package/src/runtime/obsidian/service-main.mjs +113 -17
- package/src/runtime/obsidian/service-manager-production.mjs +61 -0
- package/src/runtime/obsidian/service-managers.mjs +275 -0
- package/src/runtime/obsidian/service-record.mjs +105 -5
- package/src/runtime/obsidian/service-server.mjs +50 -12
- package/src/runtime/obsidian/service.mjs +134 -7
- package/src/runtime/obsidian/startup-adapters.mjs +59 -21
- package/src/runtime/obsidian/state-store.mjs +13 -1
- package/src/runtime/obsidian/unheld-evidence.mjs +84 -0
- package/src/runtime/obsidian/vault-location.mjs +300 -0
- package/src/runtime/obsidian/view-counts.mjs +34 -0
- package/src/server/local-sidecar.mjs +193 -7
- package/src/server/server.mjs +45 -6
- package/src/template-bindings/project.mjs +92 -0
- package/src/templates/profile.mjs +225 -0
- package/src/trackables/domain.mjs +175 -0
- package/src/trackables/store.mjs +114 -0
- package/src/ui/knowledge-page.mjs +1388 -0
- package/src/upgrade/explanation.mjs +1 -1
- package/src/upgrade/template-participant.mjs +171 -0
- package/src/upgrade/transaction.mjs +72 -25
- package/src/upgrade/upgrade.mjs +2 -1
- package/templates/external-project-workspace/pack-lifecycle.json +6 -1
- package/templates/knowledge-workspace/.gitattributes +2 -0
- package/templates/knowledge-workspace/AGENTS.md +27 -0
- package/templates/knowledge-workspace/README.md +44 -0
- package/templates/knowledge-workspace/atelier.project.json +22 -0
- package/templates/knowledge-workspace/gitignore +6 -0
- package/templates/knowledge-workspace/knowledge-plan.json +111 -0
- package/templates/knowledge-workspace/knowledge-plan.schema.json +281 -0
- package/templates/knowledge-workspace/records/forecast.md +22 -0
- package/templates/knowledge-workspace/records/inspection.md +25 -0
- package/templates/knowledge-workspace/records/telescope.md +24 -0
- package/templates/knowledge-workspace/repo-access.v1.json +9 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import { createHash } from 'node:crypto'
|
|
3
3
|
import { validateJsonSchema } from '../../export/atelier-export-contract.mjs'
|
|
4
|
+
import { titleCase } from '../../graph/knowledge-graph.mjs'
|
|
4
5
|
|
|
5
6
|
// Obsidian projection contracts: closed v1 document shapes, the checks a JSON
|
|
6
7
|
// schema cannot express, and the scope selector algebra.
|
|
@@ -29,12 +30,15 @@ const MAX_SELECTOR_DEPTH = 64
|
|
|
29
30
|
|
|
30
31
|
// Portable shapes may be committed or shared and must never carry a
|
|
31
32
|
// machine-local absolute path, port or policy. Private shapes live only in
|
|
32
|
-
// ignored machine-private state.
|
|
33
|
+
// ignored machine-private state. A shape registered in more than one major
|
|
34
|
+
// version is validated against the version its `schema` names; the generation
|
|
35
|
+
// manifest has two, one per vault layout.
|
|
33
36
|
export const OBSIDIAN_CONTRACTS = Object.freeze([
|
|
34
37
|
['corpus-profile', 'portable'],
|
|
35
38
|
['scope', 'portable'],
|
|
36
39
|
['source-snapshot', 'portable'],
|
|
37
40
|
['generation-manifest', 'portable'],
|
|
41
|
+
['generation-manifest', 'portable', 2],
|
|
38
42
|
['publication-journal', 'private'],
|
|
39
43
|
['service-state', 'private'],
|
|
40
44
|
['edit-operation', 'portable'],
|
|
@@ -42,13 +46,14 @@ export const OBSIDIAN_CONTRACTS = Object.freeze([
|
|
|
42
46
|
['proposal-receipt', 'portable'],
|
|
43
47
|
['acceptance-receipt', 'portable'],
|
|
44
48
|
['ext-settings', 'portable'],
|
|
45
|
-
].map(([shape, portability]) => Object.freeze({
|
|
49
|
+
].map(([shape, portability, version = 1]) => Object.freeze({
|
|
46
50
|
shape,
|
|
47
51
|
portability,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
version,
|
|
53
|
+
name: version === 1 ? `atelier-obsidian-${shape}` : `atelier-obsidian-${shape}-v${version}`,
|
|
54
|
+
schemaConst: `atelier-obsidian-${shape}/v${version}`,
|
|
55
|
+
contractFile: `contracts/atelier-obsidian-${shape}.v${version}.schema.json`,
|
|
56
|
+
fixtureRoot: version === 1 ? `fixtures/obsidian/contracts/${shape}` : `fixtures/obsidian/contracts/${shape}-v${version}`,
|
|
52
57
|
})))
|
|
53
58
|
|
|
54
59
|
export class ObsidianContractRefusal extends Error {
|
|
@@ -80,18 +85,33 @@ function compareIds(left, right) {
|
|
|
80
85
|
|
|
81
86
|
const schemaCache = new Map()
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
// The contract a document is validated against: the registered version its
|
|
89
|
+
// `schema` names, else the first version of the shape, whose refusal then
|
|
90
|
+
// names the mismatch.
|
|
91
|
+
function contractFor(shape, doc) {
|
|
92
|
+
const versions = OBSIDIAN_CONTRACTS.filter((item) => item.shape === shape)
|
|
93
|
+
if (versions.length === 0) refuse('unknown-contract-shape', 'no Obsidian contract is registered for the requested shape')
|
|
94
|
+
return versions.find((item) => isPlainObject(doc) && doc.schema === item.schemaConst) ?? versions[0]
|
|
87
95
|
}
|
|
88
96
|
|
|
89
97
|
function loadSchema(contract) {
|
|
90
|
-
if (!schemaCache.has(contract.
|
|
98
|
+
if (!schemaCache.has(contract.name)) {
|
|
91
99
|
const url = new URL(`../../../${contract.contractFile}`, import.meta.url)
|
|
92
|
-
schemaCache.set(contract.
|
|
100
|
+
schemaCache.set(contract.name, JSON.parse(fs.readFileSync(url, 'utf8')))
|
|
93
101
|
}
|
|
94
|
-
return schemaCache.get(contract.
|
|
102
|
+
return schemaCache.get(contract.name)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Whether a value is an identifier as the contracts define one: the
|
|
106
|
+
// `identifier` of the scope contract, which names a view, read from the
|
|
107
|
+
// shipped contract rather than restated.
|
|
108
|
+
let identifierRule = null
|
|
109
|
+
export function isContractIdentifier(value) {
|
|
110
|
+
if (identifierRule === null) {
|
|
111
|
+
const { minLength, maxLength, pattern } = loadSchema(contractFor('scope')).$defs.identifier
|
|
112
|
+
identifierRule = { minLength, maxLength, pattern: new RegExp(pattern, 'u') }
|
|
113
|
+
}
|
|
114
|
+
return typeof value === 'string' && value.length >= identifierRule.minLength && value.length <= identifierRule.maxLength && identifierRule.pattern.test(value)
|
|
95
115
|
}
|
|
96
116
|
|
|
97
117
|
const ABSOLUTE_PATH = /^(?:\/|~[\\/]|[A-Za-z]:[\\/]|\\\\|file:)/
|
|
@@ -172,12 +192,30 @@ const SEMANTIC_CHECKS = {
|
|
|
172
192
|
}
|
|
173
193
|
})
|
|
174
194
|
},
|
|
175
|
-
'generation-manifest'(doc, errors) {
|
|
195
|
+
'generation-manifest'(doc, errors, version) {
|
|
176
196
|
const identities = doc.notes.map((note) => `${note.repoId}\u0000${note.nodeId}`)
|
|
177
197
|
if (duplicates(identities).length > 0) errors.push({ code: 'duplicate-identity', message: '/notes repeats a canonical identity' })
|
|
178
198
|
if (duplicates(doc.notes.map((note) => note.path.toLowerCase())).length > 0) {
|
|
179
199
|
errors.push({ code: 'path-collision', message: '/notes allocates one path to more than one note' })
|
|
180
200
|
}
|
|
201
|
+
if (version === 2) {
|
|
202
|
+
// Notes and files share folders in layout 2: no two of them may be one file on a case- or
|
|
203
|
+
// normalization-insensitive file system, and no file may have the name of a folder.
|
|
204
|
+
const files = [...doc.notes.map((note) => note.path), ...doc.attachments.map((attachment) => attachment.path)]
|
|
205
|
+
if (duplicates(files.map(collisionKey)).length > 0) errors.push({ code: 'path-collision', message: '/notes and /attachments allocate one path to more than one file' })
|
|
206
|
+
const folders = new Set(files.flatMap((file) => file.split('/').slice(0, -1).map((_, index, parts) => collisionKey(parts.slice(0, index + 1).join('/')))))
|
|
207
|
+
if (files.some((file) => folders.has(collisionKey(file)))) errors.push({ code: 'path-collision', message: '/notes and /attachments give a file the name of a folder' })
|
|
208
|
+
doc.notes.forEach((note, index) => {
|
|
209
|
+
const { identity, body, generated } = note.regions
|
|
210
|
+
const last = generated.at(-1)
|
|
211
|
+
const inPrefix = identity.end <= body.start
|
|
212
|
+
const atEnd = last?.kind === 'identity' && last.range.start === identity.start && last.range.end === identity.end
|
|
213
|
+
if (!inPrefix && !atEnd) errors.push({ code: 'identity-region-misplaced', message: `/notes/${index}/regions/identity is neither in the front matter nor the last generated region` })
|
|
214
|
+
if (generated.some((region, at) => region.kind === 'identity' && at !== generated.length - 1)) {
|
|
215
|
+
errors.push({ code: 'identity-region-misplaced', message: `/notes/${index}/regions/generated has an identity region that is not the last` })
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
}
|
|
181
219
|
if (duplicates(doc.links.map((link) => link.edgeId)).length > 0) errors.push({ code: 'duplicate-identity', message: '/links repeats an edge identity' })
|
|
182
220
|
const nodeIds = new Set(doc.notes.map((note) => note.nodeId))
|
|
183
221
|
doc.links.forEach((link, index) => {
|
|
@@ -187,7 +225,7 @@ const SEMANTIC_CHECKS = {
|
|
|
187
225
|
}
|
|
188
226
|
})
|
|
189
227
|
doc.notes.forEach((note, index) => {
|
|
190
|
-
const ranges = [note.regions.frontmatter, note.regions.body, ...note.regions.generated.map((region) => region.range)].filter(Boolean)
|
|
228
|
+
const ranges = [note.regions.frontmatter, note.regions.identity, note.regions.body, ...note.regions.generated.map((region) => region.range)].filter(Boolean)
|
|
191
229
|
if (ranges.some((range) => range.end < range.start)) errors.push({ code: 'invalid-byte-range', message: `/notes/${index}/regions has a range that ends before it starts` })
|
|
192
230
|
})
|
|
193
231
|
if (doc.completeness.status === 'complete' && doc.completeness.writtenNotes !== doc.completeness.expectedNotes) {
|
|
@@ -227,11 +265,11 @@ const SEMANTIC_CHECKS = {
|
|
|
227
265
|
// { layer: 'schema' | 'semantic', code, message }. Semantic checks run only on
|
|
228
266
|
// schema-valid documents, so they can rely on the shape.
|
|
229
267
|
export function validateObsidianContract(shape, doc) {
|
|
230
|
-
const contract = contractFor(shape)
|
|
268
|
+
const contract = contractFor(shape, doc)
|
|
231
269
|
const schemaErrors = validateJsonSchema(loadSchema(contract), doc)
|
|
232
270
|
if (schemaErrors.length > 0) return schemaErrors.map((message) => ({ layer: 'schema', code: 'schema-violation', message }))
|
|
233
271
|
const errors = []
|
|
234
|
-
SEMANTIC_CHECKS[shape](doc, errors)
|
|
272
|
+
SEMANTIC_CHECKS[shape](doc, errors, contract.version)
|
|
235
273
|
if (contract.portability === 'portable') {
|
|
236
274
|
const found = []
|
|
237
275
|
collectAbsolutePaths(doc, '', found)
|
|
@@ -260,9 +298,12 @@ export function readObsidianExtSettings(projectConfigDoc) {
|
|
|
260
298
|
}
|
|
261
299
|
|
|
262
300
|
// ---------------------------------------------------------------------------
|
|
263
|
-
// Note identity and readable paths
|
|
301
|
+
// Note identity and readable paths, vault layout 1
|
|
264
302
|
// ---------------------------------------------------------------------------
|
|
265
303
|
|
|
304
|
+
// Layout 1, what releases up to 0.2.0-alpha.11 wrote and what a view held for
|
|
305
|
+
// an open edit is still prepared in: `notes/<readable title>--<suffix>.md`.
|
|
306
|
+
|
|
266
307
|
const RESERVED_BASENAMES = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/i
|
|
267
308
|
|
|
268
309
|
// Stable identity suffix: a digest of repository identity and node identity,
|
|
@@ -313,6 +354,171 @@ export function allocateNotePaths(nodes) {
|
|
|
313
354
|
return allocated
|
|
314
355
|
}
|
|
315
356
|
|
|
357
|
+
// ---------------------------------------------------------------------------
|
|
358
|
+
// Vault layout 2: readable names
|
|
359
|
+
// ---------------------------------------------------------------------------
|
|
360
|
+
|
|
361
|
+
// The file name is the title a person reads and the folders are the
|
|
362
|
+
// repository's own. These are the pure naming rules; allocation, collisions
|
|
363
|
+
// and stability are the path registry's (materialize/path-registry.mjs).
|
|
364
|
+
|
|
365
|
+
export const VAULT_LAYOUT_VERSION = 2
|
|
366
|
+
export const NAME_BYTES = 150
|
|
367
|
+
export const FOLDER_NAME_BYTES = 120
|
|
368
|
+
export const QUALIFIER_STEM_BYTES = 60
|
|
369
|
+
export const MIN_NAME_BYTES = 16
|
|
370
|
+
|
|
371
|
+
// Windows device names, compared on the part before the first dot.
|
|
372
|
+
const WINDOWS_DEVICE_NAMES = /^(?:con|prn|aux|nul|com[0-9¹²³]|lpt[0-9¹²³]|conin\$|conout\$)$/i
|
|
373
|
+
// Characters no name may hold: controls, path separators, what Windows
|
|
374
|
+
// forbids, and what ends or splits an Obsidian link (`# ^ [ ] |`).
|
|
375
|
+
const NAME_FORBIDDEN = /[\u0000-\u001f\u007f-\u009f\u2028\u2029/\\:*?"<>|#^[\]]/g
|
|
376
|
+
// Invisible formatting that can make a name read as another: bidirectional
|
|
377
|
+
// embedding, override and isolate controls, and a stray U+FEFF.
|
|
378
|
+
const NAME_INVISIBLE = /[\u202a-\u202e\u2066-\u2069\ufeff]/g
|
|
379
|
+
// What a cut may leave dangling at the end of a name.
|
|
380
|
+
const NAME_DANGLING = /[\p{M}\u200d\ufe00-\ufe0f]+$/u
|
|
381
|
+
|
|
382
|
+
const trimName = (value) => value.replace(/^[ .]+|[ .]+$/g, '')
|
|
383
|
+
|
|
384
|
+
// Two paths that a case-insensitive or normalization-insensitive file system
|
|
385
|
+
// would treat as one share a collision key.
|
|
386
|
+
export function collisionKey(value) {
|
|
387
|
+
return value.normalize('NFKC').toUpperCase().toLowerCase().normalize('NFKC')
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// The longest prefix of `value` within `maxBytes` of UTF-8, cut between code
|
|
391
|
+
// points, without a combining character, joiner or variation selector left
|
|
392
|
+
// dangling at the end.
|
|
393
|
+
export function cutName(value, maxBytes) {
|
|
394
|
+
if (Buffer.byteLength(value, 'utf8') <= maxBytes) return value
|
|
395
|
+
let kept = ''
|
|
396
|
+
let bytes = 0
|
|
397
|
+
for (const character of value) {
|
|
398
|
+
bytes += Buffer.byteLength(character, 'utf8')
|
|
399
|
+
if (bytes > maxBytes) break
|
|
400
|
+
kept += character
|
|
401
|
+
}
|
|
402
|
+
return trimName(kept.replace(NAME_DANGLING, ''))
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// One file or folder name made safe for macOS, Linux, Windows and Obsidian
|
|
406
|
+
// links, or '' when nothing is left of it. The author's casing and words are
|
|
407
|
+
// kept; see "File names" in docs/obsidian-contract.md for each rule.
|
|
408
|
+
export function vaultName(value, maxBytes = NAME_BYTES) {
|
|
409
|
+
const cleaned = trimName(String(value ?? '')
|
|
410
|
+
.toWellFormed()
|
|
411
|
+
.normalize('NFC')
|
|
412
|
+
.replace(NAME_INVISIBLE, '')
|
|
413
|
+
.replace(NAME_FORBIDDEN, ' ')
|
|
414
|
+
.replace(/ {2,}/g, ' '))
|
|
415
|
+
const name = cutName(cleaned, maxBytes)
|
|
416
|
+
if (name === '' || !WINDOWS_DEVICE_NAMES.test(name.split('.')[0].trimEnd())) return name
|
|
417
|
+
return `_${cutName(name, maxBytes - 1)}`
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export function fileNameOf(sourcePath) {
|
|
421
|
+
return String(sourcePath ?? '').split('/').at(-1)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// A node's extension: the canonical record's, else its path's.
|
|
425
|
+
export function extensionOf(node) {
|
|
426
|
+
if (typeof node?.extension === 'string' && node.extension !== '') return node.extension
|
|
427
|
+
const name = fileNameOf(node?.path)
|
|
428
|
+
const dot = name.lastIndexOf('.')
|
|
429
|
+
return dot > 0 ? name.slice(dot + 1) : ''
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export function fileStemOf(sourcePath) {
|
|
433
|
+
const name = fileNameOf(sourcePath)
|
|
434
|
+
const dot = name.lastIndexOf('.')
|
|
435
|
+
return dot > 0 ? name.slice(0, dot) : name
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// A title that ends in the source's own extension (`notes.md`) came from a file
|
|
439
|
+
// name; the extension is dropped. Only the source's own extension: `Node.js`
|
|
440
|
+
// or `Version 2.0` keep their ending.
|
|
441
|
+
function withoutOwnExtension(title, extension) {
|
|
442
|
+
if (!/^[A-Za-z0-9]{1,16}$/.test(extension)) return title
|
|
443
|
+
const trimmed = title.trimEnd()
|
|
444
|
+
const suffix = `.${extension}`
|
|
445
|
+
const before = trimmed.length - suffix.length
|
|
446
|
+
if (before < 1 || trimmed.slice(before).toLowerCase() !== suffix.toLowerCase() || /\s/.test(trimmed[before - 1])) return title
|
|
447
|
+
return trimmed.slice(0, before)
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// The name of a Markdown note, from the node record alone: its canonical
|
|
451
|
+
// title (front-matter title, else first H1), or the file stem as written when
|
|
452
|
+
// the title is the graph's fallback, the title-cased file name. Never ''.
|
|
453
|
+
export function noteNameOf(node) {
|
|
454
|
+
const fileName = fileNameOf(node.path)
|
|
455
|
+
const stem = fileStemOf(node.path)
|
|
456
|
+
const title = typeof node.title === 'string' ? node.title : ''
|
|
457
|
+
const chosen = title.trim() === '' || title === titleCase(fileName) ? stem : withoutOwnExtension(title, extensionOf(node))
|
|
458
|
+
return vaultName(chosen) || vaultName(stem) || 'Untitled'
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// A wrapped or embedded file keeps its own name: `{ stem, extension }`, made
|
|
462
|
+
// safe, the stem bounded so that the extension still fits. Never an empty stem.
|
|
463
|
+
export function fileNameParts(sourcePath) {
|
|
464
|
+
const name = fileNameOf(sourcePath)
|
|
465
|
+
const dot = name.lastIndexOf('.')
|
|
466
|
+
const extension = dot > 0 ? vaultName(name.slice(dot + 1), 16) : ''
|
|
467
|
+
const budget = NAME_BYTES - (extension === '' ? 0 : Buffer.byteLength(extension, 'utf8') + 1)
|
|
468
|
+
const stem = vaultName(dot > 0 ? name.slice(0, dot) : name, budget) || 'Untitled'
|
|
469
|
+
return { stem, extension }
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
export const joinFileName = ({ stem, extension }) => (extension === '' ? stem : `${stem}.${extension}`)
|
|
473
|
+
|
|
474
|
+
// A folder segment of the mirrored source directory, or the repository folder.
|
|
475
|
+
export function folderNameOf(segment) {
|
|
476
|
+
return vaultName(segment, FOLDER_NAME_BYTES) || '_'
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// The stable short identity a colliding name is qualified with: hexadecimal
|
|
480
|
+
// characters of the SHA-256 of the repository and node identity (the digest
|
|
481
|
+
// the layout 1 suffix is a prefix of).
|
|
482
|
+
export function qualifierIdOf(repoId, nodeId, length = 6) {
|
|
483
|
+
return createHash('sha256').update(`${repoId}\u0000${nodeId}`).digest('hex').slice(0, length)
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Whether `value` is a path of layout 2: relative, every segment a name the
|
|
487
|
+
// rules above can produce (no forbidden character, no leading or trailing
|
|
488
|
+
// space or dot, at most 255 bytes).
|
|
489
|
+
const HAS_FORBIDDEN = new RegExp(NAME_FORBIDDEN.source)
|
|
490
|
+
const HAS_INVISIBLE = new RegExp(NAME_INVISIBLE.source)
|
|
491
|
+
|
|
492
|
+
export function isReadableVaultPath(value) {
|
|
493
|
+
if (typeof value !== 'string' || value === '' || Buffer.byteLength(value, 'utf8') > 1024) return false
|
|
494
|
+
return value.split('/').every((segment) => segment !== ''
|
|
495
|
+
&& trimName(segment) === segment
|
|
496
|
+
&& !HAS_FORBIDDEN.test(segment)
|
|
497
|
+
&& !HAS_INVISIBLE.test(segment)
|
|
498
|
+
&& !WINDOWS_DEVICE_NAMES.test(segment.split('.')[0].trimEnd())
|
|
499
|
+
&& segment === segment.normalize('NFC')
|
|
500
|
+
&& Buffer.byteLength(segment, 'utf8') <= 255)
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// The layout a generation manifest was prepared in.
|
|
504
|
+
export function manifestLayoutVersion(manifest) {
|
|
505
|
+
return manifest?.schema === 'atelier-obsidian-generation-manifest/v2' ? manifest.layoutVersion : 1
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// The three generated properties that name a note's identity, in order.
|
|
509
|
+
export const IDENTITY_KEYS = Object.freeze(['atelier-id', 'atelier-repo', 'atelier-source'])
|
|
510
|
+
|
|
511
|
+
// A YAML double-quoted scalar: JSON's escapes, plus `\u` for what YAML does
|
|
512
|
+
// not allow unescaped (DEL, C1 controls, U+2028, U+2029, U+FEFF).
|
|
513
|
+
export function yamlQuoted(value) {
|
|
514
|
+
return JSON.stringify(String(value)).replace(/[\u007f-\u009f\u2028\u2029\ufeff]/g, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, '0')}`)
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// The identity lines of one note, without line endings.
|
|
518
|
+
export function identityLineTexts(node) {
|
|
519
|
+
return [[IDENTITY_KEYS[0], node.id], [IDENTITY_KEYS[1], node.repo], [IDENTITY_KEYS[2], node.path]].map(([key, value]) => `${key}: ${yamlQuoted(value)}`)
|
|
520
|
+
}
|
|
521
|
+
|
|
316
522
|
// ---------------------------------------------------------------------------
|
|
317
523
|
// Canonical snapshot and profile views
|
|
318
524
|
// ---------------------------------------------------------------------------
|
|
@@ -9,10 +9,11 @@ import { canonicalJson, compareText, isoTime } from '../../../runtime/obsidian/d
|
|
|
9
9
|
import { readObsidianEnablement } from '../../../runtime/obsidian/enablement.mjs'
|
|
10
10
|
import { ObsidianMaintenanceRefusal } from '../../../runtime/obsidian/errors.mjs'
|
|
11
11
|
import { protectedRoots, readInstalledApplyPolicy, readLocalPointer, readMachineSettings, resolveDataRoot, workspaceStateRoot } from '../../../runtime/obsidian/machine-settings.mjs'
|
|
12
|
-
import {
|
|
12
|
+
import { createProductionSeams, eligibilityFor } from '../../../runtime/obsidian/pipeline.mjs'
|
|
13
13
|
import { OPEN_EDIT_STATES, createMaintenanceStateStore } from '../../../runtime/obsidian/state-store.mjs'
|
|
14
|
-
import { OBSIDIAN_EXT_KEY, ObsidianContractRefusal } from '../contracts.mjs'
|
|
14
|
+
import { OBSIDIAN_EXT_KEY, ObsidianContractRefusal, manifestLayoutVersion } from '../contracts.mjs'
|
|
15
15
|
import { readMarkdownLens } from '../materialize/byte-lens.mjs'
|
|
16
|
+
import { personalOverlayRepoOf } from '../personal-workspace.mjs'
|
|
16
17
|
import { exchangeFiles, probeExchange } from '../publication/exchange.mjs'
|
|
17
18
|
import { createJournal, newJournalId } from '../recovery/journal.mjs'
|
|
18
19
|
import { recheckDisplacedFiles } from '../recovery/late-writer.mjs'
|
|
@@ -91,6 +92,7 @@ export const SOURCE_APPLY_REFUSALS = Object.freeze([
|
|
|
91
92
|
'source-inside-managed-root', 'source-inside-git-directory', 'source-git-ignored', 'source-ignore-state-unknown', 'sibling-edit-unobservable', 'lease-held', 'object-conflicted',
|
|
92
93
|
'stale-source', 'edit-not-applicable', 'change-outside-authored-body', 'no-source-change', 'exchange-unavailable', 'apply-volume-mismatch', 'batch-bound-reached',
|
|
93
94
|
'concurrent-source-writer', 'source-changed-during-apply', 'interrupted-before-exchange', 'apply-interrupted-needs-person', 'recovery-state-unreadable', 'apply-outcome-unknown', 'source-changed-after-apply',
|
|
95
|
+
'personal-overlay-proposals-only',
|
|
94
96
|
])
|
|
95
97
|
|
|
96
98
|
// Refusals that say the source or the object is contested, not that this machine or this request cannot apply.
|
|
@@ -137,6 +139,10 @@ function readNoFollow(file, { withMode = false } = {}) {
|
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
const NOT_A_FILE = new Set(['EISDIR', 'EINVAL', 'ENOTDIR', 'EMLINK'])
|
|
142
|
+
// How often a file another program replaces by rename is read again: the pointer to the current manifest, as the
|
|
143
|
+
// publisher reads a note, and the published note prepared again. One that keeps changing is a typed refusal.
|
|
144
|
+
const READ_ATTEMPTS = 5
|
|
145
|
+
const PREPARE_ATTEMPTS = 3
|
|
140
146
|
const UNREADABLE = new Set(['EACCES', 'EPERM', 'EIO'])
|
|
141
147
|
|
|
142
148
|
// The digest of the file, null when nothing is there, 'unreadable' when what is there is not a regular file: whatever
|
|
@@ -265,7 +271,7 @@ export function createSourceApplyForOracleTests(primitives = SOURCE_APPLY_PRIMIT
|
|
|
265
271
|
// ones the workspace has.
|
|
266
272
|
return function createSourceApply(context = {}) {
|
|
267
273
|
const {
|
|
268
|
-
loadProject, dataRoot, env = process.env, platform = process.platform, clock = () => new Date(), eligibility =
|
|
274
|
+
loadProject, dataRoot, env = process.env, platform = process.platform, clock = () => new Date(), eligibility: fixedEligibility = null,
|
|
269
275
|
quietPeriodMs = DEFAULT_APPLY_QUIET_PERIOD_MS, recheckWindowMs = DEFAULT_APPLY_RECHECK_WINDOW_MS, exchangeOptions = {},
|
|
270
276
|
crash = () => {}, beforeExchange = async () => {}, leasePid, extraManagedRoots = [], manualBatchBound = MAX_MANUAL_BATCH_SIZE, objectStore = openObjectStore,
|
|
271
277
|
} = context
|
|
@@ -303,26 +309,41 @@ export function createSourceApplyForOracleTests(primitives = SOURCE_APPLY_PRIMIT
|
|
|
303
309
|
return workspace
|
|
304
310
|
}
|
|
305
311
|
|
|
306
|
-
// The canonical graph as it is now, and the corpus profile of this machine. Built once per call
|
|
312
|
+
// The canonical graph as it is now, and the corpus profile of this machine. Built once per call, with the notes the
|
|
313
|
+
// machine settings let into a view, exactly as the engine builds it (eligibilityFor), unless a test fixes them.
|
|
307
314
|
function currentCorpus(workspace) {
|
|
308
|
-
// The graph reads every enrolled source. A file this process may not read is a refusal that names no file.
|
|
315
|
+
// The graph reads every enrolled source. A file this process may not read is a refusal that names no file. So is
|
|
316
|
+
// one another program removes or replaces while the graph is built (a save by delete and create, a checkout):
|
|
317
|
+
// the graph cannot be built from what is there at this moment, and the cause says which of the two it was.
|
|
309
318
|
try {
|
|
310
319
|
workspace.corpus ??= {
|
|
311
|
-
graph: seams.buildGraph({ project: workspace.project, eligibility }),
|
|
320
|
+
graph: seams.buildGraph({ project: workspace.project, eligibility: fixedEligibility ?? eligibilityFor({ machine: workspace.machine, project: workspace.project }) }),
|
|
312
321
|
profile: seams.profileFor({ project: workspace.project, workspaceId: workspace.workspaceId, audienceAllow: workspace.machine.audienceAllow }),
|
|
313
322
|
}
|
|
314
323
|
} catch (error) {
|
|
315
|
-
if (isTyped(error) || !UNREADABLE.has(error?.code)) throw error
|
|
324
|
+
if (isTyped(error) || !(UNREADABLE.has(error?.code) || GONE.has(error?.code) || error?.code === 'ELEAFCHANGED')) throw error
|
|
316
325
|
refuse('corpus-unreadable', { cause: error.code })
|
|
317
326
|
}
|
|
318
327
|
return workspace.corpus
|
|
319
328
|
}
|
|
320
329
|
|
|
330
|
+
// The pointer to the current manifest is replaced by rename as the last step of every publication, so a
|
|
331
|
+
// publication by the engine can replace it between the look at its path and its open (ELEAFCHANGED). Every rename
|
|
332
|
+
// leaves a complete pointer, so it is read again, as the publisher reads a note; one that keeps changing refuses.
|
|
333
|
+
function currentManifestOf(store) {
|
|
334
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
335
|
+
try { return store.readCurrentManifest() } catch (error) {
|
|
336
|
+
if (error?.code !== 'ELEAFCHANGED') throw error
|
|
337
|
+
if (attempt >= READ_ATTEMPTS) refuse('manifest-unavailable', { cause: 'changed-while-reading' })
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
321
342
|
// The immutable manifest of one generation of one view. The current one when it is that generation; otherwise
|
|
322
343
|
// the stored file, whose name carries the generation and the head of its digest.
|
|
323
344
|
function manifestOf(workspace, scopeId, generationId) {
|
|
324
345
|
const store = workspace.storeOf(scopeId)
|
|
325
|
-
const current = store
|
|
346
|
+
const current = currentManifestOf(store)
|
|
326
347
|
if (current?.generationId === generationId) return current
|
|
327
348
|
const directory = path.join(workspace.workspaceRoot, 'state', 'manifests', segment(scopeId))
|
|
328
349
|
let names = []
|
|
@@ -338,22 +359,41 @@ export function createSourceApplyForOracleTests(primitives = SOURCE_APPLY_PRIMIT
|
|
|
338
359
|
}
|
|
339
360
|
|
|
340
361
|
// The note exactly as it was published, which the lens needs to tell generated bytes from authored ones. The
|
|
341
|
-
// publisher keeps no copy of a note it created, so the note is prepared again from the sources as they are now
|
|
342
|
-
// and used only when it has the digest the manifest recorded; a retained
|
|
362
|
+
// publisher keeps no copy of a note it created, so the note is prepared again from the sources as they are now,
|
|
363
|
+
// in the vault layout of that generation, and used only when it has the digest the manifest recorded; a retained
|
|
364
|
+
// object of that digest serves as well.
|
|
365
|
+
//
|
|
366
|
+
// A source replaced between the look at its path and its open (ELEAFCHANGED) is another program writing it, as it
|
|
367
|
+
// is to the publisher. A rename leaves a complete file, so the note is prepared again from what is there now: a
|
|
368
|
+
// source saved with the same bytes, or another source of the scope replaced, then prepares the note as published,
|
|
369
|
+
// and a source with other bytes prepares another note, which the caller tells from the digest and refuses
|
|
370
|
+
// stale-source. A preparation that cannot be carried out answers null, and the caller reads the source once more
|
|
371
|
+
// to tell which typed refusal that is. Only a preparation that succeeded is kept for its scope and generation: a
|
|
372
|
+
// failure tells of one moment, not of the generation, and is never the answer to a later edit.
|
|
343
373
|
function publishedNoteOf(workspace, { scope, manifest, noteEntry }) {
|
|
344
374
|
const store = workspace.storeOf(scope.scopeId)
|
|
345
375
|
try { return store.readObject(noteEntry.noteDigest) } catch (error) { if (error.code !== 'ENOENT' && error.code !== 'recovery-object-corrupt') throw error }
|
|
346
376
|
workspace.prepared ??= new Map()
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
377
|
+
const preparedKey = `${scope.scopeId}\u0000${manifest.generationId}`
|
|
378
|
+
if (!workspace.prepared.has(preparedKey)) {
|
|
379
|
+
let files
|
|
380
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
381
|
+
try {
|
|
382
|
+
const { graph, profile } = currentCorpus(workspace)
|
|
383
|
+
const snapshot = seams.captureSnapshot({ project: workspace.project, graph, workspaceId: workspace.workspaceId, index: new Map(), configDigest: manifest.ext?.[EXT]?.configDigest ?? `sha256:${'0'.repeat(64)}`, capturedAt: isoTime(clock) })
|
|
384
|
+
files = seams.prepareView({
|
|
385
|
+
snapshot, profile, scope, persistentPathRegistry: workspace.stateStore.readPathRegistry(), priorManifest: manifest, existingSettings: null, clock,
|
|
386
|
+
vaultRootBytes: Buffer.byteLength(store.vaultRoot, 'utf8'), layout: manifestLayoutVersion(manifest),
|
|
387
|
+
}).files
|
|
388
|
+
break
|
|
389
|
+
} catch (error) {
|
|
390
|
+
if (!isTyped(error) && error?.code !== 'ELEAFCHANGED' && !GONE.has(error?.code) && !UNREADABLE.has(error?.code)) throw error
|
|
391
|
+
if (error?.code !== 'ELEAFCHANGED' || attempt >= PREPARE_ATTEMPTS) return null
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
workspace.prepared.set(preparedKey, files)
|
|
355
395
|
}
|
|
356
|
-
const file = workspace.prepared.get(
|
|
396
|
+
const file = workspace.prepared.get(preparedKey).find((item) => item.path === noteEntry.path && item.digest === noteEntry.noteDigest)
|
|
357
397
|
return file ? file.bytes : null
|
|
358
398
|
}
|
|
359
399
|
|
|
@@ -528,6 +568,10 @@ export function createSourceApplyForOracleTests(primitives = SOURCE_APPLY_PRIMIT
|
|
|
528
568
|
const decideWith = (editClass, attempts) => rules.decide({ request, workspace: { workspaceRoot: workspace.workspaceRoot, workspaceId: workspace.workspaceId }, graph, profile, object: identity, editClass, attempts })
|
|
529
569
|
const visibility = decideWith('body-replacement', [])
|
|
530
570
|
if (!visibility.allowed && visibility.code === 'object-not-visible') refuse('object-not-visible')
|
|
571
|
+
// A private note of a personal workspace is authored in its overlay, and its file belongs to a generation the
|
|
572
|
+
// personal-workspace module owns: an edit to it is never written there. It is not proposed yet either; it stays
|
|
573
|
+
// held in the vault.
|
|
574
|
+
if (identity.repoId === personalOverlayRepoOf(workspace.project)) refuse('personal-overlay-proposals-only')
|
|
531
575
|
|
|
532
576
|
const resolved = resolveEdit(workspace, edit)
|
|
533
577
|
const key = resolved.idempotencyKey
|