@mnstry/atelier 0.2.0-alpha.12 → 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 +661 -0
- package/README.md +142 -6
- 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-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/docs/architecture.md +89 -0
- package/docs/assurance-controls.md +2 -2
- 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 +181 -16
- package/docs/obsidian-contract.md +223 -15
- package/docs/obsidian-plugin.md +38 -4
- package/docs/obsidian.md +613 -51
- 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 +49 -0
- 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 +47 -2
- 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/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 +59 -5
- 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 +754 -63
- 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 +30 -0
- package/src/coordination/index.mjs +110 -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/projection/obsidian/edits/apply.mjs +55 -16
- package/src/projection/obsidian/personal-workspace.mjs +436 -0
- package/src/projection/obsidian/proposals/adapter.mjs +47 -8
- package/src/projection/obsidian/proposals/observation.mjs +10 -2
- package/src/projection/obsidian/publication/publisher.mjs +142 -13
- package/src/projection/obsidian/publication/vault-list.mjs +4 -3
- package/src/projection/obsidian/recovery/index.mjs +4 -1
- package/src/projection/obsidian/recovery/store.mjs +160 -7
- package/src/projection/obsidian/selection-ui/contribution.mjs +6 -5
- package/src/readiness/readiness.mjs +10 -3
- package/src/reflection/index.mjs +56 -0
- package/src/runtime/obsidian/app-production-seams.mjs +48 -16
- package/src/runtime/obsidian/app-registration.mjs +175 -28
- package/src/runtime/obsidian/app-restart.mjs +154 -0
- package/src/runtime/obsidian/engine.mjs +163 -20
- package/src/runtime/obsidian/extension-points.mjs +1 -1
- package/src/runtime/obsidian/index.mjs +10 -7
- package/src/runtime/obsidian/launch-plan.mjs +7 -4
- package/src/runtime/obsidian/lifecycle.mjs +92 -12
- package/src/runtime/obsidian/login-item.mjs +332 -0
- package/src/runtime/obsidian/machine-settings.mjs +119 -12
- package/src/runtime/obsidian/opening.mjs +171 -37
- package/src/runtime/obsidian/pipeline.mjs +71 -3
- package/src/runtime/obsidian/plugin-channel.mjs +11 -3
- package/src/runtime/obsidian/plugin-choice.mjs +16 -4
- package/src/runtime/obsidian/plugin-drift.mjs +59 -11
- package/src/runtime/obsidian/plugin-presence.mjs +14 -1
- 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 +99 -16
- 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 +87 -23
- package/src/runtime/obsidian/service.mjs +36 -3
- package/src/runtime/obsidian/startup-adapters.mjs +59 -21
- 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 +169 -2
- package/src/server/server.mjs +28 -2
- 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 +1 -0
- 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
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
import { canonicalize } from '../attestation/jcs.mjs'
|
|
2
|
+
import { createIntakeStore, intakeDigest } from '../intake/store.mjs'
|
|
3
|
+
import { createIngestionStore } from '../ingestion/store.mjs'
|
|
4
|
+
import { ingestionJson, ingestionDigest } from '../ingestion/contracts.mjs'
|
|
5
|
+
import { prepareSemanticInput, prepareSemanticProposals, readSemanticProposals } from '../ingestion/semantic.mjs'
|
|
6
|
+
import { appendHarness, readHarness } from '../harnesses/store.mjs'
|
|
7
|
+
import { harnessRef, contentDigest } from '../harnesses/contracts.mjs'
|
|
8
|
+
import { inspectKnowledge } from './ledger.mjs'
|
|
9
|
+
import { prepareIngestionContribution, localKnowledgeContext } from './ingestion.mjs'
|
|
10
|
+
import { knowledgeGraphProposal } from './projection.mjs'
|
|
11
|
+
import { learningDigest } from '../learning/contracts.mjs'
|
|
12
|
+
|
|
13
|
+
const OPERATION = 'atelier.semantic-operation/v0'
|
|
14
|
+
export const SEMANTIC_OPERATION_PROFILE = 'atelier.semantic-operation-profile/v0'
|
|
15
|
+
export class SemanticOperationError extends Error {
|
|
16
|
+
constructor(code, message) { super(message); this.name = 'SemanticOperationError'; this.code = code }
|
|
17
|
+
}
|
|
18
|
+
function withSavedReceipts(error, receipts) {
|
|
19
|
+
if (Object.keys(receipts).length === 0) return error
|
|
20
|
+
let code
|
|
21
|
+
if (error !== null && ['object', 'function'].includes(typeof error)) {
|
|
22
|
+
try {
|
|
23
|
+
const codeProperty = Object.getOwnPropertyDescriptor(error, 'code')
|
|
24
|
+
if (typeof codeProperty?.value === 'string' && /^SEMANTIC_[A-Z_]+$/.test(codeProperty.value)) code = codeProperty.value
|
|
25
|
+
const descriptors = {}, extensible = Object.isExtensible(error)
|
|
26
|
+
let writable = true
|
|
27
|
+
for (const [key, value] of Object.entries(receipts)) {
|
|
28
|
+
const existing = Object.getOwnPropertyDescriptor(error, key)
|
|
29
|
+
if (existing ? !Object.hasOwn(existing, 'value') || !existing.writable : !extensible) { writable = false; break }
|
|
30
|
+
descriptors[key] = existing ? { value } : { value, writable: true, configurable: true, enumerable: true }
|
|
31
|
+
}
|
|
32
|
+
if (writable) { Object.defineProperties(error, descriptors); return error }
|
|
33
|
+
} catch { /* Reflection/decoration failure must not erase the original cause. */ }
|
|
34
|
+
}
|
|
35
|
+
const failure = new SemanticOperationError(code ?? 'SEMANTIC_OPERATION_INTERRUPTED', 'Semantic operation was interrupted after saving recoverable receipts')
|
|
36
|
+
Object.defineProperty(failure, 'cause', { value: error, writable: true, configurable: true })
|
|
37
|
+
Object.assign(failure, receipts)
|
|
38
|
+
return failure
|
|
39
|
+
}
|
|
40
|
+
function check(condition, code, message) { if (!condition) throw new SemanticOperationError(code, message) }
|
|
41
|
+
function identifier(value) { check(typeof value === 'string' && /^[a-z][a-z0-9-]{0,63}$/.test(value), 'SEMANTIC_OPERATION_INVALID', 'A bounded operation identifier is required'); return value }
|
|
42
|
+
function json(value) {
|
|
43
|
+
try { return ingestionJson(value) }
|
|
44
|
+
catch (error) {
|
|
45
|
+
const limit = ['ingestion JSON depth exceeded', 'ingestion member ceiling exceeded', 'ingestion document byte ceiling exceeded'].includes(error?.message)
|
|
46
|
+
throw new SemanticOperationError(limit ? 'SEMANTIC_OPERATION_LIMIT' : 'SEMANTIC_OPERATION_INVALID', limit ? 'Operation JSON limit exceeded' : 'Bounded plain operation JSON is required')
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function closed(value, fields) {
|
|
50
|
+
check(value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === fields.length && fields.every(key => Object.hasOwn(value, key)), 'SEMANTIC_OPERATION_INVALID', 'The declared operation shape is required')
|
|
51
|
+
}
|
|
52
|
+
const eventId = (operationId, phase) => `semantic-${intakeDigest(`${operationId}:${phase}`).slice(0, 40)}`
|
|
53
|
+
function extractorPins(value, inputDigest) {
|
|
54
|
+
const pins = json(value)
|
|
55
|
+
closed(pins, ['id', 'version', 'route', 'model', 'promptDigest', 'parameters'])
|
|
56
|
+
identifier(pins.id)
|
|
57
|
+
check(typeof pins.version === 'string' && /^[a-zA-Z0-9._-]{1,64}$/.test(pins.version), 'SEMANTIC_OPERATION_INVALID', 'A bounded extractor version is required')
|
|
58
|
+
check(['model', 'deterministic', 'authored'].includes(pins.route), 'SEMANTIC_OPERATION_INVALID', 'Declare the extraction route')
|
|
59
|
+
check(pins.route === 'model' ? typeof pins.model === 'string' && pins.model.length > 0 && pins.model.length <= 256 : pins.model === null, 'SEMANTIC_OPERATION_INVALID', 'Model routes need a model pin; other routes use null')
|
|
60
|
+
check(typeof pins.promptDigest === 'string' && /^[a-f0-9]{64}$/.test(pins.promptDigest), 'SEMANTIC_OPERATION_INVALID', 'A prompt or configuration digest is required')
|
|
61
|
+
check(pins.parameters && typeof pins.parameters === 'object' && !Array.isArray(pins.parameters), 'SEMANTIC_OPERATION_INVALID', 'Plain extractor parameters are required')
|
|
62
|
+
return { ...pins, configurationDigest: intakeDigest(canonicalize({ ...pins, inputDigest })) }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Called only after the proposal validator has checked the complete assertion.
|
|
66
|
+
// Omission is explicit: the qualified contribution remains available for review.
|
|
67
|
+
export function plainAssertionEligibility(assertion, domain) {
|
|
68
|
+
check(assertion && assertion.time && Array.isArray(assertion.time.unknowns) && domain?.data &&
|
|
69
|
+
['from', 'until', 'expression'].every(key => Object.hasOwn(assertion.time, key)), 'SEMANTIC_PROJECTION_SUPPORT', 'An explicitly qualified assertion and domain are required')
|
|
70
|
+
const reasons = []
|
|
71
|
+
if (assertion.objectId === null || assertion.direction !== 'subject-to-object') reasons.push('unary')
|
|
72
|
+
if (assertion.negated !== false) reasons.push('negated')
|
|
73
|
+
if (assertion.modality !== 'asserted') reasons.push('modal')
|
|
74
|
+
if (assertion.time.from !== null || assertion.time.until !== null || assertion.time.expression !== null || assertion.time.unknowns.length) reasons.push('temporal')
|
|
75
|
+
if (assertion.scope !== domain.data.scope) reasons.push('scope')
|
|
76
|
+
return { eligible: reasons.length === 0, reasons }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const semanticRelationId = assertionId => `relation-${intakeDigest(identifier(assertionId)).slice(0, 40)}`
|
|
80
|
+
export function assertSemanticOperationProfile({ references = [], candidates = null }) {
|
|
81
|
+
if (Array.isArray(references)) for (const reference of references) {
|
|
82
|
+
check(!reference?.locator || ['line', 'csv-cell', 'json-pointer'].includes(reference.locator.kind), 'SEMANTIC_UNSUPPORTED_LOCATOR', 'unsupported-locator')
|
|
83
|
+
}
|
|
84
|
+
if (Array.isArray(candidates?.assertions)) for (const assertion of candidates.assertions) {
|
|
85
|
+
if (!assertion || typeof assertion !== 'object' || Array.isArray(assertion)) continue
|
|
86
|
+
check(assertion.scope === undefined || typeof assertion.scope === 'string', 'SEMANTIC_UNSUPPORTED_SCOPE', 'unsupported-scope')
|
|
87
|
+
check(!Object.hasOwn(assertion, 'literalObject') && (assertion.objectId === undefined || assertion.objectId === null || typeof assertion.objectId === 'string'), 'SEMANTIC_UNSUPPORTED_LITERAL_OBJECT', 'unsupported-literal-object')
|
|
88
|
+
if (Array.isArray(assertion.evidence)) for (const support of assertion.evidence) {
|
|
89
|
+
check(typeof support?.quote !== 'string' || !/[\r\n]/u.test(support.quote), 'SEMANTIC_UNSUPPORTED_LOCATOR', 'unsupported-locator: multiline quote')
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export function semanticDependencyWitnesses({ citations, sources, endpoints = [] }) {
|
|
94
|
+
const basedOn = [], sourceWitness = []
|
|
95
|
+
function witness(record, quote, dependency = 'source') {
|
|
96
|
+
check(typeof quote === 'string' && quote.length > 0, 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'A source quote is required for a dependency witness')
|
|
97
|
+
let encoded = ''
|
|
98
|
+
for (const point of quote) {
|
|
99
|
+
const encodedPoint = JSON.stringify(point).slice(1, -1)
|
|
100
|
+
if (encoded.length + encodedPoint.length > 8192) break
|
|
101
|
+
encoded += encodedPoint
|
|
102
|
+
}
|
|
103
|
+
check(encoded.length > 0 && record.data.body.includes(encoded), 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'The encoded dependency witness is absent from the stored contribution body')
|
|
104
|
+
if (basedOn.some(item => item.contribution.id === record.id)) return
|
|
105
|
+
check(basedOn.length < 64, 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'Sources and endpoints exceed the existing dependency limit')
|
|
106
|
+
basedOn.push({ contribution: harnessRef(record), quote: encoded })
|
|
107
|
+
sourceWitness.push({ contributionId: record.id, encoding: 'json-string-substring', purpose: 'ledger-dependency-only', dependency })
|
|
108
|
+
}
|
|
109
|
+
for (const citation of citations) {
|
|
110
|
+
const matches = sources.filter(record => record.data.origin.method === 'extracted' && record.data.origin.attemptId === citation.attemptId && record.data.origin.blobDigest === `sha256:${citation.sourceDigest}`)
|
|
111
|
+
check(matches.length === 1, 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'Each citation needs one exact current structural source contribution')
|
|
112
|
+
witness(matches[0], citation.quote)
|
|
113
|
+
}
|
|
114
|
+
for (const endpoint of endpoints) witness(endpoint.record, endpoint.quote, endpoint.dependency)
|
|
115
|
+
return { basedOn, sourceWitness }
|
|
116
|
+
}
|
|
117
|
+
// Relation support is not a ledger dependency in harness v1. This guard is
|
|
118
|
+
// stateless and fails closed even when withdrawal cleanup has not run.
|
|
119
|
+
export function assertSemanticProjection({ records, activationId, reconsider = [] }) {
|
|
120
|
+
const state = inspectKnowledge(records), byId = new Map(records.map(record => [record.id, record]))
|
|
121
|
+
const stale = new Set([...state.reconsider, ...reconsider].map(item => item.id))
|
|
122
|
+
const accepted = new Set(state.accepted), active = new Set(), selected = new Set()
|
|
123
|
+
const activation = byId.get(activationId)
|
|
124
|
+
check(activation?.kind === 'activation' && !stale.has(activationId), 'SEMANTIC_PROJECTION_STALE', 'A current activation is required')
|
|
125
|
+
for (const record of records) if (record.kind === 'activation' && !stale.has(record.id)) {
|
|
126
|
+
for (const pin of record.data.reviews) active.add(byId.get(pin.id).data.target.id)
|
|
127
|
+
}
|
|
128
|
+
function include(id) {
|
|
129
|
+
if (selected.has(id)) return
|
|
130
|
+
check(accepted.has(id) && !stale.has(id), 'SEMANTIC_PROJECTION_STALE', 'Every projected dependency must have current acceptance')
|
|
131
|
+
selected.add(id)
|
|
132
|
+
const record = byId.get(id)
|
|
133
|
+
if (record.kind === 'relation') {
|
|
134
|
+
const support = /(?:^|\n)semantic-support: ([a-z][a-z0-9-]{0,63}) (sha256:[a-f0-9]{64})$/.exec(record.data.rationale)
|
|
135
|
+
check(support && record.id === semanticRelationId(support[1]), 'SEMANTIC_PROJECTION_SUPPORT', 'A semantic relation needs its unique exact assertion support pin')
|
|
136
|
+
const assertion = byId.get(support[1])
|
|
137
|
+
check(assertion?.kind === 'contribution' && harnessRef(assertion).digest === support[2], 'SEMANTIC_PROJECTION_SUPPORT', 'Relation assertion support digest differs')
|
|
138
|
+
check(accepted.has(assertion.id) && active.has(assertion.id) && !stale.has(assertion.id), 'SEMANTIC_PROJECTION_SUPPORT', 'Relation support must be currently accepted, active and not withdrawn or superseded')
|
|
139
|
+
let body
|
|
140
|
+
try { body = JSON.parse(assertion.data.body) } catch { throw new SemanticOperationError('SEMANTIC_PROJECTION_SUPPORT', 'A qualified assertion body is required') }
|
|
141
|
+
check(body?.schema === SEMANTIC_OPERATION_PROFILE && body.kind === 'assertion', 'SEMANTIC_PROJECTION_SUPPORT', 'A semantic assertion contribution is required')
|
|
142
|
+
check(plainAssertionEligibility(body.candidate, state.domain).eligible, 'SEMANTIC_PROJECTION_QUALIFIED', 'A qualified assertion cannot become a plain edge')
|
|
143
|
+
check(body.candidate.predicate === record.data.predicate && body.endpoints?.subject?.id === record.data.subject.id && body.endpoints?.object?.id === record.data.object.id,
|
|
144
|
+
'SEMANTIC_PROJECTION_SUPPORT', 'Relation participants differ from its reviewed assertion')
|
|
145
|
+
include(assertion.id)
|
|
146
|
+
include(record.data.subject.id); include(record.data.object.id)
|
|
147
|
+
} else for (const pin of record.data.basedOn) include(pin.contribution.id)
|
|
148
|
+
}
|
|
149
|
+
for (const pin of activation.data.reviews) include(byId.get(pin.id).data.target.id)
|
|
150
|
+
return { selected: [...selected], activation: harnessRef(activation), authority: 'none' }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Existing intake owns bytes; the existing harness owns all durable metadata.
|
|
154
|
+
// This runner never invokes an extractor or infers a receiver decision.
|
|
155
|
+
export function createSemanticOperation({ workspaceRoot, workspaceId, run }) {
|
|
156
|
+
identifier(run)
|
|
157
|
+
const intake = createIntakeStore({ workspaceRoot })
|
|
158
|
+
const store = createIngestionStore({ workspaceRoot, workspaceId })
|
|
159
|
+
const readHistory = () => readHarness({ workspaceRoot, profile: 'knowledge', run })
|
|
160
|
+
let verification = null
|
|
161
|
+
const history = () => verification?.state ?? readHistory()
|
|
162
|
+
function verified(read) {
|
|
163
|
+
if (verification) return read()
|
|
164
|
+
const state = readHistory()
|
|
165
|
+
verification = { state, completed: new Map(), sources: new Map() }
|
|
166
|
+
let result
|
|
167
|
+
try {
|
|
168
|
+
result = read()
|
|
169
|
+
for (const current of verification.completed.values()) {
|
|
170
|
+
const input = current.initial.value.input
|
|
171
|
+
const refreshed = prepareSemanticInput({ store, plan: input.plan, domain: state.domain, references: input.evidence.map(span => span.reference), identityCandidates: input.identityCandidates })
|
|
172
|
+
check(refreshed.digest === input.digest, 'SEMANTIC_OPERATION_STALE', 'Semantic evidence changed during the operation')
|
|
173
|
+
}
|
|
174
|
+
check(readHistory().head === (result.head ?? state.head), 'SEMANTIC_OPERATION_HEAD', 'Knowledge history changed during the operation')
|
|
175
|
+
return result
|
|
176
|
+
} catch (error) {
|
|
177
|
+
const receipts = result?.record && result.head
|
|
178
|
+
? { recorded: { record: harnessRef(result.record), head: result.head, nextAction: 'reopen-recorded-write' } } : {}
|
|
179
|
+
throw withSavedReceipts(error, receipts)
|
|
180
|
+
} finally { verification = null }
|
|
181
|
+
}
|
|
182
|
+
function events(state) {
|
|
183
|
+
const result = []
|
|
184
|
+
for (const record of state.records) {
|
|
185
|
+
if (record.kind !== 'contribution') continue
|
|
186
|
+
let value
|
|
187
|
+
try { value = JSON.parse(record.data.body) } catch { continue }
|
|
188
|
+
if (value?.schema !== OPERATION) continue
|
|
189
|
+
check(record.data.origin.method === 'captured' && record.data.origin.contentDigest === contentDigest(record.data.body) && record.id === eventId(value.operationId, value.phase), 'SEMANTIC_OPERATION_INTEGRITY', 'Operation record identity differs')
|
|
190
|
+
result.push({ record, value })
|
|
191
|
+
}
|
|
192
|
+
return result
|
|
193
|
+
}
|
|
194
|
+
function operation(operationId, state = history()) {
|
|
195
|
+
identifier(operationId)
|
|
196
|
+
const matching = events(state).filter(event => event.value.operationId === operationId)
|
|
197
|
+
check(matching.length > 0 && matching[0].value.phase === 'reserved', 'SEMANTIC_OPERATION_MISSING', 'No reserved semantic operation exists')
|
|
198
|
+
return { initial: matching[0], latest: matching.at(-1), state }
|
|
199
|
+
}
|
|
200
|
+
function append(value, { term, at, by, confirm, basedOn = [] }) {
|
|
201
|
+
const state = history(), domain = state.domain
|
|
202
|
+
check(domain && state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'The current knowledge history digest is required')
|
|
203
|
+
const body = canonicalize(json(value))
|
|
204
|
+
const record = { schema: 'atelier-knowledge-record@v1', id: eventId(value.operationId, value.phase), run, at, by, kind: 'contribution', data: {
|
|
205
|
+
domain: harnessRef(domain), category: 'decision-rationale', term, title: `Semantic operation ${value.operationId}: ${value.phase}`, body,
|
|
206
|
+
audience: domain.data.audience, scope: domain.data.scope,
|
|
207
|
+
origin: { method: 'captured', locator: `semantic-operation:${value.operationId}`, contentDigest: contentDigest(body), rightsBasis: 'Host-declared operation metadata; integrity is not semantic acceptance.' }, basedOn,
|
|
208
|
+
} }
|
|
209
|
+
return { ...appendHarness({ workspaceRoot, profile: 'knowledge', record, confirm }), record }
|
|
210
|
+
}
|
|
211
|
+
function expectedAttempt(initial) {
|
|
212
|
+
const value = initial.value
|
|
213
|
+
return { schema: 'mnstry.atelier-intake-attempt@v1', attemptId: value.attemptId, blobId: value.source.digest,
|
|
214
|
+
extractorId: value.extractor.id, extractorVersion: value.extractor.version, configurationDigest: value.extractor.configurationDigest }
|
|
215
|
+
}
|
|
216
|
+
function foreignAttempt(initial, result) {
|
|
217
|
+
return result.status !== 'absent' && ingestionDigest(result.attempt) !== ingestionDigest(expectedAttempt(initial))
|
|
218
|
+
}
|
|
219
|
+
function inspected(initial) {
|
|
220
|
+
const value = initial.value, result = intake.readAttempt(value.attemptId)
|
|
221
|
+
check(!foreignAttempt(initial, result), 'SEMANTIC_OPERATION_INTEGRITY', 'Raw attempt differs from its operation pins')
|
|
222
|
+
if (result.status === 'complete') {
|
|
223
|
+
check(ingestionDigest(intake.readCompletion(value.attemptId)) === ingestionDigest(result.completion), 'SEMANTIC_OPERATION_INTEGRITY', 'Completion readback differs')
|
|
224
|
+
}
|
|
225
|
+
return result
|
|
226
|
+
}
|
|
227
|
+
function assertNoReconciledCapture(initial, attempt, state) {
|
|
228
|
+
if (!foreignAttempt(initial, attempt) && ['partial', 'complete'].includes(attempt.status)) {
|
|
229
|
+
const error = new SemanticOperationError('SEMANTIC_RECONCILE_REQUIRED', 'Own output contradicts the host reconciliation; do not start another execution')
|
|
230
|
+
error.captured = { attemptId: initial.value.attemptId, completion: attempt.completion, head: state.head, nextAction: 'reopen-captured-output' }
|
|
231
|
+
throw error
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function status({ operationId }) {
|
|
235
|
+
const { initial, latest, state } = operation(operationId), value = initial.value
|
|
236
|
+
let attempt
|
|
237
|
+
if (latest.value.phase === 'reconciled' && latest.value.recovery) {
|
|
238
|
+
const actual = intake.readAttempt(value.attemptId), recovery = latest.value.recovery
|
|
239
|
+
closed(recovery, ['kind', 'attemptId', 'manifestDigest'])
|
|
240
|
+
check(recovery.kind === 'foreign-manifest-before-readiness' && recovery.attemptId === value.attemptId &&
|
|
241
|
+
latest.value.outcome === 'not-executed' && foreignAttempt(initial, actual) && recovery.manifestDigest === ingestionDigest(actual.attempt),
|
|
242
|
+
'SEMANTIC_OPERATION_INTEGRITY', 'Reconciled foreign manifest readback differs')
|
|
243
|
+
attempt = { status: 'foreign-manifest', attemptId: value.attemptId, manifestDigest: recovery.manifestDigest }
|
|
244
|
+
} else {
|
|
245
|
+
attempt = inspected(initial)
|
|
246
|
+
if (latest.value.phase === 'reconciled') assertNoReconciledCapture(initial, attempt, state)
|
|
247
|
+
}
|
|
248
|
+
let freshness = 'current'
|
|
249
|
+
try {
|
|
250
|
+
intake.readSource({ ref: value.source.ref, expectedDigest: value.source.digest })
|
|
251
|
+
const refreshed = prepareSemanticInput({ store, plan: value.input.plan, domain: state.domain, references: value.input.evidence.map(span => span.reference), identityCandidates: value.input.identityCandidates })
|
|
252
|
+
check(refreshed.digest === value.input.digest, 'SEMANTIC_OPERATION_STALE', 'Current semantic input differs')
|
|
253
|
+
} catch { freshness = 'stale' }
|
|
254
|
+
if (latest.value.phase === 'completed') {
|
|
255
|
+
check(attempt.status === 'complete' && ingestionDigest(attempt.completion) === ingestionDigest(latest.value.completion), 'SEMANTIC_OPERATION_INTEGRITY', 'Saved completion differs from intake')
|
|
256
|
+
}
|
|
257
|
+
return { schema: 'atelier.semantic-operation-status/v0', operationId, phase: latest.value.phase, head: state.head, input: value.input, extractor: value.extractor,
|
|
258
|
+
attempt, freshness, execution: latest.value.phase === 'reconciled' ? 'reconciled' : attempt.status === 'complete' ? 'complete' : 'unknown',
|
|
259
|
+
usage: latest.value.usage ?? null, authority: 'none', semanticAcceptance: 'pending' }
|
|
260
|
+
}
|
|
261
|
+
function begin(request) {
|
|
262
|
+
const selected = json(request)
|
|
263
|
+
closed(selected, ['operationId', 'attemptId', 'at', 'term', 'plan', 'references', 'identityCandidates', 'extractor', 'confirm'])
|
|
264
|
+
const { operationId, attemptId, at, term, confirm } = selected
|
|
265
|
+
assertSemanticOperationProfile({ references: selected.references })
|
|
266
|
+
identifier(operationId); identifier(attemptId)
|
|
267
|
+
const state = history()
|
|
268
|
+
check(state.domain && state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'The current knowledge history digest is required')
|
|
269
|
+
check(!events(state).some(event => event.value.operationId === operationId), 'SEMANTIC_OPERATION_EXISTS', 'Reopen the existing operation; do not execute it again')
|
|
270
|
+
const input = prepareSemanticInput({ store, domain: state.domain, ...selected })
|
|
271
|
+
const extractor = extractorPins(selected.extractor, input.digest), source = { ref: input.evidence[0].receipt.ref, digest: input.evidence[0].reference.sourceDigest }
|
|
272
|
+
const starts = events(state).filter(event => event.value.phase === 'reserved')
|
|
273
|
+
for (const prior of starts) {
|
|
274
|
+
if (prior.value.source.digest !== source.digest || prior.value.source.ref !== source.ref || prior.value.extractor.configurationDigest !== extractor.configurationDigest) continue
|
|
275
|
+
const known = operation(prior.value.operationId, state)
|
|
276
|
+
if (known.latest.value.phase === 'reconciled') {
|
|
277
|
+
assertNoReconciledCapture(known.initial, intake.readAttempt(prior.value.attemptId), state)
|
|
278
|
+
continue
|
|
279
|
+
}
|
|
280
|
+
const attempt = inspected(known.initial)
|
|
281
|
+
check(attempt.status === 'complete', 'SEMANTIC_EXECUTION_UNKNOWN', 'Reconcile the prior source/configuration execution before a new attempt')
|
|
282
|
+
check(known.latest.value.phase === 'completed', 'SEMANTIC_RECONCILE_REQUIRED', 'Finish recording the existing completed attempt before reuse')
|
|
283
|
+
const cached = status({ operationId: prior.value.operationId })
|
|
284
|
+
check(cached.freshness === 'current', 'SEMANTIC_OPERATION_STALE', 'Cached semantic input is stale')
|
|
285
|
+
return { ...cached, cacheReuse: true }
|
|
286
|
+
}
|
|
287
|
+
check(!starts.some(prior => prior.value.attemptId === attemptId), 'SEMANTIC_OPERATION_EXISTS', 'Attempt identity is already reserved')
|
|
288
|
+
check(intake.readAttempt(attemptId).status === 'absent', 'SEMANTIC_OPERATION_EXISTS', 'Attempt identity is already in use')
|
|
289
|
+
intake.ingest({ ref: source.ref, expectedDigest: source.digest })
|
|
290
|
+
const value = { schema: OPERATION, operationId, phase: 'reserved', attemptId, source, input, extractor }
|
|
291
|
+
const recorded = append(value, { term, at, by: `host-model:${extractor.id}@${extractor.version}`, confirm })
|
|
292
|
+
try {
|
|
293
|
+
intake.beginAttempt({ attemptId, blobId: source.digest, extractorId: extractor.id, extractorVersion: extractor.version, configurationDigest: extractor.configurationDigest })
|
|
294
|
+
const ready = status({ operationId })
|
|
295
|
+
check(ready.phase === 'reserved' && ready.head === recorded.head && ready.attempt.status === 'begun', 'SEMANTIC_RECONCILE_REQUIRED', 'Reservation changed before host execution')
|
|
296
|
+
check(ready.freshness === 'current', 'SEMANTIC_OPERATION_STALE', 'Source or domain changed during reservation')
|
|
297
|
+
return { ...ready, execution: 'ready-for-host', cacheReuse: false }
|
|
298
|
+
} catch (error) {
|
|
299
|
+
throw withSavedReceipts(error, { recorded: { record: harnessRef(recorded.record), head: recorded.head, nextAction: 'reopen-recorded-write' } })
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function reconcile({ operationId, at, by, reason, outcome, confirm }) {
|
|
303
|
+
const { initial, latest } = operation(operationId), attempt = intake.readAttempt(initial.value.attemptId)
|
|
304
|
+
const foreign = foreignAttempt(initial, attempt)
|
|
305
|
+
check(latest.value.phase === 'reserved' && (foreign && outcome === 'not-executed' || !foreign && ['absent', 'begun'].includes(attempt.status)),
|
|
306
|
+
'SEMANTIC_RECONCILE_REQUIRED', 'Partial own output must be completed; a foreign manifest permits only explicit not-executed reconciliation')
|
|
307
|
+
check(['not-executed', 'failed-no-output'].includes(outcome) && typeof reason === 'string' && reason.trim().length > 0 && reason.length <= 8192, 'SEMANTIC_OPERATION_INVALID', 'An explicit host reconciliation outcome and reason are required')
|
|
308
|
+
const recovery = foreign ? { recovery: { kind: 'foreign-manifest-before-readiness', attemptId: initial.value.attemptId, manifestDigest: ingestionDigest(attempt.attempt) } } : {}
|
|
309
|
+
const recorded = append({ schema: OPERATION, operationId, phase: 'reconciled', reserved: harnessRef(initial.record), outcome, reason, assurance: 'host-declared-not-independently-verified', ...recovery }, { term: initial.record.data.term, at, by, confirm })
|
|
310
|
+
try { return { ...status({ operationId }), head: recorded.head } }
|
|
311
|
+
catch (error) {
|
|
312
|
+
throw withSavedReceipts(error, { recorded: { record: harnessRef(recorded.record), head: recorded.head, nextAction: 'reopen-recorded-write' } })
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function complete({ operationId, output, expectedOutputDigest, candidates, usage, at, confirm }) {
|
|
316
|
+
const { initial, latest, state } = operation(operationId), value = initial.value
|
|
317
|
+
check(state.head === confirm && latest.value.phase === 'reserved', 'SEMANTIC_OPERATION_HEAD', 'Complete the reserved operation against current history')
|
|
318
|
+
// Verify byte custody before publication; never write into another run's attempt.
|
|
319
|
+
const before = inspected(initial)
|
|
320
|
+
check(before.status !== 'absent', 'SEMANTIC_RECONCILE_REQUIRED', 'Reconcile the absent own manifest before completing output')
|
|
321
|
+
// Store owned executed bytes before interpreting even an oversized/malformed envelope.
|
|
322
|
+
const completion = intake.completeAttempt({ attemptId: value.attemptId, output, expectedOutputDigest })
|
|
323
|
+
let recorded
|
|
324
|
+
try {
|
|
325
|
+
const attempt = inspected(initial)
|
|
326
|
+
check(status({ operationId }).freshness === 'current', 'SEMANTIC_OPERATION_STALE', 'The source or adopted domain changed before completion')
|
|
327
|
+
const declared = json({ candidates, usage })
|
|
328
|
+
closed(declared.usage, ['inputTokens', 'outputTokens', 'cost', 'currency', 'elapsedMs', 'retries'])
|
|
329
|
+
for (const key of ['inputTokens', 'outputTokens', 'elapsedMs', 'retries']) check(declared.usage[key] === null || Number.isSafeInteger(declared.usage[key]) && declared.usage[key] >= 0, 'SEMANTIC_OPERATION_INVALID', 'Usage counts are nonnegative integers or unknown')
|
|
330
|
+
check(declared.usage.cost === null || typeof declared.usage.cost === 'number' && Number.isFinite(declared.usage.cost) && declared.usage.cost >= 0, 'SEMANTIC_OPERATION_INVALID', 'Cost is nonnegative or unknown')
|
|
331
|
+
check(declared.usage.currency === null || typeof declared.usage.currency === 'string' && /^[A-Z]{3}$/.test(declared.usage.currency), 'SEMANTIC_OPERATION_INVALID', 'Currency is explicit or unknown')
|
|
332
|
+
assertSemanticOperationProfile({ candidates: declared.candidates })
|
|
333
|
+
// Preserve executed raw bytes even when their interpretation is refused.
|
|
334
|
+
// Resuming interpretation reuses this completion; it never runs the host.
|
|
335
|
+
const proposals = prepareSemanticProposals({ store, input: value.input, candidates: declared.candidates })
|
|
336
|
+
recorded = append({ schema: OPERATION, operationId, phase: 'completed', reserved: harnessRef(initial.record), completion: attempt.completion,
|
|
337
|
+
candidates: declared.candidates, usage: declared.usage, usageAssurance: 'host-reported', inputDigest: value.input.digest }, { term: initial.record.data.term, at, by: `host-model:${value.extractor.id}@${value.extractor.version}`, confirm })
|
|
338
|
+
const ready = status({ operationId })
|
|
339
|
+
if (ready.freshness !== 'current') {
|
|
340
|
+
const error = new SemanticOperationError('SEMANTIC_OPERATION_STALE', 'Source or domain changed after recording completion')
|
|
341
|
+
throw error
|
|
342
|
+
}
|
|
343
|
+
return { ...ready, head: recorded.head, proposals }
|
|
344
|
+
} catch (error) {
|
|
345
|
+
const receipts = { captured: { attemptId: value.attemptId, completion, head: recorded?.head ?? state.head, nextAction: 'reopen-captured-output' } }
|
|
346
|
+
if (recorded) receipts.recorded = { record: harnessRef(recorded.record), head: recorded.head, nextAction: 'reopen-recorded-write' }
|
|
347
|
+
throw withSavedReceipts(error, receipts)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
function completed(operationId) {
|
|
351
|
+
if (verification?.completed.has(operationId)) return verification.completed.get(operationId)
|
|
352
|
+
const value = operation(operationId), inspectedStatus = status({ operationId })
|
|
353
|
+
check(value.latest.value.phase === 'completed' && inspectedStatus.attempt.status === 'complete', 'SEMANTIC_RECONCILE_REQUIRED', 'Record the completed raw attempt before preparing interpretations')
|
|
354
|
+
check(inspectedStatus.freshness === 'current', 'SEMANTIC_OPERATION_STALE', 'Current source and adopted domain are required')
|
|
355
|
+
const proposals = prepareSemanticProposals({ store, input: value.initial.value.input, candidates: value.latest.value.candidates })
|
|
356
|
+
const receipt = inspectedStatus.attempt.completion
|
|
357
|
+
const result = { ...value, proposals, raw: { attemptId: value.initial.value.attemptId, attemptDigest: receipt.attemptDigest, outputDigest: receipt.outputDigest, completionDigest: intakeDigest(JSON.stringify(receipt)) } }
|
|
358
|
+
verification?.completed.set(operationId, result)
|
|
359
|
+
return result
|
|
360
|
+
}
|
|
361
|
+
function proposals({ operationId, query, limit = 64 }) {
|
|
362
|
+
const current = completed(operationId)
|
|
363
|
+
return { answerClass: 'pending-proposals', ...readSemanticProposals({ store, input: current.initial.value.input, proposals: current.proposals, query, limit }) }
|
|
364
|
+
}
|
|
365
|
+
function semanticBody(record) {
|
|
366
|
+
if (record?.kind !== 'contribution') return null
|
|
367
|
+
let body
|
|
368
|
+
try { body = JSON.parse(record.data.body) } catch { return null }
|
|
369
|
+
return body?.schema === SEMANTIC_OPERATION_PROFILE ? body : null
|
|
370
|
+
}
|
|
371
|
+
function endpointWitnessQuote(record) {
|
|
372
|
+
const candidateId = semanticBody(record)?.candidate?.id
|
|
373
|
+
if (typeof candidateId === 'string' && record.data.body.includes(JSON.stringify(candidateId).slice(1, -1))) return candidateId
|
|
374
|
+
// An ordinary accepted concept need not repeat its record identifier.
|
|
375
|
+
// Choose actual body text whose JSON encoding is also a body substring.
|
|
376
|
+
let quote = ''
|
|
377
|
+
for (const point of record.data.body) {
|
|
378
|
+
if (JSON.stringify(point).slice(1, -1) !== point) {
|
|
379
|
+
if (quote.trim()) return quote.trim()
|
|
380
|
+
quote = ''; continue
|
|
381
|
+
}
|
|
382
|
+
if (!quote && !point.trim()) continue
|
|
383
|
+
if (quote.length + point.length > 8192) break
|
|
384
|
+
quote += point
|
|
385
|
+
}
|
|
386
|
+
check(quote.trim().length > 0, 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'The accepted endpoint body has no representable dependency witness')
|
|
387
|
+
return quote.trim()
|
|
388
|
+
}
|
|
389
|
+
function verifySemantic(record) {
|
|
390
|
+
const body = semanticBody(record)
|
|
391
|
+
check(body && ['entity', 'assertion', 'unknown'].includes(body.kind), 'SEMANTIC_OPERATION_INTEGRITY', 'An operation interpretation is required')
|
|
392
|
+
const current = completed(body.operationId), collection = { entity: 'entities', assertion: 'assertions', unknown: 'unknowns' }[body.kind]
|
|
393
|
+
const candidate = current.proposals[collection].find(value => value.id === body.candidate?.id)
|
|
394
|
+
check(candidate && ingestionDigest(candidate) === ingestionDigest(body.candidate) && ingestionDigest(current.raw) === ingestionDigest(body.raw) &&
|
|
395
|
+
body.inputDigest === current.proposals.inputDigest && ingestionDigest(body.usage) === ingestionDigest(current.latest.value.usage), 'SEMANTIC_OPERATION_INTEGRITY', 'Interpretation differs from current candidate or raw capture pins')
|
|
396
|
+
closed(body, ['schema', 'operationId', 'kind', 'candidate', 'endpoints', 'raw', 'inputDigest', 'usage', 'sourceBinding', 'source', 'sourceWitness'])
|
|
397
|
+
const sourceRecord = sourceFor(body.source, body.sourceBinding, current), endpoints = {}, endpointWitnesses = []
|
|
398
|
+
if (body.kind === 'assertion') for (const role of ['subject', 'object']) {
|
|
399
|
+
const id = candidate[`${role}Id`]
|
|
400
|
+
if (id === null) { endpoints[role] = null; continue }
|
|
401
|
+
const { target: resolved, interpretation } = endpoint(current.proposals.entities.find(entity => entity.id === id), current)
|
|
402
|
+
endpoints[role] = harnessRef(resolved)
|
|
403
|
+
endpointWitnesses.push({ record: interpretation, quote: endpointWitnessQuote(interpretation), dependency: 'identity-choice' })
|
|
404
|
+
if (resolved.id !== interpretation.id) endpointWitnesses.push({ record: resolved, quote: endpointWitnessQuote(resolved), dependency: 'resolved-identity' })
|
|
405
|
+
}
|
|
406
|
+
const witnesses = semanticDependencyWitnesses({ citations: candidate.evidence, sources: [sourceRecord], endpoints: endpointWitnesses })
|
|
407
|
+
check(ingestionDigest(body.endpoints) === ingestionDigest(endpoints) && ingestionDigest(record.data.basedOn) === ingestionDigest(witnesses.basedOn) && ingestionDigest(body.sourceWitness) === ingestionDigest(witnesses.sourceWitness), 'SEMANTIC_OPERATION_INTEGRITY', 'Interpretation dependency, witness or endpoint pins differ')
|
|
408
|
+
const value = current.initial.value
|
|
409
|
+
check(record.by === `host-model:${value.extractor.id}@${value.extractor.version}` && record.data.origin.method === 'authored' &&
|
|
410
|
+
record.data.category === (body.kind === 'entity' ? 'concept' : body.kind === 'assertion' ? 'claim' : 'interpretation') &&
|
|
411
|
+
(body.kind !== 'entity' || record.data.term === candidate.type), 'SEMANTIC_OPERATION_INTEGRITY', 'Interpretation author, category or entity type differs')
|
|
412
|
+
return body
|
|
413
|
+
}
|
|
414
|
+
function sourceFor(source, binding, current) {
|
|
415
|
+
const record = current.state.records.find(record => record.id === source.id)
|
|
416
|
+
check(record?.kind === 'contribution' && harnessRef(record).digest === source.digest, 'SEMANTIC_OPERATION_INTEGRITY', 'The exact structural source contribution is required')
|
|
417
|
+
check(!current.state.reconsider.some(item => item.id === record.id), 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION', 'The structural source contribution requires reconsideration')
|
|
418
|
+
const key = ingestionDigest({ source, binding })
|
|
419
|
+
if (verification?.sources.has(key)) return verification.sources.get(key)
|
|
420
|
+
const value = current.initial.value, selected = prepareIngestionContribution({ workspaceRoot, workspaceId, records: current.state.records, ...value.input.plan,
|
|
421
|
+
sourceId: value.input.evidence[0].reference.sourceId, title: record.data.title, term: record.data.term })
|
|
422
|
+
const expected = { ...selected.sourceBinding, contributionDataDigest: learningDigest(record.data) }
|
|
423
|
+
check(ingestionDigest(expected) === ingestionDigest(binding) && record.data.body === selected.data.body && ingestionDigest(record.data.origin) === ingestionDigest(selected.data.origin), 'SEMANTIC_OPERATION_INTEGRITY', 'Structural source provenance or binding differs')
|
|
424
|
+
verification?.sources.set(key, record)
|
|
425
|
+
return record
|
|
426
|
+
}
|
|
427
|
+
function endpoint(entity, current) {
|
|
428
|
+
const record = current.state.records.findLast(record => {
|
|
429
|
+
const body = semanticBody(record)
|
|
430
|
+
return body?.operationId === current.initial.value.operationId && body.kind === 'entity' && body.candidate?.id === entity.id
|
|
431
|
+
})
|
|
432
|
+
check(record && current.state.accepted.includes(record.id), 'SEMANTIC_IDENTITY_PENDING', 'The receiver must review each endpoint entity first')
|
|
433
|
+
verifySemantic(record)
|
|
434
|
+
if (entity.identity.status === 'source-local') return { target: record, interpretation: record }
|
|
435
|
+
// The ordinary review record carries the explicit receiver identity choice.
|
|
436
|
+
const acceptedReview = current.state.records.findLast(item => item.kind === 'review' && item.data.target.id === record.id)
|
|
437
|
+
let decision
|
|
438
|
+
try { decision = JSON.parse(acceptedReview.data.basis) } catch { /* A prose acceptance does not resolve a canonical identity. */ }
|
|
439
|
+
check(decision?.schema === 'atelier.semantic-identity-decision/v0' && decision.operationId === current.initial.value.operationId && decision.candidateId === entity.id && ['existing', 'source-local'].includes(decision.resolution?.status), 'SEMANTIC_IDENTITY_PENDING', 'An explicit receiver identity review is required')
|
|
440
|
+
if (decision.resolution.status === 'source-local') return { target: record, interpretation: record }
|
|
441
|
+
const target = current.state.records.find(item => item.id === decision.resolution.contribution?.id)
|
|
442
|
+
check(target?.kind === 'contribution' && entity.identity.candidateIds.includes(target.id) && target.data.term === entity.type && current.state.accepted.includes(target.id) && harnessRef(target).digest === decision.resolution.contribution.digest,
|
|
443
|
+
'SEMANTIC_IDENTITY_PENDING', 'Canonical identity must be a supplied currently accepted matching contribution')
|
|
444
|
+
return { target, interpretation: record }
|
|
445
|
+
}
|
|
446
|
+
function prepareContribution({ operationId, id, kind, candidateId, source, sourceBinding, term, at, confirm, supersedes = null, revisionReason = null }) {
|
|
447
|
+
identifier(id)
|
|
448
|
+
const current = completed(operationId), collection = { entity: 'entities', assertion: 'assertions', unknown: 'unknowns' }[kind]
|
|
449
|
+
check(collection && current.state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'A declared interpretation kind and current history are required')
|
|
450
|
+
const candidate = current.proposals[collection].find(value => value.id === candidateId)
|
|
451
|
+
check(candidate, 'SEMANTIC_OPERATION_INVALID', 'The candidate is absent from the completed operation')
|
|
452
|
+
check(kind !== 'entity' || term === candidate.type, 'SEMANTIC_OPERATION_INVALID', 'Entity contributions must retain their proposed vocabulary type')
|
|
453
|
+
const sourceRecord = sourceFor(source, sourceBinding, current), endpoints = {}, endpointWitnesses = []
|
|
454
|
+
if (kind === 'assertion') for (const role of ['subject', 'object']) {
|
|
455
|
+
const candidateId = candidate[`${role}Id`]
|
|
456
|
+
if (candidateId === null) { endpoints[role] = null; continue }
|
|
457
|
+
const entity = current.proposals.entities.find(entity => entity.id === candidateId), { target: resolved, interpretation } = endpoint(entity, current)
|
|
458
|
+
endpoints[role] = harnessRef(resolved)
|
|
459
|
+
endpointWitnesses.push({ record: interpretation, quote: endpointWitnessQuote(interpretation), dependency: 'identity-choice' })
|
|
460
|
+
if (resolved.id !== interpretation.id) endpointWitnesses.push({ record: resolved, quote: endpointWitnessQuote(resolved), dependency: 'resolved-identity' })
|
|
461
|
+
}
|
|
462
|
+
const witnesses = semanticDependencyWitnesses({ citations: candidate.evidence, sources: [sourceRecord], endpoints: endpointWitnesses })
|
|
463
|
+
const value = current.initial.value, body = canonicalize(json({ schema: SEMANTIC_OPERATION_PROFILE, operationId, kind, candidate, endpoints, raw: current.raw,
|
|
464
|
+
inputDigest: current.proposals.inputDigest, usage: current.latest.value.usage, sourceBinding, source: harnessRef(sourceRecord), sourceWitness: witnesses.sourceWitness }))
|
|
465
|
+
const record = { schema: 'atelier-knowledge-record@v1', id, run, at, by: `host-model:${value.extractor.id}@${value.extractor.version}`, kind: 'contribution', data: {
|
|
466
|
+
domain: current.proposals.domainRef, category: kind === 'entity' ? 'concept' : kind === 'assertion' ? 'claim' : 'interpretation', term,
|
|
467
|
+
title: kind === 'entity' ? candidate.label : kind === 'assertion' ? `${candidate.subjectId} ${candidate.predicate} ${candidate.objectId ?? ''}`.trim() : candidate.reason,
|
|
468
|
+
body, audience: current.state.domain.data.audience, scope: current.state.domain.data.scope,
|
|
469
|
+
origin: { method: 'authored', reason: `Machine-authored interpretation by ${value.extractor.id}@${value.extractor.version} in operation ${operationId}; pending receiver review.` }, basedOn: witnesses.basedOn,
|
|
470
|
+
} }
|
|
471
|
+
const prior = current.state.records.filter(item => semanticBody(item)?.operationId === operationId && semanticBody(item)?.kind === kind && semanticBody(item)?.candidate?.id === candidateId)
|
|
472
|
+
if (supersedes !== null) {
|
|
473
|
+
const old = prior.at(-1)
|
|
474
|
+
check(old && ingestionDigest(harnessRef(old)) === ingestionDigest(supersedes) && typeof revisionReason === 'string' && revisionReason.trim().length > 0 && revisionReason.length <= 8192,
|
|
475
|
+
'SEMANTIC_OPERATION_INVALID', 'A revision must explicitly supersede the latest exact interpretation with a reason')
|
|
476
|
+
record.data.supersedes = supersedes; record.data.revisionReason = revisionReason
|
|
477
|
+
} else check(prior.length === 0 && revisionReason === null, 'SEMANTIC_OPERATION_EXISTS', 'A candidate already has its immutable contribution; an explicit revision is required')
|
|
478
|
+
return { ...appendHarness({ workspaceRoot, profile: 'knowledge', record, confirm }), record, semanticAcceptance: 'pending' }
|
|
479
|
+
}
|
|
480
|
+
function record({ record, confirm }) {
|
|
481
|
+
check(record.run === run && ['evaluation', 'review', 'withdrawal', 'activation'].includes(record.kind), 'SEMANTIC_OPERATION_INVALID', 'Supply an actual receiver evaluation, review, withdrawal or activation')
|
|
482
|
+
return appendHarness({ workspaceRoot, profile: 'knowledge', record, confirm })
|
|
483
|
+
}
|
|
484
|
+
function prepareRelation({ assertion, at, confirm }) {
|
|
485
|
+
const state = history(), contribution = state.records.find(record => record.id === assertion.id)
|
|
486
|
+
check(contribution && harnessRef(contribution).digest === assertion.digest && state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'The exact assertion and current history are required')
|
|
487
|
+
const body = verifySemantic(contribution)
|
|
488
|
+
check(body.kind === 'assertion' && state.accepted.includes(contribution.id), 'SEMANTIC_IDENTITY_PENDING', 'The receiver must accept the assertion before its relation')
|
|
489
|
+
const eligibility = plainAssertionEligibility(body.candidate, state.domain)
|
|
490
|
+
if (!eligibility.eligible) return { head: state.head, record: null, projectionOmission: { assertion, ...eligibility }, authority: 'none' }
|
|
491
|
+
const relation = { schema: 'atelier-knowledge-record@v1', run, id: semanticRelationId(contribution.id), at, by: contribution.by, kind: 'relation', data: {
|
|
492
|
+
domain: contribution.data.domain, subject: body.endpoints.subject, object: body.endpoints.object, predicate: body.candidate.predicate,
|
|
493
|
+
rationale: `Machine-prepared plain relation; pending receiver review.\nsemantic-support: ${contribution.id} ${assertion.digest}`,
|
|
494
|
+
} }
|
|
495
|
+
return { ...appendHarness({ workspaceRoot, profile: 'knowledge', record: relation, confirm }), record: relation, semanticAcceptance: 'pending' }
|
|
496
|
+
}
|
|
497
|
+
function cascade({ withdrawalId, at, confirm }) {
|
|
498
|
+
let state = history(), head = confirm
|
|
499
|
+
check(state.head === confirm, 'SEMANTIC_OPERATION_HEAD', 'Resume cleanup against current history')
|
|
500
|
+
const withdrawal = state.records.find(record => record.id === withdrawalId && record.kind === 'withdrawal')
|
|
501
|
+
check(withdrawal, 'SEMANTIC_OPERATION_INVALID', 'An existing explicit receiver withdrawal is required')
|
|
502
|
+
const cleaned = []
|
|
503
|
+
for (const relation of state.records.filter(record => record.kind === 'relation')) {
|
|
504
|
+
const support = /(?:^|\n)semantic-support: ([a-z][a-z0-9-]{0,63}) (sha256:[a-f0-9]{64})$/.exec(relation.data.rationale)
|
|
505
|
+
if (support?.[1] !== withdrawal.data.target.id || support[2] !== withdrawal.data.target.digest || relation.id !== semanticRelationId(support[1])) continue
|
|
506
|
+
state = history()
|
|
507
|
+
if (state.records.some(record => record.kind === 'withdrawal' && record.data.target.id === relation.id)) continue
|
|
508
|
+
const cleanup = { schema: 'atelier-knowledge-record@v1', id: `cleanup-${intakeDigest(`${withdrawalId}:${relation.id}`).slice(0, 40)}`, run, at, by: 'semantic-operation:withdrawal-cleanup', kind: 'withdrawal', data: {
|
|
509
|
+
target: harnessRef(relation), reason: `Consequential cleanup of explicit receiver withdrawal ${withdrawalId}; supporting assertion is withdrawn.`,
|
|
510
|
+
} }
|
|
511
|
+
head = appendHarness({ workspaceRoot, profile: 'knowledge', record: cleanup, confirm: head }).head
|
|
512
|
+
cleaned.push(relation.id)
|
|
513
|
+
}
|
|
514
|
+
return { head, cleaned, authority: 'none' }
|
|
515
|
+
}
|
|
516
|
+
function context({ query }) {
|
|
517
|
+
const state = history(), bindings = [], failures = []
|
|
518
|
+
for (const record of state.records) {
|
|
519
|
+
const body = semanticBody(record)
|
|
520
|
+
if (!body) continue
|
|
521
|
+
try { if (state.accepted.includes(record.id)) verifySemantic(record) }
|
|
522
|
+
catch (error) {
|
|
523
|
+
if (!(error instanceof SemanticOperationError) || !['SEMANTIC_OPERATION_STALE', 'SEMANTIC_OPERATION_INTEGRITY', 'SEMANTIC_IDENTITY_PENDING', 'SEMANTIC_UNSUPPORTED_LEDGER_CITATION'].includes(error.code)) throw error
|
|
524
|
+
failures.push({ id: record.id, reason: 'semantic-record-requires-reconsideration', code: error.code })
|
|
525
|
+
}
|
|
526
|
+
if (!bindings.some(binding => ingestionDigest(binding) === ingestionDigest(body.sourceBinding))) bindings.push(body.sourceBinding)
|
|
527
|
+
}
|
|
528
|
+
const view = localKnowledgeContext({ workspaceRoot, workspaceId, records: state.records, sourceBindings: bindings, query })
|
|
529
|
+
const reconsider = new Map(view.reconsider.map(item => [item.id, [...item.reasons]]))
|
|
530
|
+
for (const failure of failures) reconsider.set(failure.id, [...new Set([...(reconsider.get(failure.id) ?? []), failure.reason])])
|
|
531
|
+
// Preserve the full immutable ledger. Withhold failed interpretations and
|
|
532
|
+
// their dependents from this view without changing receiver decisions.
|
|
533
|
+
for (const record of state.records) {
|
|
534
|
+
const d = record.data
|
|
535
|
+
const refs = record.kind === 'contribution' ? [d.domain, ...d.basedOn.map(pin => pin.contribution)]
|
|
536
|
+
: record.kind === 'evaluation' ? [d.contribution]
|
|
537
|
+
: record.kind === 'relation' ? [d.domain, d.subject, d.object]
|
|
538
|
+
: record.kind === 'review' ? [d.target, ...d.evaluations]
|
|
539
|
+
: record.kind === 'activation' ? d.reviews : []
|
|
540
|
+
const reasons = refs.flatMap(pin => reconsider.get(pin.id) ?? [])
|
|
541
|
+
if (reasons.length) reconsider.set(record.id, [...new Set([...(reconsider.get(record.id) ?? []), ...reasons])])
|
|
542
|
+
}
|
|
543
|
+
const active = new Set()
|
|
544
|
+
for (const record of state.records) if (record.kind === 'activation' && !reconsider.has(record.id)) {
|
|
545
|
+
for (const pin of record.data.reviews) active.add(state.records.find(item => item.id === pin.id).data.target.id)
|
|
546
|
+
}
|
|
547
|
+
return { answerClass: 'accepted-knowledge', ...view,
|
|
548
|
+
hits: view.hits.filter(hit => active.has(hit.reference.id) && !reconsider.has(hit.reference.id)),
|
|
549
|
+
reconsider: [...reconsider].map(([id, reasons]) => ({ id, reasons })),
|
|
550
|
+
diagnostics: [...view.diagnostics, ...failures] }
|
|
551
|
+
|
|
552
|
+
}
|
|
553
|
+
function project({ activationId, namespace }) {
|
|
554
|
+
const state = history(), view = context({ query: 'semantic' })
|
|
555
|
+
const selected = assertSemanticProjection({ records: state.records, activationId, reconsider: view.reconsider }).selected
|
|
556
|
+
const typed = selected.map(id => ({ record: state.records.find(record => record.id === id), body: semanticBody(state.records.find(record => record.id === id)) })).filter(item => item.body)
|
|
557
|
+
for (const item of typed) verifySemantic(item.record)
|
|
558
|
+
return { ...knowledgeGraphProposal(state.records, { activationId, namespace }), semanticProfile: SEMANTIC_OPERATION_PROFILE,
|
|
559
|
+
semanticEntities: typed.filter(item => item.body.kind === 'entity').map(item => ({ record: harnessRef(item.record), candidate: item.body.candidate })),
|
|
560
|
+
semanticAssertions: typed.filter(item => item.body.kind === 'assertion').map(item => ({ record: harnessRef(item.record), candidate: item.body.candidate, endpoints: item.body.endpoints })),
|
|
561
|
+
dependencyWitnesses: typed.map(item => ({ record: harnessRef(item.record), witnesses: item.body.sourceWitness })),
|
|
562
|
+
projectionOmissions: typed.filter(item => item.body.kind === 'assertion').map(item => ({ assertion: harnessRef(item.record), ...plainAssertionEligibility(item.body.candidate, state.domain) })).filter(item => !item.eligible) }
|
|
563
|
+
}
|
|
564
|
+
return Object.freeze({ begin, status, reconcile, complete, proposals: request => verified(() => proposals(request)),
|
|
565
|
+
prepareContribution: request => verified(() => prepareContribution(request)), prepareRelation: request => verified(() => prepareRelation(request)),
|
|
566
|
+
record, cascade, context: request => verified(() => context(request)), project: request => verified(() => project(request)) })
|
|
567
|
+
}
|