You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(dashboard-agent): move the mandatory-sweep imperative into tool descriptions
The system-prompt bullet doesn't bind at decision time; get_run,
get_error, get_queue, and correlate_version now carry the imperative
in their own descriptions (tools.chars is uncapped). correlate_version
also gained project/environment overrides and lost its "dev runs
behave this way" claim, which asserted a run's deploy state from a
single-environment 404 — the same fabricated-absence bug banned
elsewhere. Tool schemas rebuild fresh every turn with no caching or
dashboard-override path (unlike the system prompt, which resolves
through a managed prompt cached per worker process), so this change
is live on the very next call.
// Only a real 404 says "no commit"; a transport failure says nothing.
677
+
// Only a real 404 says "no commit here"; a transport failure says nothing, and a
678
+
// 404 is never evidence the run isn't locked/deployed — only that this environment
679
+
// has no record of it. Asserting "dev run" or "no locked commit" from it is the bug.
673
680
if("status"inresult&&result.status===404){
681
+
constscope=target ? "that project/environment" : "the current environment";
674
682
return{
675
-
error: `Run ${runId} isn't locked to a deployed version, so there's no commit to correlate (dev runs behave this way).`,
683
+
error: `No commit found for run ${runId}in ${scope}. That is not evidence the run isn't locked to a deployment — sweep (list_projects, then get_run with project/environment) before concluding, then retry this call with project/environment for wherever it's found.`,
676
684
};
677
685
}
678
686
return{error: `Couldn't resolve the commit for ${runId}${fetchReason(result)}.`};
"Get the status, timing, cost, and error details for a single run in the current environment, by its run id (run_...). The `wait` field is the already-computed queue wait (or, when unreliable, time since creation) — never recompute it from createdAt/startedAt.",
97
+
"Get the status, timing, cost, and error details for a single run in the current environment, by its run id (run_...). The `wait` field is the already-computed queue wait (or, when unreliable, time since creation) — never recompute it from createdAt/startedAt. A 404 (in the error message) means this run isn't in the current environment, never that it doesn't exist: you MUST immediately, this same turn, with no permission question, call list_projects and repeat this call with `project`/`environment` set for the current project's other environments and every sibling project's matching environment, then answer naming what you checked.",
98
98
inputSchema: z.object({
99
99
runId: z.string().describe("The run id, e.g. run_abc123."),
"Get the full detail for a single error group by its id (error_...): type, message, occurrence count, first/last seen, affected task versions, and lifecycle state (who resolved/ignored it and when). `recurredSinceResolve` is already computed — true when an occurrence landed after resolvedAt, so never compare those dates yourself. Pair with list_runs(errorId) to see the runs behind it.",
146
+
"Get the full detail for a single error group by its id (error_...): type, message, occurrence count, first/last seen, affected task versions, and lifecycle state (who resolved/ignored it and when). `recurredSinceResolve` is already computed — true when an occurrence landed after resolvedAt, so never compare those dates yourself. Pair with list_runs(errorId) to see the runs behind it. A 404 (in the error message) means this error group isn't in the current environment, never that it doesn't exist: you MUST immediately, this same turn, with no permission question, call list_projects and repeat this call with `project`/`environment` set for the current project's other environments and every sibling project's matching environment, then answer naming what you checked.",
147
147
inputSchema: z.object({
148
148
errorId: z.string().describe("The error group id, e.g. error_abc123, from list_errors."),
"Get one queue's metrics over a window: wait latency (p50/p95), peak depth, how many runs started (throughput), and how often the queue was throttled by its concurrency limit. Use this for 'how deep is the X queue', 'is X backed up', or 'why are runs waiting'. The answer also carries the queue's live row: `paused`, `queuedNow`, `runningNow`, `concurrencyLimit`, and `exists: false` when no queue of that name is there at all. When that read fails rather than answers, `exists` is `\"unknown\"` with a `liveStateError`: the queue's state is unknown, not missing. For a custom queue it also carries `consumerTasks`: the deployed tasks whose queue config names this queue. When present, `slotHolders` (each run's id, status, uri, consistency, phase (`admitted` | `dequeued`), and concurrencyKey) lists the runs holding the queue's concurrency slots, but the list is never guaranteed exhaustive; `slotHolderFacts` (admittedCount, dequeuedCount, runningReported, truncated, unlistedRunning, consistency) is the server-computed snapshot summary — `truncated` or `unlistedRunning > 0` mean there are holders `slotHolders` doesn't list. When present, `concurrency` (current, base, override, overriddenBy, overriddenAt) distinguishes a temporary override from configured `concurrencyLimit`. When present, `envConcurrency` (limit, current, burstFactor) is the environment-wide dequeue gate: the environment saturates at `current >= limit * burstFactor`, not at `current >= limit` (burstFactor defaults to 2, so headroom above the plain limit is often still open) — and `current` is the last-displayed dequeued count, which can lag the number actually gating dequeues. Use these three fields together before naming the environment as the bottleneck; never infer that from throttledCount alone. All are absent on an older API rather than empty. A holder's phase `admitted` (not yet `dequeued`) may legitimately be pending, not a mismatch. Consistency \"mismatch\" on a holder means the scheduler still counts it as a holder though its run state disagrees; on slotHolderFacts it means the scheduler's own counters disagree right now — prefer those facts to comparing runningNow yourself, and never call either \"leaked\" or \"stale\". Consistency `unresolved` means the run id is citable but its state, and slotHolderFacts' counts, are not — don't assert either. Never assert a run is currently executing from runningNow or concurrencyLimit alone, and never say holders are unaccounted for beyond what truncated/unlistedRunning/consistency actually state — 'nothing holds the slots' is never licensed by an incomplete list.",
214
+
"Get one queue's metrics over a window: wait latency (p50/p95), peak depth, how many runs started (throughput), and how often the queue was throttled by its concurrency limit. Use this for 'how deep is the X queue', 'is X backed up', or 'why are runs waiting'. The answer also carries the queue's live row: `paused`, `queuedNow`, `runningNow`, `concurrencyLimit`, and `exists: false` when no queue of that name is there at all. When `exists` is `false` in the current environment, you MUST immediately, this same turn, with no permission question, call list_projects and repeat this call with `project`/`environment` set for the current project's other environments and every sibling project's matching environment, then answer naming what you checked. When that read fails rather than answers, `exists` is `\"unknown\"` with a `liveStateError`: the queue's state is unknown, not missing. For a custom queue it also carries `consumerTasks`: the deployed tasks whose queue config names this queue. When present, `slotHolders` (each run's id, status, uri, consistency, phase (`admitted` | `dequeued`), and concurrencyKey) lists the runs holding the queue's concurrency slots, but the list is never guaranteed exhaustive; `slotHolderFacts` (admittedCount, dequeuedCount, runningReported, truncated, unlistedRunning, consistency) is the server-computed snapshot summary — `truncated` or `unlistedRunning > 0` mean there are holders `slotHolders` doesn't list. When present, `concurrency` (current, base, override, overriddenBy, overriddenAt) distinguishes a temporary override from configured `concurrencyLimit`. When present, `envConcurrency` (limit, current, burstFactor) is the environment-wide dequeue gate: the environment saturates at `current >= limit * burstFactor`, not at `current >= limit` (burstFactor defaults to 2, so headroom above the plain limit is often still open) — and `current` is the last-displayed dequeued count, which can lag the number actually gating dequeues. Use these three fields together before naming the environment as the bottleneck; never infer that from throttledCount alone. All are absent on an older API rather than empty. A holder's phase `admitted` (not yet `dequeued`) may legitimately be pending, not a mismatch. Consistency \"mismatch\" on a holder means the scheduler still counts it as a holder though its run state disagrees; on slotHolderFacts it means the scheduler's own counters disagree right now — prefer those facts to comparing runningNow yourself, and never call either \"leaked\" or \"stale\". Consistency `unresolved` means the run id is citable but its state, and slotHolderFacts' counts, are not — don't assert either. Never assert a run is currently executing from runningNow or concurrencyLimit alone, and never say holders are unaccounted for beyond what truncated/unlistedRunning/consistency actually state — 'nothing holds the slots' is never licensed by an incomplete list.",
"Find the exact code a run executed: the deployed version it locked to, that version's commit SHA, and the commit message, branch, and pull request behind it. Use this for 'what commit is this run running', 'which change broke this', or before reading source for a run.",
271
+
"Find the exact code a run executed: the deployed version it locked to, that version's commit SHA, and the commit message, branch, and pull request behind it. Use this for 'what commit is this run running', 'which change broke this', or before reading source for a run. A 404 here means not found IN THIS environment, never that the run isn't locked or deployed: you MUST immediately, this same turn, with no permission question, call list_projects and repeat this call with `project`/`environment` set for the current project's other environments and every sibling project's matching environment, then answer naming what you checked. Never infer 'dev run' or 'no locked commit' from a single-environment 404.",
272
272
inputSchema: z.object({
273
273
runId: z.string().describe("The run id, e.g. run_abc123."),
0 commit comments