Pipeline Tracker
Tracks ticket-to-PR pipeline runs, syncs status to Notion, and provides a dashboard view.
Commands
Parse the user's request to determine which command to run:
status(default) - Show dashboard of all ticketssync- Queue Notion updates for current statusresume {ticket-id}- Resume a paused runcheck-merged- Check for merged PRs and update to Done
Configuration
The skill uses the production API by default. No configuration needed for read-only operations.
Defaults (no setup required):
- API URL:
https://api-gateway-856475788601.us-central1.run.app - Read-only endpoints at
/public/*require no authentication
For write operations (transitions, sync), set:
export PIPELINE_API_KEY="..." # Get from GCP Secret Manager or ask admin
Command: status (default)
-
Query tickets from public API (no auth required):
# Use the public endpoint directly - no auth needed curl -s "https://api-gateway-856475788601.us-central1.run.app/public/tickets" | jqOr fetch with standard HTTP request:
const API_URL = process.env.PIPELINE_API_URL || 'https://api-gateway-856475788601.us-central1.run.app' const response = await fetch(`${API_URL}/public/tickets`) const { tickets } = await response.json() -
Present dashboard:
# Pipeline Dashboard ## Active Tickets | Ticket | State | PR | Last Updated | | ------- | ------------- | ---- | ------------ | | {title} | π’ RESEARCH | - | 2h ago | | {title} | π‘ PR_CREATED | #123 | 1d ago | | {title} | π΄ BLOCKED | - | 3d ago | ## Details ### {Ticket Title} - **URL:** {ticketUrl} - **State:** {state} - **Started:** {created_at} - **Last Updated:** {updated_at} - **PR:** {pr_url or "not created"} -
Offer options:
Options: A) Sync all to Notion B) View details for specific ticket C) Resume a ticket
State Icons
- π’ Active: INTAKE, RESEARCH, PLANNING, IMPLEMENTATION
- π‘ Review: PR_CREATED, CI_PASSED
- π΄ Blocked: BLOCKED
- β Done: DONE
Command: sync
Queue Notion updates for all tickets via the sync queue.
Requires PIPELINE_API_KEY for authentication.
-
List tickets from public API:
const API_URL = process.env.PIPELINE_API_URL || 'https://api-gateway-856475788601.us-central1.run.app' const response = await fetch(`${API_URL}/public/tickets`) const { tickets } = await response.json() -
Map state to Notion Status:
Pipeline State Notion Status INTAKE, RESEARCH, PLANNING, IMPLEMENTATION In Progress PR_CREATED, CI_PASSED In Review DONE Done BLOCKED (keep current) -
Queue sync for each ticket:
for (const ticket of tickets) { const notionStatus = mapStateToNotionStatus(ticket.state) await client.queueSync(ticket.id, 'update_notion', { status: notionStatus, prUrl: ticket.pr_url, }) } -
Report results:
Queued {X} Notion syncs: - {Ticket 1}: Status β In Progress - {Ticket 2}: Status β In Review, PR β #123
Command: resume {ticket-id}
Resume a paused or stale ticket.
-
Fetch ticket from API:
const ticket = await client.getTicket(ticketId) -
Determine next skill based on state:
State Next Skill RESEARCH research-orchestrator PLANNING plan-generator IMPLEMENTATION implementation-runner PR_CREATED (wait for merge) BLOCKED (show blockers, ask user) -
Prompt user:
Resuming: {ticket.title} Current state: {ticket.state} Last updated: {ticket.updated_at} Next step: Load {skill-name} skill Continue? (Y/n) -
If confirmed, load the appropriate skill.
Empty State
If no tickets exist:
# Pipeline Dashboard
No active tickets.
To start a new ticket, use the ticket-intake skill.
Command: check-merged
Check for merged PRs and update to Done. This handles the common case where you close the agent before PR merge.
-
Find tickets in review state:
const { tickets } = await client.listTickets({ state: 'PR_CREATED' }) -
Check each PR's merge status:
gh pr view $PR_NUMBER --json state,mergedAt -
For merged PRs, transition to DONE:
await client.transitionState(ticketId, 'DONE', 'PR merged') -
Report:
Checked {X} open PRs: - ABC-123: PR #456 merged β β Transitioned to DONE - DEF-456: PR #789 still open
For detailed merge watching (including closed PR handling), use /skill pr-merge-watcher.
Auto-Check on Status
When running status command, automatically check for merged PRs:
# Pipeline Dashboard
β‘ Quick check: Found 1 merged PR not yet marked Done
β ABC-123: PR #456 merged 2 days ago
Update now? (Y/n)
API Client Reference
Available Methods
| Method | Description |
|---|---|
listTickets({ state, agent_id, limit, offset }) | List tickets with optional filters |
getTicket(id) | Retrieve a ticket by ID |
transitionState(id, state, reason) | Move ticket to a new state |
queueSync(id, action, payload) | Queue a sync action (e.g., Notion status update) |
Listing Tickets
// List all tickets
const { tickets, total } = await client.listTickets({})
// Filter by state
const prCreated = await client.listTickets({ state: 'PR_CREATED' })
const research = await client.listTickets({ state: 'RESEARCH' })
// Filter by agent
const myTickets = await client.listTickets({ agent_id: 'my-agent' })
// Pagination
const page2 = await client.listTickets({ limit: 10, offset: 10 })
The listTickets() method returns:
{
tickets: Ticket[]; // array of ticket objects
total: number; // total count matching filter
limit: number; // page size
offset: number; // current offset
}
Error Handling
import { PipelineClient, PipelineAPIError } from '@pipeline/client'
try {
const ticket = await client.getTicket('invalid-id')
} catch (error) {
if (error instanceof PipelineAPIError) {
console.error(`API error ${error.status}: ${error.message}`)
}
}
