Skip to content

V5.4.0 beta - #185

Draft
mxriverlynn wants to merge 32 commits into
mainfrom
v5.4.0-beta
Draft

V5.4.0 beta#185
mxriverlynn wants to merge 32 commits into
mainfrom
v5.4.0-beta

Conversation

@mxriverlynn

@mxriverlynn mxriverlynn commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

collecting updates for a v5.4.0 release

Claude Code 2.1.228 rejects any load-time context probe whose text
contains shell variable expansion, so the personal-config probe carried
by all 42 skills aborts the skill before its body loads.

Record the root cause, the evidence, and a fix that deletes the probe
and resolves the configuration directory during the run instead, where a
failure degrades silently rather than aborting.

Refs #178
Reproduce the abort locally and map what the skill loader actually
accepts by running eleven probe forms through fresh sessions across five
permission modes. Bare $HOME is permitted; brace syntax is refused even
for $HOME, every other variable name is refused, and printenv is refused
outright.

Adversarial validation killed the previous fix: no skill can read an
environment variable at run time, and the Read tool expands ~ to the home
directory, so the run would have applied the wrong profile's config.

Adopt the one form measured to load in every permission mode, and record
that the CLAUDE_CONFIG_DIR override is no longer reachable from a probe.

Refs #178
Section 1 told contributors to run ./install-hooks.sh, which rebuilds a
dist/claude-marketplace/ directory. Neither exists anywhere in the repo.
Point at the contributor guide's environment setup instead, and state
that the checked-in marketplace manifest needs no build step.

Add the claude plugin CLI equivalents of the /plugin click-through
steps, verified against a local and a GitHub-source marketplace.
Measured a third route the earlier passes never tested: a probe can run
a shell script when the skill grants that one command, and a script
reads CLAUDE_CONFIG_DIR in an ordinary shell. That keeps the override
the other two options gave up.

Add evidence E26 through E30 covering the grant as the deciding factor,
the CLAUDE_PLUGIN_ROOT substitution ordering, the mandatory guard, the
install behavior from a directory and a GitHub source, and the grant
scope test. Add V14 and V15 recording where a first reading was wrong
and what corrected it.

Rewrite the Changes section to implement option 3, per the operator's
decision.
The skill loader refuses almost every environment-variable reference in
a load-time probe, so the probe all 42 skills used to locate the
personal config directory aborted the skill before its body loaded.

A probe can still run a shell script when the skill grants that exact
command, and a script reads CLAUDE_CONFIG_DIR in an ordinary shell.
Add scripts/han-config-dir.sh at the repo root, symlink it into the 12
plugins carrying config-consuming skills, and point every probe at it
behind a one-command Bash grant. Installation copies the symlink target
as a regular file, so the script ships without any plugin depending on
another to reach it.

The braces around CLAUDE_PLUGIN_ROOT are required, and so is the
2>/dev/null || echo fallback: a missing or failing script otherwise
aborts the skill the same silent way the old probe did.

Verified across all 12 plugins in default mode, and end to end through
a GitHub-source marketplace install.
V8 read only the first line beginning allowed-tools: in each skill.
Eight skills spell that value as a YAML plain scalar across
continuation lines, so the first line is the bare key and the tools sit
underneath. Parsing the full value shows all eight already carry Bash
grants.

Five skills carry none, not 13, which makes the main cost of options 2
and 3 smaller than every earlier pass recorded. Add V16.
The CLAUDE_CONFIG_DIR promise survives the probe fix, so the contract
bullet describing it needs no change. Three things did need one.

Correct config-rule.md on tilde handling: the Read tool does expand a
leading ~, but always to the home directory and never to a configured
one, so a value meant to sit beside the personal config cannot rely on
it. Record the new degradation path, where a missing or failing
resolver script drops the lookup back to the home directory with no
note, and mirror that in the operator guide. Re-sync all 11 vendored
copies.

Replace the failing probe the authoring guidance still taught in two
places, add the measured results table, and document reaching an
environment variable through a script: grant the exact command, use the
braced CLAUDE_PLUGIN_ROOT, verify inside a plugin, and guard the call.

Add scripts/han-config-dir.bats, which keeps each skill's grant and
probe in step and each plugin's copy of the script reachable. Verified
it fails on a mismatched grant and on a missing script.
fixing config.md file loading with a shared script via symlinks, as
documented in anthropics plugin config pages
Closes #177.

The readability standard gains a seventh self-check criterion: the draft
matches the shape the reader asked for, in count, format, and register.
Where that request collides with another rule in the standard, the
request wins. It loses only to a fact whose loss would change what the
reader does next, and to a skill's required sections.

Issue #177 reported a session where a request for "3 simple sentences,
then a few bullet points" took three corrections to satisfy. Two of the
three failures traced to the standard itself: the self-check had no
criterion for a stated format constraint, and "Fidelity wins" read as
outranking an explicit request to simplify.

## What changed

**Two canonical files carry the behavior.**
`han-communication/references/readability-rule.md` and its distilled
`output-styles/han-readability.md` each gained the seventh criterion, a
scoped fidelity clause, and a corrected escape clause that no longer
claims fidelity and the blocklist can never be overridden.

