agentera 3.0.0-dev.5 → 3.0.0-dev.51
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 +119 -22
- package/bundle/CHANGELOG.md +1351 -0
- package/bundle/DESIGN.md +229 -0
- package/bundle/LICENSE +201 -0
- package/bundle/README.md +143 -0
- package/bundle/UPGRADE.md +236 -0
- package/bundle/extract-corpus-parity.json +21 -0
- package/bundle/fixtures/routing/hybrid-corpus.yaml +154 -0
- package/bundle/references/adapters/package-publication.json +437 -0
- package/bundle/references/adapters/package-registry.yaml +435 -189
- package/bundle/references/adapters/package-surface-characterization.md +66 -35
- 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 +518 -0
- package/bundle/references/analysis/verification-policy.yaml +191 -0
- package/bundle/references/artifacts/artifact-registry-interface-model.yaml +20 -10
- package/bundle/references/artifacts/glossary-entry-contract.yaml +1254 -0
- package/bundle/references/artifacts/state-storage-authority.yaml +3022 -0
- package/bundle/references/artifacts/verbosity-budget-authority.yaml +42 -0
- package/bundle/references/cli/app-lifecycle-vocabulary.yaml +7 -8
- 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 +155 -0
- package/bundle/references/cli/trigger-schema-enrichment.md +147 -0
- package/bundle/references/cli/update-channels.yaml +19 -1
- package/bundle/references/cli/vocabulary-index.yaml +20 -17
- package/bundle/references/cli/vocabulary.md +326 -361
- package/bundle/references/meta/retained-reference-authority.yaml +151 -0
- package/bundle/registry.json +13 -13
- package/bundle/skills/agentera/SKILL.md +224 -422
- package/bundle/skills/agentera/capabilities/audit/schemas/artifacts.yaml +84 -0
- package/bundle/skills/agentera/capabilities/{inspektera → audit}/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/audit/schemas/triggers.yaml +25 -0
- package/bundle/skills/agentera/capabilities/{inspektera → audit}/schemas/validation.yaml +37 -18
- package/bundle/skills/agentera/capabilities/build/schemas/artifacts.yaml +102 -0
- package/bundle/skills/agentera/capabilities/{realisera → build}/schemas/exit.yaml +6 -5
- package/bundle/skills/agentera/capabilities/build/schemas/triggers.yaml +27 -0
- package/bundle/skills/agentera/capabilities/build/schemas/validation.yaml +176 -0
- package/bundle/skills/agentera/capabilities/{visualisera → design}/schemas/artifacts.yaml +12 -12
- package/bundle/skills/agentera/capabilities/{visualisera → design}/schemas/exit.yaml +5 -5
- package/bundle/skills/agentera/capabilities/design/schemas/triggers.yaml +16 -0
- package/bundle/skills/agentera/capabilities/{visualisera → design}/schemas/validation.yaml +7 -7
- package/bundle/skills/agentera/capabilities/discuss/schemas/artifacts.yaml +51 -0
- package/bundle/skills/agentera/capabilities/{resonera → discuss}/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/discuss/schemas/triggers.yaml +20 -0
- package/bundle/skills/agentera/capabilities/discuss/schemas/validation.yaml +144 -0
- package/bundle/skills/agentera/capabilities/document/schemas/artifacts.yaml +80 -0
- package/bundle/skills/agentera/capabilities/document/schemas/triggers.yaml +16 -0
- package/bundle/skills/agentera/capabilities/{dokumentera → document}/schemas/validation.yaml +18 -18
- package/bundle/skills/agentera/capabilities/{optimera → optimize}/schemas/artifacts.yaml +18 -18
- package/bundle/skills/agentera/capabilities/{optimera → optimize}/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/optimize/schemas/triggers.yaml +16 -0
- package/bundle/skills/agentera/capabilities/{optimera → optimize}/schemas/validation.yaml +9 -9
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/artifacts.yaml +76 -0
- package/bundle/skills/agentera/capabilities/{orkestrera → orchestrate}/schemas/exit.yaml +9 -7
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/triggers.yaml +23 -0
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/validation.yaml +121 -0
- package/bundle/skills/agentera/capabilities/plan/schemas/artifacts.yaml +66 -0
- package/bundle/skills/agentera/capabilities/{planera → plan}/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/plan/schemas/triggers.yaml +23 -0
- package/bundle/skills/agentera/capabilities/plan/schemas/validation.yaml +121 -0
- package/bundle/skills/agentera/capabilities/profile/schemas/artifacts.yaml +23 -0
- package/bundle/skills/agentera/capabilities/{profilera → profile}/schemas/exit.yaml +6 -5
- package/bundle/skills/agentera/capabilities/profile/schemas/triggers.yaml +20 -0
- package/bundle/skills/agentera/capabilities/profile/schemas/validation.yaml +115 -0
- package/bundle/skills/agentera/capabilities/research/schemas/artifacts.yaml +24 -0
- package/bundle/skills/agentera/capabilities/research/schemas/triggers.yaml +16 -0
- package/bundle/skills/agentera/capabilities/{inspirera → research}/schemas/validation.yaml +2 -2
- package/bundle/skills/agentera/capabilities/status/schemas/artifacts.yaml +73 -0
- package/bundle/skills/agentera/capabilities/status/schemas/triggers.yaml +22 -0
- package/bundle/skills/agentera/capabilities/{hej → status}/schemas/validation.yaml +5 -5
- package/bundle/skills/agentera/capabilities/{visionera → vision}/schemas/artifacts.yaml +16 -16
- package/bundle/skills/agentera/capabilities/{visionera → vision}/schemas/exit.yaml +7 -6
- package/bundle/skills/agentera/capabilities/vision/schemas/triggers.yaml +23 -0
- package/bundle/skills/agentera/capabilities/{visionera → vision}/schemas/validation.yaml +18 -20
- package/bundle/skills/agentera/capability_schema_contract.yaml +178 -34
- package/bundle/skills/agentera/protocol.yaml +31 -31
- package/bundle/skills/agentera/route-phrases.yaml +81 -0
- package/bundle/skills/agentera/schemas/artifacts/changelog.yaml +5 -4
- package/bundle/skills/agentera/schemas/artifacts/decisions.yaml +39 -21
- package/bundle/skills/agentera/schemas/artifacts/design.yaml +5 -4
- package/bundle/skills/agentera/schemas/artifacts/docs.yaml +15 -19
- package/bundle/skills/agentera/schemas/artifacts/experiments.yaml +145 -14
- package/bundle/skills/agentera/schemas/artifacts/glossary.yaml +82 -0
- package/bundle/skills/agentera/schemas/artifacts/health.yaml +58 -21
- package/bundle/skills/agentera/schemas/artifacts/objective.yaml +22 -8
- package/bundle/skills/agentera/schemas/artifacts/plan.yaml +458 -36
- package/bundle/skills/agentera/schemas/artifacts/progress.yaml +128 -17
- package/bundle/skills/agentera/schemas/artifacts/todo.yaml +342 -42
- package/bundle/skills/agentera/schemas/artifacts/vision.yaml +3 -3
- package/dist/analytics/extractCorpus/cli.js +190 -0
- package/dist/analytics/extractCorpus/copilotSessions.js +275 -0
- package/dist/analytics/extractCorpus/core.js +392 -0
- package/dist/analytics/extractCorpus/corpus.js +167 -0
- package/dist/analytics/extractCorpus/coverageAudit.js +260 -0
- package/dist/analytics/extractCorpus/cursorSessions.js +425 -0
- package/dist/analytics/extractCorpus/evidenceTiers.js +603 -0
- package/dist/analytics/extractCorpus/extractCorpusParity.js +105 -0
- package/dist/analytics/extractCorpus/filesystemSources.js +118 -0
- package/dist/analytics/extractCorpus/index.js +14 -0
- package/dist/analytics/extractCorpus/jsonlSessions.js +204 -0
- package/dist/analytics/extractCorpus/sqliteCaps.js +43 -0
- package/dist/analytics/extractCorpus/sqliteSessions.js +367 -0
- package/dist/analytics/extractCorpus/tierReader.js +108 -0
- package/dist/analytics/extractCorpus.js +2 -1791
- package/dist/analytics/glossaryAdviceResolution.js +166 -0
- package/dist/analytics/glossaryInputAcquisition.js +319 -0
- package/dist/analytics/personalGlossaryAdmission.js +133 -0
- package/dist/analytics/personalGlossaryProfile.js +219 -0
- package/dist/analytics/profileSignals.js +211 -0
- package/dist/analytics/usageStats.js +169 -42
- package/dist/audit/terminologyDrift.js +281 -0
- package/dist/bin/agentera.js +3 -2
- package/dist/capabilities/audit/instructions.js +16 -0
- package/dist/capabilities/build/instructions.js +56 -0
- package/dist/capabilities/design/instructions.js +4 -0
- package/dist/capabilities/discuss/instructions.js +29 -0
- package/dist/capabilities/document/instructions.js +11 -0
- package/dist/capabilities/index.js +29 -27
- package/dist/capabilities/optimize/instructions.js +14 -0
- package/dist/capabilities/orchestrate/instructions.js +42 -0
- package/dist/capabilities/plan/instructions.js +33 -0
- package/dist/capabilities/profile/instructions.js +70 -0
- package/dist/capabilities/research/instructions.js +5 -0
- package/dist/capabilities/status/instructions.js +15 -0
- package/dist/capabilities/status/startupInstructions.js +34 -0
- package/dist/capabilities/vision/instructions.js +4 -0
- package/dist/cli/appContext.js +30 -24
- package/dist/cli/argvalidate.js +0 -1
- package/dist/cli/capabilityContext/benchmark.js +565 -0
- package/dist/cli/capabilityContext/bespoke.js +44 -0
- package/dist/cli/capabilityContext/build.js +242 -0
- package/dist/cli/capabilityContext/closeout.js +233 -0
- package/dist/cli/capabilityContext/contract.js +179 -0
- package/dist/cli/capabilityContext/evidence.js +463 -0
- package/dist/cli/capabilityContext/index.js +3 -0
- package/dist/cli/capabilityContext/orchestration.js +131 -0
- package/dist/cli/capabilityContext/planState.js +260 -0
- package/dist/cli/capabilityContext/progress.js +142 -0
- package/dist/cli/capabilityContext/projectVerification.js +409 -0
- package/dist/cli/capabilityContext/shared.js +83 -0
- package/dist/cli/capabilityContext/slim.js +152 -0
- package/dist/cli/capabilityContext/startup.js +150 -0
- package/dist/cli/capabilityContext/startupAggregation.js +68 -0
- package/dist/cli/capabilityContext/types.js +56 -0
- package/dist/cli/capabilityContext.js +1 -2487
- package/dist/cli/commands/appHome.js +22 -0
- package/dist/cli/commands/capability.js +4 -4
- package/dist/cli/commands/compact.js +164 -14
- package/dist/cli/commands/doctor.js +122 -97
- package/dist/cli/commands/durability.js +81 -0
- package/dist/cli/commands/glossaryAdvice.js +138 -0
- package/dist/cli/commands/lint.js +26 -44
- package/dist/cli/commands/personalGlossary.js +176 -0
- package/dist/cli/commands/prime/briefOrientation.js +747 -0
- package/dist/cli/commands/prime/buildExecutionRequest.js +165 -0
- package/dist/cli/commands/prime/bundleStatus.js +190 -0
- package/dist/cli/commands/prime/collectEntityOrientation.js +326 -0
- package/dist/cli/commands/prime/collectOrientationState.js +212 -0
- package/dist/cli/commands/prime/orientationOutput.js +399 -0
- package/dist/cli/commands/prime/types.js +1 -0
- package/dist/cli/commands/prime/v1Migration.js +38 -0
- package/dist/cli/commands/prime.js +80 -558
- package/dist/cli/commands/profileGrounding.js +55 -0
- package/dist/cli/commands/query.js +78 -53
- package/dist/cli/commands/report.js +96 -25
- package/dist/cli/commands/route.js +142 -0
- package/dist/cli/commands/schema.js +266 -143
- package/dist/cli/commands/state/decisions.js +387 -0
- package/dist/cli/commands/state/docs.js +70 -0
- package/dist/cli/commands/state/experimentRecords.js +151 -0
- package/dist/cli/commands/state/experiments.js +14 -0
- package/dist/cli/commands/state/get.js +129 -0
- package/dist/cli/commands/state/health.js +14 -0
- package/dist/cli/commands/state/index.js +16 -0
- package/dist/cli/commands/state/list.js +194 -0
- package/dist/cli/commands/state/objective.js +25 -0
- package/dist/cli/commands/state/plan.js +14 -0
- 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 +13 -0
- package/dist/cli/commands/state/shared.js +14 -0
- package/dist/cli/commands/state/todo.js +42 -0
- package/dist/cli/commands/state/write.js +430 -0
- package/dist/cli/commands/upgrade.js +146 -5
- package/dist/cli/commands/upgradeVerify.js +118 -0
- package/dist/cli/commands/validate.js +272 -223
- package/dist/cli/commands/verify.js +24 -9
- package/dist/cli/contracts/bundleStatus.js +1 -0
- package/dist/cli/contracts/orientationState.js +1 -0
- package/dist/cli/dispatch/argvParser.js +32 -0
- package/dist/cli/dispatch/check.js +372 -0
- package/dist/cli/dispatch/commands.js +27 -0
- package/dist/cli/dispatch/index.js +207 -0
- package/dist/cli/dispatch/lifecycle.js +652 -0
- package/dist/cli/dispatch/prime.js +139 -0
- package/dist/cli/dispatch/projections.js +17 -0
- package/dist/cli/dispatch/shared.js +63 -0
- package/dist/cli/dispatch/state.js +140 -0
- package/dist/cli/dispatch.js +1 -1294
- package/dist/cli/errors.js +16 -17
- package/dist/cli/help.js +394 -43
- package/dist/cli/migrationRequired.js +87 -0
- package/dist/cli/orientation/attention.js +61 -0
- package/dist/cli/orientation/corpusCoverage.js +102 -0
- package/dist/cli/orientation.js +438 -170
- 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/profileAcquisition.js +167 -0
- package/dist/cli/startupCompletenessContract.js +59 -0
- package/dist/cli/stateQuery.js +56 -14
- 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 +18 -0
- package/dist/core/atomicWriter.js +20 -0
- package/dist/core/developmentChannel.js +1 -0
- package/dist/core/developmentInvocation.js +374 -0
- package/dist/core/difflib.js +0 -1
- package/dist/core/envPaths.js +20 -0
- package/dist/core/jsonValue.js +5 -0
- package/dist/core/paths.js +0 -1
- package/dist/core/pyjson.js +67 -3
- 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 +8 -1
- package/dist/eval/evalSkills.js +30 -26
- package/dist/eval/hybridRouteEvaluation.js +155 -0
- package/dist/eval/semanticEval.js +43 -20
- package/dist/eval/semanticFixtures.js +16 -5
- package/dist/hooks/common.js +11 -79
- package/dist/hooks/compaction/apply.js +446 -0
- package/dist/hooks/compaction/dryRun.js +184 -0
- package/dist/hooks/compaction/index.js +22 -0
- package/dist/hooks/compaction/parse.js +325 -0
- package/dist/hooks/compaction/retention.js +202 -0
- package/dist/hooks/compaction/status.js +360 -0
- package/dist/hooks/compaction/types.js +5 -0
- package/dist/hooks/validateArtifact/agentFacing.js +9 -0
- package/dist/hooks/validateArtifact/index.js +92 -0
- package/dist/hooks/validateArtifact/markdown.js +145 -0
- package/dist/hooks/validateArtifact/schema.js +546 -0
- package/dist/hooks/validateArtifact/traversal.js +107 -0
- package/dist/hooks/validateArtifact/violations.js +107 -0
- package/dist/migrate/v2HandoffManifest.js +452 -0
- package/dist/registries/activationContract.js +2 -0
- package/dist/registries/activationTuples.js +107 -0
- package/dist/registries/artifactProtocolIds.js +78 -0
- package/dist/registries/artifactRegistry.js +224 -63
- package/dist/registries/artifactSchemaProjection.js +45 -0
- package/dist/registries/capabilityContract.js +129 -2
- package/dist/registries/evaluatorHandoffContract.js +2 -3
- package/dist/registries/evidenceTierContract.js +371 -0
- package/dist/registries/glossaryAdviceContract.js +79 -0
- package/dist/registries/glossaryCaveatContract.js +67 -0
- package/dist/registries/glossaryConsumerContractValidation.js +787 -0
- package/dist/registries/glossaryEntryContract.js +757 -0
- package/dist/registries/glossaryTermIdentity.js +17 -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 +229 -0
- package/dist/registries/packageRegistry.js +187 -211
- package/dist/registries/todoReadinessContract.js +448 -0
- package/dist/registries/triggerLoader.js +174 -0
- package/dist/registries/verbosityBudgetContract.js +205 -0
- package/dist/release/releaseMetadata.js +385 -0
- 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 +502 -0
- package/dist/setup/opencode.js +20 -0
- package/dist/setup/opencodeConstants.js +1 -0
- package/dist/setup/sharedSkill.js +45 -0
- package/dist/setup/smokeChecks.js +21 -82
- 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 +846 -0
- package/dist/state/entityMigrationTodo.js +133 -0
- package/dist/state/entityPublicationContext.js +806 -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 +64 -25
- 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 +982 -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/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 +432 -0
- package/dist/state/startupAnalysis/contract.js +160 -0
- package/dist/state/startupAnalysis/helpers.js +286 -0
- package/dist/state/startupAnalysis/index.js +6 -0
- package/dist/state/startupAnalysis/metrics.js +340 -0
- package/dist/state/startupAnalysis/records.js +198 -0
- package/dist/state/startupAnalysis/report.js +111 -0
- package/dist/state/startupAnalysis/threshold.js +512 -0
- package/dist/state/startupAnalysis.js +2 -1953
- package/dist/state/startupProjection.js +499 -0
- package/dist/state/stateMode.js +85 -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/todoDocsEntities.js +1069 -0
- package/dist/state/todoDocsEntityValidation.js +158 -0
- package/dist/state/todoMarkdownProjection.js +51 -0
- package/dist/state/todoReconciliationActivation.js +140 -0
- package/dist/state/todoReconciliationInspection.js +169 -0
- package/dist/state/todoReconciliationRepair.js +170 -0
- package/dist/state/todoReconciliationTransaction.js +582 -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 +363 -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 +367 -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 +144 -0
- package/dist/state/write/serialize.js +1 -0
- package/dist/state/write/transaction.js +52 -0
- package/dist/state/write/validate.js +7 -0
- package/dist/upgrade/appContentRefresh.js +383 -0
- package/dist/upgrade/appModel.js +8 -7
- package/dist/upgrade/atomicWriter.js +1 -0
- package/dist/upgrade/bundleEvidence.js +33 -0
- package/dist/upgrade/channels.js +12 -8
- package/dist/upgrade/compatibility.js +56 -21
- package/dist/upgrade/doctor.js +197 -192
- package/dist/upgrade/doctorClassifier.js +187 -0
- package/dist/upgrade/installedHooksRetirement.js +196 -0
- package/dist/upgrade/legacyAgentCleanup.js +282 -0
- package/dist/upgrade/lifecycleUpgrade.js +113 -0
- package/dist/upgrade/migrateArtifactsV2ToV3.js +367 -149
- package/dist/upgrade/migrationPublication.js +122 -0
- package/dist/upgrade/nextMajorDoctor.js +42 -8
- package/dist/upgrade/npxPlatformStatus.js +22 -0
- package/dist/upgrade/projectIntegration.js +145 -187
- package/dist/upgrade/projectIntegrationDecision.js +50 -0
- package/dist/upgrade/retiredResourceDiagnostics.js +117 -0
- package/dist/upgrade/runtimeMigration.js +273 -363
- package/dist/upgrade/upgradeCommands.js +14 -1
- package/dist/upgrade/upgradeLock.js +85 -0
- package/dist/upgrade/upgradeOrchestrator.js +263 -59
- package/dist/upgrade/v3CapabilitySurface.js +14 -0
- package/dist/upgrade/versionResolution.js +8 -1
- package/dist/validate/activationArtifactEvidence.js +844 -0
- package/dist/validate/activationConjunction.js +816 -0
- package/dist/validate/activationEvidenceManifest.js +515 -0
- package/dist/validate/activationPackageSemantics.js +29 -0
- package/dist/validate/appHomeContract.js +5 -11
- package/dist/validate/bootstrapAuthority.js +44 -0
- package/dist/validate/capability.js +133 -12
- package/dist/validate/crossCapability.js +15 -10
- package/dist/validate/retainedReferenceAuthority.js +879 -0
- package/dist/validate/selfAudit.js +73 -37
- package/dist/validate/v1LegacyCruft.js +131 -0
- package/dist/validate/vocabularyAuthority.js +303 -0
- package/package.json +53 -27
- package/bundle/references/adapters/cursor.md +0 -213
- 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 -548
- 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 -355
- package/bundle/references/cli/bundle-skill-vocabulary.yaml +0 -278
- package/bundle/references/cli/capability-tool-classification.yaml +0 -53
- package/bundle/references/cli/routing-execution-vocabulary.yaml +0 -281
- package/bundle/references/meta/documentation-inventory.md +0 -43
- package/bundle/references/v1-section-mapping.md +0 -47
- package/bundle/skills/agentera/.claude-plugin/plugin.json +0 -27
- package/bundle/skills/agentera/agents/dokumentera.toml +0 -6
- package/bundle/skills/agentera/agents/hej.toml +0 -6
- package/bundle/skills/agentera/agents/inspektera.toml +0 -6
- package/bundle/skills/agentera/agents/inspirera.toml +0 -6
- package/bundle/skills/agentera/agents/optimera.toml +0 -6
- package/bundle/skills/agentera/agents/orkestrera.toml +0 -6
- package/bundle/skills/agentera/agents/planera.toml +0 -6
- package/bundle/skills/agentera/agents/profilera.toml +0 -6
- package/bundle/skills/agentera/agents/realisera.toml +0 -6
- package/bundle/skills/agentera/agents/resonera.toml +0 -6
- package/bundle/skills/agentera/agents/visionera.toml +0 -6
- package/bundle/skills/agentera/agents/visualisera.toml +0 -6
- package/bundle/skills/agentera/capabilities/dokumentera/schemas/artifacts.yaml +0 -73
- package/bundle/skills/agentera/capabilities/dokumentera/schemas/triggers.yaml +0 -35
- package/bundle/skills/agentera/capabilities/hej/schemas/artifacts.yaml +0 -69
- package/bundle/skills/agentera/capabilities/hej/schemas/triggers.yaml +0 -58
- package/bundle/skills/agentera/capabilities/inspektera/schemas/artifacts.yaml +0 -76
- package/bundle/skills/agentera/capabilities/inspektera/schemas/triggers.yaml +0 -38
- package/bundle/skills/agentera/capabilities/inspirera/schemas/artifacts.yaml +0 -24
- package/bundle/skills/agentera/capabilities/inspirera/schemas/triggers.yaml +0 -34
- package/bundle/skills/agentera/capabilities/optimera/schemas/triggers.yaml +0 -39
- package/bundle/skills/agentera/capabilities/orkestrera/schemas/artifacts.yaml +0 -64
- package/bundle/skills/agentera/capabilities/orkestrera/schemas/triggers.yaml +0 -42
- package/bundle/skills/agentera/capabilities/orkestrera/schemas/validation.yaml +0 -120
- package/bundle/skills/agentera/capabilities/planera/schemas/artifacts.yaml +0 -62
- package/bundle/skills/agentera/capabilities/planera/schemas/triggers.yaml +0 -34
- package/bundle/skills/agentera/capabilities/planera/schemas/validation.yaml +0 -61
- package/bundle/skills/agentera/capabilities/profilera/schemas/artifacts.yaml +0 -18
- package/bundle/skills/agentera/capabilities/profilera/schemas/triggers.yaml +0 -45
- package/bundle/skills/agentera/capabilities/profilera/schemas/validation.yaml +0 -57
- package/bundle/skills/agentera/capabilities/realisera/schemas/artifacts.yaml +0 -80
- package/bundle/skills/agentera/capabilities/realisera/schemas/triggers.yaml +0 -39
- package/bundle/skills/agentera/capabilities/realisera/schemas/validation.yaml +0 -110
- package/bundle/skills/agentera/capabilities/resonera/schemas/artifacts.yaml +0 -47
- package/bundle/skills/agentera/capabilities/resonera/schemas/triggers.yaml +0 -46
- package/bundle/skills/agentera/capabilities/resonera/schemas/validation.yaml +0 -77
- package/bundle/skills/agentera/capabilities/visionera/schemas/triggers.yaml +0 -41
- package/bundle/skills/agentera/capabilities/visualisera/schemas/triggers.yaml +0 -33
- package/bundle/skills/agentera/references/contract.md +0 -1039
- package/bundle/skills/hej/.claude-plugin/plugin.json +0 -6
- package/bundle/skills/hej/SKILL.md +0 -69
- package/bundle/skills/hej/agents/hej.toml +0 -11
- package/bundle/skills/hej/agents/openai.yaml +0 -8
- 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/dokumentera/instructions.js +0 -6
- package/dist/capabilities/dokumentera/instructions.js.map +0 -1
- package/dist/capabilities/hej/instructions.js +0 -6
- package/dist/capabilities/hej/instructions.js.map +0 -1
- package/dist/capabilities/index.js.map +0 -1
- package/dist/capabilities/inspektera/instructions.js +0 -6
- package/dist/capabilities/inspektera/instructions.js.map +0 -1
- package/dist/capabilities/inspirera/instructions.js +0 -6
- package/dist/capabilities/inspirera/instructions.js.map +0 -1
- package/dist/capabilities/optimera/instructions.js +0 -6
- package/dist/capabilities/optimera/instructions.js.map +0 -1
- package/dist/capabilities/orkestrera/instructions.js +0 -6
- package/dist/capabilities/orkestrera/instructions.js.map +0 -1
- package/dist/capabilities/planera/instructions.js +0 -6
- package/dist/capabilities/planera/instructions.js.map +0 -1
- package/dist/capabilities/profilera/instructions.js +0 -6
- package/dist/capabilities/profilera/instructions.js.map +0 -1
- package/dist/capabilities/realisera/instructions.js +0 -6
- package/dist/capabilities/realisera/instructions.js.map +0 -1
- package/dist/capabilities/resonera/instructions.js +0 -6
- package/dist/capabilities/resonera/instructions.js.map +0 -1
- package/dist/capabilities/visionera/instructions.js +0 -6
- package/dist/capabilities/visionera/instructions.js.map +0 -1
- package/dist/capabilities/visualisera/instructions.js +0 -6
- package/dist/capabilities/visualisera/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.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.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.js +0 -1023
- package/dist/cli/commands/state.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/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.js.map +0 -1
- package/dist/cli/prime-blob.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/core/difflib.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.js +0 -935
- package/dist/hooks/compaction.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 -71
- package/dist/hooks/cursorSessionStart.js.map +0 -1
- package/dist/hooks/sessionStart.js +0 -209
- package/dist/hooks/sessionStart.js.map +0 -1
- package/dist/hooks/sessionStop.js +0 -212
- package/dist/hooks/sessionStop.js.map +0 -1
- package/dist/hooks/validateArtifact.js +0 -935
- package/dist/hooks/validateArtifact.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 -315
- package/dist/registries/runtimeAdapterRegistry.js.map +0 -1
- package/dist/setup/codex.js +0 -1197
- 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 -127
- package/dist/setup/cursor.js.map +0 -1
- package/dist/setup/doctor.js +0 -1297
- package/dist/setup/doctor.js.map +0 -1
- package/dist/setup/smokeChecks.js.map +0 -1
- package/dist/state/installRoot.js.map +0 -1
- package/dist/state/startupAnalysis.js.map +0 -1
- package/dist/upgrade/appModel.js.map +0 -1
- package/dist/upgrade/channels.js.map +0 -1
- package/dist/upgrade/compatibility.js.map +0 -1
- package/dist/upgrade/doctor.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/projectIntegration.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/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.js +0 -772
- package/dist/validate/lifecycleAdapters.js.map +0 -1
- package/dist/validate/selfAudit.js.map +0 -1
- /package/bundle/skills/agentera/capabilities/{dokumentera → document}/schemas/exit.yaml +0 -0
- /package/bundle/skills/agentera/capabilities/{inspirera → research}/schemas/exit.yaml +0 -0
- /package/bundle/skills/agentera/capabilities/{hej → status}/schemas/exit.yaml +0 -0
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { resolveSourceRoot } from "../core/sourceRoot.js";
|
|
4
|
+
import { loadYamlMapping } from "../core/yaml.js";
|
|
5
|
+
const SCHEMA_VERSION = "agentera.todoReadiness.v1";
|
|
6
|
+
const PHASE_AUTHORITY = "protocol.yaml#PHASES[*].capabilities";
|
|
7
|
+
const REQUIRED_FIELDS = [
|
|
8
|
+
"capability",
|
|
9
|
+
"reason",
|
|
10
|
+
"dependencies",
|
|
11
|
+
"blocked",
|
|
12
|
+
"gate",
|
|
13
|
+
"queue_rank",
|
|
14
|
+
"order_reason",
|
|
15
|
+
];
|
|
16
|
+
const EVALUATION_PRECEDENCE = [
|
|
17
|
+
"todo_resolved",
|
|
18
|
+
"readiness_absent",
|
|
19
|
+
"blocked",
|
|
20
|
+
"gate_pending",
|
|
21
|
+
"dependency_cross_artifact",
|
|
22
|
+
"dependency_missing",
|
|
23
|
+
"dependency_cycle",
|
|
24
|
+
"dependency_open",
|
|
25
|
+
"ordering_conflict",
|
|
26
|
+
"actionable",
|
|
27
|
+
];
|
|
28
|
+
const PROHIBITED_TIEBREAKERS = [
|
|
29
|
+
"entity_id",
|
|
30
|
+
"file_order",
|
|
31
|
+
"filesystem_time",
|
|
32
|
+
"created_or_modified_time",
|
|
33
|
+
"description_text",
|
|
34
|
+
];
|
|
35
|
+
const OUTCOME_EXPECTATIONS = {
|
|
36
|
+
todo_resolved: { result: "resolved", eligible: false, attention: "none", recovery: "null" },
|
|
37
|
+
readiness_absent: { result: "needs-triage", eligible: false, attention: "item", recovery: "required" },
|
|
38
|
+
blocked: { result: "blocked", eligible: false, attention: "item", recovery: "required" },
|
|
39
|
+
gate_pending: { result: "gated", eligible: false, attention: "none", recovery: "required" },
|
|
40
|
+
dependency_cross_artifact: { result: "needs-triage", eligible: false, attention: "item", recovery: "required" },
|
|
41
|
+
dependency_missing: { result: "needs-triage", eligible: false, attention: "item", recovery: "required" },
|
|
42
|
+
dependency_cycle: { result: "needs-triage", eligible: false, attention: "item", recovery: "required" },
|
|
43
|
+
dependency_open: { result: "waiting", eligible: false, attention: "none", recovery: "required" },
|
|
44
|
+
dependency_resolved: { result: "satisfied", eligible: null, attention: "none", recovery: "null" },
|
|
45
|
+
ordering_conflict: { result: "needs-triage", eligible: false, attention: "item", recovery: "required" },
|
|
46
|
+
actionable: { result: "actionable", eligible: true, attention: "none", recovery: "null" },
|
|
47
|
+
};
|
|
48
|
+
const QUEUE_EXPECTATIONS = {
|
|
49
|
+
mixed_actionable_and_triage: {
|
|
50
|
+
selection: "highest_ordered_actionable",
|
|
51
|
+
attention: "bounded_triage_summary",
|
|
52
|
+
},
|
|
53
|
+
all_non_actionable: {
|
|
54
|
+
selection: "abstain",
|
|
55
|
+
attention: "bounded_highest_severity_summary",
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
function isMapping(value) {
|
|
59
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
60
|
+
}
|
|
61
|
+
function stringList(value) {
|
|
62
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string"))
|
|
63
|
+
return null;
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
function sameList(actual, expected) {
|
|
67
|
+
const list = stringList(actual);
|
|
68
|
+
return list !== null && list.length === expected.length && list.every((value, index) => value === expected[index]);
|
|
69
|
+
}
|
|
70
|
+
function canonicalCapabilities(capabilityContract, errors, sourceLabel) {
|
|
71
|
+
const aliases = isMapping(capabilityContract.ROUTE_ALIASES)
|
|
72
|
+
? capabilityContract.ROUTE_ALIASES.primary_aliases
|
|
73
|
+
: null;
|
|
74
|
+
if (!Array.isArray(aliases)) {
|
|
75
|
+
errors.push(`${sourceLabel}: ROUTE_ALIASES.primary_aliases must be a list`);
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
const capabilities = [];
|
|
79
|
+
for (const alias of aliases) {
|
|
80
|
+
if (!isMapping(alias) || typeof alias.capability !== "string" || !alias.capability.trim()) {
|
|
81
|
+
errors.push(`${sourceLabel}: each ROUTE_ALIASES.primary_aliases entry must declare capability`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
capabilities.push(alias.capability);
|
|
85
|
+
}
|
|
86
|
+
return capabilities;
|
|
87
|
+
}
|
|
88
|
+
function derivePhaseMapping(protocol, canonical, errors, sourceLabel) {
|
|
89
|
+
const mapping = new Map();
|
|
90
|
+
if (!isMapping(protocol.PHASES)) {
|
|
91
|
+
errors.push(`${sourceLabel}: protocol PHASES must be a mapping`);
|
|
92
|
+
return mapping;
|
|
93
|
+
}
|
|
94
|
+
for (const entry of Object.values(protocol.PHASES)) {
|
|
95
|
+
if (!isMapping(entry))
|
|
96
|
+
continue;
|
|
97
|
+
const phase = typeof entry.value === "string" ? entry.value : "";
|
|
98
|
+
const capabilities = stringList(entry.capabilities);
|
|
99
|
+
if (!phase || capabilities === null) {
|
|
100
|
+
errors.push(`${sourceLabel}: each PHASES entry must declare a value and capabilities list`);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
for (const capability of capabilities) {
|
|
104
|
+
if (!canonical.has(capability)) {
|
|
105
|
+
errors.push(`${sourceLabel}: PHASES capability '${capability}' is not canonical`);
|
|
106
|
+
}
|
|
107
|
+
if (mapping.has(capability)) {
|
|
108
|
+
errors.push(`${sourceLabel}: capability '${capability}' appears in multiple PHASES entries`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
mapping.set(capability, phase);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return mapping;
|
|
116
|
+
}
|
|
117
|
+
function validateFields(readiness, errors, sourceLabel) {
|
|
118
|
+
const fields = readiness.fields;
|
|
119
|
+
if (!isMapping(fields)) {
|
|
120
|
+
errors.push(`${sourceLabel}: READINESS.fields must be a mapping`);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
for (const name of REQUIRED_FIELDS) {
|
|
124
|
+
const field = fields[name];
|
|
125
|
+
if (!isMapping(field)) {
|
|
126
|
+
errors.push(`${sourceLabel}: READINESS.fields.${name} must be a mapping`);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (field.required !== true) {
|
|
130
|
+
errors.push(`${sourceLabel}: READINESS.fields.${name}.required must be true`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const capability = fields.capability;
|
|
134
|
+
if (isMapping(capability) && capability.enum_source !== PHASE_AUTHORITY) {
|
|
135
|
+
errors.push(`${sourceLabel}: READINESS.fields.capability.enum_source must be ${PHASE_AUTHORITY}`);
|
|
136
|
+
}
|
|
137
|
+
const dependencies = fields.dependencies;
|
|
138
|
+
const dependencyEntries = isMapping(dependencies) && isMapping(dependencies.entries)
|
|
139
|
+
? dependencies.entries
|
|
140
|
+
: null;
|
|
141
|
+
const dependencyArtifact = dependencyEntries && isMapping(dependencyEntries.artifact)
|
|
142
|
+
? dependencyEntries.artifact
|
|
143
|
+
: null;
|
|
144
|
+
if (dependencyArtifact?.const !== "todo") {
|
|
145
|
+
errors.push(`${sourceLabel}: dependency artifact const must be todo`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function validateOutcomes(readiness, errors, sourceLabel) {
|
|
149
|
+
const outcomes = readiness.outcomes;
|
|
150
|
+
if (!isMapping(outcomes)) {
|
|
151
|
+
errors.push(`${sourceLabel}: READINESS.outcomes must be a mapping`);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
for (const [name, expected] of Object.entries(OUTCOME_EXPECTATIONS)) {
|
|
155
|
+
const outcome = outcomes[name];
|
|
156
|
+
if (!isMapping(outcome)) {
|
|
157
|
+
errors.push(`${sourceLabel}: READINESS.outcomes.${name} must be a mapping`);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (outcome.result !== expected.result) {
|
|
161
|
+
errors.push(`${sourceLabel}: READINESS.outcomes.${name}.result must be ${expected.result}`);
|
|
162
|
+
}
|
|
163
|
+
if (outcome.eligible !== expected.eligible) {
|
|
164
|
+
errors.push(`${sourceLabel}: READINESS.outcomes.${name}.eligible must be ${String(expected.eligible)}`);
|
|
165
|
+
}
|
|
166
|
+
if (outcome.attention !== expected.attention) {
|
|
167
|
+
errors.push(`${sourceLabel}: READINESS.outcomes.${name}.attention must be one of: none, item`);
|
|
168
|
+
}
|
|
169
|
+
const validRecovery = expected.recovery === "null"
|
|
170
|
+
? outcome.recovery === null
|
|
171
|
+
: typeof outcome.recovery === "string" && outcome.recovery.trim().length > 0;
|
|
172
|
+
if (!validRecovery) {
|
|
173
|
+
errors.push(`${sourceLabel}: READINESS.outcomes.${name}.recovery must be ${expected.recovery === "null" ? "null" : "a non-empty string"}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function validateQueueOutcomes(readiness, errors, sourceLabel) {
|
|
178
|
+
const outcomes = readiness.queue_outcomes;
|
|
179
|
+
if (!isMapping(outcomes)) {
|
|
180
|
+
errors.push(`${sourceLabel}: READINESS.queue_outcomes must be a mapping`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
for (const [name, expected] of Object.entries(QUEUE_EXPECTATIONS)) {
|
|
184
|
+
const outcome = outcomes[name];
|
|
185
|
+
if (!isMapping(outcome)) {
|
|
186
|
+
errors.push(`${sourceLabel}: READINESS.queue_outcomes.${name} must be a mapping`);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (outcome.selection !== expected.selection || outcome.attention !== expected.attention) {
|
|
190
|
+
errors.push(`${sourceLabel}: READINESS.queue_outcomes.${name} must use selection=${expected.selection} and attention=${expected.attention}`);
|
|
191
|
+
}
|
|
192
|
+
if (typeof outcome.recovery !== "string" || !outcome.recovery.trim()) {
|
|
193
|
+
errors.push(`${sourceLabel}: READINESS.queue_outcomes.${name}.recovery must be a non-empty string`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function validateOrdering(readiness, errors, sourceLabel) {
|
|
198
|
+
const ordering = readiness.ordering;
|
|
199
|
+
if (!isMapping(ordering)) {
|
|
200
|
+
errors.push(`${sourceLabel}: READINESS.ordering must be a mapping`);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (ordering.primary !== "protocol.yaml#SEVERITY_ISSUE") {
|
|
204
|
+
errors.push(`${sourceLabel}: READINESS.ordering.primary must be protocol.yaml#SEVERITY_ISSUE`);
|
|
205
|
+
}
|
|
206
|
+
for (const legacy of ["within_severity", "duplicate_rank", "prohibited_tiebreakers"]) {
|
|
207
|
+
if (legacy in ordering)
|
|
208
|
+
errors.push(`${sourceLabel}: READINESS.ordering.${legacy} must be declared under one ordering mode`);
|
|
209
|
+
}
|
|
210
|
+
const modes = ordering.modes;
|
|
211
|
+
if (!isMapping(modes)) {
|
|
212
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes must be a mapping`);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (Object.keys(modes).sort().join(",") !== "nonprojected,projected_startup") {
|
|
216
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes must contain only nonprojected and projected_startup`);
|
|
217
|
+
}
|
|
218
|
+
const nonprojected = modes.nonprojected;
|
|
219
|
+
if (!isMapping(nonprojected)) {
|
|
220
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes.nonprojected must be a mapping`);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
if (Object.keys(nonprojected).sort().join(",") !== "duplicate_rank,prohibited_tiebreakers,within_severity") {
|
|
224
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes.nonprojected has unsupported fields`);
|
|
225
|
+
}
|
|
226
|
+
if (nonprojected.within_severity !== "queue_rank_ascending") {
|
|
227
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes.nonprojected.within_severity must be queue_rank_ascending`);
|
|
228
|
+
}
|
|
229
|
+
if (nonprojected.duplicate_rank !== "ordering_conflict") {
|
|
230
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes.nonprojected.duplicate_rank must be ordering_conflict`);
|
|
231
|
+
}
|
|
232
|
+
if (!sameList(nonprojected.prohibited_tiebreakers, PROHIBITED_TIEBREAKERS)) {
|
|
233
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes.nonprojected.prohibited_tiebreakers must equal ${PROHIBITED_TIEBREAKERS.join(", ")}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const projected = modes.projected_startup;
|
|
237
|
+
const projectedRules = {
|
|
238
|
+
entity_annotation: "required_for_every_entity",
|
|
239
|
+
eligibility: "before_order",
|
|
240
|
+
managed_before_absent: true,
|
|
241
|
+
managed_within_severity: "markdown_order_ascending",
|
|
242
|
+
managed_duplicate_rank: "ignored",
|
|
243
|
+
absent_within_severity: "queue_rank_then_id",
|
|
244
|
+
absent_duplicate_rank: "entity_id_ascending",
|
|
245
|
+
};
|
|
246
|
+
if (!isMapping(projected)) {
|
|
247
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes.projected_startup must be a mapping`);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
if (Object.keys(projected).sort().join(",") !== Object.keys(projectedRules).sort().join(",")) {
|
|
251
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes.projected_startup has unsupported fields`);
|
|
252
|
+
}
|
|
253
|
+
for (const [field, expected] of Object.entries(projectedRules)) {
|
|
254
|
+
if (projected[field] !== expected)
|
|
255
|
+
errors.push(`${sourceLabel}: READINESS.ordering.modes.projected_startup.${field} must be ${String(expected)}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
export function validateTodoReadinessContract(todoSchema, protocol, capabilityContract, sourceLabel = "TODO readiness contract") {
|
|
260
|
+
const errors = [];
|
|
261
|
+
const readiness = todoSchema.READINESS;
|
|
262
|
+
if (!isMapping(readiness))
|
|
263
|
+
return [`${sourceLabel}: READINESS must be a mapping`];
|
|
264
|
+
if (readiness.schema_version !== SCHEMA_VERSION) {
|
|
265
|
+
errors.push(`${sourceLabel}: READINESS.schema_version must be ${SCHEMA_VERSION}`);
|
|
266
|
+
}
|
|
267
|
+
const canonicalList = canonicalCapabilities(capabilityContract, errors, sourceLabel);
|
|
268
|
+
const canonical = new Set(canonicalList);
|
|
269
|
+
const phaseByCapability = derivePhaseMapping(protocol, canonical, errors, sourceLabel);
|
|
270
|
+
const destination = readiness.destination;
|
|
271
|
+
if (!isMapping(destination)) {
|
|
272
|
+
errors.push(`${sourceLabel}: READINESS.destination must be a mapping`);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
if (destination.phase_authority !== PHASE_AUTHORITY) {
|
|
276
|
+
errors.push(`${sourceLabel}: READINESS.destination.phase_authority must be ${PHASE_AUTHORITY}`);
|
|
277
|
+
}
|
|
278
|
+
for (const duplicate of ["allowed_destinations", "phase_mapping"]) {
|
|
279
|
+
if (duplicate in destination) {
|
|
280
|
+
errors.push(`${sourceLabel}: READINESS.destination.${duplicate} duplicates the canonical PHASES authority`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const excluded = destination.excluded_capabilities;
|
|
284
|
+
if (!isMapping(excluded)) {
|
|
285
|
+
errors.push(`${sourceLabel}: READINESS.destination.excluded_capabilities must be a mapping`);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
for (const capability of canonicalList) {
|
|
289
|
+
const mapped = phaseByCapability.has(capability);
|
|
290
|
+
const exclusion = excluded[capability];
|
|
291
|
+
if (mapped && exclusion !== undefined) {
|
|
292
|
+
errors.push(`${sourceLabel}: mapped capability '${capability}' must not also be excluded`);
|
|
293
|
+
}
|
|
294
|
+
else if (!mapped && (typeof exclusion !== "string" || !exclusion.trim())) {
|
|
295
|
+
errors.push(`${sourceLabel}: canonical capability '${capability}' must be mapped to one phase or explicitly excluded`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
for (const [capability, reason] of Object.entries(excluded)) {
|
|
299
|
+
if (!canonical.has(capability)) {
|
|
300
|
+
errors.push(`${sourceLabel}: excluded capability '${capability}' is not canonical`);
|
|
301
|
+
}
|
|
302
|
+
if (typeof reason !== "string" || !reason.trim()) {
|
|
303
|
+
errors.push(`${sourceLabel}: excluded capability '${capability}' must have a non-empty reason`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
validateFields(readiness, errors, sourceLabel);
|
|
309
|
+
const evaluation = readiness.evaluation;
|
|
310
|
+
if (!isMapping(evaluation) || !sameList(evaluation.precedence, EVALUATION_PRECEDENCE)) {
|
|
311
|
+
errors.push(`${sourceLabel}: READINESS.evaluation.precedence must equal ${EVALUATION_PRECEDENCE.join(", ")}`);
|
|
312
|
+
}
|
|
313
|
+
validateOutcomes(readiness, errors, sourceLabel);
|
|
314
|
+
validateQueueOutcomes(readiness, errors, sourceLabel);
|
|
315
|
+
validateOrdering(readiness, errors, sourceLabel);
|
|
316
|
+
return errors;
|
|
317
|
+
}
|
|
318
|
+
function requiredMappingFields(label, value, names) {
|
|
319
|
+
if (!isMapping(value))
|
|
320
|
+
return [`${label} must be a mapping or null`];
|
|
321
|
+
const errors = [];
|
|
322
|
+
for (const name of names) {
|
|
323
|
+
if (!(name in value))
|
|
324
|
+
errors.push(`${label}.${name} is required`);
|
|
325
|
+
else if (typeof value[name] !== "string" || !String(value[name]).trim())
|
|
326
|
+
errors.push(`${label}.${name} must be a non-empty string`);
|
|
327
|
+
}
|
|
328
|
+
for (const name of Object.keys(value)) {
|
|
329
|
+
if (!names.includes(name))
|
|
330
|
+
errors.push(`${label} has unsupported field '${name}'`);
|
|
331
|
+
}
|
|
332
|
+
return errors;
|
|
333
|
+
}
|
|
334
|
+
export function todoReadinessRecordViolations(readiness, contract = loadTodoReadinessContract()) {
|
|
335
|
+
if (!isMapping(readiness))
|
|
336
|
+
return ["readiness must be a mapping"];
|
|
337
|
+
const errors = [];
|
|
338
|
+
for (const field of REQUIRED_FIELDS) {
|
|
339
|
+
if (!(field in readiness))
|
|
340
|
+
errors.push(`${field} is required when readiness is declared`);
|
|
341
|
+
}
|
|
342
|
+
for (const field of Object.keys(readiness)) {
|
|
343
|
+
if (!REQUIRED_FIELDS.includes(field))
|
|
344
|
+
errors.push(`readiness has unsupported field '${field}'`);
|
|
345
|
+
}
|
|
346
|
+
if (typeof readiness.capability !== "string" || !contract.allowedDestinations.includes(readiness.capability)) {
|
|
347
|
+
errors.push(`capability must be one of: ${contract.allowedDestinations.join(", ")}`);
|
|
348
|
+
}
|
|
349
|
+
if (typeof readiness.reason !== "string" || !readiness.reason.trim())
|
|
350
|
+
errors.push("reason must be a non-empty string");
|
|
351
|
+
if (!Array.isArray(readiness.dependencies))
|
|
352
|
+
errors.push("dependencies must be a list");
|
|
353
|
+
else
|
|
354
|
+
for (const [index, dependency] of readiness.dependencies.entries()) {
|
|
355
|
+
if (!isMapping(dependency)) {
|
|
356
|
+
errors.push(`dependencies[${index}] must be a mapping`);
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
for (const field of Object.keys(dependency)) {
|
|
360
|
+
if (field !== "artifact" && field !== "id")
|
|
361
|
+
errors.push(`dependencies[${index}] has unsupported field '${field}'`);
|
|
362
|
+
}
|
|
363
|
+
if (dependency.artifact !== "todo")
|
|
364
|
+
errors.push(`dependencies[${index}] dependency artifact must be 'todo'`);
|
|
365
|
+
if (!/^[a-z]{10}$/.test(String(dependency.id ?? "")))
|
|
366
|
+
errors.push(`dependencies[${index}] dependency ID must be ten lowercase letters`);
|
|
367
|
+
}
|
|
368
|
+
if (readiness.blocked !== null)
|
|
369
|
+
errors.push(...requiredMappingFields("blocked", readiness.blocked, ["reason", "recovery"]));
|
|
370
|
+
if (readiness.gate !== null) {
|
|
371
|
+
errors.push(...requiredMappingFields("gate", readiness.gate, ["state", "reason", "recovery"]));
|
|
372
|
+
const gate = isMapping(readiness.gate) ? readiness.gate : {};
|
|
373
|
+
const gateFields = isMapping(contract.fields.gate) && isMapping(contract.fields.gate.fields) ? contract.fields.gate.fields : {};
|
|
374
|
+
const stateField = isMapping(gateFields.state) ? gateFields.state : {};
|
|
375
|
+
const allowed = stringList(stateField.enum) ?? [];
|
|
376
|
+
if (typeof gate.state === "string" && !allowed.includes(gate.state))
|
|
377
|
+
errors.push(`gate.state must be one of: ${allowed.join(", ")}`);
|
|
378
|
+
}
|
|
379
|
+
const queueField = isMapping(contract.fields.queue_rank) ? contract.fields.queue_rank : {};
|
|
380
|
+
const minimum = typeof queueField.minimum === "number" ? queueField.minimum : 1;
|
|
381
|
+
if (!Number.isInteger(readiness.queue_rank) || Number(readiness.queue_rank) < minimum)
|
|
382
|
+
errors.push(`queue_rank must be an integer greater than or equal to ${minimum}`);
|
|
383
|
+
if (typeof readiness.order_reason !== "string" || !readiness.order_reason.trim())
|
|
384
|
+
errors.push("order_reason must be a non-empty string");
|
|
385
|
+
return [...new Set(errors)];
|
|
386
|
+
}
|
|
387
|
+
export function todoReadinessReferenceViolations(itemId, readiness, todos) {
|
|
388
|
+
if (!isMapping(readiness) || !Array.isArray(readiness.dependencies))
|
|
389
|
+
return [];
|
|
390
|
+
const dependencies = readiness.dependencies
|
|
391
|
+
.filter(isMapping)
|
|
392
|
+
.map((dependency) => String(dependency.id ?? ""))
|
|
393
|
+
.filter((id) => /^[a-z]{10}$/.test(id));
|
|
394
|
+
const byId = new Map(todos.map((todo) => [todo.id, todo.record]));
|
|
395
|
+
const errors = [];
|
|
396
|
+
for (const dependency of dependencies) {
|
|
397
|
+
if (dependency === itemId)
|
|
398
|
+
errors.push(`TODO '${itemId}' cannot depend on itself`);
|
|
399
|
+
else if (!byId.has(dependency))
|
|
400
|
+
errors.push(`TODO dependency '${dependency}' does not exist`);
|
|
401
|
+
}
|
|
402
|
+
const reachesItem = (id, seen) => {
|
|
403
|
+
if (id === itemId)
|
|
404
|
+
return true;
|
|
405
|
+
if (seen.has(id))
|
|
406
|
+
return false;
|
|
407
|
+
seen.add(id);
|
|
408
|
+
const record = byId.get(id);
|
|
409
|
+
const nested = isMapping(record?.readiness) && Array.isArray(record.readiness.dependencies)
|
|
410
|
+
? record.readiness.dependencies.filter(isMapping).map((dependency) => String(dependency.id ?? ""))
|
|
411
|
+
: [];
|
|
412
|
+
return nested.some((dependency) => reachesItem(dependency, seen));
|
|
413
|
+
};
|
|
414
|
+
if (!errors.length && dependencies.some((dependency) => reachesItem(dependency, new Set()))) {
|
|
415
|
+
errors.push(`TODO '${itemId}' would create a dependency cycle`);
|
|
416
|
+
}
|
|
417
|
+
return errors;
|
|
418
|
+
}
|
|
419
|
+
export class TodoReadinessContractError extends Error {
|
|
420
|
+
errors;
|
|
421
|
+
constructor(errors) {
|
|
422
|
+
super(errors.join("; "));
|
|
423
|
+
this.errors = errors;
|
|
424
|
+
this.name = "TodoReadinessContractError";
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
export function loadTodoReadinessContract(todoSchemaPath = path.join(resolveSourceRoot(), "skills", "agentera", "schemas", "artifacts", "todo.yaml"), protocolPath = path.join(resolveSourceRoot(), "skills", "agentera", "protocol.yaml"), capabilityContractPath = path.join(resolveSourceRoot(), "skills", "agentera", "capability_schema_contract.yaml")) {
|
|
428
|
+
const todoSchema = loadYamlMapping(fs.readFileSync(todoSchemaPath, "utf8"));
|
|
429
|
+
const protocol = loadYamlMapping(fs.readFileSync(protocolPath, "utf8"));
|
|
430
|
+
const capabilityContract = loadYamlMapping(fs.readFileSync(capabilityContractPath, "utf8"));
|
|
431
|
+
const errors = validateTodoReadinessContract(todoSchema, protocol, capabilityContract, todoSchemaPath);
|
|
432
|
+
if (errors.length)
|
|
433
|
+
throw new TodoReadinessContractError(errors);
|
|
434
|
+
const readiness = todoSchema.READINESS;
|
|
435
|
+
const destination = readiness.destination;
|
|
436
|
+
const phaseByCapability = derivePhaseMapping(protocol, new Set(canonicalCapabilities(capabilityContract, [], capabilityContractPath)), [], protocolPath);
|
|
437
|
+
return {
|
|
438
|
+
schemaVersion: readiness.schema_version,
|
|
439
|
+
allowedDestinations: [...phaseByCapability.keys()],
|
|
440
|
+
phaseByCapability,
|
|
441
|
+
excludedCapabilities: destination.excluded_capabilities,
|
|
442
|
+
fields: readiness.fields,
|
|
443
|
+
precedence: readiness.evaluation.precedence,
|
|
444
|
+
outcomes: readiness.outcomes,
|
|
445
|
+
queueOutcomes: readiness.queue_outcomes,
|
|
446
|
+
ordering: readiness.ordering,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { loadYamlMapping } from "../core/yaml.js";
|
|
4
|
+
import { resolveSourceRoot } from "../core/sourceRoot.js";
|
|
5
|
+
export class TriggerLoaderError extends Error {
|
|
6
|
+
errors;
|
|
7
|
+
constructor(errors) {
|
|
8
|
+
super(errors.join("; "));
|
|
9
|
+
this.name = "TriggerLoaderError";
|
|
10
|
+
this.errors = errors;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function isMapping(value) {
|
|
14
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
function isNumericKey(key) {
|
|
17
|
+
return /^\d+$/.test(key) && Number(key) >= 1;
|
|
18
|
+
}
|
|
19
|
+
/** Absolute directory holding the Agentera capability schemas. */
|
|
20
|
+
export function capabilitiesBaseDir(sourceRoot = resolveSourceRoot()) {
|
|
21
|
+
return path.join(sourceRoot, "skills", "agentera", "capabilities");
|
|
22
|
+
}
|
|
23
|
+
/** Absolute path to a capability's triggers.yaml. */
|
|
24
|
+
export function triggersYamlPath(capability, sourceRoot = resolveSourceRoot()) {
|
|
25
|
+
return path.join(capabilitiesBaseDir(sourceRoot), capability, "schemas", "triggers.yaml");
|
|
26
|
+
}
|
|
27
|
+
function readTriggersYaml(filePath) {
|
|
28
|
+
if (!fs.existsSync(filePath)) {
|
|
29
|
+
throw new TriggerLoaderError([`triggers.yaml not found at ${filePath}`]);
|
|
30
|
+
}
|
|
31
|
+
return loadYamlMapping(fs.readFileSync(filePath, "utf8")); // cast: YAML parse IO boundary
|
|
32
|
+
}
|
|
33
|
+
function resolveDisambiguation(value, location, allowedCapabilityIds) {
|
|
34
|
+
if (value === undefined || value === null)
|
|
35
|
+
return [];
|
|
36
|
+
if (!Array.isArray(value)) {
|
|
37
|
+
throw new TriggerLoaderError([
|
|
38
|
+
`${location} disambiguates_against must be a list of mappings`,
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
const entries = [];
|
|
42
|
+
for (let i = 0; i < value.length; i++) {
|
|
43
|
+
const item = value[i];
|
|
44
|
+
if (!isMapping(item)) {
|
|
45
|
+
throw new TriggerLoaderError([
|
|
46
|
+
`${location} disambiguates_against[${i}] must be a mapping with 'capability' and 'hint'`,
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
const capability = item.capability;
|
|
50
|
+
if (typeof capability !== "string" || !capability) {
|
|
51
|
+
throw new TriggerLoaderError([
|
|
52
|
+
`${location} disambiguates_against[${i}] missing 'capability' (must be one of: ${allowedCapabilityIds.join(", ")})`,
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
if (!allowedCapabilityIds.includes(capability)) {
|
|
56
|
+
throw new TriggerLoaderError([
|
|
57
|
+
`${location} disambiguates_against[${i}].capability=${JSON.stringify(capability)} is not a canonical capability ID (must be one of: ${allowedCapabilityIds.join(", ")})`,
|
|
58
|
+
]);
|
|
59
|
+
}
|
|
60
|
+
const hint = item.hint;
|
|
61
|
+
if (typeof hint !== "string" || hint.trim() === "") {
|
|
62
|
+
throw new TriggerLoaderError([
|
|
63
|
+
`${location} disambiguates_against[${i}] missing or empty 'hint' (must be a non-empty string)`,
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
entries.push({ capability, hint });
|
|
67
|
+
}
|
|
68
|
+
return entries;
|
|
69
|
+
}
|
|
70
|
+
function buildTriggerEntry(key, raw, capability, contract) {
|
|
71
|
+
const location = `TRIGGERS entry ${key} in ${capability}/schemas/triggers.yaml`;
|
|
72
|
+
const id = raw.id;
|
|
73
|
+
if (typeof id !== "string" || !id) {
|
|
74
|
+
throw new TriggerLoaderError([`${location} missing 'id'`]);
|
|
75
|
+
}
|
|
76
|
+
const description = raw.description;
|
|
77
|
+
if (typeof description !== "string" || description.trim() === "") {
|
|
78
|
+
throw new TriggerLoaderError([`${location} missing 'description'`]);
|
|
79
|
+
}
|
|
80
|
+
const priorityRaw = raw.priority;
|
|
81
|
+
if (typeof priorityRaw !== "string" ||
|
|
82
|
+
!contract.triggerPriorityRules.allowedValues.includes(priorityRaw)) {
|
|
83
|
+
throw new TriggerLoaderError([
|
|
84
|
+
`${location} has invalid priority=${JSON.stringify(priorityRaw)} (must be one of: ${contract.triggerPriorityRules.allowedValues.join(", ")})`,
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
const priority = priorityRaw;
|
|
88
|
+
const disambiguatesAgainst = resolveDisambiguation(raw.disambiguates_against, location, contract.triggerEnrichment.allowedCapabilityIds);
|
|
89
|
+
const fallback = raw.fallback === true;
|
|
90
|
+
return {
|
|
91
|
+
id,
|
|
92
|
+
description,
|
|
93
|
+
priority,
|
|
94
|
+
disambiguatesAgainst,
|
|
95
|
+
fallback,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function buildCapabilityTriggers(capability, contract, sourceRoot) {
|
|
99
|
+
const filePath = triggersYamlPath(capability, sourceRoot);
|
|
100
|
+
const data = readTriggersYaml(filePath);
|
|
101
|
+
const triggersGroup = data.TRIGGERS;
|
|
102
|
+
if (!isMapping(triggersGroup)) {
|
|
103
|
+
throw new TriggerLoaderError([
|
|
104
|
+
`${capability}/schemas/triggers.yaml is missing the TRIGGERS group`,
|
|
105
|
+
]);
|
|
106
|
+
}
|
|
107
|
+
const triggers = [];
|
|
108
|
+
for (const key of Object.keys(triggersGroup)) {
|
|
109
|
+
if (!isNumericKey(key)) {
|
|
110
|
+
throw new TriggerLoaderError([
|
|
111
|
+
`${capability}/schemas/triggers.yaml has non-numeric key ${JSON.stringify(key)} in TRIGGERS`,
|
|
112
|
+
]);
|
|
113
|
+
}
|
|
114
|
+
const entry = triggersGroup[key];
|
|
115
|
+
if (!isMapping(entry)) {
|
|
116
|
+
throw new TriggerLoaderError([
|
|
117
|
+
`TRIGGERS entry ${key} in ${capability}/schemas/triggers.yaml is not a mapping`,
|
|
118
|
+
]);
|
|
119
|
+
}
|
|
120
|
+
triggers.push(buildTriggerEntry(key, entry, capability, contract));
|
|
121
|
+
}
|
|
122
|
+
return { capability, triggers };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Load all twelve capability triggers.yaml files into a typed active
|
|
126
|
+
* TriggerModel.
|
|
127
|
+
* The capability set is the ROUTE_ALIASES.primary_aliases list owned by the
|
|
128
|
+
* capability schema contract. Absent `disambiguates_against` defaults to an
|
|
129
|
+
* empty list; its capability references are validated against the canonical
|
|
130
|
+
* capability IDs and each must resolve to a capability present in the returned
|
|
131
|
+
* model.
|
|
132
|
+
*/
|
|
133
|
+
export function loadTriggerModel(contract, options = {}) {
|
|
134
|
+
const sourceRoot = options.sourceRoot ?? resolveSourceRoot();
|
|
135
|
+
const capabilities = contract.routeAliases.primaryAliases.map((alias) => alias.capability);
|
|
136
|
+
const errors = [];
|
|
137
|
+
const model = new Map();
|
|
138
|
+
for (const capability of capabilities) {
|
|
139
|
+
try {
|
|
140
|
+
model.set(capability, buildCapabilityTriggers(capability, contract, sourceRoot));
|
|
141
|
+
}
|
|
142
|
+
catch (exc) {
|
|
143
|
+
if (exc instanceof TriggerLoaderError) {
|
|
144
|
+
errors.push(...exc.errors);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
throw exc;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (errors.length > 0) {
|
|
152
|
+
throw new TriggerLoaderError(errors);
|
|
153
|
+
}
|
|
154
|
+
// Resolve disambiguates_against references: each capability referenced must
|
|
155
|
+
// resolve to a capability present in the model with at least one trigger.
|
|
156
|
+
const resolutionErrors = [];
|
|
157
|
+
for (const { capability, triggers } of model.values()) {
|
|
158
|
+
for (const entry of triggers) {
|
|
159
|
+
for (const ref of entry.disambiguatesAgainst) {
|
|
160
|
+
const referenced = model.get(ref.capability);
|
|
161
|
+
if (!referenced) {
|
|
162
|
+
resolutionErrors.push(`TRIGGERS entry ${entry.id} in ${capability}/schemas/triggers.yaml disambiguates_against.capability=${JSON.stringify(ref.capability)} does not resolve to a loaded capability`);
|
|
163
|
+
}
|
|
164
|
+
else if (referenced.triggers.length === 0) {
|
|
165
|
+
resolutionErrors.push(`TRIGGERS entry ${entry.id} in ${capability}/schemas/triggers.yaml disambiguates_against.capability=${JSON.stringify(ref.capability)} resolves to a capability with no trigger entries`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (resolutionErrors.length > 0) {
|
|
171
|
+
throw new TriggerLoaderError(resolutionErrors);
|
|
172
|
+
}
|
|
173
|
+
return { capabilities: model };
|
|
174
|
+
}
|