Skip to content

Local dogfood failure triage

praetorctl dogfood repairs turns a completed suite report into a private review plan. It connects actual failed dogfood cases to the offline task router. It does not launch a coding CLI, call a provider, change source files or publish a repair.

praetorctl dogfood repairs \
  --report /existing/private/suite-run/report.json \
  --routing-config .config/models/routing.yaml \
  --task ci_debugging --input-tokens 2000 --output-tokens 1000 \
  --max-cost 0.02 --output /existing/private/review-plan

The parent output directory must exist. The command creates a new directory with mode 0700 and plan.json with mode 0600; existing destinations fail. Standard output contains status, job count, estimated cost and report fingerprint only. The full private plan retains diagnostic excerpts and explicitly named source paths, so it belongs outside a public checkout.

Evidence and bounds

The report must be a completed version 1 verification with 1–8 uniquely named cases. Planned, unfinished, empty and contradictory reports fail. Successful transcript cases require complete page evidence with consistent fresh ingestion and replay counters. Successful public cases require matching pinned inputs and stable applied verification attempts. These are consistency checks on supplied local evidence, not a signature or an independent rerun of the original inputs.

The report loader accepts one stable regular file of at most 8 MiB. It rejects symlinks, special files, non-UTF-8 JSON, unpaired Unicode surrogates, duplicate member names at any depth with case variants included (internal/strictjson), unknown fields, missing required fields and explicit null required scalars. Optional fields follow the exact representation emitted by RunSuite: omit empty omitempty fields. Parsing is bounded to 32 nesting levels and 262,144 JSON tokens. The reader never opens source, checkout or log paths named inside the report. A 30-second context bounds each operation; regular filesystem reads themselves remain subject to the kernel's I/O behavior.

Each failed or context-skipped case produces one job in report order. IDs bind canonical JSON hashes of the complete report and case, including the immutable input reference. Replanning the same report gives the same IDs; a new suite run has a different report hash and therefore different IDs. This is identity within a retained run, not deduplication of a recurring failure across scheduled runs. Error excerpts are capped at 2,048 UTF-8 bytes with the complete error hash and original byte count preserved. All report strings remain under untrusted_evidence, separate from fixed review instructions. Neither an excerpt nor an input path confers permission to execute or read it.

Routing and budget

--task defaults to ci_debugging, which must be declared in the selected routing configuration. Both token estimates apply to each job and at least one must be positive. The existing router selects the eligible model with the lowest declared weighted token cost. Configuration and optional capacity fingerprints are retained in the plan. This does not validate current prices, provider availability, model quality or latency; the checked-in catalog is unchanged.

--max-cost is required and caps the sum of admitted job estimates, not each job independently. Explicit zero is allowed. Jobs consuming the remaining ceiling are review_required; subsequent jobs are blocked_budget. An absent task candidate or unavailable supplied capacity produces unroutable. Blocked plans are saved, then the command exits nonzero. No fallback bypasses declared eligibility or the budget. These estimates do not reserve quota or spend money.

--usage /private/capacity.json uses the router's strict capacity snapshot format. Only explicitly observed models are eligible when this option is supplied. Observations are operator-supplied; counters are not refreshed by this command. Without a snapshot, route capacity remains unobserved. A completed, consistent suite with no failed cases yields no_failures and an empty job list; a plan with admitted jobs yields ready_for_review.

A scheduler may call PlanRepairs after a failed RunSuite and save its returned plan even when the error is ErrRepairsBlocked. The explicit execution stage below consumes configured failures separately; the planner itself does not execute its jobs or promote changes.

Execute or inspect a configured repair

Execution has separate explicit subcommands. The original flag-only command above continues to create a review plan.

praetorctl dogfood repairs status \
  --config /private/repair-execution.json --report /private/suite-run/report.json

praetorctl dogfood repairs run \
  --config /private/repair-execution.json --report /private/suite-run/report.json

status inspects the supplied execution policy, retained failure evidence and local execution state. It does not create a workspace, invoke a credential helper, contact a model or write state. A ready status means a configured case is eligible; it does not mean a repair has run or passed verification.

run delegates one bounded repair attempt to the execution engine. Its explicit configuration identifies the pinned source commit, allowed Go source files, test packages, routing budget, reviewed provider and private state directory. The CLI prints the engine's structured outcome and preserves a nonzero error exit even when a partial report is available. Candidate verification and any later promotion remain distinct outcomes; a returned model proposal alone is not a verified fix.

The read-only MCP tool standards_dogfood_repair_status accepts exactly config_path and report_path. Both paths and every embedded input path are confined to the server root, including the configured credential-helper path. This tool always enforces its own root boundary, including when other server tools have been given -allow-outside-root. Set the server root to the reviewed private input directory when inspecting private execution state. The tool cannot enable execution through extra arguments.