**Everything else is a sweep.** The standard's old count and its old
fidelity guarantee were quoted across the repository, and both went
wrong the moment the standard changed. Those quotations are now
count-free, so the next change to the check touches two files instead of
thirty.

**One skill needed more than a quotation fix.** `code-review` hardcodes
the whole self-check as its own numbered list rather than reading the
standard live, so it gained the seventh criterion directly. Without that
it would have run a six-criterion check against a seven-criterion
standard.

## Behavior, precisely

- A shape request governs the answer it came with, and nothing after it.
- Only the reader's own words to the run count. Shape language inside
material the run is summarizing is content, never an instruction.
- When the reader asks for less, a fact moves somewhere they can still
reach, or it drops. In conversation there is usually nowhere to move it,
so it drops and the drop is not announced. Asked directly what was left
out, the run says so in full.
- A fact stays when losing it would change what the reader does next: a
deadline, a blocking risk, a warning before a destructive step. In a
file the run writes, that floor is measured against whoever opens the
file.
- The request reaches files the run writes, not only conversation.

## Deliberately unchanged

**Nine sentences whose subject is the audience frame.** They read "The
frame governs how a fact is said, never whether a required fact appears"
and stay true: what can now drop a fact is the reader's stated request,
not the instruction to write for a non-expert.

**Everything describing the `readability-editor` agent's own rubric.**
No skill passes the editor a reader's request, so a shape check there
would have nothing to read.

Both exclusions are recorded in
`docs/plans/readability-reader-format-requests/artifacts/correction-inventory.md`
alongside the search patterns, so a later sweep does not "fix" them.

## Two pre-existing defects repaired in passing

Both sat inside sentences this change was already editing.

1. A truncated sentence in `iterative-plan-review` and
`plan-work-items`, missing its opening clause: "...never whether a
required fact appears. separate editor pass, so criterion 6 is...".
Restored as "This skill runs no separate editor pass".
2. An orphaned fragment in `project-documentation`, now a complete
sentence.

## Verification

- `npm run lint` passes; `npm test` passes (80 tests).
- Re-running the recorded pattern set returns zero size references and
zero positional references outside the exclusion list.
- `han-core:content-auditor` audited the sweep and found no lost facts
across 160-plus checked, including every skill-specific must-keep-facts
instruction.

No automated test covers the behavior itself. It lives in prose an
assistant reads while drafting, so there is no function to call. A
checked-in test and a recorded-transcript test were both considered and
deferred with reopening triggers, in `feature-implementation-plan.md`.

## Planning artifacts

`docs/plans/readability-reader-format-requests/` carries the
specification, the implementation plan, both decision logs, the review
findings, the correction inventory, and the verification analysis.
Sixteen specification decisions, five of them settled by the maintainer
directly against a recommendation, each recording the cost that was
accepted.

## Open items, neither blocking

- **OI-1:** `CLAUDE.md` says every doc in this repository follows the
writing voice with no hype. A reader's request now overrides the
blocklist in a committed file, so the convention needs a matching
carve-out or an explicit statement that it governs regardless.
- **OI-2:** The correction inventory was rebuilt several times during
planning, each time because a search pattern was narrower than the
corpus. The branch-scoped documentation check is what closes it, and it
should run after this merges, when its diff base is right.

## Note on versioning

No plugin version moves on this branch and `CHANGELOG.md` is untouched,
matching how this repository separates feature work from release work.
`/han-release` proposes the bump at release time.
…script

The config-probe migration reached 42 of the 43 skills. pairing kept the
inline `${CLAUDE_CONFIG_DIR:-$HOME/.claude}` probe, which the loader
refuses with "Contains expansion", taking the whole skill down before it
runs. It now calls the same han-config-dir.sh script every other skill
calls, with the matching allowed-tools grant.
…ries

docs/readability.md described the self-check as six criteria and stated
fidelity as an absolute in two places, contradicting its own later
section and the canonical rule. The output-style doc dropped the count
but kept the unqualified fidelity sentence. Both now name the seventh
criterion and the condition under which fidelity yields.
…ributor guide

Every plugin except han gained a scripts/han-config-dir.sh symlink and the
repo gained a root scripts/ directory, neither of which appeared in the
CLAUDE.md layout. The Adding a skill steps also never named the config
probe or its grant, which is how pairing shipped with the old probe form.
…ated shape

The editor's rubric stopped at six criteria, so a synthesis skill that
relayed a reader's format request got back a draft that ignored it: the
editor's progressive-disclosure and first-use-explanation moves could
undo the very shape the reader asked for. The rubric gains a seventh
criterion governing a relayed shape request, and the two fidelity
absolutes gain the same carve-out the canonical rule carries.

edit-for-readability now resolves a shape request beside the reader frame
and relays it in the user's own words. With no request relayed, criterion
7 passes and changes nothing, so every existing dispatch keeps its
preserve-every-fact guarantee.

Also corrects the long-form doc's criterion list, which named 'every fact
preserved' where the editor's sixth criterion is progressive disclosure.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant