@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
|
@@ -224,7 +224,7 @@ function recordCoalescedObservation(db, params) {
|
|
|
224
224
|
// novelty_score populated. Without this, coalesced inserts only get
|
|
225
225
|
// summarized via the daemon-startup reclaim sweep — a row that lands
|
|
226
226
|
// mid-run sits at `summary_status='pending'` forever and the
|
|
227
|
-
//
|
|
227
|
+
// activity_scan skill is forced into the legacy fetch-on-doubt path.
|
|
228
228
|
if (inserted)
|
|
229
229
|
notifyObservationSummarizer(inserted.id);
|
|
230
230
|
return 1;
|
|
@@ -257,7 +257,7 @@ function recordCoalescedObservation(db, params) {
|
|
|
257
257
|
// summary describes obsolete content. Reset the summarizer-owned columns
|
|
258
258
|
// to mirror `recordObservation`'s UPSERT on payload change — without
|
|
259
259
|
// this, `summary_text` / `novelty_score` linger from the prior payload
|
|
260
|
-
// and the
|
|
260
|
+
// and the activity_scan skill consumes a stale summary as if it were
|
|
261
261
|
// current (`summary_status='done'` with `summaryStale=false`).
|
|
262
262
|
db.prepare(`UPDATE observations
|
|
263
263
|
SET change_type = ?,
|
|
@@ -99,10 +99,14 @@ function round2(value) {
|
|
|
99
99
|
function storeFileAttr(scope) {
|
|
100
100
|
return scopeStoreFile(scope) ?? "";
|
|
101
101
|
}
|
|
102
|
-
/** Collapse a one-line excerpt of a signal/lesson for an XML text node.
|
|
102
|
+
/** Collapse a one-line excerpt of a signal/lesson for an XML text node.
|
|
103
|
+
* The clip strips a trailing lone high surrogate so cutting through an
|
|
104
|
+
* astral char (emoji) can't leave a U+FFFD in the worksheet. */
|
|
103
105
|
function inline(text, max = 300) {
|
|
104
106
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
105
|
-
const clipped = flat.length > max
|
|
107
|
+
const clipped = flat.length > max
|
|
108
|
+
? `${flat.slice(0, max - 1).replace(/[\uD800-\uDBFF]$/, "")}…`
|
|
109
|
+
: flat;
|
|
106
110
|
return xmlEscape(clipped);
|
|
107
111
|
}
|
|
108
112
|
/** Authority ranking for picking a candidate's representative `src=` trailer. */
|
|
@@ -154,12 +158,20 @@ function renderLessonsScope(input, opts, out) {
|
|
|
154
158
|
? extractMarkdownSection(input.existingFileMd, "Lessons")
|
|
155
159
|
: null;
|
|
156
160
|
const existing = sectionBody ? parseLessonsSection(sectionBody) : [];
|
|
157
|
-
|
|
158
|
-
|
|
161
|
+
// `current_bytes` measures the on-disk `## Lessons` SECTION body — the
|
|
162
|
+
// §6 cap unit (`lessonsSectionByteLength` in lesson-format.ts), the same
|
|
163
|
+
// unit `enforceCaps` below derives `over_cap` from. Measuring the whole
|
|
164
|
+
// file here while `over_cap` measured the section produced a
|
|
165
|
+
// self-contradictory tag (and disagreed with the §6 unit the eviction
|
|
166
|
+
// engine actually controls).
|
|
167
|
+
const currentBytes = sectionBody
|
|
168
|
+
? Buffer.byteLength(sectionBody, "utf-8")
|
|
159
169
|
: 0;
|
|
160
170
|
// Eviction ranking: ascending score → rank 1 = evict-first. The plan
|
|
161
171
|
// (post-dedupe) tells the LLM whether the store is already over cap.
|
|
162
|
-
|
|
172
|
+
// Pass the same half-life the displayed `ranked` scores use so the plan
|
|
173
|
+
// and the ranking can never derive from two different scorings.
|
|
174
|
+
const plan = enforceCaps(existing, { maxBytes: input.caps.capBytes, maxEntries: input.caps.maxEntries }, opts.nowIso, { scopeLabel: label }, undefined, halfLife);
|
|
163
175
|
const ranked = [...existing].sort((a, b) => scoreLesson(a, opts.nowIso, undefined, halfLife) -
|
|
164
176
|
scoreLesson(b, opts.nowIso, undefined, halfLife));
|
|
165
177
|
out.push(` <scope label="${xmlEscape(label)}" store="${xmlEscape(storeFile)}" ` +
|
|
@@ -103,9 +103,13 @@ export function enforceCaps(lessons, cap, nowIso, opts, weights = DEFAULT_EVICTI
|
|
|
103
103
|
scoreLesson(a, nowIso, weights, halfLifeDays));
|
|
104
104
|
const evicted = [];
|
|
105
105
|
let keep = sorted;
|
|
106
|
-
// Entry cap first — cheap, and shrinks the byte-cap work.
|
|
106
|
+
// Entry cap first — cheap, and shrinks the byte-cap work. Reverse the
|
|
107
|
+
// overflow slice (it comes off the descending-sorted array) so `evicted`
|
|
108
|
+
// honours its documented lowest-scored-first order; the byte-cap loop
|
|
109
|
+
// below already pushes lowest-first, so the combined array stays
|
|
110
|
+
// ascending by score.
|
|
107
111
|
if (keep.length > cap.maxEntries) {
|
|
108
|
-
evicted.push(...keep.slice(cap.maxEntries));
|
|
112
|
+
evicted.push(...keep.slice(cap.maxEntries).reverse());
|
|
109
113
|
keep = keep.slice(0, cap.maxEntries);
|
|
110
114
|
}
|
|
111
115
|
const sectionOpts = {
|
|
@@ -152,13 +152,18 @@ export function parseLessonsSection(sectionBody) {
|
|
|
152
152
|
flush();
|
|
153
153
|
continue;
|
|
154
154
|
}
|
|
155
|
-
if (current &&
|
|
156
|
-
|
|
157
|
-
// the
|
|
155
|
+
if (current &&
|
|
156
|
+
(line.startsWith(" ") || line.trim().startsWith("<!--"))) {
|
|
157
|
+
// Continuation of the current lesson: indented prose, or a trailer
|
|
158
|
+
// comment the author placed on its own non-indented line.
|
|
158
159
|
current.buffer.push(line.trim());
|
|
159
160
|
}
|
|
160
161
|
else if (current) {
|
|
161
|
-
// Blank line ends the current lesson.
|
|
162
|
+
// Blank line or non-indented stray prose ends the current lesson.
|
|
163
|
+
// The stray line itself is ignored (module contract: non-lesson
|
|
164
|
+
// lines are ignored) — folding it into the preceding lesson would
|
|
165
|
+
// absorb a hand-written note into an injectable directive and
|
|
166
|
+
// re-serialize it permanently on the next consolidation.
|
|
162
167
|
flush();
|
|
163
168
|
}
|
|
164
169
|
}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
*/
|
|
38
38
|
/**
|
|
39
39
|
* Hard inject-time byte cap for the slim hourly notify-discipline variant (§6
|
|
40
|
-
* table: "slim notify-discipline subset injected to
|
|
40
|
+
* table: "slim notify-discipline subset injected to activity_scan · hard 2048 at
|
|
41
41
|
* inject"). Exported so the builder and tests share one constant.
|
|
42
42
|
*/
|
|
43
43
|
export declare const AGENT_LESSONS_SLIM_CAP_BYTES = 2048;
|
|
@@ -39,7 +39,7 @@ import { extractMarkdownSection, parseLessonsSection, } from "./lesson-format.js
|
|
|
39
39
|
import { scoreLesson } from "./eviction-scorer.js";
|
|
40
40
|
/**
|
|
41
41
|
* Hard inject-time byte cap for the slim hourly notify-discipline variant (§6
|
|
42
|
-
* table: "slim notify-discipline subset injected to
|
|
42
|
+
* table: "slim notify-discipline subset injected to activity_scan · hard 2048 at
|
|
43
43
|
* inject"). Exported so the builder and tests share one constant.
|
|
44
44
|
*/
|
|
45
45
|
export const AGENT_LESSONS_SLIM_CAP_BYTES = 2048;
|
|
@@ -69,9 +69,24 @@ function activeLessons(fileMd) {
|
|
|
69
69
|
return [];
|
|
70
70
|
return parseLessonsSection(section).filter((lesson) => !lesson.provisional && lesson.text.length > 0);
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Neutralise XML-tag breakout in lesson prose. Lesson text is
|
|
74
|
+
* LLM-synthesized during consolidation from signals that can carry
|
|
75
|
+
* untrusted excerpts, and the rendered block is framed to the model as
|
|
76
|
+
* standing directives — a body containing `</agent_lessons>` must not be
|
|
77
|
+
* able to close the wrapper and forge a sibling high-trust block. Same
|
|
78
|
+
* escape set the worksheet builders' `xmlEscape` applies to the same text
|
|
79
|
+
* on the consolidation side (`consolidation-prep.ts`).
|
|
80
|
+
*/
|
|
81
|
+
function escapeLessonText(text) {
|
|
82
|
+
return text
|
|
83
|
+
.replace(/&/g, "&")
|
|
84
|
+
.replace(/</g, "<")
|
|
85
|
+
.replace(/>/g, ">");
|
|
86
|
+
}
|
|
72
87
|
/** One lesson as an agent-facing bullet (trailer + date stripped). */
|
|
73
88
|
function bulletFor(lesson) {
|
|
74
|
-
return `- ${lesson.text}`;
|
|
89
|
+
return `- ${escapeLessonText(lesson.text)}`;
|
|
75
90
|
}
|
|
76
91
|
function wrap(style, bullets) {
|
|
77
92
|
return [style.openTag, style.preamble, ...bullets, "</agent_lessons>"].join("\n");
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* (here, 100% covered), while the route owns only the FS read + JSON assembly.
|
|
14
14
|
*/
|
|
15
15
|
export interface LessonStoreSummary {
|
|
16
|
-
/** UTF-8 byte size of the
|
|
16
|
+
/** UTF-8 byte size of the on-disk `## Lessons` section (the cap unit, §6). */
|
|
17
17
|
bytes: number;
|
|
18
18
|
/** Per-scope byte cap. */
|
|
19
19
|
capBytes: number;
|
|
@@ -32,9 +32,13 @@ export interface LessonStoreSummary {
|
|
|
32
32
|
* Summarise one lesson store from its raw file contents. A file with no
|
|
33
33
|
* `## Lessons` section (or an empty one) reports zero entries — never throws,
|
|
34
34
|
* so a hand-edited or partially-written file degrades to "empty store" rather
|
|
35
|
-
* than breaking the overview. `bytes`
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* than breaking the overview. `bytes` measures the on-disk `## Lessons`
|
|
36
|
+
* section body — the §6 cap unit (`lessonsSectionByteLength` in
|
|
37
|
+
* lesson-format.ts) the eviction scorer and the nightly worksheet's
|
|
38
|
+
* `over_cap` enforce. Measuring the whole file here previously reported a
|
|
39
|
+
* permanently-stuck `overCap: true` in the band where the section fit the
|
|
40
|
+
* cap but frontmatter + heading overhead pushed the file past it — a state
|
|
41
|
+
* no enforcement actor would ever clear.
|
|
38
42
|
*/
|
|
39
43
|
export declare function summarizeLessonStore(fileMd: string, caps: {
|
|
40
44
|
capBytes: number;
|
|
@@ -17,15 +17,19 @@ import { extractMarkdownSection, parseLessonsSection, } from "./lesson-format.js
|
|
|
17
17
|
* Summarise one lesson store from its raw file contents. A file with no
|
|
18
18
|
* `## Lessons` section (or an empty one) reports zero entries — never throws,
|
|
19
19
|
* so a hand-edited or partially-written file degrades to "empty store" rather
|
|
20
|
-
* than breaking the overview. `bytes`
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* than breaking the overview. `bytes` measures the on-disk `## Lessons`
|
|
21
|
+
* section body — the §6 cap unit (`lessonsSectionByteLength` in
|
|
22
|
+
* lesson-format.ts) the eviction scorer and the nightly worksheet's
|
|
23
|
+
* `over_cap` enforce. Measuring the whole file here previously reported a
|
|
24
|
+
* permanently-stuck `overCap: true` in the band where the section fit the
|
|
25
|
+
* cap but frontmatter + heading overhead pushed the file past it — a state
|
|
26
|
+
* no enforcement actor would ever clear.
|
|
23
27
|
*/
|
|
24
28
|
export function summarizeLessonStore(fileMd, caps) {
|
|
25
29
|
const sectionBody = extractMarkdownSection(fileMd, "Lessons");
|
|
26
30
|
const lessons = sectionBody ? parseLessonsSection(sectionBody) : [];
|
|
27
31
|
const provisional = lessons.filter((lesson) => lesson.provisional).length;
|
|
28
|
-
const bytes = Buffer.byteLength(
|
|
32
|
+
const bytes = sectionBody ? Buffer.byteLength(sectionBody, "utf-8") : 0;
|
|
29
33
|
return {
|
|
30
34
|
bytes,
|
|
31
35
|
capBytes: caps.capBytes,
|
|
@@ -54,25 +54,32 @@ function xmlEscape(value) {
|
|
|
54
54
|
function round2(value) {
|
|
55
55
|
return (Math.round(value * 100) / 100).toFixed(2);
|
|
56
56
|
}
|
|
57
|
-
/** Collapse a one-line excerpt of a lesson for an XML text node.
|
|
57
|
+
/** Collapse a one-line excerpt of a lesson for an XML text node.
|
|
58
|
+
* The clip strips a trailing lone high surrogate so cutting through an
|
|
59
|
+
* astral char (emoji) can't leave a U+FFFD in the worksheet. */
|
|
58
60
|
function inline(text, max = 300) {
|
|
59
61
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
60
|
-
const clipped = flat.length > max
|
|
62
|
+
const clipped = flat.length > max
|
|
63
|
+
? `${flat.slice(0, max - 1).replace(/[\uD800-\uDBFF]$/, "")}…`
|
|
64
|
+
: flat;
|
|
61
65
|
return xmlEscape(clipped);
|
|
62
66
|
}
|
|
63
|
-
function
|
|
64
|
-
const sectionBody = extractMarkdownSection(existingFileMd, "Lessons");
|
|
65
|
-
return sectionBody ? parseLessonsSection(sectionBody) : [];
|
|
66
|
-
}
|
|
67
|
-
function renderScope(input, activeLessons, totalEntries, opts, out) {
|
|
67
|
+
function renderScope(input, sectionBody, activeLessons, totalEntries, opts, out) {
|
|
68
68
|
const label = formatScope(input.scope);
|
|
69
69
|
const section = scopeSectionSlug(input.scope);
|
|
70
70
|
const halfLife = opts.recencyHalfLifeDays ?? DEFAULT_RECENCY_HALFLIFE_DAYS;
|
|
71
|
-
|
|
72
|
-
//
|
|
73
|
-
// (
|
|
74
|
-
//
|
|
75
|
-
//
|
|
71
|
+
// `current_bytes` / `current_entries` describe the on-disk `## Lessons`
|
|
72
|
+
// SECTION (active + provisional) — the §6 cap unit
|
|
73
|
+
// (`lessonsSectionByteLength` in lesson-format.ts), the same unit the
|
|
74
|
+
// nightly worksheet's `over_cap` and the eviction engine measure. The
|
|
75
|
+
// whole-file measure used previously disagreed with the nightly pass in a
|
|
76
|
+
// narrow band (frontmatter + `# heading` overhead), making the two
|
|
77
|
+
// worksheets contradict each other on the same store. `over_cap` covers
|
|
78
|
+
// the full entry set, not just the collapsible active subset — the LLM's
|
|
79
|
+
// Step-12 eviction targets the disk cap. The caller extracted
|
|
80
|
+
// `sectionBody` once during eligibility (a scope is only eligible when
|
|
81
|
+
// its `## Lessons` section parsed), so it is measured here verbatim.
|
|
82
|
+
const currentBytes = Buffer.byteLength(sectionBody, "utf-8");
|
|
76
83
|
const overCap = currentBytes > input.caps.capBytes || totalEntries > input.caps.maxEntries;
|
|
77
84
|
const provisionalHeld = totalEntries - activeLessons.length;
|
|
78
85
|
// Ascending score → rank 1 = lowest score = drop-first, the same convention
|
|
@@ -111,13 +118,19 @@ function renderScope(input, activeLessons, totalEntries, opts, out) {
|
|
|
111
118
|
export function buildRegeneralizationWorksheet(scopes, opts) {
|
|
112
119
|
const eligible = [];
|
|
113
120
|
for (const input of scopes) {
|
|
114
|
-
|
|
121
|
+
// Single extraction per scope — `renderScope` reuses this body for its
|
|
122
|
+
// `current_bytes` measure instead of re-extracting (the old double
|
|
123
|
+
// extraction left renderScope with an unreachable missing-section arm).
|
|
124
|
+
const sectionBody = extractMarkdownSection(input.existingFileMd, "Lessons");
|
|
125
|
+
if (!sectionBody)
|
|
126
|
+
continue;
|
|
127
|
+
const allLessons = parseLessonsSection(sectionBody);
|
|
115
128
|
// Collapse the ACTIVE set only — provisional lessons are owned by the
|
|
116
129
|
// evening promotion gate (see module header); merging them here would
|
|
117
130
|
// bypass the `ignored`-only-never-promotes guard.
|
|
118
131
|
const active = allLessons.filter((lesson) => !lesson.provisional);
|
|
119
132
|
if (active.length >= MIN_LESSONS_FOR_REGENERALIZATION) {
|
|
120
|
-
eligible.push({ input, active, totalEntries: allLessons.length });
|
|
133
|
+
eligible.push({ input, sectionBody, active, totalEntries: allLessons.length });
|
|
121
134
|
}
|
|
122
135
|
}
|
|
123
136
|
if (eligible.length === 0)
|
|
@@ -126,8 +139,8 @@ export function buildRegeneralizationWorksheet(scopes, opts) {
|
|
|
126
139
|
out.push(`<feedback_regeneralization generated_at="${xmlEscape(opts.nowIso)}" ` +
|
|
127
140
|
`scopes="${eligible.length}">`);
|
|
128
141
|
let lessonCount = 0;
|
|
129
|
-
for (const { input, active, totalEntries } of eligible) {
|
|
130
|
-
renderScope(input, active, totalEntries, opts, out);
|
|
142
|
+
for (const { input, sectionBody, active, totalEntries } of eligible) {
|
|
143
|
+
renderScope(input, sectionBody, active, totalEntries, opts, out);
|
|
131
144
|
lessonCount += active.length;
|
|
132
145
|
}
|
|
133
146
|
out.push("</feedback_regeneralization>");
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Tuning Review Cycle — Measure stage (SELF_TUNING_REVIEW_CYCLE_DESIGN.md
|
|
3
|
+
* §3.1, Phase 1).
|
|
4
|
+
*
|
|
5
|
+
* The daemon-side, deterministic Measure step ($0 — LLM tokens buy judgment
|
|
6
|
+
* only, P1). On the weekly-review dispatch it computes SQL aggregates over
|
|
7
|
+
* `agent_actions`, `notification_log`, and the `runtime_state` self-tuning
|
|
8
|
+
* ledger for a 7-day window plus a 7-day-prior baseline (trend column), and
|
|
9
|
+
* renders one compact `<self_performance>` block — hard-capped at
|
|
10
|
+
* {@link SELF_PERFORMANCE_MAX_BYTES} — so the weekly review's "Metrics (agent
|
|
11
|
+
* side)" section copies daemon-computed facts instead of paying Sonnet prices
|
|
12
|
+
* to re-count them.
|
|
13
|
+
*
|
|
14
|
+
* Two layers, mirroring `consolidation-prep.ts`:
|
|
15
|
+
* - {@link gatherSelfPerformanceData} — the single DB read (side-effect
|
|
16
|
+
* free): per-`action_type` run/cost/duration aggregates (`agent_actions`
|
|
17
|
+
* has no process_key column; `action_type` carries the routine identity),
|
|
18
|
+
* the `routine.fetch_window` empty-run rate per integration (from the
|
|
19
|
+
* fan-out audit rows' `detail.prePass` payload the runner persists), the
|
|
20
|
+
* `activity_scan.gate` stage distribution (from `buildGateAuditDetail`'s
|
|
21
|
+
* historical per-tick rows), per-notification-type `user_reaction`
|
|
22
|
+
* breakdowns (the first reader of the column `signal-detector.ts`
|
|
23
|
+
* populates), and the `runtime_state.self_tuning:*` ledger.
|
|
24
|
+
* - {@link buildSelfPerformanceBlock} — pure renderer. Deterministic
|
|
25
|
+
* byte-capped output: per-section row budgets shrink one row at a time
|
|
26
|
+
* (largest section first) until the block fits the cap, and clipped rows
|
|
27
|
+
* surface as `omitted="N"` so truncation is never silent.
|
|
28
|
+
*
|
|
29
|
+
* Phase 1 carries no actuator: nothing here writes config, schedules, or
|
|
30
|
+
* lessons. Later phases (Recommend / Judge / Actuate) consume the same data
|
|
31
|
+
* shape; {@link SELF_TUNING_LEDGER_PREFIX} is exported so the Phase 3
|
|
32
|
+
* actuator writes the ledger keys this module already reads.
|
|
33
|
+
*/
|
|
34
|
+
import type Database from "better-sqlite3";
|
|
35
|
+
/** Measurement window length; the baseline is the same span immediately prior. */
|
|
36
|
+
export declare const SELF_PERFORMANCE_WINDOW_DAYS = 7;
|
|
37
|
+
/** §3.1 — hard cap on the rendered `<self_performance>` block, in UTF-8 bytes. */
|
|
38
|
+
export declare const SELF_PERFORMANCE_MAX_BYTES = 1500;
|
|
39
|
+
/**
|
|
40
|
+
* §3.4 ledger key prefix. Phase 3's actuator writes
|
|
41
|
+
* `runtime_state.self_tuning:<key> = {prev, applied_at, baselineMetric, rule}`;
|
|
42
|
+
* Phase 1 already reads (and renders) whatever sits under the prefix so the
|
|
43
|
+
* weekly review sees applied changes the cycle they land.
|
|
44
|
+
*/
|
|
45
|
+
export declare const SELF_TUNING_LEDGER_PREFIX = "self_tuning:";
|
|
46
|
+
/** Fan-out audit rows carry the fetcher event's type as `action_type`. */
|
|
47
|
+
export declare const FETCH_WINDOW_ACTION_TYPE = "routine.fetch_window";
|
|
48
|
+
/** Per-tick gate audit rows (`buildGateAuditDetail` payload in `detail`). */
|
|
49
|
+
export declare const ACTIVITY_SCAN_GATE_ACTION_TYPE = "activity_scan.gate";
|
|
50
|
+
export interface ActionTypeStats {
|
|
51
|
+
actionType: string;
|
|
52
|
+
runs: number;
|
|
53
|
+
success: number;
|
|
54
|
+
partial: number;
|
|
55
|
+
failed: number;
|
|
56
|
+
skipped: number;
|
|
57
|
+
costUsd: number;
|
|
58
|
+
/** Median over rows with a non-null `duration_ms`; null when none have one. */
|
|
59
|
+
p50DurationMs: number | null;
|
|
60
|
+
}
|
|
61
|
+
export interface FetchWindowIntegrationStats {
|
|
62
|
+
integrationKey: string;
|
|
63
|
+
/** Completed fan-out attempts (prePass status success|partial). */
|
|
64
|
+
runs: number;
|
|
65
|
+
/** Completed attempts with `fetched=0 ∧ posted=0` (§3.1 empty-run def). */
|
|
66
|
+
empty: number;
|
|
67
|
+
}
|
|
68
|
+
export interface HourlyGateStats {
|
|
69
|
+
/** Every audited cron tick, including rows whose detail failed to parse. */
|
|
70
|
+
ticks: number;
|
|
71
|
+
stage0: number;
|
|
72
|
+
/**
|
|
73
|
+
* Lite-triage ticks that stayed silent. The writer persists the alias
|
|
74
|
+
* `stage2_log_only` verbatim (`dispatcher-activity-scan.ts:logGateAuditRow`
|
|
75
|
+
* overrides `stage_reached` with the applied decision, and a Stage-2 tick
|
|
76
|
+
* only ever settles to log_only-silent or stage3); a bare `stage2` is
|
|
77
|
+
* accepted defensively but never occurs in production rows.
|
|
78
|
+
*/
|
|
79
|
+
stage2: number;
|
|
80
|
+
/**
|
|
81
|
+
* Full-session escalations that actually ran. Rows the legacy
|
|
82
|
+
* min-observations floor short-circuited (`result='skipped'` with
|
|
83
|
+
* `stage_reached='stage3'`) are excluded — no session ran, no spend.
|
|
84
|
+
*/
|
|
85
|
+
stage3: number;
|
|
86
|
+
/**
|
|
87
|
+
* …of those, ticks whose `gate_reason` was the low-signal fallback (R3).
|
|
88
|
+
* Forced ticks (`!run` / run-now, `detail.forced=true`) are excluded:
|
|
89
|
+
* they escalate at any signal level and say nothing about the gate.
|
|
90
|
+
*/
|
|
91
|
+
stage3LowSignal: number;
|
|
92
|
+
/** …of those, ticks whose snapshot max novelty was ≤ 1 (null counts as ≤1). */
|
|
93
|
+
stage3LowSignalLowNovelty: number;
|
|
94
|
+
}
|
|
95
|
+
export interface NotificationTypeStats {
|
|
96
|
+
notificationType: string;
|
|
97
|
+
/** Rows with status delivered|batched (suppressed/failed are not "sent"). */
|
|
98
|
+
sent: number;
|
|
99
|
+
replied: number;
|
|
100
|
+
acted: number;
|
|
101
|
+
corrected: number;
|
|
102
|
+
ignored: number;
|
|
103
|
+
/** No-reaction-yet (incl. unrecognised reaction values, clamped ≥ 0). */
|
|
104
|
+
pending: number;
|
|
105
|
+
}
|
|
106
|
+
export interface SelfPerformanceWindow {
|
|
107
|
+
actions: ActionTypeStats[];
|
|
108
|
+
fetchWindow: FetchWindowIntegrationStats[];
|
|
109
|
+
gate: HourlyGateStats;
|
|
110
|
+
notifications: NotificationTypeStats[];
|
|
111
|
+
}
|
|
112
|
+
export interface SelfTuningLedgerEntry {
|
|
113
|
+
/** Knob name — the runtime_state key with the prefix stripped. */
|
|
114
|
+
key: string;
|
|
115
|
+
prev: unknown;
|
|
116
|
+
appliedAt: string | null;
|
|
117
|
+
rule: string | null;
|
|
118
|
+
/**
|
|
119
|
+
* §3.4 — the rule's target metric captured at apply time, so the weekly
|
|
120
|
+
* review can compare it against the current `<self_performance>` numbers
|
|
121
|
+
* (the "measured effect" §3.1 asks the ledger section to carry). Absent
|
|
122
|
+
* until Phase 3's actuator writes it.
|
|
123
|
+
*/
|
|
124
|
+
baselineMetric?: unknown;
|
|
125
|
+
/**
|
|
126
|
+
* §3.4 — stamped by the Phase 3 auto-revert monitor. Present means the
|
|
127
|
+
* change regressed and was rolled back; the Phase 2 recommender reads it
|
|
128
|
+
* to apply the extended 28-day cool-down (vs the normal 14-day
|
|
129
|
+
* hysteresis) so the apply→revert→re-apply cycle can't flap.
|
|
130
|
+
*/
|
|
131
|
+
revertedAt?: string;
|
|
132
|
+
/**
|
|
133
|
+
* §3.4 — stamped by the auto-revert monitor after a clean 7-day verify
|
|
134
|
+
* window (`pass`, `no_baseline`, …). Rendered so the weekly judge can
|
|
135
|
+
* tell a verified-clean change from one still inside its window.
|
|
136
|
+
*/
|
|
137
|
+
verifyResult?: string;
|
|
138
|
+
}
|
|
139
|
+
export interface SelfPerformanceData {
|
|
140
|
+
windowDays: number;
|
|
141
|
+
current: SelfPerformanceWindow;
|
|
142
|
+
baseline: SelfPerformanceWindow;
|
|
143
|
+
ledger: SelfTuningLedgerEntry[];
|
|
144
|
+
}
|
|
145
|
+
/** §3.5 — lesson-store byte pressure, the standing cost multiplier to watch. */
|
|
146
|
+
export interface LessonStoreUtilization {
|
|
147
|
+
/** Canonical scope label — `agent` or `agent:<slug>`. */
|
|
148
|
+
scope: string;
|
|
149
|
+
/** UTF-8 byte size of the `## Lessons` section body (the §6 cap unit). */
|
|
150
|
+
bytes: number;
|
|
151
|
+
capBytes: number;
|
|
152
|
+
entries: number;
|
|
153
|
+
/** Median `ev=` across all entries (R5's evidence signal); null when empty. */
|
|
154
|
+
medianEv: number | null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The single DB read. Computes the current window `[now − windowDays, now)`
|
|
158
|
+
* and the baseline window `[now − 2·windowDays, now − windowDays)` over
|
|
159
|
+
* `agent_actions` / `notification_log` (both store SQLite UTC
|
|
160
|
+
* `YYYY-MM-DD HH:MM:SS` timestamps, so lexicographic comparison against
|
|
161
|
+
* `formatSqliteDatetime` cutoffs is exact), plus the self-tuning ledger.
|
|
162
|
+
*/
|
|
163
|
+
export declare function gatherSelfPerformanceData(db: Database.Database, opts: {
|
|
164
|
+
now: Date;
|
|
165
|
+
windowDays?: number;
|
|
166
|
+
}): SelfPerformanceData;
|
|
167
|
+
/**
|
|
168
|
+
* §3.5 — summarise one lesson store's byte pressure from its raw file
|
|
169
|
+
* contents. Pure (the caller does the FS read); a file with no `## Lessons`
|
|
170
|
+
* section degrades to an empty store, never a throw. `medianEv` carries the
|
|
171
|
+
* evidence signal R5's Phase 2 rule keys on (utilization > 90% with median
|
|
172
|
+
* evidence ≤ 1), so the measurement lands one phase ahead of the rule.
|
|
173
|
+
*/
|
|
174
|
+
export declare function summarizeLessonStoreUtilization(scope: string, fileMd: string, capBytes: number): LessonStoreUtilization;
|
|
175
|
+
/**
|
|
176
|
+
* Compose the `<self_performance>` block. Returns `null` when there is no
|
|
177
|
+
* telemetry at all (fresh install) so the caller stamps nothing — no empty
|
|
178
|
+
* block in the prompt. The byte cap is a hard guarantee: row budgets shrink
|
|
179
|
+
* until the block fits; in the (synthetic) case where even the skeleton
|
|
180
|
+
* exceeds the cap, a minimal self-closing element is emitted instead.
|
|
181
|
+
*/
|
|
182
|
+
export declare function buildSelfPerformanceBlock(data: SelfPerformanceData, opts: {
|
|
183
|
+
generatedAt: string;
|
|
184
|
+
lessonStores?: ReadonlyArray<LessonStoreUtilization>;
|
|
185
|
+
maxBytes?: number;
|
|
186
|
+
}): string | null;
|