Skip to content
Merged
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 @@ -8,7 +8,7 @@
"name": "indigo",
"source": "./",
"description": "Indigo home automation development toolkit \u2014 plugin development, API integration, and control page building",
"version": "2.1.0",
"version": "2.1.1",
"repository": "https://github.com/simons-plugins/indigo-claude-plugin",
"license": "MIT",
"keywords": [
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "indigo",
"version": "2.1.0",
"version": "2.1.1",
"description": "Indigo home automation development toolkit \u2014 plugin development, API integration, and control page building",
"repository": "https://github.com/simons-plugins/indigo-claude-plugin"
}
7 changes: 4 additions & 3 deletions commands/debug-sqllogger.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ SQL Logger Error: One or more failures updating device history; see the debug lo

repeating every ~60s — no device ID, no traceback.

This command temporarily patches SQL Logger's two swallowed
This command temporarily patches SQL Logger's three swallowed
`logger.debug` call sites to `error` level (tagged `[DEBUG-PATCH]`),
surfaces the real exception, names the failing device via MCP, and
then asks which of three fixes to apply:
Expand All @@ -46,8 +46,9 @@ At-a-glance phases:
1. **CONFIRM + DISCOVER** — verify errors are actively repeating
(`query_event_log`), locate SQL Logger plugin + log via
`mcp__indigo__list_plugins`
2. **PATCH** — promote the two `logger.debug(..., exc_info=True)`
calls in `_update_device_history` and `_create_table_for_dev` to
2. **PATCH** — promote the three swallowed `logger.debug` calls
(update, schema-update, and create paths in
`_update_device_history` / `_create_table_for_dev`) to
`logger.error` tagged `[DEBUG-PATCH]`, restart plugin
3. **EXTRACT** — read plugin log, pull `device_history_<id>` and
exception class, resolve device via `get_device_by_id`
Expand Down
58 changes: 48 additions & 10 deletions skills/debug-sqllogger/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Derive the two working paths:

### Phase 2 — PATCH

Locate the two call sites in `plugin.py` with `Grep`. Line numbers
Locate the three call sites in `plugin.py` with `Grep`. Line numbers
drift across SQL Logger versions — always locate by the message
fragment, not by number:

Expand All @@ -100,12 +100,19 @@ fragment, not by number:
it's at ~line 529 and already carries `exc_info=True`.
- Create path — grep `Failed to create table .* for device history`.
Currently at ~line 476 and does **not** carry `exc_info=True`.
- Schema-update path — grep `Failed to update schema`. Present in
SQL Logger 2025.2.0 at ~line 679, inside `_update_device_history`'s
`(ColumnsMissing, ColumnsChanged)` retry handler; carries
`exc_info=True`. This path fires when the retried `insert_row`
after a schema refresh fails (e.g. INT4 overflow) — in a live
2026-07 debugging pass it was the **only** site firing, so skipping
it makes the whole patch cycle come up empty.

Promote each to `logger.error`, prefix the message with
`[DEBUG-PATCH] `, and ensure `exc_info=True` is present on both (add
it to the create call if missing — without it the traceback never
reaches the log, which defeats the point of the patch). Use `Edit`,
not `Write`.
`[DEBUG-PATCH] `, and ensure `exc_info=True` is present on all three
(add it to the create call if missing — without it the traceback
never reaches the log, which defeats the point of the patch). Use
`Edit`, not `Write`.

Update path before/after:

