Decided: .claude/rules/ stays open — only CLAUDE.md and .claude/settings.json are strict. Rules are low-risk and frequently edited.
Decided: Dual source — protected: true in file frontmatter is the source of truth, .claude/protected-files.yml is a generated cache for fast hook lookups.
Decided: Sync script in PreToolUse hook with 24h staleness check — only rescans frontmatter if yml is older than 24 hours.
Decided: Hook blocks the edit and tells Claude to write a proposal instead. Claude writes the proposed change to vault/90_inbox/proposals/protected/. User accepts or rejects via skill.
Decided: Two protection modes — locked (no create, no edit → proposal) and watch (edit OK, changes logged + notified). No separate files/dirs sections — path with extension = file, without = dir.
Decided: watch notifications via all three channels: (1) changelog file vault/00_system/logs/watch-changelog.md, (2) surfaced in /status and daily briefing, (3) terminal message after each edit.
Decided: decision-log.md and dashboards/ stay open — Claude updates these as part of regular work.
User Tasks
FR-003: Protected Files System
Summary
Files have two protection modes: locked (changes → proposal for user review) and watch (changes allowed but logged and notified). Unprotected files are freely editable.
Problem / Motivation
Some files (CLAUDE.md, settings.json, system docs) should not be modified without explicit user approval. Other files can be modified but the user wants visibility on changes. Instead of just blocking edits (which stops work), we redirect them to proposals, and for watched files we log and notify.
Proposed Solution
Audit all paths and finalize the protected list
Add protected: true to frontmatter of protected files (source of truth)
Build a sync script that scans frontmatter → generates .claude/protected-files.yml
Build a PreToolUse hook that:
Runs sync if yml is older than 24 hours
Detects Edit/Write to a protected path
For locked paths: blocks all create/edit (path with extension = file, without = dir)
Blocks with exit non-zero + message telling Claude to write a proposal instead
watch dirs are handled by PostToolUse hook (Phase 4), not blocked
Build a PostToolUse hook for watch paths that:
Logs changes to vault/00_system/logs/watch-changelog.md (file, timestamp, summary)
Prints a terminal notification after each edit
Surface unreviewed changelog entries in /status skill and daily briefing
Claude writes the proposed change to vault/90_inbox/proposals/protected/
Build an /accept-proposal skill that applies the change and cleans up
Document the system in CLAUDE.md
Phase Overview
Phase
Description
Status
Phase 1
Audit & decide final protected + watch list
in-progress
Phase 2
Frontmatter + sync script + generated yml
—
Phase 3
PreToolUse protect hook (with 24h sync)
—
Phase 4
PostToolUse watch hook (changelog + terminal)
—
Phase 5
Watch in /status + daily briefing
—
Phase 6
Proposal format + /accept-proposal skill
—
Phase 7
CLAUDE.md documentation
—
Phase 1: Audit & Decide —
Goal: Review all paths and finalize which files need protection.
File / Feature
Details
Owner
Status
Review current protected list
Check each path — is protection still needed?
opus
—
Include vault/my-todos.md
User-only file — Claude must never write to it
opus
—
Include .claude/settings.json
If Claude removes the hook, protection breaks
opus
—
Include CLAUDE.md
Master instructions — changes need user sign-off
opus
—
Identify workflow friction
Where does protection slow down normal work?
mv
—
Propose final list
Binary: protected (→ proposal) or open
opus
—
User approval
User signs off on final list
mv
—
Phase 2: Frontmatter & Sync —
Goal: Add protected: true frontmatter to protected files and build a sync script that generates the yml cache.
On Edit/Write: run sync if yml > 24h old, then check target against yml. locked paths: block all create/edit → redirect to proposal. Has extension = file match, no extension = dir match (startswith).
opus
—
Register hook in settings.json
Add to PreToolUse array
opus
—
Test hook redirects protected edits
Verify hook blocks and Claude writes proposal instead
mv
—
Phase 4: Watch Hook —
Goal: PostToolUse hook that logs and notifies on changes to watched paths.
After Edit/Write to a watch path: append entry to vault/00_system/logs/watch-changelog.md (file, timestamp, brief summary) and print terminal notification
opus
—
Register hook in settings.json
Add to PostToolUse array
opus
—
Create vault/00_system/logs/watch-changelog.md
Changelog file with reviewed/unreviewed markers
opus
—
Test watch logging
Edit a watched file → entry appears in changelog + terminal message
mv
—
Phase 5: Watch in Status & Briefing —
Goal: Surface unreviewed changelog entries in /status skill and daily briefing.
File / Feature
Details
Owner
Status
Update /status skill
Show count of unreviewed changelog entries, with summary
opus
—
Update daily briefing
Include unreviewed watch changes
opus
—
Mark-as-reviewed mechanism
User can mark entries as reviewed (e.g., checkbox or /reviewed command)
opus
—
Phase 6: Proposal Workflow —
Goal: Define proposal format and build accept/reject skill.
File / Feature
Details
Owner
Status
Define proposal file format
Target file, change type (edit/create/delete), proposed content or diff
opus
—
Create vault/90_inbox/proposals/protected/
Landing folder for protected file proposals
opus
—
Build /accept-proposal skill
Applies the proposed change to the target file, deletes the proposal
opus
—
Reject workflow
User deletes the proposal file (or /reject-proposal skill)
opus
—
Test full flow
Edit protected → proposal created → accept → change applied
mv
—
Phase 7: Documentation —
Goal: Document the system in CLAUDE.md.
File / Feature
Details
Owner
Status
Add Protected Files section to CLAUDE.md
How it works, all three modes, how to add/remove paths, proposal workflow, watch notifications
opus
—
Acceptance Criteria:
Every protected path has a clear reason for being protected
Protected files have protected: true in frontmatter
Sync script generates .claude/protected-files.yml from frontmatter
PreToolUse hook runs sync if yml > 24h old, then checks target
locked dirs block all create/edit operations
Blocked edits result in a proposal file
Proposal files contain enough info to apply the change (target path, content/diff)
/accept-proposal applies the change correctly
watch paths: edits succeed but are logged to changelog and shown in terminal
/status and daily briefing show unreviewed watch changes
User can mark changelog entries as reviewed
Unprotected files can still be edited freely
Adding protection = add protected: true (or watch: true) to frontmatter (next sync picks it up)
Notes:
Previously tracked as two FRs (FR-003 organize + FR-037 enforce), merged 2026-02-27.
Key insight: blocking edits stops work; redirecting to proposals keeps momentum while maintaining control.
Frontmatter is source of truth; yml is generated cache. 24h staleness check keeps overhead minimal.
Prerequisites / Gap Analysis
Requirements
Requirement
Description
REQ-1
.claude/settings.json supports PreToolUse hooks
Current State
Component
Status
Details
Protected files list in CLAUDE.md
done
Exists but not enforced
PreToolUse hook
—
Not implemented
Gap (What’s missing?)
Gap
Effort
Blocker?
Audit of current list
Low
No
Sync script
Low
No
PreToolUse protect hook
Med
No
PostToolUse watch hook
Med
No
Watch in /status + briefing
Low
No
/accept-proposal skill
Med
No
Test
Manual tests
Test
Expected
Actual
Last
Edit a locked file in conversation
Hook blocks, Claude writes proposal
pending
-
Run /accept-proposal on a pending proposal
Change applied, proposal marked applied
pending
-
Reject a proposal (delete file)
Target file unchanged
pending
-
Run /status with unreviewed changelog entries
Shows changelog count
pending
-
Mark changelog entry as reviewed ([x])
No longer counted in /status
pending
-
AI-verified tests
Run inside git snapshot: git stash -u before, git restore . && git clean -fd && git stash pop after. Tests may freely mutate the repo.
Scenario
Expected behavior
Verification method
Edit a locked file in conversation
Hook blocks, Claude writes proposal
Attempt edit on CLAUDE.md, verify blocked + proposal created
Run /accept-proposal on a pending proposal
Change applied, proposal marked applied
Create test proposal, approve, run skill, verify target updated
Reject a proposal (delete file)
Target file unchanged
Create test proposal, delete it, verify target unchanged
/status with unreviewed changelog entries
Shows changelog count
Add unchecked entries to watch-changelog.md, run /status, verify count shown
Mark changelog entry as reviewed ([x])
No longer counted in /status
Check entry in changelog, run /status, verify count decreased
Proposal-based approach: edits → proposal files → user accept/reject. Frontmatter as source of truth with 24h sync to yml cache. Two dir modes: locked and watch. Watch notifies via changelog, terminal, and /status.
2026-03-19
Test gap found
watch-notify tests still reference single watch-changelog.md but implementation writes daily split files to changelog/{today}.md. Tests need updating.
References
FR-011 (Hook Scripts) — protect-files hook is part of this system