Skip to content

Commit 185afdd

Browse files
committed
Tooling: root doc-reachability at the repo-root CLAUDE.md, enforce specs + notes, add specs index
Follow-ups to the `docs-reachable` check, per review: - **Root is now the repo-root `CLAUDE.md`** (the real entry point Claude Code loads first, which `@import`s AGENTS.md), not AGENTS.md directly. - **`docs/specs` and `docs/notes` are no longer exempt.** Everything under `docs/` is enforced: scratch dirs must still be discoverable while they exist. Dropped the ephemeral-dir carve-out. - **New `docs/specs/index.md`** lists every spec (root + `later/`) as a dated checklist (`[x]` = shipped), linked from `AGENTS.md` § File structure. This connects all 34 specs. Done/not-done is best-effort from each spec's top + git; a few are uncertain (see the worktree report). Net effect: 230 docs reachable, 23 orphans remaining (4 subsystem CLAUDE.md, 13 guides, 6 notes) for connecting in a later pass. Enabling notes surfaced only 6 real orphans: the other ~12 were already linked from their colocated CLAUDE.md/DETAILS.md, which the graph counts.
1 parent 69e91db commit 185afdd

9 files changed

Lines changed: 126 additions & 83 deletions

File tree

AGENTS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ Core structure:
108108
- `/docs/` - Dev docs
109109
- `guides/` - How-to guides
110110
- `notes/` - Temporary reference notes (benchmarks, analysis) linked from CLAUDE.md files
111+
- `specs/` - Per-development specs and task lists (temporary, periodically wiped); see
112+
[specs/index.md](docs/specs/index.md)
111113
- `tooling/` - Internal tooling docs
112114
- `architecture.md` - Map of all subsystems with links to their `CLAUDE.md` files
113115
- `style-guide.md` - Writing, code, and design style rules

docs/specs/index.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Specs index
2+
3+
Spec docs and task lists for Cmdr developments, indexed so each stays discoverable. See [README.md](README.md) for what
4+
this folder is and when it gets wiped. Checked means the work shipped; unchecked means not yet, or deferred under
5+
[`later/`](later/). The date is each spec's creation date.
6+
7+
## Specs
8+
9+
- [x] 2026-05-25 component-catalog-plan.md - In-app dev-only catalog of every UI primitive
10+
- [x] 2026-05-28 downloads-watcher-plan.md - Hotkey and toast to jump to the latest download
11+
- [x] 2026-05-28 viewer-tail-encoding-regex-plan.md - Viewer regex search, encoding picker, and tail mode
12+
- [x] 2026-05-29 pending-dir-size-hourglass-plan.md - Per-directory hourglass while folder sizes are still updating
13+
- [x] 2026-05-31 per-folder-icons.md - Distinctive per-folder icons in the file list
14+
- [x] 2026-06-03 go-to-path-plan.md - Keyboard-first "Go to path" (⌘G) jump action
15+
- [x] 2026-06-04 explorer-architecture-plan.md - Master explorer refactor to module store and typed dispatch
16+
- [x] 2026-06-05 explorer-store-phase1-plan.md - Un-trap explorer state into one module store
17+
- [x] 2026-06-05 explorer-command-bus-phase2-plan.md - Route every command entry path through one typed dispatch bus
18+
- [x] 2026-06-05 explorer-navigation-phase3-plan.md - Collapse navigation braid into one transactional navigate call
19+
- [x] 2026-06-05 explorer-capabilities-phase4-plan.md - Capability-driven virtual-volume guards replacing volume-id
20+
strings
21+
- [x] 2026-06-05 command-handler-record-plan.md - Convert command dispatch switch to a typed flat handler record
22+
- [x] 2026-06-05 e2e-stability-quick-wins-plan.md - SMB fixture resilience plus looser Playwright Linux-lane timeouts
23+
- [x] 2026-06-05 folder-merge-plan.md - Always-merge folder conflicts plus instant same-volume moves
24+
- [x] 2026-06-05 smb-shared-stack-plan.md - Share the SMB Docker fixture stack across worktrees safely
25+
- [x] 2026-06-06 drag-out-file-promises-plan.md - Drag files out of MTP and SMB panes via file promises
26+
- [x] 2026-06-06 indexing-status-indicator-plan.md - Soften drive-indexing status into an unobtrusive hourglass
27+
- [x] 2026-06-06 progressive-scan-sizes-plan.md - Show growing partial folder sizes during a full scan
28+
- [x] 2026-06-06 scan-progress-eta-plan.md - Add scan progress percent and ETA to the indicator
29+
- [x] 2026-06-06 shortcut-display-unification-plan.md - Unify and make truthful every shortcut shown in the UI
30+
- [x] 2026-06-08 typed-events-plan.md - Make Tauri event names and payloads generated and typed
31+
- [x] 2026-06-09 beta-analytics-plan.md - Privacy-clean beta usage analytics with a true daily-active count
32+
- [x] 2026-06-11 query-dialogs-overhaul-plan.md - Overhaul the Search and Select dialogs end to end
33+
34+
## Later
35+
36+
Deferred future work. Unchecked by default; the folder name is the status.
37+
38+
- [ ] 2026-03-10 later/db-first-listings-plan.md - Serve directory listings from the SQLite index for sub-ms navigation
39+
- [ ] 2026-03-10 later/dropbox-sync-status-linux.md - Detect Dropbox sync status on Linux via command socket
40+
- [ ] 2026-03-10 later/linux-builds-plan.md - Add Linux release build target plus website download detection
41+
- [ ] 2026-03-10 later/viewer-menu-swap-plan.md - Per-window menu bar for the viewer on macOS
42+
- [ ] 2026-04-01 later/rust-word-wrap-heights-plan.md - Move viewer word-wrap height calculation from JS to Rust
43+
- [ ] 2026-04-03 later/connect-to-server-plan.md - Manual "Connect to server" for non-mDNS SMB shares
44+
- [ ] 2026-06-04 later/agent-spec.md - Persistent in-app agent proposing file operations
45+
- [ ] 2026-06-04 later/data-dir-rename-spec-draft.md - Rename data directories from bundle-id to plain names
46+
- [ ] 2026-06-10 later/codegraph-tauri-resolver.md - Teach CodeGraph to trace Cmdr's Tauri IPC boundary
47+
- [ ] 2026-06-11 later/viewer-horizontal-virtualization-plan.md - Horizontally virtualize long lines in the file viewer
48+
- [ ] 2026-06-11 later/whats-new-popup-plan.md - Post-update "What's new" changelog dialog

