Skip to content

Make Quota Burn run existing CoS and app scheduled tasks #6372

Description

@atomantic

Problem / Goal

Make Scheduled Tasks the source of work definitions for Quota Burn. Users should select an existing PortOS CoS scheduled task or an app-specific custom scheduled task and configure its burn settings. New actions belong in Scheduled Tasks as on-demand work runnable through the ordinary task system, rather than in a separate quota-burn automation catalog.

All audit actions must support File issues only versus Implement fixes, with the selected mode enforced through the ordinary task generation and completion contract.

Context

  • server/lib/quotaBurnPresets.js defines 14 copied prompt presets. server/routes/quotaBurn.js exposes them and the separate job-type catalog. client/src/components/quotaBurn/{FamilyCard,JobRow,PresetPicker}.jsx lets users create standalone prompt jobs. Preset selection copies text; stored jobs do not reliably retain preset identity.
  • The requested scheduled audit coverage already exists: server/lib/auditCatalog.js maps every preset to a shipped scheduled audit, and auditCatalog.test.js guards the mapping. server/services/taskScheduleRegistry.js ships these as on-demand defaults. Reuse them; do not add duplicates or replace established missions with a generic audit.
  • Preset → scheduled type: ux-auditux; a11y-auditaccessibility; mobile-auditmobile-responsive; resilience-auditerror-handling; perf-auditperformance; test-gap-audittest-coverage; simplify-auditsimplify; data-safety-auditdata-safety; docs-auditdocumentation; security-auditsecurity; api-contract-auditapi-contract; react-lifecycle-auditreact-lifecycle; observability-auditobservability; copy-auditcopy.
  • Scheduled audits already use taskMetadata.fileIssues and shared mode banners in auditCatalog.js. Some existing scheduled defaults implement fixes; legacy burn presets are issues-only. Migration must not silently turn an audit into code-writing work.
  • Built-in tasks use taskSchedule.js#triggerOnDemandTask and cosTaskGenerator.js; app custom tasks are autonomous jobs, with generation in server/services/autonomousJobs/skillTemplates.js and manual execution in server/routes/cosJobRoutes.js. They are different persisted identities and execution paths. The latter manual endpoint deliberately bypasses approval and revives/force-spawns tasks: automated burns must not inherit those privileges.
  • quotaBurnJobs/agentPrompt.js queues directly through cosTaskStore.js. quotaBurnRunner.js, quotaBurnCompletions.js, and quotaBurnDenials.js own ordered dispatch, run-once state, continuation, quota provenance and refusal handling. There are also programmatic universe-bible-describe and universe-bible-images jobs; their behavior must remain available through scheduled actions.

Proposed approach

  1. Use the existing task catalogs. Retain the 14 scheduled audit counterparts and their mode controls. Make scheduled definitions/missions canonical; keep legacy preset renderings only where migration recognition or compatibility needs them. New shipped actions default to on-demand and never spend at boot. Preserve existing schedules, enabled states, customized prompts, and modes.

  2. Represent a burn step as a task reference plus invocation settings. Use a discriminated reference for a built-in scheduled type (plus validated target app where required) or a custom scheduled job ID (whose app scope is authoritative). Keep the burn step ID stable and retain order, enabled state, label, run-once state and family settings. Expose provider/model/effort and supported run parameters as explicit per-invocation overrides; unset values inherit the task's saved settings. Overrides do not edit the underlying schedule. A provider pin must belong to the selected burn family; absent pins resolve inside that family, never fall back to another family's subscription. Show the effective settings and mode before saving/running.

  3. Add a shared invocation path, not an HTTP loopback or synthetic free-form task. Resolve and validate the reference, reuse canonical task generation, and pass immutable run overrides through to the resulting task. Add a distinct quota-burn origin carrying family, limiting-reset, burn-step and request/task identity. Keep finite single-invocation semantics: selecting a perpetual task must not restart or drain its perpetual loop. Preserve the built-in master Improve, enabled, feature, scope and invocation eligibility gates and the custom-job approval/lifecycle rules. Restrict the picker to eligible AI agent tasks and explicitly supported programmatic scheduled handlers; exclude shell jobs, unrelated scripts and system-managed-only actions. Deleted, disabled, mismatched-scope or incompatible tasks remain visible as unavailable steps with an actionable reason and no dispatch or quota charge. Force may bypass the existing quota gates only, not task eligibility or approval.

