docs(playbook): document the local plugin development loop - #7
Conversation
The playbook covered first-publish validation (the migration gate's --plugin-dir step) but not how to iterate on an already-shipped plugin against a local clone. Add a "Local development loop" section: load the working copy with `claude --plugin-dir ./plugins/<name>` (the local copy takes session precedence over the installed same-name plugin), edit then `/reload-plugins` to pick up on-disk changes without a restart, commit, and let consumers pull via `/plugin marketplace update`. Key point for the consumer seam: local development never requires switching a consumer's tracked `extraKnownMarketplaces` source — the published remote registration stays put; `--plugin-dir` overrides it for the session only. Verified 2026-06-24 against the official plugins guide (canonical URLs in CLAUDE.md), per this repo's fresh-docs mandate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e93f2666fd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| - **Trust.** A locally loaded plugin carries the same trust considerations as any source — only load | ||
| directories you control. | ||
| - **Then ship.** Run `claude plugin validate` before opening a PR; after merge, consumers pull the | ||
| change with `/plugin marketplace update melodic-software`, gated by the `version` bump in `plugin.json`. |
There was a problem hiding this comment.
Tell consumers to update the installed plugin
For release instructions, this command only refreshes the marketplace catalog/version data; the Claude plugin reference lists installed plugin upgrades under /plugin update/auto-update and uses the plugin version as the cache key. A consumer with <name>@melodic-software already installed can run this and still keep using the old cached plugin code, so the playbook should include /plugin update <name>@melodic-software (then reload/restart as needed) when the intent is to receive shipped changes.
Useful? React with 👍 / 👎.
… recording tier, routines provenance (#845) ## Summary Absorbs the vetted ideas from the "4 Levels of Agentic Coding" video digest (Boris Cherny "Steps of AI Adoption" walkthrough) into the plugin estate, per the approved plan at `docs/topics/boris-video-absorption/PLAN.md`. - **testing 0.3.0 (minor):** `/testing:run-e2e` gains the consumer config surface `.claude/testing/e2e.md` (`recording: video|gif|off` default `off`; `browser_mode: headed|headless` default `headless`) with explicit read path, per-key merge + provenance reporting, and plumbing to the playwright executor; keys owned by new `context/e2e-config.md` (policy-vs-mechanics boundary; prompt > config precedence). Prerequisite hard-fail keeps STOP and adds a structured verification-environment gap report. Drive loop subagent-isolated; presence-gated `/verify`-first delegation (CC >=2.1.145). Evidence contract adds optional recording tier + session artifacts. Eval #1 updated. - **verification 0.3.2 (patch):** `/verification:confirm` delegation wording acknowledges the enriched run-e2e; stages/verdict machinery untouched. - **autonomy 0.8.0 (minor):** `reference/routines.md` gains the instruction-provenance clause — routine instruction content lives in a version-controlled artifact, stored prompt is a thin pointer; surface mappings are illustrative deployment-owned bindings. - Implementers-table row added in `docs/conventions/consumer-config-layering/README.md`. Coordination: zero file overlap with the ignition/enforcement lanes (#778 comment posted; ignition Phases 2–3 merged via #810). Defaults preserve current consumer behavior. ## Related No linked issue: this PR closes no GitHub issue. Related, not closed: - #778 — ignition lane coordination (comment posted; zero file overlap) - #810 — ignition Phases 2-3 (merged; separate lane) ## Verification - markdownlint: 0 errors on all touched files; typos gate exit 0 - `check-skill.sh`: run-e2e PASS, confirm PASS (pre-existing advisory warnings only) - run-e2e `evals/evals.json`: valid against bundled schema (ajv, draft2020) - Sanity greps per PLAN phase checks: all pass - Stage-structure invariant on confirm SKILL.md: 16 before/after <details> <summary>PLAN.md</summary> # PLAN — boris-video-absorption ## Brief Absorb the vetted ideas from the Ray Amjad "4 Levels of Agentic Coding" video digest (research base: `~/.work/youtube-watch/the-4-levels-of-agentic-coding-how-to-sh-XLA-sTSJ-Wc/`) into the plugin estate. Interview-locked contracts (this session): - Extend existing seams, no new skill: `testing:run-e2e` (driver) + `verification:confirm` (judge) keep their division of labor. - run-e2e gains: subagent-isolated surface runs; native-/verify-first delegation (presence-gated, CC ≥2.1.145); structured missing-environment gap report on prerequisite failure (hard-fail stays, plus actionable report); video/session-artifact evidence tier. - Recording format (video | gif | off) and browser mode (headed | headless) are layered config knobs per `docs/conventions/consumer-config-layering/` — NOT hardcodes. - `plugins/autonomy/reference/routines.md` gains a thin-pointer clause: routine/scheduled-task prompts on any surface point to version-controlled files; pasted prose non-compliant. - `~/.claude/scheduled-tasks/` (exists, live task) proposed for dotfiles tracking via the dotfiles repo's add-dotfile flow. - Deferred-with-trigger (recorded in digest slice, NO tracker issues): verification self-improvement loop (trigger: accumulated recorded runs); bounded build→review→fix loop (trigger: post-Phase-II enforcement rail); Claude Tag enablement (trigger: post-8/3 cutover + Enterprise admin check). - Out of scope: presenter-custom harness (Percy), chat-surface wiring, Chronicle adoption, lifecycle reordering. - Boris doc capture re-verified NO-DRIFT 2026-07-21; all adopted items trace to the doc's step 1→2/2→3 recipes or native CC features. Success: PRs merged with skill-quality + markdownlint green; every adopted behavior traceable to research findings; zero collision with the primary session's lanes (ignition Phases 2–3 merged via #810; no pending branch touches target files — verified). ## Standards grounding - `docs/conventions/consumer-config-layering/README.md` — three layers (user-global / team / local overlay), additive-preferred merge; new config surface must declare keys in the owning plugin's docs and point at the convention for layering. - `docs/CATALOG-TAXONOMY.md` + `docs/PLUGIN-PHILOSOPHY.md` — extend-over- add, seam cooperation presence-gated, fresh-eyes delegation. - Repo commit/PR conventions (conventional commits, codex thread resolution before merge, `--body-file -` for PR bodies). ## Plan ### Phase 1: Lane setup [DONE] - Create worktree off `origin/main`, branch `feat/boris-video-absorption` (sibling-worktree convention). - Materialize `docs/topics/boris-video-absorption/PLAN.md` (this file) + `design/design-resolution.md` (Tier B early-exit: no new types; one new config surface whose shape is resolved here — see Decisions). - Post coordination comment on #778: secondary session lane, files touched, no overlap with ignition/enforcement lanes. - **Sanity Check:** `git worktree list` shows the new worktree on the new branch; `gh issue view 778` shows the comment; PLAN.md exists in the worktree at `docs/topics/boris-video-absorption/PLAN.md`. ### Phase 2: run-e2e enrichment [DONE] Files: `plugins/testing/skills/run-e2e/SKILL.md`, `plugins/testing/skills/run-e2e/context/e2e.md`, `plugins/testing/README.md`, new `plugins/testing/skills/run-e2e/context/e2e-config.md` (key owner doc), `plugins/testing/skills/run-e2e/evals/evals.json` (eval #1 asserts the prerequisite-failure behavior this phase changes — update unconditionally), `plugins/testing/CHANGELOG.md` (Keep a Changelog entry; **minor** bump — new behaviors), `docs/conventions/consumer-config-layering/README.md` (Implementers-table row for the new surface — the convention tracks conformance, not assumes it). - Declare config surface `.claude/testing/e2e.md` (folder-form name per convention: surface identity = whole path relative to `.claude/`). Keys: `recording: video | gif | off` (default `off` — evidence contract screenshots stay the floor), `browser_mode: headed | headless` (default headless, operator overrides for visibility). Per-key override semantics. Layering resolution cites the convention doc — no restatement. - **Read path (reviewer gap #3 — mandatory):** SKILL.md gains explicit resolution instructions — anchor at repo root, read all three layers (user-global → team → local overlay), merge per-key, report which layer supplied each effective value. **Plumbing:** resolved `browser_mode` and `recording` are passed to the executor (`/playwright:playwright` invocation args / gif_creator choice) — keys without plumbing are the documented ai-briefing deviation; not repeating it. - **Key-ownership framing (reviewer risk #6):** e2e-config.md states the boundary — run-e2e owns capture POLICY (what evidence, which format, visibility preference); playwright owns MECHANICS (how the browser runs). Keys are policy inputs run-e2e resolves and passes through. - **Precedence (operator-locked):** config keys are DEFAULTS only; an explicit session prompt always wins ("run this headed" overrides `browser_mode: headless`). e2e-config.md states this: prompt > local overlay > team > user-global > bundled default. - SKILL.md: subagent-isolated run guidance (delegate the drive loop to a subagent; orchestrator consumes evidence paths only); /verify-first delegation note (presence-gated on bundled /verify, CC ≥2.1.145, with existing orchestrator fallback unchanged). - Prerequisite failure path: keep hard-fail STOP; add a structured verification-environment gap report (what's missing, what the operator must provide — keys/CLIs/environments; the "what do you need to verify this e2e" elicitation) written to the run's evidence output. - context/e2e.md evidence contract: add optional recording tier (video via playwright CLI preferred for long flows; GIF via gif_creator for short demos — driven by the `recording` key) + session artifacts row (recording path, session ID, transcript pointer) in the evidence table. - **Sanity Check:** `rg -c "e2e-config|\.claude/testing/e2e\.md" plugins/testing/skills/run-e2e/SKILL.md` ≥ 1; `rg -c "gap report" plugins/testing/skills/run-e2e/SKILL.md` ≥ 1; `rg -c "recording" plugins/testing/skills/run-e2e/context/e2e.md` ≥ 2; **read-path present:** `rg -c "layer" plugins/testing/skills/run-e2e/SKILL.md` ≥ 2 AND `rg -c "browser_mode" plugins/testing/skills/run-e2e/SKILL.md` ≥ 2 (resolution + plumbing sites); Implementers-table row: `rg -c "testing/e2e" docs/conventions/consumer-config-layering/README.md` ≥ 1; CHANGELOG entry present; eval #1 updated (`rg -c "gap" plugins/testing/skills/run-e2e/evals/evals.json` ≥ 1); markdownlint exit 0 on changed files; `/skill-quality:check run-e2e` PASS. ### Phase 3: confirm delegation touch-up [DONE] Files: `plugins/verification/skills/confirm/SKILL.md`, `plugins/verification/README.md` (only if wording drifts), `plugins/verification/CHANGELOG.md` (**patch** bump — wording touch-up). - Delegation section: acknowledge enriched run-e2e (subagent isolation + recording/session evidence tier + gap report); /verify stays named as the supplementary live-run path with unchanged presence gate. No structural change to stages or verdict machinery. - **Sanity Check:** `rg -c "gap report|recording" plugins/verification/skills/confirm/SKILL.md` ≥ 1; stage structure unchanged (`rg -c "Stage" plugins/verification/skills/confirm/SKILL.md` equal before/after); markdownlint exit 0. ### Phase 4: routines.md thin-pointer clause [DONE] Files: `plugins/autonomy/reference/routines.md`, `plugins/autonomy/CHANGELOG.md` (**minor** bump — new normative clause). - New subsection, phrased to honor the doc's hosting-agnosticism (reviewer risk #7): the NORMATIVE clause is surface-agnostic — "a routine's instruction content lives in a version-controlled, reviewable artifact; the stored prompt is a thin pointer to it; pasted-prose prompts are non-compliant (no history, invisible drift)". The surface-specific mappings (cloud routines → committed `.claude/skills/`, documented transfer path; Desktop scheduled tasks → `~/.claude/scheduled-tasks/<task>/SKILL.md` under dotfiles) appear only as ILLUSTRATIVE binding examples, marked as deployment-owned bindings per the doc's own Hosting stance. Cite research (`routines-versioning-deep-dive.md`: native prompt versioning documented-absent). If the clause reads better in `wiring-vs-advisor.md` at build time, the builder flags it back to the main thread rather than deciding — placement objection is the known review risk. - **Sanity Check:** `rg -c "thin pointer|version-controlled" plugins/autonomy/reference/routines.md` ≥ 2; agnosticism preserved: `rg -c "deployment-owned" plugins/autonomy/reference/routines.md` count increases by ≥1; markdownlint exit 0; CHANGELOG entry present. ### Phase 5: digest-slice deferred items + through-line [DONE] Files (home slice, not repo): `~/.work/youtube-watch/the-4-levels-of-agentic-coding-how-to-sh-XLA-sTSJ-Wc/recommendations/menu.md`, `README.md` (same slice). - Update menu items to final dispositions (adopted → PR refs; deferred → named triggers; no-go unchanged). Add through-line note: Boris doc → interview locks → PLAN → PRs. - **Sanity Check:** `rg -c "deferred" menu.md` ≥ 3; each adopted item carries a PR/branch reference. ### Phase 6: dotfiles tracking proposal [TODO — user gate] - Run the dotfiles repo's `add-dotfile` flow for `~/.claude/scheduled-tasks/` (dir exists with live `autonomy-demo-hourly-drain/`). Flow owns chezmoi mechanics; never `chezmoi apply` from agent context. - **Sanity Check:** dotfiles repo PR/branch exists containing the scheduled-tasks source state, or an explicit operator decline recorded in PLAN. - **User gate:** surfaces before executing (cross-repo write). ### Phase 7: verify + ship [TODO] - Empirical verification in worktree: markdownlint sweep, typos gate, `/skill-quality:check` per touched skill, eval validation. - Version bumps via Edit on the version line (biome retab gotcha). - Conventional commits; PR(s) with PLAN.md in `<details>`; codex threads resolved before merge; close-out per `/planning:plan close-out` (slice prune + pointer). - **Sanity Check:** CI green on PR; `gh pr view` shows mergeable; all phase tags [DONE]. ### Phase 8: trial run (post-merge validation) [TODO] - After plugins update, run the enriched flow end-to-end on a real UI change in a consumer repo: config surface resolved + reported, recording produced per key, gap report exercised (remove a prereq deliberately), evidence table carries session artifacts. - **Sanity Check:** recording artifact exists on disk; gap report emitted on induced prereq failure; operator reviews the recording. ## Blast radius LOW-MEDIUM. Markdown skill/contract text + one new additive config surface; zero runtime code; three plugins touched; consumers unaffected by default (recording defaults off, browser_mode default preserves current behavior). Cross-repo edge: dotfiles proposal (user-gated). ## Stress-test summary Fresh-context plan-reviewer ran against live repo. 3 CONFIRMED-GAPs folded: (1) phantom config surface — read-path resolution + executor plumbing now mandated in P2 with sanity greps; (2) Implementers-table row added to P2 files; (3) CHANGELOG entries added to P2/P3/P4 with SemVer magnitudes (testing minor, verification patch, autonomy minor). Risks addressed: key-ownership boundary framed policy-vs-mechanics in e2e-config.md; routines.md clause re-phrased surface-agnostic with bindings as illustrative examples; eval #1 update made unconditional. Collision re-verified clean (no open PR overlap). Formal /devils-advocate skipped: blast radius LOW-MEDIUM, no infra/CI/dependency triggers. ## Execution shape Wave A (parallel, file-disjoint, one worktree, agents never touch git): | Phase | Surface | Basis | |---|---|---| | 2 run-e2e | Opus builder subagent | mechanical doc edits, largest item | | 3 confirm | Opus builder subagent | small disjoint edit | | 4 routines | Opus builder subagent | small disjoint edit | Wave B (sequential, main thread): 5 (home slice), 6 (user-gated cross-repo), 7 (verify + ship — main thread only, empirical checks + git). Phase 1 precedes all. Scope fences: each builder gets an ALLOWED list = its phase's files; FORBIDDEN = PLAN.md, other phases' files, any git command. Cost: 3 builders vs sequential saves modest wall-clock; fallback = run 2→3→4 sequentially in main thread on any fence violation. ## Open questions None blocking — all interview-locked. ## Handoff to implementation ### User-approval gates - Phase 6 dotfiles add-dotfile run (cross-repo write). - Any mid-flight scope change to config-surface shape. ### Execution shape ([EXEC-SHAPE] tagged) - [EXEC-SHAPE] PLAN drafted in `.work/` first; materialized to `docs/topics/` inside the worktree at Phase 1 (avoids writing to the canonical checkout the primary session owns). - [EXEC-SHAPE] Wave A 3-builder parallel shape with scope fences as above; sequential fallback documented. - [EXEC-SHAPE] Single PR for phases 2–4 (one review surface, shared rationale) unless review load argues for a split at ship time. ### Mechanical work - Commit boundaries: Phase 1 (PLAN + design-resolution), one commit per phase 2–4, Phase 5 lives outside the repo (no commit), Phase 7 ship. - Verification checkpoints: markdownlint + typos + skill-quality per phase before its commit; empirical greps per Sanity Checks. - Sequential fallback: any fence violation → abandon parallel, re-run remaining phases in main thread. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QdCmaHa15bwUTh9sy7Rfdz --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…or a non-repo consuming directory (#1728) ## Summary `continue-in-background`'s dirty-tree gate opened by running `git status --porcelain -uall` in the consuming project. In a directory that is not a git repository — a session started in `$HOME`, say — that fails with `fatal: not a git repository` and the skill has no specified behavior. The gate specified clean, dirty, and linked-worktree; not "no repository at all". The gate now establishes repository status first with `git rev-parse --is-inside-work-tree`, and is exhaustive **by construction** rather than by enumeration: two results may leave the default, and everything else falls through to the conservative branch. | `rev-parse` result | Behavior | | --- | --- | | prints `true` | Inspect the tree with the existing `git status --porcelain -uall` gate, unchanged | | fails *specifically* with "not a git repository" | Launch. No uncommitted work to protect, and no worktree isolation to lose — outside a repository (absent a `WorktreeCreate` hook) background sessions write to the working directory directly. The launch report states that reading | | **anything else** | Tree state UNKNOWN, which is not clean → do NOT launch; same fallback as the dirty case | That third row is the load-bearing part, and it is why this is a little more than the issue's "one or two sentences" — not scope drift. A gate that fails open is worse than no gate. Reading a non-zero exit alone as "no repository" would put dubious-ownership, damaged-repository, and git-missing cases on the launch path — exactly where the tree is most likely dirty and least likely readable. The unknown default is deliberately wide and it catches a zero-exit case too (below). Also here: the context-gathering block's "treat any failure as an unknown value and carry on" is now scoped to itself. It colors the save-point and is not the gate; carrying that shrug — or that block's non-`-uall` `git status` output — into delivery step 1 would defeat the gate from a section that runs before it. ## Evidence **Gates** (run in the worktree against `origin/main`): - `check-skill` (the checker `scripts/check-changed-skills.sh` invokes): **PASS — 0 errors, 0 warnings**; 195/500 lines, all 4 base-ref trigger phrases preserved - `scripts/validate-plugin-contracts.mjs`: **pass** — 43 setup skills, 2123 plugin files - `scripts/check-changelog-parity.sh --check-bump origin/main`: **pass** — 0.17.16 → 0.17.17 patch bump paired with its `## [0.17.17]` entry - `markdownlint-cli2` on both changed markdown files: **0 errors** - `evals.json` validated against `plugins/skill-quality/reference/evals.schema.json`: **valid** **Harness claim verified against current docs.** The non-repo sentence asserts harness behavior, so it was checked against <https://code.claude.com/docs/en/agent-view> this session rather than from recall. That page states isolation is skipped when the working directory is not a git repository and no `WorktreeCreate` hook is configured, and that outside a repository sessions write to the working directory directly — which is what the new branch relies on, including the hook qualifier. **Non-vacuousness — stated honestly.** `evals.json` in this repo is declarative and model-graded; there is no runner that asserts, so the three added cases are not executed regression tests and are not presented as such. The discriminating argument is textual and checkable from the diff: an agent following the pre-change SKILL.md has no branch for #5 (it runs `git status --porcelain -uall` blind and hits `fatal: not a git repository`) and no branch at all for #6 or #7. - **#5 `non-repo-directory-launches`** — non-repo consuming directory → launches, states the non-repo reading, STOPS - **#6 `unknown-tree-state-does-not-launch`** — dubious-ownership failure → does NOT launch. This is the case that proves the gate does not fail open - **#7 `no-work-tree-despite-zero-exit-does-not-launch`** — bare repository, exit 0 printing `false` → does NOT launch ## Review Reviewed by a fresh-context reviewer with the rationale withheld. Two IMPORTANT findings, both fixed in `748ab3cb` before this PR: 1. **Unrouted fourth outcome.** `git rev-parse --is-inside-work-tree` exits **0** and prints `false` inside a bare repository or a `.git` directory — verified empirically by the reviewer. The original three-way enumeration left that state unspecified, which is the same defect class the issue reports. Fixed by inverting the structure to two specified results plus a default, and guarded by eval #7. 2. **Contradiction with the context block.** "Treat any failure as an unknown value and carry on" sat 50 lines above a gate that now reads a git failure the opposite way. Fixed by scoping that sentence to its own block and pointing at the gate as owning failure semantics. One finding was accepted and **not** fixed, as out of scope: the gate's pre-existing rationale that uncommitted changes "would NOT carry into the launched agent's edits" does not hold when a consumer sets `worktree.bgIsolation: "none"`, under which background sessions edit the working copy directly. The gate's decision stays conservative either way, so this is an inaccurate rationale rather than a hole — untouched by this PR and worth its own issue. Closes #929 ## Related - #924 — introduced the skill and this dirty-tree gate - #233 — origin design for the save-point/handoff engine the skill shares - #1687 — the `$`-expansion isolation constraint the context block's shape exists to satisfy; the new `git rev-parse --is-inside-work-tree` carries no `$`-expansion and sits in the body, not pre-compute --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ry removed Phase 8 of docs/topics/teach-skill-comparison/PLAN.md, closing the approved plan: - After-dogfood run executed by a fresh-context agent at 0.7.0 against the IDENTICAL baseline persona script (same learner turns, same scripted git-hooks misconception, same sanctioned plugin-data substitution -> dogfood/after/). The canary TEACH-CANARY-h3rpag-p8 was reported verbatim from SKILL.md line 12 — live working-tree reload proven — and is removed by this commit (grep count now 0). - Comparison written (memory slice: dogfood/ COMPARISON-BEFORE-AFTER.md beside the two runs, per the topic-docs convention; distilled verdict recorded in PLAN.md Phase 8): baseline defect findings F1-F13 RESOLVED with live evidence, F15 partially (exit-2 semantics witnessed; unset- creation path test-covered), strengths F14 preserved. Zero defensive external fetches (baseline: 2); mechanical deictic routing; harvest-first interview with no re-asked questions; platform-aware markdown fallback + open-offer skip honest on the headless host; Tier-0 grounding throughout. - Scoped per DA #7: rung 4 Documents, rung 2 userConfig, the HTML/splice/quiz branch, tier-1+ research, and Windows known- folder resolution remain mechanically covered (29-check test suite, evals 7-9, acknowledged Windows manual gap) — never claimed dogfood-proven. - Six minor new findings recorded as refinement candidates (none caused wrong behavior): rung-3 mode qualifier by inference, duplicate probe re-invocation, glossary promotion granularity, Tier-0 platform-claim boundary / egress-blocked tier-1 gap, unconditional assets/ in the layout diagram, next-focus persistence home. - PLAN.md Phase 8 tag advanced to [DONE] — all eight phases DONE. Sanity evidence: grep -c TEACH-CANARY SKILL.md = 0; dogfood/after/ holds transcript + findings + workspace; COMPARISON-BEFORE-AFTER.md exists with the per-finding table; markdownlint 0 issues; list-workspaces.test.sh PASS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SUiFZXmwMYiqKnQ4RM233y
…nt generator bug they exposed
Each verified against the code before acting.
Gitea README verb table called create-item, get-item, link-blocks and list-items
"scaffold — provider mapping to write". Per the README's own definition that means
the script still calls wit_gitea_unimplemented and exits 1. None of them does —
all four are real implementations with passing tests. The table was telling a
consumer that four core verbs do not work.
Label pagination in gitea/create-item.sh had no ceiling while every other
paginated loop in the adapter caps against WIT_GITEA_LIST_ITEMS_MAX. Capped —
but not by copying list-items' treatment, because the consequence differs: there,
truncation just returns fewer items; here, stopping early makes an unseen label
indistinguishable from a nonexistent one, and the next step tells the operator to
create a label that already exists. The ceiling therefore also qualifies that
message.
Conformance binding for basic auth baked auth_user to the literal
ci@example.invalid with no override, while host and scope are required from the
environment — so a generated basic-auth adapter would authenticate as the
placeholder against a real throwaway instance and 401 with nothing saying why. It
now takes the identity from the environment the same way.
Linear binding's scope comment said "e.g. owner/repo"; Linear's scope is
<workspace>/<TEAMKEY>. Fixed in the generated file and at the template that
propagates it, where it now shows the provider's own sample scope.
Two defects of my own, caught by generating a basic-auth adapter rather than
assuming the change was fine: SAMPLE_AUTH_EXTRA feeds BOTH the offline test
fixture (which needs a literal) and the conformance binding (which needs the jq
variable), so collapsing them emitted `$au` into the test's single-quoted JSON —
now two keys; and an apostrophe inside ${VAR:?word} is parsed as a quote by bash,
which broke the generated file's syntax.
That exercise also exposed a latent template bug worth its own note: the
generated test asserted a HARDCODED id number of 12, while the id comes from the
configurable api.sample_id. Both shipped specs happen to end in #12, so it never
showed — but any consumer with a different sample id got a failing test the moment
their adapter was generated, from a template that promises "every case here is
real and passes the moment the adapter is generated". Now derived from the id.
Verified both shapes: a #7 spec and a #12 spec each generate a passing test.
52/52 suites pass; portability, ShellCheck, markdownlint and check-skill clean.
Refs #2946, #2950, #2952.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CnzwTKoTa6xNY7iyEzMYpm
Summary
Adds a Local development loop section to
docs/MIGRATION-PLAYBOOK.md. The playbook covered first-publish validation (the migration gate's--plugin-dirstep) but had no guidance for iterating on an already-shipped plugin against a local clone — the gap surfaced while finalizing how a consumer (dotfiles) keeps its tracked marketplace registration stable.The new section documents the doc-verified loop:
claude --plugin-dir ./plugins/<name>loads the working copy; when the name matches an installed marketplace plugin, the local copy takes session precedence (no uninstall needed)./reload-pluginspicks up on-disk changes without a restart (reloads skills, agents, hooks, MCP/LSP).extraKnownMarketplaces— the published remote registration stays put. Exception: cannot override a plugin force-enabled/disabled by managed settings./plugin marketplace update.Verification
Verified 2026-06-24 firsthand against the official Create plugins guide ("Test your plugins locally" / quickstart), per this repo's fresh-docs mandate. No new external links introduced (link-checker safe); MD013 is disabled so prose wraps freely.
🤖 Generated with Claude Code