scripts/check/checks/CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ see [`../CLAUDE.md`](../CLAUDE.md).
1818
tracking plumbing.
1919
- Warn-only scanners with their JSON allowlists: `file-length.go`, `claude-md-length.go`, `e2e-durations.go`,
2020
`website-bundle-size.go`. Error-level allowlist scanner: `docs-reachable.go` (+ shared `docs_graph.go`), which fails
21-
when a `CLAUDE.md` / `DETAILS.md` / `docs` file isn't reachable from `AGENTS.md`.
21+
when a `CLAUDE.md` / `DETAILS.md` / `docs` file isn't reachable from the repo-root `CLAUDE.md`.
2222

2323
## Must-knows
2424

scripts/check/checks/DETAILS.md

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ freestyle.sh remote execution), see [`../CLAUDE.md`](../CLAUDE.md).
1818
| `file-length-allowlist.json` | Allowlist for file-length check: `{ "exempt": { "path": reason }, "files": { "path": lineCount } }`. See § File-length allowlist. |
1919
| `claude-md-length.go` | Warn-only push-tier scanner: warns when a `CLAUDE.md` exceeds 600 words (`DETAILS.md` is the unlimited pull tier, not scanned). Allowlist with the same shrink-wrap semantics as file-length. See § CLAUDE.md length. |
2020
| `claude-md-length-allowlist.json` | Allowlist for claude-md-length: `{ "files": { "path": wordCount } }`. Same ratchet/consent rules as file-length. |
21-
| `docs_graph.go` | Shared doc-discoverability graph: reachability from `AGENTS.md` over references between docs. Powers both the `docs-reachable` check and the `--docs-graph` renderer. See § Docs reachable. |
22-
| `docs-reachable.go` | Errors (not warn-only) when any `CLAUDE.md` / `DETAILS.md` / `docs/` file can't be reached from `AGENTS.md`. Allowlist with the same shrink-wrap/consent semantics as file-length. See § Docs reachable. |
21+
| `docs_graph.go` | Shared doc-discoverability graph: reachability from the repo-root `CLAUDE.md` over references between docs. Powers both the `docs-reachable` check and the `--docs-graph` renderer. See § Docs reachable. |
22+
| `docs-reachable.go` | Errors (not warn-only) when any `CLAUDE.md` / `DETAILS.md` / `docs/` file can't be reached from the root `CLAUDE.md`. Allowlist with the same shrink-wrap/consent semantics as file-length. See § Docs reachable. |
2323
| `docs-reachable-allowlist.json` | Allowlist for docs-reachable: `{ "files": { "path": reason } }` of docs intentionally unreachable. Goal is empty. Shrink-wraps gone/now-reachable entries; adding one needs David's OK. |
2424
| `e2e-durations.go` | E2E test duration flagger (warn-only): parses the Playwright JSON reports after each E2E run and flags tests over the 2 s budget. Embedded in both E2E checks, not a registry check. See § E2E test duration flagger. |
2525
| `e2e-duration-allowlist.json` | Per-platform (`macos` / `linux`) allowlist for the duration flagger: `{ "<spec>::<describe chain>::<title>": reason }`. Entries need a reason; new entries need David's OK. |
@@ -191,24 +191,26 @@ change. Adding or raising an entry needs David's OK (`.claude/rules/file-length-
191191
## Docs reachable
192192

