Skip to content

fix(#859): scope /remember:doctor's allowed-tools, match the directory's ALLOWED_TOOLS_BROAD rule, add listing links, document the observed portal scans - #861

Merged
fdaviddpt merged 5 commits into
mainfrom
fix/859
Oct 2, 2026
Merged

fdaviddpt merged 5 commits into
mainfrom
fix/859

Conversation

@fdaviddpt

Copy link
Copy Markdown
Contributor

The Anthropic directory's scan of the slim release tree (v0.37.0, e6cf58f) holds it on exactly one rule: ALLOWED_TOOLS_BROAD, from commands/doctor.md's allowed-tools: Bash. This PR clears that hold, adds the listing fields we control, and records what the portal actually checks, for claude-supertool and claude-jit-context to reuse.

Closes #859

Plugin

  • commands/doctor.md: allowed-tools: Bash(${CLAUDE_PLUGIN_ROOT}/scripts/doctor.sh:*). The script is now run directly, and scripts/doctor.sh is executable (100755). This is the same form skills/remember/SKILL.md already uses, and the portal accepted it there.
  • .claude-plugin/plugin.json: adds documentationUrl, supportUrl, privacyPolicyUrl and termsOfServiceUrl, the fields the directory reads for the listing (Claude Code ignores them).
  • Two reworded comments: in pipeline/shell.py and scripts/log.sh. They are the likely trigger of the RUNTIME_FETCH_EXEC warning on release; this is inferred, and the next scan will confirm or refute it. The shell.py docstring was also wrong: the real consumer is safe_eval.
  • docs/privacy.md: names the git backup push, the one way memory leaves the machine.

Release tooling

  • check_release_tree.py: now matches the portal's full ALLOWED_TOOLS_BROAD wording. It holds bare Bash, Bash(*), a wildcard after a shell (including pwsh/powershell), an interpreter, a package manager or runner, or curl/wget, a relative path, and a wildcard inside the path. The portal's own accepted examples still pass.
  • Workflow: CLAUDE_CLI_VERSION 2.1.280 → 2.1.287. Observed: claude plugin validate --strict fails on 2.1.280 with "Unknown field 'privacyPolicyUrl'" and passes on 2.1.287. The minimum is 2.1.281.

Docs

  • docs/releasing.md:
    • a dated record of the portal scans, comparing the full tree with release, and each rule with its trigger and fix;
    • "Listing details: what comes from where", sourced from claude.com and code.claude.com;
    • how to contact the directory team;
    • steps for another repository.
  • Fact-check: an independent agent checked all 85 claims in the doc against code, git, the remote and the portal's wording. All 24 corrections are applied: wrong, stale and contradictory claims, with inferences labelled.

Testing

  • New cases written red first:
    • 22 portal-wording forms, plus pwsh and powershell, must fail;
    • the portal's accepted examples must pass, as positive controls;
    • doctor.md scope and mode tests.
  • Targeted suites: 223 passed, 1 skipped (a case-insensitive-filesystem guard).
  • The built release tree from this branch passes check_release_tree.py and claude plugin validate --strict on 2.1.287.
  • The full suite was not run locally (the maintainer's machine is too slow), so CI is the full-suite gate.

Cross-platform

  • Observed on macOS: the check, validate on two CLI versions, and direct exec of doctor.sh.
  • Reasoned, not observed: direct exec of the .sh on Windows Git Bash works the way write-handoff.sh already does there.

🤖 Generated with Claude Code

[AI-generated]

fdaviddpt and others added 5 commits October 2, 2026 15:34
commands/doctor.md granted bare `Bash` -- unrestricted shell for the whole
command run -- when the command body only ever needs one script. Scope the
grant to Bash(${CLAUDE_PLUGIN_ROOT}/scripts/doctor.sh:*), mirroring
skills/remember/SKILL.md's existing narrow grant for write-handoff.sh, and
invoke doctor.sh directly instead of through `bash "..."` (a scoped pattern
cannot match a `bash` prefix). Make scripts/doctor.sh executable in git
(mode 100755) so the direct exec works, the same as write-handoff.sh already
is.

Add a preflight rule to check_release_tree.py: fail on any shipped skill,
command or agent whose allowed-tools grants unrestricted shell -- bare Bash,
Bash(*), Bash(:*), or a bare shell/interpreter wildcard (bash, sh, zsh, env,
python/python2/python3, with or without a trailing *) -- in both the string
and YAML-list form, so this class is caught before a release tree ships. A
narrow Bash(<path>:*) naming one script still passes.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
…eword two comments behind RUNTIME_FETCH_EXEC, document the observed portal scans

Co-Authored-By: Max <noreply>
…ory leaves the machine

Co-Authored-By: Max <noreply>
…elease validator to claude 2.1.287, which accepts them under --strict

Co-Authored-By: Max <noreply>
…/powershell grants as broad

releasing.md: .gitattributes filters stop validation rather than hold it; the
directory follows release since 2026-10-02; release commits are direct on main;
the verify job pins claude >= 2.1.281 and skips validate with only a warning if
npm fails; release_publish.py belongs to the oss plugin; a flagged listing blocks
newer versions; REVIEW lines are a starting list, not a prediction; nothing
enforces a version bump per release commit; the listing switch and webhook are
written up as done, with the steps for another repository; the marketplace ref
switch is a pending follow-up; inferences are labelled. New section on where
listing details come from and how to contact the directory team. The reuse
section now says which script reads which config key and what is hard-coded.

check_release_tree.py: pwsh and powershell join the unscoped shells, and the
module docstring lists what the code actually holds.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@fdaviddpt
fdaviddpt merged commit 337b58c into main Oct 2, 2026
16 checks passed
@fdaviddpt
fdaviddpt deleted the fix/859 branch October 2, 2026 14:09
fdaviddpt added a commit that referenced this pull request Oct 2, 2026
… guess on v0.38.0 (#871)

* docs(#864): narrow (not confirm) the RUNTIME_FETCH_EXEC third-finding guess on v0.38.0

#861's rewording of pipeline/shell.py and scripts/log.sh did not clear the
directory portal's RUNTIME_FETCH_EXEC warning; v0.38.0 raised the count
from 2 to 3 instead. Which third file matched is only visible behind the
expanded row in the portal's web UI, which this lane has no access to, so
the real trigger stays unconfirmed.

Source-only follow-up: grepped the two largest v0.37.0->v0.38.0 diffs
(scripts/lib-memory-context.sh, scripts/session-start-hook.sh, both from
#842/#845) for curl, wget, download, fetch, eval and exec and found
nothing in either -- the existing doc guess that #842/#845's SessionStart
budget code is the new third match has no textual support. scripts/log.sh
is the one file here with real eval calls on validated input, the
strongest literal (still unconfirmed) candidate for why it keeps matching.

No code changed. docs/releasing.md records the narrowed state and flags
that a human with portal access still needs to expand the row and record
the file/line before this can be closed.

Co-Authored-By: Claude Sonnet 5 <[email protected]>

* docs(#864): precise churn figures, clarify grep scope per self-review

Explore review flagged two accuracy issues in 4ccd6dd's docs/releasing.md
text: "+164"/"+74 lines" were git diff --stat churn totals (insertions
plus deletions), not insertion counts, misleading by ~2 and ~11 lines
respectively -- replaced with explicit insertions/deletions. The "found
nothing" grep claim was ambiguous between grepping the whole shipped file
vs only the diff's added lines; under the whole-file reading it is false
(scripts/session-start-hook.sh has 9 pre-existing `exec` hits). Clarified
that only the added (+) lines were grepped, gave the exact command, and
noted why the whole-file reading is misleading (those hits pre-date
v0.38.0 and cannot explain a count that only rose between versions).

Co-Authored-By: Claude Sonnet 5 <[email protected]>

---------

Co-authored-by: Claude Sonnet 5 <[email protected]>
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.

/remember:doctor pre-approves unrestricted Bash (allowed-tools: Bash): directory holds it as broad shell access

1 participant