diff options
Diffstat (limited to '.claude')
| -rw-r--r-- | .claude/commands/lint-org.md | 1 | ||||
| -rw-r--r-- | .claude/commands/refactor.md | 39 | ||||
| -rw-r--r-- | .claude/commands/respond-to-cj-comments.md | 8 | ||||
| -rw-r--r-- | .claude/commands/start-work.md | 21 | ||||
| -rw-r--r-- | .claude/settings.json | 10 |
5 files changed, 68 insertions, 11 deletions
diff --git a/.claude/commands/lint-org.md b/.claude/commands/lint-org.md index 953629c..64ec967 100644 --- a/.claude/commands/lint-org.md +++ b/.claude/commands/lint-org.md @@ -50,6 +50,7 @@ Out of scope (refuse, don't try to lint): | `invalid-fuzzy-link` | (1) Repair to a `[[*Heading]]` ref if a similar heading exists. (2) Drop to `=verbatim label=` text. (3) Skip. | | `misplaced-heading` *(verbatim-asterisk case)* | (1) Strip asterisks and rephrase to preserve semantics. (2) Convert surrounding markup to `~code~` style. (3) Skip. | | `suspicious-language-in-src-block` | (1) Emit an Emacs init one-liner that registers the language. (2) Change the block label to `text` or `example`. (3) Skip. | +| `level-2-dated-header` *(custom check, not org-lint)* | A `** <YYYY-MM-DD> …` heading is a completion defect per `todo-format.md` (no keyword, so `--archive-done` can't archive it). (1) Convert to `DONE`/`CANCELLED` + `CLOSED:`, keeping the heading text — the usual fix. (2) Demote to `***` if it's really a mis-leveled sub-entry. (3) Skip (a dated-log-format org file where `**` dates are intentional). | | anything else | Surface the raw `org-lint` message and ask the user how to proceed. | ## Phase A — Run the script diff --git a/.claude/commands/refactor.md b/.claude/commands/refactor.md index 08cbdab..97ce366 100644 --- a/.claude/commands/refactor.md +++ b/.claude/commands/refactor.md @@ -1,5 +1,5 @@ --- -description: Scan code for refactoring opportunities or perform a targeted refactor. Six modes — `full` (default; complexity + duplication + dead-code scans), `quick` (high-severity findings only), `complexity` (length / nesting / cyclomatic / parameter count / boolean ops with severity bands and techniques like guard clauses, extract method/predicate, parameter object, decompose conditional), `duplication` (clones / logic / constants / patterns / error-handling with extract-function / parameterize / template-method strategies), `dead-code` (imports / exports / branches / feature flags / deps with high/medium/low confidence labels), `rename old new` (codebase-wide symbol rename with reference search, preview gate, atomic commit, post-apply verification). Findings render as `[SEVERITY] Category — File / Metric / Issue / Suggestion` blocks plus a summary table and quick-wins. Structure-only — no feature work mixed in, no auto-apply without confirmation, characterization tests first when coverage is missing, small focused commits. Use for cleanup or wide renames. Do NOT use for behavior changes (`fix:` or `feat:`, not refactor), green-field design (use `/arch-design`), or single-symbol single-file renames (just edit). Companion to `/add-tests` for the characterization-test prereq. +description: Scan code for refactoring opportunities or perform a targeted refactor. Seven modes — `full` (default; complexity + duplication + dead-code + simplification scans), `quick` (high-severity findings only), `complexity` (length / nesting / cyclomatic / parameter count / boolean ops with severity bands and techniques like guard clauses, extract method/predicate, parameter object, decompose conditional), `duplication` (clones / logic / constants / patterns / error-handling with extract-function / parameterize / template-method strategies), `dead-code` (imports / exports / branches / feature flags / deps with high/medium/low confidence labels), `simplification` (over-defensive guards / needless indirection / convoluted logic / redundant state / legibility rewrites — behavior-preserving clarity and size reduction, distinct from the metric-driven complexity scan), `rename old new` (codebase-wide symbol rename with reference search, preview gate, atomic commit, post-apply verification). Findings render as `[SEVERITY] Category — File / Metric / Issue / Suggestion` blocks plus a summary table and quick-wins. Structure-only — no feature work mixed in, no auto-apply without confirmation, characterization tests first when coverage is missing, small focused commits. Use for cleanup or wide renames. Do NOT use for behavior changes (`fix:` or `feat:`, not refactor), green-field design (use `/arch-design`), or single-symbol single-file renames (just edit). Companion to `/add-tests` for the characterization-test prereq. argument-hint: "[scope: full|quick|complexity|duplication|dead-code|rename old new]" --- @@ -9,11 +9,12 @@ Parse `$ARGUMENTS` to determine the operation: | Argument | Description | |----------|-------------| -| `full` (default) | Run all scans: complexity + duplication + dead code | +| `full` (default) | Run all scans: complexity + duplication + dead code + simplification | | `quick` | High-severity issues only (critical/high across all scans) | | `complexity` | Analyze code complexity: nesting, length, parameters, boolean expressions | | `duplication` | Detect duplicated logic, clone blocks, repeated patterns | | `dead-code` | Find unused imports, exports, unreachable code, dead feature flags | +| `simplification` | Find over-complicated code: redundant guards, needless indirection, convoluted logic, redundant state, legibility rewrites | | `rename old new` | Codebase-wide symbol rename with verification | If a file or directory path is included in the arguments, scope the scan to that path. Otherwise scan the project source directories (exclude vendored code, node_modules, build output, test fixtures). @@ -182,6 +183,40 @@ Group findings by category with confidence levels: --- +## Mode: Simplification + +Scan for code that's more complicated than it needs to be — a plainer, smaller, more direct expression of the same behavior. Behavior-preserving like every other mode; this targets clarity and size, not metrics (complexity mode) or repetition (duplication mode). + +### What to Check + +- **Over-defensive / redundant guards** — existence checks and fallbacks for conditions that can't occur given the actual call sites. +- **Needless indirection / unearned abstraction** — single-use closures, helpers, or wrappers; a single-use local that could inline (or a repeated expression that should be a local); a parameter always passed the same value; an option or branch never exercised. +- **Convoluted logic expressible more directly** — a manual loop that's a map/filter/comprehension; a verbose if-chain that's a lookup table; an if/else assigning a value that's a ternary; boolean expressions that simplify; redundant intermediate computations. +- **Redundant state** — a cache rebuilt every call anyway; two variables tracking the same thing; write-only "dead storage" (assigned, never read); dead flags. +- **Legibility rewrites** — named locals to expose a decision matrix obscured by indexing or chaining. No structural change, large readability win. + +For identical-twin branches and plain deletion of unreachable code, see Mode: Dead Code; for repeated literals → named constant, see Mode: Duplication. Those modes already own that detection. + +### Detection Heuristics + +- Search for guard clauses and fallbacks (null checks, default branches), then check every call site to see whether the guarded condition can actually occur +- Search for helpers, closures, and locals referenced exactly once +- Search for manual index/accumulator loops that build or filter a collection +- Search for variables assigned but never read, and for values recomputed on every call that never change + +### Rules + +- Behavior-preserving only. +- Verify against **all** call sites before deleting a guard, dropping an option, or removing "never read" state — "can't occur" and "never read" are only true relative to every caller. Never remove a guard or fallback that's genuinely reachable. +- Run the test suite after each change. +- Present findings before applying. + +### Boundary with /simplify + +`/refactor simplification` sweeps the whole tree (or a scoped path), presents findings, and applies on confirmation. The built-in `/simplify` works on the current diff and applies its lenses directly. Reach for `/simplify` on a change in flight; reach for `/refactor simplification` to sweep existing code. + +--- + ## Mode: Rename Perform a codebase-wide symbol rename. diff --git a/.claude/commands/respond-to-cj-comments.md b/.claude/commands/respond-to-cj-comments.md index 7ee3909..2f16099 100644 --- a/.claude/commands/respond-to-cj-comments.md +++ b/.claude/commands/respond-to-cj-comments.md @@ -1,5 +1,5 @@ --- -description: Scan an org file for cj comments — Craig's annotations wrapped in `#+begin_src cj: ... #+end_src` source blocks — and process each via subagent-delegated accuracy. Each item is classified instruction / question / both, then dispatched to an instruction subagent (proposes a file:line patch) or a question subagent (researches with explicit scope, reports answer + evidence + confidence). Main thread reviews proposals before editing; subagents don't write to the source file. Org-mode TODO parents flip to DOING; new content lands under timestamped subheadings one level deeper; on completion, top- and second-level tasks advance to `DONE` while deeper tasks get their heading rewritten to a dated action description (no DONE keyword), becoming an in-place event log. VERIFY tasks at any depth flip to dated log entries with body replaced by the answer or action taken. Public-facing writing (commits, PRs, Slack, email, public docs) gets `/voice personal`; private writing skips it. Summary lists handled instructions, answered questions with evidence + confidence, follow-ups, unresolved items, and an explicit clean / N-remain verdict. Anything needing Craig's input becomes a `VERIFY` task in `todo.org` (top-level or first-level child of a parent task — never deeper) rather than a separate summary file. File/URL references render as clickable org-mode links. Use when an org file accumulates cj comments. Do NOT use for general code review (`/review-code`), new work without cj comments, or trivial items. +description: Scan an org file for cj comments — Craig's annotations wrapped in `#+begin_src cj: ... #+end_src` source blocks — and process each via subagent-delegated accuracy. Each item is classified instruction / question / both, then dispatched to an instruction subagent (proposes a file:line patch) or a question subagent (researches with explicit scope, reports answer + evidence + confidence). Main thread reviews proposals before editing; subagents don't write to the source file. Org-mode TODO parents flip to DOING; new content lands under timestamped subheadings one level deeper; on completion, top- and second-level tasks advance to `DONE` while deeper tasks get their heading rewritten to a dated action description (no DONE keyword), becoming an in-place event log. VERIFY tasks at `***` and deeper flip to dated log entries with body replaced by the answer or action taken; a top-level (`**`) VERIFY instead closes as `DONE`/`CANCELLED` + `CLOSED:` like any top-level task, the answer in its body. Public-facing writing (commits, PRs, Slack, email, public docs) gets `/voice personal`; private writing skips it. Summary lists handled instructions, answered questions with evidence + confidence, follow-ups, unresolved items, and an explicit clean / N-remain verdict. Anything needing Craig's input becomes a `VERIFY` task in `todo.org` (top-level or first-level child of a parent task — never deeper) rather than a separate summary file. File/URL references render as clickable org-mode links. Use when an org file accumulates cj comments. Do NOT use for general code review (`/review-code`), new work without cj comments, or trivial items. --- # /respond-to-cj-comments — Process cj Comments in an Org File @@ -143,9 +143,9 @@ For **instructions**: - **Regular `TODO`/`DOING` at `*` or `**`** — advance to `DONE` + `CLOSED:` line; the keyword and original heading stay visible in the agenda. - **Regular `TODO`/`DOING` at `***` and deeper** — rewrite the heading to `<depth> YYYY-MM-DD Day @ HH:MM:SS -ZZZZ <past-tense description>`; drop the keyword/priority/tags. - - **`VERIFY` at any depth** — dated-heading rewrite *and* a body replacement: replace the body with either the information Craig provided (when the VERIFY was a question) or a description of the action taken (when it was an instruction / pending-decision marker). VERIFYs at `**` follow this rule even though regular `**` DONE tasks stay task-shaped — a resolved VERIFY is an answered question, not a finished task. + - **`VERIFY` — depth decides the heading.** At `***` and deeper, a dated-heading rewrite. At `**`, a terminal keyword (`DONE`/`CANCELLED` + `CLOSED:`) like any top-level task — never a dated `**` header. Either way, replace the body with the information Craig provided (when the VERIFY was a question) or a description of the action taken (when it was an instruction / pending-decision marker). - **VERIFY-answer pattern.** When a cj annotation's `parent_heading_chain` ends with a `VERIFY ...` heading (i.e., the cj sits directly inside a VERIFY task), the cj is Craig's answer to the question that VERIFY held open. The cj content is the source for the dated-rewrite body. Two shapes: + **VERIFY-answer pattern.** When a cj annotation's `parent_heading_chain` ends with a `VERIFY ...` heading (i.e., the cj sits directly inside a VERIFY task), the cj is Craig's answer to the question that VERIFY held open. The cj content is the source for the resolved body. Two shapes: - *Direct answer.* The cj body IS the answer (a value, decision, link, paste from elsewhere). Lift the cj body verbatim into the new dated body; trim filler ("okay," "approved," "yes,") that isn't load-bearing. - *Indirect answer.* The cj points at where the answer lives ("Kostya gave this in Slack — pull it from DM channel X," "see the attached doc"). Execute the instruction first (per step 3 — subagent if research is needed), then the resolved info becomes the dated body. @@ -153,7 +153,7 @@ For **instructions**: Both shapes land at the same end state: 1. Generate the timestamp with `date "+%Y-%m-%d %a @ %H:%M:%S %z"`. - 2. Rewrite the VERIFY heading to its dated form (depth-preserving) with a short summary of what got answered. + 2. Rewrite the VERIFY heading by depth: at `***` and deeper, its dated form with a short summary of what got answered; at `**`, a `DONE`/`CANCELLED` keyword + `CLOSED:` line with the heading text kept. 3. Replace the body with the resolved info (the cj body for direct, the executed result for indirect). 4. Delete the cj annotation — it's now folded into the body. Don't keep both. diff --git a/.claude/commands/start-work.md b/.claude/commands/start-work.md index d146622..85ed6b0 100644 --- a/.claude/commands/start-work.md +++ b/.claude/commands/start-work.md @@ -1,12 +1,12 @@ --- -description: Pick up a task (Linear ticket, GitHub issue, todo.org task, or a described scope) and take it through Pre-work, Claim, Justify, Approach, Implement, Verify, and Hand-off. Three user-approval gates separate the phases. Pre-work covers eligibility, a fetch-and-reconcile against the base branch, and a source-code check that the problem still exists in the tree. The Justify gate weighs benefits, costs, impact, urgency, effort, alternatives, and ticket quality. The Approach gate covers root cause, risk, refactor prerequisites, test strategy (unit, integration, e2e, pairwise, characterization), migration and backwards-compat, feature flags, commit decomposition, and branch name. Implementation uses TDD (red, green, edge cases); a refactor audit then walks every touched file against a language-agnostic checklist, fixing each finding here or filing it as a ticket, never dropping one. A verify phase exercises the feature end-to-end locally (Playwright against localhost for web, scripted manual test otherwise) before the final gate hands off to the Review-and-Publish flow in commits.md. Use when starting work on a specific task where both "should we" and "how exactly" are worth deliberating. Do NOT use for open-ended bug investigation without a clear target (use debug first), for architectural paradigm exploration (use arch-design), for architectural decision recording (use arch-decide), when the task is trivial and obvious (just do it), or when requirements are still being shaped (use brainstorm). +description: Pick up a task (Linear ticket, GitHub issue, todo.org task, or a described scope) and take it through Pre-work, Claim, Justify, Approach, Implement, Verify, and Hand-off. Three user-approval gates separate the phases. Pre-work covers eligibility, a fetch-and-reconcile against the base branch, a green-baseline suite run, and a source-code check that the problem still exists in the tree. The Justify gate weighs benefits, costs, impact, urgency, effort, alternatives, and ticket quality. The Approach gate covers root cause, risk, refactor prerequisites, test strategy (unit, integration, e2e, pairwise, characterization), migration and backwards-compat, feature flags, commit decomposition, and branch name. Implementation uses TDD (red, green, edge cases); a refactor audit then walks every touched file against a language-agnostic checklist, fixing each finding here or filing it as a ticket, never dropping one. A verify phase exercises the feature end-to-end locally (Playwright against localhost for web, scripted manual test otherwise) before the final gate hands off to the Review-and-Publish flow in commits.md. Use when starting work on a specific task where both "should we" and "how exactly" are worth deliberating. Do NOT use for open-ended bug investigation without a clear target (use debug first), for architectural paradigm exploration (use arch-design), for architectural decision recording (use arch-decide), when the task is trivial and obvious (just do it), or when requirements are still being shaped (use brainstorm). --- # /start-work: pick up a task, justify it, plan it, build it Three review gates separate the phases. The user can redirect or kill the work at each one. -0. **Pre-work.** Eligibility check, fetch-and-reconcile against the base branch, source-code check that the problem still exists. +0. **Pre-work.** Eligibility check, fetch-and-reconcile against the base branch, green-baseline suite run, source-code check that the problem still exists. 1. **Claim.** Mark in-progress, assign, label, verify project. 2. **Justify (gate 1).** Benefits, costs, impact, urgency, effort, alternatives, ticket quality. Stop for approval. 3. **Approach (gate 2).** Root cause, risk, tests, migration, flag, commit decomposition. Stop for approval. @@ -53,7 +53,7 @@ If the reference is ambiguous, ask the user to clarify before proceeding. ## Phase 0: pre-work -Three checks before claiming the task. All run before any state change — no assignee added, no label written, no status moved. If any of them disqualify the task, the rollback is free. +Four checks before claiming the task. All run before any state change — no assignee added, no label written, no status moved. If any of them disqualify the task, the rollback is free. ### 0.1 Eligibility @@ -84,7 +84,18 @@ The branch this task will be cut from must reflect the remote — otherwise the 4. If the current branch is *not* the base branch (e.g. left over from a prior task), surface and ask whether to switch before continuing. Don't auto-switch — the user may want to finish or stash WIP first. -### 0.3 Existence check (validate the problem is real) +### 0.3 Green baseline (confirm the tree starts known-good) + +Run the project's test suite now, against the reconciled base, so the baseline you build on is actually green (see the Green Baseline section in `verification.md`). This runs after 0.2 — baselining a stale tree is pointless. + +- **Green** — proceed to 0.4. +- **Red** — fix the failure first, or, when it's out of scope or needs a decision, file a tracked task with the diagnosis and carry its name forward as the only tolerated failure for this work. Surface the baseline result either way so "we started from green" is on the record. +- **No suite** — nothing to baseline. Note it and proceed (your personal/doc projects hit this). +- **Suite can't run** (no network, missing dep, sandbox limit) — that's the "When You Cannot Verify" case in `verification.md`, not a blocker. Record what you couldn't run, name the risk, and proceed. + +This baseline is the green starting point; the intentional red test you write in Phase 4 (TDD) is expected and distinct from a baseline failure. + +### 0.4 Existence check (validate the problem is real) The ticket may describe a problem the code no longer has — fixed independently of the ticket, made obsolete by another change, or never present in the first place. Read the source to confirm the problem exists in the tree as the ticket describes, before justifying or planning the fix. @@ -337,7 +348,7 @@ Follow `commits.md` exactly. Summary of the flow: ## Anti-patterns - **Skipping the pre-flight reconcile.** Cutting a new branch from a stale base means the whole task happens on top of yesterday's main. Conflicts surface at PR time instead of at the start; rebases later are noisier than a fetch up front. -- **Taking the ticket's word that the problem still exists.** Tickets age. Read the source. A `git log --grep` for a fix commit is a hint, not a check — fixes ship under all kinds of commit-message wording, and the buggy behavior may be gone for reasons that never landed in a commit titled "fix." Five minutes of source-read at Phase 0.3 saves an entire Justify-and-Approach cycle on a phantom problem. +- **Taking the ticket's word that the problem still exists.** Tickets age. Read the source. A `git log --grep` for a fix commit is a hint, not a check — fixes ship under all kinds of commit-message wording, and the buggy behavior may be gone for reasons that never landed in a commit titled "fix." Five minutes of source-read at Phase 0.4 saves an entire Justify-and-Approach cycle on a phantom problem. - **Skipping the Justify gate.** "This is obviously worth doing" is exactly what the gate exists to verify. If the answer really is obvious, the gate takes thirty seconds. - **Skipping the Approach gate.** Implementation without a plan is how scope creep happens. It is also how the user loses the chance to redirect. - **Marking a personal todo task DOING before Phase 2 approval.** Personal claims carry no teammate signal, so they wait until the gate clears — a killed task then needs no rollback. Team-tracker claims (Linear, GitHub) are the exception: they happen in Phase 1 to flag intent, but only after the prior state is recorded so the gate can restore it cleanly. diff --git a/.claude/settings.json b/.claude/settings.json index f648e44..1006916 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -49,6 +49,16 @@ } ] } + ], + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "~/.claude/hooks/ai-wrap-teardown.sh" + } + ] + } ] }, "statusLine": { |
