@openhands/extensions 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/.github/workflows/check-extensions.yml +4 -0
  2. package/.github/workflows/pr-artifacts.yml +294 -0
  3. package/.github/workflows/pr-description-check.yml +4 -2
  4. package/.release-please-manifest.json +1 -1
  5. package/AGENTS.md +28 -4
  6. package/README.md +5 -2
  7. package/automations/README.md +52 -36
  8. package/automations/bundle-index.js +13 -3
  9. package/automations/catalog/custom-automation/manifest.json +229 -0
  10. package/automations/catalog/github-agents-md-maintainer/manifest.json +2 -1
  11. package/automations/catalog/github-issue-to-pr/manifest.json +3 -2
  12. package/automations/catalog/github-issue-triage/manifest.json +72 -0
  13. package/automations/catalog/github-pr-reviewer/manifest.json +3 -2
  14. package/automations/catalog/gitlab-issue-to-mr/manifest.json +124 -0
  15. package/automations/catalog/qa-changes/manifest.json +1 -1
  16. package/automations/catalog-index.js +23 -17
  17. package/automations/catalog.schema.json +81 -7
  18. package/automations/index.d.ts +52 -2
  19. package/automations/interface.json +2 -1
  20. package/integrations/catalog/gitlab.json +27 -5
  21. package/integrations/catalog/reportportal.json +76 -0
  22. package/integrations/catalog-index.js +6 -4
  23. package/marketplaces/openhands-extensions.json +36 -0
  24. package/package.json +1 -1
  25. package/pyproject.toml +2 -2
  26. package/python/openhands_extensions/_version.py +1 -1
  27. package/skills/github/scripts/github_client.py +204 -0
  28. package/skills/github-agents-md-maintainer/SKILL.md +7 -1
  29. package/skills/github-agents-md-maintainer/scripts/main.py +4 -40
  30. package/skills/github-issue-to-pr/SKILL.md +8 -1
  31. package/skills/github-issue-to-pr/scripts/main.py +3 -40
  32. package/skills/github-issue-triage/.plugin/plugin.json +9 -0
  33. package/skills/github-issue-triage/README.md +9 -0
  34. package/skills/github-issue-triage/SKILL.md +37 -0
  35. package/skills/github-issue-triage/commands/github-issue-triage.md +8 -0
  36. package/skills/github-issue-triage/scripts/worker.py +123 -0
  37. package/skills/github-pr-reviewer/SKILL.md +8 -1
  38. package/skills/github-pr-reviewer/scripts/main.py +3 -41
  39. package/skills/github-repo-monitor/SKILL.md +7 -1
  40. package/skills/github-repo-monitor/scripts/main.py +4 -46
  41. package/skills/gitlab-issue-to-mr/.plugin/plugin.json +19 -0
  42. package/skills/gitlab-issue-to-mr/README.md +92 -0
  43. package/skills/gitlab-issue-to-mr/SKILL.md +408 -0
  44. package/skills/gitlab-issue-to-mr/commands/issue-to-mr-setup.md +8 -0
  45. package/skills/gitlab-issue-to-mr/references/state-schema.md +140 -0
  46. package/skills/gitlab-issue-to-mr/scripts/main.py +1448 -0
  47. package/skills/index.js +43 -6
  48. package/skills/openhands-automation/README.md +1 -1
  49. package/skills/openhands-automation/SKILL.md +18 -8
  50. package/skills/openhands-enterprise-troubleshooting/.plugin/plugin.json +20 -0
  51. package/skills/openhands-enterprise-troubleshooting/README.md +79 -0
  52. package/skills/openhands-enterprise-troubleshooting/SKILL.md +339 -0
  53. package/skills/openhands-enterprise-troubleshooting/references/diagnostics.md +698 -0
  54. package/skills/openhands-enterprise-troubleshooting/references/support-bundle-analysis.md +570 -0
  55. package/skills/openhands-enterprise-troubleshooting/scripts/bundle_triage.py +532 -0
  56. package/skills/openhands-sdk/SKILL.md +2 -0
  57. package/tests/fixtures/automations/custom-automation.json +398 -0
  58. package/tests/fixtures/automations/github-pr-reviewer.json +9 -9
  59. package/tests/github_automation_helpers.py +25 -0
  60. package/tests/test_automation_setup.py +340 -92
  61. package/tests/test_github_automation_foundation.py +73 -0
  62. package/tests/test_github_skill_installation.py +63 -0
  63. package/tests/test_github_triage_delivery.py +53 -0
  64. package/tests/test_gitlab_issue_to_mr.py +823 -0
