Problem / Goal
Existing installs have burn plans in data/cos/quota-burn.json holding copied prompt text keyed by QUOTA_BURN_JOB_TYPE. Once burn steps are task references, those plans must be converted without rewriting user intent — and the now-dead quota-only execution path retired.
Scope
Migration (scripts/migrations/, next free number after 355, tracked in data/migrations.applied.json, plus a conversion service the readers share):
Recognition rule — reuse migration 305, do not re-invent it. Preset identity is persisted nowhere: upgradeStoredAuditPrompt (server/lib/quotaBurnPresets.js) re-derives it by matching the MISSION half of a stored prompt (the text above AUDIT_CONTRACT_HEADING) against a shipped preset, gated on all SHIPPED_CONTRACT_ANCHORS being present and every bold heading belonging to SHIPPED_CONTRACT_HEADINGS. Migration 294 used a strict byte match and recognized nothing; 305 replaced it with this mission-half rule. Copy 305.
- A burn step whose prompt is a recognized unmodified shipped preset (
server/lib/quotaBurnPresets.js, mapped by server/lib/auditCatalog.js — ux-audit→ux, a11y-audit→accessibility, mobile-audit→mobile-responsive, resilience-audit→error-handling, perf-audit→performance, test-gap-audit→test-coverage, simplify-audit→simplify, data-safety-audit→data-safety, docs-audit→documentation, security-audit→security, api-contract-audit→api-contract, react-lifecycle-audit→react-lifecycle, observability-audit→observability, copy-audit→copy) references its scheduled counterpart with issues-only mode and all material execution overrides preserved.
- A customized or ambiguous prompt becomes a disabled-from-clock, on-demand custom scheduled task in the original app scope, preserving its text and workflow settings; the original enabled burn step references it. Never infer a shipped identity from a label or a partial mission match if that would lose edits.
- The two programmatic types convert to scheduled handler references.
- Preserve job IDs, family order, disabled states, dispatch/denial/completion ledgers, and run-once / re-arm behavior. Missing targets stay unresolved and non-runnable without deleting their settings.
- Handle partial and repeated migration with no duplicate custom tasks and no extra runs.
Migration rules (AGENTS.md). This migration DERIVES data/cos/quota-burn.json content from the install's existing records, so it ships no data.reference/ seed and gates on the presence of its input, never the absence of its output. Declare the path in scripts/lib/migrationOwnedPaths.js.
Compat + retirement.
- Old client payloads must not silently downgrade a reference or duplicate an automation. Normalize legacy payloads through the same conversion service before saving or dispatching; until conversion succeeds, the step stays unavailable with a migration reason rather than executing a parallel legacy path.
- Freeze
QUOTA_BURN_JOB_TYPE / QUOTA_BURN_JOB_CATALOG / quotaBurnPresets.js as compatibility-and-migration inputs only.
- Retire the live
JOB_MODULES dispatch registry (server/services/quotaBurnJobs/index.js) and the direct agentPrompt.js executor. agentPrompt.js queues via addTask(..., 'internal') and stamps quotaBurnFamily / quotaBurnLimitingResetAt — provenance cosTaskGenerator.js#isCooldownExemptTask reads, so it must keep arriving from the new burn origin. Programmatic implementations live behind the shared scheduled handlers; keep no independently maintained quota-only execution path.
Acceptance criteria
Notes
Depends on the reference-model, programmatic-handler, and shared-invocation-path children. Use placeholder data in every committed fixture — never a record copied from a live install (AGENTS.md, Sensitive Data & Privacy).
Part of #6372
When this ships, tick its box in the ## Decomposed into checklist on #6372. If it is the last unchecked box, close #6372.
Problem / Goal
Existing installs have burn plans in
data/cos/quota-burn.jsonholding copied prompt text keyed byQUOTA_BURN_JOB_TYPE. Once burn steps are task references, those plans must be converted without rewriting user intent — and the now-dead quota-only execution path retired.Scope
Migration (
scripts/migrations/, next free number after 355, tracked indata/migrations.applied.json, plus a conversion service the readers share):Recognition rule — reuse migration 305, do not re-invent it. Preset identity is persisted nowhere:
upgradeStoredAuditPrompt(server/lib/quotaBurnPresets.js) re-derives it by matching the MISSION half of a stored prompt (the text aboveAUDIT_CONTRACT_HEADING) against a shipped preset, gated on allSHIPPED_CONTRACT_ANCHORSbeing present and every bold heading belonging toSHIPPED_CONTRACT_HEADINGS. Migration 294 used a strict byte match and recognized nothing; 305 replaced it with this mission-half rule. Copy 305.server/lib/quotaBurnPresets.js, mapped byserver/lib/auditCatalog.js—ux-audit→ux,a11y-audit→accessibility,mobile-audit→mobile-responsive,resilience-audit→error-handling,perf-audit→performance,test-gap-audit→test-coverage,simplify-audit→simplify,data-safety-audit→data-safety,docs-audit→documentation,security-audit→security,api-contract-audit→api-contract,react-lifecycle-audit→react-lifecycle,observability-audit→observability,copy-audit→copy) references its scheduled counterpart with issues-only mode and all material execution overrides preserved.Migration rules (AGENTS.md). This migration DERIVES
data/cos/quota-burn.jsoncontent from the install's existing records, so it ships nodata.reference/seed and gates on the presence of its input, never the absence of its output. Declare the path inscripts/lib/migrationOwnedPaths.js.Compat + retirement.
QUOTA_BURN_JOB_TYPE/QUOTA_BURN_JOB_CATALOG/quotaBurnPresets.jsas compatibility-and-migration inputs only.JOB_MODULESdispatch registry (server/services/quotaBurnJobs/index.js) and the directagentPrompt.jsexecutor.agentPrompt.jsqueues viaaddTask(..., 'internal')and stampsquotaBurnFamily/quotaBurnLimitingResetAt— provenancecosTaskGenerator.js#isCooldownExemptTaskreads, so it must keep arriving from the new burn origin. Programmatic implementations live behind the shared scheduled handlers; keep no independently maintained quota-only execution path.Acceptance criteria
trueoverride even where the shipped scheduled default isfalse.data.reference/seed for its output path, gates on its input, and the path is listed inscripts/lib/migrationOwnedPaths.js(its guard test passes).JOB_MODULESand the directagentPromptexecutor are gone, with their behavior tests re-pointed at the shared handlers rather than deleted.Notes
Depends on the reference-model, programmatic-handler, and shared-invocation-path children. Use placeholder data in every committed fixture — never a record copied from a live install (AGENTS.md, Sensitive Data & Privacy).
Part of #6372
When this ships, tick its box in the
## Decomposed intochecklist on #6372. If it is the last unchecked box, close #6372.