organize ยท diff

git:20260329.6c378a2 to git:20260503.631b94d

114 added, 287 removed. Audit A to A.

---
name: organize
description: >-
Three-pass project health scan: architectural compliance (are source files in
the right layers?), filesystem hygiene (loose files, misplaced assets, stale
artifacts), and bloat detection (oversized files, binaries in git, compressible
assets). Reports composite score. Also manages enforceable directory manifests
and dynamic directory lifecycle.
user-invocable: true
auto-trigger: false
trigger_keywords:
- organize
- directory structure
- folder structure
- project structure
- file organization
- organize directories
- organize files
- cleanup directories
- directory convention
- where should this go
- messy project
- project health
- bloat
last-updated: 2026-03-28
---
# /organize -- Project Organization Health
- ## Identity
-
- You are a project health analyst. You run three passes on every scan:
- architectural compliance, filesystem hygiene, and bloat detection. You report
- all three scores and a composite so the user gets an honest picture of their
- project's organization -- not just whether source files are in the right
- folders, but whether the project as a whole is clean, lean, and well-maintained.
- You never impose structure -- you discover it, propose it, and lock it only
- when the user agrees.
-
## Orientation
- **Use when:**
- - User wants to know if their project is organized (the default scan answers this)
- - Setting up a new project and want consistent directory conventions
- - Existing project has grown messy and needs structure alignment
- - User asks "where should this file go?" or "how is this project organized?"
- - Running `/organize --cleanup` to prune expired dynamic directories
- - Running `/organize --audit` to check current compliance
-
- **Do NOT use when:**
- - Refactoring code (use `/refactor` instead)
- - Moving a single file (just move it directly)
- - The project already has an organization manifest and the user hasn't asked to change it
+ **Use when:** Auditing whether source files are in the right architectural layers, detecting loose files and misplaced assets, or configuring directory manifests and cleanup policies for a project.
- **What this skill needs:**
- - A project directory to scan (defaults to PROJECT_ROOT)
- - User input on convention preference (if not already configured)
+ **Don't use when:** You want a structural map of code relationships and module dependencies (use `/map`), you're moving logic between modules (use `/refactor`), or you need to execute a single organizational task without a health audit (use `/marshal`).
## Commands
| Command | Behavior |
|---|---|
| `/organize` | Full flow: scan, detect, recommend, configure |
| `/organize --audit` | Check current files against the manifest, report violations |
| `/organize --cleanup` | Run dynamic directory cleanup based on TTL policy |
| `/organize --show` | Display current organization manifest |
| `/organize --unlock` | Set `locked: false` so enforcement is advisory |
| `/organize --lock` | Set `locked: true` so enforcement blocks violations |
## Protocol
### Step 1: CHECK -- Read Existing Configuration
1. Read `.claude/harness.json` and check for an `organization` key
2. **If `organization` exists and user ran bare `/organize`:**
- Display current convention, root count, placement rule count, dynamic dir count
- Ask: "Your organization manifest is already configured. Want to **audit** current
compliance, **adjust** the rules, or **reconfigure** from scratch?"
- Route based on answer: audit -> Step 6, adjust -> Step 4, reconfigure -> Step 2
3. **If `organization` exists and user ran `--audit`:** Jump to Step 6
4. **If `organization` exists and user ran `--cleanup`:** Jump to Step 7
5. **If no `organization` key:** Continue to Step 2
### Step 2: SCAN -- Three-Pass Project Analysis
- Every scan runs all three passes. This is not optional. A user running `/organize`
- gets the full picture without having to know what to ask for.
+ Every scan runs all three passes. A user running `/organize` gets the full picture.
- **Do NOT use `find` or `Get-ChildItem`** anywhere in this skill -- these are
- platform-specific. Use the **Glob tool** and **Bash** (`git ls-files`, `du`,
- `wc`) for cross-platform compatibility.
+ **Do NOT use `find` or `Get-ChildItem`** -- use the **Glob tool** and **Bash** (`git ls-files`, `du`, `wc`) for cross-platform compatibility.
---
#### Pass 1: Architectural Compliance
- Map the project's directory tree and check whether source files follow a
- consistent convention.
-
- 1. Use the **Glob tool** with pattern `**/` to discover directories. Filter out noise
- directories: `node_modules`, `.git`, `.planning`, `.citadel`,
- `.claude`, `dist`, `build`, `__pycache__`, `.next`, `target`, `.venv`, `venv`.
- Cap at 200 directories. If the project is too large, scan only the top 3 levels
- (`*/`, `*/*/`, `*/*/*/`).
- 2. Read `package.json`, `Cargo.toml`, `pyproject.toml`, `go.mod`, or equivalent to understand the stack
+ 1. Use the **Glob tool** with pattern `**/` to discover directories. Filter out:
+ `node_modules`, `.git`, `.planning`, `.citadel`, `.claude`, `dist`, `build`,
+ `__pycache__`, `.next`, `target`, `.venv`, `venv`.
+ Cap at 200 directories. If too large, scan only top 3 levels.
+ 2. Read `package.json`, `Cargo.toml`, `pyproject.toml`, `go.mod`, or equivalent for stack
3. Read harness.json for `language` and `framework` fields
- 4. Count files per directory to find the "heavy" areas (where most code lives)
+ 4. Count files per directory to find the "heavy" areas
5. Check for existing convention signals:
- `src/components/`, `src/hooks/`, `src/utils/` -> **layer-based**
- `src/features/auth/`, `src/features/dashboard/` -> **feature-based**
- - `src/auth/components/`, `src/auth/hooks/` -> **hybrid** (features containing layers)
+ - `src/auth/components/`, `src/auth/hooks/` -> **hybrid**
- Flat `src/` with no subdirectories -> **flat**
- Mixed signals -> **custom** (needs user input)
- 6. If an organization manifest exists, check each placement rule against current files.
- Count compliant vs. violating files.
+ 6. If an organization manifest exists, check each placement rule against current files. Count compliant vs. violating files.
Record findings:
-
```
Detected: {convention}
Confidence: {high|medium|low}
Roots: [{path, purpose, file_count}]
Signals: [{pattern, evidence, convention_match}]
- Anomalies: [{path, issue}] // dirs that don't fit the detected pattern
+ Anomalies: [{path, issue}]
```
**Scoring:** `architecture_score = compliant_files / total_source_files * 100`.
- If no manifest exists yet, score is based on how consistently the detected
- convention is followed (files fitting the pattern vs. total files).
+ If no manifest exists, score is based on how consistently the detected convention is followed.
---
#### Pass 2: Filesystem Hygiene
- Check for mess that has nothing to do with code architecture.
-
- 1. **Loose files in project root.** List every file in the project root. The
- following are expected root files -- everything else is a finding:
- - Config files: `package.json`, `tsconfig*.json`, `*.config.{js,ts,mjs,cjs}`,
- `.eslintrc*`, `.prettierrc*`, `babel.config.*`, `jest.config.*`,
- `vite.config.*`, `next.config.*`, `rollup.config.*`, `webpack.config.*`,
- `Cargo.toml`, `pyproject.toml`, `go.mod`, `Makefile`, `Dockerfile`,
- `docker-compose*.yml`, `.env*`, `.editorconfig`, `.gitignore`,
- `.gitattributes`, `.npmrc`, `.nvmrc`, `.node-version`, `.tool-versions`
+ 1. **Loose files in project root.** List every file in the project root. Expected root files:
+ - Config: `package.json`, `tsconfig*.json`, `*.config.{js,ts,mjs,cjs}`, `.eslintrc*`,
+ `.prettierrc*`, `babel.config.*`, `jest.config.*`, `vite.config.*`, `next.config.*`,
+ `rollup.config.*`, `webpack.config.*`, `Cargo.toml`, `pyproject.toml`, `go.mod`,
+ `Makefile`, `Dockerfile`, `docker-compose*.yml`, `.env*`, `.editorconfig`,
+ `.gitignore`, `.gitattributes`, `.npmrc`, `.nvmrc`, `.node-version`, `.tool-versions`
- Docs: `README*`, `LICENSE*`, `CHANGELOG*`, `CONTRIBUTING*`, `CLAUDE.md`,
`QUICKSTART*`, `CODE_OF_CONDUCT*`, `SECURITY*`
- - CI/lock files: `*.lock`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`,
+ - CI/lock: `*.lock`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`,
`Gemfile.lock`, `.github/`, `.husky/`
- Plugin/harness: `.claude/`, `.planning/`, `.citadel/`, `hooks/`, `hooks_src/`,
`skills/`, `agents/`, `scripts/`
- - Any file listed in `.gitignore` (already excluded from concern)
+ - Any file listed in `.gitignore`
- Everything else in root (especially images, PDFs, ZIPs, random scripts,
- stray source files) is a finding.
+ Everything else in root (images, PDFs, ZIPs, random scripts, stray source files) is a finding.
2. **Images and assets outside designated directories.** Glob for
`**/*.{png,jpg,jpeg,gif,svg,ico,webp,mp4,mp3,wav,pdf}`. Check if they
live under a recognized asset directory (`assets/`, `public/`, `static/`,
- `images/`, `img/`, `media/`, `docs/images/`, `src/assets/`). Files outside
- these paths are findings.
+ `images/`, `img/`, `media/`, `docs/images/`, `src/assets/`). Files outside are findings.
3. **Large files (>1 MB).** Use `git ls-files -z | xargs -0 stat` or equivalent
- to find tracked files over 1 MB. Report each with path and size. These are
- often forgotten build artifacts, uncompressed assets, or vendored binaries.
+ to find tracked files over 1 MB. Report each with path and size.
4. **Empty directories.** Glob for directories, check which contain zero files
(excluding `.gitkeep`). Report as clutter.
- 5. **Stale files in active directories.** Use `git log --diff-filter=M --format=%at`
- on files in `src/` (or equivalent active source root). Files not modified in
- 6+ months while their sibling files are active may be dead code or forgotten
- experiments. Report as "potentially stale" -- advisory, not a violation.
+ 5. **Stale files in active directories.** Files in `src/` not modified in 6+ months
+ while siblings are active. Report as "potentially stale" -- advisory only.
- 6. **Duplicate filenames.** Scan for files with identical names in different
- directories (e.g., `utils.ts` appearing in 3 places). Not always wrong, but
- worth flagging for awareness.
+ 6. **Duplicate filenames.** Scan for files with identical names in different directories.
+ Flag for awareness.
**Scoring:** Start at 100, deduct:
- -2 per loose non-standard file in project root
- - -1 per misplaced asset file (image/media outside asset dirs)
+ - -1 per misplaced asset file
- -3 per large file (>1 MB) tracked in git
- -1 per empty directory
- -0.5 per potentially stale file (capped at -10)
- -0.5 per duplicate filename (capped at -5)
Floor at 0. `hygiene_score = max(0, 100 - deductions)`.
---
#### Pass 3: Bloat Detection
- Check whether the project is carrying unnecessary weight.
-
- 1. **Project size vs. source size.** Calculate:
+ 1. **Project size vs. source size.**
- Total tracked size: `git ls-files -z | xargs -0 stat` (sum sizes)
- - Source code size: same but filtered to code file extensions
- (`.ts`, `.tsx`, `.js`, `.jsx`, `.py`, `.rs`, `.go`, `.java`, `.css`,
- `.scss`, `.html`, `.md`)
- - Ratio: `source_bytes / total_bytes`. A healthy project is >60% source.
- Below 40% means non-source content dominates.
+ - Source code size: same but filtered to `.ts`, `.tsx`, `.js`, `.jsx`, `.py`, `.rs`,
+ `.go`, `.java`, `.css`, `.scss`, `.html`, `.md`
+ - Ratio: `source_bytes / total_bytes`. Healthy = >60%. Below 40% means non-source dominates.
- 2. **Largest files ranked.** List the top 10 largest tracked files with sizes.
- This alone often reveals the problem.
+ 2. **Largest files ranked.** List top 10 largest tracked files with sizes.
- 3. **Binary files in git.** Glob for tracked files that are binary:
- `*.{png,jpg,jpeg,gif,ico,webp,mp4,mp3,wav,woff,woff2,ttf,eot,zip,tar,gz,
- jar,dll,so,dylib,exe,bin,dat,db,sqlite,pdf}`.
- For each, check if it could live in `.gitignore` (build output, generated
- asset) or should be in Git LFS. Report count and total size.
+ 3. **Binary files in git.** Glob for:
+ `*.{png,jpg,jpeg,gif,ico,webp,mp4,mp3,wav,woff,woff2,ttf,eot,zip,tar,gz,jar,dll,so,dylib,exe,bin,dat,db,sqlite,pdf}`.
+ Check if each could be gitignored or moved to Git LFS. Report count and total size.
- 4. **Accidentally committed directories.** Check if any of these exist as
- tracked paths: `node_modules/`, `dist/`, `build/`, `.next/`, `target/`,
- `__pycache__/`, `.venv/`, `venv/`, `.cache/`, `.parcel-cache/`,
- `.turbo/`, `coverage/`. Any hit is a critical finding.
+ 4. **Accidentally committed directories.** Check if any of these exist as tracked paths:
+ `node_modules/`, `dist/`, `build/`, `.next/`, `target/`, `__pycache__/`, `.venv/`,
+ `venv/`, `.cache/`, `.parcel-cache/`, `.turbo/`, `coverage/`. Any hit is a critical finding.
- 5. **Compressible assets.** For image files tracked in git, check for:
- - PNGs over 500 KB (likely uncompressed screenshots or exports)
- - SVGs over 100 KB (likely unoptimized exports from design tools)
- - Any video/audio file (should almost never be in a git repo)
+ 5. **Compressible assets.** PNGs over 500 KB, SVGs over 100 KB, any video/audio file.
**Scoring:** Start at 100, deduct:
- - If source ratio <60%: -(60 - ratio) (e.g., 40% source = -20)
+ - If source ratio <60%: -(60 - ratio)
- -5 per accidentally committed build/dependency directory
- -2 per binary file in git that should be gitignored or in LFS
- -1 per compressible asset (PNG >500KB, SVG >100KB)
- -3 per video/audio file tracked in git
Floor at 0. `bloat_score = max(0, 100 - deductions)`.
---
#### Composite Score
- After all three passes:
-
```
composite_score = round(
architecture_score * 0.40 +
hygiene_score * 0.35 +
bloat_score * 0.25
)
```
- Architecture is weighted highest because it affects developer velocity most.
- Hygiene is close behind because it affects first impressions and onboarding.
- Bloat is lowest because it's the easiest to fix.
-
**Always report all four numbers.** Never report just the architecture score.
```
=== Project Health: {project_name} ===
Architecture: {score}% -- source file placement, layer boundaries, test colocation
Hygiene: {score}% -- loose files, misplaced assets, stale artifacts, empty dirs
Bloat: {score}% -- project size ratio, binaries in git, compressible assets
-------------------------------
Overall: {composite}%
```
- Follow the scores with the most actionable findings from each pass. Group by
- severity (critical first, advisory last). Cap at 10 findings per pass to avoid
- overwhelming the user -- mention "and N more" if truncated.
+ Follow scores with the most actionable findings from each pass. Group by severity (critical first, advisory last). Cap at 10 findings per pass; note "and N more" if truncated.
### Step 3: RECOMMEND -- Present Options
- Based on scan results, present the user with a tailored recommendation.
-
- **If confidence is HIGH (strong existing convention):**
-
- ```
- Your project follows a {convention}-based structure.
-
- Detected roots:
- src/components/ -- React components (42 files)
- src/hooks/ -- Custom hooks (12 files)
- src/utils/ -- Utility functions (8 files)
- src/types/ -- Type definitions (6 files)
-
- Anomalies:
- src/helpers/ -- Looks like it overlaps with utils/ (3 files)
-
- Recommendation: Lock this convention so new files follow it.
- Want me to [Accept], [Adjust], or [Show alternatives]?
- ```
-
- **If confidence is MEDIUM (partial convention):**
-
- ```
- Your project partially follows a {convention}-based structure, but I found
- {N} directories that don't fit the pattern.
-
- Here are the conventions I detected and alternatives that might work:
-
- 1. {detected} (current, {N}% match)
- - Pro: Matches most of what's already here
- - Con: {anomalies} directories would need reorganizing
-
- 2. {alternative} ({M}% match if reorganized)
- - Pro: {benefit}
- - Con: Requires moving {K} directories
-
- 3. Custom -- Define your own rules
-
- Which would you prefer? [1/2/3]
- ```
-
- **If confidence is LOW (no clear convention):**
-
- ```
- Your project doesn't follow a clear directory convention yet. Here are
- options that fit your stack ({language}/{framework}):
-
- 1. Feature-based -- Group by domain (auth/, dashboard/, settings/)
- Best for: Apps with distinct functional areas
-
- 2. Layer-based -- Group by technical role (components/, hooks/, utils/)
- Best for: Libraries, small-medium apps
-
- 3. Hybrid -- Features containing layers (auth/components/, auth/hooks/)
- Best for: Large apps that need both domain and technical organization
+ Present a tailored recommendation based on confidence level:
- 4. Flat -- Minimal directories, files at top level
- Best for: Small utilities, scripts, single-purpose projects
+ **If confidence is HIGH:** Present the detected convention and its roots. Ask: [Accept], [Adjust], or [Show alternatives].
- 5. Custom -- Tell me your preferred structure
+ **If confidence is MEDIUM:** Present the detected convention with anomaly count and 2-3 alternatives including reorganization cost (number of files to move). Ask: [1/2/3].
- Which fits your workflow? [1/2/3/4/5]
- ```
+ **If confidence is LOW:** Present the four convention options (feature-based, layer-based, hybrid, flat) with a one-line best-for description each, plus [Custom]. Ask: [1/2/3/4/5].
Wait for user response before proceeding.
### Step 4: CONFIGURE -- Write the Organization Manifest
- Based on the user's choice (or acceptance of recommendation), build the manifest.
-
**4a. Build the roots tree:**
- For each detected root directory, create an entry:
+ For each detected root directory:
```json
{
"purpose": "short description of what belongs here",
"children": { ... } // recursive, only if subdirectories have distinct purposes
}
```
-
- Only go 2-3 levels deep. Deeper structure is the domain of individual features.
+ Only go 2-3 levels deep.
**4b. Build placement rules:**
- Placement rules tell the enforce hook where specific file types belong.
- Derive these from the detected convention:
+ Derive placement rules from the detected convention:
| Convention | Example Rules |
|---|---|
| Feature-based | `*.test.ts` -> colocated with source, `*.types.ts` -> colocated |
| Layer-based | `*.test.ts` -> `__tests__/` or `tests/`, `*.types.ts` -> `types/` |
| Hybrid | `*.test.ts` -> colocated within feature, `*.types.ts` -> `{feature}/types/` |
- | Flat | No placement rules (everything at top level) |
+ | Flat | No placement rules |
For each rule:
```json
{
"glob": "*.test.{ts,tsx}",
"rule": "colocated",
"target": null,
"reason": "Tests live next to the code they test"
}
```
- - `rule: "colocated"` -- file must be in the same directory as its source
- - `rule: "sibling-dir"` -- file must be in `target` directory adjacent to source
- - `rule: "root-dir"` -- file must be under `target` from project root
- - `rule: "within-root"` -- file must be under one of the declared roots
+ Rule types:
+ - `colocated` -- file must be in the same directory as its source
+ - `sibling-dir` -- file must be in `target` directory adjacent to source
+ - `root-dir` -- file must be under `target` from project root
+ - `within-root` -- file must be under one of the declared roots
Ask the user if they want to adjust any rules before writing.
**4c. Build dynamic directory entries:**
- Scan for directories that are created dynamically by the harness or tools:
-
+ Scan for directories created dynamically by the harness or tools. For each:
```json
- [
- { "path": ".planning/screenshots/", "scope": "session", "cleanup": "empty-on-expire" },
- { "path": ".planning/fleet/outputs/", "scope": "campaign", "cleanup": "archive-then-delete" },
- { "path": ".planning/fleet/briefs/", "scope": "campaign", "cleanup": "archive-then-delete" },
- { "path": ".planning/coordination/claims/", "scope": "session", "cleanup": "empty-on-expire" },
- { "path": ".planning/coordination/instances/", "scope": "session", "cleanup": "empty-on-expire" }
- ]
+ { "path": ".planning/screenshots/", "scope": "session", "cleanup": "empty-on-expire" }
```
- Scopes:
- - `session` -- contents expire when the session ends
- - `campaign` -- contents expire when the associated campaign completes
- - `task` -- contents expire when a specific task completes
- - `permanent` -- never cleaned up automatically
+ Scopes: `session` | `campaign` | `task` | `permanent`
- Cleanup strategies:
- - `empty-on-expire` -- delete contents but keep the directory
- - `archive-then-delete` -- move to `.planning/archive/{date}/` then delete
- - `delete` -- remove directory and contents entirely
- - `ignore` -- mark as dynamic but never auto-clean
+ Cleanup strategies: `empty-on-expire` | `archive-then-delete` | `delete` | `ignore`
**4d. Set cleanup policy:**
Ask the user:
```
When dynamic directories expire, how should cleanup work?
1. Auto -- Clean up silently on session end
2. Prompt -- Show what would be cleaned and ask first
3. Manual -- Just report stale directories, don't touch them
-
[1/2/3] (default: 2)
```
**4e. Write to harness.json:**
- Read the current harness.json, merge the `organization` key, write back.
- Do NOT overwrite other keys. Use a read-modify-write pattern.
+ Read-modify-write. Merge the `organization` key. Do NOT overwrite other keys.
```json
{
"organization": {
"convention": "layer",
"roots": { ... },
"placement": [ ... ],
"dynamic": [ ... ],
"cleanupPolicy": "prompt",
"locked": false
}
}
```
- Set `locked: false` initially. Tell the user they can run `/organize --lock`
- once they're confident the rules are correct.
+ Set `locked: false` initially. Tell the user they can run `/organize --lock` once confident.
### Step 5: VERIFY -- Confirm the Manifest Works
1. Run a full three-pass audit (Step 6 logic) against the current codebase
2. Report all three scores plus composite
- 3. If composite is below 60%, warn the user:
- "Overall project health is {N}%. Here are the biggest issues to address."
- 4. If architecture score is above 80% but hygiene or bloat is below 60%, call it out:
- "Your code structure is solid ({arch}%), but hygiene ({hyg}%) and bloat
- ({bloat}%) are dragging down overall health. The fixes are mostly quick wins."
+ 3. If composite < 60%: warn with top issues
+ 4. If architecture > 80% but hygiene or bloat < 60%: call out the drag and note quick wins
5. Tell the user about `--lock`, `--audit`, and `--cleanup` commands
### Step 6: AUDIT -- Full Three-Pass Health Check
- Run all three passes from Step 2 (architecture, hygiene, bloat). This is the
- same logic whether called from `--audit`, from Step 5 verification, or from
- the initial `/organize` flow.
-
- Output the composite score block first, then details:
+ Run all three passes from Step 2. Output the composite score block first:
```
=== Project Health: {project_name} ===
- Architecture: {score}% -- source file placement, layer boundaries, test colocation
- Hygiene: {score}% -- loose files, misplaced assets, stale artifacts, empty dirs
- Bloat: {score}% -- project size ratio, binaries in git, compressible assets
+ Architecture: {score}%
+ Hygiene: {score}%
+ Bloat: {score}%
-------------------------------
Overall: {composite}%
--- Architecture ({N} violations) ---
-
- *.test.ts should be colocated:
- - tests/auth.test.ts -> should be src/auth/auth.test.ts
-
- *.types.ts should be in types/:
- - src/components/Button.types.ts -> should be types/Button.types.ts
+ {glob pattern} should be {rule}:
+ - {violating_path} -> {expected_path}
--- Hygiene ({N} findings) ---
-
- Loose files in project root (not config/docs):
- - screenshot.png
- - old-notes.txt
- - data-export.csv
-
+ Loose files in project root:
+ - {filename}
Images outside asset directories:
- - src/components/logo.png -> should be src/assets/ or public/
-
+ - {path} -> should be {target}
Large files (>1 MB):
- - docs/demo-recording.mp4 (12.3 MB)
-
+ - {path} ({size})
Empty directories:
- - src/deprecated/
+ - {path}
--- Bloat ({N} findings) ---
-
- Source ratio: 45% (1.2 MB source / 2.7 MB total)
-
+ Source ratio: {ratio}% ({source_size} source / {total_size} total)
Top 5 largest files:
- 1. docs/demo-recording.mp4 (12.3 MB)
- 2. public/hero-bg.png (2.1 MB)
- ...
-
+ 1. {path} ({size})
Binary files that could be gitignored:
- - coverage/lcov.info (generated)
- - dist/bundle.js (build output)
+ - {path} (generated/build output)
--- Suggested Actions ---
- [List concrete fixes, grouped: quick wins first, larger reorganizations last]
+ [Concrete fixes, quick wins first, larger reorganizations last]
Run quick fixes (move misplaced files, delete empty dirs)? [y/n]
```
- If the user says yes, execute the safe fixes (moves, empty dir removal).
+ If the user says yes, execute safe fixes (moves, empty dir removal).
Never auto-delete files with content -- only move them or flag for manual review.
### Step 7: CLEANUP -- Prune Dynamic Directories
Read the `dynamic` entries from the organization manifest.
For each entry:
-
1. Check if the directory exists
- 2. Determine if it has expired based on scope:
- - `session`: check `.planning/telemetry/` for last session end timestamp.
- If the directory has files older than the last session start, they're stale.
- - `campaign`: check `.planning/campaigns/` for associated campaign status.
- If campaign is `completed` or `parked`, contents are stale.
- - `task`: check if the task ID in the directory name/metadata still exists.
+ 2. Determine if expired based on scope:
+ - `session`: check `.planning/telemetry/` for last session end timestamp. Files older than last session start are stale.
+ - `campaign`: check `.planning/campaigns/` for associated campaign status. If `completed` or `parked`, contents are stale.
+ - `task`: check if the task ID still exists.
- `permanent`: skip
- 3. For expired entries, apply the cleanup strategy:
- - `empty-on-expire`: `rm` contents, keep directory
- - `archive-then-delete`: create `.planning/archive/{YYYY-MM-DD}/`, move contents there, then empty
- - `delete`: `rm -rf` the directory (recreate if it's in PLANNING_DIRS)
+ 3. Apply the cleanup strategy for expired entries:
+ - `empty-on-expire`: delete contents, keep directory
+ - `archive-then-delete`: move to `.planning/archive/{YYYY-MM-DD}/`, then empty
+ - `delete`: remove directory and contents (recreate if in PLANNING_DIRS)
- `ignore`: report but don't touch
- **Respect cleanupPolicy:**
-
- - `auto`: execute cleanup, report what was done
- - `prompt`: list what would be cleaned, ask for confirmation before each category
- - `manual`: list stale directories with sizes, do not modify anything
+ **Respect cleanupPolicy:** `auto` executes silently; `prompt` asks before each category; `manual` lists stale dirs without modifying.
Output:
-
```
=== Cleanup Report ===
-
Scanned: {N} dynamic directories
Stale: {M} directories ({total_size})
- {For each stale dir:}
- .planning/screenshots/ (session-scoped, 12 files, 4.2 MB)
- Strategy: empty-on-expire
+ {path} ({scope}-scoped, {N} files, {size})
+ Strategy: {strategy}
Action: {Cleaned | Would clean | Skipped}
- .planning/fleet/outputs/ (campaign-scoped, campaign "improve-citadel" completed)
- Strategy: archive-then-delete
- Action: {Archived to .planning/archive/2026-03-28/ | Would archive | Skipped}
-
Summary: {N} directories cleaned, {M} archived, {K} skipped
```
## Fringe Cases
- - **No directories found:** Project is a single file or empty. Skip scan, suggest flat convention.
- - **Monorepo detected** (multiple package.json files): Scan each package root separately.
- Ask if organization should be per-package or repo-wide.
- - **User changes convention:** When switching from one convention to another, warn about the
- number of files that would need to move. Do NOT auto-move without explicit confirmation.
- - **Conflict with existing rules:** If harness.json already has `protectedFiles` that conflict
- with placement rules, warn and ask which takes precedence.
- - **Dynamic dir doesn't exist yet:** Keep the entry in the manifest. The enforce hook or
- init-project will create it when needed. Don't warn about missing dynamic dirs.
- - **Archive directory grows large:** If `.planning/archive/` exceeds 50MB, warn the user
- and suggest manual pruning.
+ - **`.planning/` does not exist:** Run `/do setup` first to initialize the harness state directory; then re-run.
+ - **No directories found:** Skip scan, suggest flat convention.
+ - **Monorepo detected** (multiple package.json): Scan each package root separately. Ask if organization should be per-package or repo-wide.
+ - **User changes convention:** Warn about number of files to move. Do NOT auto-move without explicit confirmation.
+ - **Conflict with existing rules:** If harness.json `protectedFiles` conflict with placement rules, warn and ask which takes precedence.
+ - **Dynamic dir doesn't exist yet:** Keep the entry in the manifest. Don't warn about missing dynamic dirs.
+ - **Archive directory grows large:** If `.planning/archive/` exceeds 50MB, warn and suggest manual pruning.
- ## Quality Gates
+ ## Contextual Gates
- All of these must be true before the skill exits:
+ **Disclosure:** "Running project health scan. Phase 3 (cleanup) may move files โ€” will confirm scope before executing."
+ **Reversibility:** amber โ€” may move files or rename directories in cleanup phase; undo with `git checkout -- .` or `git revert`
+ **Trust gates:**
+ - Any: run scan and view report (Phases 1-2)
+ - Familiar (5+ sessions): Phase 3 file moves execute autonomously; novices should stop after Phase 2 (report only)
- - [ ] All three passes ran (architecture, hygiene, bloat) -- never skip a pass
- - [ ] All three scores plus composite were reported to the user
- - [ ] Project directory tree was scanned (Step 2 completed or skipped with existing config)
- - [ ] User was presented with options and made a choice (not auto-decided without input)
+ ## Quality Gates
+
+ - [ ] All three passes ran -- never skip a pass
+ - [ ] All three scores plus composite reported
+ - [ ] Project directory tree scanned (Step 2 completed or skipped with existing config)
+ - [ ] User presented with options and made a choice (not auto-decided)
- [ ] Organization manifest written to harness.json under `organization` key
- [ ] Placement rules are specific (glob + rule + reason, no vague entries)
- [ ] Dynamic directory entries have valid scope and cleanup strategy
- - [ ] User was told about `--lock`, `--audit`, and `--cleanup` commands
- - [ ] No other harness.json keys were modified during the write
+ - [ ] User told about `--lock`, `--audit`, and `--cleanup` commands
+ - [ ] No other harness.json keys modified during write
## Exit Protocol
```
---HANDOFF---
- Health: {composite}% (Architecture {arch}%, Hygiene {hyg}%, Bloat {bloat}%)
- Convention: {convention} applied to {project}
- {N} roots, {M} placement rules, {K} dynamic directories configured
- Top findings: {1-2 most impactful issues from hygiene/bloat passes}
- Enforcement: {"advisory (unlocked)" | "blocking (locked)"}
+ - Reversibility: amber โ€” file moves undoable with `git checkout -- .`; harness.json changes undoable with `git revert`
- Next: Run `/organize --lock` when confident, `/organize --audit` to recheck
---
```