For pending selection, define a shared countPending → { count, detail, context? } contract on resolved references. An eligible AI agent task reports one ready unit after eligibility and pending/running checks; an ineligible or already active task reports zero with its reason. Programmatic handlers supply their domain backlog count. The runner retains first-enabled-unspent-with-positive-count selection; zero-work steps are skipped. Probes must not enqueue requests or call AI providers.

  1. Preserve accounting across asynchronous dispatch. Tie accepted requests to their eventual task IDs. Probe/status reads remain side-effect free. An already pending/running equivalent scheduled invocation must not enqueue a second run or consume the cap. Charge the cap and run-once ledger exactly once when work is actually queued/accepted for execution, not merely when an on-demand request that may later be refused is recorded. Pending reservations must prevent another cycle queuing the same step; rejection/cancellation before dispatch releases them. Preserve task provenance through persistence, restart and completion so refusal blocks, cooldown exemptions and completion continuation still work. Ordinary schedule runs must not be counted as burns or consume a burn step's one-shot state.

  2. Enforce audit mode end to end. Use the shared mode contract for scheduled audits and eligible custom agent tasks. File-issues mode must forward noCodeOutput, no expected code changes, and appropriate worktree/PR/simplify settings through both ordinary and quota-triggered paths. It must never emit commit/push/PR/auto-merge instructions or fail/retry merely because there is no diff. Implement mode uses the task's normal code-delivery policy. Keep saved defaults intact; migrated issue-only burns get an explicit true override even when the corresponding scheduled default is false. Do not present an issues-only toggle for programmatic image/description handlers that cannot implement it.

  3. Move existing programmatic burn actions into Scheduled Tasks. Register enabled ON_DEMAND scheduled handlers (no interval or clock-due run) for bible description and image work, using the existing domain services/media queue, parameter descriptors and side-effect-free pending probes. Retain explicit scope, depth/backend/batch settings, describe-before-render ordering, family affinity and existing no-work behavior. Preserve the opaque probe-to-run context handoff so dispatch does not repeat expensive scans; execution also works without context, including a forced/manual invocation. Manual and quota invocations share the same handler; no duplicate implementation or fresh provider calls from catalog/status reads. Future burn actions extend the scheduled catalog and declare eligibility, rather than adding quota-only executors.

  4. Migrate without rewriting user intent. Add an applied-list migration and compatible readers/validation for legacy burn plans. Recognized unmodified shipped prompts can reference their scheduled counterpart with issues-only mode and all material execution overrides preserved. Customized or ambiguous prompts become disabled-from-clock, on-demand custom scheduled tasks in the original app scope, preserving their text and workflow settings; the original enabled burn step references them. Do not infer a shipped identity from a label or a partially matching mission if that loses edits. Preserve job IDs, family order, disabled states, dispatch/denial/completion ledgers and run-once/re-arm behavior. Convert the two programmatic types to scheduled handler references. Missing targets remain unresolved and non-runnable without deleting their settings. Handle partial/repeated migration without duplicate custom tasks. Follow docs/STORAGE.md, migration-owned-path rules, and prompt version/previous-default rules where applicable; add no seed that preempts derived migration output. Old client payloads must not silently downgrade references or duplicate automations. Normalize legacy payloads through the same conversion service before saving or dispatching; until conversion succeeds, leave the step unavailable with a migration reason rather than executing a parallel legacy path. Freeze old enum/preset renderings as compatibility/migration inputs only. Retire the live JOB_MODULES dispatch registry and direct agentPrompt executor once references are wired; move programmatic implementations behind shared scheduled handlers and keep no independently maintained quota-only execution path.

  5. Support genuinely on-demand custom jobs. server/services/autonomousJobs/constants.js and scheduler.js currently offer recurring intervals only. Add explicit on-demand cadence across schema, CRUD, due/next-due calculations, timer registration and client/src/components/apps/tabs/CustomTasksSection.jsx. Make the cadence first-class in resolveIntervalMs (no interval, e.g. null), never falling through to its daily default, and ensure every due/registration consumer handles that sentinel explicitly. An enabled on-demand job is manually/quota runnable but never clock-due; do not emulate this by disabling a weekly job. Preserve existing recurring cadences and job:spawned bookkeeping. Do not reintroduce the retired per-app quota-burn scheduled task type.

  6. Replace the Quota Burn editor. Offer a searchable/grouped task picker (PortOS scheduled tasks and app custom scheduled tasks), target selection where supported, shared settings controls, and a link to view/edit/create the source task. Remove preset-copy/free-text automation creation from Quota Burn. Creating custom work happens in Scheduled Tasks with on-demand as the default. Keep the existing family quota controls, ordering, pending/skip feedback, manual run and re-arm affordances; gate dependent runs on saved settings. Removing a burn step never deletes its scheduled task. Update docs/QUOTA-BURN.md, relevant API/CoS documentation and extension guidance.

