Skip to content

fix: wrapper commands run straight through, and a smaller memory boost - #25

Merged
SpoBo merged 1 commit into
masterfrom
vincent/taskguard-issue-24
Oct 12, 2026
Merged

SpoBo merged 1 commit into
masterfrom
vincent/taskguard-issue-24

Conversation

@SpoBo

@SpoBo SpoBo commented Oct 12, 2026

Copy link
Copy Markdown
Owner

Closes #24.

Problem

Agents run taskguard bun run ci:local and taskguard sh -c "git fetch … && git merge … && bun install && bun run ci:local". Inside, turbo starts package scripts that call taskguard again; a nested call runs straight through, so the whole pipeline was one job. It learned "max of the last 10 runs": a full build (20 GB) also when turbo's cache left almost nothing to do (0.1 GB). These wrappers waited 995 minutes in 17 days on one machine, and held 20 GB booked while they ran.

Change

  1. Wrappers run straight through. A nested call leaves a note for the job it runs in (nested/<outer>.<pid> in the state directory). At its end the job records how many it got (runs.nested_jobs). A command where any of its last runs had nested jobs runs straight through, with one line saying so; the jobs inside it then queue on their own, each by its own need. "Any of the last runs" covers a run where turbo's cache started nothing.
    • Stays queued: long-lived jobs (the dev stack's start-up builds belong to its claim), jobs in a pool, jobs with a minimum.
    • taskguard prune 'KEY' --apply forgets the history, so the command queues again.
    • Parts of a wrapper that do not call taskguard (git merge, bun install) now run unguarded, as they do when run bare.
  2. Smaller memory boost. A run starved of memory raises the next need by 25% only when its peak reached 90% of its need. Outside the wrappers, 340 of 344 boosted runs never used the extra room (8.4 GB-hours booked for nothing).

Tests

  • a_command_that_wraps_taskguard_jobs_runs_straight_through_next_time (CLI, real binary): first run queued with nested_jobs = 1, second run straight through, inner job recorded on its own.
  • a_run_with_jobs_inside_it_makes_its_command_a_wrapper, a_starved_run_raises_the_need_only_when_it_reached_it, nested_calls_leave_notes_for_their_outer_job.

Mixed versions

  • Database: one new nullable column, nested_jobs, in runs and pruned_runs (added on open), and in RUN_COLUMNS. Older versions insert NULL and ignore it; an older prune drops the value, which only makes the command queue again.
  • No change to queue::Entry, machine::MachineSample, or job keys.
  • An older version runs a wrapper as one job, as before. An inner call of an older version leaves no note, so its outer job is not learned as a wrapper.

🤖 Generated with Claude Code

A command that wraps other taskguard jobs, such as `taskguard bun run
ci:local` around a turbo run, was queued as one job. It booked the memory
of its biggest run, a full build of up to 20 GB, also when turbo's cache
left almost nothing to do, and the jobs inside it ran unqueued under its
claim. On one machine such wrappers waited 995 minutes in 17 days.

Each nested call now leaves a note for the job it runs in
(`nested/<outer>.<pid>`), and the run records how many it got (new
nullable column `nested_jobs`, in `runs` and `pruned_runs`). A command
whose last runs started taskguard jobs inside them runs straight through,
with one line saying so, and the jobs inside it queue on their own. A
long-lived job, a job in a pool, and a job with a minimum stay queued.

A run starved of memory now raises the next need by 25% only when it
reached 90% of its need. Outside the wrappers, 340 of 344 boosted runs
never used the extra room.

Closes #24

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@SpoBo
SpoBo merged commit cfd962d into master Oct 12, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Jobs wait for memory that nobody will use

1 participant