Yesterday I laid out the case for rewriting my four deployment commands around the 1M token context window. This post covers the first and highest-impact rewrite: /commit.

If you haven’t read the deep dive on how /commit works , the short version is: it’s a 1,170-line markdown state machine that handles quality gates, review triage, agent dispatch, commit message generation, pushing, and Linear updates. One command, twelve steps.

The 1M context window didn’t change what /commit does. It changed what /commit needs to defend against. And that defense was expensive.


The Audit

I mapped every operation in /commit by type: sequential Bash calls, MCP round-trips, agent dispatches, session file writes. Then I identified which operations were sequential because they had to be (data dependency) versus sequential because they were written that way at 200K tokens when keeping context small mattered more than speed.

The results were clarifying. Three categories of waste:

  1. Independent operations running sequentially — type-check and lint, simplify agents and review agents, Linear read calls
  2. Redundant computation — the git diff computed three separate times across three steps
  3. Defensive overhead — ten session file writes during a single commit flow, most of which exist for a compaction scenario that almost never happens at 1M tokens

Six Changes

1. Parallel Quality Gates

The simplest win. Step 2 ran pnpm run type-check then pnpm run lint sequentially. Both are read-only operations that don’t modify files. They don’t depend on each other.

Before:

pnpm run type-check    # ~30s
pnpm run lint           # ~30s
# Total: ~60s

After:

pnpm turbo type-check lint --concurrency=2    # ~35s

Turbo handles the parallelism natively. Both tasks run simultaneously, bounded by whichever finishes last. The --concurrency=2 flag is explicit about what we want — it’s not a magic number, it’s “these two specific tasks, in parallel.”

Savings: ~25 seconds per commit.

2. Collapsed Simplify + Review Pipeline

This was the biggest conceptual change. Previously, /commit had a two-phase pipeline:

  1. Phase 1 (Step 2.5): Dispatch 3 simplify agents on Sonnet. Wait for all to complete. Re-stage any changes they made.
  2. Phase 2 (Step 4): Dispatch N review agents on Sonnet. Wait for all to complete.

The rationale was that review agents should see the “improved” diff after simplify fixed things. But in practice, simplify finds nothing on the majority of commits. The review agents were waiting 30-45 seconds for a phase that usually produced no changes.

After: Triage runs first (it needs the file list to determine which agents to dispatch), then ALL agents — simplify and review — launch simultaneously in a single message. In the common case where simplify finds nothing, review agents already see the final diff. If simplify does modify files, only the review agents whose findings overlap with modified files get re-dispatched.

The key insight came from a review comment on the Linear ticket: triage must run before dispatch (you need to know the review level to know which agents to launch), but triage only reads file names — it doesn’t need file content. So the sequence is: cache the diff once, run triage on the file list, then dispatch everything in parallel.

This created a new step numbering. The old Step 2.5 (Simplify) and Step 4 (Review Dispatch) merged into Step 2.75 (Parallel Simplify + Review Dispatch). The old Steps 3 and 4 still exist as documentation of the triage logic and agent selection — they just note that execution moved to Step 2.75.

Savings: ~30-45 seconds on commits where simplify finds nothing (majority). ~15-25 seconds when simplify does modify files (targeted re-dispatch instead of full re-run).

3. Cached Git Diff

The diff was computed three times:

  • Step 2.5: passed to simplify agents
  • Step 3: used for triage signal-gathering
  • Step 4: passed to review agents

Now it’s computed once in Step 2.5 (“Compute and Cache Diff”) and the cached DIFF_CONTENT and ALL_FILES variables are reused by all downstream consumers.

Savings: Tokens, not seconds. But fewer tokens means faster processing throughout the pipeline.

4. Batched Linear MCP Calls

Step 8 (Update Linear) was making 4-6 serial MCP calls: fetch the issue, update status, fetch all workspace labels, update with merged labels, fetch comments (for threading), post progress comment.

A review comment caught my initial design: I’d planned 2 messages, but list_comments needs the UUID from get_issue. The corrected design uses 3 messages:

  1. get_issue (returns UUID)
  2. list_issue_labels + list_comments (both need UUID, dispatched in parallel)
  3. save_issue (status + labels) + save_comment (dispatched in parallel)

Savings: ~5-8 seconds per commit.

5. Aggressive Learning Capture Skip

Step 1.5 scans the conversation for learnings to capture before committing. It already skipped in chain mode and short conversations. I added one more skip condition: NONE-level review triage (only docs/config changed). If you’re committing a markdown file, there’s unlikely to be a novel technical insight worth capturing.

Savings: ~3-5 seconds on doc/config commits.

6. Reduced Checkpointing

The old /commit wrote session state at multiple points throughout the flow — after quality gates, after triage, after review, after staging. With 200K tokens, this made sense: if context compacted mid-commit, the session file told you where to resume.

With 1M tokens, context compaction during a single /commit run is extremely rare. Two writes are sufficient:

  1. Entry: awaiting_user_testcommitting
  2. Exit: committingcommitted

If context does compact between these two points (unlikely but possible for enormous commits), the session shows committing and you re-run /commit — all steps are idempotent.

Savings: ~2-3 seconds per commit.

Bonus: Timing Instrumentation

A review comment on the ticket suggested adding baseline measurements before optimizing. I added COMMIT_START at Step 0 and COMMIT_DURATION at Step 10, displayed in every commit’s success summary. This gives us the “before” numbers to compare against, and — critically — feeds into the pipeline automation system (PLA-781) which uses average commit duration as an advancement criterion.


What I Learned

The biggest lesson isn’t about any specific optimization. It’s about how constraints shape architecture in ways that persist long after the constraint changes.

Every one of these sequential patterns had a reason at 200K tokens. Serializing simplify → review kept context smaller. Multiple session checkpoints enabled recovery. Separate diff computations avoided storing large strings in variables. The architecture was correct for its constraint.

When the constraint changed — 200K to 1M, a 5x increase — the architecture didn’t automatically adapt. The code still worked. It was just slow. And “slow but correct” feels fine until you measure it and realize you’re spending two minutes on overhead that could take thirty seconds.

The meta-lesson: when a foundational constraint changes by an order of magnitude, audit everything built on that constraint. Don’t fix one thing — map the entire dependency chain. I found six optimizations in /commit because I looked at every operation type, not just the one that felt slowest.


Performance Target

MetricBeforeAfter
Quality gates~60s~35s
Simplify → Review~45s serial~30s parallel (0s when nothing found)
Linear updates~12s~5s
Learning capture (doc commits)~5s0s
Checkpointing~5s~2s
Total~127s~72s

I’ll update this table with measured numbers after a week of real usage. The timing instrumentation makes that straightforward — every commit logs its duration now.


What’s Next

Three more commands to optimize: /start (parallel ticket fetch, conditional task creation, inline plans for simple tickets), /staging (parallel test+build, parallel Sentry queries, parallel worktree resets), and /production (parallel verification, slimmer health audit). Same theme throughout: identify independent operations, run them concurrently, remove defensive overhead that 1M tokens makes unnecessary.

The implementations are done — all four commands are updated. The next three posts will cover what changed and what I learned in each one.