openclaw-hybrid-memory 2026.5.310 → 2026.6.10
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/api/plugin-runtime.ts +2 -0
- package/backends/facts-db/contradictions.ts +1 -1
- package/cli/cmd-extract-directives.ts +225 -11
- package/cli/cmd-extract-proposals.ts +5 -6
- package/cli/cmd-extract-reinforcement.ts +71 -0
- package/cli/cmd-feedback.ts +15 -9
- package/cli/commands/manage/register-reflection-pipeline.ts +247 -13
- package/cli/commands/manage/register-storage-maintenance.ts +224 -15
- package/cli/commands/manage/storage-stats-helpers.ts +13 -2
- package/cli/context.ts +9 -19
- package/cli/distill.ts +31 -1
- package/cli/register.ts +28 -38
- package/dist/api/plugin-runtime.js.map +1 -1
- package/dist/backends/agent-health-store.js.map +1 -1
- package/dist/backends/apitap-store.js.map +1 -1
- package/dist/backends/audit-store.js.map +1 -1
- package/dist/backends/base-sqlite-store.js.map +1 -1
- package/dist/backends/cost-tracker.js.map +1 -1
- package/dist/backends/credentials-db.js +2 -3
- package/dist/backends/credentials-db.js.map +1 -1
- package/dist/backends/crystallization-store.js.map +1 -1
- package/dist/backends/edict-store.js.map +1 -1
- package/dist/backends/event-bus.js.map +1 -1
- package/dist/backends/event-log.js.map +1 -1
- package/dist/backends/facts-db/cache-manager.js.map +1 -1
- package/dist/backends/facts-db/clusters.js.map +1 -1
- package/dist/backends/facts-db/contradictions.js +1 -1
- package/dist/backends/facts-db/contradictions.js.map +1 -1
- package/dist/backends/facts-db/crud.js.map +1 -1
- package/dist/backends/facts-db/db-connection.js.map +1 -1
- package/dist/backends/facts-db/entity-autolink.js.map +1 -1
- package/dist/backends/facts-db/entity-layer.js.map +1 -1
- package/dist/backends/facts-db/episodes.js.map +1 -1
- package/dist/backends/facts-db/fact-queries.js.map +1 -1
- package/dist/backends/facts-db/fact-read-queries.js.map +1 -1
- package/dist/backends/facts-db/facts-db-layer1.js.map +1 -1
- package/dist/backends/facts-db/facts-db-layer2.js.map +1 -1
- package/dist/backends/facts-db/facts-db-layer3.js.map +1 -1
- package/dist/backends/facts-db/fts-text.js.map +1 -1
- package/dist/backends/facts-db/generated-skills/policy.js.map +1 -1
- package/dist/backends/facts-db/generated-skills.js.map +1 -1
- package/dist/backends/facts-db/housekeeping.js.map +1 -1
- package/dist/backends/facts-db/links.js.map +1 -1
- package/dist/backends/facts-db/maintenance.js.map +1 -1
- package/dist/backends/facts-db/procedures/crud.js.map +1 -1
- package/dist/backends/facts-db/procedures/internal.js.map +1 -1
- package/dist/backends/facts-db/procedures/promotion.js.map +1 -1
- package/dist/backends/facts-db/procedures/search.js.map +1 -1
- package/dist/backends/facts-db/procedures/stats.js.map +1 -1
- package/dist/backends/facts-db/reinforcement.js.map +1 -1
- package/dist/backends/facts-db/row-mapper.js.map +1 -1
- package/dist/backends/facts-db/scan-cursors.js.map +1 -1
- package/dist/backends/facts-db/schema-bootstrap.js.map +1 -1
- package/dist/backends/facts-db/scope-sql.js.map +1 -1
- package/dist/backends/facts-db/search.js.map +1 -1
- package/dist/backends/facts-db/stats.js.map +1 -1
- package/dist/backends/facts-db/types.js.map +1 -1
- package/dist/backends/facts-db/variants.js.map +1 -1
- package/dist/backends/identity-reflection-store.js.map +1 -1
- package/dist/backends/issue-store.js.map +1 -1
- package/dist/backends/learnings-db.js.map +1 -1
- package/dist/backends/migrations/facts-migrations.js.map +1 -1
- package/dist/backends/migrations/procedures.js.map +1 -1
- package/dist/backends/narratives-db.js.map +1 -1
- package/dist/backends/persona-state-store.js.map +1 -1
- package/dist/backends/proposals-db.js.map +1 -1
- package/dist/backends/scope-filter-sql.js.map +1 -1
- package/dist/backends/sqlite-schema-meta.js.map +1 -1
- package/dist/backends/tool-proposal-store.js.map +1 -1
- package/dist/backends/vector-db/constants.js.map +1 -1
- package/dist/backends/vector-db/path-utils.js.map +1 -1
- package/dist/backends/vector-db/runtime-locks.js.map +1 -1
- package/dist/backends/vector-db/vector-db-class.js.map +1 -1
- package/dist/backends/wal.js.map +1 -1
- package/dist/backends/workflow-store.js.map +1 -1
- package/dist/benchmark/shadow-eval.js.map +1 -1
- package/dist/cli/active-tasks.js.map +1 -1
- package/dist/cli/backup.js.map +1 -1
- package/dist/cli/benchmark.js.map +1 -1
- package/dist/cli/cmd-backfill.js.map +1 -1
- package/dist/cli/cmd-config.js.map +1 -1
- package/dist/cli/cmd-credentials.js.map +1 -1
- package/dist/cli/cmd-demo.js.map +1 -1
- package/dist/cli/cmd-distill.js.map +1 -1
- package/dist/cli/cmd-doctor.js.map +1 -1
- package/dist/cli/cmd-examples.js.map +1 -1
- package/dist/cli/cmd-extract-daily.js.map +1 -1
- package/dist/cli/cmd-extract-directives.js +141 -10
- package/dist/cli/cmd-extract-directives.js.map +1 -1
- package/dist/cli/cmd-extract-procedures.js.map +1 -1
- package/dist/cli/cmd-extract-proposals.js +3 -2
- package/dist/cli/cmd-extract-proposals.js.map +1 -1
- package/dist/cli/cmd-extract-reinforcement.js +39 -0
- package/dist/cli/cmd-extract-reinforcement.js.map +1 -1
- package/dist/cli/cmd-extract-sessions.js.map +1 -1
- package/dist/cli/cmd-feedback.js +9 -4
- package/dist/cli/cmd-feedback.js.map +1 -1
- package/dist/cli/cmd-health.js.map +1 -1
- package/dist/cli/cmd-providers.js.map +1 -1
- package/dist/cli/cmd-selfcorrection.js.map +1 -1
- package/dist/cli/cmd-setup.js.map +1 -1
- package/dist/cli/cmd-status.js.map +1 -1
- package/dist/cli/cmd-store.js.map +1 -1
- package/dist/cli/cmd-user-friendly.js.map +1 -1
- package/dist/cli/cmd-verify.js.map +1 -1
- package/dist/cli/commands/manage/bindings.js.map +1 -1
- package/dist/cli/commands/manage/dream-cycle-followup.js.map +1 -1
- package/dist/cli/commands/manage/maintenance-heartbeat.js.map +1 -1
- package/dist/cli/commands/manage/register-agents-audit-runall.js.map +1 -1
- package/dist/cli/commands/manage/register-analyze-maintenance-logs.js.map +1 -1
- package/dist/cli/commands/manage/register-budget-proposals.js.map +1 -1
- package/dist/cli/commands/manage/register-config-cli.js.map +1 -1
- package/dist/cli/commands/manage/register-corrections-and-pipeline.js.map +1 -1
- package/dist/cli/commands/manage/register-corrections.js.map +1 -1
- package/dist/cli/commands/manage/register-council.js.map +1 -1
- package/dist/cli/commands/manage/register-credentials-scope.js.map +1 -1
- package/dist/cli/commands/manage/register-digest.js.map +1 -1
- package/dist/cli/commands/manage/register-lifecycle.js.map +1 -1
- package/dist/cli/commands/manage/register-procedure-lifecycle.js.map +1 -1
- package/dist/cli/commands/manage/register-reconcile-cron-ledgers.js.map +1 -1
- package/dist/cli/commands/manage/register-reflection-pipeline.js +144 -7
- package/dist/cli/commands/manage/register-reflection-pipeline.js.map +1 -1
- package/dist/cli/commands/manage/register-self-correction-feedback.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-and-stats.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-entities-decay.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-graph-audit.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-maintenance.js +152 -9
- package/dist/cli/commands/manage/register-storage-maintenance.js.map +1 -1
- package/dist/cli/commands/manage/register-validate-cron-exit.js.map +1 -1
- package/dist/cli/commands/manage/storage-stats-helpers.js +10 -3
- package/dist/cli/commands/manage/storage-stats-helpers.js.map +1 -1
- package/dist/cli/commands/register-manage-commands.js.map +1 -1
- package/dist/cli/config-feature-summaries.js.map +1 -1
- package/dist/cli/config-output-sink.js.map +1 -1
- package/dist/cli/distill-session-jsonl.js.map +1 -1
- package/dist/cli/distill.js +10 -1
- package/dist/cli/distill.js.map +1 -1
- package/dist/cli/global-verbose.js.map +1 -1
- package/dist/cli/goals.js.map +1 -1
- package/dist/cli/hybrid-mem-commander-utils.js.map +1 -1
- package/dist/cli/install/config-merge.js.map +1 -1
- package/dist/cli/install/cron-jobs.js.map +1 -1
- package/dist/cli/install/embedding-detect.js.map +1 -1
- package/dist/cli/install/run-install.js.map +1 -1
- package/dist/cli/install/workspace.js.map +1 -1
- package/dist/cli/proposals.js.map +1 -1
- package/dist/cli/register.js.map +1 -1
- package/dist/cli/shared.js.map +1 -1
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/task-queue-status.js.map +1 -1
- package/dist/cli/verified.js.map +1 -1
- package/dist/cli/verify/fact-count.js.map +1 -1
- package/dist/cli/verify/openclaw-config.js.map +1 -1
- package/dist/cli/verify/plugin-config-credentials.js.map +1 -1
- package/dist/cli/verify/sections/config-cron.js.map +1 -1
- package/dist/cli/verify/sections/embeddings.js.map +1 -1
- package/dist/cli/verify/sections/infrastructure.js.map +1 -1
- package/dist/cli/verify/sections/llm-models.js.map +1 -1
- package/dist/cli/verify/sections/reconcile.js.map +1 -1
- package/dist/cli/verify/verify-run-state.js.map +1 -1
- package/dist/cli/verify-llm-azure-auth.js.map +1 -1
- package/dist/cli/verify.js.map +1 -1
- package/dist/config/hybrid-schema.js.map +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/maintenance-fallback-policy.js.map +1 -1
- package/dist/config/parsers/capture.js.map +1 -1
- package/dist/config/parsers/core.js.map +1 -1
- package/dist/config/parsers/features.js.map +1 -1
- package/dist/config/parsers/index.js.map +1 -1
- package/dist/config/parsers/maintenance.js.map +1 -1
- package/dist/config/parsers/retrieval.js.map +1 -1
- package/dist/config/parsers/sensors.js.map +1 -1
- package/dist/config/skill-sections.js.map +1 -1
- package/dist/config/skill-size-limits.js.map +1 -1
- package/dist/config/types/agents.js.map +1 -1
- package/dist/config/types/bootstrap.js.map +1 -1
- package/dist/config/types/core.js.map +1 -1
- package/dist/config/types/index.js.map +1 -1
- package/dist/config/utils.js.map +1 -1
- package/dist/index-help.js.map +1 -1
- package/dist/index-testing-exports.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/hook-resolution-api.js.map +1 -1
- package/dist/lifecycle/hooks.js +0 -1
- package/dist/lifecycle/hooks.js.map +1 -1
- package/dist/lifecycle/resolve-agent-id.js.map +1 -1
- package/dist/lifecycle/session-state.js.map +1 -1
- package/dist/lifecycle/stage-active-task.js.map +1 -1
- package/dist/lifecycle/stage-auth-failure.js.map +1 -1
- package/dist/lifecycle/stage-capture/run-capture.js.map +1 -1
- package/dist/lifecycle/stage-capture.js.map +1 -1
- package/dist/lifecycle/stage-cleanup.js.map +1 -1
- package/dist/lifecycle/stage-credential-hint.js.map +1 -1
- package/dist/lifecycle/stage-frustration.js.map +1 -1
- package/dist/lifecycle/stage-goal-stewardship.js.map +1 -1
- package/dist/lifecycle/stage-goal-subagent.js.map +1 -1
- package/dist/lifecycle/stage-injection.js +1 -1
- package/dist/lifecycle/stage-injection.js.map +1 -1
- package/dist/lifecycle/stage-recall/run-recall.js.map +1 -1
- package/dist/lifecycle/stage-recall.js.map +1 -1
- package/dist/lifecycle/stage-setup.js.map +1 -1
- package/dist/routes/dashboard/collectors.js.map +1 -1
- package/dist/routes/dashboard/html.js.map +1 -1
- package/dist/routes/dashboard/server.js.map +1 -1
- package/dist/routes/dashboard-graph.js.map +1 -1
- package/dist/routes/graphql-resolvers.js.map +1 -1
- package/dist/routes/graphql-server.js.map +1 -1
- package/dist/services/active-task-checkpoint.js.map +1 -1
- package/dist/services/active-task-injection.js.map +1 -1
- package/dist/services/active-task.js.map +1 -1
- package/dist/services/adaptive-catch-up-pacing.js +25 -0
- package/dist/services/adaptive-catch-up-pacing.js.map +1 -0
- package/dist/services/adaptive-maintenance-llm.js.map +1 -1
- package/dist/services/adaptive-model-limits.js.map +1 -1
- package/dist/services/ambient-retrieval.js.map +1 -1
- package/dist/services/apitap-service.js.map +1 -1
- package/dist/services/audit-health-exit-info.js.map +1 -1
- package/dist/services/audit-health-json.js.map +1 -1
- package/dist/services/auth-failure-detect.js.map +1 -1
- package/dist/services/auto-capture.js.map +1 -1
- package/dist/services/auto-classifier.js.map +1 -1
- package/dist/services/auto-skills-audit.js.map +1 -1
- package/dist/services/bootstrap-optional.js.map +1 -1
- package/dist/services/bootstrap-priority.js.map +1 -1
- package/dist/services/bootstrap.js.map +1 -1
- package/dist/services/capture-provenance.js.map +1 -1
- package/dist/services/capture-utils.js.map +1 -1
- package/dist/services/chat.js +22 -3
- package/dist/services/chat.js.map +1 -1
- package/dist/services/classification-scope.js.map +1 -1
- package/dist/services/classification.js.map +1 -1
- package/dist/services/cli-sql-dump.js.map +1 -1
- package/dist/services/consolidation.js.map +1 -1
- package/dist/services/context-audit.js +1 -1
- package/dist/services/context-audit.js.map +1 -1
- package/dist/services/context-budget.js.map +1 -1
- package/dist/services/context-engine.js.map +1 -1
- package/dist/services/contextual-variants.js.map +1 -1
- package/dist/services/continuous-verifier.js.map +1 -1
- package/dist/services/contradiction-adjudicator.js.map +1 -1
- package/dist/services/cost-context.js.map +1 -1
- package/dist/services/cost-feature-labels.js.map +1 -1
- package/dist/services/credential-migration.js.map +1 -1
- package/dist/services/credential-scanner.js.map +1 -1
- package/dist/services/credential-validation.js.map +1 -1
- package/dist/services/cron-exit-validator.js.map +1 -1
- package/dist/services/cron-guard.js.map +1 -1
- package/dist/services/cron-job-bash-harness.js +52 -5
- package/dist/services/cron-job-bash-harness.js.map +1 -1
- package/dist/services/cron-maintenance-reconciler.js +1 -3
- package/dist/services/cron-maintenance-reconciler.js.map +1 -1
- package/dist/services/cross-agent-learning.js.map +1 -1
- package/dist/services/crystallization-proposer.js.map +1 -1
- package/dist/services/dedupe-policy.js.map +1 -1
- package/dist/services/deprecated-cron-commands.js.map +1 -1
- package/dist/services/directive-extract.js.map +1 -1
- package/dist/services/document-chunker.js.map +1 -1
- package/dist/services/document-grader.js.map +1 -1
- package/dist/services/dream-cycle.js.map +1 -1
- package/dist/services/embedding-migration.js.map +1 -1
- package/dist/services/embedding-registry.js.map +1 -1
- package/dist/services/embeddings/chain-provider.js.map +1 -1
- package/dist/services/embeddings/factory.js.map +1 -1
- package/dist/services/embeddings/fallback-provider.js.map +1 -1
- package/dist/services/embeddings/ollama-provider.js.map +1 -1
- package/dist/services/embeddings/onnx-provider.js.map +1 -1
- package/dist/services/embeddings/openai-provider.js.map +1 -1
- package/dist/services/embeddings/shared.js +3 -3
- package/dist/services/embeddings/shared.js.map +1 -1
- package/dist/services/embeddings/types.js.map +1 -1
- package/dist/services/entity-enrichment-adaptive.js +128 -0
- package/dist/services/entity-enrichment-adaptive.js.map +1 -0
- package/dist/services/entity-enrichment-cli.js +389 -42
- package/dist/services/entity-enrichment-cli.js.map +1 -1
- package/dist/services/entity-enrichment.js +31 -5
- package/dist/services/entity-enrichment.js.map +1 -1
- package/dist/services/error-reporter/noisy-errors.js.map +1 -1
- package/dist/services/error-reporter/sanitize.js.map +1 -1
- package/dist/services/error-reporter.js.map +1 -1
- package/dist/services/event-hub-repair.js.map +1 -1
- package/dist/services/export-memory.js.map +1 -1
- package/dist/services/fact-extraction.js.map +1 -1
- package/dist/services/feedback-effectiveness.js.map +1 -1
- package/dist/services/find-duplicates.js.map +1 -1
- package/dist/services/frustration-detector.js.map +1 -1
- package/dist/services/fts-search.js.map +1 -1
- package/dist/services/gap-detector.js.map +1 -1
- package/dist/services/generated-skill-lifecycle.js.map +1 -1
- package/dist/services/generated-skill-validation.js.map +1 -1
- package/dist/services/goal-active-task-mirror.js.map +1 -1
- package/dist/services/goal-circuit-breaker.js.map +1 -1
- package/dist/services/goal-health.js.map +1 -1
- package/dist/services/goal-registry.js.map +1 -1
- package/dist/services/goal-stewardship-heartbeat.js.map +1 -1
- package/dist/services/goal-stewardship-llm-triage.js.map +1 -1
- package/dist/services/goal-stewardship-verify-cron.js.map +1 -1
- package/dist/services/goal-stewardship.js.map +1 -1
- package/dist/services/goal-subagent.js.map +1 -1
- package/dist/services/graph-retrieval.js.map +1 -1
- package/dist/services/humanizer-score.js.map +1 -1
- package/dist/services/hybrid-mem-cron-default-job-steps.js.map +1 -1
- package/dist/services/hyde-helper.js.map +1 -1
- package/dist/services/identity-reflection.js.map +1 -1
- package/dist/services/implicit-feedback-extract.js.map +1 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/ingest-utils.js.map +1 -1
- package/dist/services/intent-template.js.map +1 -1
- package/dist/services/json-array-parser.js.map +1 -1
- package/dist/services/knowledge-gaps.js.map +1 -1
- package/dist/services/language-keywords-build.js.map +1 -1
- package/dist/services/lifecycle/github-adapter.js.map +1 -1
- package/dist/services/llm-rate-limit-headers.js +1 -2
- package/dist/services/llm-rate-limit-headers.js.map +1 -1
- package/dist/services/maintenance-auto-fix.js.map +1 -1
- package/dist/services/maintenance-log-analyzer.js +7 -1
- package/dist/services/maintenance-log-analyzer.js.map +1 -1
- package/dist/services/maintenance-timestamp.js.map +1 -1
- package/dist/services/memory-diagnostics.js.map +1 -1
- package/dist/services/memory-index.js.map +1 -1
- package/dist/services/merge-results.js.map +1 -1
- package/dist/services/model-capabilities.js.map +1 -1
- package/dist/services/model-pricing.js.map +1 -1
- package/dist/services/narrative-recall.js.map +1 -1
- package/dist/services/openclaw-session-artifact.js.map +1 -1
- package/dist/services/passive-observer.js.map +1 -1
- package/dist/services/pattern-detector-hash.js.map +1 -1
- package/dist/services/pattern-detector.js.map +1 -1
- package/dist/services/pending-autopilot/foundation.js.map +1 -1
- package/dist/services/pending-autopilot/redaction.js.map +1 -1
- package/dist/services/pending-autopilot/store.js.map +1 -1
- package/dist/services/pending-autopilot/types.js.map +1 -1
- package/dist/services/pending-digest-autopilot-cron.js.map +1 -1
- package/dist/services/pending-digest-autopilot.js.map +1 -1
- package/dist/services/pending-review-digest.js.map +1 -1
- package/dist/services/persona-proposal-triage.js.map +1 -1
- package/dist/services/persona-state-promotion.js.map +1 -1
- package/dist/services/post-compaction-recall.js.map +1 -1
- package/dist/services/pre-consolidation-flush.js.map +1 -1
- package/dist/services/pre-finalization-guard.js.map +1 -1
- package/dist/services/procedure-cluster.js.map +1 -1
- package/dist/services/procedure-extractor.js.map +1 -1
- package/dist/services/procedure-promotion/duplicate-skill-cache.js.map +1 -1
- package/dist/services/procedure-promotion-policy.js.map +1 -1
- package/dist/services/procedure-selection-metrics.js.map +1 -1
- package/dist/services/procedure-skill-eval.js.map +1 -1
- package/dist/services/procedure-skill-generator.js.map +1 -1
- package/dist/services/procedure-skill-recipe.js.map +1 -1
- package/dist/services/procedure-skill-shrink.js.map +1 -1
- package/dist/services/procedure-skill-workflow.js.map +1 -1
- package/dist/services/provenance.js.map +1 -1
- package/dist/services/public-export-bundle.js.map +1 -1
- package/dist/services/python-bridge.js.map +1 -1
- package/dist/services/query-expander.js.map +1 -1
- package/dist/services/query-validator.js.map +1 -1
- package/dist/services/recall-pipeline.js.map +1 -1
- package/dist/services/recall-timing.js.map +1 -1
- package/dist/services/recent-http-attempts.js.map +1 -1
- package/dist/services/reflection/shared.js.map +1 -1
- package/dist/services/reflection.js.map +1 -1
- package/dist/services/reinforcement-extract.js.map +1 -1
- package/dist/services/reranker.js.map +1 -1
- package/dist/services/responses-adapter.js.map +1 -1
- package/dist/services/retrieval-aliases.js.map +1 -1
- package/dist/services/retrieval-mode-policy.js.map +1 -1
- package/dist/services/retrieval-orchestrator/packing.js.map +1 -1
- package/dist/services/retrieval-orchestrator.d.ts +2 -3
- package/dist/services/retrieval-orchestrator.js.map +1 -1
- package/dist/services/rrf-fusion.js.map +1 -1
- package/dist/services/self-correction-extract.js.map +1 -1
- package/dist/services/session-observability.js.map +1 -1
- package/dist/services/session-pre-filter.js.map +1 -1
- package/dist/services/shortest-path.js.map +1 -1
- package/dist/services/skill-allowed-tools.js.map +1 -1
- package/dist/services/skill-creator-validator.js.map +1 -1
- package/dist/services/skill-crystallizer-helpers.js.map +1 -1
- package/dist/services/skill-crystallizer.js.map +1 -1
- package/dist/services/skill-description-builder.js.map +1 -1
- package/dist/services/skill-eval-synthesizer.js.map +1 -1
- package/dist/services/skill-examples-builder.js.map +1 -1
- package/dist/services/skill-frontmatter.js.map +1 -1
- package/dist/services/skill-name-validator.js.map +1 -1
- package/dist/services/skill-prompt-injection.js.map +1 -1
- package/dist/services/skill-reference-sidecar.js.map +1 -1
- package/dist/services/skill-script-bundler.js.map +1 -1
- package/dist/services/skill-validator.js.map +1 -1
- package/dist/services/startup-memory-attribution.js.map +1 -1
- package/dist/services/task-hygiene.js.map +1 -1
- package/dist/services/task-ledger/canonical.js.map +1 -1
- package/dist/services/task-ledger-facts.js.map +1 -1
- package/dist/services/task-queue-leases.js.map +1 -1
- package/dist/services/task-queue-watchdog.js.map +1 -1
- package/dist/services/tool-effectiveness.js.map +1 -1
- package/dist/services/tool-proposer.js.map +1 -1
- package/dist/services/tools-md-section.js.map +1 -1
- package/dist/services/topic-clusters.js.map +1 -1
- package/dist/services/trajectory-tracker.js.map +1 -1
- package/dist/services/vector-backend-observability.js.map +1 -1
- package/dist/services/vector-lifecycle-audit.js.map +1 -1
- package/dist/services/vector-maintenance.js.map +1 -1
- package/dist/services/vector-search.js.map +1 -1
- package/dist/services/verification-store.js.map +1 -1
- package/dist/services/verified-fact-triage.js.map +1 -1
- package/dist/services/wal-helpers.js.map +1 -1
- package/dist/services/workflow-tracker.js.map +1 -1
- package/dist/setup/bootstrap-databases.js.map +1 -1
- package/dist/setup/cli-context/cli-services.js.map +1 -1
- package/dist/setup/cli-context/help-text.js.map +1 -1
- package/dist/setup/cli-context/metadata.js.map +1 -1
- package/dist/setup/cli-context/register-cli-with-help.js.map +1 -1
- package/dist/setup/cli-context/register-full.js.map +1 -1
- package/dist/setup/cli-context/register-help.js.map +1 -1
- package/dist/setup/cost-instrumentation.js.map +1 -1
- package/dist/setup/hybrid-memory-generation-state.js.map +1 -1
- package/dist/setup/hybrid-memory-reload-coordinator.js +13 -13
- package/dist/setup/hybrid-memory-reload-coordinator.js.map +1 -1
- package/dist/setup/plugin-service.js.map +1 -1
- package/dist/setup/provider-router.js.map +1 -1
- package/dist/setup/register-context-engine.js.map +1 -1
- package/dist/setup/register-hooks.js.map +1 -1
- package/dist/setup/register-plugin.js +25 -21
- package/dist/setup/register-plugin.js.map +1 -1
- package/dist/setup/register-tools.js.map +1 -1
- package/dist/setup/reregister-policy.js +2 -2
- package/dist/setup/reregister-policy.js.map +1 -1
- package/dist/setup/tool-installers.js.map +1 -1
- package/dist/setup/workspace-bootstrap.js.map +1 -1
- package/dist/src/worker/narratives.js.map +1 -1
- package/dist/tools/apitap-tools.js.map +1 -1
- package/dist/tools/credential-tools.js.map +1 -1
- package/dist/tools/crystallization-tools.js.map +1 -1
- package/dist/tools/dashboard-routes.js.map +1 -1
- package/dist/tools/document-tools.js.map +1 -1
- package/dist/tools/goal-tools.js.map +1 -1
- package/dist/tools/graph-tools.js.map +1 -1
- package/dist/tools/issue-tools.js.map +1 -1
- package/dist/tools/memory/build-runtime.js.map +1 -1
- package/dist/tools/memory/helpers.js.map +1 -1
- package/dist/tools/memory/register-checkpoint-tools.js.map +1 -1
- package/dist/tools/memory/register-directory-tools.js.map +1 -1
- package/dist/tools/memory/register-edict-tools.js.map +1 -1
- package/dist/tools/memory/register-episode-tools.js.map +1 -1
- package/dist/tools/memory/register-recall-tools.js.map +1 -1
- package/dist/tools/memory/register-store-tools.js.map +1 -1
- package/dist/tools/memory-tools.js.map +1 -1
- package/dist/tools/persona-tools.js.map +1 -1
- package/dist/tools/provenance-tools.js.map +1 -1
- package/dist/tools/public-api-routes.js.map +1 -1
- package/dist/tools/safe-register-http-route.js.map +1 -1
- package/dist/tools/self-extension-tools.js.map +1 -1
- package/dist/tools/task-hygiene-tools.js.map +1 -1
- package/dist/tools/utility-tools.js.map +1 -1
- package/dist/tools/verification-tools.js.map +1 -1
- package/dist/tools/workflow-tools.js.map +1 -1
- package/dist/types/issue-types.js.map +1 -1
- package/dist/types/learnings-types.js.map +1 -1
- package/dist/types/memory.js.map +1 -1
- package/dist/utils/apim-gateway-fetch.js.map +1 -1
- package/dist/utils/atomic-write.js.map +1 -1
- package/dist/utils/auth-failover.js.map +1 -1
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/compaction-model-watchdog.js.map +1 -1
- package/dist/utils/consolidation-controls.js.map +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/date-detector.js.map +1 -1
- package/dist/utils/dates.js.map +1 -1
- package/dist/utils/decay.js.map +1 -1
- package/dist/utils/duration.js.map +1 -1
- package/dist/utils/embed-call.js.map +1 -1
- package/dist/utils/entity-lookup-resolve.js.map +1 -1
- package/dist/utils/entity-mention-quality.js.map +1 -1
- package/dist/utils/entity-stopwords.js.map +1 -1
- package/dist/utils/env-manager.js.map +1 -1
- package/dist/utils/error-tracking.js.map +1 -1
- package/dist/utils/event-loop-yield.js.map +1 -1
- package/dist/utils/extract-last-user-message.js.map +1 -1
- package/dist/utils/extraction-from-template.js.map +1 -1
- package/dist/utils/fact-embeddings.js.map +1 -1
- package/dist/utils/file-snapshot.js.map +1 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/gh-repo-arg.js.map +1 -1
- package/dist/utils/hybrid-mem-json-cli.js.map +1 -1
- package/dist/utils/language-keywords.js.map +1 -1
- package/dist/utils/lifecycle-generation.js.map +1 -1
- package/dist/utils/llm-json-array.js.map +1 -1
- package/dist/utils/llm-selection.js.map +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/model-provider-family.js.map +1 -1
- package/dist/utils/model-tier.js.map +1 -1
- package/dist/utils/openclaw-agent-defaults.js.map +1 -1
- package/dist/utils/path.js.map +1 -1
- package/dist/utils/plugin-root.js.map +1 -1
- package/dist/utils/plugin-update-check.js.map +1 -1
- package/dist/utils/procedure-risk.js.map +1 -1
- package/dist/utils/progress-indicators.js.map +1 -1
- package/dist/utils/prompt-loader.js.map +1 -1
- package/dist/utils/provenance.js.map +1 -1
- package/dist/utils/provider-detection.js.map +1 -1
- package/dist/utils/registration-superseded.js.map +1 -1
- package/dist/utils/salience.js.map +1 -1
- package/dist/utils/sanitize-messages.js.map +1 -1
- package/dist/utils/scope-filter.js.map +1 -1
- package/dist/utils/skill-discovery.js.map +1 -1
- package/dist/utils/sqlite-file-perms.js.map +1 -1
- package/dist/utils/sqlite-outcome-compat.js.map +1 -1
- package/dist/utils/sqlite-transaction.js.map +1 -1
- package/dist/utils/stable-stringify.js.map +1 -1
- package/dist/utils/subagent-ended-utils.js.map +1 -1
- package/dist/utils/tags.js.map +1 -1
- package/dist/utils/text.js.map +1 -1
- package/dist/utils/timeout.js.map +1 -1
- package/dist/utils/typebox.js.map +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/wal-replay.js.map +1 -1
- package/dist/versionInfo.js.map +1 -1
- package/index.ts +2 -2
- package/lifecycle/hooks.ts +0 -1
- package/npm-shrinkwrap.json +487 -186
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/services/adaptive-catch-up-pacing.ts +28 -0
- package/services/chat.ts +34 -1
- package/services/cron-job-bash-harness.ts +52 -5
- package/services/embeddings/shared.ts +5 -2
- package/services/entity-enrichment-adaptive.ts +245 -0
- package/services/entity-enrichment-cli.ts +553 -47
- package/services/entity-enrichment.ts +43 -2
- package/services/llm-rate-limit-headers.ts +1 -4
- package/services/maintenance-log-analyzer.ts +13 -9
- package/services/reinforcement-extract.ts +19 -0
- package/setup/hybrid-memory-reload-coordinator.ts +26 -0
- package/setup/register-plugin.ts +62 -32
- package/setup/reregister-policy.ts +10 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","names":[],"sources":["../../../services/pending-autopilot/store.ts"],"sourcesContent":["/** Durable SQLite state for Pending Autopilot control-plane runs (#1334). */\n\nimport { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { DatabaseSync, type SQLInputValue } from \"node:sqlite\";\nimport { BaseSqliteStore } from \"../../backends/base-sqlite-store.js\";\nimport { createTransaction } from \"../../utils/sqlite-transaction.js\";\nimport { sanitizePendingDecision, shouldAdvancePendingCursor, stableRunSummaryJson } from \"./foundation.js\";\nimport type {\n AutopilotMode,\n PendingAutopilotLock,\n PendingAutopilotRunSummary,\n PendingDecision,\n PendingQueue,\n} from \"./types.js\";\nimport { assertKnownEnum } from \"./types.js\";\n\nexport interface CreatePendingRunInput {\n runId: string;\n mode: AutopilotMode;\n policy: string;\n policyVersion: string;\n inputHash: string;\n queues: PendingQueue[];\n startedAt?: number;\n summary?: PendingAutopilotRunSummary;\n}\n\nexport class PendingAutopilotStore extends BaseSqliteStore {\n constructor(dbPath: string) {\n mkdirSync(dirname(dbPath), { recursive: true });\n const db = new DatabaseSync(dbPath);\n super(db);\n migratePendingAutopilotTables(this.liveDb);\n }\n\n protected getSubsystemName(): string {\n return \"pending-autopilot-store\";\n }\n\n createRun(input: CreatePendingRunInput): void {\n assertKnownEnum(\"mode\", input.mode);\n for (const queue of input.queues) assertKnownEnum(\"queue\", queue);\n if (input.mode === \"dry-run\") return;\n const now = input.startedAt ?? nowSeconds();\n this.liveDb\n .prepare(\n `INSERT OR IGNORE INTO pending_autopilot_runs\n (id, mode, policy, policy_version, input_hash, queues_json, started_at, summary_json)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n input.runId,\n input.mode,\n input.policy,\n input.policyVersion,\n input.inputHash,\n JSON.stringify(input.queues),\n now,\n input.summary ? stableRunSummaryJson(input.summary) : null,\n );\n }\n\n finishRun(runId: string, summary: PendingAutopilotRunSummary, finishedAt = nowSeconds()): void {\n if (summary.mode === \"dry-run\") return;\n this.liveDb\n .prepare(\"UPDATE pending_autopilot_runs SET finished_at = ?, summary_json = ? WHERE id = ?\")\n .run(finishedAt, stableRunSummaryJson(summary), runId);\n }\n\n recordDecision(decision: PendingDecision): { inserted: boolean } {\n const safe = sanitizePendingDecision(decision);\n if (safe.mode === \"dry-run\") return { inserted: false };\n return this.insertDecision(safe);\n }\n\n recordLatestDecision(decision: PendingDecision): { inserted: boolean } {\n const safe = sanitizePendingDecision(decision);\n if (safe.mode === \"dry-run\") return { inserted: false };\n const tx = createTransaction(\n this.liveDb,\n () => {\n this.liveDb\n .prepare(\n `DELETE FROM pending_autopilot_decisions\n WHERE queue = ?\n AND item_id = ?\n AND policy = ?\n AND policy_version = ?\n AND (input_hash <> ? OR action <> ?)`,\n )\n .run(safe.queue, safe.itemId, safe.policy, safe.policyVersion, safe.inputHash, safe.action);\n return this.insertDecision(safe);\n },\n \"IMMEDIATE\",\n );\n return tx();\n }\n\n advanceCursorIfSafe(decision: PendingDecision, cursor: string): boolean {\n const safe = sanitizePendingDecision(decision);\n if (safe.mode === \"dry-run\" || !shouldAdvancePendingCursor(safe)) return false;\n this.liveDb\n .prepare(\n `INSERT INTO pending_autopilot_cursors (queue, policy, cursor, input_hash, policy_version, updated_at)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(queue, policy) DO UPDATE SET\n cursor = excluded.cursor,\n input_hash = excluded.input_hash,\n policy_version = excluded.policy_version,\n updated_at = excluded.updated_at`,\n )\n .run(safe.queue, safe.policy, cursor, safe.inputHash, safe.policyVersion, nowSeconds());\n return true;\n }\n\n getCursor(\n queue: PendingQueue,\n policy = \"default\",\n ): {\n queue: PendingQueue;\n policy: string;\n cursor: string;\n inputHash: string;\n policyVersion: string;\n updatedAt: number;\n } | null {\n assertKnownEnum(\"queue\", queue);\n const row = this.liveDb\n .prepare(\"SELECT * FROM pending_autopilot_cursors WHERE queue = ? AND policy = ?\")\n .get(queue, policy) as Record<string, unknown> | undefined;\n if (!row) return null;\n return {\n queue,\n policy: row.policy as string,\n cursor: row.cursor as string,\n inputHash: row.input_hash as string,\n policyVersion: row.policy_version as string,\n updatedAt: row.updated_at as number,\n };\n }\n\n acquireLock(input: {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n owner: string;\n ttlSeconds: number;\n mode: AutopilotMode;\n }): boolean {\n assertKnownEnum(\"queue\", input.queue);\n assertKnownEnum(\"mode\", input.mode);\n if (input.mode === \"dry-run\") return false;\n const now = nowSeconds();\n const tx = createTransaction(\n this.liveDb,\n () => {\n this.liveDb.prepare(\"DELETE FROM pending_autopilot_locks WHERE expires_at <= ?\").run(now);\n const result = this.liveDb\n .prepare(\n `INSERT OR IGNORE INTO pending_autopilot_locks (queue, item_id, input_hash, owner, expires_at, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`,\n )\n .run(input.queue, input.itemId, input.inputHash, input.owner, now + input.ttlSeconds, now);\n return result.changes > 0;\n },\n \"IMMEDIATE\",\n );\n return tx();\n }\n\n releaseLock(input: {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n owner: string;\n mode: AutopilotMode;\n }): boolean {\n assertKnownEnum(\"queue\", input.queue);\n assertKnownEnum(\"mode\", input.mode);\n if (input.mode === \"dry-run\") return false;\n const result = this.liveDb\n .prepare(\"DELETE FROM pending_autopilot_locks WHERE queue = ? AND item_id = ? AND input_hash = ? AND owner = ?\")\n .run(input.queue, input.itemId, input.inputHash, input.owner);\n return result.changes > 0;\n }\n\n mutateWithLockAndAudit(input: {\n decision: PendingDecision;\n owner: string;\n actualInputHash: string;\n mutate: () => void;\n audit: () => void;\n }): boolean {\n const safe = sanitizePendingDecision(input.decision);\n if (safe.mode === \"dry-run\") return false;\n assertKnownEnum(\"queue\", safe.queue);\n const tx = createTransaction(\n this.liveDb,\n () => {\n if (safe.inputHash !== input.actualInputHash) return false;\n const lock = this.getActiveLockInternal(safe.queue, safe.itemId, input.owner, nowSeconds());\n if (!lock || lock.inputHash !== safe.inputHash) return false;\n const inserted = this.insertDecision(safe).inserted;\n if (!inserted) return false;\n input.audit();\n input.mutate();\n return true;\n },\n \"IMMEDIATE\",\n );\n return tx();\n }\n\n /**\n * @deprecated Use mutateWithLockAndAudit so lock ownership and audit atomicity are enforced.\n * This legacy CAS-only helper intentionally no-ops: #1334 requires every mutating path\n * to revalidate an active lock and write audit state transactionally before mutation.\n */\n mutateWithInputHash(input: {\n queue: PendingQueue;\n itemId: string;\n expectedInputHash: string;\n actualInputHash: string;\n mode: AutopilotMode;\n mutate: () => void;\n }): boolean {\n assertKnownEnum(\"queue\", input.queue);\n assertKnownEnum(\"mode\", input.mode);\n void input.itemId;\n void input.expectedInputHash;\n void input.actualInputHash;\n void input.mutate;\n return false;\n }\n\n listDecisions(filter: { queue?: PendingQueue; itemId?: string } = {}): PendingDecision[] {\n const clauses: string[] = [];\n const params: SQLInputValue[] = [];\n if (filter.queue) {\n clauses.push(\"queue = ?\");\n params.push(filter.queue);\n }\n if (filter.itemId) {\n clauses.push(\"item_id = ?\");\n params.push(filter.itemId);\n }\n const where = clauses.length ? `WHERE ${clauses.join(\" AND \")}` : \"\";\n const rows = this.liveDb\n .prepare(`SELECT * FROM pending_autopilot_decisions ${where} ORDER BY created_at, queue, item_id`)\n .all(...params) as Record<string, unknown>[];\n return rows.map(rowToDecision);\n }\n\n listLocks(): PendingAutopilotLock[] {\n const rows = this.liveDb.prepare(\"SELECT * FROM pending_autopilot_locks ORDER BY queue, item_id\").all() as Record<\n string,\n unknown\n >[];\n return rows.map((row) => ({\n queue: row.queue as PendingQueue,\n itemId: row.item_id as string,\n inputHash: row.input_hash as string,\n owner: row.owner as string,\n expiresAt: row.expires_at as number,\n createdAt: row.created_at as number,\n }));\n }\n\n tableCounts(): Record<string, number> {\n const out: Record<string, number> = {};\n for (const table of [\n \"pending_autopilot_runs\",\n \"pending_autopilot_decisions\",\n \"pending_autopilot_cursors\",\n \"pending_autopilot_locks\",\n ] as const) {\n out[table] = (this.liveDb.prepare(`SELECT COUNT(*) AS n FROM ${table}`).get() as { n: number }).n;\n }\n return out;\n }\n\n private insertDecision(safe: PendingDecision): { inserted: boolean } {\n const createdAt = safe.createdAt ?? nowSeconds();\n const result = this.liveDb\n .prepare(\n `INSERT OR IGNORE INTO pending_autopilot_decisions\n (queue, item_id, input_hash, policy, policy_version, mode, action, reason_code, action_class, capability_class, confidence, human_review_required, evidence_json, actor_json, run_id, job_id, summary_json, audit_json, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n safe.queue,\n safe.itemId,\n safe.inputHash,\n safe.policy,\n safe.policyVersion,\n safe.mode,\n safe.action,\n safe.reasonCode,\n safe.actionClass,\n safe.capabilityClass,\n safe.confidence,\n safe.humanReviewRequired ? 1 : 0,\n JSON.stringify(safe.evidence),\n JSON.stringify(safe.actor),\n safe.runId,\n safe.jobId ?? null,\n safe.summary ? JSON.stringify(safe.summary) : null,\n safe.audit ? JSON.stringify(safe.audit) : null,\n createdAt,\n );\n return { inserted: result.changes > 0 };\n }\n\n private getActiveLockInternal(\n queue: PendingQueue,\n itemId: string,\n owner: string,\n now: number,\n ): PendingAutopilotLock | null {\n const row = this.liveDb\n .prepare(\n `SELECT * FROM pending_autopilot_locks\n WHERE queue = ? AND item_id = ? AND owner = ? AND expires_at > ?`,\n )\n .get(queue, itemId, owner, now) as Record<string, unknown> | undefined;\n if (!row) return null;\n return {\n queue: row.queue as PendingQueue,\n itemId: row.item_id as string,\n inputHash: row.input_hash as string,\n owner: row.owner as string,\n expiresAt: row.expires_at as number,\n createdAt: row.created_at as number,\n };\n }\n}\n\nexport function migratePendingAutopilotTables(db: DatabaseSync): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS pending_autopilot_runs (\n id TEXT PRIMARY KEY,\n mode TEXT NOT NULL,\n policy TEXT NOT NULL DEFAULT 'default',\n policy_version TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n queues_json TEXT NOT NULL DEFAULT '[]',\n started_at INTEGER NOT NULL,\n finished_at INTEGER,\n summary_json TEXT\n );\n\n CREATE TABLE IF NOT EXISTS pending_autopilot_decisions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n queue TEXT NOT NULL,\n item_id TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n policy TEXT NOT NULL DEFAULT 'default',\n policy_version TEXT NOT NULL,\n mode TEXT NOT NULL,\n action TEXT NOT NULL,\n reason_code TEXT NOT NULL,\n action_class TEXT NOT NULL,\n capability_class TEXT NOT NULL,\n confidence REAL NOT NULL,\n human_review_required INTEGER NOT NULL,\n evidence_json TEXT NOT NULL DEFAULT '[]',\n actor_json TEXT NOT NULL DEFAULT '{}',\n run_id TEXT NOT NULL,\n job_id TEXT,\n summary_json TEXT,\n audit_json TEXT,\n created_at INTEGER NOT NULL,\n UNIQUE(queue, item_id, input_hash, policy, policy_version, action)\n );\n `);\n\n migrateDecisionPolicyVersionUnique(db);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS pending_autopilot_cursors (\n queue TEXT NOT NULL,\n policy TEXT NOT NULL DEFAULT 'default',\n cursor TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n policy_version TEXT NOT NULL,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY(queue, policy)\n );\n\n CREATE TABLE IF NOT EXISTS pending_autopilot_locks (\n queue TEXT NOT NULL,\n item_id TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n owner TEXT NOT NULL,\n expires_at INTEGER NOT NULL,\n created_at INTEGER NOT NULL,\n PRIMARY KEY(queue, item_id)\n );\n\n CREATE INDEX IF NOT EXISTS idx_pending_autopilot_runs_started ON pending_autopilot_runs(started_at DESC);\n CREATE INDEX IF NOT EXISTS idx_pending_autopilot_decisions_run ON pending_autopilot_decisions(run_id);\n CREATE INDEX IF NOT EXISTS idx_pending_autopilot_decisions_queue ON pending_autopilot_decisions(queue, item_id);\n CREATE INDEX IF NOT EXISTS idx_pending_autopilot_locks_expiry ON pending_autopilot_locks(expires_at);\n `);\n}\n\nfunction migrateDecisionPolicyVersionUnique(db: DatabaseSync): void {\n const row = db\n .prepare(\"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'pending_autopilot_decisions'\")\n .get() as { sql?: string } | undefined;\n if (!row?.sql?.includes(\"UNIQUE(queue, item_id, input_hash, policy, action)\")) return;\n\n db.exec(`\n BEGIN;\n\n ALTER TABLE pending_autopilot_decisions RENAME TO pending_autopilot_decisions_old_policy_unique;\n\n CREATE TABLE pending_autopilot_decisions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n queue TEXT NOT NULL,\n item_id TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n policy TEXT NOT NULL DEFAULT 'default',\n policy_version TEXT NOT NULL,\n mode TEXT NOT NULL,\n action TEXT NOT NULL,\n reason_code TEXT NOT NULL,\n action_class TEXT NOT NULL,\n capability_class TEXT NOT NULL,\n confidence REAL NOT NULL,\n human_review_required INTEGER NOT NULL,\n evidence_json TEXT NOT NULL DEFAULT '[]',\n actor_json TEXT NOT NULL DEFAULT '{}',\n run_id TEXT NOT NULL,\n job_id TEXT,\n summary_json TEXT,\n audit_json TEXT,\n created_at INTEGER NOT NULL,\n UNIQUE(queue, item_id, input_hash, policy, policy_version, action)\n );\n\n INSERT OR IGNORE INTO pending_autopilot_decisions\n (id, queue, item_id, input_hash, policy, policy_version, mode, action, reason_code, action_class, capability_class, confidence, human_review_required, evidence_json, actor_json, run_id, job_id, summary_json, audit_json, created_at)\n SELECT\n id, queue, item_id, input_hash, policy, policy_version, mode, action, reason_code, action_class, capability_class, confidence, human_review_required, evidence_json, actor_json, run_id, job_id, summary_json, audit_json, created_at\n FROM pending_autopilot_decisions_old_policy_unique;\n\n DROP TABLE pending_autopilot_decisions_old_policy_unique;\n\n COMMIT;\n `);\n}\n\nfunction rowToDecision(row: Record<string, unknown>): PendingDecision {\n return {\n queue: row.queue as PendingQueue,\n itemId: row.item_id as string,\n inputHash: row.input_hash as string,\n policy: row.policy as string,\n policyVersion: row.policy_version as string,\n mode: row.mode as AutopilotMode,\n action: row.action as PendingDecision[\"action\"],\n reasonCode: row.reason_code as PendingDecision[\"reasonCode\"],\n actionClass: row.action_class as PendingDecision[\"actionClass\"],\n capabilityClass: row.capability_class as PendingDecision[\"capabilityClass\"],\n confidence: row.confidence as number,\n humanReviewRequired: Boolean(row.human_review_required),\n evidence: JSON.parse(row.evidence_json as string),\n actor: JSON.parse(row.actor_json as string),\n runId: row.run_id as string,\n jobId: (row.job_id as string | null) ?? undefined,\n summary: row.summary_json ? JSON.parse(row.summary_json as string) : undefined,\n audit: row.audit_json ? JSON.parse(row.audit_json as string) : undefined,\n createdAt: row.created_at as number,\n };\n}\n\nfunction nowSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n"],"mappings":";;;;;;;;;AA4BA,IAAa,wBAAb,cAA2C,gBAAgB;CACzD,YAAY,QAAgB;EAC1B,UAAU,QAAQ,OAAO,EAAE,EAAE,WAAW,MAAM,CAAC;EAC/C,MAAM,KAAK,IAAI,aAAa,OAAO;EACnC,MAAM,GAAG;EACT,8BAA8B,KAAK,OAAO;;CAG5C,mBAAqC;EACnC,OAAO;;CAGT,UAAU,OAAoC;EAC5C,gBAAgB,QAAQ,MAAM,KAAK;EACnC,KAAK,MAAM,SAAS,MAAM,QAAQ,gBAAgB,SAAS,MAAM;EACjE,IAAI,MAAM,SAAS,WAAW;EAC9B,MAAM,MAAM,MAAM,aAAa,YAAY;EAC3C,KAAK,OACF,QACC;;0CAGD,CACA,IACC,MAAM,OACN,MAAM,MACN,MAAM,QACN,MAAM,eACN,MAAM,WACN,KAAK,UAAU,MAAM,OAAO,EAC5B,KACA,MAAM,UAAU,qBAAqB,MAAM,QAAQ,GAAG,KACvD;;CAGL,UAAU,OAAe,SAAqC,aAAa,YAAY,EAAQ;EAC7F,IAAI,QAAQ,SAAS,WAAW;EAChC,KAAK,OACF,QAAQ,mFAAmF,CAC3F,IAAI,YAAY,qBAAqB,QAAQ,EAAE,MAAM;;CAG1D,eAAe,UAAkD;EAC/D,MAAM,OAAO,wBAAwB,SAAS;EAC9C,IAAI,KAAK,SAAS,WAAW,OAAO,EAAE,UAAU,OAAO;EACvD,OAAO,KAAK,eAAe,KAAK;;CAGlC,qBAAqB,UAAkD;EACrE,MAAM,OAAO,wBAAwB,SAAS;EAC9C,IAAI,KAAK,SAAS,WAAW,OAAO,EAAE,UAAU,OAAO;EAkBvD,OAjBW,kBACT,KAAK,cACC;GACJ,KAAK,OACF,QACC;;;;;qDAMD,CACA,IAAI,KAAK,OAAO,KAAK,QAAQ,KAAK,QAAQ,KAAK,eAAe,KAAK,WAAW,KAAK,OAAO;GAC7F,OAAO,KAAK,eAAe,KAAK;KAElC,YAEO,EAAE;;CAGb,oBAAoB,UAA2B,QAAyB;EACtE,MAAM,OAAO,wBAAwB,SAAS;EAC9C,IAAI,KAAK,SAAS,aAAa,CAAC,2BAA2B,KAAK,EAAE,OAAO;EACzE,KAAK,OACF,QACC;;;;;;6CAOD,CACA,IAAI,KAAK,OAAO,KAAK,QAAQ,QAAQ,KAAK,WAAW,KAAK,eAAe,YAAY,CAAC;EACzF,OAAO;;CAGT,UACE,OACA,SAAS,WAQF;EACP,gBAAgB,SAAS,MAAM;EAC/B,MAAM,MAAM,KAAK,OACd,QAAQ,yEAAyE,CACjF,IAAI,OAAO,OAAO;EACrB,IAAI,CAAC,KAAK,OAAO;EACjB,OAAO;GACL;GACA,QAAQ,IAAI;GACZ,QAAQ,IAAI;GACZ,WAAW,IAAI;GACf,eAAe,IAAI;GACnB,WAAW,IAAI;GAChB;;CAGH,YAAY,OAOA;EACV,gBAAgB,SAAS,MAAM,MAAM;EACrC,gBAAgB,QAAQ,MAAM,KAAK;EACnC,IAAI,MAAM,SAAS,WAAW,OAAO;EACrC,MAAM,MAAM,YAAY;EAexB,OAdW,kBACT,KAAK,cACC;GACJ,KAAK,OAAO,QAAQ,4DAA4D,CAAC,IAAI,IAAI;GAOzF,OANe,KAAK,OACjB,QACC;wCAED,CACA,IAAI,MAAM,OAAO,MAAM,QAAQ,MAAM,WAAW,MAAM,OAAO,MAAM,MAAM,YAAY,IAC3E,CAAC,UAAU;KAE1B,YAEO,EAAE;;CAGb,YAAY,OAMA;EACV,gBAAgB,SAAS,MAAM,MAAM;EACrC,gBAAgB,QAAQ,MAAM,KAAK;EACnC,IAAI,MAAM,SAAS,WAAW,OAAO;EAIrC,OAHe,KAAK,OACjB,QAAQ,uGAAuG,CAC/G,IAAI,MAAM,OAAO,MAAM,QAAQ,MAAM,WAAW,MAAM,MAC5C,CAAC,UAAU;;CAG1B,uBAAuB,OAMX;EACV,MAAM,OAAO,wBAAwB,MAAM,SAAS;EACpD,IAAI,KAAK,SAAS,WAAW,OAAO;EACpC,gBAAgB,SAAS,KAAK,MAAM;EAepC,OAdW,kBACT,KAAK,cACC;GACJ,IAAI,KAAK,cAAc,MAAM,iBAAiB,OAAO;GACrD,MAAM,OAAO,KAAK,sBAAsB,KAAK,OAAO,KAAK,QAAQ,MAAM,OAAO,YAAY,CAAC;GAC3F,IAAI,CAAC,QAAQ,KAAK,cAAc,KAAK,WAAW,OAAO;GAEvD,IAAI,CADa,KAAK,eAAe,KAAK,CAAC,UAC5B,OAAO;GACtB,MAAM,OAAO;GACb,MAAM,QAAQ;GACd,OAAO;KAET,YAEO,EAAE;;;;;;;CAQb,oBAAoB,OAOR;EACV,gBAAgB,SAAS,MAAM,MAAM;EACrC,gBAAgB,QAAQ,MAAM,KAAK;EACnC,MAAW;EACX,MAAW;EACX,MAAW;EACX,MAAW;EACX,OAAO;;CAGT,cAAc,SAAoD,EAAE,EAAqB;EACvF,MAAM,UAAoB,EAAE;EAC5B,MAAM,SAA0B,EAAE;EAClC,IAAI,OAAO,OAAO;GAChB,QAAQ,KAAK,YAAY;GACzB,OAAO,KAAK,OAAO,MAAM;;EAE3B,IAAI,OAAO,QAAQ;GACjB,QAAQ,KAAK,cAAc;GAC3B,OAAO,KAAK,OAAO,OAAO;;EAE5B,MAAM,QAAQ,QAAQ,SAAS,SAAS,QAAQ,KAAK,QAAQ,KAAK;EAIlE,OAHa,KAAK,OACf,QAAQ,6CAA6C,MAAM,sCAAsC,CACjG,IAAI,GAAG,OACC,CAAC,IAAI,cAAc;;CAGhC,YAAoC;EAKlC,OAJa,KAAK,OAAO,QAAQ,gEAAgE,CAAC,KAIvF,CAAC,KAAK,SAAS;GACxB,OAAO,IAAI;GACX,QAAQ,IAAI;GACZ,WAAW,IAAI;GACf,OAAO,IAAI;GACX,WAAW,IAAI;GACf,WAAW,IAAI;GAChB,EAAE;;CAGL,cAAsC;EACpC,MAAM,MAA8B,EAAE;EACtC,KAAK,MAAM,SAAS;GAClB;GACA;GACA;GACA;GACD,EACC,IAAI,SAAU,KAAK,OAAO,QAAQ,6BAA6B,QAAQ,CAAC,KAAK,CAAmB;EAElG,OAAO;;CAGT,eAAuB,MAA8C;EACnE,MAAM,YAAY,KAAK,aAAa,YAAY;EA4BhD,OAAO,EAAE,UA3BM,KAAK,OACjB,QACC;;2EAGD,CACA,IACC,KAAK,OACL,KAAK,QACL,KAAK,WACL,KAAK,QACL,KAAK,eACL,KAAK,MACL,KAAK,QACL,KAAK,YACL,KAAK,aACL,KAAK,iBACL,KAAK,YACL,KAAK,sBAAsB,IAAI,GAC/B,KAAK,UAAU,KAAK,SAAS,EAC7B,KAAK,UAAU,KAAK,MAAM,EAC1B,KAAK,OACL,KAAK,SAAS,MACd,KAAK,UAAU,KAAK,UAAU,KAAK,QAAQ,GAAG,MAC9C,KAAK,QAAQ,KAAK,UAAU,KAAK,MAAM,GAAG,MAC1C,UAEqB,CAAC,UAAU,GAAG;;CAGzC,sBACE,OACA,QACA,OACA,KAC6B;EAC7B,MAAM,MAAM,KAAK,OACd,QACC;2EAED,CACA,IAAI,OAAO,QAAQ,OAAO,IAAI;EACjC,IAAI,CAAC,KAAK,OAAO;EACjB,OAAO;GACL,OAAO,IAAI;GACX,QAAQ,IAAI;GACZ,WAAW,IAAI;GACf,OAAO,IAAI;GACX,WAAW,IAAI;GACf,WAAW,IAAI;GAChB;;;AAIL,SAAgB,8BAA8B,IAAwB;CACpE,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoCN;CAEF,mCAAmC,GAAG;CAEtC,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;IAyBN;;AAGJ,SAAS,mCAAmC,IAAwB;CAIlE,IAAI,CAHQ,GACT,QAAQ,8FAA8F,CACtG,KACK,EAAE,KAAK,SAAS,qDAAqD,EAAE;CAE/E,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAsCN;;AAGJ,SAAS,cAAc,KAA+C;CACpE,OAAO;EACL,OAAO,IAAI;EACX,QAAQ,IAAI;EACZ,WAAW,IAAI;EACf,QAAQ,IAAI;EACZ,eAAe,IAAI;EACnB,MAAM,IAAI;EACV,QAAQ,IAAI;EACZ,YAAY,IAAI;EAChB,aAAa,IAAI;EACjB,iBAAiB,IAAI;EACrB,YAAY,IAAI;EAChB,qBAAqB,QAAQ,IAAI,sBAAsB;EACvD,UAAU,KAAK,MAAM,IAAI,cAAwB;EACjD,OAAO,KAAK,MAAM,IAAI,WAAqB;EAC3C,OAAO,IAAI;EACX,OAAQ,IAAI,UAA4B,KAAA;EACxC,SAAS,IAAI,eAAe,KAAK,MAAM,IAAI,aAAuB,GAAG,KAAA;EACrE,OAAO,IAAI,aAAa,KAAK,MAAM,IAAI,WAAqB,GAAG,KAAA;EAC/D,WAAW,IAAI;EAChB;;AAGH,SAAS,aAAqB;CAC5B,OAAO,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK"}
|
|
1
|
+
{"version":3,"file":"store.js","names":[],"sources":["../../../services/pending-autopilot/store.ts"],"sourcesContent":["/** Durable SQLite state for Pending Autopilot control-plane runs (#1334). */\n\nimport { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { DatabaseSync, type SQLInputValue } from \"node:sqlite\";\nimport { BaseSqliteStore } from \"../../backends/base-sqlite-store.js\";\nimport { createTransaction } from \"../../utils/sqlite-transaction.js\";\nimport { sanitizePendingDecision, shouldAdvancePendingCursor, stableRunSummaryJson } from \"./foundation.js\";\nimport type {\n AutopilotMode,\n PendingAutopilotLock,\n PendingAutopilotRunSummary,\n PendingDecision,\n PendingQueue,\n} from \"./types.js\";\nimport { assertKnownEnum } from \"./types.js\";\n\nexport interface CreatePendingRunInput {\n runId: string;\n mode: AutopilotMode;\n policy: string;\n policyVersion: string;\n inputHash: string;\n queues: PendingQueue[];\n startedAt?: number;\n summary?: PendingAutopilotRunSummary;\n}\n\nexport class PendingAutopilotStore extends BaseSqliteStore {\n constructor(dbPath: string) {\n mkdirSync(dirname(dbPath), { recursive: true });\n const db = new DatabaseSync(dbPath);\n super(db);\n migratePendingAutopilotTables(this.liveDb);\n }\n\n protected getSubsystemName(): string {\n return \"pending-autopilot-store\";\n }\n\n createRun(input: CreatePendingRunInput): void {\n assertKnownEnum(\"mode\", input.mode);\n for (const queue of input.queues) assertKnownEnum(\"queue\", queue);\n if (input.mode === \"dry-run\") return;\n const now = input.startedAt ?? nowSeconds();\n this.liveDb\n .prepare(\n `INSERT OR IGNORE INTO pending_autopilot_runs\n (id, mode, policy, policy_version, input_hash, queues_json, started_at, summary_json)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n input.runId,\n input.mode,\n input.policy,\n input.policyVersion,\n input.inputHash,\n JSON.stringify(input.queues),\n now,\n input.summary ? stableRunSummaryJson(input.summary) : null,\n );\n }\n\n finishRun(runId: string, summary: PendingAutopilotRunSummary, finishedAt = nowSeconds()): void {\n if (summary.mode === \"dry-run\") return;\n this.liveDb\n .prepare(\"UPDATE pending_autopilot_runs SET finished_at = ?, summary_json = ? WHERE id = ?\")\n .run(finishedAt, stableRunSummaryJson(summary), runId);\n }\n\n recordDecision(decision: PendingDecision): { inserted: boolean } {\n const safe = sanitizePendingDecision(decision);\n if (safe.mode === \"dry-run\") return { inserted: false };\n return this.insertDecision(safe);\n }\n\n recordLatestDecision(decision: PendingDecision): { inserted: boolean } {\n const safe = sanitizePendingDecision(decision);\n if (safe.mode === \"dry-run\") return { inserted: false };\n const tx = createTransaction(\n this.liveDb,\n () => {\n this.liveDb\n .prepare(\n `DELETE FROM pending_autopilot_decisions\n WHERE queue = ?\n AND item_id = ?\n AND policy = ?\n AND policy_version = ?\n AND (input_hash <> ? OR action <> ?)`,\n )\n .run(safe.queue, safe.itemId, safe.policy, safe.policyVersion, safe.inputHash, safe.action);\n return this.insertDecision(safe);\n },\n \"IMMEDIATE\",\n );\n return tx();\n }\n\n advanceCursorIfSafe(decision: PendingDecision, cursor: string): boolean {\n const safe = sanitizePendingDecision(decision);\n if (safe.mode === \"dry-run\" || !shouldAdvancePendingCursor(safe)) return false;\n this.liveDb\n .prepare(\n `INSERT INTO pending_autopilot_cursors (queue, policy, cursor, input_hash, policy_version, updated_at)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(queue, policy) DO UPDATE SET\n cursor = excluded.cursor,\n input_hash = excluded.input_hash,\n policy_version = excluded.policy_version,\n updated_at = excluded.updated_at`,\n )\n .run(safe.queue, safe.policy, cursor, safe.inputHash, safe.policyVersion, nowSeconds());\n return true;\n }\n\n getCursor(\n queue: PendingQueue,\n policy = \"default\",\n ): {\n queue: PendingQueue;\n policy: string;\n cursor: string;\n inputHash: string;\n policyVersion: string;\n updatedAt: number;\n } | null {\n assertKnownEnum(\"queue\", queue);\n const row = this.liveDb\n .prepare(\"SELECT * FROM pending_autopilot_cursors WHERE queue = ? AND policy = ?\")\n .get(queue, policy) as Record<string, unknown> | undefined;\n if (!row) return null;\n return {\n queue,\n policy: row.policy as string,\n cursor: row.cursor as string,\n inputHash: row.input_hash as string,\n policyVersion: row.policy_version as string,\n updatedAt: row.updated_at as number,\n };\n }\n\n acquireLock(input: {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n owner: string;\n ttlSeconds: number;\n mode: AutopilotMode;\n }): boolean {\n assertKnownEnum(\"queue\", input.queue);\n assertKnownEnum(\"mode\", input.mode);\n if (input.mode === \"dry-run\") return false;\n const now = nowSeconds();\n const tx = createTransaction(\n this.liveDb,\n () => {\n this.liveDb.prepare(\"DELETE FROM pending_autopilot_locks WHERE expires_at <= ?\").run(now);\n const result = this.liveDb\n .prepare(\n `INSERT OR IGNORE INTO pending_autopilot_locks (queue, item_id, input_hash, owner, expires_at, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`,\n )\n .run(input.queue, input.itemId, input.inputHash, input.owner, now + input.ttlSeconds, now);\n return result.changes > 0;\n },\n \"IMMEDIATE\",\n );\n return tx();\n }\n\n releaseLock(input: {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n owner: string;\n mode: AutopilotMode;\n }): boolean {\n assertKnownEnum(\"queue\", input.queue);\n assertKnownEnum(\"mode\", input.mode);\n if (input.mode === \"dry-run\") return false;\n const result = this.liveDb\n .prepare(\"DELETE FROM pending_autopilot_locks WHERE queue = ? AND item_id = ? AND input_hash = ? AND owner = ?\")\n .run(input.queue, input.itemId, input.inputHash, input.owner);\n return result.changes > 0;\n }\n\n mutateWithLockAndAudit(input: {\n decision: PendingDecision;\n owner: string;\n actualInputHash: string;\n mutate: () => void;\n audit: () => void;\n }): boolean {\n const safe = sanitizePendingDecision(input.decision);\n if (safe.mode === \"dry-run\") return false;\n assertKnownEnum(\"queue\", safe.queue);\n const tx = createTransaction(\n this.liveDb,\n () => {\n if (safe.inputHash !== input.actualInputHash) return false;\n const lock = this.getActiveLockInternal(safe.queue, safe.itemId, input.owner, nowSeconds());\n if (!lock || lock.inputHash !== safe.inputHash) return false;\n const inserted = this.insertDecision(safe).inserted;\n if (!inserted) return false;\n input.audit();\n input.mutate();\n return true;\n },\n \"IMMEDIATE\",\n );\n return tx();\n }\n\n /**\n * @deprecated Use mutateWithLockAndAudit so lock ownership and audit atomicity are enforced.\n * This legacy CAS-only helper intentionally no-ops: #1334 requires every mutating path\n * to revalidate an active lock and write audit state transactionally before mutation.\n */\n mutateWithInputHash(input: {\n queue: PendingQueue;\n itemId: string;\n expectedInputHash: string;\n actualInputHash: string;\n mode: AutopilotMode;\n mutate: () => void;\n }): boolean {\n assertKnownEnum(\"queue\", input.queue);\n assertKnownEnum(\"mode\", input.mode);\n void input.itemId;\n void input.expectedInputHash;\n void input.actualInputHash;\n void input.mutate;\n return false;\n }\n\n listDecisions(filter: { queue?: PendingQueue; itemId?: string } = {}): PendingDecision[] {\n const clauses: string[] = [];\n const params: SQLInputValue[] = [];\n if (filter.queue) {\n clauses.push(\"queue = ?\");\n params.push(filter.queue);\n }\n if (filter.itemId) {\n clauses.push(\"item_id = ?\");\n params.push(filter.itemId);\n }\n const where = clauses.length ? `WHERE ${clauses.join(\" AND \")}` : \"\";\n const rows = this.liveDb\n .prepare(`SELECT * FROM pending_autopilot_decisions ${where} ORDER BY created_at, queue, item_id`)\n .all(...params) as Record<string, unknown>[];\n return rows.map(rowToDecision);\n }\n\n listLocks(): PendingAutopilotLock[] {\n const rows = this.liveDb.prepare(\"SELECT * FROM pending_autopilot_locks ORDER BY queue, item_id\").all() as Record<\n string,\n unknown\n >[];\n return rows.map((row) => ({\n queue: row.queue as PendingQueue,\n itemId: row.item_id as string,\n inputHash: row.input_hash as string,\n owner: row.owner as string,\n expiresAt: row.expires_at as number,\n createdAt: row.created_at as number,\n }));\n }\n\n tableCounts(): Record<string, number> {\n const out: Record<string, number> = {};\n for (const table of [\n \"pending_autopilot_runs\",\n \"pending_autopilot_decisions\",\n \"pending_autopilot_cursors\",\n \"pending_autopilot_locks\",\n ] as const) {\n out[table] = (this.liveDb.prepare(`SELECT COUNT(*) AS n FROM ${table}`).get() as { n: number }).n;\n }\n return out;\n }\n\n private insertDecision(safe: PendingDecision): { inserted: boolean } {\n const createdAt = safe.createdAt ?? nowSeconds();\n const result = this.liveDb\n .prepare(\n `INSERT OR IGNORE INTO pending_autopilot_decisions\n (queue, item_id, input_hash, policy, policy_version, mode, action, reason_code, action_class, capability_class, confidence, human_review_required, evidence_json, actor_json, run_id, job_id, summary_json, audit_json, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n safe.queue,\n safe.itemId,\n safe.inputHash,\n safe.policy,\n safe.policyVersion,\n safe.mode,\n safe.action,\n safe.reasonCode,\n safe.actionClass,\n safe.capabilityClass,\n safe.confidence,\n safe.humanReviewRequired ? 1 : 0,\n JSON.stringify(safe.evidence),\n JSON.stringify(safe.actor),\n safe.runId,\n safe.jobId ?? null,\n safe.summary ? JSON.stringify(safe.summary) : null,\n safe.audit ? JSON.stringify(safe.audit) : null,\n createdAt,\n );\n return { inserted: result.changes > 0 };\n }\n\n private getActiveLockInternal(\n queue: PendingQueue,\n itemId: string,\n owner: string,\n now: number,\n ): PendingAutopilotLock | null {\n const row = this.liveDb\n .prepare(\n `SELECT * FROM pending_autopilot_locks\n WHERE queue = ? AND item_id = ? AND owner = ? AND expires_at > ?`,\n )\n .get(queue, itemId, owner, now) as Record<string, unknown> | undefined;\n if (!row) return null;\n return {\n queue: row.queue as PendingQueue,\n itemId: row.item_id as string,\n inputHash: row.input_hash as string,\n owner: row.owner as string,\n expiresAt: row.expires_at as number,\n createdAt: row.created_at as number,\n };\n }\n}\n\nexport function migratePendingAutopilotTables(db: DatabaseSync): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS pending_autopilot_runs (\n id TEXT PRIMARY KEY,\n mode TEXT NOT NULL,\n policy TEXT NOT NULL DEFAULT 'default',\n policy_version TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n queues_json TEXT NOT NULL DEFAULT '[]',\n started_at INTEGER NOT NULL,\n finished_at INTEGER,\n summary_json TEXT\n );\n\n CREATE TABLE IF NOT EXISTS pending_autopilot_decisions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n queue TEXT NOT NULL,\n item_id TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n policy TEXT NOT NULL DEFAULT 'default',\n policy_version TEXT NOT NULL,\n mode TEXT NOT NULL,\n action TEXT NOT NULL,\n reason_code TEXT NOT NULL,\n action_class TEXT NOT NULL,\n capability_class TEXT NOT NULL,\n confidence REAL NOT NULL,\n human_review_required INTEGER NOT NULL,\n evidence_json TEXT NOT NULL DEFAULT '[]',\n actor_json TEXT NOT NULL DEFAULT '{}',\n run_id TEXT NOT NULL,\n job_id TEXT,\n summary_json TEXT,\n audit_json TEXT,\n created_at INTEGER NOT NULL,\n UNIQUE(queue, item_id, input_hash, policy, policy_version, action)\n );\n `);\n\n migrateDecisionPolicyVersionUnique(db);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS pending_autopilot_cursors (\n queue TEXT NOT NULL,\n policy TEXT NOT NULL DEFAULT 'default',\n cursor TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n policy_version TEXT NOT NULL,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY(queue, policy)\n );\n\n CREATE TABLE IF NOT EXISTS pending_autopilot_locks (\n queue TEXT NOT NULL,\n item_id TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n owner TEXT NOT NULL,\n expires_at INTEGER NOT NULL,\n created_at INTEGER NOT NULL,\n PRIMARY KEY(queue, item_id)\n );\n\n CREATE INDEX IF NOT EXISTS idx_pending_autopilot_runs_started ON pending_autopilot_runs(started_at DESC);\n CREATE INDEX IF NOT EXISTS idx_pending_autopilot_decisions_run ON pending_autopilot_decisions(run_id);\n CREATE INDEX IF NOT EXISTS idx_pending_autopilot_decisions_queue ON pending_autopilot_decisions(queue, item_id);\n CREATE INDEX IF NOT EXISTS idx_pending_autopilot_locks_expiry ON pending_autopilot_locks(expires_at);\n `);\n}\n\nfunction migrateDecisionPolicyVersionUnique(db: DatabaseSync): void {\n const row = db\n .prepare(\"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'pending_autopilot_decisions'\")\n .get() as { sql?: string } | undefined;\n if (!row?.sql?.includes(\"UNIQUE(queue, item_id, input_hash, policy, action)\")) return;\n\n db.exec(`\n BEGIN;\n\n ALTER TABLE pending_autopilot_decisions RENAME TO pending_autopilot_decisions_old_policy_unique;\n\n CREATE TABLE pending_autopilot_decisions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n queue TEXT NOT NULL,\n item_id TEXT NOT NULL,\n input_hash TEXT NOT NULL,\n policy TEXT NOT NULL DEFAULT 'default',\n policy_version TEXT NOT NULL,\n mode TEXT NOT NULL,\n action TEXT NOT NULL,\n reason_code TEXT NOT NULL,\n action_class TEXT NOT NULL,\n capability_class TEXT NOT NULL,\n confidence REAL NOT NULL,\n human_review_required INTEGER NOT NULL,\n evidence_json TEXT NOT NULL DEFAULT '[]',\n actor_json TEXT NOT NULL DEFAULT '{}',\n run_id TEXT NOT NULL,\n job_id TEXT,\n summary_json TEXT,\n audit_json TEXT,\n created_at INTEGER NOT NULL,\n UNIQUE(queue, item_id, input_hash, policy, policy_version, action)\n );\n\n INSERT OR IGNORE INTO pending_autopilot_decisions\n (id, queue, item_id, input_hash, policy, policy_version, mode, action, reason_code, action_class, capability_class, confidence, human_review_required, evidence_json, actor_json, run_id, job_id, summary_json, audit_json, created_at)\n SELECT\n id, queue, item_id, input_hash, policy, policy_version, mode, action, reason_code, action_class, capability_class, confidence, human_review_required, evidence_json, actor_json, run_id, job_id, summary_json, audit_json, created_at\n FROM pending_autopilot_decisions_old_policy_unique;\n\n DROP TABLE pending_autopilot_decisions_old_policy_unique;\n\n COMMIT;\n `);\n}\n\nfunction rowToDecision(row: Record<string, unknown>): PendingDecision {\n return {\n queue: row.queue as PendingQueue,\n itemId: row.item_id as string,\n inputHash: row.input_hash as string,\n policy: row.policy as string,\n policyVersion: row.policy_version as string,\n mode: row.mode as AutopilotMode,\n action: row.action as PendingDecision[\"action\"],\n reasonCode: row.reason_code as PendingDecision[\"reasonCode\"],\n actionClass: row.action_class as PendingDecision[\"actionClass\"],\n capabilityClass: row.capability_class as PendingDecision[\"capabilityClass\"],\n confidence: row.confidence as number,\n humanReviewRequired: Boolean(row.human_review_required),\n evidence: JSON.parse(row.evidence_json as string),\n actor: JSON.parse(row.actor_json as string),\n runId: row.run_id as string,\n jobId: (row.job_id as string | null) ?? undefined,\n summary: row.summary_json ? JSON.parse(row.summary_json as string) : undefined,\n audit: row.audit_json ? JSON.parse(row.audit_json as string) : undefined,\n createdAt: row.created_at as number,\n };\n}\n\nfunction nowSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../../services/pending-autopilot/types.ts"],"sourcesContent":["/**\n * Shared Pending Autopilot control-plane contracts (#1334).\n *\n * This foundation is intentionally queue-policy agnostic. Child issues #1326-#1330\n * plug concrete queue adapters for persona, procedures, verified facts, tool\n * proposals, and crystallization on top of these contracts without changing the\n * durable state or audit invariants defined here.\n */\n\nexport const PENDING_QUEUES = [\"persona\", \"procedures\", \"verified\", \"tools\", \"crystallization\"] as const;\nexport type PendingQueue = (typeof PENDING_QUEUES)[number];\n\nexport const AUTOPILOT_MODES = [\"dry-run\", \"apply\"] as const;\nexport type AutopilotMode = (typeof AUTOPILOT_MODES)[number];\n\nexport const AUTOPILOT_ACTIONS = [\n \"reported\",\n \"classified\",\n \"applied\",\n \"rejected\",\n \"promoted-to-draft\",\n \"deferred-for-human\",\n \"failed-validation\",\n \"failed-audit\",\n \"unknown-decision\",\n \"skipped-by-policy\",\n] as const;\nexport type AutopilotAction = (typeof AUTOPILOT_ACTIONS)[number];\n\nexport const AUTOPILOT_REASON_CODES = [\n \"already-processed\",\n \"approved\",\n \"audit-write-failed\",\n \"capability-not-allowed\",\n \"dry-run\",\n \"duplicate-input\",\n \"human-review-required\",\n \"input-hash-mismatch\",\n \"invalid-item\",\n \"lock-conflict\",\n \"lock-expired\",\n \"lock-missing\",\n \"lock-owner-mismatch\",\n \"policy-denied\",\n \"policy-report-only\",\n \"policy-requires-human\",\n \"policy-threshold-not-met\",\n \"duplicate-applied-proposal\",\n \"duplicate-pending-proposal\",\n \"stale-target-context\",\n \"low-confidence\",\n \"non-actionable\",\n \"secret-or-private-data-risk\",\n \"identity-boundary-change\",\n \"privacy-boundary-change\",\n \"security-boundary-change\",\n \"user-preference-change-requires-approval\",\n \"missing-evidence\",\n \"validation-failed\",\n \"safe-low-risk-localized-change\",\n \"schema-validation-failed\",\n \"unknown-decision\",\n \"unknown-queue\",\n] as const;\nexport type AutopilotReasonCode = (typeof AUTOPILOT_REASON_CODES)[number];\n\n/**\n * Ordered from least to most authority. `apply` is only intent; queue adapters\n * must map every planned action to one of these explicit approval boundaries.\n */\nexport const AUTOPILOT_CAPABILITY_CLASSES = [\n \"read-only\",\n \"dry-run\",\n \"record-review-metadata\",\n \"safe-state-transition\",\n \"write-draft-artifact\",\n \"apply-low-risk-change\",\n \"enable-behaviour\",\n \"trust-changing-action\",\n \"external-side-effect\",\n \"destructive-action\",\n] as const;\nexport type AutopilotCapabilityClass = (typeof AUTOPILOT_CAPABILITY_CLASSES)[number];\n\nexport const AUTOPILOT_ACTION_CLASSES = [\n \"observe\",\n \"preview\",\n \"record-review\",\n \"state-transition\",\n \"draft-artifact\",\n \"low-risk-apply\",\n \"enable-behaviour\",\n \"trust-change\",\n \"external-side-effect\",\n \"destructive\",\n] as const;\nexport type AutopilotActionClass = (typeof AUTOPILOT_ACTION_CLASSES)[number];\n\nconst enumSets = {\n queue: PENDING_QUEUES,\n mode: AUTOPILOT_MODES,\n action: AUTOPILOT_ACTIONS,\n reasonCode: AUTOPILOT_REASON_CODES,\n capabilityClass: AUTOPILOT_CAPABILITY_CLASSES,\n actionClass: AUTOPILOT_ACTION_CLASSES,\n} as const;\n\ntype EnumName = keyof typeof enumSets;\n\nexport function isPendingQueue(value: unknown): value is PendingQueue {\n return includes(PENDING_QUEUES, value);\n}\n\nexport function isAutopilotMode(value: unknown): value is AutopilotMode {\n return includes(AUTOPILOT_MODES, value);\n}\n\nexport function isAutopilotAction(value: unknown): value is AutopilotAction {\n return includes(AUTOPILOT_ACTIONS, value);\n}\n\nexport function isAutopilotReasonCode(value: unknown): value is AutopilotReasonCode {\n return includes(AUTOPILOT_REASON_CODES, value);\n}\n\nexport function isAutopilotCapabilityClass(value: unknown): value is AutopilotCapabilityClass {\n return includes(AUTOPILOT_CAPABILITY_CLASSES, value);\n}\n\nexport function isAutopilotActionClass(value: unknown): value is AutopilotActionClass {\n return includes(AUTOPILOT_ACTION_CLASSES, value);\n}\n\nexport function assertKnownEnum<T extends EnumName>(name: T, value: unknown): (typeof enumSets)[T][number] {\n const values = enumSets[name];\n if (!includes(values, value)) {\n throw new Error(`Unknown pending-autopilot ${name}: ${String(value)}`);\n }\n return value;\n}\n\nfunction includes<const T extends readonly string[]>(values: T, value: unknown): value is T[number] {\n return typeof value === \"string\" && (values as readonly string[]).includes(value);\n}\n\nexport interface RedactedAutopilotText {\n redacted: string;\n redactionCount: number;\n}\n\nexport interface PendingItem<TPayload extends Record<string, unknown> = Record<string, unknown>> {\n queue: PendingQueue;\n id: string;\n /** Stable content/policy input hash. Queue adapters must not include raw secrets in hash sources. */\n inputHash: string;\n policyVersion: string;\n capabilityClasses: AutopilotCapabilityClass[];\n payload: TPayload;\n visibleAfterCursor?: string | null;\n requiresHumanReview?: boolean;\n validationFailed?: boolean;\n}\n\nexport interface PendingDecisionEvidence {\n type: string;\n id?: string;\n summary?: string;\n}\n\nexport interface PendingDecisionActorContext {\n type: \"system\" | \"agent\" | \"human\" | \"cron\" | \"test\";\n id: string;\n}\n\nexport interface PendingDecision {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n /** Stable policy identifier/name; policyVersion identifies the exact revision. */\n policy: string;\n policyVersion: string;\n mode: AutopilotMode;\n action: AutopilotAction;\n reasonCode: AutopilotReasonCode;\n actionClass: AutopilotActionClass;\n capabilityClass: AutopilotCapabilityClass;\n confidence: number;\n humanReviewRequired: boolean;\n evidence: PendingDecisionEvidence[];\n actor: PendingDecisionActorContext;\n runId: string;\n jobId?: string;\n summary?: RedactedAutopilotSummary;\n audit?: RedactedAutopilotAudit;\n createdAt?: number;\n}\n\nexport interface PendingQueueAdapter<TItem extends PendingItem = PendingItem> {\n queue: PendingQueue;\n listPending(cursor?: PendingAutopilotCursor | null): Promise<TItem[]> | TItem[];\n decide(item: TItem, context: PendingDecisionContext): Promise<PendingDecision> | PendingDecision;\n apply?(decision: PendingDecision, item: TItem): Promise<void> | void;\n}\n\nexport interface PendingDecisionContext {\n runId: string;\n jobId?: string;\n mode: AutopilotMode;\n policy: string;\n policyVersion: string;\n inputHash: string;\n actor: PendingDecisionActorContext;\n}\n\nexport interface PendingAutopilotRunSummary {\n runId: string;\n mode: AutopilotMode;\n policy: string;\n policyVersion: string;\n queues: PendingQueue[];\n startedAt: number;\n finishedAt?: number;\n totals: Record<AutopilotAction, number>;\n decisions: Array<\n Pick<\n PendingDecision,\n | \"queue\"\n | \"itemId\"\n | \"inputHash\"\n | \"policy\"\n | \"policyVersion\"\n | \"action\"\n | \"reasonCode\"\n | \"capabilityClass\"\n | \"confidence\"\n | \"humanReviewRequired\"\n >\n >;\n}\n\nexport interface RedactedAutopilotSummary {\n title?: string;\n body?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface RedactedAutopilotAudit {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n policy: string;\n policyVersion: string;\n action: AutopilotAction;\n reasonCode: AutopilotReasonCode;\n capabilityClass: AutopilotCapabilityClass;\n humanReviewRequired: boolean;\n evidence: PendingDecisionEvidence[];\n actor: PendingDecisionActorContext;\n runId: string;\n jobId?: string;\n summary?: RedactedAutopilotSummary;\n}\n\nexport interface PendingAutopilotCursor {\n queue: PendingQueue;\n policy: string;\n cursor: string;\n inputHash: string;\n policyVersion: string;\n updatedAt: number;\n}\n\nexport interface PendingAutopilotLock {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n owner: string;\n expiresAt: number;\n createdAt: number;\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,iBAAiB;CAAC;CAAW;CAAc;CAAY;CAAS;
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../../services/pending-autopilot/types.ts"],"sourcesContent":["/**\n * Shared Pending Autopilot control-plane contracts (#1334).\n *\n * This foundation is intentionally queue-policy agnostic. Child issues #1326-#1330\n * plug concrete queue adapters for persona, procedures, verified facts, tool\n * proposals, and crystallization on top of these contracts without changing the\n * durable state or audit invariants defined here.\n */\n\nexport const PENDING_QUEUES = [\"persona\", \"procedures\", \"verified\", \"tools\", \"crystallization\"] as const;\nexport type PendingQueue = (typeof PENDING_QUEUES)[number];\n\nexport const AUTOPILOT_MODES = [\"dry-run\", \"apply\"] as const;\nexport type AutopilotMode = (typeof AUTOPILOT_MODES)[number];\n\nexport const AUTOPILOT_ACTIONS = [\n \"reported\",\n \"classified\",\n \"applied\",\n \"rejected\",\n \"promoted-to-draft\",\n \"deferred-for-human\",\n \"failed-validation\",\n \"failed-audit\",\n \"unknown-decision\",\n \"skipped-by-policy\",\n] as const;\nexport type AutopilotAction = (typeof AUTOPILOT_ACTIONS)[number];\n\nexport const AUTOPILOT_REASON_CODES = [\n \"already-processed\",\n \"approved\",\n \"audit-write-failed\",\n \"capability-not-allowed\",\n \"dry-run\",\n \"duplicate-input\",\n \"human-review-required\",\n \"input-hash-mismatch\",\n \"invalid-item\",\n \"lock-conflict\",\n \"lock-expired\",\n \"lock-missing\",\n \"lock-owner-mismatch\",\n \"policy-denied\",\n \"policy-report-only\",\n \"policy-requires-human\",\n \"policy-threshold-not-met\",\n \"duplicate-applied-proposal\",\n \"duplicate-pending-proposal\",\n \"stale-target-context\",\n \"low-confidence\",\n \"non-actionable\",\n \"secret-or-private-data-risk\",\n \"identity-boundary-change\",\n \"privacy-boundary-change\",\n \"security-boundary-change\",\n \"user-preference-change-requires-approval\",\n \"missing-evidence\",\n \"validation-failed\",\n \"safe-low-risk-localized-change\",\n \"schema-validation-failed\",\n \"unknown-decision\",\n \"unknown-queue\",\n] as const;\nexport type AutopilotReasonCode = (typeof AUTOPILOT_REASON_CODES)[number];\n\n/**\n * Ordered from least to most authority. `apply` is only intent; queue adapters\n * must map every planned action to one of these explicit approval boundaries.\n */\nexport const AUTOPILOT_CAPABILITY_CLASSES = [\n \"read-only\",\n \"dry-run\",\n \"record-review-metadata\",\n \"safe-state-transition\",\n \"write-draft-artifact\",\n \"apply-low-risk-change\",\n \"enable-behaviour\",\n \"trust-changing-action\",\n \"external-side-effect\",\n \"destructive-action\",\n] as const;\nexport type AutopilotCapabilityClass = (typeof AUTOPILOT_CAPABILITY_CLASSES)[number];\n\nexport const AUTOPILOT_ACTION_CLASSES = [\n \"observe\",\n \"preview\",\n \"record-review\",\n \"state-transition\",\n \"draft-artifact\",\n \"low-risk-apply\",\n \"enable-behaviour\",\n \"trust-change\",\n \"external-side-effect\",\n \"destructive\",\n] as const;\nexport type AutopilotActionClass = (typeof AUTOPILOT_ACTION_CLASSES)[number];\n\nconst enumSets = {\n queue: PENDING_QUEUES,\n mode: AUTOPILOT_MODES,\n action: AUTOPILOT_ACTIONS,\n reasonCode: AUTOPILOT_REASON_CODES,\n capabilityClass: AUTOPILOT_CAPABILITY_CLASSES,\n actionClass: AUTOPILOT_ACTION_CLASSES,\n} as const;\n\ntype EnumName = keyof typeof enumSets;\n\nexport function isPendingQueue(value: unknown): value is PendingQueue {\n return includes(PENDING_QUEUES, value);\n}\n\nexport function isAutopilotMode(value: unknown): value is AutopilotMode {\n return includes(AUTOPILOT_MODES, value);\n}\n\nexport function isAutopilotAction(value: unknown): value is AutopilotAction {\n return includes(AUTOPILOT_ACTIONS, value);\n}\n\nexport function isAutopilotReasonCode(value: unknown): value is AutopilotReasonCode {\n return includes(AUTOPILOT_REASON_CODES, value);\n}\n\nexport function isAutopilotCapabilityClass(value: unknown): value is AutopilotCapabilityClass {\n return includes(AUTOPILOT_CAPABILITY_CLASSES, value);\n}\n\nexport function isAutopilotActionClass(value: unknown): value is AutopilotActionClass {\n return includes(AUTOPILOT_ACTION_CLASSES, value);\n}\n\nexport function assertKnownEnum<T extends EnumName>(name: T, value: unknown): (typeof enumSets)[T][number] {\n const values = enumSets[name];\n if (!includes(values, value)) {\n throw new Error(`Unknown pending-autopilot ${name}: ${String(value)}`);\n }\n return value;\n}\n\nfunction includes<const T extends readonly string[]>(values: T, value: unknown): value is T[number] {\n return typeof value === \"string\" && (values as readonly string[]).includes(value);\n}\n\nexport interface RedactedAutopilotText {\n redacted: string;\n redactionCount: number;\n}\n\nexport interface PendingItem<TPayload extends Record<string, unknown> = Record<string, unknown>> {\n queue: PendingQueue;\n id: string;\n /** Stable content/policy input hash. Queue adapters must not include raw secrets in hash sources. */\n inputHash: string;\n policyVersion: string;\n capabilityClasses: AutopilotCapabilityClass[];\n payload: TPayload;\n visibleAfterCursor?: string | null;\n requiresHumanReview?: boolean;\n validationFailed?: boolean;\n}\n\nexport interface PendingDecisionEvidence {\n type: string;\n id?: string;\n summary?: string;\n}\n\nexport interface PendingDecisionActorContext {\n type: \"system\" | \"agent\" | \"human\" | \"cron\" | \"test\";\n id: string;\n}\n\nexport interface PendingDecision {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n /** Stable policy identifier/name; policyVersion identifies the exact revision. */\n policy: string;\n policyVersion: string;\n mode: AutopilotMode;\n action: AutopilotAction;\n reasonCode: AutopilotReasonCode;\n actionClass: AutopilotActionClass;\n capabilityClass: AutopilotCapabilityClass;\n confidence: number;\n humanReviewRequired: boolean;\n evidence: PendingDecisionEvidence[];\n actor: PendingDecisionActorContext;\n runId: string;\n jobId?: string;\n summary?: RedactedAutopilotSummary;\n audit?: RedactedAutopilotAudit;\n createdAt?: number;\n}\n\nexport interface PendingQueueAdapter<TItem extends PendingItem = PendingItem> {\n queue: PendingQueue;\n listPending(cursor?: PendingAutopilotCursor | null): Promise<TItem[]> | TItem[];\n decide(item: TItem, context: PendingDecisionContext): Promise<PendingDecision> | PendingDecision;\n apply?(decision: PendingDecision, item: TItem): Promise<void> | void;\n}\n\nexport interface PendingDecisionContext {\n runId: string;\n jobId?: string;\n mode: AutopilotMode;\n policy: string;\n policyVersion: string;\n inputHash: string;\n actor: PendingDecisionActorContext;\n}\n\nexport interface PendingAutopilotRunSummary {\n runId: string;\n mode: AutopilotMode;\n policy: string;\n policyVersion: string;\n queues: PendingQueue[];\n startedAt: number;\n finishedAt?: number;\n totals: Record<AutopilotAction, number>;\n decisions: Array<\n Pick<\n PendingDecision,\n | \"queue\"\n | \"itemId\"\n | \"inputHash\"\n | \"policy\"\n | \"policyVersion\"\n | \"action\"\n | \"reasonCode\"\n | \"capabilityClass\"\n | \"confidence\"\n | \"humanReviewRequired\"\n >\n >;\n}\n\nexport interface RedactedAutopilotSummary {\n title?: string;\n body?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface RedactedAutopilotAudit {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n policy: string;\n policyVersion: string;\n action: AutopilotAction;\n reasonCode: AutopilotReasonCode;\n capabilityClass: AutopilotCapabilityClass;\n humanReviewRequired: boolean;\n evidence: PendingDecisionEvidence[];\n actor: PendingDecisionActorContext;\n runId: string;\n jobId?: string;\n summary?: RedactedAutopilotSummary;\n}\n\nexport interface PendingAutopilotCursor {\n queue: PendingQueue;\n policy: string;\n cursor: string;\n inputHash: string;\n policyVersion: string;\n updatedAt: number;\n}\n\nexport interface PendingAutopilotLock {\n queue: PendingQueue;\n itemId: string;\n inputHash: string;\n owner: string;\n expiresAt: number;\n createdAt: number;\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,iBAAiB;CAAC;CAAW;CAAc;CAAY;CAAS;AAAiB;AAG9F,MAAa,kBAAkB,CAAC,WAAW,OAAO;AAGlD,MAAa,oBAAoB;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,yBAAyB;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;AAOA,MAAa,+BAA+B;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,2BAA2B;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAM,WAAW;CACf,OAAO;CACP,MAAM;CACN,QAAQ;CACR,YAAY;CACZ,iBAAiB;CACjB,aAAa;AACf;AAIA,SAAgB,eAAe,OAAuC;CACpE,OAAO,SAAS,gBAAgB,KAAK;AACvC;AAEA,SAAgB,gBAAgB,OAAwC;CACtE,OAAO,SAAS,iBAAiB,KAAK;AACxC;AAEA,SAAgB,kBAAkB,OAA0C;CAC1E,OAAO,SAAS,mBAAmB,KAAK;AAC1C;AAEA,SAAgB,sBAAsB,OAA8C;CAClF,OAAO,SAAS,wBAAwB,KAAK;AAC/C;AAEA,SAAgB,2BAA2B,OAAmD;CAC5F,OAAO,SAAS,8BAA8B,KAAK;AACrD;AAEA,SAAgB,uBAAuB,OAA+C;CACpF,OAAO,SAAS,0BAA0B,KAAK;AACjD;AAEA,SAAgB,gBAAoC,MAAS,OAA8C;CACzG,MAAM,SAAS,SAAS;CACxB,IAAI,CAAC,SAAS,QAAQ,KAAK,GACzB,MAAM,IAAI,MAAM,6BAA6B,KAAK,IAAI,OAAO,KAAK,GAAG;CAEvE,OAAO;AACT;AAEA,SAAS,SAA4C,QAAW,OAAoC;CAClG,OAAO,OAAO,UAAU,YAAa,OAA6B,SAAS,KAAK;AAClF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pending-digest-autopilot-cron.js","names":[],"sources":["../../services/pending-digest-autopilot-cron.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { HybridMemoryConfig } from \"../config.js\";\nimport { validateMaintenanceExecution } from \"./cron-exit-validator.js\";\nimport { getGuardFilePath, readGuardTimestampMs } from \"./cron-guard.js\";\nimport { canonicalJson, redactAutopilotValue } from \"./pending-autopilot/index.js\";\nimport type { PendingDigestAutopilotResult, PendingDigestFactsDb } from \"./pending-digest-autopilot.js\";\nimport { runPendingDigestAutopilot } from \"./pending-digest-autopilot.js\";\n\nexport const PENDING_DIGEST_AUTOPILOT_CRON_JOB = \"weekly-pending-digest-autopilot\";\nconst PENDING_DIGEST_JOB = \"weekly-pending-digest\";\nconst REQUIRED_STEPS = [\n \"guard-check\",\n \"config-load\",\n \"latest-digest-check\",\n \"digest-autopilot\",\n \"persona-triage\",\n \"procedure-promotion\",\n \"verified-triage\",\n \"tool-proposals\",\n \"crystallization-proposals\",\n \"summary-write\",\n \"validate-cron-exit\",\n \"notification-policy\",\n] as const;\n\ntype CronStepStatus = \"ok\" | \"failed\" | \"skipped\";\ntype CronStatus = \"ok\" | \"failed\" | \"skipped\" | \"partial\";\n\ntype CronStepName = (typeof REQUIRED_STEPS)[number];\n\nexport interface PendingDigestAutopilotCronArtifacts {\n hmLog: string;\n hmExit: string;\n summaryJson: string;\n summaryText: string;\n notificationJson?: string;\n}\n\nexport interface PendingDigestAutopilotCronSummary {\n runId: string;\n mode: \"dry-run\" | \"apply\";\n status: CronStatus;\n skipReason?: string;\n latestDigest: {\n found: boolean;\n path?: string;\n timestamp?: string;\n status?: \"success\" | \"failed\";\n };\n policies: {\n persona: string;\n procedure: string;\n verified: string;\n tool: string;\n crystallization: string;\n };\n counts: {\n inspected: number;\n applied: number;\n deferredForHuman: number;\n rejected: number;\n failed: number;\n skipped: number;\n };\n humanReviewRequired: boolean;\n notificationSent: boolean;\n artifacts: PendingDigestAutopilotCronArtifacts;\n}\n\nexport interface PendingDigestAutopilotCronResult {\n summary: PendingDigestAutopilotCronSummary;\n humanSummary: string;\n autopilotResult?: PendingDigestAutopilotResult;\n}\n\nexport interface RunPendingDigestAutopilotCronOptions {\n cfg: HybridMemoryConfig;\n factsDb: PendingDigestFactsDb;\n now?: Date;\n openclawHome?: string;\n runId?: string;\n}\n\ntype StepRow = {\n name: CronStepName;\n exit: number;\n status: CronStepStatus;\n reason: string;\n durationMs: number;\n};\n\nexport async function runPendingDigestAutopilotCron(\n opts: RunPendingDigestAutopilotCronOptions,\n): Promise<PendingDigestAutopilotCronResult> {\n const now = opts.now ?? new Date();\n const runId = opts.runId ?? `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${now.toISOString()}`;\n const openclawHome = resolveOpenclawHome(opts.openclawHome);\n const cronLogRoot = resolveWritableCronHybridMemRoot(openclawHome);\n const artifactDir = join(cronLogRoot, now.toISOString().slice(0, 10).replace(/-/g, \"\"));\n mkdirSync(artifactDir, { recursive: true });\n const runToken = now.toISOString().replace(/[:.]/g, \"-\");\n const hmLog = process.env.HM_LOG?.trim() || join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.log`);\n const hmExit =\n process.env.HM_EXIT?.trim() || join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.exit.txt`);\n const summaryJson = join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.summary.json`);\n const summaryText = join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.summary.txt`);\n ensureFile(hmLog);\n ensureFile(hmExit);\n\n const artifacts: PendingDigestAutopilotCronArtifacts = { hmLog, hmExit, summaryJson, summaryText };\n const stepRows = new Map<CronStepName, StepRow>();\n const autopilotCfg = opts.cfg.digest.autopilot;\n const guardPath = getGuardFilePath(PENDING_DIGEST_AUTOPILOT_CRON_JOB, openclawHome);\n const lockPath = join(openclawHome, \"cron\", \"locks\", `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}.lock.json`);\n let acquiredLock = false;\n let status: CronStatus = \"ok\";\n let skipReason: string | undefined;\n let autopilotResult: PendingDigestAutopilotResult | undefined;\n let notificationSent = false;\n let latestDigest: PendingDigestAutopilotCronSummary[\"latestDigest\"] = { found: false };\n\n const markStep = (name: CronStepName, row: Omit<StepRow, \"name\">): void => {\n const entry = { name, ...row };\n stepRows.set(name, entry);\n appendStepLine(hmExit, entry);\n };\n\n const skipRemaining = (reason: string): void => {\n skipReason = skipReason ?? reason;\n for (const step of REQUIRED_STEPS) {\n if (stepRows.has(step)) continue;\n markStep(step, { exit: 0, status: \"skipped\", reason, durationMs: 0 });\n }\n };\n const markMissingAsSkipped = (reason: string): void => {\n for (const step of REQUIRED_STEPS) {\n if (step === \"summary-write\" || step === \"validate-cron-exit\" || step === \"notification-policy\") continue;\n if (stepRows.has(step)) continue;\n markStep(step, { exit: 0, status: \"skipped\", reason, durationMs: 0 });\n }\n };\n\n logLine(hmLog, `run.start run_id=${runId} job=${PENDING_DIGEST_AUTOPILOT_CRON_JOB}`);\n logLine(hmLog, `run.guard_path ${guardPath}`);\n logLine(hmLog, `run.lock_path ${lockPath}`);\n logLine(hmLog, `run.config ${canonicalJson(redactAutopilotValue(autopilotCfg))}`);\n\n const guardStartedAt = Date.now();\n try {\n const guardTs = readGuardTimestampMs(PENDING_DIGEST_AUTOPILOT_CRON_JOB, openclawHome);\n const guardWindowMs = autopilotCfg.guardWindowHours * 60 * 60 * 1000;\n if (guardTs && now.getTime() - guardTs < guardWindowMs) {\n status = \"skipped\";\n skipReason = \"guard_window_active\";\n markStep(\"guard-check\", {\n exit: 0,\n status: \"skipped\",\n reason: \"guard_window_active\",\n durationMs: Date.now() - guardStartedAt,\n });\n } else {\n markStep(\"guard-check\", { exit: 0, status: \"ok\", reason: \"ok\", durationMs: Date.now() - guardStartedAt });\n }\n } catch (err) {\n status = \"failed\";\n markStep(\"guard-check\", {\n exit: 1,\n status: \"failed\",\n reason: \"guard_check_failed\",\n durationMs: Date.now() - guardStartedAt,\n });\n logLine(hmLog, `error.guard-check ${stringifyError(err)}`);\n }\n\n if (status !== \"failed\" && status !== \"skipped\") {\n const configStartedAt = Date.now();\n if (!autopilotCfg.enabled) {\n status = \"skipped\";\n skipReason = \"autopilot_disabled\";\n markStep(\"config-load\", {\n exit: 0,\n status: \"skipped\",\n reason: \"autopilot_disabled\",\n durationMs: Date.now() - configStartedAt,\n });\n } else {\n markStep(\"config-load\", { exit: 0, status: \"ok\", reason: \"ok\", durationMs: Date.now() - configStartedAt });\n }\n }\n\n if (status !== \"failed\" && status !== \"skipped\") {\n const latestStartedAt = Date.now();\n latestDigest = findLatestWeeklyPendingDigestArtifact(cronLogRoot);\n logLine(\n hmLog,\n `run.latest_digest found=${String(latestDigest.found)} status=${latestDigest.status ?? \"unknown\"} path=${latestDigest.path ?? \"none\"}`,\n );\n if (!latestDigest.found) {\n status = \"skipped\";\n skipReason = latestDigest.status === \"failed\" ? \"latest_digest_failed\" : \"latest_digest_missing\";\n markStep(\"latest-digest-check\", {\n exit: 0,\n status: \"skipped\",\n reason: skipReason,\n durationMs: Date.now() - latestStartedAt,\n });\n } else {\n markStep(\"latest-digest-check\", {\n exit: 0,\n status: \"ok\",\n reason: \"ok\",\n durationMs: Date.now() - latestStartedAt,\n });\n }\n }\n\n if (status !== \"failed\" && status !== \"skipped\" && autopilotCfg.mode === \"apply\") {\n const lockStartedAt = Date.now();\n const lock = tryAcquireAutopilotLock(lockPath, runId, autopilotCfg.lockTtlMinutes, now.getTime());\n logLine(hmLog, `run.lock status=${lock.reason}`);\n if (!lock.acquired) {\n status = \"skipped\";\n skipReason = lock.reason;\n markStep(\"digest-autopilot\", {\n exit: 0,\n status: \"skipped\",\n reason: lock.reason,\n durationMs: Date.now() - lockStartedAt,\n });\n logLine(hmLog, `run.lock_skip ${lock.reason}`);\n } else {\n acquiredLock = true;\n }\n }\n\n let summary!: PendingDigestAutopilotCronSummary;\n let humanSummary = \"\";\n\n try {\n if (status !== \"failed\" && status !== \"skipped\" && !stepRows.has(\"digest-autopilot\")) {\n const startedAt = Date.now();\n try {\n logLine(\n hmLog,\n `run.command openclaw hybrid-mem digest autopilot --${autopilotCfg.mode} --max-persona ${autopilotCfg.maxPersona} --max-procedures ${autopilotCfg.maxProcedures} --max-verified ${autopilotCfg.maxVerified} --max-tools ${autopilotCfg.maxTools} --max-crystallization ${autopilotCfg.maxCrystallization}`,\n );\n autopilotResult = await runPendingDigestAutopilot({\n cfg: opts.cfg,\n factsDb: opts.factsDb,\n mode: autopilotCfg.mode,\n runId,\n jobId: `hybrid-mem:${PENDING_DIGEST_AUTOPILOT_CRON_JOB}`,\n now,\n stateDbPath: join(dirname(opts.cfg.sqlitePath), \"pending-autopilot.db\"),\n policies: {\n persona: autopilotCfg.personaPolicy,\n procedures: autopilotCfg.procedurePolicy,\n verified: autopilotCfg.verifiedPolicy,\n tools: autopilotCfg.toolPolicy,\n crystallization: autopilotCfg.crystallizationPolicy,\n },\n max: {\n persona: autopilotCfg.maxPersona,\n procedures: autopilotCfg.maxProcedures,\n verified: autopilotCfg.maxVerified,\n tools: autopilotCfg.maxTools,\n crystallization: autopilotCfg.maxCrystallization,\n },\n });\n markStep(\"digest-autopilot\", { exit: 0, status: \"ok\", reason: \"ok\", durationMs: Date.now() - startedAt });\n } catch (err) {\n status = \"failed\";\n markStep(\"digest-autopilot\", {\n exit: 1,\n status: \"failed\",\n reason: \"inner_command_failed\",\n durationMs: Date.now() - startedAt,\n });\n logLine(hmLog, `error.digest-autopilot ${stringifyError(err)}`);\n }\n }\n\n const queueMap: Array<[CronStepName, keyof NonNullable<typeof autopilotResult>[\"queues\"]]> = [\n [\"persona-triage\", \"persona\"],\n [\"procedure-promotion\", \"procedures\"],\n [\"verified-triage\", \"verified\"],\n [\"tool-proposals\", \"tools\"],\n [\"crystallization-proposals\", \"crystallization\"],\n ];\n for (const [stepName, queueName] of queueMap) {\n if (stepRows.has(stepName)) continue;\n if (!autopilotResult) {\n markStep(stepName, {\n exit: 0,\n status: \"skipped\",\n reason: skipReason ?? \"digest_autopilot_not_run\",\n durationMs: 0,\n });\n continue;\n }\n const queue = autopilotResult.queues[queueName];\n if (queue.skipped) {\n markStep(stepName, { exit: 0, status: \"skipped\", reason: queue.skipReason ?? \"queue_skipped\", durationMs: 0 });\n } else if (queue.decisions.length === 0) {\n markStep(stepName, { exit: 0, status: \"skipped\", reason: \"policy_report_only_no_actions\", durationMs: 0 });\n } else {\n markStep(stepName, { exit: 0, status: \"ok\", reason: \"ok\", durationMs: 0 });\n }\n }\n\n if (status === \"skipped\") {\n markMissingAsSkipped(skipReason ?? \"skipped\");\n } else if (status === \"failed\") {\n markMissingAsSkipped(\"blocked_by_failure\");\n }\n\n summary = buildCronSummary({\n runId,\n status,\n skipReason,\n mode: autopilotCfg.mode,\n latestDigest,\n autopilotResult,\n artifacts,\n notificationSent,\n autopilotCfg,\n });\n\n const validateStartedAt = Date.now();\n const requiredBeforeValidate = REQUIRED_STEPS.filter(\n (s) => s !== \"validate-cron-exit\" && s !== \"notification-policy\" && s !== \"summary-write\",\n );\n const validation = validateMaintenanceExecution(hmExit, hmLog, [...requiredBeforeValidate], true);\n if (validation.maintenanceStatus === \"failed\" || validation.maintenanceStatus === \"partial\") {\n status = \"failed\";\n summary.status = \"failed\";\n markStep(\"validate-cron-exit\", {\n exit: 1,\n status: \"failed\",\n reason: \"validate_cron_exit_failed\",\n durationMs: Date.now() - validateStartedAt,\n });\n logLine(hmLog, `error.validate-cron-exit ${validation.error ?? \"validation_failed\"}`);\n } else {\n markStep(\"validate-cron-exit\", {\n exit: 0,\n status: \"ok\",\n reason: \"ok\",\n durationMs: Date.now() - validateStartedAt,\n });\n }\n\n const notifyStartedAt = Date.now();\n try {\n const shouldNotify = shouldNotifyRun(summary, autopilotCfg);\n if (shouldNotify) {\n const payloadPath = join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.notification.json`);\n const payload = {\n runId: summary.runId,\n status: summary.status,\n counts: summary.counts,\n humanReviewRequired: summary.humanReviewRequired,\n skipReason: summary.skipReason,\n artifacts: summary.artifacts,\n };\n writeFileSync(payloadPath, `${canonicalJson(redactAutopilotValue(payload))}\\n`, \"utf-8\");\n artifacts.notificationJson = payloadPath;\n notificationSent = true;\n summary.notificationSent = true;\n markStep(\"notification-policy\", {\n exit: 0,\n status: \"ok\",\n reason: \"notification_sent\",\n durationMs: Date.now() - notifyStartedAt,\n });\n logLine(hmLog, `run.notification payload=${payloadPath}`);\n } else {\n markStep(\"notification-policy\", {\n exit: 0,\n status: \"skipped\",\n reason: \"notification_not_required\",\n durationMs: Date.now() - notifyStartedAt,\n });\n }\n } catch (err) {\n if (status === \"ok\" || status === \"skipped\") status = \"partial\";\n summary.status = status;\n markStep(\"notification-policy\", {\n exit: 1,\n status: \"failed\",\n reason: \"notification_failed\",\n durationMs: Date.now() - notifyStartedAt,\n });\n logLine(hmLog, `error.notification-policy ${stringifyError(err)}`);\n }\n\n summary.status = status;\n summary.skipReason = status === \"skipped\" ? skipReason : undefined;\n summary.notificationSent = notificationSent;\n\n const summaryStartedAt = Date.now();\n humanSummary = renderCronHumanSummary(summary);\n try {\n writeFileSync(summaryJson, `${canonicalJson(redactAutopilotValue(summary))}\\n`, \"utf-8\");\n writeFileSync(summaryText, `${humanSummary}\\n`, \"utf-8\");\n markStep(\"summary-write\", { exit: 0, status: \"ok\", reason: \"ok\", durationMs: Date.now() - summaryStartedAt });\n } catch (err) {\n status = \"failed\";\n summary.status = \"failed\";\n markStep(\"summary-write\", {\n exit: 1,\n status: \"failed\",\n reason: \"artifact_write_failed\",\n durationMs: Date.now() - summaryStartedAt,\n });\n logLine(hmLog, `error.summary-write ${stringifyError(err)}`);\n }\n } finally {\n if (acquiredLock) releaseAutopilotLock(lockPath, runId);\n }\n\n logLine(hmLog, `run.finish status=${summary.status} skip_reason=${summary.skipReason ?? \"none\"}`);\n if (status === \"ok\" && !skipReason) {\n mkdirSync(dirname(guardPath), { recursive: true });\n writeFileSync(guardPath, `${Date.now()}`, \"utf-8\");\n }\n if (status === \"skipped\") skipRemaining(skipReason ?? \"skipped\");\n\n return { summary, humanSummary, autopilotResult };\n}\n\nfunction resolveOpenclawHome(openclawHome?: string): string {\n if (typeof openclawHome === \"string\" && openclawHome.trim().length > 0) return openclawHome;\n if (typeof process.env.OPENCLAW_HOME === \"string\" && process.env.OPENCLAW_HOME.trim().length > 0) {\n return process.env.OPENCLAW_HOME.trim();\n }\n return join(homedir(), \".openclaw\");\n}\n\n/** Match hybrid-mem cron bash harness: prefer ~/.openclaw/logs/cron-hybrid-mem, fall back to /tmp when not writable. */\nfunction resolveWritableCronHybridMemRoot(openclawHome: string): string {\n const primary = join(openclawHome, \"logs\", \"cron-hybrid-mem\");\n try {\n mkdirSync(primary, { recursive: true });\n const probe = join(primary, `.write-probe-${process.pid}-${Date.now()}`);\n writeFileSync(probe, \"ok\", \"utf-8\");\n unlinkSync(probe);\n return primary;\n } catch {\n const user = process.env.USER || process.env.USERNAME || \"user\";\n const fallback =\n process.platform === \"win32\"\n ? join(tmpdir(), `openclaw-cron-hybrid-mem-${user}`)\n : join(\"/tmp\", `openclaw-cron-hybrid-mem-${user}`);\n mkdirSync(fallback, { recursive: true });\n return fallback;\n }\n}\n\nfunction spinWaitMs(ms: number): void {\n const end = Date.now() + ms;\n while (Date.now() < end) {\n /* tight spin for short lock-acquisition backoff */\n }\n}\n\nfunction ensureFile(path: string): void {\n mkdirSync(dirname(path), { recursive: true });\n if (!existsSync(path)) writeFileSync(path, \"\", \"utf-8\");\n}\n\nfunction appendStepLine(path: string, row: StepRow): void {\n const ts = new Date().toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n writeFileSync(\n path,\n `${ts} step=${row.name} exit=${row.exit} status=${row.status} reason=${row.reason} duration_ms=${row.durationMs}\\n`,\n {\n encoding: \"utf-8\",\n flag: \"a\",\n },\n );\n}\n\nfunction logLine(path: string, line: string): void {\n writeFileSync(path, `${new Date().toISOString()} ${line}\\n`, { encoding: \"utf-8\", flag: \"a\" });\n}\n\nfunction stringifyError(err: unknown): string {\n if (err instanceof Error) return err.stack || err.message;\n return String(err);\n}\n\nfunction findLatestWeeklyPendingDigestArtifact(root: string): PendingDigestAutopilotCronSummary[\"latestDigest\"] {\n if (!existsSync(root)) return { found: false };\n const stack = [root];\n const candidates: Array<{ path: string; mtimeMs: number; success: boolean }> = [];\n while (stack.length > 0) {\n const dir = stack.pop();\n if (!dir) continue;\n for (const entry of safeReadDir(dir)) {\n const fullPath = join(dir, entry);\n let st: ReturnType<typeof statSync>;\n try {\n st = statSync(fullPath);\n } catch {\n continue;\n }\n if (st.isDirectory()) {\n stack.push(fullPath);\n continue;\n }\n if (!entry.startsWith(`${PENDING_DIGEST_JOB}-`) || !entry.endsWith(\".exit.txt\")) continue;\n if (entry.startsWith(`${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-`)) continue;\n const content = readSafe(fullPath);\n const success =\n /\\bstep=digest-pending\\b.*\\bexit=0\\b/.test(content) || /\\bdigest-pending\\b.*\\bexit=0\\b/.test(content);\n candidates.push({ path: fullPath, mtimeMs: st.mtimeMs, success });\n }\n }\n if (candidates.length === 0) return { found: false };\n candidates.sort((a, b) => b.mtimeMs - a.mtimeMs);\n const newest = candidates[0];\n if (!newest) return { found: false };\n if (newest.success) {\n return {\n found: true,\n path: newest.path,\n timestamp: new Date(newest.mtimeMs).toISOString(),\n status: \"success\",\n };\n }\n return {\n found: false,\n path: newest.path,\n timestamp: new Date(newest.mtimeMs).toISOString(),\n status: \"failed\",\n };\n}\n\nfunction safeReadDir(path: string): string[] {\n try {\n return readdirSync(path);\n } catch {\n return [];\n }\n}\n\nfunction readSafe(path: string): string {\n try {\n return readFileSync(path, \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\nfunction buildCronSummary(input: {\n runId: string;\n mode: \"dry-run\" | \"apply\";\n status: CronStatus;\n skipReason?: string;\n latestDigest: PendingDigestAutopilotCronSummary[\"latestDigest\"];\n autopilotResult?: PendingDigestAutopilotResult;\n notificationSent: boolean;\n artifacts: PendingDigestAutopilotCronArtifacts;\n autopilotCfg: HybridMemoryConfig[\"digest\"][\"autopilot\"];\n}): PendingDigestAutopilotCronSummary {\n return {\n runId: input.runId,\n mode: input.mode,\n status: input.status,\n skipReason: input.skipReason,\n latestDigest: input.latestDigest,\n policies: {\n persona: input.autopilotCfg.personaPolicy,\n procedure: input.autopilotCfg.procedurePolicy,\n verified: input.autopilotCfg.verifiedPolicy,\n tool: input.autopilotCfg.toolPolicy,\n crystallization: input.autopilotCfg.crystallizationPolicy,\n },\n counts: {\n inspected: input.autopilotResult?.counts.inspected ?? 0,\n applied: input.autopilotResult?.counts.applied ?? 0,\n deferredForHuman: input.autopilotResult?.counts.deferred ?? 0,\n rejected: input.autopilotResult?.counts.rejected ?? 0,\n failed: input.autopilotResult?.counts.failedValidation ?? 0,\n skipped: input.autopilotResult?.counts.skipped ?? 0,\n },\n humanReviewRequired: (input.autopilotResult?.counts.humanReviewRequired ?? 0) > 0,\n notificationSent: input.notificationSent,\n artifacts: input.artifacts,\n };\n}\n\nfunction renderCronHumanSummary(summary: PendingDigestAutopilotCronSummary): string {\n return [\n `Pending digest autopilot cron ${summary.runId}`,\n `Status: ${summary.status}${summary.skipReason ? ` (${summary.skipReason})` : \"\"}`,\n `Mode: ${summary.mode}`,\n `Latest digest: ${summary.latestDigest.found ? `${summary.latestDigest.path ?? \"found\"} (${summary.latestDigest.timestamp ?? \"unknown\"})` : \"not found\"}`,\n `Counts: inspected=${summary.counts.inspected}, applied=${summary.counts.applied}, deferredForHuman=${summary.counts.deferredForHuman}, rejected=${summary.counts.rejected}, failed=${summary.counts.failed}, skipped=${summary.counts.skipped}`,\n `Human review required: ${summary.humanReviewRequired ? \"yes\" : \"no\"}`,\n `Artifacts: HM_LOG=${summary.artifacts.hmLog}, HM_EXIT=${summary.artifacts.hmExit}, summaryJson=${summary.artifacts.summaryJson}`,\n summary.notificationSent ? \"Notification payload generated.\" : \"Notification not required by policy.\",\n ].join(\"\\n\");\n}\n\nfunction shouldNotifyRun(\n summary: PendingDigestAutopilotCronSummary,\n cfg: HybridMemoryConfig[\"digest\"][\"autopilot\"],\n): boolean {\n if (summary.status === \"failed\") return cfg.notifyOnFailure;\n if (summary.status === \"partial\") return cfg.notifyOnFailure;\n if (summary.humanReviewRequired) return cfg.notifyOnHumanReviewRequired;\n if (summary.mode === \"apply\" && summary.counts.applied > 0) return cfg.notifyOnApplyActions;\n if (summary.mode === \"dry-run\" && summary.counts.inspected > 0 && summary.counts.applied === 0) {\n return cfg.notifyOnDryRunActions;\n }\n if (summary.counts.inspected === 0 && summary.counts.applied === 0) return cfg.notifyOnNoop;\n return false;\n}\n\nfunction tryAcquireAutopilotLock(\n lockPath: string,\n runId: string,\n ttlMinutes: number,\n nowMs: number,\n): { acquired: boolean; reason: \"lock_already_held\" | \"lock_stale_recovered\" | \"lock_acquired\" } {\n mkdirSync(dirname(lockPath), { recursive: true });\n const expiresAt = nowMs + ttlMinutes * 60 * 1000;\n const payload = { runId, acquiredAt: nowMs, expiresAt };\n const tryWriteExclusive = (): boolean => {\n try {\n writeFileSync(lockPath, `${canonicalJson(payload)}\\n`, { encoding: \"utf-8\", flag: \"wx\" });\n return true;\n } catch {\n return false;\n }\n };\n\n const recoverStaleOrCorruptLock = (): { acquired: boolean; reason: \"lock_stale_recovered\" | \"lock_already_held\" } => {\n for (let attempt = 0; attempt < 4; attempt++) {\n try {\n const snapshot = readSafe(lockPath);\n const existing = parseLock(snapshot);\n if (existing && existing.expiresAt > nowMs) return { acquired: false, reason: \"lock_already_held\" };\n if (existing && existing.expiresAt <= nowMs) {\n rmSync(lockPath, { force: true });\n } else if (!existing) {\n rmSync(lockPath, { force: true });\n }\n spinWaitMs(2 + attempt * 5);\n if (tryWriteExclusive()) return { acquired: true, reason: \"lock_stale_recovered\" };\n } catch {\n spinWaitMs(2 + attempt * 5);\n }\n }\n return { acquired: false, reason: \"lock_already_held\" };\n };\n\n try {\n if (tryWriteExclusive()) return { acquired: true, reason: \"lock_acquired\" };\n const existing = parseLock(readSafe(lockPath));\n if (!existing) return recoverStaleOrCorruptLock();\n if (existing.expiresAt > nowMs) return { acquired: false, reason: \"lock_already_held\" };\n return recoverStaleOrCorruptLock();\n } catch {\n return { acquired: false, reason: \"lock_already_held\" };\n }\n}\n\nfunction releaseAutopilotLock(lockPath: string, runId: string): void {\n const existing = parseLock(readSafe(lockPath));\n if (!existing || existing.runId !== runId) return;\n rmSync(lockPath, { force: true });\n}\n\nfunction parseLock(raw: string): { runId: string; expiresAt: number } | null {\n try {\n const parsed = JSON.parse(raw) as { runId?: unknown; expiresAt?: unknown };\n if (typeof parsed.runId !== \"string\") return null;\n if (typeof parsed.expiresAt !== \"number\" || !Number.isFinite(parsed.expiresAt)) return null;\n return { runId: parsed.runId, expiresAt: parsed.expiresAt };\n } catch {\n return null;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pending-digest-autopilot-cron.js","names":[],"sources":["../../services/pending-digest-autopilot-cron.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { HybridMemoryConfig } from \"../config.js\";\nimport { validateMaintenanceExecution } from \"./cron-exit-validator.js\";\nimport { getGuardFilePath, readGuardTimestampMs } from \"./cron-guard.js\";\nimport { canonicalJson, redactAutopilotValue } from \"./pending-autopilot/index.js\";\nimport type { PendingDigestAutopilotResult, PendingDigestFactsDb } from \"./pending-digest-autopilot.js\";\nimport { runPendingDigestAutopilot } from \"./pending-digest-autopilot.js\";\n\nexport const PENDING_DIGEST_AUTOPILOT_CRON_JOB = \"weekly-pending-digest-autopilot\";\nconst PENDING_DIGEST_JOB = \"weekly-pending-digest\";\nconst REQUIRED_STEPS = [\n \"guard-check\",\n \"config-load\",\n \"latest-digest-check\",\n \"digest-autopilot\",\n \"persona-triage\",\n \"procedure-promotion\",\n \"verified-triage\",\n \"tool-proposals\",\n \"crystallization-proposals\",\n \"summary-write\",\n \"validate-cron-exit\",\n \"notification-policy\",\n] as const;\n\ntype CronStepStatus = \"ok\" | \"failed\" | \"skipped\";\ntype CronStatus = \"ok\" | \"failed\" | \"skipped\" | \"partial\";\n\ntype CronStepName = (typeof REQUIRED_STEPS)[number];\n\nexport interface PendingDigestAutopilotCronArtifacts {\n hmLog: string;\n hmExit: string;\n summaryJson: string;\n summaryText: string;\n notificationJson?: string;\n}\n\nexport interface PendingDigestAutopilotCronSummary {\n runId: string;\n mode: \"dry-run\" | \"apply\";\n status: CronStatus;\n skipReason?: string;\n latestDigest: {\n found: boolean;\n path?: string;\n timestamp?: string;\n status?: \"success\" | \"failed\";\n };\n policies: {\n persona: string;\n procedure: string;\n verified: string;\n tool: string;\n crystallization: string;\n };\n counts: {\n inspected: number;\n applied: number;\n deferredForHuman: number;\n rejected: number;\n failed: number;\n skipped: number;\n };\n humanReviewRequired: boolean;\n notificationSent: boolean;\n artifacts: PendingDigestAutopilotCronArtifacts;\n}\n\nexport interface PendingDigestAutopilotCronResult {\n summary: PendingDigestAutopilotCronSummary;\n humanSummary: string;\n autopilotResult?: PendingDigestAutopilotResult;\n}\n\nexport interface RunPendingDigestAutopilotCronOptions {\n cfg: HybridMemoryConfig;\n factsDb: PendingDigestFactsDb;\n now?: Date;\n openclawHome?: string;\n runId?: string;\n}\n\ntype StepRow = {\n name: CronStepName;\n exit: number;\n status: CronStepStatus;\n reason: string;\n durationMs: number;\n};\n\nexport async function runPendingDigestAutopilotCron(\n opts: RunPendingDigestAutopilotCronOptions,\n): Promise<PendingDigestAutopilotCronResult> {\n const now = opts.now ?? new Date();\n const runId = opts.runId ?? `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${now.toISOString()}`;\n const openclawHome = resolveOpenclawHome(opts.openclawHome);\n const cronLogRoot = resolveWritableCronHybridMemRoot(openclawHome);\n const artifactDir = join(cronLogRoot, now.toISOString().slice(0, 10).replace(/-/g, \"\"));\n mkdirSync(artifactDir, { recursive: true });\n const runToken = now.toISOString().replace(/[:.]/g, \"-\");\n const hmLog = process.env.HM_LOG?.trim() || join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.log`);\n const hmExit =\n process.env.HM_EXIT?.trim() || join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.exit.txt`);\n const summaryJson = join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.summary.json`);\n const summaryText = join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.summary.txt`);\n ensureFile(hmLog);\n ensureFile(hmExit);\n\n const artifacts: PendingDigestAutopilotCronArtifacts = { hmLog, hmExit, summaryJson, summaryText };\n const stepRows = new Map<CronStepName, StepRow>();\n const autopilotCfg = opts.cfg.digest.autopilot;\n const guardPath = getGuardFilePath(PENDING_DIGEST_AUTOPILOT_CRON_JOB, openclawHome);\n const lockPath = join(openclawHome, \"cron\", \"locks\", `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}.lock.json`);\n let acquiredLock = false;\n let status: CronStatus = \"ok\";\n let skipReason: string | undefined;\n let autopilotResult: PendingDigestAutopilotResult | undefined;\n let notificationSent = false;\n let latestDigest: PendingDigestAutopilotCronSummary[\"latestDigest\"] = { found: false };\n\n const markStep = (name: CronStepName, row: Omit<StepRow, \"name\">): void => {\n const entry = { name, ...row };\n stepRows.set(name, entry);\n appendStepLine(hmExit, entry);\n };\n\n const skipRemaining = (reason: string): void => {\n skipReason = skipReason ?? reason;\n for (const step of REQUIRED_STEPS) {\n if (stepRows.has(step)) continue;\n markStep(step, { exit: 0, status: \"skipped\", reason, durationMs: 0 });\n }\n };\n const markMissingAsSkipped = (reason: string): void => {\n for (const step of REQUIRED_STEPS) {\n if (step === \"summary-write\" || step === \"validate-cron-exit\" || step === \"notification-policy\") continue;\n if (stepRows.has(step)) continue;\n markStep(step, { exit: 0, status: \"skipped\", reason, durationMs: 0 });\n }\n };\n\n logLine(hmLog, `run.start run_id=${runId} job=${PENDING_DIGEST_AUTOPILOT_CRON_JOB}`);\n logLine(hmLog, `run.guard_path ${guardPath}`);\n logLine(hmLog, `run.lock_path ${lockPath}`);\n logLine(hmLog, `run.config ${canonicalJson(redactAutopilotValue(autopilotCfg))}`);\n\n const guardStartedAt = Date.now();\n try {\n const guardTs = readGuardTimestampMs(PENDING_DIGEST_AUTOPILOT_CRON_JOB, openclawHome);\n const guardWindowMs = autopilotCfg.guardWindowHours * 60 * 60 * 1000;\n if (guardTs && now.getTime() - guardTs < guardWindowMs) {\n status = \"skipped\";\n skipReason = \"guard_window_active\";\n markStep(\"guard-check\", {\n exit: 0,\n status: \"skipped\",\n reason: \"guard_window_active\",\n durationMs: Date.now() - guardStartedAt,\n });\n } else {\n markStep(\"guard-check\", { exit: 0, status: \"ok\", reason: \"ok\", durationMs: Date.now() - guardStartedAt });\n }\n } catch (err) {\n status = \"failed\";\n markStep(\"guard-check\", {\n exit: 1,\n status: \"failed\",\n reason: \"guard_check_failed\",\n durationMs: Date.now() - guardStartedAt,\n });\n logLine(hmLog, `error.guard-check ${stringifyError(err)}`);\n }\n\n if (status !== \"failed\" && status !== \"skipped\") {\n const configStartedAt = Date.now();\n if (!autopilotCfg.enabled) {\n status = \"skipped\";\n skipReason = \"autopilot_disabled\";\n markStep(\"config-load\", {\n exit: 0,\n status: \"skipped\",\n reason: \"autopilot_disabled\",\n durationMs: Date.now() - configStartedAt,\n });\n } else {\n markStep(\"config-load\", { exit: 0, status: \"ok\", reason: \"ok\", durationMs: Date.now() - configStartedAt });\n }\n }\n\n if (status !== \"failed\" && status !== \"skipped\") {\n const latestStartedAt = Date.now();\n latestDigest = findLatestWeeklyPendingDigestArtifact(cronLogRoot);\n logLine(\n hmLog,\n `run.latest_digest found=${String(latestDigest.found)} status=${latestDigest.status ?? \"unknown\"} path=${latestDigest.path ?? \"none\"}`,\n );\n if (!latestDigest.found) {\n status = \"skipped\";\n skipReason = latestDigest.status === \"failed\" ? \"latest_digest_failed\" : \"latest_digest_missing\";\n markStep(\"latest-digest-check\", {\n exit: 0,\n status: \"skipped\",\n reason: skipReason,\n durationMs: Date.now() - latestStartedAt,\n });\n } else {\n markStep(\"latest-digest-check\", {\n exit: 0,\n status: \"ok\",\n reason: \"ok\",\n durationMs: Date.now() - latestStartedAt,\n });\n }\n }\n\n if (status !== \"failed\" && status !== \"skipped\" && autopilotCfg.mode === \"apply\") {\n const lockStartedAt = Date.now();\n const lock = tryAcquireAutopilotLock(lockPath, runId, autopilotCfg.lockTtlMinutes, now.getTime());\n logLine(hmLog, `run.lock status=${lock.reason}`);\n if (!lock.acquired) {\n status = \"skipped\";\n skipReason = lock.reason;\n markStep(\"digest-autopilot\", {\n exit: 0,\n status: \"skipped\",\n reason: lock.reason,\n durationMs: Date.now() - lockStartedAt,\n });\n logLine(hmLog, `run.lock_skip ${lock.reason}`);\n } else {\n acquiredLock = true;\n }\n }\n\n let summary!: PendingDigestAutopilotCronSummary;\n let humanSummary = \"\";\n\n try {\n if (status !== \"failed\" && status !== \"skipped\" && !stepRows.has(\"digest-autopilot\")) {\n const startedAt = Date.now();\n try {\n logLine(\n hmLog,\n `run.command openclaw hybrid-mem digest autopilot --${autopilotCfg.mode} --max-persona ${autopilotCfg.maxPersona} --max-procedures ${autopilotCfg.maxProcedures} --max-verified ${autopilotCfg.maxVerified} --max-tools ${autopilotCfg.maxTools} --max-crystallization ${autopilotCfg.maxCrystallization}`,\n );\n autopilotResult = await runPendingDigestAutopilot({\n cfg: opts.cfg,\n factsDb: opts.factsDb,\n mode: autopilotCfg.mode,\n runId,\n jobId: `hybrid-mem:${PENDING_DIGEST_AUTOPILOT_CRON_JOB}`,\n now,\n stateDbPath: join(dirname(opts.cfg.sqlitePath), \"pending-autopilot.db\"),\n policies: {\n persona: autopilotCfg.personaPolicy,\n procedures: autopilotCfg.procedurePolicy,\n verified: autopilotCfg.verifiedPolicy,\n tools: autopilotCfg.toolPolicy,\n crystallization: autopilotCfg.crystallizationPolicy,\n },\n max: {\n persona: autopilotCfg.maxPersona,\n procedures: autopilotCfg.maxProcedures,\n verified: autopilotCfg.maxVerified,\n tools: autopilotCfg.maxTools,\n crystallization: autopilotCfg.maxCrystallization,\n },\n });\n markStep(\"digest-autopilot\", { exit: 0, status: \"ok\", reason: \"ok\", durationMs: Date.now() - startedAt });\n } catch (err) {\n status = \"failed\";\n markStep(\"digest-autopilot\", {\n exit: 1,\n status: \"failed\",\n reason: \"inner_command_failed\",\n durationMs: Date.now() - startedAt,\n });\n logLine(hmLog, `error.digest-autopilot ${stringifyError(err)}`);\n }\n }\n\n const queueMap: Array<[CronStepName, keyof NonNullable<typeof autopilotResult>[\"queues\"]]> = [\n [\"persona-triage\", \"persona\"],\n [\"procedure-promotion\", \"procedures\"],\n [\"verified-triage\", \"verified\"],\n [\"tool-proposals\", \"tools\"],\n [\"crystallization-proposals\", \"crystallization\"],\n ];\n for (const [stepName, queueName] of queueMap) {\n if (stepRows.has(stepName)) continue;\n if (!autopilotResult) {\n markStep(stepName, {\n exit: 0,\n status: \"skipped\",\n reason: skipReason ?? \"digest_autopilot_not_run\",\n durationMs: 0,\n });\n continue;\n }\n const queue = autopilotResult.queues[queueName];\n if (queue.skipped) {\n markStep(stepName, { exit: 0, status: \"skipped\", reason: queue.skipReason ?? \"queue_skipped\", durationMs: 0 });\n } else if (queue.decisions.length === 0) {\n markStep(stepName, { exit: 0, status: \"skipped\", reason: \"policy_report_only_no_actions\", durationMs: 0 });\n } else {\n markStep(stepName, { exit: 0, status: \"ok\", reason: \"ok\", durationMs: 0 });\n }\n }\n\n if (status === \"skipped\") {\n markMissingAsSkipped(skipReason ?? \"skipped\");\n } else if (status === \"failed\") {\n markMissingAsSkipped(\"blocked_by_failure\");\n }\n\n summary = buildCronSummary({\n runId,\n status,\n skipReason,\n mode: autopilotCfg.mode,\n latestDigest,\n autopilotResult,\n artifacts,\n notificationSent,\n autopilotCfg,\n });\n\n const validateStartedAt = Date.now();\n const requiredBeforeValidate = REQUIRED_STEPS.filter(\n (s) => s !== \"validate-cron-exit\" && s !== \"notification-policy\" && s !== \"summary-write\",\n );\n const validation = validateMaintenanceExecution(hmExit, hmLog, [...requiredBeforeValidate], true);\n if (validation.maintenanceStatus === \"failed\" || validation.maintenanceStatus === \"partial\") {\n status = \"failed\";\n summary.status = \"failed\";\n markStep(\"validate-cron-exit\", {\n exit: 1,\n status: \"failed\",\n reason: \"validate_cron_exit_failed\",\n durationMs: Date.now() - validateStartedAt,\n });\n logLine(hmLog, `error.validate-cron-exit ${validation.error ?? \"validation_failed\"}`);\n } else {\n markStep(\"validate-cron-exit\", {\n exit: 0,\n status: \"ok\",\n reason: \"ok\",\n durationMs: Date.now() - validateStartedAt,\n });\n }\n\n const notifyStartedAt = Date.now();\n try {\n const shouldNotify = shouldNotifyRun(summary, autopilotCfg);\n if (shouldNotify) {\n const payloadPath = join(artifactDir, `${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-${runToken}.notification.json`);\n const payload = {\n runId: summary.runId,\n status: summary.status,\n counts: summary.counts,\n humanReviewRequired: summary.humanReviewRequired,\n skipReason: summary.skipReason,\n artifacts: summary.artifacts,\n };\n writeFileSync(payloadPath, `${canonicalJson(redactAutopilotValue(payload))}\\n`, \"utf-8\");\n artifacts.notificationJson = payloadPath;\n notificationSent = true;\n summary.notificationSent = true;\n markStep(\"notification-policy\", {\n exit: 0,\n status: \"ok\",\n reason: \"notification_sent\",\n durationMs: Date.now() - notifyStartedAt,\n });\n logLine(hmLog, `run.notification payload=${payloadPath}`);\n } else {\n markStep(\"notification-policy\", {\n exit: 0,\n status: \"skipped\",\n reason: \"notification_not_required\",\n durationMs: Date.now() - notifyStartedAt,\n });\n }\n } catch (err) {\n if (status === \"ok\" || status === \"skipped\") status = \"partial\";\n summary.status = status;\n markStep(\"notification-policy\", {\n exit: 1,\n status: \"failed\",\n reason: \"notification_failed\",\n durationMs: Date.now() - notifyStartedAt,\n });\n logLine(hmLog, `error.notification-policy ${stringifyError(err)}`);\n }\n\n summary.status = status;\n summary.skipReason = status === \"skipped\" ? skipReason : undefined;\n summary.notificationSent = notificationSent;\n\n const summaryStartedAt = Date.now();\n humanSummary = renderCronHumanSummary(summary);\n try {\n writeFileSync(summaryJson, `${canonicalJson(redactAutopilotValue(summary))}\\n`, \"utf-8\");\n writeFileSync(summaryText, `${humanSummary}\\n`, \"utf-8\");\n markStep(\"summary-write\", { exit: 0, status: \"ok\", reason: \"ok\", durationMs: Date.now() - summaryStartedAt });\n } catch (err) {\n status = \"failed\";\n summary.status = \"failed\";\n markStep(\"summary-write\", {\n exit: 1,\n status: \"failed\",\n reason: \"artifact_write_failed\",\n durationMs: Date.now() - summaryStartedAt,\n });\n logLine(hmLog, `error.summary-write ${stringifyError(err)}`);\n }\n } finally {\n if (acquiredLock) releaseAutopilotLock(lockPath, runId);\n }\n\n logLine(hmLog, `run.finish status=${summary.status} skip_reason=${summary.skipReason ?? \"none\"}`);\n if (status === \"ok\" && !skipReason) {\n mkdirSync(dirname(guardPath), { recursive: true });\n writeFileSync(guardPath, `${Date.now()}`, \"utf-8\");\n }\n if (status === \"skipped\") skipRemaining(skipReason ?? \"skipped\");\n\n return { summary, humanSummary, autopilotResult };\n}\n\nfunction resolveOpenclawHome(openclawHome?: string): string {\n if (typeof openclawHome === \"string\" && openclawHome.trim().length > 0) return openclawHome;\n if (typeof process.env.OPENCLAW_HOME === \"string\" && process.env.OPENCLAW_HOME.trim().length > 0) {\n return process.env.OPENCLAW_HOME.trim();\n }\n return join(homedir(), \".openclaw\");\n}\n\n/** Match hybrid-mem cron bash harness: prefer ~/.openclaw/logs/cron-hybrid-mem, fall back to /tmp when not writable. */\nfunction resolveWritableCronHybridMemRoot(openclawHome: string): string {\n const primary = join(openclawHome, \"logs\", \"cron-hybrid-mem\");\n try {\n mkdirSync(primary, { recursive: true });\n const probe = join(primary, `.write-probe-${process.pid}-${Date.now()}`);\n writeFileSync(probe, \"ok\", \"utf-8\");\n unlinkSync(probe);\n return primary;\n } catch {\n const user = process.env.USER || process.env.USERNAME || \"user\";\n const fallback =\n process.platform === \"win32\"\n ? join(tmpdir(), `openclaw-cron-hybrid-mem-${user}`)\n : join(\"/tmp\", `openclaw-cron-hybrid-mem-${user}`);\n mkdirSync(fallback, { recursive: true });\n return fallback;\n }\n}\n\nfunction spinWaitMs(ms: number): void {\n const end = Date.now() + ms;\n while (Date.now() < end) {\n /* tight spin for short lock-acquisition backoff */\n }\n}\n\nfunction ensureFile(path: string): void {\n mkdirSync(dirname(path), { recursive: true });\n if (!existsSync(path)) writeFileSync(path, \"\", \"utf-8\");\n}\n\nfunction appendStepLine(path: string, row: StepRow): void {\n const ts = new Date().toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n writeFileSync(\n path,\n `${ts} step=${row.name} exit=${row.exit} status=${row.status} reason=${row.reason} duration_ms=${row.durationMs}\\n`,\n {\n encoding: \"utf-8\",\n flag: \"a\",\n },\n );\n}\n\nfunction logLine(path: string, line: string): void {\n writeFileSync(path, `${new Date().toISOString()} ${line}\\n`, { encoding: \"utf-8\", flag: \"a\" });\n}\n\nfunction stringifyError(err: unknown): string {\n if (err instanceof Error) return err.stack || err.message;\n return String(err);\n}\n\nfunction findLatestWeeklyPendingDigestArtifact(root: string): PendingDigestAutopilotCronSummary[\"latestDigest\"] {\n if (!existsSync(root)) return { found: false };\n const stack = [root];\n const candidates: Array<{ path: string; mtimeMs: number; success: boolean }> = [];\n while (stack.length > 0) {\n const dir = stack.pop();\n if (!dir) continue;\n for (const entry of safeReadDir(dir)) {\n const fullPath = join(dir, entry);\n let st: ReturnType<typeof statSync>;\n try {\n st = statSync(fullPath);\n } catch {\n continue;\n }\n if (st.isDirectory()) {\n stack.push(fullPath);\n continue;\n }\n if (!entry.startsWith(`${PENDING_DIGEST_JOB}-`) || !entry.endsWith(\".exit.txt\")) continue;\n if (entry.startsWith(`${PENDING_DIGEST_AUTOPILOT_CRON_JOB}-`)) continue;\n const content = readSafe(fullPath);\n const success =\n /\\bstep=digest-pending\\b.*\\bexit=0\\b/.test(content) || /\\bdigest-pending\\b.*\\bexit=0\\b/.test(content);\n candidates.push({ path: fullPath, mtimeMs: st.mtimeMs, success });\n }\n }\n if (candidates.length === 0) return { found: false };\n candidates.sort((a, b) => b.mtimeMs - a.mtimeMs);\n const newest = candidates[0];\n if (!newest) return { found: false };\n if (newest.success) {\n return {\n found: true,\n path: newest.path,\n timestamp: new Date(newest.mtimeMs).toISOString(),\n status: \"success\",\n };\n }\n return {\n found: false,\n path: newest.path,\n timestamp: new Date(newest.mtimeMs).toISOString(),\n status: \"failed\",\n };\n}\n\nfunction safeReadDir(path: string): string[] {\n try {\n return readdirSync(path);\n } catch {\n return [];\n }\n}\n\nfunction readSafe(path: string): string {\n try {\n return readFileSync(path, \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\nfunction buildCronSummary(input: {\n runId: string;\n mode: \"dry-run\" | \"apply\";\n status: CronStatus;\n skipReason?: string;\n latestDigest: PendingDigestAutopilotCronSummary[\"latestDigest\"];\n autopilotResult?: PendingDigestAutopilotResult;\n notificationSent: boolean;\n artifacts: PendingDigestAutopilotCronArtifacts;\n autopilotCfg: HybridMemoryConfig[\"digest\"][\"autopilot\"];\n}): PendingDigestAutopilotCronSummary {\n return {\n runId: input.runId,\n mode: input.mode,\n status: input.status,\n skipReason: input.skipReason,\n latestDigest: input.latestDigest,\n policies: {\n persona: input.autopilotCfg.personaPolicy,\n procedure: input.autopilotCfg.procedurePolicy,\n verified: input.autopilotCfg.verifiedPolicy,\n tool: input.autopilotCfg.toolPolicy,\n crystallization: input.autopilotCfg.crystallizationPolicy,\n },\n counts: {\n inspected: input.autopilotResult?.counts.inspected ?? 0,\n applied: input.autopilotResult?.counts.applied ?? 0,\n deferredForHuman: input.autopilotResult?.counts.deferred ?? 0,\n rejected: input.autopilotResult?.counts.rejected ?? 0,\n failed: input.autopilotResult?.counts.failedValidation ?? 0,\n skipped: input.autopilotResult?.counts.skipped ?? 0,\n },\n humanReviewRequired: (input.autopilotResult?.counts.humanReviewRequired ?? 0) > 0,\n notificationSent: input.notificationSent,\n artifacts: input.artifacts,\n };\n}\n\nfunction renderCronHumanSummary(summary: PendingDigestAutopilotCronSummary): string {\n return [\n `Pending digest autopilot cron ${summary.runId}`,\n `Status: ${summary.status}${summary.skipReason ? ` (${summary.skipReason})` : \"\"}`,\n `Mode: ${summary.mode}`,\n `Latest digest: ${summary.latestDigest.found ? `${summary.latestDigest.path ?? \"found\"} (${summary.latestDigest.timestamp ?? \"unknown\"})` : \"not found\"}`,\n `Counts: inspected=${summary.counts.inspected}, applied=${summary.counts.applied}, deferredForHuman=${summary.counts.deferredForHuman}, rejected=${summary.counts.rejected}, failed=${summary.counts.failed}, skipped=${summary.counts.skipped}`,\n `Human review required: ${summary.humanReviewRequired ? \"yes\" : \"no\"}`,\n `Artifacts: HM_LOG=${summary.artifacts.hmLog}, HM_EXIT=${summary.artifacts.hmExit}, summaryJson=${summary.artifacts.summaryJson}`,\n summary.notificationSent ? \"Notification payload generated.\" : \"Notification not required by policy.\",\n ].join(\"\\n\");\n}\n\nfunction shouldNotifyRun(\n summary: PendingDigestAutopilotCronSummary,\n cfg: HybridMemoryConfig[\"digest\"][\"autopilot\"],\n): boolean {\n if (summary.status === \"failed\") return cfg.notifyOnFailure;\n if (summary.status === \"partial\") return cfg.notifyOnFailure;\n if (summary.humanReviewRequired) return cfg.notifyOnHumanReviewRequired;\n if (summary.mode === \"apply\" && summary.counts.applied > 0) return cfg.notifyOnApplyActions;\n if (summary.mode === \"dry-run\" && summary.counts.inspected > 0 && summary.counts.applied === 0) {\n return cfg.notifyOnDryRunActions;\n }\n if (summary.counts.inspected === 0 && summary.counts.applied === 0) return cfg.notifyOnNoop;\n return false;\n}\n\nfunction tryAcquireAutopilotLock(\n lockPath: string,\n runId: string,\n ttlMinutes: number,\n nowMs: number,\n): { acquired: boolean; reason: \"lock_already_held\" | \"lock_stale_recovered\" | \"lock_acquired\" } {\n mkdirSync(dirname(lockPath), { recursive: true });\n const expiresAt = nowMs + ttlMinutes * 60 * 1000;\n const payload = { runId, acquiredAt: nowMs, expiresAt };\n const tryWriteExclusive = (): boolean => {\n try {\n writeFileSync(lockPath, `${canonicalJson(payload)}\\n`, { encoding: \"utf-8\", flag: \"wx\" });\n return true;\n } catch {\n return false;\n }\n };\n\n const recoverStaleOrCorruptLock = (): { acquired: boolean; reason: \"lock_stale_recovered\" | \"lock_already_held\" } => {\n for (let attempt = 0; attempt < 4; attempt++) {\n try {\n const snapshot = readSafe(lockPath);\n const existing = parseLock(snapshot);\n if (existing && existing.expiresAt > nowMs) return { acquired: false, reason: \"lock_already_held\" };\n if (existing && existing.expiresAt <= nowMs) {\n rmSync(lockPath, { force: true });\n } else if (!existing) {\n rmSync(lockPath, { force: true });\n }\n spinWaitMs(2 + attempt * 5);\n if (tryWriteExclusive()) return { acquired: true, reason: \"lock_stale_recovered\" };\n } catch {\n spinWaitMs(2 + attempt * 5);\n }\n }\n return { acquired: false, reason: \"lock_already_held\" };\n };\n\n try {\n if (tryWriteExclusive()) return { acquired: true, reason: \"lock_acquired\" };\n const existing = parseLock(readSafe(lockPath));\n if (!existing) return recoverStaleOrCorruptLock();\n if (existing.expiresAt > nowMs) return { acquired: false, reason: \"lock_already_held\" };\n return recoverStaleOrCorruptLock();\n } catch {\n return { acquired: false, reason: \"lock_already_held\" };\n }\n}\n\nfunction releaseAutopilotLock(lockPath: string, runId: string): void {\n const existing = parseLock(readSafe(lockPath));\n if (!existing || existing.runId !== runId) return;\n rmSync(lockPath, { force: true });\n}\n\nfunction parseLock(raw: string): { runId: string; expiresAt: number } | null {\n try {\n const parsed = JSON.parse(raw) as { runId?: unknown; expiresAt?: unknown };\n if (typeof parsed.runId !== \"string\") return null;\n if (typeof parsed.expiresAt !== \"number\" || !Number.isFinite(parsed.expiresAt)) return null;\n return { runId: parsed.runId, expiresAt: parsed.expiresAt };\n } catch {\n return null;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pending-digest-autopilot.js","names":[],"sources":["../../services/pending-digest-autopilot.ts"],"sourcesContent":["/**\n * Parent pending-digest autopilot orchestration (#1326).\n *\n * This service is intentionally a read-only/classification skeleton. It consumes\n * the shared pending-autopilot foundation (#1334), builds live queue inventory\n * from the same sources as `digest pending`, and delegates decisions to queue\n * adapters. Child issues #1327/#1328/#1329 own deep persona/procedure/verified\n * policy and mutation semantics; this parent must not duplicate them.\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\nimport { CrystallizationStore } from \"../backends/crystallization-store.js\";\nimport type { ProcedureTriageReport, ProcedureTriageRow } from \"../backends/facts-db/procedures.js\";\nimport { ProposalsDB } from \"../backends/proposals-db.js\";\nimport { type ToolProposal, ToolProposalStore } from \"../backends/tool-proposal-store.js\";\nimport type { HybridMemoryConfig } from \"../config.js\";\nimport {\n type AutopilotMode,\n PENDING_QUEUES,\n type PendingAutopilotRunSummary,\n PendingAutopilotStore,\n canonicalJson,\n redactAutopilotValue,\n type PendingDecision,\n type PendingDecisionContext,\n type PendingItem,\n type PendingQueue,\n type PendingQueueAdapter,\n computePendingInputHash,\n createPendingAutopilotRunId,\n createStableRunSummary,\n shouldAdvancePendingCursor,\n} from \"./pending-autopilot/index.js\";\nimport {\n createPersonaProposalTriageAdapter,\n runPersonaProposalTriage,\n type PersonaProposalDecisionView,\n type PersonaProposalPendingItem,\n} from \"./persona-proposal-triage.js\";\nimport { buildPendingReviewDigestReport, pendingStorePaths } from \"./pending-review-digest.js\";\n\nexport const PENDING_DIGEST_AUTOPILOT_POLICY_VERSION = \"parent-skeleton-v1\";\n\nexport type PersonaAutopilotPolicy = \"disabled\" | \"report-only\" | \"cautious\" | \"apply-safe\";\nexport type ProcedureAutopilotPolicy = \"disabled\" | \"report-only\" | \"dry-run-skills\" | \"auto-safe\";\nexport type VerifiedAutopilotPolicy = \"disabled\" | \"report-only\" | \"classify\" | \"apply-obvious\";\nexport type ReadOnlyClassifyPolicy = \"disabled\" | \"report-only\" | \"classify\";\nexport type PendingDigestAutopilotPolicy =\n | PersonaAutopilotPolicy\n | ProcedureAutopilotPolicy\n | VerifiedAutopilotPolicy\n | ReadOnlyClassifyPolicy;\n\nexport interface PendingDigestAutopilotPolicies {\n persona: PersonaAutopilotPolicy;\n procedures: ProcedureAutopilotPolicy;\n verified: VerifiedAutopilotPolicy;\n tools: ReadOnlyClassifyPolicy;\n crystallization: ReadOnlyClassifyPolicy;\n}\n\nexport interface PendingDigestAutopilotMaxima {\n persona: number;\n procedures: number;\n verified: number;\n tools: number;\n crystallization: number;\n}\n\nexport interface PendingDigestAutopilotOptions {\n cfg: HybridMemoryConfig;\n factsDb: PendingDigestFactsDb;\n workspace?: string;\n mode?: AutopilotMode;\n policies?: Partial<PendingDigestAutopilotPolicies>;\n max?: Partial<PendingDigestAutopilotMaxima>;\n runId?: string;\n jobId?: string;\n actorId?: string;\n now?: Date;\n stateDbPath?: string;\n adapters?: Partial<Record<PendingQueue, PendingQueueAdapter>>;\n}\n\nexport interface PendingDigestFactsDb {\n proceduresCount(): number;\n proceduresValidatedCount(): number;\n proceduresPromotedCount(): number;\n countVerifiedFacts(): number;\n proceduresValidatedSince?(sinceSec: number): number;\n getRawDb?(): DatabaseSync | undefined | null;\n triageProcedures?(options?: {\n status?: \"validated\" | \"all\";\n notPromoted?: boolean;\n limit?: number;\n validationThreshold?: number;\n }): ProcedureTriageReport;\n}\n\nexport interface PendingDigestAutopilotResult {\n schemaVersion: 1;\n runId: string;\n mode: AutopilotMode;\n policyVersion: string;\n applyBehavior: \"child-guarded-persona-apply\" | \"record-decisions-only\" | \"non-mutating-dry-run\";\n policies: PendingDigestAutopilotPolicies;\n max: PendingDigestAutopilotMaxima;\n counts: {\n inspected: number;\n classified: number;\n applied: number;\n deferred: number;\n rejected: number;\n failedValidation: number;\n skipped: number;\n humanReviewRequired: number;\n };\n queues: Record<PendingQueue, PendingDigestQueueResult>;\n foundationSummary: PendingAutopilotRunSummary;\n digestContext: ReturnType<typeof buildPendingReviewDigestReport>[\"pendingReview\"];\n humanSummary: string;\n}\n\nexport interface PendingDigestQueueResult {\n policy: PendingDigestAutopilotPolicy;\n inspected: number;\n skipped: boolean;\n skipReason?: \"queue-disabled-by-policy\" | \"adapter-unavailable\" | \"inventory-failed\";\n decisions: PendingDecision[];\n}\n\ntype QueuePayload = Record<string, unknown>;\ntype QueueItem = PendingItem<QueuePayload>;\n\nconst DEFAULT_POLICIES: PendingDigestAutopilotPolicies = {\n persona: \"cautious\",\n procedures: \"auto-safe\",\n verified: \"classify\",\n tools: \"classify\",\n crystallization: \"classify\",\n};\n\nconst DEFAULT_MAX: PendingDigestAutopilotMaxima = {\n persona: 20,\n procedures: 50,\n verified: 100,\n tools: 50,\n crystallization: 50,\n};\n\nexport function normalizePendingDigestAutopilotOptions(input: {\n mode?: AutopilotMode;\n policies?: Partial<PendingDigestAutopilotPolicies>;\n max?: Partial<PendingDigestAutopilotMaxima>;\n}): {\n mode: AutopilotMode;\n policies: PendingDigestAutopilotPolicies;\n max: PendingDigestAutopilotMaxima;\n} {\n const mode = input.mode ?? \"dry-run\";\n if (mode !== \"dry-run\" && mode !== \"apply\") throw new Error(`Unsupported pending autopilot mode: ${mode}`);\n const policies: PendingDigestAutopilotPolicies = { ...DEFAULT_POLICIES };\n const policyInput = input.policies ?? {};\n if (policyInput.persona !== undefined) policies.persona = policyInput.persona;\n if (policyInput.procedures !== undefined) policies.procedures = policyInput.procedures;\n if (policyInput.verified !== undefined) policies.verified = policyInput.verified;\n if (policyInput.tools !== undefined) policies.tools = policyInput.tools;\n if (policyInput.crystallization !== undefined) policies.crystallization = policyInput.crystallization;\n validatePolicies(policies);\n const max: PendingDigestAutopilotMaxima = { ...DEFAULT_MAX };\n for (const [queue, value] of Object.entries(input.max ?? {})) {\n if (value !== undefined) max[queue as PendingQueue] = value;\n }\n for (const [queue, value] of Object.entries(max)) {\n if (!Number.isFinite(value) || value < 0) throw new Error(`Invalid max for ${queue}: ${value}`);\n max[queue as PendingQueue] = Math.floor(value);\n }\n return { mode, policies, max };\n}\n\nexport async function runPendingDigestAutopilot(\n opts: PendingDigestAutopilotOptions,\n): Promise<PendingDigestAutopilotResult> {\n const normalized = normalizePendingDigestAutopilotOptions(opts);\n const runId = opts.runId ?? createPendingAutopilotRunId();\n const startedAt = Math.floor((opts.now ?? new Date()).getTime() / 1000);\n const actor = {\n type: \"agent\" as const,\n id: opts.actorId ?? \"pending-digest-autopilot\",\n };\n if (normalized.mode === \"apply\" && !opts.stateDbPath) {\n throw new Error(\"--apply requires --state-db so parent classification decisions are recorded durably\");\n }\n const digest = buildPendingReviewDigestReport({\n cfg: opts.cfg,\n factsDb: opts.factsDb,\n now: opts.now,\n });\n\n let store: PendingAutopilotStore | undefined;\n let adapters: Partial<Record<PendingQueue, PendingQueueAdapter>> | null = null;\n try {\n adapters = createPendingDigestAdapters(opts);\n store = normalized.mode === \"apply\" ? new PendingAutopilotStore(opts.stateDbPath as string) : undefined;\n const decisions: PendingDecision[] = [];\n const queues = Object.fromEntries(\n PENDING_QUEUES.map((queue) => [\n queue,\n {\n policy: normalized.policies[queue],\n inspected: 0,\n skipped: false,\n decisions: [] as PendingDecision[],\n },\n ]),\n ) as Record<PendingQueue, PendingDigestQueueResult>;\n\n const inputHash = computePendingInputHash({\n command: \"digest-autopilot\",\n policies: normalized.policies,\n max: normalized.max,\n digest: digest.pendingReview,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n });\n store?.createRun({\n runId,\n mode: normalized.mode,\n policy: \"parent\",\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n inputHash,\n queues: [...PENDING_QUEUES],\n startedAt,\n });\n\n for (const queue of PENDING_QUEUES) {\n const policy = normalized.policies[queue];\n const adapter = adapters[queue];\n const queueResult = queues[queue];\n if (policy === \"disabled\") {\n const decision = makeSkippedDecision({\n queue,\n policy,\n mode: normalized.mode,\n runId,\n jobId: opts.jobId,\n actor,\n });\n decisions.push(decision);\n queueResult.decisions.push(decision);\n queueResult.inspected = 0;\n queueResult.skipped = true;\n queueResult.skipReason = \"queue-disabled-by-policy\";\n store?.recordDecision(decision);\n continue;\n }\n if (!adapter) {\n const decision = makeSkippedDecision({\n queue,\n policy,\n mode: normalized.mode,\n runId,\n jobId: opts.jobId,\n actor,\n });\n decisions.push(decision);\n queueResult.decisions.push(decision);\n queueResult.skipped = true;\n queueResult.skipReason = \"adapter-unavailable\";\n store?.recordDecision(decision);\n continue;\n }\n\n try {\n const listed = await adapter.listPending(store?.getCursor(queue, policy) ?? null);\n const items = listed.slice(0, normalized.max[queue]);\n queueResult.inspected = items.length;\n let cursorAdvanceCandidate: { decision: PendingDecision; cursor: string } | null = null;\n let cursorAdvanceBlocked = false;\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const context: PendingDecisionContext = {\n runId,\n jobId: opts.jobId,\n mode: normalized.mode,\n policy,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n inputHash: item.inputHash,\n actor,\n };\n let decision = await adapter.decide(item, context);\n if (queue === \"persona\" && normalized.mode === \"apply\" && policy !== \"report-only\") {\n if (hasPersonaParentApplyMetadata(adapter)) {\n const applied = await runPersonaProposalTriage({\n proposalsDb: adapter.proposalsDb,\n cfg: opts.cfg,\n workspace: opts.workspace,\n stateDbPath: opts.stateDbPath,\n mode: \"apply\",\n policy: policy as \"cautious\" | \"apply-safe\",\n max: 1,\n proposalId: item.id,\n runId,\n jobId: opts.jobId,\n actor,\n now: opts.now,\n runLifecycle: \"embedded\",\n store,\n });\n const childDecision = applied.decisions.find((d) => d.proposalId === item.id);\n const latestDecision = childDecision\n ? ((store?.listDecisions({ queue: \"persona\", itemId: item.id }).at(-1) as\n | PendingDecision\n | undefined) ?? decisionFromPersonaView(decision, childDecision))\n : makeUnprocessedPersonaDecision(decision);\n decision = latestDecision;\n if (!childDecision) {\n store?.recordDecision(decision);\n }\n } else {\n decision = makeUnsupportedPersonaApplyAdapterDecision(decision);\n store?.recordDecision(decision);\n }\n } else {\n store?.recordDecision(decision);\n }\n decisions.push(decision);\n queueResult.decisions.push(decision);\n const itemCursor = item.visibleAfterCursor ?? item.id;\n if (shouldAdvancePendingCursor(decision)) {\n if (!cursorAdvanceBlocked) {\n cursorAdvanceCandidate = { decision, cursor: itemCursor };\n }\n } else {\n cursorAdvanceBlocked = true;\n }\n }\n if (policy !== \"report-only\" && cursorAdvanceCandidate !== null && items.length > 0) {\n store?.advanceCursorIfSafe(cursorAdvanceCandidate.decision, cursorAdvanceCandidate.cursor);\n }\n } catch (err) {\n queueResult.inspected = queueResult.decisions.length;\n const decision = makeFailureDecision({\n queue,\n policy,\n mode: normalized.mode,\n runId,\n jobId: opts.jobId,\n actor,\n error: err,\n });\n decisions.push(decision);\n queueResult.decisions.push(decision);\n queueResult.skipped = true;\n queueResult.skipReason = \"inventory-failed\";\n try {\n store?.recordDecision(decision);\n } catch {\n // Best-effort record for inventory failure; do not cascade store errors.\n }\n }\n }\n\n const foundationSummary = createStableRunSummary({\n runId,\n mode: normalized.mode,\n policy: \"parent\",\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n queues: [...PENDING_QUEUES],\n startedAt,\n finishedAt: Math.floor((opts.now ?? new Date()).getTime() / 1000),\n decisions,\n });\n store?.finishRun(runId, foundationSummary);\n\n const result: PendingDigestAutopilotResult = {\n schemaVersion: 1,\n runId,\n mode: normalized.mode,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n applyBehavior: normalized.mode === \"apply\" ? \"child-guarded-persona-apply\" : \"non-mutating-dry-run\",\n policies: normalized.policies,\n max: normalized.max,\n counts: summarizeCounts(decisions),\n queues,\n foundationSummary,\n digestContext: digest.pendingReview,\n humanSummary: \"\",\n };\n result.humanSummary = renderPendingDigestAutopilotHumanSummary(result);\n return result;\n } finally {\n for (const adapter of Object.values(adapters ?? {})) {\n (adapter as { close?: () => void }).close?.();\n }\n store?.close();\n }\n}\n\nexport function renderPendingDigestAutopilotHumanSummary(result: PendingDigestAutopilotResult): string {\n const lines = [\n `Pending digest autopilot ${result.runId} (${result.mode})`,\n `Apply behavior: ${result.applyBehavior}. Persona apply-mode decisions route through the guarded child adapter; other queues remain read-only parent classifications.`,\n `Inspected ${result.counts.inspected}; classified ${result.counts.classified}; deferred ${result.counts.deferred}; skipped ${result.counts.skipped}; failed validation ${result.counts.failedValidation}.`,\n \"Queues:\",\n ];\n for (const queue of PENDING_QUEUES) {\n const q = result.queues[queue];\n const human = q.decisions.filter((d) => d.humanReviewRequired).length;\n const suffix = q.skipped ? ` skipped (${q.skipReason ?? \"unknown\"})` : ` ${q.inspected} inspected`;\n lines.push(`- ${queue}: policy=${q.policy};${suffix}; humanReview=${human}`);\n }\n if (result.counts.humanReviewRequired > 0) {\n lines.push(\n \"Next: review deferred human-review items; child adapters #1327/#1328/#1329 own queue-specific apply gates.\",\n );\n } else {\n lines.push(\n \"Next: no parent-applied non-persona queue mutations. Use child adapters for queue-specific review/apply when implemented.\",\n );\n }\n return lines.join(\"\\n\");\n}\n\nexport function createDefaultPendingDigestAdapters(\n opts: Pick<PendingDigestAutopilotOptions, \"cfg\" | \"factsDb\" | \"workspace\">,\n): Record<PendingQueue, PendingQueueAdapter> {\n return createPendingDigestAdapters(opts) as Record<PendingQueue, PendingQueueAdapter>;\n}\n\nfunction createPendingDigestAdapters(\n opts: Pick<PendingDigestAutopilotOptions, \"cfg\" | \"factsDb\" | \"workspace\" | \"adapters\">,\n): Partial<Record<PendingQueue, PendingQueueAdapter>> {\n const overrides = opts.adapters ?? {};\n const paths = pendingStorePaths(opts.cfg.sqlitePath);\n return {\n persona:\n overrides.persona ?? createPersonaProposalTriageAdapterWithCloseable(paths.proposals, opts.cfg, opts.workspace),\n procedures: overrides.procedures ?? createProcedureReadOnlyAdapter(opts.factsDb),\n verified: overrides.verified ?? createVerifiedReadOnlyAdapter(opts.factsDb),\n tools: overrides.tools ?? createToolProposalReadOnlyAdapter(paths.toolProposals),\n crystallization: overrides.crystallization ?? createCrystallizationReadOnlyAdapter(paths.crystallization),\n };\n}\n\ntype PersonaParentAdapter = PendingQueueAdapter<QueueItem> & { proposalsDb: ProposalsDB; close?: () => void };\n\nfunction hasPersonaParentApplyMetadata(adapter: PendingQueueAdapter): adapter is PersonaParentAdapter {\n return (adapter as { proposalsDb?: unknown }).proposalsDb instanceof ProposalsDB;\n}\n\nfunction createPersonaProposalTriageAdapterWithCloseable(\n dbPath: string,\n cfg: HybridMemoryConfig,\n workspace?: string,\n): PersonaParentAdapter {\n const proposalsDb = new ProposalsDB(dbPath);\n return {\n queue: \"persona\",\n proposalsDb,\n listPending: (cursor) => {\n if (!cfg.personaProposals.enabled) return [];\n const adapter = createPersonaProposalTriageAdapter({ proposalsDb, cfg, workspace });\n return adapter.listPending(cursor);\n },\n decide: (item, context) => {\n const adapter = createPersonaProposalTriageAdapter({\n proposalsDb,\n cfg,\n workspace,\n allProposals: proposalsDb.list(),\n });\n return adapter.decide(item as PersonaProposalPendingItem, context);\n },\n close: () => proposalsDb.close(),\n };\n}\n\nfunction makeUnsupportedPersonaApplyAdapterDecision(base: PendingDecision): PendingDecision {\n const summaryBody =\n \"Persona parent apply mode requires the built-in persona adapter metadata for guarded child triage; custom adapter output was left unmutated and the cursor will not advance.\";\n return {\n ...base,\n action: \"failed-validation\",\n reasonCode: \"capability-not-allowed\",\n actionClass: \"observe\",\n capabilityClass: \"read-only\",\n humanReviewRequired: true,\n summary: {\n ...(base.summary ?? {}),\n body: summaryBody,\n },\n audit: {\n ...(base.audit ?? {\n queue: base.queue,\n itemId: base.itemId,\n inputHash: base.inputHash,\n policy: base.policy,\n policyVersion: base.policyVersion,\n action: base.action,\n reasonCode: base.reasonCode,\n capabilityClass: base.capabilityClass,\n humanReviewRequired: base.humanReviewRequired,\n evidence: base.evidence,\n actor: base.actor,\n runId: base.runId,\n jobId: base.jobId,\n }),\n action: \"failed-validation\",\n reasonCode: \"capability-not-allowed\",\n capabilityClass: \"read-only\",\n humanReviewRequired: true,\n },\n };\n}\n\nfunction makeUnprocessedPersonaDecision(base: PendingDecision): PendingDecision {\n return {\n ...base,\n action: \"failed-validation\",\n reasonCode: \"invalid-item\",\n actionClass: \"observe\",\n capabilityClass: \"read-only\",\n humanReviewRequired: true,\n summary: {\n ...(base.summary ?? {}),\n body: \"Targeted persona child triage did not process this proposal; parent will not advance cursor or record fallback mutation.\",\n },\n audit: {\n ...(base.audit ?? {\n queue: base.queue,\n itemId: base.itemId,\n inputHash: base.inputHash,\n policy: base.policy,\n policyVersion: base.policyVersion,\n action: base.action,\n reasonCode: base.reasonCode,\n capabilityClass: base.capabilityClass,\n humanReviewRequired: base.humanReviewRequired,\n evidence: base.evidence,\n actor: base.actor,\n runId: base.runId,\n jobId: base.jobId,\n }),\n action: \"failed-validation\",\n reasonCode: \"invalid-item\",\n capabilityClass: \"read-only\",\n humanReviewRequired: true,\n },\n };\n}\n\nfunction decisionFromPersonaView(base: PendingDecision, view: PersonaProposalDecisionView): PendingDecision {\n const actionClass = deriveActionClass(view.action);\n return {\n ...base,\n action: view.action,\n reasonCode: view.reason,\n actionClass,\n capabilityClass: view.capability,\n confidence: view.confidence,\n humanReviewRequired: view.humanReviewRequired,\n summary: { ...(base.summary ?? {}), body: view.diffSummary },\n audit: base.audit\n ? {\n ...base.audit,\n action: view.action,\n reasonCode: view.reason,\n capabilityClass: view.capability,\n humanReviewRequired: view.humanReviewRequired,\n }\n : undefined,\n };\n}\n\nfunction deriveActionClass(action: PendingDecision[\"action\"]): PendingDecision[\"actionClass\"] {\n if (action === \"applied\") return \"low-risk-apply\";\n if (action === \"rejected\") return \"state-transition\";\n if (action === \"deferred-for-human\") return \"record-review\";\n if (action === \"failed-validation\") return \"observe\";\n if (action === \"reported\") return \"observe\";\n if (action === \"classified\") return \"preview\";\n return \"observe\";\n}\n\nexport function createProcedureReadOnlyAdapter(factsDb: PendingDigestFactsDb): PendingQueueAdapter<QueueItem> {\n return {\n queue: \"procedures\",\n listPending: () => {\n if (!factsDb.triageProcedures) return [];\n const report = factsDb.triageProcedures({\n status: \"validated\",\n notPromoted: true,\n limit: 10_000,\n });\n return report.rows.map(procedureRowToItem);\n },\n decide: decideReadOnlyItem,\n };\n}\n\nexport function createVerifiedReadOnlyAdapter(factsDb: PendingDigestFactsDb): PendingQueueAdapter<QueueItem> {\n return {\n queue: \"verified\",\n listPending: () => {\n const count = Math.max(0, factsDb.countVerifiedFacts());\n return Array.from({ length: count }, (_, i) => verifiedPlaceholderToItem(i + 1));\n },\n decide: decideReadOnlyItem,\n };\n}\n\nexport function createToolProposalReadOnlyAdapter(dbPath: string): PendingQueueAdapter<QueueItem> {\n return {\n queue: \"tools\",\n listPending: () =>\n withCloseable(\n () => new ToolProposalStore(dbPath),\n (store) => store.list({ status: \"proposed\" }).map(toolProposalToItem),\n ),\n decide: decideReadOnlyItem,\n };\n}\n\nexport function createCrystallizationReadOnlyAdapter(dbPath: string): PendingQueueAdapter<QueueItem> {\n return {\n queue: \"crystallization\",\n listPending: () =>\n withCloseable(\n () => new CrystallizationStore(dbPath),\n (store) => store.list({ status: \"pending\" }).map(crystallizationProposalToItem),\n ),\n decide: decideReadOnlyItem,\n };\n}\n\nexport function decideReadOnlyItem(item: QueueItem, context: PendingDecisionContext): PendingDecision {\n if (context.policy === \"disabled\") {\n return makeSkippedDecision({\n queue: item.queue,\n policy: context.policy,\n mode: context.mode,\n runId: context.runId,\n jobId: context.jobId,\n actor: context.actor,\n });\n }\n const reportOnly = context.policy === \"report-only\";\n const requiresHuman = item.requiresHumanReview === true || reportOnly;\n return {\n queue: item.queue,\n itemId: item.id,\n inputHash: item.inputHash,\n policy: context.policy,\n policyVersion: context.policyVersion,\n mode: context.mode,\n action: reportOnly ? \"reported\" : requiresHuman ? \"deferred-for-human\" : \"classified\",\n reasonCode: reportOnly\n ? \"policy-denied\"\n : requiresHuman\n ? \"human-review-required\"\n : context.mode === \"dry-run\"\n ? \"dry-run\"\n : \"policy-threshold-not-met\",\n actionClass: reportOnly ? \"observe\" : \"preview\",\n capabilityClass: context.mode === \"dry-run\" ? \"dry-run\" : \"read-only\",\n confidence: typeof item.payload.confidence === \"number\" ? item.payload.confidence : 0.5,\n humanReviewRequired: requiresHuman,\n evidence: [\n {\n type: \"pending-item\",\n id: item.id,\n summary: String(item.payload.title ?? item.id),\n },\n ],\n actor: context.actor,\n runId: context.runId,\n jobId: context.jobId,\n summary: {\n title: String(item.payload.title ?? item.id),\n body: String(item.payload.summary ?? \"read-only pending digest classification\"),\n metadata: {\n queue: item.queue,\n source: item.payload.source ?? \"live-inventory\",\n },\n },\n };\n}\n\nfunction procedureRowToItem(p: ProcedureTriageRow): QueueItem {\n const payload = {\n source: \"procedures-triage\",\n title: p.title,\n validatedAt: p.validatedAt,\n promotionBlockReason: p.promotionBlockReason,\n successCount: p.successCount,\n confidence: p.confidence,\n skillPath: p.skillPath,\n summary: `Procedure promotion candidate blocked by ${p.promotionBlockReason}`,\n };\n return makeItem(\"procedures\", p.id, payload, true);\n}\n\nfunction verifiedPlaceholderToItem(index: number): QueueItem {\n const id = `verified-review-${index}`;\n return makeItem(\n \"verified\",\n id,\n {\n source: \"verified-facts-count\",\n title: `Verified fact review placeholder ${index}`,\n summary:\n \"#1329 must define the exact verified-fact review queue. Parent #1326 only reports/classifies the current digest count.\",\n },\n true,\n );\n}\n\nfunction toolProposalToItem(p: ToolProposal): QueueItem {\n return makeItem(\n \"tools\",\n p.id,\n {\n source: \"tool-proposals\",\n title: p.name,\n summary: p.description,\n createdAt: p.createdAt,\n updatedAt: p.updatedAt,\n },\n false,\n );\n}\n\nfunction crystallizationProposalToItem(p: {\n id: string;\n skillName: string;\n createdAt: string;\n updatedAt: string;\n}): QueueItem {\n return makeItem(\n \"crystallization\",\n p.id,\n {\n source: \"crystallization-proposals\",\n title: p.skillName,\n summary: \"Pending crystallization proposal; #1326 parent only classifies/read-only reports.\",\n createdAt: p.createdAt,\n updatedAt: p.updatedAt,\n },\n false,\n );\n}\n\nfunction makeItem(queue: PendingQueue, id: string, payload: QueuePayload, requiresHumanReview: boolean): QueueItem {\n return {\n queue,\n id,\n inputHash: computePendingInputHash({\n queue,\n id,\n payload,\n policy: \"default\",\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n }),\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n capabilityClasses: [\"read-only\"],\n payload,\n visibleAfterCursor: id,\n requiresHumanReview,\n };\n}\n\nfunction makeSkippedDecision(input: {\n queue: PendingQueue;\n policy: string;\n mode: AutopilotMode;\n runId: string;\n jobId?: string;\n actor: PendingDecision[\"actor\"];\n}): PendingDecision {\n const itemId = `${input.queue}:skipped`;\n const inputHash = computePendingInputHash({\n queue: input.queue,\n itemId,\n policy: input.policy,\n reason: \"disabled\",\n });\n return {\n queue: input.queue,\n itemId,\n inputHash,\n policy: input.policy,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n mode: input.mode,\n action: \"skipped-by-policy\",\n reasonCode: \"policy-denied\",\n actionClass: \"observe\",\n capabilityClass: input.mode === \"dry-run\" ? \"dry-run\" : \"read-only\",\n confidence: 1,\n humanReviewRequired: false,\n evidence: [\n {\n type: \"policy\",\n id: input.policy,\n summary: \"queue disabled or unavailable\",\n },\n ],\n actor: input.actor,\n runId: input.runId,\n jobId: input.jobId,\n summary: {\n title: `${input.queue} skipped`,\n body: \"Queue skipped by parent orchestration policy.\",\n },\n };\n}\n\nfunction makeFailureDecision(input: {\n queue: PendingQueue;\n policy: string;\n mode: AutopilotMode;\n runId: string;\n jobId?: string;\n actor: PendingDecision[\"actor\"];\n error: unknown;\n}): PendingDecision {\n const itemId = `${input.queue}:inventory-failed`;\n const message = input.error instanceof Error ? input.error.message : String(input.error);\n return {\n queue: input.queue,\n itemId,\n inputHash: computePendingInputHash({\n queue: input.queue,\n itemId,\n policy: input.policy,\n message,\n }),\n policy: input.policy,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n mode: input.mode,\n action: \"failed-validation\",\n reasonCode: \"schema-validation-failed\",\n actionClass: \"observe\",\n capabilityClass: input.mode === \"dry-run\" ? \"dry-run\" : \"read-only\",\n confidence: 0,\n humanReviewRequired: true,\n evidence: [{ type: \"error\", summary: message }],\n actor: input.actor,\n runId: input.runId,\n jobId: input.jobId,\n summary: { title: `${input.queue} inventory failed`, body: message },\n };\n}\n\nfunction summarizeCounts(decisions: PendingDecision[]): PendingDigestAutopilotResult[\"counts\"] {\n return {\n inspected: decisions.filter((d) => d.action !== \"skipped-by-policy\" && d.action !== \"failed-validation\").length,\n classified: decisions.filter((d) => d.action === \"classified\" || d.action === \"reported\").length,\n applied: decisions.filter((d) => d.action === \"applied\").length,\n deferred: decisions.filter((d) => d.action === \"deferred-for-human\").length,\n rejected: decisions.filter((d) => d.action === \"rejected\").length,\n failedValidation: decisions.filter((d) => d.action === \"failed-validation\").length,\n skipped: decisions.filter((d) => d.action === \"skipped-by-policy\").length,\n humanReviewRequired: decisions.filter((d) => d.humanReviewRequired).length,\n };\n}\n\nfunction validatePolicies(policies: PendingDigestAutopilotPolicies): void {\n const allowed: Record<PendingQueue, readonly string[]> = {\n persona: [\"disabled\", \"report-only\", \"cautious\", \"apply-safe\"],\n procedures: [\"disabled\", \"report-only\", \"dry-run-skills\", \"auto-safe\"],\n verified: [\"disabled\", \"report-only\", \"classify\", \"apply-obvious\"],\n tools: [\"disabled\", \"report-only\", \"classify\"],\n crystallization: [\"disabled\", \"report-only\", \"classify\"],\n };\n for (const queue of PENDING_QUEUES) {\n if (!allowed[queue].includes(policies[queue])) {\n throw new Error(`Unsupported ${queue} pending autopilot policy: ${policies[queue]}`);\n }\n }\n}\n\nfunction withCloseable<TStore extends { close?: () => void }, T>(factory: () => TStore, fn: (store: TStore) => T): T {\n let store: TStore | null = null;\n try {\n store = factory();\n const result = fn(store);\n if (result instanceof Promise) {\n return result.finally(() => {\n try {\n store?.close?.();\n } catch {\n // Best-effort close for inventory readers.\n }\n }) as T;\n }\n try {\n store?.close?.();\n } catch {\n // Best-effort close for inventory readers.\n }\n return result;\n } catch (err) {\n try {\n store?.close?.();\n } catch {\n // Best-effort close for inventory readers.\n }\n throw err;\n }\n}\n\nexport function stablePendingDigestAutopilotJson(result: PendingDigestAutopilotResult): string {\n return `${canonicalJson(redactAutopilotValue(result))}\\n`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pending-digest-autopilot.js","names":[],"sources":["../../services/pending-digest-autopilot.ts"],"sourcesContent":["/**\n * Parent pending-digest autopilot orchestration (#1326).\n *\n * This service is intentionally a read-only/classification skeleton. It consumes\n * the shared pending-autopilot foundation (#1334), builds live queue inventory\n * from the same sources as `digest pending`, and delegates decisions to queue\n * adapters. Child issues #1327/#1328/#1329 own deep persona/procedure/verified\n * policy and mutation semantics; this parent must not duplicate them.\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\nimport { CrystallizationStore } from \"../backends/crystallization-store.js\";\nimport type { ProcedureTriageReport, ProcedureTriageRow } from \"../backends/facts-db/procedures.js\";\nimport { ProposalsDB } from \"../backends/proposals-db.js\";\nimport { type ToolProposal, ToolProposalStore } from \"../backends/tool-proposal-store.js\";\nimport type { HybridMemoryConfig } from \"../config.js\";\nimport {\n type AutopilotMode,\n PENDING_QUEUES,\n type PendingAutopilotRunSummary,\n PendingAutopilotStore,\n canonicalJson,\n redactAutopilotValue,\n type PendingDecision,\n type PendingDecisionContext,\n type PendingItem,\n type PendingQueue,\n type PendingQueueAdapter,\n computePendingInputHash,\n createPendingAutopilotRunId,\n createStableRunSummary,\n shouldAdvancePendingCursor,\n} from \"./pending-autopilot/index.js\";\nimport {\n createPersonaProposalTriageAdapter,\n runPersonaProposalTriage,\n type PersonaProposalDecisionView,\n type PersonaProposalPendingItem,\n} from \"./persona-proposal-triage.js\";\nimport { buildPendingReviewDigestReport, pendingStorePaths } from \"./pending-review-digest.js\";\n\nexport const PENDING_DIGEST_AUTOPILOT_POLICY_VERSION = \"parent-skeleton-v1\";\n\nexport type PersonaAutopilotPolicy = \"disabled\" | \"report-only\" | \"cautious\" | \"apply-safe\";\nexport type ProcedureAutopilotPolicy = \"disabled\" | \"report-only\" | \"dry-run-skills\" | \"auto-safe\";\nexport type VerifiedAutopilotPolicy = \"disabled\" | \"report-only\" | \"classify\" | \"apply-obvious\";\nexport type ReadOnlyClassifyPolicy = \"disabled\" | \"report-only\" | \"classify\";\nexport type PendingDigestAutopilotPolicy =\n | PersonaAutopilotPolicy\n | ProcedureAutopilotPolicy\n | VerifiedAutopilotPolicy\n | ReadOnlyClassifyPolicy;\n\nexport interface PendingDigestAutopilotPolicies {\n persona: PersonaAutopilotPolicy;\n procedures: ProcedureAutopilotPolicy;\n verified: VerifiedAutopilotPolicy;\n tools: ReadOnlyClassifyPolicy;\n crystallization: ReadOnlyClassifyPolicy;\n}\n\nexport interface PendingDigestAutopilotMaxima {\n persona: number;\n procedures: number;\n verified: number;\n tools: number;\n crystallization: number;\n}\n\nexport interface PendingDigestAutopilotOptions {\n cfg: HybridMemoryConfig;\n factsDb: PendingDigestFactsDb;\n workspace?: string;\n mode?: AutopilotMode;\n policies?: Partial<PendingDigestAutopilotPolicies>;\n max?: Partial<PendingDigestAutopilotMaxima>;\n runId?: string;\n jobId?: string;\n actorId?: string;\n now?: Date;\n stateDbPath?: string;\n adapters?: Partial<Record<PendingQueue, PendingQueueAdapter>>;\n}\n\nexport interface PendingDigestFactsDb {\n proceduresCount(): number;\n proceduresValidatedCount(): number;\n proceduresPromotedCount(): number;\n countVerifiedFacts(): number;\n proceduresValidatedSince?(sinceSec: number): number;\n getRawDb?(): DatabaseSync | undefined | null;\n triageProcedures?(options?: {\n status?: \"validated\" | \"all\";\n notPromoted?: boolean;\n limit?: number;\n validationThreshold?: number;\n }): ProcedureTriageReport;\n}\n\nexport interface PendingDigestAutopilotResult {\n schemaVersion: 1;\n runId: string;\n mode: AutopilotMode;\n policyVersion: string;\n applyBehavior: \"child-guarded-persona-apply\" | \"record-decisions-only\" | \"non-mutating-dry-run\";\n policies: PendingDigestAutopilotPolicies;\n max: PendingDigestAutopilotMaxima;\n counts: {\n inspected: number;\n classified: number;\n applied: number;\n deferred: number;\n rejected: number;\n failedValidation: number;\n skipped: number;\n humanReviewRequired: number;\n };\n queues: Record<PendingQueue, PendingDigestQueueResult>;\n foundationSummary: PendingAutopilotRunSummary;\n digestContext: ReturnType<typeof buildPendingReviewDigestReport>[\"pendingReview\"];\n humanSummary: string;\n}\n\nexport interface PendingDigestQueueResult {\n policy: PendingDigestAutopilotPolicy;\n inspected: number;\n skipped: boolean;\n skipReason?: \"queue-disabled-by-policy\" | \"adapter-unavailable\" | \"inventory-failed\";\n decisions: PendingDecision[];\n}\n\ntype QueuePayload = Record<string, unknown>;\ntype QueueItem = PendingItem<QueuePayload>;\n\nconst DEFAULT_POLICIES: PendingDigestAutopilotPolicies = {\n persona: \"cautious\",\n procedures: \"auto-safe\",\n verified: \"classify\",\n tools: \"classify\",\n crystallization: \"classify\",\n};\n\nconst DEFAULT_MAX: PendingDigestAutopilotMaxima = {\n persona: 20,\n procedures: 50,\n verified: 100,\n tools: 50,\n crystallization: 50,\n};\n\nexport function normalizePendingDigestAutopilotOptions(input: {\n mode?: AutopilotMode;\n policies?: Partial<PendingDigestAutopilotPolicies>;\n max?: Partial<PendingDigestAutopilotMaxima>;\n}): {\n mode: AutopilotMode;\n policies: PendingDigestAutopilotPolicies;\n max: PendingDigestAutopilotMaxima;\n} {\n const mode = input.mode ?? \"dry-run\";\n if (mode !== \"dry-run\" && mode !== \"apply\") throw new Error(`Unsupported pending autopilot mode: ${mode}`);\n const policies: PendingDigestAutopilotPolicies = { ...DEFAULT_POLICIES };\n const policyInput = input.policies ?? {};\n if (policyInput.persona !== undefined) policies.persona = policyInput.persona;\n if (policyInput.procedures !== undefined) policies.procedures = policyInput.procedures;\n if (policyInput.verified !== undefined) policies.verified = policyInput.verified;\n if (policyInput.tools !== undefined) policies.tools = policyInput.tools;\n if (policyInput.crystallization !== undefined) policies.crystallization = policyInput.crystallization;\n validatePolicies(policies);\n const max: PendingDigestAutopilotMaxima = { ...DEFAULT_MAX };\n for (const [queue, value] of Object.entries(input.max ?? {})) {\n if (value !== undefined) max[queue as PendingQueue] = value;\n }\n for (const [queue, value] of Object.entries(max)) {\n if (!Number.isFinite(value) || value < 0) throw new Error(`Invalid max for ${queue}: ${value}`);\n max[queue as PendingQueue] = Math.floor(value);\n }\n return { mode, policies, max };\n}\n\nexport async function runPendingDigestAutopilot(\n opts: PendingDigestAutopilotOptions,\n): Promise<PendingDigestAutopilotResult> {\n const normalized = normalizePendingDigestAutopilotOptions(opts);\n const runId = opts.runId ?? createPendingAutopilotRunId();\n const startedAt = Math.floor((opts.now ?? new Date()).getTime() / 1000);\n const actor = {\n type: \"agent\" as const,\n id: opts.actorId ?? \"pending-digest-autopilot\",\n };\n if (normalized.mode === \"apply\" && !opts.stateDbPath) {\n throw new Error(\"--apply requires --state-db so parent classification decisions are recorded durably\");\n }\n const digest = buildPendingReviewDigestReport({\n cfg: opts.cfg,\n factsDb: opts.factsDb,\n now: opts.now,\n });\n\n let store: PendingAutopilotStore | undefined;\n let adapters: Partial<Record<PendingQueue, PendingQueueAdapter>> | null = null;\n try {\n adapters = createPendingDigestAdapters(opts);\n store = normalized.mode === \"apply\" ? new PendingAutopilotStore(opts.stateDbPath as string) : undefined;\n const decisions: PendingDecision[] = [];\n const queues = Object.fromEntries(\n PENDING_QUEUES.map((queue) => [\n queue,\n {\n policy: normalized.policies[queue],\n inspected: 0,\n skipped: false,\n decisions: [] as PendingDecision[],\n },\n ]),\n ) as Record<PendingQueue, PendingDigestQueueResult>;\n\n const inputHash = computePendingInputHash({\n command: \"digest-autopilot\",\n policies: normalized.policies,\n max: normalized.max,\n digest: digest.pendingReview,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n });\n store?.createRun({\n runId,\n mode: normalized.mode,\n policy: \"parent\",\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n inputHash,\n queues: [...PENDING_QUEUES],\n startedAt,\n });\n\n for (const queue of PENDING_QUEUES) {\n const policy = normalized.policies[queue];\n const adapter = adapters[queue];\n const queueResult = queues[queue];\n if (policy === \"disabled\") {\n const decision = makeSkippedDecision({\n queue,\n policy,\n mode: normalized.mode,\n runId,\n jobId: opts.jobId,\n actor,\n });\n decisions.push(decision);\n queueResult.decisions.push(decision);\n queueResult.inspected = 0;\n queueResult.skipped = true;\n queueResult.skipReason = \"queue-disabled-by-policy\";\n store?.recordDecision(decision);\n continue;\n }\n if (!adapter) {\n const decision = makeSkippedDecision({\n queue,\n policy,\n mode: normalized.mode,\n runId,\n jobId: opts.jobId,\n actor,\n });\n decisions.push(decision);\n queueResult.decisions.push(decision);\n queueResult.skipped = true;\n queueResult.skipReason = \"adapter-unavailable\";\n store?.recordDecision(decision);\n continue;\n }\n\n try {\n const listed = await adapter.listPending(store?.getCursor(queue, policy) ?? null);\n const items = listed.slice(0, normalized.max[queue]);\n queueResult.inspected = items.length;\n let cursorAdvanceCandidate: { decision: PendingDecision; cursor: string } | null = null;\n let cursorAdvanceBlocked = false;\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const context: PendingDecisionContext = {\n runId,\n jobId: opts.jobId,\n mode: normalized.mode,\n policy,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n inputHash: item.inputHash,\n actor,\n };\n let decision = await adapter.decide(item, context);\n if (queue === \"persona\" && normalized.mode === \"apply\" && policy !== \"report-only\") {\n if (hasPersonaParentApplyMetadata(adapter)) {\n const applied = await runPersonaProposalTriage({\n proposalsDb: adapter.proposalsDb,\n cfg: opts.cfg,\n workspace: opts.workspace,\n stateDbPath: opts.stateDbPath,\n mode: \"apply\",\n policy: policy as \"cautious\" | \"apply-safe\",\n max: 1,\n proposalId: item.id,\n runId,\n jobId: opts.jobId,\n actor,\n now: opts.now,\n runLifecycle: \"embedded\",\n store,\n });\n const childDecision = applied.decisions.find((d) => d.proposalId === item.id);\n const latestDecision = childDecision\n ? ((store?.listDecisions({ queue: \"persona\", itemId: item.id }).at(-1) as\n | PendingDecision\n | undefined) ?? decisionFromPersonaView(decision, childDecision))\n : makeUnprocessedPersonaDecision(decision);\n decision = latestDecision;\n if (!childDecision) {\n store?.recordDecision(decision);\n }\n } else {\n decision = makeUnsupportedPersonaApplyAdapterDecision(decision);\n store?.recordDecision(decision);\n }\n } else {\n store?.recordDecision(decision);\n }\n decisions.push(decision);\n queueResult.decisions.push(decision);\n const itemCursor = item.visibleAfterCursor ?? item.id;\n if (shouldAdvancePendingCursor(decision)) {\n if (!cursorAdvanceBlocked) {\n cursorAdvanceCandidate = { decision, cursor: itemCursor };\n }\n } else {\n cursorAdvanceBlocked = true;\n }\n }\n if (policy !== \"report-only\" && cursorAdvanceCandidate !== null && items.length > 0) {\n store?.advanceCursorIfSafe(cursorAdvanceCandidate.decision, cursorAdvanceCandidate.cursor);\n }\n } catch (err) {\n queueResult.inspected = queueResult.decisions.length;\n const decision = makeFailureDecision({\n queue,\n policy,\n mode: normalized.mode,\n runId,\n jobId: opts.jobId,\n actor,\n error: err,\n });\n decisions.push(decision);\n queueResult.decisions.push(decision);\n queueResult.skipped = true;\n queueResult.skipReason = \"inventory-failed\";\n try {\n store?.recordDecision(decision);\n } catch {\n // Best-effort record for inventory failure; do not cascade store errors.\n }\n }\n }\n\n const foundationSummary = createStableRunSummary({\n runId,\n mode: normalized.mode,\n policy: \"parent\",\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n queues: [...PENDING_QUEUES],\n startedAt,\n finishedAt: Math.floor((opts.now ?? new Date()).getTime() / 1000),\n decisions,\n });\n store?.finishRun(runId, foundationSummary);\n\n const result: PendingDigestAutopilotResult = {\n schemaVersion: 1,\n runId,\n mode: normalized.mode,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n applyBehavior: normalized.mode === \"apply\" ? \"child-guarded-persona-apply\" : \"non-mutating-dry-run\",\n policies: normalized.policies,\n max: normalized.max,\n counts: summarizeCounts(decisions),\n queues,\n foundationSummary,\n digestContext: digest.pendingReview,\n humanSummary: \"\",\n };\n result.humanSummary = renderPendingDigestAutopilotHumanSummary(result);\n return result;\n } finally {\n for (const adapter of Object.values(adapters ?? {})) {\n (adapter as { close?: () => void }).close?.();\n }\n store?.close();\n }\n}\n\nexport function renderPendingDigestAutopilotHumanSummary(result: PendingDigestAutopilotResult): string {\n const lines = [\n `Pending digest autopilot ${result.runId} (${result.mode})`,\n `Apply behavior: ${result.applyBehavior}. Persona apply-mode decisions route through the guarded child adapter; other queues remain read-only parent classifications.`,\n `Inspected ${result.counts.inspected}; classified ${result.counts.classified}; deferred ${result.counts.deferred}; skipped ${result.counts.skipped}; failed validation ${result.counts.failedValidation}.`,\n \"Queues:\",\n ];\n for (const queue of PENDING_QUEUES) {\n const q = result.queues[queue];\n const human = q.decisions.filter((d) => d.humanReviewRequired).length;\n const suffix = q.skipped ? ` skipped (${q.skipReason ?? \"unknown\"})` : ` ${q.inspected} inspected`;\n lines.push(`- ${queue}: policy=${q.policy};${suffix}; humanReview=${human}`);\n }\n if (result.counts.humanReviewRequired > 0) {\n lines.push(\n \"Next: review deferred human-review items; child adapters #1327/#1328/#1329 own queue-specific apply gates.\",\n );\n } else {\n lines.push(\n \"Next: no parent-applied non-persona queue mutations. Use child adapters for queue-specific review/apply when implemented.\",\n );\n }\n return lines.join(\"\\n\");\n}\n\nexport function createDefaultPendingDigestAdapters(\n opts: Pick<PendingDigestAutopilotOptions, \"cfg\" | \"factsDb\" | \"workspace\">,\n): Record<PendingQueue, PendingQueueAdapter> {\n return createPendingDigestAdapters(opts) as Record<PendingQueue, PendingQueueAdapter>;\n}\n\nfunction createPendingDigestAdapters(\n opts: Pick<PendingDigestAutopilotOptions, \"cfg\" | \"factsDb\" | \"workspace\" | \"adapters\">,\n): Partial<Record<PendingQueue, PendingQueueAdapter>> {\n const overrides = opts.adapters ?? {};\n const paths = pendingStorePaths(opts.cfg.sqlitePath);\n return {\n persona:\n overrides.persona ?? createPersonaProposalTriageAdapterWithCloseable(paths.proposals, opts.cfg, opts.workspace),\n procedures: overrides.procedures ?? createProcedureReadOnlyAdapter(opts.factsDb),\n verified: overrides.verified ?? createVerifiedReadOnlyAdapter(opts.factsDb),\n tools: overrides.tools ?? createToolProposalReadOnlyAdapter(paths.toolProposals),\n crystallization: overrides.crystallization ?? createCrystallizationReadOnlyAdapter(paths.crystallization),\n };\n}\n\ntype PersonaParentAdapter = PendingQueueAdapter<QueueItem> & { proposalsDb: ProposalsDB; close?: () => void };\n\nfunction hasPersonaParentApplyMetadata(adapter: PendingQueueAdapter): adapter is PersonaParentAdapter {\n return (adapter as { proposalsDb?: unknown }).proposalsDb instanceof ProposalsDB;\n}\n\nfunction createPersonaProposalTriageAdapterWithCloseable(\n dbPath: string,\n cfg: HybridMemoryConfig,\n workspace?: string,\n): PersonaParentAdapter {\n const proposalsDb = new ProposalsDB(dbPath);\n return {\n queue: \"persona\",\n proposalsDb,\n listPending: (cursor) => {\n if (!cfg.personaProposals.enabled) return [];\n const adapter = createPersonaProposalTriageAdapter({ proposalsDb, cfg, workspace });\n return adapter.listPending(cursor);\n },\n decide: (item, context) => {\n const adapter = createPersonaProposalTriageAdapter({\n proposalsDb,\n cfg,\n workspace,\n allProposals: proposalsDb.list(),\n });\n return adapter.decide(item as PersonaProposalPendingItem, context);\n },\n close: () => proposalsDb.close(),\n };\n}\n\nfunction makeUnsupportedPersonaApplyAdapterDecision(base: PendingDecision): PendingDecision {\n const summaryBody =\n \"Persona parent apply mode requires the built-in persona adapter metadata for guarded child triage; custom adapter output was left unmutated and the cursor will not advance.\";\n return {\n ...base,\n action: \"failed-validation\",\n reasonCode: \"capability-not-allowed\",\n actionClass: \"observe\",\n capabilityClass: \"read-only\",\n humanReviewRequired: true,\n summary: {\n ...(base.summary ?? {}),\n body: summaryBody,\n },\n audit: {\n ...(base.audit ?? {\n queue: base.queue,\n itemId: base.itemId,\n inputHash: base.inputHash,\n policy: base.policy,\n policyVersion: base.policyVersion,\n action: base.action,\n reasonCode: base.reasonCode,\n capabilityClass: base.capabilityClass,\n humanReviewRequired: base.humanReviewRequired,\n evidence: base.evidence,\n actor: base.actor,\n runId: base.runId,\n jobId: base.jobId,\n }),\n action: \"failed-validation\",\n reasonCode: \"capability-not-allowed\",\n capabilityClass: \"read-only\",\n humanReviewRequired: true,\n },\n };\n}\n\nfunction makeUnprocessedPersonaDecision(base: PendingDecision): PendingDecision {\n return {\n ...base,\n action: \"failed-validation\",\n reasonCode: \"invalid-item\",\n actionClass: \"observe\",\n capabilityClass: \"read-only\",\n humanReviewRequired: true,\n summary: {\n ...(base.summary ?? {}),\n body: \"Targeted persona child triage did not process this proposal; parent will not advance cursor or record fallback mutation.\",\n },\n audit: {\n ...(base.audit ?? {\n queue: base.queue,\n itemId: base.itemId,\n inputHash: base.inputHash,\n policy: base.policy,\n policyVersion: base.policyVersion,\n action: base.action,\n reasonCode: base.reasonCode,\n capabilityClass: base.capabilityClass,\n humanReviewRequired: base.humanReviewRequired,\n evidence: base.evidence,\n actor: base.actor,\n runId: base.runId,\n jobId: base.jobId,\n }),\n action: \"failed-validation\",\n reasonCode: \"invalid-item\",\n capabilityClass: \"read-only\",\n humanReviewRequired: true,\n },\n };\n}\n\nfunction decisionFromPersonaView(base: PendingDecision, view: PersonaProposalDecisionView): PendingDecision {\n const actionClass = deriveActionClass(view.action);\n return {\n ...base,\n action: view.action,\n reasonCode: view.reason,\n actionClass,\n capabilityClass: view.capability,\n confidence: view.confidence,\n humanReviewRequired: view.humanReviewRequired,\n summary: { ...(base.summary ?? {}), body: view.diffSummary },\n audit: base.audit\n ? {\n ...base.audit,\n action: view.action,\n reasonCode: view.reason,\n capabilityClass: view.capability,\n humanReviewRequired: view.humanReviewRequired,\n }\n : undefined,\n };\n}\n\nfunction deriveActionClass(action: PendingDecision[\"action\"]): PendingDecision[\"actionClass\"] {\n if (action === \"applied\") return \"low-risk-apply\";\n if (action === \"rejected\") return \"state-transition\";\n if (action === \"deferred-for-human\") return \"record-review\";\n if (action === \"failed-validation\") return \"observe\";\n if (action === \"reported\") return \"observe\";\n if (action === \"classified\") return \"preview\";\n return \"observe\";\n}\n\nexport function createProcedureReadOnlyAdapter(factsDb: PendingDigestFactsDb): PendingQueueAdapter<QueueItem> {\n return {\n queue: \"procedures\",\n listPending: () => {\n if (!factsDb.triageProcedures) return [];\n const report = factsDb.triageProcedures({\n status: \"validated\",\n notPromoted: true,\n limit: 10_000,\n });\n return report.rows.map(procedureRowToItem);\n },\n decide: decideReadOnlyItem,\n };\n}\n\nexport function createVerifiedReadOnlyAdapter(factsDb: PendingDigestFactsDb): PendingQueueAdapter<QueueItem> {\n return {\n queue: \"verified\",\n listPending: () => {\n const count = Math.max(0, factsDb.countVerifiedFacts());\n return Array.from({ length: count }, (_, i) => verifiedPlaceholderToItem(i + 1));\n },\n decide: decideReadOnlyItem,\n };\n}\n\nexport function createToolProposalReadOnlyAdapter(dbPath: string): PendingQueueAdapter<QueueItem> {\n return {\n queue: \"tools\",\n listPending: () =>\n withCloseable(\n () => new ToolProposalStore(dbPath),\n (store) => store.list({ status: \"proposed\" }).map(toolProposalToItem),\n ),\n decide: decideReadOnlyItem,\n };\n}\n\nexport function createCrystallizationReadOnlyAdapter(dbPath: string): PendingQueueAdapter<QueueItem> {\n return {\n queue: \"crystallization\",\n listPending: () =>\n withCloseable(\n () => new CrystallizationStore(dbPath),\n (store) => store.list({ status: \"pending\" }).map(crystallizationProposalToItem),\n ),\n decide: decideReadOnlyItem,\n };\n}\n\nexport function decideReadOnlyItem(item: QueueItem, context: PendingDecisionContext): PendingDecision {\n if (context.policy === \"disabled\") {\n return makeSkippedDecision({\n queue: item.queue,\n policy: context.policy,\n mode: context.mode,\n runId: context.runId,\n jobId: context.jobId,\n actor: context.actor,\n });\n }\n const reportOnly = context.policy === \"report-only\";\n const requiresHuman = item.requiresHumanReview === true || reportOnly;\n return {\n queue: item.queue,\n itemId: item.id,\n inputHash: item.inputHash,\n policy: context.policy,\n policyVersion: context.policyVersion,\n mode: context.mode,\n action: reportOnly ? \"reported\" : requiresHuman ? \"deferred-for-human\" : \"classified\",\n reasonCode: reportOnly\n ? \"policy-denied\"\n : requiresHuman\n ? \"human-review-required\"\n : context.mode === \"dry-run\"\n ? \"dry-run\"\n : \"policy-threshold-not-met\",\n actionClass: reportOnly ? \"observe\" : \"preview\",\n capabilityClass: context.mode === \"dry-run\" ? \"dry-run\" : \"read-only\",\n confidence: typeof item.payload.confidence === \"number\" ? item.payload.confidence : 0.5,\n humanReviewRequired: requiresHuman,\n evidence: [\n {\n type: \"pending-item\",\n id: item.id,\n summary: String(item.payload.title ?? item.id),\n },\n ],\n actor: context.actor,\n runId: context.runId,\n jobId: context.jobId,\n summary: {\n title: String(item.payload.title ?? item.id),\n body: String(item.payload.summary ?? \"read-only pending digest classification\"),\n metadata: {\n queue: item.queue,\n source: item.payload.source ?? \"live-inventory\",\n },\n },\n };\n}\n\nfunction procedureRowToItem(p: ProcedureTriageRow): QueueItem {\n const payload = {\n source: \"procedures-triage\",\n title: p.title,\n validatedAt: p.validatedAt,\n promotionBlockReason: p.promotionBlockReason,\n successCount: p.successCount,\n confidence: p.confidence,\n skillPath: p.skillPath,\n summary: `Procedure promotion candidate blocked by ${p.promotionBlockReason}`,\n };\n return makeItem(\"procedures\", p.id, payload, true);\n}\n\nfunction verifiedPlaceholderToItem(index: number): QueueItem {\n const id = `verified-review-${index}`;\n return makeItem(\n \"verified\",\n id,\n {\n source: \"verified-facts-count\",\n title: `Verified fact review placeholder ${index}`,\n summary:\n \"#1329 must define the exact verified-fact review queue. Parent #1326 only reports/classifies the current digest count.\",\n },\n true,\n );\n}\n\nfunction toolProposalToItem(p: ToolProposal): QueueItem {\n return makeItem(\n \"tools\",\n p.id,\n {\n source: \"tool-proposals\",\n title: p.name,\n summary: p.description,\n createdAt: p.createdAt,\n updatedAt: p.updatedAt,\n },\n false,\n );\n}\n\nfunction crystallizationProposalToItem(p: {\n id: string;\n skillName: string;\n createdAt: string;\n updatedAt: string;\n}): QueueItem {\n return makeItem(\n \"crystallization\",\n p.id,\n {\n source: \"crystallization-proposals\",\n title: p.skillName,\n summary: \"Pending crystallization proposal; #1326 parent only classifies/read-only reports.\",\n createdAt: p.createdAt,\n updatedAt: p.updatedAt,\n },\n false,\n );\n}\n\nfunction makeItem(queue: PendingQueue, id: string, payload: QueuePayload, requiresHumanReview: boolean): QueueItem {\n return {\n queue,\n id,\n inputHash: computePendingInputHash({\n queue,\n id,\n payload,\n policy: \"default\",\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n }),\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n capabilityClasses: [\"read-only\"],\n payload,\n visibleAfterCursor: id,\n requiresHumanReview,\n };\n}\n\nfunction makeSkippedDecision(input: {\n queue: PendingQueue;\n policy: string;\n mode: AutopilotMode;\n runId: string;\n jobId?: string;\n actor: PendingDecision[\"actor\"];\n}): PendingDecision {\n const itemId = `${input.queue}:skipped`;\n const inputHash = computePendingInputHash({\n queue: input.queue,\n itemId,\n policy: input.policy,\n reason: \"disabled\",\n });\n return {\n queue: input.queue,\n itemId,\n inputHash,\n policy: input.policy,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n mode: input.mode,\n action: \"skipped-by-policy\",\n reasonCode: \"policy-denied\",\n actionClass: \"observe\",\n capabilityClass: input.mode === \"dry-run\" ? \"dry-run\" : \"read-only\",\n confidence: 1,\n humanReviewRequired: false,\n evidence: [\n {\n type: \"policy\",\n id: input.policy,\n summary: \"queue disabled or unavailable\",\n },\n ],\n actor: input.actor,\n runId: input.runId,\n jobId: input.jobId,\n summary: {\n title: `${input.queue} skipped`,\n body: \"Queue skipped by parent orchestration policy.\",\n },\n };\n}\n\nfunction makeFailureDecision(input: {\n queue: PendingQueue;\n policy: string;\n mode: AutopilotMode;\n runId: string;\n jobId?: string;\n actor: PendingDecision[\"actor\"];\n error: unknown;\n}): PendingDecision {\n const itemId = `${input.queue}:inventory-failed`;\n const message = input.error instanceof Error ? input.error.message : String(input.error);\n return {\n queue: input.queue,\n itemId,\n inputHash: computePendingInputHash({\n queue: input.queue,\n itemId,\n policy: input.policy,\n message,\n }),\n policy: input.policy,\n policyVersion: PENDING_DIGEST_AUTOPILOT_POLICY_VERSION,\n mode: input.mode,\n action: \"failed-validation\",\n reasonCode: \"schema-validation-failed\",\n actionClass: \"observe\",\n capabilityClass: input.mode === \"dry-run\" ? \"dry-run\" : \"read-only\",\n confidence: 0,\n humanReviewRequired: true,\n evidence: [{ type: \"error\", summary: message }],\n actor: input.actor,\n runId: input.runId,\n jobId: input.jobId,\n summary: { title: `${input.queue} inventory failed`, body: message },\n };\n}\n\nfunction summarizeCounts(decisions: PendingDecision[]): PendingDigestAutopilotResult[\"counts\"] {\n return {\n inspected: decisions.filter((d) => d.action !== \"skipped-by-policy\" && d.action !== \"failed-validation\").length,\n classified: decisions.filter((d) => d.action === \"classified\" || d.action === \"reported\").length,\n applied: decisions.filter((d) => d.action === \"applied\").length,\n deferred: decisions.filter((d) => d.action === \"deferred-for-human\").length,\n rejected: decisions.filter((d) => d.action === \"rejected\").length,\n failedValidation: decisions.filter((d) => d.action === \"failed-validation\").length,\n skipped: decisions.filter((d) => d.action === \"skipped-by-policy\").length,\n humanReviewRequired: decisions.filter((d) => d.humanReviewRequired).length,\n };\n}\n\nfunction validatePolicies(policies: PendingDigestAutopilotPolicies): void {\n const allowed: Record<PendingQueue, readonly string[]> = {\n persona: [\"disabled\", \"report-only\", \"cautious\", \"apply-safe\"],\n procedures: [\"disabled\", \"report-only\", \"dry-run-skills\", \"auto-safe\"],\n verified: [\"disabled\", \"report-only\", \"classify\", \"apply-obvious\"],\n tools: [\"disabled\", \"report-only\", \"classify\"],\n crystallization: [\"disabled\", \"report-only\", \"classify\"],\n };\n for (const queue of PENDING_QUEUES) {\n if (!allowed[queue].includes(policies[queue])) {\n throw new Error(`Unsupported ${queue} pending autopilot policy: ${policies[queue]}`);\n }\n }\n}\n\nfunction withCloseable<TStore extends { close?: () => void }, T>(factory: () => TStore, fn: (store: TStore) => T): T {\n let store: TStore | null = null;\n try {\n store = factory();\n const result = fn(store);\n if (result instanceof Promise) {\n return result.finally(() => {\n try {\n store?.close?.();\n } catch {\n // Best-effort close for inventory readers.\n }\n }) as T;\n }\n try {\n store?.close?.();\n } catch {\n // Best-effort close for inventory readers.\n }\n return result;\n } catch (err) {\n try {\n store?.close?.();\n } catch {\n // Best-effort close for inventory readers.\n }\n throw err;\n }\n}\n\nexport function stablePendingDigestAutopilotJson(result: PendingDigestAutopilotResult): string {\n return `${canonicalJson(redactAutopilotValue(result))}\\n`;\n}\n"],"mappings":"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"}
|