agentera 3.0.0-dev.25 → 3.0.0-dev.27
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 +29 -23
- package/bundle/CHANGELOG.md +18 -25
- package/bundle/README.md +13 -34
- package/bundle/UPGRADE.md +71 -165
- package/bundle/references/adapters/package-manifest-interface-model.yaml +40 -241
- package/bundle/references/adapters/package-registry.yaml +0 -145
- package/bundle/references/adapters/package-surface-characterization.md +22 -42
- package/bundle/references/adapters/runtime-lifecycle-adapters.yaml +5 -219
- package/bundle/references/adapters/runtime-lifecycle-authority.yaml +2 -29
- package/bundle/references/adapters/runtime-lifecycle-operation-contract.yaml +1 -1
- package/bundle/references/analysis/analytics-boundary-proportional-2026-07-20.yaml +74 -0
- package/bundle/references/analysis/benchmark.md +11 -0
- package/bundle/references/analysis/evidence/analytics-boundary-proportional-2026-07-20/source-focused-1.json.gz +0 -0
- package/bundle/references/analysis/evidence/analytics-boundary-proportional-2026-07-20/source-focused-2.json.gz +0 -0
- package/bundle/references/analysis/evidence/analytics-boundary-proportional-2026-07-20/source-focused-3.json.gz +0 -0
- package/bundle/references/analysis/evidence/migration-pagination-proportional-2026-07-20/source-focused-1.json.gz +0 -0
- package/bundle/references/analysis/evidence/migration-pagination-proportional-2026-07-20/source-focused-2.json.gz +0 -0
- package/bundle/references/analysis/evidence/migration-pagination-proportional-2026-07-20/source-focused-3.json.gz +0 -0
- package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/precommit-cli-route.log.gz +0 -0
- package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/precommit-cli.log.gz +0 -0
- package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/precommit-documentation.log.gz +0 -0
- package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/recompute.mjs +98 -0
- package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/source-1.json.gz +0 -0
- package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/source-2.json.gz +0 -0
- package/bundle/references/analysis/evidence/verification-baseline-2026-07-20/source-3.json.gz +0 -0
- package/bundle/references/analysis/migration-pagination-proportional-2026-07-20.yaml +64 -0
- package/bundle/references/analysis/verification-baseline-2026-07-20.yaml +313 -0
- package/bundle/references/analysis/verification-final-proof-2026-07-21.yaml +340 -0
- package/bundle/references/analysis/verification-policy.yaml +142 -0
- package/bundle/references/analysis/worker-policy-2026-07-21.yaml +207 -0
- package/bundle/references/artifacts/state-storage-authority.yaml +48 -448
- package/bundle/references/cli/agent-ready-state-contract.yaml +9 -9
- package/bundle/references/cli/app-lifecycle-vocabulary.yaml +3 -4
- package/bundle/references/cli/bundle-skill-vocabulary.yaml +9 -18
- package/bundle/references/cli/capability-tool-classification.yaml +2 -2
- package/bundle/references/cli/prime-consumer-compatibility.yaml +86 -112
- package/bundle/references/cli/routing-execution-vocabulary.yaml +4 -22
- package/bundle/references/cli/upgrade-repair-wording.md +8 -28
- package/bundle/references/cli/v3-handoff-manifest.schema.yaml +2 -3
- package/bundle/references/cli/vocabulary.md +18 -23
- package/bundle/references/meta/documentation-inventory.md +3 -1
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/artifacts.yaml +3 -2
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/exit.yaml +1 -1
- package/bundle/skills/agentera/schemas/artifacts/docs.yaml +3 -11
- package/bundle/skills/agentera/schemas/artifacts/plan.yaml +23 -5
- package/dist/analytics/extractCorpus/cli.js.map +1 -1
- package/dist/analytics/extractCorpus/copilotSessions.js.map +1 -1
- package/dist/analytics/extractCorpus/core.js.map +1 -1
- package/dist/analytics/extractCorpus/corpus.js.map +1 -1
- package/dist/analytics/extractCorpus/coverageAudit.js.map +1 -1
- package/dist/analytics/extractCorpus/cursorSessions.js.map +1 -1
- package/dist/analytics/extractCorpus/evidenceTiers.js.map +1 -1
- package/dist/analytics/extractCorpus/extractCorpusParity.js +1 -1
- package/dist/analytics/extractCorpus/extractCorpusParity.js.map +1 -1
- package/dist/analytics/extractCorpus/filesystemSources.js.map +1 -1
- package/dist/analytics/extractCorpus/index.js.map +1 -1
- package/dist/analytics/extractCorpus/jsonlSessions.js.map +1 -1
- package/dist/analytics/extractCorpus/sqliteCaps.js.map +1 -1
- package/dist/analytics/extractCorpus/sqliteSessions.js.map +1 -1
- package/dist/analytics/extractCorpus/tierReader.js.map +1 -1
- package/dist/analytics/extractCorpus.js.map +1 -1
- package/dist/analytics/profileSignals.js.map +1 -1
- package/dist/analytics/usageStats.js.map +1 -1
- package/dist/bin/agentera.js.map +1 -1
- package/dist/capabilities/audit/instructions.js.map +1 -1
- package/dist/capabilities/build/instructions.js.map +1 -1
- package/dist/capabilities/design/instructions.js.map +1 -1
- package/dist/capabilities/discuss/instructions.js.map +1 -1
- package/dist/capabilities/document/instructions.js.map +1 -1
- package/dist/capabilities/index.js.map +1 -1
- package/dist/capabilities/optimize/instructions.js.map +1 -1
- package/dist/capabilities/orchestrate/instructions.js +1 -1
- package/dist/capabilities/orchestrate/instructions.js.map +1 -1
- package/dist/capabilities/plan/instructions.js.map +1 -1
- package/dist/capabilities/profile/instructions.js.map +1 -1
- package/dist/capabilities/research/instructions.js.map +1 -1
- package/dist/capabilities/status/instructions.js.map +1 -1
- package/dist/capabilities/status/startupInstructions.js.map +1 -1
- package/dist/capabilities/vision/instructions.js.map +1 -1
- package/dist/cli/appContext.js.map +1 -1
- package/dist/cli/argvalidate.js.map +1 -1
- package/dist/cli/capabilityContext/benchmark.js.map +1 -1
- package/dist/cli/capabilityContext/bespoke.js +8 -2
- package/dist/cli/capabilityContext/bespoke.js.map +1 -1
- package/dist/cli/capabilityContext/build.js.map +1 -1
- package/dist/cli/capabilityContext/closeout.js +3 -3
- package/dist/cli/capabilityContext/closeout.js.map +1 -1
- package/dist/cli/capabilityContext/contract.js.map +1 -1
- package/dist/cli/capabilityContext/evidence.js +52 -40
- package/dist/cli/capabilityContext/evidence.js.map +1 -1
- package/dist/cli/capabilityContext/index.js.map +1 -1
- package/dist/cli/capabilityContext/orchestration.js +15 -5
- package/dist/cli/capabilityContext/orchestration.js.map +1 -1
- package/dist/cli/capabilityContext/planState.js +1 -1
- package/dist/cli/capabilityContext/planState.js.map +1 -1
- package/dist/cli/capabilityContext/progress.js.map +1 -1
- package/dist/cli/capabilityContext/shared.js.map +1 -1
- package/dist/cli/capabilityContext/slim.js +16 -3
- package/dist/cli/capabilityContext/slim.js.map +1 -1
- package/dist/cli/capabilityContext/startup.js +4 -1
- package/dist/cli/capabilityContext/startup.js.map +1 -1
- package/dist/cli/capabilityContext/types.js.map +1 -1
- package/dist/cli/capabilityContext.js.map +1 -1
- package/dist/cli/commands/appHome.js.map +1 -1
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/compact.js.map +1 -1
- package/dist/cli/commands/doctor.js +6 -64
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/durability.js +12 -48
- package/dist/cli/commands/durability.js.map +1 -1
- package/dist/cli/commands/entityMigrate.js.map +1 -1
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/commands/prime/briefOrientation.js +25 -24
- package/dist/cli/commands/prime/briefOrientation.js.map +1 -1
- package/dist/cli/commands/prime/bundleStatus.js +8 -2
- package/dist/cli/commands/prime/bundleStatus.js.map +1 -1
- package/dist/cli/commands/prime/collectEntityOrientation.js +76 -24
- package/dist/cli/commands/prime/collectEntityOrientation.js.map +1 -1
- package/dist/cli/commands/prime/collectOrientationState.js +34 -53
- package/dist/cli/commands/prime/collectOrientationState.js.map +1 -1
- package/dist/cli/commands/prime/orientationOutput.js +9 -14
- package/dist/cli/commands/prime/orientationOutput.js.map +1 -1
- package/dist/cli/commands/prime/types.js.map +1 -1
- package/dist/cli/commands/prime/v1Migration.js.map +1 -1
- package/dist/cli/commands/prime.js +43 -25
- package/dist/cli/commands/prime.js.map +1 -1
- package/dist/cli/commands/query.js +17 -49
- package/dist/cli/commands/query.js.map +1 -1
- package/dist/cli/commands/report.js.map +1 -1
- package/dist/cli/commands/schema.js +19 -78
- package/dist/cli/commands/schema.js.map +1 -1
- package/dist/cli/commands/state/decisions.js +11 -57
- package/dist/cli/commands/state/decisions.js.map +1 -1
- package/dist/cli/commands/state/docs.js +56 -120
- package/dist/cli/commands/state/docs.js.map +1 -1
- package/dist/cli/commands/state/experimentRecords.js +22 -121
- package/dist/cli/commands/state/experimentRecords.js.map +1 -1
- package/dist/cli/commands/state/experiments.js +9 -75
- package/dist/cli/commands/state/experiments.js.map +1 -1
- package/dist/cli/commands/state/get.js +62 -143
- package/dist/cli/commands/state/get.js.map +1 -1
- package/dist/cli/commands/state/health.js +9 -123
- package/dist/cli/commands/state/health.js.map +1 -1
- package/dist/cli/commands/state/index.js +2 -2
- package/dist/cli/commands/state/index.js.map +1 -1
- package/dist/cli/commands/state/list.js +20 -36
- package/dist/cli/commands/state/list.js.map +1 -1
- package/dist/cli/commands/state/objective.js +19 -86
- package/dist/cli/commands/state/objective.js.map +1 -1
- package/dist/cli/commands/state/plan.js +9 -388
- package/dist/cli/commands/state/plan.js.map +1 -1
- package/dist/cli/commands/state/planTasks.js +58 -93
- package/dist/cli/commands/state/planTasks.js.map +1 -1
- package/dist/cli/commands/state/plans.js +13 -40
- package/dist/cli/commands/state/plans.js.map +1 -1
- package/dist/cli/commands/state/progress.js +10 -55
- package/dist/cli/commands/state/progress.js.map +1 -1
- package/dist/cli/commands/state/shared.js.map +1 -1
- package/dist/cli/commands/state/todo.js +24 -133
- package/dist/cli/commands/state/todo.js.map +1 -1
- package/dist/cli/commands/state/write.js +13 -35
- package/dist/cli/commands/state/write.js.map +1 -1
- package/dist/cli/commands/upgrade.js +48 -18
- package/dist/cli/commands/upgrade.js.map +1 -1
- package/dist/cli/commands/upgradeVerify.js +21 -15
- package/dist/cli/commands/upgradeVerify.js.map +1 -1
- package/dist/cli/commands/validate.js +1 -9
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/commands/verify.js.map +1 -1
- package/dist/cli/contracts/bundleStatus.js.map +1 -1
- package/dist/cli/contracts/orientationState.js.map +1 -1
- package/dist/cli/dispatch/argvParser.js.map +1 -1
- package/dist/cli/dispatch/check.js +5 -12
- package/dist/cli/dispatch/check.js.map +1 -1
- package/dist/cli/dispatch/commands.js.map +1 -1
- package/dist/cli/dispatch/index.js +30 -29
- package/dist/cli/dispatch/index.js.map +1 -1
- package/dist/cli/dispatch/lifecycle.js +23 -40
- package/dist/cli/dispatch/lifecycle.js.map +1 -1
- package/dist/cli/dispatch/prime.js.map +1 -1
- package/dist/cli/dispatch/shared.js.map +1 -1
- package/dist/cli/dispatch/state.js.map +1 -1
- package/dist/cli/dispatch.js.map +1 -1
- package/dist/cli/errors.js.map +1 -1
- package/dist/cli/help.js +20 -100
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/migrationRequired.js +22 -19
- package/dist/cli/migrationRequired.js.map +1 -1
- package/dist/cli/orientation/attention.js +1 -97
- package/dist/cli/orientation/attention.js.map +1 -1
- package/dist/cli/orientation/corpusCoverage.js.map +1 -1
- package/dist/cli/orientation.js +18 -4
- package/dist/cli/orientation.js.map +1 -1
- package/dist/cli/planArtifacts.js.map +1 -1
- package/dist/cli/planEvidence.js.map +1 -1
- package/dist/cli/planLifecycleState.js.map +1 -1
- package/dist/cli/planTaskIndex.js +12 -0
- package/dist/cli/planTaskIndex.js.map +1 -0
- package/dist/cli/prime-blob.js +1 -1
- package/dist/cli/prime-blob.js.map +1 -1
- package/dist/cli/startupCompletenessContract.js.map +1 -1
- package/dist/cli/stateQuery.js +1 -2
- package/dist/cli/stateQuery.js.map +1 -1
- package/dist/cli/structured.js.map +1 -1
- package/dist/cli/todoMarkdown.js.map +1 -1
- package/dist/cli/todoSeverity.js.map +1 -1
- package/dist/core/atomicWriter.js.map +1 -1
- package/dist/core/difflib.js.map +1 -1
- package/dist/core/envPaths.js.map +1 -1
- package/dist/core/jsonValue.js.map +1 -1
- package/dist/core/paths.js.map +1 -1
- package/dist/core/pyjson.js.map +1 -1
- package/dist/core/skillIdentity.js +24 -0
- package/dist/core/skillIdentity.js.map +1 -0
- package/dist/core/sourceRoot.js.map +1 -1
- package/dist/core/text.js.map +1 -1
- package/dist/core/toml.js.map +1 -1
- package/dist/core/yaml.js.map +1 -1
- package/dist/eval/evalSkills.js.map +1 -1
- package/dist/eval/semanticEval.js.map +1 -1
- package/dist/eval/semanticFixtures.js.map +1 -1
- package/dist/hooks/common.js +1 -1
- package/dist/hooks/common.js.map +1 -1
- package/dist/hooks/compaction/apply.js.map +1 -1
- package/dist/hooks/compaction/dryRun.js.map +1 -1
- package/dist/hooks/compaction/index.js.map +1 -1
- package/dist/hooks/compaction/parse.js.map +1 -1
- package/dist/hooks/compaction/retention.js.map +1 -1
- package/dist/hooks/compaction/status.js +2 -1
- package/dist/hooks/compaction/status.js.map +1 -1
- package/dist/hooks/compaction/types.js.map +1 -1
- package/dist/hooks/cursorPreToolUse.js.map +1 -1
- package/dist/hooks/cursorSessionStart.js +4 -25
- package/dist/hooks/cursorSessionStart.js.map +1 -1
- package/dist/hooks/projectHookInput.js +26 -0
- package/dist/hooks/projectHookInput.js.map +1 -0
- package/dist/hooks/sessionStart.js +23 -239
- package/dist/hooks/sessionStart.js.map +1 -1
- package/dist/hooks/sessionStop.js +4 -12
- package/dist/hooks/sessionStop.js.map +1 -1
- package/dist/hooks/validateArtifact/agentFacing.js.map +1 -1
- package/dist/hooks/validateArtifact/index.js.map +1 -1
- package/dist/hooks/validateArtifact/markdown.js.map +1 -1
- package/dist/hooks/validateArtifact/runtime.js.map +1 -1
- package/dist/hooks/validateArtifact/schema.js.map +1 -1
- package/dist/hooks/validateArtifact/traversal.js +1 -1
- package/dist/hooks/validateArtifact/traversal.js.map +1 -1
- package/dist/hooks/validateArtifact/violations.js.map +1 -1
- package/dist/migrate/v2HandoffManifest.js.map +1 -1
- package/dist/registries/artifactProtocolIds.js.map +1 -1
- package/dist/registries/artifactRegistry.js +2 -1
- package/dist/registries/artifactRegistry.js.map +1 -1
- package/dist/registries/capabilityContract.js.map +1 -1
- package/dist/registries/evaluatorHandoffContract.js.map +1 -1
- package/dist/registries/evidenceTierContract.js.map +1 -1
- package/dist/registries/packageRegistry.js +57 -231
- package/dist/registries/packageRegistry.js.map +1 -1
- package/dist/registries/triggerLoader.js.map +1 -1
- package/dist/registries/verbosityBudgetContract.js.map +1 -1
- package/dist/release/releaseMetadata.js +1 -13
- package/dist/release/releaseMetadata.js.map +1 -1
- package/dist/runtime/lifecycleAdapterContract.js +4 -4
- package/dist/runtime/lifecycleAdapterContract.js.map +1 -1
- package/dist/runtime/lifecycleAdapters.js +14 -2
- package/dist/runtime/lifecycleAdapters.js.map +1 -1
- package/dist/runtime/lifecycleAuthority.js +5 -43
- package/dist/runtime/lifecycleAuthority.js.map +1 -1
- package/dist/runtime/lifecycleOperationContract.js +3 -2
- package/dist/runtime/lifecycleOperationContract.js.map +1 -1
- package/dist/runtime/lifecycleOperations.js.map +1 -1
- package/dist/runtime/lifecycleOwnershipJournal.js.map +1 -1
- package/dist/runtime/lifecyclePublication.js +21 -0
- package/dist/runtime/lifecyclePublication.js.map +1 -1
- package/dist/runtime/lifecycleSnapshot.js.map +1 -1
- package/dist/runtime/retiredRuntimeCleanup.js.map +1 -1
- package/dist/setup/codex/agents.js.map +1 -1
- package/dist/setup/codex/cli.js.map +1 -1
- package/dist/setup/codex/configToml.js.map +1 -1
- package/dist/setup/codex/constants.js.map +1 -1
- package/dist/setup/codex/installRoot.js.map +1 -1
- package/dist/setup/codex/state.js.map +1 -1
- package/dist/setup/codex.js.map +1 -1
- package/dist/setup/opencode.js +20 -12
- package/dist/setup/opencode.js.map +1 -1
- package/dist/setup/opencodeConstants.js.map +1 -1
- package/dist/setup/sharedSkill.js +46 -0
- package/dist/setup/sharedSkill.js.map +1 -0
- package/dist/setup/smokeChecks.js +16 -43
- package/dist/setup/smokeChecks.js.map +1 -1
- package/dist/state/archiveDiscovery.js.map +1 -1
- package/dist/state/archivePublication.js.map +1 -1
- package/dist/state/archiveRecovery.js.map +1 -1
- package/dist/state/archiveReplay.js.map +1 -1
- package/dist/state/decisionEntities.js +7 -4
- package/dist/state/decisionEntities.js.map +1 -1
- package/dist/state/decisionLegacyValidation.js.map +1 -1
- package/dist/state/decisionOverlay.js.map +1 -1
- package/dist/state/decisionRevision.js.map +1 -1
- package/dist/state/decisionRevisionPublication.js.map +1 -1
- package/dist/state/directRetrieval.js.map +1 -1
- package/dist/state/durability.js +4 -240
- package/dist/state/durability.js.map +1 -1
- package/dist/state/entityCutover.js +90 -186
- package/dist/state/entityCutover.js.map +1 -1
- package/dist/state/entityCutoverGit.js.map +1 -1
- package/dist/state/entityMigrationPreview.js +3 -3
- package/dist/state/entityMigrationPreview.js.map +1 -1
- package/dist/state/entityPublicationContext.js.map +1 -1
- package/dist/state/entityStorage.js +49 -10
- package/dist/state/entityStorage.js.map +1 -1
- package/dist/state/experimentArchive.js.map +1 -1
- package/dist/state/experimentIdentity.js.map +1 -1
- package/dist/state/experimentRetrieval.js.map +1 -1
- package/dist/state/healthEntities.js +7 -4
- package/dist/state/healthEntities.js.map +1 -1
- package/dist/state/healthEntityValidation.js.map +1 -1
- package/dist/state/healthRepair.js.map +1 -1
- package/dist/state/installRoot.js.map +1 -1
- package/dist/state/legacyEntityCutoverEvidence.js.map +1 -1
- package/dist/state/legacyIdentity.js.map +1 -1
- package/dist/state/listAccounting.js.map +1 -1
- package/dist/state/listClassification.js.map +1 -1
- package/dist/state/listRetrieval.js.map +1 -1
- package/dist/state/objectiveExperimentEntities.js +7 -5
- package/dist/state/objectiveExperimentEntities.js.map +1 -1
- package/dist/state/planEntities.js +60 -12
- package/dist/state/planEntities.js.map +1 -1
- package/dist/state/planIdentity.js.map +1 -1
- package/dist/state/planRetrieval.js.map +1 -1
- package/dist/state/planTaskRetrieval.js.map +1 -1
- package/dist/state/progressEntities.js +4 -2
- package/dist/state/progressEntities.js.map +1 -1
- package/dist/state/projectRoot.js.map +1 -1
- package/dist/state/projectionPolicy.js.map +1 -1
- package/dist/state/retrievalAuthority.js.map +1 -1
- package/dist/state/safeProjectFile.js.map +1 -1
- package/dist/state/startupAnalysis/benchmark.js.map +1 -1
- package/dist/state/startupAnalysis/contract.js.map +1 -1
- package/dist/state/startupAnalysis/helpers.js.map +1 -1
- package/dist/state/startupAnalysis/index.js.map +1 -1
- package/dist/state/startupAnalysis/metrics.js.map +1 -1
- package/dist/state/startupAnalysis/records.js.map +1 -1
- package/dist/state/startupAnalysis/report.js.map +1 -1
- package/dist/state/startupAnalysis/threshold.js.map +1 -1
- package/dist/state/startupAnalysis.js.map +1 -1
- package/dist/state/startupProjection.js +5 -3
- package/dist/state/startupProjection.js.map +1 -1
- package/dist/state/stateMode.js +7 -0
- package/dist/state/stateMode.js.map +1 -1
- package/dist/state/todoDocsEntities.js +6 -4
- package/dist/state/todoDocsEntities.js.map +1 -1
- package/dist/state/todoDocsEntityValidation.js.map +1 -1
- package/dist/state/write/assign.js.map +1 -1
- package/dist/state/write/candidateMutation.js.map +1 -1
- package/dist/state/write/errors.js.map +1 -1
- package/dist/state/write/experimentPublication.js.map +1 -1
- package/dist/state/write/explain.js +10 -12
- package/dist/state/write/explain.js.map +1 -1
- package/dist/state/write/fields.js.map +1 -1
- package/dist/state/write/helpers.js.map +1 -1
- package/dist/state/write/index.js.map +1 -1
- package/dist/state/write/input.js.map +1 -1
- package/dist/state/write/lock.js.map +1 -1
- package/dist/state/write/mutation.js.map +1 -1
- package/dist/state/write/operations.js +6 -0
- package/dist/state/write/operations.js.map +1 -1
- package/dist/state/write/planEvaluation.js +19 -5
- package/dist/state/write/planEvaluation.js.map +1 -1
- package/dist/state/write/planPublication.js +7 -0
- package/dist/state/write/planPublication.js.map +1 -1
- package/dist/state/write/serialize.js.map +1 -1
- package/dist/state/write/transaction.js +23 -532
- package/dist/state/write/transaction.js.map +1 -1
- package/dist/state/write/validate.js.map +1 -1
- package/dist/upgrade/appContentRefresh.js +54 -44
- package/dist/upgrade/appContentRefresh.js.map +1 -1
- package/dist/upgrade/appModel.js.map +1 -1
- package/dist/upgrade/atomicWriter.js.map +1 -1
- package/dist/upgrade/bundleEvidence.js.map +1 -1
- package/dist/upgrade/channels.js.map +1 -1
- package/dist/upgrade/coexistenceProbe.js.map +1 -1
- package/dist/upgrade/compatibility.js.map +1 -1
- package/dist/upgrade/doctor.js +5 -1
- package/dist/upgrade/doctor.js.map +1 -1
- package/dist/upgrade/doctorClassifier.js.map +1 -1
- package/dist/upgrade/installedHooksRetirement.js +46 -39
- package/dist/upgrade/installedHooksRetirement.js.map +1 -1
- package/dist/upgrade/legacyAgentCleanup.js +132 -32
- package/dist/upgrade/legacyAgentCleanup.js.map +1 -1
- package/dist/upgrade/lifecycleUpgrade.js +65 -378
- package/dist/upgrade/lifecycleUpgrade.js.map +1 -1
- package/dist/upgrade/migrateArtifactsV2ToV3.js +151 -52
- package/dist/upgrade/migrateArtifactsV2ToV3.js.map +1 -1
- package/dist/upgrade/migrationPublication.js +123 -0
- package/dist/upgrade/migrationPublication.js.map +1 -0
- package/dist/upgrade/nextMajorDoctor.js.map +1 -1
- package/dist/upgrade/npxPlatformStatus.js.map +1 -1
- package/dist/upgrade/projectIntegration.js +46 -113
- package/dist/upgrade/projectIntegration.js.map +1 -1
- package/dist/upgrade/projectIntegrationDecision.js +6 -96
- package/dist/upgrade/projectIntegrationDecision.js.map +1 -1
- package/dist/upgrade/runtimeMigration.js +222 -402
- package/dist/upgrade/runtimeMigration.js.map +1 -1
- package/dist/upgrade/upgradeCommands.js +5 -4
- package/dist/upgrade/upgradeCommands.js.map +1 -1
- package/dist/upgrade/upgradeLock.js +73 -41
- package/dist/upgrade/upgradeLock.js.map +1 -1
- package/dist/upgrade/upgradeOrchestrator.js +91 -158
- package/dist/upgrade/upgradeOrchestrator.js.map +1 -1
- package/dist/upgrade/v3CapabilitySurface.js +2 -2
- package/dist/upgrade/v3CapabilitySurface.js.map +1 -1
- package/dist/upgrade/versionResolution.js.map +1 -1
- package/dist/validate/appHomeContract.js +0 -4
- package/dist/validate/appHomeContract.js.map +1 -1
- package/dist/validate/capability.js.map +1 -1
- package/dist/validate/crossCapability.js.map +1 -1
- package/dist/validate/selfAudit.js.map +1 -1
- package/dist/validate/vocabularyAuthority.js.map +1 -1
- package/package.json +23 -8
- package/bundle/.codex-plugin/plugin.json +0 -92
- package/bundle/.cursor/agents/agentera.md +0 -7
- package/bundle/.cursor/hooks.json +0 -32
- package/bundle/.cursor-plugin/plugin.json +0 -34
- package/bundle/.github/hooks/postToolUse.json +0 -9
- package/bundle/.github/hooks/preToolUse.json +0 -8
- package/bundle/.github/hooks/sessionEnd.json +0 -8
- package/bundle/.github/hooks/sessionStart.json +0 -8
- package/bundle/.github/plugin/plugin.json +0 -7
- package/bundle/.opencode/agents/agentera.md +0 -12
- package/bundle/.opencode/commands/agentera.md +0 -5
- package/bundle/.opencode/package.json +0 -31
- package/bundle/.opencode/plugins/agentera.js +0 -820
- package/bundle/agents/openai.yaml +0 -87
- package/bundle/hooks/codex-hooks.json +0 -31
- package/bundle/hooks/codex-plugin-hooks.json +0 -31
- package/bundle/plugin.json +0 -13
- package/bundle/references/adapters/cursor.md +0 -224
- package/bundle/references/adapters/opencode.md +0 -529
- package/bundle/references/adapters/runtime-adapter-characterization.md +0 -44
- package/bundle/references/adapters/runtime-adapter-interface-model.yaml +0 -200
- package/bundle/references/adapters/runtime-adapter-registry.yaml +0 -387
- package/bundle/references/adapters/runtime-feature-parity.md +0 -129
- package/dist/cli/commands/backfill.js +0 -231
- package/dist/cli/commands/backfill.js.map +0 -1
- package/dist/cli/commands/migrate.js +0 -681
- package/dist/cli/commands/migrate.js.map +0 -1
- package/dist/registries/runtimeAdapterRegistry.js +0 -324
- package/dist/registries/runtimeAdapterRegistry.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 -296
- package/dist/setup/doctor/core.js.map +0 -1
- package/dist/setup/doctor/diagnostics.js +0 -201
- package/dist/setup/doctor/diagnostics.js.map +0 -1
- package/dist/setup/doctor/opencode.js +0 -301
- 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/state/gitBackfill.js +0 -561
- package/dist/state/gitBackfill.js.map +0 -1
- package/dist/state/gitBackfillAuthority.js +0 -141
- package/dist/state/gitBackfillAuthority.js.map +0 -1
- package/dist/state/gitBackfillHistory.js +0 -278
- package/dist/state/gitBackfillHistory.js.map +0 -1
- package/dist/state/gitBackfillOutput.js +0 -209
- package/dist/state/gitBackfillOutput.js.map +0 -1
- package/dist/state/legacyMigration.js +0 -516
- package/dist/state/legacyMigration.js.map +0 -1
- package/dist/state/legacyMigrationParser.js +0 -489
- package/dist/state/legacyMigrationParser.js.map +0 -1
- package/dist/state/migrationAuthority.js +0 -413
- package/dist/state/migrationAuthority.js.map +0 -1
- package/dist/state/migrationEnrichment.js +0 -35
- package/dist/state/migrationEnrichment.js.map +0 -1
- package/dist/state/projectionRecovery.js +0 -458
- package/dist/state/projectionRecovery.js.map +0 -1
- package/dist/upgrade/migrateArtifactsV1ToV2.js +0 -568
- package/dist/upgrade/migrateArtifactsV1ToV2.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/lifecycleMain.js +0 -154
- package/dist/validate/lifecycleAdapters/lifecycleMain.js.map +0 -1
- package/dist/validate/lifecycleAdapters/nodeFormChecks.js +0 -481
- 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 -10
- package/dist/validate/lifecycleAdapters.js.map +0 -1
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
4
5
|
import { isFile, pathExists, resolvePath } from "../core/paths.js";
|
|
5
6
|
import { resolveSourceRoot } from "../core/sourceRoot.js";
|
|
6
|
-
import { loadRegistry } from "../registries/runtimeAdapterRegistry.js";
|
|
7
7
|
import { codexCopiedHooksAreAgenteraOnly, codexPluginHooksEnabled, retireCodexCopiedHookTrust, } from "../setup/codex.js";
|
|
8
8
|
import { hasManagedMarker, opencodeConfigDir, } from "../setup/opencode.js";
|
|
9
9
|
import { OPENCODE_SKILL_NAMES } from "../setup/opencodeConstants.js";
|
|
10
10
|
import { resolveInvokedUpdateChannel } from "./channels.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { projectUsesV3CapabilityInstructionModules } from "./v3CapabilitySurface.js";
|
|
11
|
+
import { doctorRoots } from "./appModel.js";
|
|
12
|
+
import { bindMigrationResource, removeBoundMigrationResource, updateBoundMigrationFile, verifyBoundMigrationResource, } from "./migrationPublication.js";
|
|
14
13
|
const PYTHON_MANAGED_PATTERNS = [
|
|
15
14
|
/hooks\/validate_artifact\.py/,
|
|
16
15
|
/hooks\/cursor_session_start\.py/,
|
|
@@ -37,12 +36,11 @@ export function projectHasProjectLevelRuntimeHooks(project) {
|
|
|
37
36
|
return candidates.some((candidate) => isFile(candidate) || pathExists(candidate));
|
|
38
37
|
}
|
|
39
38
|
const OPENCODE_COMMAND_NAMES = ["agentera"];
|
|
40
|
-
|
|
41
|
-
export function resolveNpxHookCommands(ctx) {
|
|
39
|
+
export function resolveNpxHookCommands(ctx, resolvedChannel) {
|
|
42
40
|
const env = ctx.env ?? process.env;
|
|
43
41
|
const home = ctx.home ?? env.HOME ?? os.homedir();
|
|
44
42
|
const sourceRoot = ctx.sourceRoot ?? resolveSourceRoot(env);
|
|
45
|
-
const channel = resolveInvokedUpdateChannel({
|
|
43
|
+
const channel = resolvedChannel ?? resolveInvokedUpdateChannel({
|
|
46
44
|
channel: ctx.channel ?? null,
|
|
47
45
|
env,
|
|
48
46
|
home,
|
|
@@ -72,15 +70,9 @@ export function rewireRuntimeText(text, runtime, commands) {
|
|
|
72
70
|
next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/hooks\/validate_artifact\.py\\?"?/g, commands.validate);
|
|
73
71
|
next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/app\/hooks\/validate_artifact\.py\\?"?/g, commands.validate);
|
|
74
72
|
next = next.replace(/uv run\s+\\?"?\$\{PLUGIN_ROOT\}\/hooks\/validate_artifact\.py\\?"?/g, commands.validate);
|
|
75
|
-
next = next.replace(/uv run\s
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
next = next.replace(/["']?[^"'\n]*cursor_session_start\.py[^"'\n]*["']?/g, `"${commands.cursorSessionStart}"`);
|
|
80
|
-
next = next.replace(/["']?[^"'\n]*cursor_pre_tool_use\.py[^"'\n]*["']?/g, `"${commands.cursorPreTool}"`);
|
|
81
|
-
next = next.replace(/["']?[^"'\n]*cursor_session_stop\.py[^"'\n]*["']?/g, `"${commands.cursorSessionStop}"`);
|
|
82
|
-
next = next.replace(/["']?[^"'\n]*\/app\/scripts\/agentera[^"'\n]*["']?/g, `"${commands.cliEntrypoint}"`);
|
|
83
|
-
next = next.replace(/["']?[^"'\n]*scripts\/agentera[^"'\n]*["']?/g, `"${commands.cliEntrypoint}"`);
|
|
73
|
+
next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/(?:app\/scripts|(?:app\/)?hooks)\/cursor_session_start\.py\\?"?/g, `"${commands.cursorSessionStart}"`);
|
|
74
|
+
next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/(?:app\/)?hooks\/cursor_pre_tool_use\.py\\?"?/g, `"${commands.cursorPreTool}"`);
|
|
75
|
+
next = next.replace(/uv run\s+\\?"?\$\{AGENTERA_HOME\}\/(?:app\/)?hooks\/cursor_session_stop\.py\\?"?/g, `"${commands.cursorSessionStop}"`);
|
|
84
76
|
next = next.replace(/npx -y agentera hook /g, `${commands.cliEntrypoint} hook `);
|
|
85
77
|
next = next.replace(/npx -y agentera@latest hook /g, `${commands.cliEntrypoint} hook `);
|
|
86
78
|
if (runtime === "codex") {
|
|
@@ -102,10 +94,23 @@ function needsChannelNpxRewire(text, cliEntrypoint) {
|
|
|
102
94
|
}
|
|
103
95
|
return false;
|
|
104
96
|
}
|
|
105
|
-
function
|
|
97
|
+
function textHasAuthoritativeV2AgenteraEvidence(text) {
|
|
98
|
+
const variableReference = /\$\{AGENTERA_HOME\}\/(?:app\/scripts\/(?:agentera|cursor_session_start\.py)|(?:app\/)?hooks\/(?:validate_artifact|cursor_session_start|cursor_pre_tool_use|cursor_session_stop|session_start|session_stop)\.py)/;
|
|
99
|
+
if (variableReference.test(text))
|
|
100
|
+
return true;
|
|
101
|
+
if (/AGENTERA_HOME\s*=/.test(text))
|
|
102
|
+
return true;
|
|
103
|
+
if (/\[plugins\."agentera@agentera"\]/.test(text) && /AGENTERA_HOME\s*=/.test(text))
|
|
104
|
+
return true;
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
function pushRewireItem(items, runtime, filePath, commands, allowedRoot) {
|
|
106
108
|
const text = fs.readFileSync(filePath, "utf8");
|
|
107
109
|
const needsBare = needsChannelNpxRewire(text, commands.cliEntrypoint);
|
|
108
|
-
|
|
110
|
+
const authoritative = hasManagedMarker(text)
|
|
111
|
+
|| textHasAuthoritativeV2AgenteraEvidence(text)
|
|
112
|
+
|| needsBare;
|
|
113
|
+
if (!authoritative) {
|
|
109
114
|
if (textUsesV3NpmEntrypoint(text)) {
|
|
110
115
|
items.push({
|
|
111
116
|
status: "noop",
|
|
@@ -121,7 +126,7 @@ function pushRewireItem(items, runtime, filePath, commands) {
|
|
|
121
126
|
}
|
|
122
127
|
const newText = rewireRuntimeText(text, runtime, commands);
|
|
123
128
|
const status = newText === text ? "blocked" : "pending";
|
|
124
|
-
|
|
129
|
+
const item = {
|
|
125
130
|
status,
|
|
126
131
|
action: "rewire-runtime",
|
|
127
132
|
runtime,
|
|
@@ -131,36 +136,19 @@ function pushRewireItem(items, runtime, filePath, commands) {
|
|
|
131
136
|
message: status === "pending"
|
|
132
137
|
? "will rewire runtime config from Python managed app-home to npm self-contained entrypoint"
|
|
133
138
|
: "runtime config uses Python managed paths but could not be rewritten safely",
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
function copyIfChanged(source, target) {
|
|
140
|
-
if (!isFile(source)) {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
if (isFile(target)) {
|
|
144
|
-
const before = fs.readFileSync(source);
|
|
145
|
-
const after = fs.readFileSync(target);
|
|
146
|
-
if (before.equals(after)) {
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
139
|
+
};
|
|
140
|
+
const evidenceError = bindMigrationResource(item, "target", filePath, [allowedRoot], "file");
|
|
141
|
+
if (evidenceError) {
|
|
142
|
+
item.status = "blocked";
|
|
143
|
+
item.message = `runtime config preserved: ${evidenceError}; review the unsafe path manually`;
|
|
149
144
|
}
|
|
150
|
-
|
|
151
|
-
const sourceBytes = fs.readFileSync(source);
|
|
152
|
-
writeFileAtomic(target, sourceBytes);
|
|
153
|
-
return true;
|
|
145
|
+
items.push(item);
|
|
154
146
|
}
|
|
155
|
-
function planCodexItems(items, home, project, commands
|
|
147
|
+
function planCodexItems(items, home, project, commands) {
|
|
156
148
|
for (const root of [project, home]) {
|
|
157
149
|
const hooksPath = path.join(root, ".codex", "hooks", "codex-hooks.json");
|
|
158
150
|
const configPath = path.join(root, ".codex", "config.toml");
|
|
159
|
-
if (isFile(hooksPath)) {
|
|
160
|
-
pushRewireItem(items, "codex", hooksPath, commands);
|
|
161
|
-
}
|
|
162
151
|
if (isFile(configPath)) {
|
|
163
|
-
pushRewireItem(items, "codex", configPath, commands);
|
|
164
152
|
const configText = fs.readFileSync(configPath, "utf8");
|
|
165
153
|
const pluginHooks = codexPluginHooksEnabled(configText);
|
|
166
154
|
if (pluginHooks && isFile(hooksPath)) {
|
|
@@ -172,292 +160,88 @@ function planCodexItems(items, home, project, commands, force) {
|
|
|
172
160
|
hooksText = "";
|
|
173
161
|
}
|
|
174
162
|
if (codexCopiedHooksAreAgenteraOnly(hooksText)) {
|
|
175
|
-
|
|
163
|
+
const rewiredConfig = rewireRuntimeText(configText, "codex", commands);
|
|
164
|
+
const item = {
|
|
176
165
|
status: "pending",
|
|
177
166
|
action: "retire-hooks",
|
|
178
167
|
runtime: "codex",
|
|
179
168
|
source: hooksPath,
|
|
180
169
|
target: configPath,
|
|
170
|
+
newText: retireCodexCopiedHookTrust(rewiredConfig, hooksPath),
|
|
181
171
|
message: "will remove Agentera-owned copied Codex hooks because plugin hooks are enabled",
|
|
182
|
-
}
|
|
172
|
+
};
|
|
173
|
+
const sourceError = bindMigrationResource(item, "source", hooksPath, [root], "file");
|
|
174
|
+
const targetError = bindMigrationResource(item, "target", configPath, [root], "file");
|
|
175
|
+
if (sourceError || targetError) {
|
|
176
|
+
item.status = "blocked";
|
|
177
|
+
item.message = `copied Codex hooks preserved: ${sourceError ?? targetError}; review the unsafe path manually`;
|
|
178
|
+
}
|
|
179
|
+
items.push(item);
|
|
180
|
+
continue;
|
|
183
181
|
}
|
|
184
182
|
else if (hooksText.includes("validate_artifact") || hooksText.includes("hook validate-artifact")) {
|
|
185
183
|
items.push({
|
|
186
|
-
status:
|
|
184
|
+
status: "blocked",
|
|
187
185
|
action: "retire-hooks",
|
|
188
186
|
runtime: "codex",
|
|
189
187
|
source: hooksPath,
|
|
190
188
|
target: configPath,
|
|
191
189
|
message: "plugin hooks are enabled, but copied hook target needs manual review before retirement",
|
|
192
190
|
});
|
|
191
|
+
continue;
|
|
193
192
|
}
|
|
194
193
|
}
|
|
194
|
+
pushRewireItem(items, "codex", configPath, commands, root);
|
|
195
|
+
}
|
|
196
|
+
if (isFile(hooksPath)) {
|
|
197
|
+
pushRewireItem(items, "codex", hooksPath, commands, root);
|
|
195
198
|
}
|
|
196
199
|
}
|
|
197
200
|
}
|
|
198
|
-
function planCursorItems(items, home, project,
|
|
199
|
-
for (const hooksPath of [
|
|
200
|
-
path.join(project, ".cursor", "hooks.json"),
|
|
201
|
-
path.join(home, ".cursor", "hooks.json"),
|
|
201
|
+
function planCursorItems(items, home, project, commands) {
|
|
202
|
+
for (const [root, hooksPath] of [
|
|
203
|
+
[project, path.join(project, ".cursor", "hooks.json")],
|
|
204
|
+
[home, path.join(home, ".cursor", "hooks.json")],
|
|
202
205
|
]) {
|
|
203
206
|
if (isFile(hooksPath)) {
|
|
204
|
-
pushRewireItem(items, "cursor", hooksPath, commands);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
const agentsSource = path.join(sourceRoot, ".cursor", "agents");
|
|
208
|
-
const pluginSource = path.join(sourceRoot, ".cursor-plugin", "plugin.json");
|
|
209
|
-
for (const root of [project]) {
|
|
210
|
-
const agentsDir = path.join(root, ".cursor", "agents");
|
|
211
|
-
if (isFile(pluginSource) && root === project) {
|
|
212
|
-
const pluginTarget = path.join(root, ".cursor-plugin", "plugin.json");
|
|
213
|
-
if (!isFile(pluginTarget)) {
|
|
214
|
-
items.push({
|
|
215
|
-
status: "pending",
|
|
216
|
-
action: "copy-plugin",
|
|
217
|
-
runtime: "cursor",
|
|
218
|
-
source: pluginSource,
|
|
219
|
-
target: pluginTarget,
|
|
220
|
-
message: "will copy managed Cursor plugin manifest",
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
else if (!fs.readFileSync(pluginSource).equals(fs.readFileSync(pluginTarget))) {
|
|
224
|
-
items.push({
|
|
225
|
-
status: "pending",
|
|
226
|
-
action: "copy-plugin",
|
|
227
|
-
runtime: "cursor",
|
|
228
|
-
source: pluginSource,
|
|
229
|
-
target: pluginTarget,
|
|
230
|
-
message: "will refresh managed Cursor plugin manifest",
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
const skipInTreeCursorAgents = root === project && projectUsesV3CapabilityInstructionModules(project);
|
|
235
|
-
if (skipInTreeCursorAgents) {
|
|
236
|
-
items.push({
|
|
237
|
-
status: "noop",
|
|
238
|
-
action: "copy-agent",
|
|
239
|
-
runtime: "cursor",
|
|
240
|
-
target: agentsDir,
|
|
241
|
-
message: "v3 capability instruction modules present; in-tree .cursor/agents/ uses prime --context and is not overwritten",
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
else if (pathExists(agentsSource)) {
|
|
245
|
-
const CURSOR_MANAGED_AGENT = "agentera.md";
|
|
246
|
-
const src = path.join(agentsSource, CURSOR_MANAGED_AGENT);
|
|
247
|
-
if (isFile(src)) {
|
|
248
|
-
const dst = path.join(agentsDir, CURSOR_MANAGED_AGENT);
|
|
249
|
-
if (!isFile(dst)) {
|
|
250
|
-
items.push({
|
|
251
|
-
status: "pending",
|
|
252
|
-
action: "copy-agent",
|
|
253
|
-
runtime: "cursor",
|
|
254
|
-
source: src,
|
|
255
|
-
target: dst,
|
|
256
|
-
message: "will copy managed Cursor Agentera agent",
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
const dstText = fs.readFileSync(dst, "utf8");
|
|
261
|
-
const srcText = fs.readFileSync(src, "utf8");
|
|
262
|
-
if (hasCursorManagedAgentMarker(dstText) && dstText !== srcText) {
|
|
263
|
-
items.push({
|
|
264
|
-
status: "pending",
|
|
265
|
-
action: "copy-agent",
|
|
266
|
-
runtime: "cursor",
|
|
267
|
-
source: src,
|
|
268
|
-
target: dst,
|
|
269
|
-
message: "will refresh stale managed Cursor Agentera agent",
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
207
|
+
pushRewireItem(items, "cursor", hooksPath, commands, root);
|
|
274
208
|
}
|
|
275
209
|
}
|
|
276
210
|
}
|
|
277
|
-
function planOpencodeItems(items, home,
|
|
211
|
+
function planOpencodeItems(items, home, env, commands) {
|
|
278
212
|
const configDir = opencodeConfigDir(home, env);
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
needsChannelNpxRewire(targetContent, commands.cliEntrypoint)));
|
|
288
|
-
items.push({
|
|
289
|
-
status: needsCopy ? "pending" : "noop",
|
|
290
|
-
action: "copy-plugin",
|
|
291
|
-
runtime: "opencode",
|
|
292
|
-
source: pluginSource,
|
|
293
|
-
target: pluginTarget,
|
|
294
|
-
message: needsCopy
|
|
295
|
-
? "will copy current Agentera OpenCode plugin to native plugin path"
|
|
296
|
-
: "OpenCode plugin already current at native plugin path",
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
const commandsSourceDir = path.join(sourceRoot, ".opencode", "commands");
|
|
300
|
-
const commandsTargetDir = path.join(configDir, "commands");
|
|
301
|
-
for (const name of OPENCODE_COMMAND_NAMES) {
|
|
302
|
-
const src = path.join(commandsSourceDir, `${name}.md`);
|
|
303
|
-
const dst = path.join(commandsTargetDir, `${name}.md`);
|
|
304
|
-
if (isFile(src)) {
|
|
305
|
-
const needsCopy = !isFile(dst) || (hasManagedMarker(fs.readFileSync(dst, "utf8")) && !fs.readFileSync(src).equals(fs.readFileSync(dst)));
|
|
306
|
-
items.push({
|
|
307
|
-
status: needsCopy ? "pending" : "noop",
|
|
308
|
-
action: "copy-command",
|
|
309
|
-
runtime: "opencode",
|
|
310
|
-
source: src,
|
|
311
|
-
target: dst,
|
|
312
|
-
message: needsCopy ? "will sync managed OpenCode command" : "OpenCode managed command already current",
|
|
313
|
-
});
|
|
314
|
-
}
|
|
213
|
+
const existingResources = [
|
|
214
|
+
path.join(configDir, "plugins", "agentera.js"),
|
|
215
|
+
...OPENCODE_COMMAND_NAMES.map((name) => path.join(configDir, "commands", `${name}.md`)),
|
|
216
|
+
path.join(configDir, "agents", "agentera.md"),
|
|
217
|
+
];
|
|
218
|
+
for (const resource of existingResources) {
|
|
219
|
+
if (isFile(resource))
|
|
220
|
+
pushRewireItem(items, "opencode", resource, commands, configDir);
|
|
315
221
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
status: needsCopy ? "pending" : "noop",
|
|
326
|
-
action: "copy-agent",
|
|
327
|
-
runtime: "opencode",
|
|
328
|
-
source: src,
|
|
329
|
-
target: dst,
|
|
330
|
-
message: needsCopy ? "will copy managed OpenCode Agentera agent" : "OpenCode Agentera agent already current",
|
|
331
|
-
});
|
|
332
|
-
}
|
|
222
|
+
}
|
|
223
|
+
function symlinkOwnership(linkPath, managedSkillsRoot) {
|
|
224
|
+
let stat;
|
|
225
|
+
let target;
|
|
226
|
+
try {
|
|
227
|
+
stat = fs.lstatSync(linkPath);
|
|
228
|
+
if (!stat.isSymbolicLink())
|
|
229
|
+
return null;
|
|
230
|
+
target = fs.readlinkSync(linkPath);
|
|
333
231
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
// from both ~/.config/opencode/skills and ~/.agents/skills and requires skill
|
|
337
|
-
// names unique across locations — opencode.ai/docs/skills). Maintain the link
|
|
338
|
-
// here; the legacy ~/.config/opencode/skills entry is retired below.
|
|
339
|
-
const skillsTargetDir = path.join(home, ".agents", "skills");
|
|
340
|
-
for (const name of OPENCODE_SKILL_NAMES) {
|
|
341
|
-
const src = path.join(skillsSourceRoot, name);
|
|
342
|
-
const dst = path.join(skillsTargetDir, name);
|
|
343
|
-
if (!isFile(path.join(src, "SKILL.md"))) {
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
if (!pathExists(dst)) {
|
|
347
|
-
items.push({
|
|
348
|
-
status: "pending",
|
|
349
|
-
action: "link-skill",
|
|
350
|
-
runtime: "opencode",
|
|
351
|
-
source: src,
|
|
352
|
-
target: dst,
|
|
353
|
-
message: "will create OpenCode skill link",
|
|
354
|
-
});
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
try {
|
|
358
|
-
const linkTarget = fs.readlinkSync(dst);
|
|
359
|
-
if (!linkTarget.includes("agentera") && path.basename(linkTarget) !== name) {
|
|
360
|
-
items.push({
|
|
361
|
-
status: "blocked",
|
|
362
|
-
action: "link-skill",
|
|
363
|
-
runtime: "opencode",
|
|
364
|
-
source: src,
|
|
365
|
-
target: dst,
|
|
366
|
-
message: "OpenCode skill path is user-owned; manual review required",
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
else if (path.resolve(path.dirname(dst), linkTarget) !== path.resolve(src)) {
|
|
370
|
-
items.push({
|
|
371
|
-
status: "pending",
|
|
372
|
-
action: "link-skill",
|
|
373
|
-
runtime: "opencode",
|
|
374
|
-
source: src,
|
|
375
|
-
target: dst,
|
|
376
|
-
message: "will update stale Agentera-managed OpenCode skill link",
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
catch {
|
|
381
|
-
items.push({
|
|
382
|
-
status: "pending",
|
|
383
|
-
action: "link-skill",
|
|
384
|
-
runtime: "opencode",
|
|
385
|
-
source: src,
|
|
386
|
-
target: dst,
|
|
387
|
-
message: "will replace non-symlink OpenCode skill path with managed link",
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
// D78: retire the legacy opencode-specific skill symlinks now that
|
|
392
|
-
// ~/.agents/skills is canonical. The opencode doc requires skill names
|
|
393
|
-
// unique across its discovery locations; a skill present in both
|
|
394
|
-
// ~/.config/opencode/skills and ~/.agents/skills is the duplicate-name error
|
|
395
|
-
// that let a stale copy load.
|
|
396
|
-
const legacySkillsDir = path.join(configDir, "skills");
|
|
397
|
-
if (pathExists(legacySkillsDir) && fs.statSync(legacySkillsDir).isDirectory()) {
|
|
398
|
-
for (const name of OPENCODE_SKILL_NAMES) {
|
|
399
|
-
const legacy = path.join(legacySkillsDir, name);
|
|
400
|
-
let linkTarget = null;
|
|
401
|
-
try {
|
|
402
|
-
linkTarget = fs.readlinkSync(legacy);
|
|
403
|
-
}
|
|
404
|
-
catch {
|
|
405
|
-
linkTarget = null;
|
|
406
|
-
}
|
|
407
|
-
if (linkTarget !== null) {
|
|
408
|
-
if (linkTarget.toLowerCase().includes("agentera") || path.basename(linkTarget) === name) {
|
|
409
|
-
items.push({
|
|
410
|
-
status: "pending",
|
|
411
|
-
action: "remove-stale-skill",
|
|
412
|
-
runtime: "opencode",
|
|
413
|
-
source: legacy,
|
|
414
|
-
message: `will retire duplicate OpenCode skill symlink ${name} (agent-compatible root ~/.agents/skills is canonical; D78)`,
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
items.push({
|
|
419
|
-
status: "blocked",
|
|
420
|
-
action: "remove-stale-skill",
|
|
421
|
-
runtime: "opencode",
|
|
422
|
-
source: legacy,
|
|
423
|
-
message: `legacy OpenCode skill symlink ${name} targets a non-agentera path; manual review required`,
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
else if (pathExists(legacy)) {
|
|
428
|
-
try {
|
|
429
|
-
const dirEntries = fs.readdirSync(legacy);
|
|
430
|
-
if (dirEntries.length === 0) {
|
|
431
|
-
items.push({
|
|
432
|
-
status: "pending",
|
|
433
|
-
action: "remove-stale-skill",
|
|
434
|
-
runtime: "opencode",
|
|
435
|
-
source: legacy,
|
|
436
|
-
message: `will retire empty legacy OpenCode skill directory ${name} (agent-compatible root ~/.agents/skills is canonical; D78)`,
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
else {
|
|
440
|
-
items.push({
|
|
441
|
-
status: "blocked",
|
|
442
|
-
action: "remove-stale-skill",
|
|
443
|
-
runtime: "opencode",
|
|
444
|
-
source: legacy,
|
|
445
|
-
message: `legacy OpenCode skill path ${name} is a non-empty real directory (entries: ${dirEntries.length}); manual review required (D78 retires agentera-managed symlinks and empty dirs only)`,
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
catch {
|
|
450
|
-
items.push({
|
|
451
|
-
status: "blocked",
|
|
452
|
-
action: "remove-stale-skill",
|
|
453
|
-
runtime: "opencode",
|
|
454
|
-
source: legacy,
|
|
455
|
-
message: `legacy OpenCode skill path ${name} could not be inspected; manual review required`,
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
232
|
+
catch {
|
|
233
|
+
return null;
|
|
460
234
|
}
|
|
235
|
+
const resolvedTarget = path.resolve(path.dirname(linkPath), target);
|
|
236
|
+
const relative = path.relative(managedSkillsRoot, resolvedTarget);
|
|
237
|
+
if (relative === "" || relative.startsWith("..") || path.isAbsolute(relative))
|
|
238
|
+
return null;
|
|
239
|
+
return {
|
|
240
|
+
kind: "managed-app-symlink",
|
|
241
|
+
identity: `${stat.dev}:${stat.ino}`,
|
|
242
|
+
fingerprint: `sha256:${createHash("sha256").update(target).digest("hex")}`,
|
|
243
|
+
root: managedSkillsRoot,
|
|
244
|
+
};
|
|
461
245
|
}
|
|
462
246
|
export function planStaleCommandCleanupItems(ctx, items) {
|
|
463
247
|
const env = ctx.env ?? process.env;
|
|
@@ -483,48 +267,99 @@ export function planStaleCommandCleanupItems(ctx, items) {
|
|
|
483
267
|
if (currentNames.has(name)) {
|
|
484
268
|
continue;
|
|
485
269
|
}
|
|
486
|
-
|
|
270
|
+
const item = {
|
|
487
271
|
status: "pending",
|
|
488
272
|
action: "remove-stale-command",
|
|
489
273
|
runtime: "opencode",
|
|
490
274
|
source: filePath,
|
|
491
275
|
message: `will remove stale managed command ${path.basename(filePath)}`,
|
|
492
|
-
}
|
|
276
|
+
};
|
|
277
|
+
const evidenceError = bindMigrationResource(item, "source", filePath, [home], "file");
|
|
278
|
+
if (evidenceError) {
|
|
279
|
+
item.status = "blocked";
|
|
280
|
+
item.message = `stale command preserved: ${evidenceError}; review the unsafe path manually`;
|
|
281
|
+
}
|
|
282
|
+
items.push(item);
|
|
493
283
|
}
|
|
494
284
|
}
|
|
495
285
|
export function planStaleSkillCleanupItems(ctx, items) {
|
|
496
286
|
const env = ctx.env ?? process.env;
|
|
497
287
|
const home = resolvePath(ctx.home);
|
|
498
288
|
const skillsDir = path.join(opencodeConfigDir(home, env), "skills");
|
|
499
|
-
|
|
289
|
+
let skillsDirectory;
|
|
290
|
+
try {
|
|
291
|
+
skillsDirectory = fs.lstatSync(skillsDir);
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (!skillsDirectory.isDirectory()) {
|
|
297
|
+
items.push({
|
|
298
|
+
status: "blocked",
|
|
299
|
+
action: "remove-stale-skill",
|
|
300
|
+
runtime: "opencode",
|
|
301
|
+
source: skillsDir,
|
|
302
|
+
message: `preserved ${skillsDir}: the legacy skills path is not a real directory; replace the unsafe path or review it manually`,
|
|
303
|
+
});
|
|
500
304
|
return;
|
|
501
305
|
}
|
|
502
306
|
const requiredNames = new Set(OPENCODE_SKILL_NAMES);
|
|
307
|
+
const managedSkillsRoot = path.join(doctorRoots(resolvePath(ctx.appHome)).activeBundleRoot, "skills");
|
|
503
308
|
for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
|
|
309
|
+
const linkPath = path.join(skillsDir, entry.name);
|
|
504
310
|
if (!entry.isSymbolicLink()) {
|
|
311
|
+
if (requiredNames.has(entry.name)) {
|
|
312
|
+
items.push({
|
|
313
|
+
status: "blocked",
|
|
314
|
+
action: "remove-stale-skill",
|
|
315
|
+
runtime: "opencode",
|
|
316
|
+
source: linkPath,
|
|
317
|
+
message: `preserved ${linkPath}: name and directory shape do not prove Agentera ownership; review and remove it manually if appropriate`,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
505
320
|
continue;
|
|
506
321
|
}
|
|
507
|
-
const linkPath = path.join(skillsDir, entry.name);
|
|
508
322
|
let linkTarget;
|
|
509
323
|
try {
|
|
510
324
|
linkTarget = fs.readlinkSync(linkPath);
|
|
511
325
|
}
|
|
512
326
|
catch {
|
|
327
|
+
items.push({
|
|
328
|
+
status: "blocked",
|
|
329
|
+
action: "remove-stale-skill",
|
|
330
|
+
runtime: "opencode",
|
|
331
|
+
source: linkPath,
|
|
332
|
+
message: `preserved ${linkPath}: the symlink target could not be inspected; review the unsafe resource manually`,
|
|
333
|
+
});
|
|
513
334
|
continue;
|
|
514
335
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
336
|
+
const ownership = symlinkOwnership(linkPath, managedSkillsRoot);
|
|
337
|
+
if (!ownership) {
|
|
338
|
+
if (requiredNames.has(entry.name) || linkTarget.toLowerCase().includes("agentera")) {
|
|
339
|
+
items.push({
|
|
340
|
+
status: "blocked",
|
|
341
|
+
action: "remove-stale-skill",
|
|
342
|
+
runtime: "opencode",
|
|
343
|
+
source: linkPath,
|
|
344
|
+
message: `preserved ${linkPath}: skill name or target text does not prove Agentera ownership; confirm ownership and remove it manually if appropriate`,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
519
347
|
continue;
|
|
520
348
|
}
|
|
521
|
-
|
|
349
|
+
const item = {
|
|
522
350
|
status: "pending",
|
|
523
351
|
action: "remove-stale-skill",
|
|
524
352
|
runtime: "opencode",
|
|
525
353
|
source: linkPath,
|
|
526
|
-
|
|
527
|
-
|
|
354
|
+
ownership,
|
|
355
|
+
message: `will remove v2 app-owned OpenCode skill symlink ${entry.name}`,
|
|
356
|
+
};
|
|
357
|
+
const evidenceError = bindMigrationResource(item, "source", linkPath, [home], "symlink");
|
|
358
|
+
if (evidenceError) {
|
|
359
|
+
item.status = "blocked";
|
|
360
|
+
item.message = `legacy skill preserved: ${evidenceError}; review the unsafe path manually`;
|
|
361
|
+
}
|
|
362
|
+
items.push(item);
|
|
528
363
|
}
|
|
529
364
|
}
|
|
530
365
|
function walkJsonHookFiles(dir) {
|
|
@@ -550,7 +385,7 @@ function walkJsonHookFiles(dir) {
|
|
|
550
385
|
function planCopilotItems(items, project, commands) {
|
|
551
386
|
const hooksDir = path.join(project, ".github", "hooks");
|
|
552
387
|
for (const hookFile of walkJsonHookFiles(hooksDir)) {
|
|
553
|
-
pushRewireItem(items, "copilot", hookFile, commands);
|
|
388
|
+
pushRewireItem(items, "copilot", hookFile, commands, project);
|
|
554
389
|
}
|
|
555
390
|
if (!items.some((item) => item.runtime === "copilot")) {
|
|
556
391
|
items.push({
|
|
@@ -561,7 +396,7 @@ function planCopilotItems(items, project, commands) {
|
|
|
561
396
|
});
|
|
562
397
|
}
|
|
563
398
|
}
|
|
564
|
-
export function planRuntimeMigrationItems(ctx) {
|
|
399
|
+
export function planRuntimeMigrationItems(ctx, resolvedChannel) {
|
|
565
400
|
if (!ctx.env) {
|
|
566
401
|
throw new Error("MigrationContext.env is required for runtime migration planning; pass sandboxMigrationEnv(home, sourceRoot) in tests or an explicit env in callers.");
|
|
567
402
|
}
|
|
@@ -569,21 +404,25 @@ export function planRuntimeMigrationItems(ctx) {
|
|
|
569
404
|
const project = resolvePath(ctx.project);
|
|
570
405
|
const env = ctx.env;
|
|
571
406
|
const sourceRoot = resolvePath(ctx.sourceRoot ?? resolveSourceRoot(env));
|
|
572
|
-
const commands = resolveNpxHookCommands({ ...ctx, home, env, sourceRoot });
|
|
407
|
+
const commands = resolveNpxHookCommands({ ...ctx, home, env, sourceRoot }, resolvedChannel);
|
|
573
408
|
const items = [];
|
|
574
|
-
planCodexItems(items, home, project, commands
|
|
575
|
-
planCursorItems(items, home, project,
|
|
576
|
-
planOpencodeItems(items, home,
|
|
409
|
+
planCodexItems(items, home, project, commands);
|
|
410
|
+
planCursorItems(items, home, project, commands);
|
|
411
|
+
planOpencodeItems(items, home, env, commands);
|
|
577
412
|
planStaleCommandCleanupItems(ctx, items);
|
|
578
413
|
planStaleSkillCleanupItems(ctx, items);
|
|
579
414
|
planCopilotItems(items, project, commands);
|
|
580
|
-
const hookRetirement = planInstalledHooksRetirementItems(ctx).filter((item) => item.status === "pending");
|
|
581
|
-
if (hookRetirement.length > 0 && items.some((item) => item.action === "rewire-runtime" && item.status === "pending")) {
|
|
582
|
-
items.push(...hookRetirement);
|
|
583
|
-
}
|
|
584
|
-
void loadRegistry();
|
|
585
415
|
return items;
|
|
586
416
|
}
|
|
417
|
+
const RUNTIME_MIGRATION_ACTIONS = new Set([
|
|
418
|
+
"rewire-runtime",
|
|
419
|
+
"retire-hooks",
|
|
420
|
+
"remove-stale-command",
|
|
421
|
+
"remove-stale-skill",
|
|
422
|
+
]);
|
|
423
|
+
function isRuntimeMigrationAction(action) {
|
|
424
|
+
return RUNTIME_MIGRATION_ACTIONS.has(action);
|
|
425
|
+
}
|
|
587
426
|
export function applyRuntimeMigrationItem(item, _commands) {
|
|
588
427
|
if (item.status !== "pending") {
|
|
589
428
|
return;
|
|
@@ -596,71 +435,31 @@ export function applyRuntimeMigrationItem(item, _commands) {
|
|
|
596
435
|
item.message = "rewire-runtime missing target or newText";
|
|
597
436
|
return;
|
|
598
437
|
}
|
|
599
|
-
|
|
438
|
+
updateBoundMigrationFile(item, "target", item.newText);
|
|
600
439
|
item.status = "applied";
|
|
601
440
|
item.message = "runtime config rewired to npm self-contained entrypoint";
|
|
602
441
|
break;
|
|
603
442
|
}
|
|
604
|
-
case "
|
|
605
|
-
|
|
606
|
-
case "copy-command": {
|
|
607
|
-
if (!item.source || !item.target) {
|
|
608
|
-
item.status = "failed";
|
|
609
|
-
item.message = `${item.action} missing source or target`;
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
copyIfChanged(item.source, item.target);
|
|
613
|
-
item.status = "applied";
|
|
614
|
-
item.message = `applied ${item.action}`;
|
|
615
|
-
break;
|
|
616
|
-
}
|
|
617
|
-
case "link-skill": {
|
|
618
|
-
if (!item.source || !item.target) {
|
|
443
|
+
case "retire-hooks": {
|
|
444
|
+
if (!item.source) {
|
|
619
445
|
item.status = "failed";
|
|
620
|
-
item.message = "
|
|
446
|
+
item.message = "retire-hooks missing source";
|
|
621
447
|
return;
|
|
622
448
|
}
|
|
623
|
-
if (!
|
|
449
|
+
if (!item.target) {
|
|
624
450
|
item.status = "failed";
|
|
625
|
-
item.message =
|
|
451
|
+
item.message = "retire-hooks missing target";
|
|
626
452
|
return;
|
|
627
453
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
try {
|
|
632
|
-
targetStat = fs.lstatSync(item.target);
|
|
633
|
-
}
|
|
634
|
-
catch {
|
|
635
|
-
/* target absent */
|
|
636
|
-
}
|
|
637
|
-
if (targetStat) {
|
|
638
|
-
if (targetStat.isSymbolicLink()) {
|
|
639
|
-
fs.unlinkSync(item.target);
|
|
640
|
-
}
|
|
641
|
-
else {
|
|
642
|
-
fs.rmSync(item.target, { recursive: true, force: true });
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
fs.symlinkSync(item.source, item.target);
|
|
646
|
-
item.status = "applied";
|
|
647
|
-
item.message = "OpenCode skill link created";
|
|
648
|
-
break;
|
|
649
|
-
}
|
|
650
|
-
case "retire-hooks": {
|
|
651
|
-
if (!item.source) {
|
|
454
|
+
verifyBoundMigrationResource(item, "source");
|
|
455
|
+
verifyBoundMigrationResource(item, "target");
|
|
456
|
+
if (item.newText === undefined) {
|
|
652
457
|
item.status = "failed";
|
|
653
|
-
item.message = "retire-hooks missing
|
|
458
|
+
item.message = "retire-hooks missing newText";
|
|
654
459
|
return;
|
|
655
460
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
}
|
|
659
|
-
if (item.target && isFile(item.target)) {
|
|
660
|
-
const configText = fs.readFileSync(item.target, "utf8");
|
|
661
|
-
const next = retireCodexCopiedHookTrust(configText, item.source);
|
|
662
|
-
writeFileAtomic(item.target, next, "utf8");
|
|
663
|
-
}
|
|
461
|
+
updateBoundMigrationFile(item, "target", item.newText);
|
|
462
|
+
removeBoundMigrationResource(item, "source");
|
|
664
463
|
item.status = "applied";
|
|
665
464
|
item.message = "retired Agentera-owned copied Codex hooks";
|
|
666
465
|
break;
|
|
@@ -671,15 +470,15 @@ export function applyRuntimeMigrationItem(item, _commands) {
|
|
|
671
470
|
item.message = "remove-stale-command missing source";
|
|
672
471
|
return;
|
|
673
472
|
}
|
|
674
|
-
if (
|
|
675
|
-
fs.rmSync(item.source, { force: true });
|
|
676
|
-
item.status = "applied";
|
|
677
|
-
item.message = `removed stale managed command ${path.basename(item.source)}`;
|
|
678
|
-
}
|
|
679
|
-
else {
|
|
473
|
+
if (!pathExists(item.source)) {
|
|
680
474
|
item.status = "noop";
|
|
681
475
|
item.message = `stale command already absent at ${item.source}`;
|
|
682
476
|
}
|
|
477
|
+
else {
|
|
478
|
+
removeBoundMigrationResource(item, "source");
|
|
479
|
+
item.status = "applied";
|
|
480
|
+
item.message = `removed stale managed command ${path.basename(item.source)}`;
|
|
481
|
+
}
|
|
683
482
|
break;
|
|
684
483
|
}
|
|
685
484
|
case "remove-stale-skill": {
|
|
@@ -691,47 +490,68 @@ export function applyRuntimeMigrationItem(item, _commands) {
|
|
|
691
490
|
try {
|
|
692
491
|
const stat = fs.lstatSync(item.source);
|
|
693
492
|
if (stat.isSymbolicLink()) {
|
|
694
|
-
fs.
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
item.
|
|
703
|
-
item.
|
|
704
|
-
|
|
705
|
-
|
|
493
|
+
const target = fs.readlinkSync(item.source);
|
|
494
|
+
const identity = `${stat.dev}:${stat.ino}`;
|
|
495
|
+
const fingerprint = `sha256:${createHash("sha256").update(target).digest("hex")}`;
|
|
496
|
+
const resolvedTarget = path.resolve(path.dirname(item.source), target);
|
|
497
|
+
const relative = item.ownership?.root
|
|
498
|
+
? path.relative(item.ownership.root, resolvedTarget)
|
|
499
|
+
: "..";
|
|
500
|
+
if (item.ownership?.kind !== "managed-app-symlink"
|
|
501
|
+
|| item.ownership.identity !== identity
|
|
502
|
+
|| item.ownership.fingerprint !== fingerprint
|
|
503
|
+
|| relative === ""
|
|
504
|
+
|| relative.startsWith("..")
|
|
505
|
+
|| path.isAbsolute(relative)) {
|
|
706
506
|
item.status = "blocked";
|
|
707
|
-
item.message = `
|
|
507
|
+
item.message = `preserved ${item.source}: authoritative symlink ownership changed or is missing; rerun migration and review the resource`;
|
|
508
|
+
break;
|
|
708
509
|
}
|
|
510
|
+
removeBoundMigrationResource(item, "source");
|
|
511
|
+
item.status = "applied";
|
|
512
|
+
item.message = `removed stale skill symlink ${path.basename(item.source)}`;
|
|
709
513
|
}
|
|
710
514
|
else {
|
|
711
|
-
item.status = "
|
|
712
|
-
item.message =
|
|
515
|
+
item.status = "blocked";
|
|
516
|
+
item.message = `preserved ${item.source}: only a fingerprinted v2 app-owned symlink is eligible; review it manually`;
|
|
713
517
|
}
|
|
714
518
|
}
|
|
715
|
-
catch {
|
|
716
|
-
|
|
717
|
-
|
|
519
|
+
catch (error) {
|
|
520
|
+
if (error.code === "ENOENT") {
|
|
521
|
+
item.status = "noop";
|
|
522
|
+
item.message = "stale skill already absent";
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
item.status = "failed";
|
|
526
|
+
item.message = `remove-stale-skill failed: ${error.message}`;
|
|
527
|
+
}
|
|
718
528
|
}
|
|
719
529
|
break;
|
|
720
530
|
}
|
|
721
531
|
default:
|
|
532
|
+
item.status = "failed";
|
|
533
|
+
item.message = `unsupported runtime migration action: ${item.action}`;
|
|
722
534
|
break;
|
|
723
535
|
}
|
|
724
536
|
}
|
|
725
537
|
catch (exc) {
|
|
726
|
-
item.status = "
|
|
727
|
-
item.message = `${item.action}
|
|
538
|
+
item.status = "blocked";
|
|
539
|
+
item.message = `${item.action} preserved the resource: ${exc.message}; rerun migration and review it manually`;
|
|
728
540
|
}
|
|
729
541
|
}
|
|
730
542
|
export function applyRuntimeMigrationItems(items, ctx) {
|
|
731
543
|
const commands = resolveNpxHookCommands(ctx);
|
|
732
544
|
for (const item of items) {
|
|
733
|
-
|
|
545
|
+
if (item.status !== "pending") {
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
if (isRuntimeMigrationAction(item.action)) {
|
|
549
|
+
applyRuntimeMigrationItem(item, commands);
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
item.status = "failed";
|
|
553
|
+
item.message = `unsupported runtime migration action: ${item.action}`;
|
|
554
|
+
}
|
|
734
555
|
}
|
|
735
|
-
applyInstalledHooksRetirementItems(items, ctx);
|
|
736
556
|
}
|
|
737
557
|
//# sourceMappingURL=runtimeMigration.js.map
|