@aitne/daemon 0.1.10 → 0.1.11
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/dist/adapters/adapter-watchdog.d.ts +70 -0
- package/dist/adapters/adapter-watchdog.js +115 -0
- package/dist/adapters/discord.d.ts +17 -1
- package/dist/adapters/discord.js +33 -0
- package/dist/adapters/notification-manager.d.ts +27 -1
- package/dist/adapters/notification-manager.js +54 -39
- package/dist/adapters/slack-adapter.d.ts +26 -1
- package/dist/adapters/slack-adapter.js +41 -0
- package/dist/adapters/telegram-adapter.d.ts +18 -1
- package/dist/adapters/telegram-adapter.js +41 -2
- package/dist/adapters/types.d.ts +20 -0
- package/dist/adapters/whatsapp-adapter.d.ts +26 -7
- package/dist/adapters/whatsapp-adapter.js +74 -21
- package/dist/api/env-writer.js +8 -5
- package/dist/api/helpers/agent-errors-registry.d.ts +5 -5
- package/dist/api/helpers/agent-errors-registry.js +5 -5
- package/dist/api/routes/agent.js +33 -12
- package/dist/api/routes/agents/index.js +75 -16
- package/dist/api/routes/agents/views.d.ts +37 -2
- package/dist/api/routes/agents/views.js +64 -2
- package/dist/api/routes/background-task.d.ts +22 -0
- package/dist/api/routes/background-task.js +338 -0
- package/dist/api/routes/browser-history.js +9 -1
- package/dist/api/routes/context/permissions.js +3 -2
- package/dist/api/routes/context/snapshots.js +0 -3
- package/dist/api/routes/context/write.js +3 -17
- package/dist/api/routes/dashboard/config.js +48 -12
- package/dist/api/routes/dashboard/cost-approvals.js +66 -0
- package/dist/api/routes/dashboard/notifications.js +9 -9
- package/dist/api/routes/integrations/crud-patch.js +5 -1
- package/dist/api/routes/integrations-reconcile.js +2 -2
- package/dist/api/routes/notion.d.ts +1 -1
- package/dist/api/routes/observations.js +7 -7
- package/dist/api/routes/obsidian.d.ts +1 -1
- package/dist/api/routes/receipts.js +5 -1
- package/dist/api/routes/setup-migrate.js +1 -1
- package/dist/api/routes/setup.js +1 -1
- package/dist/api/routes/task-flows.d.ts +1 -1
- package/dist/api/routes/task-flows.js +1 -1
- package/dist/api/routes/tuning.d.ts +29 -0
- package/dist/api/routes/tuning.js +304 -0
- package/dist/api/server.d.ts +44 -16
- package/dist/api/server.js +9 -0
- package/dist/bootstrap/adapters.d.ts +19 -0
- package/dist/bootstrap/adapters.js +61 -0
- package/dist/bootstrap/api.d.ts +5 -3
- package/dist/bootstrap/api.js +45 -13
- package/dist/bootstrap/catchup.d.ts +1 -1
- package/dist/bootstrap/catchup.js +11 -11
- package/dist/bootstrap/event-pipeline.d.ts +11 -0
- package/dist/bootstrap/event-pipeline.js +245 -7
- package/dist/bootstrap/observers.js +9 -6
- package/dist/bootstrap/schedule-helpers.d.ts +104 -6
- package/dist/bootstrap/schedule-helpers.js +172 -19
- package/dist/config.js +26 -12
- package/dist/core/agent-core.d.ts +33 -1
- package/dist/core/agent-core.js +36 -1
- package/dist/core/agents/activity-scan-cadence.d.ts +103 -0
- package/dist/core/agents/activity-scan-cadence.js +127 -0
- package/dist/core/agents/agent-route-override.d.ts +53 -0
- package/dist/core/agents/agent-route-override.js +69 -0
- package/dist/core/agents/builtin-registry.d.ts +51 -14
- package/dist/core/agents/builtin-registry.js +92 -15
- package/dist/core/agents/config-gate-reconcile.d.ts +38 -0
- package/dist/core/agents/config-gate-reconcile.js +51 -0
- package/dist/core/agents/cron-substitute.d.ts +1 -1
- package/dist/core/agents/cron-substitute.js +1 -1
- package/dist/core/agents/custom-routine-migration.d.ts +60 -0
- package/dist/core/agents/custom-routine-migration.js +149 -0
- package/dist/core/agents/firing-blocked.d.ts +1 -1
- package/dist/core/agents/hourly-cadence.d.ts +102 -0
- package/dist/core/agents/hourly-cadence.js +126 -0
- package/dist/core/agents/loader-boot.js +23 -0
- package/dist/core/agents/loader.d.ts +19 -0
- package/dist/core/agents/loader.js +34 -2
- package/dist/core/agents/override-merge.d.ts +1 -1
- package/dist/core/agents/override-merge.js +9 -1
- package/dist/core/agents/recurrence-convert.d.ts +1 -1
- package/dist/core/agents/recurrence-convert.js +1 -1
- package/dist/core/agents/recurring-schedule-adapter.js +8 -0
- package/dist/core/alerts.js +6 -6
- package/dist/core/backends/auth-health-monitor.d.ts +2 -2
- package/dist/core/backends/auth-health-monitor.js +1 -1
- package/dist/core/backends/backend-router.d.ts +27 -1
- package/dist/core/backends/backend-router.js +165 -1
- package/dist/core/backends/claude-code-core.d.ts +71 -31
- package/dist/core/backends/claude-code-core.js +282 -54
- package/dist/core/backends/cli-quota-guards.d.ts +29 -1
- package/dist/core/backends/cli-quota-guards.js +40 -5
- package/dist/core/backends/codex-core.d.ts +6 -0
- package/dist/core/backends/codex-core.js +22 -6
- package/dist/core/backends/failure-spend.d.ts +58 -0
- package/dist/core/backends/failure-spend.js +137 -0
- package/dist/core/backends/gemini-cli-core.d.ts +6 -0
- package/dist/core/backends/gemini-cli-core.js +25 -6
- package/dist/core/backends/model-registry.d.ts +1 -1
- package/dist/core/backends/model-registry.js +4 -4
- package/dist/core/backends/opencode-core.d.ts +1 -1
- package/dist/core/backends/opencode-core.js +5 -5
- package/dist/core/backends/plan-presets.js +39 -15
- package/dist/core/bang-commands/commands-cost.js +3 -1
- package/dist/core/bang-commands/commands-report.js +4 -3
- package/dist/core/bang-commands/commands-research.js +4 -1
- package/dist/core/bang-commands/commands-revert-tuning.d.ts +18 -0
- package/dist/core/bang-commands/commands-revert-tuning.js +63 -0
- package/dist/core/bang-commands/commands-stop-start.js +3 -3
- package/dist/core/bang-commands/commands-task-control.d.ts +19 -0
- package/dist/core/bang-commands/commands-task-control.js +147 -0
- package/dist/core/bang-commands/commands-wiki.js +5 -5
- package/dist/core/bang-commands/index.d.ts +2 -0
- package/dist/core/bang-commands/index.js +12 -0
- package/dist/core/bang-commands/registry.d.ts +12 -0
- package/dist/core/browser-history/research-cluster-fanout.d.ts +28 -14
- package/dist/core/browser-history/research-cluster-fanout.js +39 -16
- package/dist/core/channel-timeline.d.ts +5 -1
- package/dist/core/channel-timeline.js +13 -0
- package/dist/core/context/index-reconciler.js +5 -2
- package/dist/core/context/policy-index-reconciler.d.ts +6 -4
- package/dist/core/context/policy-index-runner.js +25 -6
- package/dist/core/context-builder-calendar.js +10 -2
- package/dist/core/context-builder-conversation.d.ts +8 -1
- package/dist/core/context-builder-conversation.js +41 -7
- package/dist/core/context-builder-yesterday.js +4 -3
- package/dist/core/context-builder.d.ts +7 -2
- package/dist/core/context-builder.js +62 -20
- package/dist/core/context-file-serializer.d.ts +1 -1
- package/dist/core/context-file-serializer.js +1 -1
- package/dist/core/context-health.js +2 -2
- package/dist/core/context-paths.d.ts +1 -1
- package/dist/core/context-paths.js +1 -1
- package/dist/core/context-validation/prepare-write.js +1 -1
- package/dist/core/context-validation/routine-rulebook.d.ts +1 -1
- package/dist/core/context-vault-aliases.d.ts +0 -13
- package/dist/core/context-vault-aliases.js +37 -0
- package/dist/core/custom-routines.d.ts +99 -0
- package/dist/core/custom-routines.js +187 -0
- package/dist/core/daemon-api-cli.js +49 -0
- package/dist/core/day-boundary.d.ts +46 -0
- package/dist/core/day-boundary.js +40 -0
- package/dist/core/dispatcher-activity-scan.d.ts +221 -0
- package/dist/core/dispatcher-activity-scan.js +775 -0
- package/dist/core/dispatcher-error-handling.d.ts +6 -11
- package/dist/core/dispatcher-error-handling.js +38 -62
- package/dist/core/dispatcher-hourly-check.js +6 -1
- package/dist/core/dispatcher-message-handler.d.ts +10 -0
- package/dist/core/dispatcher-message-handler.js +17 -0
- package/dist/core/dispatcher-morning-routine.d.ts +6 -6
- package/dist/core/dispatcher-morning-routine.js +13 -13
- package/dist/core/dispatcher-result-processor.d.ts +33 -0
- package/dist/core/dispatcher-result-processor.js +167 -11
- package/dist/core/dispatcher-scheduled-background-task.d.ts +42 -0
- package/dist/core/dispatcher-scheduled-background-task.js +89 -0
- package/dist/core/dispatcher-scheduled-tasks.d.ts +63 -1
- package/dist/core/dispatcher-scheduled-tasks.js +213 -6
- package/dist/core/dispatcher-task-delivery.d.ts +105 -0
- package/dist/core/dispatcher-task-delivery.js +555 -0
- package/dist/core/dispatcher-types.d.ts +48 -9
- package/dist/core/dispatcher-types.js +3 -3
- package/dist/core/dispatcher.d.ts +112 -31
- package/dist/core/dispatcher.js +284 -59
- package/dist/core/dm-freshness-metrics.d.ts +1 -1
- package/dist/core/drift-effects.js +2 -2
- package/dist/core/feedback/consolidation-prep.js +17 -5
- package/dist/core/feedback/eviction-scorer.js +6 -2
- package/dist/core/feedback/lesson-format.js +9 -4
- package/dist/core/feedback/lesson-injection.d.ts +1 -1
- package/dist/core/feedback/lesson-injection.js +17 -2
- package/dist/core/feedback/lesson-store-overview.d.ts +8 -4
- package/dist/core/feedback/lesson-store-overview.js +8 -4
- package/dist/core/feedback/regeneralization-prep.js +29 -16
- package/dist/core/feedback/self-performance-prep.d.ts +186 -0
- package/dist/core/feedback/self-performance-prep.js +541 -0
- package/dist/core/feedback/tuning-actuator.d.ts +198 -0
- package/dist/core/feedback/tuning-actuator.js +432 -0
- package/dist/core/feedback/tuning-recommender.d.ts +247 -0
- package/dist/core/feedback/tuning-recommender.js +580 -0
- package/dist/core/feedback/tuning-revert-monitor.d.ts +90 -0
- package/dist/core/feedback/tuning-revert-monitor.js +213 -0
- package/dist/core/health-monitor.d.ts +6 -0
- package/dist/core/health-monitor.js +1 -1
- package/dist/core/injection-policy.d.ts +4 -4
- package/dist/core/injection-policy.js +4 -4
- package/dist/core/integration-main-backend.js +4 -0
- package/dist/core/management-md.d.ts +2 -2
- package/dist/core/management-md.js +51 -13
- package/dist/core/morning/orchestrator.d.ts +2 -2
- package/dist/core/morning/orchestrator.js +2 -2
- package/dist/core/notification-gate.d.ts +64 -0
- package/dist/core/notification-gate.js +51 -0
- package/dist/core/notification-rate-limit.d.ts +40 -0
- package/dist/core/notification-rate-limit.js +50 -0
- package/dist/core/policy-files.d.ts +1 -1
- package/dist/core/policy-files.js +2 -2
- package/dist/core/pre-pass-freshness.d.ts +4 -4
- package/dist/core/retention.d.ts +5 -0
- package/dist/core/retention.js +20 -4
- package/dist/core/review-context.d.ts +1 -1
- package/dist/core/review-context.js +10 -5
- package/dist/core/roadmap-write-lock.d.ts +2 -1
- package/dist/core/roadmap-write-lock.js +15 -10
- package/dist/core/routine-acquisition-plan.d.ts +47 -1
- package/dist/core/routine-acquisition-plan.js +78 -20
- package/dist/core/routine-fetch-window-retry.js +7 -4
- package/dist/core/routine-fetch-window-runner.d.ts +39 -3
- package/dist/core/routine-fetch-window-runner.js +264 -13
- package/dist/core/routine-windows.d.ts +2 -2
- package/dist/core/routine-windows.js +8 -5
- package/dist/core/scheduler.d.ts +175 -16
- package/dist/core/scheduler.js +559 -102
- package/dist/core/signal-detector.d.ts +12 -0
- package/dist/core/signal-detector.js +53 -9
- package/dist/core/skills-compiler-denied-tools.js +2 -2
- package/dist/core/skills-compiler-skill-index.d.ts +2 -2
- package/dist/core/skills-compiler-skill-index.js +2 -2
- package/dist/core/skills-compiler-variants.d.ts +1 -1
- package/dist/core/skills-compiler-variants.js +8 -0
- package/dist/core/skills-compiler.d.ts +29 -26
- package/dist/core/skills-compiler.js +117 -81
- package/dist/core/skills-manifest.d.ts +37 -0
- package/dist/core/skills-manifest.js +73 -2
- package/dist/core/sleep-inhibitor.d.ts +79 -0
- package/dist/core/sleep-inhibitor.js +132 -0
- package/dist/core/slim-system-prompt-loader.d.ts +77 -0
- package/dist/core/slim-system-prompt-loader.js +141 -0
- package/dist/core/spawn-gates.d.ts +126 -0
- package/dist/core/spawn-gates.js +180 -0
- package/dist/core/today-direct-writer.d.ts +2 -2
- package/dist/core/today-direct-writer.js +1 -1
- package/dist/core/today-write-lock.d.ts +4 -2
- package/dist/core/today-write-lock.js +30 -20
- package/dist/core/wake-detector.d.ts +55 -0
- package/dist/core/wake-detector.js +80 -0
- package/dist/core/wiki/compile-lock.d.ts +1 -1
- package/dist/core/wiki/compile-lock.js +1 -1
- package/dist/core/workdir.js +15 -6
- package/dist/db/activity-scan-signals.d.ts +77 -0
- package/dist/db/activity-scan-signals.js +378 -0
- package/dist/db/agents-store.d.ts +28 -0
- package/dist/db/agents-store.js +62 -0
- package/dist/db/background-task-clarifications-store.d.ts +81 -0
- package/dist/db/background-task-clarifications-store.js +152 -0
- package/dist/db/background-task-store.d.ts +207 -0
- package/dist/db/background-task-store.js +380 -0
- package/dist/db/browser-history-store.d.ts +39 -6
- package/dist/db/browser-history-store.js +51 -7
- package/dist/db/browser-task-clarifications-store.d.ts +12 -0
- package/dist/db/browser-task-clarifications-store.js +35 -5
- package/dist/db/browser-task-store.d.ts +3 -0
- package/dist/db/browser-task-store.js +29 -4
- package/dist/db/deferred-dm.d.ts +86 -0
- package/dist/db/deferred-dm.js +199 -0
- package/dist/db/migrations.js +330 -0
- package/dist/db/observations.d.ts +2 -2
- package/dist/db/observations.js +3 -3
- package/dist/db/schema.js +217 -16
- package/dist/db/voice-transcripts-store.d.ts +1 -1
- package/dist/index.js +86 -29
- package/dist/messaging/browser-task-mcp-notifier.d.ts +12 -70
- package/dist/messaging/browser-task-mcp-notifier.js +30 -151
- package/dist/messaging/browser-task-screenshot-attachment.d.ts +15 -0
- package/dist/messaging/browser-task-screenshot-attachment.js +63 -0
- package/dist/observers/delegated-sync-worker.d.ts +6 -6
- package/dist/observers/delegated-sync-worker.js +10 -10
- package/dist/observers/git-delegated-cron.d.ts +1 -1
- package/dist/observers/git-delegated-cron.js +2 -2
- package/dist/observers/github-poller-classifier.d.ts +3 -3
- package/dist/observers/github-poller-classifier.js +3 -3
- package/dist/observers/imminent-event-scheduler.d.ts +1 -1
- package/dist/observers/imminent-event-scheduler.js +1 -1
- package/dist/observers/mail-poller.d.ts +1 -0
- package/dist/observers/mail-poller.js +42 -3
- package/dist/observers/observation-summarizer/summarizer-client.d.ts +2 -2
- package/dist/observers/observation-summarizer/summarizer-client.js +2 -2
- package/dist/observers/observation-summarizer/worker.d.ts +2 -2
- package/dist/observers/observation-summarizer/worker.js +4 -4
- package/dist/observers/obsidian-watcher.d.ts +1 -1
- package/dist/observers/obsidian-watcher.js +1 -1
- package/dist/safety/agent-write-tracker.d.ts +4 -4
- package/dist/safety/agent-write-tracker.js +4 -4
- package/dist/safety/audit.d.ts +43 -5
- package/dist/safety/audit.js +86 -18
- package/dist/safety/risk-classifier.d.ts +6 -0
- package/dist/safety/risk-classifier.js +75 -11
- package/dist/scheduler/activity-scan-gate.d.ts +86 -0
- package/dist/scheduler/activity-scan-gate.js +132 -0
- package/dist/services/background-task/background-task-budget.d.ts +80 -0
- package/dist/services/background-task/background-task-budget.js +91 -0
- package/dist/services/background-task/background-task-driver.d.ts +105 -0
- package/dist/services/background-task/background-task-driver.js +416 -0
- package/dist/services/background-task/background-task-runner.d.ts +96 -0
- package/dist/services/background-task/background-task-runner.js +673 -0
- package/dist/services/background-task/background-task-tools.d.ts +84 -0
- package/dist/services/background-task/background-task-tools.js +247 -0
- package/dist/services/background-task/background-task-transition-events.d.ts +43 -0
- package/dist/services/background-task/background-task-transition-events.js +54 -0
- package/dist/services/browser-history/automation/egress-denylist.d.ts +1 -1
- package/dist/services/browser-history/automation/egress-denylist.js +16 -6
- package/dist/services/browser-history/managed-chromium/sandbox-launcher.js +0 -1
- package/dist/services/browser-task/browser-task-runner.js +53 -8
- package/dist/services/observations-batch.d.ts +1 -1
- package/dist/services/observations-batch.js +2 -2
- package/dist/settings/runtime-settings.d.ts +38 -11
- package/dist/settings/runtime-settings.js +203 -40
- package/dist/settings/settings-store.js +11 -3
- package/package.json +4 -4
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* docs/design/appendices/routine-data-acquisition.md §6.1.1 + docs/design/appendices/pre-pass-fan-out.md
|
|
5
5
|
* — every routine dispatcher (morning_routine, today_refresh,
|
|
6
|
-
*
|
|
6
|
+
* activity_scan, evening / weekly / monthly review) calls this runner
|
|
7
7
|
* immediately before dispatching the parent session. The runner:
|
|
8
8
|
*
|
|
9
9
|
* 1. Reads the per-routine plan from `ROUTINE_WINDOWS` and the current
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* 4. The caller grafts the block into the **parent** routine event's
|
|
28
28
|
* `event.data.fetchReportBlock`. ContextBuilder injects it verbatim
|
|
29
29
|
* into the parent session's prompt (mirrors the `<gate_decision>`
|
|
30
|
-
* pattern used by
|
|
30
|
+
* pattern used by activity_scan Stage 3).
|
|
31
31
|
*
|
|
32
32
|
* Failure-mode contract (docs/design/appendices/pre-pass-fan-out.md §5):
|
|
33
33
|
*
|
|
@@ -57,6 +57,7 @@ import type { IAgentRouter } from "./backends/backend-router.js";
|
|
|
57
57
|
import type { IAuditLogger, IContextBuilder } from "./dispatcher-types.js";
|
|
58
58
|
import type { PromptAssembler } from "./dispatcher-prompt.js";
|
|
59
59
|
import { type RoutineWindowKey } from "./routine-windows.js";
|
|
60
|
+
import type { AutonomousSpawnGate } from "./spawn-gates.js";
|
|
60
61
|
/**
|
|
61
62
|
* Structured form of the agent's single-line JSON output. Matches the
|
|
62
63
|
* contract in `agent-profiles/routine-fetch-window.md`:
|
|
@@ -142,7 +143,7 @@ export interface RoutineFetchWindowResult {
|
|
|
142
143
|
/**
|
|
143
144
|
* HOURLY_CHECK_GATE_REDESIGN_PLAN.md §3.4 — caller options for `run()`.
|
|
144
145
|
*
|
|
145
|
-
* The
|
|
146
|
+
* The activity_scan coordinator passes `integrationKeyFilter` to restrict
|
|
146
147
|
* the fan-out to the subset of integrations whose freshness window has
|
|
147
148
|
* elapsed. Morning_routine / evening_review / weekly_review call
|
|
148
149
|
* `run()` without options so they fetch every integration the routine
|
|
@@ -194,6 +195,14 @@ export interface RoutineFetchWindowRunnerDeps {
|
|
|
194
195
|
getEventBroadcaster?: () => {
|
|
195
196
|
broadcastEvent: (data: unknown) => void;
|
|
196
197
|
} | null;
|
|
198
|
+
/**
|
|
199
|
+
* PREPASS_COST_REDUCTION_PLAN.md N2 — offline/auth spawn gate shared
|
|
200
|
+
* with the dispatcher. Evaluated per integration sub-session (the
|
|
201
|
+
* hourly `harvestForGate` path spawns the runner directly, bypassing
|
|
202
|
+
* the dispatcher's own gate). Optional: when undefined the runner
|
|
203
|
+
* spawns unconditionally, exactly as pre-N2.
|
|
204
|
+
*/
|
|
205
|
+
spawnGate?: AutonomousSpawnGate;
|
|
197
206
|
}
|
|
198
207
|
/**
|
|
199
208
|
* Compose the per-execute `allowedToolsOverride` for the pre-pass. The
|
|
@@ -340,6 +349,7 @@ export declare class RoutineFetchWindowRunner {
|
|
|
340
349
|
private readonly prompt;
|
|
341
350
|
private readonly getActiveMailAccounts;
|
|
342
351
|
private readonly getEventBroadcaster;
|
|
352
|
+
private readonly spawnGate;
|
|
343
353
|
constructor(deps: RoutineFetchWindowRunnerDeps);
|
|
344
354
|
/**
|
|
345
355
|
* Broadcast a single pre-pass progress event to the dashboard SSE
|
|
@@ -426,6 +436,32 @@ export declare class RoutineFetchWindowRunner {
|
|
|
426
436
|
private budgetCapAttemptRecord;
|
|
427
437
|
private didExhaustRetries;
|
|
428
438
|
private backoffForAttempt;
|
|
439
|
+
/**
|
|
440
|
+
* PREPASS_COST_REDUCTION_PLAN.md N2 — evaluate the offline/auth spawn
|
|
441
|
+
* gate for one integration's sub-session. Candidates are the
|
|
442
|
+
* pre-resolved binding's main + fallback backends; when pre-resolve
|
|
443
|
+
* failed, the sub-plan's `requiredBackend` is the only candidate the
|
|
444
|
+
* attempt loop could use. Fail-open on every error path (returns null).
|
|
445
|
+
*/
|
|
446
|
+
private evaluateSpawnGate;
|
|
447
|
+
/**
|
|
448
|
+
* Build the `skipped` SubReport for a spawn-gate skip and write its
|
|
449
|
+
* audit row. Mirrors the empty-attempts synthetic record (attempt 0,
|
|
450
|
+
* no SSE sub-session emits — no session was spawned). The audit row is
|
|
451
|
+
* `result='skipped'` with `detail.prePass.skipReason` carrying N2's
|
|
452
|
+
* `offline` / `auth_unhealthy`, matching the N3 plan-drop row shape so
|
|
453
|
+
* all pre-pass skip telemetry is queryable through one path.
|
|
454
|
+
*/
|
|
455
|
+
private spawnGateSkippedSubReport;
|
|
456
|
+
/**
|
|
457
|
+
* PREPASS_COST_REDUCTION_PLAN.md N3 — one `skipped` audit row per
|
|
458
|
+
* (integration × reason) group of plan-assembly drops, with the
|
|
459
|
+
* dropped windows listed in `detail.prePass.windows`. Grouped at
|
|
460
|
+
* integration granularity because that is the unit a session would
|
|
461
|
+
* have been spawned for (and the unit the deferred R5 streak skip
|
|
462
|
+
* will key on). Observability only — no skip behavior changes here.
|
|
463
|
+
*/
|
|
464
|
+
private logPlanAssemblyDrops;
|
|
429
465
|
/**
|
|
430
466
|
* Unified audit-row companion for every fan-out failure mode —
|
|
431
467
|
* binding-resolve-failed, global-budget-cap, budget-cap (per-integration),
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* docs/design/appendices/routine-data-acquisition.md §6.1.1 + docs/design/appendices/pre-pass-fan-out.md
|
|
5
5
|
* — every routine dispatcher (morning_routine, today_refresh,
|
|
6
|
-
*
|
|
6
|
+
* activity_scan, evening / weekly / monthly review) calls this runner
|
|
7
7
|
* immediately before dispatching the parent session. The runner:
|
|
8
8
|
*
|
|
9
9
|
* 1. Reads the per-routine plan from `ROUTINE_WINDOWS` and the current
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* 4. The caller grafts the block into the **parent** routine event's
|
|
28
28
|
* `event.data.fetchReportBlock`. ContextBuilder injects it verbatim
|
|
29
29
|
* into the parent session's prompt (mirrors the `<gate_decision>`
|
|
30
|
-
* pattern used by
|
|
30
|
+
* pattern used by activity_scan Stage 3).
|
|
31
31
|
*
|
|
32
32
|
* Failure-mode contract (docs/design/appendices/pre-pass-fan-out.md §5):
|
|
33
33
|
*
|
|
@@ -54,7 +54,9 @@ import { readIntegrations } from "../db/integrations-store.js";
|
|
|
54
54
|
import { renderPartialForFanOut } from "./prompts.js";
|
|
55
55
|
import { OBSERVATIONS_MCP_TOOL_NAME } from "../services/mcp/sdk-observations-server.js";
|
|
56
56
|
import { ROUTINE_WINDOWS, routineHasWindows, WINDOW_QUERIES, } from "./routine-windows.js";
|
|
57
|
-
import { buildAcquisitionTimestamps, splitAcquisitionPlanByIntegration, } from "./routine-acquisition-plan.js";
|
|
57
|
+
import { buildAcquisitionPlanAssembly, buildAcquisitionTimestamps, splitAcquisitionPlanByIntegration, } from "./routine-acquisition-plan.js";
|
|
58
|
+
import { extractBackendSpend } from "./agent-core.js";
|
|
59
|
+
import { BackendRouterHandledError } from "./backends/backend-router.js";
|
|
58
60
|
import { RETRY_REASONS, buildPriorAttemptHintBlock, defaultRetryDecision, } from "./routine-fetch-window-retry.js";
|
|
59
61
|
import { writeRuntimeState } from "../db/runtime-state.js";
|
|
60
62
|
import { prePassLastRunRuntimeStateKey } from "./pre-pass-freshness.js";
|
|
@@ -118,7 +120,7 @@ const FETCH_WINDOW_INTEGRATION_PARTIAL_PLACEHOLDER = "{integration_partial}";
|
|
|
118
120
|
function buildPrePassDaemonRestPatterns(apiPort, sessionBackend) {
|
|
119
121
|
const root = `http://localhost:${apiPort}/api`;
|
|
120
122
|
// Observations WRITE surface — the only write the pre-pass performs (GET
|
|
121
|
-
// reads of pending observations live in the
|
|
123
|
+
// reads of pending observations live in the activity-scan session, never
|
|
122
124
|
// here). For Claude the structured MCP tool
|
|
123
125
|
// `mcp__aitne-observations__submit_observations` (added by
|
|
124
126
|
// `composePrePassAllowedTools`) is the ONLY sanctioned write path, so we
|
|
@@ -774,6 +776,55 @@ async function runWithConcurrency(tasks, concurrency) {
|
|
|
774
776
|
await Promise.all(workers);
|
|
775
777
|
return results;
|
|
776
778
|
}
|
|
779
|
+
function recoverRouterErrorSpend(error) {
|
|
780
|
+
const failures = [];
|
|
781
|
+
if (error instanceof BackendRouterHandledError) {
|
|
782
|
+
failures.push(error.mainFailure);
|
|
783
|
+
if (error.fallbackFailure && error.fallbackFailure !== error.mainFailure) {
|
|
784
|
+
failures.push(error.fallbackFailure);
|
|
785
|
+
}
|
|
786
|
+
if (error.cause && !failures.includes(error.cause)) {
|
|
787
|
+
failures.push(error.cause);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
else {
|
|
791
|
+
failures.push(error);
|
|
792
|
+
}
|
|
793
|
+
let found = false;
|
|
794
|
+
let costUsd = 0;
|
|
795
|
+
let numTurns = 0;
|
|
796
|
+
let inputTokens = 0;
|
|
797
|
+
let outputTokens = 0;
|
|
798
|
+
let cacheCreationInputTokens = 0;
|
|
799
|
+
let cacheReadInputTokens = 0;
|
|
800
|
+
let costSource = null;
|
|
801
|
+
for (const failure of failures) {
|
|
802
|
+
const spend = extractBackendSpend(failure);
|
|
803
|
+
if (!spend)
|
|
804
|
+
continue;
|
|
805
|
+
found = true;
|
|
806
|
+
costUsd += spend.costUsd;
|
|
807
|
+
numTurns += spend.numTurns;
|
|
808
|
+
inputTokens += spend.usage.inputTokens;
|
|
809
|
+
outputTokens += spend.usage.outputTokens;
|
|
810
|
+
cacheCreationInputTokens += spend.usage.cacheCreationInputTokens;
|
|
811
|
+
cacheReadInputTokens += spend.usage.cacheReadInputTokens;
|
|
812
|
+
costSource = costSource ?? spend.costSource ?? null;
|
|
813
|
+
}
|
|
814
|
+
if (!found)
|
|
815
|
+
return null;
|
|
816
|
+
return {
|
|
817
|
+
costUsd,
|
|
818
|
+
numTurns,
|
|
819
|
+
costSource,
|
|
820
|
+
usage: {
|
|
821
|
+
inputTokens,
|
|
822
|
+
outputTokens,
|
|
823
|
+
cacheCreationInputTokens,
|
|
824
|
+
cacheReadInputTokens,
|
|
825
|
+
},
|
|
826
|
+
};
|
|
827
|
+
}
|
|
777
828
|
// ── Runner ────────────────────────────────────────────────────────────────
|
|
778
829
|
export class RoutineFetchWindowRunner {
|
|
779
830
|
db;
|
|
@@ -784,6 +835,7 @@ export class RoutineFetchWindowRunner {
|
|
|
784
835
|
prompt;
|
|
785
836
|
getActiveMailAccounts;
|
|
786
837
|
getEventBroadcaster;
|
|
838
|
+
spawnGate;
|
|
787
839
|
constructor(deps) {
|
|
788
840
|
this.db = deps.db;
|
|
789
841
|
this.config = deps.config;
|
|
@@ -793,6 +845,7 @@ export class RoutineFetchWindowRunner {
|
|
|
793
845
|
this.prompt = deps.prompt;
|
|
794
846
|
this.getActiveMailAccounts = deps.getActiveMailAccounts;
|
|
795
847
|
this.getEventBroadcaster = deps.getEventBroadcaster ?? null;
|
|
848
|
+
this.spawnGate = deps.spawnGate ?? null;
|
|
796
849
|
}
|
|
797
850
|
/**
|
|
798
851
|
* Broadcast a single pre-pass progress event to the dashboard SSE
|
|
@@ -925,8 +978,13 @@ export class RoutineFetchWindowRunner {
|
|
|
925
978
|
catch (err) {
|
|
926
979
|
return this.fail(key, agentDay, parentEvent, "plan-assembly-failed", err);
|
|
927
980
|
}
|
|
981
|
+
// PREPASS_COST_REDUCTION_PLAN.md N3 — surface plan-assembly drops as
|
|
982
|
+
// `skipped` audit rows before the empty-plan short-circuit below, so
|
|
983
|
+
// the all-cells-dropped case (the one the short-circuit hides) is
|
|
984
|
+
// recorded too. Observability only — no new skip behavior.
|
|
985
|
+
this.logPlanAssemblyDrops(parentEvent, key, planContext.drops);
|
|
928
986
|
// HOURLY_CHECK_GATE_REDESIGN_PLAN.md §3.4 — when the caller is the
|
|
929
|
-
//
|
|
987
|
+
// activity_scan coordinator, the freshness gate restricts pre-pass to
|
|
930
988
|
// a subset of integrations. `integrationKeyFilter` is honoured here
|
|
931
989
|
// (before fan-out) so the runner only spawns sub-sessions for stale
|
|
932
990
|
// integrations.
|
|
@@ -1010,7 +1068,7 @@ export class RoutineFetchWindowRunner {
|
|
|
1010
1068
|
accounts,
|
|
1011
1069
|
timestamps,
|
|
1012
1070
|
};
|
|
1013
|
-
const subPlans =
|
|
1071
|
+
const { subPlans, drops } = buildAcquisitionPlanAssembly(planInput);
|
|
1014
1072
|
// Observability: surface integrations whose `<fetch>` row will spawn
|
|
1015
1073
|
// on a backend OTHER than the pre-pass default. Per-integration
|
|
1016
1074
|
// backend routing (resolveIntegrationBackend +
|
|
@@ -1042,6 +1100,7 @@ export class RoutineFetchWindowRunner {
|
|
|
1042
1100
|
subPlans,
|
|
1043
1101
|
accounts,
|
|
1044
1102
|
timestamps,
|
|
1103
|
+
drops,
|
|
1045
1104
|
};
|
|
1046
1105
|
}
|
|
1047
1106
|
/**
|
|
@@ -1183,6 +1242,17 @@ export class RoutineFetchWindowRunner {
|
|
|
1183
1242
|
return merged;
|
|
1184
1243
|
}
|
|
1185
1244
|
async runOneIntegrationWithRetry(input) {
|
|
1245
|
+
// PREPASS_COST_REDUCTION_PLAN.md N2 — offline/auth spawn gate, per
|
|
1246
|
+
// sub-session because each integration can route to a different
|
|
1247
|
+
// backend (`requiredBackend`). Skips only when EVERY candidate
|
|
1248
|
+
// backend is non-viable; the DNS verdict is cached (~60s) inside the
|
|
1249
|
+
// gate so an N-integration fan-out costs one lookup per host.
|
|
1250
|
+
// Freshness (`pre_pass_last_run:<key>`) is untouched by construction
|
|
1251
|
+
// — only `success` writes it — so the next tick retries.
|
|
1252
|
+
const gateDecision = await this.evaluateSpawnGate(input);
|
|
1253
|
+
if (gateDecision?.skip) {
|
|
1254
|
+
return this.spawnGateSkippedSubReport(input, gateDecision);
|
|
1255
|
+
}
|
|
1186
1256
|
const attempts = [];
|
|
1187
1257
|
// Per-integration budget cap is enforced at TWO complementary layers,
|
|
1188
1258
|
// BOTH driven by `policy.perIntegrationBudgetUsd`:
|
|
@@ -1414,10 +1484,16 @@ export class RoutineFetchWindowRunner {
|
|
|
1414
1484
|
record = this.attemptRecordFromResult(attempt, fetcherEvent, startedAt, result);
|
|
1415
1485
|
}
|
|
1416
1486
|
catch (err) {
|
|
1417
|
-
|
|
1418
|
-
|
|
1487
|
+
// PREPASS_COST_REDUCTION_PLAN.md N1 — the throw path can still
|
|
1488
|
+
// have billed the provider (post-hoc budget kill, partial stream
|
|
1489
|
+
// abort). Recover the spend the backend cores attached so the
|
|
1490
|
+
// budget guards account for real consumption and the attempt
|
|
1491
|
+
// record / audit row carry the cost instead of a silent 0.
|
|
1492
|
+
const failureSpend = recoverRouterErrorSpend(err);
|
|
1493
|
+
input.globalBudget.commit(globalReservation, failureSpend?.costUsd ?? 0);
|
|
1494
|
+
integrationBudget.commit(integrationReservation, failureSpend?.costUsd ?? 0);
|
|
1419
1495
|
executeErr = err;
|
|
1420
|
-
record = this.failedAttemptRecord(attempt, fetcherEvent.correlationId, startedAt, "agent-execute-failed", err);
|
|
1496
|
+
record = this.failedAttemptRecord(attempt, fetcherEvent.correlationId, startedAt, "agent-execute-failed", err, failureSpend);
|
|
1421
1497
|
}
|
|
1422
1498
|
attempts.push(record);
|
|
1423
1499
|
const decision = retryOn(record, attempt, input.policy, attempts.slice(0, -1));
|
|
@@ -1439,6 +1515,7 @@ export class RoutineFetchWindowRunner {
|
|
|
1439
1515
|
err: executeErr,
|
|
1440
1516
|
binding: binding.main,
|
|
1441
1517
|
startedAt,
|
|
1518
|
+
spend: recoverRouterErrorSpend(executeErr),
|
|
1442
1519
|
});
|
|
1443
1520
|
}
|
|
1444
1521
|
this.emitSubSessionCompleted(input, fetcherEvent.correlationId, attempt, record, decision);
|
|
@@ -1470,7 +1547,7 @@ export class RoutineFetchWindowRunner {
|
|
|
1470
1547
|
// timestamp on every successful integration completion. The
|
|
1471
1548
|
// coordinator's `harvestForGate` reads this key to suppress
|
|
1472
1549
|
// redundant pre-pass spawns within the configured freshness window
|
|
1473
|
-
// (default 30 min). Shared across morning_routine /
|
|
1550
|
+
// (default 30 min). Shared across morning_routine / activity_scan /
|
|
1474
1551
|
// evening_review / weekly_review / today_refresh by construction:
|
|
1475
1552
|
// the runner has no notion of parent routine.
|
|
1476
1553
|
//
|
|
@@ -1602,7 +1679,14 @@ export class RoutineFetchWindowRunner {
|
|
|
1602
1679
|
numTurns: result.numTurns,
|
|
1603
1680
|
};
|
|
1604
1681
|
}
|
|
1605
|
-
failedAttemptRecord(attempt, fetcherCorrelationId, startedAt, kind, err
|
|
1682
|
+
failedAttemptRecord(attempt, fetcherCorrelationId, startedAt, kind, err,
|
|
1683
|
+
/**
|
|
1684
|
+
* PREPASS_COST_REDUCTION_PLAN.md N1 — spend recovered from the
|
|
1685
|
+
* failure signal when the provider already billed the attempt.
|
|
1686
|
+
* Absent for pre-execute failures (binding/context), which are
|
|
1687
|
+
* genuinely zero-cost.
|
|
1688
|
+
*/
|
|
1689
|
+
spend) {
|
|
1606
1690
|
const message = err instanceof Error ? err.message : String(err);
|
|
1607
1691
|
const endedAt = new Date().toISOString();
|
|
1608
1692
|
return {
|
|
@@ -1615,8 +1699,8 @@ export class RoutineFetchWindowRunner {
|
|
|
1615
1699
|
fetcherCorrelationId,
|
|
1616
1700
|
startedAt,
|
|
1617
1701
|
endedAt,
|
|
1618
|
-
costUsd: 0,
|
|
1619
|
-
numTurns: 0,
|
|
1702
|
+
costUsd: spend?.costUsd ?? 0,
|
|
1703
|
+
numTurns: spend?.numTurns ?? 0,
|
|
1620
1704
|
};
|
|
1621
1705
|
}
|
|
1622
1706
|
budgetCapAttemptRecord(attempt, fetcherCorrelationId, startedAt, type, remaining) {
|
|
@@ -1663,6 +1747,156 @@ export class RoutineFetchWindowRunner {
|
|
|
1663
1747
|
const last = policy.backoffMs[policy.backoffMs.length - 1];
|
|
1664
1748
|
return typeof last === "number" ? Math.max(0, last) : 0;
|
|
1665
1749
|
}
|
|
1750
|
+
/**
|
|
1751
|
+
* PREPASS_COST_REDUCTION_PLAN.md N2 — evaluate the offline/auth spawn
|
|
1752
|
+
* gate for one integration's sub-session. Candidates are the
|
|
1753
|
+
* pre-resolved binding's main + fallback backends; when pre-resolve
|
|
1754
|
+
* failed, the sub-plan's `requiredBackend` is the only candidate the
|
|
1755
|
+
* attempt loop could use. Fail-open on every error path (returns null).
|
|
1756
|
+
*/
|
|
1757
|
+
async evaluateSpawnGate(input) {
|
|
1758
|
+
if (!this.spawnGate)
|
|
1759
|
+
return null;
|
|
1760
|
+
try {
|
|
1761
|
+
const binding = input.preResolvedBinding;
|
|
1762
|
+
const candidates = binding
|
|
1763
|
+
? [binding.main.backendId]
|
|
1764
|
+
: [input.subPlan.requiredBackend];
|
|
1765
|
+
if (binding?.fallback
|
|
1766
|
+
&& binding.fallback.backendId !== binding.main.backendId) {
|
|
1767
|
+
candidates.push(binding.fallback.backendId);
|
|
1768
|
+
}
|
|
1769
|
+
return await this.spawnGate.evaluate(candidates);
|
|
1770
|
+
}
|
|
1771
|
+
catch (err) {
|
|
1772
|
+
logger.warn({
|
|
1773
|
+
err,
|
|
1774
|
+
routine: input.key,
|
|
1775
|
+
integrationKey: input.subPlan.integrationKey,
|
|
1776
|
+
}, "Pre-pass spawn-gate evaluation failed — failing open");
|
|
1777
|
+
return null;
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
/**
|
|
1781
|
+
* Build the `skipped` SubReport for a spawn-gate skip and write its
|
|
1782
|
+
* audit row. Mirrors the empty-attempts synthetic record (attempt 0,
|
|
1783
|
+
* no SSE sub-session emits — no session was spawned). The audit row is
|
|
1784
|
+
* `result='skipped'` with `detail.prePass.skipReason` carrying N2's
|
|
1785
|
+
* `offline` / `auth_unhealthy`, matching the N3 plan-drop row shape so
|
|
1786
|
+
* all pre-pass skip telemetry is queryable through one path.
|
|
1787
|
+
*/
|
|
1788
|
+
spawnGateSkippedSubReport(input, decision) {
|
|
1789
|
+
const reason = decision.reason ?? "offline";
|
|
1790
|
+
const now = new Date().toISOString();
|
|
1791
|
+
const record = {
|
|
1792
|
+
attempt: 0,
|
|
1793
|
+
status: "skipped",
|
|
1794
|
+
fetched: 0,
|
|
1795
|
+
posted: 0,
|
|
1796
|
+
duplicates: 0,
|
|
1797
|
+
errors: [{ type: "spawn-gate-skipped", reason, attempt: 0 }],
|
|
1798
|
+
fetcherCorrelationId: input.parentEvent.correlationId,
|
|
1799
|
+
startedAt: now,
|
|
1800
|
+
endedAt: now,
|
|
1801
|
+
costUsd: 0,
|
|
1802
|
+
numTurns: 0,
|
|
1803
|
+
};
|
|
1804
|
+
try {
|
|
1805
|
+
const fetcherEvent = this.createFanOutFetcherEvent(input.parentEvent, input.key, input.subPlan, 0, input.policy.maxAttempts);
|
|
1806
|
+
this.audit.logSkip(fetcherEvent, reason, "autonomous", {
|
|
1807
|
+
prePass: {
|
|
1808
|
+
parentCorrelationId: input.parentEvent.correlationId,
|
|
1809
|
+
parentRoutine: input.key,
|
|
1810
|
+
integrationKey: input.subPlan.integrationKey,
|
|
1811
|
+
skipReason: reason,
|
|
1812
|
+
spawnGate: { backends: decision.backends },
|
|
1813
|
+
},
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
catch (err) {
|
|
1817
|
+
logger.warn({
|
|
1818
|
+
err,
|
|
1819
|
+
routine: input.key,
|
|
1820
|
+
integrationKey: input.subPlan.integrationKey,
|
|
1821
|
+
reason,
|
|
1822
|
+
}, "Failed to log spawn-gate skip audit row");
|
|
1823
|
+
}
|
|
1824
|
+
logger.info({
|
|
1825
|
+
routine: input.key,
|
|
1826
|
+
integrationKey: input.subPlan.integrationKey,
|
|
1827
|
+
reason,
|
|
1828
|
+
backends: decision.backends,
|
|
1829
|
+
parentCorrelationId: input.parentEvent.correlationId,
|
|
1830
|
+
}, "Pre-pass sub-session skipped — spawn gate (offline / auth-unhealthy backends)");
|
|
1831
|
+
return {
|
|
1832
|
+
...record,
|
|
1833
|
+
integrationKey: input.subPlan.integrationKey,
|
|
1834
|
+
attempts: [record],
|
|
1835
|
+
retriesExhausted: false,
|
|
1836
|
+
};
|
|
1837
|
+
}
|
|
1838
|
+
/**
|
|
1839
|
+
* PREPASS_COST_REDUCTION_PLAN.md N3 — one `skipped` audit row per
|
|
1840
|
+
* (integration × reason) group of plan-assembly drops, with the
|
|
1841
|
+
* dropped windows listed in `detail.prePass.windows`. Grouped at
|
|
1842
|
+
* integration granularity because that is the unit a session would
|
|
1843
|
+
* have been spawned for (and the unit the deferred R5 streak skip
|
|
1844
|
+
* will key on). Observability only — no skip behavior changes here.
|
|
1845
|
+
*/
|
|
1846
|
+
logPlanAssemblyDrops(parentEvent, key, allDrops) {
|
|
1847
|
+
// `direct_inline_prefetch` is the catalog working as designed (the
|
|
1848
|
+
// daemon fetches that data inline; see the reason's doc comment) —
|
|
1849
|
+
// auditing it every run would bury the genuine drop signal R4/R5
|
|
1850
|
+
// need under deterministic noise.
|
|
1851
|
+
const drops = allDrops.filter((d) => d.reason !== "direct_inline_prefetch");
|
|
1852
|
+
if (drops.length === 0)
|
|
1853
|
+
return;
|
|
1854
|
+
try {
|
|
1855
|
+
const groups = new Map();
|
|
1856
|
+
for (const drop of drops) {
|
|
1857
|
+
const groupKey = `${drop.integration}|${drop.reason}`;
|
|
1858
|
+
const existing = groups.get(groupKey);
|
|
1859
|
+
if (existing) {
|
|
1860
|
+
existing.windows.push(drop.window);
|
|
1861
|
+
}
|
|
1862
|
+
else {
|
|
1863
|
+
groups.set(groupKey, {
|
|
1864
|
+
integration: drop.integration,
|
|
1865
|
+
reason: drop.reason,
|
|
1866
|
+
windows: [drop.window],
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
for (const group of groups.values()) {
|
|
1871
|
+
const dropEvent = {
|
|
1872
|
+
...createEvent({
|
|
1873
|
+
type: FETCH_WINDOW_EVENT_TYPE,
|
|
1874
|
+
source: parentEvent.source,
|
|
1875
|
+
priority: EventPriority.NORMAL,
|
|
1876
|
+
correlationId: parentEvent.correlationId,
|
|
1877
|
+
}),
|
|
1878
|
+
routine: "fetch_window",
|
|
1879
|
+
};
|
|
1880
|
+
this.audit.logSkip(dropEvent, `plan_drop:${group.reason}`, "autonomous", {
|
|
1881
|
+
prePass: {
|
|
1882
|
+
parentCorrelationId: parentEvent.correlationId,
|
|
1883
|
+
parentRoutine: key,
|
|
1884
|
+
integrationKey: group.integration,
|
|
1885
|
+
skipReason: group.reason,
|
|
1886
|
+
windows: group.windows,
|
|
1887
|
+
},
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
logger.debug({
|
|
1891
|
+
routine: key,
|
|
1892
|
+
parentCorrelationId: parentEvent.correlationId,
|
|
1893
|
+
drops,
|
|
1894
|
+
}, "Pre-pass plan-assembly drops recorded");
|
|
1895
|
+
}
|
|
1896
|
+
catch (err) {
|
|
1897
|
+
logger.warn({ err, routine: key, dropCount: drops.length }, "Failed to log pre-pass plan-assembly drop audit rows");
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1666
1900
|
/**
|
|
1667
1901
|
* Unified audit-row companion for every fan-out failure mode —
|
|
1668
1902
|
* binding-resolve-failed, global-budget-cap, budget-cap (per-integration),
|
|
@@ -1694,6 +1928,23 @@ export class RoutineFetchWindowRunner {
|
|
|
1694
1928
|
...(durationMs !== undefined ? { durationMs } : {}),
|
|
1695
1929
|
...(options.binding ? { backendId: options.binding.backendId } : {}),
|
|
1696
1930
|
...(options.binding ? { modelId: options.binding.modelId } : {}),
|
|
1931
|
+
...(options.spend
|
|
1932
|
+
? {
|
|
1933
|
+
costUsd: options.spend.costUsd,
|
|
1934
|
+
numTurns: options.spend.numTurns,
|
|
1935
|
+
...(options.spend.costSource
|
|
1936
|
+
? { costSource: options.spend.costSource }
|
|
1937
|
+
: {}),
|
|
1938
|
+
...(options.spend.usage
|
|
1939
|
+
? {
|
|
1940
|
+
tokensInput: options.spend.usage.inputTokens,
|
|
1941
|
+
tokensOutput: options.spend.usage.outputTokens,
|
|
1942
|
+
tokensCacheCreation: options.spend.usage.cacheCreationInputTokens,
|
|
1943
|
+
tokensCacheRead: options.spend.usage.cacheReadInputTokens,
|
|
1944
|
+
}
|
|
1945
|
+
: {}),
|
|
1946
|
+
}
|
|
1947
|
+
: {}),
|
|
1697
1948
|
failureKind: options.failureKind,
|
|
1698
1949
|
prePass: {
|
|
1699
1950
|
parentCorrelationId: input.parentEvent.correlationId,
|
|
@@ -49,7 +49,7 @@ export type WindowSymbol = (typeof WINDOW_SYMBOLS)[number];
|
|
|
49
49
|
* `routine.morning_routine`; the daemon-prepared `<roadmap_skeleton>`
|
|
50
50
|
* block (not a window fetch) handles the first-run roadmap populate.
|
|
51
51
|
*/
|
|
52
|
-
export declare const ROUTINE_WINDOW_KEYS: readonly ["routine.morning_routine", "routine.today_refresh", "routine.
|
|
52
|
+
export declare const ROUTINE_WINDOW_KEYS: readonly ["routine.morning_routine", "routine.today_refresh", "routine.activity_scan", "routine.evening_review", "routine.weekly_review", "routine.monthly_review"];
|
|
53
53
|
export type RoutineWindowKey = (typeof ROUTINE_WINDOW_KEYS)[number];
|
|
54
54
|
export interface RoutineWindowSpec {
|
|
55
55
|
/** Fetch shape — drives partial selection (mail-acquire vs calendar-acquire vs notion-acquire). */
|
|
@@ -102,7 +102,7 @@ export interface RoutineWindowSpec {
|
|
|
102
102
|
* differs). The dispatcher's `applySinceFilter` in
|
|
103
103
|
* `db/observations.ts` ensures the main session reads back the
|
|
104
104
|
* merged pending set uniformly.
|
|
105
|
-
* - `
|
|
105
|
+
* - `activity_scan`: small, frequent. `unread_last_hour` typically
|
|
106
106
|
* yields ≤1 mail item; `imminent_2h` ≤1 calendar item. Notion
|
|
107
107
|
* `updated_1h` is similarly bounded.
|
|
108
108
|
* - `evening_review`: ContextBuilder covers `<calendar_events_3d>`,
|
|
@@ -83,7 +83,7 @@ export const WINDOW_SYMBOLS = [
|
|
|
83
83
|
export const ROUTINE_WINDOW_KEYS = [
|
|
84
84
|
"routine.morning_routine",
|
|
85
85
|
"routine.today_refresh",
|
|
86
|
-
"routine.
|
|
86
|
+
"routine.activity_scan",
|
|
87
87
|
"routine.evening_review",
|
|
88
88
|
"routine.weekly_review",
|
|
89
89
|
"routine.monthly_review",
|
|
@@ -112,7 +112,7 @@ export const ROUTINE_WINDOW_KEYS = [
|
|
|
112
112
|
* differs). The dispatcher's `applySinceFilter` in
|
|
113
113
|
* `db/observations.ts` ensures the main session reads back the
|
|
114
114
|
* merged pending set uniformly.
|
|
115
|
-
* - `
|
|
115
|
+
* - `activity_scan`: small, frequent. `unread_last_hour` typically
|
|
116
116
|
* yields ≤1 mail item; `imminent_2h` ≤1 calendar item. Notion
|
|
117
117
|
* `updated_1h` is similarly bounded.
|
|
118
118
|
* - `evening_review`: ContextBuilder covers `<calendar_events_3d>`,
|
|
@@ -147,7 +147,7 @@ export const ROUTINE_WINDOWS = {
|
|
|
147
147
|
"routine.today_refresh": [
|
|
148
148
|
{ kind: "calendar", window: "cal_next_24h_drift", perAccount: false },
|
|
149
149
|
],
|
|
150
|
-
"routine.
|
|
150
|
+
"routine.activity_scan": [
|
|
151
151
|
{ kind: "mail", window: "unread_last_hour", perAccount: true },
|
|
152
152
|
{ kind: "calendar", window: "imminent_2h", perAccount: false },
|
|
153
153
|
{ kind: "notion", window: "updated_1h", perAccount: false },
|
|
@@ -216,7 +216,7 @@ export const WINDOW_QUERIES = {
|
|
|
216
216
|
// shell-fragile Unicode whitespace. Filtering at the FETCH boundary
|
|
217
217
|
// means the agent never sees these messages at all: zero cost, zero
|
|
218
218
|
// chance of a Unicode-whitespace-bearing curl body, zero observations
|
|
219
|
-
// for the morning_routine /
|
|
219
|
+
// for the morning_routine / activity_scan skill to wade through.
|
|
220
220
|
//
|
|
221
221
|
// Sent-folder windows (today_outcomes) skip the filter — sent mail is
|
|
222
222
|
// the user's own writing, not promotional.
|
|
@@ -334,6 +334,9 @@ export const WINDOW_QUERIES = {
|
|
|
334
334
|
// (Outlook), so a pre-pass row would double-fetch. The dispatcher
|
|
335
335
|
// skips rows whose `(symbol, integration, mode)` cell is undefined
|
|
336
336
|
// (cf. `lookupQuery`); pre-pass only fires for delegated / native.
|
|
337
|
+
// Plan assembly classifies this pattern as `direct_inline_prefetch`
|
|
338
|
+
// (N3) — distinct from `no_window_query` (a genuine catalog hole) —
|
|
339
|
+
// and the runner excludes it from the drop-audit stream.
|
|
337
340
|
cal_morning_7d: {
|
|
338
341
|
google_calendar: {
|
|
339
342
|
delegated: 'timeMin="{day_start_iso}" timeMax="{week_end_iso}" maxResults=100',
|
|
@@ -401,7 +404,7 @@ export function routineHasWindows(key) {
|
|
|
401
404
|
return ROUTINE_WINDOWS[key].length > 0;
|
|
402
405
|
}
|
|
403
406
|
// Note: there is intentionally no `routineHasCalendarPrepass` helper
|
|
404
|
-
// even though every morning_routine /
|
|
407
|
+
// even though every morning_routine / activity_scan / today_refresh /
|
|
405
408
|
// weekly_review row carries a calendar entry. The decision a caller
|
|
406
409
|
// (e.g. ContextBuilder.buildCalendarBlock) really wants to make is
|
|
407
410
|
// "does the pre-pass own the window I'm about to emit," and that needs
|