Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b84f90b
BRIX-1899: restrict review-finding Linear issues to synthetic_review …
lafawnduh1966 Jul 13, 2026
8d8c513
BRIX-1897: remove dead TS outbox-deliver Linear handler
lafawnduh1966 Jul 13, 2026
a479ee5
BRIX-1898: admin-UI toggle for review-finding Linear issue creation
lafawnduh1966 Jul 13, 2026
0c1d6c0
Merge pull request #135 from InverterNetwork/brix-1899-adopted-eligib…
lafawnduh1966 Jul 13, 2026
1cfd7a4
Merge pull request #137 from InverterNetwork/brix-1898-linear-issue-t…
lafawnduh1966 Jul 13, 2026
db8b26c
Merge pull request #136 from InverterNetwork/brix-1897-remove-dead-de…
lafawnduh1966 Jul 13, 2026
77fa438
BRIX-1897: remove now-dead loadCurrentFinding
lafawnduh1966 Jul 13, 2026
68ac418
Merge pull request #138 from InverterNetwork/brix-1897-cleanup-loadcu…
lafawnduh1966 Jul 13, 2026
6ca35dc
feat: add `quay task resnapshot` to re-baseline a task's ticket snapshot
lafawnduh1966 Jul 13, 2026
5197537
fix(core): back off spawn failures (BRIX-1919)
Jul 13, 2026
1d55c09
Merge pull request #139 from InverterNetwork/quay/BRIX-1919
lafawnduh1966 Jul 13, 2026
09b931e
fix(merge): use repo's allowed merge method and back off on policy re…
lafawnduh1966 Jul 13, 2026
3afbf26
fix(core): handle spawn-window missing worktrees (BRIX-1922)
Jul 14, 2026
f45a2f0
Merge pull request #140 from InverterNetwork/quay/BRIX-1922
lafawnduh1966 Jul 14, 2026
de33cea
fix(core): harden missing worktree recovery (BRIX-1922)
Jul 14, 2026
cb3f98f
Merge pull request #141 from InverterNetwork/quay/BRIX-1922
lafawnduh1966 Jul 14, 2026
ba383cb
feat(cli): add task worktree recreation command
Jul 14, 2026
0003c8e
Merge pull request #145 from InverterNetwork/quay/BRIX-1923
lafawnduh1966 Jul 14, 2026
23238b4
Merge branch 'dev' into feat/BRIX-1916-task-resnapshot
lafawnduh1966 Jul 14, 2026
dd343c0
fix(umbrella): retire umbrella workflow when all children are cancelled
lafawnduh1966 Jul 14, 2026
7416f05
Merge remote-tracking branch 'origin/main' into codex/sync-dev-main-2…
lafawnduh1966 Jul 14, 2026
4103384
Merge pull request #146 from InverterNetwork/feat/BRIX-1924-umbrella-…
lafawnduh1966 Jul 14, 2026
eea3e07
Merge pull request #143 from InverterNetwork/feat/BRIX-1920-1921-merg…
lafawnduh1966 Jul 14, 2026
2623a9f
Merge pull request #142 from InverterNetwork/feat/BRIX-1916-task-resn…
lafawnduh1966 Jul 14, 2026
bdb56a9
fix(resnapshot): update task objective
lafawnduh1966 Jul 14, 2026
027c232
Merge pull request #148 from InverterNetwork/codex/fix-resnapshot-obj…
lafawnduh1966 Jul 14, 2026
f1ccd81
docs: clarify resnapshot objective refresh
lafawnduh1966 Jul 14, 2026
f0c3e79
Merge pull request #149 from InverterNetwork/codex/update-resnapshot-…
lafawnduh1966 Jul 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions docs/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,7 @@ components:
- model_reviewer
- preamble_worker
- preamble_reviewer
- review_finding_linear_enabled
- archived_at
- created_at
properties:
Expand Down Expand Up @@ -861,6 +862,11 @@ components:
- integer
- "null"
minimum: 1
review_finding_linear_enabled:
description: Per-repo override for filing non-blocking review findings as Linear issues. null inherits the deployment default; true/false pin the repo.
type:
- boolean
- "null"
archived_at:
type:
- string
Expand All @@ -886,6 +892,7 @@ components:
- model_reviewer
- preamble_worker
- preamble_reviewer
- review_finding_linear_enabled
- archived_at
- created_at
- active_task_count
Expand Down Expand Up @@ -945,6 +952,11 @@ components:
- integer
- "null"
minimum: 1
review_finding_linear_enabled:
description: Per-repo override for filing non-blocking review findings as Linear issues. null inherits the deployment default; true/false pin the repo.
type:
- boolean
- "null"
archived_at:
type:
- string
Expand Down Expand Up @@ -1079,6 +1091,7 @@ components:
- operations
- ci_policy
- adapters
- review_findings
- agents
- preambles
- retry_templates
Expand All @@ -1104,6 +1117,15 @@ components:
type: array
items:
$ref: "#/components/schemas/AdapterSummary"
review_findings:
type: object
additionalProperties: false
required:
- linear_enabled
properties:
linear_enabled:
description: Global default for filing non-blocking review findings as Linear issues (resolves ON when the deployment setting is unset). Policy flag, distinct from the Linear adapter connectivity toggle.
type: boolean
agents:
$ref: "#/components/schemas/AgentsReadModel"
preambles:
Expand Down Expand Up @@ -2053,6 +2075,11 @@ components:
- integer
- "null"
minimum: 1
review_finding_linear_enabled:
description: Per-repo override for filing non-blocking review findings as Linear issues. null inherits the deployment default; true/false pin the repo. Affects synthetic_review tasks only.
type:
- boolean
- "null"
ci_ignore_mode:
type: string
enum:
Expand Down Expand Up @@ -2125,6 +2152,11 @@ components:
- string
- "null"
minLength: 1
review_finding_linear_enabled:
description: Global default for filing non-blocking review findings as Linear issues. null leaves it unset (resolves to ON). Policy flag, distinct from the Linear adapter connectivity toggle.
type:
- boolean
- "null"
TagsReplaceChange:
type: object
additionalProperties: false
Expand Down
15 changes: 8 additions & 7 deletions docs/quay-spec.md

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions docs/user/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,8 @@ quay task events <task_id>
quay task claim <task_id>
quay task release-claim <task_id> --claim-id <claim_id>
quay task retarget <task_id> --repo <target_repo> [--base-branch <branch>] --yes
quay task resnapshot <task_id> --reason <text>
quay task recreate-worktree <task_id> --yes [--force]
```

`task claim` only succeeds for `awaiting-next-brief` tasks.
Expand All @@ -435,6 +437,15 @@ It also includes `authors`, parsed from the ticket's `quay-config.authors`
block as `{name, slack_id}` objects. Legacy or malformed rows return
`authors: []`.

`task recreate-worktree` recreates an existing task's recorded worktree. By
default it only runs when `task.worktree_path` is missing and no active attempt
is recorded. It uses `origin/<task.branch_name>` when that remote branch exists;
otherwise it rebuilds from `origin/<base_branch>` while restoring the task
branch name. The repo install command runs after recreation, and Quay records a
`worktree_recreated` event with the recovery base. Use `--force` only after
confirming no worker is live; it allows recreation when the path already exists
or an active attempt is still recorded.

`task list`, `task get`, and `task events` accept legacy `task_id` values and
return the same task/run rows as before. JSON output now also includes
run-aware compatibility fields:
Expand Down Expand Up @@ -510,6 +521,22 @@ but before the source reaches terminal state, the next `quay tick` recovers the
cancel intent and writes the same source-side `retargeted` audit context from
the linked clone.

`task resnapshot` re-baselines a task's frozen `ticket_snapshot` and current
`task_objective` — the definition of done the reviewer enforces and the
objective worker/reviewer prompts load. It re-fetches the task's Linear ticket,
re-parses the `quay-config` block, and re-composes both artifacts with the same
code path enqueue uses. Use it when an operator has edited the live ticket to
change scope mid-flight: without a resnapshot, later prompts keep enforcing the
stale acceptance criteria. It emits a `ticket_resnapshotted` audit event
carrying the required `--reason` and a before/after diff of the snapshot, and it
invalidates the latest review verdict (superseding a standing `approved` /
`changes_requested`) so the next `quay tick` runs a fresh review against the new
snapshot and objective rather than being blocked by a stale verdict. Running it
when the ticket is unchanged is a safe, still-audited no-op: the event is
recorded but the artifacts are not rewritten and no verdict is invalidated. The
command requires the Linear adapter to be configured, and the task must have an
`external_ref`.

## Submit Brief

```bash
Expand Down
13 changes: 7 additions & 6 deletions docs/user/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ Before enqueueing work, the operator must:
At enqueue time, Quay fetches the effective base branch, creates a local branch
named `quay/<slug>`, creates a worktree from `origin/<base_branch>`, runs the
repo `install_cmd`, stores the task-level `task_objective` artifact (the raw
original brief) plus the first attempt's `brief` and `final_prompt` artifacts,
and creates the first pending attempt. The effective base branch is the repo
default unless a task-level override is supplied.
initial brief) plus the first attempt's `brief` and `final_prompt` artifacts,
and creates the first pending attempt. `task resnapshot` can append a newer
task-level objective after the live ticket changes. The effective base branch is
the repo default unless a task-level override is supplied.

