agentera 3.0.0-dev.7 → 3.0.0-dev.72
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 +2 -4
- 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 +17 -8
- 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 +3 -4
- package/bundle/references/cli/capability-instruction-contract.yaml +11 -14
- package/bundle/references/cli/hybrid-route-contract.yaml +438 -0
- package/bundle/references/cli/routing-model.md +152 -93
- package/bundle/references/cli/trigger-schema-enrichment.md +57 -46
- package/bundle/references/cli/update-channels.yaml +4 -2
- package/bundle/references/cli/vocabulary-index.yaml +5 -7
- package/bundle/references/cli/vocabulary.md +51 -93
- package/bundle/references/meta/retained-reference-authority.yaml +151 -0
- package/bundle/skills/agentera/SKILL.md +183 -63
- package/bundle/skills/agentera/capabilities/audit/schemas/artifacts.yaml +27 -19
- package/bundle/skills/agentera/capabilities/audit/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/audit/schemas/triggers.yaml +13 -35
- package/bundle/skills/agentera/capabilities/audit/schemas/validation.yaml +30 -11
- package/bundle/skills/agentera/capabilities/build/schemas/artifacts.yaml +44 -21
- package/bundle/skills/agentera/capabilities/build/schemas/exit.yaml +8 -6
- package/bundle/skills/agentera/capabilities/build/schemas/triggers.yaml +14 -36
- package/bundle/skills/agentera/capabilities/build/schemas/validation.yaml +95 -21
- package/bundle/skills/agentera/capabilities/design/schemas/artifacts.yaml +6 -6
- package/bundle/skills/agentera/capabilities/design/schemas/exit.yaml +5 -5
- package/bundle/skills/agentera/capabilities/design/schemas/triggers.yaml +5 -34
- package/bundle/skills/agentera/capabilities/design/schemas/validation.yaml +2 -2
- package/bundle/skills/agentera/capabilities/discuss/schemas/artifacts.yaml +17 -13
- package/bundle/skills/agentera/capabilities/discuss/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/discuss/schemas/triggers.yaml +6 -40
- package/bundle/skills/agentera/capabilities/discuss/schemas/validation.yaml +72 -5
- package/bundle/skills/agentera/capabilities/document/schemas/artifacts.yaml +24 -17
- package/bundle/skills/agentera/capabilities/document/schemas/triggers.yaml +5 -35
- package/bundle/skills/agentera/capabilities/document/schemas/validation.yaml +13 -13
- package/bundle/skills/agentera/capabilities/optimize/schemas/artifacts.yaml +10 -10
- package/bundle/skills/agentera/capabilities/optimize/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/optimize/schemas/triggers.yaml +4 -35
- package/bundle/skills/agentera/capabilities/optimize/schemas/validation.yaml +3 -3
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/artifacts.yaml +34 -22
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/exit.yaml +9 -7
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/triggers.yaml +5 -37
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/validation.yaml +38 -37
- package/bundle/skills/agentera/capabilities/plan/schemas/artifacts.yaml +20 -16
- package/bundle/skills/agentera/capabilities/plan/schemas/triggers.yaml +8 -31
- package/bundle/skills/agentera/capabilities/plan/schemas/validation.yaml +66 -6
- package/bundle/skills/agentera/capabilities/profile/schemas/artifacts.yaml +9 -4
- package/bundle/skills/agentera/capabilities/profile/schemas/exit.yaml +4 -4
- package/bundle/skills/agentera/capabilities/profile/schemas/triggers.yaml +8 -37
- package/bundle/skills/agentera/capabilities/profile/schemas/validation.yaml +61 -3
- package/bundle/skills/agentera/capabilities/research/schemas/artifacts.yaml +6 -6
- package/bundle/skills/agentera/capabilities/research/schemas/triggers.yaml +5 -29
- package/bundle/skills/agentera/capabilities/status/schemas/artifacts.yaml +13 -12
- package/bundle/skills/agentera/capabilities/status/schemas/triggers.yaml +7 -49
- package/bundle/skills/agentera/capabilities/vision/schemas/artifacts.yaml +8 -8
- package/bundle/skills/agentera/capabilities/vision/schemas/exit.yaml +7 -6
- package/bundle/skills/agentera/capabilities/vision/schemas/triggers.yaml +7 -39
- package/bundle/skills/agentera/capabilities/vision/schemas/validation.yaml +14 -16
- package/bundle/skills/agentera/capability_schema_contract.yaml +32 -32
- package/bundle/skills/agentera/protocol.yaml +4 -4
- package/bundle/skills/agentera/route-phrases.yaml +81 -0
- package/bundle/skills/agentera/schemas/artifacts/changelog.yaml +1 -0
- package/bundle/skills/agentera/schemas/artifacts/decisions.yaml +30 -12
- package/bundle/skills/agentera/schemas/artifacts/design.yaml +1 -0
- package/bundle/skills/agentera/schemas/artifacts/docs.yaml +7 -12
- package/bundle/skills/agentera/schemas/artifacts/experiments.yaml +140 -9
- package/bundle/skills/agentera/schemas/artifacts/glossary.yaml +82 -0
- package/bundle/skills/agentera/schemas/artifacts/health.yaml +56 -19
- package/bundle/skills/agentera/schemas/artifacts/objective.yaml +18 -4
- package/bundle/skills/agentera/schemas/artifacts/plan.yaml +457 -32
- package/bundle/skills/agentera/schemas/artifacts/progress.yaml +131 -18
- package/bundle/skills/agentera/schemas/artifacts/todo.yaml +302 -7
- package/dist/analytics/extractCorpus/cli.js +52 -11
- package/dist/analytics/extractCorpus/copilotSessions.js +6 -4
- package/dist/analytics/extractCorpus/core.js +40 -12
- package/dist/analytics/extractCorpus/corpus.js +39 -17
- package/dist/analytics/extractCorpus/coverageAudit.js +44 -45
- package/dist/analytics/extractCorpus/cursorSessions.js +6 -4
- package/dist/analytics/extractCorpus/evidenceTiers.js +603 -0
- package/dist/analytics/extractCorpus/extractCorpusParity.js +4 -4
- package/dist/analytics/extractCorpus/filesystemSources.js +1 -5
- package/dist/analytics/extractCorpus/index.js +3 -1
- package/dist/analytics/extractCorpus/jsonlSessions.js +24 -5
- package/dist/analytics/extractCorpus/sqliteCaps.js +0 -1
- package/dist/analytics/extractCorpus/sqliteSessions.js +0 -1
- 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 +150 -23
- package/dist/audit/terminologyDrift.js +281 -0
- package/dist/bin/agentera.js +3 -2
- package/dist/capabilities/audit/instructions.js +16 -6
- package/dist/capabilities/build/instructions.js +59 -6
- package/dist/capabilities/design/instructions.js +3 -4
- package/dist/capabilities/discuss/instructions.js +29 -6
- package/dist/capabilities/document/instructions.js +11 -6
- package/dist/capabilities/index.js +16 -14
- package/dist/capabilities/optimize/instructions.js +14 -6
- package/dist/capabilities/orchestrate/instructions.js +42 -6
- package/dist/capabilities/plan/instructions.js +30 -3
- package/dist/capabilities/profile/instructions.js +70 -6
- package/dist/capabilities/research/instructions.js +4 -5
- package/dist/capabilities/status/instructions.js +15 -6
- package/dist/capabilities/status/startupInstructions.js +34 -0
- package/dist/capabilities/vision/instructions.js +3 -5
- package/dist/cli/appContext.js +14 -7
- package/dist/cli/argvalidate.js +0 -1
- package/dist/cli/capabilityContext/benchmark.js +5 -4
- package/dist/cli/capabilityContext/bespoke.js +14 -6
- package/dist/cli/capabilityContext/build.js +116 -42
- package/dist/cli/capabilityContext/closeout.js +30 -27
- package/dist/cli/capabilityContext/contract.js +18 -27
- package/dist/cli/capabilityContext/evidence.js +84 -77
- package/dist/cli/capabilityContext/index.js +0 -1
- package/dist/cli/capabilityContext/orchestration.js +42 -18
- package/dist/cli/capabilityContext/planState.js +89 -96
- package/dist/cli/capabilityContext/progress.js +51 -12
- package/dist/cli/capabilityContext/projectVerification.js +409 -0
- package/dist/cli/capabilityContext/shared.js +9 -20
- package/dist/cli/capabilityContext/slim.js +52 -8
- package/dist/cli/capabilityContext/startup.js +51 -114
- package/dist/cli/capabilityContext/startupAggregation.js +68 -0
- package/dist/cli/capabilityContext/types.js +26 -10
- package/dist/cli/capabilityContext.js +0 -1
- package/dist/cli/commands/appHome.js +0 -1
- package/dist/cli/commands/capability.js +2 -2
- package/dist/cli/commands/compact.js +163 -13
- package/dist/cli/commands/doctor.js +117 -11
- package/dist/cli/commands/durability.js +81 -0
- package/dist/cli/commands/glossaryAdvice.js +138 -0
- package/dist/cli/commands/lint.js +22 -8
- package/dist/cli/commands/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 +54 -4
- package/dist/cli/commands/prime/collectEntityOrientation.js +326 -0
- package/dist/cli/commands/prime/collectOrientationState.js +126 -63
- package/dist/cli/commands/prime/orientationOutput.js +267 -56
- package/dist/cli/commands/prime/types.js +0 -1
- package/dist/cli/commands/prime/v1Migration.js +0 -1
- package/dist/cli/commands/prime.js +76 -11
- package/dist/cli/commands/profileGrounding.js +55 -0
- package/dist/cli/commands/query.js +74 -52
- package/dist/cli/commands/report.js +73 -19
- package/dist/cli/commands/route.js +142 -0
- package/dist/cli/commands/schema.js +257 -138
- package/dist/cli/commands/state/decisions.js +40 -56
- package/dist/cli/commands/state/docs.js +58 -85
- package/dist/cli/commands/state/experimentRecords.js +151 -0
- package/dist/cli/commands/state/experiments.js +11 -65
- package/dist/cli/commands/state/get.js +129 -0
- package/dist/cli/commands/state/health.js +11 -113
- package/dist/cli/commands/state/index.js +6 -41
- package/dist/cli/commands/state/list.js +194 -0
- package/dist/cli/commands/state/objective.js +21 -65
- package/dist/cli/commands/state/plan.js +11 -170
- package/dist/cli/commands/state/planTasks.js +154 -0
- package/dist/cli/commands/state/plans.js +154 -0
- package/dist/cli/commands/state/progress.js +11 -45
- package/dist/cli/commands/state/shared.js +0 -1
- package/dist/cli/commands/state/todo.js +28 -107
- package/dist/cli/commands/state/write.js +433 -0
- package/dist/cli/commands/upgrade.js +146 -5
- package/dist/cli/commands/upgradeVerify.js +118 -0
- package/dist/cli/commands/validate.js +235 -136
- package/dist/cli/commands/verify.js +23 -8
- package/dist/cli/contracts/bundleStatus.js +0 -1
- package/dist/cli/contracts/orientationState.js +0 -1
- package/dist/cli/dispatch/argvParser.js +0 -1
- package/dist/cli/dispatch/check.js +84 -40
- package/dist/cli/dispatch/commands.js +3 -3
- package/dist/cli/dispatch/index.js +77 -52
- package/dist/cli/dispatch/lifecycle.js +117 -62
- package/dist/cli/dispatch/prime.js +37 -2
- package/dist/cli/dispatch/projections.js +17 -0
- package/dist/cli/dispatch/shared.js +1 -2
- package/dist/cli/dispatch/state.js +62 -66
- package/dist/cli/dispatch.js +0 -1
- package/dist/cli/errors.js +16 -17
- package/dist/cli/help.js +358 -39
- package/dist/cli/migrationRequired.js +122 -0
- package/dist/cli/orientation/attention.js +19 -19
- package/dist/cli/orientation/corpusCoverage.js +32 -1
- package/dist/cli/orientation.js +346 -129
- package/dist/cli/planArtifacts.js +350 -0
- package/dist/cli/planEvidence.js +157 -0
- package/dist/cli/planLifecycleState.js +36 -0
- package/dist/cli/planTaskIndex.js +11 -0
- package/dist/cli/preCutoverCommand.js +32 -0
- package/dist/cli/prime-blob.js +71 -3
- package/dist/cli/profileAcquisition.js +167 -0
- package/dist/cli/startupCompletenessContract.js +11 -8
- package/dist/cli/stateQuery.js +47 -12
- package/dist/cli/structured.js +0 -1
- package/dist/cli/todoMarkdown.js +25 -12
- package/dist/cli/todoReadinessSelection.js +192 -0
- package/dist/cli/todoSeverity.js +0 -1
- package/dist/core/atomicWriter.js +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 +0 -1
- package/dist/core/jsonValue.js +0 -1
- package/dist/core/paths.js +0 -1
- package/dist/core/pyjson.js +0 -1
- package/dist/core/shell.js +4 -0
- package/dist/core/skillIdentity.js +23 -0
- package/dist/core/sourceRoot.js +9 -12
- package/dist/core/text.js +10 -0
- package/dist/core/toml.js +0 -1
- package/dist/core/yaml.js +8 -1
- package/dist/eval/evalSkills.js +13 -14
- package/dist/eval/hybridRouteEvaluation.js +155 -0
- package/dist/eval/semanticEval.js +0 -1
- package/dist/eval/semanticFixtures.js +0 -1
- package/dist/hooks/common.js +3 -56
- package/dist/hooks/compaction/apply.js +224 -47
- package/dist/hooks/compaction/dryRun.js +2 -1
- package/dist/hooks/compaction/index.js +5 -6
- package/dist/hooks/compaction/parse.js +73 -6
- package/dist/hooks/compaction/retention.js +28 -25
- package/dist/hooks/compaction/status.js +145 -26
- package/dist/hooks/compaction/types.js +0 -1
- package/dist/hooks/validateArtifact/agentFacing.js +0 -1
- package/dist/hooks/validateArtifact/index.js +6 -65
- package/dist/hooks/validateArtifact/markdown.js +9 -10
- package/dist/hooks/validateArtifact/schema.js +96 -9
- package/dist/hooks/validateArtifact/traversal.js +12 -11
- package/dist/hooks/validateArtifact/violations.js +5 -3
- package/dist/migrate/v2HandoffManifest.js +8 -3
- package/dist/registries/activationContract.js +2 -0
- package/dist/registries/activationTuples.js +108 -0
- package/dist/registries/artifactProtocolIds.js +2 -1
- package/dist/registries/artifactRegistry.js +207 -60
- package/dist/registries/artifactSchemaProjection.js +45 -0
- package/dist/registries/capabilityContract.js +5 -21
- package/dist/registries/evaluatorHandoffContract.js +0 -1
- package/dist/registries/evidenceTierContract.js +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 +184 -209
- package/dist/registries/todoReadinessContract.js +448 -0
- package/dist/registries/triggerLoader.js +7 -44
- package/dist/registries/verbosityBudgetContract.js +205 -0
- package/dist/release/releaseMetadata.js +155 -5
- 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 +14 -75
- package/dist/state/archiveDiscovery.js +580 -0
- package/dist/state/archivePublication.js +225 -0
- package/dist/state/archiveRecovery.js +237 -0
- package/dist/state/archiveReplay.js +53 -0
- package/dist/state/canonicalMigrationRecord.js +36 -0
- package/dist/state/changelog.js +221 -0
- package/dist/state/decisionEntities.js +367 -0
- package/dist/state/decisionLegacyValidation.js +215 -0
- package/dist/state/decisionMigrationProvenance.js +199 -0
- package/dist/state/decisionOverlay.js +254 -0
- package/dist/state/decisionRevision.js +256 -0
- package/dist/state/decisionRevisionMigration.js +89 -0
- package/dist/state/directRetrieval.js +323 -0
- package/dist/state/durability.js +324 -0
- package/dist/state/entityCutover.js +459 -0
- package/dist/state/entityCutoverGit.js +127 -0
- package/dist/state/entityGlossaryAuthority.js +13 -0
- package/dist/state/entityListProjection.js +187 -0
- package/dist/state/entityListRuntimeRegistry.js +85 -0
- package/dist/state/entityMigrationCausality.js +97 -0
- package/dist/state/entityMigrationIdentity.js +5 -0
- package/dist/state/entityMigrationPreview.js +840 -0
- package/dist/state/entityMigrationTodo.js +133 -0
- package/dist/state/entityPublicationContext.js +859 -0
- package/dist/state/entityRetrievalHelp.js +506 -0
- package/dist/state/entityStorage.js +899 -0
- package/dist/state/exactReplacementRecovery.js +18 -0
- package/dist/state/experimentArchive.js +63 -0
- package/dist/state/experimentIdentity.js +202 -0
- package/dist/state/healthEntities.js +262 -0
- package/dist/state/healthEntityValidation.js +18 -0
- package/dist/state/healthRepair.js +69 -0
- package/dist/state/installRoot.js +15 -7
- package/dist/state/legacyEntityCutoverEvidence.js +65 -0
- package/dist/state/legacyIdentity.js +47 -0
- package/dist/state/legacySummaryRecord.js +6 -0
- package/dist/state/listAccounting.js +54 -0
- package/dist/state/listClassification.js +17 -0
- package/dist/state/listCursor.js +42 -0
- package/dist/state/listRetrieval.js +781 -0
- package/dist/state/migrationSourceBinding.js +30 -0
- package/dist/state/objectiveExperimentEntities.js +322 -0
- package/dist/state/planEntities.js +1027 -0
- package/dist/state/planIdentity.js +47 -0
- package/dist/state/planLineageValidation.js +52 -0
- package/dist/state/planReplacementTransaction.js +475 -0
- package/dist/state/planRetrieval.js +313 -0
- package/dist/state/planTaskRetrieval.js +294 -0
- package/dist/state/progressEntities.js +512 -0
- package/dist/state/progressGlossaryCaveat.js +168 -0
- package/dist/state/progressPublicationOrder.js +19 -0
- package/dist/state/progressWritePolicy.js +33 -0
- package/dist/state/projectRoot.js +62 -0
- package/dist/state/projectionPolicy.js +190 -0
- package/dist/state/retrievalAuthority.js +156 -0
- package/dist/state/safeProjectFile.js +155 -0
- package/dist/state/startupAnalysis/benchmark.js +70 -9
- package/dist/state/startupAnalysis/contract.js +44 -10
- package/dist/state/startupAnalysis/helpers.js +1 -2
- package/dist/state/startupAnalysis/index.js +0 -1
- package/dist/state/startupAnalysis/metrics.js +0 -1
- package/dist/state/startupAnalysis/records.js +0 -1
- package/dist/state/startupAnalysis/report.js +0 -1
- package/dist/state/startupAnalysis/threshold.js +13 -1
- package/dist/state/startupAnalysis.js +0 -1
- package/dist/state/startupProjection.js +499 -0
- package/dist/state/stateMode.js +222 -0
- package/dist/state/stateStorageAuthority.js +47 -0
- package/dist/state/summaryEntityRead.js +25 -0
- package/dist/state/summaryMigrationProvenance.js +66 -0
- package/dist/state/summarySourceRowAuthority.js +36 -0
- package/dist/state/todoActivationSafety.js +58 -0
- package/dist/state/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 +77 -36
- package/dist/upgrade/appModel.js +0 -1
- package/dist/upgrade/atomicWriter.js +1 -0
- package/dist/upgrade/bundleEvidence.js +0 -1
- package/dist/upgrade/channels.js +6 -9
- package/dist/upgrade/compatibility.js +43 -17
- package/dist/upgrade/doctor.js +55 -32
- package/dist/upgrade/doctorClassifier.js +11 -1
- package/dist/upgrade/installedHooksRetirement.js +46 -40
- package/dist/upgrade/legacyAgentCleanup.js +187 -21
- package/dist/upgrade/lifecycleUpgrade.js +113 -0
- package/dist/upgrade/migrateArtifactsV2ToV3.js +334 -64
- package/dist/upgrade/migrationPublication.js +122 -0
- package/dist/upgrade/nextMajorDoctor.js +0 -1
- package/dist/upgrade/npxPlatformStatus.js +0 -1
- package/dist/upgrade/projectIntegration.js +121 -159
- package/dist/upgrade/projectIntegrationDecision.js +42 -85
- package/dist/upgrade/retiredResourceDiagnostics.js +117 -0
- package/dist/upgrade/runtimeMigration.js +262 -453
- 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 +0 -1
- 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 +1 -7
- package/dist/validate/bootstrapAuthority.js +44 -0
- package/dist/validate/capability.js +11 -3
- package/dist/validate/crossCapability.js +14 -9
- package/dist/validate/retainedReferenceAuthority.js +879 -0
- package/dist/validate/selfAudit.js +39 -45
- package/dist/validate/v1LegacyCruft.js +131 -0
- package/dist/validate/vocabularyAuthority.js +8 -8
- package/package.json +41 -13
- package/bundle/references/adapters/cursor.md +0 -214
- package/bundle/references/adapters/opencode.md +0 -530
- package/bundle/references/adapters/package-manifest-interface-model.yaml +0 -337
- package/bundle/references/adapters/runtime-adapter-characterization.md +0 -79
- package/bundle/references/adapters/runtime-adapter-interface-model.yaml +0 -200
- package/bundle/references/adapters/runtime-adapter-registry.yaml +0 -554
- package/bundle/references/adapters/runtime-feature-parity.md +0 -189
- package/bundle/references/analysis/benchmark.md +0 -267
- package/bundle/references/analysis/startup-measurement-contract.yaml +0 -424
- package/bundle/references/cli/agent-ready-state-contract.yaml +0 -953
- package/bundle/references/cli/audience-namespace-cli-migration.yaml +0 -369
- package/bundle/references/cli/bundle-skill-vocabulary.yaml +0 -250
- package/bundle/references/cli/capability-tool-classification.yaml +0 -53
- package/bundle/references/cli/coexistence-probe.yaml +0 -13
- package/bundle/references/cli/parity-expected-actual-template.md +0 -30
- package/bundle/references/cli/routing-execution-vocabulary.yaml +0 -281
- package/bundle/references/cli/single-name-protocol.yaml +0 -42
- package/bundle/references/cli/upgrade-repair-wording.md +0 -45
- package/bundle/references/cli/v3-handoff-manifest.schema.yaml +0 -98
- package/bundle/references/meta/documentation-inventory.md +0 -49
- package/bundle/skills/agentera/.claude-plugin/plugin.json +0 -27
- package/bundle/skills/agentera/agents/audit.toml +0 -6
- package/bundle/skills/agentera/agents/build.toml +0 -6
- package/bundle/skills/agentera/agents/design.toml +0 -6
- package/bundle/skills/agentera/agents/discuss.toml +0 -6
- package/bundle/skills/agentera/agents/document.toml +0 -6
- package/bundle/skills/agentera/agents/optimize.toml +0 -6
- package/bundle/skills/agentera/agents/orchestrate.toml +0 -6
- package/bundle/skills/agentera/agents/plan.toml +0 -6
- package/bundle/skills/agentera/agents/profile.toml +0 -6
- package/bundle/skills/agentera/agents/research.toml +0 -6
- package/bundle/skills/agentera/agents/status.toml +0 -6
- package/bundle/skills/agentera/agents/vision.toml +0 -6
- package/bundle/skills/agentera/references/contract.md +0 -1048
- package/dist/analytics/extractCorpus/cli.js.map +0 -1
- package/dist/analytics/extractCorpus/copilotSessions.js.map +0 -1
- package/dist/analytics/extractCorpus/core.js.map +0 -1
- package/dist/analytics/extractCorpus/corpus.js.map +0 -1
- package/dist/analytics/extractCorpus/coverageAudit.js.map +0 -1
- package/dist/analytics/extractCorpus/cursorSessions.js.map +0 -1
- package/dist/analytics/extractCorpus/extractCorpusParity.js.map +0 -1
- package/dist/analytics/extractCorpus/filesystemSources.js.map +0 -1
- package/dist/analytics/extractCorpus/index.js.map +0 -1
- package/dist/analytics/extractCorpus/jsonlSessions.js.map +0 -1
- package/dist/analytics/extractCorpus/sqliteCaps.js.map +0 -1
- package/dist/analytics/extractCorpus/sqliteSessions.js.map +0 -1
- package/dist/analytics/extractCorpus.js.map +0 -1
- package/dist/analytics/usageStats.js.map +0 -1
- package/dist/bin/agentera.js.map +0 -1
- package/dist/capabilities/audit/instructions.js.map +0 -1
- package/dist/capabilities/build/instructions.js.map +0 -1
- package/dist/capabilities/design/instructions.js.map +0 -1
- package/dist/capabilities/discuss/instructions.js.map +0 -1
- package/dist/capabilities/document/instructions.js.map +0 -1
- package/dist/capabilities/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/optimize/instructions.js.map +0 -1
- package/dist/capabilities/orchestrate/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/plan/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/profile/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/research/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/status/instructions.js.map +0 -1
- package/dist/capabilities/vision/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 -5
- 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/build.js.map +0 -1
- package/dist/cli/capabilityContext/closeout.js.map +0 -1
- package/dist/cli/capabilityContext/contract.js.map +0 -1
- package/dist/cli/capabilityContext/evidence.js.map +0 -1
- package/dist/cli/capabilityContext/index.js.map +0 -1
- package/dist/cli/capabilityContext/orchestration.js.map +0 -1
- package/dist/cli/capabilityContext/planState.js.map +0 -1
- package/dist/cli/capabilityContext/progress.js.map +0 -1
- package/dist/cli/capabilityContext/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/appHome.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/bundleStatus.js.map +0 -1
- package/dist/cli/commands/prime/collectOrientationState.js.map +0 -1
- package/dist/cli/commands/prime/orientationOutput.js.map +0 -1
- package/dist/cli/commands/prime/routeOutput.js +0 -50
- package/dist/cli/commands/prime/routeOutput.js.map +0 -1
- package/dist/cli/commands/prime/types.js.map +0 -1
- package/dist/cli/commands/prime/v1Migration.js.map +0 -1
- package/dist/cli/commands/prime.js.map +0 -1
- package/dist/cli/commands/query.js.map +0 -1
- package/dist/cli/commands/report.js.map +0 -1
- package/dist/cli/commands/schema.js.map +0 -1
- package/dist/cli/commands/state/decisions.js.map +0 -1
- package/dist/cli/commands/state/docs.js.map +0 -1
- package/dist/cli/commands/state/experiments.js.map +0 -1
- package/dist/cli/commands/state/health.js.map +0 -1
- package/dist/cli/commands/state/index.js.map +0 -1
- package/dist/cli/commands/state/objective.js.map +0 -1
- package/dist/cli/commands/state/plan.js.map +0 -1
- package/dist/cli/commands/state/progress.js.map +0 -1
- package/dist/cli/commands/state/shared.js.map +0 -1
- package/dist/cli/commands/state/todo.js.map +0 -1
- package/dist/cli/commands/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/contracts/bundleStatus.js.map +0 -1
- package/dist/cli/contracts/orientationState.js.map +0 -1
- package/dist/cli/dispatch/argvParser.js.map +0 -1
- package/dist/cli/dispatch/check.js.map +0 -1
- package/dist/cli/dispatch/commands.js.map +0 -1
- package/dist/cli/dispatch/index.js.map +0 -1
- package/dist/cli/dispatch/lifecycle.js.map +0 -1
- package/dist/cli/dispatch/prime.js.map +0 -1
- package/dist/cli/dispatch/shared.js.map +0 -1
- package/dist/cli/dispatch/state.js.map +0 -1
- package/dist/cli/dispatch.js.map +0 -1
- package/dist/cli/errors.js.map +0 -1
- package/dist/cli/help.js.map +0 -1
- package/dist/cli/orientation/attention.js.map +0 -1
- package/dist/cli/orientation/corpusCoverage.js.map +0 -1
- package/dist/cli/orientation.js.map +0 -1
- package/dist/cli/prime-blob.js.map +0 -1
- package/dist/cli/startupCompletenessContract.js.map +0 -1
- package/dist/cli/stateQuery.js.map +0 -1
- package/dist/cli/structured.js.map +0 -1
- package/dist/cli/todoMarkdown.js.map +0 -1
- package/dist/cli/todoSeverity.js.map +0 -1
- package/dist/core/difflib.js.map +0 -1
- package/dist/core/envPaths.js.map +0 -1
- package/dist/core/git.js +0 -43
- package/dist/core/git.js.map +0 -1
- package/dist/core/jsonValue.js.map +0 -1
- package/dist/core/paths.js.map +0 -1
- package/dist/core/pyjson.js.map +0 -1
- package/dist/core/sourceRoot.js.map +0 -1
- package/dist/core/toml.js.map +0 -1
- package/dist/core/yaml.js.map +0 -1
- package/dist/eval/evalSkills.js.map +0 -1
- package/dist/eval/semanticEval.js.map +0 -1
- package/dist/eval/semanticFixtures.js.map +0 -1
- package/dist/hooks/common.js.map +0 -1
- package/dist/hooks/compaction/apply.js.map +0 -1
- package/dist/hooks/compaction/dryRun.js.map +0 -1
- package/dist/hooks/compaction/index.js.map +0 -1
- package/dist/hooks/compaction/parse.js.map +0 -1
- package/dist/hooks/compaction/retention.js.map +0 -1
- package/dist/hooks/compaction/status.js.map +0 -1
- package/dist/hooks/compaction/todoResolved.js +0 -137
- package/dist/hooks/compaction/todoResolved.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 -79
- package/dist/hooks/cursorSessionStart.js.map +0 -1
- package/dist/hooks/sessionStart.js +0 -216
- package/dist/hooks/sessionStart.js.map +0 -1
- package/dist/hooks/sessionStop.js +0 -206
- package/dist/hooks/sessionStop.js.map +0 -1
- package/dist/hooks/todoLayout.js +0 -177
- package/dist/hooks/todoLayout.js.map +0 -1
- package/dist/hooks/validateArtifact/agentFacing.js.map +0 -1
- package/dist/hooks/validateArtifact/index.js.map +0 -1
- package/dist/hooks/validateArtifact/markdown.js.map +0 -1
- package/dist/hooks/validateArtifact/runtime.js +0 -86
- package/dist/hooks/validateArtifact/runtime.js.map +0 -1
- package/dist/hooks/validateArtifact/schema.js.map +0 -1
- package/dist/hooks/validateArtifact/traversal.js.map +0 -1
- package/dist/hooks/validateArtifact/violations.js.map +0 -1
- package/dist/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 -316
- package/dist/registries/runtimeAdapterRegistry.js.map +0 -1
- package/dist/registries/triggerLoader.js.map +0 -1
- package/dist/release/releaseMetadata.js.map +0 -1
- package/dist/routing/index.js +0 -2
- package/dist/routing/index.js.map +0 -1
- package/dist/routing/routeEngine.js +0 -189
- package/dist/routing/routeEngine.js.map +0 -1
- package/dist/setup/codex/agents.js +0 -96
- package/dist/setup/codex/agents.js.map +0 -1
- package/dist/setup/codex/cli.js +0 -161
- package/dist/setup/codex/cli.js.map +0 -1
- package/dist/setup/codex/configToml.js +0 -639
- package/dist/setup/codex/configToml.js.map +0 -1
- package/dist/setup/codex/constants.js +0 -29
- package/dist/setup/codex/constants.js.map +0 -1
- package/dist/setup/codex/installRoot.js +0 -64
- package/dist/setup/codex/installRoot.js.map +0 -1
- package/dist/setup/codex/state.js +0 -270
- package/dist/setup/codex/state.js.map +0 -1
- package/dist/setup/codex.js +0 -12
- package/dist/setup/codex.js.map +0 -1
- package/dist/setup/copilot.js +0 -227
- package/dist/setup/copilot.js.map +0 -1
- package/dist/setup/cursor.js +0 -129
- package/dist/setup/cursor.js.map +0 -1
- package/dist/setup/cursorSurfaces.js +0 -67
- package/dist/setup/cursorSurfaces.js.map +0 -1
- package/dist/setup/doctor/core.js +0 -300
- package/dist/setup/doctor/core.js.map +0 -1
- package/dist/setup/doctor/diagnostics.js +0 -240
- package/dist/setup/doctor/diagnostics.js.map +0 -1
- package/dist/setup/doctor/opencode.js +0 -313
- package/dist/setup/doctor/opencode.js.map +0 -1
- package/dist/setup/doctor/report.js +0 -425
- package/dist/setup/doctor/report.js.map +0 -1
- package/dist/setup/doctor.js +0 -10
- package/dist/setup/doctor.js.map +0 -1
- package/dist/setup/opencode.js.map +0 -1
- package/dist/setup/smokeChecks.js.map +0 -1
- package/dist/state/installRoot.js.map +0 -1
- package/dist/state/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/appContentRefresh.js.map +0 -1
- package/dist/upgrade/appModel.js.map +0 -1
- package/dist/upgrade/bundleEvidence.js.map +0 -1
- package/dist/upgrade/channels.js.map +0 -1
- package/dist/upgrade/cliProbe.js +0 -22
- package/dist/upgrade/cliProbe.js.map +0 -1
- package/dist/upgrade/coexistenceProbe.js +0 -107
- package/dist/upgrade/coexistenceProbe.js.map +0 -1
- package/dist/upgrade/compatibility.js.map +0 -1
- package/dist/upgrade/doctor.js.map +0 -1
- package/dist/upgrade/doctorClassifier.js.map +0 -1
- package/dist/upgrade/installedHooksRetirement.js.map +0 -1
- package/dist/upgrade/legacyAgentCleanup.js.map +0 -1
- package/dist/upgrade/migrateArtifactsV1ToV2.js +0 -570
- package/dist/upgrade/migrateArtifactsV1ToV2.js.map +0 -1
- package/dist/upgrade/migrateArtifactsV2ToV3.js.map +0 -1
- package/dist/upgrade/nextMajorDoctor.js.map +0 -1
- package/dist/upgrade/npxPlatformStatus.js.map +0 -1
- package/dist/upgrade/projectIntegration.js.map +0 -1
- package/dist/upgrade/projectIntegrationDecision.js.map +0 -1
- package/dist/upgrade/runtimeMigration.js.map +0 -1
- package/dist/upgrade/upgradeCommands.js.map +0 -1
- package/dist/upgrade/upgradeOrchestrator.js.map +0 -1
- package/dist/upgrade/v3CapabilitySurface.js.map +0 -1
- package/dist/upgrade/versionResolution.js.map +0 -1
- package/dist/validate/appHomeContract.js.map +0 -1
- package/dist/validate/capability.js.map +0 -1
- package/dist/validate/crossCapability.js.map +0 -1
- package/dist/validate/lifecycleAdapters/legacyPythonParity.js +0 -93
- package/dist/validate/lifecycleAdapters/legacyPythonParity.js.map +0 -1
- package/dist/validate/lifecycleAdapters/nodeFormChecks.js +0 -488
- package/dist/validate/lifecycleAdapters/nodeFormChecks.js.map +0 -1
- package/dist/validate/lifecycleAdapters/shared.js +0 -198
- package/dist/validate/lifecycleAdapters/shared.js.map +0 -1
- package/dist/validate/lifecycleAdapters.js +0 -62
- package/dist/validate/lifecycleAdapters.js.map +0 -1
- package/dist/validate/selfAudit.js.map +0 -1
- package/dist/validate/vocabularyAuthority.js.map +0 -1
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { ACTIVATION_CANONICAL_TUPLES } from "../registries/activationTuples.js";
|
|
7
|
+
import { loadRegistry } from "../registries/packageRegistry.js";
|
|
8
|
+
import { packageCommandDeclarations, packageDescriptorSemantics, packageDescriptors, } from "./activationPackageSemantics.js";
|
|
9
|
+
import { GENERATED_OWNER_EVIDENCE_SCHEMA, OWNER_EVIDENCE_MAX_BYTES, PACKAGE_IDENTITY_MAX_BYTES, PACKAGE_IDENTITY_SCHEMA, PACKAGE_OWNER_EVIDENCE_SCHEMA, PACKAGE_SNAPSHOT_DIRECTORY, PACKAGE_SNAPSHOT_EXTRACTED_MAX_BYTES, PACKAGE_SNAPSHOT_MARKER_MAX_BYTES, PACKAGE_SNAPSHOT_MAX_ENTRIES, PACKAGE_SNAPSHOT_SCHEMA, PACKAGE_SNAPSHOT_TARBALL_MAX_BYTES, SOURCE_OWNER_EVIDENCE_SCHEMA, } from "./activationArtifactEvidenceTypes.js";
|
|
10
|
+
import { bootstrapMatrixAuthority } from "./bootstrapAuthority.js";
|
|
11
|
+
export * from "./activationArtifactEvidenceTypes.js";
|
|
12
|
+
const sourceCapabilityCache = new Map();
|
|
13
|
+
const CAPABILITY_IDS = Object.freeze(ACTIVATION_CANONICAL_TUPLES
|
|
14
|
+
.filter((tuple) => tuple.class === "capability")
|
|
15
|
+
.map((tuple) => tuple.surface_id)
|
|
16
|
+
.sort());
|
|
17
|
+
function canonical(value) {
|
|
18
|
+
if (Array.isArray(value))
|
|
19
|
+
return value.map(canonical);
|
|
20
|
+
if (value && typeof value === "object") {
|
|
21
|
+
const object = value;
|
|
22
|
+
return Object.fromEntries(Object.keys(object).sort().map((key) => [key, canonical(object[key])]));
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
export function canonicalObservationJson(value) {
|
|
27
|
+
return JSON.stringify(canonical(value));
|
|
28
|
+
}
|
|
29
|
+
export function observationDigest(value) {
|
|
30
|
+
return createHash("sha256").update(canonicalObservationJson(value), "utf8").digest("hex");
|
|
31
|
+
}
|
|
32
|
+
function fileSha256(file) {
|
|
33
|
+
return createHash("sha256").update(fs.readFileSync(file)).digest("hex");
|
|
34
|
+
}
|
|
35
|
+
function artifactDigest(root, relatives) {
|
|
36
|
+
return observationDigest([...relatives].sort().map((relative) => ({
|
|
37
|
+
path: relative.split(path.sep).join("/"),
|
|
38
|
+
sha256: fs.existsSync(path.join(root, relative)) && fs.statSync(path.join(root, relative)).isFile()
|
|
39
|
+
? fileSha256(path.join(root, relative))
|
|
40
|
+
: "missing",
|
|
41
|
+
})));
|
|
42
|
+
}
|
|
43
|
+
function filesBelow(root, relative = "") {
|
|
44
|
+
const directory = path.join(root, relative);
|
|
45
|
+
if (!fs.existsSync(directory))
|
|
46
|
+
return [];
|
|
47
|
+
return fs.readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
|
|
48
|
+
const child = path.join(relative, entry.name);
|
|
49
|
+
if (entry.isSymbolicLink())
|
|
50
|
+
return [];
|
|
51
|
+
return entry.isDirectory() ? filesBelow(root, child) : [child];
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function completeTreeObservation(root, options = {}) {
|
|
55
|
+
const rootStat = fs.lstatSync(root);
|
|
56
|
+
if (!rootStat.isDirectory() || rootStat.isSymbolicLink())
|
|
57
|
+
throw new Error("authoritative extracted package root is not a directory");
|
|
58
|
+
const entries = [];
|
|
59
|
+
let fileCount = 0;
|
|
60
|
+
let totalBytes = 0;
|
|
61
|
+
const visit = (directory) => {
|
|
62
|
+
const directoryPath = path.join(root, directory);
|
|
63
|
+
const directoryBefore = fs.lstatSync(directoryPath);
|
|
64
|
+
const names = fs.readdirSync(directoryPath).sort();
|
|
65
|
+
for (const name of names) {
|
|
66
|
+
const relative = path.join(directory, name);
|
|
67
|
+
const target = path.join(root, relative);
|
|
68
|
+
const stat = fs.lstatSync(target);
|
|
69
|
+
const normalized = relative.split(path.sep).join("/");
|
|
70
|
+
if (normalized.length > 512 || /[\0\r\n]/.test(normalized))
|
|
71
|
+
throw new Error("authoritative extracted package path violates its bound");
|
|
72
|
+
if (entries.length >= (options.maxEntries ?? PACKAGE_SNAPSHOT_MAX_ENTRIES))
|
|
73
|
+
throw new Error("authoritative extracted package exceeds its entry bound");
|
|
74
|
+
if (stat.isDirectory()) {
|
|
75
|
+
entries.push({ path: normalized, type: "directory", mode: stat.mode & 0o777 });
|
|
76
|
+
visit(relative);
|
|
77
|
+
}
|
|
78
|
+
else if (stat.isFile()) {
|
|
79
|
+
const bytes = readBoundedRegularFile(target, Math.max(0, (options.maxTotalBytes ?? PACKAGE_SNAPSHOT_EXTRACTED_MAX_BYTES) - totalBytes), true, stat);
|
|
80
|
+
fileCount += 1;
|
|
81
|
+
totalBytes += bytes.length;
|
|
82
|
+
if (totalBytes > (options.maxTotalBytes ?? PACKAGE_SNAPSHOT_EXTRACTED_MAX_BYTES))
|
|
83
|
+
throw new Error("authoritative extracted package exceeds its byte bound");
|
|
84
|
+
entries.push({
|
|
85
|
+
path: normalized,
|
|
86
|
+
type: "file",
|
|
87
|
+
mode: stat.mode & 0o777,
|
|
88
|
+
size: bytes.length,
|
|
89
|
+
sha256: createHash("sha256").update(bytes).digest("hex"),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
else if (stat.isSymbolicLink()) {
|
|
93
|
+
if (options.allowSymlinks === false)
|
|
94
|
+
throw new Error("authoritative extracted package contains a symlink");
|
|
95
|
+
entries.push({
|
|
96
|
+
path: normalized,
|
|
97
|
+
type: "symlink",
|
|
98
|
+
mode: stat.mode & 0o777,
|
|
99
|
+
targetSha256: observationDigest(fs.readlinkSync(target)),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
throw new Error(`authoritative extracted package contains unsupported entry '${normalized}'`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const directoryAfter = fs.lstatSync(directoryPath);
|
|
107
|
+
if (names.join("\0") !== fs.readdirSync(directoryPath).sort().join("\0")
|
|
108
|
+
|| directoryBefore.dev !== directoryAfter.dev || directoryBefore.ino !== directoryAfter.ino
|
|
109
|
+
|| directoryBefore.mtimeMs !== directoryAfter.mtimeMs) {
|
|
110
|
+
throw new Error("authoritative extracted package changed while it was observed");
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
visit("");
|
|
114
|
+
return { entries, digest: observationDigest(entries), fileCount, totalBytes };
|
|
115
|
+
}
|
|
116
|
+
function readBoundedRegularFile(file, maximumBytes, allowEmpty = false, expected) {
|
|
117
|
+
const noFollow = fs.constants.O_NOFOLLOW ?? 0;
|
|
118
|
+
const descriptor = fs.openSync(file, fs.constants.O_RDONLY | noFollow);
|
|
119
|
+
try {
|
|
120
|
+
const before = fs.fstatSync(descriptor);
|
|
121
|
+
if (!before.isFile() || (!allowEmpty && before.size <= 0) || before.size > maximumBytes
|
|
122
|
+
|| (expected && (expected.dev !== before.dev || expected.ino !== before.ino))) {
|
|
123
|
+
throw new Error("authoritative package file violates its regular-file or byte bound");
|
|
124
|
+
}
|
|
125
|
+
const bytes = fs.readFileSync(descriptor);
|
|
126
|
+
const after = fs.fstatSync(descriptor);
|
|
127
|
+
if (bytes.length !== before.size || before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeMs !== after.mtimeMs) {
|
|
128
|
+
throw new Error("authoritative package tarball changed while it was read");
|
|
129
|
+
}
|
|
130
|
+
return bytes;
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
fs.closeSync(descriptor);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function packageArtifactIdentity(filename, bytes) {
|
|
137
|
+
return {
|
|
138
|
+
filename,
|
|
139
|
+
integrity: `sha512-${createHash("sha512").update(bytes).digest("base64")}`,
|
|
140
|
+
shasum: createHash("sha1").update(bytes).digest("hex"),
|
|
141
|
+
tarballSha256: createHash("sha256").update(bytes).digest("hex"),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function preflightPackageBytes(bytes) {
|
|
145
|
+
const listed = spawnSync("tar", ["-tvzf", "-", "--numeric-owner", "--full-time"], {
|
|
146
|
+
input: bytes,
|
|
147
|
+
encoding: "utf8",
|
|
148
|
+
env: { ...process.env, LC_ALL: "C", TZ: "UTC" },
|
|
149
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
150
|
+
timeout: 30_000,
|
|
151
|
+
maxBuffer: PACKAGE_SNAPSHOT_MAX_ENTRIES * 2_048,
|
|
152
|
+
});
|
|
153
|
+
if (listed.status !== 0)
|
|
154
|
+
throw new Error("authoritative package tarball cannot be listed");
|
|
155
|
+
const lines = listed.stdout.trimEnd() === "" ? [] : listed.stdout.trimEnd().split("\n");
|
|
156
|
+
if (lines.length < 1 || lines.length > PACKAGE_SNAPSHOT_MAX_ENTRIES)
|
|
157
|
+
throw new Error("authoritative package tarball violates its entry bound");
|
|
158
|
+
let totalBytes = 0;
|
|
159
|
+
for (const line of lines) {
|
|
160
|
+
const columns = line.trim().split(/\s+/);
|
|
161
|
+
const size = Number(columns[2]);
|
|
162
|
+
if (line.length > 2_048 || !["-", "d"].includes(line[0] ?? "") || !Number.isSafeInteger(size) || size < 0) {
|
|
163
|
+
throw new Error("authoritative package tarball listing is malformed or contains an unsupported entry");
|
|
164
|
+
}
|
|
165
|
+
totalBytes += size;
|
|
166
|
+
if (totalBytes > PACKAGE_SNAPSHOT_EXTRACTED_MAX_BYTES)
|
|
167
|
+
throw new Error("authoritative package tarball exceeds its extracted byte bound");
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function extractPackageBytes(bytes, temporary) {
|
|
171
|
+
preflightPackageBytes(bytes);
|
|
172
|
+
const extracted = spawnSync("tar", ["-xzf", "-", "-C", temporary], {
|
|
173
|
+
input: bytes,
|
|
174
|
+
encoding: "utf8",
|
|
175
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
176
|
+
timeout: 30_000,
|
|
177
|
+
maxBuffer: 65_536,
|
|
178
|
+
});
|
|
179
|
+
if (extracted.status !== 0)
|
|
180
|
+
throw new Error("authoritative package tarball cannot be extracted");
|
|
181
|
+
const topLevel = fs.readdirSync(temporary, { withFileTypes: true });
|
|
182
|
+
if (topLevel.length !== 1 || topLevel[0]?.name !== "package" || !topLevel[0].isDirectory() || topLevel[0].isSymbolicLink()) {
|
|
183
|
+
throw new Error("authoritative package tarball has an invalid package root");
|
|
184
|
+
}
|
|
185
|
+
return path.join(temporary, "package");
|
|
186
|
+
}
|
|
187
|
+
function snapshotMarker(artifact, tree) {
|
|
188
|
+
const unsigned = {
|
|
189
|
+
schemaVersion: PACKAGE_SNAPSHOT_SCHEMA,
|
|
190
|
+
packageArtifact: artifact,
|
|
191
|
+
tarballTree: { count: tree.entries.length, digest: tree.digest, fileCount: tree.fileCount, totalBytes: tree.totalBytes },
|
|
192
|
+
};
|
|
193
|
+
return { ...unsigned, snapshotDigest: observationDigest(unsigned) };
|
|
194
|
+
}
|
|
195
|
+
function writeRetainedPackageSnapshot(directory, bytes, packageRoot, artifact, tree) {
|
|
196
|
+
const parent = path.dirname(path.resolve(directory));
|
|
197
|
+
fs.mkdirSync(parent, { recursive: true, mode: 0o700 });
|
|
198
|
+
const parentReal = fs.realpathSync(parent);
|
|
199
|
+
const target = path.join(parentReal, path.basename(directory));
|
|
200
|
+
if (path.resolve(directory) !== target || fs.existsSync(target))
|
|
201
|
+
throw new Error("retained package snapshot target is not a new direct child of its parent");
|
|
202
|
+
const staging = `${target}.${process.pid}.tmp`;
|
|
203
|
+
fs.mkdirSync(staging, { mode: 0o700 });
|
|
204
|
+
try {
|
|
205
|
+
fs.writeFileSync(path.join(staging, "package.tgz"), bytes, { flag: "wx", mode: 0o600 });
|
|
206
|
+
fs.cpSync(packageRoot, path.join(staging, "extracted"), { recursive: true, verbatimSymlinks: true });
|
|
207
|
+
const marker = snapshotMarker(artifact, tree);
|
|
208
|
+
const markerBytes = `${canonicalObservationJson(marker)}\n`;
|
|
209
|
+
if (Buffer.byteLength(markerBytes, "utf8") > PACKAGE_SNAPSHOT_MARKER_MAX_BYTES)
|
|
210
|
+
throw new Error("retained package snapshot marker exceeds its byte bound");
|
|
211
|
+
fs.writeFileSync(path.join(staging, "snapshot.json"), markerBytes, { flag: "wx", mode: 0o600 });
|
|
212
|
+
fs.renameSync(staging, target);
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
export function observeCurrentPackageArtifact(tarball, extractedRoot, snapshotDirectory) {
|
|
219
|
+
const bytes = readBoundedRegularFile(tarball, PACKAGE_SNAPSHOT_TARBALL_MAX_BYTES);
|
|
220
|
+
const packageArtifact = {
|
|
221
|
+
...packageArtifactIdentity(path.basename(tarball), bytes),
|
|
222
|
+
};
|
|
223
|
+
const extractedTree = completeTreeObservation(extractedRoot, { allowSymlinks: true });
|
|
224
|
+
const temporary = fs.mkdtempSync(path.join(process.env.TMPDIR ?? os.tmpdir(), "activation-tarball-tree-"));
|
|
225
|
+
let tarballTree;
|
|
226
|
+
try {
|
|
227
|
+
const packageRoot = extractPackageBytes(bytes, temporary);
|
|
228
|
+
tarballTree = completeTreeObservation(packageRoot, { allowSymlinks: false });
|
|
229
|
+
if (snapshotDirectory)
|
|
230
|
+
writeRetainedPackageSnapshot(snapshotDirectory, bytes, packageRoot, packageArtifact, tarballTree);
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
fs.rmSync(temporary, { recursive: true, force: true });
|
|
234
|
+
}
|
|
235
|
+
const runtimeSupportPaths = extractedTree.entries
|
|
236
|
+
.filter((entry) => entry.path === "node_modules" && entry.type === "symlink")
|
|
237
|
+
.map((entry) => entry.path);
|
|
238
|
+
const extractedPayload = extractedTree.entries.filter((entry) => !runtimeSupportPaths.includes(entry.path));
|
|
239
|
+
if (canonicalObservationJson(extractedPayload) !== canonicalObservationJson(tarballTree.entries)) {
|
|
240
|
+
throw new Error("authoritative extracted package tree does not exactly match the current tarball payload");
|
|
241
|
+
}
|
|
242
|
+
return { ...packageArtifact, extractedTree, tarballTree, runtimeSupportPaths };
|
|
243
|
+
}
|
|
244
|
+
function packageSnapshotRootViolations(snapshotRoot, expectedIdentity, allowedRoot) {
|
|
245
|
+
const invalid = "retained package snapshot differs from the independently retained package identity";
|
|
246
|
+
if (activationPackageIdentityViolations(expectedIdentity).length > 0)
|
|
247
|
+
return [invalid];
|
|
248
|
+
const identity = expectedIdentity;
|
|
249
|
+
let temporary;
|
|
250
|
+
try {
|
|
251
|
+
const snapshotStat = fs.lstatSync(snapshotRoot);
|
|
252
|
+
if (!snapshotStat.isDirectory() || snapshotStat.isSymbolicLink())
|
|
253
|
+
return [invalid];
|
|
254
|
+
const snapshotReal = fs.realpathSync(snapshotRoot);
|
|
255
|
+
if (snapshotReal !== path.resolve(snapshotRoot))
|
|
256
|
+
return [invalid];
|
|
257
|
+
if (allowedRoot) {
|
|
258
|
+
const rootStat = fs.lstatSync(allowedRoot);
|
|
259
|
+
if (!rootStat.isDirectory() || rootStat.isSymbolicLink())
|
|
260
|
+
return [invalid];
|
|
261
|
+
const rootReal = fs.realpathSync(allowedRoot);
|
|
262
|
+
if (snapshotReal !== path.join(rootReal, PACKAGE_SNAPSHOT_DIRECTORY))
|
|
263
|
+
return [invalid];
|
|
264
|
+
}
|
|
265
|
+
const entries = fs.readdirSync(snapshotReal, { withFileTypes: true });
|
|
266
|
+
if (entries.map((entry) => entry.name).sort().join("\0") !== ["extracted", "package.tgz", "snapshot.json"].join("\0")
|
|
267
|
+
|| entries.some((entry) => entry.isSymbolicLink()))
|
|
268
|
+
return [invalid];
|
|
269
|
+
const markerBytes = readBoundedRegularFile(path.join(snapshotReal, "snapshot.json"), PACKAGE_SNAPSHOT_MARKER_MAX_BYTES);
|
|
270
|
+
const marker = JSON.parse(markerBytes.toString("utf8"));
|
|
271
|
+
const { snapshotDigest, ...unsignedMarker } = marker;
|
|
272
|
+
if (Object.keys(marker).sort().join("\0") !== ["packageArtifact", "schemaVersion", "snapshotDigest", "tarballTree"].join("\0")
|
|
273
|
+
|| Object.keys(marker.packageArtifact ?? {}).sort().join("\0") !== ["filename", "integrity", "shasum", "tarballSha256"].join("\0")
|
|
274
|
+
|| Object.keys(marker.tarballTree ?? {}).sort().join("\0") !== ["count", "digest", "fileCount", "totalBytes"].join("\0")
|
|
275
|
+
|| marker.schemaVersion !== PACKAGE_SNAPSHOT_SCHEMA || snapshotDigest !== observationDigest(unsignedMarker))
|
|
276
|
+
return [invalid];
|
|
277
|
+
const tarballBytes = readBoundedRegularFile(path.join(snapshotReal, "package.tgz"), PACKAGE_SNAPSHOT_TARBALL_MAX_BYTES);
|
|
278
|
+
const artifact = packageArtifactIdentity(identity.packageArtifact.filename, tarballBytes);
|
|
279
|
+
const extractedTree = completeTreeObservation(path.join(snapshotReal, "extracted"), { allowSymlinks: false });
|
|
280
|
+
temporary = fs.mkdtempSync(path.join(process.env.TMPDIR ?? os.tmpdir(), "activation-snapshot-check-"));
|
|
281
|
+
const reextractedRoot = extractPackageBytes(tarballBytes, temporary);
|
|
282
|
+
const tarballTree = completeTreeObservation(reextractedRoot, { allowSymlinks: false });
|
|
283
|
+
const treeSummary = { count: tarballTree.entries.length, digest: tarballTree.digest };
|
|
284
|
+
if (canonicalObservationJson(artifact) !== canonicalObservationJson(identity.packageArtifact)
|
|
285
|
+
|| canonicalObservationJson(treeSummary) !== canonicalObservationJson(identity.tarballTree)
|
|
286
|
+
|| canonicalObservationJson(extractedTree.entries) !== canonicalObservationJson(tarballTree.entries)
|
|
287
|
+
|| canonicalObservationJson(marker.packageArtifact) !== canonicalObservationJson(identity.packageArtifact)
|
|
288
|
+
|| marker.tarballTree.count !== tarballTree.entries.length
|
|
289
|
+
|| marker.tarballTree.digest !== tarballTree.digest
|
|
290
|
+
|| marker.tarballTree.fileCount !== tarballTree.fileCount
|
|
291
|
+
|| marker.tarballTree.totalBytes !== tarballTree.totalBytes)
|
|
292
|
+
return [invalid];
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
return [invalid];
|
|
297
|
+
}
|
|
298
|
+
finally {
|
|
299
|
+
if (temporary)
|
|
300
|
+
fs.rmSync(temporary, { recursive: true, force: true });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
export function retainedPackageSnapshotViolations(generationRoot, expectedIdentity) {
|
|
304
|
+
return packageSnapshotRootViolations(path.join(path.resolve(generationRoot), PACKAGE_SNAPSHOT_DIRECTORY), expectedIdentity, generationRoot);
|
|
305
|
+
}
|
|
306
|
+
export function installRetainedPackageSnapshot(sourceSnapshot, generationRoot, expectedIdentity) {
|
|
307
|
+
const sourceViolations = packageSnapshotRootViolations(sourceSnapshot, expectedIdentity);
|
|
308
|
+
if (sourceViolations.length > 0)
|
|
309
|
+
throw new Error(sourceViolations[0]);
|
|
310
|
+
const generationStat = fs.lstatSync(generationRoot);
|
|
311
|
+
if (!generationStat.isDirectory() || generationStat.isSymbolicLink())
|
|
312
|
+
throw new Error("authoritative generation root is not a regular directory");
|
|
313
|
+
const generationReal = fs.realpathSync(generationRoot);
|
|
314
|
+
if (generationReal !== path.resolve(generationRoot))
|
|
315
|
+
throw new Error("authoritative generation root realpath drifted");
|
|
316
|
+
const target = path.join(generationReal, PACKAGE_SNAPSHOT_DIRECTORY);
|
|
317
|
+
if (!fs.existsSync(target)) {
|
|
318
|
+
const staging = `${target}.${process.pid}.tmp`;
|
|
319
|
+
fs.cpSync(sourceSnapshot, staging, { recursive: true, verbatimSymlinks: true, errorOnExist: true });
|
|
320
|
+
try {
|
|
321
|
+
const copiedViolations = packageSnapshotRootViolations(staging, expectedIdentity);
|
|
322
|
+
if (copiedViolations.length > 0)
|
|
323
|
+
throw new Error(copiedViolations[0]);
|
|
324
|
+
fs.renameSync(staging, target);
|
|
325
|
+
}
|
|
326
|
+
finally {
|
|
327
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const installedViolations = retainedPackageSnapshotViolations(generationReal, expectedIdentity);
|
|
331
|
+
if (installedViolations.length > 0)
|
|
332
|
+
throw new Error(installedViolations[0]);
|
|
333
|
+
return { schemaVersion: PACKAGE_SNAPSHOT_SCHEMA, path: PACKAGE_SNAPSHOT_DIRECTORY, identityDigest: expectedIdentity.identityDigest };
|
|
334
|
+
}
|
|
335
|
+
export function removeRetainedPackageSnapshot(generationRoot) {
|
|
336
|
+
const generationReal = fs.realpathSync(generationRoot);
|
|
337
|
+
const target = path.join(generationReal, PACKAGE_SNAPSHOT_DIRECTORY);
|
|
338
|
+
if (path.dirname(target) !== generationReal)
|
|
339
|
+
throw new Error("retained package snapshot cleanup escaped its generation root");
|
|
340
|
+
fs.rmSync(target, { recursive: true, force: true });
|
|
341
|
+
}
|
|
342
|
+
function bodyObservation(bodies) {
|
|
343
|
+
return {
|
|
344
|
+
identities: Object.keys(bodies).sort(),
|
|
345
|
+
bodies: Object.fromEntries(Object.entries(bodies).sort(([left], [right]) => left.localeCompare(right)).map(([id, body]) => [id, {
|
|
346
|
+
sha256: createHash("sha256").update(body, "utf8").digest("hex"),
|
|
347
|
+
bytes: Buffer.byteLength(body, "utf8"),
|
|
348
|
+
}])),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function registryCapabilities(file) {
|
|
352
|
+
const registry = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
353
|
+
return [...(registry?.skills?.[0]?.capabilities ?? [])].sort();
|
|
354
|
+
}
|
|
355
|
+
function schemaCapabilities(root) {
|
|
356
|
+
return fs.readdirSync(root, { withFileTypes: true })
|
|
357
|
+
.filter((entry) => entry.isDirectory())
|
|
358
|
+
.filter((entry) => ["triggers.yaml", "artifacts.yaml", "validation.yaml", "exit.yaml"]
|
|
359
|
+
.every((file) => fs.existsSync(path.join(root, entry.name, "schemas", file))))
|
|
360
|
+
.map((entry) => entry.name)
|
|
361
|
+
.sort();
|
|
362
|
+
}
|
|
363
|
+
export function loadSourceCapabilityInstructions(root) {
|
|
364
|
+
const cacheKey = `${root}\0${activationSourceDigest(root)}`;
|
|
365
|
+
const cached = sourceCapabilityCache.get(cacheKey);
|
|
366
|
+
if (cached)
|
|
367
|
+
return structuredClone(cached);
|
|
368
|
+
const script = path.join(root, "packages/cli/scripts/observe-capability-source.mjs");
|
|
369
|
+
const result = spawnSync(process.execPath, [script, root], {
|
|
370
|
+
cwd: root,
|
|
371
|
+
env: process.env,
|
|
372
|
+
encoding: "utf8",
|
|
373
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
374
|
+
timeout: 30_000,
|
|
375
|
+
});
|
|
376
|
+
if (result.status !== 0)
|
|
377
|
+
throw new Error(`source capability observation failed: ${(result.stderr || result.stdout).trim()}`);
|
|
378
|
+
const observed = JSON.parse(result.stdout);
|
|
379
|
+
sourceCapabilityCache.set(cacheKey, observed);
|
|
380
|
+
return structuredClone(observed);
|
|
381
|
+
}
|
|
382
|
+
function sourceProjection(root) {
|
|
383
|
+
const parsed = loadSourceCapabilityInstructions(root);
|
|
384
|
+
const schemaRoot = path.join(root, "skills/agentera/capabilities");
|
|
385
|
+
const moduleFiles = CAPABILITY_IDS.map((id) => `packages/cli/src/capabilities/${id}/instructions.ts`);
|
|
386
|
+
const schemaFiles = filesBelow(root, "skills/agentera/capabilities");
|
|
387
|
+
return {
|
|
388
|
+
modules: bodyObservation(parsed.modules),
|
|
389
|
+
runtimeRegistry: bodyObservation(parsed.runtimeRegistry),
|
|
390
|
+
registry: registryCapabilities(path.join(root, "registry.json")),
|
|
391
|
+
routes: [...parsed.routes].sort(),
|
|
392
|
+
schemas: schemaCapabilities(schemaRoot),
|
|
393
|
+
artifacts: {
|
|
394
|
+
modules: artifactDigest(root, moduleFiles),
|
|
395
|
+
runtimeRegistry: artifactDigest(root, [...moduleFiles, "packages/cli/src/capabilities/index.ts"]),
|
|
396
|
+
registry: artifactDigest(root, ["registry.json"]),
|
|
397
|
+
routes: artifactDigest(root, ["packages/cli/src/cli/commands/capability.ts"]),
|
|
398
|
+
schemas: artifactDigest(root, schemaFiles),
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function runtimeArtifactObservation(runtimeRoot, projectRoot, sourceRoot, mode = "full") {
|
|
403
|
+
const script = path.join(sourceRoot, "packages/cli/scripts/observe-runtime-artifact.mjs");
|
|
404
|
+
const result = spawnSync(process.execPath, [script, runtimeRoot, projectRoot, mode], {
|
|
405
|
+
cwd: projectRoot,
|
|
406
|
+
env: process.env,
|
|
407
|
+
encoding: "utf8",
|
|
408
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
409
|
+
timeout: 120_000,
|
|
410
|
+
});
|
|
411
|
+
if (result.status !== 0)
|
|
412
|
+
throw new Error(`runtime artifact observation failed: ${(result.stderr || result.stdout).trim()}`);
|
|
413
|
+
const parsed = JSON.parse(result.stdout);
|
|
414
|
+
const registryFile = path.join(runtimeRoot, "bundle/registry.json");
|
|
415
|
+
const schemaRelative = "bundle/skills/agentera/capabilities";
|
|
416
|
+
const schemaRoot = path.join(runtimeRoot, schemaRelative);
|
|
417
|
+
const moduleFiles = CAPABILITY_IDS.map((id) => `dist/capabilities/${id}/instructions.js`);
|
|
418
|
+
return { bootstrap: parsed.bootstrap, projection: {
|
|
419
|
+
modules: bodyObservation(parsed.capabilities.modules),
|
|
420
|
+
runtimeRegistry: bodyObservation(parsed.capabilities.runtimeRegistry),
|
|
421
|
+
served: bodyObservation(parsed.capabilities.served),
|
|
422
|
+
registry: registryCapabilities(registryFile),
|
|
423
|
+
routes: [...parsed.capabilities.routes].sort(),
|
|
424
|
+
schemas: schemaCapabilities(schemaRoot),
|
|
425
|
+
startupProducers: parsed.capabilities.startupProducers,
|
|
426
|
+
artifacts: {
|
|
427
|
+
modules: artifactDigest(runtimeRoot, moduleFiles),
|
|
428
|
+
runtimeRegistry: artifactDigest(runtimeRoot, [...moduleFiles, "dist/capabilities/index.js"]),
|
|
429
|
+
served: artifactDigest(runtimeRoot, ["dist/bin/agentera.js"]),
|
|
430
|
+
registry: artifactDigest(runtimeRoot, ["bundle/registry.json"]),
|
|
431
|
+
routes: artifactDigest(runtimeRoot, ["dist/cli/commands/capability.js"]),
|
|
432
|
+
schemas: artifactDigest(runtimeRoot, filesBelow(runtimeRoot, schemaRelative)),
|
|
433
|
+
startupProducers: artifactDigest(runtimeRoot, ["dist/bin/agentera.js", "bundle/skills/agentera/SKILL.md"]),
|
|
434
|
+
},
|
|
435
|
+
} };
|
|
436
|
+
}
|
|
437
|
+
function runtimeProjection(runtimeRoot, projectRoot, sourceRoot, mode = "full") {
|
|
438
|
+
return runtimeArtifactObservation(runtimeRoot, projectRoot, sourceRoot, mode).projection;
|
|
439
|
+
}
|
|
440
|
+
function createRecord(producerKind, artifactClass, artifactIdentity, artifactContentDigest, content, generation, packageIntegrity) {
|
|
441
|
+
return {
|
|
442
|
+
producerKind,
|
|
443
|
+
artifactClass,
|
|
444
|
+
artifactIdentity,
|
|
445
|
+
artifactContentDigest,
|
|
446
|
+
generation,
|
|
447
|
+
packageIntegrity,
|
|
448
|
+
content,
|
|
449
|
+
observationDigest: observationDigest(content),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function finishEvidence(value) {
|
|
453
|
+
return { ...value, evidenceDigest: observationDigest(value) };
|
|
454
|
+
}
|
|
455
|
+
function packageRecord(root) {
|
|
456
|
+
return loadRegistry(path.join(root, "references/adapters/package-registry.yaml"), root).get("agentera");
|
|
457
|
+
}
|
|
458
|
+
export function activationSourceDigest(root) {
|
|
459
|
+
const files = new Set([
|
|
460
|
+
"registry.json",
|
|
461
|
+
"references/adapters/package-registry.yaml",
|
|
462
|
+
"references/meta/retained-reference-authority.yaml",
|
|
463
|
+
"skills/agentera/capability_schema_contract.yaml",
|
|
464
|
+
...ACTIVATION_CANONICAL_TUPLES.map((tuple) => tuple.owner_path),
|
|
465
|
+
]);
|
|
466
|
+
return observationDigest([...files].sort().map((file) => ({ path: file, sha256: fs.existsSync(path.join(root, file)) ? fileSha256(path.join(root, file)) : "missing" })));
|
|
467
|
+
}
|
|
468
|
+
const runtimeAuthority = ["references", "adapters", "runtime-lifecycle-authority.yaml"].join("/");
|
|
469
|
+
const retiredAuthority = ["references", "adapters", "runtime-retired-resources.yaml"].join("/");
|
|
470
|
+
const GENERIC_SOURCE_ARTIFACTS = {
|
|
471
|
+
"cli.discovery": ["packages/cli/src/cli/dispatch/commands.ts"],
|
|
472
|
+
"cli.behavior": ["packages/cli/src/cli/dispatch/index.ts"],
|
|
473
|
+
"cli.diagnostics": ["packages/cli/src/cli/dispatch/projections.ts", "packages/cli/src/cli/dispatch/commands.ts"],
|
|
474
|
+
"cli.instructions": ["packages/cli/src/cli/help.ts"],
|
|
475
|
+
"cli.adversarial": ["packages/cli/src/cli/dispatch/commands.ts", "packages/cli/src/cli/errors.ts"],
|
|
476
|
+
"runtime.discovery": [runtimeAuthority, retiredAuthority],
|
|
477
|
+
"runtime.behavior": [runtimeAuthority, retiredAuthority, "packages/cli/src/runtime/nativeResourceCleanup.ts"],
|
|
478
|
+
"runtime.diagnostics": [retiredAuthority, "packages/cli/src/runtime/nativeResourceCleanup.ts"],
|
|
479
|
+
"runtime.instructions": [runtimeAuthority, retiredAuthority],
|
|
480
|
+
"runtime.adversarial": [runtimeAuthority, retiredAuthority],
|
|
481
|
+
"reference.discovery": ["references/meta/retained-reference-authority.yaml"],
|
|
482
|
+
"reference.behavior": ["references/meta/retained-reference-authority.yaml"],
|
|
483
|
+
"reference.diagnostics": ["references/meta/retained-reference-authority.yaml"],
|
|
484
|
+
"reference.instructions": ["references/meta/retained-reference-authority.yaml"],
|
|
485
|
+
"reference.adversarial": ["references/meta/retained-reference-authority.yaml"],
|
|
486
|
+
"state.discovery": ["packages/cli/src/state/entityListRuntimeRegistry.ts", "packages/cli/src/state/write/runtimeOperations.ts"],
|
|
487
|
+
"state.behavior": ["packages/cli/src/state/entityListRuntimeRegistry.ts", "packages/cli/src/state/write/runtimeOperations.ts"],
|
|
488
|
+
"state.diagnostics": ["packages/cli/src/state/write/runtimeOperations.ts", "packages/cli/src/state/entityListRuntimeRegistry.ts"],
|
|
489
|
+
"state.instructions": ["packages/cli/src/state/entityRetrievalHelp.ts", "packages/cli/src/state/write/runtimeOperations.ts"],
|
|
490
|
+
"state.adversarial": ["packages/cli/src/state/entityListRuntimeRegistry.ts", "packages/cli/src/state/write/runtimeOperations.ts"],
|
|
491
|
+
};
|
|
492
|
+
function genericDimensionObservation(classId, dimension, input) {
|
|
493
|
+
if (classId === "cli") {
|
|
494
|
+
if (dimension === "discovery")
|
|
495
|
+
return { commands: input.commands };
|
|
496
|
+
if (dimension === "behavior")
|
|
497
|
+
return { dispatchSourceDigest: observationDigest(input.dispatchSource), capabilityRoutes: input.capabilityRoutes };
|
|
498
|
+
if (dimension === "diagnostics")
|
|
499
|
+
return { diagnosticCommands: input.commands, runtimeCommands: input.runtimeDiagnosticCommands };
|
|
500
|
+
if (dimension === "instructions")
|
|
501
|
+
return { helpDigest: observationDigest(input.helpText), declaredCommands: input.declaredCommands };
|
|
502
|
+
return { commandClassifications: input.commands.map((command) => ({ command, safe: !/\s|[;&|]/.test(command) })) };
|
|
503
|
+
}
|
|
504
|
+
if (classId === "runtime") {
|
|
505
|
+
const resources = input.retired.resources;
|
|
506
|
+
const diagnostics = input.retired.diagnosticResources;
|
|
507
|
+
if (dimension === "discovery")
|
|
508
|
+
return { lifecycleSource: input.lifecycle.sourcePath, runtimeIds: input.lifecycle.runtimes.map((entry) => entry.id), resources: resources.map((entry) => ({ host: entry.host, id: entry.id })) };
|
|
509
|
+
if (dimension === "behavior")
|
|
510
|
+
return { hosts: resources.map((entry) => ({ host: entry.host, support: entry.hostSupportStatus, safety: entry.safetyNote })), diagnosticDestinations: diagnostics.map((entry) => ({ id: entry.id, destinations: entry.destinations })) };
|
|
511
|
+
if (dimension === "diagnostics")
|
|
512
|
+
return { durableProof: resources.map((entry) => ({ host: entry.host, proof: entry.durableProof })), diagnosticIds: diagnostics.map((entry) => ({ id: entry.id, names: entry.names })) };
|
|
513
|
+
if (dimension === "instructions")
|
|
514
|
+
return { canonicalSkillPath: input.lifecycle.canonicalSkillPath, safetyNotes: resources.map((entry) => ({ host: entry.host, safety: entry.safetyNote })) };
|
|
515
|
+
return { resourceShapes: resources.map((entry) => ({ host: entry.host, safe: /^[A-Za-z0-9._:-]+$/.test(entry.host) })), diagnosticShapes: diagnostics.map((entry) => ({ id: entry.id, bounded: !/[\0\r\n]/.test(entry.id) })) };
|
|
516
|
+
}
|
|
517
|
+
if (classId === "reference") {
|
|
518
|
+
const inventory = input.inventory;
|
|
519
|
+
if (dimension === "discovery")
|
|
520
|
+
return inventory.map((entry) => ({ path: entry.path, classification: entry.classification }));
|
|
521
|
+
if (dimension === "behavior")
|
|
522
|
+
return inventory.map((entry) => ({ path: entry.path, consumers: entry.consumers ?? null, command: entry.command ?? null }));
|
|
523
|
+
if (dimension === "diagnostics")
|
|
524
|
+
return inventory.map((entry) => ({ path: entry.path, owner: entry.production_owner ?? null, maintainer: entry.maintainer ?? null }));
|
|
525
|
+
if (dimension === "instructions")
|
|
526
|
+
return inventory.map((entry) => ({ path: entry.path, modules: (entry.consumers ?? []).map((consumer) => [consumer.module, consumer.symbol]), command: entry.command ?? null }));
|
|
527
|
+
return inventory.map((entry) => ({ path: entry.path, ownerShape: entry.production_owner ? [entry.production_owner.module, entry.production_owner.symbol] : null, commandSafe: entry.command ? !/[\0\r\n]/.test(entry.command) : true }));
|
|
528
|
+
}
|
|
529
|
+
const reads = input.readFamilies;
|
|
530
|
+
const writes = input.operations;
|
|
531
|
+
if (dimension === "discovery")
|
|
532
|
+
return { reads: reads.map((entry) => entry.key), writes: writes.map((entry) => `${entry.artifact}.${entry.verb}`) };
|
|
533
|
+
if (dimension === "behavior")
|
|
534
|
+
return { reads: reads.map((entry) => ({ key: entry.key, tokens: entry.commandTokens })), writes: writes.map((entry) => ({ id: `${entry.artifact}.${entry.verb}`, inputMode: entry.inputMode })) };
|
|
535
|
+
if (dimension === "diagnostics")
|
|
536
|
+
return { bounds: input.bounds, recovery: writes.map((entry) => ({ id: `${entry.artifact}.${entry.verb}`, recovery: entry.projection.recovery.runtime })) };
|
|
537
|
+
if (dimension === "instructions")
|
|
538
|
+
return { help: input.helpFamilies, examples: writes.map((entry) => ({ id: `${entry.artifact}.${entry.verb}`, examples: entry.projection.examples })) };
|
|
539
|
+
return { bounds: input.bounds, inputBounds: writes.map((entry) => ({ id: `${entry.artifact}.${entry.verb}`, bytes: entry.inputMaxBytes, formats: entry.projection.formatValues })) };
|
|
540
|
+
}
|
|
541
|
+
export function createSourceOwnerEvidence(root, productionInputs, packageExecution) {
|
|
542
|
+
const capabilities = sourceProjection(root);
|
|
543
|
+
const record = packageRecord(root);
|
|
544
|
+
const records = {
|
|
545
|
+
"capability.source-modules": createRecord("source-owner", "capability-source-modules", "packages/cli/src/capabilities/*/instructions.ts", capabilities.artifacts.modules, capabilities.modules, null, null),
|
|
546
|
+
"capability.source-runtime-registry": createRecord("source-owner", "capability-source-runtime-registry", "packages/cli/src/capabilities/index.ts#CAPABILITY_INSTRUCTIONS", capabilities.artifacts.runtimeRegistry, capabilities.runtimeRegistry, null, null),
|
|
547
|
+
"capability.source-registry": createRecord("source-owner", "capability-source-registry", "registry.json#skills[0].capabilities", capabilities.artifacts.registry, capabilities.registry, null, null),
|
|
548
|
+
"capability.source-routes": createRecord("source-owner", "capability-source-routes", "packages/cli/src/cli/commands/capability.ts#CAPABILITY_ROUTING_NAMES", capabilities.artifacts.routes, capabilities.routes, null, null),
|
|
549
|
+
"capability.source-schemas": createRecord("source-owner", "capability-source-schemas", "skills/agentera/capabilities/*/schemas", capabilities.artifacts.schemas, capabilities.schemas, null, null),
|
|
550
|
+
"package.source-registry": createRecord("source-owner", "package-source-registry", "references/adapters/package-registry.yaml#records[agentera]", artifactDigest(root, ["references/adapters/package-registry.yaml"]), packageDescriptorSemantics(packageDescriptors(record)), null, null),
|
|
551
|
+
"package.source-construction": createRecord("source-owner", "package-source-construction", "references/adapters/package-registry.yaml#records[agentera].bundle_surfaces", artifactDigest(root, ["references/adapters/package-registry.yaml", "packages/cli/scripts/package-construction.mjs"]), packageDescriptors(record).map(({ id, entry }) => ({ id, path: entry.path })), null, null),
|
|
552
|
+
"package.source-selectors": createRecord("source-owner", "package-source-selectors", "references/adapters/package-registry.yaml#records[agentera].semantic_fields", artifactDigest(root, ["references/adapters/package-registry.yaml"]), { semanticSelectors: packageDescriptorSemantics(packageDescriptors(record)) }, null, null),
|
|
553
|
+
"bootstrap.source-authority": createRecord("source-owner", "bootstrap-source-authority", "packages/cli/src/validate/bootstrapAuthority.ts#bootstrapMatrixAuthority", artifactDigest(root, ["packages/cli/src/validate/bootstrapAuthority.ts"]), bootstrapMatrixAuthority(), null, null),
|
|
554
|
+
};
|
|
555
|
+
if (productionInputs?.classes) {
|
|
556
|
+
for (const classId of ["cli", "runtime", "reference", "state"]) {
|
|
557
|
+
for (const dimension of ["discovery", "behavior", "diagnostics", "instructions", "adversarial"]) {
|
|
558
|
+
const content = productionInputs.classes[classId]?.dimensions?.[dimension];
|
|
559
|
+
records[`generic.${classId}.${dimension}`] = createRecord("source-owner", `${classId}-${dimension}-source-observation`, `${classId}.${dimension}`, artifactDigest(root, GENERIC_SOURCE_ARTIFACTS[`${classId}.${dimension}`] ?? []), genericDimensionObservation(classId, dimension, content), null, null);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (packageExecution) {
|
|
564
|
+
const { fixture, runtimeSummary, missingSurfaceResults } = packageExecution;
|
|
565
|
+
const capabilityProject = path.join(fixture.root, "activation-source-package-capability-project");
|
|
566
|
+
resetObservationProject(capabilityProject);
|
|
567
|
+
const packageCapabilities = runtimeProjection(fixture.packageRoot, capabilityProject, root);
|
|
568
|
+
const packageRows = runtimeSummary.rows.filter((row) => row.runtime === "package");
|
|
569
|
+
const rejectedRows = packageRows.filter((row) => !row.accepted);
|
|
570
|
+
const commandPolicy = {
|
|
571
|
+
rowCount: packageRows.length,
|
|
572
|
+
accepted: packageRows.filter((row) => row.accepted).length,
|
|
573
|
+
rejected: rejectedRows.length,
|
|
574
|
+
classifications: Object.fromEntries([...new Set(packageRows.map((row) => row.classification))].sort().map((classification) => [classification, packageRows.filter((row) => row.classification === classification).length])),
|
|
575
|
+
compositeIdentityDigest: observationDigest(packageRows.map((row) => `${row.runtime}/${row.projectState}/${row.id}`).sort()),
|
|
576
|
+
};
|
|
577
|
+
const adversarial = {
|
|
578
|
+
rowCount: rejectedRows.length,
|
|
579
|
+
allBlockedBeforeChildStart: rejectedRows.every((row) => row.childStarted === false),
|
|
580
|
+
classifications: Object.fromEntries([...new Set(rejectedRows.map((row) => row.classification))].sort().map((classification) => [classification, rejectedRows.filter((row) => row.classification === classification).length])),
|
|
581
|
+
};
|
|
582
|
+
records["capability.extracted-served"] = createRecord("source-owner", "capability-extracted-served", "package/dist/bin/agentera.js#prime-context", packageCapabilities.artifacts.served, packageCapabilities.served, null, null);
|
|
583
|
+
records["package.command-policy"] = createRecord("source-owner", "package-command-policy", "source-integration/runtime-matrix/classifications", observationDigest(packageRows), commandPolicy, null, null);
|
|
584
|
+
records["package.adversarial"] = createRecord("source-owner", "package-adversarial", "source-integration/runtime-matrix/rejections", observationDigest(rejectedRows), adversarial, null, null);
|
|
585
|
+
records["bootstrap.extracted-classifications"] = createRecord("source-owner", "bootstrap-extracted-classifications", "source-integration/runtime-matrix/rows", observationDigest(packageRows), packageRows, null, null);
|
|
586
|
+
records["bootstrap.extracted-diagnostics"] = createRecord("source-owner", "bootstrap-extracted-diagnostics", "source-integration/runtime-matrix/rejection-diagnostics", observationDigest(rejectedRows), rejectedRows, null, null);
|
|
587
|
+
const parity = {
|
|
588
|
+
...(runtimeSummary.runtimeObservationDigests ?? {}),
|
|
589
|
+
packageArtifact: runtimeSummary.packageArtifact ?? null,
|
|
590
|
+
};
|
|
591
|
+
records["bootstrap.source-package-parity"] = createRecord("source-owner", "bootstrap-source-package-parity", "source-integration/runtime-matrix/parity", observationDigest(parity), parity, null, null);
|
|
592
|
+
records["bootstrap.missing-surface"] = createRecord("source-owner", "bootstrap-missing-surface", "source-integration/runtime-matrix/missing-required-surfaces", observationDigest(missingSurfaceResults), missingSurfaceResults, null, null);
|
|
593
|
+
}
|
|
594
|
+
return finishEvidence({
|
|
595
|
+
schemaVersion: SOURCE_OWNER_EVIDENCE_SCHEMA,
|
|
596
|
+
producerKind: "source-owner",
|
|
597
|
+
sourceDigest: activationSourceDigest(root),
|
|
598
|
+
generation: null,
|
|
599
|
+
packageIntegrity: null,
|
|
600
|
+
records,
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
function packageArtifactObservation(runtimeRoot, fixture, requiredFiles, snapshotDirectory) {
|
|
604
|
+
const tarball = path.join(fixture.root, fixture.manifest.filename);
|
|
605
|
+
const current = observeCurrentPackageArtifact(tarball, runtimeRoot, snapshotDirectory);
|
|
606
|
+
const { tarballTree, ...currentWithoutTarballEntries } = current;
|
|
607
|
+
const manifestFile = path.join(runtimeRoot, "package.json");
|
|
608
|
+
const manifestEntry = current.extractedTree.entries.find((entry) => entry.path === "package.json");
|
|
609
|
+
return {
|
|
610
|
+
...currentWithoutTarballEntries,
|
|
611
|
+
tarballTree: { count: tarballTree.entries.length, digest: tarballTree.digest },
|
|
612
|
+
manifest: {
|
|
613
|
+
path: "package.json",
|
|
614
|
+
type: "file",
|
|
615
|
+
mode: manifestEntry?.mode ?? null,
|
|
616
|
+
contentDigest: fileSha256(manifestFile),
|
|
617
|
+
},
|
|
618
|
+
requiredSurfaces: requiredFiles.map((relative) => {
|
|
619
|
+
const file = path.join(runtimeRoot, relative);
|
|
620
|
+
const stat = fs.lstatSync(file);
|
|
621
|
+
return { path: relative, type: stat.isFile() ? "file" : stat.isDirectory() ? "directory" : stat.isSymbolicLink() ? "symlink" : "other", mode: stat.mode & 0o777, contentDigest: stat.isFile() ? fileSha256(file) : null };
|
|
622
|
+
}),
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
function seedObservationProject(project) {
|
|
626
|
+
fs.mkdirSync(path.join(project, ".agentera"), { recursive: true, mode: 0o700 });
|
|
627
|
+
fs.writeFileSync(path.join(project, ".agentera/state-mode.yaml"), "schemaVersion: agentera.stateMode.v1\nmode: entities\n", { flag: "wx", mode: 0o600 });
|
|
628
|
+
}
|
|
629
|
+
function resetObservationProject(project) {
|
|
630
|
+
fs.rmSync(project, { recursive: true, force: true });
|
|
631
|
+
seedObservationProject(project);
|
|
632
|
+
}
|
|
633
|
+
export async function finalizePackageOwnerEvidence(options) {
|
|
634
|
+
const { root, fixture } = options;
|
|
635
|
+
const runtimeRoot = fixture.packageRoot;
|
|
636
|
+
const capabilityProject = path.join(fixture.root, "activation-capability-project");
|
|
637
|
+
resetObservationProject(capabilityProject);
|
|
638
|
+
const capabilities = runtimeProjection(runtimeRoot, capabilityProject, root, "package-smoke");
|
|
639
|
+
const record = packageRecord(path.join(runtimeRoot, "bundle"));
|
|
640
|
+
const packageArtifact = packageArtifactObservation(runtimeRoot, fixture, options.requiredFiles, options.snapshotDirectory);
|
|
641
|
+
const integrity = packageArtifact.integrity;
|
|
642
|
+
const portability = {
|
|
643
|
+
deterministicPackRuns: fixture.deterministicBytes.packRuns,
|
|
644
|
+
deterministicTarballSha256: fixture.deterministicBytes.sha256,
|
|
645
|
+
secondTarballSha256: fixture.deterministicBytes.secondSha256,
|
|
646
|
+
constructionRootCount: fixture.pathIndependence.constructionRoots.length,
|
|
647
|
+
constructionRootsDistinct: new Set(fixture.pathIndependence.constructionRoots).size === fixture.pathIndependence.constructionRoots.length,
|
|
648
|
+
extractedRootCount: fixture.pathIndependence.extractedRoots.length,
|
|
649
|
+
extractedRootsDistinct: new Set(fixture.pathIndependence.extractedRoots).size === fixture.pathIndependence.extractedRoots.length,
|
|
650
|
+
regularFiles: fixture.pathIndependence.regularFiles,
|
|
651
|
+
contentSha256: fixture.pathIndependence.contentSha256,
|
|
652
|
+
forbiddenPathMatches: fixture.pathIndependence.forbiddenPathMatches,
|
|
653
|
+
pathNeedleClasses: fixture.pathIndependence.pathNeedleClasses,
|
|
654
|
+
secondManifest: {
|
|
655
|
+
filename: fixture.pathIndependence.secondManifest.filename,
|
|
656
|
+
integrity: fixture.pathIndependence.secondManifest.integrity,
|
|
657
|
+
shasum: fixture.pathIndependence.secondManifest.shasum,
|
|
658
|
+
files: fixture.pathIndependence.secondManifest.files,
|
|
659
|
+
},
|
|
660
|
+
};
|
|
661
|
+
const records = {
|
|
662
|
+
"capability.extracted-modules": createRecord("package-owner", "capability-extracted-modules", "package/dist/capabilities/*/instructions.js", capabilities.artifacts.modules, capabilities.modules, null, integrity),
|
|
663
|
+
"capability.extracted-runtime-registry": createRecord("package-owner", "capability-extracted-runtime-registry", "package/dist/capabilities/index.js#CAPABILITY_INSTRUCTIONS", capabilities.artifacts.runtimeRegistry, capabilities.runtimeRegistry, null, integrity),
|
|
664
|
+
"capability.extracted-registry": createRecord("package-owner", "capability-extracted-registry", "package/bundle/registry.json#skills[0].capabilities", capabilities.artifacts.registry, capabilities.registry, null, integrity),
|
|
665
|
+
"capability.extracted-routes": createRecord("package-owner", "capability-extracted-routes", "package/dist/cli/commands/capability.js#CAPABILITY_ROUTING_NAMES", capabilities.artifacts.routes, capabilities.routes, null, integrity),
|
|
666
|
+
"capability.extracted-schemas": createRecord("package-owner", "capability-extracted-schemas", "package/bundle/skills/agentera/capabilities/*/schemas", capabilities.artifacts.schemas, capabilities.schemas, null, integrity),
|
|
667
|
+
"package.extracted-artifact": createRecord("package-owner", "package-extracted-artifact", "npm-tarball/extracted-package", observationDigest(packageArtifact), packageArtifact, null, integrity),
|
|
668
|
+
"package.extracted-registry": createRecord("package-owner", "package-extracted-registry", "package/bundle/references/adapters/package-registry.yaml#records[agentera]", artifactDigest(runtimeRoot, ["bundle/references/adapters/package-registry.yaml"]), packageDescriptorSemantics(packageDescriptors(record)), null, integrity),
|
|
669
|
+
"package.extracted-smoke": createRecord("package-owner", "package-extracted-smoke", "package/dist/bin/agentera.js#prime-context-status", capabilities.artifacts.served, capabilities.served, null, integrity),
|
|
670
|
+
"package.portability": createRecord("package-owner", "package-portability", "npm-tarball/path-portability", fixture.pathIndependence.contentSha256, portability, null, integrity),
|
|
671
|
+
"bootstrap.extracted-startup": createRecord("package-owner", "bootstrap-extracted-startup", "package/dist/bin/agentera.js#startup-producers", capabilities.artifacts.startupProducers, capabilities.startupProducers, null, integrity),
|
|
672
|
+
"bootstrap.extracted-declarations": createRecord("package-owner", "bootstrap-extracted-declarations", "package/bundle/references/adapters/package-registry.yaml#bootstrap_command_authority", artifactDigest(runtimeRoot, ["bundle/references/adapters/package-registry.yaml"]), packageCommandDeclarations(record), null, integrity),
|
|
673
|
+
};
|
|
674
|
+
for (const classId of ["runtime", "reference", "state"]) {
|
|
675
|
+
const relative = classId === "runtime"
|
|
676
|
+
? [["bundle", "references", "adapters", "runtime-lifecycle-authority.yaml"].join("/"), ["bundle", "references", "adapters", "runtime-retired-resources.yaml"].join("/")]
|
|
677
|
+
: classId === "reference"
|
|
678
|
+
? ["bundle/references/meta/retained-reference-authority.yaml"]
|
|
679
|
+
: ["dist/state/entityListRuntimeRegistry.js", "dist/state/write/runtimeOperations.js", "dist/state/write/operations.js"];
|
|
680
|
+
records[`generic.${classId}.package_projection`] = createRecord("package-owner", `${classId}-package-projection`, `package/${classId}/projection`, artifactDigest(runtimeRoot, relative), relative.map((file) => ({ file, sha256: fs.existsSync(path.join(runtimeRoot, file)) ? fileSha256(path.join(runtimeRoot, file)) : "missing" })), null, integrity);
|
|
681
|
+
}
|
|
682
|
+
const evidence = finishEvidence({
|
|
683
|
+
schemaVersion: PACKAGE_OWNER_EVIDENCE_SCHEMA,
|
|
684
|
+
producerKind: "package-owner",
|
|
685
|
+
sourceDigest: activationSourceDigest(root),
|
|
686
|
+
generation: null,
|
|
687
|
+
packageIntegrity: integrity,
|
|
688
|
+
records,
|
|
689
|
+
});
|
|
690
|
+
const unsignedIdentity = {
|
|
691
|
+
schemaVersion: PACKAGE_IDENTITY_SCHEMA,
|
|
692
|
+
packageEvidenceDigest: evidence.evidenceDigest,
|
|
693
|
+
packageArtifact: {
|
|
694
|
+
filename: packageArtifact.filename,
|
|
695
|
+
integrity: packageArtifact.integrity,
|
|
696
|
+
shasum: packageArtifact.shasum,
|
|
697
|
+
tarballSha256: packageArtifact.tarballSha256,
|
|
698
|
+
},
|
|
699
|
+
packageArtifactObservationDigest: records["package.extracted-artifact"].observationDigest,
|
|
700
|
+
extractedTree: { count: packageArtifact.extractedTree.entries.length, digest: packageArtifact.extractedTree.digest },
|
|
701
|
+
tarballTree: { count: packageArtifact.tarballTree.count, digest: packageArtifact.tarballTree.digest },
|
|
702
|
+
};
|
|
703
|
+
return { evidence, packageIdentity: { ...unsignedIdentity, identityDigest: observationDigest(unsignedIdentity) } };
|
|
704
|
+
}
|
|
705
|
+
export function createGeneratedOwnerEvidence(options) {
|
|
706
|
+
const project = fs.mkdtempSync(path.join(process.env.TMPDIR ?? options.generationRoot, "activation-generated-project-"));
|
|
707
|
+
seedObservationProject(project);
|
|
708
|
+
let runtimeObservation;
|
|
709
|
+
try {
|
|
710
|
+
runtimeObservation = runtimeArtifactObservation(options.generationRoot, project, options.root);
|
|
711
|
+
}
|
|
712
|
+
finally {
|
|
713
|
+
fs.rmSync(project, { recursive: true, force: true });
|
|
714
|
+
}
|
|
715
|
+
const capabilities = runtimeObservation.projection;
|
|
716
|
+
const bundleRoot = path.join(options.generationRoot, "bundle");
|
|
717
|
+
const record = packageRecord(bundleRoot);
|
|
718
|
+
const bootstrap = runtimeObservation.bootstrap;
|
|
719
|
+
const generationFiles = [".agentera-generation.json", "dist/.agentera-generation.json", "bundle/.agentera-generation.json", "bundle/.agentera-npx-bundle.json", "bundle/extract-corpus-parity.json"]
|
|
720
|
+
.filter((file) => fs.existsSync(path.join(options.generationRoot, file)));
|
|
721
|
+
const records = {
|
|
722
|
+
"capability.generated-modules": createRecord("generated-owner", "capability-generated-modules", "generation/dist/capabilities/*/instructions.js", capabilities.artifacts.modules, capabilities.modules, options.generation, null),
|
|
723
|
+
"capability.generated-runtime-registry": createRecord("generated-owner", "capability-generated-runtime-registry", "generation/dist/capabilities/index.js#CAPABILITY_INSTRUCTIONS", capabilities.artifacts.runtimeRegistry, capabilities.runtimeRegistry, options.generation, null),
|
|
724
|
+
"capability.generated-served": createRecord("generated-owner", "capability-generated-served", "generation/dist/bin/agentera.js#prime-context", capabilities.artifacts.served, capabilities.served, options.generation, null),
|
|
725
|
+
"capability.generated-registry": createRecord("generated-owner", "capability-generated-registry", "generation/bundle/registry.json#skills[0].capabilities", capabilities.artifacts.registry, capabilities.registry, options.generation, null),
|
|
726
|
+
"capability.generated-routes": createRecord("generated-owner", "capability-generated-routes", "generation/dist/cli/commands/capability.js#CAPABILITY_ROUTING_NAMES", capabilities.artifacts.routes, capabilities.routes, options.generation, null),
|
|
727
|
+
"capability.generated-schemas": createRecord("generated-owner", "capability-generated-schemas", "generation/bundle/skills/agentera/capabilities/*/schemas", capabilities.artifacts.schemas, capabilities.schemas, options.generation, null),
|
|
728
|
+
"package.generated-construction": createRecord("generated-owner", "package-generated-construction", "generation/package-construction-markers", artifactDigest(options.generationRoot, generationFiles), generationFiles.map((file) => ({ file, sha256: fileSha256(path.join(options.generationRoot, file)) })), options.generation, null),
|
|
729
|
+
"package.generated-registry": createRecord("generated-owner", "package-generated-registry", "generation/bundle/references/adapters/package-registry.yaml#records[agentera]", artifactDigest(options.generationRoot, ["bundle/references/adapters/package-registry.yaml"]), packageDescriptorSemantics(packageDescriptors(record)), options.generation, null),
|
|
730
|
+
"package.generated-selectors": createRecord("generated-owner", "package-generated-selectors", "generation/bundle/references/adapters/package-registry.yaml#semantic_fields", artifactDigest(options.generationRoot, ["bundle/references/adapters/package-registry.yaml"]), { semanticSelectors: packageDescriptorSemantics(packageDescriptors(record)) }, options.generation, null),
|
|
731
|
+
"bootstrap.generated-binder": createRecord("generated-owner", "bootstrap-generated-binder", "generation/dist/core/developmentInvocation.js#bindDevelopmentInvocation", artifactDigest(options.generationRoot, ["dist/core/developmentInvocation.js", "dist/validate/bootstrapAuthority.js"]), bootstrap, options.generation, null),
|
|
732
|
+
"bootstrap.generated-diagnostics": createRecord("generated-owner", "bootstrap-generated-diagnostics", "generation/dist/core/developmentInvocation.js#DevelopmentInvocationError", artifactDigest(options.generationRoot, ["dist/core/developmentInvocation.js"]), bootstrap.rows.filter((row) => row.classification !== "accepted"), options.generation, null),
|
|
733
|
+
"bootstrap.generated-startup": createRecord("generated-owner", "bootstrap-generated-startup", "generation/dist/bin/agentera.js#startup-producers", capabilities.artifacts.startupProducers, capabilities.startupProducers, options.generation, null),
|
|
734
|
+
"bootstrap.generated-declarations": createRecord("generated-owner", "bootstrap-generated-declarations", "generation/bundle/references/adapters/package-registry.yaml#bootstrap_command_authority", artifactDigest(options.generationRoot, ["bundle/references/adapters/package-registry.yaml"]), packageCommandDeclarations(record), options.generation, null),
|
|
735
|
+
"generic.cli.package_projection": createRecord("generated-owner", "cli-package-projection", "generation/dist/cli/dispatch/projections.js", artifactDigest(options.generationRoot, ["dist/cli/dispatch/projections.js"]), options.productionInputs.classes.cli.dimensions.package_projection, options.generation, null),
|
|
736
|
+
};
|
|
737
|
+
return finishEvidence({
|
|
738
|
+
schemaVersion: GENERATED_OWNER_EVIDENCE_SCHEMA,
|
|
739
|
+
producerKind: "generated-owner",
|
|
740
|
+
sourceDigest: activationSourceDigest(options.root),
|
|
741
|
+
generation: options.generation,
|
|
742
|
+
packageIntegrity: null,
|
|
743
|
+
records,
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
export function writeContentAddressedOwnerEvidence(directory, evidence) {
|
|
747
|
+
const bytes = `${canonicalObservationJson(evidence)}\n`;
|
|
748
|
+
const byteLength = Buffer.byteLength(bytes, "utf8");
|
|
749
|
+
if (byteLength > OWNER_EVIDENCE_MAX_BYTES)
|
|
750
|
+
throw new Error(`activation owner evidence exceeds ${OWNER_EVIDENCE_MAX_BYTES} bytes`);
|
|
751
|
+
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
752
|
+
const name = `${evidence.producerKind}-${evidence.evidenceDigest}.json`;
|
|
753
|
+
const target = path.join(directory, name);
|
|
754
|
+
const temporary = path.join(directory, `.${name}.${process.pid}.tmp`);
|
|
755
|
+
fs.writeFileSync(temporary, bytes, { flag: "wx", mode: 0o600 });
|
|
756
|
+
fs.renameSync(temporary, target);
|
|
757
|
+
return { path: target, digest: evidence.evidenceDigest, bytes: byteLength };
|
|
758
|
+
}
|
|
759
|
+
export function activationPackageIdentityViolations(identity, packageEvidence) {
|
|
760
|
+
if (!identity || typeof identity !== "object")
|
|
761
|
+
return ["trusted immutable package identity is missing or malformed"];
|
|
762
|
+
const actual = identity;
|
|
763
|
+
const { identityDigest, ...unsigned } = actual;
|
|
764
|
+
const violations = [];
|
|
765
|
+
if (Object.keys(actual).sort().join("\0") !== ["extractedTree", "identityDigest", "packageArtifact", "packageArtifactObservationDigest", "packageEvidenceDigest", "schemaVersion", "tarballTree"].join("\0")
|
|
766
|
+
|| Object.keys(actual.packageArtifact ?? {}).sort().join("\0") !== ["filename", "integrity", "shasum", "tarballSha256"].join("\0")
|
|
767
|
+
|| Object.keys(actual.extractedTree ?? {}).sort().join("\0") !== ["count", "digest"].join("\0")
|
|
768
|
+
|| Object.keys(actual.tarballTree ?? {}).sort().join("\0") !== ["count", "digest"].join("\0")
|
|
769
|
+
|| actual.schemaVersion !== PACKAGE_IDENTITY_SCHEMA
|
|
770
|
+
|| !/^[a-f0-9]{64}$/.test(actual.packageEvidenceDigest ?? "")
|
|
771
|
+
|| !/^[a-f0-9]{64}$/.test(actual.packageArtifactObservationDigest ?? "")
|
|
772
|
+
|| !/^agentera-\d+\.\d+\.\d+(?:-dev\.\d+)?\.tgz$/.test(actual.packageArtifact?.filename ?? "")
|
|
773
|
+
|| !/^sha512-[A-Za-z0-9+/]+={0,2}$/.test(actual.packageArtifact?.integrity ?? "")
|
|
774
|
+
|| !/^[a-f0-9]{40}$/.test(actual.packageArtifact?.shasum ?? "")
|
|
775
|
+
|| !/^[a-f0-9]{64}$/.test(actual.packageArtifact?.tarballSha256 ?? "")
|
|
776
|
+
|| !Number.isInteger(actual.extractedTree?.count) || actual.extractedTree.count < 1
|
|
777
|
+
|| !/^[a-f0-9]{64}$/.test(actual.extractedTree?.digest ?? "")
|
|
778
|
+
|| !Number.isInteger(actual.tarballTree?.count) || actual.tarballTree.count < 1
|
|
779
|
+
|| !/^[a-f0-9]{64}$/.test(actual.tarballTree?.digest ?? "")
|
|
780
|
+
|| identityDigest !== observationDigest(unsigned)) {
|
|
781
|
+
violations.push("trusted immutable package identity is missing or malformed");
|
|
782
|
+
}
|
|
783
|
+
if (packageEvidence) {
|
|
784
|
+
const artifact = packageEvidence.records?.["package.extracted-artifact"];
|
|
785
|
+
const content = artifact?.content;
|
|
786
|
+
if (packageEvidence.evidenceDigest !== actual.packageEvidenceDigest
|
|
787
|
+
|| artifact?.observationDigest !== actual.packageArtifactObservationDigest
|
|
788
|
+
|| canonicalObservationJson({
|
|
789
|
+
filename: content?.filename,
|
|
790
|
+
integrity: content?.integrity,
|
|
791
|
+
shasum: content?.shasum,
|
|
792
|
+
tarballSha256: content?.tarballSha256,
|
|
793
|
+
}) !== canonicalObservationJson(actual.packageArtifact)
|
|
794
|
+
|| content?.extractedTree?.entries?.length !== actual.extractedTree?.count
|
|
795
|
+
|| content?.extractedTree?.digest !== actual.extractedTree?.digest
|
|
796
|
+
|| content?.tarballTree?.count !== actual.tarballTree?.count
|
|
797
|
+
|| content?.tarballTree?.digest !== actual.tarballTree?.digest) {
|
|
798
|
+
violations.push("package-owner evidence differs from the independently retained package identity");
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
return [...new Set(violations)];
|
|
802
|
+
}
|
|
803
|
+
export function writeContentAddressedPackageIdentity(directory, identity) {
|
|
804
|
+
const violations = activationPackageIdentityViolations(identity);
|
|
805
|
+
if (violations.length > 0)
|
|
806
|
+
throw new Error(violations[0]);
|
|
807
|
+
const bytes = `${canonicalObservationJson(identity)}\n`;
|
|
808
|
+
const byteLength = Buffer.byteLength(bytes, "utf8");
|
|
809
|
+
if (byteLength > PACKAGE_IDENTITY_MAX_BYTES)
|
|
810
|
+
throw new Error(`activation package identity exceeds ${PACKAGE_IDENTITY_MAX_BYTES} bytes`);
|
|
811
|
+
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
812
|
+
const name = `package-identity-${identity.identityDigest}.json`;
|
|
813
|
+
const target = path.join(directory, name);
|
|
814
|
+
const temporary = path.join(directory, `.${name}.${process.pid}.tmp`);
|
|
815
|
+
fs.writeFileSync(temporary, bytes, { flag: "wx", mode: 0o600 });
|
|
816
|
+
fs.renameSync(temporary, target);
|
|
817
|
+
return { path: target, digest: identity.identityDigest, bytes: byteLength };
|
|
818
|
+
}
|
|
819
|
+
export function readContentAddressedPackageIdentity(directory) {
|
|
820
|
+
const entries = fs.existsSync(directory) ? fs.readdirSync(directory, { withFileTypes: true }) : [];
|
|
821
|
+
if (entries.length !== 1 || !entries[0]?.isFile() || entries[0].isSymbolicLink()) {
|
|
822
|
+
throw new Error("package identity is missing, duplicated, unknown, or not a regular file");
|
|
823
|
+
}
|
|
824
|
+
const file = path.join(directory, entries[0].name);
|
|
825
|
+
const stat = fs.statSync(file);
|
|
826
|
+
if (stat.size <= 0 || stat.size > PACKAGE_IDENTITY_MAX_BYTES)
|
|
827
|
+
throw new Error("package identity violates its byte bound");
|
|
828
|
+
const identity = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
829
|
+
if (entries[0].name !== `package-identity-${identity.identityDigest}.json`
|
|
830
|
+
|| activationPackageIdentityViolations(identity).length > 0) {
|
|
831
|
+
throw new Error("package identity has wrong content-addressed provenance");
|
|
832
|
+
}
|
|
833
|
+
return identity;
|
|
834
|
+
}
|
|
835
|
+
export function readContentAddressedOwnerEvidence(directory, producerKind) {
|
|
836
|
+
const entries = fs.existsSync(directory) ? fs.readdirSync(directory, { withFileTypes: true }) : [];
|
|
837
|
+
if (entries.length !== 1 || !entries[0]?.isFile() || entries[0].isSymbolicLink()) {
|
|
838
|
+
throw new Error(`${producerKind} evidence is missing, duplicated, unknown, or not a regular file`);
|
|
839
|
+
}
|
|
840
|
+
const file = path.join(directory, entries[0].name);
|
|
841
|
+
const stat = fs.statSync(file);
|
|
842
|
+
if (stat.size <= 0 || stat.size > OWNER_EVIDENCE_MAX_BYTES)
|
|
843
|
+
throw new Error(`${producerKind} evidence violates its byte bound`);
|
|
844
|
+
const evidence = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
845
|
+
if (evidence.producerKind !== producerKind || entries[0].name !== `${producerKind}-${evidence.evidenceDigest}.json`) {
|
|
846
|
+
throw new Error(`${producerKind} evidence has wrong content-addressed provenance`);
|
|
847
|
+
}
|
|
848
|
+
const { evidenceDigest, ...unsigned } = evidence;
|
|
849
|
+
if (observationDigest(unsigned) !== evidenceDigest)
|
|
850
|
+
throw new Error(`${producerKind} evidence digest does not match its content`);
|
|
851
|
+
return evidence;
|
|
852
|
+
}
|