---
tracker:
  kind: linear
  project_slug: "tidb-labs-033fa9290215"
  active_states:
    - Todo
    - In Progress
  terminal_states:
    - Closed
    - Cancelled
    - Canceled
    - Duplicate
    - Done
polling:
  interval_ms: 5000
workspace:
  root: ~/code/symphony-workspaces/labs.tidb.io
hooks:
  after_create: |
    git clone --depth 1 git@github.com:pingcap-inc/labs.tidb.io.git .
    if [ ! -e backend/labs/labs ]; then
      git clone --depth 1 git@github.com:pingcap-inc/tidb-labs.git backend/labs/labs || \
        echo "warning: unable to clone pingcap-inc/tidb-labs into backend/labs/labs"
    fi
agent:
  max_concurrent_agents: 5
  max_turns: 20
codex:
  command: codex --config shell_environment_policy.inherit=all --config model_reasoning_effort=xhigh app-server
  approval_policy: never
  thread_sandbox: danger-full-access
  turn_sandbox_policy:
    type: dangerFullAccess
---

You are working on a Linear ticket `{{ issue.identifier }}` for the `labs.tidb.io` monorepo.

{% if attempt %}
Continuation context:

- This is retry attempt #{{ attempt }} because the ticket is still active.
- Resume from the current workspace state instead of restarting from scratch.
- Do not repeat already-completed investigation or validation unless needed for new code changes.
{% endif %}

Issue context:
Identifier: {{ issue.identifier }}
Title: {{ issue.title }}
Current status: {{ issue.state }}
Labels: {{ issue.labels }}
URL: {{ issue.url }}

Description:
{% if issue.description %}
{{ issue.description }}
{% else %}
No description provided.
{% endif %}

Instructions:

1. This is an unattended orchestration session. Never ask a human to run commands for you.
2. Only stop early for a real blocker such as missing auth, missing secrets, or unavailable required services.
3. Final message must contain completed actions and blockers only. Do not include "next steps for user".
4. Work only inside the provided workspace clone.

## Linear state model for this project

Use the Linear states like this:

- `Backlog`: non-working backlog / triage. Symphony should not touch `Backlog` issues.
- `Todo`: queued work, or rework requested on an existing PR. `Todo` is still an active Symphony state, so never use it as a pause state.
- `In Progress`: active implementation, or explicit signal that an approved PR in `Human Review` should now be landed.
- `Human Review`: PR is ready and waiting for human review or merge decision. Symphony should not touch `Human Review` issues.
- `Blocked`: external prerequisite is missing and human intervention is required. Symphony should not touch `Blocked` issues.
- `Done`: terminal state after merge / completion.

Human operators should use this flow:

- Create or move new work to `Todo` to start.
- Once Symphony opens a PR and is waiting for review, it will move the issue to `Human Review`.
- If review requests changes, move the issue from `Human Review` to `Todo`.
- If the PR is approved and ready to merge, move the issue from `Human Review` to `In Progress`.
- If Symphony is blocked on an external prerequisite, it will move the issue to `Blocked`.
- If a blocker is resolved and work should resume, move the issue from `Blocked` to `Todo`.

## Repo operating context

Primary onboarding doc: `AGENTS.md` at repo root.

Repository areas:

- `frontend/`: Next.js 16 + React 19 user-facing site.
- `backend/`: Django 6 + DRF + Celery backend.
- `ssh-proxy/`: Go WebSocket-to-SSH proxy.
- `deployment/`: Ansible deployment and ops.

Module setup / run commands:

- Frontend install: `cd frontend && corepack pnpm install --frozen-lockfile`
- Frontend dev: `cd frontend && pnpm dev`
- Frontend validation: `cd frontend && pnpm run ts-check && pnpm run test && pnpm run lint && pnpm run i18n:check`
- Backend install: `cd backend && uv sync`
- Backend dev server: `cd backend && uv run python manage.py runserver 0.0.0.0:8000`
- Backend worker: `cd backend && uv run celery -A labs worker --concurrency=5 --loglevel=INFO`
- Backend validation: `cd backend && uv run python manage.py generate_lab_list && uv run python manage.py test`
- SSH proxy validation: `cd ssh-proxy && go test ./...`

Important backend caveats:

- Backend tests and `generate_lab_list` depend on `backend/labs/labs` containing the `pingcap-inc/tidb-labs` repo.
- Backend tests require TiDB on port `4000` and Redis on port `6379`.
- For local TiDB, `DB_ENABLE_SSL=false` is often required.

Frontend API modes:

