Closes the iteration loop: review.md → plan via source_findings audit trail.
Adds versioning row, validator-map entry, full Handover 6 section, and
stability summary row mirroring the shape of Handovers 1-5.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wave 1 / Step 3 of v5.1.0 plain-language UX humanizer.
scanners/lib/humanizer.mjs exports three pure functions:
- humanizeFinding(f) -> new finding object with translated
title/description/recommendation + three new fields
(userImpactCategory, userActionLanguage, relevanceContext).
- humanizeFindings(findings) -> mapped array.
- humanizeEnvelope(env) -> walks env.scanners[].findings.
Plus computeRelevanceContext(filePath) as a named export for
unit testing.
Field semantics:
- userImpactCategory: from scanner prefix per research/02 line 124
(Configuration mistake / Conflict / Wasted tokens / Dead config /
Missed opportunity / Other).
- userActionLanguage: from severity per research/02 line 134
(Fix this now / Fix soon / Fix when convenient / Optional cleanup
/ FYI).
- relevanceContext: deterministic file-path heuristic — looks for
/tests/fixtures/ or /test/fixtures/ substring (test-fixture-no-impact),
*.local.* basename (affects-this-machine-only), defaults to
affects-everyone. No subprocess, no network.
Lookup order per scanner: static[title] -> patterns regex match ->
_default -> fall through to original strings (when scanner prefix
absent).
Original id, scanner, severity, file, line, evidence, category,
autoFixable, and optional details are preserved exactly. Pure —
verified by deepEqual of input before/after.
Test (32 cases): purity, field preservation across all paths,
known/unknown scanner handling, all 5 severities, all 6 categories,
relevance heuristic for 4 path types, envelope walking, ANSI-free
guarantee. All pass.
Regression: 689/689 tests (657 + 32 new = 54 new across Wave 1).
Project: .claude/projects/2026-05-01-config-audit-ux-redesign/
Wave 1 / Step 2 of v5.1.0 plain-language UX humanizer.
scanners/lib/humanizer-data.mjs exports TRANSLATIONS keyed by
scanner prefix (CML, SET, HKV, RUL, MCP, IMP, CNF, GAP, TOK, CPS,
DIS, COL, PLH). Each scanner has:
- static: exact-title -> {title, description, recommendation}
- patterns: array of {regex, translation} for template-literal titles
- _default: graceful fallback for unknown findings
Architectural change vs. plan: keys translations by exact scanner
title (not finding ID). Reason: finding IDs are sequence-based
(global counter in lib/output.mjs:34), not stable per finding-type
— two runs can produce different IDs for the same logical issue.
Title strings ARE stable (defined as string literals or template
patterns in the scanner source).
Translations follow research/03 SR-1..SR-17:
- active voice, second person, present tense
- sentences <= 25 words
- tier1 absolute prohibitions and tier3 domain jargon are kept out
of prose
- tier1/tier3 terms are permitted inside `backtick spans` (code
references like filenames and field names) — established
technical-doc convention
Test (12 cases): all 13 scanners covered; every static and pattern
entry has the 3 required fields; tier1 and tier3 forbidden-word
checks pass (with backtick-span exclusion); reference-stable
imports. All pass.
Regression: 657/657 tests (645 + 12 new).
Project: .claude/projects/2026-05-01-config-audit-ux-redesign/
Wave 1 / Step 1 of v5.1.0 plain-language UX humanizer.
tests/lint-forbidden-words.json defines the SC-3 forbidden-words
vocabulary used by the lint runner (Wave 4 / Step 8) and the
humanizer-data translation guard (Wave 1 / Step 2).
- Tier 1: 19 absolute prohibitions (failure if matched in default
output) — sourced from Microsoft Writing Style Guide, Federal
Plain Language, GOV.UK, Google Developer Style, Apple HIG.
- Tier 2: 24 strong-avoidance terms (warning if matched) — same
sources plus Mailchimp.
- Tier 3: 12 domain-specific jargon terms (failure if matched in
default output, allowed in --raw and --json paths) — sourced
from research/03 jargon table.
Counts diverge from plan.md (18/21/11) — JSON tracks the brief's
verbatim lists at research/03 lines 200-202 plus tier3 hook entry
from the brief's table. Plan revision noted in audit-doc.
Test: 10 cases verifying parse, count, schema completeness, spot
checks per tier, no cross-tier duplicates. All pass.
Regression: 645/645 tests (635 + 10 new).
Project: .claude/projects/2026-05-01-config-audit-ux-redesign/
Wave 0 / Step 0 of the v5.1.0 plain-language UX humanizer plan.
Captures v5.0.0 baseline output for all 8 CLIs at
tests/snapshots/v5.0.0/ — these snapshots are immutable references
for SC-6 (--json byte-equal) and SC-7 (--raw byte-equal) tests in
later waves.
- 5 CLIs captured via --output-file: scan-orchestrator, posture,
token-hotspots-cli, manifest, whats-active
- 3 CLIs captured via stdout redirect (no --output-file support):
drift-cli (after baseline seed), fix-cli, plugin-health-scanner
- Posture stderr scorecard captured separately for SC-7 stderr-mode
comparison
docs/v5.1.0-test-audit.md classifies all 42 .title references in
7 known test files: 34 will break under humanization (literal
string equality / substring), 8 are safe (test fixtures or error
formatting). This document is the change list for Step 4.
Project: .claude/projects/2026-05-01-config-audit-ux-redesign/
These were committed in b37b938 by mistake — KTG's convention is that
planning docs in plugins/ultraplan-local/docs/ are local working files
and never pushed to the public marketplace.
- git rm --cached on both files (kept on disk, just untracked)
- .gitignore extended with explicit entries for the two filenames
Existing tracked docs in plugins/ultraplan-local/docs/ predate this rule
and are left alone (separate decision).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds two sibling files in plugins/ultraplan-local/docs/ that together
specify a new /ultracontinue command for zero-friction multi-session
resumption — drafted from design dialogue at the end of the config-audit
v5.0.0 release session (5 sessions, ~10 manual NEXT-SESSION-PROMPT
context-handovers — friction this work removes).
ultracontinue-brief.md (159 lines):
- Follows the /ultrabrief-local template (frontmatter brief_version: 2.0)
so /ultraplan-local can consume it directly
- Defines per-project state-file convention .claude/projects/<project>/
.session-state.local.json as the contract; /ultracontinue is read-only,
multiple writers may update
- 10 falsifiable success criteria including cross-project consistency,
no-new-deps, validator + helper command, docs sweep across plugin
README + CLAUDE.md + marketplace root README
- 3 research topics: ultraexecute end-of-session integration depth,
graceful-handoff alignment (no hard dep), Claude Code slash-command
conventions for read+execute commands
- Explicit non-goals: not replacing /ultraexecute-local --resume, not
replacing graceful-handoff, not auto-orchestrating N sessions
- Open questions and assumptions flagged for plan-critic / scope-guardian
ultracontinue-design-notes.md (117 lines):
- Captures the dialogue rationale that shaped the brief, so the
implementing session has full context without needing to read this
conversation's transcript
- Origin (config-audit v5 release pain point), key design insight
("state-fil ER kontrakten, ikke verktøyet"), 6 design decisions with
alternatives considered, anti-patterns from KTG auto-memory to respect,
recommended reading order, expected scope (1-2 execution sessions)
No code changes. Brief is ready for /ultraplan-local --brief
plugins/ultraplan-local/docs/ultracontinue-brief.md (light path) or
/ultraresearch-local for full research path.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
v5.0.0 SHIPPED 2026-05-01. Tag config-audit/v5.0.0 pushed to Forgejo.
SC-6b release-gate PASS at -0.85% delta (CLAUDE.md actual 589 vs
estimated 594, well within ±5% gate).
Per-step:
- Step 28: README/CLAUDE.md straggler-sweep + self-audit counter alignment
- Step 29: version bump 4.0.0 → 5.0.0 + consolidated CHANGELOG
- Step 30: full audit + live SC-6b gate + tag (incl. one in-step bug fix
for hotspot.path exposure, required to make calibration measurable)
635 tests still green throughout. No blockers carried forward.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The v5.0.0-rc.1 N5 implementation looked up hotspot.path in
calibrateAgainstApi() but token-hotspots.mjs only emitted hotspot.source —
calibration silently produced 0 actual_tokens because every iteration hit
the `if (!hotspot?.path) continue` guard.
Fix: file-backed hotspots now expose `path: h.absPath` in the JSON output.
MCP-server hotspots intentionally leave path unset — their tokens are
runtime tool-schema (formula-based: 500 + toolCount × 200), not file
content readable by count_tokens.
SC-6b release-gate verified against tests/fixtures/marketplace-large:
- Actual (count_tokens, claude-opus-4-7): 589 tokens for CLAUDE.md
- Estimated (4-bytes/token byte heuristic): 594 tokens
- Delta: -5 tokens / -0.85% — well within ±5% gate. PASS.
CHANGELOG: documented the fix + SC-6b result inline under [5.0.0].
All 635 tests still green. No estimateTokens tuning required for v5.0.0.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Stop hook fallback antok 200K-vindu. På Opus 4.7 (faktisk 1M) kunne
auto-handoff fyre 5–7x for tidlig — estimert 70% når reell bruk var
~14%. Erstatter enkel fallback med 4-stegs resolution-kjede:
1. payload.context_window.used_percentage (autoritativ)
2. payload.context_window.context_window_size + transcript-estimat
3. MODEL_WINDOWS[payload.model.id] + estimat
4. FALLBACK_WINDOW=1_000_000 + estimat (2026-default)
additionalContext-meldinger inkluderer nå [kilde: <source>] for innsyn.
Brief som kilde-artefakt i docs/brief-context-window-detection.md.
6 nye tester (57 totalt). Ingen regresjoner.
beta.1 wrap entry covering N1-N4 + N6 (Steps 18-22b). Includes
explicit Known breaking changes section on CA-TOK-* glob suppression
matching CA-TOK-005, and notes plugin-vs-built-in collision is
deferred to v5.0.1.
Tests: 586 → 625 (+39).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New COL scanner detects skill-name collisions across plugins and
between user-level skills (~/.claude/skills/) and plugin-bundled
skills. Skill identity is the directory basename — matches how
enumerateSkills resolves names.
Detection rules (per docs/v5-namespace-research.md, confidence: medium):
- Plugin-vs-plugin same skill name → severity low (CA-COL-001)
- User-vs-plugin same skill name → severity medium (CA-COL-001)
- Plugin-vs-built-in collisions: out of scope for v5.0.0 (insufficient
verification — recorded for v5.0.1 follow-up).
Findings carry details.namespaces array with {source, name, path} for
every conflicting source — supports per-collision reporting downstream.
output.mjs: finding() helper now passes through optional `details`
field (scanner-specific structured payload).
scoring.mjs: COL → "Plugin Hygiene" (new area, 10 total). Posture test
updated from 9 → 10 area scores.
.gitignore: docs/v5-namespace-research.md is local-only (Step 22a
research output, gitignored per plan).
Fixture collision-plugins/fake-home/ has user skill `review` colliding
with plugin-a + plugin-b's `review` (medium severity), plus plugin-c's
unique `summarize` (no collision).
[skip-docs] reason: v5 plan fences off README/CLAUDE.md badge updates
to Session 5; Forgejo pre-commit-docs-gate hook requires this tag.
Tests: 617 → 625 (+8).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New DIS scanner detects tools that appear in BOTH permissions.deny
and permissions.allow within the same settings.json file. The deny
list wins, so allow entries are dead config but still load on every
turn and confuse intent.
Tool identity = bare name (everything before "("). `Bash(npm:*)` and
`Bash` are treated as the same tool, so a deny on `Bash` flags any
`Bash(...)` allow entry.
Severity: low. Wired into scan-orchestrator + scoring (area: Settings).
Fixture denied-tools-in-schema has Bash in both arrays; healthy-project
serves as the negative case.
[skip-docs] reason: v5 plan fences off README/CLAUDE.md badge updates
to Session 5; Forgejo pre-commit-docs-gate hook requires this tag.
Tests: 611 → 617 (+6).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New CPS scanner walks CLAUDE.md cascade and flags volatile content
between lines 31 and 150 — the cache-prefix window beyond TOK Pattern
A's top-30 territory. Volatile content anywhere in the cached prefix
forces a fresh cache write from that line down on every turn.
Volatile-pattern set extends TOK Pattern A with:
- shell-exec lines (! prefix) — common in CLAUDE.md to inject git/date
- ${VAR} substitutions — vary per-shell, defeat cache reuse
Severity: medium per finding. Skips lines 1-30 to avoid duplicating
Pattern A's range; CPS' value is in the 31-150 zone.
Wired into scan-orchestrator + scoring SCANNER_AREA_MAP. CPS shares
the "Token Efficiency" area with TOK; scoreByArea now deduplicates by
area name and combines counts across scanners contributing to the
same area, so the 9-area scorecard contract holds.
Fixtures volatile-mid-section/{volatile-line-60, volatile-line-200}
verify both positive (line 60) and out-of-window (line 200) cases.
[skip-docs] reason: v5 plan fences off README/CLAUDE.md badge updates
to Session 5; Forgejo pre-commit-docs-gate hook requires this tag.
Tests: 604 → 611 (+7).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New scanners/manifest.mjs CLI + commands/manifest.md slash command.
Reads activeConfig and produces a flat, ranked list of every token
source (CLAUDE.md cascade entries, plugins, skills, MCP servers, hooks)
sorted DESC by estimated_tokens.
CLAUDE.md per-file tokens are derived by distributing
claudeMd.estimatedTokens across the cascade proportional to bytes.
Tests cover both real-config (plugin root) and fixture (rich-repo with
patched HOME containing 2 plugins + 3 skills + .mcp.json) paths, plus
error handling (nonexistent path → exit 3, --output-file).
Builds on readActiveConfig from M1 (v5 alpha.2).
[skip-docs] reason: v5 plan fences off README/CLAUDE.md badge updates
to Session 5; Forgejo pre-commit-docs-gate hook requires this tag on
feat commits without doc changes.
Tests: 593 → 604 (+11).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds detectMcpToolBudget detection block in TOK scanner. Tiered severity
per project-local .mcp.json server based on toolCount:
- < 20: no finding
- 20-49: low
- 50-99: medium
- 100+: high
- null (manifest unparseable): low + "tool count unknown" message
Scoped to source==='.mcp.json' to keep findings actionable for the
audited path; plugin/user-level MCP servers are surfaced by the
manifest scanner (Step 19 / N2).
5 fixtures (mcp-budget/{14,25,60,120,unknown}-tools) use inline `tools`
arrays in .mcp.json — no node_modules needed for these tests.
Tests assert title+severity (not exact ID) since TOK IDs are sequential
per scan, not semantic per pattern.
[skip-docs] reason: v5 plan fences off README/CLAUDE.md badge updates
to Session 5; Forgejo pre-commit-docs-gate hook requires this tag on
feat commits without doc changes.
Tests: 586 → 593 (+7).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Filesystem counts are the source of truth; README badges parsed via
line-anchored substring (badge/<kind>-<N>-...). Emits readmeCheck object
with counts/badges/mismatches.
CLI: node scanners/self-audit.mjs --check-readme [--json]
API: runSelfAudit({ checkReadme: true }) → result.readmeCheck
Helper: checkReadmeBadges(pluginDir) for per-fixture testing
New fixture: readme-desynced/ (commands/foo + bar, README claims 1).
Note: alpha phase does NOT require result.readmeCheck.passed === true.
Self-test of real plugin currently fails (scanners 10 vs 9, tests 31 vs 543);
will be reconciled in Session 5 Step 28 (README sync).
582 → 586 tests, all green.
The mcp-tool-heavy fixture relies on node_modules/mcp-heavy/package.json
being committed so the v5 M1 tool-count detection test runs deterministically.
Add an unignore rule for tests/fixtures/**/node_modules/.