@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
|
@@ -42,10 +42,13 @@ import { isAgentTaskEvent, isDocsQAMessage, isMessageEvent, isRoutineEvent, isSc
|
|
|
42
42
|
import { getContextDir } from "../config.js";
|
|
43
43
|
import { finalizeRetemplate } from "./template-store.js";
|
|
44
44
|
import { recordManagementInitDone, recordManagementScan, } from "../db/repositories-store.js";
|
|
45
|
-
import { formatForwardSuffix,
|
|
45
|
+
import { formatForwardSuffix, isProactiveForwardMetadata, parseMessageMetadata, recordProactiveForwardDeliveries, } from "./channel-timeline.js";
|
|
46
46
|
import { randomUUID } from "node:crypto";
|
|
47
|
+
import { statSync } from "node:fs";
|
|
48
|
+
import { join } from "node:path";
|
|
47
49
|
import { OWNER_DM_SCOPE, OWNER_SCOPE_KEY, DASHBOARD_CHAT_SCOPE, DASHBOARD_SCOPE_KEY, getConversationScope, } from "../messaging/constants.js";
|
|
48
50
|
import { readEventReplyTarget } from "./wiki/dispatcher.js";
|
|
51
|
+
import { TASK_DELIVERY_ATTACHMENTS_KEY } from "./dispatcher-task-delivery.js";
|
|
49
52
|
import { createLogger } from "../logging.js";
|
|
50
53
|
import { assertOutboundAllowedForAgent, OutboundPurchaseTemplateError, } from "../safety/outbound-purchase-guard.js";
|
|
51
54
|
const logger = createLogger("dispatcher-result");
|
|
@@ -138,6 +141,16 @@ export class ResultProcessor {
|
|
|
138
141
|
threadId: explicitReply.threadId ?? null,
|
|
139
142
|
};
|
|
140
143
|
}
|
|
144
|
+
// BACKGROUND_TASK_RUNNER_DESIGN.md Phase 1 (delivery assets) — the
|
|
145
|
+
// task.delivery active turn is a no-tool DM turn, so the daemon (not
|
|
146
|
+
// the agent) attaches any deliverable files the task produced. The
|
|
147
|
+
// delivery handler resolved them and stashed the refs on the
|
|
148
|
+
// synthetic event; carry them onto the woven reply send. Only ever
|
|
149
|
+
// populated for the synthetic scheduled.dm delivery event.
|
|
150
|
+
const deliveryAttachments = readTaskDeliveryAttachments(event);
|
|
151
|
+
if (deliveryAttachments.length > 0 && explicitReply) {
|
|
152
|
+
sendOptions.attachments = deliveryAttachments;
|
|
153
|
+
}
|
|
141
154
|
// MANAGED_CHROMIUM_IMPLEMENTATION_PLAN.md §17.7 structural-anti-
|
|
142
155
|
// spoofing layer. The LLM's outbound text reaches the messaging
|
|
143
156
|
// adapter via this notificationMgr.send chokepoint; refuse any
|
|
@@ -189,6 +202,7 @@ export class ResultProcessor {
|
|
|
189
202
|
// the send itself, so wrap in try/catch.
|
|
190
203
|
if (explicitReply && output.length > 0) {
|
|
191
204
|
try {
|
|
205
|
+
const taskDeliveryRecord = readTaskDeliveryRecord(event);
|
|
192
206
|
recordProactiveForwardDeliveries({
|
|
193
207
|
db: this.db,
|
|
194
208
|
config: this.config,
|
|
@@ -203,7 +217,10 @@ export class ResultProcessor {
|
|
|
203
217
|
...(options.originSessionId !== undefined
|
|
204
218
|
? { originSessionIds: [options.originSessionId] }
|
|
205
219
|
: {}),
|
|
206
|
-
notificationType: "proactive_forward",
|
|
220
|
+
notificationType: taskDeliveryRecord?.notificationType ?? "proactive_forward",
|
|
221
|
+
...(taskDeliveryRecord
|
|
222
|
+
? { extraMetadata: taskDeliveryRecord.metadata }
|
|
223
|
+
: {}),
|
|
207
224
|
});
|
|
208
225
|
}
|
|
209
226
|
catch (err) {
|
|
@@ -213,6 +230,24 @@ export class ResultProcessor {
|
|
|
213
230
|
}
|
|
214
231
|
}
|
|
215
232
|
}
|
|
233
|
+
// RESEARCH_CLUSTER_COST_FIX_PLAN F5 — outcome verification. The
|
|
234
|
+
// routine.research_cluster_update flow's ONLY deliverable is the
|
|
235
|
+
// per-cluster journal at context/research/<slug>.md. The 2026-06-11
|
|
236
|
+
// incident showed the flow ending "successfully" (no backend error,
|
|
237
|
+
// num_turns=1) while never writing the file — every "success" was a
|
|
238
|
+
// text-only narration. Upgrade "success" from "the session ended
|
|
239
|
+
// without a backend error" to "...AND the journal was written this
|
|
240
|
+
// run": a clean-but-unwritten run is recorded as `partial` /
|
|
241
|
+
// `journal_write_missing` (surfaced in the dashboard activity feed,
|
|
242
|
+
// `!report`, and `aitne audit --result partial`) rather than a
|
|
243
|
+
// misleading success. Gated to clean runs — a hard error already took
|
|
244
|
+
// the logError path with a more informative message.
|
|
245
|
+
const outcomeOverride = isRoutineEvent(event)
|
|
246
|
+
&& event.routine === "research_cluster_update"
|
|
247
|
+
&& !result.isError
|
|
248
|
+
&& !this.researchClusterJournalWritten(event, result)
|
|
249
|
+
? { result: "partial", error: "journal_write_missing" }
|
|
250
|
+
: undefined;
|
|
216
251
|
this.audit.logAction({
|
|
217
252
|
event,
|
|
218
253
|
model: result.model,
|
|
@@ -226,6 +261,7 @@ export class ResultProcessor {
|
|
|
226
261
|
costSource: result.costSource,
|
|
227
262
|
contextUpdated: result.contextUpdated,
|
|
228
263
|
advisorCallCount: result.advisorCallCount,
|
|
264
|
+
...(outcomeOverride ?? {}),
|
|
229
265
|
...(options.dmFreshness ? { dmFreshness: options.dmFreshness } : {}),
|
|
230
266
|
...(options.dailyWrite ? { dailyWrite: options.dailyWrite } : {}),
|
|
231
267
|
});
|
|
@@ -249,7 +285,7 @@ export class ResultProcessor {
|
|
|
249
285
|
// - github.* (GitHub poller high-priority events)
|
|
250
286
|
// - git.* (git watcher batched events)
|
|
251
287
|
// - notion.* (notion poller)
|
|
252
|
-
// - routine.
|
|
288
|
+
// - routine.activity_scan (Phase-9 polling sink for obsidian/git/notion)
|
|
253
289
|
if (this.isObserverEvent(event)) {
|
|
254
290
|
logger.info({
|
|
255
291
|
eventType: event.type,
|
|
@@ -450,13 +486,9 @@ export class ResultProcessor {
|
|
|
450
486
|
if (message.role !== "assistant")
|
|
451
487
|
return message.role;
|
|
452
488
|
const metadata = parseMessageMetadata(message.metadata);
|
|
453
|
-
const
|
|
454
|
-
if (
|
|
455
|
-
return
|
|
456
|
-
}
|
|
457
|
-
if (type !== null) {
|
|
458
|
-
return "assistant (forwarded from autonomous run)";
|
|
459
|
-
}
|
|
489
|
+
const suffix = formatForwardSuffix(metadata);
|
|
490
|
+
if (suffix.length > 0)
|
|
491
|
+
return `assistant${suffix}`;
|
|
460
492
|
return message.role;
|
|
461
493
|
}
|
|
462
494
|
buildCrossSessionConversationHistory(event) {
|
|
@@ -546,13 +578,91 @@ export class ResultProcessor {
|
|
|
546
578
|
* contextUpdated observability log in processResult.
|
|
547
579
|
*/
|
|
548
580
|
isObserverEvent(event) {
|
|
549
|
-
return ((isRoutineEvent(event) && event.routine === "
|
|
581
|
+
return ((isRoutineEvent(event) && event.routine === "activity_scan") ||
|
|
550
582
|
event.type.startsWith("calendar.") ||
|
|
551
583
|
event.type === "schedule.approaching" ||
|
|
552
584
|
event.type.startsWith("notion.") ||
|
|
553
585
|
event.type.startsWith("github.") ||
|
|
554
586
|
event.type.startsWith("git."));
|
|
555
587
|
}
|
|
588
|
+
/**
|
|
589
|
+
* RESEARCH_CLUSTER_COST_FIX_PLAN F5 — was the cluster journal actually
|
|
590
|
+
* written during this `routine.research_cluster_update` run?
|
|
591
|
+
*
|
|
592
|
+
* Detection is the on-disk journal file itself — the authoritative,
|
|
593
|
+
* path-specific, backend-agnostic signal. The daemon writes the journal
|
|
594
|
+
* via the context-API chokepoint (`writeFileAtomically`), so the file's
|
|
595
|
+
* mtime reflects the real write time; a write that landed inside the run
|
|
596
|
+
* window (`[min(event enqueue, now − durationMs) − buffer, now]`) proves
|
|
597
|
+
* the agent executed the append rather than narrating success.
|
|
598
|
+
*
|
|
599
|
+
* Why not the `context_write` audit row (the plan's first idea): that
|
|
600
|
+
* row is emitted only inside `notifyPromptContextChanged`, which fires
|
|
601
|
+
* solely for prompt-refreshing paths (`shouldRefreshPromptContext`).
|
|
602
|
+
* `research/*` is intentionally a *quiet* namespace — it never triggers
|
|
603
|
+
* a refresh — so a research write records **no** `context_write` row.
|
|
604
|
+
* (The plan's §1 "zero context_write rows ⇒ zero writes" inference was
|
|
605
|
+
* therefore unsound for this namespace; the on-disk check has none of
|
|
606
|
+
* that coupling.) F1 guarantees ≤ 1 cluster_update run/cluster/day, so
|
|
607
|
+
* the run window cannot collide with another run writing the same file;
|
|
608
|
+
* the sibling research flows write *different* files
|
|
609
|
+
* (`<slug>-assistance-<date>.md`, `<slug>-wiki.md`), never `<slug>.md`.
|
|
610
|
+
*
|
|
611
|
+
* Returns `true` (treat as written — do NOT downgrade) when the slug is
|
|
612
|
+
* absent/invalid or the stat fails for any reason other than ENOENT: a
|
|
613
|
+
* verification fault must never relabel a genuinely-successful run.
|
|
614
|
+
*/
|
|
615
|
+
researchClusterJournalWritten(event, result) {
|
|
616
|
+
const data = (event.data ?? {});
|
|
617
|
+
const slug = typeof data.slug === "string" ? data.slug : null;
|
|
618
|
+
// Defense in depth against path traversal even though the slug comes
|
|
619
|
+
// from the daemon's own cluster table — same sanitized character set
|
|
620
|
+
// the context-API whitelist enforces (PLACEHOLDER_SEGMENT_RE).
|
|
621
|
+
if (!slug || !/^[a-z0-9._-]+$/.test(slug)) {
|
|
622
|
+
logger.warn({ correlationId: event.correlationId, slug }, "research_cluster_update: missing/invalid slug — skipping journal-write verification");
|
|
623
|
+
return true;
|
|
624
|
+
}
|
|
625
|
+
// Resolve the dir WITHOUT the db argument, mirroring the context
|
|
626
|
+
// route's own `getCurrentContextDir` (api/routes/context/index.ts):
|
|
627
|
+
// with `db`, `getContextDir` falls back to the legacy
|
|
628
|
+
// `<dataDir>/context` while the vault is degraded — but the write
|
|
629
|
+
// route never writes there (degraded mode 503s every request), so
|
|
630
|
+
// statting the fallback could mislabel a run that wrote to the real
|
|
631
|
+
// vault just before degraded mode engaged. Always stat the path the
|
|
632
|
+
// agent's writes would have landed at.
|
|
633
|
+
const journalPath = join(getContextDir(this.config), "research", `${slug}.md`);
|
|
634
|
+
// Anchor the window at the event's enqueue time when it is older than
|
|
635
|
+
// `now − durationMs`: `durationMs` covers only the FINAL backend
|
|
636
|
+
// attempt, so a write made during an earlier `executeWithRetry`
|
|
637
|
+
// attempt (or before any dispatcher latency between run end and this
|
|
638
|
+
// check) would otherwise fall outside the window and downgrade a run
|
|
639
|
+
// that DID write. Widening backwards is safe — F1 guarantees at most
|
|
640
|
+
// one run per cluster per agent day and no sibling flow writes
|
|
641
|
+
// `<slug>.md`, so the only possible writer inside the widened window
|
|
642
|
+
// is this run.
|
|
643
|
+
const bufferMs = 5_000;
|
|
644
|
+
const eventCreatedMs = event.timestamp instanceof Date
|
|
645
|
+
? event.timestamp.getTime()
|
|
646
|
+
: Date.parse(String(event.timestamp));
|
|
647
|
+
const runStartMs = Date.now() - (result.durationMs ?? 0);
|
|
648
|
+
const windowStartMs = (Number.isFinite(eventCreatedMs)
|
|
649
|
+
? Math.min(eventCreatedMs, runStartMs)
|
|
650
|
+
: runStartMs) - bufferMs;
|
|
651
|
+
try {
|
|
652
|
+
return statSync(journalPath).mtimeMs >= windowStartMs;
|
|
653
|
+
}
|
|
654
|
+
catch (err) {
|
|
655
|
+
if (err.code === "ENOENT") {
|
|
656
|
+
// File never created — the strongest "not written" signal.
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
/* c8 ignore next 5 — non-ENOENT stat failure (e.g. EACCES) is not
|
|
660
|
+
* reproducible in the test harness; the conservative fall-through
|
|
661
|
+
* (treat as written) is asserted indirectly by the ENOENT path. */
|
|
662
|
+
logger.warn({ err, journalPath, correlationId: event.correlationId }, "research_cluster_update: journal stat failed — skipping verification");
|
|
663
|
+
return true;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
556
666
|
/**
|
|
557
667
|
* Confirm that a `wiki.ingest_url` session actually wrote a raw note via
|
|
558
668
|
* the Wiki API before letting the agent's claimed success DM reach the
|
|
@@ -620,3 +730,49 @@ export class ResultProcessor {
|
|
|
620
730
|
return `Failed ${url ?? "<url>"} — agent reported completion but no raw note was POSTed via the Wiki API; the vault is unchanged.`;
|
|
621
731
|
}
|
|
622
732
|
}
|
|
733
|
+
export function readTaskDeliveryRecord(event) {
|
|
734
|
+
const raw = event.data
|
|
735
|
+
?.task_delivery_record;
|
|
736
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
737
|
+
return null;
|
|
738
|
+
const record = raw;
|
|
739
|
+
if (record.notificationType !== "task_result"
|
|
740
|
+
&& record.notificationType !== "task_clarification"
|
|
741
|
+
// Phase 4 autonomous-forward natural delivery: the active weave turn
|
|
742
|
+
// carries a task_delivery_record whose notificationType is
|
|
743
|
+
// "proactive_forward" (autonomous forwards have no task row, so they
|
|
744
|
+
// reuse the proactive_forward type). Its metadata still tags the woven
|
|
745
|
+
// message with taskKind/deliveredTaskId so `deliverActive`'s
|
|
746
|
+
// message-existence check can confirm the weave landed and skip the
|
|
747
|
+
// verbatim re-send. Without accepting it here the metadata is dropped,
|
|
748
|
+
// the existence check misses, and the owner receives BOTH the woven DM
|
|
749
|
+
// and a verbatim duplicate.
|
|
750
|
+
&& record.notificationType !== "proactive_forward") {
|
|
751
|
+
return null;
|
|
752
|
+
}
|
|
753
|
+
const metadata = record.metadata
|
|
754
|
+
&& typeof record.metadata === "object"
|
|
755
|
+
&& !Array.isArray(record.metadata)
|
|
756
|
+
? record.metadata
|
|
757
|
+
: {};
|
|
758
|
+
return {
|
|
759
|
+
notificationType: record.notificationType,
|
|
760
|
+
metadata,
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Resolved deliverable-file refs the task.delivery handler stashed on the
|
|
765
|
+
* synthetic `scheduled.dm` event (BACKGROUND_TASK_RUNNER_DESIGN.md Phase 1
|
|
766
|
+
* — delivery assets). Returns `[]` for every ordinary event. Shape is
|
|
767
|
+
* validated loosely — a malformed entry is dropped rather than thrown so a
|
|
768
|
+
* bad ref never blocks the woven reply.
|
|
769
|
+
*/
|
|
770
|
+
function readTaskDeliveryAttachments(event) {
|
|
771
|
+
const raw = event.data?.[TASK_DELIVERY_ATTACHMENTS_KEY];
|
|
772
|
+
if (!Array.isArray(raw))
|
|
773
|
+
return [];
|
|
774
|
+
return raw.filter((a) => !!a
|
|
775
|
+
&& typeof a === "object"
|
|
776
|
+
&& typeof a.path === "string"
|
|
777
|
+
&& typeof a.id === "string");
|
|
778
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dispatcher handler for `scheduled.background_task`
|
|
3
|
+
* (BACKGROUND_TASK_RUNNER_DESIGN.md §4.2).
|
|
4
|
+
*
|
|
5
|
+
* Lifts fire-time row creation + runner handoff out of `dispatcher.ts`,
|
|
6
|
+
* mirroring `dispatcher-scheduled-browser-task.ts` but with the whole
|
|
7
|
+
* allowlist / site-registry plane removed — a background task carries
|
|
8
|
+
* only a self-contained brief.
|
|
9
|
+
*
|
|
10
|
+
* Flow:
|
|
11
|
+
* 1. Re-validate the persisted `task_context` (a hand-crafted DB row
|
|
12
|
+
* cannot smuggle invalid fields through the scheduler boundary).
|
|
13
|
+
* 2. Dedup on `preGeneratedTaskId` (a scheduler/dispatcher restart
|
|
14
|
+
* between event.put and dispatch must not double-insert).
|
|
15
|
+
* 3. Insert the `background_task` row pinned to the pre-generated id.
|
|
16
|
+
* 4. Hand off to the runner. The runner's RunResult drives the
|
|
17
|
+
* `background_task` lifecycle from here; the `agent_schedule` row's
|
|
18
|
+
* status is independent (the dispatcher marks it completed on
|
|
19
|
+
* successful dispatch, failed on rejection).
|
|
20
|
+
*/
|
|
21
|
+
import type Database from "better-sqlite3";
|
|
22
|
+
import type { ScheduledBackgroundTaskEvent } from "@aitne/shared";
|
|
23
|
+
import type { BackgroundTaskRunner } from "../services/background-task/background-task-runner.js";
|
|
24
|
+
export type ScheduledBackgroundTaskOutcome = {
|
|
25
|
+
kind: "dispatched";
|
|
26
|
+
taskId: string;
|
|
27
|
+
} | {
|
|
28
|
+
kind: "task_context_invalid";
|
|
29
|
+
reason: string;
|
|
30
|
+
} | {
|
|
31
|
+
kind: "row_already_exists";
|
|
32
|
+
taskId: string;
|
|
33
|
+
} | {
|
|
34
|
+
kind: "runner_unavailable";
|
|
35
|
+
taskId: string;
|
|
36
|
+
};
|
|
37
|
+
export interface BackgroundTaskDispatchDeps {
|
|
38
|
+
db: Database.Database;
|
|
39
|
+
runner: BackgroundTaskRunner | null;
|
|
40
|
+
nowFn?: () => number;
|
|
41
|
+
}
|
|
42
|
+
export declare function handleScheduledBackgroundTask(deps: BackgroundTaskDispatchDeps, event: ScheduledBackgroundTaskEvent): Promise<ScheduledBackgroundTaskOutcome>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dispatcher handler for `scheduled.background_task`
|
|
3
|
+
* (BACKGROUND_TASK_RUNNER_DESIGN.md §4.2).
|
|
4
|
+
*
|
|
5
|
+
* Lifts fire-time row creation + runner handoff out of `dispatcher.ts`,
|
|
6
|
+
* mirroring `dispatcher-scheduled-browser-task.ts` but with the whole
|
|
7
|
+
* allowlist / site-registry plane removed — a background task carries
|
|
8
|
+
* only a self-contained brief.
|
|
9
|
+
*
|
|
10
|
+
* Flow:
|
|
11
|
+
* 1. Re-validate the persisted `task_context` (a hand-crafted DB row
|
|
12
|
+
* cannot smuggle invalid fields through the scheduler boundary).
|
|
13
|
+
* 2. Dedup on `preGeneratedTaskId` (a scheduler/dispatcher restart
|
|
14
|
+
* between event.put and dispatch must not double-insert).
|
|
15
|
+
* 3. Insert the `background_task` row pinned to the pre-generated id.
|
|
16
|
+
* 4. Hand off to the runner. The runner's RunResult drives the
|
|
17
|
+
* `background_task` lifecycle from here; the `agent_schedule` row's
|
|
18
|
+
* status is independent (the dispatcher marks it completed on
|
|
19
|
+
* successful dispatch, failed on rejection).
|
|
20
|
+
*/
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import { createBackgroundTask, getBackgroundTask, markTerminal, } from "../db/background-task-store.js";
|
|
23
|
+
import { createLogger } from "../logging.js";
|
|
24
|
+
const logger = createLogger("dispatcher-scheduled-background-task");
|
|
25
|
+
const taskContextSchema = z.object({
|
|
26
|
+
preGeneratedTaskId: z.string().uuid(),
|
|
27
|
+
brief: z.string().min(1).max(16_384),
|
|
28
|
+
title: z.string().min(1).max(200).nullable().optional(),
|
|
29
|
+
notificationPolicy: z
|
|
30
|
+
.enum(["always", "if_significant", "silent"])
|
|
31
|
+
.optional(),
|
|
32
|
+
significanceCriteria: z
|
|
33
|
+
.array(z.string().min(1).max(500))
|
|
34
|
+
.max(12)
|
|
35
|
+
.nullable()
|
|
36
|
+
.optional(),
|
|
37
|
+
tier: z.enum(["lite", "medium", "high"]).nullable().optional(),
|
|
38
|
+
maxBudgetUsd: z.number().positive().max(15).nullable().optional(),
|
|
39
|
+
originatingChannel: z.string().nullable().optional(),
|
|
40
|
+
});
|
|
41
|
+
export async function handleScheduledBackgroundTask(deps, event) {
|
|
42
|
+
const now = deps.nowFn ?? (() => Date.now());
|
|
43
|
+
const parsed = taskContextSchema.safeParse(event.taskContext);
|
|
44
|
+
if (!parsed.success) {
|
|
45
|
+
const reason = parsed.error.issues
|
|
46
|
+
.slice(0, 3)
|
|
47
|
+
.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
|
|
48
|
+
.join("; ");
|
|
49
|
+
logger.error({ scheduleId: event.scheduleId, reason }, "scheduled.background_task: task_context failed schema validation");
|
|
50
|
+
return { kind: "task_context_invalid", reason };
|
|
51
|
+
}
|
|
52
|
+
const ctx = parsed.data;
|
|
53
|
+
const existing = getBackgroundTask(deps.db, ctx.preGeneratedTaskId);
|
|
54
|
+
if (existing) {
|
|
55
|
+
logger.warn({ taskId: ctx.preGeneratedTaskId, scheduleId: event.scheduleId, state: existing.state }, "scheduled.background_task: row already exists for preGeneratedTaskId — skipping re-dispatch");
|
|
56
|
+
return { kind: "row_already_exists", taskId: ctx.preGeneratedTaskId };
|
|
57
|
+
}
|
|
58
|
+
createBackgroundTask(deps.db, {
|
|
59
|
+
id: ctx.preGeneratedTaskId,
|
|
60
|
+
brief: ctx.brief,
|
|
61
|
+
title: ctx.title ?? null,
|
|
62
|
+
notificationPolicy: ctx.notificationPolicy ?? "always",
|
|
63
|
+
significanceCriteria: ctx.significanceCriteria ?? null,
|
|
64
|
+
originatingChannel: ctx.originatingChannel ?? null,
|
|
65
|
+
correlationId: event.correlationId ?? null,
|
|
66
|
+
scheduleRowId: event.scheduleId,
|
|
67
|
+
tier: ctx.tier ?? null,
|
|
68
|
+
maxBudgetUsd: ctx.maxBudgetUsd ?? null,
|
|
69
|
+
createdAt: now(),
|
|
70
|
+
});
|
|
71
|
+
if (!deps.runner) {
|
|
72
|
+
markTerminal(deps.db, {
|
|
73
|
+
id: ctx.preGeneratedTaskId,
|
|
74
|
+
state: "failed",
|
|
75
|
+
outcomeDetail: "runner_unavailable",
|
|
76
|
+
finishedAt: now(),
|
|
77
|
+
report: "The background-task runner was not wired at fire time.",
|
|
78
|
+
draft: "That scheduled task couldn't start — the runner was unavailable.",
|
|
79
|
+
notify: true,
|
|
80
|
+
});
|
|
81
|
+
logger.warn({ taskId: ctx.preGeneratedTaskId, scheduleId: event.scheduleId }, "scheduled.background_task: runner not wired — marked failed (runner_unavailable)");
|
|
82
|
+
return { kind: "runner_unavailable", taskId: ctx.preGeneratedTaskId };
|
|
83
|
+
}
|
|
84
|
+
void deps.runner.runFromScheduleRow(ctx.preGeneratedTaskId).catch((err) => {
|
|
85
|
+
logger.error({ err, taskId: ctx.preGeneratedTaskId, scheduleId: event.scheduleId }, "background-task runFromScheduleRow threw — task left in pending state");
|
|
86
|
+
});
|
|
87
|
+
logger.info({ taskId: ctx.preGeneratedTaskId, scheduleId: event.scheduleId }, "scheduled.background_task dispatched to runner");
|
|
88
|
+
return { kind: "dispatched", taskId: ctx.preGeneratedTaskId };
|
|
89
|
+
}
|
|
@@ -196,6 +196,29 @@ export declare const SKILL_CURATION_OPTIMIZER_ALLOWED_TOOLS: readonly ["Read", "
|
|
|
196
196
|
* consciously.
|
|
197
197
|
*/
|
|
198
198
|
export declare const REFRESH_ARCHITECTURE_ALLOWED_TOOLS: readonly ["Read", "Glob", "Grep", "Bash(curl http://localhost:8321/api/repositories/*/architecture-section*)", "Bash(jq *)"];
|
|
199
|
+
/**
|
|
200
|
+
* BACKGROUND_TASK_RUNNER_DESIGN.md §4.5 / §4.5-bis / Phase 4 — the active
|
|
201
|
+
* delivery turn is a NO-TOOL DM turn. Its sole job is to weave the
|
|
202
|
+
* already-injected artifact (`taskContext.task_delivery.report` carries the
|
|
203
|
+
* full verbatim result) into the live conversation; the agent's reply text
|
|
204
|
+
* IS the DM (recorded by the result processor) and any deliverable files
|
|
205
|
+
* are attached by the daemon, not by the agent. So the turn needs no tools
|
|
206
|
+
* at all — and an EMPTY override structurally prevents it from taking
|
|
207
|
+
* "further action" (spawning another task, writing memory, sending mail)
|
|
208
|
+
* during what should be a pure phrasing turn. Follow-up turns ("what did it
|
|
209
|
+
* find?") are ordinary DM turns and keep the full envelope, including the
|
|
210
|
+
* `GET /api/background-task/:id` read affordance.
|
|
211
|
+
*/
|
|
212
|
+
export declare const TASK_DELIVERY_TURN_ALLOWED_TOOLS: readonly string[];
|
|
213
|
+
/**
|
|
214
|
+
* True when `taskCtx` is a synthetic `scheduled.dm` event minted by the
|
|
215
|
+
* task-delivery handler (`createScheduledDmDeliveryEvent`) — the only place
|
|
216
|
+
* that sets the `task_delivery` block. Used to pin the no-tool clamp above.
|
|
217
|
+
* Keying off this structural marker (not `event.source`) is fail-safe: the
|
|
218
|
+
* clamp only ever NARROWS the envelope, so a false positive degrades a turn
|
|
219
|
+
* to no-tool rather than widening anything.
|
|
220
|
+
*/
|
|
221
|
+
export declare function isTaskDeliveryTurn(taskCtx: AgentTaskEvent["taskContext"]): boolean;
|
|
199
222
|
/**
|
|
200
223
|
* Backends that honor the per-execute `allowedToolsOverride` clamp end-to-
|
|
201
224
|
* end. Claude consumes the list verbatim through the SDK's `dontAsk` +
|
|
@@ -207,6 +230,14 @@ export declare const REFRESH_ARCHITECTURE_ALLOWED_TOOLS: readonly ["Read", "Glob
|
|
|
207
230
|
* envelope; the operator sees an `agent_actions` row of action_type
|
|
208
231
|
* `scheduled_task_clamp_unsupported` and a clear log line.
|
|
209
232
|
*
|
|
233
|
+
* Exception — the Phase-4 task-delivery turn (`isTaskDeliveryTurn`)
|
|
234
|
+
* consumes this same set but DEGRADES rather than refuses: when the
|
|
235
|
+
* resolved backend can't enforce `[]` it still runs the delivery turn
|
|
236
|
+
* with the default envelope (logged), because failing to deliver the
|
|
237
|
+
* owner's result is worse than running the phrasing turn untooled. The
|
|
238
|
+
* clamp is keyed off `binding.main.backendId`, so — as with the refuse
|
|
239
|
+
* path — a runtime fallback to a non-claude backend is not re-evaluated.
|
|
240
|
+
*
|
|
210
241
|
* Add a backend here only after verifying its core threads
|
|
211
242
|
* `allowedToolsOverride` through to its concrete deny enforcement layer
|
|
212
243
|
* — NOT just into the CLI flag set.
|
|
@@ -227,7 +258,7 @@ export interface ScheduledTaskRunnerDeps {
|
|
|
227
258
|
* in `ROUTINE_WINDOWS` (today_refresh / evening_review / weekly_review;
|
|
228
259
|
* monthly_review is registered but has zero rows so the runner
|
|
229
260
|
* short-circuits without dispatching a session). Idempotent against
|
|
230
|
-
* the morning_routine +
|
|
261
|
+
* the morning_routine + activity_scan paths: when the upstream
|
|
231
262
|
* dispatcher already attached a `fetchReportBlock`, `executeDefault`
|
|
232
263
|
* skips re-running the pre-pass.
|
|
233
264
|
*/
|
|
@@ -465,6 +496,37 @@ export declare class ScheduledTaskRunner {
|
|
|
465
496
|
* in `buildFeedbackWorksheet`, which is 100% unit-tested.
|
|
466
497
|
*/
|
|
467
498
|
private prepareFeedbackWorksheet;
|
|
499
|
+
/**
|
|
500
|
+
* SELF_TUNING_REVIEW_CYCLE_DESIGN.md §3.1 + §3.2 / Phases 1–2 — the
|
|
501
|
+
* deterministic Measure + Recommend pre-steps. Computes the 7-day window +
|
|
502
|
+
* 7-day-prior baseline SQL aggregates over `agent_actions` /
|
|
503
|
+
* `notification_log` / the `runtime_state.self_tuning:*` ledger, reads each
|
|
504
|
+
* lesson store's byte pressure (§3.5), and composes the
|
|
505
|
+
* `<self_performance>` block via the pure
|
|
506
|
+
* `core/feedback/self-performance-prep.ts` module. The same gathered data
|
|
507
|
+
* then feeds the Phase 2 rule table (`core/feedback/tuning-recommender.ts`):
|
|
508
|
+
* the resulting pending cycle is persisted to
|
|
509
|
+
* `runtime_state.self_tuning.pending_cycle` — overwriting (and thereby
|
|
510
|
+
* expiring, §3.4 single-use ids) the previous cycle even when this week
|
|
511
|
+
* produced zero recommendations — and rendered as the
|
|
512
|
+
* `<tuning_recommendations>` block for the Phase 3c verdict step.
|
|
513
|
+
*
|
|
514
|
+
* Either field is `null` when there is nothing to inject or its step threw —
|
|
515
|
+
* the caller simply skips stamping and the weekly review proceeds
|
|
516
|
+
* unchanged. The Recommend step is failure-isolated from the Measure step:
|
|
517
|
+
* a recommender throw never drops the `<self_performance>` block.
|
|
518
|
+
*
|
|
519
|
+
* The DB handle + lesson-file FS reads live here (the dispatcher is
|
|
520
|
+
* coverage-excluded); the byte-deterministic aggregation, rule table, and
|
|
521
|
+
* rendering live in the pure modules, which are 100% unit-tested. Unlike
|
|
522
|
+
* the consolidation/re-generalization pre-steps this is NOT gated on
|
|
523
|
+
* `feedbackLearningEnabled` — it measures core daemon telemetry, not the
|
|
524
|
+
* lesson loop; nor on `selfTuningEnabled` — that flag gates Phase 3
|
|
525
|
+
* *actuation* only, while recommendation generation + verdict recording IS
|
|
526
|
+
* the Phase 2 shadow period (§7). An unreadable lesson store only drops the
|
|
527
|
+
* `<lesson_stores>` rows / the R5 input, never the whole block.
|
|
528
|
+
*/
|
|
529
|
+
private prepareSelfTuningBlocks;
|
|
468
530
|
/**
|
|
469
531
|
* FEEDBACK_LEARNING_LOOP_DESIGN.md §4 "Monthly re-generalization" / Phase 5 —
|
|
470
532
|
* the deterministic monthly pre-step. Enumerates the consolidated lesson
|