llm-security cut v7.8.0 (TRG/SIG/AST deep-scan scanners) and tagged `v7.8.0`
(commit 6d3c4b5) in its repo. Sync the marketplace coordinator:
- .claude-plugin/marketplace.json: source.ref v7.7.2 → v7.8.0 (installs track the
real release; version-consistency gate → OK for llm-security).
- README.md: version label v7.7.2 → v7.8.0; scanner count 23 → 26 (+3: TRG/SIG/AST)
in both the "Deterministic scanning" bullet and the stat line; tests 1822 → 1863.
- docs/state-version-rollout.md: mark llm-security STATE.md row DONE (it is tracked,
not gitignored), add the missing playground-design-system row, and refresh the
Workstream B run note (8 OK / 2 WARN; llm-security resolved this day).
Gate: `node scripts/check-versions.mjs` → 8 OK, 2 WARN (linkedin-studio,
ms-ai-architect — pre-existing, operator decision), 0 ERROR.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3s6WnubSSrFjAQTLQdVbG
Marketplace-wide coordination brief in catalog/docs/. Two cross-cutting workstreams:
(A) STATE.md tracked in every repo per the updated global continuity rule —
verified status: 2 DONE (config-audit, ms-ai-architect), 3 avgitignore+track
(voyage, linkedin-studio, claude-design), 6 avgitignore-only; per-repo steps +
testable verification. (B) version-consistency via check-versions.mjs — 8 OK,
2 WARN (linkedin-studio, ms-ai-architect: plugin.json ahead of an untagged ref),
each needing an operator release-intent decision. Plan only — execution is per
repo with its own GO.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ter3E2JSi1Khgmuf2kady8
Forgejo rate-limits rapid port-22 handshakes. The bare per-target
`git push --all` + `git push --tags` opened ~22 SSH connections in rapid
succession; the server refused around the 6th (voyage's tag push) with
"port 22: Connection refused" (TCP-level, not auth), deterministically, on
every run. Export GIT_SSH_COMMAND with ControlMaster/ControlPath/ControlPersist
so all git-over-SSH reuses ONE persistent master connection (one TCP handshake
for the whole rollout).
Verified: 8 rapid multiplexed connections all succeed where the 6th bare
connection is refused; the full 11-target rollout then completed clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The operator window's step [a] called 40-validate-standalone.sh directly (strict
exit-code), so it STOPped on the first target carrying pre-existing in-repo test
red — voyage (2 doc-consistency drifts re phase_models/phase_signals, content moved
to docs/operations.md) and ai-psychosis (1). But the migration's ratified contract,
the one the Step-11 dry-run validated as PASS 11/11, is 'introduce no regression':
pre-existing in-repo red is the plugin's own concern, not a migration regression.
The window enforced a STRICTER gate than the contract the dry-run signed off.
Fix: new 41-validate-or-regression.sh — the single per-target gate the window calls
in [a]. It runs 40 strict, then on failure passes iff the standalone failing-test
NAME set is a SUBSET of the live in-repo set (the exact decision 99-dryrun.sh makes),
reusing sc2-regression.sh. A genuine extraction-introduced regression still STOPs the
window; a structure-validator fail and the config-audit gate stay strict.
Single-source the failing-name capture: extract capture_fails into capture-fails.sh
(mirrors the sc2-regression.sh extraction) so the live gate and the dry-run agree on
what 'failing' means; 99-dryrun.sh now delegates to it (behaviour identical).
Verified end-to-end on the real extracts: 40 strict fails voyage+ai-psychosis while
41 passes them 'N pre-existing, regression-relative'; clean targets (llm-security,
graceful-handoff) still pass via the strict path. New hermetic tests: capture-fails
3/3, 41 6/6 (strict-pass, regression-relative-pass, genuine-regression-fail,
structure-not-eligible, gate pass/fail). RUNBOOK per-repo step updated to 41.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pilot died at line 93 with 'key<byte>: unbound variable': $key glued to
the U+2026 ellipsis let bash 5.3.9 read the multibyte byte as part of the name.
Braced to ${key}…; proven on /usr/local/bin/bash (repro + fixed form + bash -n).
Nothing was mutated on Forgejo — it failed before the [b] repo-create POST.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review of the rollout script found 2 deterministic blockers on target #2,
playground-design-system — a shared component, not a marketplace plugin:
- step (d): DS has no .claude-plugin/plugin.json (it ships tokens.css/base.css/
schemas). The plugin.json assertion would die. Now DS-aware: assert tokens.css
for DS_KEY, plugin.json otherwise.
- step (e): 60-rewrite --only playground-design-system errors (--only name not in
marketplace.json) since DS has no catalog entry. New entry_present() gate skips
the flip when the key has no marketplace entry, mirroring 60-rewrite --all
(which only touches the 10 real plugins).
Net: pilot + 9 plugins flip (count_local to 0); DS is stood up as a repo but
never flipped. Verified: bash -n OK, entry_present + 60-rewrite behaviour tested.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-review scope a44e37b..85a8ee3. BLOCK (1+6+3) → WARN (2 new MAJOR surfaced in
30-fix-references.mjs) → ALLOW (both remediated, re-verified by the independent
code-correctness reviewer). 0 BLOCKER / 0 MAJOR / 0 MINOR / 0 SUGGESTION.
Operator window (RUNBOOK.md) no longer gated by a review BLOCK.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The /trekreview re-review's high-effort deep read of 30-fix-references.mjs
surfaced 2 MAJOR (both pre-existing in the original delivery, not remediation
regressions):
- PLAN_EXECUTE_DRIFT: the rewriter set repository.url but left a monorepo-relative
repository.directory (e.g. llm-security's plugins/llm-security) intact, so the
standalone package.json/plugin.json shipped a directory pointing nowhere. Now
dropped in BOTH the plugin.json (3a) and package.json (3b) object branches;
idempotency preserved (gated on 'directory' in repository).
- MISSING_TEST: the package.json rewrite branch only ran against voyage/llm-security
but the only test used graceful-handoff (no package.json) — unguarded. Added a test
driving both branches against a synthetic llm-security extract (pre-init .git,
fixtures carrying repository.directory), asserting reconciliation + directory-drop
on both files + idempotency.
Independent code-correctness reviewer re-verified both RESOLVED, no new issue.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MAJOR
- 9e97cd5 40-validate-standalone.sh: route a target's sc2_gate to its dedicated
gate (config-audit → 50-config-audit-sc2.sh), mirroring 99-dryrun.sh, so --all
no longer falsely FAILs config-audit on the machine-locked v5.0.0 tests.
- 1708e90 99-dryrun.sh: assert EXACTLY one tag survives (F5); a partial tag-strip
no longer silently reports the wrong tag via head -1.
- 4e494c8 99-dryrun.sh: capture the SC2 standalone failing set from the dry-run's
own prepped extract ($dest), not the 40-validate side-effect clean room.
- aeb6292 00-preflight.sh: assert every map path is whitespace/glob-free, making
the word-split path handling in 99-dryrun.sh sound.
- 5d112cb extract the SC6 DROP + SC2 regression detectors into sc6-check.sh /
sc2-regression.sh and add sc-checks.test.mjs — a negative test proving each
detector FIRES (force-fresh re-extraction would undo a planted file-drop).
- 9e588ca 10-extract.sh re-asserts git filter-repo before use (self-heal runs
preflight only on a missing mirror); RUNBOOK lists git-filter-repo + python3>=3.6.
MINOR
- bc0f8a7 plugin-map.json: reset ms-ai-architect blob_strip_safe to null
(00-preflight.sh populates it per run).
- 8d649e9 99-dryrun.sh: gate SC6 behind extract success; a failed extract is
labelled (extract failed), not a content DROP.
- 4044c49 99-dryrun.sh: guard mktemp — an empty capture is an error, not a
false zero-regression PASS.
Also: 00-preflight.test.mjs asserted all 3 'renamed' plugins carry >=2 paths, but
llm-security became single-path in 836b8e9 (copilot was a coexisting plugin, not a
rename) — a stale pre-existing failure. Aligned the test to the ratified map and
added a positive single-path lock against re-introducing the 87-file-drop defect.
Verified: full dry-run 11/11, 0 pushes; sc-checks/99-dryrun/40-validate/00-preflight/
60-rewrite suites green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
60-rewrite-marketplace.mjs:87 emitted a flat { source: 'url', url, ref }
shape. The official Claude Code marketplace schema (verified at
code.claude.com/docs/en/plugin-marketplaces) and brief §6 both require the
nested form { source: { source: 'url', url, ref } } — a flat shape would not
resolve at install, breaking SC1/SC3/SC8 for every externalised entry.
- l.87: emit nested source-object
- validate(): branch on object (external) vs string (local ./plugins/) source
- 60-rewrite-marketplace.test.mjs: assert nested voyage.source.source / .url / .ref
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
RUNBOOK.md: the single doc the operator follows in the authorized window. Pilot gate on graceful-handoff with the B3 ordering fix (flip the catalog entry to external BEFORE the install-smoke, else the Forgejo/HTTPS/ref chain is untested). Forgejo repo creation via API (auto_init:false, public), per-repo create->push->flip->install-smoke loop, batch order (design-system -> high-churn -> low-churn), thin-catalog last, ref-update flow, and a reversible-until-thinning rollback. References the prior scripts; push-window-aware.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
70-thin-catalog.sh: renders the thin-catalog end-state into --workspace (never the live tree). git-archive HEAD -> remove plugins/ + shared/ + scripts/sync-design-system.mjs(+test) -> extract CLAUDE.md conventions into CONVENTIONS.md (D6) -> thin the catalog CLAUDE.md -> rewrite README.md with external Forgejo repo links and versions re-stated from plugin-map.json (M15 coupled to the D6 rewrite).
Verify: workspace has no plugins/ or shared/, CONVENTIONS.md present; rewritten README has 0 local links and corrects the stale playground-design-system v0.1 -> v0.6.0. Test 4/4.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
60-rewrite-marketplace.mjs: flips a named subset (--only) or all (--all) plugin entries from local './plugins/<name>' to external {source:'url', url, ref:v<version>} read from plugin-map.json. Validates output (name+source+description; external => https url under Forgejo /open/ + ref). Writes to a required --out path only — never the live .claude-plugin/marketplace.json (D8). Enables the mixed-source live states (SC3/SC8).
Verify: --only voyage => 9 local + 1 external (https + ref:v5.1.1), 0 ssh. Test 4/4 (mixed-source, --all all-external, refuses --out-less run, rejects unknown name).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
50-config-audit-sc2.sh: re-seeds snapshot-default-output in-clone (UPDATE_SNAPSHOT=1), then runs the SC2 gate = full 'find tests -name *.test.mjs' MINUS the 6-file machine-locked v5.0.0 byte-stability surface. 730 tests across 46 files pass standalone.
templates/validate-plugin.generic.sh: ported, parameterized structure validator for the two test-less plugins (okr, human-friendly-style) — STRUCTURE OK on valid plugin.json + non-empty surface + parseable frontmatter; STRUCTURE FAIL otherwise. Reuses the claude-design/tests/validate-plugin.sh pattern.
Brief-correction (operator-ratified 2026-06-17): plan F4 named only json-backcompat + raw-backcompat (2 files). The verified machine-locked surface is 6 — the v5.0.0 fixtures embed the original absolute path AND the claude_md/plugin_hygiene scanners key off a plugins/ ancestor, so findings drift by path (behavioral, not a string rewrite). Dropped clean-room SC2 coverage = config-audit's humanizer/posture-humanizer/scan-orchestrator-humanizer prose-snapshot surface, recorded in the script header + plugin-map.json (not silent). The 3 other v5.0.0-referencing tests (posture, scoring-humanizer, scenario-read-test) are path-independent and stay in the gate. config-audit backlog (out of migration scope): normalize the v5.0.0 fixtures + path-agnostic scanners, then re-include.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Plan for splitting the monorepo into per-plugin Forgejo repos + a DS repo
+ a thin catalog. Built from the ratified brief via /trekplan: 6-agent
exploration verified the brief and surfaced 6 under-scoped findings
(F1-F6: plugin renames, ssh->https, 148MB blob bloat, config-audit
snapshot path-coupling, tag namespace, README link rot). plan-critic
REVISE on first draft (3 blockers + 8 majors) all addressed after
re-verifying contested facts; scope-guardian ALIGNED. Local Claude half
(Steps 1-11) is fully reversible NULL-push; operator window is a separate
runbook. Held unpushed per D8.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Flip status DRAFT -> RATIFIED. All eight decision blocks ratified as
recommended on 2026-06-17:
- D1 bare slug open/<plugin>
- D2 filter-repo preserve on a fresh clone + pre-polyrepo-archive tag
- D3 own DS repo, consumers keep vendoring
- D4 tag-pin (ref vX.Y.Z)
- D5 DS first -> high-churn -> low-churn -> thin catalog last
- D6 catalog keeps json/README/GOVERNANCE/conventions; shared+sync leave
- D7 per-repo .gitignore re-rooted; local state stays uncommitted
- D8 no push until one authorized weekend window
Next: /trekplan --brief in a fresh session at repo root.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>