Skip to content

fix: boundary hook checks NotebookEdit + resolves ..; AC convention actually auto-loads (0.20.1) - #23

Merged
stid merged 4 commits into
mainfrom
fix/boundary-notebook-ac-rule
Oct 25, 2026
Merged

stid merged 4 commits into
mainfrom
fix/boundary-notebook-ac-rule

Conversation

@stid

@stid stid commented Oct 24, 2026

Copy link
Copy Markdown
Owner

Fixes #21, fixes #22.

#21 — edit-boundary hook

  • NotebookEdit sends tool_input.notebook_path. The hook now reads it when file_path is absent, so notebook edits outside the boundary are denied.
  • . and .. are resolved lexically before matching. src/x/../../docs/y is checked as docs/y, and a path that resolves outside the project stays unpoliced. The split doesn't use read, which would stop at a newline, and runs under set -f, so a * segment stays literal.
  • Fail-open is unchanged (D-003): an empty or unparseable path still allows.
  • Resolution is lexical, not physical (symlinks aren't followed). That's deliberate: the target may not exist yet, and this hook guards scope, not security.

#22 — AC convention auto-load

  • Confirmed before fixing: in a plugin-only project, reading a docs/lcd/**/spec.md did not load the rule. A control project with the rule in .claude/rules/ did load it.
  • Onboard: now always writes .claude/rules/ac-convention.md. It rewrites paths: for a custom root. If an existing copy doesn't cover the root (for example a vendored seed), onboard rewrites only that line and logs it.
  • Doctor: checks the copy at every root. Missing or non-covering is a WARN on the default root (projects onboarded earlier: re-run /lcd:onboard) and a FAIL on a custom root, as before. Coverage is judged on the paths: globs, not a substring of the file.
  • Docs: rules/lcd.md, the ac-convention.md header, README and doctor.md no longer claim the plugin copy auto-loads.

Also

  • Boundary-hook tests: the fixture's branch switch-back used git checkout on an unborn branch, which failed silently. Every later case ran with no active work-item and passed without testing anything. It now uses symbolic-ref, asserted. The "placeholder-only" case really is placeholder-only now.

Verification

  • Suite: 14/14. Every touched test also passes under macOS /bin/bash 3.2. claude plugin validate passes.
  • Mutation checks: each fix was reverted in turn, and every revert fails its AC test. The cases: notebook fallback, dot resolution, newline split, set -f, default-root WARN, the regex grep, and substring coverage.
  • Independent closeout evaluator: it challenged the work with a substring false-OK in the doctor coverage check, and a set -f regression no test would catch. Both are fixed in the last commit.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VCp4cMxLbQXy83ZZv9RDXp

stid and others added 4 commits October 24, 2026 12:12
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCp4cMxLbQXy83ZZv9RDXp
…s ac-convention at every root (#21, #22)

- boundary hook: NotebookEdit's tool_input.notebook_path is checked when file_path is
  absent; . and .. are resolved lexically before matching, so src/x/../../docs/y is
  matched as docs/y (and a path resolving outside the project stays unpoliced)
- doctor: plugins have no rules/ component, so the AC rule only auto-loads from
  .claude/rules/ac-convention.md — missing/wrong-root copy now WARNs at the default
  root (FAIL at a non-default root, as before); root matched with grep -F
- test fixture: the branch switch-back used checkout on an unborn branch and failed
  silently, so every later boundary case ran with nothing active; now symbolic-ref +
  asserted, and the placeholder-only case really is placeholder-only

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCp4cMxLbQXy83ZZv9RDXp
…ing plugin auto-load; boundary split survives newlines (#21, #22)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCp4cMxLbQXy83ZZv9RDXp
…he glob-literal split (evaluator)

Root 'docs' (or 'spec') was a substring of the stock docs/lcd copy, so doctor reported
OK for globs that never match docs/work/<slug>/spec.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCp4cMxLbQXy83ZZv9RDXp
@stid
stid merged commit a2e73cb into main Oct 25, 2026
3 checks passed
@stid
stid deleted the fix/boundary-notebook-ac-rule branch October 25, 2026 00:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant