Await Polygraph CI
Wait for all CI pipelines in a Polygraph session to reach a stable state (succeeded, failed, etc.), then produce a unified summary. If any pipelines failed, investigate via child agents and present fix options.
Some Polygraph tools have both MCP and CLI equivalents — use whichever is available in your environment. See the polygraph skill's tool table for the full mapping.
CI status source
CI polling uses the polygraph-mcp show_session tool, which now carries per-PR CI status directly on each pull request:
show_session(sessionId: "<session-id>")
It returns the full session, including repositories[] (for repo display names) and pullRequests[]. Each pullRequests[] entry has id, repositoryId, url, branch, status (PR status: DRAFT / OPEN / MERGED / CLOSED), and a ci object — ci may be absent if the PR has no CI. When present, ci has status, cipeUrl (non-null ⇒ CIPE; null + externalCIRuns ⇒ external CI), completedAt, selfHealingStatus, and externalCIRuns[] (each with runId, name, status, conclusion, url, and jobs[]). Always read ci defensively (pr.ci?.…).
cipeUrl is a human-facing web link, NOT a data source. It points at the Nx Cloud web app, which requires browser authentication and returns no machine-readable data. Never fetch, curl, WebFetch, or poll cipeUrl (or any other Nx Cloud URL) directly. CI status comes only from polling show_session; CIPE details (failed tasks, logs, self-healing) come only from the Nx MCP ci_information tool. The only thing to do with cipeUrl is display it to the user so they can open it in a browser.
Prerequisite: Nx MCP server (CIPE deep-dive + self-healing)
CIPE failure investigation (ci_information) and applying/rejecting self-healing fixes (update_self_healing_fix) are not polygraph-mcp tools — they are provided by the Nx MCP server (mcp__plugin_nx_nx-mcp). Before relying on the Phase 4 CIPE deep-dive or the Phase 5 self-healing actions, install the Nx MCP server and verify it is available.
If the Nx MCP server is not available, this skill can still:
- Monitor CI to a terminal state (Phases 1–3) via
show_session, and
- Download and inspect external-CI job logs via
get_ci_logs (a polygraph-mcp tool).
But it cannot perform CIPE deep-dives (ci_information) or apply self-healing fixes (update_self_healing_fix) without the Nx MCP server. Do NOT compensate by fetching or scraping cipeUrl — there is no HTTP fallback for CIPE data; the Nx MCP server is the only programmatic access.
If nx-mcp is missing, don't just report the limitation — tell the user how to install it:
- In an Nx workspace, run
nx configure-ai-agents — it sets up the Nx MCP server (and Nx agent skills) for their AI tools, or
- Add the server manually as a stdio MCP server:
npx nx-mcp@latest (see https://github.com/nrwl/nx-ai-agents-config for details).
MCP servers load at session start, so the user must restart the agent session after installing before the deep-dive and self-healing actions become available.
Phase 1: Session Setup
Fetch the session using show_session and read per-PR CI status from pullRequests[].
Parameters:
sessionId (required): The Polygraph session ID
show_session(sessionId: "<session-id>")
- Record
monitorStartedAt = current timestamp (epoch millis).
- Build a tracking table from
pullRequests[]. For each PR, map:
repo: repository display name from the matching repositories[] entry by pr.repositoryId (fall back to pr.branch if not found)
repoId: pr.repositoryId (pass straight to get_ci_logs)
prUrl: pr.url
prStatus: pr.status (DRAFT / OPEN / MERGED / CLOSED)
ciStatus: pr.ci?.status (may already be a terminal status from a previous run)
cipeUrl: pr.ci?.cipeUrl (null if none → external CI or no CI)
cipeCompletedAt: pr.ci?.completedAt (epoch millis, null if CIPE is active or absent)
selfHealingStatus: pr.ci?.selfHealingStatus (null if none)
jobs: pr.ci?.externalCIRuns?.flatMap(r => r.jobs) (external-CI job list, used in Phase 4)
firstSeenAt: current timestamp
- If
pullRequests[] is empty, report "No PRs in session" and exit.
- Stale detection: For each PR, determine if its CI status is stale — meaning it reflects a previous run, not a current one. A PR's CI status is stale if:
cipeCompletedAt is non-null AND cipeCompletedAt < monitorStartedAt (the CIPE finished before the monitor started)
- Mark these PRs as
stale: true
- Display the initial status table, annotating stale PRs:
backend: SUCCEEDED (stale) | frontend: SUCCEEDED (stale) | shared-lib: NOT_STARTED
Phase 2: Polling Loop
Configuration:
- Timeout: 30 minutes total
- Backoff: 60s → 90s → 120s (cap)
- Circuit breaker: exit after 5 consecutive polls with no status change
Each poll iteration:
- Call
show_session(sessionId: <session-id>)
- Update each tracked PR from its matching
pullRequests[] entry (by PR id / repositoryId): ciStatus ← pr.ci?.status, cipeUrl ← pr.ci?.cipeUrl, cipeCompletedAt ← pr.ci?.completedAt, selfHealingStatus ← pr.ci?.selfHealingStatus, prStatus ← pr.status, and jobs ← pr.ci?.externalCIRuns?.flatMap(r => r.jobs)
- Clear stale flag: If a PR was marked
stale: true and its cipeCompletedAt has changed (or become null, meaning a new CIPE is active), clear the stale flag — this PR now has fresh CI data.
- Display status update:
[await-polygraph-ci] Poll #N | Elapsed: Xm | Repos: Y total, Z completed
backend: SUCCEEDED | frontend: FAILED (self-healing: PENDING) | shared-lib: SUCCEEDED (stale)
Include selfHealingStatus inline when non-null. Annotate stale PRs.
- Check exclusion rule: if a PR has
prStatus: DRAFT and ciStatus: NOT_STARTED for more than 5 minutes since firstSeenAt, mark it as EXCLUDED (DRAFT PRs may not trigger CI)
- Check terminal conditions — a PR is terminal when:
- It is NOT stale, AND:
- CI status is
SUCCEEDED, CANCELED, or TIMED_OUT, OR
- CI status is
FAILED AND there is no active self-healing (i.e., selfHealingStatus is null or a final state like APPLIED, REJECTED, FAILED)
- A
FAILED PR with selfHealingStatus indicating an in-progress fix (e.g., PENDING, IN_PROGRESS) is NOT terminal — keep polling to track the self-healing outcome
- A stale PR is NOT terminal — keep polling until it gets a fresh CIPE or is excluded
- Stale timeout: If a stale PR remains stale for more than 5 minutes, assume no new CI is expected for it. Clear the stale flag and treat its current status as final.
- If all non-excluded PRs are terminal → proceed to Phase 3
- If timeout or circuit breaker hit → proceed to Phase 3 with partial results
- Otherwise → wait with backoff, then poll again
Phase 3: Results Analysis
Categorize repos into: succeeded, failed, canceled, timed_out, excluded, in_progress (if timed out).
Display final summary table. When showing self-healing status, distinguish clearly between these states:
COMPLETED = a fix was generated and verified, but NOT yet applied. Display as fix available.
APPLIED = the fix was applied by the user or agent. Display as fix applied, awaiting re-run.
IN_PROGRESS / PENDING = the fix is still being generated. Display as in progress.
REJECTED = the fix was rejected. Display as fix rejected.
FAILED = self-healing failed to produce a fix. Display as fix failed.
[await-polygraph-ci] Final Results | Elapsed: Xm
SUCCEEDED: backend, shared-lib
FAILED: frontend (self-healing: fix available)
EXCLUDED: docs (DRAFT, no CI)
Include self-healing status for any repo that has one.
- If all succeeded → report success and exit
- If any failed with
selfHealingStatus: APPLIED, inform the user that the fix was applied and a CI re-run may be in progress or needed
- If any failed with
selfHealingStatus: COMPLETED, inform the user that a fix is available but not yet applied, and offer to apply it
- If any failed → proceed to Phase 4
Phase 4: Failure Investigation (Child Agent Delegation)
For each repo with ciStatus: FAILED, branch on the PR's ci object from show_session (pullRequests[]):
- If
pr.ci.cipeUrl is non-null → CIPE is authoritative. Delegate investigation using the Nx MCP ci_information tool (requires the Nx MCP server — see the prerequisite note above; if nx-mcp is unavailable, report the CIPE URL to the user, offer the install steps from the prerequisite section, and do NOT fetch the URL as a substitute).
- If
pr.ci.cipeUrl is null but pr.ci.externalCIRuns exists → external CI only. Examine failed jobs from pr.ci.externalCIRuns[].jobs and use get_ci_logs(sessionId, repositoryId, jobId) (a polygraph-mcp tool) for log retrieval, passing pr.repositoryId and the failed job's jobId straight from the same PR object.
{% if platform == "codex" %}
Codex subagent wrapper: Call the Polygraph MCP spawn_agent directly to start each investigation and collect its delegation id, then launch one Codex spawn_agent with agent_type: "polygraph-delegate-subagent" per id to wait on it, collecting them with wait_agent. Only the waiting belongs in the subagent; the unwaited show_agent read that returns each investigation is yours to make here.
{% endif %}
Display known info from the PR's ci object before delegating:
Repository: frontend
CI Source: <CIPE or External CI (GitHub Actions)>
CI Pipeline: <pr.ci.cipeUrl, or GitHub Actions run URL>
Self-healing: <pr.ci.selfHealingStatus, or "None">
Investigating failure details...
Delegate investigation (non-blocking) — call spawn_agent for each failed repo:
sessionId: the session ID
repo: the repository name
instruction (when CIPE exists): Use the Nx MCP ci_information tool to investigate the CI failure on this branch (the Nx MCP server must be installed). Return a structured summary with: (1) list of failed task IDs with a one-line error summary each, (2) failure category (Build / Test / Lint / E2E / Infra / Other).
instruction (when no CIPE, external CI only): The PR's ci object shows external CI failures with these failed jobs: [list jobId + name from pr.ci.externalCIRuns[].jobs where conclusion is failure]. Use get_ci_logs(sessionId, repositoryId, jobId) to save the log for each failed job to a local file, then use the Read tool to examine the log file contents. Return a structured summary with: (1) one-line error summary per failed job, (2) failure category (Build / Test / Lint / E2E / Infra / Other), (3) relevant log excerpts.
context: Polygraph session monitoring — investigating CI failure for unified summary. The repository ID for this repo is the PR's repositoryId.
Since spawn_agent is non-blocking, you can delegate to multiple failed repos in parallel.
Monitor investigation progress — launch one background polygraph-delegate-subagent per delegation id and let it do the waiting. When it exits, read that investigation with a single unwaited show_agent:
show_agent(sessionId: "<session-id>", id: "<delegation-id>")
result.text is the child's investigation summary. Never run a waited show_agent loop here, and do not pass tail unless result.text alone is insufficient.
Collect each child agent's response from its unwaited show_agent read. If a child agent fails or gets stuck, use stop_agent with its delegation id to terminate it and skip that repo.
Display failure summary for each repo:
Repository: frontend
CI Pipeline: <cipeUrl>
Failed Tasks (2):
- frontend:build → TypeScript error in src/app.tsx:42
- frontend:test → 3 test suites failed
Category: Build + Test failures
Self-healing: <selfHealingStatus>
Job Logs: <number of logs retrieved, if any>
If CI job logs were retrieved via get_ci_logs, include relevant excerpts (error messages, stack traces) in the summary. Keep excerpts concise — only the most relevant lines.
Phase 5: Fix Planning
- Group failures by category (Build, Test, Lint, E2E, Infra)
- Identify cross-repo dependency issues (e.g., shared-lib build failure blocking frontend)
- Suggest fix order based on dependency graph (upstream repos first)
- Present next actions to the user based on self-healing status:
- If any repo has
selfHealingStatus with an available fix → offer to apply self-healing via update_self_healing_fix(action: "APPLY") or reject it. update_self_healing_fix is an Nx MCP tool (mcp__plugin_nx_nx-mcp) — it requires the Nx MCP server. If nx-mcp is unavailable, report that a fix is available but cannot be applied from here, and offer the install steps from the prerequisite section.
- If self-healing was already applied → offer to resume monitoring to watch the re-triggered CI
- Delegate fixes: use Polygraph to send fix instructions to child agents (for repos without self-healing or where self-healing was rejected/failed)
- Get more details: drill into a specific repo's failure
- Exit: done monitoring
Notes
- This skill does NOT push code directly. The only write action it may take is applying/rejecting a self-healing fix via
update_self_healing_fix, an Nx MCP tool that performs an Nx Cloud operation (not a local code change) and requires the Nx MCP server.
- Both
ci_information and update_self_healing_fix are Nx MCP tools (mcp__plugin_nx_nx-mcp), not polygraph-mcp tools. Their responses include a hints array with contextual guidance (e.g., disclaimers about which CI Attempt was retrieved). Always check and surface non-empty hints.
cipeUrl is a browser link for the user — never fetch, curl, WebFetch, or poll it (in the main agent or in child agents). CIPE data is only available via the Nx MCP ci_information tool.
- All heavy CI data inspection happens in child agents via
spawn_agent to keep this context window clean.
{% if platform == "codex" %}
- On Codex, the waiting runs inside
polygraph-delegate-subagent and the main conversation uses wait_agent to collect it; spawn_agent and the unwaited show_agent read stay in the main conversation.
{% endif %}
- Child agents can use
get_ci_logs to save CI job logs to local files, but ONLY when no CIPE exists for the PR (pr.ci.cipeUrl is null). When a CIPE exists, logs come from the CIPE system via the Nx MCP ci_information tool. Job IDs come from pr.ci.externalCIRuns[].jobs[].jobId in the show_session response. The tool returns a file path (logFile) and size (sizeBytes) — use the Read tool to examine the log content. Logs can be large (100KB+), so only fetch logs for failed or relevant jobs.
spawn_agent is non-blocking — it starts the child agent and returns a delegation id immediately. Waiting on that id belongs in a background poller subagent; an unwaited show_agent by id returns the result, and stop_agent by id terminates a stuck agent.
- The
show_session response is compact and safe to poll from the main agent.
1---2name: await-polygraph-ci3description: Await Polygraph CI4---56# Await Polygraph CI78Wait for all CI pipelines in a Polygraph session to reach a stable state (succeeded, failed, etc.), then produce a unified summary. If any pipelines failed, investigate via child agents and present fix options.910Some Polygraph tools have both MCP and CLI equivalents — use whichever is available in your environment. See the polygraph skill's tool table for the full mapping.1112## CI status source1314CI polling uses the polygraph-mcp `show_session` tool, which now carries per-PR CI status directly on each pull request:1516```17show_session(sessionId: "<session-id>")18```1920It returns the full session, including `repositories[]` (for repo display names) and `pullRequests[]`. Each `pullRequests[]` entry has `id`, `repositoryId`, `url`, `branch`, `status` (PR status: `DRAFT` / `OPEN` / `MERGED` / `CLOSED`), and a `ci` object — **`ci` may be absent if the PR has no CI**. When present, `ci` has `status`, `cipeUrl` (non-null ⇒ CIPE; null + `externalCIRuns` ⇒ external CI), `completedAt`, `selfHealingStatus`, and `externalCIRuns[]` (each with `runId`, `name`, `status`, `conclusion`, `url`, and `jobs[]`). Always read `ci` defensively (`pr.ci?.…`).2122**`cipeUrl` is a human-facing web link, NOT a data source.** It points at the Nx Cloud web app, which requires browser authentication and returns no machine-readable data. Never fetch, curl, WebFetch, or poll `cipeUrl` (or any other Nx Cloud URL) directly. CI *status* comes only from polling `show_session`; CIPE *details* (failed tasks, logs, self-healing) come only from the Nx MCP `ci_information` tool. The only thing to do with `cipeUrl` is display it to the user so they can open it in a browser.2324## Prerequisite: Nx MCP server (CIPE deep-dive + self-healing)2526CIPE failure investigation (`ci_information`) and applying/rejecting self-healing fixes (`update_self_healing_fix`) are **not** polygraph-mcp tools — they are provided by the **Nx MCP server** (`mcp__plugin_nx_nx-mcp`). Before relying on the Phase 4 CIPE deep-dive or the Phase 5 self-healing actions, install the Nx MCP server and verify it is available.2728If the Nx MCP server is **not** available, this skill can still:2930- Monitor CI to a terminal state (Phases 1–3) via `show_session`, and31- Download and inspect **external-CI** job logs via `get_ci_logs` (a polygraph-mcp tool).3233But it **cannot** perform CIPE deep-dives (`ci_information`) or apply self-healing fixes (`update_self_healing_fix`) without the Nx MCP server. Do NOT compensate by fetching or scraping `cipeUrl` — there is no HTTP fallback for CIPE data; the Nx MCP server is the only programmatic access.3435If nx-mcp is missing, don't just report the limitation — tell the user how to install it:3637- In an Nx workspace, run `nx configure-ai-agents` — it sets up the Nx MCP server (and Nx agent skills) for their AI tools, or38- Add the server manually as a stdio MCP server: `npx nx-mcp@latest` (see https://github.com/nrwl/nx-ai-agents-config for details).3940MCP servers load at session start, so the user must restart the agent session after installing before the deep-dive and self-healing actions become available.4142## Phase 1: Session Setup4344Fetch the session using `show_session` and read per-PR CI status from `pullRequests[]`.4546**Parameters:**4748- `sessionId` (required): The Polygraph session ID4950```51show_session(sessionId: "<session-id>")52```53541. Record `monitorStartedAt` = current timestamp (epoch millis).552. Build a tracking table from `pullRequests[]`. For each PR, map:56 - `repo`: repository display name from the matching `repositories[]` entry by `pr.repositoryId` (fall back to `pr.branch` if not found)57 - `repoId`: `pr.repositoryId` (pass straight to `get_ci_logs`)58 - `prUrl`: `pr.url`59 - `prStatus`: `pr.status` (DRAFT / OPEN / MERGED / CLOSED)60 - `ciStatus`: `pr.ci?.status` (may already be a terminal status from a previous run)61 - `cipeUrl`: `pr.ci?.cipeUrl` (null if none → external CI or no CI)62 - `cipeCompletedAt`: `pr.ci?.completedAt` (epoch millis, null if CIPE is active or absent)63 - `selfHealingStatus`: `pr.ci?.selfHealingStatus` (null if none)64 - `jobs`: `pr.ci?.externalCIRuns?.flatMap(r => r.jobs)` (external-CI job list, used in Phase 4)65 - `firstSeenAt`: current timestamp663. If `pullRequests[]` is empty, report "No PRs in session" and exit.674. **Stale detection**: For each PR, determine if its CI status is **stale** — meaning it reflects a previous run, not a current one. A PR's CI status is stale if:68 - `cipeCompletedAt` is non-null AND `cipeCompletedAt < monitorStartedAt` (the CIPE finished before the monitor started)69 - Mark these PRs as `stale: true`705. Display the initial status table, annotating stale PRs:71 ```72 backend: SUCCEEDED (stale) | frontend: SUCCEEDED (stale) | shared-lib: NOT_STARTED73 ```7475## Phase 2: Polling Loop7677**Configuration:**7879- Timeout: 30 minutes total80- Backoff: 60s → 90s → 120s (cap)81- Circuit breaker: exit after 5 consecutive polls with no status change8283**Each poll iteration:**84851. Call `show_session(sessionId: <session-id>)`862. Update each tracked PR from its matching `pullRequests[]` entry (by PR `id` / `repositoryId`): `ciStatus` ← `pr.ci?.status`, `cipeUrl` ← `pr.ci?.cipeUrl`, `cipeCompletedAt` ← `pr.ci?.completedAt`, `selfHealingStatus` ← `pr.ci?.selfHealingStatus`, `prStatus` ← `pr.status`, and `jobs` ← `pr.ci?.externalCIRuns?.flatMap(r => r.jobs)`873. **Clear stale flag**: If a PR was marked `stale: true` and its `cipeCompletedAt` has changed (or become null, meaning a new CIPE is active), clear the stale flag — this PR now has fresh CI data.884. Display status update:89 ```90 [await-polygraph-ci] Poll #N | Elapsed: Xm | Repos: Y total, Z completed91 backend: SUCCEEDED | frontend: FAILED (self-healing: PENDING) | shared-lib: SUCCEEDED (stale)92 ```93 Include `selfHealingStatus` inline when non-null. Annotate stale PRs.945. Check exclusion rule: if a PR has `prStatus: DRAFT` and `ciStatus: NOT_STARTED` for more than 5 minutes since `firstSeenAt`, mark it as `EXCLUDED` (DRAFT PRs may not trigger CI)956. Check terminal conditions — a PR is terminal when:96 - It is NOT stale, AND:97 - CI status is `SUCCEEDED`, `CANCELED`, or `TIMED_OUT`, OR98 - CI status is `FAILED` AND there is no active self-healing (i.e., `selfHealingStatus` is null or a final state like `APPLIED`, `REJECTED`, `FAILED`)99 - A `FAILED` PR with `selfHealingStatus` indicating an in-progress fix (e.g., `PENDING`, `IN_PROGRESS`) is NOT terminal — keep polling to track the self-healing outcome100 - A **stale** PR is NOT terminal — keep polling until it gets a fresh CIPE or is excluded1017. **Stale timeout**: If a stale PR remains stale for more than 5 minutes, assume no new CI is expected for it. Clear the stale flag and treat its current status as final.1028. If all non-excluded PRs are terminal → proceed to Phase 31039. If timeout or circuit breaker hit → proceed to Phase 3 with partial results10410. Otherwise → wait with backoff, then poll again105106## Phase 3: Results Analysis107108Categorize repos into: succeeded, failed, canceled, timed_out, excluded, in_progress (if timed out).109110Display final summary table. When showing self-healing status, distinguish clearly between these states:111112- `COMPLETED` = a fix was **generated and verified**, but **NOT yet applied**. Display as `fix available`.113- `APPLIED` = the fix was **applied** by the user or agent. Display as `fix applied, awaiting re-run`.114- `IN_PROGRESS` / `PENDING` = the fix is still being generated. Display as `in progress`.115- `REJECTED` = the fix was rejected. Display as `fix rejected`.116- `FAILED` = self-healing failed to produce a fix. Display as `fix failed`.117118```119[await-polygraph-ci] Final Results | Elapsed: Xm120 SUCCEEDED: backend, shared-lib121 FAILED: frontend (self-healing: fix available)122 EXCLUDED: docs (DRAFT, no CI)123```124125Include self-healing status for any repo that has one.126127- If all succeeded → report success and exit128- If any failed with `selfHealingStatus: APPLIED`, inform the user that the fix was applied and a CI re-run may be in progress or needed129- If any failed with `selfHealingStatus: COMPLETED`, inform the user that a fix is **available but not yet applied**, and offer to apply it130- If any failed → proceed to Phase 4131132## Phase 4: Failure Investigation (Child Agent Delegation)133134For each repo with `ciStatus: FAILED`, branch on the PR's `ci` object from `show_session` (`pullRequests[]`):135136- **If `pr.ci.cipeUrl` is non-null** → CIPE is authoritative. Delegate investigation using the Nx MCP `ci_information` tool (requires the Nx MCP server — see the prerequisite note above; if nx-mcp is unavailable, report the CIPE URL to the user, offer the install steps from the prerequisite section, and do NOT fetch the URL as a substitute).137- **If `pr.ci.cipeUrl` is null but `pr.ci.externalCIRuns` exists** → external CI only. Examine failed jobs from `pr.ci.externalCIRuns[].jobs` and use `get_ci_logs(sessionId, repositoryId, jobId)` (a polygraph-mcp tool) for log retrieval, passing `pr.repositoryId` and the failed job's `jobId` straight from the same PR object.138{% if platform == "codex" %}139140**Codex subagent wrapper:** Call the Polygraph MCP `spawn_agent` directly to start each investigation and collect its delegation id, then launch one Codex `spawn_agent` with `agent_type: "polygraph-delegate-subagent"` per id to wait on it, collecting them with `wait_agent`. Only the waiting belongs in the subagent; the unwaited `show_agent` read that returns each investigation is yours to make here.141{% endif %}1421431. Display known info from the PR's `ci` object before delegating:144145 ```146 Repository: frontend147 CI Source: <CIPE or External CI (GitHub Actions)>148 CI Pipeline: <pr.ci.cipeUrl, or GitHub Actions run URL>149 Self-healing: <pr.ci.selfHealingStatus, or "None">150 Investigating failure details...151 ```1521532. **Delegate investigation** (non-blocking) — call `spawn_agent` for each failed repo:154155 - `sessionId`: the session ID156 - `repo`: the repository name157 - `instruction` (when CIPE exists): Use the Nx MCP `ci_information` tool to investigate the CI failure on this branch (the Nx MCP server must be installed). Return a structured summary with: (1) list of failed task IDs with a one-line error summary each, (2) failure category (Build / Test / Lint / E2E / Infra / Other).158 - `instruction` (when no CIPE, external CI only): The PR's `ci` object shows external CI failures with these failed jobs: [list `jobId` + `name` from `pr.ci.externalCIRuns[].jobs` where `conclusion` is `failure`]. Use `get_ci_logs(sessionId, repositoryId, jobId)` to save the log for each failed job to a local file, then use the `Read` tool to examine the log file contents. Return a structured summary with: (1) one-line error summary per failed job, (2) failure category (Build / Test / Lint / E2E / Infra / Other), (3) relevant log excerpts.159 - `context`: Polygraph session monitoring — investigating CI failure for unified summary. The repository ID for this repo is the PR's `repositoryId`.160161 Since `spawn_agent` is non-blocking, you can delegate to multiple failed repos in parallel.1621633. **Monitor investigation progress** — launch one background `polygraph-delegate-subagent` per delegation id and let it do the waiting. When it exits, read that investigation with a single unwaited `show_agent`:164165 ```166 show_agent(sessionId: "<session-id>", id: "<delegation-id>")167 ```168169 `result.text` is the child's investigation summary. Never run a waited `show_agent` loop here, and do not pass `tail` unless `result.text` alone is insufficient.1701714. Collect each child agent's response from its unwaited `show_agent` read. If a child agent fails or gets stuck, use `stop_agent` with its delegation id to terminate it and skip that repo.1721735. Display failure summary for each repo:174175 ```176 Repository: frontend177 CI Pipeline: <cipeUrl>178 Failed Tasks (2):179 - frontend:build → TypeScript error in src/app.tsx:42180 - frontend:test → 3 test suites failed181 Category: Build + Test failures182 Self-healing: <selfHealingStatus>183 Job Logs: <number of logs retrieved, if any>184 ```185186 If CI job logs were retrieved via `get_ci_logs`, include relevant excerpts (error messages, stack traces) in the summary. Keep excerpts concise — only the most relevant lines.187188## Phase 5: Fix Planning1891901. Group failures by category (Build, Test, Lint, E2E, Infra)1912. Identify cross-repo dependency issues (e.g., shared-lib build failure blocking frontend)1923. Suggest fix order based on dependency graph (upstream repos first)1934. Present next actions to the user based on self-healing status:194 - If any repo has `selfHealingStatus` with an available fix → offer to **apply self-healing** via `update_self_healing_fix(action: "APPLY")` or **reject** it. `update_self_healing_fix` is an **Nx MCP** tool (`mcp__plugin_nx_nx-mcp`) — it requires the Nx MCP server. If nx-mcp is unavailable, report that a fix is available but cannot be applied from here, and offer the install steps from the prerequisite section.195 - If self-healing was already applied → offer to **resume monitoring** to watch the re-triggered CI196 - **Delegate fixes**: use Polygraph to send fix instructions to child agents (for repos without self-healing or where self-healing was rejected/failed)197 - **Get more details**: drill into a specific repo's failure198 - **Exit**: done monitoring199200## Notes201202- This skill does NOT push code directly. The only write action it may take is applying/rejecting a self-healing fix via `update_self_healing_fix`, an **Nx MCP** tool that performs an Nx Cloud operation (not a local code change) and requires the Nx MCP server.203- Both `ci_information` and `update_self_healing_fix` are **Nx MCP** tools (`mcp__plugin_nx_nx-mcp`), not polygraph-mcp tools. Their responses include a `hints` array with contextual guidance (e.g., disclaimers about which CI Attempt was retrieved). Always check and surface non-empty hints.204- `cipeUrl` is a browser link for the user — never fetch, curl, WebFetch, or poll it (in the main agent or in child agents). CIPE data is only available via the Nx MCP `ci_information` tool.205- All heavy CI data inspection happens in child agents via `spawn_agent` to keep this context window clean.206{% if platform == "codex" %}207- On Codex, the waiting runs inside `polygraph-delegate-subagent` and the main conversation uses `wait_agent` to collect it; `spawn_agent` and the unwaited `show_agent` read stay in the main conversation.208{% endif %}209- Child agents can use `get_ci_logs` to save CI job logs to local files, but ONLY when no CIPE exists for the PR (`pr.ci.cipeUrl` is null). When a CIPE exists, logs come from the CIPE system via the Nx MCP `ci_information` tool. Job IDs come from `pr.ci.externalCIRuns[].jobs[].jobId` in the `show_session` response. The tool returns a file path (`logFile`) and size (`sizeBytes`) — use the `Read` tool to examine the log content. Logs can be large (100KB+), so only fetch logs for failed or relevant jobs.210- `spawn_agent` is **non-blocking** — it starts the child agent and returns a delegation id immediately. Waiting on that id belongs in a background poller subagent; an unwaited `show_agent` by id returns the result, and `stop_agent` by id terminates a stuck agent.211- The `show_session` response is compact and safe to poll from the main agent.