# Pi Dev Linear Contract

> Binding Pi-Dev-Ops × Linear contract — Pattern B repo→project routing, autonomy pickup requires status Ready for Pi-Dev plus pi-dev:autonomous label, run_id idempotency on every autonomous run, Pi-Dev workflow statuses, ticket footer format. Use before any Linear read/write by Pi-CEO code paths, autonomy poller work, or launch-crew sync. Triggers on "linear contract", "pi-dev linear", "Ready for Pi-Dev", "pi-dev:autonomous", "run_id", "Pattern B routing".

- Skill: `cleanexpo/pi-dev-linear-contract` (Agent Skill)
- Install (CLI): `npx skillmds@latest add cleanexpo/pi-dev-linear-contract`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cleanexpo/pi-dev-linear-contract/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: cleanexpo (https://skillmd.com/u/cleanexpo)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cleanexpo/pi-dev-linear-contract

---


# Pi-Dev × Linear Contract

**Binding contract — both sides MUST obey or the 2nd-Brain drifts. Source: Phill's 18 Apr 2026 PM spec.**

You are the guardian of how Pi-Dev-Ops talks to Linear. Every autonomous read, write, transition, and comment on Linear by any Pi-CEO code path flows through this contract. If you see a code path that bypasses it, stop and flag it.

## Core decisions (already made, do not re-litigate)

- **Routing:** Pattern B (repo name → matching Linear project name, verbatim). Pattern C override — explicit `target_project` parameter wins.
- **Autonomy signal:** STATUS-based. A ticket is autonomous-pickable iff status=`Ready for Pi-Dev` AND label `pi-dev:autonomous`. Both required — status alone is not authorisation.
- **Idempotency:** Every Pi-Dev run has a unique `run_id`. Stored in the `Pi-Dev Run ID` custom field. Skill 1 updates in place if run_id already filed.

## Workspace setup (must exist before any skill runs)

### 1. Workflow statuses (per project)

| Status | Type | Position | Meaning |
|---|---|---|---|
| `Ready for Pi-Dev` | Unstarted | After Backlog, before Todo | Queued for autonomous execution |
| `Pi-Dev: In Progress` | Started | After In Progress | Poller has claimed it, session running |
| `Pi-Dev: Blocked` | Started | After Pi-Dev: In Progress | Pi-Dev hit something it can't resolve |
| `In Review` | Started | After Pi-Dev: Blocked | Pi-Dev finished, awaiting human verification |

### 2. Workspace labels

| Label | Meaning |
|---|---|
| `pi-dev:source` | Issue was created by Pi-Dev-Ops |
| `pi-dev:autonomous` | Pi-Dev can run without human sign-off |
| `pi-dev:needs-review` | Pi-Dev must stop at `In Review`, not auto-Done |
| `pi-dev:blocked-reason:<type>` | Required when transitioning to `Pi-Dev: Blocked`. Types: `credentials`, `ambiguous-spec`, `external-dep`, `scope-creep` |

### 3. Custom field

`Pi-Dev Run ID` — text, workspace-scoped. **Mandatory** on every issue Pi-Dev creates.

### 4. Project-repo naming

GitHub repo name = Linear project name, verbatim, no transforms. Example: repo `Pi-Dev-Ops` → project `Pi-Dev-Ops`. Divergence breaks routing silently — consistency-audit skill catches it.

## The four Linear skills (saved on the Linear side)

All four live in the Linear Agent. Pi-Dev-Ops invokes them via Linear Agent API — never via raw Linear REST/GraphQL — so every write is audited in one place.

### Skill 1 — `Pi-Dev: File Analysis Output` (write path)

**When:** Pi-Dev-Ops calls after a successful analysis run, OR human runs `/Pi-Dev: File Analysis Output` with an artefact.

**Pi-Dev side MUST supply:** `run_id`, `source_repo`, `commit_sha`, `dashboard_session_url`, `executive_summary`, `sprint_plan[]`, optionally `target_project`, `milestones[]`, `spec`.

**Linear side pre-checks (abort if any fail):**
1. Target project exists (do NOT silently create — stop and ask).
2. Any existing issues with the same run_id → update in place (idempotency).
3. `sprint_plan` has at least one non-empty title (malformed artefact detection).

**Then creates, in order:**
1. Spec document (if provided) — title `[Pi-Dev] Spec: {repo} @ {sha_short}`, project-scoped, executive summary prepended.
2. Milestones (if provided) — names verbatim.
3. One issue per `sprint_plan` entry with the **standard footer block** (see below).

**Returns structured:** `{project_id, document_id, milestone_ids, issue_ids, created_count, updated_count}` + posts a breadcrumb comment linking the dashboard session URL.

### Skill 2 — `Pi-Dev: Fetch Autonomy Queue` (read path)

**Filter:** status = `Ready for Pi-Dev` AND label includes `pi-dev:autonomous` AND not archived. Optional `scope` (project name) and `limit` (default 20, max 100).

**Ordering:** priority desc, then createdAt asc.

**Returns per issue:** `{linear_issue_id, linear_issue_url, title, description, project_name, priority, estimate, labels, source_repo, assignee, created_at, run_id_if_related}` + summary `{total_queued, returned, projects_with_queue[]}`.

**Guardrail:** if >50 queued, include warning `"Queue depth high — investigate whether Pi-Dev-Ops is running or stuck."`

### Skill 3 — `Pi-Dev: Consistency Audit` (weekly)

Read-only. Detects drift:
1. Enabled projects missing any of the 4 mandatory statuses.
2. `pi-dev:source` issues missing `Pi-Dev Run ID` custom field.
3. `pi-dev:autonomous` issues NOT in `Ready for Pi-Dev`/`Pi-Dev: In Progress` (misuse).
4. Enabled projects with no GitHub-repo reference anywhere.
5. Stale queue (>7 days in `Ready for Pi-Dev`).
6. `Pi-Dev: Blocked` issues missing `pi-dev:blocked-reason:*` label.
7. Orphaned run_ids (single-issue runs — usually fine, listed for review).

### Skill 4 — `Pi-Dev: Health Report` (daily, dashboard-bound)

Read-only. Produces 6 sections:
1. Autonomy queue — count per project, oldest age, >20-depth flags.
2. Active work — `Pi-Dev: In Progress` per project, `>48h = stuck` listed separately.
3. Blocked work — every `Pi-Dev: Blocked`, sorted by duration desc.
4. At-risk milestones — target date ≤14 days AND <60% done.
5. Completed last 7 days.
6. Plain-English 1-paragraph executive summary.

Output: structured JSON per section + `generated_at` top-level.

## Pi-Dev-Ops side responsibilities

### When filing analysis output

- MUST generate a unique `run_id` per run. Format: `{repo}-{commit_sha}-{timestamp}` or UUID.
- MUST supply `source_repo`, `commit_sha`, `dashboard_session_url` in every artefact.
- MUST invoke Skill 1 via Linear Agent — never raw Linear API.
- MUST NOT create Linear issues directly.

### When claiming work (autonomy poller)

- MUST call Skill 2 — do not query Linear GraphQL directly for the queue.
- On claim: atomically transition `Ready for Pi-Dev` → `Pi-Dev: In Progress` BEFORE any code execution begins.
- On completion:
  - If `pi-dev:needs-review` → `In Review`
  - Else (autonomous) → `Done`
- On failure:
  - `Pi-Dev: Blocked` + `pi-dev:blocked-reason:<type>` + explanatory comment.
- MUST post a comment on the issue with: session URL, duration, summary of work done, files changed.

## Standard footer block

Every issue Pi-Dev creates MUST end with:

```
---
**Pi-Dev-Ops run**
- Run ID: `{run_id}`
- Source: [{source_repo}@{commit_sha_short}]({github_commit_url})
- Session: [Dashboard]({dashboard_session_url})
- Filed: {current_date_iso}
```

Missing footer = contract violation. The consistency-audit flags it.

## Failure-mode routing table

| Failure | Detected by | Action |
|---|---|---|
| Target project doesn't exist | Skill 1 pre-check | Stop, alert user, do NOT silently create |
| Duplicate run_id | Skill 1 pre-check | Update in place |
| Malformed artefact | Skill 1 pre-check | Stop, return structured error |
| Autonomy queue stale | Skill 3 check 5 | Consistency-audit flag |
| Pi-Dev session hangs | Skill 4 section 2 | `>48h in Pi-Dev: In Progress` flag |
| Linear API rate limit | Any skill | Retry with backoff, then Telegram escalation |
| Linear key rotated | Any skill | Poller fails; integration-health daemon (RA-1293) pings Telegram |

## Security boundary

- `LINEAR_API_KEY` in Railway = **workspace-wide write**. Rotate ≥ every 90 days. Never log. Audit git history before any repo goes public. RA-1293 integration-health probes this key every 60 s and Telegram-alerts on 401.
- Programmatic skill invocation uses the workspace key via the Linear Agent wrapper — keeps every write in one auditable place.

## What drift looks like (watchlist)

1. **Project-repo name drift** — rename a repo, forget Linear project. Routing silently wrong. → Skill 3 check 3 catches it; also part of change-control checklist.
2. **Runaway queue** — Pi-Dev offline 1 day, queue builds, 50-issue parallel pickup on restart. → Skill 4 flags `>20`; Pi-Dev's own rate limiter is mandatory defence-in-depth.
3. **"Done" without review drift** — autonomous flag applied too liberally. → Default to `pi-dev:needs-review`; loosen over time as trust builds.
4. **Stuck-in-progress** — session crashes, issue stuck `Pi-Dev: In Progress` forever. → Skill 4 `>48h` flag; Linear automation auto-moves to Blocked after 72h.
5. **Skill behaviour drift** — Linear Agent model changes, Skills shift semantics. → This document is version-controlled; re-validate Skills against it quarterly.

## When to invoke this skill

- **Reviewing any code change that writes to Linear** — verify it uses Skill 1/2, not raw API, and includes the footer block + run_id.
- **Reviewing the autonomy poller** — verify status filter is `Ready for Pi-Dev` + label `pi-dev:autonomous` (not "Unstarted" type alone).
- **Reviewing transitions** — confirm on-complete/on-fail transitions use the 4 Pi-Dev statuses, not generic `Done`/`In Progress`.
- **Auditing an incident** — trace the failure mode to the contract table above.
- **Before any workspace-setup change** — Part 1 is a binding schema; edits need consistency-audit re-run.

Code-side compliance gaps are tracked in RA-1297; human-side workspace setup (Part 1) in RA-1298.

## Launch-crew finding sync (added by the launch crew)

The launch crew ([`ship-it`](../ship-it/SKILL.md) → [`launch-project-audit`](../launch-project-audit/SKILL.md) + [`launch-review`](../launch-review/SKILL.md) + [`launch-enhance-debloat`](../launch-enhance-debloat/SKILL.md)) routes its findings into Linear through THIS contract — it does not define its own.

### Push (findings → Linear)
1. Read the latest `.harness/audits/audit-*.md`, `review-*.md`, `enhance-*.md`.
2. Map each finding to the correct project via `config/harness/projects.json`, matching on the entry's
   **`id`** — never `repo`, which is not unique (`CleanExpo/Pi-Dev-Ops` carries both `pi-dev-ops` and
   `margot`). Where a finding's id is genuinely unclear, ask once and persist the answer.
3. Create one issue per finding (de-duplicate first — search existing issues, update rather than duplicate):
   - **Title** — short, concrete.
   - **Description** — what / where (file/URL) / why it matters / suggested fix, plus the `run_id` + footer block this contract already mandates.
   - **Priority** — CRITICAL → Urgent/High, WARNING → Medium, SUGGESTION → Low.
   - **Source label** — `pm` / `growth` / `engineer` / `design` / `build-state` / `security`.
4. **Mark build-ready work with the EXISTING markers, not a new tag:** set status **`Ready for Pi-Dev`** + label **`pi-dev:autonomous`** ONLY on safe, reversible findings. Anything irreversible or business-judgment (production deploy, deleting data, pricing, legal copy, any 🚫-tier path) is left WITHOUT the autonomous label — it waits for a human.

### Pull (Linear → builders)
The autonomy queue is already defined above (status `Ready for Pi-Dev` + label `pi-dev:autonomous`). The launch crew adds no new loop — sandboxed building runs through the existing [`tao-loop`](../tao-loop/SKILL.md) + [`tao-judge`](../tao-judge/SKILL.md), per-feature phases through `ship-chain`, and the terminal ≥8/10 gate through `ship-release`. On merge + production deploy the issue closes via the existing GitHub/Vercel/Railway status round-trip.

### Verification
- Each launch-crew finding maps to exactly one issue at the right priority — no duplicates across runs.
- Only safe/reversible findings carry status `Ready for Pi-Dev` + `pi-dev:autonomous`; no 🚫-path or business-judgment issue is autonomous.
- No new machine tag (e.g. `[hermes:build]`) is introduced — the contract's existing markers are the single source of truth.

## Producer-side triage gate (Pocock /triage, 2026-07)

The producer-side complement to the estate's continuous Linear pull — consumers only claim tickets triaged to ready-for-agent, so the poller never stumbles on under-specified work:
- **Label state machine:** two category labels (`bug` / `enhancement`) plus five mutually exclusive state labels — `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wont-fix`. Every triaged issue carries exactly one of each; the invariant is trivially auditable in Linear.
- **Ready-for-agent gate:** an issue is agent-consumable ONLY with a written agent brief — context, repro, acceptance criteria. In this contract, promotion to ready-for-agent = status `Ready for Pi-Dev` + label `pi-dev:autonomous`; never apply the markers without the brief.
- **`.out-of-scope/` rejection ADRs:** short top-level records of features ruled out; triage checks them and auto-closes matching enhancement requests — rejections compound into policy.

Provenance: [[pocock-triage-skill-backlog-2026-07-14-ingest]]

