docs(plan): v5.4.0 Session A — reconciliation + ship-list GO (Option A) [skip-docs]
Re-verified the 6 deferred v5.4 candidates against HEAD on two axes (code-state + CC premise, primary-source where risky). Operator GO "Option A": ship #1 PLH shadow-folder + #5 PLH skills:-array + #4 autoMode structure/dead-config; no new scanner (badge stays 13). #2 acceptEdits-writes + #6 nested-.claude deferred; #3 Read-deny/Glob-Grep WONTFIX — premise refuted by code.claude.com/docs (Read deny already covers Glob/Grep), matrix row 175 was framed backwards and is now fixed. - New: docs/v5.4.0-release-plan.md (Session A→C, mirrors v5.3.0 structure) - Updated: docs/cc-2.1.x-gap-matrix.md (## v5.4.0 reconciliation block + row-175 fix) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ter3E2JSi1Khgmuf2kady8
This commit is contained in:
parent
fe686b6594
commit
c6992cad57
2 changed files with 266 additions and 0 deletions
|
|
@ -10,6 +10,34 @@
|
|||
> `.mcp.json`-dokumentasjon FØR endring — agenten kan ta feil i begge retninger. Manuelt forhåndsverifisert av
|
||||
> hovedkontekst: `xhigh` (settings-validator.mjs:66), manglende hook-events, 4.7-hardkoding, feature-evolution v2.1.111.
|
||||
|
||||
## v5.4.0 reconciliation (2026-06-19 — supersedes the v5.3.0 block + rows below)
|
||||
|
||||
The six M-effort candidates deferred at v5.3.0 were re-verified against HEAD (`fe686b6`) on both
|
||||
axes: **code-state** (still open?) and **CC premise** (real? — primary-source where risky).
|
||||
See `docs/v5.4.0-release-plan.md` for the full per-candidate evidence.
|
||||
|
||||
**Operator GO 2026-06-19: "Option A"** → ship #1, #5, #4. No new scanner (badge stays 13).
|
||||
|
||||
| # | Candidate (row) | Code-state @HEAD | CC premise | Verdict |
|
||||
|---|---|---|---|---|
|
||||
| 1 | PLH shadow-folder (164) | OPEN (parses only name/desc/version) | CONFIRMED ~2.1.140 | **ship-5.4** → `CA-PLH-015` |
|
||||
| 5 | PLH `skills:`-array dirs (165) | OPEN (no `parsed.skills` read) | CONFIRMED ~2.1.145 `plugin validate` | **ship-5.4** → `CA-PLH-016` |
|
||||
| 4 | autoMode.hard_deny structure (179) | OPEN (key known, no nested val) | CONFIRMED (primary source) | **ship-5.4** → `CA-SET-NNN` |
|
||||
| 2 | acceptEdits-writes shell/build (176) | OPEN (0 matches) | CONFIRMED ~2.1.160, file-list unpinned | **defer** (needs primary-source field list) |
|
||||
| 6 | nested-.claude closest-wins (139/166) | OPEN (no scanner) | CONFIRMED ~2.1.178 | **defer** (NEW scanner, badge bump → own release) |
|
||||
| 3 | Read-deny hides Glob/Grep (175) | PARTIAL (`permission-rules.mjs:158-159` hint only) | **REFUTED** by primary source | **wontfix** |
|
||||
|
||||
**Row 175 correction (Verifiseringsplikt).** The row was framed **backwards**. The CC permissions
|
||||
doc states: *"Claude makes a best-effort attempt to apply `Read` rules to all built-in tools that
|
||||
read files like Grep and Glob"* — so a Read deny **already** covers Glob/Grep. A "Read-deny is
|
||||
bypassable → false security" finding would be a false positive (same failure mode as the invented
|
||||
MCP `trust` field). The only real Read-deny bypass is a Bash subprocess (python/node script that
|
||||
opens files itself), which is documented behavior, not a config mistake. The Windows-path half (CC
|
||||
normalizes `C:\…` → `/c/…` before matching) is real but narrow/low-value → rolling maintenance.
|
||||
|
||||
The L-priority `update-knowledge` rows (env vars, model nuance, hook-output fields, plugin/skill
|
||||
doc, nested-.claude doc) remain rolling knowledge maintenance — fold in opportunistically.
|
||||
|
||||
## v5.3.0 reconciliation (2026-06-19 — supersedes stale rows below)
|
||||
|
||||
This matrix was the **v5.2.0** plan. Verified against HEAD (`9b828fa`) during the v5.3.0 Session A
|
||||
|
|
|
|||
238
docs/v5.4.0-release-plan.md
Normal file
238
docs/v5.4.0-release-plan.md
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
# v5.4.0 Release — Multi-Session Plan
|
||||
|
||||
_Status: PLANNED. No version bump yet. `plugin.json` = 5.3.0. All work below is gated on
|
||||
explicit operator GO per session. Plans live next to STATE per the continuity system.
|
||||
Mirrors the structure of `docs/v5.3.0-release-plan.md`._
|
||||
|
||||
## Goal
|
||||
|
||||
Release **v5.4.0** (minor, backward-compatible): three **net-new additive scanner findings**
|
||||
that extend the plugin-hygiene (PLH) and settings (SET) surfaces, mirroring real Claude Code
|
||||
warnings/validation that config-audit does not yet detect. Unlike v5.3.0 (which documented work
|
||||
already on `main`), **the features here do not exist yet** — Session B is the core build, not a
|
||||
conditional. No bugs/false-positives are involved; all three are enhancements with confirmed CC
|
||||
premises.
|
||||
|
||||
**Theme:** *plugin-hygiene & settings-validation hardening.*
|
||||
|
||||
## Pre-verified facts (do NOT re-derive)
|
||||
|
||||
- Last release: **v5.3.0** = commit `fe686b6`, tag `v5.3.0`, 2026-06-19. `git rev-list --count
|
||||
v5.3.0..HEAD` = **0** → working tree is at the tag; v5.4.0 builds net-new code.
|
||||
- Suite at HEAD: **936/936** (clean tree, unchanged since the v5.3.0 release). self-audit at
|
||||
v5.3.0: configGrade A 97, pluginGrade A 100, readmeCheck.passed.
|
||||
- **Scanner count = 13** (authoritative source `countScannerShape`, `scanners/self-audit.mjs:56`;
|
||||
README badge `scanners-13`). All three approved features **extend existing scanners** (PLH, SET)
|
||||
— **no new scanner file**, so the badge, the scanner table, and `countScannerShape` need **no
|
||||
change**. (An early grep of `export async function scan` counted 15 shapes — that set includes
|
||||
lib/non-badge shapes like CNF/IMP/SAL and is NOT the badge count. Do not bump the badge.)
|
||||
- PLH currently emits `CA-PLH-001`..`CA-PLH-014` (014 = namespace collision, 013 = command-name
|
||||
ambiguity, both shipped v5.3.0). Next free: `CA-PLH-015`, `CA-PLH-016`.
|
||||
- Edit-target files (v5.3.0 release pattern): `.claude-plugin/plugin.json`, `README.md`
|
||||
(badges + What's New + version-history row + TOC), `CHANGELOG.md` (`## [5.4.0]` above `[5.3.0]`),
|
||||
`docs/cc-2.1.x-gap-matrix.md`, the two target scanners, their tests, and 3 knowledge entries.
|
||||
- **CC premises primary-source verified** (code.claude.com/docs, 2026-06-19) — see Session A
|
||||
reconciliation. The matrix is NOT ground truth; row 175 was found to be framed backwards.
|
||||
|
||||
---
|
||||
|
||||
## Session A — Reconciliation & scope decision (read/plan; this session) ✅ DONE
|
||||
|
||||
**No code changes.** Re-reconcile the gap-matrix against HEAD, verify each candidate is still open
|
||||
AND that its CC premise is real, classify ship/defer/wontfix, get operator GO on the ship-list,
|
||||
draft the changelog. Output recorded below + a `## v5.4.0 reconciliation` block appended to
|
||||
`docs/cc-2.1.x-gap-matrix.md`.
|
||||
|
||||
**Verifisering (testbar):**
|
||||
- Every v5.4 candidate has a recorded code-state verdict (IMPLEMENTED/OPEN/PARTIAL) with file:line.
|
||||
- Every candidate has a CC-premise verdict (CONFIRMED/REFUTED/UNVERIFIABLE) with a source.
|
||||
- Ship-list has a recorded operator GO before any build. ✅
|
||||
- The refuted premise (#3) is corrected in the gap-matrix. ✅
|
||||
|
||||
---
|
||||
|
||||
## Session B — Implement the 3 approved features (CORE build)
|
||||
|
||||
**One feature per chunk. Iron Law: failing test FIRST (/tdd), then minimal implementation.**
|
||||
Re-confirm each feature's exact CC behavior against primary docs at the start of its chunk
|
||||
(Verifiseringsplikt — premises were verified in Session A but the exact field lists / warning text
|
||||
must be pinned before coding). Checkpoint STATE + this plan after each feature.
|
||||
|
||||
### Feature 1 — PLH shadow-folder (`CA-PLH-015`)
|
||||
- **What:** flag when a `plugin.json` component-path key (`commands`/`agents`/`skills`/`hooks`)
|
||||
points at a **custom path** while the **default folder of that name also exists** in the plugin,
|
||||
so one silently shadows the other. Mirrors CC's warning in `/doctor` & `claude plugin list`
|
||||
(introduced ~2.1.140; 2.1.142 names every conflicting key).
|
||||
- **Where:** `scanners/plugin-health-scanner.mjs` (per-plugin loop; the scanner already reads
|
||||
`plugin.json` but only checks `name`/`description`/`version`). Add component-path-key parsing.
|
||||
- **Severity:** MEDIUM — silently-shadowed components = dead config (a whole command/skill/agent
|
||||
set goes unreachable). `category: 'plugin-hygiene'`.
|
||||
- **Tests:** fixture plugin with both `"commands": "custom/"` AND a `commands/` folder → flagged;
|
||||
fixture with only one of the two → not flagged; fixture with no component keys → not flagged.
|
||||
|
||||
### Feature 2 — PLH `skills:`-array validation (`CA-PLH-016`)
|
||||
- **What:** when `plugin.json` has a `skills:` array, validate each entry resolves to an existing
|
||||
**directory inside the plugin root**. Flag: non-string entry, missing path, path that is a file
|
||||
not a directory, path escaping the plugin root. Mirrors `claude plugin validate` (~2.1.145; the
|
||||
CC error suggests the parent directory when an entry points at a file).
|
||||
- **Where:** `scanners/plugin-health-scanner.mjs` (read `parsed.skills` after the parse-success
|
||||
guard).
|
||||
- **Severity:** MEDIUM (broken/partly-broken plugin manifest). `category: 'plugin-hygiene'`.
|
||||
- **Tests:** fixture `skills: ["valid-dir", "points-to-file.md", "missing", "../escape"]` → one
|
||||
finding per bad entry, none for `valid-dir`; fixture with no `skills:` key → not flagged.
|
||||
|
||||
### Feature 3 — SET autoMode structure + dead-config (`CA-SET-NNN`)
|
||||
- **What (two sub-checks):**
|
||||
1. **Structure validation** — `autoMode`, if present, must be an object whose only keys are
|
||||
`environment`, `allow`, `soft_deny`, `hard_deny`, each a **string array** (entries are prose
|
||||
rules; `"$defaults"` is a valid literal). Flag unknown sub-keys and wrong value types.
|
||||
2. **Dead-config** — `autoMode` placed in **shared project settings** (`.claude/settings.json`)
|
||||
is **ignored by CC** ("Not read from shared project settings" — official docs). Flag it as
|
||||
dead config; valid scopes are user (`~/.claude/settings.json`), local
|
||||
(`.claude/settings.local.json`), and managed.
|
||||
- **Where:** `scanners/settings-validator.mjs` (`autoMode` is already in `KNOWN_KEYS:21` but has no
|
||||
TYPE_CHECKS / nested validation). The dead-config sub-check needs the settings file's **scope**;
|
||||
confirm the scanner already knows per-file scope (it validates user/project/local files).
|
||||
- **Severity:** structure = LOW/MEDIUM (malformed config); dead-config = LOW (dead config).
|
||||
- **Tests:** valid autoMode in user settings → clean; unknown sub-key / non-array value → flagged;
|
||||
autoMode in shared `.claude/settings.json` → dead-config finding.
|
||||
|
||||
**Per-feature gates (all must pass before that feature's commit):**
|
||||
- New tests RED→GREEN; full suite N/N green.
|
||||
- `node scanners/self-audit.mjs --json --check-readme` → configGrade ≥ A, pluginGrade ≥ A,
|
||||
readmeCheck.passed, scanner count still 13.
|
||||
- Any snapshot/fixture touch → SC-5 re-seed + contamination-grep clean; gitleaks clean.
|
||||
- **docs-gate** (`feat:` commits): README **and** CLAUDE.md each get ≥3 substantive lines
|
||||
documenting the new finding — OR `[skip-docs]`. Prefer real docs (each finding deserves a
|
||||
CLAUDE.md "Scanner" note + README mention). Stage docs in a separate Bash call before commit.
|
||||
- Humanizer: each new finding needs a `userImpactCategory` mapping (dead config / conflict /
|
||||
configuration mistake) — verify `--json`/`--raw` stay byte-stable for *existing* findings
|
||||
(`json-backcompat` + `raw-backcompat` green); new findings are additive.
|
||||
|
||||
**Scanner count stays 13.** No badge/table/`countScannerShape` change (no new scanner file).
|
||||
|
||||
---
|
||||
|
||||
## Session C — Release v5.4.0 (version sync + docs + tag + push)
|
||||
|
||||
1. **Bump** `.claude-plugin/plugin.json` 5.3.0 → 5.4.0. (Version lives ONLY here.)
|
||||
2. **README:** `version-` badge → 5.4.0; `tests-` badge → exact suite count after Session B
|
||||
(will rise — new tests added). Replace "What's New in v5.3.0" → **v5.4.0** (+ TOC anchor).
|
||||
Insert a new version-history row above `**5.3.0**`. **Scanner count stays 13.**
|
||||
3. **CHANGELOG.md:** insert `## [5.4.0] - <date>` above `## [5.3.0]` (Added / Test count /
|
||||
Verification — mirror the 5.3.0 block; this release is Added-only + Internal if any).
|
||||
4. **Knowledge:** apply the 3 backing entries (list below).
|
||||
5. **Marketplace cross-repo (`../catalog/`, separate repo):** bump the config-audit `ref`/version
|
||||
in `marketplace.json` + README **after** the plugin tag is pushed. Same push-window rules,
|
||||
separate push. **Cross-repo edit requires operator GO.**
|
||||
6. **Gates:** suite N/N; self-audit configGrade A, pluginGrade A, readmeCheck.passed, count 13;
|
||||
SC-5 byte-equal or re-seeded + contamination-grep clean; gitleaks clean (both repos).
|
||||
7. **Commit** `release: v5.4.0 — <one-line>`, **tag** `v5.4.0`, **push** (in push window).
|
||||
|
||||
**Verifisering (testbar):** `git tag --list v5.4.0` returns it; README `version-` badge ==
|
||||
`plugin.json` version; `self-audit --check-readme` passed + badge tests == suite count;
|
||||
`git log -1` subject starts `release: v5.4.0`; marketplace entry shows 5.4.0.
|
||||
|
||||
---
|
||||
|
||||
## Key assumptions (test, don't trust)
|
||||
|
||||
- **5.4.0 is non-breaking.** Three additive findings; no envelope/JSON-shape change. Verify
|
||||
`json-backcompat` + `raw-backcompat` + SC-5 snapshot stay green; new findings appear only in
|
||||
configs that trigger them. If anything changes the JSON shape or existing-finding output → it is
|
||||
a Breaking note, not Added.
|
||||
- **settings-validator knows per-file scope.** Feature 3's dead-config sub-check needs to know a
|
||||
settings file is the *shared project* one. **Test this assumption first in Feature 3's chunk** —
|
||||
if the scanner doesn't already carry scope per file, either thread it through or drop the
|
||||
dead-config sub-check to structure-only (still ships).
|
||||
- **docs-gate blocks `feat:` commits** lacking ≥3 substantive lines in BOTH README and CLAUDE —
|
||||
proven 2026-06-19. (`release:`/`fix:`/`chore:`/`docs:` pass freely.)
|
||||
- **self-audit `--check-readme` is number-only** (badge vs filesystem) — it does NOT catch prose
|
||||
gaps. Manually eyeball the scanner table + "What's New" (the SKL-row gap slipped exactly here).
|
||||
|
||||
## Knowledge-touch list (Session C step 4)
|
||||
|
||||
Three short backing entries (mirrors v5.3.0's 3-entry pattern; grep-verify each is absent first):
|
||||
1. `knowledge/claude-code-capabilities.md` — plugin component-path keys shadow default folders;
|
||||
CC warns in `/doctor` & `claude plugin list` (~2.1.140/142). Backs `CA-PLH-015`.
|
||||
2. `knowledge/claude-code-capabilities.md` — `claude plugin validate` requires `skills:` entries to
|
||||
be directories (~2.1.145). Backs `CA-PLH-016`.
|
||||
3. `knowledge/claude-code-capabilities.md` *or* `configuration-best-practices.md` — `autoMode`
|
||||
schema (`environment`/`allow`/`soft_deny`/`hard_deny` string arrays, `"$defaults"` literal) and
|
||||
the "not read from shared project settings" rule. Backs `CA-SET` autoMode finding.
|
||||
|
||||
Everything else in the matrix (env-var rows, model-lineup nuance, hook-output fields, nested
|
||||
.claude doc) → **defer** to rolling knowledge maintenance.
|
||||
|
||||
## Out of scope (do not start without separate GO)
|
||||
|
||||
- **#2 acceptEdits-on-shell/build-config** (deferred — needs the exact CC special-cased file-category
|
||||
list primary-source-confirmed before it's buildable). Candidate for a later release.
|
||||
- **#6 nested-.claude closest-wins** (deferred — a NEW scanner: ancestor-chain walker + grouping +
|
||||
badge bump 13→14. Heaviest item; natural headline for its own release, e.g. v5.5.0).
|
||||
- **#3 Read-deny/Glob-Grep** — **wontfix** (premise refuted by primary source; see reconciliation).
|
||||
- Any scanner refactor not required by the 3 approved features; marketplace-wide changes beyond the
|
||||
config-audit catalog entry.
|
||||
|
||||
---
|
||||
|
||||
## v5.4.0 scope decision (Session A output, 2026-06-19)
|
||||
|
||||
### Operator GO (recorded verbatim)
|
||||
> **"Option A"** — ship #1 PLH shadow-folder + #5 PLH skills:-array + #4 autoMode structure/
|
||||
> dead-config. No new scanner (badge stays 13). #2 and #6 deferred, #3 wontfix.
|
||||
|
||||
**Ship-list (3 features):** `CA-PLH-015` shadow-folder · `CA-PLH-016` skills:-array · `CA-SET-NNN`
|
||||
autoMode structure + dead-config. All extend existing scanners.
|
||||
|
||||
### Reconciliation result (6 candidates vs HEAD, code-state + CC-premise)
|
||||
|
||||
| # | Candidate (matrix row) | Code-state @HEAD | CC premise | Verdict |
|
||||
|---|---|---|---|---|
|
||||
| 1 | PLH shadow-folder (164) | OPEN — `plugin-health-scanner` parses only name/desc/version | CONFIRMED (~2.1.140; `/doctor`+`plugin list` warning) | **ship-5.4** |
|
||||
| 5 | PLH `skills:`-array dirs (165) | OPEN — does not read `parsed.skills` | CONFIRMED (~2.1.145 `claude plugin validate`) | **ship-5.4** |
|
||||
| 4 | autoMode.hard_deny structure (179) | OPEN — key in `KNOWN_KEYS:21`, no TYPE_CHECKS/nested val | CONFIRMED (primary source: 4 string-array sub-keys; not read from shared project settings) | **ship-5.4** |
|
||||
| 2 | acceptEdits-writes shell/build (176) | OPEN — 0 matches in `scanners/` | CONFIRMED (~2.1.160) but exact file-category list unpinned | **defer** (needs primary-source field list) |
|
||||
| 6 | nested-.claude closest-wins (139/166) | OPEN — no scanner; CML walks only the CLAUDE.md cascade | CONFIRMED (~2.1.178) | **defer** (NEW scanner, badge bump) |
|
||||
| 3 | Read-deny hides Glob/Grep (175) | PARTIAL — hint in `permission-rules.mjs:158-159`, but `dominates()` treats Read/Glob/Grep as distinct | **REFUTED** — docs: "Claude makes a best-effort attempt to apply `Read` rules to … Grep and Glob"; Read-deny already covers them | **wontfix** |
|
||||
|
||||
**Matrix correction (Verifiseringsplikt):** row 175's framing was **backwards**. CC's permissions
|
||||
doc states Read deny rules already apply (best-effort) to Glob/Grep, so a "Read-deny is bypassable"
|
||||
finding would be a false positive — the same failure mode as the invented MCP `trust` field. The
|
||||
only real Read-deny bypass is via Bash subprocesses (a python/node script that opens files), which
|
||||
is already documented behavior, not a config mistake to flag. The Windows-path half (CC normalizes
|
||||
`C:\` → `/c/`) is real but narrow/low-value and is folded into "defer rolling maintenance".
|
||||
|
||||
### Draft CHANGELOG narrative (finalize after Session B)
|
||||
|
||||
**Added**
|
||||
- **PLH plugin-folder shadowing** (`CA-PLH-015`) — flags a `plugin.json` component-path key
|
||||
(`commands`/`agents`/`skills`/`hooks`) that points at a custom path while the default folder of
|
||||
that name also exists, so one silently shadows the other. Mirrors Claude Code's `/doctor` &
|
||||
`claude plugin list` warning. Severity **medium** (dead config), `category: 'plugin-hygiene'`.
|
||||
- **PLH `skills:`-array validation** (`CA-PLH-016`) — validates each entry in a `plugin.json`
|
||||
`skills:` array resolves to a directory inside the plugin; flags non-string entries, missing
|
||||
paths, file-not-directory, and path-escape. Mirrors `claude plugin validate`. Severity
|
||||
**medium**, `category: 'plugin-hygiene'`.
|
||||
- **SET autoMode structure + dead-config** (`CA-SET-NNN`) — validates `autoMode` contains only
|
||||
the four known sub-keys (`environment`/`allow`/`soft_deny`/`hard_deny`), each a string array,
|
||||
and flags `autoMode` placed in shared project settings (`.claude/settings.json`), which Claude
|
||||
Code ignores. Structure = low/medium, dead-config = low.
|
||||
|
||||
**Internal / Test count / Verification** — fill in Session C (mirror the 5.3.0 block).
|
||||
|
||||
Scanner count stays **13** (all extend existing PLH/SET scanners). `--json`/`--raw` byte-stable.
|
||||
|
||||
### What's New in v5.4.0 (draft prose)
|
||||
> **v5.4.0 — plugin-hygiene & settings-validation hardening.** Three additive findings extend the
|
||||
> plugin and settings surfaces: PLH now flags a plugin.json component-path key that silently shadows
|
||||
> the default folder of the same name (mirroring Claude Code's `/doctor` warning), and validates
|
||||
> that `skills:`-array entries resolve to real directories (mirroring `claude plugin validate`); the
|
||||
> settings validator now checks the structure of `autoMode` and flags it when placed in shared
|
||||
> project settings, where Claude Code ignores it. Scanner count stays **13** (all extend existing
|
||||
> scanners). `--json`/`--raw` remain byte-stable.
|
||||
|
||||
### Version & non-breaking confirmation
|
||||
- **5.4.0** (minor). Additive findings only; no envelope/JSON-shape change. `json-backcompat` +
|
||||
`raw-backcompat` + SC-5 snapshot green at HEAD; new findings are additive (appear only in configs
|
||||
that trigger them).
|
||||
Loading…
Add table
Add a link
Reference in a new issue