@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
|
@@ -5,6 +5,7 @@ import fs from 'node:fs'
|
|
|
5
5
|
import http from 'node:http'
|
|
6
6
|
import path from 'node:path'
|
|
7
7
|
import { fileURLToPath } from 'node:url'
|
|
8
|
+
import { AtelierDiagnosticError } from '../project/config.mjs'
|
|
8
9
|
import {
|
|
9
10
|
atomicReplacePrivateText,
|
|
10
11
|
ensureContainedPrivateDirectory,
|
|
@@ -24,6 +25,7 @@ import {
|
|
|
24
25
|
trustedMutationRequest,
|
|
25
26
|
trustedReadRequest,
|
|
26
27
|
} from './security.mjs'
|
|
28
|
+
import { canonicalize } from '../attestation/jcs.mjs'
|
|
27
29
|
import { createProposalStore } from '../collaboration/proposals.mjs'
|
|
28
30
|
import {
|
|
29
31
|
renderProposalDetailPageHtml,
|
|
@@ -33,6 +35,9 @@ import {
|
|
|
33
35
|
import { createReviewStore } from '../collaboration/review-store.mjs'
|
|
34
36
|
import { loadBoundRun, currentRunEligibility } from '../readiness-protocols/evidence.mjs'
|
|
35
37
|
import { renderReviewPage } from '../ui/review-page.mjs'
|
|
38
|
+
import { renderKnowledgePage } from '../ui/knowledge-page.mjs'
|
|
39
|
+
import { knowledgeDashboard, knowledgeQuestionContext, loadKnowledgeWorkspace } from '../knowledge/workspace.mjs'
|
|
40
|
+
import { createKnowledgeSessions } from '../knowledge/sessions.mjs'
|
|
36
41
|
|
|
37
42
|
export const ATELIER_CONTEXT_SCHEMA = 'atelier-context@v1'
|
|
38
43
|
export const ATELIER_PRESENCE_SCHEMA = 'atelier-presence@v1'
|
|
@@ -196,6 +201,47 @@ function capabilityContract() {
|
|
|
196
201
|
}
|
|
197
202
|
}
|
|
198
203
|
|
|
204
|
+
// A listen failure a person can fix by choosing another port becomes a typed
|
|
205
|
+
// diagnostic the CLI prints with that remedy. Any other failure is returned
|
|
206
|
+
// unchanged, so the CLI's own rule for unknown errors still decides what shows.
|
|
207
|
+
function listenFailure(error, port) {
|
|
208
|
+
if (error?.code === 'EADDRINUSE') {
|
|
209
|
+
return new AtelierDiagnosticError('port-in-use', `port ${port} is already in use`, {
|
|
210
|
+
hint: 'Pass --port=<free port> to choose another.',
|
|
211
|
+
cause: error,
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
if (error?.code === 'EACCES') {
|
|
215
|
+
return new AtelierDiagnosticError('port-permission-denied', `permission to listen on port ${port} was denied`, {
|
|
216
|
+
hint: 'Pass --port=<free port from 1024 to 65535> to choose another; lower ports need elevated privileges.',
|
|
217
|
+
cause: error,
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
return error
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function knowledgeError(error) {
|
|
224
|
+
const message = error instanceof Error ? error.message : ''
|
|
225
|
+
if (message === 'coauthor requires a Git workspace with untracked, ignored .atelier-local/ state')
|
|
226
|
+
return 'coauthor requires a Git workspace with untracked, ignored local state. Initialize Git and ignore the .atelier-local directory.'
|
|
227
|
+
if (/^collaboration (ledger|event).*ceiling/.test(message))
|
|
228
|
+
return 'knowledge history capacity reached. Preserve the ledger and saved values for operator inspection; do not compact active session chains.'
|
|
229
|
+
if (message.startsWith('EEXIST: private state is locked'))
|
|
230
|
+
return 'knowledge writer is busy. Preserve the request and retry after the active writer finishes.'
|
|
231
|
+
const safe = [
|
|
232
|
+
'workspace changed', 'stale revision', 'event id conflict', 'source changed',
|
|
233
|
+
'coauthor session not found', 'coauthor requires', 'unknown knowledge',
|
|
234
|
+
'invalid knowledge', 'request UUID', 'retry budget exhausted',
|
|
235
|
+
'receipt and failure events are store-owned', 'event refused in',
|
|
236
|
+
'coauthor plan must', 'knowledge session configuration mismatch',
|
|
237
|
+
'knowledge session identity mismatch', 'knowledge session exceeds',
|
|
238
|
+
'knowledge session list exceeds',
|
|
239
|
+
'knowledge history unavailable', 'knowledge start marker mismatch',
|
|
240
|
+
]
|
|
241
|
+
return safe.some(prefix => message.startsWith(prefix)) && !message.includes('/')
|
|
242
|
+
? message : 'Knowledge operation unavailable. Preserve your draft and inspect the local workspace or active writer.'
|
|
243
|
+
}
|
|
244
|
+
|
|
199
245
|
function doctorEnvelope() {
|
|
200
246
|
return {
|
|
201
247
|
ok: true,
|
|
@@ -211,6 +257,7 @@ export function createAtelierSidecarServer({
|
|
|
211
257
|
workspaceRoot = process.cwd(),
|
|
212
258
|
stateDir = workspaceRoot,
|
|
213
259
|
reviewProject = null,
|
|
260
|
+
knowledgeProject = null,
|
|
214
261
|
port = 0,
|
|
215
262
|
presenceTtlMs = Number(process.env.ATELIER_PRESENCE_TTL_MS || 5 * 60 * 1000),
|
|
216
263
|
} = {}) {
|
|
@@ -223,6 +270,7 @@ export function createAtelierSidecarServer({
|
|
|
223
270
|
})
|
|
224
271
|
const publication = loadPublishedWorkspaceManifest(root)
|
|
225
272
|
const review = reviewProject ? createReviewStore(reviewProject) : null
|
|
273
|
+
const knowledge = knowledgeProject ? createKnowledgeSessions(knowledgeProject) : null
|
|
226
274
|
const workspaceId = workspaceIdForRoot(root)
|
|
227
275
|
const noncePath = path.join(stateDirReal, '.atelier-nonce')
|
|
228
276
|
const presencePath = path.join(stateDirReal, '.atelier-presence.json')
|
|
@@ -233,6 +281,95 @@ export function createAtelierSidecarServer({
|
|
|
233
281
|
workspaceId,
|
|
234
282
|
})
|
|
235
283
|
|
|
284
|
+
// One copy-only declaration is retained from the workshop: this path, this
|
|
285
|
+
// action, from this view. The request stays `{ sessionId }`; everything
|
|
286
|
+
// retained is derived here from fresh owning readbacks, and the generic
|
|
287
|
+
// /api/proposals route keeps its published-HTML fence.
|
|
288
|
+
const WORKSHOP_HANDOFF_TARGET = Object.freeze({ path: 'records/checklist.md', action: 'copy.repoPath', viewId: 'knowledge-workshop' })
|
|
289
|
+
const sameJson = (left, right) => canonicalize(left) === canonicalize(right)
|
|
290
|
+
const refusedRetention = (error, status = 'refused') => ({ status: 409, body: { ok: false, error, retention: { status } } })
|
|
291
|
+
const retentionSummary = (record, outcome, sourceCurrent) => ({
|
|
292
|
+
status: 'retained',
|
|
293
|
+
outcome,
|
|
294
|
+
sourceCurrent,
|
|
295
|
+
proposalId: record.proposal.id,
|
|
296
|
+
readback: `/api/proposals/${record.proposal.id}`,
|
|
297
|
+
receipt: {
|
|
298
|
+
sessionId: record.retention.sessionId,
|
|
299
|
+
requestId: record.retention.requestId,
|
|
300
|
+
valueDigest: record.retention.valueDigest,
|
|
301
|
+
},
|
|
302
|
+
payloadDigest: record.retention.payloadDigest,
|
|
303
|
+
proposalStatus: record.proposal.status,
|
|
304
|
+
eventVersion: record.proposal.eventVersion,
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
function retainWorkshopHandoff(body) {
|
|
308
|
+
if (!body || Array.isArray(body) || Object.keys(body).join(',') !== 'sessionId' || typeof body.sessionId !== 'string') {
|
|
309
|
+
return refusedRetention('workshop handoff accepts a session id only')
|
|
310
|
+
}
|
|
311
|
+
// A fresh owning readback: this throws when the session, its ledger or a
|
|
312
|
+
// saved value is missing, redirected or altered.
|
|
313
|
+
const session = knowledge.read(body.sessionId)
|
|
314
|
+
const selected = session.record.flow === 'workshop-review'
|
|
315
|
+
? session.state.saved.find((value) => value.fieldId === 'authored-revision')
|
|
316
|
+
: null
|
|
317
|
+
if (!selected) {
|
|
318
|
+
// No separately selected draft receipt: prepared only, as before. An
|
|
319
|
+
// incomplete Review or a response that selects nothing is refused by
|
|
320
|
+
// the existing preparation.
|
|
321
|
+
return { status: 200, body: { ...knowledge.workshopHandoff(body), retention: { status: 'not-retained', reason: 'no separately selected draft receipt' } } }
|
|
322
|
+
}
|
|
323
|
+
const own = session.owningReadbacks?.verified === true
|
|
324
|
+
? session.owningReadbacks.immutableValues.find((value) => sameJson(value.receipt, selected.receipt))
|
|
325
|
+
: null
|
|
326
|
+
if (!own || own.text !== selected.text || selected.receipt.sessionId !== session.record.id) {
|
|
327
|
+
return refusedRetention('the selected draft receipt is not confirmed by its owning readback')
|
|
328
|
+
}
|
|
329
|
+
if (!session.current) {
|
|
330
|
+
// Reopen after a source change: read back what was retained, never append.
|
|
331
|
+
const known = proposals.lookupRetainedProposal(selected.receipt)
|
|
332
|
+
if (known.outcome === 'retained') {
|
|
333
|
+
return {
|
|
334
|
+
status: 200,
|
|
335
|
+
body: {
|
|
336
|
+
ok: true,
|
|
337
|
+
handoff: proposals.retainedHandoff(known.record),
|
|
338
|
+
sourceEditsApplied: false,
|
|
339
|
+
directWrite: false,
|
|
340
|
+
retention: retentionSummary(known.record, 'existing', false),
|
|
341
|
+
},
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return known.outcome === 'not-found'
|
|
345
|
+
? refusedRetention('the source changed before this draft was retained; nothing is retained for this receipt', 'not-retained')
|
|
346
|
+
: refusedRetention(known.error, known.outcome === 'conflict' ? 'refused' : 'unknown')
|
|
347
|
+
}
|
|
348
|
+
const prepared = knowledge.workshopHandoff(body)
|
|
349
|
+
const handoff = prepared.handoff
|
|
350
|
+
if (
|
|
351
|
+
!sameJson(handoff.proposal.selectedDraftReceipt, selected.receipt) || handoff.sessionId !== session.record.id ||
|
|
352
|
+
handoff.path !== WORKSHOP_HANDOFF_TARGET.path || handoff.action !== WORKSHOP_HANDOFF_TARGET.action ||
|
|
353
|
+
handoff.viewId !== WORKSHOP_HANDOFF_TARGET.viewId || handoff.directWrite !== false ||
|
|
354
|
+
handoff.applyEndpoint !== null || handoff.diff?.replacement !== selected.text
|
|
355
|
+
) {
|
|
356
|
+
return refusedRetention('the prepared handoff does not match the selected draft readback')
|
|
357
|
+
}
|
|
358
|
+
// The original contribution is read back from its own session as well.
|
|
359
|
+
const original = knowledge.read(handoff.proposal.contributionSessionId)
|
|
360
|
+
const values = original.owningReadbacks?.verified === true ? original.owningReadbacks.immutableValues : null
|
|
361
|
+
if (
|
|
362
|
+
!values ||
|
|
363
|
+
!sameJson([...values.map((value) => value.receipt), selected.receipt], handoff.proposal.savedDraftReceipts) ||
|
|
364
|
+
values.find((value) => value.receipt.fieldId === 'original-words')?.text !== handoff.proposal.originalWords
|
|
365
|
+
) {
|
|
366
|
+
return refusedRetention('the original contribution is not confirmed by its owning readback')
|
|
367
|
+
}
|
|
368
|
+
const result = proposals.retainProposal(handoff)
|
|
369
|
+
if (!result.ok) return refusedRetention(result.error, result.outcome === 'unknown' ? 'unknown' : 'refused')
|
|
370
|
+
return { status: 200, body: { ...prepared, retention: retentionSummary(result.record, result.outcome, true) } }
|
|
371
|
+
}
|
|
372
|
+
|
|
236
373
|
function resolvePublishedPath({ rel, requireFile = false, requireHtml = false } = {}) {
|
|
237
374
|
const resolved = resolveWorkspacePath({
|
|
238
375
|
workspaceRoot: root,
|
|
@@ -375,8 +512,8 @@ export function createAtelierSidecarServer({
|
|
|
375
512
|
// Browsers send Origin on POST; same-origin GET normally omits it. Keep
|
|
376
513
|
// the strict origin gate for nonce disclosure instead of relaxing the
|
|
377
514
|
// existing session-auth GET contract or accepting unclassified reads.
|
|
378
|
-
if (review && url.pathname === '/api/review/session') {
|
|
379
|
-
if (!trustedMutationRequest(req.headers) || !body || Array.isArray(body) || Object.keys(body).length) {
|
|
515
|
+
if ((review && url.pathname === '/api/review/session') || (knowledge && url.pathname === '/api/knowledge/session')) {
|
|
516
|
+
if (!trustedMutationRequest(req.headers) || !body || Array.isArray(body) || Object.keys(body).length || (url.pathname === '/api/knowledge/session' && url.search)) {
|
|
380
517
|
json(res, 403, { ok: false, error: 'review session requires a same-origin empty request' })
|
|
381
518
|
return
|
|
382
519
|
}
|
|
@@ -391,6 +528,22 @@ export function createAtelierSidecarServer({
|
|
|
391
528
|
return
|
|
392
529
|
}
|
|
393
530
|
|
|
531
|
+
if (knowledge && url.pathname.startsWith('/api/knowledge/')) {
|
|
532
|
+
const operation = url.pathname.slice('/api/knowledge/'.length)
|
|
533
|
+
if (!['start', 'event', 'recover', 'lookup', 'workshop-handoff', 'workshop-review'].includes(operation) || url.search) {
|
|
534
|
+
json(res, 404, { ok: false, error: 'unknown knowledge action' }); return
|
|
535
|
+
}
|
|
536
|
+
try {
|
|
537
|
+
if (operation === 'workshop-handoff') {
|
|
538
|
+
const retained = retainWorkshopHandoff(body)
|
|
539
|
+
json(res, retained.status, retained.body)
|
|
540
|
+
} else {
|
|
541
|
+
json(res, 200, knowledge[operation === 'workshop-review' ? 'workshopReview' : operation](body))
|
|
542
|
+
}
|
|
543
|
+
} catch (error) { json(res, 409, { ok: false, error: knowledgeError(error) }) }
|
|
544
|
+
return
|
|
545
|
+
}
|
|
546
|
+
|
|
394
547
|
if (review && url.pathname === '/api/review/contributions') {
|
|
395
548
|
const result = review.contribute(body)
|
|
396
549
|
json(res, result.status, result)
|
|
@@ -508,6 +661,38 @@ export function createAtelierSidecarServer({
|
|
|
508
661
|
return
|
|
509
662
|
}
|
|
510
663
|
|
|
664
|
+
if (knowledge && url.pathname === '/knowledge' && !url.search) {
|
|
665
|
+
const body = renderKnowledgePage()
|
|
666
|
+
res.writeHead(200, htmlDocumentHeaders(Buffer.byteLength(body)))
|
|
667
|
+
res.end(body)
|
|
668
|
+
return
|
|
669
|
+
}
|
|
670
|
+
if (knowledge && url.pathname.startsWith('/api/knowledge/')) {
|
|
671
|
+
try {
|
|
672
|
+
let result
|
|
673
|
+
const operation = url.pathname.slice('/api/knowledge/'.length)
|
|
674
|
+
const parameters = operation === 'context' ? ['id', 'mode'] : operation === 'read' ? ['id'] : []
|
|
675
|
+
if ([...url.searchParams.keys()].some(k => !parameters.includes(k)) || [...url.searchParams.keys()].length !== new Set(url.searchParams.keys()).size) throw new Error('invalid knowledge query')
|
|
676
|
+
if (operation === 'dashboard') {
|
|
677
|
+
const dashboard = knowledgeDashboard(loadKnowledgeWorkspace(knowledgeProject))
|
|
678
|
+
try {
|
|
679
|
+
const profile = knowledge.workshopProfile()
|
|
680
|
+
dashboard.flows = [profile.flow, ...dashboard.flows]
|
|
681
|
+
dashboard.workshop = { available: true, context: profile.context }
|
|
682
|
+
} catch {
|
|
683
|
+
dashboard.workshop = { available: false, reason: 'No current actionable public workshop finding.' }
|
|
684
|
+
}
|
|
685
|
+
result = { dashboard }
|
|
686
|
+
}
|
|
687
|
+
else if (operation === 'context') result = { context: knowledgeQuestionContext(loadKnowledgeWorkspace(knowledgeProject), url.searchParams.get('id'), url.searchParams.get('mode') || 'graph') }
|
|
688
|
+
else if (operation === 'sessions') result = knowledge.list()
|
|
689
|
+
else if (operation === 'read') result = knowledge.read(url.searchParams.get('id'))
|
|
690
|
+
else { json(res, 404, { ok: false, error: 'unknown knowledge action' }); return }
|
|
691
|
+
json(res, 200, { ok: true, ...result })
|
|
692
|
+
} catch (error) { json(res, 409, { ok: false, error: knowledgeError(error) }) }
|
|
693
|
+
return
|
|
694
|
+
}
|
|
695
|
+
|
|
511
696
|
if (review && url.pathname === '/review') {
|
|
512
697
|
const body = renderReviewPage()
|
|
513
698
|
res.writeHead(200, htmlDocumentHeaders(Buffer.byteLength(body)))
|
|
@@ -606,6 +791,8 @@ export function createAtelierSidecarServer({
|
|
|
606
791
|
proposal: record.proposal,
|
|
607
792
|
diff: record.diff,
|
|
608
793
|
copyable: record.copyable,
|
|
794
|
+
// A retained workshop handoff is read back whole; other proposals are unchanged.
|
|
795
|
+
...(record.retention ? { payload: record.payload, retention: record.retention } : {}),
|
|
609
796
|
} : { ok: false, error: result.error, diagnostics: result.diagnostics })
|
|
610
797
|
return
|
|
611
798
|
}
|
|
@@ -662,14 +849,13 @@ export function createAtelierSidecarServer({
|
|
|
662
849
|
if (!isLoopbackHost(host)) {
|
|
663
850
|
return Promise.reject(new Error(`non-loopback listen host refused: ${host}`))
|
|
664
851
|
}
|
|
665
|
-
// A busy port is an ordinary condition, not a crash: surface
|
|
666
|
-
// rejection the CLI
|
|
852
|
+
// A busy or refused port is an ordinary condition, not a crash: surface
|
|
853
|
+
// it as a typed rejection the CLI prints with its remedy, instead of an
|
|
854
|
+
// unhandled 'error' event or a redacted internal error.
|
|
667
855
|
return new Promise((resolve, reject) => {
|
|
668
856
|
const onError = (error) => {
|
|
669
857
|
server.removeListener('listening', onListening)
|
|
670
|
-
reject(error
|
|
671
|
-
? new Error(`port ${listenPort} is already in use — pass --port=<free port> to choose another`)
|
|
672
|
-
: error)
|
|
858
|
+
reject(listenFailure(error, listenPort))
|
|
673
859
|
}
|
|
674
860
|
const onListening = () => {
|
|
675
861
|
server.removeListener('error', onError)
|
package/src/server/server.mjs
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { AtelierDiagnosticError, resolveProjectConfig } from '../project/config.mjs'
|
|
2
4
|
import { createAtelierSidecarServer } from './local-sidecar.mjs'
|
|
3
5
|
|
|
6
|
+
// dev serves what build wrote and builds nothing itself. Before build, the
|
|
7
|
+
// output folder (or, after graph alone, its manifest) is absent, and the
|
|
8
|
+
// sidecar failed with a raw ENOENT carrying an absolute path or a redacted
|
|
9
|
+
// internal error. Name the missing steps instead, and name the folder only
|
|
10
|
+
// relative to the project config. A non-directory is left to the sidecar.
|
|
11
|
+
function assertProjectionBuilt(project) {
|
|
12
|
+
const stat = fs.statSync(project.outputRoot, { throwIfNoEntry: false })
|
|
13
|
+
if (stat && !stat.isDirectory()) return
|
|
14
|
+
const manifestMissing = stat && !fs.existsSync(path.join(project.outputRoot, 'atelier.manifest.json'))
|
|
15
|
+
if (stat && !manifestMissing) return
|
|
16
|
+
const rel = path.relative(project.configDir, project.outputRoot)
|
|
17
|
+
const contained = rel !== '' && rel !== '..' && !rel.startsWith(`..${path.sep}`) && !path.isAbsolute(rel)
|
|
18
|
+
const folder = contained ? `projection output folder ${rel}` : 'the projection output folder'
|
|
19
|
+
const state = manifestMissing ? 'has no atelier.manifest.json' : 'does not exist'
|
|
20
|
+
throw new AtelierDiagnosticError('projection-output-missing', `${folder} ${state}; this project has not been built yet`, {
|
|
21
|
+
hint: 'Run atelier graph, then atelier build, with the same --project path, then retry.',
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
4
25
|
function parseServerArgs(argv = []) {
|
|
5
26
|
const args = { projectArgs: [] }
|
|
6
27
|
for (const arg of argv) {
|
|
@@ -11,17 +32,35 @@ function parseServerArgs(argv = []) {
|
|
|
11
32
|
return args
|
|
12
33
|
}
|
|
13
34
|
|
|
35
|
+
// argv > PORT env > default. Supervisors that assign a free port (preview
|
|
36
|
+
// panes, dev harnesses) pass it via PORT, and an Atelier that ignores that
|
|
37
|
+
// fights whatever already holds the canonical port instead of coexisting.
|
|
38
|
+
// A value listen would refuse is refused here, naming where it came from;
|
|
39
|
+
// Node's own range error names neither the flag nor the variable.
|
|
40
|
+
function resolvePort(args, env = process.env) {
|
|
41
|
+
const [source, raw] = args.port ? ['--port', args.port] : env.PORT ? ['PORT', env.PORT] : [null, '8137']
|
|
42
|
+
const port = Number(raw)
|
|
43
|
+
if (Number.isInteger(port) && port >= 0 && port <= 65535) return port
|
|
44
|
+
throw new AtelierDiagnosticError('port-invalid', `${source} must be a whole number from 0 to 65535, got ${JSON.stringify(raw)}`, {
|
|
45
|
+
hint: source === 'PORT'
|
|
46
|
+
? 'Set PORT to a free port or unset it, or pass --port=<free port> to override it.'
|
|
47
|
+
: 'Pass a free port, for example --port=8138.',
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
14
51
|
export async function runServerCommand(argv = process.argv.slice(2)) {
|
|
15
52
|
const args = parseServerArgs(argv)
|
|
16
53
|
const project = resolveProjectConfig({ argv: args.projectArgs })
|
|
54
|
+
// An unusable --port or PORT is refused before the project's build state,
|
|
55
|
+
// so a mistyped argument is named even in a project not built yet.
|
|
56
|
+
const port = args.smoke ? 0 : resolvePort(args)
|
|
57
|
+
assertProjectionBuilt(project)
|
|
17
58
|
const sidecar = createAtelierSidecarServer({
|
|
18
59
|
workspaceRoot: project.outputRoot,
|
|
19
60
|
stateDir: project.outputRoot,
|
|
20
61
|
reviewProject: argv.includes('--review') ? project : null,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// fights whatever already holds the canonical port instead of coexisting.
|
|
24
|
-
port: args.smoke ? 0 : Number(args.port || process.env.PORT || 8137),
|
|
62
|
+
knowledgeProject: argv.includes('--knowledge') ? project : null,
|
|
63
|
+
port,
|
|
25
64
|
})
|
|
26
65
|
|
|
27
66
|
if (args.smoke) {
|
|
@@ -40,5 +79,5 @@ export async function runServerCommand(argv = process.argv.slice(2)) {
|
|
|
40
79
|
}
|
|
41
80
|
|
|
42
81
|
const address = await sidecar.listen()
|
|
43
|
-
console.log(`MNSTRY Atelier listening on http://127.0.0.1:${address.port}
|
|
82
|
+
console.log(`MNSTRY Atelier listening on http://127.0.0.1:${address.port}/${argv.includes('--knowledge') ? 'knowledge' : ''}`)
|
|
44
83
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import { buildCanonicalGraph, createGraphFileCache } from '../graph/graph.mjs'
|
|
3
|
+
import { projectGraph, PROJECTION_TARGETS } from '../projection/policy.mjs'
|
|
4
|
+
import { renderReadOnlyDocument, validatePresentation } from '../ui/presentation/index.mjs'
|
|
5
|
+
import { templateReference, validateTemplateDefinition, validateTemplateBinding, validateTemplateHost } from '../templates/profile.mjs'
|
|
6
|
+
|
|
7
|
+
const packageVersion = JSON.parse(fs.readFileSync(new URL('../../package.json', import.meta.url), 'utf8')).version
|
|
8
|
+
const identity = value => templateReference('PayloadRef', 'identity', '1', value).digest.slice(7, 39)
|
|
9
|
+
const outcome = (ok, errors, rest = {}) => ({ ok, errors, authority: 'structural-only', executionAuthority: false, publicationAuthority: false, conformanceClaim: 'none', ...rest })
|
|
10
|
+
|
|
11
|
+
/** Read-only composition over a loaded project, not a graph or source writer.
|
|
12
|
+
* The request is bounded JSON text: {profile, projectRef, roleNodeIds, target,
|
|
13
|
+
* theme?}. This initial binding supports classified active Markdown resources,
|
|
14
|
+
* Resource bindings and CollectionView/StatusView. Other requirements
|
|
15
|
+
* refuse instead of being converted to a superficially similar surface.
|
|
16
|
+
*/
|
|
17
|
+
export function createTemplateProjectView(project, requestJson) {
|
|
18
|
+
try {
|
|
19
|
+
if (typeof requestJson !== 'string' || Buffer.byteLength(requestJson) > 1048576) return outcome(false, ['invalid request'])
|
|
20
|
+
const request = JSON.parse(requestJson)
|
|
21
|
+
// The profile reference validator also enforces bounded plain JSON before
|
|
22
|
+
// the request is used; no caller-supplied accessors enter this adapter.
|
|
23
|
+
templateReference('PayloadRef', 'request', '1', request)
|
|
24
|
+
if (!request || Array.isArray(request) || Object.keys(request).some(key => !['profile', 'projectRef', 'roleNodeIds', 'target', 'theme'].includes(key))) return outcome(false, ['invalid request'])
|
|
25
|
+
const { profile, projectRef, roleNodeIds, target, theme = 'light' } = request
|
|
26
|
+
const definition = validateTemplateDefinition(profile)
|
|
27
|
+
if (!definition.ok) return outcome(false, definition.errors)
|
|
28
|
+
if (!Object.hasOwn(PROJECTION_TARGETS, target)) return outcome(false, ['unknown projection target'])
|
|
29
|
+
if (!roleNodeIds || Array.isArray(roleNodeIds) || typeof roleNodeIds !== 'object') return outcome(false, ['invalid role selection'])
|
|
30
|
+
if (profile.runtimeProfileRef !== null) return outcome(false, ['runtime profile requires its owning adapter'])
|
|
31
|
+
const templateRef = templateReference('TemplateRef', profile.id, profile.version, profile)
|
|
32
|
+
const host = validateTemplateHost(profile, {
|
|
33
|
+
schema: 'atelier-template-host@v1', templateRef, carrier: 'web', atelierVersion: packageVersion,
|
|
34
|
+
packRefs: [], semanticPrimitives: ['Resource'], surfacePrimitives: ['CollectionView', 'StatusView'],
|
|
35
|
+
runtimeProfileRef: null, optionalDecisions: [],
|
|
36
|
+
})
|
|
37
|
+
if (!host.ok) return outcome(false, host.errors)
|
|
38
|
+
const cache = createGraphFileCache()
|
|
39
|
+
const graph = buildCanonicalGraph(project, { fileCache: cache })
|
|
40
|
+
if (!graph.ok) return outcome(false, ['canonical graph invalid'])
|
|
41
|
+
const projected = projectGraph(graph, { target })
|
|
42
|
+
const visible = new Map(projected.nodes.filter(node => node.classification === 'classified' && node.status === 'active').map(node => [node.id, node]))
|
|
43
|
+
const records = [], sources = new Map(), roles = []
|
|
44
|
+
for (const [roleRef, ids] of Object.entries(roleNodeIds)) {
|
|
45
|
+
if (!profile.semanticRoles.some(role => role.id === roleRef) || !Array.isArray(ids) || !ids.length || ids.length > 256 || ids.some(id => typeof id !== 'string') || new Set(ids).size !== ids.length) return outcome(false, ['invalid role selection'])
|
|
46
|
+
if (profile.semanticRoles.find(role => role.id === roleRef).primitive !== 'Resource') return outcome(false, ['semantic role has no canonical binding'])
|
|
47
|
+
const refs = []
|
|
48
|
+
for (const id of ids) {
|
|
49
|
+
const node = visible.get(id)
|
|
50
|
+
// A node's audience cannot widen its repository's read boundary.
|
|
51
|
+
if (!node || !PROJECTION_TARGETS[target].has(node.repoAccess?.readBoundary)) return outcome(false, ['selected source unavailable for this view'])
|
|
52
|
+
const source = cache.files.get(`${node.repo}\u0000${node.path}`)
|
|
53
|
+
if (!source || !/^[a-f0-9]{64}$/.test(source.digest)) return outcome(false, ['source byte pin unavailable'])
|
|
54
|
+
if (!sources.has(id)) {
|
|
55
|
+
const document = { nodeId: id, repository: node.repo, path: node.path, rawDigest: `sha256:${source.digest}`, title: node.title, summary: node.summary }
|
|
56
|
+
const ref = templateReference('SourceRef', `source.${identity(id)}`, document.rawDigest, document)
|
|
57
|
+
sources.set(id, { ref, document }); records.push({ ref, document })
|
|
58
|
+
}
|
|
59
|
+
refs.push(sources.get(id).ref)
|
|
60
|
+
}
|
|
61
|
+
roles.push({ roleRef, sourceRefs: refs })
|
|
62
|
+
}
|
|
63
|
+
const binding = { schema: 'atelier-template-binding@v1', id: `binding.${identity(projectRef)}`, version: '1.0.0', templateRef, projectRef, roles }
|
|
64
|
+
const checked = validateTemplateBinding(profile, binding, records)
|
|
65
|
+
if (!checked.ok) return outcome(false, checked.errors)
|
|
66
|
+
const bindingRef = templateReference('BindingRef', binding.id, binding.version, binding)
|
|
67
|
+
const nodes = profile.surfaceRoles.map((view, index) => {
|
|
68
|
+
const id = `view-${index}`
|
|
69
|
+
if (view.primitive === 'StatusView') return { id, type: 'status', label: view.id, text: 'Read-only local projection. Runtime actions and publication are unavailable.', tone: 'neutral', details: host.diagnostics.map(item => ({ label: item.id, value: item.kind === 'semantic-role' ? 'Optional role unsupported; binding unavailable' : `${item.status}; deterministic or manual fallback` })), actions: [] }
|
|
70
|
+
const sourceIds = [...new Set(view.semanticRoleRefs.flatMap(role => roleNodeIds[role] ?? []))]
|
|
71
|
+
return { id, type: 'collection', label: view.id, items: sourceIds.map(sourceId => ({ id: `item-${identity(sourceId)}`, label: sources.get(sourceId).document.title, detail: sources.get(sourceId).document.summary })) }
|
|
72
|
+
})
|
|
73
|
+
nodes.unshift({ id: 'description', type: 'text', label: 'Inputs and limits', text: `Inputs: ${profile.inputs.join('; ')}. Limits: ${profile.limitations.join('; ')}` })
|
|
74
|
+
nodes.push({ id: 'identity', type: 'text', label: 'Template and binding identity', text: `Template: ${templateRef.id}@${templateRef.version}; ${templateRef.digest}. Binding: ${bindingRef.id}@${bindingRef.version}; ${bindingRef.digest}. Release: none (local preview). Structural references only; not verified authorship, release acceptance or rights.` })
|
|
75
|
+
// Provenance travels with readable exports, not only the API envelope.
|
|
76
|
+
// Use opaque refs and byte pins; never expose local repository paths here.
|
|
77
|
+
for (let offset = 0; offset < records.length; offset += 128) nodes.push({
|
|
78
|
+
id: `provenance-${offset}`, type: 'collection', label: 'Source provenance',
|
|
79
|
+
items: records.slice(offset, offset + 128).map(({ ref, document }) => ({ id: `source-${identity(ref.id)}`, label: document.title, detail: `SourceRef: ${ref.id}; ${ref.digest}. Source bytes: ${document.rawDigest}.` })),
|
|
80
|
+
})
|
|
81
|
+
const model = { schema: 'atelier.presentation/v1', version: '1.0.0', id: `template-${identity(profile.id)}`, title: profile.purpose, lang: 'en', direction: 'ltr', theme, density: 'comfortable', navigation: [], panes: [{ id: 'content', label: 'Template preview', role: 'primary', blocks: nodes.map(node => node.id) }], nodes }
|
|
82
|
+
if (validatePresentation(model).length) return outcome(false, ['presentation binding invalid'])
|
|
83
|
+
// Reuse the exact same non-interactive renderer for local web and document
|
|
84
|
+
// preview. This creates bytes only; it does not publish or erase old copies.
|
|
85
|
+
const html = renderReadOnlyDocument(model)
|
|
86
|
+
const textPreview = [model.title, ...nodes.flatMap(node => [node.label, ...(node.items ? node.items.flatMap(item => [item.label, item.detail]) : [node.text]), ...(node.details ?? []).map(item => `${item.label}: ${item.value}`)])].join('\n\n')
|
|
87
|
+
return outcome(true, [], { templateRef, bindingRef, binding, records, model, html, textPreview, capabilityDiagnostics: host.diagnostics, optionalDecisions: host.diagnostics.filter(item => item.kind !== 'semantic-role'), target, lifecycle: 'active-only', artifacts: { web: html, documents: html } })
|
|
88
|
+
} catch {
|
|
89
|
+
// Do not disclose source paths or source text through exception messages.
|
|
90
|
+
return outcome(false, ['template project composition refused'])
|
|
91
|
+
}
|
|
92
|
+
}
|