aboutsummaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
...
* feat: Add cmail IMAP action script and test suiteCraig Jennings2026-05-084-0/+1786
| | | | | | | | Add cmail-action.py for IMAP triage operations against Proton Mail Bridge (list-unread, read, mark-read, star, unstar, trash, send, folders) mirroring the Gmail MCP workflow. Also add comprehensive tests for cmail-action, gmail-fetch-attachments, and maildir-flag-manager scripts.
* feat(scripts): add readability tool + pre-warm textstat in depsCraig Jennings2026-05-082-0/+116
| | | | | | | | Adds scripts/readability — a Python tool that prints standard readability metrics (Flesch Reading Ease, Flesch-Kincaid Grade, Gunning Fog, SMOG, Coleman-Liau, ARI, Dale-Chall, Linsear-Write) for one input file or as a side-by-side comparison of two. Self-contained via PEP 723 inline metadata: textstat is declared as the script's only dependency, and the `#!/usr/bin/env -S uv run --quiet --script` shebang lets uv resolve it on each invocation. The Makefile `deps` target now also pre-warms textstat in uv's cache so the first interactive run is fast.
* feat(claude-rules): add interaction.md — no popup menus for choicesCraig Jennings2026-05-081-0/+31
| | | | | | Codify the rule that AskUserQuestion's popup menu obscures the chat text the user needs to read to make the choice. Choice prompts go inline as numbered options instead, with a "pick a number" prompt at the end. Applies to all three approval gates in commits.md (commit message, PR description, PR review reply).
* chore(ai): correct stale ~/projects/work/ path references in workflows and ↵Craig Jennings2026-05-084-5/+5
| | | | scripts
* feat(wrap-it-up): add Linear Dev-Review sweep stepCraig Jennings2026-05-081-2/+23
| | | | Sweep Dev-Review tickets assigned to Craig before the wrap-up commit. Any whose linked PR has merged gets proposed for Done (chores, refactors, test backfills, dead-code removal) or PM Acceptance (real fixes or features users can verify). Tickets stuck in Dev Review after the PR merges hide real in-progress work. The step is idempotent and skips when Linear is not in use.
* feat(make): add bootstrap target for fresh-machine setupCraig Jennings2026-05-081-0/+9
| | | | Bootstrap chains install, install-hooks, and install-mcp into one command. The three targets stay split so routine re-symlinking stays cheap (no GPG pinentry, no network), but bootstrap gives the fresh-install case one entry point. The gap surfaced on a fresh machine where doctor flagged 4 hook warnings and 8 MCP failures.
* docs(todo): add follow-ups for category-3 rules and language-rule auditCraig Jennings2026-05-071-0/+19
| | | | | | | Two open decisions from the 2026-05-07 rulesets centralization pass: - Category-3 rule copies in the deepsat tree (`coding-rulesets/` and `orchestration_dashboard_mvp/`) — read each and decide between leave, sync, or symlink. - Language-specific rule files (python-testing, typescript-testing, elisp-testing, elisp) duplicated across multiple project mirrors — audit and possibly canonicalize.
* fix(commits): anchor .ai/ detection to repo root with :/ pathspecCraig Jennings2026-05-071-2/+4
| | | | | | | | The detection command for personal vs. general voice mode used `git ls-files .ai/`, which returns no matches when run from a subdirectory of the repo, even when `.ai/` is tracked at the root. That silently misclassified projects as personal-voice when they should have been general-voice. Switching to `git ls-files :/.ai/` anchors the search to the repo root via the `:/` pathspec, so the command works correctly from any cwd. I hit this myself today: ran the check from `claude-rules/` inside the rulesets repo, got an empty result, and applied `/voice personal` to a commit that should have used `/voice` (general mode).
* docs(commits): add bundled-review shape, voice mode gating, drop humanizerCraig Jennings2026-05-071-16/+101
| | | | | | | | I rewrote the PR review subflow into three explicit shapes. Shape 1 is a single review that bundles the verdict, the summary body, and zero or more inline pins into one `gh api .../reviews` call. Shape 2 is an issue-thread comment with no verdict. Shape 3 is a reply on an existing inline thread. The single-review path replaces the prior pattern where a Request-Changes verdict with line-specific findings needed separate `gh pr review` + `gh pr comment` calls. That fragmented the Slack notification and the review history. I migrated all `humanizer` references to `/voice personal`. The voice skill replaced humanizer, so the old name was dead. I dropped the two lineage mentions of "humanizer's signs of AI writing" since they pointed at a skill that no longer exists. I added a Voice mode and approval gate preamble at the top of Step 2. The mode is decided by whether `.ai/` is tracked in the repo. Gitignored or absent means personal-voice with the full approval gate. Tracked means general-voice and the gate is skipped, since the personal-only patterns (first-person rewrite, contractions, semicolon swap) don't fit a shared rules file. I also updated the Single-skill gate wrap-up paragraph at the end of Step 2 to reference both modes.
* feat: voice skill, make doctor, MCP token bundlingCraig Jennings2026-05-072-151/+310
| | | | | | | | Voice skill consolidates the prose-quality passes (humanizer plus universal good-writing rules plus personal-style) into one /voice invocation with two modes. General mode for arbitrary writing. Personal mode for commit messages, PR descriptions, and PR review comments. The standalone humanizer skill is retired. make doctor verifies ~/.claude/ live state matches the repo and settings.json. Eight checks covering skills, rules, hooks, settings.json hook references, plugins, MCP server registrations, and dangling symlinks. The MCP install pipeline now bundles Google Docs OAuth tokens alongside the GCP keys, so a fresh machine boots fully connected after make install-mcp without requiring a manual OAuth dance per profile.
* chore(skills): remove humanizer (superseded by voice)Craig Jennings2026-05-074-476/+212
| | | | | | | | I deleted humanizer/SKILL.md now that all three callers (commits.md, respond-to-cj-comments.md, start-work.md) invoke /voice instead. The 25 humanizer patterns live on as patterns 1-25 in voice/SKILL.md. Same source (Wikipedia's Signs of AI writing), same prose, same examples — just renumbered alongside the universal good-writing additions and the personal-only patterns. I also updated .ai/notes.org and .ai/workflows/wrap-it-up.org to reference /voice personal instead of the old humanizer + manual-passes flow. The wrap-it-up change landed upstream in claude-templates first so it survives the next startup rsync. todo.org gets the matching update: the voice TODO is marked DONE with a "Built and shipped" timestamp, the publish-mode terminology is renamed to personal-mode throughout, the V1 scope checklist is ticked, the open questions are resolved with the answers we landed on during implementation, and the migration section records the delete-not-alias decision.
* chore: migrate humanizer callers to /voice personalCraig Jennings2026-05-073-51/+30
| | | | | | | | | | I switched the three publish subflows in commits.md (commit messages, PR descriptions, PR review comments) from "run humanizer; apply five personal-style passes in order" to a single "run /voice personal" invocation. The new skill walks 39 patterns in one editorial review and absorbs the five passes wholesale, plus four more personal-style additions (felt-experience cut, fragment-in-prose rewrite, terse cut, public-artifact scope flag) and six universal good-writing patterns. The numbered steps in each subflow collapse from 5 to 4 (commits) and 9 to 8 (PRs) since the dedicated personal-style step folds into the voice invocation. The Multi-pass gate paragraph becomes a Single-skill gate. The mid-flow "all the passes" prompt now means re-run the full 39-pattern walk in personal mode rather than reapplying six discrete steps. I also updated respond-to-cj-comments.md to invoke /voice personal for public writing and /voice general for the lighter pass on internal notes when wanted, and updated start-work.md's Phase 7 summary to match. The humanizer skill itself stays in place for now. The next commit removes it.
* feat(skills): add voice skill (humanizer + universal + personal passes)Craig Jennings2026-05-071-0/+635
| | | | | | | | I built voice as a single skill that walks 39 numbered prose-editing patterns. The first 25 patterns come straight from the existing humanizer skill (Wikipedia's Signs of AI Writing). Patterns 26-31 add universal good-writing rules from Strunk & White, Orwell, the Plain English Campaign, and Garner — long-word → short-word, active-over-passive, comma splices, cliché flag, jargon-fragment-in-prose rewrite, and corporate-speak nominalizations. Patterns 32-39 are tagged "personal only" and cover first-person rewrite, semicolon swaps, contractions, sentence-split on conjunctions, felt-experience cut, sentence-fragment-in-prose rewrite, terse cut for rhetorical padding, and a public-artifact scope flag. Two modes determine which patterns get walked. General mode (default) walks 1-31 and is the right fit for research notes, philosophy and history essays, emails, README prose, journal entries, anything that isn't a commit, PR, or PR review comment. Personal mode walks all 39 patterns and is invoked explicitly by the publish flow in commits.md (and similar callers) so first-person and contraction enforcement don't leak into academic or literary writing where they don't belong. The follow-up commits migrate callers to /voice and remove the standalone humanizer skill.
* feat(make): add doctor target for ~/.claude drift detectionCraig Jennings2026-05-073-1/+264
| | | | | | | | | | | | =make doctor= scans =~/.claude/= and reports drift against the repo + settings.json. Read-only diagnostic. Eight checks cover skills, rules, default hooks, claude config, settings.json hook references, enabledPlugins, MCP server registrations, and dangling symlinks. Each line prints =ok= / =WARN= / =FAIL= with a final summary. Exit 1 on any FAIL. A sweep last night found =~/.claude/hooks/= didn't exist on this machine even though =settings.json= referenced a PreCompact hook there. Compaction would have silently failed to invoke it. doctor catches that kind of drift in one command instead of relying on a manual look. The MCP drift check reads =~/.claude.json= directly rather than parsing =claude mcp list=. The CLI has no JSON output and runs a per-server health probe (~10s). The JSON file is the user-scope source of truth for registrations and parses in well under a second. I verified by injecting four drift scenarios — removed hook symlink, removed skill symlink, moved-aside plugin data dir, unregistered MCP server. Each produced the expected =FAIL= line and exit 1. After restoring state, doctor came back clean (33 ok). Bundling four other improvement TODOs from the same sweep — =mcp/README.org=, =make uninstall-mcp= and =mcp/install.py --check=, a README.org section for the MCP install pipeline, and a token-rotation helper for =@a-bonus/google-docs-mcp= OAuth refresh. Plus a stale-bullet note on the existing =make remove= TODO (the bridge symlink it references was removed earlier).
* chore(mcp): mark install.py executableCraig Jennings2026-05-061-0/+0
| | | | The shebang was already there but the file mode was 644. The Makefile invokes via "python3 mcp/install.py" so it worked anyway, but the mode now matches the shebang.
* chore(ai): sync template updates from claude-templatesCraig Jennings2026-05-065-5/+12
| | | | | | I added a "Shell aliases (=ls= → =exa=)" note to protocols.org so future sessions know to use \ls when capturing ls output programmatically. exa prints nothing to non-TTY pipes, so the symptom looks like an empty directory. I hit this earlier in the session when a sweep came back blank for a directory I knew was populated. I also fixed three stale ~/projects/career/ examples in cross-agent-comms/ docs that didn't get updated when career was renamed to work, and the daily-prep.org path leak from last session (~/code/deepsat/... → ~/projects/work/deepsat/code/...). The authoritative edits live in claude-templates. These rulesets snapshots landed via the standard rsync from upstream.
* chore(make): remove unused claude-rules bridge symlinkCraig Jennings2026-05-061-18/+0
| | | | | | The bridge at ~/.claude/skills/claude-rules existed so a SKILL.md could resolve a relative path like ../claude-rules/testing.md from the install layout. No SKILL.md actually uses that pattern. Every reference I grepped — across debug, add-tests, and pairwise-tests — names the rule file by bare filename in prose, which doesn't go through any link. The symlink was defensive scaffolding for a use case that didn't land. The four rule files keep loading via ~/.claude/rules/ unchanged. Claude Code's skill harness was silently ignoring the bridge anyway because the target directory has no SKILL.md, so no behavior moves except that make install stops creating the dead entry. If a future SKILL.md wants deep-linking, the bridge can come back deliberately.
* feat(mcp): add user-scope MCP install pipelineCraig Jennings2026-05-065-1/+230
| | | | | | | | | | I needed a single source of truth for MCP server registration so a fresh machine boots with the full set instead of being rebuilt by hand. install.py decrypts mcp/secrets.env.gpg, expands ${VAR} placeholders in mcp/servers.json, and runs claude mcp add --scope user for anything not already registered. Idempotent. The encrypted bundle carries six values: the Google client id and secret, the Figma API key, the GCP OAuth keys JSON (base64), and the two @a-bonus/google-docs-mcp token caches (personal and work, base64). install.py writes the keys file and the two token files to the paths each package reads at startup, all mode 600. Bundling the Google Docs tokens lets a new machine connect google-docs-personal and google-docs-work without the interactive OAuth flow. Without the cached token, the package falls back to a browser-redirect flow that Claude Code's stdio MCP loader can't drive, so it shows "Failed to connect" until the user runs the npx command manually. Make target: install-mcp. Plaintext secrets and the decrypted keys file are gitignored.
* chore(ai): initialize project notes and Claude tooling surfacesCraig Jennings2026-05-0670-0/+11660
| | | | Replace the seed notes.org with project-specific context (layout, install modes, task tracker location, recent inflection point). Bring in the synced template surfaces (protocols, workflows, scripts, references, retrospectives, someday-maybe) as tracked content for this content/documentation project.
* chore(claude): bump skillListingBudgetFraction to 5%Craig Jennings2026-05-061-2/+3
| | | | Default 1% of context maps to ~8K chars (the floor). The current skill listing totals ~10K chars and overflows on small-context models, triggering the truncation warning. Bumping to 5% leaves headroom even with the model-invocable skills' full descriptions present, and the file-based skill descriptions are now <=1000 chars each.
* chore(commands): mark user-invoked commands disable-model-invocationCraig Jennings2026-05-0617-1/+30
| | | | Add disable-model-invocation: true to the user-triggered slash commands so the harness drops their descriptions from the model's preloaded skill listing while keeping /<name> routing intact. Skills meant for model recommendation (add-tests, debug, five-whys, frontend-design, humanizer, pairwise-tests, playwright-js, playwright-py, root-cause-trace) are unchanged.
* docs(skills): tighten descriptions under 1000 charsCraig Jennings2026-05-064-3/+8
| | | | Trim each long description to <=1000 chars while preserving content (phases, when-to-use, when-not-to, companion references). Frees enough per-session skill-listing budget to quiet the truncation warning on small-context models.
* feat(languages): add typescript bundle (Vitest-canonical)Craig Jennings2026-05-061-0/+214
| | | | Mirrors the python bundle's minimal shape: one language-specific file under claude/rules/. Vitest is canonical, with brief notes for Mocha+Chai and Angular Karma legacy idioms. Covers RTL query priorities, MSW for network mocking, it.each for parametrize, async patterns, and TS-specific discipline (no any in tests, prefer satisfies, etc.).
* feat(make): fzf-pick LANG when not set, mirror project pickerCraig Jennings2026-05-061-8/+29
| | | | Add a pick_lang_shell macro that fzf-picks from $(LANGUAGES) when LANG isn't set, mirroring pick_project_shell. Wire it into install-lang and diff so both vars are now optional. Blank $(LANG) when its origin is environment, since LANG is the standard POSIX locale env var and Make would otherwise inherit "en_US.UTF-8" and bypass the picker.
* feat(hooks): make destructive-bash-confirm opt-inCraig Jennings2026-05-061-3/+16
| | | | | | | | | | I added an OPTIN_HOOKS list in the Makefile and excluded those entries from the default install-hooks recipe. destructive-bash-confirm.py is the first opt-in. The recipe now prints the exact ln -s command for each opt-in so users can wire individual ones without consulting docs. uninstall-hooks and list still iterate the full HOOKS list so they keep handling opt-ins that someone has manually linked.
* chore(claude): unwire destructive-bash-confirm hookCraig Jennings2026-05-061-11/+0
| | | | | | | Removed the PreToolUse → Bash hook entry from settings.json. The hook script stays in hooks/ for other machines that may want it. The local ~/.claude/hooks/destructive-bash-confirm.py symlink was also removed on this machine.
* docs(todo): add make-remove fzf-picker taskCraig Jennings2026-05-061-0/+1130
| | | | | | Captures the design discussion for an interactive Makefile target that lists installed rulesets and removes selected entries via fzf. Granular alternative to the bulk make uninstall.
* fix(commands): drop leftover name: frontmatter from converted commandsCraig Jennings2026-05-0613-13/+0
| | | | | | | | The conversion commit ran sed -i to strip the name: line, but the staged version from git mv was captured before the sed ran. Result: the commit shipped the original frontmatter, and the sed cleanup was sitting in the working tree. This commit lands the cleanup that should have been in aa69245.
* refactor(skills): convert 16 user-invoked skills to commandsCraig Jennings2026-05-0617-0/+0
| | | | | | | | I converted 16 user-invoked skills to commands. Skills cost ~150-300 tokens each per session for descriptions the model uses to auto-route. Commands cost nothing until you type the slash. These 16 are workflows I always trigger deliberately. The auto-routing wasn't earning its keep. This reclaims ~4-5k tokens per session. Nine skills stayed where auto-routing genuinely helps: debug, root-cause-trace, five-whys, add-tests, frontend-design, humanizer, playwright-js, playwright-py, and pairwise-tests. Pairwise-tests stays a skill because its helper files don't fit a single-file command shape. For arch-decide, I preserved the upstream MIT LICENSE alongside the command at .claude/commands/arch-decide.LICENSE so attribution stays intact.
* feat(claude): add claude config and wire it into make installCraig Jennings2026-05-065-7/+376
| | | | | | | | I moved Claude Code's user-level config into this repo so it travels with rulesets across machines instead of being machine-specific. The three pieces are settings.json, .mcp.json, and commands/refactor.md. I extended make install, uninstall, and list to handle the new .claude/ directory. The wildcard for CLAUDE_CONFIG matches both `*.json` and `.*.json` because make's glob skips dotfiles by default. Without the dot variant, .mcp.json wouldn't get picked up. I also added settings.local.json to .gitignore. That file is per-machine by convention and shouldn't ever land in the shared repo.
* feat: add humanizer skillCraig Jennings2026-05-061-0/+474
| | | | I moved this in from another repo so it sits alongside the rest of the skills here. The file content is unchanged.
* refactor(debug): make debug a triage router, align specialist cross-refsCraig Jennings2026-05-063-30/+36
| | | | I sharpened the debug skill so it stops duplicating root-cause-trace and five-whys. Phase 1 captures evidence and stops there. Phase 2 routes to the right specialist instead of asking why three times inline. Phases 3 and 4 keep the verify-and-fix discipline. I also updated the companion lines in root-cause-trace and five-whys so all three descriptions stay in sync.
* docs(commits): require @-mention of PR author in Slack notifyCraig Jennings2026-05-021-3/+3
|
* docs(commits): keep follow-up approvals terseCraig Jennings2026-05-021-0/+2
|
* docs(commits): drop "on" from Slack notify templatesCraig Jennings2026-05-021-2/+2
|
* docs(commits): add first-person voice as a personal-style passCraig Jennings2026-05-011-5/+5
| | | | | | I told Claude that the commit-message draft should sound personal, like it's coming from me. That move wasn't in the documented passes, so the drafts kept landing on impersonal third-person ("Add a test for X", "The change introduces Y"). I had to ask for the rewrite each time. First person is now the new pass (a) in all three subflows: commit messages, PR descriptions, PR review comments. The subject line and PR title stay imperative per Conventional Commits, and I left an exception for purely mechanical bodies where the subject already carries the message. I bumped the Multi-pass gate counts and the example announcement string to match.
* docs(commits): add post-review Slack notify + approve-vs-merge noteCraig Jennings2026-05-011-0/+7
| | | | | | | | Step 8 of the PR review/publish flow now sends a one-line message to channel C0AM2MWHCJU after every approve or changes-requested verdict. The new step skips humanizer and personal-style passes since the message is short and templated. The approve case sends "Approved on PR #N." with the PR URL on the next line. The changes-requested case sends "Changes Requested on PR #N" with the PR URL on the next line. I also added an explicit line saying approve doesn't authorize a merge. That keeps the merge decision with the PR author. The team's practice is approve-then-author-merges, not approve-and-merge.
* chore(build): wildcard SKILLS, claude-rules bridge symlink, link lintCraig Jennings2026-04-262-5/+54
| | | | | | | | | | The refactor scan flagged three install/lint problems. I fixed all three. - The Makefile SKILLS list was hand-maintained and had drifted: `respond-to-cj-comments` exists on disk but wasn't installed by `make install`. I replaced the list with `$(patsubst %/SKILL.md,%,$(wildcard */SKILL.md))` so every directory containing a SKILL.md is picked up automatically. - Cross-references in installed skills point at `../claude-rules/foo.md`. The install layout puts rules at `~/.claude/rules/`, not `~/.claude/skills/claude-rules/`, so those links resolved in the source repo and silently broke at install. I added a bridge symlink to the install target. `~/.claude/skills/claude-rules` now points at the source `claude-rules/` directory, so the same relative path works in both layouts. - I extended `scripts/lint.sh` with a `check_md_links` function that validates `claude-rules/` cross-references in `claude-rules/*.md` and `*/SKILL.md`. Scoped narrowly on purpose: skill bodies cite illustrative file names (ADR templates, arc42 sections) that aren't real source files and would generate noise. Verified locally: `make install` is idempotent, the bridge resolves the previously-broken link, and `bash scripts/lint.sh` is clean.
* docs(commits): Conventional Commits spec + terminal-first reviewCraig Jennings2026-04-261-64/+135
| | | | | | | | | | | | | | | | | I reworked commits.md with two structural shifts and five smaller rule changes. Structural: - Drafts print inline in the terminal. `emacsclient` only opens when asked. Was: editor by default, humanize after. - Adopted the full Conventional Commits spec. New sections: Structure, Types, Scope, Breaking changes (`!` and `BREAKING CHANGE:` footer), Subject line, Body, Footers, How to write, Examples. Smaller: - Personal-tooling files (`claude-rules/*.md`, any `CLAUDE.md`, `.claude/`, `.ai/`, `SKILL.md`) aren't cited as authority in shared messages. State the reason, not the rule. Carve-out for when one of these files IS the change. - Voice and Focus opens with a colleague-tone framing. Four anti-patterns called out below it: no felt-experience narration, no verb-as-noun ("the ask", "a learn"), no sentence fragments in prose, and no first-person "I" for software behavior — all caught real drafting tics today. "Brief. Terse is fine." also tightened to "Brief. Terse is preferred." - Future-debugger framing added to message-writing guidance. Imperative summaries beat diary notes, and the body becomes a lightweight decision log of the constraint or tradeoff. - PR titles end with the ticket ID in parens, e.g. `refactor: drop dead check (SE-289)`. - Multi-pass gate tightened to match the new mandatory ordering.
* docs(testing): rewrite time-mocking helper rule to be language-agnosticCraig Jennings2026-04-251-7/+15
| | | | | | | | The original phrasing leaned on Lisp terms (let-bind, defvar) that don't translate to most other languages. Generalize to two named failure modes (infinite recursion against the mocked primitive, scope-shadowing that production callers can't see) with examples across Python, Lisp, Go, and JavaScript so the rule applies regardless of stack.
* docs(commits,testing): add merge strategy + multi-pass gate + time-mocking ↵Craig Jennings2026-04-252-0/+31
| | | | | | | | | | | | | | | | | safety commits.md gets two additions. A new "## Merge Strategy" section makes squash-merge the default for feature branches and requires explicit confirmation of the merge approach before pushing or merging. A new "Multi-pass gate" paragraph in Review and Publish requires every humanizer-flow pass to run and be named when declaring done, so silent skips become defects. testing.md gets a new bullet under "### Determinism": time/clock-mocking helpers must not recurse against the primitive they're mocking, and must not let-bind over a defvar — the binding shadows only inside the test scope, so production code reading the symbol still gets the original value (silent test miss).
* docs: split Linear vs PR structure; propagate content-scope rule to Tier 1 ↵Craig Jennings2026-04-249-5/+52
| | | | | | | | | | | | | | | skills Linear ticket bodies are now Problem + Fix only. PR descriptions keep the four-section format (Problem, Fix, Why this fixes it, How it was tested). Linear's GitHub integration handles the cross-link via the PR body's Linear: line. Cross-ref to the content-scope rule appended at the end of each Tier 1 skill that produces public artifacts: testing.md, arch-document, arch-decide, arch-design, review-code, respond-to-review, brainstorm, codify. Single-source the rule in commits.md, point at it from each output-producing skill.
* docs(commits): add content scope rule for public artifactsCraig Jennings2026-04-241-0/+27
| | | | | | | | PR descriptions, Linear ticket bodies, and PR review comments are visible to the team. New section codifies what not to mention (local paths, private repos, personal tooling) and a concise four-section structure for shipped-fix descriptions: Problem, Fix, Why this fixes it, How it was tested.
* docs(commits): require explicit reviewer requests on PR creationCraig Jennings2026-04-241-3/+12
| | | | | | | | | Adds step 7 to the Review-and-Publish PR-description flow: pass --reviewer at create time or use gh pr edit --add-reviewer right after. Notes that CODEOWNERS auto-suggestions aren't requests, that picking reviewers should follow the team's per-repo convention, and that follow-up PRs benefit from tagging the parent PR's author. Renumbers the Linear-comment and Dev-Review status steps accordingly.
* feat: add respond-to-cj-comments skillCraig Jennings2026-04-231-0/+232
| | | | Scans a file for cj: annotations (Craig's in-line instructions and questions) and handles each one with subagent-delegated accuracy. Classifies each comment as instruction or question, spawns subagents per item, applies changes from the main thread, and produces a structured summary. Covers the voice and attribution discipline for any public-facing writing the skill produces, a long-summary-to-file pattern that writes to /tmp/ and opens in emacsclient when the output runs long, and a requirement that every file path in the summary is a clickable org-mode link.
* refactor: scope start-work refactor audit to every touched fileCraig Jennings2026-04-231-13/+17
| | | | The old "refactor pass" framed the step as a polish over new code. Expanded to "refactor audit" — walks each touched file against the checklist, top to bottom, and every finding lands somewhere: fixed on this branch or filed as a ticket. Drops "skip" as a first-class disposition. Tightens Phase 6 gate 3 to require filed ticket IDs, not just surfaced intent.
* docs(commits): codify voice rules + PR-comment publish flowCraig Jennings2026-04-231-10/+22
| | | | | | | | Three new paragraphs under "Voice and Focus": first person where it fits, brief/terse, kind. The section now applies to PR comments (review replies, follow-up notes, thread responses) as well as commit bodies and PR descriptions. New "For PR review comments and replies" subsection under Step 2 mirrors the commit-message and PR-description flows: draft to /tmp/pr-<N>-comment.md, humanizer skill, plain-English pass, user approval, then post with the right gh command for the comment type. The trivial-one-liner exception at the bottom of Step 2 now covers acknowledgment-style replies ("thanks for the review") alongside trivial commits.
* docs(commits): add Voice and Focus, expand humanizer checklistCraig Jennings2026-04-221-2/+29
| | | | | | Added a new Voice and Focus section between Commit Message Format and Review and Publish. It covers three rules that kept coming up in practice. Write in the user's voice — first person fits, and "This PR introduces X" reads as press-release self-narration. Focus on what was wrong and what was corrected, not the mechanics. Don't stack three or more type signatures or API names in a single sentence. Also extended the post-humanizer checklist in both the commit-message and PR-description flows. Items (c) "prefer contractions" and (d) "break up long sentences" now sit alongside the existing (a) "rewrite dev-jargon" and (b) "replace semicolons". Uncontracted English reads stiff in short prose, and stacked-clause sentences read easier split on a conjunction.
* chore: remove fix-issue skill, superseded by start-workCraig Jennings2026-04-225-63/+4
| | | | | | | | | | | | The fix-issue skill has been replaced by start-work, which covers the same ground (picking up a ticket with a known fix and carrying it through to handoff) with a seven-phase structure and three user-approval gates. Deleted fix-issue/SKILL.md and swept the references. Updated: - Makefile SKILLS list: remove fix-issue, add start-work so make install creates the right symlink. - brainstorm/SKILL.md: implementation-path list points at start-work. - debug/SKILL.md description: both "do NOT use for ticket-driven work" and "Companion to" references updated. - review-code/SKILL.md description: "drafting implementation" redirect updated. No change in meaning. Every old fix-issue context now names start-work.
* docs(commits): add review-and-publish flow, tighten message conventionsCraig Jennings2026-04-221-0/+87
| | | | | | | | | | Three additions to claude-rules/commits.md. A new conventions section adds two rules. First, do not hard-wrap commit body lines. Let the renderer soft-wrap instead. Hard wraps shrink the visible width in web UIs and cause awkward mid-sentence breaks. Second, do not reference how the change was produced (code review, linting, test runs) in the message. The body is for the what and the why. The how belongs in the PR discussion. A new Review and Publish section defines a two-step gate for every commit and PR. Step 1 runs /review-code against the change and blocks on Critical or Important findings unless the user overrides. Step 2 drafts the message to /tmp, opens it in the user's editor, runs the humanizer skill, and waits for explicit approval before committing or pushing. PRs also require a Linear cross-link line, a Linear comment with the PR URL after creation, and a status transition to Dev Review. A short hook-level authorization note clarifies that the review-plus-approval flow is the authorization gate. Tools like git-commit-confirm should not add a second independent prompt once Step 2 has been approved.