193193
`docs-reachable` (`IsFast`, an **error** not a warn: the doc tree must stay connected) enforces that every `CLAUDE.md`,
194-
`DETAILS.md`, and `docs/` file is discoverable from the single root `AGENTS.md` by link-walking, so a reader entering
195-
there can find every doc. `docs_graph.go` builds the graph (shared with the `--docs-graph` renderer in
194+
`DETAILS.md`, and `docs/` file is discoverable from the repo-root `CLAUDE.md` by link-walking, so a reader entering at
195+
the real entry point can find every doc. `docs_graph.go` builds the graph (shared with the `--docs-graph` renderer in
196196
`../docs_graph_render.go`); `docs-reachable.go` is the check shell + allowlist.
197197

198198
How reachability is decided (`BuildDocGraph`):
199199

200-
- **One root, `AGENTS.md`.** A doc is reached when a doc already reached from the root references it. BFS, so each doc
201-
is placed under its closest-to-root reference (a cycle just hits an already-reached node and stops).
200+
- **One root, the repo-root `CLAUDE.md`.** It's the true entry point: Claude Code loads it first, and it `@import`s
201+
`AGENTS.md` + the core docs. A doc is reached when a doc already reached from the root references it. BFS, so each doc
202+
is placed under its closest-to-root reference (a cycle just hits an already-reached node and stops). The root itself
203+
is never an orphan.
202204
- **A reference is any mention, syntax-agnostic:** Markdown link, `@import`, backtick path, or bare path token are all
203205
equal. We watch intent, not form. Matching is generous (relative-to-source, repo-root-relative, and ≥2-segment path
204206
suffix), because over-connecting only hides a would-be orphan, while a false orphan would be a noisy CI failure.
205207
- **The CLAUDE.md asymmetry:** a `DETAILS.md` or `docs/` file must be named, but a `CLAUDE.md` also counts as reached
206208
when a reachable doc mentions its _directory_ (`architecture.md` lists most subsystems as `` `some/dir/` ``, and
207209
Claude Code auto-injects a `CLAUDE.md` from its directory regardless). Such edges are tagged `ViaDir`; the renderer
208210
shows "(dir reference)".
209-
- **Ephemeral dirs are excluded** from the enforced candidate set: `docs/specs` and `docs/notes` self-declare in their
210-
READMEs as temporary scratch "wiped periodically", so requiring each to be linked fights their purpose
211-
(`ephemeralDocDirs`). The repo-root `CLAUDE.md` (the loader shim that only `@import`s the entry docs) is excluded too.
211+
- **Everything under `docs/` is enforced, including `docs/specs` and `docs/notes`.** Those dirs are periodically-wiped
212+
scratch, but they must still be discoverable while they exist: specs hang off `docs/specs/index.md`, and a note is
213+
expected to be linked from the colocated `CLAUDE.md` / `DETAILS.md` whose work it informs.
212214

213215
`docs-reachable-allowlist.json` maps a doc path → the reason it's intentionally unreachable. The goal is an empty list:
214216
connect docs rather than exempt them. Shrink-wrap drops entries whose file is gone or which became reachable; adding or
@@ -283,16 +285,16 @@ RUSTSEC ignores — that's a quarterly task in `docs/maintenance.md`.
283285

284286
## Apps and check counts
285287

286-
| App | Tech | Checks |
287-
| ---------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
288-
| Desktop | Rust | rustfmt, clippy, cargo-audit, cargo-deny, cargo-machete, cargo-udeps (CI-only), jscpd, log-error-macro, error-string-match, lock-poison, bindings-fresh, ipc-enum-camelcase, tests, integration-tests (Docker SMB), tests-linux (slow) |
289-
| Desktop | Svelte | prettier, eslint, svelte-kit-sync, eslint-typecheck-svelte, eslint-typecheck-typescript, stylelint, css-unused, a11y-contrast, btn-restyle, bare-poll, svelte-check, import-cycles, knip, type-drift, tests, e2e-linux-typecheck, e2e-linux (slow), e2e-playwright (slow) |
290-
| Website | Astro | prettier, eslint, typecheck, build, html-validate, bundle-size (warn-only), e2e |
291-
| Website | Docker | docker-build |
292-
| API server | TS | oxfmt, eslint, typecheck, tests |
293-
| Scripts | Go | gofmt, go-vet, staticcheck, ineffassign, misspell, gocyclo, nilaway, deadcode, go-tests, govulncheck |
294-
| Other | Metrics | file-length (warn-only), CLAUDE.md-reminder (warn-only), claude-md-length (warn-only), docs-reachable (errors when a CLAUDE.md/DETAILS.md/docs file isn't reachable from AGENTS.md), changelog-commit-links, workflows-rustup (forbids `rustup target/component add` in workflows), ci-coverage (registry-to-workflows contract) |
295-
| Other | Security | workflows-hardening (SHA-pinning, no `pull_request_target`, job-scoped `id-token: write`) |
288+
| App | Tech | Checks |
289+
| ---------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
290+
| Desktop | Rust | rustfmt, clippy, cargo-audit, cargo-deny, cargo-machete, cargo-udeps (CI-only), jscpd, log-error-macro, error-string-match, lock-poison, bindings-fresh, ipc-enum-camelcase, tests, integration-tests (Docker SMB), tests-linux (slow) |
291+
| Desktop | Svelte | prettier, eslint, svelte-kit-sync, eslint-typecheck-svelte, eslint-typecheck-typescript, stylelint, css-unused, a11y-contrast, btn-restyle, bare-poll, svelte-check, import-cycles, knip, type-drift, tests, e2e-linux-typecheck, e2e-linux (slow), e2e-playwright (slow) |
292+
| Website | Astro | prettier, eslint, typecheck, build, html-validate, bundle-size (warn-only), e2e |
293+
| Website | Docker | docker-build |
294+
| API server | TS | oxfmt, eslint, typecheck, tests |
295+
| Scripts | Go | gofmt, go-vet, staticcheck, ineffassign, misspell, gocyclo, nilaway, deadcode, go-tests, govulncheck |
296+
| Other | Metrics | file-length (warn-only), CLAUDE.md-reminder (warn-only), claude-md-length (warn-only), docs-reachable (errors when a CLAUDE.md/DETAILS.md/docs file isn't reachable from the root CLAUDE.md), changelog-commit-links, workflows-rustup (forbids `rustup target/component add` in workflows), ci-coverage (registry-to-workflows contract) |
297+
| Other | Security | workflows-hardening (SHA-pinning, no `pull_request_target`, job-scoped `id-token: write`) |
296298

297299
## Key decisions
298300

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"$comment": "Docs intentionally NOT reachable from AGENTS.md, each mapped to its reason. The goal is an empty list: connect docs instead of exempting them. The docs-reachable check shrink-wraps stale entries (file gone or now reachable) on local runs; adding or keeping an entry needs David's explicit consent (see .claude/rules/file-length-allowlist.md).",
2+
"$comment": "Docs intentionally NOT reachable from the repo-root CLAUDE.md, each mapped to its reason. The goal is an empty list: connect docs instead of exempting them. The docs-reachable check shrink-wraps stale entries (file gone or now reachable) on local runs; adding or keeping an entry needs David's explicit consent (see .claude/rules/file-length-allowlist.md).",
33
"files": {}
44
}

0 commit comments

Comments
 (0)