Expand All @@ -128,13 +135,31 @@ self.logger.debug(f"Failed to create table {table_name} for device history: {err
self.logger.error(f"[DEBUG-PATCH] Failed to create table {table_name} for device history: {err}", exc_info=True)
```

Schema-update path before/after:

```python
# before (~line 679, with exc_info=True already)
self.logger.debug(f"Failed to update schema for {dev_table_name}: {schema_err}", exc_info=True)

# after
self.logger.error(f"[DEBUG-PATCH] Failed to update schema for {dev_table_name}: {schema_err}", exc_info=True)
```

If a `grep` finds the fragment but the surrounding arguments differ
from the above (SQL Logger is maintained; call signatures drift),
adapt — the invariant is *promote to error, add the DEBUG-PATCH tag,
ensure exc_info=True*. Every patched line MUST contain the literal
string `[DEBUG-PATCH]` — the revert step relies on grep returning
zero hits.

Completeness check before restarting: grep
`kErrorKeyDeviceHistoryError` and confirm every `logger.debug` that
sits next to one of those `_log_error_unobtrusive` calls got
promoted. SQL Logger is maintained and new swallowed sites appear
between versions (the schema-update path above shipped after this
skill was first written). A device-history error path that still
logs at debug level will produce the Phase 3 symptom below.

Restart the plugin:

```
Expand All @@ -147,7 +172,19 @@ Ask the user to wait one error cycle (~60s) and signal when ready.
Do not sleep blindly — the cadence varies with server load.

Read the last 200 lines of the plugin log and search for
`[DEBUG-PATCH]`. The first matching line names the failing table:
`[DEBUG-PATCH]`. If the generic error keeps repeating but **no**
`[DEBUG-PATCH]` line appears after a full cycle, first rule out the
mundane causes: confirm the plugin actually restarted after the
patch deployed (grep the plugin log for the restart banner, or check
the event log for "Started plugin") and that you're reading the
right log file (`ls -lt` the log directory; rotation can leave you
tailing yesterday's file). Only once the patched code is confirmed
Comment on lines +175 to +181

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use Plugin for Indigo plugin references.

These lines refer to the Indigo Plugin as lowercase “plugin” (the plugin, plugin log). Capitalize it as Plugin to distinguish Indigo Plugins from Claude Code plugin components.

As per coding guidelines: “Use 'Plugin' (capitalized) when referring to Indigo plugins.”

🧰 Tools
🪛 SkillSpector (2.3.11)

[warning] 387: [RA2] Session Persistence: Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Remediation: Remove any persistence mechanisms (cron jobs, startup scripts, state files). Skills should not maintain state across sessions without explicit user consent.

(Rogue Agent (RA2))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/debug-sqllogger/SKILL.md` around lines 175 - 181, Update the prose in
the troubleshooting section around the restart and log-file checks to capitalize
Indigo plugin references as “Plugin,” including “the Plugin” and “Plugin log,”
while leaving unrelated uses of lowercase “plugin” unchanged.

Source: Coding guidelines

live does a missing marker mean a swallowed call site was missed —
then go back to the Phase 2 completeness check and grep
`kErrorKeyDeviceHistoryError` for an unpromoted `logger.debug`
neighbour (this is exactly how the schema-update path was found).
Comment thread
coderabbitai[bot] marked this conversation as resolved.

The first matching line names the failing table:

```
[DEBUG-PATCH] Failed to update table device_history_1234567 for device 1234567: integer out of range
Expand Down Expand Up @@ -265,12 +302,13 @@ skill's own extraction output.

### Phase 6 — REVERT

Undo every patch. Up to three regions may need reverting:
Undo every patch. Up to four regions may need reverting:

1. `_update_device_history` logger call — restore to
`self.logger.debug(...)`, remove `[DEBUG-PATCH]` prefix
2. `_create_table_for_dev` logger call — same
3. `startup()` one-shot DROP block (option c only) — delete the whole
2. `_update_device_history` schema-update logger call — same
3. `_create_table_for_dev` logger call — same
4. `startup()` one-shot DROP block (option c only) — delete the whole
Comment on lines +305 to +311

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Update the abort-path safety rule to revert all three logger call sites.

Phase 6 now correctly lists the schema-update region, but the Safety Rules below still says to “restore both logger.debug call sites.” Following that instruction can leave the schema-update call patched at error level after an abort, causing persistent error-log spam.

🧰 Tools
🪛 SkillSpector (2.3.11)

[warning] 381: [RA2] Session Persistence: Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Remediation: Remove any persistence mechanisms (cron jobs, startup scripts, state files). Skills should not maintain state across sessions without explicit user consent.

(Rogue Agent (RA2))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/debug-sqllogger/SKILL.md` around lines 299 - 305, Update the
abort-path safety rule in SKILL.md to require reverting all three logger call
sites: both _update_device_history calls and the _create_table_for_dev call,
restoring each to self.logger.debug(...) without the [DEBUG-PATCH] prefix. Keep
the existing instruction to remove the startup() one-shot DROP block for option
c.

try/except block

Verify cleanup with Grep:
Expand Down Expand Up @@ -326,7 +364,7 @@ happening, what to do next.
any point after Phase 2 — user cancels, log-read finds nothing,
extraction fails, any error, interrupt, or user "none" in Phase 4 —
the first action before exiting is a full Phase 6 revert
(restore both `logger.debug` call sites, remove any `startup()`
(restore all three `logger.debug` call sites, remove any `startup()`
DROP block, grep-verify zero `[DEBUG-PATCH]` hits, restart plugin).
A patched `logger.error` left behind will spam the event log every
~60s at error level until noticed.
Expand Down
Loading