## Work Items, Runs, And Attempts

Expand Down Expand Up @@ -61,8 +62,8 @@ Every attempt has:

- A reason, such as `initial`, `ci_fail`, `crash`, `review`, or
`blocker_resolved`.
- A `brief` artifact: a structured composed prompt body with the original
task objective (rendered from the task-level `task_objective` artifact),
- A `brief` artifact: a structured composed prompt body with the current
task objective (rendered from the newest task-level `task_objective` artifact),
the current attempt's guidance, and any diagnostics for this attempt.
- A `final_prompt` artifact: for code-worker attempts, Quay's worker preamble
followed by the composed `brief`; for review attempts, Quay's static
Expand Down Expand Up @@ -91,7 +92,7 @@ A supervisor lock prevents overlapping ticks and serializes side effects with
Artifacts are snapshots of data that crosses a boundary, such as:

- `ticket_snapshot`
- `task_objective` (task-level; the raw original brief, source of every later attempt's stable objective section)
- `task_objective` (task-level; the canonical brief used by later prompt objective sections)
- `brief` (per-attempt composed body)
- `final_prompt` (worker preamble + `brief`, or reviewer protocol + guidance
+ review `brief`)
Expand Down
12 changes: 5 additions & 7 deletions docs/user/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ supervisor_lock_stale_seconds = 30
[adapters.linear]
enabled = true
api_key_env = "LINEAR_API_KEY"
# Required when reviewer-created human follow-up findings should create
# Linear issues.
default_issue_team_key = "BRIX"
# For OAuth/app-actor tokens, use Bearer mode. The token is resolved for each
# Linear request, so a Hermes-owned helper can mint/cache/refresh it.
# auth_mode = "bearer"
Expand Down Expand Up @@ -254,10 +251,11 @@ are probed against the target repository before their attempts are promoted.
Worker tokens are checked before tmux starts by exercising repo access, branch
PR visibility, and worker write access. Invalid, expired, empty, missing, or
repo-inaccessible worker tokens fail as `worker_auth_invalid`: Quay retries one
freshly resolved token source, then moves the task to `awaiting-next-brief`
with a `worker_auth_invalid` handoff if the preflight still fails. Reviewer
auth failures remain `spawn_substrate_failed` and stay out of the
`review_infra_failed` retry accounting.
freshly resolved token source after the task's spawn backoff expires, then moves
the task to `awaiting-next-brief` with a `worker_auth_invalid` handoff if the
preflight still fails. Reviewer auth failures remain `spawn_substrate_failed`
until the reviewer infrastructure failure threshold parks the task in
`non_budget_loop`.

`worker.gh_token_file` is the preferred worker source when configured, even if
`QUAY_WORKER_GH_TOKEN` is also present in the tick environment.
Expand Down
1 change: 0 additions & 1 deletion docs/user/linear-and-slack.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ see [External Services Setup](external-services.md).
[adapters.linear]
enabled = true
api_key_env = "LINEAR_API_KEY"
default_issue_team_key = "BRIX"

[adapters.slack]
enabled = true
Expand Down
12 changes: 7 additions & 5 deletions docs/user/monitoring-and-artifacts.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ binary and invalid UTF-8 artifacts such as `malformed_signal`.

| Kind | Meaning |
| --- | --- |
| `ticket_snapshot` | Snapshot of source ticket/context at enqueue time. |
| `task_objective` | Stable original task brief, written once at enqueue and reused by every later code-worker attempt as the canonical objective. Task-level (no `attempt_id`). |
| `brief` | Per-attempt composed prompt body: a structured `<quay-task-objective>` block pointing at the task-level `task_objective` artifact, a `<quay-current-attempt-guidance>` block (initial instruction, retry/respawn template, or orchestrator-submitted brief), and an optional `<quay-diagnostics>` block (CI excerpt, review comments, conflict slice, etc.). The raw original brief lives in `task_objective`, not here. |
| `ticket_snapshot` | Snapshot of source ticket/context. Enqueue writes the first task-level row; `task resnapshot` can append a newer task-level snapshot after the live ticket changes. |
| `task_objective` | Canonical task brief reused by later code-worker and reviewer prompts. Enqueue writes the first task-level row; `task resnapshot` can append a newer task-level objective. |
| `brief` | Per-attempt composed prompt body: a structured `<quay-task-objective>` block pointing at the current task-level `task_objective` artifact, a `<quay-current-attempt-guidance>` block (initial instruction, retry/respawn template, or orchestrator-submitted brief), and an optional `<quay-diagnostics>` block (CI excerpt, review comments, conflict slice, etc.). The current task objective lives in `task_objective`, not here. |
| `final_prompt` | Code-worker attempts: worker preamble plus the attempt's composed `brief`. Review attempts: static reviewer protocol, reviewer guidance, then the review `brief`. |
| `session_log` | Captured tmux output. |
| `usage` | JSON usage envelope captured per attempt. `.quay-usage.json` is stored verbatim when present; otherwise Codex `--json` JSONL in `.quay-tool-trace.log` can synthesize normalized model/token totals. |
Expand Down Expand Up @@ -111,5 +111,7 @@ a `tick_error` event and continues processing other tasks. A later successful
tick path clears the task's `tick_error` field.

Worker GitHub auth preflight failures are not `tick_error`: they are classified
as `worker_auth_invalid`, retried once with freshly resolved credentials, then
surfaced through an `awaiting-next-brief` handoff if the retry also fails.
as `worker_auth_invalid`, retried once after `spawn_retry_next_eligible_at` with
freshly resolved credentials, then surfaced through an `awaiting-next-brief`
handoff if the retry also fails. Spawn/reviewer infrastructure failures record
their latest operator-facing reason in `tasks.spawn_failure_reason`.
23 changes: 20 additions & 3 deletions docs/user/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ not consume retry budget.
## `worker_auth_invalid`

The worker GitHub token failed Quay's spawn-time auth preflight. Quay retries
once after re-reading the configured token source. If the retry also fails, the
task moves to `awaiting-next-brief` with a `worker_auth_invalid` handoff.
once after re-reading the configured token source and waiting for
`spawn_retry_next_eligible_at`. If the retry also fails, the task moves to
`awaiting-next-brief` with a `worker_auth_invalid` handoff.

Check the configured worker token source:

Expand All @@ -201,7 +202,23 @@ quay task events <task_id>
quay artifact get <task_id> session_log --path
```

Manual recovery is currently cancellation:
`tasks.spawn_failure_reason` records the latest spawn or reviewer
infrastructure diagnostic, and `tasks.spawn_retry_next_eligible_at` shows when a
non-parked retry becomes eligible.

If the task row still points at a missing `worktree_path`, recreate that
recorded worktree without DB surgery:

```bash
quay task recreate-worktree <task_id> --yes
```

Quay prefers `origin/<task.branch_name>` when it exists. If that branch is gone
from the remote, Quay rebuilds from `origin/<base_branch>` and checks out the
task branch name again. The command refuses existing paths and active attempts
unless `--force` is supplied.

Cancellation remains available when the task should not continue:

```bash
quay cancel <task_id> --keep-worktree
Expand Down
14 changes: 13 additions & 1 deletion packages/admin-ui/src/api/quayAdmin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface QuayAdminRepo {
model_reviewer: string | null;
preamble_worker: number | null;
preamble_reviewer: number | null;
review_finding_linear_enabled: boolean | null;
archived_at: string | null;
created_at: string;
}
Expand Down Expand Up @@ -203,6 +204,9 @@ interface QuayAdminGlobal {
ignored_workflow_names: string[];
};
adapters: QuayAdminAdapter[];
review_findings: {
linear_enabled: boolean;
};
agents: {
defaults: QuayAdminAgentDefaults;
invocations: QuayAdminAgentInvocation[];
Expand Down Expand Up @@ -461,13 +465,17 @@ function toRepoSummary(repo: QuayAdminRepoDetail): RepoSummary {
repo.preamble_worker,
repo.preamble_reviewer,
].filter(Boolean);
// Tri-state override: both on (true) and off (false) count as overrides;
// only inherit (null) does not. `filter(Boolean)` above would drop `false`,
// so count this one by non-null instead.
const reviewFindingOverrides = repo.review_finding_linear_enabled != null ? 1 : 0;

return {
revision: repo.revision,
id: repo.repo_id,
active: repo.active_task_count,
agent: repo.agent_worker ?? 'inherits',
overrides: overrideFields.length,
overrides: overrideFields.length + reviewFindingOverrides,
url: repo.repo_url,
baseBranch: repo.base_branch,
createdAt: repo.created_at,
Expand All @@ -482,6 +490,7 @@ function toRepoSummary(repo: QuayAdminRepoDetail): RepoSummary {
modelReviewer: repo.model_reviewer,
preambleWorker: repo.preamble_worker,
preambleReviewer: repo.preamble_reviewer,
reviewFindingLinearEnabled: repo.review_finding_linear_enabled,
ciPolicy: {
ignoreMode: repo.ci_policy.ignore_mode,
ignoredCheckNames: repo.ci_policy.ignored_check_names,
Expand Down Expand Up @@ -537,6 +546,9 @@ function toGlobalSummary(global: QuayAdminGlobal): GlobalConfigSummary {
ignoredWorkflowNames: global.ci_policy.ignored_workflow_names,
},
adapters: global.adapters.map(toAdapterSummary),
reviewFindings: {
linearEnabled: global.review_findings.linear_enabled,
},
agents: {
defaults: {
worker: global.agents.defaults.worker,
Expand Down
Loading