@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
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Private supplier artifacts. These receipts do not replace Atelier intake."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import dataclasses
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def portable(value):
|
|
12
|
+
"""Preserve native data fields without repr-based or lossy coercion."""
|
|
13
|
+
if dataclasses.is_dataclass(value):
|
|
14
|
+
value = dataclasses.asdict(value)
|
|
15
|
+
elif isinstance(value, Enum):
|
|
16
|
+
value = value.value
|
|
17
|
+
elif hasattr(value, "model_dump"):
|
|
18
|
+
value = value.model_dump(mode="json")
|
|
19
|
+
if value is None or isinstance(value, (str, bool, int, float)):
|
|
20
|
+
# Reject NaN/Infinity, which are not portable JSON.
|
|
21
|
+
json.dumps(value, allow_nan=False)
|
|
22
|
+
return value
|
|
23
|
+
if isinstance(value, (list, tuple)):
|
|
24
|
+
return [portable(item) for item in value]
|
|
25
|
+
if isinstance(value, dict) and all(isinstance(key, str) for key in value):
|
|
26
|
+
return {key: portable(item) for key, item in value.items()}
|
|
27
|
+
raise TypeError("Native artifact needs a host JSON serializer; object was not discarded")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def encoded(value):
|
|
31
|
+
return json.dumps(portable(value), ensure_ascii=False, sort_keys=True,
|
|
32
|
+
separators=(",", ":"), allow_nan=False).encode("utf-8")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def digest(value):
|
|
36
|
+
return "sha256:" + hashlib.sha256(encoded(value)).hexdigest()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class MemoryArtifacts:
|
|
40
|
+
"""Test/host injection sink; the host must retain its returned bytes."""
|
|
41
|
+
def __init__(self):
|
|
42
|
+
self.objects = {}
|
|
43
|
+
|
|
44
|
+
def put_bytes(self, kind, data):
|
|
45
|
+
if not isinstance(data, bytes):
|
|
46
|
+
raise TypeError("Artifact bytes are required")
|
|
47
|
+
sha = hashlib.sha256(data).hexdigest()
|
|
48
|
+
self.objects.setdefault(sha, data)
|
|
49
|
+
return {"artifactId": "sha256:" + sha, "kind": kind,
|
|
50
|
+
"bytes": len(data), "storage": "host-memory"}
|
|
51
|
+
|
|
52
|
+
def put_json(self, kind, value):
|
|
53
|
+
return self.put_bytes(kind, encoded(value))
|
|
54
|
+
|
|
55
|
+
def read_json(self, ref):
|
|
56
|
+
return json.loads(self.read_bytes(ref))
|
|
57
|
+
|
|
58
|
+
def read_bytes(self, ref):
|
|
59
|
+
data = self.objects[ref["artifactId"].removeprefix("sha256:")]
|
|
60
|
+
if "sha256:" + hashlib.sha256(data).hexdigest() != ref["artifactId"]:
|
|
61
|
+
raise ValueError("Artifact readback digest differs")
|
|
62
|
+
return data
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class FileArtifacts:
|
|
66
|
+
"""Immutable, content addressed files under an explicitly allocated root."""
|
|
67
|
+
def __init__(self, root, *, owner_root):
|
|
68
|
+
self.root, owner = Path(root).resolve(), Path(owner_root).resolve()
|
|
69
|
+
if not self.root.is_relative_to(owner):
|
|
70
|
+
raise ValueError("Artifact root is outside the supplier allocation")
|
|
71
|
+
self.root.mkdir(parents=True, exist_ok=True)
|
|
72
|
+
|
|
73
|
+
def put_bytes(self, kind, data):
|
|
74
|
+
if not isinstance(data, bytes):
|
|
75
|
+
raise TypeError("Artifact bytes are required")
|
|
76
|
+
sha = hashlib.sha256(data).hexdigest()
|
|
77
|
+
target = self.root / (sha + ".artifact")
|
|
78
|
+
try:
|
|
79
|
+
with target.open("xb") as output:
|
|
80
|
+
output.write(data)
|
|
81
|
+
output.flush()
|
|
82
|
+
import os
|
|
83
|
+
os.fsync(output.fileno())
|
|
84
|
+
except FileExistsError:
|
|
85
|
+
if target.read_bytes() != data:
|
|
86
|
+
raise ValueError("Existing artifact differs from its content address")
|
|
87
|
+
return {"artifactId": "sha256:" + sha, "kind": kind,
|
|
88
|
+
"bytes": len(data), "storage": "supplier-file", "path": str(target)}
|
|
89
|
+
|
|
90
|
+
def put_json(self, kind, value):
|
|
91
|
+
return self.put_bytes(kind, encoded(value))
|
|
92
|
+
|
|
93
|
+
def read_json(self, ref):
|
|
94
|
+
return json.loads(self.read_bytes(ref))
|
|
95
|
+
|
|
96
|
+
def read_bytes(self, ref):
|
|
97
|
+
target = self.root / (ref["artifactId"].removeprefix("sha256:") + ".artifact")
|
|
98
|
+
data = target.read_bytes()
|
|
99
|
+
if "sha256:" + hashlib.sha256(data).hexdigest() != ref["artifactId"]:
|
|
100
|
+
raise ValueError("Artifact readback digest differs")
|
|
101
|
+
return data
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Derived native projection of the actual semantic runner project() result.
|
|
2
|
+
|
|
3
|
+
Canonical acceptance/identity remains with the host's existing knowledge runner.
|
|
4
|
+
Opaque IDs are native-normalization-safe. Native traversal stays undirected.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import hashlib
|
|
9
|
+
import re
|
|
10
|
+
from .artifacts import digest, encoded, portable
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def record_ref(value):
|
|
14
|
+
if not (isinstance(value, dict) and isinstance(value.get("id"), str)
|
|
15
|
+
and re.fullmatch(r"sha256:[a-f0-9]{64}", value.get("digest", ""))):
|
|
16
|
+
raise ValueError("An exact existing harnessRef {id,digest} is required")
|
|
17
|
+
return portable(value)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def opaque(kind, value):
|
|
21
|
+
return "ATELIER_" + kind + "_" + hashlib.sha256(encoded(value)).hexdigest().upper()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def build_projection(project, *, profile="assertion-incidence"):
|
|
25
|
+
if (project.get("schema") != "atelier-knowledge-graph-proposal@v1"
|
|
26
|
+
or project.get("semanticProfile") != "atelier.semantic-operation-profile/v0"
|
|
27
|
+
or project.get("canonicalMutation") is not False or project.get("authority") != "none"):
|
|
28
|
+
raise ValueError("The existing runner semantic projection profile is required")
|
|
29
|
+
if profile not in {"assertion-incidence", "semantic-adjacency"}:
|
|
30
|
+
raise ValueError("Declare a supported projection profile")
|
|
31
|
+
result = {"chunks": [], "entities": [], "relationships": []}
|
|
32
|
+
mapping = {"entities": {}, "assertions": {}, "roles": {}, "chunks": {}}
|
|
33
|
+
losses = ["Native traversal is undirected; resolve direction from retained assertion records",
|
|
34
|
+
"Native summaries, weights and edits do not establish canonical truth",
|
|
35
|
+
"Native chunk IDs hash content: identical quote chunks can coalesce; exact evidence remains retained",
|
|
36
|
+
"Native entity/assertion source links use their first evidence alias; all evidence remains retained and indexed as chunks"]
|
|
37
|
+
entity_by_candidate, entity_by_record, seen_records = {}, {}, set()
|
|
38
|
+
for item in project.get("semanticEntities", []):
|
|
39
|
+
ref, candidate = record_ref(item["record"]), portable(item["candidate"])
|
|
40
|
+
if ref["id"] in seen_records or candidate["id"] in entity_by_candidate:
|
|
41
|
+
raise ValueError("Semantic entity identities are ambiguous")
|
|
42
|
+
seen_records.add(ref["id"])
|
|
43
|
+
name = opaque("ENTITY", ref)
|
|
44
|
+
entity_by_candidate[candidate["id"]] = name
|
|
45
|
+
entity_by_record[(ref["id"], ref["digest"])] = name
|
|
46
|
+
mapping["entities"][name] = {"record": ref, "candidate": candidate}
|
|
47
|
+
aliases = []
|
|
48
|
+
for index, evidence in enumerate(candidate.get("evidence", [])):
|
|
49
|
+
if not isinstance(evidence.get("quote"), str) or not evidence.get("quote"):
|
|
50
|
+
raise ValueError("Entity evidence needs its actual located quote")
|
|
51
|
+
alias = opaque("EVIDENCE", {"entity": ref, "index": index, "evidence": evidence})
|
|
52
|
+
aliases.append(alias)
|
|
53
|
+
mapping["chunks"][alias] = {"entity": ref, "evidence": evidence}
|
|
54
|
+
result["chunks"].append({"content": evidence["quote"], "source_id": alias,
|
|
55
|
+
"file_path": evidence.get("ref", "retained-evidence:" + alias), "chunk_order_index": index})
|
|
56
|
+
if not aliases:
|
|
57
|
+
losses.append("Entity " + ref["id"] + " has no native chunk source; exact canonical identity reference remains retained")
|
|
58
|
+
result["entities"].append({"entity_name": name, "entity_type": candidate["type"],
|
|
59
|
+
"description": encoded({"label": candidate["label"], "record": ref,
|
|
60
|
+
"identity": candidate.get("identity")}).decode(),
|
|
61
|
+
"source_id": aliases[0] if aliases else ""})
|
|
62
|
+
|
|
63
|
+
adjacency_pairs = {}
|
|
64
|
+
for item in project.get("semanticAssertions", []):
|
|
65
|
+
ref, candidate = record_ref(item["record"]), portable(item["candidate"])
|
|
66
|
+
if ref["id"] in seen_records:
|
|
67
|
+
raise ValueError("Duplicate canonical assertion record")
|
|
68
|
+
seen_records.add(ref["id"])
|
|
69
|
+
evidence = candidate.get("evidence", [])
|
|
70
|
+
if not evidence:
|
|
71
|
+
raise ValueError("An assertion requires retained located evidence")
|
|
72
|
+
aliases = []
|
|
73
|
+
for index, evidence_item in enumerate(evidence):
|
|
74
|
+
if not isinstance(evidence_item.get("quote"), str) or not evidence_item.get("quote"):
|
|
75
|
+
raise ValueError("The actual candidate's exact evidence quote is required")
|
|
76
|
+
alias = opaque("EVIDENCE", {"assertion": ref, "index": index, "evidence": evidence_item})
|
|
77
|
+
aliases.append(alias)
|
|
78
|
+
mapping["chunks"][alias] = {"assertion": ref, "evidence": evidence_item}
|
|
79
|
+
result["chunks"].append({"content": evidence_item["quote"], "source_id": alias,
|
|
80
|
+
"file_path": evidence_item.get("ref", "retained-evidence:" + alias),
|
|
81
|
+
"chunk_order_index": index})
|
|
82
|
+
|
|
83
|
+
# Endpoints returned by the real runner use resolved canonical records.
|
|
84
|
+
# A source-local candidate ID is not a canonical identity decision.
|
|
85
|
+
endpoints = item.get("endpoints", {})
|
|
86
|
+
participants = []
|
|
87
|
+
for role, field in [("subject", "subjectId"), ("object", "objectId")]:
|
|
88
|
+
if candidate.get(field) is None:
|
|
89
|
+
continue
|
|
90
|
+
endpoint = endpoints.get(role)
|
|
91
|
+
if endpoint is None:
|
|
92
|
+
raise ValueError("The runner's resolved endpoint record is required")
|
|
93
|
+
endpoint = record_ref(endpoint)
|
|
94
|
+
name = entity_by_record.get((endpoint["id"], endpoint["digest"]))
|
|
95
|
+
if name is None:
|
|
96
|
+
# Existing identities can resolve outside selected semanticEntities.
|
|
97
|
+
# Do not invent their type/label; host must hydrate them explicitly.
|
|
98
|
+
hydrated = project.get("resolvedEntities", [])
|
|
99
|
+
selected = [entity for entity in hydrated if entity.get("record") == endpoint]
|
|
100
|
+
if len(selected) != 1:
|
|
101
|
+
raise ValueError("A resolved canonical endpoint needs exact owner-hydrated identity data")
|
|
102
|
+
entity = selected[0]
|
|
103
|
+
name = opaque("ENTITY", endpoint)
|
|
104
|
+
entity_by_record[(endpoint["id"], endpoint["digest"])] = name
|
|
105
|
+
mapping["entities"][name] = portable(entity)
|
|
106
|
+
result["entities"].append({"entity_name": name, "entity_type": entity["type"],
|
|
107
|
+
"description": encoded({"label": entity["label"], "record": endpoint}).decode()})
|
|
108
|
+
losses.append("Hydrated endpoint " + endpoint["id"] + " has no native source chunk; authority stays in exact canonical record")
|
|
109
|
+
participants.append((role, name, endpoint))
|
|
110
|
+
assertion_name = opaque("ASSERTION", ref)
|
|
111
|
+
mapping["assertions"][assertion_name] = portable(item)
|
|
112
|
+
description = encoded({"record": ref, "candidate": candidate,
|
|
113
|
+
"endpoints": endpoints}).decode()
|
|
114
|
+
if profile == "assertion-incidence":
|
|
115
|
+
result["entities"].append({"entity_name": assertion_name, "entity_type": "DERIVED_ASSERTION",
|
|
116
|
+
"description": description, "source_id": aliases[0]})
|
|
117
|
+
for role, entity_name, endpoint in participants:
|
|
118
|
+
role_name = opaque("ROLE", {"assertion": ref, "role": role})
|
|
119
|
+
mapping["roles"][role_name] = {"assertion": ref, "role": role, "entity": endpoint}
|
|
120
|
+
result["entities"].append({"entity_name": role_name, "entity_type": "DERIVED_ROLE_BINDING",
|
|
121
|
+
"description": encoded(mapping["roles"][role_name]).decode(), "source_id": aliases[0]})
|
|
122
|
+
for source, target in [(assertion_name, role_name), (role_name, entity_name)]:
|
|
123
|
+
result["relationships"].append({"src_id": source, "tgt_id": target,
|
|
124
|
+
"description": description, "keywords": candidate["predicate"] + "," + role,
|
|
125
|
+
"source_id": aliases[0], "weight": 1.0})
|
|
126
|
+
else:
|
|
127
|
+
if len(participants) != 2 or participants[0][1] == participants[1][1]:
|
|
128
|
+
losses.append("Adjacency omitted native edge for unary/self assertion " + ref["id"])
|
|
129
|
+
continue
|
|
130
|
+
pair = tuple(sorted([participants[0][1], participants[1][1]]))
|
|
131
|
+
adjacency_pairs.setdefault(pair, []).append(ref)
|
|
132
|
+
result["relationships"].append({"src_id": participants[0][1], "tgt_id": participants[1][1],
|
|
133
|
+
"description": description, "keywords": candidate["predicate"],
|
|
134
|
+
"source_id": aliases[0], "weight": 1.0})
|
|
135
|
+
if profile == "semantic-adjacency":
|
|
136
|
+
losses.append("Adjacency coalesces direction, predicates, negation, modality and time on a native pair")
|
|
137
|
+
for pair, refs in adjacency_pairs.items():
|
|
138
|
+
if len(refs) > 1:
|
|
139
|
+
losses.append("Native pair collapses assertions: " + ",".join(ref["id"] for ref in refs))
|
|
140
|
+
# Ensure entities have native source aliases when exact assertion evidence is available.
|
|
141
|
+
for entity in result["entities"]:
|
|
142
|
+
entity.setdefault("source_id", "")
|
|
143
|
+
return {"custom_kg": result, "mapping": mapping, "profile": profile,
|
|
144
|
+
"canonicalProjection": portable(project), "inputDigest": digest(project),
|
|
145
|
+
"losses": losses, "authority": "none", "canonicalMutation": False,
|
|
146
|
+
"nativeWeightMeaning": "native evidence floor/boost, never semantic confidence"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util'
|
|
2
|
+
|
|
3
|
+
const own = (value, key) => value && typeof value === 'object' ? Object.getOwnPropertyDescriptor(value, key)?.value : undefined
|
|
4
|
+
const object = value => value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
5
|
+
const nonempty = value => typeof value === 'string' && value.length > 0
|
|
6
|
+
const artifact = value => object(value) && nonempty(own(value, 'artifactId'))
|
|
7
|
+
const sources = value => Array.isArray(value) && value.length > 0 && value.every(source => object(source) &&
|
|
8
|
+
['sourceId', 'sourceDigest', 'attemptId'].every(key => nonempty(own(source, key))))
|
|
9
|
+
|
|
10
|
+
export class LightRAGCompositionBindingError extends TypeError {
|
|
11
|
+
constructor(message, returned, { snapshotState = 'received', snapshotError = null } = {}) {
|
|
12
|
+
super(message, snapshotError ? { cause: snapshotError } : undefined)
|
|
13
|
+
this.name = 'LightRAGCompositionBindingError'
|
|
14
|
+
this.retainedReturn = returned
|
|
15
|
+
this.snapshotState = snapshotState
|
|
16
|
+
this.snapshotError = snapshotError
|
|
17
|
+
this.effectUncertain = true
|
|
18
|
+
this.retryAuthorized = false
|
|
19
|
+
// Failure data/costs are custody, never a successful host receipt identity.
|
|
20
|
+
for (const [key, value] of [['usage', own(own(returned, 'envelope'), 'usage') ?? null], ['supplierCosts', own(returned, 'costs') ?? null]]) {
|
|
21
|
+
try { this[key] = structuredClone(value) }
|
|
22
|
+
catch (error) { this[key] = value; this[`${key}SnapshotError`] = error }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Private host-dispatched binding; no Python/SDK process or receipt principal is
|
|
28
|
+
* constructed here. The actual host owns execution and the verified receipt bridge.
|
|
29
|
+
*/
|
|
30
|
+
export function createLightRAGCompositionBinding({ dispatch }) {
|
|
31
|
+
if (typeof dispatch !== 'function') throw new TypeError('Existing host supplier dispatch required')
|
|
32
|
+
const run = async (operation, payload) => {
|
|
33
|
+
// The host dispatches exactly one selected supplier query, canonical citation
|
|
34
|
+
// receiving, then receive_composition with its actual verified receipt owner.
|
|
35
|
+
const returned = await dispatch({ operation, payload })
|
|
36
|
+
let received
|
|
37
|
+
try { received = structuredClone(returned) }
|
|
38
|
+
catch (snapshotError) {
|
|
39
|
+
throw new LightRAGCompositionBindingError('Original supplier return could not be snapshotted', returned,
|
|
40
|
+
{ snapshotState: 'failed', snapshotError })
|
|
41
|
+
}
|
|
42
|
+
const envelope = received?.envelope
|
|
43
|
+
if (received?.operation !== 'receive-composition' || received.outcome !== 'composition-envelope-received' ||
|
|
44
|
+
!object(envelope) || envelope.provider !== 'lightrag' || !nonempty(received.generationId) || envelope.generation !== received.generationId ||
|
|
45
|
+
envelope.nativeOperation !== operation || !envelope.receiptRef || !envelope.bridgeReceipt ||
|
|
46
|
+
envelope.receiptAssurance !== 'explicit-verified-existing-host-bridge' ||
|
|
47
|
+
!artifact(received.supplierQueryReceipt) || !artifact(received.supplierReceivingReceipt) ||
|
|
48
|
+
!artifact(received.envelopeArtifact) || !artifact(received.artifact) ||
|
|
49
|
+
!artifact(envelope.supplierQueryReceipt) || !artifact(envelope.supplierReceivingReceipt) || !artifact(envelope.artifactRef) ||
|
|
50
|
+
!sources(received.sourceBindings) || !sources(envelope.sourceBindings) ||
|
|
51
|
+
!Array.isArray(envelope.hits) || !Array.isArray(envelope.unresolvedReferences) ||
|
|
52
|
+
!isDeepStrictEqual(envelope.artifactRef, received.supplierReceivingReceipt) ||
|
|
53
|
+
!isDeepStrictEqual(envelope.supplierReceivingReceipt, received.supplierReceivingReceipt) ||
|
|
54
|
+
!isDeepStrictEqual(envelope.supplierQueryReceipt, received.supplierQueryReceipt) ||
|
|
55
|
+
!isDeepStrictEqual(envelope.sourceBindings, received.sourceBindings)) {
|
|
56
|
+
throw new LightRAGCompositionBindingError('Original supplier descriptors, source binding/capture and actual verified host receipt bridge required', received)
|
|
57
|
+
}
|
|
58
|
+
if (operation === 'answer' && !envelope.nativeResult?.llm_response) throw new LightRAGCompositionBindingError('Original coupled native answer required', received)
|
|
59
|
+
return structuredClone(envelope)
|
|
60
|
+
}
|
|
61
|
+
return Object.freeze({
|
|
62
|
+
bindings: Object.freeze({ retrieve: payload => run('retrieve', payload), nativeAnswer: payload => run('answer', payload) }),
|
|
63
|
+
operationRoles: Object.freeze({ retrieve: 'retrieve', nativeAnswer: 'native-answer' }),
|
|
64
|
+
hostRequired: Object.freeze(['single-selected-supplier-query', 'existing-canonical-citation-hydration',
|
|
65
|
+
'existing-current-source-and-quote-support', 'actual-verified-host-receipt-bridge']),
|
|
66
|
+
})
|
|
67
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { createVanillaIngestionBridge, normalizeCandidateJson, readVanillaCapture, VanillaIngestionError } from './index.mjs'
|
|
2
|
+
|
|
3
|
+
const check = (value, message) => { if (!value) throw new VanillaIngestionError('VANILLA_COMPOSITION_BINDING', message) }
|
|
4
|
+
|
|
5
|
+
/** Private host adapter for the parent's createComposition callable interface.
|
|
6
|
+
* Receipt references come from the host, not from a new supplier receipt owner.
|
|
7
|
+
*/
|
|
8
|
+
export function createVanillaCompositionBinding({ runner, captureAttempt, extract,
|
|
9
|
+
normalize = normalizeCandidateJson, receiptFor, now, monotonic }) {
|
|
10
|
+
check(typeof extract === 'function' && typeof receiptFor === 'function', 'Existing host extractor and receipt-reference callback are required')
|
|
11
|
+
check(typeof runner?.context === 'function', 'The existing fresh knowledge context owner is required')
|
|
12
|
+
const bridge = createVanillaIngestionBridge({ runner, captureAttempt, now, monotonic })
|
|
13
|
+
|
|
14
|
+
async function bound(operationId) {
|
|
15
|
+
const status = await runner.status({ operationId })
|
|
16
|
+
check(status.phase === 'completed' && status.freshness === 'current', 'Current completed semantic operation is required')
|
|
17
|
+
const saved = readVanillaCapture(status)
|
|
18
|
+
return { status, operationBinding: {
|
|
19
|
+
operationId: status.operationId,
|
|
20
|
+
attemptId: status.attempt.attempt.attemptId,
|
|
21
|
+
inputDigest: status.input.digest,
|
|
22
|
+
domainRef: structuredClone(status.input.domainRef),
|
|
23
|
+
configurationDigest: status.extractor.configurationDigest,
|
|
24
|
+
completion: structuredClone(status.attempt.completion),
|
|
25
|
+
rawOutputDigest: saved.capture.raw.sha256,
|
|
26
|
+
historyDigest: status.head,
|
|
27
|
+
sourceReferences: status.input.evidence.map(span => structuredClone(span.reference)),
|
|
28
|
+
} }
|
|
29
|
+
}
|
|
30
|
+
async function receipt(operation, current, extra = {}) {
|
|
31
|
+
const receiptRef = await receiptFor({ operation, operationBinding: structuredClone(current.operationBinding),
|
|
32
|
+
usageAssurance: 'host-reported', authority: 'none', ...extra })
|
|
33
|
+
check(receiptRef !== undefined && receiptRef !== null && receiptRef !== '', 'Host must return its actual receipt/state reference')
|
|
34
|
+
return receiptRef
|
|
35
|
+
}
|
|
36
|
+
function operationId(input, extraction) {
|
|
37
|
+
const id = extraction?.operationBinding?.operationId ?? input?.resume?.operationId
|
|
38
|
+
check(typeof id === 'string' && id.length > 0, 'Use the actual extraction operation or an explicit saved operation')
|
|
39
|
+
return id
|
|
40
|
+
}
|
|
41
|
+
function query(input) {
|
|
42
|
+
check(typeof input?.proposalQuery === 'string' && input.proposalQuery.trim().length > 0, 'Explicit proposal query is required for the current knowledge view')
|
|
43
|
+
return input.proposalQuery
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const extractOperation = async ({ input }, { signal } = {}) => {
|
|
47
|
+
check(Boolean(input?.begin) !== Boolean(input?.resume), 'Select one new reservation or one explicit saved-operation recovery')
|
|
48
|
+
const result = input.begin
|
|
49
|
+
? await bridge.execute({ begin: input.begin, extract, normalize, signal })
|
|
50
|
+
: await bridge.resume({ operationId: input.resume.operationId, normalize, signal })
|
|
51
|
+
// A cache hit can return an older operation ID than the requested new one.
|
|
52
|
+
// Bind the actual runner result, never the caller's requested reservation.
|
|
53
|
+
const current = await bound(result.status.operationId)
|
|
54
|
+
return { result, operationBinding: current.operationBinding,
|
|
55
|
+
receiptRef: await receipt('extract', current, { cacheReuse: result.cacheReuse }),
|
|
56
|
+
usage: result.cacheReuse ? null : current.status.usage,
|
|
57
|
+
captureUsage: current.status.usage, cacheReuse: result.cacheReuse,
|
|
58
|
+
receiptAssurance: 'host-reference-to-existing-state', authority: 'none', semanticAcceptance: 'pending' }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const readKnowledgeView = async ({ requestedView, input, extraction }) => {
|
|
62
|
+
check(['native-exploration', 'accepted-knowledge'].includes(requestedView), 'Select an existing knowledge view')
|
|
63
|
+
const current = await bound(operationId(input, extraction)), selectedQuery = query(input)
|
|
64
|
+
// A domain reference identifies existing ledger/domain custody. It does not
|
|
65
|
+
// authenticate a human receiver or assert that any candidate was admitted.
|
|
66
|
+
const knowledgeView = requestedView === 'native-exploration'
|
|
67
|
+
? await runner.proposals({ operationId: current.status.operationId, query: selectedQuery })
|
|
68
|
+
: await runner.context({ query: selectedQuery })
|
|
69
|
+
return { kind: requestedView, ownerRef: current.status.input.domainRef,
|
|
70
|
+
ownerRefSemantics: 'existing-knowledge-domain-reference', operationBinding: current.operationBinding,
|
|
71
|
+
knowledgeView, authority: 'none', canonicalMutation: false }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const retrieveOperation = async ({ input, question, view }) => {
|
|
75
|
+
check(view?.kind === 'native-exploration', 'This located proposal retriever serves native exploration only; accepted context stays with its receiver')
|
|
76
|
+
const current = await bound(view.operationBinding?.operationId)
|
|
77
|
+
// Revalidate evidence at retrieval, rather than serving a captured view object.
|
|
78
|
+
const proposalView = await runner.proposals({ operationId: current.status.operationId,
|
|
79
|
+
query: typeof question === 'string' && question.trim() ? question : query(input) })
|
|
80
|
+
const hits = proposalView.assertions.flatMap(assertion => assertion.evidence.map(citation => ({
|
|
81
|
+
evidenceRef: { sourceId: citation.sourceId, revision: citation.sourceDigest,
|
|
82
|
+
representationId: citation.attemptId, locator: structuredClone(citation.locator) },
|
|
83
|
+
quote: citation.quote, assertion: structuredClone(assertion),
|
|
84
|
+
score: null, scoreSemantics: 'literal-pending-proposal-match', semanticAcceptance: 'pending',
|
|
85
|
+
})))
|
|
86
|
+
return { hits, proposalView, operationBinding: current.operationBinding,
|
|
87
|
+
generation: proposalView.inputDigest,
|
|
88
|
+
artifactRef: { attemptId: current.operationBinding.attemptId,
|
|
89
|
+
outputDigest: current.operationBinding.completion.outputDigest },
|
|
90
|
+
receiptRef: await receipt('retrieve', current, { viewBinding: {
|
|
91
|
+
inputDigest: proposalView.inputDigest, domainRef: proposalView.domainRef,
|
|
92
|
+
answerClass: proposalView.answerClass, query: question ?? input.proposalQuery,
|
|
93
|
+
} }),
|
|
94
|
+
usage: null, receiptAssurance: 'host-reference-to-existing-state',
|
|
95
|
+
coverage: proposalView.coverage, readScope: proposalView.readScope,
|
|
96
|
+
authority: 'none', canonicalMutation: false, semanticAcceptance: 'pending' }
|
|
97
|
+
}
|
|
98
|
+
return Object.freeze({ bindings: Object.freeze({ extract: extractOperation, retrieve: retrieveOperation }),
|
|
99
|
+
// Private execution declaration for the receiver's own-property role checks.
|
|
100
|
+
// This does not register a capability or establish admission authority.
|
|
101
|
+
operationRoles: Object.freeze({ extract: 'extract', retrieve: 'retrieve' }), readKnowledgeView })
|
|
102
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { performance } from 'node:perf_hooks'
|
|
3
|
+
|
|
4
|
+
// Private supplier serialization, not an ontology, ledger, or public contract.
|
|
5
|
+
export const VANILLA_CAPTURE_FORMAT = 'atelier.vanilla-extraction-capture/v0'
|
|
6
|
+
export const MAX_CAPTURE_BYTES = 16 * 1024 * 1024 // Existing intake UTF-8 ceiling.
|
|
7
|
+
const digest = bytes => createHash('sha256').update(bytes).digest('hex')
|
|
8
|
+
const fields = ['inputTokens', 'outputTokens', 'cost', 'currency', 'elapsedMs', 'retries']
|
|
9
|
+
|
|
10
|
+
export class VanillaIngestionError extends Error {
|
|
11
|
+
constructor(code, message, { cause, recovery, recorded, captured, attemptedCapture, uncaptured } = {}) {
|
|
12
|
+
super(message, { cause }); this.name = 'VanillaIngestionError'; this.code = code
|
|
13
|
+
if (recovery) this.recovery = recovery
|
|
14
|
+
if (recorded) this.recorded = recorded
|
|
15
|
+
if (captured) this.captured = captured
|
|
16
|
+
if (attemptedCapture) this.attemptedCapture = attemptedCapture
|
|
17
|
+
if (uncaptured) this.uncaptured = uncaptured
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function check(value, code, message) { if (!value) throw new VanillaIngestionError(code, message) }
|
|
21
|
+
function ownData(value, key) {
|
|
22
|
+
if (value === null || !['object', 'function'].includes(typeof value)) return undefined
|
|
23
|
+
try { return Object.getOwnPropertyDescriptor(value, key)?.value } catch { return undefined }
|
|
24
|
+
}
|
|
25
|
+
function same(left, right) {
|
|
26
|
+
// Object key order is not an intake or runner receipt contract.
|
|
27
|
+
const stable = value => value === null || typeof value !== 'object' ? JSON.stringify(value)
|
|
28
|
+
: Array.isArray(value) ? `[${value.map(stable).join(',')}]`
|
|
29
|
+
: `{${Object.keys(value).sort().map(key => `${JSON.stringify(key)}:${stable(value[key])}`).join(',')}}`
|
|
30
|
+
return stable(left) === stable(right)
|
|
31
|
+
}
|
|
32
|
+
function rawBytes(output) {
|
|
33
|
+
check(typeof output === 'string' || output instanceof Uint8Array, 'VANILLA_OUTPUT', 'Extractor output must be text or bytes')
|
|
34
|
+
return Buffer.from(output) // Copy: the host cannot mutate the captured buffer later.
|
|
35
|
+
}
|
|
36
|
+
function captureFor(status, output, suppliedUsage, elapsedMs) {
|
|
37
|
+
const bytes = rawBytes(output)
|
|
38
|
+
const usage = Object.fromEntries(fields.map(key => [key, suppliedUsage?.[key] ?? (key === 'elapsedMs' ? elapsedMs : null)]))
|
|
39
|
+
for (const value of Object.values(usage)) check(typeof value !== 'number' || Number.isFinite(value),
|
|
40
|
+
'VANILLA_USAGE_ENCODING', 'Nonfinite reported usage cannot be losslessly encoded; retain returned bytes and settle host accounting')
|
|
41
|
+
const capture = {
|
|
42
|
+
format: VANILLA_CAPTURE_FORMAT,
|
|
43
|
+
inputDigest: status.input.digest,
|
|
44
|
+
extractor: status.extractor,
|
|
45
|
+
raw: { encoding: 'base64', bytes: bytes.length, sha256: digest(bytes), data: bytes.toString('base64') },
|
|
46
|
+
usage, usageAssurance: 'host-reported',
|
|
47
|
+
timing: { extractionElapsedMs: elapsedMs, assurance: 'host-measured-monotonic' },
|
|
48
|
+
coverage: status.input.coverage,
|
|
49
|
+
}
|
|
50
|
+
const outputEnvelope = JSON.stringify(capture)
|
|
51
|
+
check(Buffer.byteLength(outputEnvelope) <= MAX_CAPTURE_BYTES, 'VANILLA_CAPTURE_LIMIT', 'Capture exceeds the existing intake byte ceiling')
|
|
52
|
+
return { capture, outputEnvelope, outputDigest: digest(outputEnvelope) }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Verify the immutable wrapper and exact producer/input pins before reuse. */
|
|
56
|
+
export function readVanillaCapture(status) {
|
|
57
|
+
check(['partial', 'complete'].includes(status?.attempt?.status) && typeof status.attempt.output === 'string', 'VANILLA_CAPTURE_MISSING', 'No saved extraction bytes are available')
|
|
58
|
+
const outputEnvelope = status.attempt.output
|
|
59
|
+
check(Buffer.byteLength(outputEnvelope) <= MAX_CAPTURE_BYTES, 'VANILLA_CAPTURE_LIMIT', 'Saved capture exceeds the intake ceiling')
|
|
60
|
+
let capture
|
|
61
|
+
try { capture = JSON.parse(outputEnvelope) } catch (cause) { throw new VanillaIngestionError('VANILLA_CAPTURE_INTEGRITY', 'Saved output is not a vanilla capture', { cause }) }
|
|
62
|
+
check(capture?.format === VANILLA_CAPTURE_FORMAT && capture.inputDigest === status.input.digest &&
|
|
63
|
+
same(capture.extractor, status.extractor) && capture.coverage === status.input.coverage &&
|
|
64
|
+
capture.usageAssurance === 'host-reported' && same(Object.keys(capture.usage ?? {}).sort(), [...fields].sort()),
|
|
65
|
+
'VANILLA_CAPTURE_INTEGRITY', 'Capture producer, input, coverage or usage pins differ')
|
|
66
|
+
const raw = capture.raw
|
|
67
|
+
check(raw?.encoding === 'base64' && typeof raw.data === 'string' && Number.isSafeInteger(raw.bytes) && raw.bytes >= 0,
|
|
68
|
+
'VANILLA_CAPTURE_INTEGRITY', 'Capture must retain exact encoded raw bytes')
|
|
69
|
+
const bytes = Buffer.from(raw.data, 'base64')
|
|
70
|
+
check(bytes.toString('base64') === raw.data && bytes.length === raw.bytes && digest(bytes) === raw.sha256,
|
|
71
|
+
'VANILLA_CAPTURE_INTEGRITY', 'Extractor raw-byte digest differs')
|
|
72
|
+
const outputDigest = digest(outputEnvelope)
|
|
73
|
+
check(status.attempt.status !== 'complete' || status.attempt.completion?.outputDigest === outputDigest,
|
|
74
|
+
'VANILLA_CAPTURE_INTEGRITY', 'Intake envelope digest differs')
|
|
75
|
+
if (status.phase === 'completed') check(same(status.usage, capture.usage), 'VANILLA_CAPTURE_INTEGRITY', 'Recorded usage differs from immutable capture')
|
|
76
|
+
return { capture, bytes, outputEnvelope, outputDigest }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function normalizeCandidateJson({ bytes }) {
|
|
80
|
+
return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** A provider-free authored/deterministic callback; vocabulary remains host-owned. */
|
|
84
|
+
export function createCandidateExtractor(buildCandidates) {
|
|
85
|
+
check(typeof buildCandidates === 'function', 'VANILLA_EXTRACTOR', 'A candidate authoring function is required')
|
|
86
|
+
return async ({ input, extractor, signal }) => {
|
|
87
|
+
check(['authored', 'deterministic'].includes(extractor.route), 'VANILLA_EXTRACTOR', 'This helper only implements provider-free routes')
|
|
88
|
+
const candidates = await buildCandidates({ input, signal })
|
|
89
|
+
return { output: JSON.stringify(candidates), usage: { inputTokens: 0, outputTokens: 0, cost: 0, currency: null, retries: 0 } }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Host composition supplies the existing createSemanticOperation result. */
|
|
94
|
+
export function createVanillaIngestionBridge({ runner, captureAttempt = null, now = () => new Date().toISOString(), monotonic = () => performance.now() }) {
|
|
95
|
+
for (const method of ['begin', 'status', 'complete', 'proposals']) check(typeof runner?.[method] === 'function', 'VANILLA_RUNNER', `Existing semantic runner.${method} is required`)
|
|
96
|
+
check(captureAttempt === null || typeof captureAttempt === 'function', 'VANILLA_CAPTURE', 'The existing intake completion callback is required when supplied')
|
|
97
|
+
function notAborted(signal) { check(!signal?.aborted, 'VANILLA_ABORTED', 'Host cancelled extraction or interpretation; reopen saved state') }
|
|
98
|
+
async function failure(error, operationId, stage, extra = {}) {
|
|
99
|
+
let status = null
|
|
100
|
+
try { status = await runner.status({ operationId }) } catch { /* Never erase original saved receipts. */ }
|
|
101
|
+
let captured = extra.captured
|
|
102
|
+
const attemptedCapture = extra.attemptedCapture ?? ownData(error, 'captured')
|
|
103
|
+
const expectedOutputDigest = extra.expectedOutputDigest ?? ownData(ownData(attemptedCapture, 'completion'), 'outputDigest')
|
|
104
|
+
const expectedAttemptId = extra.expectedAttemptId ?? ownData(attemptedCapture, 'attemptId')
|
|
105
|
+
if (!captured && !extra.captureReadbackFailed && (expectedOutputDigest || stage === 'recovery') &&
|
|
106
|
+
['partial', 'complete'].includes(status?.attempt?.status)) {
|
|
107
|
+
try {
|
|
108
|
+
const saved = readVanillaCapture(status)
|
|
109
|
+
if (status.operationId === operationId && (!expectedOutputDigest || saved.outputDigest === expectedOutputDigest) &&
|
|
110
|
+
(!expectedAttemptId || status.attempt.attempt.attemptId === expectedAttemptId)) captured = { attemptId: status.attempt.attempt.attemptId,
|
|
111
|
+
completion: status.attempt.completion, head: status.head, nextAction: 'reopen-captured-output' }
|
|
112
|
+
} catch { /* Unverified readback is never presented as a saved receipt. */ }
|
|
113
|
+
}
|
|
114
|
+
const code = ownData(error, 'code'), message = ownData(error, 'message')
|
|
115
|
+
return new VanillaIngestionError(typeof code === 'string' ? code : 'VANILLA_INTERRUPTED', typeof message === 'string' ? message : 'Host operation was interrupted', {
|
|
116
|
+
cause: error, recorded: ownData(error, 'recorded'), captured, attemptedCapture, uncaptured: captured ? undefined : extra.uncaptured,
|
|
117
|
+
recovery: { operationId, stage, phase: status?.phase ?? null, execution: status?.execution ?? 'unknown',
|
|
118
|
+
nextAction: captured ? 'resume-interpretation-from-capture' : 'inspect-and-explicitly-reconcile-execution',
|
|
119
|
+
extractorMayRunAgain: false },
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
async function verifyCapture({ operationId, attemptId, expectedOutputDigest, completion }) {
|
|
123
|
+
const reread = await runner.status({ operationId })
|
|
124
|
+
const verified = readVanillaCapture(reread)
|
|
125
|
+
check(reread.operationId === operationId && reread.attempt.attempt.attemptId === attemptId &&
|
|
126
|
+
reread.attempt.status === 'complete' && verified.outputDigest === expectedOutputDigest && same(completion, reread.attempt.completion),
|
|
127
|
+
'VANILLA_CAPTURE_INTEGRITY', 'Existing intake completion readback differs')
|
|
128
|
+
return { attemptId, completion: reread.attempt.completion, head: reread.head, nextAction: 'reopen-captured-output' }
|
|
129
|
+
}
|
|
130
|
+
async function result(status, { query, proposals = null, cacheReuse = false } = {}) {
|
|
131
|
+
check(status.freshness === 'current', 'VANILLA_STALE', 'Saved extraction is stale; use a new structural plan and extraction operation')
|
|
132
|
+
const saved = readVanillaCapture(status)
|
|
133
|
+
return { status, capture: saved.capture, proposals,
|
|
134
|
+
proposalView: query === undefined ? null : await runner.proposals({ operationId: status.operationId, query }),
|
|
135
|
+
cacheReuse, coverage: status.input.coverage, readScope: status.input.readScope,
|
|
136
|
+
sourceReferences: status.input.evidence.map(span => span.reference),
|
|
137
|
+
semanticAcceptance: 'pending', canonicalMutation: false, authority: 'none' }
|
|
138
|
+
}
|
|
139
|
+
async function interpret(status, { normalize, query, signal }) {
|
|
140
|
+
check(status.freshness === 'current', 'VANILLA_STALE', 'Captured output is retained but its source or domain is stale')
|
|
141
|
+
const saved = readVanillaCapture(status)
|
|
142
|
+
if (status.phase === 'completed') return result(status, { query, cacheReuse: true })
|
|
143
|
+
check(status.phase === 'reserved', 'VANILLA_RECOVERY_REQUIRED', 'Only a reserved capture may finish interpretation')
|
|
144
|
+
notAborted(signal)
|
|
145
|
+
const candidates = await normalize({ bytes: Buffer.from(saved.bytes), input: structuredClone(status.input), extractor: structuredClone(status.extractor) })
|
|
146
|
+
notAborted(signal)
|
|
147
|
+
// Reopen after asynchronous normalization. The actual runner rechecks source,
|
|
148
|
+
// input, immutable raw bytes and history before recording candidates.
|
|
149
|
+
const current = await runner.status({ operationId: status.operationId })
|
|
150
|
+
if (current.phase === 'completed') return result(current, { query, cacheReuse: true })
|
|
151
|
+
check(current.freshness === 'current', 'VANILLA_STALE', 'Source or adopted domain changed during interpretation')
|
|
152
|
+
const completed = await runner.complete({ operationId: status.operationId, output: saved.outputEnvelope,
|
|
153
|
+
expectedOutputDigest: saved.outputDigest, candidates, usage: saved.capture.usage, at: now(), confirm: current.head })
|
|
154
|
+
return result(completed, { query, proposals: completed.proposals })
|
|
155
|
+
}
|
|
156
|
+
async function execute({ begin, extract, normalize = normalizeCandidateJson, query, signal }) {
|
|
157
|
+
check(typeof extract === 'function' && typeof normalize === 'function', 'VANILLA_EXTRACTOR', 'Host extraction and pure normalization callbacks are required')
|
|
158
|
+
notAborted(signal)
|
|
159
|
+
let ready, extracted, retainedOutput, saved, captured, attemptedCapture, captureReadbackFailed = false, stage = 'reservation'
|
|
160
|
+
try {
|
|
161
|
+
ready = await runner.begin(begin)
|
|
162
|
+
if (ready.cacheReuse) return await result(ready, { query, cacheReuse: true })
|
|
163
|
+
check(ready.execution === 'ready-for-host', 'VANILLA_EXECUTION_UNKNOWN', 'Only a new ready reservation permits host extraction')
|
|
164
|
+
notAborted(signal); stage = 'extraction'
|
|
165
|
+
const started = monotonic()
|
|
166
|
+
extracted = await extract({ input: structuredClone(ready.input), extractor: structuredClone(ready.extractor), signal,
|
|
167
|
+
limits: { maxCaptureBytes: MAX_CAPTURE_BYTES, rawEncoding: 'base64' } })
|
|
168
|
+
const elapsedMs = Math.max(0, Math.round(monotonic() - started))
|
|
169
|
+
stage = 'capture'
|
|
170
|
+
retainedOutput = { output: rawBytes(extracted?.output), usage: structuredClone(extracted?.usage) }
|
|
171
|
+
saved = captureFor(ready, extracted?.output, extracted?.usage, elapsedMs)
|
|
172
|
+
const current = await runner.status({ operationId: ready.operationId })
|
|
173
|
+
if (captureAttempt) {
|
|
174
|
+
// The manifest is the runner's reservation. Capture uses that same
|
|
175
|
+
// existing intake owner; runner.complete subsequently verifies it again.
|
|
176
|
+
const attemptId = current.attempt.attempt?.attemptId
|
|
177
|
+
check(current.phase === 'reserved' && attemptId === ready.attempt.attempt.attemptId,
|
|
178
|
+
'VANILLA_CAPTURE_INTEGRITY', 'Capture requires the original reserved intake manifest')
|
|
179
|
+
attemptedCapture = { attemptId, expectedOutputDigest: saved.outputDigest, head: current.head, nextAction: 'inspect-capture-custody' }
|
|
180
|
+
attemptedCapture.completion = await captureAttempt({ attemptId, output: saved.outputEnvelope, expectedOutputDigest: saved.outputDigest })
|
|
181
|
+
stage = 'capture-readback'; captureReadbackFailed = true
|
|
182
|
+
captured = await verifyCapture({ operationId: ready.operationId, attemptId, expectedOutputDigest: saved.outputDigest, completion: attemptedCapture.completion })
|
|
183
|
+
captureReadbackFailed = false
|
|
184
|
+
} else {
|
|
185
|
+
// Runner-only compatibility fallback. There is currently no runner
|
|
186
|
+
// capture-only method; absent candidates produce an expected refusal.
|
|
187
|
+
try {
|
|
188
|
+
await runner.complete({ operationId: ready.operationId, output: saved.outputEnvelope, expectedOutputDigest: saved.outputDigest,
|
|
189
|
+
candidates: null, usage: saved.capture.usage, at: now(), confirm: current.head })
|
|
190
|
+
throw new VanillaIngestionError('VANILLA_RUNNER_PROFILE', 'Runner unexpectedly admitted absent candidates')
|
|
191
|
+
} catch (error) {
|
|
192
|
+
const receipt = ownData(error, 'captured')
|
|
193
|
+
if (!receipt) throw error
|
|
194
|
+
attemptedCapture = receipt
|
|
195
|
+
if (ownData(error, 'code') !== 'SEMANTIC_INVALID') throw error
|
|
196
|
+
stage = 'capture-readback'; captureReadbackFailed = true
|
|
197
|
+
captured = await verifyCapture({ operationId: ready.operationId, attemptId: ready.attempt.attempt.attemptId,
|
|
198
|
+
expectedOutputDigest: saved.outputDigest, completion: ownData(receipt, 'completion') })
|
|
199
|
+
captureReadbackFailed = false
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
stage = 'interpretation'
|
|
203
|
+
return await interpret(await runner.status({ operationId: ready.operationId }), { normalize, query, signal })
|
|
204
|
+
} catch (error) {
|
|
205
|
+
throw await failure(error, ready?.operationId ?? begin?.operationId, stage,
|
|
206
|
+
{ captured, attemptedCapture, captureReadbackFailed, expectedOutputDigest: saved?.outputDigest,
|
|
207
|
+
expectedAttemptId: ready?.attempt?.attempt?.attemptId,
|
|
208
|
+
uncaptured: stage.startsWith('capture') && !captured && extracted ? retainedOutput ?? extracted : undefined })
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// No extractor argument by design: recovery cannot charge extraction again.
|
|
212
|
+
async function resume({ operationId, normalize = normalizeCandidateJson, query, signal }) {
|
|
213
|
+
check(typeof normalize === 'function', 'VANILLA_EXTRACTOR', 'A pure normalization callback is required')
|
|
214
|
+
try { return await interpret(await runner.status({ operationId }), { normalize, query, signal }) }
|
|
215
|
+
catch (error) { throw await failure(error, operationId, 'recovery') }
|
|
216
|
+
}
|
|
217
|
+
return Object.freeze({ execute, resume })
|
|
218
|
+
}
|