Skip to content
Back to skills

2976 2026 02 20 Duckdb Lock Scope Flag 18db1838

ASecurity

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Fix the DuckDB write-lock conflict, add `--scope` flag to `sentiment-score.py` for lesson output targeting, create a `.gitignore` for local-scope output, and add a BACKLOG todo for MCP consolidation analysis. **Architecture:** Three independent changes to the `agentskill-kaizen` plugin: (1) one-line `plugin.json` patch to make the motherduck MCP server read-only, freeing the wr...

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
toolspythongobashsqlgit

Works with

  • cli
  • mcp

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2976-2026-02-20-duckdb-lock-scope-flag_18db1838 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2976 2026 02 20 Duckdb Lock Scope Flag 18db1838?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2976 2026 02 20 Duckdb Lock Scope Flag 18db1838
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2976-2026-02-20-duckdb-lock-scope-flag-18db1838/badge)](https://www.skillsdirectory.com/skills/tools-only-2976-2026-02-20-duckdb-lock-scope-flag-18db1838)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# DuckDB Lock Fix, --scope Flag, .gitignore, and Consolidation Todo

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

**Goal:** Fix the DuckDB write-lock conflict, add `--scope` flag to `sentiment-score.py` for lesson output targeting, create a `.gitignore` for local-scope output, and add a BACKLOG todo for MCP consolidation analysis.

**Architecture:** Three independent changes to the `agentskill-kaizen` plugin: (1) one-line `plugin.json` patch to make the motherduck MCP server read-only, freeing the write lock for the script; (2) a new `--scope` Typer option that routes lesson output to one of three destinations; (3) a `.gitignore` in the plugin root and a BACKLOG todo entry. No new dependencies. No schema changes.

**Tech Stack:** Python 3.11+, Typer, DuckDB, uv/PEP 723, JSON (plugin.json)

---

## Task 1: Fix DuckDB lock — make MCP server read-only

**Files:**
- Modify: `plugins/agentskill-kaizen/.claude-plugin/plugin.json` line 32

**Context:**
`mcp-server-motherduck` is launched with `--read-write`, which acquires DuckDB's exclusive write lock. When `sentiment-score.py` runs while the MCP server is active, it fails with `IOException: Could not set lock`. DuckDB allows multiple readers but only one writer. Making the MCP server read-only releases the write lock so the script can acquire it.

**Step 1: Apply the one-line patch**

In `plugins/agentskill-kaizen/.claude-plugin/plugin.json`, change:

```json
"args": ["mcp-server-motherduck", "--db-path", "${HOME}/.claude/kaizen/kaizen.duckdb", "--read-write"]
```

to:

```json
"args": ["mcp-server-motherduck", "--db-path", "${HOME}/.claude/kaizen/kaizen.duckdb", "--read-only"]
```

**Step 2: Verify the JSON is still valid**

```bash
python3 -c "import json, sys; json.load(open('plugins/agentskill-kaizen/.claude-plugin/plugin.json')); print('OK')"
```

Expected: `OK`

**Step 3: Commit**

```bash
git add plugins/agentskill-kaizen/.claude-plugin/plugin.json
```

Then `/commit-staged`

---

## Task 2: Add `--scope` flag to `sentiment-score.py`

**Files:**
- Modify: `plugins/agentskill-kaizen/scripts/sentiment-score.py`

**Context:**
The `--scope` flag controls where lesson output (future feature) is written. Three destinations:

| Scope | Destination |
|-------|-------------|
| `user` | `~/.claude/kaizen/lessons/` |
| `project` | `{cwd}/.claude/kaizen/lessons.md` (git-tracked) |
| `local` | `{cwd}/.claude/kaizen/lessons.local.md` (gitignored) |

For now, the flag is plumbing only — it validates, resolves, and prints the resolved destination path to stderr. The actual lesson extraction logic is a separate future task. Adding the flag now means callers can pass `--scope` today and it will be wired up when lesson extraction lands.

**Step 1: Add `ScopeTarget` enum after the `_DEFAULT_DB` constant (around line 392)**

```python
import enum  # add to stdlib imports at top of file

class ScopeTarget(str, enum.Enum):
    """Output scope for lesson files."""
    user = "user"
    project = "project"
    local = "local"
```

Note: `str, enum.Enum` is required for Typer to accept enum values as CLI arguments.

**Step 2: Add `_resolve_scope_path` helper after `ScopeTarget`**

```python
def _resolve_scope_path(scope: ScopeTarget) -> Path:
    """Return the resolved output path for *scope*.

    Args:
        scope: The target scope for lesson output.

    Returns:
        Absolute path to the lesson file or directory.
    """
    if scope == ScopeTarget.user:
        return Path("~/.claude/kaizen/lessons/").expanduser()
    if scope == ScopeTarget.project:
        return Path.cwd() / ".claude" / "kaizen" / "lessons.md"
    # local
    return Path.cwd() / ".claude" / "kaizen" / "lessons.local.md"
```

**Step 3: Add `scope` parameter to the `score()` CLI function**

In the `score()` function signature, add after the `db` parameter:

```python
scope: Annotated[
    ScopeTarget | None,
    typer.Option(
        "--scope",
        help=(
            "Lesson output scope: 'user' → ~/.claude/kaizen/lessons/, "
            "'project' → {cwd}/.claude/kaizen/lessons.md (git-tracked), "
            "'local' → {cwd}/.claude/kaizen/lessons.local.md (gitignored)."
        ),
        rich_help_panel="Output Options",
    ),
] = None,
```

**Step 4: Add scope path resolution and reporting in the `score()` function body**

After the `_write_duckdb` call (around line 617), add:

```python
if scope is not None:
    scope_path = _resolve_scope_path(scope)
    stderr.print(
        f"[dim]Lesson scope:[/dim] [cyan]{scope.value}[/cyan] → {scope_path}"
    )
```

**Step 5: Verify the CLI help renders correctly**

```bash
uv run --script plugins/agentskill-kaizen/scripts/sentiment-score.py score --help
```

Expected: `--scope` appears under "Output Options" with the three scope descriptions.

**Step 6: Verify the flag is accepted without error**

```bash
uv run --script plugins/agentskill-kaizen/scripts/sentiment-score.py score --scope local --help
```

Expected: exits 0, no error about unknown option.

**Step 7: Commit**

```bash
git add plugins/agentskill-kaizen/scripts/sentiment-score.py
```

Then `/commit-staged`

---

## Task 3: Add `.gitignore` for local scope output

**Files:**
- Create: `plugins/agentskill-kaizen/.gitignore`

**Context:**
The `local` scope writes `{cwd}/.claude/kaizen/lessons.local.md` — a per-project file that should never be committed. A `.gitignore` in the plugin root handles this for the plugin's own working directory.

**Step 1: Create the `.gitignore`**

Create `plugins/agentskill-kaizen/.gitignore` with content:

```gitignore
# Local-scope lesson output (gitignored by design — use --scope project for tracked lessons)
.claude/kaizen/lessons.local.md
```

**Step 2: Verify git sees it as ignored**

```bash
touch plugins/agentskill-kaizen/.claude/kaizen/lessons.local.md 2>/dev/null || true
git check-ignore -v plugins/agentskill-kaizen/.claude/kaizen/lessons.local.md
```

Expected: output references `.gitignore` and the file pattern.

**Step 3: Clean up the test file**

```bash
rm -f plugins/agentskill-kaizen/.claude/kaizen/lessons.local.md
```

**Step 4: Commit**

```bash
git add plugins/agentskill-kaizen/.gitignore
```

Then `/commit-staged`

---

## Task 4: Add BACKLOG todo for MCP consolidation analysis

**Files:**
- Modify: `.claude/BACKLOG.md` (repo root of `claude_skills`)

**Context:**
The plugin runs two MCP servers: `kaizen-duckdb` (motherduck, SQL queries) and `kaizen-analysis` (custom server.py, PM4Py tools + dashboard). The question is whether `sentiment-score.py` as a standalone script should instead be an MCP tool in `server.py`, and whether the two servers can be consolidated. This needs investigation before any architectural change.

**Step 1: Add a P2 BACKLOG entry**

In `.claude/BACKLOG.md`, add the following entry to the `## P2 - Nice to Have` section:

```markdown
### kaizen: MCP consolidation analysis

**Source**: Design session 2026-02-20
**Added**: 2026-02-20
**Description**: The plugin currently runs two MCP servers (`kaizen-duckdb` via mcp-server-motherduck, `kaizen-analysis` via server.py) plus a standalone CLI script (`sentiment-score.py`). Investigate: (1) What does each MCP server provide that the other cannot? Can they be merged into a single server? (2) Why is `sentiment-score.py` a standalone script rather than an MCP tool inside `server.py`? What would be gained or lost by moving scoring into the MCP server (always-on scoring, no manual invocation, lock ownership)? (3) Is there a clean boundary between "batch processing" (script) and "query/serve" (MCP) that should be preserved?
**Decision needed**: Consolidate vs. keep separate, with rationale.
**Suggested location**: `plugins/agentskill-kaizen/`
```

**Step 2: Update the frontmatter counts**

In `.claude/BACKLOG.md` frontmatter, increment `p2-count` by 1.

**Step 3: Commit**

```bash
git add .claude/BACKLOG.md
```

Then `/commit-staged`

---

## Done

After all four tasks, verify:

```bash
# MCP config is valid JSON
python3 -c "import json; json.load(open('plugins/agentskill-kaizen/.claude-plugin/plugin.json')); print('plugin.json OK')"

# Script help shows --scope
uv run --script plugins/agentskill-kaizen/scripts/sentiment-score.py score --help | grep scope

# .gitignore exists
cat plugins/agentskill-kaizen/.gitignore

# BACKLOG has the new entry
grep "MCP consolidation" .claude/BACKLOG.md
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.