From 53f13d60311fdafe4a28e1000f43c644b1ebde62 Mon Sep 17 00:00:00 2001 From: Eliott Jacopin Date: Mon, 14 Sep 2026 15:40:30 +0200 Subject: [PATCH 1/2] docs(docs): add the VS Code install example and strip history from the standalone docs The Agent Plugins 1.0 install path is verified in VS Code (Command Palette, "Chat: Install Plugin from Source", the repository slug), so the README now gives that walkthrough instead of a hedge about the spec leaving installation to clients. The standalone docs must read as-is: a README reader or a maintainer loading a dev skill has no access to the sessions that produced the rules. The dev skills cited MEM (the lead's memory), PR numbers, incident dates and this machine's paths; those are removed, the rules they backed stay, and every report shorthand the skills cite (KT-*, OBS-*, PH, CI, RI) is now a row of the AGENTS.md legend so each citation resolves inside the repository. Three cross-references to headings that no longer exist are repointed. Co-Authored-By: Claude Fable 5.1 --- AGENTS.md | 19 +++++-- README.md | 18 +++++-- dev/skills/campaign-lead/SKILL.md | 37 +++++++------- .../references/dirtree-gotchas.md | 6 +-- .../references/dispatch-prompt.md | 33 ++++++------- .../references/reviewer-brief.md | 16 +++--- dev/skills/landing-and-release/SKILL.md | 39 ++++++++------- .../references/commitizen-gotchas.md | 10 ++-- .../references/landing-a-pr.md | 12 ++--- dev/skills/maintainer-policy/SKILL.md | 14 +++--- .../references/drift-tests.md | 4 +- .../references/input-proportional-waste.md | 6 +-- dev/skills/stack-traps/SKILL.md | 25 +++++----- .../stack-traps/references/claude-code.md | 29 +++++------ dev/skills/stack-traps/references/colgrep.md | 21 ++++---- dev/skills/stack-traps/references/machine.md | 49 ++++++++----------- dev/skills/stack-traps/references/mcp-sdk.md | 12 ++--- 17 files changed, 177 insertions(+), 173 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index fce6ec6..6c467df 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -67,11 +67,12 @@ Opt-in: `COLGREP_MCP_REAL=1 uv run pytest` adds the few tests that need the real `colgrep`; `uv run python tests/e2e/run_e2e.py --corpus ` runs the end-to-end driver — never against this repository (see `stack-traps`). -## Report ids in docstrings +## Report ids in docstrings and skills -Docstrings cite report ids as pointers to measured evidence, not narration. -The same `R01` label is reused per campaign; the module docstring's topic -disambiguates which one. +Docstrings and the dev skills cite report ids as pointers to measured evidence, +not narration. The same `R01` label is reused per campaign; the module +docstring's topic disambiguates which one. `KT-*` are knowledge-transfer +reports, `OBS-*` observation reports from a reviewer pass. | Id | Report | |:--|:--| @@ -87,6 +88,16 @@ disambiguates which one. | `R01` (harness_wiring) | `__reports__/harness_wiring/00-architecture_v0.md` | | `R01` (index_housekeeping) | `__reports__/index_housekeeping/00-architecture_v0.md` | | `R02` (index_housekeeping) | `__reports__/index_housekeeping/00-findings_clear_probe_v0.md` | +| `KT-B` | `__reports__/colgrep_mcp/03-knowledge_transfer_v0.md` | +| `KT-H` | `__reports__/repo_health/02-knowledge_transfer_v0.md` | +| `KT-C` | `__reports__/consistency/02-knowledge_transfer_v0.md` | +| `KT-D` | `__reports__/dev_plugin/03-knowledge_transfer_v0.md` | +| `OBS-H` | `__reports__/repo_health/01-observation_review_v0.md` | +| `OBS-C` | `__reports__/consistency/01-observation_review_v0.md` | +| `OBS-D` | `__reports__/dev_plugin/02-observation_review_v0.md` | +| `PH` | `__reports__/repo_health/00-findings_launch_placeholders_v0.md` | +| `CI` | `__reports__/repo_health/03-findings_ci_matrix_v0.md` | +| `RI` | `__reports__/repo_health/04-findings_remote_install_v0.md` | ## Where the rest went diff --git a/README.md b/README.md index 315f5eb..1012798 100644 --- a/README.md +++ b/README.md @@ -42,11 +42,19 @@ codex plugin marketplace add CrackingShells/colgrep-mcp codex plugin add colgrep-mcp@colgrep-mcp-marketplace ``` -The Codex manifests are `.agents/plugins/marketplace.json` and `.codex-plugin/plugin.json`. These commands follow the Codex plugin documentation and have not yet been exercised end to end; a report of a working (or failing) install is welcome as an issue. +The Codex manifests are `.agents/plugins/marketplace.json` and `.codex-plugin/plugin.json`. ### Agent Plugins 1.0 clients (Cursor, GitHub Copilot, VS Code, Kiro) -The [Agent Plugins 1.0 spec](https://agent-plugins.org/specification) defines the plugin package (`plugin.json`, `mcp.json`) but explicitly leaves installation, distribution and marketplaces to each client — there is no spec-defined command for installing straight from a git URL. Check that client's own plugin or extension docs for how it adds a plugin from a repository; until then, point it at a local clone the way it expects a plugin directory (below). +The [Agent Plugins 1.0 spec](https://agent-plugins.org/specification) defines the plugin package (`plugin.json`, `mcp.json`) and leaves installation, distribution and marketplaces to each client, so the install command is the client's own. Each of these clients can add a plugin straight from this repository; its plugin or extension docs name the command. + +For example, in VS Code: + +1. Open the Command Palette (`Cmd`+`Shift`+`P` on macOS, `Ctrl`+`Shift`+`P` elsewhere). +2. Run **Chat: Install Plugin from Source**. +3. Choose the git repository option and enter `CrackingShells/colgrep-mcp` (the full URL `https://github.com/CrackingShells/colgrep-mcp` works too). + +A client without such a command takes a local clone as its plugin directory ([From a local clone](#from-a-local-clone)). ### Any MCP client @@ -140,7 +148,7 @@ The plugin also ships harness hooks (`hooks/`), so the policy the skill teaches | `PreToolUse` on `Grep` and `Bash` | Denies the built-in Grep tool and shell corpus searches (`grep -r`, `rg`, `find -exec grep`, `xargs grep`) inside a source corpus, with a reason naming `search`, `find_files` and `expand`. Single-file grep, `cmd \| grep`, `grep -c`/`-v`/`-o`, `rg --files` and file-name lookup stay allowed. Targets that are machine state (hidden directories, `~/Library`, temp directories outside a git work tree) are never gated. Prefix `COLGREP_BYPASS=1` to a command colgrep cannot serve. | | `WorktreeRemove` (Claude Code only) | Clears the colgrep index a removed worktree owned, never one it was folded into. | -`hooks/hooks.json` holds only events that Claude Code, Codex and Cursor all understand; `hooks/claude-code.json` holds the Claude-only event and is named by the Claude Code manifest alone. Codex loads a plugin's `hooks/hooks.json` and sets `CLAUDE_PLUGIN_ROOT` for it, but skips the hooks until you trust them once in `/hooks`. Cursor imports Claude Code hooks from `settings.json` files, not from plugins, so a Cursor project copies the three `hooks.json` entries into its `.claude/settings.json`. Agent Plugins 1.0 defines no hooks component and ignores the directory. Design and measurements: `__reports__/harness_wiring/00-architecture_v0.md`. +`hooks/hooks.json` holds only events that Claude Code, Codex and Cursor all understand; `hooks/claude-code.json` holds the Claude-only event and is named by the Claude Code manifest alone. Codex loads a plugin's `hooks/hooks.json` and sets `CLAUDE_PLUGIN_ROOT` for it, but skips the hooks until you trust them once in `/hooks`. Cursor imports Claude Code hooks from `settings.json` files, not from plugins, so a Cursor project copies the three `hooks.json` entries into its `.claude/settings.json`. Agent Plugins 1.0 defines no hooks component and ignores the directory. ## Configuration @@ -174,7 +182,7 @@ cd server && uv run pytest -q If you are a coding agent maintaining this repository, start with `AGENTS.md`: repo map, gate commands, conventions and known traps. -Tests run against a fake `colgrep` (`server/tests/fake_colgrep.py`); set `COLGREP_MCP_REAL=1` to include the few that need the real binary. Architecture, measured behaviour and decisions live in `__reports__/colgrep_mcp/`; the execution plan in `__roadmap__/colgrep_mcp/`; commit conventions in `CONTRIBUTING.md`. +Tests run against a fake `colgrep` (`server/tests/fake_colgrep.py`); set `COLGREP_MCP_REAL=1` to include the few that need the real binary. Architecture, findings and retrospectives live under `__reports__/`, one directory per campaign; the roadmaps under `__roadmap__/`; commit conventions in `CONTRIBUTING.md`. `server/tests/e2e/run_e2e.py` is a separate, non-pytest script (no `test_` prefix, so `pytest` never collects it) that drives the assembled server over stdio against a **real** `colgrep` binary and a real repository, for measured end-to-end validation rather than fixture-driven unit tests: @@ -183,7 +191,7 @@ cd server && uv run python tests/e2e/run_e2e.py --corpus /path/to/a/real/repo cd server && uv run python tests/e2e/run_e2e.py --corpus /path/to/a/real/repo --dry-run # print the call plan, exit 0 ``` -It refuses to run against this repository/its worktrees or anything under `/private/tmp` (colgrep folds such paths into whichever project already anchors that prefix — see `__reports__/colgrep_mcp/02-architecture_v1.md` D3). Findings from the latest run live in `__reports__/colgrep_mcp/02-findings_e2e_validation_v0.md`. +It refuses to run against this repository, its worktrees or anything under `/private/tmp`: colgrep folds such paths into whichever project already anchors that prefix, and the driver builds and clears indexes. ## Packaging diff --git a/dev/skills/campaign-lead/SKILL.md b/dev/skills/campaign-lead/SKILL.md index c67147f..e379937 100644 --- a/dev/skills/campaign-lead/SKILL.md +++ b/dev/skills/campaign-lead/SKILL.md @@ -6,8 +6,8 @@ description: "Guides a lead through running a multi-agent campaign on this repos # Campaign Lead Composes with the machine-level `writing-reports`, `managing-roadmaps` and `writing-history` -skills for mechanics; this skill is the order of operations and the rules three prior campaigns -(`colgrep_mcp`, `repo_health`, `consistency`) paid to learn. +skills for mechanics; this skill is the order of operations and the rules this repository's +campaigns established, each cited to the retrospective that records it (`AGENTS.md` legend). ## Order of Operations @@ -21,14 +21,14 @@ skills for mechanics; this skill is the order of operations and the rules three KT-C §Wins: helpers before dispatch → zero conflicts). 4. **One worktree per leaf, created by hand**: `git worktree add -b task/ `. Never rely on the Agent tool's `isolation: worktree` for this — it - branches from the primary checkout's `main`, not the campaign branch, and cost a full - wasted dispatch round in `repo_health` (KT-H §Pain Points, KT-B §Root Causes, lead memory). + branches from the primary checkout's `main`, not the campaign branch, and a whole dispatch + round lands on the wrong base (KT-H §Pain Points, KT-B §Root Causes). 5. **Dispatch** with `references/dispatch-prompt.md`. Every prompt states "stop if the leaf - file is missing from your worktree" — it turned the wrong-base failure above into a - ~15-second no-op with zero stray commits instead of wasted work (KT-H §Wins). + file is missing from your worktree" — it turns a wrong-base worktree into a ~15-second + no-op with zero stray commits instead of wasted work (KT-H §Wins). 6. **Merge level by level**, rebase-then-`--no-ff` (mechanics: `writing-history`). Re-run the - gates yourself on every branch first — an implementer's reported count is not evidence; one - branch reported 196 passing tests on a tree that actually collected 206 (KT-C §Pain Points). + gates yourself on every branch first — an implementer's reported test count is not evidence + (KT-C §Pain Points). 7. **Reviewer after any level with more than two parallel branches** — see `references/reviewer-brief.md` — before merging onward. 8. **Close with a knowledge-transfer report** (`writing-reports`); its Next-cycle Changes seed @@ -39,9 +39,8 @@ skills for mechanics; this skill is the order of operations and the rules three - **Worktrees see only committed files.** Commit every spec and helper before dispatching, or the implementer's worktree simply will not have them. - **File-disjoint ownership**, stated in the roadmap README's Gotchas, not assumed: each leaf - edits only its own files and *reports* anything else it notices in its final message. - `repo_health` and `consistency` both closed with zero merge conflicts this way (KT-H, KT-C - §Wins). + edits only its own files and *reports* anything else it notices in its final message. This + is what closes a campaign with zero merge conflicts (KT-H, KT-C §Wins). - **Hard stop time**, stated in both the leaf and the dispatch prompt: the lead merges whatever is green at the stop (`consistency` roadmap README §Gotchas). - **Do lead-sized leaves yourself.** Scaffolding, shared helpers, CI wiring, `AGENTS.md`, @@ -57,18 +56,18 @@ skills for mechanics; this skill is the order of operations and the rules three whenever a leaf is the first to exercise a previously-untested path, and name that path in the PR body (KT-C §Pain Points, CI). - **A subagent that says it is "watching CI in the background" has already ended its turn.** - Make it block on `gh run watch --exit-status`, or read the run yourself (lead memory). + Make it block on `gh run watch --exit-status`, or read the run yourself. - **A drift test that relates two artefacts owned by different leaves is red until both land.** Order the roadmap so the *naming* side lands first (e.g. the `AGENTS.md` skill table before - the skill leaves it names), or every merge in between is red on a test nobody owns; the - `dev_plugin` campaign had to land its surface leaf ahead of BFS order for this (dev_plugin - KT §Pain Points). Also: git does not track empty directories, so a scaffolded-but-empty - directory never reaches a task worktree — a test that lists it must treat "absent" as "empty". + the skill leaves it names), even ahead of BFS order, or every merge in between is red on a + test nobody owns (KT-D §Pain Points). Also: git does not track empty directories, so a + scaffolded-but-empty directory never reaches a task worktree — a test that lists it must + treat "absent" as "empty". - **Merge commits are commits too.** Probe every merge subject with `cz check --message` and run `cz check --rev-range main..HEAD` on the campaign branch before pushing; per-task-branch ranges - never contain the lead's own merges (PR #4 of `dev_plugin` failed CI on one). -- **Note the clock at the start; time-box the cycle.** The three prior cycles closed between - 50 minutes and 4 hours (KT-C, KT-H). + never contain the lead's own merges, and CI checks the whole range (KT-D §Pain Points). +- **Note the clock at the start; time-box the cycle.** A cycle here runs between one and four + hours (KT-C, KT-H). ## What This Skill Does Not Restate diff --git a/dev/skills/campaign-lead/references/dirtree-gotchas.md b/dev/skills/campaign-lead/references/dirtree-gotchas.md index add4d01..77a6be1 100644 --- a/dev/skills/campaign-lead/references/dirtree-gotchas.md +++ b/dev/skills/campaign-lead/references/dirtree-gotchas.md @@ -1,14 +1,14 @@ # dirtree-rdm Grammar Gotchas `managing-roadmaps` owns `dirtree-rdm` itself and its full BNF grammar; this file only lists -the traps this repository's campaigns have actually hit. Before writing any leaf file or -roadmap README by hand, run: +the traps that matter in this repository. Before writing any leaf file or roadmap README by +hand, run: ```bash bash ~/.claude/skills/managing-roadmaps/scripts/dirtree-rdm.sh grammar leaf ``` -Read what it prints — do not guess the shape from a prior campaign's file and hand-edit a new +Read what it prints — do not guess the shape from another campaign's file and hand-edit a new one to match; the grammar is strict and a mismatch fails validation without necessarily saying which line is wrong. diff --git a/dev/skills/campaign-lead/references/dispatch-prompt.md b/dev/skills/campaign-lead/references/dispatch-prompt.md index 4be378a..7cbf4c7 100644 --- a/dev/skills/campaign-lead/references/dispatch-prompt.md +++ b/dev/skills/campaign-lead/references/dispatch-prompt.md @@ -1,27 +1,26 @@ # Dispatch-Prompt Template Copy this template for every implementer you dispatch; fill the `` from the -leaf file and the roadmap README. Every field exists because a prior campaign paid for its -absence, not because the shape looked complete: +leaf file and the roadmap README. Every field answers a recorded failure, not a wish for the +shape to look complete: - **Worktree/branch, created from the campaign branch** and the **"stop if the leaf file is - missing"** instruction both answer the same failure from two directions: `KT-H` records a - worktree made from `main` instead of the campaign branch (the Agent tool's `isolation: - worktree` does this by default) — the field names the correct base explicitly. When a - worktree still ends up wrong-based, the "stop if missing" line is what turned that mistake - into a ~15-second no-op with zero stray commits, instead of an implementer inventing work - against a repo state the lead never intended (`KT-H` §Wins). + missing"** instruction both answer the same failure from two directions: a worktree made + from `main` instead of the campaign branch (the Agent tool's `isolation: worktree` does this + by default) — the field names the correct base explicitly. When a worktree still ends up + wrong-based, the "stop if missing" line turns that mistake into a ~15-second no-op with zero + stray commits, instead of an implementer inventing work against a repo state the lead never + intended (`KT-H` §Pain Points, §Wins). - **Read-first list and owned files, plus "commit specs before dispatching"** answer `KT-B`: - specs that existed only in the lead's own working tree were invisible to a worktree that - sees only committed files, and separately an unanchored `.gitignore` rule once hid roadmap - leaf files from git entirely. Naming the exact files to read, and stating that the lead - commits specs first, closes both holes. + a spec that exists only in the lead's own working tree is invisible to a worktree, which + sees only committed files, and an unanchored `.gitignore` rule can hide roadmap leaf files + from git entirely. Naming the exact files to read, and stating that the lead commits specs + first, closes both holes. - **Gate commands, spelled out verbatim, and the final-report shape asking for gate output - lines** answer `KT-C`: an implementer's own claimed test count is not evidence (one branch - reported 196 passing on a tree that actually collected 206), and a refactor with no named - oracle has nothing for the lead — or a reviewer — to diff against. The template asks for the - exact output line of each gate, not a paraphrase, precisely so the lead re-runs and compares - rather than trusting a summary. + lines** answer `KT-C`: an implementer's own claimed test count is not evidence, and a + refactor with no named oracle has nothing for the lead — or a reviewer — to diff against. + The template asks for the exact output line of each gate, not a paraphrase, precisely so + the lead re-runs and compares rather than trusting a summary. - **Commit rules and hard-stop time** keep the history and the time-box legible across many parallel branches the lead did not watch being written in real time. diff --git a/dev/skills/campaign-lead/references/reviewer-brief.md b/dev/skills/campaign-lead/references/reviewer-brief.md index 0467d93..1c2ae47 100644 --- a/dev/skills/campaign-lead/references/reviewer-brief.md +++ b/dev/skills/campaign-lead/references/reviewer-brief.md @@ -7,17 +7,17 @@ whether the tests pass (that is a gate, run it yourself first). A reviewer's dispatch prompt must contain all five of the following. -1. **The architecture contract.** Point it at the campaign's own contract sections (this - campaign's `C1`–`C8`, or the equivalent for another campaign) so it checks the merged code - against stated invariants, not against its own guess at what "correct" means. +1. **The architecture contract.** Point it at the campaign's own contract sections (the + `C` sections of its architecture report) so it checks the merged code against stated + invariants, not against its own guess at what "correct" means. 2. **The list of intentional client-visible deltas** (e.g. the campaign's oracle/delta table). Without this the reviewer either re-reports an approved behavior change as a bug, or cannot confirm it is the *only* delta — both failures waste the lead's time triaging noise. 3. **Instructions to probe every validator with deliberately invalid input, not just read valid history.** `cz check --rev-range` only ever sees commits that already passed; feed it - a bad `--message` instead. Give a drift test a deliberately broken fixture. Both commitizen - defects found in this repository's history were caught this way — never by reading valid - history (KT-H §Review process changes, OBS-H). + a bad `--message` instead. Give a drift test a deliberately broken fixture. Validator + defects are found this way, never by reading valid history (KT-H §Review process changes, + OBS-H). 4. **The dump-and-diff oracle for anything client-visible**: dump `Client.list_tools()`/`list_resources()`/`list_resource_templates()`/`list_prompts()` JSON on the base and the branch, diff must be empty (KT-C §Wins, OBS-C probe 1). @@ -35,5 +35,5 @@ skill for the detach-and-remove pattern — don't restate it here. When the brief says "break the guard and confirm the test fails", state the delta relative to the artefact's *current* margin, not as a fixed number: "add 10 lines" to an 89-line file under a -130-line cap never crosses the cap, and the probe passes without exercising anything (dev_plugin -review F2). Ask for "enough to exceed the cap" and have the reviewer report the size used. +130-line cap never crosses the cap, and the probe passes without exercising anything (OBS-D +F2). Ask for "enough to exceed the cap" and have the reviewer report the size used. diff --git a/dev/skills/landing-and-release/SKILL.md b/dev/skills/landing-and-release/SKILL.md index 93f309b..d116d73 100644 --- a/dev/skills/landing-and-release/SKILL.md +++ b/dev/skills/landing-and-release/SKILL.md @@ -5,15 +5,15 @@ description: Git and release mechanics for colgrep-mcp — commit shape, rebase- # Landing and release -Three cycles of this repository hit the same detours at these mechanics. This -skill is the fourth cycle not repeating them. +The git and release mechanics of this repository, with the reason behind each +rule and a citation to the report that records it (`AGENTS.md` legend). ## Commit shape Why: `cz check` enforces the schema in `server/pyproject.toml` `[tool.commitizen.customize]`, and CI blocks a PR on it — a subject that looks right by eye can still fail the regex. The type/bump table lives in -[`CONTRIBUTING.md`](../../../CONTRIBUTING.md#allowed-types); this skill does +[`CONTRIBUTING.md`](../../../CONTRIBUTING.md#commit-convention); this skill does not repeat it. Rules the schema enforces: `type(scope): description`, scope mandatory and @@ -42,20 +42,20 @@ whatever the task branch happened to have last. Rebase the task branch onto its target, re-run the gates, then `git merge --no-ff -m ""` into the target — never `git merge -F -`, which does not read stdin inside an `&&` chain. After any conflicting merge, search the tree for `<<<<<<<` before -committing; it has bitten this repository twice. (`KT-C`, `KT-B` §Pain -Points.) The merge commit is a commit too: probe its subject with -`cz check --message` before merging, and run `cz check --rev-range -main..HEAD` on the campaign branch before pushing — checking each task -branch's range is not enough (PR #4 of the `dev_plugin` campaign failed CI -on a 111-char merge subject the lead wrote; `land_branch.sh` now probes it). The general rebase-then-merge method is the machine-level -`writing-history` skill (`~/.claude/skills/writing-history/SKILL.md`, -`references/branches.md`); `scripts/land_branch.sh` runs the sequence for -this repository's gates. +committing (`KT-C`, `KT-B` §Pain Points). The merge commit is a commit too: +probe its subject with `cz check --message` before merging, and run +`cz check --rev-range main..HEAD` on the campaign branch before pushing — +checking each task branch's range is not enough, because the lead's own +merge subjects appear only in the campaign branch's range (`KT-D` §Pain +Points; `land_branch.sh` probes the subject). The general rebase-then-merge +method is the machine-level `writing-history` skill (`references/branches.md` +there); `scripts/land_branch.sh` runs the sequence for this repository's +gates. Never bare `git stash`: the stash stack is shared across worktrees and sessions, so a pop can take someone else's work. Prefer a throwaway commit; if you must stash, `git stash push -u -m ` and restore by SHA, never -`pop`. (Environment rule, `MEM`.) +`pop`. `.gitignore` rules are written for the whole repository, not one package — anchor them (`/server/build/`); a bare `build/` once hid @@ -64,10 +64,10 @@ anchor them (`/server/build/`); a bare `build/` once hid ## Branches and worktree cleanup `main` is always installable; one `task/` branch per roadmap leaf, -branched from the campaign branch (which may itself be the session's +branched from the campaign branch (which may itself be a harness-created `claude/` branch). Delete a branch and remove its worktree only after the branch is merged (`git worktree remove`, `git branch -d`). -(`CONTRIBUTING.md` §Branching.) +(`CONTRIBUTING.md` §Gates.) ## Landing a PR @@ -81,8 +81,9 @@ pushed straight to `main` leaves the PR open on GitHub. Why: `cz bump` mutates version-tracked files across the tree and pushes a tag; running it anywhere but the one checkout that is actually `main` risks bumping a version nobody merges, or a push a sandboxed permission classifier -silently blocks. Only from the main checkout -(`~/colgrep-mcp`; `release.sh` reads it from `git worktree list`), never a scratch or detached worktree: +silently blocks. Only from the main checkout (the first entry of +`git worktree list`, which is how `release.sh` finds it), never a scratch or +detached worktree: ```bash cd server @@ -96,8 +97,8 @@ version-tracked manifests, the `uvx colgrep-mcp==` pin in the three MCP manifests, and `CHANGELOG.md`, and writes its own `release(colgrep-mcp): v` commit — never author that commit or edit a version by hand; a version-drift test failing means a file was hand-edited, -not that the environment is stale. (`AGENTS.md` §Traps, `OBS-H` Check 4, -`CONTRIBUTING.md`, `MEM`.) `scripts/release.sh` enforces the checkout/branch +not that the environment is stale. (`OBS-H` Check 4, `CONTRIBUTING.md` +§Versioning and release.) `scripts/release.sh` enforces the checkout/branch check and runs the recipe up to (never including) the push. The tag push is the publish decision: `.github/workflows/publish.yml` fires diff --git a/dev/skills/landing-and-release/references/commitizen-gotchas.md b/dev/skills/landing-and-release/references/commitizen-gotchas.md index d8fb3da..7790ce1 100644 --- a/dev/skills/landing-and-release/references/commitizen-gotchas.md +++ b/dev/skills/landing-and-release/references/commitizen-gotchas.md @@ -2,11 +2,11 @@ The validator and bump machinery in `server/pyproject.toml` `[tool.commitizen]` / `[tool.commitizen.customize]` behave slightly -differently from what their flags suggest. Each row below was found by -deliberately probing the validator with an invalid input, not by reading -valid history — `cz check --rev-range` only ever sees commits that already -passed, so it cannot show you a rejection. (`KT-H` §Pain Points, `OBS-H` -findings 1-3.) +differently from what their flags suggest. Each row below comes from probing +the validator with a deliberately invalid input, not from reading valid +history — `cz check --rev-range` only ever sees commits that already passed, +so it cannot show you a rejection. (`KT-H` §Pain Points, `OBS-H` findings +1-3.) | Symptom | Cause | What to do | |:--|:--|:--| diff --git a/dev/skills/landing-and-release/references/landing-a-pr.md b/dev/skills/landing-and-release/references/landing-a-pr.md index eb10c76..795dd71 100644 --- a/dev/skills/landing-and-release/references/landing-a-pr.md +++ b/dev/skills/landing-and-release/references/landing-a-pr.md @@ -4,7 +4,7 @@ A GitHub PR and a local `git merge --no-ff` are two different ways to integrate a branch, and they leave GitHub's own bookkeeping in different states. Pick the PR path deliberately when the unit of work is going through GitHub review, and follow it all the way through — mixing the two is what -causes the failure mode below. (`MEM`.) +causes the failure mode below. ## The sequence @@ -28,9 +28,8 @@ causes the failure mode below. (`MEM`.) traceable back to the PR from `git log` alone. Pass `--body ""` as well: with `--subject` alone GitHub copies the PR *title* into the merge commit's body, and if that title is itself a `feat(...)`/`fix(...)` line - commitizen parses it as a second entry — v0.3.0's changelog lists the - PR #6 subject twice for exactly this reason. Probe the subject first with - `cz check --message` (the merge commit is a commit too). + commitizen parses it as a second changelog entry. Probe the subject first + with `cz check --message` (the merge commit is a commit too). ## Why not a local rebase-then-merge here @@ -38,9 +37,8 @@ A local `git merge --no-ff` followed by `git push origin :main` does land the code, but it rewrites the commit SHAs relative to what GitHub's PR page is tracking. GitHub cannot recognize the pushed commits as "this PR, merged" and leaves the PR showing **open** even though `main` now contains -the work. This has happened twice (PR #1, #2): the fix each time was to close -the PR by hand with a comment pointing at the merge commit SHA that actually -landed the change. +the work. The only fix then is to close the PR by hand with a comment +pointing at the merge commit SHA that actually landed the change. If a PR is open for a branch, land it through `gh pr merge`, not a local merge and push. Reserve the local `land_branch.sh` path (see `SKILL.md` diff --git a/dev/skills/maintainer-policy/SKILL.md b/dev/skills/maintainer-policy/SKILL.md index ae81447..7ef84ee 100644 --- a/dev/skills/maintainer-policy/SKILL.md +++ b/dev/skills/maintainer-policy/SKILL.md @@ -12,7 +12,7 @@ reach it through the MCP tools, maintainers reach it through this dev plugin. Every design, engineering, and project-management decision is judged by one question — does it make an agent's next command shorter, or make a failure disappear? `README.md` is the sole exception: humans read it to decide -whether to install the tool or point their own agent at it (`MEM`, `KT-H` +whether to install the tool or point their own agent at it (`KT-H` §Executive Summary). When you are drafting anything else — a doc, a check, a convention — picture the agent that will read it under time pressure, not a human skimming for reassurance. @@ -22,13 +22,13 @@ human skimming for reassurance. Generic GitHub ceremony — heavy CI, pre-commit hooks, badges, issue/PR templates, bot integrations — is suspect by default. Before adding any of it, name the agent command it shortens or the agent failure it removes; if you -can't, don't add it (`MEM`: "a lot of good code or github practice is -overengineering"). +can't, don't add it: most of what passes for good GitHub practice is +overengineering here (`KT-H`). This is why enforcement here is **CI-only**: there is no blocking local git hook, because an agent authoring a commit would pay a retry loop for no local benefit. `cz check`, `pytest`, and `ruff check` gate the pull request, not the -commit (`CONTRIBUTING.md` §Checks, `KT-H`). +commit (`CONTRIBUTING.md` §Gates, `KT-H`). ## Drift tests, not checklists @@ -62,8 +62,8 @@ program sharing the machine, not once. Hunt for work proportional to the round-trips, environment copies, a `Path.resolve()` per lock — and remove it even when a single instance looks negligible; make I/O lazy where the answer may not be needed at all. A change justified only by human readability, with -no effect on an agent's commands or failures, does not meet this bar (`MEM`, -`KT-C`). The measured examples that anchor this rule — `find_files` and +no effect on an agent's commands or failures, does not meet this bar +(`KT-C`). The measured examples that anchor this rule — `find_files` and `expand` before/after, the per-spawn env copy, the per-lock resolve, the per-request guide read — are in `references/input-proportional-waste.md`; read it before arguing a hunt target is too small to matter. @@ -73,7 +73,7 @@ read it before arguing a hunt target is too small to matter. An agent should navigate this codebase by symbol, not by re-deriving the pattern each time. Every concern below has exactly one entry point; a tool that reimplements it instead of calling it is a bug, not a style choice -(`AGENTS.md` §Conventions, `KT-C`): +(`KT-C`): | Concern | Single idiom | |:--|:--| diff --git a/dev/skills/maintainer-policy/references/drift-tests.md b/dev/skills/maintainer-policy/references/drift-tests.md index 6ef1357..d8a8d01 100644 --- a/dev/skills/maintainer-policy/references/drift-tests.md +++ b/dev/skills/maintainer-policy/references/drift-tests.md @@ -15,7 +15,9 @@ in a leaf or a PR template. | `tests/test_version.py` | `colgrep_mcp.__version__` equals `pyproject.toml`'s version; every manifest's `version` field equals it too; `uv.lock` records exactly that version for this package. | | `tests/test_manifests.py` | All four plugin manifests (`plugin.json`, `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, `dev/.claude-plugin/plugin.json`) carry the same version; the Agent Plugins 1.0 manifest only uses its permitted field set and the right `$schema`; the three ecosystems' MCP server configs launch the server the same way (same `uv run` invocation shape, no unexpanded `$` placeholders outside project scope). | | `tests/test_changelog.py` | Every `## ` version heading in `CHANGELOG.md` is shaped so commitizen's incremental changelog mode can parse it — a hand-written Keep-a-Changelog heading in the wrong shape would make `cz bump --changelog` duplicate that section instead of appending to it. | -| `tests/test_readme.py` | The tool names listed in `README.md`'s table match the tools the server actually registers — a renamed or removed tool that isn't updated in the README fails here instead of shipping stale docs. | +| `tests/test_readme.py` | The tool names listed in the Tools table of `README.md` and of `server/README.md` (the PyPI page) match the tools the server actually registers — a renamed or removed tool that isn't updated in a README fails here instead of shipping stale docs. | +| `tests/test_packaging.py` | `server/LICENSE` is a byte copy of the repository `LICENSE` (hatchling only packages files under `server/`); `[project.urls]` point at the repository; no tracked text file carries a path from a maintainer's machine. | +| `tests/test_hooks.py` | The hook script's decisions for each event, fed the harness's JSON by hand; `hooks/hooks.json` carries only events every hook-capable harness knows and `hooks/claude-code.json` the Claude-only one; the Claude Code manifest names both files, the Codex manifest only the portable one. | | `tests/test_dev_plugin.py` | `AGENTS.md` stays under its line cap and names every skill under `dev/skills/`; every `dev/skills/*/SKILL.md` has front matter whose `name` matches its directory and a description long enough to state when to load it; the dev plugin manifest is the versioned skills plugin (no `mcpServers`); the marketplace lists both plugins from disjoint sources; the product plugin's skills path never resolves inside `dev/`. | ## Recipe for a new one diff --git a/dev/skills/maintainer-policy/references/input-proportional-waste.md b/dev/skills/maintainer-policy/references/input-proportional-waste.md index aeec9c6..f67229a 100644 --- a/dev/skills/maintainer-policy/references/input-proportional-waste.md +++ b/dev/skills/maintainer-policy/references/input-proportional-waste.md @@ -34,15 +34,15 @@ or once per line of subprocess output: None of these matter for a single call in isolation — that's exactly the trap. On a shared machine, every one of these runs again for every other program's request too; "it's I/O-bound anyway" ignores that the same waste is -paid by everyone else at the same time (`MEM`). Remove it even when a single +paid by everyone else at the same time. Remove it even when a single instance looks negligible, and prefer making the I/O lazy — don't do it until the caller's request actually needs the answer. ## Measured examples (`KT-C`) These are the numbers that anchor the rule — not hypothetical savings, but -what this repository's own consistency campaign measured, median of 5, on a -synthetic corpus: +what the `consistency` campaign measured, median of 5, on a synthetic +corpus: | Hot path | Before | After | What changed | |:--|:--|:--|:--| diff --git a/dev/skills/stack-traps/SKILL.md b/dev/skills/stack-traps/SKILL.md index 39a1073..f8dca52 100644 --- a/dev/skills/stack-traps/SKILL.md +++ b/dev/skills/stack-traps/SKILL.md @@ -6,10 +6,10 @@ description: Lists what colgrep, the MCP Python SDK v2, and Claude Code's plugin # stack-traps Four layers hide behind this repository's day-to-day commands, and each one -has already bitten a maintaining agent at least once. This skill is the -symptom index; each fact lives in exactly one `references/*.md` file, cited -back to the report or docstring that established it — read the linked -section, don't re-derive the trap from scratch. +fails in ways its output does not explain. This skill is the symptom index; +each fact lives in exactly one `references/*.md` file, cited back to the +report or docstring that established it (`AGENTS.md` legend) — read the +linked section, don't re-derive the trap from scratch. ## Symptom index @@ -40,13 +40,13 @@ section, don't re-derive the trap from scratch. what to do, in that order). 2. Open only the reference file the row names; the other three files are for different symptoms and not worth loading. -3. Do what "what to do" says before trying anything else — every trap here - already cost someone real time working around the wrong layer (fixing - the server for what was actually a test-harness bug, treating a naming - coincidence as an error, adding a root `.mcp.json` back, etc.). -4. If you hit a stack trap not listed here, it belongs in a future revision - of the matching `references/*.md` file, cited to its source — don't - leave it as tribal knowledge in a commit message or a private aside. +3. Do what "what to do" says before trying anything else — the usual way to + lose an hour is to work around the wrong layer (fixing the server for a + test-harness bug, treating a naming coincidence as an error, adding a + root `.mcp.json` back). +4. If you hit a stack trap not listed here, add it to the matching + `references/*.md` file, cited to its source — don't leave it as tribal + knowledge in a commit message or a private aside. ## References @@ -61,4 +61,5 @@ section, don't re-derive the trap from scratch. on an expired OAuth session, the `uvx colgrep-mcp==` pin, plugin hooks loading (reload, Codex trust, the portable/Claude-only split). - `references/machine.md` — the plugin's shell-search hook and `COLGREP_BYPASS=1`, - Windows CI's two known causes, the detached-worktree trick for `main`. + Windows CI's two known causes, the detached-worktree trick for `main`, the + permission classifier, a venv whose shebangs point at a moved checkout. diff --git a/dev/skills/stack-traps/references/claude-code.md b/dev/skills/stack-traps/references/claude-code.md index 67ebd5d..08cf135 100644 --- a/dev/skills/stack-traps/references/claude-code.md +++ b/dev/skills/stack-traps/references/claude-code.md @@ -13,10 +13,10 @@ loader, one that has no notion of `CLAUDE_PLUGIN_ROOT` and so leaves the placeholder unexpanded, tried literally as a path. This is why this repository's MCP config lives at `.claude-plugin/mcp.json` instead: a root-level project open then discovers no `mcpServers.colgrep` entry at -all. Since 0.3.0 no manifest carries a placeholder in `args` at all — every -one launches `uvx colgrep-mcp==` (see `#uvx-pin`) — and the only -one left, `COLGREP_MCP_ROOT=${CLAUDE_PROJECT_DIR}` in `env`, is in the Claude -Code manifest only; Codex has its own `.codex-plugin/mcp.json` without it. +all. No manifest carries a placeholder in `args` — every one launches +`uvx colgrep-mcp==` (see `#uvx-pin`) — and the only placeholder at +all, `COLGREP_MCP_ROOT=${CLAUDE_PROJECT_DIR}` in `env`, is in the Claude Code +manifest only; Codex has its own `.codex-plugin/mcp.json` without it. Placeholders belong only in `args`/`env` (never `command` — no ecosystem expands placeholders there); `${VAR:-default}` fallback syntax is documented only for *project*-scope `.mcp.json`, not for the plugin substitution path, @@ -48,9 +48,8 @@ cached environment (pypi_publication R01 §C6, D4). The third symptom is uv's HTTP cache: it keeps PyPI's simple-index page for `colgrep-mcp` for as long as PyPI's cache headers allow, so a pin that was -uploaded a moment ago is "no version of colgrep-mcp==X" to a warm cache -(seen on the v0.3.1 release: the gate failed twice, then connected after a -refresh). The plugin loader shows none of that text — only the closed pipe. +uploaded a moment ago is "no version of colgrep-mcp==X" to a warm cache. +The plugin loader shows none of that text — only the closed pipe. **What to do**: after a release, warm the cache once with `uvx --refresh colgrep-mcp== --version`, then re-run the gate. To @@ -78,8 +77,7 @@ not a bug. Codex's own marketplace file names itself `colgrep-mcp-marketplace` ecosystems' install commands don't mirror each other syntactically. A `source` field of `"./"` or `"./dev"` in a marketplace manifest resolves relative to the marketplace root, which works for a marketplace added from -a git source or local directory (confirmed end-to-end for this repo's own -`.claude-plugin/marketplace.json`) but not for a direct URL to the +a git source or local directory but not for a direct URL to the `marketplace.json` file itself. (`RI`.) **What to do**: don't "fix" the `colgrep-mcp@colgrep-mcp` string as if it @@ -92,17 +90,16 @@ copy that ecosystem's own marketplace `name`, not Claude Code's. OAuth session expired`; `claude plugin eval` or skill-creator's `run_loop.py`/`run_eval.py` fail the same way. -**Cause**: all of these need an authenticated `claude -p` session; on this -machine that OAuth session is expired, and none of them have a working -fallback. (`KT-B`; this campaign.) +**Cause**: all of these need an authenticated `claude -p` session; when +the OAuth session has expired, none of them has a working fallback. +(`KT-B`.) **What to do**: don't treat this as a bug in the plugin or the skill. Degrade the plugin-connectivity gate to `claude --plugin-dir . mcp list` (non-interactive, shows `✔ Connected` without needing `-p`) instead of -trying to force `claude -p` to work. Eval cases in `dev/evals/*/case.yaml` -are authored to the documented schema and left unrun this cycle for the -same reason — the first session with a working authenticated `claude -p` -should run them, not this one. +trying to force `claude -p` to work. The eval cases in +`dev/evals/*/case.yaml` need the same authenticated session; run them from +one that has it. ## The plugin's hooks don't fire, or run the old text, after a change {#plugin-hooks} diff --git a/dev/skills/stack-traps/references/colgrep.md b/dev/skills/stack-traps/references/colgrep.md index 0e37ca2..30e0bb5 100644 --- a/dev/skills/stack-traps/references/colgrep.md +++ b/dev/skills/stack-traps/references/colgrep.md @@ -11,8 +11,8 @@ current directory. `[QUERY]` positional of the default `search` command. `colgrep --color never status` is not "status with color off"; it is a search for the words `--color never status` is never reached because `--color` is itself consumed -as part of the query token stream ahead of any subcommand. One agent indexed -its worktree this way. (`KT-B` §Pain Points; `server/colgrep_mcp/adapter.py` +as part of the query token stream ahead of any subcommand, so the command +indexes and searches the cwd. (`KT-B` §Pain Points; `server/colgrep_mcp/adapter.py` docstring — the adapter itself always inserts `--color never` *after* `argv[0]`, i.e. right after the subcommand, for exactly this reason.) @@ -38,12 +38,9 @@ against its corpus. A path with **no** indexed ancestor has no such problem: the first `search` creates a fresh project rooted at that path (`index_status` afterwards reports `project == requested_path`), and the plugin's `WorktreeRemove` hook reaps that index when the worktree goes. -That is exactly why the maintainer's worktrees live outside the repository -tree (`~/…/claude-worktrees/…`, not `/.claude/worktrees`, which -colgrep ignores): each gets its own index. Verified 2026-09-13 on the -`harness_wiring` worktree: no ancestor among 164 indexed projects, first -`search` indexed it in 13 s, `project` equalled the worktree path. (`KT-B`, -`R03`, harness_wiring R01, `MEM`.) +That is why worktrees belong outside the repository tree (not under +`/.claude/worktrees`, which colgrep ignores): each gets its own +index. (`KT-B`, `R03`, harness_wiring R01.) **What to do**: before the first `search` in a worktree, call `index_status` on it. `indexed: false` means the search will create the @@ -52,8 +49,8 @@ from `requested_path` means you are folded into an ancestor: search from that ancestor knowingly, and never `index_clear` from the worktree path (the tool refuses with `PROJECT_ROOT_MISMATCH` anyway, R05 D3). Never run `run_e2e.py` against this repository; use `uv run python -tests/e2e/run_e2e.py --corpus ` (the standing corpus is -`~/colgrep-e2e-corpus/click`). Tests exercise behaviour through +tests/e2e/run_e2e.py --corpus ` against a clone of any +other project. Tests exercise behaviour through `fake_colgrep.py`; `COLGREP_MCP_REAL=1 uv run pytest` is the one opt-in for the real binary and does not touch this tree. @@ -68,8 +65,8 @@ sampled units, while `unit.code` itself is exact. The server does not trust colgrep's line numbers as-is: `locate.py` re-derives `(line, end_line)` by finding `code`'s first line verbatim in the file (disambiguating by following-line match or nearest distance to the reported line), and sets -`location_verified` accordingly. (`R03`; `KT-B` §Open Questions — whether -`--no-pool` changes this is still an open re-probe, not yet answered.) +`location_verified` accordingly. (`R03`; `KT-B` §Open Questions lists +whether `--no-pool` changes this.) **What to do**: trust `line`/`end_line` only when `location_verified` is true; when it is false, cite the file rather than a specific line range, diff --git a/dev/skills/stack-traps/references/machine.md b/dev/skills/stack-traps/references/machine.md index e9fc5ed..bd6782b 100644 --- a/dev/skills/stack-traps/references/machine.md +++ b/dev/skills/stack-traps/references/machine.md @@ -1,4 +1,4 @@ -# This machine's traps +# Machine and harness traps ## A Bash command gets blocked even though it looks harmless {#shell-hook} @@ -14,12 +14,10 @@ Bash command text whose targets are a source corpus, on the theory that a corpus search should go through the `search` tool instead of brute-force recursive grep. The block is on the text of the command, not just its runtime behaviour, so even a `cat < -b main` (or any variant naming `main`) fails because `main` is already checked out in another -worktree (the main checkout, typically -`~/colgrep-mcp`). +worktree (the main checkout). **Cause**: git refuses to check out the same branch in two worktrees at once. A reviewer or lead adding a read-only worktree for inspection hits @@ -82,9 +78,8 @@ implementer, which names a real branch on purpose. ## Auto-mode permission classifier blocks compound history rewrites {#classifier} **Symptom**: a Bash command chaining `git checkout --detach … && git merge … && git cherry-pick … -&& git branch -f … && git push --force-with-lease` is refused with "Blocked by classifier", -as was `git push … HEAD:main` and `cz bump` from a detached `/private/tmp` worktree in the -consistency session (`MEM`). +&& git branch -f … && git push --force-with-lease` is refused with "Blocked by classifier"; +so is `git push … HEAD:main` or `cz bump` run from a detached worktree under a temp directory. **Cause**: the auto-mode classifier judges the whole command; anything that rewrites a checked-out branch or force-pushes reads as destructive, and a scratch worktree under a temp @@ -93,8 +88,7 @@ directory makes it worse. **What to do**: never rewrite history in place. Create a fresh branch (`git worktree add -b `), rebuild it with single-purpose commands (`git merge`, `git cherry-pick …`, one per call), push it normally, open a new PR and close the old one -with a pointer — the `dev_plugin` campaign's PR #4 → #5 is the precedent. Do releases from the -main checkout (`landing-and-release`). +with a pointer. Do releases from the main checkout (`landing-and-release`). ## `uv run` says "Failed to spawn: `cz`" although `uv sync` audits every package {#stale-venv} @@ -106,8 +100,7 @@ reports every package present and `.venv/bin/cz` exists. launcher in `.venv/bin/` has an absolute shebang (`#!/old/path/server/.venv/bin/python3`), `uv sync` audits installed packages rather than shebangs, so nothing rewrites them; the kernel's "bad -interpreter" surfaces as uv's "Failed to spawn". Bit the v0.3.0 release -(main checkout moved from `~/colgrep-mcp`). +interpreter" surfaces as uv's "Failed to spawn". **What to do**: `rm -rf server/.venv && uv sync --directory server`. Never hand-edit the shebangs and never "fix" it by pointing the release at another diff --git a/dev/skills/stack-traps/references/mcp-sdk.md b/dev/skills/stack-traps/references/mcp-sdk.md index 418fda2..2a850ff 100644 --- a/dev/skills/stack-traps/references/mcp-sdk.md +++ b/dev/skills/stack-traps/references/mcp-sdk.md @@ -42,10 +42,9 @@ handler or the completion callback, but the SDK gives these no request **Cause**: only tool handlers receive a request `Context`. The process-wide adapter/settings still need to be reachable from handlers the SDK doesn't -hand one to. (`KT-C`; review finding `OBS-C` OV1 — an earlier attempt at -this used a plain module global, which corrupted state across overlapping -sessions, e.g. two in-memory test clients whose lifespans overlap in one -process.) +hand one to. (`KT-C`; `OBS-C` OV1 — a plain module global corrupts state +across overlapping sessions, e.g. two in-memory test clients whose +lifespans overlap in one process.) **What to do**: call `server.get_app(ctx=None)` (or `get_adapter`/ `get_settings`, which are thin wrappers over it). It reads a `ContextVar`, @@ -74,7 +73,7 @@ open the session in legacy mode. Never assume a deprecation warning at startup indicates a bug to silence differently — it's filtered deliberately. Send every client notification through `logging_utils.safe_log`/`safe_progress`/`safe_notify_resource_updated` -(see `references/../SKILL.md` cross-reference in `AGENTS.md` §Conventions) +(`maintainer-policy` §One idiom per concern) so a client that has dropped the logging capability never fails a tool call — never wrap a notification in a tool's own bare `try/except Exception: pass`. @@ -87,8 +86,7 @@ resolves to something with a leading slash before the drive letter. **Cause**: client roots arrive as `file:///C:/Users/...` URIs. Building a path with `Path(uri.path)` keeps the URI's leading `/` before the drive -letter, which is not a valid Windows path. (`KT-C` §Pain Points; the -`url2pathname` fix landed in PR #3.) +letter, which is not a valid Windows path. (`KT-C` §Pain Points.) **What to do**: convert a root URI with `urllib.request.url2pathname`, never `Path(uri.path)` — this is exactly what `paths.py` does today; don't From 1bbb515edd2e7ff602ea6a3325126af4b6abc009 Mon Sep 17 00:00:00 2001 From: Eliott Jacopin Date: Mon, 14 Sep 2026 16:15:14 +0200 Subject: [PATCH 2/2] docs(docs): state the independence from LightOn and the agent-run development cycle Nothing in the repository claimed LightOn's endorsement, but nothing denied it either; a reader deciding where to file a colgrep bug needs the boundary stated at the top. The new section tells a human reader who does the work here and how a change reaches main, so the agent-run cycle is visible rather than implied by the commit history, and names the two conditions it depends on: a frontier model and a maintainer who reads every diff. Co-Authored-By: Claude Fable 5.1 --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 1012798..0cad103 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Semantic and hybrid code search for coding agents, as an MCP server. [colgrep](https://github.com/lightonai/next-plaid) indexes a repository into *code units* (functions, classes, methods, Markdown sections) and ranks them with a ColBERT late-interaction model fused with keyword search. It is fast and it understands meaning. It is also a CLI, and agents trained on `grep` rarely reach for it unprompted. `colgrep-mcp` puts the same capability in the agent's tool list, where it gets used. +This is an independent project. It is not affiliated with or supported by [LightOn](https://www.lighton.ai), who make colgrep. A problem with the search tools belongs in this repository's issues, a problem with colgrep itself in [next-plaid](https://github.com/lightonai/next-plaid/issues). + One directory installs as a **Claude Code plugin**, an **[Agent Plugins 1.0](https://agent-plugins.org) plugin** (Codex, Cursor, GitHub Copilot, VS Code, Kiro) and a **Codex plugin**. ## Requirements @@ -174,6 +176,14 @@ Without `COLGREP_MCP_ROOT` the server falls back to the client's first root, if - **`index_clear` refuses.** colgrep folds a directory into the nearest already-indexed ancestor project. The tool tells you the project root it would clear; pass that root explicitly if that is really intended. - **Line numbers.** colgrep 1.6 reports wrong `line`/`end_line` for most units. The server re-locates every unit from its source text and flags `location_verified` on each hit. +## For agents, by agents + +Everyone who touches this repository is an LLM agent. Users reach it through the MCP tools, and the maintenance itself is handed to a coding agent, at present Claude Fable 5.1 in Claude Code: it reads the architecture reports, plans the work as a roadmap, implements in its own git worktree, writes the tests and the docs, and opens the pull request. The MCP server and the skill are the two layers made for the human and the agent to talk to each other; everything else, from the drift tests to the maintainer skills in `dev/`, is optimised for an agent picking the work up cold. + +A change goes through an ordinary pull-request cycle. The agent commits with the vocabulary `cz check` enforces (`CONTRIBUTING.md`), pushes a branch and opens the PR; CI runs ruff, the test suite on Linux, macOS and Windows, the commit check and a build; the maintainer reads the diff and the PR body, then merges; a release is a `cz bump` on `main` and a tag push, which publishes to PyPI. Larger work runs as a campaign: an architecture report under `__reports__/`, a roadmap under `__roadmap__/`, one worktree per leaf, a read-only reviewer pass, and a retrospective whose lessons become the next revision of the `dev/` skills. + +This holds because the agent is a frontier model and because the maintainer, who has built MCP servers before, reads every diff. The tests, the drift guards and the reports exist so that the trust placed in the agent is verified at each merge rather than assumed; the same process with a weaker model, or with merges nobody reads, would drift. + ## Development ```bash