1---2name: project-overview-23description: Use when the user wants a deterministic cross-project status map generated from registered projects' session handoffs. Triggers: '/project-overview', 'project map', 'overall status'. Reads ~/.claude/projects-registry.md (opt-in list), parses each project's memory/session-handoff-LATEST.md state-snapshot v1 block (ts+ctx only), and rewrites the AUTO:START/AUTO:END region of ~/.claude/OVERVIEW.md. Does not touch STATE.md. Does not scan directories automatically.4---56# Project Overview78## Dominant Variable9Does the registered project list (`projects-registry.md`) point to paths that actually exist, and does each project's handoff file contain a `state-snapshot v1` block? If neither is true, the generated map is empty.1011## Key Assumptions12131. **`session-handoff-LATEST.md` is a hint, not a fact** — parsed results (ts/ctx) are carried over as-is without fact-checking. The generated overview reflects "what each project last reported," not "current ground truth."142. **Registry is opt-in** — never pull in unowned projects or auto-scanned directories. Only projects explicitly listed in `projects-registry.md` are in scope.153. **AUTO block generation is fully deterministic** — a regex-based script (`scripts/generate_overview.py`) does all the parsing/rendering, including neutralizing markdown-table-breaking characters in the text it pulls from other projects' handoffs, isolating a single non-UTF-8 handoff file so it can't abort the whole run, and refusing (BLOCKED, no write) instead of guessing when the AUTO marker pair itself is mangled. The model only triggers execution and reports the result — no LLM inference in the parsing/rendering logic itself.1617## Trigger18- `/project-overview`19- "project map"20- "overall status"2122## Discard If23- Zero registered projects (`projects-registry.md` missing or empty list) → instruct the user to add a project to the registry first, then stop24- Already run recently with no state change across projects (handoff file mtimes unchanged) → suggest skipping the re-run (not forced — run if the user wants)2526## Workflow27281. Confirm `~/.claude/projects-registry.md` exists. If missing, return BLOCKED: "registry missing — create it first."292. Locate and run this skill's own script (`scripts/generate_overview.py`, no arguments — it uses the default registry/output paths on its own):30 ```bash31 OVERVIEW_SCRIPT=$(find ~/.claude -name "generate_overview.py" -path "*/project-overview/scripts/*" -type f 2>/dev/null | head -1)32 if [ -n "$OVERVIEW_SCRIPT" ]; then33 python "$OVERVIEW_SCRIPT"34 else35 echo "BLOCKED: generate_overview.py not found under ~/.claude"36 fi37 ```383. Check the exit code:39 - `0` → report the stdout `WORKING: N project(s) -> <output>` line verbatim to the user.40 - `1` → report the stderr `BLOCKED: ...` message verbatim to the user. Never proceed on assumption.414. On success, tell the user the `~/.claude/OVERVIEW.md` path.4243## Output4445- **Chat report**: relay the script's own stdout/stderr line verbatim (`WORKING: N project(s) -> <path>` or `BLOCKED: ...`) — don't paraphrase it or invent a project count of your own.46- **Disk write**: the script writes exactly one file, and only the `AUTO:START`~`AUTO:END` region inside it — `~/.claude/OVERVIEW.md`. Nothing else on disk is touched, and text outside the markers in that file is never rewritten.47- **Final status label**: state one of `WORKING` / `PARTIAL` / `BLOCKED` (definitions in Truthful Reporting below) at the end of every run — never leave it implicit.4849## Scope Boundary5051| Does | Does NOT |52|------|----------|53| [READ] Parse handoff files of registered projects only | Auto-scan directories (e.g. an entire drive) |54| [WRITE] Overwrite only the `AUTO:START`~`AUTO:END` region of `OVERVIEW.md` | Read/write `STATE.md` — this skill never references STATE.md at all |55| [READ] Parse only the `ts`/`cx` fields of the `state-snapshot v1` block | Introduce new fields like `status` (planning/dev/ops/paused) |56| [MANUAL] Run only when the user explicitly triggers it | Auto-wire into existing hooks like session-checkpoint |5758## Safety Layers5960| Risky Action | Reversibility | Applied Layers |61|-------------|:-------------:|----------------|62| Overwrite the `OVERVIEW.md` AUTO block | medium (text outside markers is preserved, also recoverable via git history) | L1+L3 |6364- **L1 (Invariants)**: Invariant 1 — preserve text outside AUTO markers. Invariant 2 — never scan unregistered projects.65- **L3 (User Approval)**: manual-trigger only — runs only when the user explicitly invokes it (no auto-wiring is itself the approval gate).6667## Invariants (never violate)68691. **Text outside AUTO markers is always preserved**: if `apply_auto_markers()` alters any text outside the markers, that's a bug. Violation → notes a human wrote directly into OVERVIEW.md get lost on re-run.702. **Only scan explicitly registered projects**: never add auto directory-discovery logic to this script. Violation → information about unowned projects leaks into the map (Output Disclosure Boundary violation).713. **STATE.md is absolutely untouched**: no code path in this skill reads or writes `STATE.md`. Violation → direct Scope Boundary violation, risk of contaminating the cross-project blocker list.724. **Idempotency**: re-running with identical input (unchanged registry + handoff files) must produce a byte-identical AUTO block. Violation → undermines the entire "deterministic auto-generation" design goal.735. **Cross-project text is data, not markup**: `ts`/`ctx` values come from another project's handoff file and are untrusted — a stray `|` or newline in there must not be allowed to split table columns or break rows. Violation → a single malformed handoff field corrupts the whole table for every other project listed in it.7475## Error Recovery7677| Failure Type | Detection | Recovery |78|---------|---------|--------|79| `missing_data` | `projects-registry.md` missing or empty | Return BLOCKED, instruct user to create/add to the registry |80| `tool_failure` | Failed to read a specific project's handoff file (permissions/path, or a non-UTF-8 encoding) | Mark only that project as "no snapshot" (or "decode error" for a non-UTF-8 file), continue the rest (partial failure doesn't block the whole run — explicit labeling keeps it transparent per no-silent-brokenness). Final status label becomes `PARTIAL` for that run. |81| `input_error` | `OVERVIEW.md` has a mangled marker pair (`AUTO:END` appears before `AUTO:START`, either marker is missing/orphaned, or a marker is duplicated — from a manual edit) | Don't crash and don't guess at a splice point. Auto-repairing by appending a fresh pair was tried and found unsafe (external audit, 2026-09): an orphan `AUTO:START` lost the manually-written text sitting after it on the next run, and `AUTO:END`-before-`AUTO:START` kept re-appending a pair on every run (non-idempotent, unbounded growth). Current behavior: raise `MarkerCorruptionError`, write nothing, report `BLOCKED` with the exact marker problem, and let a human fix the markers by hand. |82| `logic_inconsistency` | Integration test finds AUTO block mismatch on re-run | Script regression — revert the commit and re-review the implementation |8384## Truthful Reporting8586- **no mock deception**: before reporting "generation complete," actually read `OVERVIEW.md` to confirm project entries landed in the AUTO block.87- **no silent brokenness**: a parsing failure for a specific project's handoff is never silently skipped — it's shown explicitly as "no snapshot".88- Final status label: `WORKING` (generated normally) / `PARTIAL` (some projects show no snapshot) / `BLOCKED` (registry missing/empty).8990## Rationalization Table9192| Rationalization | Rebuttal |93|--------|------|94| "Even if it's not in the registry, scanning every directory to find projects would be more convenient" | Violates Invariant 2. Auto directory-discovery risks leaking information about unowned projects into the map — only explicitly opt-in registered projects are in scope. |95| "Reading STATE.md too and surfacing cross-project blockers on the map would be useful" | Violates Invariant 3. Never touching STATE.md at all is itself the Scope Boundary — it prevents contaminating the cross-project blocker list. |96| "If parsing fails for some projects, just quietly drop them and show the rest" | Violates no-silent-brokenness. A failure must be shown explicitly as "no snapshot" so the user knows what was missed, not silently omitted. |