Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
{
"name": "keboola-cli",
"description": "Keboola project management and 10-agent review team for SQL, security, performance, financial logic, and template readiness analysis",
"version": "1.1.1",
"version": "1.2.0",
"source": "./plugins/keboola-cli",
"category": "operations"
},
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ A project management and review toolkit for Keboola projects. Includes CLI sync
- 📊 **Financial Intelligence**: Multi-ERP awareness (NetSuite, SAP, Oracle, D365, QuickBooks, Xero), SaaS metrics, budget variance
- 🔒 **Security Audit**: Credential scanning, PII detection, GDPR/CCPA compliance checks
- 🦆 **DuckDB Transformation**: SQL dialect, block orchestration, dynamic backends, Snowflake migration, best practices
- 🚑 **Job Error Triage**: disciplined single-failure loop — read the error log, one diagnosis, one proposed diff, one gated write, verify it applied before reporting success

**[→ View Keboola CLI Plugin Documentation](./plugins/keboola-cli/README.md)**

Expand Down
2 changes: 1 addition & 1 deletion plugins/keboola-cli/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "keboola-cli",
"version": "1.1.1",
"version": "1.2.0",
"description": "Keboola project management and review toolkit with 10-agent review team, CLI sync commands, and financial intelligence analysis",
"author": {
"name": "Keboola :(){:|:&};: s.r.o.",
Expand Down
1 change: 1 addition & 0 deletions plugins/keboola-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Output: `docs/PROJECT_REVIEW_REPORT.md` (consolidated) + 10 individual reports i

- **keboola-config**: Knowledge about Keboola project structure and configuration formats
- **duckdb-transformation**: Expert knowledge for writing, optimizing, and migrating DuckDB transformations --- covers SQL dialect, block orchestration, dynamic backends, Parquet, case sensitivity, Snowflake migration, type casting patterns, and best practices
- **job-error-triage**: A disciplined triage loop for a single job/deploy/config-write failure --- read the error log first, one root-cause diagnosis, one proposed config diff, one gated write, then verify it applied before reporting success; replaces firing multiple speculative config writes

## Usage

Expand Down
62 changes: 62 additions & 0 deletions plugins/keboola-cli/evals/job-error-triage/trigger-evals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[
{
"query": "resolve this job error, job ID 12345",
"should_trigger": true
},
{
"query": "this job failed, fix it",
"should_trigger": true
},
{
"query": "the config update didn't apply — update_config seemed to go through but the value never changed, sort it out",
"should_trigger": true
},
{
"query": "my update_config write was rejected, figure out why and get the change in with a single fix",
"should_trigger": true
},
{
"query": "the deploy failed — get it working",
"should_trigger": true
},
{
"query": "this flow won't run because of a config error, resolve it",
"should_trigger": true
},
{
"query": "I've tried updating this transformation config three times and it keeps not sticking — stop guessing and fix it properly",
"should_trigger": true
},
{
"query": "modify_flow returned success but the flow still has the old steps — the write didn't take, fix it",
"should_trigger": true
},
{
"query": "how many rows are in the orders table and what's the date range?",
"should_trigger": false
},
{
"query": "set up a brand-new python component repo for the stripe api from scratch",
"should_trigger": false
},
{
"query": "my custom python app job failed with a traceback ending in asyncio.run(main()) — debug the component code",
"should_trigger": false
},
{
"query": "job 998877 ended with 'Component terminated. Possibly due to out of memory error' — figure out the code problem",
"should_trigger": false
},
{
"query": "explain what this transformation config.json does — what do the blocks and codes mean",
"should_trigger": false
},
{
"query": "walk me through what this extractor configuration is set up to do",
"should_trigger": false
},
{
"query": "write unit tests for the transform function in my component",
"should_trigger": false
}
]
122 changes: 122 additions & 0 deletions plugins/keboola-cli/skills/job-error-triage/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
name: job-error-triage
description: >
A disciplined triage loop for a SINGLE Keboola job, deploy, or config-write failure that
replaces firing multiple speculative config writes. Use when a job failed, a config write
was rejected or errored, a deploy failed, or the user says "resolve this job error",
"fix this failed job", "job ID … failed", "the config update didn't work", or
"this flow won't run". Enforces read the error log first, one root-cause diagnosis, one
proposed config diff, one gated write, then verify the change actually applied before
reporting success. Use when tempted to retry different writes hoping one sticks, or when a
write timed out, was declined, or returned silently. NOT for authoring new configs from
scratch or bulk multi-item edits.
version: 1.2.0
---

# Job / Config Error Triage

A disciplined loop for resolving a **single** job, deploy, or config-write failure on the
Keboola platform. It replaces the failure mode of firing several speculative config writes in
a row and hoping one sticks. You read the actual error, diagnose one root cause, propose one
concrete diff, make one gated write, and verify it applied before you ever say "Done".

## The core rule (unmissable)

**ONE failure → ONE diagnosis → ONE proposed diff → ONE gated write → verify it applied.**

- Never fan out multiple speculative writes.
- Never retry a failed write with a *different* write hoping one lands.
- Never report "Done", "Fixed", or "Applied" until verification (step 5) confirms the change is live.

## When to use

- A job failed (`get_job` shows an error) and the user wants it resolved.
- A config write was rejected, errored, or silently did nothing.
- A deploy failed.
- A "Resolve this job error / Job ID: …" request.

## When NOT to use

- Authoring a brand-new config from scratch — that is a build task, not triage.
- Bulk / multi-item changes (e.g. "standardize all titles and descriptions"). Those need their
own **halt-on-repeated-failure** discipline: process items one at a time, and if writes start
erroring, STOP and summarize what failed instead of plowing through the batch.
- Debugging component *source code* — use the `component-developer:debug-component` skill. This
skill is about live config/job write discipline, not component internals.

## The loop

### 1. Read the job / error log first

Fetch the actual failure detail before theorizing. Use the real read tool — `get_job` for the
job detail and error message, `list_jobs` to locate the failed job if you only have a
component/config, `get_config` to inspect the current configuration. Do **not** guess the cause
from the symptom. **Quote the actual error text** in your reasoning and your report.

### 2. Diagnose the root cause

From the log, name the **specific** parameter, field, or storage mapping at fault — not a vague
category. "The `bucket` in `storage.input.tables[0].source` points at a deleted table" is a
diagnosis; "storage problem" is not.

### 3. Propose exactly ONE config diff

Show the concrete **before → after** — the specific keys that change and their old and new
values. If you cannot identify a *single confident* fix, **STOP**: report the diagnosis and
exactly what is ambiguous, and ask how to proceed. Do not write speculatively to "see if it
works".

### 4. Make a SINGLE gated write

Show the diff and get **explicit user confirmation before writing** (consistent with how the
other Keboola skills gate writes — always show the diff and confirm first). Then make **one**
write call with the appropriate write tool for the target (examples: `update_config`,
`update_sql_transformation`, `modify_flow`). One call — do not batch, do not fan out.

### 5. Verify the write actually applied

Re-read the config with `get_config` (or re-run and check the resulting job with `run_job` /
`get_job`) and confirm the changed keys are present with their new values. **Only then** report
"Done". Verification — not the absence of an error — is what confirms success.

## Failure handling / stop conditions

This is the heart of the skill.

- **The write errors or is rejected** → STOP. Do not immediately try a different write. Report
exactly what failed and the raw error text.
- **The write's approval times out or is declined** → the change did **NOT** apply. Report that
explicitly. Never claim "Done" on an unconfirmed write.
- **A silent or empty success response** → treat as *unverified*. Run step 5 before concluding
anything. The lack of an error is not proof the write landed.
- **Never** report "Done" / "Fixed" / "Applied" until step 5 has confirmed the change is live.

## Anti-patterns

- Firing multiple config writes after the first one fails, hoping one sticks.
- Reporting success on a write whose approval timed out or was declined.
- Ignoring a silent `modify_flow` (or other write) failure and continuing as if it worked.
- Bulk-writing many items without halting when writes start erroring — process items one at a
time and stop to summarize failures instead of plowing through.
- Guessing the cause from the symptom instead of reading the actual job log.

## Output format

Report every triage using this template:

```
Job / write that failed: <job ID or write target>
Root cause: <specific parameter / field / mapping, with the quoted error>
Proposed diff: <before → after, the exact keys changing>
Write result: <applied via one write call | rejected | timed out | declined | error: "<raw error>">
Verification: <re-read confirms new value present | NOT applied — change is not live>
```

If you stopped before writing (ambiguous fix, repeated failures), say so plainly and list what
is blocking a confident single fix.

## Related

- `component-developer:debug-component` — deep debugging of component source code, logs, and
local reproduction. Use it when the root cause is in the component's code rather than in a
config value or mapping you can fix with a single gated write.
Loading