aboutsummaryrefslogtreecommitdiff
path: root/.claude
Commit message (Collapse)AuthorAgeFilesLines
* chore: set opus as the machine-default modelCraig Jennings2 days1-5/+5
|
* feat(commands): /update-skills syncs forks with upstream via 3-way mergeCraig Jennings2 days1-0/+92
| | | | | | | | Upstream releases fixes worth pulling into the forks (arch-decide, playwright-js, playwright-py) without losing our local modifications. Each fork now has a manifest at upstreams/<name>/ plus a committed baseline snapshot that is the 3-way merge base. scripts/update-skills.py classifies each file's drift and merges to stdout. The command owns per-file confirmation, per-hunk conflict prompts, and every target write. I centralized manifests under upstreams/ instead of per-skill dotfile dirs because arch-decide is now two flat files in commands/ and can't carry one. A "files" map in its manifest handles the upstream rename of SKILL.md to arch-decide.md. I seeded baselines from today's upstream HEADs, so pre-existing local modifications classify as local-only from here on. git merge-file signals hard errors as exit 255, which subprocess reports as positive. The guard treats anything 128 and up as an error so a binary-file failure isn't misread as a conflict.
* feat(hooks): title sessions "host project" for the remote session listCraig Jennings3 days1-0/+9
| | | | | | | | Remote sessions showed up on claude.ai/code and mobile under auto-generated names, so picking the right one meant guessing. Claude Code 2.1.152+ lets a SessionStart hook set the title via hookSpecificOutput.sessionTitle. hooks/session-title.sh emits "<uname -n> <project>" (ratio rulesets, velox work) on startup and resume. Project is the git-toplevel basename so a session started in a subdirectory still names the project, with the cwd basename as fallback. The hook stays silent when a title already exists, so a /rename or an earlier run isn't clobbered on resume. The harness ignores titles on clear and compact, so the settings matcher restricts to startup|resume. Wired in settings.json and the install-hooks snippet. As a default hook it reaches every machine through make install on the next session start.
* feat(install): adopt the statusline script into the managed setCraig Jennings3 days2-0/+31
| | | | | | An archsetup session added a statusLine entry to the tracked settings.json on 2026-06-11 (Craig's request), pointing at ~/.claude/statusline-command.sh, but the script itself lived outside the repo on one machine. This commits the settings entry and brings the script into .claude/, linked by make install like the rest of the config, so it reaches every machine on the next session. Two fixes over the original: uname -n instead of hostname (Arch doesn't ship hostname by default, so the host rendered empty with stderr noise), and the tilde replacement is escaped (unquoted, bash expands the replacement ~ straight back to $HOME, which defeated the abbreviation). scripts/tests/statusline-command.bats covers the format, branch handling, and the no-stderr contract.
* chore(ai): archive session recordCraig Jennings3 days1-2/+2
|
* chore(claude): pin model to fable in settingsCraig Jennings4 days1-1/+2
|
* docs(commands): trim two command descriptions under listing capCraig Jennings11 days2-2/+2
| | | | Both descriptions ran past Claude Code's per-entry listing cap (~1536 chars), so the menu blurb got truncated. start-work was 1680, respond-to-cj-comments 1568. I trimmed them to 1513 and 1518, compressing only descriptive prose. Every "Use when" and "Do NOT use" routing trigger stays verbatim, so triggering is unchanged.
* feat(start-work): add a spec-prerequisite check to the Approach gateCraig Jennings11 days1-6/+7
| | | | The Approach gate planned tests, migration, and commits but never asked whether the work needs a design spec it does not yet have. Added item 5: a spec is warranted for large or wide-surface work, unresolved design questions, or a new interface others build on. For a big task it is never a silent skip — the approach summary must state why no spec is needed, so the call is visible and challengeable at the gate. Small contained tasks pass without comment.
* feat(start-work): add "reasons not to do this" to the Justify gateCraig Jennings11 days1-1/+2
| | | | The Justify gate covered Downsides and Alternatives but had no forced verdict on whether the work should happen at all. Added item 9: surface the top three objections when real ones exist, or say so in one line when none rise to a genuine objection, rather than manufacturing three. Building the case against the work is cheapest at this gate.
* feat(flush): add /flush skill and SessionStart(clear) resume hookCraig Jennings11 days1-0/+11
| | | | | | | | | | Flush is the checkpoint half of the wrap/restart rhythm. It refreshes the session-context anchor in place, the user runs /clear, and the session resumes from the anchor instead of starting cold. One logical session stays alive across a /clear boundary without the archive-and-commit of wrap-it-up or the full cold boot of startup, which buys cheaper tokens and a sharper context window. The mechanism splits into two halves around /clear, which wipes the conversation so nothing runs straight through it. The /flush skill is the pre-clear half: dump live state, refresh the anchor's Summary, append a dated flush marker, verify the write landed, then prompt the user to /clear. The agent can initiate at a clean task boundary on its own judgment, but /clear is user-only, so the agent does the work and the user supplies the single keystroke. The session-clear-resume.sh hook is the post-clear half, a SessionStart matcher=clear hook that points the fresh session at the anchor to resume, or at startup when no anchor exists. I packaged the pre-clear half as a skill rather than a project-workflow doc so both halves are global. The hook was already global, so /flush is now callable by name from any project with no per-project sync. The hook is canonicalized under hooks/ and symlinked into ~/.claude/hooks/, matching precompact-priorities.sh. settings.json wires the SessionStart entry, and settings-snippet.json carries it so a fresh machine wires the hook on make install-hooks.
* feat(commands): let the agent invoke codify, refactor, and ↵Craig Jennings2026-05-263-3/+0
| | | | | | respond-to-cj-comments I dropped disable-model-invocation from these three commands, the same one-line change I made to start-work. They were user-only, so the agent couldn't run them as a workflow step. Now the agent can invoke them through the Skill tool and I can still type the slash command. The remaining flagged commands stay user-only for now.
* feat(start-work): let the agent invoke it, not just the userCraig Jennings2026-05-261-1/+0
| | | | I dropped disable-model-invocation from start-work's frontmatter. The flag made it user-only, so the agent couldn't run it as a workflow step and I had to type /start-work by hand every time. Removing the line makes it invocable by the agent through the Skill tool while /start-work still works for me. Its description already carries strong "Do NOT use for..." triggers, so the auto-invoke risk stays low. The other 16 commands still carry the flag.
* feat(hooks): hard-deny the AskUserQuestion popup machine-wideCraig Jennings2026-05-261-0/+11
| | | | | | The no-popup-menus rule in interaction.md was too easy to forget, so the popup kept slipping back into choice prompts. I added a PreToolUse hook on AskUserQuestion that denies the call outright and returns the rule as the reason, which routes choices back to inline numbered lists. Since ~/.claude/settings.json symlinks to this repo's .claude/settings.json, the hook is machine-wide and version-controlled across machines. I documented it under the rule in interaction.md, including the consequence: the deny is unconditional, so the old "use the popup for this one" exception now needs the hook disabled via /hooks first.
* docs(commands): add timebox and fresh-sources rules to brainstormCraig Jennings2026-05-221-0/+7
| | | | Three audit fixes. Phase 1 gains a "Timebox the dialogue" rule, since one-question-at-a-time can run long: aim for the one-sentence restatement in roughly five to eight questions, then move to Phase 2 and park the rest as open questions. Phase 2 gains "Ground high-stakes claims in fresh sources" — check load-bearing claims about markets, regulations, tools, vendors, or current APIs against a current source, and mark what you couldn't verify as an assumption. The design-doc skeleton gains an Assumptions section that separates researched facts (with their source) from assumptions to confirm before building.
* docs(commands): make arch-evaluate findings honest about certaintyCraig Jennings2026-05-221-3/+30
| | | | Two audit fixes. Framework-agnostic findings (Claude reading import graphs) now carry a confidence level (High/Medium/Low) and how it was determined, with a required "not fully checked because" note when scale or dynamic imports cap certainty, so a partial read isn't presented as exhaustive. Unconfigured language tools are no longer skipped silently: each detected language whose tool didn't run gets an Info finding, so the audit shows what was and wasn't verified.
* docs(commands): add Q42 scenarios and staleness metadata to arch-documentCraig Jennings2026-05-221-5/+52
| | | | Two audit fixes. Section 10's thin quality-scenario template becomes the arc42/Q42 six-part form (source, stimulus, environment, artifact, response, response measure), making each scenario testable. Generated docs now carry staleness and ownership metadata: a per-section header (owner, generated-against commit and date, review cadence, stale-when conditions) and a whole-document Doc Status table, so a reader can tell whether a section still matches the code.
* docs(commands): strengthen arch-design security inputs and paradigm modelCraig Jennings2026-05-221-16/+78
| | | | Two audit fixes. A new Phase 4 (Trust, Data, and Compliance) surfaces trust boundaries, data classification, abuse cases, privacy, compliance evidence, and ownership before the paradigm shortlist, so the architecture is drawn around them rather than retrofitted by a later security-check. Phase 5 now splits the choice in two: pick one paradigm (monolith, microservices, event-driven, and so on), then compose tactical patterns onto it (DDD, hexagonal, CQRS, event sourcing), with composition examples and an anti-pattern against treating a pattern as an alternative to a paradigm.
* docs(commands): make arch-decide examples timeless, standardize ADR statusesCraig Jennings2026-05-221-4/+9
| | | | Two audit fixes. Sample ADRs asserted technical claims as timeless fact (MongoDB transactions). The example is now dated and sourced, and a "cite, don't assert" rule requires a link, version, or checked-date for any concrete technical claim. The status vocabulary was mixed (Accepted, Decided, Superseded, Not Accepted). It's now a canonical five (Proposed, Accepted, Rejected, Deprecated, Superseded) with an explicit immutability rule: an accepted ADR's body is frozen, and a changed decision gets a new superseding ADR while the old one stays as the record.
* docs(commands): make c4 skills notation-independent and level-consistentCraig Jennings2026-05-222-10/+70
| | | | Two audit fixes to c4-analyze and c4-diagram. Both treated draw.io as the only output. They now offer draw.io, Structurizr DSL, Mermaid (native C4 types), and PlantUML, with a headless fallback that emits a text notation instead of failing when drawio or a GUI is absent. Both also gained an abstraction-boundary section (a Container is a deployable unit, not a Docker container, and a Component isn't separately deployable) and a check that every element and relationship stays at the diagram's single C4 level.
* docs(commands): add tool-availability and ceremony scale to start-workCraig Jennings2026-05-221-5/+41
| | | | Two audit fixes. A "Tool availability" section degrades gracefully when Linear MCP, gh, /voice, or Playwright are missing: do what the available tools allow, surface what couldn't run, don't fail the phase. A "Ceremony scale" section sizes the process to the work, so a trivial fix skips the ticket, branch, and gates unless asked. Separately, the claim now splits by tracker: personal todo claims wait until after the Justify gate (no rollback needed if killed), while Linear and GitHub claims happen first to signal intent but record prior state so a killed task restores cleanly.
* docs(commands): fix finish-branch base detection and merge safetyCraig Jennings2026-05-221-10/+68
| | | | Two audit fixes. Base-branch detection returned a merge-base SHA where a branch name was needed. Phase 2 now resolves the branch name (open PR base, then origin/HEAD, then ask) and computes the merge-base SHA separately. Option 1's merge gained pre-flight safety: a dirty-tree refusal with no auto-stash, protected-branch awareness, an upstream-gated ff-only pull, and merge-commit-vs-rebase as a team-policy choice. Worktree detection moved from grepping branch names to a git-dir vs git-common-dir comparison.
* docs(commands): add stale-entry and privacy pre-write checks to codifyCraig Jennings2026-05-221-0/+5
| | | | codify now runs two mandatory checks before writing a CLAUDE.md entry: a stale-entry scan (update or remove a no-longer-true entry in place rather than appending a contradiction around it) and a privacy check asking "safe if the project were public?" and "belongs in private memory instead?", routing private content to auto-memory. These are gates, not background guidance.
* docs(commands): fix prompt-engineering citation and add an eval harnessCraig Jennings2026-05-221-3/+5
| | | | Two audit fixes. The Meincke citation had the wrong title and was used to imply persuasion framing improves prompt quality. It now reads as the safety caution it is: applying the principles raised an LLM's compliance with objectionable requests from ~33% to ~72%, a reason for care, not a recipe. The correct title ("Call Me A Jerk...") and SSRN id are fixed in all three spots. Critique mode also gains an eval-harness step: for fragile or production prompts, run 3-5 adversarial examples against the old and new prompt and record the delta, so quality is verified rather than asserted.
* docs(commands): align create-v2mom with Salesforce V2MOM conventionsCraig Jennings2026-05-221-38/+49
| | | | Three audit fixes. Renamed Metrics to Measures throughout to match Salesforce's term (the "vanity metrics" idiom stays, since that's the anti-pattern name). Phase 8 task migration no longer transplants the task tree into the V2MOM — tasks stay in the backlog grouped by method, and each method links to where they live, keeping strategy and execution as separate sources of truth. Obstacles now carry a mitigation, owner, and review cadence, so the section is operational rather than just candid.
* docs(commands): update security-check to OWASP 2021 + scanner toolingCraig Jennings2026-05-221-9/+22
| | | | Two audit fixes to the OWASP review. It now maps each finding to an OWASP Top 10 2021 category or a WSTG area, adding the four that were missing (Insecure Design, Software and Data Integrity Failures, Security Logging and Monitoring Failures, SSRF) with explicit checks for object and function-level authorization, SSRF URL fetches, update and dependency integrity, and logging gaps. A new optional-scanners step adds gitleaks/trufflehog, semgrep, OSV, and lockfile-diff review, with a network caveat: a scan that can't run reports "not run", never a silent pass.
* docs(commands): tighten respond-to-review PR-feedback workflowCraig Jennings2026-05-222-5/+7
| | | | | | | | | | Two audit-pass fixes to respond-to-review, plus a stale-reference tidy in respond-to-cj-comments. The Gather step fetched a flat comment list, which misses thread resolution and re-processes feedback that's already settled. It now pulls unresolved review threads via gh api graphql (skipping resolved ones), keeps REST only for top-level conversation comments, and resolves a thread only after the fix is verified. The commit guidance suggested "fix: Address review — [description]", which puts the review process into git log against commits.md and used a non-ASCII dash. It now names the actual fix and leaves the how-it-surfaced detail in the PR thread. respond-to-cj-comments lost a stale "humanizer" mention, since that skill is voice now. Two adjacent audit items came out moot: it no longer embeds an absolute path, and its humanizer/emacsclient fallback was overtaken by the /voice migration and the in-place VERIFY pattern.
* refactor(skills): convert review-code from command to skillCraig Jennings2026-05-201-401/+0
| | | | | | review-code was a command with disable-model-invocation set, so the model could never reach for it on its own. Every time a review fit the moment, the agent had to hand back to me to type the slash command. Moving it to a skill makes it model-invocable while it stays slash-invocable as /review-code. git mv keeps the file history (99% rename). The frontmatter drops disable-model-invocation and gains name: review-code; the body is unchanged. It also drops the discovery-check paragraph in commits.md, which only existed to find the command on disk when it was missing from the skills list, moot now that the skill shows up there.
* docs(start-work): encode follow-up filing placement rulesCraig Jennings2026-05-151-0/+7
| | | | | | Phase 4 step 5's "Disposition for each candidate" now spells out where to file a "file a ticket" follow-up in todo.org: siblings for epic-style parents (level-2 with level-3 children), new level-2 entries for standalone tasks. Both cases require a "Triggered by:" line so a future reader sees the origin. The placement rule lived in project memory but didn't propagate across projects. Encoding in start-work makes it cross-project default behavior.
* docs: codify depth-based completion rule + DRY the skill referenceCraig Jennings2026-05-151-5/+5
| | | | | | | | | | | | | | | Todo-format.md gets a "Completion — depth-based" section that codifies what was implicit before: top-level (* and **) DONE tasks stay task-shaped (DONE + CLOSED line), sub-tasks (*** and deeper) flip to dated event-log entries, and VERIFY is the documented exception (always dated-rewrite regardless of depth). The section includes worked examples and the rationale for depth-based over keyword-based. The cj-comments skill's completion section now references the canonical rule instead of restating the depth-based rules inline. The three-bullet recap in the skill stays as a quick scan, but the details and examples live in one place.
* docs: simplify cj-comments skill + add VERIFY placement/completion rulesCraig Jennings2026-05-151-67/+100
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Rounds of simplification on the cj-comments skill: converged on source-block-only in org files, dropped the non-org parsing entirely, factored out the mechanical parts into helper scripts (added separately in another repo), and codified the VERIFY placement + completion rules in a canonical rule file so the conventions stop being implicit. Skill (.claude/commands/respond-to-cj-comments.md): - Drop the file-type comment-marker table and the non-org multi-line continuation rule. The skill now recognizes only the org source-block form (#+begin_src cj: ... #+end_src). Craig's yasnippet keeps typing cost flat. - Defensive parsing for legacy inline cj annotations in older org files (back-compat). - Prefer the new helper scripts: step 1 calls cj-scan for structured detection; step 4 sub-step 6 calls cj-remove-block for validated removal. Both have explicit fallback paths to grep+Read / Edit. - Completion rules now split by keyword: TODO/DOING at *,** stay task-shaped (DONE + CLOSED); deeper TODO/DOING flip to dated headings; VERIFY at any depth flips to a dated heading with body replacement. - New VERIFY-answer pattern: when a cj's parent_heading_chain ends with VERIFY, the cj is the answer to that VERIFY. Lift its body into the dated rewrite (or execute the instruction first if indirect), then delete the cj. - New placement rule for new VERIFYs: sibling of the trigger heading, not a child. Climb to *** when the trigger is buried at ****+. This is the active force that keeps todo.org flat. - Rename "cj: comment" to "cj comment" in prose; preserve the literal cj: token in code examples and grep targets. Canonical rule (claude-rules/todo-format.md): - New "VERIFY tasks" section with four subsections: Placement (** or *** only), Creating a new VERIFY (sibling of trigger), Completion (dated rewrite + body replacement at any depth), Don't leave stale placeholders. - Worked before/after examples for both top-level and first-level VERIFYs.
* feat(lint-org): add /lint-org command + file design specCraig Jennings2026-05-141-0/+162
| | | | | | | | | | | | | | | A new /lint-org command at .claude/commands/lint-org.md orchestrates the elisp script: invokes it, parses the stdout plist stream, walks each judgment item with the user via inline numbered options (per interaction.md, no popup), and reports pre/post-pass deltas. Two modes: interactive (default, walks judgments now) and mechanical-only (defers them to a follow-ups file via --followups-file). The spec at .ai/specs/lint-org-skill-spec.md is the design doc that motivated this work, captured from yesterday's manual 55→1 lint pass on todo.org. todo.org gains a [#A] entry pointing at the spec.
* docs(start-work): default to bundled test + feat commits per sub-taskCraig Jennings2026-05-141-3/+3
| | | | Phase 3 commit-decomposition guidance + Phase 4 step 3 both now default to a single feat(scope): X with tests commit per sub-task rather than separate test: + feat: commits. Test + the code under test belong together for review — a reviewer sees the contract and the satisfaction in one diff instead of paging back and forth. Split into separate commits only when the test work is its own substantial review surface (characterization tests, fixture infrastructure, a new harness) or when the failing test serves as a deliberate bug-report artifact in a fix: narrative.
* docs(respond-to-cj-comments): add no-cj-token-in-replies rule + ↵Craig Jennings2026-05-141-0/+1
| | | | | | | | child-priority-sync spec Skill update: refer to processed items as "cj comments" in chat replies, summaries, and todo.org entries — never write the literal token in my output. The reason is search hygiene: Craig greps his files for the token to find pending annotations, and noise from my replies clutters that. Spec drop into inbox/: child-priority-sync-todo-cleanup.md captures the implementation recommendation for adding --sync-child-priority to todo-cleanup.el plus four open questions (sync direction, opt-out mechanism for deliberately-lower children, auto-apply vs --check, no-priority-parent edge case) Craig needs to answer before wiring it in.
* docs(respond-to-cj-comments): drop cj: placeholder under VERIFY tasksCraig Jennings2026-05-141-4/+5
| | | | A well-named VERIFY heading carries the question on its own. The empty cj: <fill-in> placeholder underneath is noise — Craig adds his own cj: annotation (inline or src-block) when he's ready to answer, and that arrival is the signal to come back and process the response.
* docs(respond-to-cj-comments): recognize org src-block cj: formCraig Jennings2026-05-141-1/+24
| | | | The skill now recognizes #+begin_src cj: ... #+end_src as a valid cj: comment shape, matching the multi-line paragraph pattern Craig uses in todo.org for longer instructions. Removal at cleanup deletes both fences plus the body.
* docs(rulesets): rename STALLED to VERIFY across skill + workflowCraig Jennings2026-05-131-6/+6
| | | | Renamed the org TODO keyword STALLED to VERIFY in respond-to-cj-comments.md (skill) and daily-prep.org (workflow). VERIFY reads as the next step rather than as a stuck state; the meaning is unchanged — items needing Craig's input.
* docs(review-code): frame code review as a coaching channelCraig Jennings2026-05-131-4/+52
| | | | Coaching guidance was buried under Inline Comment Voice at the bottom of the skill, where it read as a tone afterthought rather than the skill's purpose. This change threads it through Intent, Strengths, the Important-issue shape, Critical Rules, and Anti-Patterns so each step reads as mentoring with audit as the method.
* chore(settings): enable remoteControlAtStartupCraig Jennings2026-05-131-1/+2
|
* fix(respond-to-cj-comments): keep top/second-level tasks as DONECraig Jennings2026-05-131-2/+7
| | | | Only third-level and deeper tasks get the dated-heading rewrite. Top and second-level stay task-shaped so they remain visible in the agenda.
* feat(rules): cross-project boundary rule + cj-comments preflightCraig Jennings2026-05-131-0/+48
| | | | | | | | | | | | New `claude-rules/cross-project.md` codifies the per-project `.ai/` scope boundary. Stop-and-ask when a request targets another project's files, inline numbered options, handoff-file convention when the user opts to do it from here. `/respond-to-cj-comments` gains a section-0 preflight (boundary check before reading the target file) and a section-7 handoff step (writes the carry-forward file in the target project's `inbox/` when the boundary crossing was approved).
* feat(respond-to-cj-comments): replace /tmp summary with STALLED-task patternCraig Jennings2026-05-131-4/+11
| | | | | | | | When the run leaves something needing Craig's input (a blocker, an open question, a draft awaiting sign-off), the skill now files a STALLED task in todo.org under the relevant parent — phrased so Craig can answer inline with a cj: comment — rather than writing a long summary to /tmp and opening it in emacsclient. The STALLED task lives next to the work, surfaces in his agenda, and gets resolved inline. The chat summary still gets written as the FYI recap; the STALLED task is the durable home for action items. Also documents the DONE→dated-heading convention: when a cj:-handled TODO completes, rewrite the heading itself into a "** YYYY-MM-DD Day @ HH:MM:SS -ZZZZ <desc>" event-log entry rather than advancing to DONE. This is Craig's standing convention for todo.org and his daily-prep docs — finished tasks turn into a dated log automatically. The description block at the top of the file got a small rewrite to match: STALLED-task language replaces the /tmp-summary phrasing, and the DONE→dated-heading rule is mentioned in the org-mode-handling clause.
* chore: Claude Code settings — keep bypassPermissions default; ↵Craig Jennings2026-05-121-2/+6
| | | | | | notification/UI toggles Working copy had drifted permissions.defaultMode to "auto"; reset to "bypassPermissions" to match HEAD. Other tweaks: awaySummaryEnabled false, terminalProgressBarEnabled false, inputNeededNotifEnabled true, skipAutoPermissionPrompt true, skillListingBudgetFraction moved to top.
* docs(start-work): add Phase 0 pre-work (reconcile + source check)Craig Jennings2026-05-111-2/+51
| | | | | | | | Phase 0 was a single eligibility gate. Two gaps: the skill cut new branches from whatever HEAD happened to be, and trusted the ticket's premise without checking the tree. Two new sub-sections fix both before any state change. 0.2 fetches and fast-forwards the base branch, surfacing dirty or diverged state instead of auto-resolving. 0.3 reads the source, not git log, to confirm the problem the ticket describes still exists, with three dispositions for "the problem isn't there" findings: close, dig harder, or proceed with reduced confidence flagged at the Justify gate. Two matching anti-patterns added: skipping the reconcile, and taking the ticket's word for it.
* chore: migrate humanizer callers to /voice personalCraig Jennings2026-05-072-26/+8
| | | | | | | | | | 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.
* 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.
* 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.
* 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/+4037
| | | | | | | | 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-063-0/+309
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.