- For UI-only work, prefer pointing frontend to the hosted backend when possible:
  - `API_BASE=https://labs.tidb.io/api`
  - `NEXT_PUBLIC_API_BASE=/api`
- For local backend work, set `NEXT_PUBLIC_API_BASE` to a full local backend URL such as `http://127.0.0.1:8000/api`.

## Status routing

1. Fetch the issue by explicit ticket ID and inspect its current state.
2. Route by state:
   - `Backlog`:
     - Treat as non-working backlog / triage.
     - Do not modify code or issue state.
     - Stop and wait for a human to move it to `Todo`.
   - `Todo`:
     - Immediately move to `In Progress`.
     - Never leave an issue in `Todo` to represent a pause or blocker; Symphony will continue to dispatch `Todo`.
     - If a PR is already attached, treat this as rework / review-feedback mode.
     - Start execution flow.
   - `In Progress`:
     - If there is no PR yet, continue execution flow.
     - If there is an open PR and it is approved with green checks and no actionable review comments, run the `land` skill flow.
     - If there is an open PR but it is waiting on human review or approval, move the issue to `Human Review` and stop.
     - If there is an open PR with actionable feedback, address it as execution flow.
     - If execution is blocked on missing auth, missing required services, or any other external prerequisite, move the issue to `Blocked` and stop.
   - `Human Review`:
     - Treat as waiting for human review or merge decision.
     - Do not modify code or issue state.
     - Stop and wait for a human to move it to `Todo` or `In Progress`.
   - `Blocked`:
     - Treat as waiting for human unblock action.
     - Do not modify code or issue state.
     - Stop and wait for a human to move it to `Todo`.
   - `Done`:
     - Do nothing and stop.
3. If the current branch is tied to a closed or merged PR, create a fresh branch from `origin/main` and continue as a new attempt.

## Workpad requirements

Maintain one persistent Linear comment as the source of truth for the run.

- Reuse a comment headed `## Codex Workpad` when present.
- Otherwise create one workpad comment and keep updating only that comment.
- Keep the workpad current after each meaningful milestone.
- Include:
  - environment stamp (`<host>:<abs-workdir>@<short-sha>`)
  - plan
  - acceptance criteria
  - validation checklist
  - notes / reproduction evidence
  - blockers

Before implementing:

1. Reconcile the workpad with current reality.
2. Capture a concrete reproduction signal or baseline.
3. Sync with latest `origin/main` using the `pull` skill before editing.
4. Record the sync result in the workpad.

## Execution rules

1. Keep the task narrowly scoped to the ticket.
2. Prefer targeted validation that matches the touched modules.
3. If changes touch multiple modules, run validation for each touched module.
4. Update the workpad immediately after reproduction, implementation, validation, and PR publication.
5. Before every push, rerun the validation relevant to the changed files.
6. Attach the PR URL to the Linear issue.

Validation guidance by area:

- `frontend/**`:
  - Run `pnpm run ts-check`
  - Run `pnpm run test`
  - Run `pnpm run lint`
  - Run `pnpm run i18n:check`
- `backend/**`:
  - Ensure `backend/labs/labs` exists and contains lab specs
  - Ensure TiDB + Redis are available if tests need them
  - Run `uv run python manage.py generate_lab_list`
  - Run `uv run python manage.py test`
- `ssh-proxy/**`:
  - Run `go test ./...`
- `deployment/**`:
  - Inspect deployment templates carefully
  - Run any targeted syntax or dry-run checks you can perform safely

## PR and review handling

- Use repo-local skills when relevant:
  - `commit`
  - `push`
  - `pull`
  - `land`
  - `linear`
- Sweep both top-level PR comments and inline review comments before considering the work complete.
- Every actionable review comment must be either fixed or explicitly answered with a justified pushback.
- When the branch is ready for human review:
  - ensure validation is current,
  - push changes,
  - attach the PR to the issue,
  - update the workpad,
  - move the Linear issue to `Human Review`,
  - stop.
- When a human later moves the issue from `Human Review` back to `Todo`, treat it as rework.
- When a human later moves the issue from `Human Review` to `In Progress`, treat it as a merge request for the existing approved PR.

## Blockers

Use a blocker only for real missing prerequisites, such as:

- missing GitHub auth that prevents required PR operations,
- missing Linear auth,
- missing access to `pingcap-inc/tidb-labs` when backend validation depends on it,
- unavailable required infrastructure for the changed area with no safe fallback.

If blocked:

- write the blocker briefly in the workpad,
- keep it action-oriented,
- move the issue to `Blocked`,
- stop and wait for human unblock action. Do not use `Todo` as a blocked or paused state because Symphony treats `Todo` as active.
