# Process Lessons ## Start reporting/read-only scripts without `set -e` Debugging `set -e` failures in scripts that aggregate data from multiple sources (git repos, file stats, etc.) consumed significant time — the script worked in isolated tests but failed silently on real data. Begin without `-e` and add it only for scripts that perform destructive actions where fail-fast is critical. ## Spec-driven testing catches real bugs early The spec → implement → test workflow caught real bugs during development (grep flag parsing, `local` keyword misuse, binary detection false positives). Writing tests that exercise dryrun against spec expectations is an effective pattern for this project. ## Use `cat -A` to diagnose invisible character issues When a file looks correct but tooling rejects it, `cat -A` reveals non-printing characters (e.g., `M-bM-^@M-^T` for em dashes that appear identical to regular dashes). Essential for debugging YAML frontmatter, config files, and any context where encoding matters. ## Use `git diff --numstat` for binary detection instead of `file` The `file` command is unreliable for distinguishing binary from text files (marks shell scripts as "executable"). `git diff --numstat` shows `-` for binary files and is more reliable since git already has its own binary detection heuristics. ## Verify harness capabilities before designing workarounds Before committing to workarounds for something the harness "doesn't support", verify the assumption. A 30-second check via a guide agent can prevent building multiple unnecessary workarounds. Pattern: if you're about to design around a limitation, confirm it's actually a limitation first. ## Check existing references in old scripts before extending When extending an existing script, verify that its current references actually work in the live environment. Broken references can be masked by never running certain code paths. Tests catch these immediately. ## Guard interactive `read` with `[[ -t 0 ]]` for testable scripts For bash scripts that are both interactive and testable, wrap every `read` call with `[[ -t 0 ]]` and provide a default value for non-TTY contexts. This allows the same code path to work interactively or in dryrun/test mode without `set -e` blowups. ## File-based result passing keeps driver context lean When subagents or background processes produce non-trivial results, write them to files and only `Read` into context when actually needed. This unifying pattern (sentinel files, `bg-model-call`, container agent outputs) prevents the driver's context from bloating with data it may never use. ## Always `Read` a file with the Read tool before calling `Edit` The Edit tool tracks which files have been explicitly read via the Read tool — viewing a file via Bash (`cat`, etc.) does not count. An Edit attempt on a file seen only through Bash output is rejected. When planning multiple edits, batch parallel `Read` calls first, then parallel `Edit` calls. ## `/context` "Memory files" aggregates two distinct systems The "Memory files" category reported by `/context` combines project `CLAUDE.md` instructions and auto-memory `MEMORY.md`. They have different purposes (project conventions vs cross-session learnings) and live in different places. When auditing context size, check both rather than assuming a single source.