agentera 3.0.0-dev.8 → 3.0.0-dev.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +252 -22
- package/bundle/.agentera-build-source.json +8 -0
- package/bundle/CHANGELOG.md +1387 -0
- package/bundle/DESIGN.md +229 -0
- package/bundle/LICENSE +201 -0
- package/bundle/README.md +143 -0
- package/bundle/UPGRADE.md +271 -0
- package/bundle/extract-corpus-parity.json +2 -4
- package/bundle/fixtures/routing/hybrid-corpus.yaml +154 -0
- package/bundle/references/adapters/package-publication.json +484 -0
- package/bundle/references/adapters/package-registry.yaml +443 -188
- package/bundle/references/adapters/package-surface-characterization.md +68 -34
- package/bundle/references/adapters/product-v1-reset.yaml +101 -0
- package/bundle/references/adapters/runtime-lifecycle-adapters.yaml +74 -0
- package/bundle/references/adapters/runtime-lifecycle-authority.yaml +62 -0
- package/bundle/references/adapters/runtime-lifecycle-operation-contract.yaml +84 -0
- package/bundle/references/adapters/runtime-retired-resources.yaml +333 -0
- package/bundle/references/analysis/evidence-tier-authority.yaml +559 -0
- package/bundle/references/analysis/personal-glossary-evaluation-authority.yaml +175 -0
- package/bundle/references/analysis/personal-glossary-evaluation-corpus.yaml +291 -0
- package/bundle/references/analysis/personal-glossary-holdout.yaml +192 -0
- package/bundle/references/analysis/verification-policy.yaml +261 -0
- package/bundle/references/artifacts/artifact-registry-interface-model.yaml +17 -8
- package/bundle/references/artifacts/glossary-entry-contract.yaml +2906 -0
- package/bundle/references/artifacts/state-storage-authority.yaml +3065 -0
- package/bundle/references/artifacts/verbosity-budget-authority.yaml +42 -0
- package/bundle/references/cli/app-lifecycle-vocabulary.yaml +3 -4
- package/bundle/references/cli/capability-instruction-contract.yaml +11 -14
- package/bundle/references/cli/hybrid-route-contract.yaml +438 -0
- package/bundle/references/cli/routing-model.md +152 -93
- package/bundle/references/cli/trigger-schema-enrichment.md +57 -46
- package/bundle/references/cli/update-channels.yaml +7 -5
- package/bundle/references/cli/vocabulary-index.yaml +7 -9
- package/bundle/references/cli/vocabulary.md +54 -97
- package/bundle/references/meta/retained-reference-authority.yaml +171 -0
- package/bundle/skills/agentera/SKILL.md +183 -63
- package/bundle/skills/agentera/capabilities/audit/schemas/artifacts.yaml +27 -19
- package/bundle/skills/agentera/capabilities/audit/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/audit/schemas/triggers.yaml +13 -35
- package/bundle/skills/agentera/capabilities/audit/schemas/validation.yaml +30 -11
- package/bundle/skills/agentera/capabilities/build/schemas/artifacts.yaml +44 -21
- package/bundle/skills/agentera/capabilities/build/schemas/exit.yaml +8 -6
- package/bundle/skills/agentera/capabilities/build/schemas/triggers.yaml +14 -36
- package/bundle/skills/agentera/capabilities/build/schemas/validation.yaml +95 -21
- package/bundle/skills/agentera/capabilities/design/schemas/artifacts.yaml +6 -6
- package/bundle/skills/agentera/capabilities/design/schemas/exit.yaml +5 -5
- package/bundle/skills/agentera/capabilities/design/schemas/triggers.yaml +5 -34
- package/bundle/skills/agentera/capabilities/design/schemas/validation.yaml +2 -2
- package/bundle/skills/agentera/capabilities/discuss/schemas/artifacts.yaml +17 -13
- package/bundle/skills/agentera/capabilities/discuss/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/discuss/schemas/triggers.yaml +6 -40
- package/bundle/skills/agentera/capabilities/discuss/schemas/validation.yaml +72 -5
- package/bundle/skills/agentera/capabilities/document/schemas/artifacts.yaml +24 -17
- package/bundle/skills/agentera/capabilities/document/schemas/triggers.yaml +5 -35
- package/bundle/skills/agentera/capabilities/document/schemas/validation.yaml +13 -13
- package/bundle/skills/agentera/capabilities/optimize/schemas/artifacts.yaml +10 -10
- package/bundle/skills/agentera/capabilities/optimize/schemas/exit.yaml +2 -2
- package/bundle/skills/agentera/capabilities/optimize/schemas/triggers.yaml +4 -35
- package/bundle/skills/agentera/capabilities/optimize/schemas/validation.yaml +3 -3
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/artifacts.yaml +34 -22
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/exit.yaml +9 -7
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/triggers.yaml +5 -37
- package/bundle/skills/agentera/capabilities/orchestrate/schemas/validation.yaml +38 -37
- package/bundle/skills/agentera/capabilities/plan/schemas/artifacts.yaml +20 -16
- package/bundle/skills/agentera/capabilities/plan/schemas/triggers.yaml +8 -31
- package/bundle/skills/agentera/capabilities/plan/schemas/validation.yaml +66 -6
- package/bundle/skills/agentera/capabilities/profile/schemas/artifacts.yaml +13 -4
- package/bundle/skills/agentera/capabilities/profile/schemas/exit.yaml +8 -5
- package/bundle/skills/agentera/capabilities/profile/schemas/triggers.yaml +8 -37
- package/bundle/skills/agentera/capabilities/profile/schemas/validation.yaml +67 -3
- package/bundle/skills/agentera/capabilities/research/schemas/artifacts.yaml +6 -6
- package/bundle/skills/agentera/capabilities/research/schemas/triggers.yaml +5 -29
- package/bundle/skills/agentera/capabilities/status/schemas/artifacts.yaml +13 -12
- package/bundle/skills/agentera/capabilities/status/schemas/triggers.yaml +7 -49
- package/bundle/skills/agentera/capabilities/vision/schemas/artifacts.yaml +8 -8
- package/bundle/skills/agentera/capabilities/vision/schemas/exit.yaml +7 -6
- package/bundle/skills/agentera/capabilities/vision/schemas/triggers.yaml +7 -39
- package/bundle/skills/agentera/capabilities/vision/schemas/validation.yaml +14 -16
- package/bundle/skills/agentera/capability_schema_contract.yaml +32 -32
- package/bundle/skills/agentera/protocol.yaml +4 -4
- package/bundle/skills/agentera/route-phrases.yaml +81 -0
- package/bundle/skills/agentera/schemas/artifacts/changelog.yaml +1 -0
- package/bundle/skills/agentera/schemas/artifacts/decisions.yaml +29 -30
- package/bundle/skills/agentera/schemas/artifacts/design.yaml +1 -0
- package/bundle/skills/agentera/schemas/artifacts/docs.yaml +7 -43
- package/bundle/skills/agentera/schemas/artifacts/experiments.yaml +140 -34
- package/bundle/skills/agentera/schemas/artifacts/glossary.yaml +87 -0
- package/bundle/skills/agentera/schemas/artifacts/health.yaml +53 -51
- package/bundle/skills/agentera/schemas/artifacts/objective.yaml +18 -35
- package/bundle/skills/agentera/schemas/artifacts/plan.yaml +453 -55
- package/bundle/skills/agentera/schemas/artifacts/progress.yaml +128 -39
- package/bundle/skills/agentera/schemas/artifacts/todo.yaml +305 -7
- package/bundle/skills/agentera/schemas/artifacts/vision.yaml +0 -19
- package/dist/.agentera-build-source.json +8 -0
- package/dist/analytics/extractCorpus/cli.js +52 -11
- package/dist/analytics/extractCorpus/copilotSessions.js +19 -8
- package/dist/analytics/extractCorpus/core.js +262 -14
- package/dist/analytics/extractCorpus/corpus.js +57 -18
- package/dist/analytics/extractCorpus/coverageAudit.js +44 -45
- package/dist/analytics/extractCorpus/cursorSessions.js +28 -8
- package/dist/analytics/extractCorpus/evidenceTiers.js +709 -0
- package/dist/analytics/extractCorpus/extractCorpusParity.js +4 -4
- package/dist/analytics/extractCorpus/filesystemSources.js +5 -5
- package/dist/analytics/extractCorpus/index.js +4 -2
- package/dist/analytics/extractCorpus/jsonlSessions.js +76 -8
- package/dist/analytics/extractCorpus/sqliteCaps.js +0 -1
- package/dist/analytics/extractCorpus/sqliteSessions.js +12 -4
- package/dist/analytics/extractCorpus/tierReader.js +108 -0
- package/dist/analytics/extractCorpus.js +0 -1
- package/dist/analytics/glossaryAdviceResolution.js +166 -0
- package/dist/analytics/glossaryInputAcquisition.js +319 -0
- package/dist/analytics/personalGlossaryAdmission.js +113 -0
- package/dist/analytics/personalGlossaryCandidateProjection.js +788 -0
- package/dist/analytics/personalGlossaryCandidateProjectionExcerpts.js +144 -0
- package/dist/analytics/personalGlossaryCandidateProjectionModel.js +1 -0
- package/dist/analytics/personalGlossaryCandidateReadView.js +23 -0
- package/dist/analytics/personalGlossaryCurrentGeneration.js +25 -0
- package/dist/analytics/personalGlossaryDecision.js +203 -0
- package/dist/analytics/personalGlossaryExplicit.js +788 -0
- package/dist/analytics/personalGlossaryExplicitMining.js +285 -0
- package/dist/analytics/personalGlossaryExplicitScope.js +41 -0
- package/dist/analytics/personalGlossaryExplicitSegments.js +418 -0
- package/dist/analytics/personalGlossaryExplicitTypes.js +26 -0
- package/dist/analytics/personalGlossaryLexicalClassifier.js +175 -0
- package/dist/analytics/personalGlossaryProfile.js +229 -0
- package/dist/analytics/personalGlossaryRecurrence.js +618 -0
- package/dist/analytics/personalGlossaryRefreshProjection.js +351 -0
- package/dist/analytics/personalGlossaryReviewRecordStorage.js +428 -0
- package/dist/analytics/personalGlossaryReviewRecords.js +332 -0
- package/dist/analytics/profileSignals.js +211 -0
- package/dist/analytics/usageStats.js +150 -23
- package/dist/audit/terminologyDrift.js +281 -0
- package/dist/bin/agentera.js +3 -2
- package/dist/capabilities/audit/instructions.js +16 -6
- package/dist/capabilities/build/instructions.js +59 -6
- package/dist/capabilities/design/instructions.js +3 -4
- package/dist/capabilities/discuss/instructions.js +29 -6
- package/dist/capabilities/document/instructions.js +11 -6
- package/dist/capabilities/index.js +20 -14
- package/dist/capabilities/optimize/instructions.js +14 -6
- package/dist/capabilities/orchestrate/instructions.js +42 -6
- package/dist/capabilities/plan/instructions.js +30 -3
- package/dist/capabilities/profile/instructions.js +104 -5
- package/dist/capabilities/research/instructions.js +4 -5
- package/dist/capabilities/status/instructions.js +15 -6
- package/dist/capabilities/status/startupInstructions.js +34 -0
- package/dist/capabilities/vision/instructions.js +3 -5
- package/dist/cli/appContext.js +14 -7
- package/dist/cli/argvalidate.js +0 -1
- package/dist/cli/capabilityContext/benchmark.js +5 -4
- package/dist/cli/capabilityContext/bespoke.js +14 -6
- package/dist/cli/capabilityContext/build.js +116 -42
- package/dist/cli/capabilityContext/closeout.js +30 -27
- package/dist/cli/capabilityContext/contract.js +18 -27
- package/dist/cli/capabilityContext/evidence.js +84 -77
- package/dist/cli/capabilityContext/index.js +0 -1
- package/dist/cli/capabilityContext/orchestration.js +42 -18
- package/dist/cli/capabilityContext/planState.js +89 -96
- package/dist/cli/capabilityContext/progress.js +52 -12
- package/dist/cli/capabilityContext/projectVerification.js +409 -0
- package/dist/cli/capabilityContext/shared.js +9 -20
- package/dist/cli/capabilityContext/slim.js +52 -8
- package/dist/cli/capabilityContext/startup.js +51 -114
- package/dist/cli/capabilityContext/startupAggregation.js +68 -0
- package/dist/cli/capabilityContext/types.js +26 -10
- package/dist/cli/capabilityContext.js +0 -1
- package/dist/cli/commands/appHome.js +0 -1
- package/dist/cli/commands/capability.js +2 -2
- package/dist/cli/commands/compact.js +163 -13
- package/dist/cli/commands/doctor.js +118 -11
- package/dist/cli/commands/durability.js +81 -0
- package/dist/cli/commands/glossaryAdvice.js +138 -0
- package/dist/cli/commands/lint.js +22 -8
- package/dist/cli/commands/personalGlossaryCandidateReads.js +755 -0
- package/dist/cli/commands/personalGlossaryDecision.js +349 -0
- package/dist/cli/commands/personalGlossaryPublish.js +484 -0
- package/dist/cli/commands/personalGlossaryReviewRecordReads.js +209 -0
- package/dist/cli/commands/personalGlossaryReviewRecords.js +623 -0
- package/dist/cli/commands/prime/briefOrientation.js +845 -0
- package/dist/cli/commands/prime/buildExecutionRequest.js +165 -0
- package/dist/cli/commands/prime/bundleStatus.js +54 -4
- package/dist/cli/commands/prime/collectEntityOrientation.js +338 -0
- package/dist/cli/commands/prime/collectOrientationState.js +124 -68
- package/dist/cli/commands/prime/orientationOutput.js +271 -59
- package/dist/cli/commands/prime/types.js +0 -1
- package/dist/cli/commands/prime.js +89 -11
- package/dist/cli/commands/profileGrounding.js +55 -0
- package/dist/cli/commands/query.js +74 -52
- package/dist/cli/commands/report.js +187 -27
- package/dist/cli/commands/route.js +142 -0
- package/dist/cli/commands/schema.js +436 -138
- package/dist/cli/commands/state/decisions.js +40 -56
- package/dist/cli/commands/state/docs.js +58 -85
- package/dist/cli/commands/state/experimentRecords.js +151 -0
- package/dist/cli/commands/state/experiments.js +11 -65
- package/dist/cli/commands/state/get.js +129 -0
- package/dist/cli/commands/state/health.js +11 -113
- package/dist/cli/commands/state/index.js +6 -41
- package/dist/cli/commands/state/list.js +194 -0
- package/dist/cli/commands/state/objective.js +21 -65
- package/dist/cli/commands/state/plan.js +11 -170
- package/dist/cli/commands/state/planTasks.js +154 -0
- package/dist/cli/commands/state/plans.js +154 -0
- package/dist/cli/commands/state/progress.js +11 -45
- package/dist/cli/commands/state/shared.js +0 -1
- package/dist/cli/commands/state/todo.js +28 -107
- package/dist/cli/commands/state/write.js +459 -0
- package/dist/cli/commands/upgrade.js +176 -5
- package/dist/cli/commands/upgradeVerify.js +118 -0
- package/dist/cli/commands/validate.js +235 -136
- package/dist/cli/commands/verify.js +73 -16
- package/dist/cli/contracts/bundleStatus.js +0 -1
- package/dist/cli/contracts/orientationState.js +0 -1
- package/dist/cli/dispatch/argvParser.js +0 -1
- package/dist/cli/dispatch/check.js +84 -40
- package/dist/cli/dispatch/commands.js +3 -3
- package/dist/cli/dispatch/index.js +84 -52
- package/dist/cli/dispatch/lifecycle.js +182 -62
- package/dist/cli/dispatch/prime.js +37 -2
- package/dist/cli/dispatch/projections.js +17 -0
- package/dist/cli/dispatch/shared.js +1 -2
- package/dist/cli/dispatch/state.js +62 -66
- package/dist/cli/dispatch.js +0 -1
- package/dist/cli/errors.js +16 -17
- package/dist/cli/help.js +419 -41
- package/dist/cli/migrationRequired.js +125 -0
- package/dist/cli/orientation/attention.js +19 -22
- package/dist/cli/orientation/corpusCoverage.js +32 -1
- package/dist/cli/orientation.js +346 -129
- package/dist/cli/planArtifacts.js +350 -0
- package/dist/cli/planEvidence.js +157 -0
- package/dist/cli/planLifecycleState.js +36 -0
- package/dist/cli/planTaskIndex.js +11 -0
- package/dist/cli/preCutoverCommand.js +32 -0
- package/dist/cli/prime-blob.js +71 -3
- package/dist/cli/productV1Eol.js +55 -0
- package/dist/cli/profileAcquisition.js +167 -0
- package/dist/cli/startupCompletenessContract.js +11 -9
- package/dist/cli/stateQuery.js +47 -12
- package/dist/cli/structured.js +0 -1
- package/dist/cli/todoMarkdown.js +25 -12
- package/dist/cli/todoReadinessSelection.js +192 -0
- package/dist/cli/todoSeverity.js +0 -1
- package/dist/core/atomicWriter.js +23 -0
- package/dist/core/developmentChannel.js +1 -0
- package/dist/core/developmentInvocation.js +377 -0
- package/dist/core/difflib.js +0 -1
- package/dist/core/envPaths.js +0 -1
- package/dist/core/jsonValue.js +0 -1
- package/dist/core/paths.js +0 -1
- package/dist/core/pyjson.js +0 -1
- package/dist/core/shell.js +4 -0
- package/dist/core/skillIdentity.js +23 -0
- package/dist/core/sourceRoot.js +9 -12
- package/dist/core/text.js +10 -0
- package/dist/core/toml.js +0 -1
- package/dist/core/yaml.js +61 -2
- package/dist/eval/evalSkills.js +13 -14
- package/dist/eval/glossaryEvaluation.js +751 -0
- package/dist/eval/glossaryEvaluationProcess.js +29 -0
- package/dist/eval/glossaryEvaluationRunner.js +571 -0
- package/dist/eval/glossaryEvaluationSuccessReport.js +297 -0
- package/dist/eval/hybridRouteEvaluation.js +155 -0
- package/dist/eval/semanticEval.js +0 -1
- package/dist/eval/semanticFixtures.js +0 -1
- package/dist/hooks/common.js +3 -56
- package/dist/hooks/compaction/apply.js +224 -47
- package/dist/hooks/compaction/dryRun.js +2 -1
- package/dist/hooks/compaction/index.js +5 -6
- package/dist/hooks/compaction/parse.js +73 -6
- package/dist/hooks/compaction/retention.js +28 -25
- package/dist/hooks/compaction/status.js +145 -26
- package/dist/hooks/compaction/types.js +0 -1
- package/dist/hooks/validateArtifact/agentFacing.js +0 -1
- package/dist/hooks/validateArtifact/index.js +6 -65
- package/dist/hooks/validateArtifact/markdown.js +9 -10
- package/dist/hooks/validateArtifact/schema.js +96 -9
- package/dist/hooks/validateArtifact/traversal.js +12 -11
- package/dist/hooks/validateArtifact/violations.js +5 -3
- package/dist/migrate/v2HandoffManifest.js +8 -3
- package/dist/registries/activationContract.js +2 -0
- package/dist/registries/activationTuples.js +145 -0
- package/dist/registries/artifactProtocolIds.js +2 -1
- package/dist/registries/artifactRegistry.js +207 -60
- package/dist/registries/artifactSchemaProjection.js +45 -0
- package/dist/registries/capabilityContract.js +5 -21
- package/dist/registries/evaluatorHandoffContract.js +0 -1
- package/dist/registries/evidenceTierContract.js +375 -0
- package/dist/registries/explicitSegmentGrammarContract.js +619 -0
- package/dist/registries/glossaryAdviceContract.js +79 -0
- package/dist/registries/glossaryCandidateContractPaths.js +6 -0
- package/dist/registries/glossaryCandidateContracts.js +820 -0
- package/dist/registries/glossaryCandidateDecisionAuthority.js +119 -0
- package/dist/registries/glossaryCandidateDecisionContract.js +62 -0
- package/dist/registries/glossaryCandidateProjectionAuthority.js +345 -0
- package/dist/registries/glossaryCandidateProjectionContract.js +108 -0
- package/dist/registries/glossaryCaveatContract.js +67 -0
- package/dist/registries/glossaryConsumerContractValidation.js +787 -0
- package/dist/registries/glossaryEntryContract.js +759 -0
- package/dist/registries/glossaryEntryTemporal.js +12 -0
- package/dist/registries/glossaryMiningAuthority.js +764 -0
- package/dist/registries/glossaryProfileFullContract.js +24 -0
- package/dist/registries/glossaryReviewRecordsAuthority.js +426 -0
- package/dist/registries/glossaryReviewRecordsContract.js +129 -0
- package/dist/registries/glossaryTermIdentity.js +139 -0
- package/dist/registries/glossaryTermOccurrence.js +20 -0
- package/dist/registries/hybridRoute.js +274 -0
- package/dist/registries/hybridRouteReceipt.js +221 -0
- package/dist/registries/packagePublication.js +273 -0
- package/dist/registries/packageRegistry.js +184 -209
- package/dist/registries/personalGlossaryContracts.js +1 -0
- package/dist/registries/todoReadinessContract.js +448 -0
- package/dist/registries/triggerLoader.js +7 -44
- package/dist/registries/verbosityBudgetContract.js +205 -0
- package/dist/release/releaseMetadata.js +168 -11
- package/dist/runtime/lifecycleAdapterContract.js +457 -0
- package/dist/runtime/lifecycleAdapters.js +777 -0
- package/dist/runtime/lifecycleAuthority.js +453 -0
- package/dist/runtime/lifecycleOperationContract.js +123 -0
- package/dist/runtime/lifecycleOperations.js +634 -0
- package/dist/runtime/lifecycleOwnershipJournal.js +622 -0
- package/dist/runtime/lifecyclePublication.js +415 -0
- package/dist/runtime/lifecycleSnapshot.js +438 -0
- package/dist/runtime/nativeResourceCleanup.js +503 -0
- package/dist/setup/opencode.js +20 -13
- package/dist/setup/opencodeConstants.js +1 -0
- package/dist/setup/sharedSkill.js +45 -0
- package/dist/setup/smokeChecks.js +14 -75
- package/dist/state/archiveDiscovery.js +580 -0
- package/dist/state/archivePublication.js +225 -0
- package/dist/state/archiveRecovery.js +237 -0
- package/dist/state/archiveReplay.js +53 -0
- package/dist/state/canonicalMigrationRecord.js +36 -0
- package/dist/state/changelog.js +221 -0
- package/dist/state/decisionEntities.js +367 -0
- package/dist/state/decisionLegacyValidation.js +215 -0
- package/dist/state/decisionMigrationProvenance.js +199 -0
- package/dist/state/decisionOverlay.js +254 -0
- package/dist/state/decisionRevision.js +256 -0
- package/dist/state/decisionRevisionMigration.js +89 -0
- package/dist/state/directRetrieval.js +323 -0
- package/dist/state/durability.js +324 -0
- package/dist/state/entityCutover.js +459 -0
- package/dist/state/entityCutoverGit.js +127 -0
- package/dist/state/entityGlossaryAuthority.js +13 -0
- package/dist/state/entityListProjection.js +187 -0
- package/dist/state/entityListRuntimeRegistry.js +85 -0
- package/dist/state/entityMigrationCausality.js +97 -0
- package/dist/state/entityMigrationIdentity.js +5 -0
- package/dist/state/entityMigrationPreview.js +840 -0
- package/dist/state/entityMigrationTodo.js +133 -0
- package/dist/state/entityPublicationContext.js +859 -0
- package/dist/state/entityRetrievalHelp.js +506 -0
- package/dist/state/entityStorage.js +899 -0
- package/dist/state/exactReplacementRecovery.js +18 -0
- package/dist/state/experimentArchive.js +63 -0
- package/dist/state/experimentIdentity.js +202 -0
- package/dist/state/healthEntities.js +262 -0
- package/dist/state/healthEntityValidation.js +18 -0
- package/dist/state/healthRepair.js +69 -0
- package/dist/state/installRoot.js +15 -7
- package/dist/state/legacyEntityCutoverEvidence.js +65 -0
- package/dist/state/legacyIdentity.js +47 -0
- package/dist/state/legacySummaryRecord.js +6 -0
- package/dist/state/listAccounting.js +54 -0
- package/dist/state/listClassification.js +17 -0
- package/dist/state/listCursor.js +42 -0
- package/dist/state/listRetrieval.js +781 -0
- package/dist/state/migrationSourceBinding.js +30 -0
- package/dist/state/objectiveExperimentEntities.js +322 -0
- package/dist/state/planEntities.js +1027 -0
- package/dist/state/planIdentity.js +47 -0
- package/dist/state/planLineageValidation.js +52 -0
- package/dist/state/planReplacementTransaction.js +475 -0
- package/dist/state/planRetrieval.js +313 -0
- package/dist/state/planTaskRetrieval.js +294 -0
- package/dist/state/progressEntities.js +512 -0
- package/dist/state/progressGlossaryCaveat.js +168 -0
- package/dist/state/progressPublicationOrder.js +19 -0
- package/dist/state/progressWritePolicy.js +33 -0
- package/dist/state/projectRoot.js +62 -0
- package/dist/state/projectionPolicy.js +190 -0
- package/dist/state/retrievalAuthority.js +156 -0
- package/dist/state/safeProjectFile.js +155 -0
- package/dist/state/startupAnalysis/benchmark.js +70 -9
- package/dist/state/startupAnalysis/contract.js +44 -10
- package/dist/state/startupAnalysis/helpers.js +1 -2
- package/dist/state/startupAnalysis/index.js +0 -1
- package/dist/state/startupAnalysis/metrics.js +0 -1
- package/dist/state/startupAnalysis/records.js +0 -1
- package/dist/state/startupAnalysis/report.js +0 -1
- package/dist/state/startupAnalysis/threshold.js +13 -1
- package/dist/state/startupAnalysis.js +0 -1
- package/dist/state/startupProjection.js +499 -0
- package/dist/state/stateMode.js +222 -0
- package/dist/state/stateStorageAuthority.js +47 -0
- package/dist/state/summaryEntityRead.js +25 -0
- package/dist/state/summaryMigrationProvenance.js +66 -0
- package/dist/state/summarySourceRowAuthority.js +36 -0
- package/dist/state/todoActivationSafety.js +58 -0
- package/dist/state/todoCreateBatch.js +69 -0
- package/dist/state/todoDocsEntities.js +1339 -0
- package/dist/state/todoDocsEntityValidation.js +158 -0
- package/dist/state/todoMarkdownProjection.js +63 -0
- package/dist/state/todoReconciliationActivation.js +182 -0
- package/dist/state/todoReconciliationInspection.js +184 -0
- package/dist/state/todoReconciliationRepair.js +320 -0
- package/dist/state/todoReconciliationTransaction.js +628 -0
- package/dist/state/todoSeverityHeadings.js +71 -0
- package/dist/state/todoTransitionBatch.js +65 -0
- package/dist/state/todoUpdateBatch.js +50 -0
- package/dist/state/write/assign.js +20 -0
- package/dist/state/write/candidateMutation.js +269 -0
- package/dist/state/write/errors.js +11 -0
- package/dist/state/write/experimentPublication.js +192 -0
- package/dist/state/write/explain.js +380 -0
- package/dist/state/write/fields.js +61 -0
- package/dist/state/write/glossaryPublication.js +263 -0
- package/dist/state/write/grammar.js +285 -0
- package/dist/state/write/helpers.js +29 -0
- package/dist/state/write/index.js +12 -0
- package/dist/state/write/input.js +391 -0
- package/dist/state/write/lock.js +837 -0
- package/dist/state/write/mutation.js +234 -0
- package/dist/state/write/operations.js +170 -0
- package/dist/state/write/planEvaluation.js +128 -0
- package/dist/state/write/planPublication.js +179 -0
- package/dist/state/write/runtimeOperations.js +146 -0
- package/dist/state/write/serialize.js +1 -0
- package/dist/state/write/transaction.js +57 -0
- package/dist/state/write/validate.js +7 -0
- package/dist/upgrade/appContentRefresh.js +77 -36
- package/dist/upgrade/appModel.js +0 -1
- package/dist/upgrade/atomicWriter.js +1 -0
- package/dist/upgrade/bundleEvidence.js +0 -1
- package/dist/upgrade/channels.js +6 -9
- package/dist/upgrade/compatibility.js +43 -17
- package/dist/upgrade/doctor.js +55 -32
- package/dist/upgrade/doctorClassifier.js +11 -1
- package/dist/upgrade/installedHooksRetirement.js +46 -40
- package/dist/upgrade/legacyAgentCleanup.js +133 -34
- package/dist/upgrade/lifecycleUpgrade.js +113 -0
- package/dist/upgrade/migrateArtifactsV2ToV3.js +325 -82
- package/dist/upgrade/migrationPublication.js +122 -0
- package/dist/upgrade/nextMajorDoctor.js +0 -22
- package/dist/upgrade/npxPlatformStatus.js +2 -2
- package/dist/upgrade/productV1Reset.js +515 -0
- package/dist/upgrade/productV1ResetAuthority.js +139 -0
- package/dist/upgrade/projectIntegration.js +126 -134
- package/dist/upgrade/projectIntegrationDecision.js +21 -13
- package/dist/upgrade/retiredResourceDiagnostics.js +117 -0
- package/dist/upgrade/runtimeMigration.js +210 -430
- package/dist/upgrade/upgradeCommands.js +14 -1
- package/dist/upgrade/upgradeLock.js +85 -0
- package/dist/upgrade/upgradeOrchestrator.js +253 -48
- package/dist/upgrade/v3CapabilitySurface.js +2 -3
- package/dist/upgrade/versionResolution.js +0 -1
- package/dist/validate/activationArtifactEvidence.js +866 -0
- package/dist/validate/activationArtifactEvidenceTypes.js +12 -0
- package/dist/validate/activationConjunction.js +816 -0
- package/dist/validate/activationEvidenceManifest.js +610 -0
- package/dist/validate/activationPackageSemantics.js +29 -0
- package/dist/validate/appHomeContract.js +1 -7
- package/dist/validate/bootstrapAuthority.js +44 -0
- package/dist/validate/capability.js +11 -3
- package/dist/validate/crossCapability.js +14 -9
- package/dist/validate/glossaryVariantGuard.js +96 -0
- package/dist/validate/retainedReferenceAuthority.js +879 -0
- package/dist/validate/selfAudit.js +39 -45
- package/dist/validate/vocabularyAuthority.js +8 -8
- package/package.json +39 -13
- package/bundle/references/adapters/cursor.md +0 -214
- package/bundle/references/adapters/opencode.md +0 -530
- package/bundle/references/adapters/package-manifest-interface-model.yaml +0 -337
- package/bundle/references/adapters/runtime-adapter-characterization.md +0 -79
- package/bundle/references/adapters/runtime-adapter-interface-model.yaml +0 -200
- package/bundle/references/adapters/runtime-adapter-registry.yaml +0 -554
- package/bundle/references/adapters/runtime-feature-parity.md +0 -189
- package/bundle/references/analysis/benchmark.md +0 -267
- package/bundle/references/analysis/startup-measurement-contract.yaml +0 -424
- package/bundle/references/cli/agent-ready-state-contract.yaml +0 -953
- package/bundle/references/cli/audience-namespace-cli-migration.yaml +0 -369
- package/bundle/references/cli/bundle-skill-vocabulary.yaml +0 -250
- package/bundle/references/cli/capability-tool-classification.yaml +0 -53
- package/bundle/references/cli/coexistence-probe.yaml +0 -13
- package/bundle/references/cli/parity-expected-actual-template.md +0 -30
- package/bundle/references/cli/routing-execution-vocabulary.yaml +0 -281
- package/bundle/references/cli/single-name-protocol.yaml +0 -42
- package/bundle/references/cli/upgrade-repair-wording.md +0 -45
- package/bundle/references/cli/v3-handoff-manifest.schema.yaml +0 -98
- package/bundle/references/meta/documentation-inventory.md +0 -49
- package/bundle/skills/agentera/.claude-plugin/plugin.json +0 -27
- package/bundle/skills/agentera/agents/audit.toml +0 -6
- package/bundle/skills/agentera/agents/build.toml +0 -6
- package/bundle/skills/agentera/agents/design.toml +0 -6
- package/bundle/skills/agentera/agents/discuss.toml +0 -6
- package/bundle/skills/agentera/agents/document.toml +0 -6
- package/bundle/skills/agentera/agents/optimize.toml +0 -6
- package/bundle/skills/agentera/agents/orchestrate.toml +0 -6
- package/bundle/skills/agentera/agents/plan.toml +0 -6
- package/bundle/skills/agentera/agents/profile.toml +0 -6
- package/bundle/skills/agentera/agents/research.toml +0 -6
- package/bundle/skills/agentera/agents/status.toml +0 -6
- package/bundle/skills/agentera/agents/vision.toml +0 -6
- package/bundle/skills/agentera/references/contract.md +0 -1048
- package/dist/analytics/extractCorpus/cli.js.map +0 -1
- package/dist/analytics/extractCorpus/copilotSessions.js.map +0 -1
- package/dist/analytics/extractCorpus/core.js.map +0 -1
- package/dist/analytics/extractCorpus/corpus.js.map +0 -1
- package/dist/analytics/extractCorpus/coverageAudit.js.map +0 -1
- package/dist/analytics/extractCorpus/cursorSessions.js.map +0 -1
- package/dist/analytics/extractCorpus/extractCorpusParity.js.map +0 -1
- package/dist/analytics/extractCorpus/filesystemSources.js.map +0 -1
- package/dist/analytics/extractCorpus/index.js.map +0 -1
- package/dist/analytics/extractCorpus/jsonlSessions.js.map +0 -1
- package/dist/analytics/extractCorpus/sqliteCaps.js.map +0 -1
- package/dist/analytics/extractCorpus/sqliteSessions.js.map +0 -1
- package/dist/analytics/extractCorpus.js.map +0 -1
- package/dist/analytics/usageStats.js.map +0 -1
- package/dist/bin/agentera.js.map +0 -1
- package/dist/capabilities/audit/instructions.js.map +0 -1
- package/dist/capabilities/build/instructions.js.map +0 -1
- package/dist/capabilities/design/instructions.js.map +0 -1
- package/dist/capabilities/discuss/instructions.js.map +0 -1
- package/dist/capabilities/document/instructions.js.map +0 -1
- package/dist/capabilities/index.js.map +0 -1
- package/dist/capabilities/optimize/instructions.js.map +0 -1
- package/dist/capabilities/orchestrate/instructions.js.map +0 -1
- package/dist/capabilities/plan/instructions.js.map +0 -1
- package/dist/capabilities/profile/instructions.js.map +0 -1
- package/dist/capabilities/research/instructions.js.map +0 -1
- package/dist/capabilities/status/instructions.js.map +0 -1
- package/dist/capabilities/vision/instructions.js.map +0 -1
- package/dist/cli/appContext.js.map +0 -1
- package/dist/cli/argvalidate.js.map +0 -1
- package/dist/cli/capabilityContext/benchmark.js.map +0 -1
- package/dist/cli/capabilityContext/bespoke.js.map +0 -1
- package/dist/cli/capabilityContext/build.js.map +0 -1
- package/dist/cli/capabilityContext/closeout.js.map +0 -1
- package/dist/cli/capabilityContext/contract.js.map +0 -1
- package/dist/cli/capabilityContext/evidence.js.map +0 -1
- package/dist/cli/capabilityContext/index.js.map +0 -1
- package/dist/cli/capabilityContext/orchestration.js.map +0 -1
- package/dist/cli/capabilityContext/planState.js.map +0 -1
- package/dist/cli/capabilityContext/progress.js.map +0 -1
- package/dist/cli/capabilityContext/shared.js.map +0 -1
- package/dist/cli/capabilityContext/slim.js.map +0 -1
- package/dist/cli/capabilityContext/startup.js.map +0 -1
- package/dist/cli/capabilityContext/types.js.map +0 -1
- package/dist/cli/capabilityContext.js.map +0 -1
- package/dist/cli/commands/appHome.js.map +0 -1
- package/dist/cli/commands/capability.js.map +0 -1
- package/dist/cli/commands/compact.js.map +0 -1
- package/dist/cli/commands/doctor.js.map +0 -1
- package/dist/cli/commands/lint.js.map +0 -1
- package/dist/cli/commands/prime/bundleStatus.js.map +0 -1
- package/dist/cli/commands/prime/collectOrientationState.js.map +0 -1
- package/dist/cli/commands/prime/orientationOutput.js.map +0 -1
- package/dist/cli/commands/prime/types.js.map +0 -1
- package/dist/cli/commands/prime/v1Migration.js +0 -39
- package/dist/cli/commands/prime/v1Migration.js.map +0 -1
- package/dist/cli/commands/prime.js.map +0 -1
- package/dist/cli/commands/query.js.map +0 -1
- package/dist/cli/commands/report.js.map +0 -1
- package/dist/cli/commands/schema.js.map +0 -1
- package/dist/cli/commands/state/decisions.js.map +0 -1
- package/dist/cli/commands/state/docs.js.map +0 -1
- package/dist/cli/commands/state/experiments.js.map +0 -1
- package/dist/cli/commands/state/health.js.map +0 -1
- package/dist/cli/commands/state/index.js.map +0 -1
- package/dist/cli/commands/state/objective.js.map +0 -1
- package/dist/cli/commands/state/plan.js.map +0 -1
- package/dist/cli/commands/state/progress.js.map +0 -1
- package/dist/cli/commands/state/shared.js.map +0 -1
- package/dist/cli/commands/state/todo.js.map +0 -1
- package/dist/cli/commands/upgrade.js.map +0 -1
- package/dist/cli/commands/validate.js.map +0 -1
- package/dist/cli/commands/verify.js.map +0 -1
- package/dist/cli/contracts/bundleStatus.js.map +0 -1
- package/dist/cli/contracts/orientationState.js.map +0 -1
- package/dist/cli/dispatch/argvParser.js.map +0 -1
- package/dist/cli/dispatch/check.js.map +0 -1
- package/dist/cli/dispatch/commands.js.map +0 -1
- package/dist/cli/dispatch/index.js.map +0 -1
- package/dist/cli/dispatch/lifecycle.js.map +0 -1
- package/dist/cli/dispatch/prime.js.map +0 -1
- package/dist/cli/dispatch/shared.js.map +0 -1
- package/dist/cli/dispatch/state.js.map +0 -1
- package/dist/cli/dispatch.js.map +0 -1
- package/dist/cli/errors.js.map +0 -1
- package/dist/cli/help.js.map +0 -1
- package/dist/cli/orientation/attention.js.map +0 -1
- package/dist/cli/orientation/corpusCoverage.js.map +0 -1
- package/dist/cli/orientation.js.map +0 -1
- package/dist/cli/prime-blob.js.map +0 -1
- package/dist/cli/startupCompletenessContract.js.map +0 -1
- package/dist/cli/stateQuery.js.map +0 -1
- package/dist/cli/structured.js.map +0 -1
- package/dist/cli/todoMarkdown.js.map +0 -1
- package/dist/cli/todoSeverity.js.map +0 -1
- package/dist/core/difflib.js.map +0 -1
- package/dist/core/envPaths.js.map +0 -1
- package/dist/core/jsonValue.js.map +0 -1
- package/dist/core/paths.js.map +0 -1
- package/dist/core/pyjson.js.map +0 -1
- package/dist/core/sourceRoot.js.map +0 -1
- package/dist/core/toml.js.map +0 -1
- package/dist/core/yaml.js.map +0 -1
- package/dist/eval/evalSkills.js.map +0 -1
- package/dist/eval/semanticEval.js.map +0 -1
- package/dist/eval/semanticFixtures.js.map +0 -1
- package/dist/hooks/common.js.map +0 -1
- package/dist/hooks/compaction/apply.js.map +0 -1
- package/dist/hooks/compaction/dryRun.js.map +0 -1
- package/dist/hooks/compaction/index.js.map +0 -1
- package/dist/hooks/compaction/parse.js.map +0 -1
- package/dist/hooks/compaction/retention.js.map +0 -1
- package/dist/hooks/compaction/status.js.map +0 -1
- package/dist/hooks/compaction/types.js.map +0 -1
- package/dist/hooks/cursorPreToolUse.js +0 -19
- package/dist/hooks/cursorPreToolUse.js.map +0 -1
- package/dist/hooks/cursorSessionStart.js +0 -79
- package/dist/hooks/cursorSessionStart.js.map +0 -1
- package/dist/hooks/sessionStart.js +0 -216
- package/dist/hooks/sessionStart.js.map +0 -1
- package/dist/hooks/sessionStop.js +0 -206
- package/dist/hooks/sessionStop.js.map +0 -1
- package/dist/hooks/validateArtifact/agentFacing.js.map +0 -1
- package/dist/hooks/validateArtifact/index.js.map +0 -1
- package/dist/hooks/validateArtifact/markdown.js.map +0 -1
- package/dist/hooks/validateArtifact/runtime.js +0 -86
- package/dist/hooks/validateArtifact/runtime.js.map +0 -1
- package/dist/hooks/validateArtifact/schema.js.map +0 -1
- package/dist/hooks/validateArtifact/traversal.js.map +0 -1
- package/dist/hooks/validateArtifact/violations.js.map +0 -1
- package/dist/migrate/v2HandoffManifest.js.map +0 -1
- package/dist/registries/artifactProtocolIds.js.map +0 -1
- package/dist/registries/artifactRegistry.js.map +0 -1
- package/dist/registries/capabilityContract.js.map +0 -1
- package/dist/registries/evaluatorHandoffContract.js.map +0 -1
- package/dist/registries/packageRegistry.js.map +0 -1
- package/dist/registries/runtimeAdapterRegistry.js +0 -316
- package/dist/registries/runtimeAdapterRegistry.js.map +0 -1
- package/dist/registries/triggerLoader.js.map +0 -1
- package/dist/release/releaseMetadata.js.map +0 -1
- package/dist/setup/codex/agents.js +0 -96
- package/dist/setup/codex/agents.js.map +0 -1
- package/dist/setup/codex/cli.js +0 -161
- package/dist/setup/codex/cli.js.map +0 -1
- package/dist/setup/codex/configToml.js +0 -639
- package/dist/setup/codex/configToml.js.map +0 -1
- package/dist/setup/codex/constants.js +0 -29
- package/dist/setup/codex/constants.js.map +0 -1
- package/dist/setup/codex/installRoot.js +0 -64
- package/dist/setup/codex/installRoot.js.map +0 -1
- package/dist/setup/codex/state.js +0 -270
- package/dist/setup/codex/state.js.map +0 -1
- package/dist/setup/codex.js +0 -12
- package/dist/setup/codex.js.map +0 -1
- package/dist/setup/copilot.js +0 -227
- package/dist/setup/copilot.js.map +0 -1
- package/dist/setup/cursor.js +0 -129
- package/dist/setup/cursor.js.map +0 -1
- package/dist/setup/cursorSurfaces.js +0 -67
- package/dist/setup/cursorSurfaces.js.map +0 -1
- package/dist/setup/doctor/core.js +0 -300
- package/dist/setup/doctor/core.js.map +0 -1
- package/dist/setup/doctor/diagnostics.js +0 -240
- package/dist/setup/doctor/diagnostics.js.map +0 -1
- package/dist/setup/doctor/opencode.js +0 -313
- package/dist/setup/doctor/opencode.js.map +0 -1
- package/dist/setup/doctor/report.js +0 -425
- package/dist/setup/doctor/report.js.map +0 -1
- package/dist/setup/doctor.js +0 -10
- package/dist/setup/doctor.js.map +0 -1
- package/dist/setup/opencode.js.map +0 -1
- package/dist/setup/smokeChecks.js.map +0 -1
- package/dist/state/installRoot.js.map +0 -1
- package/dist/state/startupAnalysis/benchmark.js.map +0 -1
- package/dist/state/startupAnalysis/contract.js.map +0 -1
- package/dist/state/startupAnalysis/helpers.js.map +0 -1
- package/dist/state/startupAnalysis/index.js.map +0 -1
- package/dist/state/startupAnalysis/metrics.js.map +0 -1
- package/dist/state/startupAnalysis/records.js.map +0 -1
- package/dist/state/startupAnalysis/report.js.map +0 -1
- package/dist/state/startupAnalysis/threshold.js.map +0 -1
- package/dist/state/startupAnalysis.js.map +0 -1
- package/dist/upgrade/appContentRefresh.js.map +0 -1
- package/dist/upgrade/appModel.js.map +0 -1
- package/dist/upgrade/bundleEvidence.js.map +0 -1
- package/dist/upgrade/channels.js.map +0 -1
- package/dist/upgrade/coexistenceProbe.js +0 -107
- package/dist/upgrade/coexistenceProbe.js.map +0 -1
- package/dist/upgrade/compatibility.js.map +0 -1
- package/dist/upgrade/doctor.js.map +0 -1
- package/dist/upgrade/doctorClassifier.js.map +0 -1
- package/dist/upgrade/installedHooksRetirement.js.map +0 -1
- package/dist/upgrade/legacyAgentCleanup.js.map +0 -1
- package/dist/upgrade/migrateArtifactsV1ToV2.js +0 -570
- package/dist/upgrade/migrateArtifactsV1ToV2.js.map +0 -1
- package/dist/upgrade/migrateArtifactsV2ToV3.js.map +0 -1
- package/dist/upgrade/nextMajorDoctor.js.map +0 -1
- package/dist/upgrade/npxPlatformStatus.js.map +0 -1
- package/dist/upgrade/projectIntegration.js.map +0 -1
- package/dist/upgrade/projectIntegrationDecision.js.map +0 -1
- package/dist/upgrade/runtimeMigration.js.map +0 -1
- package/dist/upgrade/upgradeCommands.js.map +0 -1
- package/dist/upgrade/upgradeOrchestrator.js.map +0 -1
- package/dist/upgrade/v3CapabilitySurface.js.map +0 -1
- package/dist/upgrade/versionResolution.js.map +0 -1
- package/dist/validate/appHomeContract.js.map +0 -1
- package/dist/validate/capability.js.map +0 -1
- package/dist/validate/crossCapability.js.map +0 -1
- package/dist/validate/lifecycleAdapters/legacyPythonParity.js +0 -93
- package/dist/validate/lifecycleAdapters/legacyPythonParity.js.map +0 -1
- package/dist/validate/lifecycleAdapters/nodeFormChecks.js +0 -488
- package/dist/validate/lifecycleAdapters/nodeFormChecks.js.map +0 -1
- package/dist/validate/lifecycleAdapters/shared.js +0 -198
- package/dist/validate/lifecycleAdapters/shared.js.map +0 -1
- package/dist/validate/lifecycleAdapters.js +0 -62
- package/dist/validate/lifecycleAdapters.js.map +0 -1
- package/dist/validate/selfAudit.js.map +0 -1
- package/dist/validate/vocabularyAuthority.js.map +0 -1
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { loadYamlMapping } from "../core/yaml.js";
|
|
5
|
+
import { canonicalRecordJson } from "./archiveDiscovery.js";
|
|
6
|
+
import { canonicalEntityEnvelopeBytes, entityExactGetMaxBytes } from "./entityStorage.js";
|
|
7
|
+
import { FILE_REPLACEMENT_METADATA_NAME, FILE_REPLACEMENT_RECOVERY_VERSION, validateEntityRecoveryDirectory, } from "./entityPublicationContext.js";
|
|
8
|
+
import { ExactReplacementConflictError, FileReplacementError } from "./exactReplacementRecovery.js";
|
|
9
|
+
import { TODO_RECONCILIATION_ACTIVATION_PATH } from "./todoReconciliationActivation.js";
|
|
10
|
+
import { todoUpdateBatchEffectSha256 } from "./todoUpdateBatch.js";
|
|
11
|
+
import { todoCreateBatchEffectSha256 } from "./todoCreateBatch.js";
|
|
12
|
+
import { reject } from "./write/errors.js";
|
|
13
|
+
const VERSION = "agentera.todoReconciliationTransaction.v1";
|
|
14
|
+
const DIRECTORY = ".agentera/.todo-reconciliation";
|
|
15
|
+
const MAX_JOURNAL_BYTES = 4 * 1024 * 1024;
|
|
16
|
+
const MAX_TARGET_BYTES = 1024 * 1024;
|
|
17
|
+
const MAX_TARGETS = Math.floor(MAX_JOURNAL_BYTES / 32);
|
|
18
|
+
const ENTITY_MODE_MARKER = ".agentera/state-mode.yaml";
|
|
19
|
+
export class InjectedTodoReconciliationInterruption extends Error {
|
|
20
|
+
publishedTargets;
|
|
21
|
+
constructor(publishedTargets) {
|
|
22
|
+
super(`injected TODO reconciliation interruption after ${publishedTargets} target publications`);
|
|
23
|
+
this.publishedTargets = publishedTargets;
|
|
24
|
+
this.name = "InjectedTodoReconciliationInterruption";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function encode(bytes) {
|
|
28
|
+
return Buffer.from(bytes).toString("base64");
|
|
29
|
+
}
|
|
30
|
+
function decode(bytes) {
|
|
31
|
+
return Buffer.from(bytes, "base64");
|
|
32
|
+
}
|
|
33
|
+
function exactBase64(value) {
|
|
34
|
+
if (typeof value !== "string")
|
|
35
|
+
return false;
|
|
36
|
+
try {
|
|
37
|
+
return encode(decode(value)) === value;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function todoCreateRequestSha256(record) {
|
|
44
|
+
return createHash("sha256")
|
|
45
|
+
.update("agentera.todoCreateRequest.v1\0")
|
|
46
|
+
.update(canonicalRecordJson(record))
|
|
47
|
+
.digest("hex");
|
|
48
|
+
}
|
|
49
|
+
function bytesAt(root, relative) {
|
|
50
|
+
const target = path.join(root, relative);
|
|
51
|
+
return fs.existsSync(target) ? fs.readFileSync(target) : null;
|
|
52
|
+
}
|
|
53
|
+
function same(left, right) {
|
|
54
|
+
return left === null ? right === null : right !== null && left.equals(right);
|
|
55
|
+
}
|
|
56
|
+
function validTarget(relative, publicPath) {
|
|
57
|
+
return relative === publicPath
|
|
58
|
+
|| relative === TODO_RECONCILIATION_ACTIVATION_PATH
|
|
59
|
+
|| relative === ENTITY_MODE_MARKER
|
|
60
|
+
|| /^\.agentera\/entities\/[a-z][a-z0-9_]*\/[a-z][a-z0-9_]*\/[a-z]{10}\.yaml$/.test(relative);
|
|
61
|
+
}
|
|
62
|
+
function createReceiptFromTargets(targets) {
|
|
63
|
+
const created = targets.filter((target) => target.before === null && /^\.agentera\/entities\/todo\/todo_item\/[a-z]{10}\.yaml$/.test(target.path));
|
|
64
|
+
if (!created.length)
|
|
65
|
+
return undefined;
|
|
66
|
+
if (created.length !== 1)
|
|
67
|
+
return undefined;
|
|
68
|
+
const target = created[0];
|
|
69
|
+
const createdId = path.posix.basename(target.path, ".yaml");
|
|
70
|
+
let envelope;
|
|
71
|
+
try {
|
|
72
|
+
envelope = loadYamlMapping(decode(target.after).toString("utf8"));
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
invalidJournal("TODO reconciliation journal has an invalid created entity envelope");
|
|
76
|
+
}
|
|
77
|
+
if (envelope.id !== createdId || envelope.artifact !== "todo" || !envelope.record || typeof envelope.record !== "object" || Array.isArray(envelope.record)) {
|
|
78
|
+
invalidJournal("TODO reconciliation journal create target does not match its canonical entity envelope");
|
|
79
|
+
}
|
|
80
|
+
const request = structuredClone(envelope.record);
|
|
81
|
+
delete request.reconciliation;
|
|
82
|
+
return { created_id: createdId, request_sha256: todoCreateRequestSha256(request) };
|
|
83
|
+
}
|
|
84
|
+
function invalidJournal(message) {
|
|
85
|
+
reject({
|
|
86
|
+
class: "conflict",
|
|
87
|
+
message,
|
|
88
|
+
recovery: `Preserve '${DIRECTORY}', restore its last valid committed journal bytes, and retry the exact non-dry-run TODO mutation; no target bytes were changed.`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function parseJournal(bytes, fileName) {
|
|
92
|
+
if (bytes.length > MAX_JOURNAL_BYTES)
|
|
93
|
+
invalidJournal("TODO reconciliation journal exceeds its byte bound");
|
|
94
|
+
let parsed;
|
|
95
|
+
try {
|
|
96
|
+
parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
invalidJournal("TODO reconciliation journal is not valid bounded UTF-8 JSON");
|
|
100
|
+
}
|
|
101
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
102
|
+
invalidJournal("TODO reconciliation journal is not a mapping");
|
|
103
|
+
const value = parsed;
|
|
104
|
+
const expectedKeys = ["schema_version", "id", "public_path", "mapping_sha256", "targets", ...(value.create === undefined ? [] : ["create"]), ...(value.create_batch === undefined ? [] : ["create_batch"]), ...(value.activation_effect_sha256 === undefined ? [] : ["activation_effect_sha256"]), ...(value.owner_mapping_sha256 === undefined ? [] : ["owner_mapping_sha256"]), ...(value.update_batch_effect_sha256 === undefined ? [] : ["update_batch_effect_sha256"])].sort().join(",");
|
|
105
|
+
if (Object.keys(value).sort().join(",") !== expectedKeys
|
|
106
|
+
|| value.schema_version !== VERSION
|
|
107
|
+
|| typeof value.id !== "string"
|
|
108
|
+
|| !/^[a-f0-9]{24}$/.test(value.id)
|
|
109
|
+
|| typeof value.public_path !== "string"
|
|
110
|
+
|| typeof value.mapping_sha256 !== "string"
|
|
111
|
+
|| !/^[a-f0-9]{64}$/.test(value.mapping_sha256)
|
|
112
|
+
|| !Array.isArray(value.targets)
|
|
113
|
+
|| value.targets.length < 1
|
|
114
|
+
|| value.targets.length > MAX_TARGETS)
|
|
115
|
+
invalidJournal("TODO reconciliation journal is malformed");
|
|
116
|
+
if (value.activation_effect_sha256 !== undefined && !/^[a-f0-9]{64}$/.test(value.activation_effect_sha256))
|
|
117
|
+
invalidJournal("TODO reconciliation journal has an invalid activation effect authorization");
|
|
118
|
+
if (value.owner_mapping_sha256 !== undefined && !/^[a-f0-9]{64}$/.test(value.owner_mapping_sha256))
|
|
119
|
+
invalidJournal("TODO reconciliation journal has an invalid owner-mapping authorization");
|
|
120
|
+
if (value.update_batch_effect_sha256 !== undefined && !/^[a-f0-9]{64}$/.test(value.update_batch_effect_sha256))
|
|
121
|
+
invalidJournal("TODO reconciliation journal has an invalid update-batch effect authorization");
|
|
122
|
+
if (value.create_batch !== undefined && (!value.create_batch || typeof value.create_batch !== "object" || Array.isArray(value.create_batch) || Object.keys(value.create_batch).sort().join(",") !== "effect_sha256,input_sha256,local_refs" || !/^[a-f0-9]{64}$/.test(value.create_batch.effect_sha256) || !/^[a-f0-9]{64}$/.test(value.create_batch.input_sha256) || !value.create_batch.local_refs || typeof value.create_batch.local_refs !== "object" || Array.isArray(value.create_batch.local_refs) || Object.entries(value.create_batch.local_refs).some(([ref, id]) => !/^[a-z][a-z0-9_-]{0,63}$/.test(ref) || typeof id !== "string" || !/^[a-z]{10}$/.test(id))))
|
|
123
|
+
invalidJournal("TODO reconciliation journal has an invalid create-batch receipt");
|
|
124
|
+
if (value.create !== undefined && (!value.create
|
|
125
|
+
|| typeof value.create !== "object"
|
|
126
|
+
|| Array.isArray(value.create)
|
|
127
|
+
|| Object.keys(value.create).sort().join(",") !== "created_id,request_sha256"
|
|
128
|
+
|| typeof value.create.created_id !== "string"
|
|
129
|
+
|| !/^[a-z]{10}$/.test(value.create.created_id)
|
|
130
|
+
|| typeof value.create.request_sha256 !== "string"
|
|
131
|
+
|| !/^[a-f0-9]{64}$/.test(value.create.request_sha256)))
|
|
132
|
+
invalidJournal("TODO reconciliation journal has an invalid create receipt");
|
|
133
|
+
const paths = new Set();
|
|
134
|
+
for (const target of value.targets) {
|
|
135
|
+
if (!target
|
|
136
|
+
|| typeof target !== "object"
|
|
137
|
+
|| Array.isArray(target)
|
|
138
|
+
|| Object.keys(target).sort().join(",") !== "after,before,path"
|
|
139
|
+
|| typeof target.path !== "string"
|
|
140
|
+
|| !validTarget(target.path, value.public_path)
|
|
141
|
+
|| paths.has(target.path)
|
|
142
|
+
|| (target.before !== null && !exactBase64(target.before))
|
|
143
|
+
|| !exactBase64(target.after)
|
|
144
|
+
|| decode(target.after).length > MAX_TARGET_BYTES
|
|
145
|
+
|| (target.before !== null && decode(target.before).length > MAX_TARGET_BYTES))
|
|
146
|
+
invalidJournal("TODO reconciliation journal has an invalid target");
|
|
147
|
+
paths.add(target.path);
|
|
148
|
+
}
|
|
149
|
+
const body = value.targets;
|
|
150
|
+
const activates = body.some((target) => target.path === TODO_RECONCILIATION_ACTIVATION_PATH);
|
|
151
|
+
if (!activates && (value.activation_effect_sha256 !== undefined || value.owner_mapping_sha256 !== undefined))
|
|
152
|
+
invalidJournal("TODO reconciliation journal effect authorization has no activation target");
|
|
153
|
+
if (value.owner_mapping_sha256 !== undefined && value.activation_effect_sha256 === undefined)
|
|
154
|
+
invalidJournal("TODO reconciliation journal owner-mapping authorization has no effect authorization");
|
|
155
|
+
const inferredCreate = createReceiptFromTargets(body);
|
|
156
|
+
if (value.create && (!inferredCreate
|
|
157
|
+
|| value.create.created_id !== inferredCreate.created_id
|
|
158
|
+
|| value.create.request_sha256 !== inferredCreate.request_sha256))
|
|
159
|
+
invalidJournal("TODO reconciliation create receipt does not match its canonical entity target");
|
|
160
|
+
const identity = value.create || value.create_batch || value.activation_effect_sha256 || value.owner_mapping_sha256 || value.update_batch_effect_sha256
|
|
161
|
+
? { ...(value.create ? { create: value.create } : {}), ...(value.create_batch ? { create_batch: value.create_batch } : {}), ...(value.activation_effect_sha256 ? { activation_effect_sha256: value.activation_effect_sha256 } : {}), ...(value.owner_mapping_sha256 ? { owner_mapping_sha256: value.owner_mapping_sha256 } : {}), ...(value.update_batch_effect_sha256 ? { update_batch_effect_sha256: value.update_batch_effect_sha256 } : {}), targets: body }
|
|
162
|
+
: body;
|
|
163
|
+
const expectedId = createHash("sha256").update(canonicalRecordJson(identity)).digest("hex").slice(0, 24);
|
|
164
|
+
if (value.id !== expectedId || (fileName !== undefined && fileName !== `${value.id}.json`)) {
|
|
165
|
+
invalidJournal("TODO reconciliation journal identity does not match its canonical targets");
|
|
166
|
+
}
|
|
167
|
+
const create = value.create ?? (value.create_batch ? undefined : inferredCreate);
|
|
168
|
+
return { ...value, ...(create ? { create } : {}) };
|
|
169
|
+
}
|
|
170
|
+
function targetLimit(target, sourceRoot) {
|
|
171
|
+
return target.path.startsWith(".agentera/entities/") ? entityExactGetMaxBytes(sourceRoot) : MAX_TARGET_BYTES;
|
|
172
|
+
}
|
|
173
|
+
function assertBinding(journal, binding) {
|
|
174
|
+
if (journal.public_path !== binding.publicPath || journal.mapping_sha256 !== binding.mappingSha256)
|
|
175
|
+
reject({
|
|
176
|
+
class: "conflict",
|
|
177
|
+
message: "TODO reconciliation mapping changed while a transaction is pending",
|
|
178
|
+
recovery: `Restore the docs mapping that resolves TODO.md to '${journal.public_path}', then retry the exact non-dry-run mutation once; no state was changed.`,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function fsyncDirectory(directory) {
|
|
182
|
+
if (process.platform === "win32")
|
|
183
|
+
return;
|
|
184
|
+
const fd = fs.openSync(directory, "r");
|
|
185
|
+
try {
|
|
186
|
+
fs.fsyncSync(fd);
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
fs.closeSync(fd);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function removeExactRole(file, expected) {
|
|
193
|
+
if (!fs.readFileSync(file).equals(expected))
|
|
194
|
+
throw new Error(`exact replacement recovery role '${file}' changed`);
|
|
195
|
+
fs.unlinkSync(file);
|
|
196
|
+
}
|
|
197
|
+
function parseFileRecoveryMetadata(file) {
|
|
198
|
+
let parsed;
|
|
199
|
+
try {
|
|
200
|
+
const bytes = fs.readFileSync(file);
|
|
201
|
+
if (bytes.length > 1024)
|
|
202
|
+
throw new Error("over bound");
|
|
203
|
+
parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
invalidJournal(`file replacement recovery metadata '${file}' is invalid`);
|
|
207
|
+
}
|
|
208
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
209
|
+
invalidJournal(`file replacement recovery metadata '${file}' is not a mapping`);
|
|
210
|
+
}
|
|
211
|
+
const value = parsed;
|
|
212
|
+
if (Object.keys(value).sort().join(",") !== "after_sha256,before_sha256,schema_version,target_path"
|
|
213
|
+
|| value.schema_version !== FILE_REPLACEMENT_RECOVERY_VERSION
|
|
214
|
+
|| typeof value.target_path !== "string"
|
|
215
|
+
|| typeof value.before_sha256 !== "string"
|
|
216
|
+
|| typeof value.after_sha256 !== "string"
|
|
217
|
+
|| !/^[a-f0-9]{64}$/.test(value.before_sha256)
|
|
218
|
+
|| !/^[a-f0-9]{64}$/.test(value.after_sha256))
|
|
219
|
+
invalidJournal(`file replacement recovery metadata '${file}' has an invalid canonical record`);
|
|
220
|
+
return value;
|
|
221
|
+
}
|
|
222
|
+
function recoveryConflict(target, paths, detail) {
|
|
223
|
+
const boundedPaths = paths.slice(0, 4).map((file) => path.relative(process.cwd(), file).split(path.sep).join("/"));
|
|
224
|
+
reject({
|
|
225
|
+
class: "conflict",
|
|
226
|
+
message: `TODO reconciliation target '${target.path}' conflicts with retained recovery roles: ${detail}`,
|
|
227
|
+
violations: boundedPaths.length ? boundedPaths.map((file) => `preserved recovery role: ${file}`) : undefined,
|
|
228
|
+
recovery: `Preserve the pending journal, canonical competitor, and every listed recovery role. Choose the intended canonical bytes, restore '${target.path}' to the journal's recorded before or after bytes without deleting the competitor copy, then retry the exact non-dry-run mutation once; this rejection changed no bytes.`,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
function recoverImmutablePublicationStage(root, target) {
|
|
232
|
+
if (target.before !== null)
|
|
233
|
+
return;
|
|
234
|
+
const absolute = path.join(root, target.path);
|
|
235
|
+
const directory = path.dirname(absolute);
|
|
236
|
+
if (!fs.existsSync(directory))
|
|
237
|
+
return;
|
|
238
|
+
const name = path.basename(absolute);
|
|
239
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
240
|
+
const pattern = new RegExp(`^\\.${escaped}\\.\\d+\\.[a-f0-9-]+\\.tmp$`);
|
|
241
|
+
const names = fs.readdirSync(directory).filter((candidate) => pattern.test(candidate));
|
|
242
|
+
if (!names.length)
|
|
243
|
+
return;
|
|
244
|
+
if (names.length > 1)
|
|
245
|
+
recoveryConflict(target, names.map((candidate) => path.join(directory, candidate)), "multiple immutable publication stages claim the same target");
|
|
246
|
+
const stage = path.join(directory, names[0]);
|
|
247
|
+
const stat = fs.lstatSync(stage);
|
|
248
|
+
const after = decode(target.after);
|
|
249
|
+
if (!stat.isFile() || stat.isSymbolicLink() || !fs.readFileSync(stage).equals(after)) {
|
|
250
|
+
recoveryConflict(target, [stage], "an immutable publication stage changed");
|
|
251
|
+
}
|
|
252
|
+
const current = bytesAt(root, target.path);
|
|
253
|
+
if (current !== null && !current.equals(after)) {
|
|
254
|
+
recoveryConflict(target, [stage], "the canonical target contains concurrent bytes");
|
|
255
|
+
}
|
|
256
|
+
removeExactRole(stage, after);
|
|
257
|
+
fsyncDirectory(directory);
|
|
258
|
+
}
|
|
259
|
+
function recoverFileReplacementRoles(context, target, entries, recoveryRoot, recoveryRootIdentity, targetDirectory) {
|
|
260
|
+
const before = target.before === null ? null : decode(target.before);
|
|
261
|
+
if (before === null)
|
|
262
|
+
return false;
|
|
263
|
+
const after = decode(target.after);
|
|
264
|
+
const matches = [];
|
|
265
|
+
for (const entry of entries) {
|
|
266
|
+
if (entry.name === ".gitignore")
|
|
267
|
+
continue;
|
|
268
|
+
const directory = path.join(recoveryRoot, entry.name);
|
|
269
|
+
const attemptIdentity = validateEntityRecoveryDirectory(context.validatedRoot, directory, targetDirectory, `private entity recovery attempt '${path.relative(context.pinnedPath(), directory).split(path.sep).join("/")}'`);
|
|
270
|
+
const metadata = path.join(directory, FILE_REPLACEMENT_METADATA_NAME);
|
|
271
|
+
if (!fs.existsSync(metadata))
|
|
272
|
+
continue;
|
|
273
|
+
const value = parseFileRecoveryMetadata(metadata);
|
|
274
|
+
if (value.target_path !== target.path)
|
|
275
|
+
continue;
|
|
276
|
+
if (value.before_sha256 !== createHash("sha256").update(before).digest("hex")
|
|
277
|
+
|| value.after_sha256 !== createHash("sha256").update(after).digest("hex"))
|
|
278
|
+
recoveryConflict(target, [metadata], "the role digest does not match the pending journal");
|
|
279
|
+
const roleNames = fs.readdirSync(directory).sort();
|
|
280
|
+
if (roleNames.some((name) => !["original.previous", "replacement.tmp", FILE_REPLACEMENT_METADATA_NAME].includes(name))) {
|
|
281
|
+
recoveryConflict(target, roleNames.map((name) => path.join(directory, name)), "the recovery attempt contains an unknown role");
|
|
282
|
+
}
|
|
283
|
+
const previous = path.join(directory, "original.previous");
|
|
284
|
+
const stage = path.join(directory, "replacement.tmp");
|
|
285
|
+
if (fs.existsSync(previous)) {
|
|
286
|
+
const stat = fs.lstatSync(previous);
|
|
287
|
+
if (!stat.isFile() || stat.isSymbolicLink() || !fs.readFileSync(previous).equals(before)) {
|
|
288
|
+
recoveryConflict(target, [metadata, previous], "the retained baseline role changed");
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (fs.existsSync(stage)) {
|
|
292
|
+
const stat = fs.lstatSync(stage);
|
|
293
|
+
if (!stat.isFile() || stat.isSymbolicLink() || !fs.readFileSync(stage).equals(after)) {
|
|
294
|
+
recoveryConflict(target, [metadata, stage], "the replacement stage changed");
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
matches.push({
|
|
298
|
+
directory,
|
|
299
|
+
identity: attemptIdentity,
|
|
300
|
+
metadata,
|
|
301
|
+
...(fs.existsSync(previous) ? { previous } : {}),
|
|
302
|
+
...(fs.existsSync(stage) ? { stage } : {}),
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
if (matches.length > 1)
|
|
306
|
+
recoveryConflict(target, matches.map(({ metadata }) => metadata), "multiple recovery attempts claim the same target");
|
|
307
|
+
const match = matches[0];
|
|
308
|
+
if (!match)
|
|
309
|
+
return false;
|
|
310
|
+
const current = bytesAt(context.pinnedPath(), target.path);
|
|
311
|
+
if (!same(current, before) && !same(current, after)) {
|
|
312
|
+
recoveryConflict(target, [match.metadata, ...(match.previous ? [match.previous] : []), ...(match.stage ? [match.stage] : [])], current === null ? "the canonical target is absent" : "the canonical target contains concurrent bytes");
|
|
313
|
+
}
|
|
314
|
+
validateEntityRecoveryDirectory(context.validatedRoot, recoveryRoot, targetDirectory, "private entity recovery root '.agentera/.entity-recovery'", recoveryRootIdentity);
|
|
315
|
+
validateEntityRecoveryDirectory(context.validatedRoot, match.directory, targetDirectory, `private entity recovery attempt '${path.relative(context.pinnedPath(), match.directory).split(path.sep).join("/")}'`, match.identity);
|
|
316
|
+
if (match.stage)
|
|
317
|
+
removeExactRole(match.stage, after);
|
|
318
|
+
if (match.previous)
|
|
319
|
+
removeExactRole(match.previous, before);
|
|
320
|
+
removeExactRole(match.metadata, fs.readFileSync(match.metadata));
|
|
321
|
+
fs.rmdirSync(match.directory);
|
|
322
|
+
fsyncDirectory(recoveryRoot);
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
function recoverFileReplacement(context, target) {
|
|
326
|
+
if (target.before === null)
|
|
327
|
+
return;
|
|
328
|
+
const recoveryRoot = path.join(context.pinnedPath(), ".agentera/.entity-recovery");
|
|
329
|
+
if (!fs.existsSync(recoveryRoot))
|
|
330
|
+
return;
|
|
331
|
+
const targetDirectory = path.dirname(context.pinnedPath(target.path));
|
|
332
|
+
const recoveryRootIdentity = validateEntityRecoveryDirectory(context.validatedRoot, recoveryRoot, targetDirectory, "private entity recovery root '.agentera/.entity-recovery'");
|
|
333
|
+
const entries = fs.readdirSync(recoveryRoot, { withFileTypes: true });
|
|
334
|
+
if (entries.length > 128)
|
|
335
|
+
invalidJournal("file replacement recovery root exceeds its bounded entry count");
|
|
336
|
+
recoverFileReplacementRoles(context, target, entries, recoveryRoot, recoveryRootIdentity, targetDirectory);
|
|
337
|
+
}
|
|
338
|
+
function applyTarget(context, root, target, sourceRoot, publicPath) {
|
|
339
|
+
const before = target.before === null ? null : decode(target.before);
|
|
340
|
+
const after = decode(target.after);
|
|
341
|
+
recoverImmutablePublicationStage(root, target);
|
|
342
|
+
recoverFileReplacement(context, target);
|
|
343
|
+
const current = bytesAt(root, target.path);
|
|
344
|
+
if (same(current, after))
|
|
345
|
+
return null;
|
|
346
|
+
if (!same(current, before))
|
|
347
|
+
reject({
|
|
348
|
+
class: "conflict",
|
|
349
|
+
message: `TODO reconciliation target '${target.path}' changed after transaction preparation`,
|
|
350
|
+
recovery: "Preserve the pending journal and both repository changes, restore every target to either the recorded before or after bytes, then retry once; no additional state was changed.",
|
|
351
|
+
});
|
|
352
|
+
if (before === null) {
|
|
353
|
+
const identity = context.publishImmutable(target.path, after.toString("utf8"));
|
|
354
|
+
if (!identity)
|
|
355
|
+
reject({
|
|
356
|
+
class: "conflict",
|
|
357
|
+
message: `TODO reconciliation target '${target.path}' appeared during publication`,
|
|
358
|
+
recovery: `Preserve the competing target and retry the exact TODO mutation after reconciling it with the pending transaction; no competing bytes were overwritten.`,
|
|
359
|
+
});
|
|
360
|
+
return identity;
|
|
361
|
+
}
|
|
362
|
+
const replacement = target.path === publicPath
|
|
363
|
+
? context.replaceVisible(target.path, before, after.toString("utf8"), targetLimit(target, sourceRoot))
|
|
364
|
+
: context.replaceExisting(target.path, before, after.toString("utf8"), targetLimit(target, sourceRoot));
|
|
365
|
+
return replacement.publishedIdentity;
|
|
366
|
+
}
|
|
367
|
+
function rollback(context, applied, sourceRoot, publicPath) {
|
|
368
|
+
const issues = [];
|
|
369
|
+
for (const { target, identity } of [...applied].reverse()) {
|
|
370
|
+
try {
|
|
371
|
+
if (target.before === null) {
|
|
372
|
+
const result = context.removeExact(target.path, identity, false);
|
|
373
|
+
if (result !== "removed")
|
|
374
|
+
throw new Error(`exact removal returned ${result}`);
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
if (target.path === publicPath) {
|
|
378
|
+
context.restoreVisible(target.path, identity, decode(target.before).toString("utf8"), targetLimit(target, sourceRoot));
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
context.restoreExact(target.path, identity, decode(target.before).toString("utf8"), targetLimit(target, sourceRoot));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
issues.push({
|
|
387
|
+
path: target.path,
|
|
388
|
+
message: (error instanceof Error ? error.message : String(error)).slice(0, 512),
|
|
389
|
+
retainedPaths: error instanceof ExactReplacementConflictError
|
|
390
|
+
? error.retainedPaths.slice(0, 8).map((retainedPath) => retainedPath.slice(0, 512))
|
|
391
|
+
: [],
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return issues;
|
|
396
|
+
}
|
|
397
|
+
function rejectIncompleteRollback(primary, issues) {
|
|
398
|
+
const primaryMessage = (primary instanceof Error ? primary.message : String(primary)).slice(0, 512);
|
|
399
|
+
const violations = issues.slice(0, 8).map(({ path: targetPath, message }) => `rollback target '${targetPath}': ${message}`);
|
|
400
|
+
const retained = [...new Set(issues.flatMap(({ retainedPaths }) => retainedPaths))].slice(0, 8);
|
|
401
|
+
violations.push(...retained.map((role) => `preserved recovery role: ${role}`));
|
|
402
|
+
reject({
|
|
403
|
+
class: "conflict",
|
|
404
|
+
message: `TODO reconciliation attempted rollback for every published target after '${primaryMessage}', but ${issues.length} target${issues.length === 1 ? "" : "s"} could not be restored`,
|
|
405
|
+
violations,
|
|
406
|
+
recovery: "Preserve the pending journal, each listed canonical target, and every listed recovery role. Targets not listed were restored. Reconcile each listed target to the journal's recorded before or after bytes without deleting concurrent bytes, then retry the exact non-dry-run mutation once.",
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
function rejectPublicationFailure(error, pendingJournal) {
|
|
410
|
+
reject({
|
|
411
|
+
class: "unsupported_target",
|
|
412
|
+
message: `recoverable complete-file replacement is unavailable for this target${error.code ? ` (${error.code})` : ""}`,
|
|
413
|
+
violations: [error.message.slice(0, 512)],
|
|
414
|
+
recovery: `${pendingJournal ? "Preserve the pending journal. " : ""}Use an owner-controlled regular file on the project-state filesystem with standard rename support, correct the reported capability or permission, then retry the exact non-dry-run mutation; all attempted target bytes were restored.`,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
function rejectReplacementConflict(error) {
|
|
418
|
+
reject({
|
|
419
|
+
class: "conflict",
|
|
420
|
+
message: `TODO reconciliation retained a concurrent target without overwriting it: ${error.message.slice(0, 1024)}`,
|
|
421
|
+
violations: error.retainedPaths.slice(0, 4).map((role) => `preserved recovery role: ${role.slice(0, 512)}`),
|
|
422
|
+
recovery: "Preserve the pending journal, canonical competitor, and listed recovery roles. Choose the intended canonical bytes, restore the conflicted target to the journal's recorded before or after bytes without deleting the competitor copy, then retry the exact non-dry-run mutation once; no competitor bytes were overwritten.",
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
function journalPath(id) {
|
|
426
|
+
return `${DIRECTORY}/${id}.json`;
|
|
427
|
+
}
|
|
428
|
+
function finishJournal(context, relative, identity) {
|
|
429
|
+
if (context.removeExact(relative, identity) !== "removed")
|
|
430
|
+
throw new Error(`TODO reconciliation journal '${relative}' changed before cleanup`);
|
|
431
|
+
}
|
|
432
|
+
export function inspectTodoReconciliation(root, binding) {
|
|
433
|
+
const directory = path.join(root, DIRECTORY);
|
|
434
|
+
if (!fs.existsSync(directory))
|
|
435
|
+
return [];
|
|
436
|
+
const names = fs.readdirSync(directory).filter((name) => name.endsWith(".json")).sort();
|
|
437
|
+
if (names.length > 1)
|
|
438
|
+
reject({ class: "conflict", message: "multiple pending TODO reconciliation journals exist", recovery: "Preserve the journals and reconcile them to one transaction before retrying; no state was changed." });
|
|
439
|
+
return names.map((name) => { const journal = parseJournal(fs.readFileSync(path.join(directory, name)), name); assertBinding(journal, binding); return journal.id; });
|
|
440
|
+
}
|
|
441
|
+
export function recoverTodoReconciliation(context, sourceRoot, binding, options = {}) {
|
|
442
|
+
const root = context.pinnedPath();
|
|
443
|
+
const directory = path.join(root, DIRECTORY);
|
|
444
|
+
if (!fs.existsSync(directory))
|
|
445
|
+
return [];
|
|
446
|
+
const names = fs.readdirSync(directory).filter((name) => name.endsWith(".json")).sort();
|
|
447
|
+
if (names.length > 1)
|
|
448
|
+
reject({ class: "conflict", message: "multiple pending TODO reconciliation journals exist", recovery: "Preserve the journals and reconcile them to one transaction before retrying; no state was changed." });
|
|
449
|
+
const recovered = [];
|
|
450
|
+
for (const name of names) {
|
|
451
|
+
const relative = `${DIRECTORY}/${name}`;
|
|
452
|
+
const journalBytes = fs.readFileSync(path.join(root, relative));
|
|
453
|
+
const journal = parseJournal(journalBytes, name);
|
|
454
|
+
assertBinding(journal, binding);
|
|
455
|
+
if (journal.update_batch_effect_sha256) {
|
|
456
|
+
const supplied = options.updateBatch;
|
|
457
|
+
const transition = supplied && /^agentera\.todo(?:SetSeverity|Resolve)Batch\.v1$/.test(String(supplied.input.schema_version));
|
|
458
|
+
const requestEffectSha256 = supplied ? todoUpdateBatchEffectSha256(supplied.input, journal.mapping_sha256, journal.targets.map((target) => ({
|
|
459
|
+
path: target.path,
|
|
460
|
+
before_sha256: target.before === null ? null : createHash("sha256").update(decode(target.before)).digest("hex"),
|
|
461
|
+
after_sha256: createHash("sha256").update(transition && target.path.includes("/todo_item/") ? (() => { const value = loadYamlMapping(decode(target.after).toString("utf8")); const record = value.record; if (record.reconciliation && typeof record.reconciliation === "object" && !Array.isArray(record.reconciliation))
|
|
462
|
+
delete record.reconciliation.transition_batch; return canonicalEntityEnvelopeBytes({ id: String(value.id), artifact: "todo", record }); })() : decode(target.after)).digest("hex"),
|
|
463
|
+
}))) : null;
|
|
464
|
+
if (!supplied || supplied.effectSha256 !== journal.update_batch_effect_sha256 || requestEffectSha256 !== journal.update_batch_effect_sha256)
|
|
465
|
+
reject({
|
|
466
|
+
class: "conflict",
|
|
467
|
+
message: "pending TODO update batch does not match this request and effect authorization",
|
|
468
|
+
recovery: "Retry the exact original TODO update batch input with its preview effect SHA-256 and --yes; no transaction target bytes were changed.",
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
if (journal.create_batch) {
|
|
472
|
+
const supplied = options.createBatch;
|
|
473
|
+
const requestInputSha256 = supplied ? createHash("sha256").update(canonicalRecordJson(supplied.input)).digest("hex") : null;
|
|
474
|
+
const requestEffectSha256 = supplied ? todoCreateBatchEffectSha256(supplied.input, journal.mapping_sha256, journal.create_batch.local_refs, journal.targets.filter((target) => !(target.before === null && /^\.agentera\/entities\/todo\/todo_item\/[a-z]{10}\.yaml$/.test(target.path))).map((target) => ({ path: target.path, before_sha256: target.before === null ? null : createHash("sha256").update(decode(target.before)).digest("hex"), after_sha256: createHash("sha256").update(decode(target.after)).digest("hex") }))) : null;
|
|
475
|
+
if (!supplied || supplied.effectSha256 !== journal.create_batch.effect_sha256 || requestInputSha256 !== journal.create_batch.input_sha256 || requestEffectSha256 !== journal.create_batch.effect_sha256)
|
|
476
|
+
reject({ class: "conflict", message: "pending TODO create batch does not match this request and effect authorization", recovery: "Retry the exact original TODO create batch input with its preview effect SHA-256 and --yes; no transaction target bytes were changed." });
|
|
477
|
+
}
|
|
478
|
+
if (journal.create && options.createRequestSha256 !== journal.create.request_sha256)
|
|
479
|
+
reject({
|
|
480
|
+
class: "conflict",
|
|
481
|
+
message: `pending TODO create for '${journal.create.created_id}' does not match this request`,
|
|
482
|
+
recovery: `Retry the exact original TODO create input to recover '${journal.create.created_id}'; no transaction target bytes were changed.`,
|
|
483
|
+
});
|
|
484
|
+
if (journal.activation_effect_sha256 && options.activationEffectSha256 !== journal.activation_effect_sha256)
|
|
485
|
+
reject({
|
|
486
|
+
class: "conflict",
|
|
487
|
+
message: "pending TODO activation does not match the authorized preview effect",
|
|
488
|
+
recovery: "Retry the exact activation apply command returned by the original preview; no transaction target bytes were changed.",
|
|
489
|
+
});
|
|
490
|
+
if (journal.owner_mapping_sha256 && options.ownerMappingSha256 !== journal.owner_mapping_sha256)
|
|
491
|
+
reject({
|
|
492
|
+
class: "conflict",
|
|
493
|
+
message: "pending TODO owner correction does not match the supplied owner mapping",
|
|
494
|
+
recovery: "Retry the exact correction input and apply command returned by the original preview; no transaction target bytes were changed.",
|
|
495
|
+
});
|
|
496
|
+
options.beforeRecovery?.(journal.targets.map((target) => ({
|
|
497
|
+
path: target.path,
|
|
498
|
+
before: target.before === null ? null : decode(target.before),
|
|
499
|
+
after: decode(target.after),
|
|
500
|
+
})));
|
|
501
|
+
const applied = [];
|
|
502
|
+
try {
|
|
503
|
+
for (const target of journal.targets) {
|
|
504
|
+
if (target.path === ENTITY_MODE_MARKER)
|
|
505
|
+
options.beforeActivation?.();
|
|
506
|
+
const identity = applyTarget(context, root, target, sourceRoot, journal.public_path);
|
|
507
|
+
if (identity)
|
|
508
|
+
applied.push({ target, identity });
|
|
509
|
+
}
|
|
510
|
+
options.beforeCommit?.();
|
|
511
|
+
context.assertValid();
|
|
512
|
+
const journalIdentity = context.replaceExisting(relative, journalBytes, journalBytes.toString("utf8"), MAX_JOURNAL_BYTES).publishedIdentity;
|
|
513
|
+
finishJournal(context, relative, journalIdentity);
|
|
514
|
+
recovered.push({
|
|
515
|
+
transaction_id: journal.id,
|
|
516
|
+
target_count: journal.targets.length,
|
|
517
|
+
...(journal.create ? { create: journal.create } : {}),
|
|
518
|
+
...(journal.update_batch_effect_sha256 ? { update_batch_effect_sha256: journal.update_batch_effect_sha256 } : {}),
|
|
519
|
+
...(journal.create_batch ? { create_batch: journal.create_batch } : {}),
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
catch (error) {
|
|
523
|
+
const rollbackIssues = applied.length ? rollback(context, applied, sourceRoot, journal.public_path) : [];
|
|
524
|
+
if (rollbackIssues.length)
|
|
525
|
+
rejectIncompleteRollback(error, rollbackIssues);
|
|
526
|
+
if (error instanceof ExactReplacementConflictError)
|
|
527
|
+
rejectReplacementConflict(error);
|
|
528
|
+
if (error instanceof FileReplacementError)
|
|
529
|
+
rejectPublicationFailure(error, true);
|
|
530
|
+
throw error;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return recovered;
|
|
534
|
+
}
|
|
535
|
+
export function publishTodoReconciliation(context, sourceRoot, binding, targets, options = {}) {
|
|
536
|
+
const normalized = targets
|
|
537
|
+
.filter((target) => options.retainUnchangedTargets || !same(target.before, Buffer.from(target.after)))
|
|
538
|
+
.sort((left, right) => Number(left.path === ENTITY_MODE_MARKER) - Number(right.path === ENTITY_MODE_MARKER)
|
|
539
|
+
|| Number(left.path === binding.publicPath) - Number(right.path === binding.publicPath)
|
|
540
|
+
|| left.path.localeCompare(right.path));
|
|
541
|
+
const body = normalized.map((target) => ({ path: target.path, before: target.before === null ? null : encode(target.before), after: encode(target.after) }));
|
|
542
|
+
if ((options.activationEffectSha256 || options.ownerMappingSha256) && !normalized.some((target) => target.path === TODO_RECONCILIATION_ACTIVATION_PATH))
|
|
543
|
+
reject({ class: "schema_violation", message: "TODO activation authorization requires its activation target", recovery: "Recompute the complete activation target set from a fresh dry-run; no state was changed." });
|
|
544
|
+
if (options.ownerMappingSha256 && !options.activationEffectSha256)
|
|
545
|
+
reject({ class: "schema_violation", message: "TODO owner-mapping authorization requires its effect authorization", recovery: "Recompute the complete owner correction target set from a fresh dry-run; no state was changed." });
|
|
546
|
+
const identity = options.create || options.createBatch || options.activationEffectSha256 || options.ownerMappingSha256 || options.updateBatchEffectSha256
|
|
547
|
+
? { ...(options.create ? { create: options.create } : {}), ...(options.createBatch ? { create_batch: options.createBatch } : {}), ...(options.activationEffectSha256 ? { activation_effect_sha256: options.activationEffectSha256 } : {}), ...(options.ownerMappingSha256 ? { owner_mapping_sha256: options.ownerMappingSha256 } : {}), ...(options.updateBatchEffectSha256 ? { update_batch_effect_sha256: options.updateBatchEffectSha256 } : {}), targets: body }
|
|
548
|
+
: body;
|
|
549
|
+
const id = createHash("sha256").update(canonicalRecordJson(identity)).digest("hex").slice(0, 24);
|
|
550
|
+
if (!normalized.length)
|
|
551
|
+
return { id, targetCount: 0 };
|
|
552
|
+
if (body.length > MAX_TARGETS
|
|
553
|
+
|| new Set(body.map(({ path: targetPath }) => targetPath)).size !== body.length
|
|
554
|
+
|| body.some((target) => !validTarget(target.path, binding.publicPath)))
|
|
555
|
+
reject({
|
|
556
|
+
class: "schema_violation",
|
|
557
|
+
message: "TODO reconciliation transaction has invalid or duplicate bounded targets",
|
|
558
|
+
recovery: "Reduce the managed TODO working set or cutover entity inventory below the declared journal bounds and retry; no state was changed.",
|
|
559
|
+
});
|
|
560
|
+
const publicTarget = normalized.find((target) => target.path === binding.publicPath && target.before !== null);
|
|
561
|
+
if (publicTarget) {
|
|
562
|
+
const root = context.pinnedPath();
|
|
563
|
+
const publicDevice = fs.statSync(path.dirname(path.join(root, binding.publicPath)), { bigint: true }).dev;
|
|
564
|
+
const recoveryDevice = fs.statSync(path.join(root, ".agentera"), { bigint: true }).dev;
|
|
565
|
+
if (publicDevice !== recoveryDevice)
|
|
566
|
+
reject({
|
|
567
|
+
class: "unsupported_target",
|
|
568
|
+
message: `mapped TODO target '${binding.publicPath}' is on a different filesystem from its private recovery root`,
|
|
569
|
+
recovery: "Map TODO.md to a regular file on the project-state filesystem, then retry the exact mutation; no journal or target bytes were changed.",
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
const journal = {
|
|
573
|
+
schema_version: VERSION,
|
|
574
|
+
id,
|
|
575
|
+
public_path: binding.publicPath,
|
|
576
|
+
mapping_sha256: binding.mappingSha256,
|
|
577
|
+
...(options.create ? { create: options.create } : {}),
|
|
578
|
+
...(options.createBatch ? { create_batch: options.createBatch } : {}),
|
|
579
|
+
...(options.activationEffectSha256 ? { activation_effect_sha256: options.activationEffectSha256 } : {}),
|
|
580
|
+
...(options.ownerMappingSha256 ? { owner_mapping_sha256: options.ownerMappingSha256 } : {}),
|
|
581
|
+
...(options.updateBatchEffectSha256 ? { update_batch_effect_sha256: options.updateBatchEffectSha256 } : {}),
|
|
582
|
+
targets: body,
|
|
583
|
+
};
|
|
584
|
+
const bytes = `${JSON.stringify(journal)}\n`;
|
|
585
|
+
if (Buffer.byteLength(bytes) > MAX_JOURNAL_BYTES)
|
|
586
|
+
reject({ class: "schema_violation", message: "TODO reconciliation transaction exceeds its byte bound", recovery: "Reduce the managed TODO working set below the declared transaction bound and retry; no state was changed." });
|
|
587
|
+
const relativeJournal = journalPath(id);
|
|
588
|
+
const journalIdentity = context.publishImmutable(relativeJournal, bytes);
|
|
589
|
+
if (!journalIdentity)
|
|
590
|
+
reject({
|
|
591
|
+
class: "conflict",
|
|
592
|
+
message: `TODO reconciliation journal '${id}' already exists`,
|
|
593
|
+
recovery: "Retry the exact non-dry-run TODO mutation once so the existing journal is inspected and recovered before another transaction is prepared; no target bytes were changed.",
|
|
594
|
+
});
|
|
595
|
+
if (options.interruptAfterTarget === 0)
|
|
596
|
+
throw new InjectedTodoReconciliationInterruption(0);
|
|
597
|
+
const applied = [];
|
|
598
|
+
try {
|
|
599
|
+
for (const target of journal.targets) {
|
|
600
|
+
if (target.path === ENTITY_MODE_MARKER)
|
|
601
|
+
options.beforeActivation?.();
|
|
602
|
+
const identity = applyTarget(context, context.pinnedPath(), target, sourceRoot, journal.public_path);
|
|
603
|
+
if (identity)
|
|
604
|
+
applied.push({ target, identity });
|
|
605
|
+
if (options.interruptAfterTarget === applied.length)
|
|
606
|
+
throw new InjectedTodoReconciliationInterruption(applied.length);
|
|
607
|
+
}
|
|
608
|
+
options.beforeCommit?.();
|
|
609
|
+
context.assertValid();
|
|
610
|
+
finishJournal(context, relativeJournal, journalIdentity);
|
|
611
|
+
return { id, targetCount: normalized.length };
|
|
612
|
+
}
|
|
613
|
+
catch (error) {
|
|
614
|
+
if (error instanceof InjectedTodoReconciliationInterruption)
|
|
615
|
+
throw error;
|
|
616
|
+
const rollbackIssues = rollback(context, applied, sourceRoot, journal.public_path);
|
|
617
|
+
if (rollbackIssues.length)
|
|
618
|
+
rejectIncompleteRollback(error, rollbackIssues);
|
|
619
|
+
if (error instanceof ExactReplacementConflictError)
|
|
620
|
+
rejectReplacementConflict(error);
|
|
621
|
+
if (error instanceof FileReplacementError) {
|
|
622
|
+
finishJournal(context, relativeJournal, journalIdentity);
|
|
623
|
+
rejectPublicationFailure(error, false);
|
|
624
|
+
}
|
|
625
|
+
finishJournal(context, relativeJournal, journalIdentity);
|
|
626
|
+
throw error;
|
|
627
|
+
}
|
|
628
|
+
}
|