agentera 3.0.0-dev.8 → 3.0.0-dev.80
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/LICENSE +201 -0
- package/README.md +252 -22
- package/bundle/.agentera-build-source.json +8 -0
- package/bundle/CHANGELOG.md +1387 -0
- package/bundle/DESIGN.md +229 -0
- package/bundle/LICENSE +201 -0
- package/bundle/README.md +143 -0
- package/bundle/UPGRADE.md +271 -0
- package/bundle/extract-corpus-parity.json +2 -4
- package/bundle/fixtures/routing/hybrid-corpus.yaml +154 -0
- package/bundle/references/adapters/package-publication.json +484 -0
- package/bundle/references/adapters/package-registry.yaml +443 -188
- package/bundle/references/adapters/package-surface-characterization.md +68 -34
- package/bundle/references/adapters/product-v1-reset.yaml +101 -0
- package/bundle/references/adapters/runtime-lifecycle-adapters.yaml +74 -0
- package/bundle/references/adapters/runtime-lifecycle-authority.yaml +62 -0
- package/bundle/references/adapters/runtime-lifecycle-operation-contract.yaml +84 -0
- package/bundle/references/adapters/runtime-retired-resources.yaml +333 -0
- package/bundle/references/analysis/evidence-tier-authority.yaml +559 -0
- package/bundle/references/analysis/personal-glossary-evaluation-authority.yaml +175 -0
- package/bundle/references/analysis/personal-glossary-evaluation-corpus.yaml +291 -0
- package/bundle/references/analysis/personal-glossary-holdout.yaml +192 -0
- package/bundle/references/analysis/verification-policy.yaml +261 -0
- package/bundle/references/artifacts/artifact-registry-interface-model.yaml +17 -8
- package/bundle/references/artifacts/glossary-entry-contract.yaml +2906 -0
- package/bundle/references/artifacts/state-storage-authority.yaml +3065 -0
- package/bundle/references/artifacts/verbosity-budget-authority.yaml +42 -0
- package/bundle/references/cli/app-lifecycle-vocabulary.yaml +3 -4
- package/bundle/references/cli/capability-instruction-contract.yaml +11 -14
- package/bundle/references/cli/hybrid-route-contract.yaml +438 -0
- package/bundle/references/cli/routing-model.md +152 -93
- package/bundle/references/cli/trigger-schema-enrichment.md +57 -46
- package/bundle/references/cli/update-channels.yaml +7 -5
- package/bundle/references/cli/vocabulary-index.yaml +7 -9
- package/bundle/references/cli/vocabulary.md +54 -97
- package/bundle/references/meta/retained-reference-authority.yaml +171 -0
- package/bundle/skills/agentera/SKILL.md +183 -63
- package/bundle/skills/agentera/capabilities/audit/schemas/artifacts.yaml +27 -19
- package/bundle/skills/agentera/capabilities/audit/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/audit/schemas/triggers.yaml +13 -35
- package/bundle/skills/agentera/capabilities/audit/schemas/validation.yaml +30 -11
- package/bundle/skills/agentera/capabilities/build/schemas/artifacts.yaml +44 -21
- package/bundle/skills/agentera/capabilities/build/schemas/exit.yaml +8 -6
- package/bundle/skills/agentera/capabilities/build/schemas/triggers.yaml +14 -36
- package/bundle/skills/agentera/capabilities/build/schemas/validation.yaml +95 -21
- package/bundle/skills/agentera/capabilities/design/schemas/artifacts.yaml +6 -6
- package/bundle/skills/agentera/capabilities/design/schemas/exit.yaml +5 -5
- package/bundle/skills/agentera/capabilities/design/schemas/triggers.yaml +5 -34
- package/bundle/skills/agentera/capabilities/design/schemas/validation.yaml +2 -2
- package/bundle/skills/agentera/capabilities/discuss/schemas/artifacts.yaml +17 -13
- package/bundle/skills/agentera/capabilities/discuss/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/discuss/schemas/triggers.yaml +6 -40
- package/bundle/skills/agentera/capabilities/discuss/schemas/validation.yaml +72 -5
- package/bundle/skills/agentera/capabilities/document/schemas/artifacts.yaml +24 -17
- package/bundle/skills/agentera/capabilities/document/schemas/triggers.yaml +5 -35
- package/bundle/skills/agentera/capabilities/document/schemas/validation.yaml +13 -13
- package/bundle/skills/agentera/capabilities/optimize/schemas/artifacts.yaml +10 -10
- package/bundle/skills/agentera/capabilities/optimize/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/optimize/schemas/triggers.yaml +4 -35
- package/bundle/skills/agentera/capabilities/optimize/schemas/validation.yaml +3 -3
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/artifacts.yaml +34 -22
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/exit.yaml +9 -7
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/triggers.yaml +5 -37
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/validation.yaml +38 -37
- package/bundle/skills/agentera/capabilities/plan/schemas/artifacts.yaml +20 -16
- package/bundle/skills/agentera/capabilities/plan/schemas/triggers.yaml +8 -31
- package/bundle/skills/agentera/capabilities/plan/schemas/validation.yaml +66 -6
- package/bundle/skills/agentera/capabilities/profile/schemas/artifacts.yaml +13 -4
- package/bundle/skills/agentera/capabilities/profile/schemas/exit.yaml +8 -5
- package/bundle/skills/agentera/capabilities/profile/schemas/triggers.yaml +8 -37
- package/bundle/skills/agentera/capabilities/profile/schemas/validation.yaml +67 -3
- package/bundle/skills/agentera/capabilities/research/schemas/artifacts.yaml +6 -6
- package/bundle/skills/agentera/capabilities/research/schemas/triggers.yaml +5 -29
- package/bundle/skills/agentera/capabilities/status/schemas/artifacts.yaml +13 -12
- package/bundle/skills/agentera/capabilities/status/schemas/triggers.yaml +7 -49
- package/bundle/skills/agentera/capabilities/vision/schemas/artifacts.yaml +8 -8
- package/bundle/skills/agentera/capabilities/vision/schemas/exit.yaml +7 -6
- package/bundle/skills/agentera/capabilities/vision/schemas/triggers.yaml +7 -39
- package/bundle/skills/agentera/capabilities/vision/schemas/validation.yaml +14 -16
- package/bundle/skills/agentera/capability_schema_contract.yaml +32 -32
- package/bundle/skills/agentera/protocol.yaml +4 -4
- package/bundle/skills/agentera/route-phrases.yaml +81 -0
- package/bundle/skills/agentera/schemas/artifacts/changelog.yaml +1 -0
- package/bundle/skills/agentera/schemas/artifacts/decisions.yaml +29 -30
- package/bundle/skills/agentera/schemas/artifacts/design.yaml +1 -0
- package/bundle/skills/agentera/schemas/artifacts/docs.yaml +7 -43
- package/bundle/skills/agentera/schemas/artifacts/experiments.yaml +140 -34
- package/bundle/skills/agentera/schemas/artifacts/glossary.yaml +87 -0
- package/bundle/skills/agentera/schemas/artifacts/health.yaml +53 -51
- package/bundle/skills/agentera/schemas/artifacts/objective.yaml +18 -35
- package/bundle/skills/agentera/schemas/artifacts/plan.yaml +453 -55
- package/bundle/skills/agentera/schemas/artifacts/progress.yaml +128 -39
- package/bundle/skills/agentera/schemas/artifacts/todo.yaml +305 -7
- package/bundle/skills/agentera/schemas/artifacts/vision.yaml +0 -19
- package/dist/.agentera-build-source.json +8 -0
- package/dist/analytics/extractCorpus/cli.js +52 -11
- package/dist/analytics/extractCorpus/copilotSessions.js +19 -8
- package/dist/analytics/extractCorpus/core.js +262 -14
- package/dist/analytics/extractCorpus/corpus.js +57 -18
- package/dist/analytics/extractCorpus/coverageAudit.js +44 -45
- package/dist/analytics/extractCorpus/cursorSessions.js +28 -8
- package/dist/analytics/extractCorpus/evidenceTiers.js +709 -0
- package/dist/analytics/extractCorpus/extractCorpusParity.js +4 -4
- package/dist/analytics/extractCorpus/filesystemSources.js +5 -5
- package/dist/analytics/extractCorpus/index.js +4 -2
- package/dist/analytics/extractCorpus/jsonlSessions.js +76 -8
- package/dist/analytics/extractCorpus/sqliteCaps.js +0 -1
- package/dist/analytics/extractCorpus/sqliteSessions.js +12 -4
- package/dist/analytics/extractCorpus/tierReader.js +108 -0
- package/dist/analytics/extractCorpus.js +0 -1
- package/dist/analytics/glossaryAdviceResolution.js +166 -0
- package/dist/analytics/glossaryInputAcquisition.js +319 -0
- package/dist/analytics/personalGlossaryAdmission.js +113 -0
- package/dist/analytics/personalGlossaryCandidateProjection.js +788 -0
- package/dist/analytics/personalGlossaryCandidateProjectionExcerpts.js +144 -0
- package/dist/analytics/personalGlossaryCandidateProjectionModel.js +1 -0
- package/dist/analytics/personalGlossaryCandidateReadView.js +23 -0
- package/dist/analytics/personalGlossaryCurrentGeneration.js +25 -0
- package/dist/analytics/personalGlossaryDecision.js +203 -0
- package/dist/analytics/personalGlossaryExplicit.js +788 -0
- package/dist/analytics/personalGlossaryExplicitMining.js +285 -0
- package/dist/analytics/personalGlossaryExplicitScope.js +41 -0
- package/dist/analytics/personalGlossaryExplicitSegments.js +418 -0
- package/dist/analytics/personalGlossaryExplicitTypes.js +26 -0
- package/dist/analytics/personalGlossaryLexicalClassifier.js +175 -0
- package/dist/analytics/personalGlossaryProfile.js +229 -0
- package/dist/analytics/personalGlossaryRecurrence.js +618 -0
- package/dist/analytics/personalGlossaryRefreshProjection.js +351 -0
- package/dist/analytics/personalGlossaryReviewRecordStorage.js +428 -0
- package/dist/analytics/personalGlossaryReviewRecords.js +332 -0
- package/dist/analytics/profileSignals.js +211 -0
- package/dist/analytics/usageStats.js +150 -23
- package/dist/audit/terminologyDrift.js +281 -0
- package/dist/bin/agentera.js +3 -2
- package/dist/capabilities/audit/instructions.js +16 -6
- package/dist/capabilities/build/instructions.js +59 -6
- package/dist/capabilities/design/instructions.js +3 -4
- package/dist/capabilities/discuss/instructions.js +29 -6
- package/dist/capabilities/document/instructions.js +11 -6
- package/dist/capabilities/index.js +20 -14
- package/dist/capabilities/optimize/instructions.js +14 -6
- package/dist/capabilities/orchestrate/instructions.js +42 -6
- package/dist/capabilities/plan/instructions.js +30 -3
- package/dist/capabilities/profile/instructions.js +104 -5
- package/dist/capabilities/research/instructions.js +4 -5
- package/dist/capabilities/status/instructions.js +15 -6
- package/dist/capabilities/status/startupInstructions.js +34 -0
- package/dist/capabilities/vision/instructions.js +3 -5
- package/dist/cli/appContext.js +14 -7
- package/dist/cli/argvalidate.js +0 -1
- package/dist/cli/capabilityContext/benchmark.js +5 -4
- package/dist/cli/capabilityContext/bespoke.js +14 -6
- package/dist/cli/capabilityContext/build.js +116 -42
- package/dist/cli/capabilityContext/closeout.js +30 -27
- package/dist/cli/capabilityContext/contract.js +18 -27
- package/dist/cli/capabilityContext/evidence.js +84 -77
- package/dist/cli/capabilityContext/index.js +0 -1
- package/dist/cli/capabilityContext/orchestration.js +42 -18
- package/dist/cli/capabilityContext/planState.js +89 -96
- package/dist/cli/capabilityContext/progress.js +52 -12
- package/dist/cli/capabilityContext/projectVerification.js +409 -0
- package/dist/cli/capabilityContext/shared.js +9 -20
- package/dist/cli/capabilityContext/slim.js +52 -8
- package/dist/cli/capabilityContext/startup.js +51 -114
- package/dist/cli/capabilityContext/startupAggregation.js +68 -0
- package/dist/cli/capabilityContext/types.js +26 -10
- package/dist/cli/capabilityContext.js +0 -1
- package/dist/cli/commands/appHome.js +0 -1
- package/dist/cli/commands/capability.js +2 -2
- package/dist/cli/commands/compact.js +163 -13
- package/dist/cli/commands/doctor.js +118 -11
- package/dist/cli/commands/durability.js +81 -0
- package/dist/cli/commands/glossaryAdvice.js +138 -0
- package/dist/cli/commands/lint.js +22 -8
- package/dist/cli/commands/personalGlossaryCandidateReads.js +755 -0
- package/dist/cli/commands/personalGlossaryDecision.js +349 -0
- package/dist/cli/commands/personalGlossaryPublish.js +484 -0
- package/dist/cli/commands/personalGlossaryReviewRecordReads.js +209 -0
- package/dist/cli/commands/personalGlossaryReviewRecords.js +623 -0
- package/dist/cli/commands/prime/briefOrientation.js +845 -0
- package/dist/cli/commands/prime/buildExecutionRequest.js +165 -0
- package/dist/cli/commands/prime/bundleStatus.js +54 -4
- package/dist/cli/commands/prime/collectEntityOrientation.js +338 -0
- package/dist/cli/commands/prime/collectOrientationState.js +124 -68
- package/dist/cli/commands/prime/orientationOutput.js +271 -59
- package/dist/cli/commands/prime/types.js +0 -1
- package/dist/cli/commands/prime.js +89 -11
- package/dist/cli/commands/profileGrounding.js +55 -0
- package/dist/cli/commands/query.js +74 -52
- package/dist/cli/commands/report.js +187 -27
- package/dist/cli/commands/route.js +142 -0
- package/dist/cli/commands/schema.js +436 -138
- package/dist/cli/commands/state/decisions.js +40 -56
- package/dist/cli/commands/state/docs.js +58 -85
- package/dist/cli/commands/state/experimentRecords.js +151 -0
- package/dist/cli/commands/state/experiments.js +11 -65
- package/dist/cli/commands/state/get.js +129 -0
- package/dist/cli/commands/state/health.js +11 -113
- package/dist/cli/commands/state/index.js +6 -41
- package/dist/cli/commands/state/list.js +194 -0
- package/dist/cli/commands/state/objective.js +21 -65
- package/dist/cli/commands/state/plan.js +11 -170
- package/dist/cli/commands/state/planTasks.js +154 -0
- package/dist/cli/commands/state/plans.js +154 -0
- package/dist/cli/commands/state/progress.js +11 -45
- package/dist/cli/commands/state/shared.js +0 -1
- package/dist/cli/commands/state/todo.js +28 -107
- package/dist/cli/commands/state/write.js +459 -0
- package/dist/cli/commands/upgrade.js +176 -5
- package/dist/cli/commands/upgradeVerify.js +118 -0
- package/dist/cli/commands/validate.js +235 -136
- package/dist/cli/commands/verify.js +73 -16
- package/dist/cli/contracts/bundleStatus.js +0 -1
- package/dist/cli/contracts/orientationState.js +0 -1
- package/dist/cli/dispatch/argvParser.js +0 -1
- package/dist/cli/dispatch/check.js +84 -40
- package/dist/cli/dispatch/commands.js +3 -3
- package/dist/cli/dispatch/index.js +84 -52
- package/dist/cli/dispatch/lifecycle.js +182 -62
- package/dist/cli/dispatch/prime.js +37 -2
- package/dist/cli/dispatch/projections.js +17 -0
- package/dist/cli/dispatch/shared.js +1 -2
- package/dist/cli/dispatch/state.js +62 -66
- package/dist/cli/dispatch.js +0 -1
- package/dist/cli/errors.js +16 -17
- package/dist/cli/help.js +419 -41
- package/dist/cli/migrationRequired.js +125 -0
- package/dist/cli/orientation/attention.js +19 -22
- package/dist/cli/orientation/corpusCoverage.js +32 -1
- package/dist/cli/orientation.js +346 -129
- package/dist/cli/planArtifacts.js +350 -0
- package/dist/cli/planEvidence.js +157 -0
- package/dist/cli/planLifecycleState.js +36 -0
- package/dist/cli/planTaskIndex.js +11 -0
- package/dist/cli/preCutoverCommand.js +32 -0
- package/dist/cli/prime-blob.js +71 -3
- package/dist/cli/productV1Eol.js +55 -0
- package/dist/cli/profileAcquisition.js +167 -0
- package/dist/cli/startupCompletenessContract.js +11 -9
- package/dist/cli/stateQuery.js +47 -12
- package/dist/cli/structured.js +0 -1
- package/dist/cli/todoMarkdown.js +25 -12
- package/dist/cli/todoReadinessSelection.js +192 -0
- package/dist/cli/todoSeverity.js +0 -1
- package/dist/core/atomicWriter.js +23 -0
- package/dist/core/developmentChannel.js +1 -0
- package/dist/core/developmentInvocation.js +377 -0
- package/dist/core/difflib.js +0 -1
- package/dist/core/envPaths.js +0 -1
- package/dist/core/jsonValue.js +0 -1
- package/dist/core/paths.js +0 -1
- package/dist/core/pyjson.js +0 -1
- package/dist/core/shell.js +4 -0
- package/dist/core/skillIdentity.js +23 -0
- package/dist/core/sourceRoot.js +9 -12
- package/dist/core/text.js +10 -0
- package/dist/core/toml.js +0 -1
- package/dist/core/yaml.js +61 -2
- package/dist/eval/evalSkills.js +13 -14
- package/dist/eval/glossaryEvaluation.js +751 -0
- package/dist/eval/glossaryEvaluationProcess.js +29 -0
- package/dist/eval/glossaryEvaluationRunner.js +571 -0
- package/dist/eval/glossaryEvaluationSuccessReport.js +297 -0
- package/dist/eval/hybridRouteEvaluation.js +155 -0
- package/dist/eval/semanticEval.js +0 -1
- package/dist/eval/semanticFixtures.js +0 -1
- package/dist/hooks/common.js +3 -56
- package/dist/hooks/compaction/apply.js +224 -47
- package/dist/hooks/compaction/dryRun.js +2 -1
- package/dist/hooks/compaction/index.js +5 -6
- package/dist/hooks/compaction/parse.js +73 -6
- package/dist/hooks/compaction/retention.js +28 -25
- package/dist/hooks/compaction/status.js +145 -26
- package/dist/hooks/compaction/types.js +0 -1
- package/dist/hooks/validateArtifact/agentFacing.js +0 -1
- package/dist/hooks/validateArtifact/index.js +6 -65
- package/dist/hooks/validateArtifact/markdown.js +9 -10
- package/dist/hooks/validateArtifact/schema.js +96 -9
- package/dist/hooks/validateArtifact/traversal.js +12 -11
- package/dist/hooks/validateArtifact/violations.js +5 -3
- package/dist/migrate/v2HandoffManifest.js +8 -3
- package/dist/registries/activationContract.js +2 -0
- package/dist/registries/activationTuples.js +145 -0
- package/dist/registries/artifactProtocolIds.js +2 -1
- package/dist/registries/artifactRegistry.js +207 -60
- package/dist/registries/artifactSchemaProjection.js +45 -0
- package/dist/registries/capabilityContract.js +5 -21
- package/dist/registries/evaluatorHandoffContract.js +0 -1
- package/dist/registries/evidenceTierContract.js +375 -0
- package/dist/registries/explicitSegmentGrammarContract.js +619 -0
- package/dist/registries/glossaryAdviceContract.js +79 -0
- package/dist/registries/glossaryCandidateContractPaths.js +6 -0
- package/dist/registries/glossaryCandidateContracts.js +820 -0
- package/dist/registries/glossaryCandidateDecisionAuthority.js +119 -0
- package/dist/registries/glossaryCandidateDecisionContract.js +62 -0
- package/dist/registries/glossaryCandidateProjectionAuthority.js +345 -0
- package/dist/registries/glossaryCandidateProjectionContract.js +108 -0
- package/dist/registries/glossaryCaveatContract.js +67 -0
- package/dist/registries/glossaryConsumerContractValidation.js +787 -0
- package/dist/registries/glossaryEntryContract.js +759 -0
- package/dist/registries/glossaryEntryTemporal.js +12 -0
- package/dist/registries/glossaryMiningAuthority.js +764 -0
- package/dist/registries/glossaryProfileFullContract.js +24 -0
- package/dist/registries/glossaryReviewRecordsAuthority.js +426 -0
- package/dist/registries/glossaryReviewRecordsContract.js +129 -0
- package/dist/registries/glossaryTermIdentity.js +139 -0
- package/dist/registries/glossaryTermOccurrence.js +20 -0
- package/dist/registries/hybridRoute.js +274 -0
- package/dist/registries/hybridRouteReceipt.js +221 -0
- package/dist/registries/packagePublication.js +273 -0
- package/dist/registries/packageRegistry.js +184 -209
- package/dist/registries/personalGlossaryContracts.js +1 -0
- package/dist/registries/todoReadinessContract.js +448 -0
- package/dist/registries/triggerLoader.js +7 -44
- package/dist/registries/verbosityBudgetContract.js +205 -0
- package/dist/release/releaseMetadata.js +168 -11
- package/dist/runtime/lifecycleAdapterContract.js +457 -0
- package/dist/runtime/lifecycleAdapters.js +777 -0
- package/dist/runtime/lifecycleAuthority.js +453 -0
- package/dist/runtime/lifecycleOperationContract.js +123 -0
- package/dist/runtime/lifecycleOperations.js +634 -0
- package/dist/runtime/lifecycleOwnershipJournal.js +622 -0
- package/dist/runtime/lifecyclePublication.js +415 -0
- package/dist/runtime/lifecycleSnapshot.js +438 -0
- package/dist/runtime/nativeResourceCleanup.js +503 -0
- package/dist/setup/opencode.js +20 -13
- package/dist/setup/opencodeConstants.js +1 -0
- package/dist/setup/sharedSkill.js +45 -0
- package/dist/setup/smokeChecks.js +14 -75
- package/dist/state/archiveDiscovery.js +580 -0
- package/dist/state/archivePublication.js +225 -0
- package/dist/state/archiveRecovery.js +237 -0
- package/dist/state/archiveReplay.js +53 -0
- package/dist/state/canonicalMigrationRecord.js +36 -0
- package/dist/state/changelog.js +221 -0
- package/dist/state/decisionEntities.js +367 -0
- package/dist/state/decisionLegacyValidation.js +215 -0
- package/dist/state/decisionMigrationProvenance.js +199 -0
- package/dist/state/decisionOverlay.js +254 -0
- package/dist/state/decisionRevision.js +256 -0
- package/dist/state/decisionRevisionMigration.js +89 -0
- package/dist/state/directRetrieval.js +323 -0
- package/dist/state/durability.js +324 -0
- package/dist/state/entityCutover.js +459 -0
- package/dist/state/entityCutoverGit.js +127 -0
- package/dist/state/entityGlossaryAuthority.js +13 -0
- package/dist/state/entityListProjection.js +187 -0
- package/dist/state/entityListRuntimeRegistry.js +85 -0
- package/dist/state/entityMigrationCausality.js +97 -0
- package/dist/state/entityMigrationIdentity.js +5 -0
- package/dist/state/entityMigrationPreview.js +840 -0
- package/dist/state/entityMigrationTodo.js +133 -0
- package/dist/state/entityPublicationContext.js +859 -0
- package/dist/state/entityRetrievalHelp.js +506 -0
- package/dist/state/entityStorage.js +899 -0
- package/dist/state/exactReplacementRecovery.js +18 -0
- package/dist/state/experimentArchive.js +63 -0
- package/dist/state/experimentIdentity.js +202 -0
- package/dist/state/healthEntities.js +262 -0
- package/dist/state/healthEntityValidation.js +18 -0
- package/dist/state/healthRepair.js +69 -0
- package/dist/state/installRoot.js +15 -7
- package/dist/state/legacyEntityCutoverEvidence.js +65 -0
- package/dist/state/legacyIdentity.js +47 -0
- package/dist/state/legacySummaryRecord.js +6 -0
- package/dist/state/listAccounting.js +54 -0
- package/dist/state/listClassification.js +17 -0
- package/dist/state/listCursor.js +42 -0
- package/dist/state/listRetrieval.js +781 -0
- package/dist/state/migrationSourceBinding.js +30 -0
- package/dist/state/objectiveExperimentEntities.js +322 -0
- package/dist/state/planEntities.js +1027 -0
- package/dist/state/planIdentity.js +47 -0
- package/dist/state/planLineageValidation.js +52 -0
- package/dist/state/planReplacementTransaction.js +475 -0
- package/dist/state/planRetrieval.js +313 -0
- package/dist/state/planTaskRetrieval.js +294 -0
- package/dist/state/progressEntities.js +512 -0
- package/dist/state/progressGlossaryCaveat.js +168 -0
- package/dist/state/progressPublicationOrder.js +19 -0
- package/dist/state/progressWritePolicy.js +33 -0
- package/dist/state/projectRoot.js +62 -0
- package/dist/state/projectionPolicy.js +190 -0
- package/dist/state/retrievalAuthority.js +156 -0
- package/dist/state/safeProjectFile.js +155 -0
- package/dist/state/startupAnalysis/benchmark.js +70 -9
- package/dist/state/startupAnalysis/contract.js +44 -10
- package/dist/state/startupAnalysis/helpers.js +1 -2
- package/dist/state/startupAnalysis/index.js +0 -1
- package/dist/state/startupAnalysis/metrics.js +0 -1
- package/dist/state/startupAnalysis/records.js +0 -1
- package/dist/state/startupAnalysis/report.js +0 -1
- package/dist/state/startupAnalysis/threshold.js +13 -1
- package/dist/state/startupAnalysis.js +0 -1
- package/dist/state/startupProjection.js +499 -0
- package/dist/state/stateMode.js +222 -0
- package/dist/state/stateStorageAuthority.js +47 -0
- package/dist/state/summaryEntityRead.js +25 -0
- package/dist/state/summaryMigrationProvenance.js +66 -0
- package/dist/state/summarySourceRowAuthority.js +36 -0
- package/dist/state/todoActivationSafety.js +58 -0
- package/dist/state/todoCreateBatch.js +69 -0
- package/dist/state/todoDocsEntities.js +1339 -0
- package/dist/state/todoDocsEntityValidation.js +158 -0
- package/dist/state/todoMarkdownProjection.js +63 -0
- package/dist/state/todoReconciliationActivation.js +182 -0
- package/dist/state/todoReconciliationInspection.js +184 -0
- package/dist/state/todoReconciliationRepair.js +320 -0
- package/dist/state/todoReconciliationTransaction.js +628 -0
- package/dist/state/todoSeverityHeadings.js +71 -0
- package/dist/state/todoTransitionBatch.js +65 -0
- package/dist/state/todoUpdateBatch.js +50 -0
- package/dist/state/write/assign.js +20 -0
- package/dist/state/write/candidateMutation.js +269 -0
- package/dist/state/write/errors.js +11 -0
- package/dist/state/write/experimentPublication.js +192 -0
- package/dist/state/write/explain.js +380 -0
- package/dist/state/write/fields.js +61 -0
- package/dist/state/write/glossaryPublication.js +263 -0
- package/dist/state/write/grammar.js +285 -0
- package/dist/state/write/helpers.js +29 -0
- package/dist/state/write/index.js +12 -0
- package/dist/state/write/input.js +391 -0
- package/dist/state/write/lock.js +837 -0
- package/dist/state/write/mutation.js +234 -0
- package/dist/state/write/operations.js +170 -0
- package/dist/state/write/planEvaluation.js +128 -0
- package/dist/state/write/planPublication.js +179 -0
- package/dist/state/write/runtimeOperations.js +146 -0
- package/dist/state/write/serialize.js +1 -0
- package/dist/state/write/transaction.js +57 -0
- package/dist/state/write/validate.js +7 -0
- package/dist/upgrade/appContentRefresh.js +77 -36
- package/dist/upgrade/appModel.js +0 -1
- package/dist/upgrade/atomicWriter.js +1 -0
- package/dist/upgrade/bundleEvidence.js +0 -1
- package/dist/upgrade/channels.js +6 -9
- package/dist/upgrade/compatibility.js +43 -17
- package/dist/upgrade/doctor.js +55 -32
- package/dist/upgrade/doctorClassifier.js +11 -1
- package/dist/upgrade/installedHooksRetirement.js +46 -40
- package/dist/upgrade/legacyAgentCleanup.js +133 -34
- package/dist/upgrade/lifecycleUpgrade.js +113 -0
- package/dist/upgrade/migrateArtifactsV2ToV3.js +325 -82
- package/dist/upgrade/migrationPublication.js +122 -0
- package/dist/upgrade/nextMajorDoctor.js +0 -22
- package/dist/upgrade/npxPlatformStatus.js +2 -2
- package/dist/upgrade/productV1Reset.js +515 -0
- package/dist/upgrade/productV1ResetAuthority.js +139 -0
- package/dist/upgrade/projectIntegration.js +126 -134
- package/dist/upgrade/projectIntegrationDecision.js +21 -13
- package/dist/upgrade/retiredResourceDiagnostics.js +117 -0
- package/dist/upgrade/runtimeMigration.js +210 -430
- package/dist/upgrade/upgradeCommands.js +14 -1
- package/dist/upgrade/upgradeLock.js +85 -0
- package/dist/upgrade/upgradeOrchestrator.js +253 -48
- package/dist/upgrade/v3CapabilitySurface.js +2 -3
- package/dist/upgrade/versionResolution.js +0 -1
- package/dist/validate/activationArtifactEvidence.js +866 -0
- package/dist/validate/activationArtifactEvidenceTypes.js +12 -0
- package/dist/validate/activationConjunction.js +816 -0
- package/dist/validate/activationEvidenceManifest.js +610 -0
- package/dist/validate/activationPackageSemantics.js +29 -0
- package/dist/validate/appHomeContract.js +1 -7
- package/dist/validate/bootstrapAuthority.js +44 -0
- package/dist/validate/capability.js +11 -3
- package/dist/validate/crossCapability.js +14 -9
- package/dist/validate/glossaryVariantGuard.js +96 -0
- package/dist/validate/retainedReferenceAuthority.js +879 -0
- package/dist/validate/selfAudit.js +39 -45
- package/dist/validate/vocabularyAuthority.js +8 -8
- package/package.json +39 -13
- package/bundle/references/adapters/cursor.md +0 -214
- package/bundle/references/adapters/opencode.md +0 -530
- package/bundle/references/adapters/package-manifest-interface-model.yaml +0 -337
- package/bundle/references/adapters/runtime-adapter-characterization.md +0 -79
- package/bundle/references/adapters/runtime-adapter-interface-model.yaml +0 -200
- package/bundle/references/adapters/runtime-adapter-registry.yaml +0 -554
- package/bundle/references/adapters/runtime-feature-parity.md +0 -189
- package/bundle/references/analysis/benchmark.md +0 -267
- package/bundle/references/analysis/startup-measurement-contract.yaml +0 -424
- package/bundle/references/cli/agent-ready-state-contract.yaml +0 -953
- package/bundle/references/cli/audience-namespace-cli-migration.yaml +0 -369
- package/bundle/references/cli/bundle-skill-vocabulary.yaml +0 -250
- package/bundle/references/cli/capability-tool-classification.yaml +0 -53
- package/bundle/references/cli/coexistence-probe.yaml +0 -13
- package/bundle/references/cli/parity-expected-actual-template.md +0 -30
- package/bundle/references/cli/routing-execution-vocabulary.yaml +0 -281
- package/bundle/references/cli/single-name-protocol.yaml +0 -42
- package/bundle/references/cli/upgrade-repair-wording.md +0 -45
- package/bundle/references/cli/v3-handoff-manifest.schema.yaml +0 -98
- package/bundle/references/meta/documentation-inventory.md +0 -49
- package/bundle/skills/agentera/.claude-plugin/plugin.json +0 -27
- package/bundle/skills/agentera/agents/audit.toml +0 -6
- package/bundle/skills/agentera/agents/build.toml +0 -6
- package/bundle/skills/agentera/agents/design.toml +0 -6
- package/bundle/skills/agentera/agents/discuss.toml +0 -6
- package/bundle/skills/agentera/agents/document.toml +0 -6
- package/bundle/skills/agentera/agents/optimize.toml +0 -6
- package/bundle/skills/agentera/agents/orchestrate.toml +0 -6
- package/bundle/skills/agentera/agents/plan.toml +0 -6
- package/bundle/skills/agentera/agents/profile.toml +0 -6
- package/bundle/skills/agentera/agents/research.toml +0 -6
- package/bundle/skills/agentera/agents/status.toml +0 -6
- package/bundle/skills/agentera/agents/vision.toml +0 -6
- package/bundle/skills/agentera/references/contract.md +0 -1048
- package/dist/analytics/extractCorpus/cli.js.map +0 -1
- package/dist/analytics/extractCorpus/copilotSessions.js.map +0 -1
- package/dist/analytics/extractCorpus/core.js.map +0 -1
- package/dist/analytics/extractCorpus/corpus.js.map +0 -1
- package/dist/analytics/extractCorpus/coverageAudit.js.map +0 -1
- package/dist/analytics/extractCorpus/cursorSessions.js.map +0 -1
- package/dist/analytics/extractCorpus/extractCorpusParity.js.map +0 -1
- package/dist/analytics/extractCorpus/filesystemSources.js.map +0 -1
- package/dist/analytics/extractCorpus/index.js.map +0 -1
- package/dist/analytics/extractCorpus/jsonlSessions.js.map +0 -1
- package/dist/analytics/extractCorpus/sqliteCaps.js.map +0 -1
- package/dist/analytics/extractCorpus/sqliteSessions.js.map +0 -1
- package/dist/analytics/extractCorpus.js.map +0 -1
- package/dist/analytics/usageStats.js.map +0 -1
- package/dist/bin/agentera.js.map +0 -1
- package/dist/capabilities/audit/instructions.js.map +0 -1
- package/dist/capabilities/build/instructions.js.map +0 -1
- package/dist/capabilities/design/instructions.js.map +0 -1
- package/dist/capabilities/discuss/instructions.js.map +0 -1
- package/dist/capabilities/document/instructions.js.map +0 -1
- package/dist/capabilities/index.js.map +0 -1
- package/dist/capabilities/optimize/instructions.js.map +0 -1
- package/dist/capabilities/orchestrate/instructions.js.map +0 -1
- package/dist/capabilities/plan/instructions.js.map +0 -1
- package/dist/capabilities/profile/instructions.js.map +0 -1
- package/dist/capabilities/research/instructions.js.map +0 -1
- package/dist/capabilities/status/instructions.js.map +0 -1
- package/dist/capabilities/vision/instructions.js.map +0 -1
- package/dist/cli/appContext.js.map +0 -1
- package/dist/cli/argvalidate.js.map +0 -1
- package/dist/cli/capabilityContext/benchmark.js.map +0 -1
- package/dist/cli/capabilityContext/bespoke.js.map +0 -1
- package/dist/cli/capabilityContext/build.js.map +0 -1
- package/dist/cli/capabilityContext/closeout.js.map +0 -1
- package/dist/cli/capabilityContext/contract.js.map +0 -1
- package/dist/cli/capabilityContext/evidence.js.map +0 -1
- package/dist/cli/capabilityContext/index.js.map +0 -1
- package/dist/cli/capabilityContext/orchestration.js.map +0 -1
- package/dist/cli/capabilityContext/planState.js.map +0 -1
- package/dist/cli/capabilityContext/progress.js.map +0 -1
- package/dist/cli/capabilityContext/shared.js.map +0 -1
- package/dist/cli/capabilityContext/slim.js.map +0 -1
- package/dist/cli/capabilityContext/startup.js.map +0 -1
- package/dist/cli/capabilityContext/types.js.map +0 -1
- package/dist/cli/capabilityContext.js.map +0 -1
- package/dist/cli/commands/appHome.js.map +0 -1
- package/dist/cli/commands/capability.js.map +0 -1
- package/dist/cli/commands/compact.js.map +0 -1
- package/dist/cli/commands/doctor.js.map +0 -1
- package/dist/cli/commands/lint.js.map +0 -1
- package/dist/cli/commands/prime/bundleStatus.js.map +0 -1
- package/dist/cli/commands/prime/collectOrientationState.js.map +0 -1
- package/dist/cli/commands/prime/orientationOutput.js.map +0 -1
- package/dist/cli/commands/prime/types.js.map +0 -1
- package/dist/cli/commands/prime/v1Migration.js +0 -39
- package/dist/cli/commands/prime/v1Migration.js.map +0 -1
- package/dist/cli/commands/prime.js.map +0 -1
- package/dist/cli/commands/query.js.map +0 -1
- package/dist/cli/commands/report.js.map +0 -1
- package/dist/cli/commands/schema.js.map +0 -1
- package/dist/cli/commands/state/decisions.js.map +0 -1
- package/dist/cli/commands/state/docs.js.map +0 -1
- package/dist/cli/commands/state/experiments.js.map +0 -1
- package/dist/cli/commands/state/health.js.map +0 -1
- package/dist/cli/commands/state/index.js.map +0 -1
- package/dist/cli/commands/state/objective.js.map +0 -1
- package/dist/cli/commands/state/plan.js.map +0 -1
- package/dist/cli/commands/state/progress.js.map +0 -1
- package/dist/cli/commands/state/shared.js.map +0 -1
- package/dist/cli/commands/state/todo.js.map +0 -1
- package/dist/cli/commands/upgrade.js.map +0 -1
- package/dist/cli/commands/validate.js.map +0 -1
- package/dist/cli/commands/verify.js.map +0 -1
- package/dist/cli/contracts/bundleStatus.js.map +0 -1
- package/dist/cli/contracts/orientationState.js.map +0 -1
- package/dist/cli/dispatch/argvParser.js.map +0 -1
- package/dist/cli/dispatch/check.js.map +0 -1
- package/dist/cli/dispatch/commands.js.map +0 -1
- package/dist/cli/dispatch/index.js.map +0 -1
- package/dist/cli/dispatch/lifecycle.js.map +0 -1
- package/dist/cli/dispatch/prime.js.map +0 -1
- package/dist/cli/dispatch/shared.js.map +0 -1
- package/dist/cli/dispatch/state.js.map +0 -1
- package/dist/cli/dispatch.js.map +0 -1
- package/dist/cli/errors.js.map +0 -1
- package/dist/cli/help.js.map +0 -1
- package/dist/cli/orientation/attention.js.map +0 -1
- package/dist/cli/orientation/corpusCoverage.js.map +0 -1
- package/dist/cli/orientation.js.map +0 -1
- package/dist/cli/prime-blob.js.map +0 -1
- package/dist/cli/startupCompletenessContract.js.map +0 -1
- package/dist/cli/stateQuery.js.map +0 -1
- package/dist/cli/structured.js.map +0 -1
- package/dist/cli/todoMarkdown.js.map +0 -1
- package/dist/cli/todoSeverity.js.map +0 -1
- package/dist/core/difflib.js.map +0 -1
- package/dist/core/envPaths.js.map +0 -1
- package/dist/core/jsonValue.js.map +0 -1
- package/dist/core/paths.js.map +0 -1
- package/dist/core/pyjson.js.map +0 -1
- package/dist/core/sourceRoot.js.map +0 -1
- package/dist/core/toml.js.map +0 -1
- package/dist/core/yaml.js.map +0 -1
- package/dist/eval/evalSkills.js.map +0 -1
- package/dist/eval/semanticEval.js.map +0 -1
- package/dist/eval/semanticFixtures.js.map +0 -1
- package/dist/hooks/common.js.map +0 -1
- package/dist/hooks/compaction/apply.js.map +0 -1
- package/dist/hooks/compaction/dryRun.js.map +0 -1
- package/dist/hooks/compaction/index.js.map +0 -1
- package/dist/hooks/compaction/parse.js.map +0 -1
- package/dist/hooks/compaction/retention.js.map +0 -1
- package/dist/hooks/compaction/status.js.map +0 -1
- package/dist/hooks/compaction/types.js.map +0 -1
- package/dist/hooks/cursorPreToolUse.js +0 -19
- package/dist/hooks/cursorPreToolUse.js.map +0 -1
- package/dist/hooks/cursorSessionStart.js +0 -79
- package/dist/hooks/cursorSessionStart.js.map +0 -1
- package/dist/hooks/sessionStart.js +0 -216
- package/dist/hooks/sessionStart.js.map +0 -1
- package/dist/hooks/sessionStop.js +0 -206
- package/dist/hooks/sessionStop.js.map +0 -1
- package/dist/hooks/validateArtifact/agentFacing.js.map +0 -1
- package/dist/hooks/validateArtifact/index.js.map +0 -1
- package/dist/hooks/validateArtifact/markdown.js.map +0 -1
- package/dist/hooks/validateArtifact/runtime.js +0 -86
- package/dist/hooks/validateArtifact/runtime.js.map +0 -1
- package/dist/hooks/validateArtifact/schema.js.map +0 -1
- package/dist/hooks/validateArtifact/traversal.js.map +0 -1
- package/dist/hooks/validateArtifact/violations.js.map +0 -1
- package/dist/migrate/v2HandoffManifest.js.map +0 -1
- package/dist/registries/artifactProtocolIds.js.map +0 -1
- package/dist/registries/artifactRegistry.js.map +0 -1
- package/dist/registries/capabilityContract.js.map +0 -1
- package/dist/registries/evaluatorHandoffContract.js.map +0 -1
- package/dist/registries/packageRegistry.js.map +0 -1
- package/dist/registries/runtimeAdapterRegistry.js +0 -316
- package/dist/registries/runtimeAdapterRegistry.js.map +0 -1
- package/dist/registries/triggerLoader.js.map +0 -1
- package/dist/release/releaseMetadata.js.map +0 -1
- package/dist/setup/codex/agents.js +0 -96
- package/dist/setup/codex/agents.js.map +0 -1
- package/dist/setup/codex/cli.js +0 -161
- package/dist/setup/codex/cli.js.map +0 -1
- package/dist/setup/codex/configToml.js +0 -639
- package/dist/setup/codex/configToml.js.map +0 -1
- package/dist/setup/codex/constants.js +0 -29
- package/dist/setup/codex/constants.js.map +0 -1
- package/dist/setup/codex/installRoot.js +0 -64
- package/dist/setup/codex/installRoot.js.map +0 -1
- package/dist/setup/codex/state.js +0 -270
- package/dist/setup/codex/state.js.map +0 -1
- package/dist/setup/codex.js +0 -12
- package/dist/setup/codex.js.map +0 -1
- package/dist/setup/copilot.js +0 -227
- package/dist/setup/copilot.js.map +0 -1
- package/dist/setup/cursor.js +0 -129
- package/dist/setup/cursor.js.map +0 -1
- package/dist/setup/cursorSurfaces.js +0 -67
- package/dist/setup/cursorSurfaces.js.map +0 -1
- package/dist/setup/doctor/core.js +0 -300
- package/dist/setup/doctor/core.js.map +0 -1
- package/dist/setup/doctor/diagnostics.js +0 -240
- package/dist/setup/doctor/diagnostics.js.map +0 -1
- package/dist/setup/doctor/opencode.js +0 -313
- package/dist/setup/doctor/opencode.js.map +0 -1
- package/dist/setup/doctor/report.js +0 -425
- package/dist/setup/doctor/report.js.map +0 -1
- package/dist/setup/doctor.js +0 -10
- package/dist/setup/doctor.js.map +0 -1
- package/dist/setup/opencode.js.map +0 -1
- package/dist/setup/smokeChecks.js.map +0 -1
- package/dist/state/installRoot.js.map +0 -1
- package/dist/state/startupAnalysis/benchmark.js.map +0 -1
- package/dist/state/startupAnalysis/contract.js.map +0 -1
- package/dist/state/startupAnalysis/helpers.js.map +0 -1
- package/dist/state/startupAnalysis/index.js.map +0 -1
- package/dist/state/startupAnalysis/metrics.js.map +0 -1
- package/dist/state/startupAnalysis/records.js.map +0 -1
- package/dist/state/startupAnalysis/report.js.map +0 -1
- package/dist/state/startupAnalysis/threshold.js.map +0 -1
- package/dist/state/startupAnalysis.js.map +0 -1
- package/dist/upgrade/appContentRefresh.js.map +0 -1
- package/dist/upgrade/appModel.js.map +0 -1
- package/dist/upgrade/bundleEvidence.js.map +0 -1
- package/dist/upgrade/channels.js.map +0 -1
- package/dist/upgrade/coexistenceProbe.js +0 -107
- package/dist/upgrade/coexistenceProbe.js.map +0 -1
- package/dist/upgrade/compatibility.js.map +0 -1
- package/dist/upgrade/doctor.js.map +0 -1
- package/dist/upgrade/doctorClassifier.js.map +0 -1
- package/dist/upgrade/installedHooksRetirement.js.map +0 -1
- package/dist/upgrade/legacyAgentCleanup.js.map +0 -1
- package/dist/upgrade/migrateArtifactsV1ToV2.js +0 -570
- package/dist/upgrade/migrateArtifactsV1ToV2.js.map +0 -1
- package/dist/upgrade/migrateArtifactsV2ToV3.js.map +0 -1
- package/dist/upgrade/nextMajorDoctor.js.map +0 -1
- package/dist/upgrade/npxPlatformStatus.js.map +0 -1
- package/dist/upgrade/projectIntegration.js.map +0 -1
- package/dist/upgrade/projectIntegrationDecision.js.map +0 -1
- package/dist/upgrade/runtimeMigration.js.map +0 -1
- package/dist/upgrade/upgradeCommands.js.map +0 -1
- package/dist/upgrade/upgradeOrchestrator.js.map +0 -1
- package/dist/upgrade/v3CapabilitySurface.js.map +0 -1
- package/dist/upgrade/versionResolution.js.map +0 -1
- package/dist/validate/appHomeContract.js.map +0 -1
- package/dist/validate/capability.js.map +0 -1
- package/dist/validate/crossCapability.js.map +0 -1
- package/dist/validate/lifecycleAdapters/legacyPythonParity.js +0 -93
- package/dist/validate/lifecycleAdapters/legacyPythonParity.js.map +0 -1
- package/dist/validate/lifecycleAdapters/nodeFormChecks.js +0 -488
- package/dist/validate/lifecycleAdapters/nodeFormChecks.js.map +0 -1
- package/dist/validate/lifecycleAdapters/shared.js +0 -198
- package/dist/validate/lifecycleAdapters/shared.js.map +0 -1
- package/dist/validate/lifecycleAdapters.js +0 -62
- package/dist/validate/lifecycleAdapters.js.map +0 -1
- package/dist/validate/selfAudit.js.map +0 -1
- package/dist/validate/vocabularyAuthority.js.map +0 -1
|
@@ -0,0 +1,820 @@
|
|
|
1
|
+
import { loadYamlMappingFile } from "../core/yaml.js";
|
|
2
|
+
import { glossaryCandidateContractsAuthorityPath } from "./glossaryCandidateContractPaths.js";
|
|
3
|
+
import { canonicalGlossaryJson, compareGlossaryUnicodeStrings, glossaryCandidateRevision, glossaryCanonicalSha256, isGlossaryCandidateScope, stableGlossaryTermIdentity, } from "./glossaryTermIdentity.js";
|
|
4
|
+
import { glossaryEvidenceSetDigest, PERSONAL_REVIEW_DISPOSITIONS, } from "./glossaryMiningAuthority.js";
|
|
5
|
+
import { GLOSSARY_ADMISSION_OUTCOMES, GLOSSARY_ADMISSION_REASONS, hasGlossaryAdmissionReasonCodesByOutcome, validateGlossaryCandidateDecisionAuthority, } from "./glossaryCandidateDecisionAuthority.js";
|
|
6
|
+
export { GLOSSARY_ADMISSION_REASONS } from "./glossaryCandidateDecisionAuthority.js";
|
|
7
|
+
export { glossaryCandidateContractsAuthorityPath } from "./glossaryCandidateContractPaths.js";
|
|
8
|
+
const CANDIDATE_CONTRACTS_SCHEMA = "agentera.personalGlossaryCandidateContracts.v1";
|
|
9
|
+
const CANDIDATE_CONTRACTS_AUTHORITY = "candidate_contracts";
|
|
10
|
+
const LAYERS = [
|
|
11
|
+
"evidence_capsule",
|
|
12
|
+
"host_classification_receipt",
|
|
13
|
+
"cli_decision",
|
|
14
|
+
"review_record",
|
|
15
|
+
"publication_result",
|
|
16
|
+
];
|
|
17
|
+
const LAYER_OWNERS = {
|
|
18
|
+
evidence_capsule: "deterministic_discovery_projection",
|
|
19
|
+
host_classification_receipt: "semantic_host_classification",
|
|
20
|
+
cli_decision: "deterministic_cli_admission_validation",
|
|
21
|
+
review_record: "user_local_review_lifecycle",
|
|
22
|
+
publication_result: "personal_profile_publication",
|
|
23
|
+
};
|
|
24
|
+
const LAYER_SCHEMAS = {
|
|
25
|
+
evidence_capsule: "agentera.personalGlossaryCandidateCapsule.v1",
|
|
26
|
+
host_classification_receipt: "agentera.personalGlossaryHostClassificationReceipt.v1",
|
|
27
|
+
cli_decision: "agentera.personalGlossaryAdmissionDecision.v1",
|
|
28
|
+
review_record: "agentera.personalGlossaryReviewRecord.v1",
|
|
29
|
+
publication_result: "agentera.personalGlossaryPublicationResult.v1",
|
|
30
|
+
};
|
|
31
|
+
const BODY_DIGEST_FIELDS = {
|
|
32
|
+
evidence_capsule: "capsule_sha256",
|
|
33
|
+
host_classification_receipt: "receipt_sha256",
|
|
34
|
+
cli_decision: "decision_sha256",
|
|
35
|
+
review_record: "record_sha256",
|
|
36
|
+
publication_result: "result_sha256",
|
|
37
|
+
};
|
|
38
|
+
const LAYER_REQUIRED_FIELDS = {
|
|
39
|
+
evidence_capsule: [
|
|
40
|
+
"schema_version", "owner", "candidate_id", "candidate_revision", "term", "meaning", "scope",
|
|
41
|
+
"provenance_kind", "evidence", "evidence_complete", "evidence_set_sha256", "policy_version",
|
|
42
|
+
"generation", "capsule_sha256",
|
|
43
|
+
],
|
|
44
|
+
host_classification_receipt: [
|
|
45
|
+
"schema_version", "owner", "candidate_id", "candidate_revision", "candidate_capsule_sha256",
|
|
46
|
+
"candidate_projection_sha256", "generation", "policy_version", "classification", "semantic_fingerprint", "receipt_sha256",
|
|
47
|
+
],
|
|
48
|
+
cli_decision: [
|
|
49
|
+
"schema_version", "owner", "candidate_id", "candidate_revision", "candidate_capsule_sha256",
|
|
50
|
+
"candidate_projection_sha256", "host_receipt_sha256", "classification_contract_version", "semantic_fingerprint",
|
|
51
|
+
"generation", "policy_version", "outcome", "reason", "decision_sha256",
|
|
52
|
+
],
|
|
53
|
+
review_record: [
|
|
54
|
+
"schema_version", "owner", "candidate_id", "candidate_revision", "candidate_capsule_sha256",
|
|
55
|
+
"host_receipt_sha256", "cli_decision_sha256", "semantic_fingerprint", "generation", "policy_version",
|
|
56
|
+
"disposition", "corrected_meaning", "corrected_scope", "disposed_at", "expires_at", "record_sha256",
|
|
57
|
+
],
|
|
58
|
+
publication_result: [
|
|
59
|
+
"schema_version", "owner", "candidate_id", "candidate_revision", "candidate_capsule_sha256",
|
|
60
|
+
"decision_sha256", "review_record_sha256", "generation", "policy_version", "status",
|
|
61
|
+
"profile_section_sha256", "published_at", "result_sha256",
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
const LAYER_BINDING_FIELDS = {
|
|
65
|
+
evidence_capsule: ["candidate_id", "candidate_revision", "generation", "policy_version"],
|
|
66
|
+
host_classification_receipt: ["candidate_id", "candidate_revision", "candidate_capsule_sha256", "candidate_projection_sha256", "generation", "policy_version"],
|
|
67
|
+
cli_decision: ["candidate_id", "candidate_revision", "candidate_capsule_sha256", "candidate_projection_sha256", "host_receipt_sha256", "classification_contract_version", "semantic_fingerprint", "generation", "policy_version"],
|
|
68
|
+
review_record: ["candidate_id", "candidate_revision", "candidate_capsule_sha256", "host_receipt_sha256", "cli_decision_sha256", "semantic_fingerprint", "generation", "policy_version"],
|
|
69
|
+
publication_result: ["candidate_id", "candidate_revision", "candidate_capsule_sha256", "decision_sha256", "generation", "policy_version"],
|
|
70
|
+
};
|
|
71
|
+
const HOST_CLASSIFICATION_FIELDS = [
|
|
72
|
+
"term",
|
|
73
|
+
"meaning",
|
|
74
|
+
"scope",
|
|
75
|
+
"permanence",
|
|
76
|
+
"consistency",
|
|
77
|
+
"confidence",
|
|
78
|
+
];
|
|
79
|
+
const ADMISSION_OUTCOMES = GLOSSARY_ADMISSION_OUTCOMES;
|
|
80
|
+
const CONSISTENCY_VALUES = ["consistent", "inconsistent", "uncertain"];
|
|
81
|
+
function mapping(value) {
|
|
82
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
83
|
+
? value
|
|
84
|
+
: null;
|
|
85
|
+
}
|
|
86
|
+
function strings(value) {
|
|
87
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : [];
|
|
88
|
+
}
|
|
89
|
+
function nonEmpty(value) {
|
|
90
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
91
|
+
}
|
|
92
|
+
function digest(value) {
|
|
93
|
+
return typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
|
|
94
|
+
}
|
|
95
|
+
function exactStrings(actual, expected) {
|
|
96
|
+
return JSON.stringify(strings(actual)) === JSON.stringify(expected);
|
|
97
|
+
}
|
|
98
|
+
function exactFields(value, fields, label) {
|
|
99
|
+
const errors = [];
|
|
100
|
+
const missing = fields.filter((field) => !(field in value));
|
|
101
|
+
const extra = Object.keys(value).filter((field) => !fields.includes(field));
|
|
102
|
+
if (missing.length > 0)
|
|
103
|
+
errors.push(`${label} is missing fields: ${missing.join(", ")}`);
|
|
104
|
+
if (extra.length > 0)
|
|
105
|
+
errors.push(`${label} contains fields outside its contract: ${extra.join(", ")}`);
|
|
106
|
+
return errors;
|
|
107
|
+
}
|
|
108
|
+
function compareRecords(left, right) {
|
|
109
|
+
return compareGlossaryUnicodeStrings(canonicalGlossaryJson(left), canonicalGlossaryJson(right));
|
|
110
|
+
}
|
|
111
|
+
function sortEvidence(evidence) {
|
|
112
|
+
return evidence.map((item) => ({ ...item })).sort(compareRecords);
|
|
113
|
+
}
|
|
114
|
+
function bodyWithoutDigest(value, field) {
|
|
115
|
+
const body = { ...value };
|
|
116
|
+
delete body[field];
|
|
117
|
+
return body;
|
|
118
|
+
}
|
|
119
|
+
function timestamp(value) {
|
|
120
|
+
if (typeof value !== "string")
|
|
121
|
+
return false;
|
|
122
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value))
|
|
123
|
+
return false;
|
|
124
|
+
return !Number.isNaN(Date.parse(value));
|
|
125
|
+
}
|
|
126
|
+
function utf8Within(value, maxBytes) {
|
|
127
|
+
return nonEmpty(value) && Buffer.byteLength(value, "utf8") <= maxBytes;
|
|
128
|
+
}
|
|
129
|
+
function loadAuthority(pathname) {
|
|
130
|
+
return loadYamlMappingFile(pathname);
|
|
131
|
+
}
|
|
132
|
+
function loadCandidateAuthority(pathname) {
|
|
133
|
+
try {
|
|
134
|
+
const authority = loadAuthority(pathname);
|
|
135
|
+
const candidate = mapping(authority[CANDIDATE_CONTRACTS_AUTHORITY]);
|
|
136
|
+
return candidate ? { authority, candidate } : null;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function loadedContract(pathname) {
|
|
143
|
+
const loaded = loadCandidateAuthority(pathname);
|
|
144
|
+
if (!loaded) {
|
|
145
|
+
return {
|
|
146
|
+
authority: {},
|
|
147
|
+
candidate: {},
|
|
148
|
+
errors: ["candidate_contracts authority could not be loaded"],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return { ...loaded, errors: [] };
|
|
152
|
+
}
|
|
153
|
+
function contractLayer(value, name) {
|
|
154
|
+
const candidate = mapping(value);
|
|
155
|
+
return mapping(candidate?.layers)?.[name];
|
|
156
|
+
}
|
|
157
|
+
function validateLayerEnvelope(value, layerAuthority, name) {
|
|
158
|
+
const required = strings(layerAuthority.required_fields);
|
|
159
|
+
const errors = exactFields(value, required, `candidate_contracts.layers.${name}`);
|
|
160
|
+
if (layerAuthority.additional_fields !== "forbidden") {
|
|
161
|
+
errors.push(`candidate_contracts.layers.${name}.additional_fields must be forbidden`);
|
|
162
|
+
}
|
|
163
|
+
if (layerAuthority.owner !== LAYER_OWNERS[name]) {
|
|
164
|
+
errors.push(`candidate_contracts.layers.${name}.owner is invalid`);
|
|
165
|
+
}
|
|
166
|
+
if (layerAuthority.schema_version !== LAYER_SCHEMAS[name]) {
|
|
167
|
+
errors.push(`candidate_contracts.layers.${name}.schema_version is invalid`);
|
|
168
|
+
}
|
|
169
|
+
return errors;
|
|
170
|
+
}
|
|
171
|
+
function candidateBounds(candidate) {
|
|
172
|
+
return mapping(candidate.bounds) ?? {};
|
|
173
|
+
}
|
|
174
|
+
function validateBoundedIdentityFields(value, candidate, label) {
|
|
175
|
+
const bounds = candidateBounds(candidate);
|
|
176
|
+
const errors = [];
|
|
177
|
+
const identityMax = Number(bounds.binding_max_utf8_bytes ?? 0);
|
|
178
|
+
const meaningMax = Number(bounds.meaning_max_utf8_bytes ?? 0);
|
|
179
|
+
const termMax = Number(bounds.term_max_utf8_bytes ?? 0);
|
|
180
|
+
for (const field of ["candidate_id", "candidate_revision", "generation", "policy_version"]) {
|
|
181
|
+
if (!utf8Within(value[field], field.startsWith("candidate_") ? 64 : identityMax)) {
|
|
182
|
+
errors.push(`${label}.${field} is outside its binding bound`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (!utf8Within(value.term, termMax))
|
|
186
|
+
errors.push(`${label}.term is outside its bound`);
|
|
187
|
+
if (!utf8Within(value.meaning, meaningMax))
|
|
188
|
+
errors.push(`${label}.meaning is outside its bound`);
|
|
189
|
+
return errors;
|
|
190
|
+
}
|
|
191
|
+
function validateSharedClassification(classification, authority, candidate, label) {
|
|
192
|
+
const classificationAuthority = mapping(contractLayer(candidate, "host_classification_receipt")?.classification);
|
|
193
|
+
const fields = strings(classificationAuthority?.fields);
|
|
194
|
+
const errors = exactFields(classification, fields, label);
|
|
195
|
+
const primitive = mapping(authority.shared_primitive);
|
|
196
|
+
const permanence = mapping(mapping(primitive?.fields)?.permanence);
|
|
197
|
+
const consistencyValues = strings(classificationAuthority?.consistency_values);
|
|
198
|
+
const bounds = candidateBounds(candidate);
|
|
199
|
+
if (!utf8Within(classification.term, Number(bounds.term_max_utf8_bytes ?? 0))) {
|
|
200
|
+
errors.push(`${label}.term is outside its bound`);
|
|
201
|
+
}
|
|
202
|
+
if (!utf8Within(classification.meaning, Number(bounds.meaning_max_utf8_bytes ?? 0))) {
|
|
203
|
+
errors.push(`${label}.meaning is outside its bound`);
|
|
204
|
+
}
|
|
205
|
+
if (!isGlossaryCandidateScope(classification.scope))
|
|
206
|
+
errors.push(`${label}.scope is invalid`);
|
|
207
|
+
if (!strings(permanence?.values).includes(String(classification.permanence))) {
|
|
208
|
+
errors.push(`${label}.permanence is invalid`);
|
|
209
|
+
}
|
|
210
|
+
if (!consistencyValues.includes(String(classification.consistency))) {
|
|
211
|
+
errors.push(`${label}.consistency is invalid`);
|
|
212
|
+
}
|
|
213
|
+
if (!Number.isInteger(classification.confidence) || Number(classification.confidence) < 0 || Number(classification.confidence) > 100) {
|
|
214
|
+
errors.push(`${label}.confidence must be an integer from shared_primitive.fields.confidence`);
|
|
215
|
+
}
|
|
216
|
+
return errors;
|
|
217
|
+
}
|
|
218
|
+
function validateProvenanceEvidence(capsule, authority, candidate) {
|
|
219
|
+
const errors = [];
|
|
220
|
+
const kind = capsule.provenance_kind;
|
|
221
|
+
const allowedKinds = strings(mapping(mapping(authority.ownership_contracts)?.personal)?.allowed_provenance);
|
|
222
|
+
if (!nonEmpty(kind) || !allowedKinds.includes(kind)) {
|
|
223
|
+
errors.push("evidence_capsule.provenance_kind is not an allowed personal provenance variant");
|
|
224
|
+
return errors;
|
|
225
|
+
}
|
|
226
|
+
const variant = mapping(mapping(authority.provenance_variants)?.[kind]);
|
|
227
|
+
if (!variant) {
|
|
228
|
+
errors.push("evidence_capsule.provenance_kind has no provenance variant");
|
|
229
|
+
return errors;
|
|
230
|
+
}
|
|
231
|
+
const evidence = capsule.evidence;
|
|
232
|
+
if (!Array.isArray(evidence)) {
|
|
233
|
+
errors.push("evidence_capsule.evidence must be a list");
|
|
234
|
+
return errors;
|
|
235
|
+
}
|
|
236
|
+
const maxRecords = Number(candidateBounds(candidate).evidence_records_max ?? 0);
|
|
237
|
+
if (evidence.length === 0 || evidence.length > maxRecords) {
|
|
238
|
+
errors.push("evidence_capsule.evidence is outside its record bound");
|
|
239
|
+
}
|
|
240
|
+
const required = strings(variant.required_evidence_fields);
|
|
241
|
+
const expectedCount = variant.evidence_count === "variable" ? null : Number(variant.evidence_count);
|
|
242
|
+
const minimum = Number(variant.minimum_evidence_count ?? expectedCount ?? 0);
|
|
243
|
+
if ((expectedCount !== null && evidence.length !== expectedCount) || (expectedCount === null && evidence.length < minimum)) {
|
|
244
|
+
errors.push("evidence_capsule.evidence count does not satisfy its provenance variant");
|
|
245
|
+
}
|
|
246
|
+
const allowedSignals = strings(variant.allowed_signal_types);
|
|
247
|
+
const allowedSources = strings(variant.allowed_source_kinds);
|
|
248
|
+
const allowedAuthors = strings(variant.allowed_author_classes);
|
|
249
|
+
const distinctness = mapping(variant.distinctness);
|
|
250
|
+
for (const [index, item] of evidence.entries()) {
|
|
251
|
+
const itemMapping = mapping(item);
|
|
252
|
+
if (!itemMapping) {
|
|
253
|
+
errors.push(`evidence_capsule.evidence[${index}] must be an object`);
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
errors.push(...exactFields(itemMapping, required, `evidence_capsule.evidence[${index}]`));
|
|
257
|
+
for (const field of required) {
|
|
258
|
+
if (!nonEmpty(itemMapping[field]))
|
|
259
|
+
errors.push(`evidence_capsule.evidence[${index}].${field} must be non-empty`);
|
|
260
|
+
}
|
|
261
|
+
if ("signal_type" in itemMapping && !allowedSignals.includes(String(itemMapping.signal_type))) {
|
|
262
|
+
errors.push(`evidence_capsule.evidence[${index}].signal_type is invalid`);
|
|
263
|
+
}
|
|
264
|
+
if ("source_kind" in itemMapping && !allowedSources.includes(String(itemMapping.source_kind))) {
|
|
265
|
+
errors.push(`evidence_capsule.evidence[${index}].source_kind is invalid`);
|
|
266
|
+
}
|
|
267
|
+
if ("author_class" in itemMapping && !allowedAuthors.includes(String(itemMapping.author_class))) {
|
|
268
|
+
errors.push(`evidence_capsule.evidence[${index}].author_class is invalid`);
|
|
269
|
+
}
|
|
270
|
+
if ("content_fingerprint" in itemMapping && !digest(itemMapping.content_fingerprint)) {
|
|
271
|
+
errors.push(`evidence_capsule.evidence[${index}].content_fingerprint must be lowercase SHA-256`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
const sorted = sortEvidence(evidence);
|
|
275
|
+
if (JSON.stringify(evidence) !== JSON.stringify(sorted)) {
|
|
276
|
+
errors.push("evidence_capsule.evidence must be in canonical evidence order");
|
|
277
|
+
}
|
|
278
|
+
for (const [field, requiredDistinct] of Object.entries(distinctness ?? {})) {
|
|
279
|
+
const evidenceField = field.endsWith("s") ? field.slice(0, -1) : field;
|
|
280
|
+
const values = evidence.map((item) => mapping(item)?.[evidenceField]);
|
|
281
|
+
if (new Set(values).size < Number(requiredDistinct)) {
|
|
282
|
+
errors.push(`evidence_capsule.evidence requires ${requiredDistinct} distinct ${evidenceField}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (capsule.evidence_complete !== true)
|
|
286
|
+
errors.push("evidence_capsule.evidence_complete must be true");
|
|
287
|
+
if (!digest(capsule.evidence_set_sha256)) {
|
|
288
|
+
errors.push("evidence_capsule.evidence_set_sha256 must be lowercase SHA-256");
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
try {
|
|
292
|
+
const anchors = evidence.map((item) => String(mapping(item)?.evidence_anchor));
|
|
293
|
+
if (capsule.evidence_set_sha256 !== glossaryEvidenceSetDigest(String(capsule.generation), anchors)) {
|
|
294
|
+
errors.push("evidence_capsule.evidence_set_sha256 does not match generation and anchors");
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
errors.push("evidence_capsule.evidence_set_sha256 cannot be computed from evidence anchors");
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return errors;
|
|
302
|
+
}
|
|
303
|
+
function validateCapsuleIdentity(capsule) {
|
|
304
|
+
const errors = [];
|
|
305
|
+
if (!digest(capsule.candidate_id))
|
|
306
|
+
errors.push("evidence_capsule.candidate_id must be lowercase SHA-256");
|
|
307
|
+
if (!digest(capsule.candidate_revision))
|
|
308
|
+
errors.push("evidence_capsule.candidate_revision must be lowercase SHA-256");
|
|
309
|
+
if (!digest(capsule.capsule_sha256))
|
|
310
|
+
errors.push("evidence_capsule.capsule_sha256 must be lowercase SHA-256");
|
|
311
|
+
if (nonEmpty(capsule.term) && stableGlossaryTermIdentity(capsule.term) !== capsule.candidate_id) {
|
|
312
|
+
errors.push("evidence_capsule.candidate_id does not match stable term identity");
|
|
313
|
+
}
|
|
314
|
+
return errors;
|
|
315
|
+
}
|
|
316
|
+
export function validateGlossaryEvidenceCapsule(capsule, pathname = glossaryCandidateContractsAuthorityPath()) {
|
|
317
|
+
const loaded = loadedContract(pathname);
|
|
318
|
+
if (loaded.errors.length > 0)
|
|
319
|
+
return loaded.errors;
|
|
320
|
+
const layerAuthority = contractLayer(loaded.candidate, "evidence_capsule");
|
|
321
|
+
if (!layerAuthority)
|
|
322
|
+
return ["candidate_contracts.layers.evidence_capsule is missing"];
|
|
323
|
+
const errors = validateLayerEnvelope(capsule, layerAuthority, "evidence_capsule");
|
|
324
|
+
errors.push(...validateBoundedIdentityFields(capsule, loaded.candidate, "evidence_capsule"));
|
|
325
|
+
errors.push(...validateCapsuleIdentity(capsule));
|
|
326
|
+
if (capsule.schema_version !== LAYER_SCHEMAS.evidence_capsule)
|
|
327
|
+
errors.push("evidence_capsule.schema_version is invalid");
|
|
328
|
+
if (capsule.owner !== LAYER_OWNERS.evidence_capsule)
|
|
329
|
+
errors.push("evidence_capsule.owner is invalid");
|
|
330
|
+
if (!isGlossaryCandidateScope(capsule.scope))
|
|
331
|
+
errors.push("evidence_capsule.scope is invalid");
|
|
332
|
+
errors.push(...validateProvenanceEvidence(capsule, loaded.authority, loaded.candidate));
|
|
333
|
+
if (digest(capsule.capsule_sha256) && capsule.capsule_sha256 !== glossaryCanonicalSha256(bodyWithoutDigest(capsule, "capsule_sha256"))) {
|
|
334
|
+
errors.push("evidence_capsule.capsule_sha256 does not match canonical capsule bytes");
|
|
335
|
+
}
|
|
336
|
+
if (digest(capsule.candidate_revision) && Array.isArray(capsule.evidence) && isGlossaryCandidateScope(capsule.scope)) {
|
|
337
|
+
try {
|
|
338
|
+
const revision = glossaryCandidateRevision({
|
|
339
|
+
stable_term_identity: String(capsule.candidate_id),
|
|
340
|
+
meaning: String(capsule.meaning),
|
|
341
|
+
scope: capsule.scope,
|
|
342
|
+
evidence: capsule.evidence,
|
|
343
|
+
policy_version: String(capsule.policy_version),
|
|
344
|
+
generation: String(capsule.generation),
|
|
345
|
+
});
|
|
346
|
+
if (revision !== capsule.candidate_revision)
|
|
347
|
+
errors.push("evidence_capsule.candidate_revision is not current-helper output");
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
errors.push("evidence_capsule.candidate_revision cannot be computed from its bound fields");
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return errors;
|
|
354
|
+
}
|
|
355
|
+
export function createGlossaryEvidenceCapsule(input) {
|
|
356
|
+
const evidence = sortEvidence(input.evidence);
|
|
357
|
+
const candidateId = stableGlossaryTermIdentity(input.term);
|
|
358
|
+
const candidateRevision = glossaryCandidateRevision({
|
|
359
|
+
stable_term_identity: candidateId,
|
|
360
|
+
meaning: input.meaning,
|
|
361
|
+
scope: input.scope,
|
|
362
|
+
evidence: evidence,
|
|
363
|
+
policy_version: input.policy_version,
|
|
364
|
+
generation: input.generation,
|
|
365
|
+
});
|
|
366
|
+
const capsule = {
|
|
367
|
+
schema_version: LAYER_SCHEMAS.evidence_capsule,
|
|
368
|
+
owner: LAYER_OWNERS.evidence_capsule,
|
|
369
|
+
candidate_id: candidateId,
|
|
370
|
+
candidate_revision: candidateRevision,
|
|
371
|
+
term: input.term,
|
|
372
|
+
meaning: input.meaning,
|
|
373
|
+
scope: input.scope,
|
|
374
|
+
provenance_kind: input.provenance_kind,
|
|
375
|
+
evidence,
|
|
376
|
+
evidence_complete: true,
|
|
377
|
+
evidence_set_sha256: glossaryEvidenceSetDigest(input.generation, evidence.map((item) => String(item.evidence_anchor))),
|
|
378
|
+
policy_version: input.policy_version,
|
|
379
|
+
generation: input.generation,
|
|
380
|
+
};
|
|
381
|
+
capsule.capsule_sha256 = glossaryCanonicalSha256(capsule);
|
|
382
|
+
const errors = validateGlossaryEvidenceCapsule(capsule);
|
|
383
|
+
if (errors.length > 0)
|
|
384
|
+
throw new TypeError(errors.join("; "));
|
|
385
|
+
return capsule;
|
|
386
|
+
}
|
|
387
|
+
function validateHostBindings(receipt, capsule, layerAuthority, context) {
|
|
388
|
+
const errors = [];
|
|
389
|
+
for (const field of strings(layerAuthority.binding_fields)) {
|
|
390
|
+
const expected = field === "candidate_capsule_sha256"
|
|
391
|
+
? capsule.capsule_sha256
|
|
392
|
+
: field === "candidate_projection_sha256"
|
|
393
|
+
? context.candidateProjectionSha256
|
|
394
|
+
: capsule[field];
|
|
395
|
+
if (receipt[field] !== expected) {
|
|
396
|
+
errors.push(field === "candidate_projection_sha256"
|
|
397
|
+
? "host_classification_receipt.candidate_projection_sha256 does not match the current projection"
|
|
398
|
+
: `host_classification_receipt.${field} does not match the capsule`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return errors;
|
|
402
|
+
}
|
|
403
|
+
export function glossaryHostSemanticFingerprint(classification) {
|
|
404
|
+
return glossaryCanonicalSha256(classification);
|
|
405
|
+
}
|
|
406
|
+
export function validateGlossaryHostClassificationReceipt(receipt, capsule, context, pathname = glossaryCandidateContractsAuthorityPath()) {
|
|
407
|
+
const loaded = loadedContract(pathname);
|
|
408
|
+
if (loaded.errors.length > 0)
|
|
409
|
+
return loaded.errors;
|
|
410
|
+
const errors = validateGlossaryEvidenceCapsule(capsule, pathname);
|
|
411
|
+
const layerAuthority = contractLayer(loaded.candidate, "host_classification_receipt");
|
|
412
|
+
if (!layerAuthority)
|
|
413
|
+
return [...errors, "candidate_contracts.layers.host_classification_receipt is missing"];
|
|
414
|
+
errors.push(...validateLayerEnvelope(receipt, layerAuthority, "host_classification_receipt"));
|
|
415
|
+
if (receipt.schema_version !== LAYER_SCHEMAS.host_classification_receipt) {
|
|
416
|
+
errors.push("host_classification_receipt.schema_version is invalid");
|
|
417
|
+
}
|
|
418
|
+
if (receipt.owner !== LAYER_OWNERS.host_classification_receipt) {
|
|
419
|
+
errors.push("host_classification_receipt.owner is invalid");
|
|
420
|
+
}
|
|
421
|
+
if (!digest(context.candidateProjectionSha256)) {
|
|
422
|
+
errors.push("host_classification_receipt validation requires a current candidate projection SHA-256");
|
|
423
|
+
}
|
|
424
|
+
errors.push(...validateHostBindings(receipt, capsule, layerAuthority, context));
|
|
425
|
+
if (!digest(receipt.candidate_projection_sha256)) {
|
|
426
|
+
errors.push("host_classification_receipt.candidate_projection_sha256 must be lowercase SHA-256");
|
|
427
|
+
}
|
|
428
|
+
const classification = mapping(receipt.classification);
|
|
429
|
+
if (!classification) {
|
|
430
|
+
errors.push("host_classification_receipt.classification must be an object");
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
errors.push(...validateSharedClassification(classification, loaded.authority, loaded.candidate, "host_classification_receipt.classification"));
|
|
434
|
+
if (nonEmpty(classification.term) && stableGlossaryTermIdentity(classification.term) !== capsule.candidate_id) {
|
|
435
|
+
errors.push("host_classification_receipt.classification.term changes stable term identity");
|
|
436
|
+
}
|
|
437
|
+
if (digest(receipt.semantic_fingerprint) && receipt.semantic_fingerprint !== glossaryHostSemanticFingerprint(classification)) {
|
|
438
|
+
errors.push("host_classification_receipt.semantic_fingerprint does not match classification");
|
|
439
|
+
}
|
|
440
|
+
if (!digest(receipt.semantic_fingerprint))
|
|
441
|
+
errors.push("host_classification_receipt.semantic_fingerprint must be lowercase SHA-256");
|
|
442
|
+
}
|
|
443
|
+
const forbidden = strings(layerAuthority.forbidden_fields);
|
|
444
|
+
for (const field of forbidden) {
|
|
445
|
+
if (field in receipt || (classification !== null && field in classification)) {
|
|
446
|
+
errors.push(`host_classification_receipt contains forbidden authority field: ${field}`);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (digest(receipt.receipt_sha256) && receipt.receipt_sha256 !== glossaryCanonicalSha256(bodyWithoutDigest(receipt, "receipt_sha256"))) {
|
|
450
|
+
errors.push("host_classification_receipt.receipt_sha256 does not match canonical receipt bytes");
|
|
451
|
+
}
|
|
452
|
+
if (!digest(receipt.receipt_sha256))
|
|
453
|
+
errors.push("host_classification_receipt.receipt_sha256 must be lowercase SHA-256");
|
|
454
|
+
return errors;
|
|
455
|
+
}
|
|
456
|
+
export function createGlossaryHostClassificationReceipt(input) {
|
|
457
|
+
const receipt = {
|
|
458
|
+
schema_version: LAYER_SCHEMAS.host_classification_receipt,
|
|
459
|
+
owner: LAYER_OWNERS.host_classification_receipt,
|
|
460
|
+
candidate_id: input.capsule.candidate_id,
|
|
461
|
+
candidate_revision: input.capsule.candidate_revision,
|
|
462
|
+
candidate_capsule_sha256: input.capsule.capsule_sha256,
|
|
463
|
+
candidate_projection_sha256: input.candidate_projection_sha256,
|
|
464
|
+
generation: input.capsule.generation,
|
|
465
|
+
policy_version: input.capsule.policy_version,
|
|
466
|
+
classification: { ...input.classification },
|
|
467
|
+
semantic_fingerprint: glossaryHostSemanticFingerprint(input.classification),
|
|
468
|
+
};
|
|
469
|
+
receipt.receipt_sha256 = glossaryCanonicalSha256(receipt);
|
|
470
|
+
const errors = validateGlossaryHostClassificationReceipt(receipt, input.capsule, {
|
|
471
|
+
candidateProjectionSha256: input.candidate_projection_sha256,
|
|
472
|
+
});
|
|
473
|
+
if (errors.length > 0)
|
|
474
|
+
throw new TypeError(errors.join("; "));
|
|
475
|
+
return receipt;
|
|
476
|
+
}
|
|
477
|
+
export function validateGlossaryAdmissionDecision(decision, capsule, receipt, pathname = glossaryCandidateContractsAuthorityPath()) {
|
|
478
|
+
const loaded = loadedContract(pathname);
|
|
479
|
+
if (loaded.errors.length > 0)
|
|
480
|
+
return loaded.errors;
|
|
481
|
+
const errors = [
|
|
482
|
+
...validateGlossaryEvidenceCapsule(capsule, pathname),
|
|
483
|
+
...validateGlossaryHostClassificationReceipt(receipt, capsule, {
|
|
484
|
+
candidateProjectionSha256: String(decision.candidate_projection_sha256),
|
|
485
|
+
}, pathname),
|
|
486
|
+
];
|
|
487
|
+
const layerAuthority = contractLayer(loaded.candidate, "cli_decision");
|
|
488
|
+
if (!layerAuthority)
|
|
489
|
+
return [...errors, "candidate_contracts.layers.cli_decision is missing"];
|
|
490
|
+
errors.push(...validateLayerEnvelope(decision, layerAuthority, "cli_decision"));
|
|
491
|
+
if (decision.schema_version !== LAYER_SCHEMAS.cli_decision) {
|
|
492
|
+
errors.push("cli_decision.schema_version is invalid");
|
|
493
|
+
}
|
|
494
|
+
if (decision.owner !== LAYER_OWNERS.cli_decision) {
|
|
495
|
+
errors.push("cli_decision.owner is invalid");
|
|
496
|
+
}
|
|
497
|
+
if (!exactStrings(layerAuthority.outcomes, ADMISSION_OUTCOMES))
|
|
498
|
+
errors.push("cli_decision.outcomes are not the approved vocabulary");
|
|
499
|
+
if (!ADMISSION_OUTCOMES.includes(decision.outcome)) {
|
|
500
|
+
errors.push("cli_decision.outcome is invalid");
|
|
501
|
+
}
|
|
502
|
+
if (!utf8Within(decision.reason, Number(candidateBounds(loaded.candidate).reason_max_utf8_bytes ?? 0))) {
|
|
503
|
+
errors.push("cli_decision.reason is outside its bound");
|
|
504
|
+
}
|
|
505
|
+
if (!exactStrings(layerAuthority.reason_codes, GLOSSARY_ADMISSION_REASONS))
|
|
506
|
+
errors.push("cli_decision.reason_codes are not the approved vocabulary");
|
|
507
|
+
if (!hasGlossaryAdmissionReasonCodesByOutcome(layerAuthority.reason_codes_by_outcome))
|
|
508
|
+
errors.push("cli_decision.reason_codes_by_outcome is not authoritative");
|
|
509
|
+
if (!strings(mapping(layerAuthority.reason_codes_by_outcome)?.[String(decision.outcome)]).includes(String(decision.reason)))
|
|
510
|
+
errors.push("cli_decision.reason is not allowed for cli_decision.outcome");
|
|
511
|
+
if (decision.candidate_id !== capsule.candidate_id || decision.candidate_revision !== capsule.candidate_revision || decision.candidate_capsule_sha256 !== capsule.capsule_sha256 || decision.generation !== capsule.generation || decision.policy_version !== capsule.policy_version) {
|
|
512
|
+
errors.push("cli_decision bindings do not match the capsule");
|
|
513
|
+
}
|
|
514
|
+
if (decision.candidate_projection_sha256 !== receipt.candidate_projection_sha256) {
|
|
515
|
+
errors.push("cli_decision.candidate_projection_sha256 does not match the host receipt");
|
|
516
|
+
}
|
|
517
|
+
if (decision.host_receipt_sha256 !== receipt.receipt_sha256)
|
|
518
|
+
errors.push("cli_decision.host_receipt_sha256 does not match the host receipt");
|
|
519
|
+
if (decision.classification_contract_version !== receipt.schema_version) {
|
|
520
|
+
errors.push("cli_decision.classification_contract_version does not match the host receipt");
|
|
521
|
+
}
|
|
522
|
+
if (decision.semantic_fingerprint !== receipt.semantic_fingerprint) {
|
|
523
|
+
errors.push("cli_decision.semantic_fingerprint does not match the host receipt");
|
|
524
|
+
}
|
|
525
|
+
const automatic = mapping(layerAuthority.automatic_admission);
|
|
526
|
+
const automaticClassification = mapping(automatic?.required_classification);
|
|
527
|
+
if (decision.outcome === "automatic_admission") {
|
|
528
|
+
if (capsule.provenance_kind !== automatic?.allowed_provenance?.toString().replace("provenance_variants.", "")) {
|
|
529
|
+
errors.push("cli_decision automatic_admission is disabled for inferred provenance");
|
|
530
|
+
}
|
|
531
|
+
const classification = mapping(receipt.classification);
|
|
532
|
+
if (classification?.scope !== automaticClassification?.scope ||
|
|
533
|
+
classification?.consistency !== automaticClassification?.consistency ||
|
|
534
|
+
classification?.term !== capsule.term ||
|
|
535
|
+
classification?.meaning !== capsule.meaning) {
|
|
536
|
+
errors.push("cli_decision automatic_admission requires the exact personal consistent capsule classification");
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
const miningAdmission = mapping(mapping(loaded.authority.personal_mining_authority)?.admission);
|
|
540
|
+
if (miningAdmission?.inferred_automatic_admission !== "disabled")
|
|
541
|
+
errors.push("inferred automatic admission must remain disabled");
|
|
542
|
+
if (digest(decision.decision_sha256) && decision.decision_sha256 !== glossaryCanonicalSha256(bodyWithoutDigest(decision, "decision_sha256"))) {
|
|
543
|
+
errors.push("cli_decision.decision_sha256 does not match canonical decision bytes");
|
|
544
|
+
}
|
|
545
|
+
if (!digest(decision.decision_sha256))
|
|
546
|
+
errors.push("cli_decision.decision_sha256 must be lowercase SHA-256");
|
|
547
|
+
return errors;
|
|
548
|
+
}
|
|
549
|
+
export function createGlossaryAdmissionDecision(input) {
|
|
550
|
+
const decision = {
|
|
551
|
+
schema_version: LAYER_SCHEMAS.cli_decision,
|
|
552
|
+
owner: LAYER_OWNERS.cli_decision,
|
|
553
|
+
candidate_id: input.capsule.candidate_id,
|
|
554
|
+
candidate_revision: input.capsule.candidate_revision,
|
|
555
|
+
candidate_capsule_sha256: input.capsule.capsule_sha256,
|
|
556
|
+
candidate_projection_sha256: input.receipt.candidate_projection_sha256,
|
|
557
|
+
host_receipt_sha256: input.receipt.receipt_sha256,
|
|
558
|
+
classification_contract_version: input.receipt.schema_version,
|
|
559
|
+
semantic_fingerprint: input.receipt.semantic_fingerprint,
|
|
560
|
+
generation: input.capsule.generation,
|
|
561
|
+
policy_version: input.capsule.policy_version,
|
|
562
|
+
outcome: input.outcome,
|
|
563
|
+
reason: input.reason,
|
|
564
|
+
};
|
|
565
|
+
decision.decision_sha256 = glossaryCanonicalSha256(decision);
|
|
566
|
+
const errors = validateGlossaryAdmissionDecision(decision, input.capsule, input.receipt);
|
|
567
|
+
if (errors.length > 0)
|
|
568
|
+
throw new TypeError(errors.join("; "));
|
|
569
|
+
return decision;
|
|
570
|
+
}
|
|
571
|
+
function validateReviewTimeFields(record) {
|
|
572
|
+
const errors = [];
|
|
573
|
+
if (!timestamp(record.disposed_at))
|
|
574
|
+
errors.push("review_record.disposed_at must be an ISO timestamp");
|
|
575
|
+
if (!timestamp(record.expires_at))
|
|
576
|
+
errors.push("review_record.expires_at must be an ISO timestamp");
|
|
577
|
+
if (timestamp(record.disposed_at) && timestamp(record.expires_at) && Date.parse(record.expires_at) < Date.parse(record.disposed_at)) {
|
|
578
|
+
errors.push("review_record.expires_at must not precede disposed_at");
|
|
579
|
+
}
|
|
580
|
+
return errors;
|
|
581
|
+
}
|
|
582
|
+
export function validateGlossaryReviewRecord(record, capsule, receipt, decision, pathname = glossaryCandidateContractsAuthorityPath()) {
|
|
583
|
+
const loaded = loadedContract(pathname);
|
|
584
|
+
if (loaded.errors.length > 0)
|
|
585
|
+
return loaded.errors;
|
|
586
|
+
const errors = validateGlossaryAdmissionDecision(decision, capsule, receipt, pathname);
|
|
587
|
+
const layerAuthority = contractLayer(loaded.candidate, "review_record");
|
|
588
|
+
if (!layerAuthority)
|
|
589
|
+
return [...errors, "candidate_contracts.layers.review_record is missing"];
|
|
590
|
+
errors.push(...validateLayerEnvelope(record, layerAuthority, "review_record"));
|
|
591
|
+
if (decision.outcome !== "review_required")
|
|
592
|
+
errors.push("review_record requires a review_required CLI decision");
|
|
593
|
+
const expectedBindings = {
|
|
594
|
+
candidate_id: capsule.candidate_id,
|
|
595
|
+
candidate_revision: capsule.candidate_revision,
|
|
596
|
+
candidate_capsule_sha256: capsule.capsule_sha256,
|
|
597
|
+
host_receipt_sha256: receipt.receipt_sha256,
|
|
598
|
+
cli_decision_sha256: decision.decision_sha256,
|
|
599
|
+
semantic_fingerprint: receipt.semantic_fingerprint,
|
|
600
|
+
generation: capsule.generation,
|
|
601
|
+
policy_version: capsule.policy_version,
|
|
602
|
+
};
|
|
603
|
+
for (const [field, expected] of Object.entries(expectedBindings)) {
|
|
604
|
+
if (record[field] !== expected)
|
|
605
|
+
errors.push(`review_record.${field} does not match its source layer`);
|
|
606
|
+
}
|
|
607
|
+
const reviews = mapping(mapping(loaded.authority.personal_mining_authority)?.privacy)?.reviews;
|
|
608
|
+
const dispositions = strings(mapping(reviews)?.dispositions);
|
|
609
|
+
if (!dispositions.includes(String(record.disposition)) || !PERSONAL_REVIEW_DISPOSITIONS.includes(record.disposition)) {
|
|
610
|
+
errors.push("review_record.disposition is invalid");
|
|
611
|
+
}
|
|
612
|
+
const correctedMax = Number(candidateBounds(loaded.candidate).corrected_meaning_max_utf8_bytes ?? 0);
|
|
613
|
+
if (record.disposition === "correct") {
|
|
614
|
+
if (!utf8Within(record.corrected_meaning, correctedMax))
|
|
615
|
+
errors.push("review_record.corrected_meaning is required and outside its bound");
|
|
616
|
+
if (record.corrected_scope !== "personal")
|
|
617
|
+
errors.push("review_record.corrected_scope must be personal for correct");
|
|
618
|
+
}
|
|
619
|
+
else if (record.corrected_meaning !== null || record.corrected_scope !== null) {
|
|
620
|
+
errors.push("review_record correction fields must be null unless disposition is correct");
|
|
621
|
+
}
|
|
622
|
+
errors.push(...validateReviewTimeFields(record));
|
|
623
|
+
if (digest(record.record_sha256) && record.record_sha256 !== glossaryCanonicalSha256(bodyWithoutDigest(record, "record_sha256"))) {
|
|
624
|
+
errors.push("review_record.record_sha256 does not match canonical review bytes");
|
|
625
|
+
}
|
|
626
|
+
if (!digest(record.record_sha256))
|
|
627
|
+
errors.push("review_record.record_sha256 must be lowercase SHA-256");
|
|
628
|
+
return errors;
|
|
629
|
+
}
|
|
630
|
+
export function createGlossaryReviewRecord(input) {
|
|
631
|
+
const record = {
|
|
632
|
+
schema_version: LAYER_SCHEMAS.review_record,
|
|
633
|
+
owner: LAYER_OWNERS.review_record,
|
|
634
|
+
candidate_id: input.capsule.candidate_id,
|
|
635
|
+
candidate_revision: input.capsule.candidate_revision,
|
|
636
|
+
candidate_capsule_sha256: input.capsule.capsule_sha256,
|
|
637
|
+
host_receipt_sha256: input.receipt.receipt_sha256,
|
|
638
|
+
cli_decision_sha256: input.decision.decision_sha256,
|
|
639
|
+
semantic_fingerprint: input.receipt.semantic_fingerprint,
|
|
640
|
+
generation: input.capsule.generation,
|
|
641
|
+
policy_version: input.capsule.policy_version,
|
|
642
|
+
disposition: input.disposition,
|
|
643
|
+
corrected_meaning: input.corrected_meaning,
|
|
644
|
+
corrected_scope: input.corrected_scope,
|
|
645
|
+
disposed_at: input.disposed_at,
|
|
646
|
+
expires_at: input.expires_at,
|
|
647
|
+
};
|
|
648
|
+
record.record_sha256 = glossaryCanonicalSha256(record);
|
|
649
|
+
const errors = validateGlossaryReviewRecord(record, input.capsule, input.receipt, input.decision);
|
|
650
|
+
if (errors.length > 0)
|
|
651
|
+
throw new TypeError(errors.join("; "));
|
|
652
|
+
return record;
|
|
653
|
+
}
|
|
654
|
+
export function validateGlossaryPublicationResult(result, capsule, receipt, decision, review, pathname = glossaryCandidateContractsAuthorityPath()) {
|
|
655
|
+
const loaded = loadedContract(pathname);
|
|
656
|
+
if (loaded.errors.length > 0)
|
|
657
|
+
return loaded.errors;
|
|
658
|
+
const errors = validateGlossaryAdmissionDecision(decision, capsule, receipt, pathname);
|
|
659
|
+
const layerAuthority = contractLayer(loaded.candidate, "publication_result");
|
|
660
|
+
if (!layerAuthority)
|
|
661
|
+
return [...errors, "candidate_contracts.layers.publication_result is missing"];
|
|
662
|
+
errors.push(...validateLayerEnvelope(result, layerAuthority, "publication_result"));
|
|
663
|
+
const profile = mapping(mapping(loaded.authority.ownership_contracts)?.personal)?.profile_output;
|
|
664
|
+
const command = mapping(mapping(profile)?.command);
|
|
665
|
+
const statuses = strings(command?.output_statuses);
|
|
666
|
+
if (!statuses.includes(String(result.status)))
|
|
667
|
+
errors.push("publication_result.status is not an existing profile output status");
|
|
668
|
+
const expectedBindings = {
|
|
669
|
+
candidate_id: capsule.candidate_id,
|
|
670
|
+
candidate_revision: capsule.candidate_revision,
|
|
671
|
+
candidate_capsule_sha256: capsule.capsule_sha256,
|
|
672
|
+
decision_sha256: decision.decision_sha256,
|
|
673
|
+
generation: capsule.generation,
|
|
674
|
+
policy_version: capsule.policy_version,
|
|
675
|
+
};
|
|
676
|
+
for (const [field, expected] of Object.entries(expectedBindings)) {
|
|
677
|
+
if (result[field] !== expected)
|
|
678
|
+
errors.push(`publication_result.${field} does not match its source layer`);
|
|
679
|
+
}
|
|
680
|
+
if (decision.outcome === "automatic_admission" && result.review_record_sha256 !== null) {
|
|
681
|
+
errors.push("publication_result must not bind a review record for automatic admission");
|
|
682
|
+
}
|
|
683
|
+
if (decision.outcome === "review_required") {
|
|
684
|
+
if (!review)
|
|
685
|
+
errors.push("publication_result requires a review record");
|
|
686
|
+
else {
|
|
687
|
+
errors.push(...validateGlossaryReviewRecord(review, capsule, receipt, decision, pathname));
|
|
688
|
+
if (result.review_record_sha256 !== review.record_sha256)
|
|
689
|
+
errors.push("publication_result.review_record_sha256 does not match review record");
|
|
690
|
+
if (!["accept", "correct"].includes(String(review.disposition)))
|
|
691
|
+
errors.push("publication_result review disposition is not publishable");
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
if (decision.outcome === "abstain")
|
|
695
|
+
errors.push("publication_result cannot publish an abstained decision");
|
|
696
|
+
if (!digest(result.profile_section_sha256))
|
|
697
|
+
errors.push("publication_result.profile_section_sha256 must be lowercase SHA-256");
|
|
698
|
+
if (result.status === "dry_run_candidate") {
|
|
699
|
+
if (result.published_at !== null)
|
|
700
|
+
errors.push("publication_result.published_at must be null for dry-run candidates");
|
|
701
|
+
}
|
|
702
|
+
else if (!timestamp(result.published_at)) {
|
|
703
|
+
errors.push("publication_result.published_at must be an ISO timestamp for published results");
|
|
704
|
+
}
|
|
705
|
+
if (digest(result.result_sha256) && result.result_sha256 !== glossaryCanonicalSha256(bodyWithoutDigest(result, "result_sha256"))) {
|
|
706
|
+
errors.push("publication_result.result_sha256 does not match canonical publication bytes");
|
|
707
|
+
}
|
|
708
|
+
if (!digest(result.result_sha256))
|
|
709
|
+
errors.push("publication_result.result_sha256 must be lowercase SHA-256");
|
|
710
|
+
return errors;
|
|
711
|
+
}
|
|
712
|
+
export function createGlossaryPublicationResult(input) {
|
|
713
|
+
const result = {
|
|
714
|
+
schema_version: LAYER_SCHEMAS.publication_result,
|
|
715
|
+
owner: LAYER_OWNERS.publication_result,
|
|
716
|
+
candidate_id: input.capsule.candidate_id,
|
|
717
|
+
candidate_revision: input.capsule.candidate_revision,
|
|
718
|
+
candidate_capsule_sha256: input.capsule.capsule_sha256,
|
|
719
|
+
decision_sha256: input.decision.decision_sha256,
|
|
720
|
+
review_record_sha256: input.review?.record_sha256 ?? null,
|
|
721
|
+
generation: input.capsule.generation,
|
|
722
|
+
policy_version: input.capsule.policy_version,
|
|
723
|
+
status: input.status,
|
|
724
|
+
profile_section_sha256: input.profile_section_sha256,
|
|
725
|
+
published_at: input.published_at,
|
|
726
|
+
};
|
|
727
|
+
result.result_sha256 = glossaryCanonicalSha256(result);
|
|
728
|
+
const errors = validateGlossaryPublicationResult(result, input.capsule, input.receipt, input.decision, input.review);
|
|
729
|
+
if (errors.length > 0)
|
|
730
|
+
throw new TypeError(errors.join("; "));
|
|
731
|
+
return result;
|
|
732
|
+
}
|
|
733
|
+
export function validatePersonalCandidateContracts(authority) {
|
|
734
|
+
const errors = [];
|
|
735
|
+
const candidate = mapping(authority.candidate_contracts);
|
|
736
|
+
if (!candidate)
|
|
737
|
+
return ["candidate_contracts is required"];
|
|
738
|
+
if (candidate.schema_version !== CANDIDATE_CONTRACTS_SCHEMA)
|
|
739
|
+
errors.push("candidate_contracts.schema_version is invalid");
|
|
740
|
+
if (candidate.status !== "active_partial")
|
|
741
|
+
errors.push("candidate_contracts.status must be active_partial");
|
|
742
|
+
if (candidate.implementation_boundary !== "receipt_validation_deterministic_decision_and_explicit_personal_publication_runtime") {
|
|
743
|
+
errors.push("candidate_contracts must scope runtime to validation, deterministic decisions, and explicit personal publication");
|
|
744
|
+
}
|
|
745
|
+
if (!exactStrings(candidate.layers && Object.keys(mapping(candidate.layers) ?? {}), LAYERS))
|
|
746
|
+
errors.push("candidate_contracts.layers must contain exactly the five candidate layers");
|
|
747
|
+
const owners = LAYERS.map((name) => mapping(candidate.layers)?.[name]).map(mapping).map((item) => String(item?.owner ?? ""));
|
|
748
|
+
if (new Set(owners).size !== LAYERS.length || LAYERS.some((name, index) => owners[index] !== LAYER_OWNERS[name]))
|
|
749
|
+
errors.push("candidate contract layer owners must be distinct and authoritative");
|
|
750
|
+
for (const name of LAYERS) {
|
|
751
|
+
const current = mapping(mapping(candidate.layers)?.[name]);
|
|
752
|
+
if (!current) {
|
|
753
|
+
errors.push(`candidate_contracts.layers.${name} is required`);
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
const required = strings(current.required_fields);
|
|
757
|
+
if (!exactStrings(required, LAYER_REQUIRED_FIELDS[name]))
|
|
758
|
+
errors.push(`candidate_contracts.layers.${name}.required_fields must be exact and unique`);
|
|
759
|
+
errors.push(...validateLayerEnvelope({}, { ...current, required_fields: [] }, name).filter((error) => error.includes("additional_fields") || error.includes("owner") || error.includes("schema_version")));
|
|
760
|
+
if (current.additional_fields !== "forbidden")
|
|
761
|
+
errors.push(`candidate_contracts.layers.${name}.additional_fields must be forbidden`);
|
|
762
|
+
const forbidden = strings(current.forbidden_fields);
|
|
763
|
+
if (forbidden.length === 0 || new Set(forbidden).size !== forbidden.length)
|
|
764
|
+
errors.push(`candidate_contracts.layers.${name}.forbidden_fields must be explicit and unique`);
|
|
765
|
+
if (forbidden.some((field) => required.includes(field)))
|
|
766
|
+
errors.push(`candidate_contracts.layers.${name} cannot forbid a required field`);
|
|
767
|
+
if (!exactStrings(current.binding_fields, LAYER_BINDING_FIELDS[name])) {
|
|
768
|
+
errors.push(`candidate_contracts.layers.${name}.binding_fields are incomplete or reordered`);
|
|
769
|
+
}
|
|
770
|
+
if (current.body_digest !== BODY_DIGEST_FIELDS[name])
|
|
771
|
+
errors.push(`candidate_contracts.layers.${name}.body_digest is invalid`);
|
|
772
|
+
}
|
|
773
|
+
const canonicalization = mapping(candidate.canonicalization);
|
|
774
|
+
if (canonicalization?.algorithm !== "sha256" || canonicalization?.encoding !== "lowercase_hex" || canonicalization?.input !== "canonical_utf8_json" || canonicalization?.object_keys !== "unicode_code_point_sorted" || canonicalization?.evidence_records !== "canonical_json_sorted" || canonicalization?.digest_field_rule !== "exclude_digest_field_from_body") {
|
|
775
|
+
errors.push("candidate_contracts.canonicalization must reuse canonical UTF-8 JSON and lowercase SHA-256");
|
|
776
|
+
}
|
|
777
|
+
const bounds = candidateBounds(candidate);
|
|
778
|
+
if (bounds.term_max_utf8_bytes !== 256 || bounds.meaning_max_utf8_bytes !== 4096 || bounds.binding_max_utf8_bytes !== 256 || bounds.evidence_records_max !== 100 || bounds.reason_max_utf8_bytes !== 512 || bounds.corrected_meaning_max_utf8_bytes !== 4096 || bounds.digest_bytes !== 32) {
|
|
779
|
+
errors.push("candidate_contracts.bounds must preserve the declared candidate limits");
|
|
780
|
+
}
|
|
781
|
+
const identity = mapping(candidate.identity);
|
|
782
|
+
if (identity?.stable_term_identity !== "personal_mining_authority.term_identity.stable_term_identity" || identity?.candidate_revision !== "personal_mining_authority.term_identity.candidate_revision") {
|
|
783
|
+
errors.push("candidate_contracts.identity must delegate to the settled term and revision helpers");
|
|
784
|
+
}
|
|
785
|
+
const layers = mapping(candidate.layers);
|
|
786
|
+
const host = mapping(layers?.host_classification_receipt);
|
|
787
|
+
const classification = mapping(mapping(host)?.classification);
|
|
788
|
+
if (!exactStrings(classification?.fields, HOST_CLASSIFICATION_FIELDS) || classification?.term !== "shared_primitive.fields.term" || classification?.meaning !== "shared_primitive.fields.meaning" || classification?.scope !== "packages/cli/src/registries/glossaryTermIdentity.ts#GlossaryCandidateScope" || !exactStrings(classification?.consistency_values, CONSISTENCY_VALUES)) {
|
|
789
|
+
errors.push("host classification must expose only the approved semantic fields and consistency vocabulary");
|
|
790
|
+
}
|
|
791
|
+
errors.push(...validateGlossaryCandidateDecisionAuthority(authority));
|
|
792
|
+
const reviews = mapping(mapping(mapping(authority.personal_mining_authority)?.privacy)?.reviews);
|
|
793
|
+
const reviewLayer = mapping(layers?.review_record);
|
|
794
|
+
if (!exactStrings(reviewLayer?.dispositions_from, ["personal_mining_authority.privacy.reviews.dispositions"]) || !exactStrings(reviews?.dispositions, PERSONAL_REVIEW_DISPOSITIONS)) {
|
|
795
|
+
errors.push("review records must reuse the current user-local disposition vocabulary");
|
|
796
|
+
}
|
|
797
|
+
const profileOutput = mapping(mapping(mapping(authority.ownership_contracts)?.personal)?.profile_output);
|
|
798
|
+
const publicationLayer = mapping(layers?.publication_result);
|
|
799
|
+
if (publicationLayer?.owner !== "personal_profile_publication" || publicationLayer?.command !== "ownership_contracts.personal.profile_output.command.canonical" || !exactStrings(publicationLayer?.status_values_from, ["ownership_contracts.personal.profile_output.command.output_statuses"]) || !exactStrings(mapping(profileOutput?.command)?.output_statuses, ["changed", "unchanged_replay", "dry_run_candidate"])) {
|
|
800
|
+
errors.push("publication results must reuse the personal Profile output contract");
|
|
801
|
+
}
|
|
802
|
+
const invariance = mapping(candidate.shared_invariance);
|
|
803
|
+
if (invariance?.shared_primitive !== "shared_primitive" || invariance?.consumer_precedence !== "consumer_boundary.primary_selection" || invariance?.project_publication !== "ownership_contracts.project.publication" || invariance?.personal_project_isolation !== "ownership_contracts.personal.admission.isolation_rule") {
|
|
804
|
+
errors.push("candidate contracts must preserve shared entry, consumer precedence, project publication, and isolation owners");
|
|
805
|
+
}
|
|
806
|
+
const recovery = mapping(candidate.recovery);
|
|
807
|
+
if (recovery?.stale_or_mismatch !== "fail_closed_no_effects" || !nonEmpty(recovery?.retry))
|
|
808
|
+
errors.push("candidate contracts need fail-closed stale and mismatch recovery");
|
|
809
|
+
const inferredUsage = mapping(mapping(authority.provenance_variants)?.personal_inferred_usage);
|
|
810
|
+
const inferredDistinctness = mapping(inferredUsage?.distinctness);
|
|
811
|
+
if (inferredDistinctness?.source_ids !== 2 || inferredDistinctness?.evidence_anchors !== 2) {
|
|
812
|
+
errors.push("personal_inferred_usage must require two distinct source IDs and evidence anchors");
|
|
813
|
+
}
|
|
814
|
+
const forbiddenHost = strings(host?.forbidden_fields);
|
|
815
|
+
for (const field of ["admission", "decision", "mutation", "publication", "review_bypass", "trusted_publication_effect"]) {
|
|
816
|
+
if (!forbiddenHost.includes(field))
|
|
817
|
+
errors.push(`host classification must forbid ${field}`);
|
|
818
|
+
}
|
|
819
|
+
return errors;
|
|
820
|
+
}
|