Acceptance criteria

  • All 14 existing audit presets resolve to exactly one shipped scheduled counterpart with working issues-only/implement behavior; no duplicate defaults or new automatic spend on install/upgrade.
  • Users can select and run a built-in task against its supported target or an app custom task from Quota Burn, and can run the same definition through Scheduled Tasks. Source settings stay unchanged by burn overrides.
  • Migrating representative current/older presets, customized prompts, disabled/missing targets and spent one-shot steps preserves intent and history; re-running or interrupting migration creates no duplicate tasks or extra runs.
  • Route/service tests exercise resolved settings, scope validation, disabled/feature/Improve/approval refusal, wrong-family provider pins, dangling references, and legacy payload compatibility.
  • Workflow tests cover accepted execution, deferred request rejection, duplicate scheduled/burn invocation, restart, completion continuation, provider refusal, one-shot/re-arm, and force semantics with no double accounting or perpetual-loop revival.
  • A generated-task/prompt boundary test proves issues-only runs cannot acquire code-shipping instructions or no-diff retries, including custom tasks; implement mode retains normal delivery settings.
  • An enabled on-demand custom job remains never-due across save, reload, restart and elapsed time; interval conversion cannot silently turn it into a daily job.
  • Pending probes return one ready unit for eligible agent tasks, skip inactive/missing/already-active work, and use domain backlog counts for programmatic tasks, preserving ordered selection without side effects.
  • Programmatic description/image actions remain configurable and runnable with the same bounded work and family affinity through scheduled execution; listing/probing them spends nothing, probe context is reused, and execution without probe context still works.
  • Rendered UI tests cover grouped task selection, effective settings/mode, source edit/create links, stale references, and Run Now save gating. Update existing quota/preset tests to prove shared catalog behavior instead of maintaining a second automation catalog.
  • Documentation describes adding burn actions by creating on-demand scheduled tasks and explains inheritance, overrides, migration and eligibility.

Out of scope

Changing quota thresholds/provider telemetry, enabling burns by default, deleting existing user schedules, implementing audit findings, general scheduler replacement, or extending federation of private scheduled records. This is one cohesive task-reference and execution migration, not a new automation product.

Decomposed into

This is an epic. It ships as the per-slice children below, never as one PR. Each child is independently shippable in one PR; the dependency notes in each body give a sane order. Tick a box when its child merges, and close this issue when the last box is ticked.

Requirement 1 ("use the existing task catalogs, add no duplicate defaults, no new automatic spend") is a constraint carried as an acceptance criterion in #6376, #6377, #6380 and #6381 rather than a slice of its own — the 14 audit counterparts already exist in server/lib/auditCatalog.js.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    decomposedEpic already split into per-slice child issueseffort:highDispatch reasoning effort: highenhancementNew feature or requestepicUmbrella/tracking issue — shipped as per-slice children, never as one PRmodel:heavyDispatch capability: strongest available coding modelplanTracked by /do:replanplanner:gpt-6-astraPlan authored by the gpt-6-astra model

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions