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_projectparameter wins. - Autonomy signal: STATUS-based. A ticket is autonomous-pickable iff status=
Ready for Pi-DevAND labelpi-dev:autonomous. Both required — status alone is not authorisation. - Idempotency: Every Pi-Dev run has a unique
run_id. Stored in thePi-Dev Run IDcustom 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):
- Target project exists (do NOT silently create — stop and ask).
- Any existing issues with the same run_id → update in place (idempotency).
sprint_planhas at least one non-empty title (malformed artefact detection).
Then creates, in order:
- Spec document (if provided) — title
[Pi-Dev] Spec: {repo} @ {sha_short}, project-scoped, executive summary prepended. - Milestones (if provided) — names verbatim.
- One issue per
sprint_planentry 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:
- Enabled projects missing any of the 4 mandatory statuses.
pi-dev:sourceissues missingPi-Dev Run IDcustom field.pi-dev:autonomousissues NOT inReady for Pi-Dev/Pi-Dev: In Progress(misuse).- Enabled projects with no GitHub-repo reference anywhere.
- Stale queue (>7 days in
Ready for Pi-Dev). Pi-Dev: Blockedissues missingpi-dev:blocked-reason:*label.- 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:
- Autonomy queue — count per project, oldest age, >20-depth flags.
- Active work —
Pi-Dev: In Progressper project,>48h = stucklisted separately. - Blocked work — every
Pi-Dev: Blocked, sorted by duration desc. - At-risk milestones — target date ≤14 days AND <60% done.
- Completed last 7 days.
- 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_idper run. Format:{repo}-{commit_sha}-{timestamp}or UUID. - MUST supply
source_repo,commit_sha,dashboard_session_urlin 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 ProgressBEFORE any code execution begins. - On completion:
- If
pi-dev:needs-review→In Review - Else (autonomous) →
Done
- If
- 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_KEYin 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)
- 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.
- 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. - "Done" without review drift — autonomous flag applied too liberally. → Default to
pi-dev:needs-review; loosen over time as trust builds. - Stuck-in-progress — session crashes, issue stuck
Pi-Dev: In Progressforever. → Skill 4>48hflag; Linear automation auto-moves to Blocked after 72h. - 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+ labelpi-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 → launch-project-audit + launch-review + launch-enhance-debloat) routes its findings into Linear through THIS contract — it does not define its own.
Push (findings → Linear)
- Read the latest
.harness/audits/audit-*.md,review-*.md,enhance-*.md. - Map each finding to the correct project via
config/harness/projects.json, matching on the entry'sid— neverrepo, which is not unique (CleanExpo/Pi-Dev-Opscarries bothpi-dev-opsandmargot). Where a finding's id is genuinely unclear, ask once and persist the answer. - 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.
- Mark build-ready work with the EXISTING markers, not a new tag: set status
Ready for Pi-Dev+ labelpi-dev:autonomousONLY 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-judge, 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+ labelpi-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]]