@@ -26,7 +26,7 @@ This skill is activated by keywords:
26
26
 
27
27
  ## API Base URL
28
28
 
29
- All automation endpoints are at: `https://app.all-hands.dev/api/automation/v1`
29
+ Use an explicitly provided host first. When a local Agent Canvas automation server is running and no host is provided, use `http://localhost:8001/api/automation/v1`. Otherwise use the cloud default: `https://app.all-hands.dev/api/automation/v1`.
30
30
 
31
31
  ## Quick Start
32
32
 
@@ -48,7 +48,7 @@ The agent server typically runs inside a **sandbox** (a Docker or Kubernetes con
48
48
  |---|---|---|
49
49
  | `RUNTIME_URL` | Ambient in cloud environments | Public-facing URL of the **agent server** sandbox. Use this to determine whether external webhook delivery is possible — if unset or local, webhooks cannot be received. The automation service may run at a separate URL (see Determining the API Host). |
50
50
  | `AGENT_SERVER_URL` | Injected into scripts at run time only | Internal URL of the agent server. Available inside script execution context; **not** an ambient environment variable outside of a running script. |
51
- | `OPENHANDS_HOST` | Shell convention only — set manually | Base URL for the automation service API. **Not a real environment variable.** Set it from the `<HOST>` system-prompt value, or default to `https://app.all-hands.dev`. Used in all `curl` examples throughout this skill. |
51
+ | `OPENHANDS_HOST` | Shell convention only — set manually | Base URL for the automation service API. **Not a real environment variable.** Set it from an explicit host, a detected local Agent Canvas server, or the cloud default. Used in all `curl` examples throughout this skill. |
52
52
 
53
53
  > **⚠️ CRITICAL — Agent behavior rules:**
54
54
  >
@@ -113,11 +113,17 @@ Entrypoint must be `python3 main.py` (no `setup.sh` needed). Wrap your main logi
113
113
 
114
114
  ## Authentication
115
115
 
116
- All requests require Bearer authentication:
116
+ All requests require authentication:
117
117
 
118
- ```bash
119
- -H "Authorization: Bearer ${OPENHANDS_API_KEY}"
120
- ```
118
+ - Cloud (default `https://app.all-hands.dev`): Bearer token:
119
+
120
+ `-H "Authorization: Bearer ${OPENHANDS_API_KEY}"`
121
+
122
+ - Local Agent Canvas (`http://localhost:8001`): session API key through `X-Session-API-Key`:
123
+
124
+ `-H "X-Session-API-Key: ${OPENHANDS_AUTOMATION_API_KEY:-${SESSION_API_KEY}}"`
125
+
126
+ The curl examples below show cloud Bearer authentication. For local Agent Canvas, replace that header with the `X-Session-API-Key` header above.
121
127
 
122
128
  ## API Endpoints
123
129
 
@@ -127,14 +133,18 @@ All requests require Bearer authentication:
127
133
 
128
134
  The automation service may run at a different URL from the agent server. In the examples throughout this skill, `${OPENHANDS_HOST}` is a shell-variable convention for the automation service base URL — it is **not** a real environment variable. Set it from context before running any curl command:
129
135
 
130
- - Look for a `<HOST>` value in the system prompt. If present, use that URL.
136
+ - Look for a `<HOST>` value in the system prompt or runtime-services block. If present, use that URL.
137
+ - If running inside a local Agent Canvas stack and no explicit host is provided, use `http://localhost:8001` for the local automation/agent-server API.
131
138
  - Otherwise default to `https://app.all-hands.dev`.
132
139
 
140
+ For a local Agent Canvas server, validate the endpoint before making a mutating request and authenticate with the session key through `X-Session-API-Key` when that API requires it. Do not use the cloud default merely because no `<HOST>` value is present.
141
+
133
142
  ```bash
134
- OPENHANDS_HOST="https://app.all-hands.dev" # replace with <HOST> if provided
143
+ # Choose the host that matches the detected environment:
144
+ OPENHANDS_HOST="http://localhost:8001" # local Agent Canvas
145
+ # OPENHANDS_HOST="https://app.all-hands.dev" # OpenHands Cloud
135
146
  ```
136
147
 
137
-
138
148
  ### Automation Endpoints
139
149
 
140
150
  | Endpoint | Method | Description |
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "openhands-enterprise-troubleshooting",
3
+ "version": "1.0.0",
4
+ "description": "Diagnose and resolve common issues on OpenHands Enterprise self-hosted installations. Covers sandbox startup failures, auth issues, certificate errors, LLM connectivity, Keycloak login, Replicated Admin Console access, upgrade failures, and resource exhaustion. Includes support bundle generation, offline bundle analysis with a bundled triage script, and escalation handoffs.",
5
+ "author": {
6
+ "name": "OpenHands",
7
+ "email": "contact@all-hands.dev"
8
+ },
9
+ "homepage": "https://github.com/OpenHands/extensions",
10
+ "repository": "https://github.com/OpenHands/extensions",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "openhands",
14
+ "enterprise",
15
+ "troubleshooting",
16
+ "replicated",
17
+ "support-bundle",
18
+ "kubernetes"
19
+ ]
20
+ }
@@ -0,0 +1,79 @@
1
+ # OpenHands Enterprise Troubleshooting
2
+
3
+ An agent-runnable skill for diagnosing and resolving common issues on **OpenHands Enterprise (OHE)** - self-hosted installations using Replicated on VM-based infrastructure.
4
+
5
+ ## What This Skill Does
6
+
7
+ ### 1. Triage and Diagnosis
8
+ - Detects failure modes from symptoms or log output
9
+ - Checks common problem areas: sandbox startup, auth, certificates, LLM connectivity, Keycloak, Replicated Admin Console, upgrades, resource exhaustion
10
+ - Runs targeted diagnostic commands against the live environment
11
+
12
+ ### 2. Guided Recovery
13
+ - Walks through resolution steps for identified issues
14
+ - Validates each step before proceeding
15
+ - Covers the most common failures seen across real OHE installations
16
+
17
+ ### 3. Support Bundle Generation and Analysis
18
+ - Guides customers through generating and sending support bundles
19
+ - Maps the `kubectl` commands you would normally run onto the files that actually hold that data
20
+ - Ships an offline triage script that reconstructs the standard first pass in one command
21
+ - Documents what a bundle does *not* contain, so a negative result is not misread
22
+ - Reduces back-and-forth with the OpenHands team
23
+
24
+ ### 4. Escalation Handoff
25
+ - Produces a clear summary when issues cannot be resolved
26
+ - Documents what was tried, what logs show, and likely root cause
27
+ - Ready to paste into a support ticket
28
+
29
+ ## Common Issues Covered
30
+
31
+ - Sandbox fails to start / 120s timeout
32
+ - Git provider auth broken (GitHub, GitLab, Bitbucket Data Center, Azure DevOps)
33
+ - Certificate errors (self-signed, expired, chain issues)
34
+ - LLM connectivity failures (endpoint unreachable, bad credentials)
35
+ - Keycloak login issues
36
+ - Replicated Admin Console unreachable
37
+ - Upgrade stuck or failed
38
+ - OOM / resource exhaustion on the VM
39
+
40
+ ## Usage
41
+
42
+ This skill is automatically triggered when users describe OHE issues such as:
43
+ - "OpenHands is not working"
44
+ - "Sandbox failed to start"
45
+ - "Can't access admin console"
46
+ - "Certificate error"
47
+ - "LLM connection failed"
48
+ - "Upgrade failed"
49
+
50
+ ## Files
51
+
52
+ - `SKILL.md` - Main skill with diagnostic workflow and quick reference
53
+ - `references/diagnostics.md` - Detailed diagnostic commands and log interpretation for each failure mode
54
+ - `references/support-bundle-analysis.md` - How to read a support bundle offline: the
55
+ `kubectl` → bundle file map, pod state and OOM interpretation, redaction semantics, and known gaps
56
+ - `scripts/bundle_triage.py` - Offline triage script (standard library only, no dependencies)
57
+
58
+ ## Analyzing a Bundle
59
+
60
+ ```bash
61
+ tar -xzf support-bundle-<timestamp>.tar.gz
62
+ python3 scripts/bundle_triage.py support-bundle-<timestamp>
63
+
64
+ # Narrow it down
65
+ python3 scripts/bundle_triage.py <bundle> --namespace openhands --section pods --section events
66
+ ```
67
+
68
+ ## For Contributors
69
+
70
+ When new failure modes are discovered in the field, update `references/diagnostics.md` with:
71
+ 1. New symptoms and error patterns
72
+ 2. Diagnostic commands to run
73
+ 3. Resolution steps that worked
74
+ 4. Log excerpts showing the error
75
+
76
+ If a failure mode is diagnosable from a support bundle, add the offline equivalent to
77
+ `references/support-bundle-analysis.md` as well.
78
+
79
+ This skill should grow with each support issue resolved.
@@ -0,0 +1,339 @@
1
+ ---
2
+ name: openhands-enterprise-troubleshooting
3
+ description: This skill should be used when a user reports an issue with OpenHands Enterprise (OHE) on a self-hosted (Replicated VM-based) installation. Use for diagnosing sandbox startup failures, auth issues, certificate errors, LLM connectivity problems, Keycloak login issues, Replicated Admin Console access, upgrade failures, or resource exhaustion. Helps triage symptoms, run diagnostic commands, guide through recovery steps, generate and analyze Replicated support bundles offline, and produce escalation handoffs.
4
+ triggers:
5
+ - openhands enterprise
6
+ - OHE troubleshooting
7
+ - openhands not working
8
+ - sandbox failed
9
+ - replicated admin console
10
+ - keycloak login
11
+ - certificate error
12
+ - LLM connectivity
13
+ - upgrade failed
14
+ - support bundle
15
+ - openhands install
16
+ ---
17
+
18
+ # OpenHands Enterprise Troubleshooting
19
+
20
+ This skill helps diagnose and resolve common issues on OpenHands Enterprise (OHE) self-hosted installations using Replicated. It covers triage, guided recovery, support bundle generation, and escalation handoffs.
21
+
22
+ ## Diagnostic Workflow
23
+
24
+ When a user reports an OHE issue:
25
+
26
+ 1. **Collect symptoms** - Ask user to describe what they see, error messages, when it started
27
+ 2. **Identify failure mode** - Match symptoms to one of the common issues below
28
+ 3. **Run targeted diagnostics** - Use commands in `references/diagnostics.md`
29
+ 4. **Guide recovery** - Follow resolution steps for the identified issue, one at a time
30
+ 5. **Verify fix** - Confirm the original symptom is gone, not just that the last command succeeded
31
+ 6. **Generate handoff** - If unresolved, produce a clear summary for the OpenHands team
32
+
33
+ Take recovery one step at a time. Before each step, state what it will change and what you expect to
34
+ see afterwards; after it, run the check that confirms it before moving on. If the check fails or
35
+ shows something unexpected, stop and re-diagnose — a step applied on top of a failed one buries the
36
+ evidence, and several applied blind can leave the install worse than the fault you started with.
37
+ Destructive steps (restarts, rollbacks, config changes) need the user's agreement first, and are
38
+ worth recording as you go so the handoff can say exactly what was changed.
39
+
40
+ Work from whatever the user has. A described symptom starts at step 1; a support bundle goes to
41
+ [Analyzing the Support Bundle](#analyzing-the-support-bundle). If they paste raw log output, the
42
+ triage method in
43
+ [`references/support-bundle-analysis.md`](references/support-bundle-analysis.md#triaging-a-log-file)
44
+ applies to pasted text as well as to files, and notes what a hand-picked excerpt can hide.
45
+
46
+ ## Common Failure Modes
47
+
48
+ ### 1. Sandbox Fails to Start / Timeout
49
+
50
+ **Symptoms:**
51
+ - Conversation hangs then times out
52
+ - "Sandbox failed to start" error
53
+ - A timeout in the logs. Read the actual value rather than assuming one: the timeouts in
54
+ `runtime-api` are configurable and differ between the Kubernetes client and the app, so quoting a
55
+ fixed number back to a customer is how you end up chasing the wrong one.
56
+
57
+ **Diagnosis:** Check sandbox service status, the `sysbox-runc` RuntimeClass and its containerd
58
+ runtime, resource availability
59
+
60
+ **Reference:** See `references/diagnostics.md` - Section "Sandbox Startup"
61
+
62
+ ### 2. Git Provider Auth Broken
63
+
64
+ **Symptoms:**
65
+ - "Authentication failed" for the configured provider
66
+ - Can't clone or push repos
67
+ - The provider shows as disconnected
68
+
69
+ **Diagnosis:** Check the provider's secret in Kubernetes and that the provider is enabled. GitHub,
70
+ GitLab, Bitbucket Data Center, and Azure DevOps are each configured separately — confirm which one
71
+ the user is actually on before diagnosing
72
+
73
+ **Reference:** See `references/diagnostics.md` - Section "Git Provider Auth"
74
+
75
+ ### 3. Certificate Errors
76
+
77
+ **Symptoms:**
78
+ - "certificate expired" or "self-signed certificate" errors
79
+ - TLS handshake failures
80
+ - Browser shows insecure connection warning
81
+
82
+ **Diagnosis:** Check cert expiry, certificate chain, ingress configuration
83
+
84
+ **Reference:** See `references/diagnostics.md` - Section "Certificate Issues"
85
+
86
+ ### 4. LLM Connectivity Failures
87
+
88
+ **Symptoms:**
89
+ - "LLM endpoint unreachable"
90
+ - "Authentication failed" for LLM API
91
+ - Conversations fail to start
92
+
93
+ **Diagnosis:** Check LLM endpoint URL, API key secrets, network policies
94
+
95
+ **Reference:** See `references/diagnostics.md` - Section "LLM Connectivity"
96
+
97
+ ### 5. Keycloak Login Issues
98
+
99
+ **Symptoms:**
100
+ - Can't access admin console
101
+ - Login loop or "invalid credentials"
102
+ - Keycloak pod showing errors
103
+
104
+ **Diagnosis:** Check Keycloak pod status, database connectivity, realm configuration
105
+
106
+ **Reference:** See `references/diagnostics.md` - Section "Keycloak"
107
+
108
+ ### 6. Replicated Admin Console Unreachable
109
+
110
+ **Symptoms:**
111
+ - Can't access admin console URL
112
+ - Connection refused or timeout
113
+ - Browser shows "site cannot be reached"
114
+
115
+ **Diagnosis:** Check Replicated operator pod, ingress, service endpoints
116
+
117
+ **Reference:** See `references/diagnostics.md` - Section "Replicated Admin Console"
118
+
119
+ ### 7. Upgrade Stuck or Failed
120
+
121
+ **Symptoms:**
122
+ - Replicated shows upgrade as "failed"
123
+ - Pods in crash loop after upgrade
124
+ - Migration jobs failing
125
+
126
+ **Diagnosis:** Check failed job logs, resource availability, pre-flight failures
127
+
128
+ **Reference:** See `references/diagnostics.md` - Section "Upgrade Issues"
129
+
130
+ ### 8. OOM / Resource Exhaustion
131
+
132
+ **Symptoms:**
133
+ - Pods being OOMKilled
134
+ - "Too many open files" errors
135
+ - Services becoming unresponsive
136
+
137
+ **Diagnosis:** Check node resources (memory, disk, file descriptors)
138
+
139
+ **Reference:** See `references/diagnostics.md` - Section "Resource Exhaustion"
140
+
141
+ ## Diagnostic Commands Quick Reference
142
+
143
+ Access the VM and run these common commands.
144
+
145
+ **An empty result never means "healthy".** `kubectl get pods -l <selector>` prints `No resources
146
+ found` and exits 0 both when a component is down and when the selector is wrong, so the two are
147
+ indistinguishable. When you need to know whether something is running, ask its Deployment or
148
+ StatefulSet for a READY count instead — that object exists either way, and `0/1` means down while a
149
+ `NotFound` error means you had the name wrong.
150
+
151
+ ```bash
152
+ # Is it up? READY answers this; an empty pod list does not.
153
+ kubectl get deploy,statefulset -n openhands
154
+
155
+ # Check overall pod status
156
+ kubectl get pods -n openhands
157
+
158
+ # View pod logs (replace POD_NAME)
159
+ kubectl logs -n openhands POD_NAME
160
+ kubectl logs -n openhands POD_NAME --previous
161
+
162
+ # Describe a pod for events
163
+ kubectl describe pod -n openhands POD_NAME
164
+
165
+ # Check resource usage
166
+ kubectl top nodes
167
+ kubectl top pods -n openhands
168
+
169
+ # Check certificate expiry
170
+ echo | openssl s_client -connect HOST:443 2>/dev/null | openssl x509 -noout -dates
171
+
172
+ # Check the Replicated components. On Embedded Cluster these are the Admin
173
+ # Console in `kotsadm`, the operator in `embedded-cluster`, and the Replicated
174
+ # SDK in `openhands` under app.kubernetes.io/name=replicated. A `replicated`
175
+ # namespace belongs to the older kURL topology and is absent here.
176
+ kubectl get pods -n kotsadm
177
+ kubectl get pods -n embedded-cluster
178
+ kubectl get pods -n openhands -l app.kubernetes.io/name=replicated
179
+ ```
180
+
181
+ ## Support Bundle Generation
182
+
183
+ When the issue requires deeper investigation — or before escalating — generate a support bundle. It
184
+ captures both host- and cluster-level state in one archive.
185
+
186
+ ### Generating the Support Bundle
187
+
188
+ SSH to the VM, then from the directory containing the installer binary:
189
+
190
+ ```bash
191
+ sudo ./openhands support-bundle
192
+ ```
193
+
194
+ This uses the default Embedded Cluster spec to collect cluster- *and* host-level information, and
195
+ automatically includes the OpenHands application-specific collectors. Run it on a **controller
196
+ node** — on a non-controller node it cannot capture cluster-wide information.
197
+
198
+ For Embedded Cluster versions earlier than 1.17.0, use the support-bundle plugin from within the
199
+ cluster shell instead:
200
+
201
+ ```bash
202
+ sudo ./openhands shell
203
+ kubectl support-bundle --load-cluster-specs /var/lib/embedded-cluster/support/host-support-bundle.yaml
204
+ ```
205
+
206
+ The bundle is written to the working directory as `support-bundle-<UTC timestamp>.tar.gz`. Share it
207
+ with the OpenHands team, or analyze it directly with the steps below.
208
+
209
+ Support bundles carry potentially sensitive data. Replicated's redactor masks common secret patterns
210
+ as `***HIDDEN***`, but it is not a guarantee — hostnames, user and installation identifiers, and
211
+ config values routinely survive it. Treat a bundle as confidential, send it only through the channel
212
+ the OpenHands team gives you, and avoid pasting raw excerpts into public issues or chats.
213
+
214
+ ### Analyzing the Support Bundle
215
+
216
+ **Full guide: [`references/support-bundle-analysis.md`](references/support-bundle-analysis.md).**
217
+ Read it before drawing conclusions — the bundle's layout is not what you would guess from `kubectl`,
218
+ and several of its gaps produce convincing false negatives.
219
+
220
+ Fast path — the bundled triage script reconstructs the standard first pass (cluster meta, analyzer
221
+ results, pod table, OOM and restart scan, `top` equivalent, allocatable headroom, events) in one
222
+ command. It reports; the ranking and the diagnosis are yours to make:
223
+
224
+ ```bash
225
+ tar -xzf support-bundle-2026-07-28T06_54_18.tar.gz
226
+ python3 scripts/bundle_triage.py support-bundle-2026-07-28T06_54_18
227
+ ```
228
+
229
+ You are reading this bundle because something is broken, so treat a clean run as "not here" rather
230
+ than "nothing wrong" — the script sees pod objects, analyzer verdicts, node conditions and resource
231
+ totals, and reads no application logs at all. `references/support-bundle-analysis.md` has a section
232
+ on where to look next when the objects come back clean.
233
+
234
+ Then the four things that most often answer the question outright:
235
+
236
+ | Question | Where to look |
237
+ |---|---|
238
+ | What did the collector already conclude? | `analysis.json` — pre-computed verdicts, highest-value file in the bundle |
239
+ | What is each pod actually doing? | `cluster-resources/pods/<namespace>.json` |
240
+ | What did a container log? | `cluster-resources/pods/logs/<ns>/<pod>/<container>.log` |
241
+ | What is the install running? | `kots/admin_console/app-info.json` — version, channel, sequence |
242
+
243
+ Four traps worth knowing before you start:
244
+
245
+ - **Never use file mtimes for timing.** They record when you extracted the archive. Take the capture
246
+ time from the bundle directory name, which is UTC.
247
+ - **Log filenames are container names, not pod names.** Init-container failures (`migrate-db`,
248
+ `wait-for-db`) are invisible to `kubectl logs <pod>` and are the easiest real failure to miss.
249
+ - **`***HIDDEN***` means "redacted", not "unset".** The redactor over-redacts, including non-secrets.
250
+ - **Check a log's format before filtering it.** Most bundle logs are plain text, not JSON, and `jq`
251
+ aborts on the first non-JSON line — so a severity filter can print nothing on a file full of
252
+ errors. Prefix with `grep '^{'`, and read the non-JSON lines separately.
253
+
254
+ Once triage points at a failure mode, use `references/diagnostics.md` for that mode's specific
255
+ commands and error patterns.
256
+
257
+ ### Summarizing the Bundle: Most Likely Root Cause
258
+
259
+ The script reports; deciding which of its observations explains the user's symptom is your job. Work
260
+ through its output in this order, because it is roughly the order in which a finding is likely to be
261
+ the actual cause rather than a side effect.
262
+
263
+ **1. Start from the symptom and the clock, not from the output.** Get the capture time from the
264
+ bundle directory name (UTC) and establish when the user says it broke. A finding that predates the
265
+ symptom by weeks is background; one that starts within the window is a candidate. Ages in the pod
266
+ table are the cheapest way to place an event in time.
267
+
268
+ **2. Read `analysis.json` first — but not literally.** The collector's own verdicts are the
269
+ highest-value content in the bundle. Two cautions when reading them through the script: everything
270
+ non-passing prints under a `FAIL` heading, including `warn`-severity entries that may be advisory,
271
+ so check the severity in `analysis.json` before calling one a failure; and per-object analyzers are
272
+ collapsed into families with one example each, so `[x12]` means twelve objects affected and the
273
+ example shown is arbitrary. Open the file directly before quoting an analyzer verdict to a customer.
274
+
275
+ **3. Rank what remains by how directly it explains the symptom.** In descending order of
276
+ usefulness — a container in `CrashLoopBackOff` or actively OOM-killed right now; a pod that never
277
+ started (`Pending`, `CreateContainerConfigError`, an init container that never completed); a pod
278
+ that is `Running` but not `Ready`, which fails a health check and takes traffic out of rotation; a
279
+ node condition that is genuinely bad; and resource pressure, which is usually a consequence rather
280
+ than a cause. A recovered termination — visible only as `lastState` with an older age — explains a
281
+ past blip, not a live outage; do not lead with one.
282
+
283
+ **4. Prefer the cause nearest the symptom.** A failed `migrate-db` init container and an app pod
284
+ stuck `Pending` are one finding, not two, and the init container is the one to report. When several
285
+ findings share a timestamp, look for the common dependency rather than listing all of them.
286
+
287
+ **5. Say what you ruled out.** The script reads pod objects, analyzer verdicts, node conditions and
288
+ resource totals — and no application logs. If nothing in the objects explains the symptom, that is
289
+ itself a result: it puts the cause in the application logs, in the network path, or outside the
290
+ cluster. Name which, rather than reporting that the bundle looked healthy.
291
+
292
+ State the conclusion with its evidence and its confidence — the object or analyzer it rests on, and
293
+ whether it explains the reported symptom or merely coincides with it. A ranked shortlist of two or
294
+ three candidates is more useful than a single confident guess, and it drops straight into the
295
+ **Likely Root Cause** field of the handoff template below.
296
+
297
+ ## Escalation Handoff Template
298
+
299
+ When an issue cannot be resolved, produce this summary:
300
+
301
+ ```
302
+ ## Issue Summary
303
+ **Problem:** [One-line description]
304
+ **Duration:** [When it started]
305
+ **Impact:** [Who is affected]
306
+
307
+ ## Symptoms Observed
308
+ - [Symptom 1]
309
+ - [Symptom 2]
310
+
311
+ ## Diagnostic Steps Taken
312
+ 1. [Step 1]
313
+ 2. [Step 2]
314
+
315
+ ## Logs / Evidence
316
+ ```
317
+ [Relevant log excerpts]
318
+ ```
319
+
320
+ ## Resolution Attempts
321
+ - [Attempt 1] - [Result]
322
+ - [Attempt 2] - [Result]
323
+
324
+ ## Likely Root Cause
325
+ [Analysis]
326
+ ```
327
+
328
+ ## Additional Resources
329
+
330
+ - **Diagnostic Reference:** [`references/diagnostics.md`](references/diagnostics.md) — detailed commands and log interpretation for each failure mode
331
+ - **Support Bundle Analysis:** [`references/support-bundle-analysis.md`](references/support-bundle-analysis.md) — reading a bundle offline: file map, interpretation traps, known gaps
332
+ - **Triage Script:** `scripts/bundle_triage.py` — offline first-pass triage, standard library only
333
+ - **Replicated Docs:** [Generating support bundles for Embedded Cluster](https://docs.replicated.com/vendor/support-bundle-embedded)
334
+
335
+ ## Maintenance
336
+
337
+ As new failure modes are discovered in the field, add them to this skill. Update
338
+ `references/diagnostics.md` with new patterns and resolution steps, and add the offline equivalent to
339
+ `references/support-bundle-analysis.md` when the failure is diagnosable from a bundle.