agentera 3.0.0-dev.6 → 3.0.0-dev.69
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 +118 -22
- package/bundle/CHANGELOG.md +1361 -0
- package/bundle/DESIGN.md +229 -0
- package/bundle/LICENSE +201 -0
- package/bundle/README.md +143 -0
- package/bundle/UPGRADE.md +252 -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 +488 -0
- package/bundle/references/adapters/package-registry.yaml +435 -188
- package/bundle/references/adapters/package-surface-characterization.md +66 -34
- 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 +266 -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 +3061 -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 -2
- package/bundle/references/cli/vocabulary-index.yaml +20 -17
- package/bundle/references/cli/vocabulary.md +325 -362
- package/bundle/references/meta/retained-reference-authority.yaml +151 -0
- package/bundle/registry.json +13 -13
- package/bundle/skills/agentera/SKILL.md +226 -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 +103 -0
- package/bundle/skills/agentera/capabilities/{realisera → build}/schemas/exit.yaml +8 -6
- package/bundle/skills/agentera/capabilities/build/schemas/triggers.yaml +27 -0
- package/bundle/skills/agentera/capabilities/build/schemas/validation.yaml +184 -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 +461 -36
- package/bundle/skills/agentera/schemas/artifacts/progress.yaml +133 -20
- 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 +101 -12
- package/dist/analytics/extractCorpus/copilotSessions.js +53 -9
- package/dist/analytics/extractCorpus/core.js +59 -24
- package/dist/analytics/extractCorpus/corpus.js +58 -23
- package/dist/analytics/extractCorpus/coverageAudit.js +260 -0
- package/dist/analytics/extractCorpus/cursorSessions.js +12 -7
- package/dist/analytics/extractCorpus/evidenceTiers.js +603 -0
- package/dist/analytics/extractCorpus/extractCorpusParity.js +105 -0
- package/dist/analytics/extractCorpus/filesystemSources.js +1 -5
- package/dist/analytics/extractCorpus/index.js +6 -1
- package/dist/analytics/extractCorpus/jsonlSessions.js +24 -5
- package/dist/analytics/extractCorpus/sqliteCaps.js +43 -0
- package/dist/analytics/extractCorpus/sqliteSessions.js +98 -6
- 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 +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 +59 -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 +25 -17
- package/dist/cli/capabilityContext/bespoke.js +31 -12
- package/dist/cli/capabilityContext/build.js +251 -0
- package/dist/cli/capabilityContext/closeout.js +33 -30
- package/dist/cli/capabilityContext/contract.js +39 -46
- package/dist/cli/capabilityContext/evidence.js +90 -73
- package/dist/cli/capabilityContext/index.js +1 -2
- package/dist/cli/capabilityContext/orchestration.js +45 -21
- package/dist/cli/capabilityContext/planState.js +93 -100
- package/dist/cli/capabilityContext/progress.js +60 -14
- package/dist/cli/capabilityContext/projectVerification.js +409 -0
- package/dist/cli/capabilityContext/shared.js +9 -20
- package/dist/cli/capabilityContext/slim.js +56 -10
- package/dist/cli/capabilityContext/startup.js +57 -115
- package/dist/cli/capabilityContext/startupAggregation.js +68 -0
- package/dist/cli/capabilityContext/types.js +37 -24
- package/dist/cli/capabilityContext.js +1 -2
- package/dist/cli/commands/appHome.js +22 -0
- package/dist/cli/commands/capability.js +4 -4
- package/dist/cli/commands/compact.js +163 -13
- package/dist/cli/commands/doctor.js +122 -114
- 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/personalGlossary.js +176 -0
- package/dist/cli/commands/prime/briefOrientation.js +746 -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 +219 -0
- package/dist/cli/commands/prime/orientationOutput.js +421 -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 +77 -52
- package/dist/cli/commands/report.js +88 -26
- package/dist/cli/commands/route.js +142 -0
- package/dist/cli/commands/schema.js +266 -142
- package/dist/cli/commands/state/decisions.js +51 -61
- package/dist/cli/commands/state/docs.js +63 -86
- package/dist/cli/commands/state/experimentRecords.js +151 -0
- package/dist/cli/commands/state/experiments.js +11 -64
- package/dist/cli/commands/state/get.js +129 -0
- package/dist/cli/commands/state/health.js +11 -111
- 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 -64
- package/dist/cli/commands/state/plan.js +11 -169
- 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 +29 -108
- package/dist/cli/commands/state/write.js +433 -0
- package/dist/cli/commands/upgrade.js +146 -5
- package/dist/cli/commands/upgradeVerify.js +118 -0
- package/dist/cli/commands/validate.js +246 -211
- 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 +94 -50
- package/dist/cli/dispatch/commands.js +27 -0
- package/dist/cli/dispatch/index.js +82 -52
- package/dist/cli/dispatch/lifecycle.js +268 -108
- package/dist/cli/dispatch/prime.js +68 -29
- package/dist/cli/dispatch/projections.js +17 -0
- package/dist/cli/dispatch/shared.js +1 -2
- package/dist/cli/dispatch/state.js +68 -77
- package/dist/cli/dispatch.js +0 -1
- package/dist/cli/errors.js +16 -17
- package/dist/cli/help.js +395 -41
- package/dist/cli/migrationRequired.js +122 -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 +3 -56
- package/dist/hooks/compaction/apply.js +252 -50
- package/dist/hooks/compaction/dryRun.js +7 -4
- package/dist/hooks/compaction/index.js +5 -6
- package/dist/hooks/compaction/parse.js +201 -5
- package/dist/hooks/compaction/retention.js +30 -25
- package/dist/hooks/compaction/status.js +149 -32
- package/dist/hooks/compaction/types.js +0 -1
- package/dist/hooks/validateArtifact/agentFacing.js +0 -1
- package/dist/hooks/validateArtifact/index.js +7 -64
- package/dist/hooks/validateArtifact/markdown.js +57 -7
- package/dist/hooks/validateArtifact/schema.js +110 -19
- package/dist/hooks/validateArtifact/traversal.js +13 -11
- package/dist/hooks/validateArtifact/violations.js +7 -5
- package/dist/migrate/v2HandoffManifest.js +127 -8
- package/dist/registries/activationContract.js +2 -0
- package/dist/registries/activationTuples.js +108 -0
- package/dist/registries/artifactProtocolIds.js +2 -1
- 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 +273 -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 +156 -6
- 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 -13
- 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 +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 +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 +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 +92 -27
- package/dist/state/startupAnalysis/contract.js +48 -10
- package/dist/state/startupAnalysis/helpers.js +27 -73
- package/dist/state/startupAnalysis/index.js +0 -1
- package/dist/state/startupAnalysis/metrics.js +25 -19
- package/dist/state/startupAnalysis/records.js +13 -10
- package/dist/state/startupAnalysis/report.js +26 -38
- package/dist/state/startupAnalysis/threshold.js +19 -7
- 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/todoDocsEntities.js +1124 -0
- package/dist/state/todoDocsEntityValidation.js +158 -0
- package/dist/state/todoMarkdownProjection.js +51 -0
- package/dist/state/todoReconciliationActivation.js +182 -0
- package/dist/state/todoReconciliationInspection.js +171 -0
- package/dist/state/todoReconciliationRepair.js +318 -0
- package/dist/state/todoReconciliationTransaction.js +595 -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 +377 -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 +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 +165 -199
- 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 +375 -79
- package/dist/upgrade/migrationPublication.js +122 -0
- package/dist/upgrade/nextMajorDoctor.js +29 -10
- package/dist/upgrade/npxPlatformStatus.js +22 -0
- package/dist/upgrade/projectIntegration.js +145 -189
- package/dist/upgrade/projectIntegrationDecision.js +50 -0
- package/dist/upgrade/retiredResourceDiagnostics.js +117 -0
- package/dist/upgrade/runtimeMigration.js +272 -373
- 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 +2 -3
- package/dist/upgrade/versionResolution.js +2 -3
- package/dist/validate/activationArtifactEvidence.js +852 -0
- package/dist/validate/activationArtifactEvidenceTypes.js +12 -0
- package/dist/validate/activationConjunction.js +816 -0
- package/dist/validate/activationEvidenceManifest.js +531 -0
- package/dist/validate/activationPackageSemantics.js +29 -0
- package/dist/validate/appHomeContract.js +2 -8
- 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 +39 -45
- package/dist/validate/v1LegacyCruft.js +131 -0
- package/dist/validate/vocabularyAuthority.js +18 -13
- package/package.json +60 -29
- 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 -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 -9
- 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 -31
- 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/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/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/cursorSessions.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/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/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/benchmark.js.map +0 -1
- package/dist/cli/capabilityContext/bespoke.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/realisera.js +0 -174
- package/dist/cli/capabilityContext/realisera.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/backfill.js +0 -84
- package/dist/cli/commands/backfill.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/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/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/check.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.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/git.js +0 -43
- package/dist/core/git.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/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 -203
- 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 -83
- 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/hooks/validateArtifact.js +0 -924
- package/dist/hooks/validateArtifact.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 -315
- package/dist/registries/runtimeAdapterRegistry.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 -644
- 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 -127
- package/dist/setup/cursor.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 -247
- package/dist/setup/doctor/diagnostics.js.map +0 -1
- package/dist/setup/doctor/opencode.js +0 -281
- package/dist/setup/doctor/opencode.js.map +0 -1
- package/dist/setup/doctor/report.js +0 -474
- 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/progressCommit.js +0 -289
- package/dist/state/progressCommit.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/appModel.js.map +0 -1
- package/dist/upgrade/channels.js.map +0 -1
- package/dist/upgrade/coexistenceProbe.js +0 -83
- 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/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/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.js +0 -772
- package/dist/validate/lifecycleAdapters.js.map +0 -1
- package/dist/validate/selfAudit.js.map +0 -1
- package/dist/validate/vocabularyAuthority.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,18 @@
|
|
|
1
|
+
export class ExactReplacementConflictError extends Error {
|
|
2
|
+
retainedPaths;
|
|
3
|
+
constructor(message, retainedPaths = []) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.retainedPaths = retainedPaths;
|
|
6
|
+
this.name = "ExactReplacementConflictError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export class FileReplacementError extends Error {
|
|
10
|
+
code;
|
|
11
|
+
constructor(message, cause) {
|
|
12
|
+
super(message, { cause });
|
|
13
|
+
this.name = "FileReplacementError";
|
|
14
|
+
const code = cause?.code;
|
|
15
|
+
if (typeof code === "string")
|
|
16
|
+
this.code = code;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { dumpYamlMapping } from "../core/yaml.js";
|
|
5
|
+
import { assertRealpathBoundary } from "../registries/artifactRegistry.js";
|
|
6
|
+
import { canonicalRecordJson } from "./archiveDiscovery.js";
|
|
7
|
+
import { reject } from "./write/errors.js";
|
|
8
|
+
const AUTHORITY = "references/artifacts/state-storage-authority.yaml";
|
|
9
|
+
export function prepareExperimentArchive(projectRoot, objectivePath, objectiveId, experimentNumber, record) {
|
|
10
|
+
if (record.number !== experimentNumber)
|
|
11
|
+
throw new Error(`experiment archive record number must equal ${experimentNumber}`);
|
|
12
|
+
const stableId = `${objectiveId}/experiment:${experimentNumber}`;
|
|
13
|
+
const target = path.join(path.dirname(objectivePath), "archive", "experiments", `${experimentNumber}.yaml`);
|
|
14
|
+
assertRealpathBoundary(projectRoot, target, "experiment archive");
|
|
15
|
+
const canonical = canonicalRecordJson(record);
|
|
16
|
+
const recordSha256 = createHash("sha256").update(canonical, "utf8").digest("hex");
|
|
17
|
+
const provenance = {
|
|
18
|
+
authority: AUTHORITY,
|
|
19
|
+
objective_id: objectiveId,
|
|
20
|
+
experiment_id: stableId,
|
|
21
|
+
storage_scope: "objective_directory",
|
|
22
|
+
publication_order: "archive_before_projection",
|
|
23
|
+
};
|
|
24
|
+
const envelope = {
|
|
25
|
+
schemaVersion: "agentera.experimentArchive.v1",
|
|
26
|
+
stable_id: stableId,
|
|
27
|
+
objective_id: objectiveId,
|
|
28
|
+
experiment_number: experimentNumber,
|
|
29
|
+
record,
|
|
30
|
+
record_sha256: recordSha256,
|
|
31
|
+
provenance,
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
target,
|
|
35
|
+
directoryDurabilityRoot: path.dirname(objectivePath),
|
|
36
|
+
bytes: dumpYamlMapping(envelope),
|
|
37
|
+
stableId,
|
|
38
|
+
recordSha256,
|
|
39
|
+
provenance,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function assertExperimentArchiveReplay(publication) {
|
|
43
|
+
let existing;
|
|
44
|
+
try {
|
|
45
|
+
existing = fs.readFileSync(publication.target);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
reject({
|
|
49
|
+
class: "conflict",
|
|
50
|
+
message: `immutable experiment archive '${publication.target}' could not be read; existing state was preserved`,
|
|
51
|
+
violations: [`immutable archive identity: ${publication.stableId}`],
|
|
52
|
+
recovery: "Repair the unreadable archive record before retrying publication.",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (existing.equals(Buffer.from(publication.bytes, "utf8")))
|
|
56
|
+
return;
|
|
57
|
+
reject({
|
|
58
|
+
class: "conflict",
|
|
59
|
+
message: `immutable experiment archive '${publication.target}' already exists with different bytes; existing archive and projection were preserved`,
|
|
60
|
+
violations: [`immutable archive identity: ${publication.stableId}`],
|
|
61
|
+
recovery: "Retry only with the byte-equivalent experiment record for this stable identity.",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { loadYamlMapping } from "../core/yaml.js";
|
|
5
|
+
import { canonicalRecordJson } from "./archiveDiscovery.js";
|
|
6
|
+
export const PERSISTED_OBJECTIVE_ID = /^objective:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
7
|
+
export const LEGACY_OBJECTIVE_ID = /^legacy-objective:[0-9a-f]{64}$/;
|
|
8
|
+
export const OBJECTIVE_ID = /^(objective:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|legacy-objective:[0-9a-f]{64})$/;
|
|
9
|
+
function mapping(value) {
|
|
10
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
11
|
+
}
|
|
12
|
+
function list(value) {
|
|
13
|
+
return Array.isArray(value) ? value.filter((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry)) : [];
|
|
14
|
+
}
|
|
15
|
+
/** Identity inputs deliberately exclude title, lifecycle, closure, root, and slug. */
|
|
16
|
+
export function canonicalObjectiveIdentityDocument(document) {
|
|
17
|
+
const objective = mapping(document.objective);
|
|
18
|
+
return {
|
|
19
|
+
baseline: mapping(document.baseline),
|
|
20
|
+
constraints: document.constraints ?? objective.constraints ?? [],
|
|
21
|
+
description: objective.description ?? document.description ?? "",
|
|
22
|
+
gates: mapping(document.gates),
|
|
23
|
+
measurement: objective.measurement ?? document.measurement ?? "",
|
|
24
|
+
metric: mapping(document.metric),
|
|
25
|
+
scope: mapping(document.scope),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function resolveObjectiveIdentity(document) {
|
|
29
|
+
const canonicalJson = canonicalRecordJson(canonicalObjectiveIdentityDocument(document));
|
|
30
|
+
const persisted = mapping(document.header).id;
|
|
31
|
+
if (persisted !== undefined) {
|
|
32
|
+
if (typeof persisted !== "string" || !PERSISTED_OBJECTIVE_ID.test(persisted)) {
|
|
33
|
+
throw new Error("objective header.id is not a valid persisted objective identity");
|
|
34
|
+
}
|
|
35
|
+
return { stableId: persisted, persisted: true, canonicalJson, compatibility: "canonical" };
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
stableId: `legacy-objective:${createHash("sha256").update(canonicalJson, "utf8").digest("hex")}`,
|
|
39
|
+
persisted: false,
|
|
40
|
+
canonicalJson,
|
|
41
|
+
compatibility: "legacy_derived_identity",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function discoverObjectiveArtifacts(projectRoot, sourceBytes) {
|
|
45
|
+
const inspected = [];
|
|
46
|
+
const diagnostics = [];
|
|
47
|
+
for (const root of ["optimize", "optimera"]) {
|
|
48
|
+
const directory = path.join(projectRoot, ".agentera", root);
|
|
49
|
+
let sources = [];
|
|
50
|
+
if (sourceBytes) {
|
|
51
|
+
sources = [...sourceBytes.entries()].flatMap(([objectivePath, bytes]) => {
|
|
52
|
+
const candidate = path.relative(directory, objectivePath).split(path.sep);
|
|
53
|
+
return candidate.length === 2 && candidate[1] === "objective.yaml"
|
|
54
|
+
? [{ slug: candidate[0], objectivePath, bytes }]
|
|
55
|
+
: [];
|
|
56
|
+
}).sort((left, right) => left.slug.localeCompare(right.slug));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
let slugs = [];
|
|
60
|
+
try {
|
|
61
|
+
slugs = fs.readdirSync(directory).sort();
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
sources = slugs.flatMap((slug) => {
|
|
67
|
+
const objectivePath = path.join(directory, slug, "objective.yaml");
|
|
68
|
+
return fs.existsSync(objectivePath) ? [{ slug, objectivePath }] : [];
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
for (const { slug, objectivePath, bytes } of sources) {
|
|
72
|
+
try {
|
|
73
|
+
const identity = resolveObjectiveIdentity(loadYamlMapping(bytes !== undefined ? bytes.toString("utf8") : fs.readFileSync(objectivePath, "utf8")));
|
|
74
|
+
inspected.push({ ...identity, path: objectivePath, slug, root });
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
diagnostics.push({
|
|
78
|
+
class: "corrupt",
|
|
79
|
+
message: error.message,
|
|
80
|
+
candidate_paths: [objectivePath],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const objectives = [];
|
|
86
|
+
for (const stableId of [...new Set(inspected.map((candidate) => candidate.stableId))].sort()) {
|
|
87
|
+
const candidates = inspected.filter((candidate) => candidate.stableId === stableId);
|
|
88
|
+
const ambiguous = new Set(candidates.map((candidate) => candidate.canonicalJson)).size > 1;
|
|
89
|
+
if (ambiguous) {
|
|
90
|
+
diagnostics.push({
|
|
91
|
+
class: "ambiguous",
|
|
92
|
+
message: `objective identity ${stableId} resolves to conflicting documents`,
|
|
93
|
+
stable_id: stableId,
|
|
94
|
+
candidate_paths: candidates.map((candidate) => candidate.path).sort(),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
objectives.push({
|
|
98
|
+
stableId,
|
|
99
|
+
persisted: candidates.every((candidate) => candidate.persisted),
|
|
100
|
+
canonicalJson: candidates[0].canonicalJson,
|
|
101
|
+
compatibility: candidates.every((candidate) => candidate.persisted) ? "canonical" : "legacy_derived_identity",
|
|
102
|
+
paths: candidates.map((candidate) => candidate.path).sort(),
|
|
103
|
+
slugs: [...new Set(candidates.map((candidate) => candidate.slug))].sort(),
|
|
104
|
+
roots: [...new Set(candidates.map((candidate) => candidate.root))].sort(),
|
|
105
|
+
ambiguous,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
for (const slug of [...new Set(inspected.map((candidate) => candidate.slug))].sort()) {
|
|
109
|
+
const candidates = inspected.filter((candidate) => candidate.slug === slug);
|
|
110
|
+
const roots = new Set(candidates.map((candidate) => candidate.root));
|
|
111
|
+
const candidateIds = [...new Set(candidates.map((candidate) => candidate.stableId))].sort();
|
|
112
|
+
if (roots.size === 2 && candidateIds.length > 1) {
|
|
113
|
+
const candidatePaths = candidates.map((candidate) => candidate.path).sort();
|
|
114
|
+
diagnostics.push({
|
|
115
|
+
class: "ambiguous",
|
|
116
|
+
message: `canonical and legacy objective roots conflict for slug ${slug}`,
|
|
117
|
+
slug,
|
|
118
|
+
candidate_ids: candidateIds,
|
|
119
|
+
candidate_paths: candidatePaths,
|
|
120
|
+
});
|
|
121
|
+
for (const objective of objectives.filter((candidate) => candidateIds.includes(candidate.stableId)))
|
|
122
|
+
objective.ambiguous = true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return { objectives, diagnostics };
|
|
126
|
+
}
|
|
127
|
+
export function inspectExperimentIdentities(objectiveId, document) {
|
|
128
|
+
if (!OBJECTIVE_ID.test(objectiveId))
|
|
129
|
+
throw new Error("objective identity is invalid");
|
|
130
|
+
const collections = [
|
|
131
|
+
["experiments", list(document.experiments)],
|
|
132
|
+
["archive", list(document.archive)],
|
|
133
|
+
["archived_experiments", list(document.archived_experiments)],
|
|
134
|
+
];
|
|
135
|
+
const counts = new Map();
|
|
136
|
+
for (const [, entries] of collections) {
|
|
137
|
+
for (const entry of entries) {
|
|
138
|
+
if (Number.isInteger(entry.number) && Number(entry.number) >= 0)
|
|
139
|
+
counts.set(Number(entry.number), (counts.get(Number(entry.number)) ?? 0) + 1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const caveats = [];
|
|
143
|
+
const entries = collections.flatMap(([collection, values]) => values.map((data, index) => {
|
|
144
|
+
const number = Number.isInteger(data.number) && Number(data.number) >= 0 ? Number(data.number) : null;
|
|
145
|
+
let compatibility = "canonical";
|
|
146
|
+
const entryCaveats = [];
|
|
147
|
+
if (data.number === undefined || data.number === null) {
|
|
148
|
+
compatibility = "legacy_missing_identity";
|
|
149
|
+
entryCaveats.push(`legacy ${collection}[${index}] is missing experiment number and remains visible but unaddressable`);
|
|
150
|
+
}
|
|
151
|
+
else if (number === null) {
|
|
152
|
+
compatibility = "legacy_invalid_identity";
|
|
153
|
+
entryCaveats.push(`legacy ${collection}[${index}] has invalid experiment number and remains visible but unaddressable`);
|
|
154
|
+
}
|
|
155
|
+
else if ((counts.get(number) ?? 0) > 1) {
|
|
156
|
+
compatibility = "legacy_duplicate_identity";
|
|
157
|
+
entryCaveats.push(`duplicate experiment number ${number} remains visible but ambiguous and unaddressable`);
|
|
158
|
+
}
|
|
159
|
+
caveats.push(...entryCaveats);
|
|
160
|
+
return {
|
|
161
|
+
stableId: number === null ? null : `${objectiveId}/experiment:${number}`,
|
|
162
|
+
number,
|
|
163
|
+
addressable: compatibility === "canonical",
|
|
164
|
+
compatibility,
|
|
165
|
+
provenance: { collection, index },
|
|
166
|
+
data,
|
|
167
|
+
caveats: entryCaveats,
|
|
168
|
+
};
|
|
169
|
+
}));
|
|
170
|
+
return { objectiveId, entries, caveats: [...new Set(caveats)] };
|
|
171
|
+
}
|
|
172
|
+
export class ExperimentIdentityError extends Error {
|
|
173
|
+
className;
|
|
174
|
+
details;
|
|
175
|
+
constructor(className, message, details = {}) {
|
|
176
|
+
super(message);
|
|
177
|
+
this.className = className;
|
|
178
|
+
this.details = details;
|
|
179
|
+
this.name = "ExperimentIdentityError";
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/** Pure preflight used by later publication work; this function never changes project state. */
|
|
183
|
+
export function validateExperimentPublicationIdentity(discovery, projection, objectiveId, number) {
|
|
184
|
+
if (!OBJECTIVE_ID.test(objectiveId) || !Number.isInteger(number) || number < 0) {
|
|
185
|
+
throw new ExperimentIdentityError("invalid_request", "publication requires a valid objective identity and non-negative integer experiment number");
|
|
186
|
+
}
|
|
187
|
+
const objective = discovery.objectives.find((candidate) => candidate.stableId === objectiveId);
|
|
188
|
+
if (!objective)
|
|
189
|
+
throw new ExperimentIdentityError("not_found", `objective identity ${objectiveId} was not found`);
|
|
190
|
+
if (objective.ambiguous || projection.objectiveId !== objectiveId || projection.entries.some((entry) => !entry.addressable)) {
|
|
191
|
+
throw new ExperimentIdentityError("ambiguous", "experiment publication identity is ambiguous; no effects are allowed", {
|
|
192
|
+
stable_id: `${objectiveId}/experiment:${number}`,
|
|
193
|
+
candidate_paths: objective.paths,
|
|
194
|
+
compatibility_caveats: projection.caveats,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
const stableId = `${objectiveId}/experiment:${number}`;
|
|
198
|
+
if (projection.entries.some((entry) => entry.stableId === stableId)) {
|
|
199
|
+
throw new ExperimentIdentityError("ambiguous", `experiment identity ${stableId} already exists; no effects are allowed`, { stable_id: stableId });
|
|
200
|
+
}
|
|
201
|
+
return stableId;
|
|
202
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { resolveSourceRoot } from "../core/sourceRoot.js";
|
|
3
|
+
import { canonicalRecordJson } from "./archiveDiscovery.js";
|
|
4
|
+
import { StateRetrievalFailure } from "./directRetrieval.js";
|
|
5
|
+
import { allocateAndPublishEntity, allocateEntityId, assertEntityDiscoveryOrigin, discoverEntities, publishEntity, } from "./entityStorage.js";
|
|
6
|
+
import { healthEntityViolations } from "./healthEntityValidation.js";
|
|
7
|
+
import { detailMetadata, detailProvenance, isSummaryEntity } from "./summaryEntityRead.js";
|
|
8
|
+
import { decodeListCursor, encodeListCursor, projectedListSnapshot } from "./listCursor.js";
|
|
9
|
+
import { localDate } from "./write/assign.js";
|
|
10
|
+
import { loadStateStorageAuthority } from "./stateStorageAuthority.js";
|
|
11
|
+
import { entityListSelectorFlags, entityListSelectorKey, projectEntityList, resolveEntityListSelector } from "./entityListProjection.js";
|
|
12
|
+
import { shellQuoteArgument } from "../core/shell.js";
|
|
13
|
+
const ARTIFACT = "health";
|
|
14
|
+
const BOUNDARY = "health_audit";
|
|
15
|
+
const SUMMARY = "health_summary";
|
|
16
|
+
const ORDER = "appended_at_desc_then_id_asc_then_legacy_date_desc_then_id_asc";
|
|
17
|
+
const ID_PATTERN = /^[a-z]{10}$/;
|
|
18
|
+
function mapping(value) {
|
|
19
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
20
|
+
}
|
|
21
|
+
function positive(value, field) {
|
|
22
|
+
const result = Number(value);
|
|
23
|
+
if (!Number.isSafeInteger(result) || result < 1)
|
|
24
|
+
throw new Error(`invalid health entity ${field} authority`);
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
function contract(sourceRoot = resolveSourceRoot()) {
|
|
28
|
+
const { authorityPath, document: authority } = loadStateStorageAuthority(sourceRoot);
|
|
29
|
+
const target = mapping(authority.entity_target) ? authority.entity_target : {};
|
|
30
|
+
const storage = mapping(target.storage_boundary) && mapping(target.storage_boundary.shared_primitives)
|
|
31
|
+
? target.storage_boundary.shared_primitives
|
|
32
|
+
: {};
|
|
33
|
+
const entities = Array.isArray(target.entities) ? target.entities : [];
|
|
34
|
+
const health = entities.find((value) => mapping(value) && value.boundary === BOUNDARY && value.artifact === ARTIFACT);
|
|
35
|
+
const retrieval = mapping(health) && mapping(health.retrieval) ? health.retrieval : {};
|
|
36
|
+
if (typeof storage.canonical_root !== "string")
|
|
37
|
+
throw new Error(`invalid health entity contract in '${authorityPath}'`);
|
|
38
|
+
return {
|
|
39
|
+
authorityPath,
|
|
40
|
+
entityRoot: storage.canonical_root,
|
|
41
|
+
defaultLimit: positive(retrieval.default_limit, "default_limit"),
|
|
42
|
+
maximumLimit: positive(retrieval.maximum_limit, "maximum_limit"),
|
|
43
|
+
maxUtf8Bytes: positive(retrieval.max_utf8_bytes, "max_utf8_bytes"),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function failure(kind, message, recovery, id, exitCode = 1) {
|
|
47
|
+
return new StateRetrievalFailure({
|
|
48
|
+
schemaVersion: "agentera.stateFailure.v1",
|
|
49
|
+
status: "fail",
|
|
50
|
+
error: {
|
|
51
|
+
class: kind,
|
|
52
|
+
message,
|
|
53
|
+
syntax: "agentera state health get --id ID --format json",
|
|
54
|
+
example: `agentera state health get --id ${id ?? "qjtrmnpvka"} --format json`,
|
|
55
|
+
recovery,
|
|
56
|
+
artifact: ARTIFACT,
|
|
57
|
+
...(id ? { id } : {}),
|
|
58
|
+
},
|
|
59
|
+
}, exitCode);
|
|
60
|
+
}
|
|
61
|
+
function listFailure(kind, message, recovery, exitCode = 1) {
|
|
62
|
+
const result = failure(kind, message, recovery, undefined, exitCode);
|
|
63
|
+
result.body.error.syntax = "agentera state health list [--limit N] [--cursor TOKEN] --format json";
|
|
64
|
+
result.body.error.example = "agentera state health list --limit 20 --format json";
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
function healthRecord(values) {
|
|
68
|
+
for (const field of ["id", "artifact", "number", "stable_id", "artifact_id", "entry_number", "appended_at"]) {
|
|
69
|
+
if (field in values)
|
|
70
|
+
throw new Error(`health entity record forbids identity field '${field}'`);
|
|
71
|
+
}
|
|
72
|
+
const record = structuredClone(values);
|
|
73
|
+
if (typeof record.date !== "string")
|
|
74
|
+
record.date = localDate();
|
|
75
|
+
record.appended_at = new Date().toISOString();
|
|
76
|
+
const violations = healthEntityViolations(record);
|
|
77
|
+
if (violations.length)
|
|
78
|
+
throw new Error(`health entity violates the canonical audit schema: ${violations.join("; ")}`);
|
|
79
|
+
return record;
|
|
80
|
+
}
|
|
81
|
+
function envelope(published, record, dryRun) {
|
|
82
|
+
return {
|
|
83
|
+
schemaVersion: "agentera.stateWrite.v1",
|
|
84
|
+
command: "state health append",
|
|
85
|
+
status: "pass",
|
|
86
|
+
path: published.path,
|
|
87
|
+
id: published.id,
|
|
88
|
+
artifact: published.artifact,
|
|
89
|
+
record,
|
|
90
|
+
operation: { verb: "append", dry_run: dryRun, idempotent_replay: published.replay },
|
|
91
|
+
validation: { status: "pass", violations: [] },
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function withoutAppendTimestamp(record) {
|
|
95
|
+
const copy = structuredClone(record);
|
|
96
|
+
delete copy.appended_at;
|
|
97
|
+
return copy;
|
|
98
|
+
}
|
|
99
|
+
function existingReplay(root, sourceRoot, id, record) {
|
|
100
|
+
const existing = discoverEntities(root, sourceRoot).entities.find((entity) => entity.id === id
|
|
101
|
+
&& entity.artifact === ARTIFACT
|
|
102
|
+
&& entity.boundary === BOUNDARY
|
|
103
|
+
&& entity.classification === "valid"
|
|
104
|
+
&& entity.record !== null
|
|
105
|
+
&& healthEntityViolations(entity.record).length === 0);
|
|
106
|
+
if (!existing || canonicalRecordJson(withoutAppendTimestamp(existing.record)) !== canonicalRecordJson(withoutAppendTimestamp(record)))
|
|
107
|
+
return null;
|
|
108
|
+
return existing;
|
|
109
|
+
}
|
|
110
|
+
export function appendHealthEntity(req, options = {}) {
|
|
111
|
+
const sourceRoot = options.sourceRoot ?? resolveSourceRoot();
|
|
112
|
+
const declared = contract(sourceRoot);
|
|
113
|
+
const record = healthRecord(req.input ?? req.values);
|
|
114
|
+
if (req.dryRun) {
|
|
115
|
+
options.publicationContext?.assertValid();
|
|
116
|
+
const id = options.id ?? allocateEntityId(options.publicationContext?.pinnedPath() ?? req.projectRoot, options.candidate, sourceRoot);
|
|
117
|
+
options.publicationContext?.assertValid();
|
|
118
|
+
return envelope({ path: path.join(path.resolve(req.projectRoot), declared.entityRoot, ARTIFACT, BOUNDARY, `${id}.yaml`), id, artifact: ARTIFACT, replay: false }, record, true);
|
|
119
|
+
}
|
|
120
|
+
if (options.id) {
|
|
121
|
+
const replay = existingReplay(req.projectRoot, sourceRoot, options.id, record);
|
|
122
|
+
if (replay)
|
|
123
|
+
return envelope({ path: replay.path, id: options.id, artifact: ARTIFACT, replay: true }, replay.record, false);
|
|
124
|
+
}
|
|
125
|
+
const published = options.id
|
|
126
|
+
? publishEntity({ projectRoot: req.projectRoot, sourceRoot, publicationContext: options.publicationContext, artifact: ARTIFACT, boundary: BOUNDARY, id: options.id, record })
|
|
127
|
+
: allocateAndPublishEntity({ projectRoot: req.projectRoot, sourceRoot, publicationContext: options.publicationContext, artifact: ARTIFACT, boundary: BOUNDARY, record }, options.candidate);
|
|
128
|
+
return envelope(published, record, false);
|
|
129
|
+
}
|
|
130
|
+
function relative(root, candidate) {
|
|
131
|
+
return path.relative(path.resolve(root), candidate).split(path.sep).join("/");
|
|
132
|
+
}
|
|
133
|
+
function healthEntities(root, sourceRoot, supplied) {
|
|
134
|
+
if (supplied)
|
|
135
|
+
assertEntityDiscoveryOrigin(root, sourceRoot, supplied);
|
|
136
|
+
const discovery = supplied ?? discoverEntities(root, sourceRoot);
|
|
137
|
+
const relevant = discovery.entities.filter((entity) => entity.artifact === ARTIFACT || entity.boundary === BOUNDARY);
|
|
138
|
+
const bad = relevant.find((entity) => entity.classification !== "valid" || !entity.id || !entity.record || (entity.boundary === BOUNDARY && healthEntityViolations(entity.record).length > 0));
|
|
139
|
+
if (bad)
|
|
140
|
+
throw listFailure(bad.classification === "duplicate" ? "ambiguous" : "corrupt", `health entity '${bad.relativePath}' is not canonical`, "Run agentera check validate state, preserve conflicting evidence, and repair the canonical entity files.");
|
|
141
|
+
return relevant;
|
|
142
|
+
}
|
|
143
|
+
function entry(root, entity) {
|
|
144
|
+
const id = entity.id;
|
|
145
|
+
return {
|
|
146
|
+
id,
|
|
147
|
+
artifact: ARTIFACT,
|
|
148
|
+
record: entity.record,
|
|
149
|
+
...detailMetadata(entity),
|
|
150
|
+
provenance: detailProvenance(relative(root, entity.path), entity),
|
|
151
|
+
retrieval: { get: `agentera state health get --id ${id} --format json` },
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
export function getHealthEntity(root, id, sourceRoot = resolveSourceRoot()) {
|
|
155
|
+
if (!ID_PATTERN.test(id))
|
|
156
|
+
throw failure("invalid_request", `health ID '${id}' must be ten lowercase letters`, "Use a bare ID returned by health append or list.", id, 2);
|
|
157
|
+
const all = discoverEntities(root, sourceRoot).entities;
|
|
158
|
+
const matches = all.filter((entity) => entity.id === id);
|
|
159
|
+
if (matches.length > 1 || matches.some((entity) => entity.classification === "duplicate"))
|
|
160
|
+
throw failure("ambiguous", `health entity ID '${id}' has multiple canonical candidates`, "Run agentera check validate state, preserve conflicting evidence, and assign unique IDs.", id);
|
|
161
|
+
const selected = matches[0];
|
|
162
|
+
const expectedPath = path.join(path.resolve(root), contract(sourceRoot).entityRoot, ARTIFACT, selected?.boundary === SUMMARY ? SUMMARY : BOUNDARY, `${id}.yaml`);
|
|
163
|
+
const canonical = all.find((entity) => entity.path === expectedPath);
|
|
164
|
+
if (!selected && canonical)
|
|
165
|
+
throw failure("corrupt", `health entity '${canonical.relativePath}' does not match its canonical ID envelope`, "Run agentera check validate state and repair the canonical entity file.", id);
|
|
166
|
+
if (!selected || selected.artifact !== ARTIFACT || ![BOUNDARY, SUMMARY].includes(selected.boundary ?? ""))
|
|
167
|
+
throw failure("not_found", `no health entity exists with ID '${id}'`, "Copy an ID from agentera state health list --format json and retry.", id);
|
|
168
|
+
if (selected.classification !== "valid" || !selected.record || (selected.boundary === BOUNDARY && healthEntityViolations(selected.record).length > 0))
|
|
169
|
+
throw failure("corrupt", `health entity '${selected.relativePath}' is corrupt or violates the audit contract`, "Run agentera check validate state, preserve its evidence, and repair the canonical entity file.", id);
|
|
170
|
+
return {
|
|
171
|
+
schemaVersion: "agentera.stateRetrieval.v1",
|
|
172
|
+
command: "state health get",
|
|
173
|
+
status: isSummaryEntity(selected) ? "degraded" : "ok",
|
|
174
|
+
entry: entry(root, selected),
|
|
175
|
+
source: { artifact: ARTIFACT, authority: "canonical_entity_file" },
|
|
176
|
+
source_contract: { authority: "references/artifacts/state-storage-authority.yaml", detail: isSummaryEntity(selected) ? "summary" : "full" },
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function appendTimestamp(entity) {
|
|
180
|
+
return typeof entity.record?.appended_at === "string" ? entity.record.appended_at : null;
|
|
181
|
+
}
|
|
182
|
+
function compareHealthEntities(left, right) {
|
|
183
|
+
const leftTimestamp = appendTimestamp(left);
|
|
184
|
+
const rightTimestamp = appendTimestamp(right);
|
|
185
|
+
if (leftTimestamp !== null && rightTimestamp !== null) {
|
|
186
|
+
return rightTimestamp.localeCompare(leftTimestamp) || left.id.localeCompare(right.id);
|
|
187
|
+
}
|
|
188
|
+
if (leftTimestamp !== null)
|
|
189
|
+
return -1;
|
|
190
|
+
if (rightTimestamp !== null)
|
|
191
|
+
return 1;
|
|
192
|
+
return String(right.record.date ?? "").localeCompare(String(left.record.date ?? "")) || left.id.localeCompare(right.id);
|
|
193
|
+
}
|
|
194
|
+
function key(entity) {
|
|
195
|
+
return `${appendTimestamp(entity) ?? String(entity.record.date ?? "")}\0${entity.id}`;
|
|
196
|
+
}
|
|
197
|
+
function snapshot(root, entities, dimension, entityRoot) {
|
|
198
|
+
return projectedListSnapshot({
|
|
199
|
+
schemaVersion: "agentera.stateList.v1",
|
|
200
|
+
command: "state health list",
|
|
201
|
+
order: ORDER,
|
|
202
|
+
filters: { dimension: dimension ?? null },
|
|
203
|
+
source: { artifact: ARTIFACT, authority: "canonical_entity_files", root: entityRoot },
|
|
204
|
+
source_contract: { authority: "references/artifacts/state-storage-authority.yaml", detail: entities.some(isSummaryEntity) ? "mixed" : "full", cursor: "opaque_snapshot_cursor" },
|
|
205
|
+
entries: entities.map((entity) => entry(root, entity)),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function encode(payload, root, authorityPath) {
|
|
209
|
+
return encodeListCursor(payload, root, authorityPath);
|
|
210
|
+
}
|
|
211
|
+
function decode(token, root, authorityPath) {
|
|
212
|
+
try {
|
|
213
|
+
return decodeListCursor(token, root, authorityPath);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
throw listFailure("cursor_invalid", "health cursor is malformed or belongs to another project", "Copy next_cursor exactly, or omit --cursor to restart.");
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export function listHealthEntities(root, limit, dimension, cursor, options = {}) {
|
|
220
|
+
const sourceRoot = options.sourceRoot ?? resolveSourceRoot();
|
|
221
|
+
const declared = contract(sourceRoot);
|
|
222
|
+
const effectiveLimit = limit ?? declared.defaultLimit;
|
|
223
|
+
if (!Number.isSafeInteger(effectiveLimit) || effectiveLimit < 1 || effectiveLimit > declared.maximumLimit)
|
|
224
|
+
throw listFailure("invalid_request", `health list limit must be 1..${declared.maximumLimit}`, "Use a limit in the declared range.", 2);
|
|
225
|
+
const all = healthEntities(root, sourceRoot, options.discovery);
|
|
226
|
+
let filtered = [...all].sort(compareHealthEntities);
|
|
227
|
+
if (dimension) {
|
|
228
|
+
const needle = dimension.toLowerCase();
|
|
229
|
+
filtered = filtered.filter((entity) => canonicalRecordJson(entity.record).toLowerCase().includes(needle));
|
|
230
|
+
}
|
|
231
|
+
const format = options.format ?? "json";
|
|
232
|
+
const projectionOptions = { family: "health", artifact: ARTIFACT, boundary: BOUNDARY, format, maxUtf8Bytes: declared.maxUtf8Bytes, selector: options.selector };
|
|
233
|
+
const selector = resolveEntityListSelector(options.selector, filtered.map((entity) => entry(root, entity)), projectionOptions);
|
|
234
|
+
const selectorKey = entityListSelectorKey(selector);
|
|
235
|
+
const snap = snapshot(root, filtered, dimension, declared.entityRoot);
|
|
236
|
+
let start = 0;
|
|
237
|
+
if (cursor) {
|
|
238
|
+
const value = decode(cursor, root, declared.authorityPath);
|
|
239
|
+
if (value.selector !== selectorKey)
|
|
240
|
+
throw listFailure("cursor_invalid", "health cursor selectors do not match this request", "Repeat the original selector, or omit --cursor to restart from the current snapshot.");
|
|
241
|
+
if (value.version !== 1 || value.artifact !== ARTIFACT || value.order !== ORDER || value.snapshot_id !== snap || value.dimension !== (dimension ?? null))
|
|
242
|
+
throw listFailure("cursor_snapshot_unavailable", "health state or filters changed after this cursor snapshot", "Repeat the original filters, or omit --cursor to restart from the current snapshot.");
|
|
243
|
+
const found = filtered.findIndex((entity) => key(entity) === value.after_key);
|
|
244
|
+
if (found < 0)
|
|
245
|
+
throw listFailure("cursor_snapshot_unavailable", "health cursor continuation is unavailable", "Omit --cursor to restart.");
|
|
246
|
+
start = found + 1;
|
|
247
|
+
}
|
|
248
|
+
const selected = filtered.slice(start, start + effectiveLimit);
|
|
249
|
+
const response = () => {
|
|
250
|
+
const remaining = filtered.length - start - selected.length;
|
|
251
|
+
const next = remaining && selected.length ? encode({ version: 1, artifact: ARTIFACT, order: ORDER, snapshot_id: snap, selector: selectorKey, dimension: dimension ?? null, after_key: key(selected.at(-1)) }, root, declared.authorityPath) : undefined;
|
|
252
|
+
const selectorFlags = entityListSelectorFlags(selector);
|
|
253
|
+
return {
|
|
254
|
+
schemaVersion: "agentera.stateList.v1", command: "state health list", status: remaining || filtered.some(isSummaryEntity) ? "degraded" : "ok", entries: selected.map((entity) => entry(root, entity)),
|
|
255
|
+
counts: { total: filtered.length, returned: selected.length, remaining }, filters: { dimension: dimension ?? null }, snapshot: { id: snap, first_page: !cursor, order: ORDER, has_more: Boolean(remaining), candidate_count: filtered.length },
|
|
256
|
+
source: { artifact: ARTIFACT, authority: "canonical_entity_files", root: declared.entityRoot }, source_contract: { authority: "references/artifacts/state-storage-authority.yaml", detail: filtered.some(isSummaryEntity) ? "mixed" : "full", cursor: "opaque_snapshot_cursor" },
|
|
257
|
+
retrieval: { ...(next ? { continue: `agentera state health list${dimension ? ` --dimension ${shellQuoteArgument(dimension)}` : ""}${selectorFlags} --limit ${effectiveLimit} --cursor ${next} --format json` } : {}) },
|
|
258
|
+
...(remaining ? { omitted: true, omitted_count: remaining, omission_reason: "page_limit", next_cursor: next } : {}),
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
return projectEntityList(response(), selector, projectionOptions);
|
|
262
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { dumpYamlMapping } from "../core/yaml.js";
|
|
2
|
+
import { validateArtifactBytes } from "./write/validate.js";
|
|
3
|
+
export function healthEntityViolations(record) {
|
|
4
|
+
const violations = validateArtifactBytes("health", dumpYamlMapping({ audits: [{ number: 1, ...record }] }));
|
|
5
|
+
if (record.appended_at !== undefined) {
|
|
6
|
+
const value = record.appended_at;
|
|
7
|
+
let canonical = false;
|
|
8
|
+
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(value)) {
|
|
9
|
+
try {
|
|
10
|
+
canonical = new Date(value).toISOString() === value;
|
|
11
|
+
}
|
|
12
|
+
catch { /* invalid timestamp */ }
|
|
13
|
+
}
|
|
14
|
+
if (!canonical)
|
|
15
|
+
violations.push("appended_at must be a canonical UTC ISO-8601 timestamp");
|
|
16
|
+
}
|
|
17
|
+
return violations;
|
|
18
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import YAML from "yaml";
|
|
2
|
+
function healthIdentityNumber(value) {
|
|
3
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
4
|
+
const mapping = value;
|
|
5
|
+
const number = mapping.number;
|
|
6
|
+
if (Number.isSafeInteger(number) && Number(number) > 0)
|
|
7
|
+
return Number(number);
|
|
8
|
+
return healthIdentityNumber(mapping.summary);
|
|
9
|
+
}
|
|
10
|
+
if (typeof value !== "string")
|
|
11
|
+
return null;
|
|
12
|
+
const match = /^Audit\s+([1-9][0-9]*)\b/.exec(value.trim());
|
|
13
|
+
return match ? Number(match[1]) : null;
|
|
14
|
+
}
|
|
15
|
+
export function repairHealthDuplicates(doc, number, keep) {
|
|
16
|
+
const candidate = structuredClone(doc);
|
|
17
|
+
let removed = 0;
|
|
18
|
+
for (const key of ["audits", "archive"]) {
|
|
19
|
+
const values = Array.isArray(candidate[key]) ? candidate[key] : [];
|
|
20
|
+
const matches = values.flatMap((value, index) => (healthIdentityNumber(value) === number ? [index] : []));
|
|
21
|
+
if (matches.length < 2)
|
|
22
|
+
continue;
|
|
23
|
+
const retained = keep === "last" ? matches.at(-1) : matches[0];
|
|
24
|
+
candidate[key] = values.filter((_, index) => !matches.includes(index) || index === retained);
|
|
25
|
+
removed += matches.length - 1;
|
|
26
|
+
}
|
|
27
|
+
return { candidate, removed };
|
|
28
|
+
}
|
|
29
|
+
export function repairHealthProjectionBytes(bytes, number, keep) {
|
|
30
|
+
const document = YAML.parseDocument(bytes);
|
|
31
|
+
const removals = [];
|
|
32
|
+
let removed = 0;
|
|
33
|
+
for (const key of ["audits", "archive"]) {
|
|
34
|
+
const sequence = document.get(key, true);
|
|
35
|
+
const items = sequence?.items ?? [];
|
|
36
|
+
const sequenceEnd = sequence?.range?.[1];
|
|
37
|
+
const matches = items.flatMap((item, index) => {
|
|
38
|
+
const value = typeof item?.toJSON === "function"
|
|
39
|
+
? item.toJSON()
|
|
40
|
+
: item;
|
|
41
|
+
return healthIdentityNumber(value) === number ? [index] : [];
|
|
42
|
+
});
|
|
43
|
+
if (matches.length < 2)
|
|
44
|
+
continue;
|
|
45
|
+
const retained = keep === "last" ? matches.at(-1) : matches[0];
|
|
46
|
+
for (const index of matches) {
|
|
47
|
+
if (index === retained)
|
|
48
|
+
continue;
|
|
49
|
+
const range = items[index]?.range;
|
|
50
|
+
if (!range || range.length < 2)
|
|
51
|
+
throw new Error(`health ${key} row ${index} has no stable YAML range`);
|
|
52
|
+
const lineStart = bytes.lastIndexOf("\n", range[0] - 1) + 1;
|
|
53
|
+
const nextRange = items[index + 1]?.range;
|
|
54
|
+
const rawEnd = nextRange?.[0] ?? sequenceEnd ?? bytes.length;
|
|
55
|
+
const lineEnd = nextRange
|
|
56
|
+
? bytes.lastIndexOf("\n", rawEnd - 1) + 1
|
|
57
|
+
: (() => {
|
|
58
|
+
const newline = bytes.indexOf("\n", Math.max(range[1], rawEnd));
|
|
59
|
+
return newline < 0 ? bytes.length : newline + 1;
|
|
60
|
+
})();
|
|
61
|
+
removals.push([lineStart, Math.max(lineStart, lineEnd)]);
|
|
62
|
+
removed += 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
for (const [start, end] of removals.sort((left, right) => right[0] - left[0])) {
|
|
66
|
+
bytes = bytes.slice(0, start) + bytes.slice(end);
|
|
67
|
+
}
|
|
68
|
+
return { bytes, removed };
|
|
69
|
+
}
|