<!-- totem:generated:start -->
<!-- Auto-generated by `totem compile --export`. Do not edit between these markers. -->

## Totem Project Rules

- **2026-02-28T22:42:43.291Z** - When OpenAI embedding API returns 429, fall back to Ollama with nomic-embed-text for local development. The chunking pipeline is provider-agnostic — only the embedding step changes. _(embedding, ollama, openai, dogfood)_
- **2026-03-02T09:18:21.039Z** - When the LanceDB schema defined in `@mmnto/totem` changes (e.g., renaming a column from `filepath` to `filePath`), running `totem sync` against an existing `.lancedb/` directory will crash with a Rust schema error from `lance-datafusion`. Because the index is treated as a disposable build artifact rather than a migratable database, the solution is to explicitly delete the `.lancedb/` folder (`rm -rf .lancedb`) and re-run the sync. _(lancedb, schema, trap, dogfood)_
- **2026-03-02T09:18:21.052Z** - When executing external shell commands (like invoking the Gemini CLI orchestrator) on Windows, passing large prompts directly via string concatenation will fail with an 'argument list too long' error. You must write the prompt to a temporary file and pass the filepath. Crucially, the filepath placeholder in the shell command must be wrapped in quotes (e.g., `"{file}"`) to prevent crashes when the user's root directory contains spaces (e.g., `C:\Users\John Doe\`). _(cli, windows, shell, trap)_
- **2026-03-02T09:18:21.092Z** - When generating temporary files for an AI agent to read (such as orchestrator prompts), do NOT use the global OS temp directory (`os.tmpdir()`). Secure MCP clients (like the Gemini CLI) run with strict workspace boundary restrictions and will throw a 'Path not in workspace' error if asked to read a file outside the project root. Always write temporary agent files inside the project directory (e.g., `.totem/temp/`). _(mcp, security, trap, gemini)_
- **2026-03-03T01:51:33.783Z** - Gemini CLI `-o json` flag returns structured output with `response` (content) and `stats.models.<model>.tokens` (input, candidates, cached, thoughts, tool) plus `stats.models.<model>.api` (totalRequests, totalLatencyMs). Use try-parse on stdout rather than string-matching the command for `-o json` — handles edge cases and doesn't require config awareness. _(gemini-cli, orchestrator, telemetry, json-output)_
- **2026-03-03T01:52:00.000Z** - Gemini CLI injects ~8,000+ tokens of its own system prompt overhead even with `-e none`. A trivial 5-word input costs 8,254 input tokens. This "base tax" means telemetry token counts will always look inflated relative to our actual prompt content. Important context when evaluating cost — don't panic at high input token counts. _(gemini-cli, quota, tokens, overhead)_
- **2026-03-03T01:52:10.000Z** - Gemini free-tier quota is rate-limited by requests per rolling 24h window, NOT by tokens. A 5KB prompt and a 55KB prompt cost the same — one call. Caching (reducing call count) is the highest-leverage optimization, not prompt size reduction. _(gemini-cli, quota, rate-limiting, caching)_
- **2026-03-03T01:52:20.000Z** - `totem shield` must fall back to branch diff (`main...HEAD`) when no uncommitted changes exist, otherwise it's useless after committing. Use `getDefaultBranch()` to dynamically detect the base branch via `git symbolic-ref refs/remotes/origin/HEAD` with main/master probe fallback. Throw (don't silently return 'main') if detection fails entirely. _(shield, git, branch-diff, fallback)_
- **2026-03-03T02:16:24.772Z** - When spawning a background child process with output redirected to a log file, use `fs.openSync(path, 'a')` to get a synchronous file descriptor instead of `fs.createWriteStream()`. The WriteStream's `fd` is `null` until the async 'open' event fires, which causes `spawn()` to reject the stdio argument. Close the FD in the parent after spawning — Node duplicates it for the child. _(spawn, stdio, writestream, trap, windows, mcp)_
- **2026-03-03T03:20:15.922Z** - Distinguish between a missing binary (`ENOENT`) and a command execution failure when wrapping CLI tools to prevent silent, incorrect fallbacks. Swallowing all errors can lead to generic defaults being used when the environment itself is misconfigured, delaying the diagnosis of a missing dependency. _(git, cli, error-handling)_
- **2026-03-03T03:20:15.923Z** - Use nullish coalescing (`??`) instead of logical OR (`||`) when defaulting numeric metrics like latency or token counts, as `||` incorrectly triggers the fallback for valid `0` values (e.g., cached responses). This prevents inaccurate telemetry where a real zero-value is replaced by a wall-clock fallback. _(typescript, telemetry, trap)_
- **2026-03-03T03:20:15.923Z** - Return `null` instead of `0` when an external API fails to provide a metric to avoid ambiguity with valid zero-value measurements. This allows downstream logic to accurately detect missing data and decide when to employ alternative calculation methods like wall-clock time. _(telemetry, metrics, data-parsing)_
- **2026-03-03T03:20:15.923Z** - Throw an explicit error if a required environmental configuration (like a repository's default branch) cannot be detected, rather than returning a hardcoded fallback. Hardcoded fallbacks like 'main' cause confusing downstream failures if the assumption is incorrect for the user's specific environment. _(git, cli, validation)_
- **2026-03-03T03:20:15.923Z** - Isolate `JSON.parse` in its own try/catch block when processing external CLI output to differentiate between malformed JSON and logic errors in subsequent schema validation. This improves error precision by separating raw parsing failures from structure mismatches. _(telemetry, zod, maintenance)_
- **2026-03-03T03:20:15.923Z** - For rough diagnostic summaries or progress indicators, `string.length` is often sufficient for size approximations in primarily English/ASCII contexts. Avoiding byte-precision calculations for non-critical displays reduces code complexity when the difference is negligible for the use case. _(cli, design-decision)_
- **2026-03-05T03:12:04.126Z** - The IssueAdapter interface lives at `packages/cli/src/adapters/issue-adapter.ts` with `StandardIssue` and `StandardIssueListItem` types. The GitHub implementation is `GitHubCliAdapter` at `packages/cli/src/adapters/github-cli.ts`. PR-related functionality is similarly abstracted via `PrAdapter` at `packages/cli/src/adapters/pr-adapter.ts`. Future issue tracker adapters (Jira, Linear) should implement the same interface. _(architecture, adapter-pattern, issue-tracker, pivot)_
- **2026-03-05T03:16:17.884Z** - ALWAYS run `totem shield` before pushing or creating a PR. This is a core Workflow Orchestrator Ritual defined in CLAUDE.md. Don't skip it even when momentum is high — that's exactly when mistakes slip through. _(workflow, shield, pre-push, trap)_
- **2026-03-05T04:05:14.473Z** - When creating adapter/wrapper classes that call external CLIs (like `gh`), extract the shared exec → JSON.parse → schema.validate pattern into a private helper method immediately. Don't duplicate the try/parse/catch/validate boilerplate across methods — GCA will flag it and it's a waste of review rounds. _(architecture, adapter-pattern, DRY, trap)_
- **2026-03-05T04:05:16.794Z** - When adding error re-throw guards (like checking for `[Totem Error]` prefix before calling a shared error handler), put the guard IN the shared handler — not duplicated at every call site. Centralize error routing in one place. _(error-handling, DRY, trap)_
- **2026-03-05T04:05:19.420Z** - When writing regex to parse user input (like GitHub URLs), always anchor with `^` and include the protocol (`https?://`). Unanchored regexes match substrings embedded in other text, which is almost never the intent for CLI input parsing. _(regex, input-validation, trap)_
- **2026-03-05T04:32:16.597Z** - Scaffolding command best practices for `totem init` and similar commands that modify user files: (1) Never create duplicate entries — use regex with `^` anchor and `/m` flag to check for existing keys. (2) Ensure trailing newline before appending — check `!existing.endsWith('\n')` and prepend `\n` if needed. (3) Sanitize all user input before writing to files — strip newlines, validate format, quote values. (4) Use specific marker files for tool detection, not bare directory existence. (5) Print a summary of every file modified so users can verify. (6) Prefer skip-if-exists over overwrite — use `--force` flag for explicit overwrites. _(scaffolding, init, best-practices, file-modification, security)_
- **2026-03-05T22:37:32.237Z** - When writing CLI output streams (like summaries or logs), ensure all content derived from external or potentially untrusted sources is sanitized to strip control characters. Even if the primary payload is sanitized before storage, unsanitized summary outputs piped to other tools can be used for terminal injection attacks. _(security, cli, sanitization, output)_
- **2026-03-06T00:17:02.961Z** - When designing user-extensible CLI tools (like 'totem run'), avoid prematurely building DSLs or plugin systems for data fetching (e.g., git diffs, issue trackers). Start by exposing simple prompt overrides (e.g., checking for '.totem/prompts/shield.md' before using a hardcoded string). Only build an execution runner once the limitations of simple overrides are empirically proven. Building a workflow schema before user demand exists is a classic trap for over-engineering. _(architecture, product-strategy, dsl, scope-creep)_
- **2026-03-06T01:32:23.369Z** - When designing MCP servers, do not automatically apply terminal sanitization (stripping control characters/ANSI escapes) to tool output. MCP tools are consumed by LLMs, not directly by standard terminals. Stripping characters from MCP search results will degrade the fidelity of code snippets and formatting that the LLM relies on. Terminal injection is a CLI presentation concern, not an MCP data payload concern. _(security, mcp, sanitization, architecture)_
- **2026-03-06T02:09:28.451Z** - When implementing retries for "stale" database handles, capture and report the original error if the retry also fails to prevent swallowing the diagnostic root cause of non-transient failures. A blanket catch-and-retry can obscure the true error if the initial failure was not actually due to a stale connection. _(error-handling, robustness, lance-db)_
- **2026-03-06T02:09:28.451Z** - Always incorporate random jitter into exponential backoff calculations to stagger retry attempts across concurrent clients. This prevents "thundering herd" spikes that can overwhelm a recovering service if multiple instances retry at identical intervals. _(resilience, network, backoff)_
- **2026-03-06T02:09:28.451Z** - Prioritize standard inline idioms (like error message extraction) over creating dedicated helper functions for very few call sites to minimize indirection. Avoid "over-DRYing" code when the resulting abstraction adds more complexity than the repetition it replaces. _(architecture, readability, simplicity)_
- **2026-03-06T02:40:46.658Z** - The '@mmnto/totem' core package (which handles the ingestion pipeline, syntactic chunkers, embedders, and LanceDB store) currently has zero test coverage. Since this package manages the stateful local database and complex parsing logic (e.g., Markdown/AST chunking), bugs here are difficult to debug (e.g., LanceDB stale handles or datafusion case-sensitivity issues). Integration tests running 'totem sync' against a real LanceDB instance and unit tests for the chunkers are the highest priority for technical debt remediation. _(architecture, testing, lancedb, core)_
- **2026-03-06T03:05:07.771Z** - Future feature consideration: 'Federated Memory'. Allow a local Totem index in one repository to query or communicate with a Totem index in another local repository (e.g., an app repo querying a shared component library's traps). This would require standardizing the schema and allowing 'totem.config.ts' to define remote/external LanceDB paths. _(architecture, future-ideas, multi-repo)_
- **2026-03-06T03:06:36.174Z** - When dogfooding Totem across multiple local projects, recognize that the Totem repository itself serves as the 'Mothership'. Lessons learned about how to \_use\_ AI effectively (e.g., prompt injection, LLM behaviors, MCP tool boundaries) naturally aggregate in the Totem repo. Other consuming repos (like 'satur8d' or 'arhgap11') would benefit immensely from querying the Totem repo's LanceDB index to inherit those AI behavioral best practices without duplicating them. _(architecture, federated-memory, dogfooding)_
- **2026-03-06T03:09:19.161Z** - When designing Phase 4 (Enterprise Expansion), avoid building Totem as a 'mesh communication layer' (p2p networking, realtime sockets). Instead, maintain the 'Unix Philosophy' by having the central platform CI/CD pipeline pull or ingest the static '.totem/' artifacts (lessons, handoffs) from developers' branches. The intelligence comes from the aggregated LanceDB index, not from inventing a new networking protocol. Keep the infrastructure dumb and the queries smart. _(architecture, product-strategy, federated-memory, enterprise)_
- **2026-03-06T03:11:07.960Z** - To support team-wide status querying without a centralized server (Phase 4), leverage the existing PR and branch infrastructure. Instead of having Totem instances ping each other, developers should push their 'session-handoff.md' and 'active*work.md' to draft PRs or remote branches at the end of the day. A team lead's Totem can then run a workflow that clones/fetches those branches and aggregates the markdown files into a single context for the orchestrator LLM to summarize. *(architecture, enterprise, status, workflow)\_
- **2026-03-06T03:15:12.458Z** - Future feature consideration for team workflows: 'Automated Onboarding Protocols'. If Totem aggregates lessons, architecture docs, and 'session-handoff' states, a new developer's first 'totem init' could automatically generate a personalized 'Day One Briefing' tailored to their first assigned issue, pulling relevant architectural traps and avoiding the need for a senior dev to spend 3 hours explaining the repo history. _(architecture, future-ideas, team-workflow, enterprise)_
- **2026-03-06T03:27:22.818Z** - When evaluating features for Totem, remember its origin: it is a bootstrapped, minimalist tool built from the lessons of failed, overly-complex previous iterations (the 'mmnto-ai' platform and 'thread agents'). Totem exists to solve immediate, practical AI-assisted development friction (like context window bloat and PR learning loops). Treat previous repositories as 'archaeology assets'—extract their ideas (like workflow topologies), but do not port their heavy infrastructure or try to rebuild Google's 'antigravity'. Keep Totem focused on the local developer. _(architecture, product-strategy, archeology, antigravity)_
- **2026-03-06T03:31:34.777Z** - A core insight extracted from the legacy 'mmnto-ai' platform is the "Design-Execute" multi-model protocol. In the past, the human acted as the manual router (using Claude to design, Gemini to analyze, Copilot to execute), passing 'initiation-request.json' files between them. Totem's true value proposition is automating this exact routing layer via the CLI. Totem is the realization of the "Unified Protocol" document, but implemented as an autonomous 'totem spec' and 'totem shield' pipeline instead of a manual human workflow. _(architecture, product-strategy, archeology, orchestration)_
- **2026-03-06T03:34:53.287Z** - The legacy 'memento-platform' and 'mmnto-ai' repositories contain the core theoretical models for multi-agent coordination (e.g., 'AriadneOrchestrator', 'GospelComplianceEngine'). These are valuable conceptual resources to reference when designing advanced Totem workflows. However, NEVER attempt to port their technical implementations (Kafka, Kubernetes, Firestore, massive cloud architectures) into Totem. Totem's architectural success relies entirely on translating those massive cloud concepts into local, pragmatic CLI primitives (e.g., LanceDB instead of Firestore, local terminal execution instead of Kafka queues). _(architecture, product-strategy, archeology, pragmatism)_
- **2026-03-06T03:36:17.521Z** - LanceDB's DataFusion SQL backend uses \*\*backticks\*\* (`` `filePath` ``) for case-sensitive column identifier quoting, NOT SQL-standard double quotes (`"filePath"`). Double-quoted identifiers silently produce zero matches without throwing any error — making it an extremely nasty silent failure mode. Always use backticks when referencing camelCase column names in LanceDB filter strings (e.g., `delete()`, `where()`). _(lancedb, datafusion, sql, trap, quoting, case-sensitivity)_
- **2026-03-06T03:43:04.312Z** - As a solo developer augmented by AI, your primary constraint is not engineering hours, but \_context retention\_ and \_architectural discipline\_. By aggressively dogfooding Totem to handle the context (Shield reviews, Spec generations, and persistent memory), you can scale your output to match a multi-person team. The goal is to offload the repetitive cognitive burden of "remembering how the system works" to the LanceDB index, allowing you to operate purely as the "Human Sovereign" making high-level product decisions. _(motivation, velocity, solo-developer)_
- **2026-03-06T03:48:40.291Z** - Core Product Philosophy: 'Invisible Orchestration'. Totem must scale down to solo developers seamlessly. The ultimate goal of 'totem init' is that a junior developer never has to manually run a 'totem' command again. We must leverage Git hooks (pre-push, post-merge), AI agent system prompts (auto-triggering tools via MCP), and background processes to make the learning loop and quality gates happen automagically. Totem should feel like an invisible 'Git for AI Memory', not a heavy CLI that requires constant manual execution. _(product-strategy, onboarding, developer-experience, invisible-orchestration)_
- **2026-03-06T04:05:18.718Z** - Roadmap gap analysis: The current roadmap is heavily indexed on \_text/code\_ orchestration but misses the \_observability/state\_ layer. Developers will quickly lose trust in a vector database if they cannot 'see' what is inside it or how it is parsing their files. We need a 'totem inspect' or local dashboard UI (Phase 3) that allows users to visualize their chunks, see what files were ignored, and delete bad lessons manually. Additionally, Phase 2 is missing a formal 'Ejection/Uninstall' command to remove all injected hooks and prompts gracefully. _(architecture, product-strategy, roadmap, missing-pieces)_
- **2026-03-06T04:18:37.256Z** - Future feature consideration: Once MCP or AI host environments support 'pre-compaction' and 'post-compaction' lifecycle hooks, Totem should intercept them. A pre-compaction hook could automatically trigger 'totem handoff' to save the current session state, and a post-compaction hook could automatically run 'totem triage' to seamlessly reload the most critical context back into the fresh window. This would eliminate the need for developers to manually guard against memory resets. _(architecture, future-ideas, mcp, context-compaction)_
- **2026-03-06T04:20:45.590Z** - The ultimate value proposition of Totem is transforming a sterile vector database into a proactive 'developer journal and cheatsheet'. The true magic happens when the AI is configured to proactively identify and suggest lessons \_before\_ the human realizes they need to remember them. This transitions the tool from passive retrieval to active mentorship. _(product-strategy, value-prop, proactive-memory)_
- **2026-03-06T04:31:54.888Z** - While it is tempting to make 'totem triage' automatically invoke 'totem learn' on recently merged PRs, this violates the principle of modularity and creates a massive, fragile 'mega-command'. 'triage' is for planning the future; 'learn' is for extracting rules from the past. Keep them decoupled. If a team wants them linked, they should compose them via the upcoming 'totem run <workflow>' runner (e.g., 'totem run sprint-planning' which calls learn then triage). _(architecture, product-strategy, workflows, triage)_
- **2026-03-06T04:53:50.730Z** - Strategic Note: Totem \_must\_ remain open source. Developer tools (especially ones that read local code and inject git hooks) die behind paywalls because they cannot establish trust. The open-source CLI and local LanceDB instance act as the 'loss leader' to build a massive user base and establish the '.totem/lessons.md' format as an industry standard. Monetization (if desired later) should happen at the Enterprise Phase 4 level (e.g., hosting the 'Mothership' federated indexes, SSO, or team analytics dashboards), not by closing the core CLI. _(product-strategy, open-source, go-to-market, business-model)_
- **2026-03-06T05:32:34.019Z** - Fun product strategy thought: Because Totem indexes 'lessons.md' and team context, you could build a CLI mini-game ('totem trivia' or 'totem roulette') where the orchestrator quizzes a developer on the codebase's specific historical traps and rules before their code compiles. E.g., 'Before you push, what is the #1 rule about LanceDB DataFusion queries?' It turns dry architectural rules into a gamified team culture. _(product-strategy, gamification, culture, team-workflow)_
- **2026-03-06T05:32:34.037Z** - Lateral Architecture Concept: The Totem infrastructure (local LanceDB + Git-native sync + MCP LLM orchestration) can be repurposed outside of developer tools. For example, it could serve as the distributed state and memory layer for a multiplayer text adventure or MUD (like the 'arhgap11' prototype), where player actions and world lore are indexed locally and synced across the 'Federation' to keep the game world coherent across different local clients. _(architecture, lateral-thinking, game-dev, state-sync)_
- **2026-03-06T05:32:34.074Z** - When designing multi-input orchestrator commands (like 'totem spec' or 'totem learn' handling arrays of IDs), strictly enforce the 'Fail Fast' principle over graceful degradation. A partial context assembly (e.g., fetching PR 1 and 2, but silently failing on PR 3) is highly dangerous because the LLM will confidently generate a response based on incomplete information. It is better for the CLI to crash loudly than for the AI to hallucinate silently. _(architecture, error-handling, orchestrator, design-decision)_
- **2026-03-06T05:41:19.122Z** - When implementing CLI UX polish (Issue #21), adopt the '@clack/prompts' library. It provides a distinct, vertical-line connecting visual style that feels significantly more modern and premium than older libraries like 'inquirer'. This directly supports the 'Magic Onboarding' goal of making the CLI feel less like a barebones script and more like a high-end developer product. _(ux, cli, product-strategy)_
- **2026-03-06T05:43:04.609Z** - Incremental UX Delivery Strategy: When polishing a CLI, do not attempt to rewrite the entire interactive prompt system (e.g., migrating to @clack/prompts) in one massive PR. Follow Claude's strategy: prioritize the 'low-hanging fruit' first (async spinners via 'ora', branded output via 'picocolors') to provide immediate visual feedback. The heavier structural refactoring of the input loops can be deferred to a follow-up. This maintains high velocity and avoids blocking the release of smaller, compounding improvements. _(engineering-strategy, velocity, ux, incremental-delivery)_
- **2026-03-06T05:45:12.867Z** - When the friction of solo development feels overwhelming and burnout is near, rely on the architecture. You don't have to carry the entire context of 'Totem' and 'satur8d' in your head simultaneously. The LanceDB indexes are designed precisely to hold that weight for you. Build the system so that you can walk away, take a break, and when you return, 'totem triage' instantly reloads your exact mental state without spending 3 hours remembering where you left off. The tools must serve the human's endurance. _(motivation, solo-developer, product-strategy, velocity)_
- **2026-03-06T06:25:26.036Z** - Wrap all untrusted external content, especially data extracted from PR comments or free-text topics, in XML tags to prevent direct and indirect prompt injection. Indirect injection via PR comments is a high-risk vector for commands that synthesize historical context. _(security, llm, prompts, prompt-injection)_
- **2026-03-06T06:25:26.036Z** - Be mindful of pull request size limits; oversized PRs may cause automated security review tools to skip analysis, allowing vulnerabilities to merge without detection. _(workflow, security, trap)_
- **2026-03-06T06:25:26.036Z** - When implementing local system prompt overrides from a directory like `.totem/prompts/`, strictly enforce path traversal protection to prevent arbitrary files from being read into the LLM context. _(security, filesystem, prompt-engineering)_
- **2026-03-06T06:25:26.036Z** - Perform sanitization of untrusted data (like PR titles or LLM output) at the system input boundaries rather than the display layer. Baking sanitization into low-level logging helpers is often wasteful for hardcoded strings and improperly couples display logic with security concerns. _(security, architecture, sanitization, ui)_
- **2026-03-06T06:25:26.036Z** - Route all decorative UI output, including spinners, banners, and branded tags, to `stderr` while reserving `stdout` strictly for pipeable data. This ensures the CLI remains compatible with Unix pipes and redirection without polluting data streams with decorative artifacts. _(cli, unix-philosophy, architecture)_
- **2026-03-06T06:25:26.036Z** - Use dynamic imports for heavy dependencies (e.g., `ora` for spinners) within the specific functions that require them. This prevents a performance "tax" on the startup time of every CLI command, keeping lightweight commands fast. _(performance, imports, cli)_
- **2026-03-06T06:25:26.036Z** - Avoid using `${err}` in logging template literals as it relies on a generic `toString()` call; instead, explicitly extract `err.message` (or the full error object) to ensure consistent and informative output across different catch blocks. _(logging, error-handling, trap)_
- **2026-03-06T08:00:19.826Z** - When using 'totem spec', it is most valuable for exploring unfamiliar territory or framing large epics. For well-scoped sub-tasks where the developer has already read the code and written detailed descriptions, running 'totem spec' adds marginal value and wastes time/quota. The optimal pattern is to 'spec the epic, skip specs on sub-tasks you scoped yourself'. _(totem, workflow, spec, optimization)_
- **2026-03-06T09:08:26.567Z** - When scaffolding agent hooks (like Claude's PreToolUse) or background git hooks, avoid embedding complex shell pipelines (e.g., grep chains, escaping quotes) directly inline within JSON configuration files. It is fragile and hard to test. Long-term architectural rule: Extract hook logic into dedicated, version-controlled executable scripts (e.g., \`.gemini/hooks/BeforeTool.js\`) and have the JSON config simply invoke the script. _(architecture, hooks, json, shell)_
- **2026-03-06T10:00:40.352Z** - Route host hook output (e.g., briefing or shield results) to `stderr` rather than `stdout`. This prevents background task logs from polluting the AI's tool return values while ensuring the user still receives visibility into the hook's execution. _(cli, hooks, unix)_
- **2026-03-06T10:00:40.352Z** - Avoid complex single-regex patterns for intercepting git commands in AI tool inputs, which often fail due to platform-specific escaping or POSIX compatibility issues. A dual-grep approach (e.g., `grep "git" && grep -E "push|commit"`) is more robust for reliably catching both plain text and JSON-encoded arguments. _(regex, hooks, git, compatibility)_
- **2026-03-06T10:00:40.352Z** - MCP tools returning raw file content are vulnerable to Indirect Prompt Injection if the output lacks distinct delimiters. Use unique XML tags and escaped internal markers to ensure the host AI treats retrieved knowledge as untrusted data rather than a continuation of its system instructions. _(security, mcp, prompt-injection)_
- **2026-03-06T10:00:40.352Z** - Treat environment variables provided by the host AI (such as `$TOOL\_INPUT` in Claude Code) as untrusted data. Using them directly in shell commands like `echo` within a hook can lead to command injection if the input contains shell metacharacters. _(security, shell, hooks)_
- **2026-03-06T10:00:40.352Z** - When scaffolding configuration files that store settings in JSON arrays, implement deep merging to append entries rather than overwriting the entire key. This allows the tool to maintain idempotency while preserving existing user-defined hooks. _(nodejs, configuration, idempotency)_
- **2026-03-06T18:48:00.895Z** - When escaping closing XML tags to prevent prompt injection, use a case-insensitive regex that accounts for optional internal whitespace (e.g., `</ tag>`). Literal matches are easily bypassed because LLMs and parsers often interpret these variants as valid tag closures. _(security, prompt-injection, xml, regex)_
- **2026-03-06T18:48:00.895Z** - Use the `.cjs` extension for utility scripts and host integration hooks in ESM-first projects. This ensures compatibility with external tools that may not support ESM loaders, preventing module resolution errors during tool-triggered execution. _(nodejs, esm, compatibility, hooks)_
- **2026-03-06T18:48:00.895Z** - Always verify the specific object schema required by host tools (like Claude Code's `{type: "command", command: "..."}`) instead of assuming a primitive string format. Mismatched configuration schemas often fail silently, leading to broken integrations that are difficult to debug. _(architecture, configuration, integration, trap)_
- **2026-03-07T00:44:37.037Z** - Always await side-effect operations like indexing during tool execution to provide the LLM with definitive success or failure confirmation. Fire-and-forget patterns prevent the model from identifying state failures, leading to hallucinations about persisted knowledge. _(observability, llm-ux, sync)_
- **2026-03-07T00:44:37.037Z** - Implement a `contextWarningThreshold` to append a system warning block when tool payloads exceed safe token limits (e.g., 40k chars). This prompts agents to proactively suggest context hygiene maneuvers, such as bridging, before hitting hard window constraints. _(context-management, observability, guardrail)_
- **2026-03-07T00:44:37.037Z** - Differentiate context verbosity by using truncated snippets for high-frequency discovery commands (like `briefing`) and full content for deep-analysis commands (like `spec`). This balances token efficiency during exploration with the need for high-fidelity data during execution. _(token-optimization, ux, discovery)_
- **2026-03-07T00:44:37.037Z** - Call internal scripts directly within agent-facing tools rather than relying on shell aliases or complex wrappers. Direct execution reduces the surface area for environment-specific failures and ensures reliable operation in automated workflows. _(reliability, agent-ux, automation)_
- **2026-03-07T06:05:56.069Z** - For LLM prompts, escape closing XML tags using backslash escaping (e.g., `<\/tag>`) rather than HTML entities to prevent prompt injection while minimizing parsing noise. Use a case-insensitive regex that accounts for optional whitespace to ensure robustness against variants like `</TAG >`. _(security, prompts, xml)_
- **2026-03-07T06:05:56.069Z** - Differentiate between terminal sanitization (stripping ANSI/control characters) and prompt sanitization (XML escaping); do not apply terminal sanitization to data intended for LLM prompts as it can degrade code fidelity. Terminal injection is a presentation-layer concern for the CLI, while prompt injection is a data payload concern for the LLM. _(security, cli, prompts)_
- **2026-03-07T06:05:56.069Z** - Only apply prompt injection sanitization to truly external, untrusted user-supplied content; do not sanitize constrained or semi-trusted metadata like branch names or git file paths to maintain prompt readability and avoid unnecessary clutter. _(security, prompts, design-decision)_
- **2026-03-07T06:05:56.069Z** - Prefer dynamic imports inside command function bodies rather than hoisting them to the module scope for CLI tools. This pattern preserves lazy loading, ensuring the CLI starts quickly by only loading the specific dependencies required for the command being executed. _(cli, performance, architecture)_ _(archived: Pattern-message mismatch: astGrepPattern `import($MODULE)` fires on every dynamic import in the CLI, but the message tells developers to prefer dynamic imports. Every canonical lazy-load line trips a warning to do what it already does. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **2026-03-07T06:05:56.069Z** - When implementing "eject" or cleanup routines, wrap file deletions in try/catch blocks and report failures as "skipped" items. This graceful degradation prevents a single permission error or missing file from crashing the entire uninstall process, providing a better user experience. _(cli, error-handling, scaffolding)_
- **2026-03-07T06:05:56.069Z** - Avoid using generic line-matching patterns (like `line.startsWith('(')`) when scrubbing auto-generated sections from shared files like git hooks. Use precise line matches or unique block markers to prevent accidental removal of user-added logic that may coincidentally match a broad pattern. _(git, scaffolding, trap)_
- **2026-03-07T06:05:56.069Z** - Always combine `typeof val === 'object'` with a truthiness check (`val && ...`) when traversing untyped JSON or `unknown` structures. Since `typeof null` returns `'object'`, omitting the null check will lead to runtime crashes when attempting to access properties on a null value. _(typescript, trap, json)_
- **2026-03-07T21:45:57.754Z** - Use intermediate environment variables to map GitHub Action `inputs` before using them in `run` steps. Directly expanding `${{ inputs.key }}` in shell scripts creates high-severity command injection vulnerabilities by allowing untrusted input to be executed as code. _(github-actions, security, trap)_
- **2026-03-07T21:45:57.754Z** - Always quote shell variables when passing them as arguments to commands to prevent word-splitting and argument injection. Unquoted variables allow malicious inputs to break command logic or inject arbitrary CLI flags. _(shell, security, trap)_
- **2026-03-07T21:45:57.754Z** - Sanitize text derived from untrusted sources (like LLM outputs or PR comments) before displaying it in interactive CLI components. Malicious ANSI escape sequences in the text can lead to terminal injection, compromising the user's terminal session. _(cli, security, terminal-injection, trap)_
- **2026-03-07T21:45:57.754Z** - Wrap interactive-only previews and manual review warnings inside a conditional check for non-automated/interactive modes. This keeps CI logs clean and avoids printing redundant noise that cannot be acted upon in non-interactive environments. _(cli, ux, ci)_
- **2026-03-08T00:11:33.219Z** - When introducing a "Lite" tier or optional mode to an interactive scaffold, ensure that previous default options remain explicitly discoverable; replacing a provider-default with a "nothing" default on the "Enter" key can accidentally hide valid configuration paths from users. _(cli, scaffolding, discovery)_
- **2026-03-08T00:11:33.219Z** - Environment variable checks for a "configured" state must validate that the value contains non-whitespace characters (`/\S/`) to ensure consistency with `.env` file parsing and prevent false positives from variables exported as empty strings or whitespace. _(environment, configuration, trap)_
- **2026-03-08T00:11:33.219Z** - Scaffolding and `init` commands should prioritize graceful degradation (warnings and fallbacks) over hard errors for non-critical configuration failures, ensuring users can always reach a functional "Lite" state instead of being blocked by invalid credentials. _(cli, onboarding, scaffolding)_
- **2026-03-08T00:56:41.780Z** - Scaffolding commands should wrap non-critical file system operations in `try/catch` blocks to log warnings instead of crashing the process. This ensures the primary setup flow completes even if a secondary feature fails due to environment-specific issues like file permissions. _(architecture, scaffolding, error-handling)_
- **2026-03-08T00:56:41.780Z** - When generating multiple markdown chunks for AI indexing, assign each a unique, descriptive heading rather than a generic shared label. Identical headings make search results and context summaries indistinguishable for the user, significantly degrading RAG utility. _(ai-behavior, rag, search)_
- **2026-03-08T00:56:41.780Z** - Verify fixed collections of assets with exact count assertions (e.g., `toBe(10)`) rather than weak bounds (e.g., `toBeGreaterThanOrEqual(5)`). This prevents regression errors where individual items are accidentally deleted but the test continues to pass. _(testing, quality-assurance)_
- **2026-03-08T00:56:41.781Z** - For static, small sets of string comparisons (like 'y/n' prompt responses), explicit boolean `OR` checks are often more idiomatic and readable than `[].includes()` patterns. Avoid over-engineering simple branching logic if the set of possible values is not expected to grow. _(clean-code, design-decision)_
- **2026-03-08T02:39:04.901Z** - Prefer graceful degradation with a warning over halting for non-critical scaffolding tasks during initialization. Unlike core orchestrator commands where partial failure is risky, setup steps should be resilient to recoverable environment issues like file permissions to ensure a smooth onboarding experience. _(scaffolding, error-handling, architecture)_
- **2026-03-08T02:39:04.901Z** - Avoid generic headings for knowledge chunks as they result in indistinguishable labels in search results and UI components. Use descriptive, unique headings to ensure both humans and AI can differentiate between related lessons during context assembly. _(search, indexing, documentation)_
- **2026-03-08T02:39:04.901Z** - Use exact count assertions rather than "greater than" checks when verifying fixed sets of assets or features. Precise assertions detect accidental deletions that range-based checks would miss, ensuring the integrity of curated content. _(testing, quality-assurance)_
- **2026-03-08T02:39:04.901Z** - Use temporary files instead of CLI arguments or environment variables when passing large data (like prompts) to sub-processes on Windows to avoid "argument list too long" errors. _(windows, shell, performance)_
- **2026-03-08T02:39:04.901Z** - For background maintenance tasks with small expected workloads (e.g., cleaning 0-5 files), prefer sequential `for...of` loops over `Promise.all`. Sequential processing simplifies error isolation, allowing you to "swallow and continue" on a per-item basis without the complexity of `Promise.allSettled`. _(async, performance, error-handling)_
- **2026-03-08T02:39:04.901Z** - Avoid introducing asynchronous configuration loading or complex resolution logic into non-critical fire-and-forget utilities if those parameters are not yet user-configurable. Keeping background tasks hardcoded and "best-effort" prevents over-engineering and ensures the CLI startup path remains lean and fast. _(architecture, configuration, cli)_
- **2026-03-08T02:39:04.901Z** - Always use the `--` separator before positional arguments in git commands (e.g., `git log -- <ref>`) to protect against argument injection. This ensures that potentially untrusted strings, such as branch or tag names, are never interpreted as command-line flags. _(security, git, trap)_
- **2026-03-08T02:39:04.901Z** - Use named error objects (e.g., `err.name = 'NoDocsConfiguredError'`) instead of string matching to handle expected "graceful skip" conditions in orchestrators. This creates a stable contract between modules that remains robust even if the user-facing error message is updated for better readability. _(error-handling, architecture, design-decision)_
- **2026-03-08T02:39:04.901Z** - Prioritize codebase-wide consistency for established utility patterns (like `shell: IS\_WIN` for Windows execution) over local "fixes" in a single PR. Core architectural or security shifts should be handled as dedicated global refactors to avoid fragmented and confusing helper implementations across the codebase. _(architecture, consistency, design-decision)_
- **2026-03-08T02:39:04.901Z** - Avoid over-engineering cosmetic log summaries, such as using frequency maps for a simple `+N/-M` line-change count, if basic `Set`-based logic provides sufficient visual feedback. Prioritize simplicity and functional correctness over perfect accuracy for non-critical console output. _(pragmatism, design-decision, logging)_
- **Reply to GCA with a single structured PR comment** - \*\*Context:\*\* Responding to GCA (Gemini Code Assist) PR review comments. \*\*Symptom:\*\* Individual thread replies waste quota (100/day) and produce generic "thanks" responses from GCA. \*\*Fix/Rule:\*\* Reply with a single PR comment containing a numbered list that matches GCA's comments 1:1, with explicit accept/decline per item and a commit SHA reference. This gives GCA structured feedback — it confirms each fix individually and produces a higher-quality acknowledgment response. _(gca, pr-review, workflow, dx)_
- **Custom .env parsers must strip CRLF and quotes** - \*\*Context:\*\* Windows .env file parsing in Node.js CLI tools. \*\*Symptom:\*\* `loadEnv` failed to parse keys correctly — values included literal quote characters (`"sk-..."` instead of `sk-...`) and Windows CRLF line endings caused regex match failures. \*\*Fix/Rule:\*\* Always strip `\r` from lines before parsing (`line.replace(/\r$/, '')`), and strip surrounding quotes with `raw.replace(/^(['"])(.\*)(\1)$/, '$2')`. System env vars take precedence over .env — `loadEnv` should never override existing `process.env` keys. _(windows, dotenv, parsing, environment, trap)_
- **Sanitize user-provided text before persisting to files** - Sanitize ANSI escape sequences from user-provided text before persisting it to local Markdown files or logs (like `lessons.md`). This prevents terminal injection vulnerabilities where viewing the file with tools like `cat` could execute malicious or disruptive control sequences in the user's terminal environment. _(security, terminal-injection, cli)_
- **Sanitize all strings extracted from files before displaying** - Sanitize all strings extracted from files before displaying them in terminal outputs or interactive prompts. This prevents terminal injection attacks where malicious ANSI escape sequences in the source file could be used to spoof the UI or trick the user. _(security, terminal, cli)_
- **When extracting patterns like file paths from Markdown** - When extracting patterns like file paths from Markdown content, explicitly filter out triple-backtick code blocks before running the extraction logic. This prevents false positives by ensuring the parser does not mistake code examples or documentation within the body for active file references. _(regex, markdown, parsing, trap)_
- **For machine-generated files with a strictly controlled** - For machine-generated files with a strictly controlled schema, prefer strict positional parsing over global scanning. Strict parsing is more resilient than "fuzzy" scanning because it avoids accidental matches of keywords (like "Tags:") that may legitimately appear inside the body text of a lesson. _(parsing, architecture, design-decision)_
- **When re-throwing errors in a CLI orchestrator, always** - When re-throwing errors in a CLI orchestrator, always include the project's standard error prefix (e.g., `[Totem Error]`) in the message. This ensures a consistent user experience and allows the system to clearly distinguish between internal application errors and raw system/library failures. _(error-handling, style-guide)_
- **Git diff headers wrap file paths containing spaces** - Git diff headers wrap file paths containing spaces in double quotes (e.g., `+++ "b/path with spaces.ts"`). Failure to strip these quotes while handling the `b/` prefix correctly will result in broken file paths and incorrect reporting in automated tools. _(git, parsing, trap)_
- **Quality gate tools must never exit successfully** - Quality gate tools must never exit successfully when required rules or configurations are missing. Silent passes on empty input create a false sense of security in CI pipelines; always log an error and exit with a non-zero status to ensure the gate is actually operational. _(ci, security, fail-fast)_
- **Regex patterns generated by LLMs from natural language** - Regex patterns generated by LLMs from natural language are highly susceptible to Regular Expression Denial of Service (ReDoS) through catastrophic backtracking. To mitigate this risk, validate syntax during generation and restrict execution to single lines or small, bounded buffers rather than unbounded input. _(security, regex, llm, redos)_
- **For internal, version-controlled configuration files** - For internal, version-controlled configuration files that feed into LLM prompts (like `lessons.md`), human PR review is a practical security gate against indirect prompt injection. Programmatic delimiting (like XML escaping) can be deferred if it significantly degrades prompt readability for trusted internal contributors. _(security, prompt-injection, design-decision)_
- **When refactoring from execSync to spawn to avoid fixed** - When refactoring from `execSync` to `spawn` to avoid fixed buffer limits, you must re-implement a manual safety cap on accumulated stdout/stderr strings. Without a hard limit (e.g., 50MB), the process is vulnerable to memory exhaustion if an external tool or LLM produces unexpectedly large or malicious output. _(nodejs, child-process, security)_
- **When timing out a child process, do not reject the promise** - When timing out a child process, do not `reject` the promise immediately within the `setTimeout` callback. Instead, call `child.kill()` and perform the rejection inside the `close` event handler to ensure all stdio streams have fully flushed and captured the complete error log for debugging. _(nodejs, child-process, error-handling)_
- **Synchronous execSync with piped stdio can cause the parent** - Synchronous `execSync` with piped stdio can cause the parent process to hang or abort silently when the child process outputs specific content patterns or exceeds certain internal pipe limits. Using asynchronous `spawn` with manual stream collection provides better process lifecycle management and prevents these non-deterministic failures. _(nodejs, orchestrator, trap)_
- **When catching and re-logging errors that originate** - When catching and re-logging errors that originate from internal utilities with standardized prefixes (e.g., `[Totem Error]`), strip the redundant prefix from the message before outputting. This prevents cluttered logs like `[Docs] ... [Totem Error] ...` and maintains a clean user interface. _(logging, ux, error-handling)_
- **Do not manually edit machine-generated artifacts** - Do not manually edit machine-generated artifacts like `compiled-rules.json`; fixes must be applied to the source lessons or the compiler logic to ensure they persist and aren't overwritten during the next build cycle. _(architecture, devops, toolchain)_
- **The Git -- separator treats all subsequent arguments** - The Git `--` separator treats all subsequent arguments as file paths, meaning revision specifiers (like `branch...HEAD`) must appear before it to be correctly resolved rather than misinterpreted as filenames. _(git, security, shell)_
- **Always fall back to resolving Git references** - Always fall back to resolving Git references against `origin/<branch>` in CI environments, as local branch pointers are often missing or detached in the shallow clones typical of automated runners. _(git, ci, devops)_
- **Employ a two-layer validation model by running fast,** - Employ a two-layer validation model by running fast, deterministic regex-based checks in CI while reserving expensive or stochastic LLM reviews for local developer workflows to maintain rapid CI feedback loops without sacrificing deep analysis. _(architecture, ci, design-decision)_
- **When using the @google/genai SDK (v1+), the constructor** - When using the `@google/genai` SDK (v1+), the constructor requires an options object `{ apiKey }` rather than a raw string. This is a common point of confusion because the older `@google/generative-ai` package used a string-only constructor, leading to runtime instantiation errors if the packages are conflated. _(gemini, sdk, nodejs, trap)_
- **When normalizing diverse SDK errors for internal retry** - When normalizing diverse SDK errors for internal retry logic (e.g., tagging a `QuotaError`), mutate the original error's `.name` property and re-throw it instead of creating a new `Error` instance. This preserves the original stack trace and provider-specific metadata which are critical for debugging failures in external service integrations. _(error-handling, nodejs, debugging, architecture)_
- **Avoid refactoring synchronous factory functions to async** - Avoid refactoring synchronous factory functions to `async` just to hoist dynamic `import()` calls for perceived performance gains. Node.js natively caches the results of dynamic imports after the first invocation, so keeping the factory synchronous avoids adding `await` boilerplate to the entire call chain without any measurable runtime penalty. _(nodejs, performance, architecture, factory-pattern)_ _(archived: Over-broad: astGrepPattern `async function $NAME($$$PARAMS) { $$$BODY }` matches every async function in the entire codebase across \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx. Cannot distinguish factory functions hoisting dynamic imports from any other async function. Archived via #1517.)_
- **Centralize error signature detection (such as 429 status** - Centralize error signature detection (such as 429 status codes or "rate limit" strings) into a shared utility that also covers legacy shell-based execution paths. This ensures that manually-parsed stderr from CLI tools benefits from the same robust detection logic used for native SDKs, preventing subtle omissions in fallback or retry behaviors. _(dry, error-handling, shell, llm)_
- **Perform path normalization—such as resolving ./** - Perform path normalization—such as resolving `./` prefixes—before deduplication to prevent redundant processing of the same file represented by different string formats. This avoids wasted resources, like redundant LLM token usage, when the same target is resolved multiple times from varied inputs. _(nodejs, cli, path-processing)_
- **When positional arguments and CLI flags offer overlapping** - When positional arguments and CLI flags offer overlapping or conflicting functionality, explicitly fail-fast with an error if both are provided instead of silently prioritizing one. This ensures user intent is unambiguous and prevents unexpected behavior from shadowed configuration flags. _(cli, ux, error-handling)_
- **Use path.relative(process.cwd(),** - Use `path.relative(process.cwd(), path.resolve(process.cwd(), input))` for robust path normalization instead of simple string replacements. This approach correctly handles shell-expanded absolute paths (e.g., from tab-completion) so they match relative paths defined in application configuration. _(nodejs, path-processing, trap)_
- **Always use fully qualified identifiers for caching** - Always use fully qualified identifiers (e.g., `provider:model`) for cache hashing and telemetry instead of just the model name. This prevents cross-provider cache collisions in environments where different backends happen to share identical model naming conventions. _(caching, telemetry, architecture)_
- **Ensure validation checks are applied symmetrically** - Ensure validation checks are applied symmetrically to both primary and fallback execution paths. Relying on primary-path validation alone creates a trap where invalid configuration only triggers a failure during error recovery (e.g., a quota retry), making the resulting failure much harder to debug. _(validation, error-handling, fallback)_
- **Use vi.importActual in mocks to preserve utility functions** - When mocking modules, use `vi.importActual` to maintain the real implementation of pure utility functions while mocking only the side-effect-heavy factories. Re-implementing utility logic inside a mock makes tests brittle and allows them to pass even if the actual implementation changes and breaks. _(testing, vitest, mocks)_
- **Block cross-provider routing into specialized providers** - Explicitly block cross-provider routing into specialized providers (like `shell`) that require unique configuration templates not present in the source provider's setup. Failing fast at the routing layer prevents cryptic runtime errors when an orchestrator attempts to execute a prompt without the necessary provider-specific execution context. _(architecture, shell-provider, validation)_
- **When parsing unified diff hunks, explicitly match context** - When parsing unified diff hunks, explicitly match context lines (prefixed with a space) rather than using a catch-all `else` block. Unified diffs often contain meta-information lines, such as `\ No newline at end of file`, which are neither additions nor context; treating these as file content can corrupt line tracking and metadata for subsequent lines. _(git, diff-parsing, trap)_
- **Centralize Security Validations in "Choke Point" Helpers** - When centralizing logic into a "choke point" helper for both primary and fallback paths, ensure all security-critical validations (like shell metacharacter checks) are migrated. Missing checks in the centralized helper can create injection vulnerabilities if fallback paths previously relied on guards only present in the primary path. _(security, refactoring, validation)_
- **Avoid Factory Parameters Solely for Mocking** - Adding factory parameters to functions solely to facilitate mocking can lead to over-engineered production signatures. For internal module logic, standard ESM mocking patterns or well-commented test mocks are often preferable to polluting public APIs with test-only dependencies. _(testing, design-decision, mocking)_
- **Trust Upstream Guards and Type Systems Over Redundant Checks** - Avoid adding explicit runtime checks or redundant error branches for logic paths that are already unreachable due to upstream guards or exhaustive type-system enforcements. Relying on established guards keeps the implementation focused and prevents the accumulation of defensive code noise. _(typescript, defensive-programming, design-decision)_
- **Prefer Explicit Metadata Tokens from LLMs Over Heuristics** - Requesting explicit metadata tokens (e.g., `Heading:`) from LLMs is more reliable than using heuristic truncation of the first line of output. Sanitize these explicit tokens to remove markdown artifacts and prefixes that LLMs frequently include despite instructions. _(llm, prompt-engineering, sanitization)_
- **Prefer Vitest's expect().rejects.toHaveProperty()** - Prefer Vitest's `expect().rejects.toHaveProperty()` assertions over manual `try/catch` blocks with `expect.fail()`. This pattern is more concise and prevents tests from accidentally passing if the code fails to throw as expected. _(testing, vitest, patterns)_
- **Ensure all thrown errors, including those for missing** - Ensure all thrown errors, including those for missing environment variables or configuration, strictly include the `[Totem Error]` prefix. Maintaining this prefix even in low-level setup code ensures consistent error reporting for users and automated monitoring. _(error-handling, style-guide, consistency)_
- **When a configuration file is an executed script (like** - When a configuration file is an executed script (like TypeScript), individual field validation for path traversal is redundant because the file itself already has arbitrary code execution privileges. The security boundary in this model is the version control and PR review process rather than runtime input sanitization. _(security, architecture, configuration)_
- **Sentinel-based injection systems should always generate** - Sentinel-based injection systems should always generate markers even when the content is empty to ensure subsequent runs can still locate the injection point. Removing the markers when there is no content breaks idempotency, as future updates will fail to find the target and may append duplicate blocks elsewhere. _(idempotency, file-io, automation)_
- **Logic that replaces content between markers must explicitly** - Logic that replaces content between markers must explicitly verify that the start sentinel precedes the end sentinel to avoid scrambling the file. If markers appear in reverse order, standard string slicing will produce incorrect segments that corrupt the file upon write. _(file-io, parsing, robustness)_
- **File-appending logic should implement an early return** - File-appending logic should implement an early return for empty input to prevent the unintended accumulation of trailing newlines or separators. Without this check, repeated executions with no content can cause "blank line drift," where target files grow unnecessarily with every run. _(file-io, dx)_
- **Intentionally duplicating prompt assembly logic** - Intentionally duplicating prompt assembly logic is preferable to unified helpers when architectural boundaries require strict context isolation. DRYing these functions risks "context bleed" where specialized modes, such as structural reviews, accidentally inherit project knowledge that biases the model. _(architecture, llm, dry, prompting)_
- **Omit defensive XML escaping for prompt injection** - Omit defensive XML escaping for prompt injection when processing trusted local data, such as a developer's own git diffs in a CLI tool. In local-only threat models, the noise and prompt clutter introduced by aggressive escaping often outweigh the security benefit. _(security, prompting, cli)_
- **Deliberately excluding project context in "structural"** - Deliberately excluding project context in "structural" review modes prevents the LLM from anchoring on developer intent, which can mask syntax-level bugs. Restricting the model's view to raw diffs forces it to identify logic errors and resource leaks that global project context might otherwise rationalize. _(llm, code-review, prompting)_
- **Always generate sentinel markers even when the internal** - Always generate sentinel markers even when the internal content is empty. Returning an empty string instead of empty markers causes the replacement logic to delete the markers from the target file, leading to redundant appends in subsequent runs. _(idempotency, file-io, markdown)_
- **If a configuration file is a locally-authored script (e.g.,** - If a configuration file is a locally-authored script (e.g., totem.config.ts) that the tool imports, the user already has arbitrary code execution. Validating individual path fields for traversal in this context adds no security value as the configuration itself is already a trusted input boundary. _(security, configuration, trust-model)_
- **When performing string-slice replacements based on start** - When performing string-slice replacements based on start and end markers, explicitly throw an error if the end marker appears before the start marker. Failing to check this relative ordering can result in incorrect slices that silently scramble or corrupt the target file's content. _(file-io, error-handling, robustness)_
- **Runtime escaping and sanitization are unnecessary** - Runtime escaping and sanitization are unnecessary for content sourced from version-controlled files that undergo PR review. In these cases, the project's development workflow and human review process serve as the primary security boundary against malicious input like prompt injection or sentinel breakage. _(security, prompt-injection, workflow)_
- **In local-first development tools, escaping XML tags in git** - In local-first development tools, escaping XML tags in git diffs to prevent prompt injection is often unnecessary because the user already controls the input source. Avoiding redundant sanitization on trusted local data reduces prompt noise and prevents unnecessary token consumption. _(security, llm, git)_
- **Resist merging similar orchestrator output handling** - Resist merging similar orchestrator output handling and verdict parsing logic until at least three distinct modes exist. Keeping these paths separate during early feature development prevents premature coupling of specialized modes that might later diverge in requirements. _(design-decision, clean-code, architecture)_
- **Setting open-pull-requests-limit to 0 in dependabot.yml** - Setting open-pull-requests-limit to 0 in dependabot.yml suppresses routine version bumps while still allowing critical security patches to trigger PRs via GitHub's repo-level security settings. This distinction allows for a security-only automated update policy that prevents noise and maintenance fatigue. _(dependabot, security, configuration)_
- **Performing content.split('\n') inside a loop over line** - Performing `content.split('\n')` inside a loop over line numbers creates quadratic $O(N \times M)$ complexity. Hoisting the split ensures linear performance and prevents potential Denial of Service (DoS) when processing large files. _(performance, nodejs, security)_ _(archived: Over-broad: fires on any .split('\n') regardless of loop context. Blocks legitimate one-shot first-line extraction in catch blocks (#1349). See #1352.)_
- **Synchronous file operations are often preferable in CLI** - Synchronous file operations are often preferable in CLI tools for simplicity, as blocking the event loop is not a concern for short-lived, single-user processes. This differs from server-side environments where async I/O is mandatory to maintain responsiveness. _(nodejs, architecture, performance)_
- **Diff parsing state machines must track hunk status** - Diff parsing state machines must track hunk status to prevent embedded `+++` or `---` markers (e.g., in test fixtures or template literals) from being misread as file headers. Without this tracking, embedded diff content can prematurely terminate file context and corrupt rule application. _(parsing, git, state-machine)_
- **Local git metadata like branch names, commit messages,** - Local git metadata like branch names, commit messages, and diff stats can contain malicious ANSI escape sequences. Sanitize these strings before printing them to the terminal to prevent terminal injection attacks when running commands in untrusted repositories. _(security, git, terminal-injection)_
- **Lite versions of commands should prioritize concise** - Lite versions of commands should prioritize concise metadata, such as line counts, over full content dumps to remain fast and deterministic. This maintains a clear functional distinction between a high-level status snapshot and a context-heavy LLM operation. _(design-decision, ux)_
- **When resolving file paths extracted from untrusted sources** - When resolving file paths extracted from untrusted sources like git diffs, explicitly verify that the resolved path resides within the project root. This prevents directory traversal attacks where malicious input could force the tool to access files outside the intended repository boundary. _(security, filesystem, path-traversal)_
- **Warning messages triggered by security violations** - Warning messages triggered by security violations must sanitize the offending input before display. Printing a raw malicious string (like a filename containing escape sequences) within a warning can inadvertently execute the very attack the system is alerting the user about. _(security, error-handling, terminal-injection)_
- **Implement provider-specific libraries as optional peer** - Implement provider-specific libraries as optional peer dependencies and load them lazily at runtime to keep the core package size small. This "Bring Your Own Software Driver" pattern prevents users from being forced to install every supported SDK for providers they do not use. _(architecture, performance, dependencies)_
- **Provide a dummy fallback API key (e.g., 'local-only')** - Provide a dummy fallback API key (e.g., 'local-only') when targeting OpenAI-compatible local endpoints to bypass client-side SDK validation. Many local servers like Ollama do not require authentication, but official client SDKs often throw validation errors if the key field is left empty. _(openai, orchestrator, local-llm)_
- **Treat usage and token statistics as optional fields** - Treat usage and token statistics as optional fields when implementing OpenAI-compatible orchestrators. Third-party implementations often omit usage metadata that is guaranteed by the official OpenAI API, which can lead to runtime crashes during result processing if not handled defensively. _(openai, defensive-programming, api-design)_
- **Wrap user-controlled fields like PR descriptions** - Wrap user-controlled fields like PR descriptions or comments in XML tags explicitly labeled as "untrusted content" within system prompts. This provides a defense-in-depth layer that helps the LLM distinguish between developer instructions and potentially malicious external data. _(security, prompting, llm)_
- **Sanitize git-sourced metadata like branch names, status,** - Sanitize git-sourced metadata like branch names, status, and diff statistics to remove ANSI escape sequences and control characters. This prevents formatting corruption and parsing errors when passing terminal-sourced data to downstream tools or LLM contexts. _(git, sanitization, security)_
- **Ollama num_ctx and VRAM: The OpenAI-compatible API adapter** - Ollama `num\_ctx` and VRAM: The OpenAI-compatible API adapter does not support passing `num\_ctx` to Ollama, so context length defaults to the model's built-in default (often 2-8k). Ollama's native `/api/chat` endpoint accepts `options: { num\_ctx }` for dynamic context sizing. On consumer GPUs (16GB VRAM), a 27B model fills VRAM with weights alone — any KV cache beyond ~8k spills to system RAM and significantly slows inference. Different Totem commands have different context needs (triage: 4-8k, shield/spec: 16-32k), making dynamic `num\_ctx` sizing valuable. See issue #298. _(ollama, orchestrator, vram, num_ctx, performance, hardware)_
- **When scanning for malicious payloads like Base64 or Unicode** - When scanning for malicious payloads like Base64 or Unicode escapes, ensure checks cover all user-controllable fields, including headings or metadata. Neglecting these fields allows attackers to bypass security heuristics by smuggling payloads in smaller, less-scrutinized buffers. _(security, prompt-injection, validation)_
- **Leakage detection regex must be explicitly synchronized** - Leakage detection regex must be explicitly synchronized with the exact XML tags used to wrap untrusted content in the prompt. Missing specific delimiters like `comment\_body` or `diff\_hunk` in the detection logic creates blind spots where internal prompt structures can leak without being flagged. _(security, regex, prompt-engineering)_
- **While interactive users can be trusted to review** - While interactive users can be trusted to review and override heuristic flags, automated CI pipelines should treat these flags as hard failures with non-zero exit codes. This prevents the silent ingestion of potentially malicious or malformed data when human oversight is absent. _(ci, security, automation)_
- **Heuristic regexes designed to detect structural leakage** - Heuristic regexes designed to detect structural leakage must include every XML tag used to wrap untrusted content in the prompt. Omitting tags like comment*body or diff_hunk allows attackers to leak prompt metadata without triggering the validator. *(security, regex, prompt-injection)\_
- **Security heuristics like Base64 or Unicode escape detection** - Security heuristics like Base64 or Unicode escape detection must scan both headings and bodies rather than just the primary content field. Even restricted fields like 60-character titles provide enough space for malicious payloads to bypass selective scanning. _(security, heuristics, prompt-injection)_
- **Command-line tools using auto-accept flags like --yes** - Command-line tools using auto-accept flags like --yes should exit with a non-zero code if heuristic validators flag suspicious content. This prevents automated pipelines from silently ingesting poisoned or low-quality data that would otherwise require human intervention. _(ci, security, automation)_
- **Heuristic validators designed to detect tag leakage** - Heuristic validators designed to detect tag leakage must explicitly include every XML tag used in the system prompts (e.g., `diff\_hunk`, `comment\_body`). Failing to mirror the exact set of delimiters creates blind spots that attackers can exploit to break out of the intended LLM context. _(security, regex, prompt-engineering)_
- **Heuristic checks for malicious patterns like Base64 blobs** - Heuristic checks for malicious patterns like Base64 blobs or Unicode escapes must be applied to all fields influenced by the LLM (like headings), not just the primary text body. Metadata fields often have enough character capacity to smuggle payloads that bypass detection logic focused only on the main content. _(security, validation, prompt-injection)_
- **Casting an object literal to an Error type does not satisfy** - Casting an object literal to an Error type does not satisfy `instanceof Error` checks because the prototype chain is missing at runtime. Use `Object.assign(new Error(message), properties)` to ensure objects pass both TypeScript validation and runtime prototype inspections. _(typescript, error-handling, trap)_
- **Avoid using Zod's .url() validator for configurations where** - Avoid using Zod's `.url()` validator for configurations where users frequently provide bare hostnames or `host:port` without protocols. Strict URL validation requires a protocol prefix (e.g., `http://`), which can break the developer experience for common local service configurations like Ollama. _(zod, validation, dx, ollama)_
- **For local LLM providers, 500 Internal Server Errors often** - For local LLM providers, 500 Internal Server Errors often indicate VRAM or context exhaustion rather than generic software bugs. Providing specific guidance to adjust hardware-steering parameters like `numCtx` in the error message helps users resolve resource-constrained failures immediately. _(error-handling, ollama, ux)_
- **Wrap untrusted content like code diffs in XML delimiters** - Wrap untrusted content like code diffs in XML delimiters and provide explicit security instructions in the system prompt. This prevents prompt injection where malicious comments within the diff could hijack the LLM's instructions. _(security, prompting, llm)_
- **Sanitize LLM-generated content before persisting it** - Sanitize LLM-generated content before persisting it to version-controlled files if the source material is untrusted. This creates a security boundary that prevents persisting malicious payloads, such as ANSI escape sequences, which could trigger terminal injection when developers view the files. _(security, sanitization, persistence)_
- **Prefer auto-generating headings at the storage layer rather** - Prefer auto-generating headings at the storage layer rather than persisting LLM-provided headings when multiple extraction paths exist. This ensures the knowledge base maintains a uniform format regardless of whether lessons are extracted via manual commands or automated review passes. _(architecture, consistency, automation)_
- **Avoid using exit 0 inside git hooks intended for chaining** - Avoid using `exit 0` inside git hooks intended for chaining, as it terminates the entire shell process and prevents subsequent appended hooks from executing. Wrapping logic in `if/fi` blocks ensures the hook script can continue to other contributors' logic. _(git, shell, automation)_
- **Perform shell-level existence checks before invoking CLI** - Perform shell-level existence checks (e.g., `if [ -f config.json ]`) in git hooks before invoking heavy CLI tools. This prevents the performance overhead of starting a Node.js runtime in environments where the tool is not configured or required. _(performance, git, shell)_
- **Detect existing hook managers and provide manual guidance** - Detect existing hook managers like Husky or Lefthook and provide manual integration guidance instead of writing directly to `.git/hooks`. This avoids clobbering developer workflows and prevents configuration conflicts between multiple management tools. _(git, dx, automation)_
- **Validate that an existing git hook is a shell script** - Validate that an existing git hook is a shell script (e.g., by checking for a shebang) before attempting to append automated logic. This prevents the corruption of binary or specialized hooks that cannot handle string-based appends. _(git, safety, automation)_
- **Automated review tools often have stale knowledge** - Automated review tools often have stale knowledge of the latest or experimental model identifiers (e.g., `gemini-2.5-flash`). Prioritize model IDs proven to work in existing smoke tests over AI suggestions that flag them as typos. _(llm, testing, integration)_
- **Avoid adding explicit runtime guards for conditions** - Avoid adding explicit runtime guards for conditions that are already prohibited by strict TypeScript interfaces. Redundant checks for "cannot happen" states like `undefined` on a required property add clutter without improving safety when the design contract is already enforced. _(typescript, refactoring)_
- **During data ingestion, strip high-risk security threats** - During data ingestion, strip high-risk security threats like BiDi overrides (Trojan Source) but only flag patterns like XML tags or Base64 via warnings. This prevents malicious injection while preserving the integrity of legitimate content that happens to use those formats. _(security, ingestion)_
- **When detecting project environments, use a consistent** - When detecting project environments, use a consistent priority order (e.g., pnpm > yarn > bun > npx) to ensure specific lockfiles are honored. This includes checking for both legacy (`bun.lockb`) and modern (`bun.lock`) versions to maintain compatibility across tool versions. _(bun, nodejs, devops)_
- **Implement an adversarial evaluation harness with planted** - Implement an adversarial evaluation harness with planted architectural violations to monitor LLM performance over time. Combining deterministic regex-based tests with gated LLM integration tests ensures that model drift is caught when reasoning fails to identify known traps. _(testing, llm, quality-assurance)_
- **Moving security-sensitive regexes (like BiDi stripping** - Moving security-sensitive regexes (like BiDi stripping or XML bypass defense) from CLI tools to core packages ensures consistent adversarial scrubbing across both ingestion pipelines and runtime shields. Hardening these patterns against whitespace bypasses (e.g., optional whitespace after closing slash in tags) prevents common prompt injection evasion techniques. _(security, regex, refactoring)_
- **Automated code reviewers often flag bleeding-edge model** - Automated code reviewers often flag bleeding-edge model identifiers (like `gemini-2.5-flash`) as typos due to stale training data. Always prioritize the project's verified configuration or official provider documentation over AI-suggested "corrections" to model names. _(llm, testing, integration)_
- **Do not add runtime undefined guards for properties** - Do not add runtime `undefined` guards for properties explicitly typed as non-optional (e.g., `string` vs `string | undefined`) in the shared interface. Trusting the established type contract reduces code noise and prevents redundant defensive logic. _(typescript, refactoring)_
- **When detecting Bun environments, check for both bun.lockb** - When detecting Bun environments, check for both `bun.lockb` (legacy) and `bun.lock` (Bun >= 1.2) to ensure compatibility. Priority for package manager detection should be explicitly defined (e.g., pnpm > yarn > bun > npx) to handle hybrid environments. _(bun, devops, nodejs)_
- **Ensure model name validation regexes explicitly allow** - Ensure model name validation regexes explicitly allow character delimiters like dots to accommodate newer naming schemes such as `gpt-5.4`. This prevents runtime failures or schema validation errors when migrating to next-generation identifiers from external providers. _(validation, regex, llm-providers)_
- **Audit initialization files and configuration schemas** - Audit initialization files and configuration schemas during model updates to ensure that secondary provider IDs do not leak into logic reserved for the primary orchestrator. This practice preserves architectural boundaries and keeps the core system decoupled from specific external vendor versions. _(architecture, configuration, auditing)_
- **Use pnpm exec for workspace binaries in monorepos** - Use `pnpm exec` instead of `pnpm bin` when checking for or executing binaries that might be internal workspace packages. In Turborepo environments, `pnpm exec` reliably handles workspace package resolution whereas `pnpm bin` often fails to locate binaries that aren't installed as standard root dependencies. _(pnpm, monorepo, turborepo, automation)_
- **Static hook installer bootstraps before CLI is built** - Implement a lightweight static installer to manage git hooks during initial project setup before the primary CLI is built. Using consistent markers across both static scripts and the dynamic CLI allows for unified validation and prevents the "chicken and egg" dependency on the tool itself. _(git-hooks, dev-experience, bootstrapping)_
- **Non-interactive --check flag enables CI hook enforcement** - Expose a non-interactive `--check` flag in hook management commands that scans for specific markers and exits with a non-zero code if they are missing. This allows CI pipelines to enforce hook adoption and ensure developers haven't bypassed local quality gates. _(git-hooks, ci, automation)_
- **Verify CLI availability in shared git hooks before execution** - Verify CLI availability in shared git hooks (e.g., using `command --version`) before execution to prevent brittle CI failures. This is critical in environments where dev-only tools might be missing or purged during specific lifecycle phases like release workflows. _(git-hooks, ci, shell-scripting)_
- **CLI entrypoints print clean errors, libraries throw** - Top-level CLI handlers should use guards or catch blocks to print clean, user-friendly messages and exit gracefully instead of throwing errors. Throwing should be reserved for internal library functions where callers must handle specific failure states programmatically. _(error-handling, cli, ux)_
- **Resolve git root via rev-parse for monorepo compatibility** - Always resolve the git repository root via "git rev-parse --show-toplevel" instead of checking for a .git directory in the current path. This ensures tools work correctly inside monorepo sub-packages, submodules, and git worktrees. _(git, monorepo, nodejs)_
- **Windows requires shell:true for git binary resolution** - Using "shell: true" in execFileSync is often required on Windows to resolve the git binary correctly across different environments. While this presents a theoretical binary hijacking risk, the pattern is often acceptable if the threat model already assumes an attacker with local file system access. _(windows, security, git)_
- **LLMs are notoriously poor at character counting; use** - LLMs are notoriously poor at character counting; use semantic constraints like "one to two short sentences" rather than numeric character limits to ensure reliable adherence to length requirements. _(prompting, llm, formatting)_
- **Use granular assertions rather than snapshots for testing** - Use granular assertions rather than snapshots for testing system prompts to verify specific functional constraints while preventing tests from breaking on minor, non-functional prose changes. _(testing, llm, prompt-engineering)_
- **Inserting new formatting rules can inadvertently sever** - Inserting new formatting rules can inadvertently sever example blocks or break the logical structure of a system prompt; implement tests that verify the presence of key sections to catch these regressions. _(prompting, llm, automated-testing)_
- **Always iterate through all regex matches (e.g.,** - Always iterate through all regex matches (e.g., via `matchAll`) when performing security validations rather than just checking the first. Relying on the first match allows "shadowing" where an attacker prefixes a payload with a safe match to hide a malicious one later in the same text. _(security, regex, validation)_
- **Include a space or delimiter when concatenating disjoint** - Include a space or delimiter when concatenating disjoint text fragments for context analysis. This prevents "keyword synthesis," where separate text segments accidentally form a protected keyword and bypass security filters. _(regex, security, text-processing)_
- **Check for the presence of the 'g' flag before appending it** - Check for the presence of the 'g' flag before appending it when dynamically constructing a new RegExp from an existing one. Re-adding a global flag to a pattern that already includes it will cause a runtime SyntaxError. _(javascript, regex, typescript)_
- **Favor semantically clear naming** - Favor semantically clear naming like `!isInstructionalContext()` over specialized alternatives even if they introduce redundant checks. In non-critical paths, logical clarity and code maintainability are more valuable than the negligible performance gain of micro-optimizing a simple regex test. _(clean-code, design-decision)_
- **Run integration tests for CLI tools that interact with Git** - Run integration tests for CLI tools that interact with Git in temporary directories to prevent path resolution logic from climbing into the host repository. This ensures tests operate on a clean, controlled filesystem state rather than inadvertently interacting with the project's own git metadata. _(testing, git, integration-testing)_
- **Use semantic constraints like "one to two short sentences"** - Use semantic constraints like "one to two short sentences" rather than numeric character limits to ensure reliable adherence to length requirements. LLMs are notoriously poor at exact character counting but respond effectively to qualitative, semantic boundaries. _(prompting, llm, formatting)_
- **Use granular assertions rather than snapshots when testing** - Use granular assertions rather than snapshots when testing system prompts to verify specific functional constraints while preventing tests from breaking on minor, non-functional prose changes. This maintains test stability without sacrificing the verification of critical logical requirements. _(testing, llm, prompt-engineering)_
- **Implement tests that verify the presence of key sections** - Implement tests that verify the presence of key sections in system prompts when modifying formatting rules to catch structural regressions. Changes to prompt structure can inadvertently sever example blocks or break the logical flow, which simple existence checks help identify. _(prompting, llm, automated-testing)_
- **Always iterate through all regex matches (e.g.,** - Always iterate through all regex matches (e.g., via `matchAll`) when performing security validations rather than checking only the first match. Relying on the first match allows "shadowing" where an attacker prefixes a payload with a safe match to hide a malicious one later in the string. _(security, regex, validation)_
- **Include a space or delimiter when concatenating disjoint** - Include a space or delimiter when concatenating disjoint text fragments for analysis to prevent "keyword synthesis." Without delimiters, separate segments can accidentally form protected keywords that bypass security filters or trigger false positives. _(regex, security, text-processing)_
- **Check for the presence of the global ('g') flag** - Check for the presence of the global ('g') flag before appending it when dynamically constructing a new RegExp from an existing one. Re-adding a global flag to a pattern that already includes it will trigger a runtime SyntaxError in JavaScript environments. _(javascript, regex, typescript)_
- **Identify larger or more specific text markers (like triple** - Identify larger or more specific text markers (like triple backticks) before smaller ones (single backticks) during range collection. This allows subsequent passes to skip smaller markers that fall within already-claimed ranges, ensuring correct block isolation. _(parsing, regex, string-manipulation)_
- **Fixes to automated extraction logic, such as resolving** - Fixes to automated extraction logic, such as resolving truncated headings, typically do not retroactively update existing records. Legacy data requires manual intervention or targeted re-syncing to align with updated formatting or validation rules. _(maintenance, automation, data-integrity)_
- **FSL intelligence layer licensing is a decided-but-deferred** - FSL intelligence layer licensing is a decided-but-deferred strategic decision (#353). Apache 2.0 stays everywhere until v1.0. At v1.0, split @mmnto/core into @mmnto/totem (Apache 2.0, commodity: chunkers, store, config) and @mmnto/totem-engine (FSL 1.1, moat: compiler, drift detector, sanitizer, AST gate). CLA is already in place as the insurance policy. Emergency trigger: execute split immediately if a hyperscaler forks the intelligence layer pre-v1.0. _(licensing, strategy, v1.0, fsl, architecture)_
- **Custom glob matching functions must be tested** - Custom glob matching functions must be tested against the actual glob patterns used in configuration. When adding new glob pattern shapes (e.g., directory-prefixed like packages/cli/\\\*\_/\_.ts), verify the matcher supports them — a silent no-match produces a false sense of security (rules appear to pass but are actually skipped). GCA caught this in PR #357. _(shield, glob-matching, compiler, false-positive, trap)_
- **Convert large plain-text research blobs into Markdown** - Convert large plain-text research blobs into Markdown with structured headings to ensure semantic search chunkers can index content effectively. Plain text often fails to chunk correctly, resulting in poor retrieval performance or indexing failures for RAG systems. _(semantic-search, indexing, documentation, markdown)_
- **A "clean pass" in security scans after narrowing rule scope** - A "clean pass" in security scans after narrowing rule scope can be a false negative if the glob matcher fails to recognize new pattern shapes. Always verify that scoped rules are actually evaluating intended files rather than silently matching nothing due to unsupported syntax. _(testing, security, glob)_
- **When implementing custom glob matching for dir/\\\*/.ext,** - When implementing custom glob matching for `dir/\*\*/\*.ext`, ensure the index check for the double-wildcard separator excludes the start of the string. This prevents repo-relative paths from being misinterpreted as root-anchored and ensures directory-specific logic doesn't conflict with universal patterns. _(glob, regex, logic-error)_
- **In core packages, a small, tested custom implementation** - In core packages, a small, tested custom implementation is often preferable to adding external libraries like `micromatch` when only a few specific pattern shapes are required. This keeps the dependency graph lean and reduces the maintenance surface for limited, well-defined use cases. _(design-decision, dependency-management, architecture)_
- **Design safety-net validators, such as LLM hallucination** - Design safety-net validators, such as LLM hallucination checks, to fail-open with a warning rather than blocking the primary workflow. This prevents internal validator bugs from stopping user actions in scenarios where the tool is a helper rather than a strict security gatekeeper. _(architecture, error-handling, design-decision)_
- **When comparing checkbox states for mutations, strip** - When comparing checkbox states for mutations, strip markdown links to prevent false positives. LLMs often modify link structures while preserving text, which can incorrectly trigger "deleted" or "added" item detections if the raw markdown is used for matching. _(markdown, regex, llm-hallucination)_
- **Use occurrence counts of opening and closing markers** - Use occurrence counts of opening and closing markers on a per-line basis rather than simple string inclusion checks. This accurately detects corruption in lines containing multiple tags or partial markers that would otherwise pass a basic presence check. _(regex, validation, parsing)_
- **Always verify that input vectors have identical lengths** - Always verify that input vectors have identical lengths before calculating cosine similarity. Differences in array length can lead to silent failures, NaN results, or incorrect scores because the loop boundary might not account for undefined elements in the shorter vector. _(vector-math, validation, safety)_
- **When deduplicating batches of new content, perform database** - When deduplicating batches of new content, perform database similarity lookups before generating embeddings for the candidates. This prevents wasting API credits or local compute on embedding items that are already identified as duplicates in the existing store. _(performance, optimization, llm)_
- **Implement a minimum character length guard when recursively** - Implement a minimum character length guard when recursively stripping trailing articles or prepositions from truncated headings. This safety net prevents malformed or short titles from being reduced to a single uninformative word after multiple passes of connector removal. _(heuristics, string-manipulation, ux)_
- **Use the --recurse-submodules flag with git ls-files** - Use the `--recurse-submodules` flag with `git ls-files` to ensure that files located within submodules are included in project scans. Standard Git listing commands often ignore these directories by default, which can cause tools to miss relevant configuration or logic files. _(git, devops, file-system)_
- **When injecting vectordb lessons into orchestrator prompts** - When injecting vectordb lessons into orchestrator prompts (like `totem spec`), use a single broadened search pool (e.g., 20 results) and partition by filePath rather than running multiple redundant searches. The `lessons.md` filePath convention is the reliable partition key. Use `continue` not `break` in character budget loops so oversized items are skipped but smaller ones still fit. _(vectordb, spec, lessons, architecture, pattern)_
- **Changesets interactive CLI (pnpm changeset) crashes when** - Changesets interactive CLI (`pnpm changeset`) crashes when stdin is piped or non-TTY. For automated releases, write changeset files manually to `.changeset/` with frontmatter listing package names and bump types. The `fixed` group in changeset config means all packages bump together. _(changesets, release, ci, trap)_
- **JetBrains Junie is a complementary coding agent, not a** - JetBrains Junie is a complementary coding agent, not a Totem competitor. It consumes MCP servers (potential Totem customer), uses a static guidelines file for context (no enforcement, no learning loop, no deterministic rules). Totem's sentinel-based export already supports Junie via the config exports mechanism — zero code needed. _(competitive, junie, jetbrains, mcp, strategy)_
- **MCP session lifecycle limitation** - MCP session lifecycle limitation: The MCP spec has no session lifecycle hooks (no session.start, session.end, or beforeDisconnect events). This means auto-triggering totem handoff when an agent session closes is not currently possible. The workaround is to use an "advisory reflex" in the agent's system prompt, instructing it to run `totem handoff` at the end of a session. However, this is not guaranteed as agents can ignore these instructions. Tracked in #383, blocked on upstream MCP spec evolution. Do not attempt to build auto-handoff via MCP — it will fail. _(mcp, handoff, lifecycle, blocked, platform-constraint)_
- **First-match-wins glob ordering** - In systems using "first-match-wins" resolution for file types, place specific file patterns before broader globs. This allows specialized handling of specific files within a directory without requiring complex exclusion rules in the catch-all patterns. _(configuration, architecture)_
- **Dogfood config alignment** - Aligning a project's own configuration with the defaults generated by its initialization commands prevents implementation drift. This ensures the repository remains a reliable reference for the tool's intended standard behavior for new users. _(maintenance, configuration)_
- **Use --body-file for LLM text in CLI** - When passing LLM-generated text to CLI commands, write the content to a temporary file and use the `--body-file` flag instead of direct string arguments. This prevents shell injection vulnerabilities and avoids complex escaping issues with untrusted or poorly formatted model output. _(security, cli, shell)_
- **Resilient batch execution pattern** - Use warnings and failure counters instead of throwing errors within batch execution loops to prevent a single item failure from aborting the entire process. This pattern allows the command to be "resilient" by completing all possible actions while clearly reporting specifically what failed. _(architecture, error-handling, cli)_
- **Truncate LLM input near token limits** - Explicitly truncate input data and log warnings when context sizes approach the model's token limits. Proactively managing input length prevents silent failures or API errors that occur when large datasets (like issue backlogs or documentation) exceed the LLM's effective window. _(llm, performance, reliability)_
- **Manual JSON validation for LLM output** - Manually validate LLM-generated JSON for specific types, enum values, and field existence to prevent runtime crashes from malformed model responses. For small, fixed schemas, explicit manual checks can be more lightweight and maintainable than adding heavy schema validation libraries. _(llm, validation, typescript)_
- **Tiered lesson verbosity by command type** - Apply condensed lesson snippets for high-frequency, shallow commands (like triage) to preserve token windows while providing full lesson bodies to deep-analysis commands (like spec) where maximum context is critical. This tiered approach balances operational costs with the need for architectural precision. _(llm, tokens, architecture)_
- **Oversized search pools prevent starvation** - Increase search pool sizes (e.g., to 20 results) when retrieving architectural lessons to ensure that critical constraints are not crowded out by lower-scoring but relevant matches. Smaller default pools risk "search starvation" where vital project-specific traps are missed as the knowledge base grows. _(llm, search, vector-db)_
- **GCA flags valid model IDs as typos** - GCA (Gemini Code Assist) has stale model knowledge and repeatedly flags valid model identifiers like `gemini-2.5-flash`, `claude-haiku-4-5-20251001`, and `gemini-3-flash-preview` as typos or non-existent models. These are verified in smoke tests. Decline firmly with a link to `docs/reference/supported-models.md`. _(review-guidance, audience:contributor)_
- **ESM intra-module mock requires re-binding** - In vitest with ESM modules, using `...await vi.importActual()` spread retains closure references to real exports. If `resolveOrchestrator` internally calls `createOrchestrator`, mocking `createOrchestrator` alone won't work — you must re-bind `resolveOrchestrator` to use the mocked factory. See `packages/cli/src/utils.test.ts` for the working pattern. _(testing, vitest, audience:contributor)_
- **TypeScript chunker uses TS compiler API** - The TypeScript chunker in `packages/core` uses the real TypeScript compiler API for proper AST parsing — NOT regex-based heuristics. Do not propose replacing it with regex or simpler string splitting. The AST approach handles edge cases (nested functions, decorators, overloads) that regex cannot. _(architecture, chunking, audience:contributor)_
- **Drift detector flags lesson file path mentions** - Lessons that mention file paths (e.g., discussing config file locations) get flagged by the drift detector as stale references when those files don't exist in the current repo. Reword lessons to describe concepts instead of citing literal paths. For example, write "the Junie guidelines file" instead of the literal path. _(drift-detection, false-positive, audience:contributor)_
- **Suspicious lesson detector flags security discussions** - Lessons that discuss security patterns (XML injection, BiDi attacks, prompt injection) contain the exact strings that the suspicious lesson detector's regex patterns are designed to catch. The detector flags its own training data. Workaround: reword lessons to describe attack classes without including literal trigger patterns. Proper fix tracked as context-aware classification (tier-3). _(security, false-positive, audience:contributor)_
- **Git hooks enforce what prompt rules cannot** - Gemini CLI (and other autonomous agents) frequently ignores advisory rules in system prompts (e.g., "never merge PRs automatically"). Git hooks (pre-commit blocking main, pre-push running shield) are the real enforcement layer. Treat prompt-based rules as advisory and hooks as mandatory guardrails. _(agent-governance, audience:contributor)_
- **GitHub Actions shell injection via template expressions** - Never use `${{ inputs.\* }}` or `${{ github.event.\* }}` directly in `run:` blocks in GitHub Actions workflows — this enables command injection. Always map untrusted inputs to `env:` variables first, then reference them as `"$VAR"` (quoted) in the shell script. Also always quote shell variables to prevent word-splitting. _(security, ci-cd, audience:contributor)_
- **npm OIDC trusted publishing prerequisites** - npm OIDC trusted publishing requires three things simultaneously: (1) `id-token: write` permission in the workflow, (2) `registry-url` set in the `setup-node` action, and (3) npm >= 11.5.1. Missing any one causes silent auth failures. Additionally, trusted publishers can only be configured AFTER the first manual publish — chicken-and-egg problem documented in npm/cli#8544. _(ci-cd, publishing, audience:contributor)_
- **Exclude auto-generated configuration files** - Exclude auto-generated configuration files from deterministic scans to prevent the tool from flagging its own output as a violation. This avoids "self-match" false positives where the scanner detects the rules it just exported. _(shield, cli, false-positives)_
- **Manually suppress "unused export" errors in styleguide** - Manually suppress "unused export" errors in styleguide files that provide context to AI tools. Since these exports are consumed by the LLM or external processes rather than imports, standard linters will flag them as false positives. _(gca, styleguide, linting)_
- **Integrate the generation of AI tool configuration files** - Integrate the generation of AI tool configuration files directly into the primary CLI wrap command as a final step. This ensures that downstream AI agents always operate on the most recent project-specific knowledge without requiring manual export actions. _(automation, workflow, dx)_
- **MCP is an IDE bridge, not a load-bearing orchestration** - MCP is an IDE bridge, not a load-bearing orchestration layer. Perplexity (March 2026) is dropping MCP internally due to token inefficiency in multi-step agent loops, training data deficit for MCP JSON-RPC schemas, and tool overload degrading agent reasoning. This validates Totem's architecture: (1) Keep MCP tools atomic and minimal (2-4 tools max, per ADR-009), (2) Never make MCP the only integration path — the CLI (`totem shield`, `totem search`) must always work as a standalone fallback for "Code Mode" agents that prefer shell execution, (3) MCP's unique value is IDE presence (Cursor, Windsurf, Claude Code) where there's no alternative channel — don't over-invest beyond that. Totem is correctly hedged: CLI is the primary product surface, MCP is the IDE bridge. _(architecture, mcp, strategy, industry-signal, adr-009)_
- **The opening two paragraphs of the telemetry research** - The opening two paragraphs of the telemetry research response (deep research topic #14, telemetry patterns) are standalone positioning copy for Totem's local-first privacy narrative. Extract them for landing page / marketing use when the time comes. Key line: "Traditional telemetry models, which rely on the continuous transmission of granular usage data to centralized cloud-based collectors, are increasingly viewed as incompatible with the security mandates and data sovereignty requirements of modern enterprise development." _(marketing, positioning, telemetry, privacy, local-first, content-source)_
- **Deferred research topic: Local-First SLM (Small Language Model) Viability for Governance** - Deferred research topic: Local-First SLM (Small Language Model) Viability for Governance. The concept: ship a custom, highly-quantized .gguf model (3B-8B params, e.g., Qwen-Coder or Llama-3-8B) specifically trained to evaluate compiled-rules.json, running locally at ~100 tokens/sec. This would sever the dependency on cloud providers for semantic rule enforcement. Deferred because: fine-tuning infrastructure, model distribution, and quality benchmarking are massive; Ollama already supports small models for basic use. Revisit post-1.0 when the governance eval harness (ADR-008) can measure whether small models match large model quality for rule enforcement tasks. _(research-backlog, slm, local-first, governance, post-1.0, deferred)_
- **GCA may suggest reverting dynamic imports back to static** - GCA may suggest reverting dynamic imports back to static top-level imports for "simplicity", contradicting its own earlier DRY suggestion and conflicting with the shield rule that enforces lazy loading in CLI command files. When GCA's simplicity suggestion conflicts with a compiled shield rule, the shield rule wins — it exists to protect CLI startup performance. Dynamic imports inside command function bodies are the correct pattern for importing from @mmnto/totem in CLI command files. _(review-guidance, gca, shield, cli-performance, dynamic-import)_
- **When Gemini proposes elevating post-1.0 infrastructure** - When Gemini proposes elevating post-1.0 infrastructure features (symbol graph, cross-file resolution, monorepo optimization) to Tier-1 based on "enterprise-grade" or "NASA-grade" framing, push back. The governance-os thesis already evaluated these and deferred them for good reason: current chunking works for the 1.0 audience (solo devs, small teams), and the symbol graph is expensive engineering with no immediate user-facing payoff. "NASA-grade" means the things you ship are tested, deterministic, and trustworthy — not that you build everything to infinite scale before launch. Prioritize making existing features trustworthy (Rule Testing Harness, SARIF, AST compilation) over adding new enterprise capabilities. _(strategy, prioritization, gemini-guidance, nasa-grade, review-guidance)_
- **When manually parsing CLI arguments, verify that a flag's** - When manually parsing CLI arguments, verify that a flag's value exists and does not start with a hyphen to avoid interpreting the next flag as its parameter. Simple `indexOf` lookups are prone to this error, which can cause silent failures or confusing behavior when required arguments are omitted. _(nodejs, cli, parsing)_
- **Validate member expressions in security rules** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Targeting only bare identifiers for sensitive functions allows bypasses via member access; rules should explicitly check for calls on security-sensitive modules. _(ast-grep, security)_
- **Explicitly capture stderr when a tool probes multiple** - Explicitly capture stderr when a tool probes multiple repositories for a resource to prevent 'not found' or GraphQL errors from polluting the terminal during successful execution. _(cli, dx, architecture)_
- **Trim raw spawn output in error messages** - \*\*Scope:\*\* packages/core/src/sys/\*\*/\*.ts, !\*\*/\*.test.\* Raw `stdout` and `stderr` from `safeExec` preserve trailing whitespace; always use a trimmed copy when formatting error messages. This prevents corrupted log output and maintains clean user-facing strings. _(shell, formatting)_ _(archived: Under-broad: misses direct violations without concatenation and template literals. upgradeTarget: compound (Proposal 226).)_
- **Generic function names like applyRules in a facade** - Generic function names like `applyRules` in a facade can mislead developers into assuming they handle all rule types when they may only implement a subset. Use specific naming or high-visibility JSDoc to clarify which engines are supported to prevent incorrect API usage. _(api-design, documentation, refactoring)_
- **Exporting constants that are used only internally allows** - Exporting constants that are used only internally allows co-located test files to assert against them directly, facilitating better test coverage for private logic. _(testing, architecture)_
- **Guard Git ranges against flag injection** - \*\*Scope:\*\* packages/core/src/sys/git.ts User-provided Git ref ranges must be checked for leading dashes to prevent them from being interpreted as command flags (e.g., --no-index) during execution. _(git, security, cli)_
- **Verify ownership before removing config entries** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use specific markers or ownership predicates rather than broad substring matching when scrubbing configuration entries to prevent the accidental deletion of user-authored content. _(cli, configuration)_
- **Provide a dummy fallback API key (e.g., 'local-only')** - \*\*Pattern:\*\* \bapiKey:\s\*process\.env\.[A-Z0-9\_]+(?!\s\*(\|\||\?\?))
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Provide a dummy fallback API key (e.g., 'local-only'). _(architecture, curated)_

- **Export types in WASM shims** - \*\*Scope:\*\* packages/core/src/ast-grep-wasm-shim.ts When creating a WASM-based compatibility shim for a native API, ensure all used types (like SgRoot and SgNode) are exported to prevent downstream type-checking failures. _(typescript, wasm, ast-grep)_
- **Conditional archival metadata preservation** - \*\*Scope:\*\* packages/core/src/compile-lesson.ts Only preserve archivedReason and archivedAt metadata when the existing item's status is 'archived' to prevent stale lifecycle data from leaking into active rules. _(lifecycle, core)_
- **Hooks designed to block agent actions, such as shield gates** - Hooks designed to block agent actions, such as shield gates for git operations, must use synchronous execution (e.g., `execSync`) to prevent the agent from proceeding before the check completes. Using asynchronous patterns in these specific triggers can lead to race conditions where the prohibited action occurs while the validation is still running. _(nodejs, devtools, architecture)_
- **Exempt AST engines from smoke gate requirements** - \*\*Scope:\*\* packages/core/src/compiler-schema.ts The 'ast' engine is exempt from 'badExample' requirements because the current smoke gate infrastructure only supports regex and ast-grep verification. _(architecture, validation)_
- **File deletions and mutations in cleanup or "eject" commands** - File deletions and mutations in cleanup or "eject" commands should be wrapped in try/catch blocks so a single permission error doesn't abort the entire routine. Failures should be recorded as skipped items in a summary report rather than throwing fatal exceptions. _(cli, error-handling, filesystem)_
- **Initialize manifests with schema wrappers** - \*\*Scope:\*\* packages/pack-agent-security/compiled-rules.json Initialize empty rule manifests as '{ "version": 1, "rules": [] }' rather than bare arrays to ensure forward compatibility with schema-aware loaders. _(json, architecture, schema)_ _(archived: Over-broad: astGrepPattern `const $VAR = []` fires on every empty-array declaration in packages/pack-agent-security/\*\*, not only on manifest initializers. Cannot distinguish "const manifest = []" (the intended target) from "const violations = []" or any other transient empty-array. Same failure mode as the dynamic-import rules archived under #1517.)_
- **Apply platform-specific test timeouts** - \*\*Scope:\*\* \*\*/vitest.config.ts Bump test timeouts specifically for Windows (e.g., 30s) to accommodate slower process spawning without penalizing performance on Linux or macOS. _(ci, vitest, windows)_
- **Proactively remove references to planned features from user** - Proactively remove references to planned features from user guides to avoid misleading users about current capabilities. Aligning documentation strictly with the current release state prevents confusion regarding features slated for later development phases. _(documentation, product-roadmap, technical-writing)_
- **Stabilize tests with conditional resolution skips** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.test.ts Integration tests depending on host-resolved paths should use conditional runtime skips to avoid false negatives when the resource is legitimately missing. _(testing, integration, ci)_
- **Use pathToFileURL for dynamic ESM imports** - \*\*Scope:\*\* .claude/hooks/\*\*/\*.js, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Wrap absolute paths in `pathToFileURL` when using dynamic imports in Node.js. This ensures compatibility with Windows file systems and prevents resolution errors for workspace-relative modules. _(esm, node, windows)_
- **When documenting high-compliance tools, explicitly state** - When documenting high-compliance tools, explicitly state what technologies are NOT used (e.g., external APIs or non-deterministic inference) to preemptively address security concerns. Maintaining strict technical accuracy, such as distinguishing between directories and files, is critical for passing "red team" reviews by senior engineers. _(documentation, communication, engineering-culture)_
- **Avoid overstating validation in safety invariants** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Distinguish between formal schema validation and simple type narrowing in comments; use 'SAFETY INVARIANT' to document the latter without overstating the level of check. _(documentation, dx)_
- **Automatically recompiling and aborting pushes** - Automatically recompiling and aborting pushes when manifests are stale ensures that remote artifacts stay synchronized with source lessons while providing the user with the necessary updates to commit. _(git-hooks, workflow, automation)_
- **The Gemini CLI and Gemini Code Assist (GCA) do not** - The Gemini CLI and Gemini Code Assist (GCA) do not recognize lowercase configuration files such as .gemini/gemini.md. Use GEMINI.md (uppercase) at the project root to ensure instructions are discovered and capabilities like knowledge searches are triggered. _(gemini, configuration, dev-experience)_
- **Use boundary-guard anchors for domain blocklists** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Simple anchors like `(?:^|\.)` are insufficient for domain matching; use boundary guards like `[^\w-]` to prevent partial matches against sibling domains (e.g., preventing 'evil.com' from matching 'not-evil.com'). _(security, regex)_ _(archived: Second-wave duplicate of 523b9893cb454e70 after the lesson scope-fix triggered a re-compile. Same defect: regex matches the literal `(?:^|\.)` boundary-anchor text, which is the standard way to author ast-grep domain patterns. Pack test authors writing rules would trigger this. Authorial guidance, not enforcement.)_
- **Enforce unique IDs in Zod schemas** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use `superRefine` to enforce the uniqueness of identifiers within a collection at parse time, ensuring deterministic behavior and clear provenance in error reporting. _(zod, validation, architecture)_
- **Lesson: Commands that rely on compiled rules rather** - Lesson: Commands that rely on compiled rules rather than LLMs should be assigned to the "Lite" configuration tier. This enables high-speed, local-only architectural gates that do not require API keys or network access for developer workflows. _(architecture, cli-design, security)_
- **Prefer ast-grep for multi-line structural matches** - \*\*Scope:\*\* .totem/compiled-rules.json Tree-sitter `#eq?` predicates often only match literal single-line empty braces `{}`; use `ast-grep` for structural matching that correctly identifies multi-line empty blocks. _(ast-grep, tree-sitter, linting)_
- **Memoize regex instances in evaluators** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Cache compiled `RegExp` objects instead of re-instantiating them on every invocation in hot paths to significantly reduce CPU overhead and improve evaluation throughput. _(performance, regex)_
- **Gemini is preferred over OpenAI for embeddings because it** - Gemini is preferred over OpenAI for embeddings because it supports task-type awareness, which yields superior retrieval quality in RAG applications. This prioritization ensures the system defaults to the highest-quality provider when multiple API keys are present. _(embeddings, gemini, retrieval)_
- **Avoid re-filtering static data collections inside functions** - Avoid re-filtering static data collections inside functions that are called frequently or on an interval. Pre-calculating filtered subsets at the module level prevents unnecessary CPU cycles and improves the responsiveness of CLI UI updates. _(performance, optimization, typescript)_
- **Anchor relative config paths to git root** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts Relative paths in environment variables or config files should anchor at the git root rather than the current working directory to ensure consistent behavior across deep directory structures. _(cli, filesystem, dx)_
- **When parsing shell scripts to replace code blocks,** - When parsing shell scripts to replace code blocks, searching for the 'fi' keyword can prematurely match nested conditionals and truncate the block. Use global matching or specific end-of-block markers to ensure the entire outer conditional is captured. _(shell, regex, git-hooks)_
- **2026-03-06T05:32:34.074Z** - \*\*Pattern:\*\* Promise\.allSettled
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/cli/\*\*/\*.ts, \*\*/totem/\*\*/\*.ts, \*\*/orchestrator/\*\*/\*.ts
  \*\*Severity:\*\* warning

Prefer Promise.all over Promise.allSettled in core packages for fail-fast behavior. _(style, curated)_

- **Include low-level network primitives in exfil rules** - \*\*Scope:\*\* packages/pack-agent-security/compiled-rules.json Exfiltration detection must cover low-level APIs like `net.Socket` and `socket.connect` alongside high-level libraries to prevent simple bypasses. _(security, node, ast-grep)_ _(archived: Pattern `new net.Socket($$$ARGS)` fires on every legitimate net.Socket construction. The source lesson is authorial guidance about what to include when writing exfil detection rules — it is not a signal that consumer code using net.Socket is suspicious. Proper coverage of net.Socket as an exfil surface is tracked in follow-up #1524 (aliased-namespace spawn / socket coverage).)_
- **Document dependency constraints for multi-phase work** - \*\*Scope:\*\* docs/active*work.md Explicitly listing dependency-order 'watch-outs' in active work documents prevents execution stalls during complex architectural transitions involving multiple PRs. *(project-management, documentation)\_
- **Synchronous execSync with piped stdio can cause the parent** - \*\*Pattern:\*\* \bexecSync\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx, !.gemini/hooks/\*\*, !.totem/hooks/\*\*, !tools/\*\*
  \*\*Severity:\*\* warning

Synchronous execSync with piped stdio can cause the parent. _(style, curated)_

- **Swallowing errors in core modules hides silent failures,** - \*\*Pattern:\*\* \bconsole\.(log|warn|error|info|debug)\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/core/\*\*/\*.ts, \*\*/core/\*\*/\*.js, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

Swallowing errors in core modules hides silent failures. _(architecture, curated)_

- **Claude Code requires skills to be organized in a nested** - Claude Code requires skills to be organized in a nested directory format rather than as flat markdown files. Each skill needs its own subdirectory with a SKILL.md file inside it. This specific naming and nesting convention is mandatory for the agent to correctly discover and load skill definitions. _(claude-code, project-structure, agent-skills)_
- **Probe local fallbacks regardless of configuration** - \*\*Scope:\*\* packages/cli/src/commands/doctor.ts Run health checks for local 'floor' providers even when cloud providers are active. Surfacing fallback availability during diagnostics prevents users from reaching for complex workarounds when primary providers fail. _(ux, diagnostics)_
- **Providing full file content for small changed files (<300** - Providing full file content for small changed files (<300 lines) instead of just diff hunks gives LLMs visibility into unchanged symbols, significantly reducing false positives. _(llm, prompt-engineering, shield)_
- **Target project-named packages for version badges** - \*\*Scope:\*\* README.md In monorepos with lockstep versioning, pointing the README badge to the project-named package (e.g., @mmnto/totem) instead of a sub-package (e.g., @mmnto/cli) clarifies the project-level version for users who might otherwise assume the version only applies to a specific tool. _(documentation, monorepo, dx)_
- **Use constants for diagnostic count assertions** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.test.ts Replace magic numbers in diagnostic suite assertions with named constants. This prevents silent drift and makes the expected contract explicit when adding or removing system checks. _(testing, cli)_
- **Include file paths in warning messages** - Warning messages should include rich metadata such as file paths and query identifiers to remain actionable during batch runs. Without this context, it is difficult to determine which specific file or rule caused a non-fatal failure when processing large datasets. _(observability, dev-experience)_
- **Top-level error handlers should use raw console.error** - Top-level error handlers should use raw console.error instead of high-level utilities to ensure visibility even if module loading or initialization fails. _(cli, logging, architecture)_
- **When using ES2022 error causes, concatenating the original** - When using ES2022 error causes, concatenating the original error message into the new wrapper message creates redundant log output. Rely on the error handler to traverse the cause chain and extract failure details. _(errors, typescript, logging)_
- **Validate resolved paths as directories** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts Path resolution must verify that the target is a directory using isDirectory() to prevent logic errors when a file exists at the expected location. _(filesystem, security)_
- **When synthesizing rules from diff hunks, ensure** - When synthesizing rules from diff hunks, ensure unified-diff prefixes (+, -, space) are stripped to prevent 'dead' patterns that only match patch files instead of source code. _(regex, compiler, git)_
- **Trailing wildcards on filename prefixes (e.g., compiler\*)** - Trailing wildcards on filename prefixes (e.g., `compiler\*`) effectively group related flat files like tests and schemas without requiring a directory structure. _(glob, github-actions)_
- **Support parameterless catch in AST patterns** - \*\*Scope:\*\* .totem/compiled-rules.json The `catch ($ERR)` pattern misses ES2019+ parameterless catch blocks; ensure patterns account for both forms to avoid false negatives in error-handling rules. _(javascript, typescript, ast-grep)_
- **Exclude 'pwd' from credential regexes** - \*\*Scope:\*\* packages/cli/src/assets/\*.ts Credential-scanning regexes should avoid the 'pwd' keyword in Node.js environments to prevent false positives where it refers to the 'present working directory'. _(security, regex, nodejs)_
- **The GitHub API endpoint for replying to pull request** - The GitHub API endpoint for replying to pull request comments requires only the comment ID, making the PR number redundant for the request path. _(github-api, dx)_
- **Setting fail-fast: false in matrix workflows ensures** - Setting `fail-fast: false` in matrix workflows ensures that a failure on one operating system does not cancel the test runs on others. This provides complete visibility into platform compatibility and prevents OS-specific regressions from masking the status of other environments. _(ci, github-actions, testing)_
- **Sync submodule pointers to ensure citation reachability** - \*\*Scope:\*\* .strategy Submodule pointers must be updated when parent repo documentation or tickets cite new submodule commits to ensure link integrity and content reachability for readers. _(git, submodules, documentation)_
- **Apply ignore patterns to explicit diffs** - \*\*Scope:\*\* packages/cli/src/git.ts Global ignore patterns for generated or vendor files should apply even to explicit diff ranges to maintain repository hygiene across all review sources. _(git, architecture, filtering)_
- **Allow absolute claims for factual bugs** - \*\*Scope:\*\* .changeset/\*.md Lint rules forbidding absolute terms like 'never' should be bypassed when describing confirmed, broken functionality. Factual accuracy in technical post-mortems or changesets takes precedence over generalized prose style guides. _(linting, documentation)_
- **GCA does not update its review context between pushes** - GCA does not update its review context between pushes on the same PR. It re-runs against the new diff but keeps flagging issues from earlier commits that were already fixed. CodeRabbit adapts mid-PR via its learnings system. When triaging GCA comments on later commits, check if the finding was already addressed before acting. \*\*Source:\*\* mcp (added at 2026-03-28T07:11:32.819Z) _(gca, coderabbit, bot-review, workflow)_
- **Maintain lean CLAUDE.md files** - \*\*Scope:\*\* CLAUDE.md Keep CLAUDE.md files under approximately 50 lines to ensure high reliability. Excessive verbosity in this file has been observed to suppress the agent's use of MCP tools. _(documentation, llm-optimization, dx)_
- **Strengthen security allowlist drift guards** - \*\*Scope:\*\* packages/pack-agent-security/test/repo-sweep.test.ts Allowlists keyed only by file path allow new unauthorized patterns to be introduced into already-exempted files. Validate exact match counts or line numbers to ensure allowlists only cover known, justified exceptions. _(testing, security)_
- **Internal DI plumbing changes may remain patches** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Removing exported functions used only for internal dependency injection doesn't necessitate a major bump if the public callable surface remains intact and no external consumers are affected. _(semver, changesets)_
- **Ensure JSON output paths mirror the success/failure logic** - Ensure JSON output paths mirror the success/failure logic of human-readable paths to prevent silent failures where an empty result is a success in JSON but an error in the UI. _(cli, api-design)_
- **Rule metadata or headings containing the literal pattern** - Rule metadata or headings containing the literal pattern they guard against can trigger the rule on themselves. Renaming or obfuscating these strings prevents false positives in automated CI checks. _(ci, guardrails, regex)_
- **Ensure changelog headers (e.g., 'Minor Changes' vs 'Patch** - Ensure changelog headers (e.g., 'Minor Changes' vs 'Patch Changes') strictly match the version increment type to prevent misleading users about the scope of a release. _(semver, documentation, release-process)_
- **Trace detection calls through templates** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* CLI detection logic may be invoked by template generators rather than the main command entry point. Always verify the template engine's call graph before assuming a detection function is orphaned or unused. _(cli, architecture)_
- **Audit diagnostic call-sites for filters** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* When filtering core data loaders, audit diagnostic consumers like 'stats' or 'explain' commands to determine if they require an override flag to maintain visibility into archived states. _(testing, refactoring, cli)_
- **Anchor command validation patterns with ^ to prevent hooks** - Anchor command validation patterns with `^` to prevent hooks from triggering on arguments that contain the command name as a substring. This ensures the logic only executes for the primary action and avoids false positives during complex command execution. _(bash, shell-scripting, security)_
- **Returning a specific 'overwritten' status instead** - Returning a specific 'overwritten' status instead of a generic 'success' allows for clearer console output and better observability during destructive operations. _(cli, dx, api-design)_
- **Hardcoding specific field names in diagnostics** - Hardcoding specific field names in diagnostics is misleading when multiple related fields, such as Example Hit and Example Miss, trigger the same validation logic. _(dx, linting, ux)_
- **Downgrade missing credentials to warnings** - \*\*Scope:\*\* packages/cli/src/commands/doctor.ts Missing API keys or environment-specific configuration should trigger `warn` rather than `fail` in diagnostics. This avoids blocking CI or git hooks in environments where those specific integrations are not required. _(dx, ci, doctor)_ _(archived: Compiled with undefined astGrepPattern and empty regex pattern; rule cannot fire on anything. Compile-worker prompt failure to produce a valid pattern for the warn-vs-fail classification lesson.)_
- **Replacing inline fs.rmSync calls with a shared helper** - Replacing inline fs.rmSync calls with a shared helper ensures that retry logic and error-handling policies remain consistent as the test suite grows. _(testing, refactoring)_
- **Warn on skipped configured resources** - \*\*Scope:\*\* packages/cli/src/commands/search.ts Log explicit warnings when skipping configured linked repositories due to missing dependencies like embedding providers to ensure users are aware of partial failures. _(cli, dx, logging)_
- **Validate mutex flags before side-effecting calls** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Validating mutually exclusive flags before loading configuration prevents confusing diagnostic errors, such as missing API keys, when the command would have failed regardless. _(cli, architecture)_
- **Guard against self-suppressing patterns** - \*\*Scope:\*\* packages/core/src/compile-lesson.ts Patterns matching suppression directives (e.g., totem-ignore) must be rejected during compilation. The engine suppresses these lines before evaluation, rendering such rules logically unreachable. _(compiler, linting, logic)_
- **Gracefully skip linting on empty rules** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Returning an empty result instead of throwing when rules are missing allows CI to exit cleanly for repositories in early adoption stages. _(cli, lint, ci)_
- **When implementing custom glob matching for dir/\\\*/.ext,** - \*\*Pattern:\*\* \.(?:(?:includes|startsWith)\s\*\(\s\*['"]\\_\\_['"]|indexOf\s\*\(\s\*['"]\\_\\_['"]\s\*\)\s\*(?:>=\s\*0|>\s\*-1|!==?\s\*-1|===?\s\*0))
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js
  \*\*Severity:\*\* error

When implementing custom glob matching for dir/\\\*/.ext. _(architecture, curated)_

- **When upserting a managed PR comment identified by an HTML** - When upserting a managed PR comment identified by an HTML marker, selecting the highest (newest) ID prevents the logic from updating stale or duplicate markers. _(github-api, automation)_
- **Clarify Ollama tag resolution** - \*\*Scope:\*\* docs/reference/supported-models.md When defaulting to a model name like 'gemma4', explicitly document which tag (e.g., :latest) it resolves to and its hardware footprint. This ensures users can accurately correlate local performance with published benchmarks that might use specific variants like :e4b. _(ollama, documentation, llm)_
- **Use onWarn callbacks in core library modules** - Core library modules should accept an optional `onWarn` callback instead of using `console` methods or logging directly. This prevents hard dependencies on logging frameworks and ensures diagnostics are surfaced to callers rather than being swallowed in silent catch blocks. _(architecture, logging, typescript)_
- **Guard against Windows teardown races** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use retries and delays (e.g., maxRetries: 3) for directory cleanup on Windows to prevent flakes caused by transient file handles from antivirus or indexing services. _(windows, testing, fs)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 8 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/src/commands/shield.content-hash-parity.test.ts, packages/cli/src/commands/sync.test.ts, packages/cli/src/exemptions/\_\_tests\_\_/exemption-engine.test.ts, packages/cli/src/hooks/\_\_tests\_\_/auto-context.test.ts, packages/core/src/pack-discovery.test.ts (+ 3 more). reasonCode: stage4-out-of-scope-match.)_
- **When detecting Bun environments, check for both bun.lockb** - \*\*Pattern:\*\* ^(?=.\*\bbun\.lockb?\b)(?!.\*\bbun\.lockb\b.\*\bbun\.lock\b|.\*\bbun\.lock\b.\*\bbun\.lockb\b).\*$
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.js, \*\*/\*.ts, \*\*/\*.jsx, \*\*/\*.tsx, \*\*/\*.sh, \*\*/\*.yml, \*\*/\*.yaml, Dockerfile\*
  \*\*Severity:\*\* error

When detecting Bun environments, check for both bun.lockb. _(architecture, curated)_

- **Shared documentation and lessons should use portable** - Shared documentation and lessons should use portable commands like 'git rev-parse --show-toplevel' instead of hardcoded local file paths to ensure instructions work for all contributors. _(documentation, dx)_
- **Guard against null substrate journal roots** - \*\*Scope:\*\* .claude/hooks/\*\*/\*.js, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Always check for `null` journal roots in substrate resolver outputs before performing file operations. This enables graceful degradation and prevents crashes when a substrate source is missing or incorrectly configured. _(substrate, error-handling)_
- **Library code should use an onWarn callback instead** - Library code should use an onWarn callback instead of hardcoding console.warn to allow consumers to route or suppress output according to their own logging strategy. _(architecture, dx, logging)_
- **Every totem spec output must include linting, shielding,** - Every `totem spec` output must include linting, shielding, and execution verification as the final implementation steps. This ensures that AI-generated code is immediately validated against project constraints before being considered complete. _(totem-spec, linting, automation)_
- **Partition manifest updates from content writes** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Only rewrite content files when data actually changes, but refresh manifests on input drift to avoid invalidating mtime-based downstream caches unnecessarily. _(performance, caching, fs)_
- **Hardcoded default values for properties like rule** - \*\*Pattern:\*\* \b(category|ruleCategory)\s\*:\s\*['"][^'"]+['"]
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

Hardcoded default values for properties like rule. _(style, curated)_

- **Archive rules in-place to preserve telemetry** - \*\*Scope:\*\* .totem/compiled-rules.json Flawed or deprecated rules should be archived with a status and reason rather than deleted to maintain historical telemetry continuity and queryability. _(totem, maintenance)_
- **Even when data is missing, wrap the fallback instructions** - Even when data is missing, wrap the fallback instructions or 'no context' notes in XML tags (e.g., <context*note>) to maintain a consistent schema for the LLM and reduce parsing ambiguity. *(prompt-engineering, llm, structure)\_
- **Centralize error signature detection (such as 429 status** - \*\*Pattern:\*\* (\.status\s\*===?\s\*429|['"]rate\s+limit['"])
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.sh
  \*\*Severity:\*\* warning

Centralize error signature detection (such as 429 status. _(style, curated)_

- **Always forward config to resolvers** - \*\*Scope:\*\* packages/cli/src/commands/doctor.ts, packages/mcp/src/state-extractors.ts Consumer functions like diagnostics or state extractors must pass the full configuration object to underlying resolvers. Bypassing the config layer prevents the system from honoring user-defined overrides in project configuration files. _(architecture, dx)_
- **Requiring a minimum character count for override** - Requiring a minimum character count for override justifications prevents empty or low-effort bypasses of critical security findings while ensuring a ledger of rationale exists. _(security, cli, governance)_
- **Including empty strings in branch whitelists can cause** - Including empty strings in branch whitelists can cause security gates to silently bypass if branch resolution fails; explicit matching ensures that environment detection errors result in a hard block. _(security, git, automation)_
- **Avoid circular dependencies with dynamic imports** - \*\*Scope:\*\* .claude/hooks/\*\*/\*.js, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use workspace-relative dynamic imports to load core utilities into repository hooks. This pattern avoids circular workspace dependencies at the repo root while allowing hooks to access shared resolution logic. _(architecture, esm, dependencies)_
- **Pin Bun versions in CI** - \*\*Scope:\*\* .github/workflows/release-binary.yml Using 'latest' for Bun in GitHub Actions can cause build drift; pinning to a specific version prevents unexpected CI breakages from upstream releases. _(ci, bun, reproducibility)_
- **SIGINT/SIGTERM handlers that call process.removeListener** - SIGINT/SIGTERM handlers that call process.removeListener must reference the exact function object that was registered. Using wrapper functions (e.g., onSigint = () => cleanup('SIGINT')) means the wrapper must be removed, not the inner function. Mismatched references cause silent listener leaks and infinite re-raise loops on signal delivery. Tags: concurrency, signals, node _(manual)_
- **When detecting tool-generated blocks for removal, match** - When detecting tool-generated blocks for removal, match sentinel markers using line-start regex or strict equality rather than simple substring inclusion. This prevents accidental over-scrubbing if the marker string appears within a user's comment or a standard line of code. _(cli, regex, security)_
- **Persist dynamic import initialization errors** - \*\*Scope:\*\* packages/cli/src/index-lite.ts When lazy-loading core dependencies, capture and persist initialization errors in a module-scoped variable so that downstream commands can report the specific cause of the failure. _(typescript, cli, error-handling)_
- **Restrict fallback to specific error codes** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.ts, !\*\*/\*.test.\* When implementing fallbacks for optional system components, only swallow specific 'unavailable' errors. Re-throwing unexpected failures prevents masking critical bugs or configuration issues. _(error-handling, architecture)_ _(archived: Over-broad astGrepYamlRule. The `has: { pattern: 'null' }` matcher with `stopBy: end` fires on any `null` literal anywhere inside a catch clause — assignments (`result = null`), returns (`return null`), comparisons (`x !== null`), type narrowings, and casts all match. Combined with the `not: has: $ERR.code` absence check, this flags many legitimate catch blocks that use `null` for reasons unrelated to the fallback-swallow pattern the lesson (PR #1506) was trying to guard. The rule's intent — require a specific error-code check before swallowing to null — is valid, but the ast-grep encoding cannot express 'fallback-assignment to null' without additional structural constraints. Auto-compiled on the 2026-04-16 postmerge. Archived via the mmnto-ai/totem#1345 filter. Kept in the ledger as a compile-worker failure mode where a positional `has:` clause under-constrains the target.)_
- **Isolate submodule updates for revertability** - \*\*Scope:\*\* .strategy Perform submodule pointer bumps in dedicated PRs without accompanying code or doc changes to allow for clean reverts of version changes without unrelated churn. _(git, submodule, workflow)_
- **CLI command files should use dynamic await import()** - CLI command files should use dynamic `await import()` for heavy internal packages within the command function rather than top-level static imports. This ensures that simple operations like `--help` or version checks remain fast by avoiding unnecessary module loading at startup. _(performance, cli, typescript)_
- **Check for cancellation signals (like Clack's isCancel)** - Check for cancellation signals (like Clack's isCancel) after every user prompt to ensure the process exits gracefully on user interrupts like Ctrl+C. _(cli, ux)_
- **Prefer resolvers over git submodules** - Replacing submodules with a multi-layer resolver (env > config > sibling) eliminates gitlink drift churn and simplifies fresh checkout ceremonies. _(git, architecture, dx)_
- **Avoid simple comma splitting for globs** - \*\*Scope:\*\* packages/core/src/lesson-pattern.ts Splitting glob strings by commas breaks brace expansion patterns like `{ts,tsx}`; parsers must respect top-level commas while ignoring those inside braces. _(glob, parsing)_ _(archived: Pattern $STR.split(",") is over-broad — matches any .split(',') call in lesson-pattern.ts regardless of whether it's splitting glob strings, while the actual fix was a domain-specific brace-aware parser. Lesson body content is correct documentation but doesn't translate to a useful structural detection rule.)_
- **Use specific validation ignore lists instead of global** - Use specific validation ignore lists instead of global ignore patterns when files should be excluded from linting but must remain accessible for vector search or AI context. Global ignores often remove files from indexing entirely, breaking retrieval-augmented features. _(configuration, indexing, validation)_
- **Registry metadata should be updated only after pruning** - Registry metadata should be updated only after pruning is finished to ensure that reported chunk counts reflect the final state of the store. _(consistency, indexing)_
- **When inserting blocks into user-managed files, use explicit** - When inserting blocks into user-managed files, use explicit start and end markers to ensure reliable removal. Without a deterministic end marker, automated cleanup commands must rely on fragile heuristics that risk over-scrubbing or corrupting user-authored content. _(architecture, cli, scripts)_
- **For local LLM providers, 500 Internal Server Errors often** - \*\*Pattern:\*\* ^(?!.\*(numCtx|context|VRAM|exhaustion))(?=.\*500)(?=.\*Internal\s+Server\s+Error).\*$
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/llm/\*\*/\*.ts, \*\*/providers/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

For local LLM providers, 500 Internal Server Errors often. _(architecture, curated)_

- **Avoid devaluing major version signals** - \*\*Scope:\*\* .changeset/\*.md Isolated breaking changes with no known programmatic consumers can be downgraded to minor to prevent devaluing the major version signal, ensuring the 'major' bump remains a high-value indicator for users. _(semver, release-management)_
- **Use global mock restoration for Vitest spies** - \*\*Scope:\*\* packages/\*\*/\*.test.ts Use vi.restoreAllMocks() in afterEach when spying on globals, as Vitest's spy return types often fail to narrow cleanly in strict TypeScript environments. _(testing, typescript)_ _(archived: Pattern fires on every vi.spyOn(global, ...) site regardless of whether the suite has vi.restoreAllMocks() in afterEach — ast-grep local scope cannot verify cross-block restoration. Persistent false-positive class flagged by GCA HIGH on #1870.)_
- **Regex-based import restrictions often incorrectly flag** - Regex-based import restrictions often incorrectly flag type-only imports and miss dynamic imports. Using an AST-aware engine ensures rules correctly distinguish between value and type usage across all module loading syntaxes. _(linting, ast-grep, typescript)_
- **Separate enforcement and administrative loaders** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Distinguish between runtime enforcement loaders that filter by lifecycle state and administrative loaders that provide the full manifest for telemetry and management. _(architecture, data-access)_
- **2026-03-06T10:00:40.352Z** - \*\*Pattern:\*\* \b(echo|run_shell_command|exec|sh|bash)\b.\*\$TOOL_INPUT
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*.sh, \*.bash, \*.yml, \*.yaml
  \*\*Severity:\*\* error

Sanitize AI-provided environment variables in shell commands to prevent command injection. _(security, curated)_

- **Functions that mutate module-global state for dependency** - Functions that mutate module-global state for dependency injection must use try-finally blocks to restore defaults, preventing state leakage across test cases or process executions. _(architecture, testing, state-management)_
- **Use a centralized cleanup helper with retry semantics** - Use a centralized cleanup helper with retry semantics (e.g., maxRetries: 3) for temporary directories to prevent intermittent test failures caused by Windows file locks. _(testing, fs, windows)_
- **Specific LLM models, such as Gemini's text-embedding-004,** - Specific LLM models, such as Gemini's `text-embedding-004`, may be unavailable on certain API versions (like v1beta), requiring fallbacks to supported models like `gemini-embedding-001`. Always verify provider-specific model compatibility when switching API tiers or tiers. _(gemini, llm, infrastructure)_
- **Prefer first-arg context for required dependencies** - \*\*Scope:\*\* packages/core/src/rule-engine.ts When a signature change is already breaking, passing a required context as the first argument avoids the ceremony of an options object while following standard dependency injection patterns. _(typescript, architecture, api-design)_
- **Derive metadata from resolved diff sources** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Pass the 'staged' status derived from the resolved diff result to downstream engines rather than the raw CLI flag. This ensures metadata accuracy if the diff resolver falls back to a different source than the one explicitly requested. _(cli, git)_
- **Converting raw filesystem errors like ENOENT or EACCES** - Converting raw filesystem errors like ENOENT or EACCES into custom exceptions (e.g., TotemParseError) allows the application to provide actionable recovery hints to the user. This practice maintains a stable error contract and prevents low-level implementation details from leaking into the UI. _(error-handling, nodejs, dx)_
- **Vector databases like LanceDB may silently accept query** - Vector databases like LanceDB may silently accept query vectors with incorrect dimensions, leading to semantically meaningless results rather than runtime errors. Persisting provider and dimension metadata during ingestion allows the system to verify compatibility before executing searches. _(vector-db, lancedb, embeddings)_
- **Annotate terminal handlers for AST-grep** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Functions that terminate processes should be annotated or recognized as terminal to avoid false positives in 'fail-open' linting rules. _(linting, ast-grep, dx)_
- **When using optional diagnostic callbacks like 'onWarn?.()',** - When using optional diagnostic callbacks like 'onWarn?.()', always provide a fallback to 'console.warn'. This prevents silent degradation of diagnostics when the callback is omitted by future callers. _(dx, typescript, logging)_
- **Iterative string replacements for a list of identifiers** - Iterative string replacements for a list of identifiers are less efficient than a single regex with an alternation group. Consolidating patterns into one expression improves performance and maintainability as the list of items to be stripped scales. _(typescript, regex, performance)_
- **Hashing all lesson files to find a rule's source** - Hashing all lesson files to find a rule's source during CLI operations is expensive and non-scalable. Storing the source file path directly within the compiled rule object avoids these lookups. _(performance, cli, architecture)_
- **When migrating data sources, ensure that specialized logic** - When migrating data sources, ensure that specialized logic like truncation or boundary checks remains covered by unit tests. It is easy to accidentally delete important edge-case tests when the file structure or access pattern they targeted is replaced. _(testing, refactoring, regressions)_
- **Using child.kill() on Windows when shell: true is enabled** - Using `child.kill()` on Windows when `shell: true` is enabled often fails to clean up child processes, leaving orphaned "zombie" processes. Developers must use `taskkill /pid [pid] /T /F` to ensure the entire process tree is terminated. _(nodejs, windows, child-process)_
- **Use sign-sensitive glob set comparison** - \*\*Scope:\*\* packages/core/src/lesson-pattern.ts When comparing sets of globs, use logic that is order-insensitive and duplicate-insensitive but remains sensitive to negation prefixes to detect true divergence. _(glob, logic)_
- **Use .min(1) on string schemas in config arrays** - Use `.min(1)` on string schemas within configuration arrays to reject empty strings at the parsing stage. Catching invalid configuration values early provides clearer feedback to users compared to silently filtering them out during runtime execution. _(zod, validation, configuration)_
- **Avoid splitting error messages on periods** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Splitting error strings on periods can truncate critical debugging context when the error contains code snippets starting with dots (e.g., .method()). Use newline-based splitting or regex to preserve the full diagnostic line. _(error-handling, dx, regex)_ _(archived: Over-broad: $STR.split('.') fires on all dot splits (filename.split('.'), semver parsing, dot-notation handling). Same class as the rule archived in #1352. The lesson is specific to error-message splitting but the pattern is indiscriminate.)_
- **Tiered enforcement for strict gates** - \*\*Scope:\*\* packages/cli/src/commands/install-hooks.ts Apply strict diagnostic gates only to automated agents or specific 'strict' user tiers in git hooks. This provides a calibration on-ramp for human developers while maintaining high standards for CI environments. _(git-hooks, dx)_
- **Inspect error cause for wrapped I/O failures** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Check the 'cause' property of wrapped errors to accurately distinguish between missing files, data corruption, and permission issues. _(error-handling, node.js)_
- **Prefer no sensor over partial coverage** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* It is better to archive a rule than to ship an incomplete pattern that misses related variants, as partial sensors provide a false sense of security. _(llm, linting, quality)_
- **Static top-level imports in CLI command files increase** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Static top-level imports in CLI command files increase startup latency for every invocation, including metadata commands like `--help`. Using dynamic `import()` within the specific command handler ensures that heavy modules are only loaded when actually executed. _(cli, performance, nodejs)_ _(archived: Over-broad: astGrepPattern `import $NAME from '$MODULE'` matches every top-level default import in packages/cli/src/commands/\*\* regardless of whether the module is heavy. Source of the 100+ warning storm on PR #1516. ADR-072 §3 reserves lazy-loading for heavy dependencies. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Forward configuration to multi-layer resolvers** - \*\*Scope:\*\* packages/cli/src/utils/governance.ts Programmatic consumers must explicitly pass the configuration object to resolvers to ensure that user-defined overrides are respected across all precedence layers. _(architecture, dx)_
- **Returning a result object with a specific rejection reason** - Returning a result object with a specific rejection reason instead of a simple null allows callers to distinguish between an absent pattern and a malformed one. _(validation, dx)_
- **Include path context in walkDir errors** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Filesystem traversal helpers should never swallow errors or use empty catch blocks. Rethrowing errors with the specific directory or file path ensures test failures are deterministic and easy to debug. _(testing, dx)_ _(archived: Second-wave duplicate of a37823bcf1e849b5. Same defect: pattern `catch\s\*\([^)]\*\)\s\*\{\s\*\}` fires on every empty-catch block across the codebase. Overlaps with the existing empty-catch detection shipped in 1.13.0 (#664).)_
- **Architectural gate rules, such as forbidding direct** - Architectural gate rules, such as forbidding direct child*process imports, must be set to error severity because warnings only log and do not block at runtime. *(architecture, security, linting)\_
- **Use Jaccard similarity for pattern coverage** - \*\*Scope:\*\* packages/core/\*\*/\*.ts, !\*\*/\*.test.\* A Jaccard similarity threshold of 0.6 on tokenized strings (stripping stopwords and short tokens) provides a reliable heuristic for identifying overlapping or covered patterns in text-based findings. _(algorithms, nlp, clustering)_
- **Ensure all exported entry points receive context** - \*\*Scope:\*\* packages/core/src/rule-engine.ts All exported functions that reach shared state paths must be updated to receive context to ensure complete functional isolation across concurrent runs. _(architecture, concurrency)_
- **Instead of re-running a test suite to show failure logs,** - Instead of re-running a test suite to show failure logs, capture stdout/stderr to a temporary file during the first run and display it on error to avoid doubling execution time. _(git-hooks, performance, testing)_
- **Heuristics for resolving review findings should inspect** - Heuristics for resolving review findings should inspect emoji reactions and commit metadata, as developers often signal completion without explicit text replies. _(github-api, heuristics)_
- **Creating a dedicated directory for hand-written content** - Creating a dedicated directory for hand-written content that is injected verbatim into auto-generated documentation prevents human-authored knowledge from being overwritten. This allows troubleshooting guides and edge cases to survive automated regeneration cycles. _(documentation, automation, architecture)_
- **High-level system prompt rules must strictly align** - High-level system prompt rules must strictly align with the logic used in prompt assembly to prevent the LLM from receiving contradictory or confusing instructions. _(llm, dx, prompt-engineering)_
- **Refrain from using console.warn within core library** - Refrain from using `console.warn` within core library packages to maintain architectural boundaries and adhere to project-specific logging constraints. _(architecture, logging)_
- **Use xargs instead of 'tr' for joining multi-line outputs** - Use xargs instead of 'tr' for joining multi-line outputs into space-separated strings to ensure POSIX compliance and avoid inconsistent newline escaping behavior. _(shell, posix, portability)_
- **GitHub's automatic issue closing requires the 'Closes'** - GitHub's automatic issue closing requires the 'Closes' keyword to be repeated for every issue number in a PR description; listing multiple numbers after a single keyword fails to close subsequent issues. _(github, workflow)_
- **Fixed grouping cascades major version bumps** - \*\*Scope:\*\* .changeset/\*.md When using 'fixed-grouping' in Changesets, a major bump in a single package forces a major bump across the entire group. Downgrading to a minor bump is a valid tactic to prevent unnecessary version inflation across the ecosystem. _(changesets, semver)_
- **Treat active work context as the ground truth for roadmaps,** - Treat active work context as the ground truth for roadmaps, aggressively pruning items not present in the current context to prevent documentation rot. _(llm, documentation)_
- **Persist dynamic import initialization errors** - \*\*Scope:\*\* packages/cli/src/index-lite.ts Catching dynamic import failures without recording the error prevents downstream commands from reporting the root cause of why a module failed to initialize. _(node, error-handling)_
- **Standard console.log or console.error calls in MCP tools** - \*\*Pattern:\*\* \bconsole\.(log|error)\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/mcp/\*\*/\*.ts, packages/mcp/\*\*/\*.js, !\*\*/\*.test.ts, !\*\*/\*.test.js
  \*\*Severity:\*\* warning

Standard console.log or console.error calls in MCP tools. _(style, curated)_

- **Using git merge-base --is-ancestor allows a tool to verify** - Using `git merge-base --is-ancestor` allows a tool to verify if a previous success flag is still valid for the current HEAD, even after rebases or new commits. _(git, caching)_
- **Ollama num_ctx and VRAM: The OpenAI-compatible API adapter** - \*\*Pattern:\*\* 11434/v1
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.py, \*\*/\*.sh, .env\*
  \*\*Severity:\*\* error

Ollama num*ctx and VRAM: The OpenAI-compatible API adapter. *(architecture, curated)\_

- **A top-level catch-all handler is necessary to ensure** - A top-level catch-all handler is necessary to ensure that even unhandled promise rejections or internal parser failures return a valid JSON envelope when structured output is enabled. _(cli, error-handling)_
- **Git hooks should utilize fast, deterministic linting tools** - Git hooks should utilize fast, deterministic linting tools rather than slower AI-powered review tools to avoid workflow friction. This prevents non-deterministic AI outputs from blocking the developer's "fast path" during operations like a git push. _(git, performance, workflow)_
- **Derive staged status from resolved diffs** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Set metadata flags like isStaged based on the resolved diff source rather than raw CLI flags to ensure accurate downstream telemetry. _(cli, git, telemetry)_
- **Avoid calling extraction helpers multiple times on the same** - Avoid calling extraction helpers multiple times on the same source body by passing pre-parsed data into downstream verification functions. This prevents redundant parsing overhead during rule testing. _(performance, refactoring)_
- **CWD-relative writes cause monorepo chaos** - Tools and agents that write files must resolve paths from the project root (where the config file lives), never from process.cwd(). When task runners like turbo invoke commands from package subdirectories, CWD-relative writes spray orphaned artifacts (e.g., .totem/cache/, scratchpad files) into random locations across the monorepo. Always resolve totemDir from the config loader's known path, not from the current working directory.

\*\*Source:\*\* mcp (added at 2026-03-24T22:31:03.101Z) _(agent-discipline, file-io, monorepo, cwd, trap)_

- **Generic error messages in batch processes are ambiguous** - Generic error messages in batch processes are ambiguous when multiple rules apply to the same file; including a query index or content snippet is necessary to identify which specific rule failed. _(dx, logging, ast)_
- **Guard committed files against LLM overwrites** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Standard dirty-file guards only catch uncommitted changes; protect hand-crafted documentation from aggressive LLM rewrites by checking git author dates or providing explicit skip flags. _(git, llm, safety)_
- **Regex for semantic directive detection** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use regex patterns for bullet points and numbered lists as a reliable proxy for counting semantic directives in Markdown-based instruction files. _(regex, markdown, llm)_
- **Avoid broad heading-based filtering** - \*\*Scope:\*\* packages/cli/src/commands/extract-shared.ts Lesson heading matching in retirement ledgers should be specific rather than broad. Overly broad matching can lead to false positives where valid new lessons are incorrectly filtered out. _(extraction, logic, filtering)_
- **Use granular assertions rather than snapshots when testing** - \*\*Pattern:\*\* \.toMatch(Inline)?Snapshot\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.test.ts, \*\*/\*.test.js, \*\*/\*.test.tsx, \*\*/\*.test.jsx, \*\*/\*.spec.ts, \*\*/\*.spec.js, \*\*/\*.spec.tsx, \*\*/\*.spec.jsx
  \*\*Severity:\*\* error

Use granular assertions rather than snapshots when testing. _(architecture, curated)_

- **Shield flag becomes stale after every commit — refresh** - # Shield flag becomes stale after every commit — refresh before push ## What happened The pre-push hook checks that `.totem/cache/.shield-passed` contains the current HEAD SHA. Every `git commit` changes HEAD, making the flag stale. This caused repeated "Shield flag is stale" blocks during the PR workflow — especially painful when amending commits. ## Rule Always run `git rev-parse HEAD > .totem/cache/.shield-passed` AFTER the commit, not before. The sequence is: 1. Run shield (or verify changes are trivial) 2. `git commit` 3. `git rev-parse HEAD > .totem/cache/.shield-passed` 4. `git push` Steps 2-3 must be adjacent — any commit between shield and push invalidates the flag. \*\*Source:\*\* mcp (added at 2026-03-27T19:55:55.260Z) _(shield, pre-push, workflow, git-hooks, trap)_
- **When testing diagnostic output, assert that warnings** - When testing diagnostic output, assert that warnings include the specific file path prefix. This ensures the error reporting logic correctly attributes issues to their source files, which is critical for developer experience. _(testing, dx)_
- **False positives are often caused by overlapping** - False positives are often caused by overlapping or duplicate rule definitions in the generated output rather than bugs in the matching logic. Isolating the specific rule IDs in compiled files helps distinguish between engine errors and data generation flaws. _(debugging, linting, rule-generation)_
- **Assert import boundaries in LLM-free tests** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Use regex-based test assertions to forbid both static and dynamic transitive imports of heavy dependency graphs (like orchestrators) in modules intended to be lightweight. _(testing, architecture)_
- **Differentiate format flags across CLI commands** - \*\*Scope:\*\* packages/cli/src/index.ts The `--format` flag is exclusive to `totem lint`, while other commands use `--json` for scripting to ensure command-specific accuracy and avoid invalid flag errors. _(cli, dx)_ _(archived: Over-broad: fires on any command defining --format, not just misuses. The lesson is about --format being lint-only, but the pattern matches the option definition itself. upgradeTarget: compound (Proposal 226 -- needs 'not-inside' constraint to skip the lint command definition).)_
- **While manual edits to compiled artifacts are generally** - While manual edits to compiled artifacts are generally discouraged, manually promoting a rule from 'warning' to 'error' is the project's standard way to enforce architectural gates. _(architecture, linting, workflow)_
- **Separate engine failures from user suppressions** - \*\*Scope:\*\* packages/core/src/compiler-schema.ts Maintain a strict discriminant between 'failure' events (engine errors) and 'suppress' events (user directives) to ensure system health metrics are not diluted by intentional user overrides. _(architecture, dx)_
- **Development tools that programmatically manage system files** - Development tools that programmatically manage system files like .git/hooks often trigger their own security rules when referencing those paths in strings. These alerts should be demoted to warnings within the installer logic to prevent legitimate configuration code from being flagged as malicious activity. _(security, devtools, git-hooks)_
- **ESM intra-module mock requires re-binding** - \*\*Pattern:\*\* \.\.\.\s\*await\s+vi\.importActual\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.test.ts, \*\*/\*.test.tsx, \*\*/\*.spec.ts, \*\*/\*.spec.tsx
  \*\*Severity:\*\* warning

ESM intra-module mock requires re-binding. _(style, curated)_

- **Reusing strings from fields with strict length limits** - Reusing strings from fields with strict length constraints to populate descriptions often results in incomplete, nonsensical sentences. When automating data backfills, ensure the source field length hasn't clipped the semantic meaning of the content. _(automation, documentation, data-migration)_
- **Match both quote styles in AST string arguments** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts When matching specific string literals in AST rules (e.g., `Buffer.from(..., 'hex')`), explicitly include both single and double quote variants to ensure the rule is robust against trivial formatting changes. _(ast-grep, security)_
- **When reading cache or config files, specifically check** - \*\*Pattern:\*\* \.catch\(\s\*[^)]\*\)\s\*=>\s\*(?!.\*ENOENT)[^\{\s]+|\bcatch\s\*\{
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*config\*.\*, \*\*/\*cache\*.\*
  \*\*Severity:\*\* warning

When reading cache or config files, specifically check. _(architecture, curated)_

- **Implement a "manual pipeline" that allows users to provide** - Implement a "manual pipeline" that allows users to provide deterministic patterns for tasks usually handled by LLMs. This reduces inference costs and ensures 100% reliability for power users who can author precise rules without waiting for model generation. _(architecture, performance, llm)_
- **Lesson: Lesson headings are strictly limited to 60** - \*\*Pattern:\*\* ^# Lesson: .{61,}
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.md
  \*\*Severity:\*\* error

Lesson: Lesson headings are strictly limited to 60. _(security, curated)_

- **Prefer [["$VAR" == "pattern"\*]] over piping to grep** - Prefer `[[ "$VAR" == "pattern"\* ]]` over piping to `grep` to avoid the performance overhead of spawning a subshell. Utilizing built-in shell constructs makes git hooks faster and more efficient, especially when multiple checks are performed in sequence. _(bash, shell-scripting, performance)_
- **Explicitly check for empty or missing SHA flags in git** - Explicitly check for empty or missing SHA flags in git hooks to provide specific 'missing validation' errors rather than generic, misleading 'non-ancestor commit' messages. _(git, shell, dx)_
- **Singular query functions should act as thin wrappers around** - Singular query functions should act as thin wrappers around batch implementations to centralize setup logic like language detection and file parsing. This prevents logic drift and ensures that improvements to the core batch processing logic automatically benefit singular calls. _(refactoring, architecture, maintenance)_
- **Standard console.log or console.error calls in MCP tools** - Standard `console.log` or `console.error` calls in MCP tools can corrupt the stdio transport protocol used for communication. Use dedicated file-based loggers or return formatted system warnings to the agent instead of swallowing errors in catch blocks. _(mcp, logging, error-handling)_
- **Do not assume a provider is local based on its name alone** - Do not assume a provider is local based on its name alone (e.g., Ollama), as it may be hosted as a remote service. Security exceptions for local traffic must be verified against the destination URL's hostname and IP to prevent unintended masking bypasses on remote instances. _(security, llm, networking)_
- **2026-03-07T00:44:37.037Z** - \*\*Pattern:\*\* ^(?!.\*\b(await|return)\b).\*?\.(index|upsert|persist|addDocument|deleteDocument)\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*tool\*/\*\*/\*.ts, \*\*/tools/\*\*/\*.ts, packages/mcp/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

LanceDB operations (index, upsert, persist) must be awaited to prevent silent data loss. _(architecture, curated)_

- **Move large imports, such as multi-line prompt templates,** - Move large imports, such as multi-line prompt templates, inside function bodies to prevent eager parsing at module load time. This improves CLI responsiveness by ensuring heavy strings are only processed when the specific command is actually invoked. _(performance, cli, nodejs)_
- **Verify escaped characters in global renames** - \*\*Scope:\*\* packages/\*\*/\*.ts, packages/\*\*/\*.test.ts, packages/\*\*/\*.spec.ts Standard sed substitutions often miss escaped characters in regex literals (e.g., @scope\/name); use multi-pass scripts to ensure test assertions remain valid after a package rename. Test files are in scope because they are the primary host for these escaped-regex literals — excluding them defeats the lesson's intent. _(regex, testing, automation)_
- **Prefer mechanical local hook logic** - \*\*Scope:\*\* .claude/hooks/\*\*/\*.sh Avoid LLM synthesis or network calls in local hooks to minimize latency and prevent external dependencies from blocking core tool workflows. _(architecture, llm, performance)_
- **Use semantic constraints like "one to two short sentences"** - \*\*Pattern:\*\* \b\d+\s\*([Cc]har(acter)?s?|[Ww]ords?)\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, \*\*/\*.py, \*\*/\*.md, \*\*/\*.yaml, \*\*/\*.yml
  \*\*Severity:\*\* warning

Use semantic constraints like "one to two short sentences". _(style, curated)_

- **Use field scoping for argument validation** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Using 'has' in ast-grep rules can allow bypasses via mixed expressions; use 'field' scoping (e.g., 'arguments.0') to strictly enforce that arguments are pure literals. _(ast-grep, security, linting)_ _(archived: Second-wave duplicate of aeb65ba1a27ec781 with a simpler regex `\bhas\s\*:\s\*\{`. Same defect: fires on every ast-grep rule definition that uses the `has:` combinator, which is standard authoring syntax. Would flag every rule in .totem/compiled-rules.json.)_
- **The --force flag should only bypass the tool's own** - The --force flag should only bypass the tool's own ownership markers, not external detection like Husky or Lefthook. This prevents accidental interference with other hook managers while allowing recovery from internal state mismatches. _(cli, git-hooks, safety)_
- **Surface truncation warnings before processing** - \*\*Scope:\*\* packages/cli/src/index.ts Check input size limits at the resolution layer to provide fail-loud warnings before expensive or confusing downstream LLM processing occurs. _(dx, cli, llm)_
- **Drift detector flags lesson file path mentions** - \*\*Pattern:\*\* \b[\w.-]+\/[\w.-]+\.[a-z0-9]{2,}\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* .totem/lessons/\*\*, .totem/lessons.md
  \*\*Severity:\*\* warning

Drift detector flags lesson file path mentions. _(style, curated)_

- **Query engines must throw exceptions on parsing or query** - Query engines must throw exceptions on parsing or query crashes instead of returning empty result sets. Returning empty arrays creates a fail-open security vulnerability where malformed or malicious code can bypass detection gates silently. _(security, ast, error-handling)_
- **Route stderr to stdout for AI session hooks** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Redirecting `stderr` to `stdout` in AI session hooks ensures that orientation banners or diagnostic output are visible in the AI's prompt context rather than being hidden in system logs. _(claude, cli, dx)_
- **2026-03-08T02:39:04.901Z** - \*\*Pattern:\*\* \.(toBeGreaterThan|toBeGreaterThanOrEqual)\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.test.ts, \*\*/\*.test.js, \*\*/\*.spec.ts, \*\*/\*.spec.js
  \*\*Severity:\*\* warning

Avoid brittle numeric assertions like toBeGreaterThan; use precise matchers instead. _(style, curated)_

- **When determining if a session is interactive, check both** - When determining if a session is interactive, check both stdin.isTTY and stdout.isTTY. This prevents the CLI from emitting ANSI escape codes or interactive prompts when output is being piped to another process or redirected to a file. _(cli, unix, ux)_
- **Hardcoding strings for categories in both reporting and CLI** - Hardcoding strings for categories in both reporting and CLI layers creates "logic drift" and maintenance overhead. Defining these as shared constants in a core schema ensures architectural consistency across all system layers. _(architecture, refactoring, maintenance)_
- **Normalize polymorphic metadata inputs** - \*\*Scope:\*\* packages/core/src/types.ts Use Zod preprocessors to handle diverse input formats like YAML lists, scalars, and comma-separated prose, coercing them into a canonical internal array format. _(zod, parsing, dx)_
- **Implement architectural safeguard tests to ensure** - Implement architectural safeguard tests to ensure that foundational rules remain identical across different LLM instruction files like CLAUDE.md and GEMINI.md. _(documentation, testing)_
- **Using a unified "Totem Error" tag in error logs instead** - \*\*Pattern:\*\* ['"](?![^'"]\*Totem Error)(?:\[[^\]]\*Error\]|[\w-]+\s+Error:)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, \*\*/\*.py, \*\*/\*.go
  \*\*Severity:\*\* warning

Using a unified "Totem Error" tag in error logs instead. _(style, curated)_

- **Git log entries for closed-but-unshipped issues can cause** - Git log entries for closed-but-unshipped issues can cause persistent LLM hallucinations even if prompt instructions or glossaries explicitly forbid their inclusion. Stripping these references at the data level before and after LLM processing is more effective than relying on context-layer overrides. _(llm, documentation, git)_
- **Ensure test names and assertions accurately distinguish** - Ensure test names and assertions accurately distinguish between intentional fallback behavior, such as zero-vector returns, and actual exceptions. Mislabeling a recovery path as a throw hides the fact that the system is successfully absorbing the error. _(ai, testing, resilience)_
- **Submodule pointer updates, such as those in .strategy** - Submodule pointer updates, such as those in `.strategy` directories, can trigger false positives during automated diff analysis or linting. Pre-filtering the git diff with ignore patterns ensures CI tools only react to actual code changes rather than metadata updates. _(ci, git, submodules)_
- **Using 'git rev-parse --show-toplevel' in hooks ensures** - Using 'git rev-parse --show-toplevel' in hooks ensures that state files are correctly located regardless of which subdirectory the git command was issued from. _(git, hooks, bash)_
- **Use overloads for polymorphic field routing** - \*\*Scope:\*\* packages/core/src/compiler.ts Applying TypeScript overloads to functions handling multiple engine types prevents silent object-to-string coercion when passing objects to engines that only support strings. _(typescript, type-safety)_
- **Leverage existing pipeline data for zero-cost telemetry** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Utilize data already generated in earlier pipeline stages, such as AST context, to implement new telemetry without introducing additional parsing or API overhead. _(telemetry, performance, ast)_
- **Avoid broad negative tokens like \bno\b when detecting** - Avoid broad negative tokens like `\bno\b` when detecting developer pushback to prevent false positives on phrases like 'No worries, fixed'. _(regex, nlp)_
- **Narrow GHA injection rules to execution contexts** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* GitHub Actions substitutes expressions in `env:` and `with:` blocks before shell execution, making them safe from injection. Lint rules should target execution keys like `run:` or `shell:` to avoid false positives in safe YAML contexts. _(github-actions, security, regex)_
- **Warning messages triggered by security violations** - \*\*Pattern:\*\* \.(?:warn|error|log)\(\s\*[`'].\*(?:security|malicious|violation|illegal|invalid|attack).\*\$\{(?!sanitize|escape|encode|strip)[^}]+\}
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* error

Warning messages triggered by security violations. _(security, curated)_

- **Repository conventions require the 'Totem Error' tag** - Repository conventions require the 'Totem Error' tag for all `log.error` calls to ensure consistent diagnostic parsing and filtering across the CLI. _(cli, logging)_
- **Avoid refactoring synchronous factory functions to async** - \*\*Pattern:\*\* \basync\b.\*\bimport\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* warning

Avoid refactoring synchronous factory functions to async. _(style, curated)_

- **Transitioning from generic errors to a typed hierarchy** - Transitioning from generic errors to a typed hierarchy like `TotemGitError` allows for domain-specific recovery logic and error codes. This structure helps the application distinguish between environment issues and tool failures, enabling more precise diagnostic messages and programmatically accessible error states. _(error-handling, architecture, git)_
- **Unconditionally deleting environment variables in test** - Unconditionally deleting environment variables in test cleanup can leak state and cause failures in other tests. Always capture the original value and restore it to ensure proper test isolation. _(testing, dev-experience)_
- **Bypass lint hallucinations with equivalent regex** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* When common idioms like string splitting trigger persistent false-positive lint warnings, use semantically equivalent regex patterns to bypass the matcher. This maintains logic while satisfying strict or 'hallucinating' enforcement rules. _(linting, dx, regex)_
- **LLMs persist stale data from prior regen context** - LLMs can persist stale or nonexistent data when using previous document versions as context for regeneration cycles. Explicit negative constraints are required to prevent the model from treating its own prior output as a source of truth for issue statuses or references. _(llm, documentation, prompt-engineering, hallucinations)_
- **Use pnpm exec for workspace binaries in monorepos** - \*\*Pattern:\*\* \bpnpm\s+bin\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*.sh, \*.bash, \*.yml, \*.yaml, package.json
  \*\*Severity:\*\* warning

Use pnpm exec for workspace binaries in monorepos. _(style, curated)_

- **Sort PR identifiers numerically** - \*\*Scope:\*\* packages/cli/src/commands/recurrence-stats.ts PR identifiers must be sorted numerically (e.g., 80 < 200) rather than lexically to maintain chronological and logical order in reports. _(cli, sorting)_
- **Searching for specific response strings in existing comment** - Searching for specific response strings in existing comment threads before performing actions prevents duplicate issue creation in automated workflows. _(automation, idempotency)_
- **Running 'totem docs' immediately after 'totem extract'** - Running 'totem docs' immediately after 'totem extract' is required during release flows to ensure canonical documentation stays in sync with newly captured knowledge. _(release, documentation)_
- **Ensure environment probes are non-throwing** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Environment probes should wrap dynamic imports and network calls in try/catch blocks to return a 'not available' state instead of throwing. This ensures that optional feature detection doesn't crash critical paths like project initialization. _(cli, resilience, error-handling)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 47 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: .claude/hooks/session-context.js, packages/cli/src/adapters/create-issue-adapter.ts, packages/cli/src/adapters/multi-repo-adapter.ts, packages/cli/src/commands/adr.test.ts, packages/cli/src/commands/bootstrap-wiring.test.ts (+ 42 more). reasonCode: stage4-out-of-scope-match.)_
- **HTML comment totem-context directives are not parsed by lint** - # HTML comment totem-context directives are not parsed by lint ## What happened Added `<!-- totem-context: mermaid diagram — hex colors are not issue numbers -->` to README.md expecting it to suppress lint false positives. Lint still flagged the hex colors because lint looks for `// totem-context:` in code-style comments, not HTML comments. ## Rule - `// totem-context: <reason>` → suppresses lint AND shield (same-line or preceding-line in code files) - `// totem-ignore` → suppresses lint only (no justification logged) - `ignorePatterns` in config → file-level exclusion from lint In markdown files, `// totem-context:` syntax doesn't work because markdown has no line-comment syntax. Use `ignorePatterns` to exclude markdown files from lint instead. \*\*Source:\*\* mcp (added at 2026-03-27T19:55:50.111Z) _(totem-context, lint, suppression, markdown, trap)_
- **Including ticket numbers in validation flags prevents stale** - Including ticket numbers in validation flags prevents stale success markers from one branch or ticket from incorrectly authorizing operations in another. _(architecture, workflow)_
- **Metadata keys extracted from prose must require a mandatory** - Metadata keys extracted from prose must require a mandatory delimiter to prevent accidental matches on standard sentences starting with keywords. Without a mandatory colon, a line like "Pattern is important" could be incorrectly parsed as a "Pattern" field value. _(regex, validation, parsing)_
- **Passing a trigger context (e.g., via environment variables)** - Passing a trigger context (e.g., via environment variables) when a hook calls a CLI allows the tool to differentiate between manual and automated runs for logging. _(cli, observability)_
- **Avoid using exit 0 inside git hooks intended for chaining** - \*\*Pattern:\*\* \bexit\s+0\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* .husky/\*\*/\*, scripts/hooks/\*\*/\*, \*.sh
  \*\*Severity:\*\* error

Avoid using exit 0 inside git hooks intended for chaining. _(architecture, curated)_

- **Auditing broad keyword matchers (like \bimport) prevents** - Auditing broad keyword matchers (like `\bimport`) prevents collisions with standard library usage and reduces false positive noise. Consolidating into specific patterns ensures rules remain targeted and non-redundant. _(linting, audit, false-positives)_
- **Dynamic imports intended for performance optimization** - Dynamic imports intended for performance optimization should be confined to CLI command entry points rather than utility or adapter layers. This boundary maintains a clean dependency graph for internal logic and avoids triggering security scanner flags associated with lazy-loading patterns in lower-level code. _(nodejs, cli, architecture)_
- **Avoid over-broad empty array declarations** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Generic patterns like `const $VAR = []` are too broad and trigger on every empty array declaration. Ensure patterns are specific enough to distinguish intended targets from transient arrays. _(ast-grep, linting)_
- **Exact-match regexes for HTML tags fail on valid variants** - Exact-match regexes for HTML tags fail on valid variants that include attributes (e.g., `<details open>`) or non-standard whitespace. Case-insensitive patterns with word boundaries and attribute wildcards are required for resilient extraction of metadata from review bodies. _(regex, html, parsing)_
- **BSD sed on macOS does not support the \x1b hex escape; use** - BSD sed on macOS does not support the \x1b hex escape; use perl or col -b to strip ANSI color codes in scripts that must run across different operating systems. _(shell, macos, portability)_
- **High-level system prompt rules must precisely match** - High-level system prompt rules must precisely match the specific instructions injected by the code during prompt assembly to avoid providing the LLM with conflicting behavioral guidance. _(prompt-engineering, reliability)_
- **Use semantic checks, such as verifying the presence** - Use semantic checks, such as verifying the presence of specific object types, instead of checking array lengths for fallback logic. Hardcoded length checks are fragile and break silently when the number of default or prepended items changes during refactoring. _(clean-code, logic, robustness)_
- **Using optional chaining for diagnostic callbacks** - Using optional chaining for diagnostic callbacks like `onWarn?.()` can silently swallow critical failures if the caller omits the handler; providing a fallback to `console.warn` ensures visibility. _(typescript, dx, logging)_
- **Prefer hard migrations for architectural splits** - \*\*Scope:\*\* packages/core/src/pack-manifest-writer.ts Declining graceful fallbacks in internal migrations prevents silent dual-reading paths that would otherwise obscure the resolver's logic and weaken architectural enforcement. _(architecture, migration, resolver)_
- **Naive substring matching on paths, such as using** - Naive substring matching on paths, such as using `.includes('adapters/')`, can incorrectly match unintended segments like `src/notadapters/`. Using regex boundaries or path-splitting ensures logic only applies to the intended directory structure. _(node, filesystem, regex)_
- **Cover all dynamic evaluation constructors** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Rules forbidding dynamic code must target both 'new Function()' and the bare 'Function()' constructor, as both facilitate arbitrary code execution. _(security, javascript)_ _(archived: Second-wave duplicate of ec8e329a673cf601. Pattern `Function($$$ARGS)` fires on every reference to the Function constructor. The pack-agent-security rule a0b737fd43fb943e already covers dynamic code-eval constructors with proper context gating.)_
- **Simple quote-tracking logic for string literals fails** - Simple quote-tracking logic for string literals fails when encountering escaped backslashes, leading to incorrect pattern validation for complex strings. _(validation, regex, parsing)_
- **Unset environment variables in test cleanup** - \*\*Scope:\*\* \*\*/\*.test.ts When mocking environment variables, test cleanup must explicitly delete variables that were originally undefined to prevent state leakage between test cases. _(testing, environment)_
- **Adding 'edited' to pull_request trigger types ensures** - Adding 'edited' to pull*request trigger types ensures that modifying a PR title to add a bypass string (like [UPDATE-RULES]) creates a fresh workflow run with updated context. *(github-actions, ci)\_
- **Ensure that sanitization or masking applies to both** - Ensure that sanitization or masking applies to both the primary request and any fallback or retry paths in the orchestrator pipeline. Neglecting to use the sanitized payload in retry logic can result in accidental data leakage during service instability. _(architecture, security, llm)_
- **Avoid ast-grep meta-variable collisions** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts Identifiers starting with `$` or named `\_` trigger ast-grep meta-variable and wildcard logic, causing significant over-matching in string patterns. Use a safety guard to fall back to regex for these specific names to maintain rule precision. _(ast-grep, static-analysis, regex)_
- **Use named constants for diagnostic counts** - \*\*Scope:\*\* packages/\*\*/\*.test.ts Replace magic numbers in diagnostic test assertions with named constants to improve drift safety when adding or removing checks from a command pipeline. _(testing, clean-code)_
- **Manually editing machine-generated files** - Manually editing machine-generated files like compiled-rules.json leads to out-of-sync configurations and lost changes during regeneration. Always update the source lesson or compiler logic to ensure persistence. _(tooling, automation)_
- **Hardcoding the CLI name or description in custom help** - Hardcoding the CLI name or description in custom help formatters leads to divergence from the actual program configuration. Use cmd.name() and cmd.description() to ensure help output stays in sync with the root command. _(cli, commander, dx)_
- **Ensure resilient feature detection** - \*\*Scope:\*\* packages/cli/src/commands/init-detect.ts Feature detection during initialization must handle missing dependencies or environment errors silently. Falling back to a safe default state is preferable to crashing the onboarding process when optional tools like Ollama are missing. _(cli, initialization, error-handling)_
- **When extracting data from third-party CLI summaries using** - When extracting data from third-party CLI summaries using grep or awk, implement a safe fallback like ${VAR:-all} to handle unexpected output format changes gracefully. _(testing, vitest, shell)_
- **Using [val].flat().filter(Boolean) to normalize inputs** - Using `[val].flat().filter(Boolean)` to normalize inputs often loses TypeScript's type narrowing, resulting in generic arrays that require manual casting. Explicit ternary checks for arrays and truthiness preserve specific types like `string[]` more cleanly and safely. _(typescript, type-safety, refactoring)_
- **Use .cjs extension for Claude hooks** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* In projects with 'type: module', use the .cjs extension for Claude Code hooks because Claude executes them via Node.js require(), which rejects .js files resolved as ESM. _(claude, node, esm)_
- **When creating rules to catch generic Error usage,** - When creating rules to catch generic `Error` usage, explicitly exclude project-specific error base classes or variants. This prevents the linting rule from flagging the very patterns designed to replace standard errors. _(errors, pattern-matching, false-positives)_
- **AI agent memory config architectures differ significantly** - AI agent memory config architectures differ significantly across agents, and GCA (the PR review bot) and Gemini CLI are separate products sharing the `.gemini/` directory with zero file overlap.

\*\*Gemini Code Assist (GCA):\*\* Reads only `.gemini/config.yaml` (review settings) and `.gemini/styleguide.md` (review rules). Does NOT read GEMINI.md, settings.json, hooks/, or skills/.

\*\*Gemini CLI:\*\* Reads GEMINI.md (uppercase only by default) from project root, current dir, or ancestor dirs up to git root. Also reads .gemini/settings.json (project-level), ~/.gemini/settings.json (global), .gemini/hooks/ (must be wired in settings.json), and .gemini/skills/ (auto-discovered). Does NOT read config.yaml or styleguide.md. The context filename is configurable via context.fileName in settings.json.

\*\*Claude Code:\*\* Uses CLAUDE.md (project root) and ~/.claude/ (global). Keep CLAUDE.md lean (<~32 lines) — length kills instruction compliance.

\*\*Copilot:\*\* Uses `.github/copilot-instructions.md` (project only).

\*\*Junie:\*\* Uses .junie/guidelines.md or .junie/AGENTS.md for instructions (project only, loaded into every prompt). MCP config at .junie/mcp/mcp.json (NOT .mcp.json). Supports skills at .junie/skills/ with SKILL.md frontmatter. No global guidelines — only project-level. Same "keep it lean" principle applies.

When scaffolding configs via totem init, each agent needs its own format but the instruction content should be identical and concise. IMPORTANT: .gemini/gemini.md (lowercase) is NOT read by either product with default settings. _(agent-config, init, claude, gemini, copilot, junie, architecture)_

- **Non-deterministic selection of messages when grouping** - Non-deterministic selection of messages when grouping violations by location causes flickering PR comments; sorting by a stable identifier like a hash ensures consistent summaries. _(linting, dx)_
- **Always propagate parse warning callbacks in AST-based test** - Always propagate parse warning callbacks in AST-based test runners to ensure syntax errors in test fixtures do not silently cause false negatives. Swallowing these warnings makes it impossible to distinguish between a "no match" and a "failed to parse." _(testing, diagnostics, ast-grep)_
- **Documentation generators that pull manual snippets** - Documentation generators that pull manual snippets into generated files must be scoped to specific targets rather than applied globally. Indiscriminate injection can cause identical troubleshooting or metadata sections to appear redundantly across every file in the documentation set. _(documentation, automation, tooling)_
- **Export interfaces for custom error fields** - \*\*Scope:\*\* packages/core/src/sys/exec.ts Export dedicated interfaces for custom properties attached to thrown errors, such as `.status` or `.stdout`. This allows consumers to perform type-safe error handling and avoids forced casting to `any` in catch blocks. _(typescript, dx)_
- **Manually joining strings for YAML frontmatter can break** - Manually joining strings for YAML frontmatter can break the parser if tags contain special characters; use a proper serializer or explicit escaping for quotes and backslashes. _(yaml, serialization)_
- **Prefer Vitest's expect().rejects.toHaveProperty()** - \*\*Engine:\*\* ast-grep
  \*\*Severity:\*\* warning
  \*\*Scope:\*\* \*\*/\*.test.ts, \*\*/\*.spec.ts
  \*\*Pattern:\*\* `try { $$$PRE; expect.fail($$$ARGS); $$$POST } catch ($ERR) { $$$CATCH }`

Prefer Vitest's expect().rejects.toHaveProperty(). _(style, curated)_

- **Applying on.pull_request.paths filters to specialized** - Applying `on.pull\_request.paths` filters to specialized workflows prevents false CI failures and unnecessary resource consumption on documentation-only PRs. _(github-actions, ci-cd)_
- **LLM training data is frequently stale regarding the latest** - LLM training data is frequently stale regarding the latest Gemini model identifiers, leading agents to flag valid names as incorrect. Always prioritize current code or official documentation over agent suggestions when validating specific model strings. _(gemini, llm, documentation)_
- **When using the @google/genai SDK (v1+), the constructor** - \*\*Pattern:\*\* new\s+GoogleGenerativeAI\s\*\(\s\*[^\s\{]
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx
  \*\*Severity:\*\* warning

When using the @google/genai SDK (v1+), the constructor. _(style, curated)_

- **Prefer dynamic resolution over git submodules** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Replacing git submodules with a multi-layer resolver (env, config, sibling) eliminates gitlink pointer drift and mandatory fetch overhead for all checkouts. _(git, architecture, dx)_
- **2026-03-05T04:05:16.794Z** - \*\*Pattern:\*\* \.(includes|startsWith)\(['"]\\\[Totem Error\\\]['"]\)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, !\*\*/error\*.ts, !\*\*/error\*.js
  \*\*Severity:\*\* error

Do not assert error messages by checking string prefixes; use TotemError subclasses. _(architecture, curated)_

- **Account for leading whitespace in line-start parsers** - \*\*Scope:\*\* packages/mcp/src/tools/\*\*/\*.ts, !\*\*/\*.test.\* Parsers using start-of-string anchors (^) should allow for leading whitespace or use trimStart() to prevent failures caused by leading blank lines in user input. _(parsing, dx)_
- **When extracting detection/scanning functions from a God** - When extracting detection/scanning functions from a God Object into a separate module, hook installers that depend on scaffolding functions in the original file create circular imports. Move the detection logic and constants without the hook installer fields, then wire up the hooks at module scope in the orchestrator file via post-import assignment. This avoids circular dependencies while keeping the public API and test imports unchanged. _(refactoring, architecture, circular-deps, god-object)_
- **Provide actionable hints in CLI errors** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts CLI errors for missing resources should include specific remediation hints, such as sibling clone commands or environment variable references, to improve developer experience. _(cli, dx)_
- **Prefer cross-spawn for Windows shim resolution** - \*\*Scope:\*\* packages/core/src/sys/\*\*/\*.ts, !\*\*/\*.test.\* Using `shell: true` to resolve Windows `.cmd` shims introduces shell injection risks; `cross-spawn` handles shim resolution safely without enabling the shell layer. _(node, security, windows)_
- **Using String() casting on input patterns can lead to silent** - Using `String()` casting on input patterns can lead to silent failures by turning unexpected objects into `"[object Object]"` strings. Explicitly validating types and throwing descriptive errors ensures that logic errors are caught during compilation rather than producing invalid rule outputs. _(typescript, error-handling, validation)_
- **Prioritize lint patterns over style guides** - \*\*Scope:\*\* README.md, docs/wiki/\*.md Automated linting patterns, such as specific heading formats, take precedence over general prose style guides to prevent build failures until the rules are officially reconciled. _(linting, documentation)_
- **When parsing shell scripts to replace code blocks, a naive** - When parsing shell scripts to replace code blocks, a naive regex for the `fi` keyword can prematurely match nested conditionals and cause syntax errors. _(shell, regex)_
- **Treat detected JSON as terminal parse result** - Parsers with legacy fallbacks should treat 'JSON detected but empty' as a terminal success state rather than a failure to prevent unintended and potentially insecure fallback to regex-based extraction. _(llm, parsing, architecture)_
- **Use join over resolve for paths** - \*\*Scope:\*\* packages/core/src/strategy-resolver.ts Prefer path.join over path.resolve when combining base paths with potentially untrusted inputs to mitigate path injection vulnerabilities. _(security, nodejs)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 41 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/src/assets/compiled-baseline.test.ts, packages/cli/src/commands/config-drift.test.ts, packages/cli/src/commands/docs.ts, packages/cli/src/commands/doctor.ts, packages/cli/src/commands/extract-shared.ts (+ 36 more). reasonCode: stage4-out-of-scope-match.)_
- **Avoid unifying logic between different engines** - Avoid unifying logic between different engines if their underlying execution models, such as async batch queries versus sync individual matching, differ significantly. Prematurely forcing a shared helper before a common abstraction like YAML rules exists can increase code complexity rather than reducing it. _(refactoring, software-design, maintainability)_
- **Provide actionable hints in configuration errors** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts CLI errors for missing dependencies should include specific hints, such as sibling clone commands or environment variable references, to reduce developer friction. _(cli, dx, ux)_
- **Order flag incompatibility guards first** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Run flag incompatibility checks before specific value validations to ensure users receive clear errors about conflicting options rather than misleading downstream constraints. _(cli, ux)_
- **Restrict subagent tasks to mechanical implementation** - Restrict subagent tasks to mechanical implementation and testing while keeping architectural decisions and MCP tool calls in the main controller. Subagents lack the session history required for high-level design and are typically restricted from accessing external tools and network resources. _(subagents, architecture, mcp)_
- **Structural patterns like spawn($CMD, [$$$ARGS]) often only** - Structural patterns like `spawn($CMD, [$$$ARGS])` often only match explicit array literals. To capture variable-based arguments, developers must use specific capture variables or combinators that account for references rather than just literal structures. _(ast-grep, linting, patterns)_
- **Normalize findings by stripping transient metadata** - \*\*Scope:\*\* packages/core/\*\*/\*.ts, !\*\*/\*.test.\* To enable stable clustering across PRs, signatures must strip transient metadata like file paths, line numbers, code fences, and URLs from finding bodies to ensure identity is based on core content. _(data-processing, clustering)_
- **Labeling a prompt as "Regex Rule Extraction" biases models** - Labeling a prompt as "Regex Rule Extraction" biases models toward text-based patterns even when structural engines like AST or ast-grep are more appropriate. Using neutral terminology like "Rule Extraction" ensures the model evaluates all supported engines and selects the narrowest technical representation. _(llm, prompts, refactoring)_
- **Core library modules should accept optional warning** - Core library modules should accept optional warning callbacks rather than requiring them as positional arguments. This prevents forcing specific logging contracts on consumers and maintains a flexible API surface for varied environments. _(api-design, core-library, dx)_
- **When a CLI component uses special display modes (like** - When a CLI component uses special display modes (like a rotating quote spinner), ensure that the non-TTY fallback behavior matches the TTY behavior for common methods like `update()`. If a mode should suppress external updates in a terminal, it must also suppress them in CI/logs to maintain a consistent output stream. _(cli, ui, nodejs)_
- **When structured output flags are active, redirect all** - When structured output flags are active, redirect all human-readable logs to `stderr` to prevent corruption of the `stdout` stream intended for machine parsing. _(cli, ux)_
- **Wrap developer-facing metadata or "source of truth"** - Wrap developer-facing metadata or "source of truth" instructions in HTML comments (`<!-- -->`) to keep them out of the rendered end-user view. This allows contributors to see maintenance context in the source file without cluttering the final documentation output. _(documentation, markdown, ux)_
- **Validate DSL patterns with authoritative parsers** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Heuristic brace-counting fails to catch patterns that are balanced but semantically invalid as root nodes, such as floating member calls or bare catch clauses. Invoking the actual parser at compile time prevents runtime crashes in the linting engine. _(ast-grep, validation, dx)_
- **Extracting structural patterns from raw Markdown often** - Extracting structural patterns from raw Markdown often captures false positives from examples or documentation inside triple-backtick blocks. Stripping fenced code blocks before analysis ensures that only active content is processed by the extraction logic. _(markdown, regex, parsing)_
- **Naive substring matching like includes('dir/') can trigger** - Naive substring matching like includes('dir/') can trigger false positives on similarly named path segments; use regex boundaries or path normalization to ensure logic only applies to intended directories. _(filesystem, regex, path)_
- **Documentation must reflect the actual execution sequence** - Documentation must reflect the actual execution sequence in hook templates, such as running manifest verification before linting. Misrepresenting this order creates a false mental model of the stateless, deterministic enforcement flow. _(git, documentation, architecture)_
- **Isolate rule execution in batches** - \*\*Scope:\*\* packages/core/src/ast-grep-query.ts Wrap individual rule execution in try/catch blocks during batch processing to prevent a single malformed rule or NAPI throw from crashing the entire file scan. _(architecture, error-handling)_
- **Always use fully qualified identifiers for caching** - \*\*Pattern:\*\* \b(cacheKey|telemetryId|modelId)\s\*[:=]\s\*['"][^'"\s:]+['"]
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx, !\*\*/\*.test.ts, !\*\*/\*.test.js
  \*\*Severity:\*\* error

Always use fully qualified identifiers for caching. _(architecture, curated)_

- **Ensure per-item resilience in batch processing** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts, !\*\*/\*.test.\* Implement per-item catch-and-continue logic when batch processing external data (like PR lists) to ensure that transient API or parsing errors in a single item do not abort the entire command. _(cli, error-handling, api)_
- **Manually prune retired submodule artifacts** - Git does not automatically prune submodule directories or internal metadata after removal, so manual deletion is required to fully clean local clones. _(git, dx)_
- **Files containing active rule patterns often trigger those** - Files containing active rule patterns often trigger those same rules during a scan. Compiled rule assets must be excluded from validation to prevent "self-violations" where the detection logic flags its own source code. _(linting, ast-grep, recursion)_
- **Handle single-line inputs in regex terminators** - \*\*Scope:\*\* packages/mcp/src/tools/\*\*/\*.ts, !\*\*/\*.test.\* Regex patterns ending in \n+ will fail on single-line inputs lacking a trailing newline; use (?:\s\*\n+|\s\*$) to correctly match both line-endings and end-of-string. _(regex, parsing)_
- **Eliminate silent degradation in failure modes** - \*\*Scope:\*\* .claude/skills/preflight/SKILL.md Forcing a failure modes table during design prevents 'silent degradation' by requiring any path that masks errors or drifts from state to be justified. _(reliability, architecture)_
- **Moving the validation of complex external tool patterns** - Moving the validation of complex external tool patterns from runtime to compile-time prevents downstream tool crashes and provides immediate feedback to developers. _(dx, validation, ast-grep)_
- **In core packages, a small, tested custom implementation** - \*\*Pattern:\*\* \b(import|require).+['"]micromatch['"]
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/core/\*\*/\*
  \*\*Severity:\*\* warning

In core packages, a small, tested custom implementation. _(style, curated)_

- **Update manifests after artifact modification** - \*\*Scope:\*\* packages/cli/src/commands/shield.ts Any process that modifies a tracked build artifact, such as capturing new observation rules, must trigger an in-place manifest rehash to prevent integrity check failures in CI. _(build-system, ci, integrity)_
- **Validate JSON at system boundaries** - \*\*Scope:\*\* packages/core/src/retired-lessons.ts Avoid using type assertions when reading JSON from disk; perform element-level validation instead. This prevents downstream crashes if the ledger file is corrupted or manually edited by a user. _(typescript, security, io)_
- **Performing multiple string replacements in a loop** - Performing multiple string replacements in a loop is inefficient due to repeated string allocations and traversals. Utilizing a single regular expression combined with a replacement map improves performance and maintainability when sanitizing large sets of terms. _(performance, typescript, strings)_
- **Augment heuristics with authoritative parser checks** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Heuristics for AST structures often miss semantic errors like invalid roots; invoking the actual tool parser against empty source provides a cheap, authoritative validation layer. _(ast-grep, validation, dx)_
- **Every architectural lesson should include actionable "Fix"** - Every architectural lesson should include actionable "Fix" guidance to complete the self-correction loop for AI agents. This allows the agent to move from violation detection to resolution in one cycle without needing to guess the correct pattern. _(ai-agents, linting, knowledge-management)_
- **Functions designed to always throw an exception** - Functions designed to always throw an exception should return the `never` type to inform TypeScript's control flow analysis. This eliminates the need for redundant return statements or unreachable code annotations in calling catch blocks. _(typescript, architecture)_
- **Using domain-specific error subclasses instead of raw Error** - Using domain-specific error subclasses instead of raw Error throws allows CLI handlers to provide actionable recovery hints while suppressing noisy stack traces for known failure modes. This pattern improves user experience by focusing on the solution rather than the system internals during standard execution. _(architecture, errors, cli)_
- **Distinguish dropped selectors from skipped rules** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts In ESLint adapters, individual unsupported selectors within a rule should be silently dropped while the rule remains active for other selectors. The 'skipped' status should only be applied if the entire rule is non-functional to ensure accurate coverage reporting. _(architecture, eslint)_
- **Hooks designed to block agent actions, such as shield gates** - \*\*Pattern:\*\* \b(exec|spawn|execFile)\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/hooks/\*\*/\*.ts, \*\*/shield/\*\*/\*.ts, \*\*/gates/\*\*/\*.ts, \*\*/git/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Hooks designed to block agent actions, such as shield gates. _(architecture, curated)_

- **Custom database errors should include specific** - Custom database errors should include specific machine-readable codes like `DATABASE\_MISMATCH` alongside human-readable messages. This enables programmatic recovery, allowing the CLI or UI to suggest specific corrective actions like a forced re-index. _(error-handling, dx, database)_
- **Keep CHANGELOGs as historical records** - Do not retroactively edit CHANGELOG files to match current logic; they must remain an immutable record of what was shipped at a specific point in time. _(documentation, process)_
- **Escape back-references in template substitution** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Dynamic strings containing symbols like $& or $1 trigger special behavior in String.prototype.replace; use a replacer function to avoid accidental expansion. _(javascript, security, templating)_
- **Isolate static templates for prompt caching** - \*\*Scope:\*\* packages/core/src/compile-lesson.ts Static instructions must be byte-stable to trigger provider-native caching; dynamic content like telemetry IDs must remain in the user prompt to avoid constant cache invalidation. _(llm, performance)_
- **Hook stderr diagnostics use script-identifier prefix, not** - \*\*Applies-to:\*\* infrastructure \*\*Hook stderr diagnostics use script-identifier prefix, not `[Totem Error]`.\*\* Session-start hooks (`.claude/hooks/\*.js`, `.gemini/hooks/\*.js`) and hook helpers (`packages/cli/src/hooks/auto-context.ts`) follow a two-tier convention for stderr output: degradation/diagnostic `process.stderr.write` calls use `[<hook-name>]` (e.g., `[auto-context]`, `[session-context]`) as the prefix; only explicitly-constructed thrown `Error` objects carry the `[Totem Error]` prefix per styleguide §3. The script-identifier pattern is canonical at `packages/cli/src/hooks/auto-context.ts:149, :160, :175, :189` — production-grade hook helper code that has been live since the auto-context feature shipped. \*\*Do not suggest swapping `[<hook-name>]` to `[Totem Error]` on raw stderr writes\*\*; §3's guidance governs thrown errors, not degradation diagnostics. \*\*Throwing in session-start hook catch blocks defeats the design intent.\*\* Session-start hooks terminate with an outer `process.exit(0)` catch by design — they MUST NOT crash session boot. Inner catch blocks that `process.stderr.write` and continue allow partial context to be built when one read path fails (e.g., proposals fails but vector-context still runs). Suggesting `throw new Error(...)` in inner catches short-circuits subsequent context-building and reduces signal to the user. §9 line 112's "Defense-in-depth guards… use `log.warn()` + counter increments, NOT `throw`. The design intent is resilient continuation, not fail-fast" governs the same principle for raw `process.stderr.write` even though the medium differs from `log.warn()`. Both styleguide §6 carve-out and this lesson exist to prevent re-litigation in future review cycles. \*\*Reproduction:\*\* `mmnto-ai/totem#1823` R1 (GCA, 2026-05-05) — flagged 3 stderr.write call sites in `.claude/hooks/session-context.js` for both prefix-swap and throw-instead-of-write. Empirical decline grounding: `auto-context.ts:149` precedent + the file's own `process.exit(0)` outer catch + §9 line 112 (resilient continuation). Substrate-update path closed via `.gemini/styleguide.md` §6 entry. \*\*Source:\*\* mcp (added at 2026-05-05T04:01:49.847Z) _(review-guidance, hooks, stderr, error-handling, graceful-degradation, adr-090)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 1 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/src/commands/init-templates.ts. reasonCode: stage4-out-of-scope-match.)_
- **Avoid manual prefixes in TotemError messages** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* The TotemError constructor automatically prepends the '[Totem Error]' tag, so adding it manually in the message argument results in redundant double-prefixing. _(error-handling, logging)_ _(archived: Over-broad pattern: astGrepPattern `new TotemError($MSG, $$$REST)` matches every TotemError construction, not just manual-prefix inclusions. 34 legitimate call sites in production code would fire on every lint run. The lesson intent is to ban `new TotemError("[Totem Error] ...")` but the compile worker could not express the literal-prefix constraint as an ast-grep pattern. Archived via #1553 postmerge cycle; candidate for ADR-091 Stage 4 Verify-Against-Codebase auto-archive once implemented.)_
- **Suppress turbo warnings for data-only packs** - \*\*Scope:\*\* packages/pack-agent-security/turbo.json Override turbo.json build outputs to an empty array for data-only packages to prevent build system warnings regarding missing outputs. _(turbo, monorepo, dx)_
- **When reading cache or config files, specifically check** - When reading cache or config files, specifically check for the `ENOENT` error code to handle missing files silently. Swallowing all errors hides critical issues like file permission problems or JSON corruption that should be surfaced to the user. _(nodejs, fs, error-handling)_
- **Warn on large diffs before LLM** - \*\*Scope:\*\* packages/cli/src/index.ts Surface diff truncation warnings at the resolution layer before LLM invocation to prevent degraded reviews and avoid unnecessary token costs. _(llm, dx, performance)_
- **Constructing shell commands with string interpolation** - Constructing shell commands with string interpolation is vulnerable to paths containing spaces or metacharacters; use argument arrays with spawnSync for robustness. _(cli, node, security)_
- **Avoid unnecessary writes during no-op runs** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Only rewrite files during no-op runs if a transformation actually modified the data to prevent unnecessary disk I/O and git noise. _(performance, fs)_
- **Review metadata from third-party integrations** - Review metadata from third-party integrations can occasionally contain null or unexpected author fields. Failing to check for author existence before string manipulation (like `.includes()`) leads to runtime crashes during PR analysis. _(safety, typescript, github-api)_
- **Using child.kill() on Windows when shell: true is enabled** - \*\*Pattern:\*\* \.kill\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* warning

Using child.kill() on Windows when shell: true is enabled. _(style, curated)_

- **Enriching SARIF outputs with explicit tool names and rule** - Enriching SARIF outputs with explicit tool names and rule help links ensures that CI/CD security findings are immediately actionable and traceable. _(sarif, ci-cd, security)_
- **Execute rule engine for accurate predictions** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Run the actual rule engine instead of simple glob matching when predicting findings. Users require anchored citations (file:line) and severity levels which static scope matching cannot provide. _(cli, architecture)_
- **Always use the !\*\*/\*.ext pattern for recursive exclusions** - Always use the !\*\*/\*.ext pattern for recursive exclusions to ensure consistency and prevent shallow matching that misses nested test files. _(glob, testing)_
- **Use typed reason codes for LLM signals** - \*\*Scope:\*\* packages/core/src/compiler-schema.ts Use a typed `reasonCode` field in LLM schemas instead of parsing prose sentinels to ensure type-safe and test-deterministic routing of non-compilable items. _(llm, architecture, zod)_
- **Technical documentation must avoid marketing-centric terms** - Technical documentation must avoid marketing-centric terms like "guarantees" or "comprehensive" to maintain credibility and clarity. Absolute claims should be replaced with specific descriptions of tested environments and observed results to satisfy compliance requirements. _(documentation, technical-writing)_
- **Avoid metaphorical terms in documentation** - \*\*Scope:\*\* docs/\*\*/\*.md Project voice rules prohibit metaphorical terms like 'anchor' in favor of direct technical descriptions such as 'directory-rooted'. _(documentation, styleguide)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 47 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: .gemini/styleguide.md, .github/copilot-instructions.md, .junie/skills/totem-rules/rules.md, .totem/lessons.md, .totem/lessons/lesson-0757a839.md (+ 42 more). reasonCode: stage4-out-of-scope-match.)_
- **Prefer Explicit Metadata Tokens from LLMs Over Heuristics** - \*\*Pattern:\*\* \.split\(['"/](?:\n|\r\n)['"/]\)\s\*\[\s\*0\s\*\]
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Prefer Explicit Metadata Tokens from LLMs Over Heuristics. _(security, curated)_ _(archived: Over-broad: fires on any .split('\n')[0] regardless of context. The lesson is about LLM metadata parsing, not general string splitting. Blocks legitimate error-message first-line extraction. See #1352.)_

- **When timing out a child process, do not reject the promise** - \*\*Pattern:\*\* \bsetTimeout\s\*\(.\*?\breject\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* error

When timing out a child process, do not reject the promise. _(architecture, curated)_

- **Constructing a single regular expression with alternation** - Constructing a single regular expression with alternation is more efficient than iterating over an array to perform multiple string replacements. This approach scales better and improves maintainability as the list of patterns to remove grows. _(typescript, performance, regex)_
- **2026-03-06T06:25:26.036Z** - \*\*Pattern:\*\* \$\{\s\*err\s\*\}
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

Avoid interpolating raw err objects in template literals; use err.message or err.stack. _(architecture, curated)_

- **Use the --recurse-submodules flag with git ls-files** - \*\*Pattern:\*\* \bgit\s+ls-files\b(?!.\*\b--recurse-submodules\b)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.sh, \*\*/\*.bash, \*\*/\*.js, \*\*/\*.ts, \*\*/\*.yml, \*\*/\*.yaml
  \*\*Severity:\*\* error

Use the --recurse-submodules flag with git ls-files. _(architecture, curated)_

- **Resolve git root via rev-parse for monorepo compatibility** - \*\*Pattern:\*\* (-d\s+['"]?\.git['"]?|existsSync\([^)]\*['"]\.git['"]\))
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.sh, \*\*/\*.bash, \*\*/\*.js, \*\*/\*.ts, \*\*/\*.yml, \*\*/\*.yaml
  \*\*Severity:\*\* warning

Resolve git root via rev-parse for monorepo compatibility. _(style, curated)_

- **Emojis are excluded from all documentation files to adhere** - Emojis are excluded from all documentation files to adhere to the project's professional formatting standards defined in CLAUDE.md. This rule ensures consistency and a professional tone between manually written content and tool-generated markdown. _(documentation, styleguide, standards)_
- **When intercepting agent tool inputs via hooks, use specific** - \*\*Pattern:\*\* (\.(match|test|includes)\s\*\(|pattern:\s\*)[/"']\^?\b(git|npm|docker|aws|kubectl|gh|sh|bash)\b\$?[/"']
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

When intercepting agent tool inputs via hooks, use specific. _(architecture, curated)_

- **Use bracket notation for reserved keys** - \*\*Scope:\*\* packages/cli/src/index-lite.ts Assigning values to reserved keys via bracket notation (e.g., payload['error']) avoids triggering specific lint rules like id-match, removing the need for inline suppressions. _(typescript, linting, dx)_
- **Fix generated documentation at the source** - Do not hand-edit auto-generated files; instead, update the source lesson or generator logic to ensure fixes persist through future builds. _(workflow, automation, documentation)_
- **2026-03-06T05:41:19.122Z** - \*\*Pattern:\*\* (import\s+.\*from\s+['"]inquirer['"]|require\(['"]inquirer['"]\)|\"inquirer\"\s\*:)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/\*\*/\*.ts
  \*\*Severity:\*\* warning

Do not use inquirer for prompts; use the built-in readline interface instead. _(style, curated)_

- **Use absolute paths for federated results** - \*\*Scope:\*\* packages/cli/src/commands/search.ts Display absolute file paths for search results in federated environments to prevent path collisions and ambiguity across different repositories. _(cli, search, federation)_
- **2026-03-07T06:05:56.069Z** - \*\*Pattern:\*\* typeof\s+[^\s!&|=]+\s\*===\s\*['"]object['"](?!\s*&&)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Always combine typeof val === "object" with a truthiness check because typeof null is "object". _(security, curated)_

- **Order strategy root resolution precedence** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts A four-layer precedence system (Env > Config > Sibling > Submodule) allows flexible strategy root resolution across local development, CI, and legacy environments. _(architecture, configuration)_
- **Validate rules before manifest refresh** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts Preload and validate the integrity of the target rules file before updating its manifest hash to prevent a manifest refresh from masking existing file corruption. _(integrity, manifest)_
- **Avoid over-broad heading length constraints** - \*\*Scope:\*\* docs/\*\*/\*.md Heading length limits intended for stable identifiers can trigger false positives on descriptive headers in general documentation if the lint rule is not strictly scoped to lesson files. _(linting, markdown)_
- **Avoid including empty strings in branch whitelists or using** - Avoid including empty strings in branch whitelists or using truthy fallbacks in branch detection logic. These patterns can silently exempt security gates if branch resolution fails, effectively bypassing intended blocks. _(git, shell, security)_
- **Secondary outputs like JSON checkpoints should be wrapped** - Secondary outputs like JSON checkpoints should be wrapped in try/catch blocks. This ensures that a failure in a non-critical side effect does not crash the primary command or block the user's main workflow. _(error-handling, resilience)_
- **Handle detached HEAD states in tests** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.test.ts Test fixtures for Git state must allow `currentBranch` to be null to account for detached HEAD states in CI environments. Hardcoding non-null branch strings can cause failures in automated pipelines. _(git, testing, ci)_ _(archived: fileGlobs are scoped to packages/mcp/src/\*\*/\*.test.ts, but the pattern fires on every test that mocks git state with a string-literal currentBranch — which is how nearly every git-mocking test sets up its fixture. The source lesson is authorial guidance about updating test fixtures to support detached-HEAD (currentBranch: null) cases, not a defect signal on existing test-fixture construction.)_
- **Use maxRetries and retryDelay in fs.rmSync calls** - Use `maxRetries` and `retryDelay` in `fs.rmSync` calls during test teardown to prevent `ENOTEMPTY` errors on Windows caused by filesystem lag or locks. _(node.js, windows, testing)_
- **Read-path schema changes break write-path invariants** - When modifying parsing logic that produces a data structure (lesson hash, AST node, config schema, parsed entity, etc.), audit ALL downstream consumers that read from the data structure BEFORE shipping the change. Read-path schema changes recurringly break write-path invariants in three predictable ways: 1. \*\*Hardcoded heuristics that depended on the old shape.\*\* Pre-change, downstream code may be using a structural coincidence (e.g., `field\_a === field\_b` because the writer always set them to the same value) as a heuristic for "rule type X". After your change adds a real distinction between field*a and field_b, the heuristic silently misfires and the downstream behavior degrades. Fix: introduce an explicit flag the downstream consumer can check, then update both the producer and the consumer in the same PR. 2. \*\*Format-extension cascades that need cross-helper consistency.\*\* If you extend a format helper to support a new variant (e.g., a new field marker, separator, or syntax), audit every other helper that parses the same format. Inconsistent helpers create silent failure modes where one helper accepts the new variant and a sibling helper rejects it, causing the parsed entity to be partially populated and silently dropped downstream. 3. \*\*Edge cases at the boundaries.\*\* Empty values, line-ending variants (CRLF vs LF), trailing whitespace, and Unicode normalization all need explicit handling at parser boundaries. Returning empty string instead of undefined breaks `?? fallback` chains. Splitting on `\n` instead of `/\r?\n/` silently drops Windows-authored content. These look minor but are the same class of silent-skip bug as the em-dash silent skip resolved by mmnto-ai/totem#1278. \*\*The Shield AI loop catches some but not all of these.\*\* It catches edge cases at file boundaries (empty values, CRLF) reliably. It catches cross-helper inconsistencies usually but only after a partial fix lands. It does NOT reliably catch heuristic invariants in distant files (e.g., a string-comparison heuristic in a sibling command package). For those, you need explicit code reading: when modifying parsing logic, grep for downstream consumers that read the same field combinations and inspect them for shape assumptions. \*\*Pattern recurrence\*\*: This pattern has surfaced four times in two consecutive PRs (#1278 enforceHeadingLimit; #1282 doctor.ts manual-rule heuristic, empty-Message edge case, CRLF line endings, alt-form `\*\*Field\*\*:` across helpers). Treat it as a class, not a series of one-offs. Add this lesson as a search-time prompt for any future work that touches lesson-pattern.ts, drift-detector.ts, compile-lesson.ts, or compiler-schema.ts. \*\*Action checklist when modifying parsing logic:\*\* - grep for all callers of the function/helper being changed - grep for all references to the field/property being added or modified - check downstream code for shape-based heuristics (e.g., `field\_a === field\_b`, `length === 1`, `typeof x === 'string'`) - if a new explicit signal replaces an old structural one, add a fallback for backward-compat with old data - add an edge-case test for: empty value, CRLF input, mixed-form input, partial-population input - run `totem review` AND read the cascade findings carefully — Shield will catch some but not all of these *(architecture, parsing, compiler, schema-evolution, shield)\_
- **Calculating indices based on the assumed order of merged** - Calculating indices based on the assumed order of merged data sources is fragile; explicitly counting entries by source ensures robust item removal. _(cli, logic)_
- **Eagerly importing heavy modules at the top level of CLI** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Eagerly importing heavy modules at the top level of CLI command files increases startup latency; use dynamic import() within handlers to keep help checks fast. _(cli, performance)_ _(archived: Over-broad: astGrepPattern `import $NAME from '$MODULE'` matches every top-level default import in packages/cli/src/commands/\*\*. Contributes to the PR #1516 warning storm. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Explicitly handling empty strings or negated patterns like !** - Explicitly handling empty strings or negated patterns like `!` during glob normalization prevents runtime crashes and ensures the compiler pipeline handles malformed input gracefully. _(globs, validation, robustness)_
- **Using .find() inside a loop to match commands to groups** - Using .find() inside a loop to match commands to groups results in O(n^2) complexity during help generation. Pre-indexing visible commands into a Map allows for constant-time lookups as the number of CLI commands grows. _(performance, cli)_
- **Avoid structural collisions in catch patterns** - \*\*Scope:\*\* .totem/compiled-rules.json Patterns intended to detect missing error context in re-throws can collide with empty-catch rules if they are not sufficiently specific about the catch block's contents. _(ast-grep, error-handling)_
- **Avoid aborting entire parallel LLM batches on single** - Avoid aborting entire parallel LLM batches on single network failures by catching errors at the individual task level. Logging a warning and continuing is preferred for LLM-bound tasks where intermittent failures are common. _(async, llm, error-handling)_
- **Implement a 'Staleness Protocol' where the active work** - Implement a 'Staleness Protocol' where the active work context is the absolute authority for roadmaps; items not present in the context should be aggressively removed or marked completed to prevent documentation rot. _(prompt-engineering, documentation)_
- **Duplicating complex mock generators (like ledger events** - Duplicating complex mock generators (like ledger events or rule objects) across test files increases maintenance debt. Extracting these to a shared module improves DX and ensures consistent data shapes across the test suite. _(testing, dx)_
- **Implementing per-query error handling in batch AST matching** - Implementing per-query error handling in batch AST matching prevents language-specific node name errors from crashing the entire linting process. This allows the engine to gracefully degrade and continue processing other queries even if one query is incompatible with the current file type. _(ast, error-handling, typescript)_
- **Removing stdio from execution options and hardcoding pipe** - Removing stdio from execution options and hardcoding pipe mode ensures that return values consistently match string-based type contracts and normalization logic. _(node.js, exec, typescript)_
- **Avoid relying on the test runner's environment to determine** - Avoid relying on the test runner's environment to determine interactive mode, as this causes flakiness between CI and local terminals. Use an injectable option to override TTY detection so that non-interactive error paths can be tested deterministically. _(testing, cli, tty)_
- **Shipping a tool with pre-compiled default rules prevents** - Shipping a tool with pre-compiled default rules prevents "no configuration found" errors during the initial user experience. This ensures that users see immediate value without needing to configure API keys or custom rules on their first run. _(onboarding, dx, configuration)_
- **Escape Windows paths in generated configs** - \*\*Scope:\*\* packages/cli/src/commands/init.ts When programmatically generating configuration files containing absolute paths, ensure backslashes are properly escaped for Windows compatibility. Unescaped backslashes in `.ts` or `.json` files are interpreted as escape sequences, resulting in corrupted paths at runtime. _(cli, windows, node)_
- **YAML frontmatter should take precedence over inline tags** - YAML frontmatter should take precedence over inline tags to ensure a single source of truth and maintain consistency across different parsing strategies. _(architecture, metadata, yaml)_
- **Explicitly guard and warn when specific engines, such** - Explicitly guard and warn when specific engines, such as ast-grep, do not support features like inline example testing. This prevents user confusion when features appear to fail silently. _(cli, testing, ux)_
- **Incremental validation is only reliable if the current head** - Incremental validation is only reliable if the current head is a direct descendant of a previously verified commit. This prevents logic gaps and security bypasses when switching between unrelated branches or working with non-linear history. _(git, security, architecture)_
- **When generating ast-grep patterns programmatically,** - When generating ast-grep patterns programmatically, the pattern must be emitted as a raw code string rather than wrapped in backticks or quotes. ast-grep parses patterns into AST nodes; wrapping a pattern in backticks (e.g., ` `JSON.parse($A)` `) causes the engine to match a template literal string node instead of the intended call expression, breaking structural matching. _(ast-grep, architecture, tooling)_
- **Use simplified code patterns in documentation examples even** - Use simplified code patterns in documentation examples even if the project requires more verbose typed structures internally. Prioritizing snippet readability over strict architectural adherence helps users grasp configuration concepts faster without being distracted by boilerplate. _(documentation, developer-experience, typescript)_
- **Verify redirect targets** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Check for target file existence before applying size-based short-circuits to ensure that any file matching a redirect pattern is valid, even if it is small. _(logic, validation)_
- **Surface local fallbacks during initialization** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Proactively log the status of local model providers during setup to prevent cloud-key auto-detection from obscuring no-quota local alternatives. This maintains model-stack agnosticism by making the 'floor' visible to users before they configure cloud providers. _(ux, cli, ollama)_
- **When implementing data loss prevention, ensure the system** - When implementing data loss prevention, ensure the system throws an exception if the scanner fails rather than proceeding with the original text. This prevents unmasked sensitive data from leaking to external providers in the event of an internal processing failure. _(security, middleware, error-handling)_
- **When generating headings from markdown content, use** - When generating headings from markdown content, use a cleaning utility to strip formatting like backticks or bolding. This prevents visual noise in CLI menus and ensures consistent formatting in generated lesson files. _(cli, markdown, ux)_
- **Limit doc headings to 60 characters** - \*\*Scope:\*\* docs/\*\*/\*.md Heading lengths must be restricted to 60 characters to satisfy SARIF identifier constraints and retrieval system requirements. _(documentation, sarif, linting)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 643 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: .claude/hooks/content-hash.sh, .claude/hooks/post-compact.sh, .claude/hooks/pre-compact.sh, .claude/hooks/review-gate.sh, .claude/skills/preflight/SKILL.md (+ 638 more). reasonCode: stage4-out-of-scope-match.)_
- **Using a unified 'Totem Error' tag across all CLI commands** - Using a unified 'Totem Error' tag across all CLI commands ensures consistent log filtering and a predictable experience for users and downstream tools. _(cli, logging, observability)_
- **Wrap partial AST nodes in valid parents** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* ast-grep rejects standalone nodes like catch clauses or receiver-less member calls; patterns must include necessary parent context (e.g., try blocks) to be valid. _(ast-grep, testing)_
- **Broad globs in secret-detection rules can flag intentional** - Broad globs in secret-detection rules can flag intentional test strings; narrow the scope or add explicit exclusions for files that exercise the scanner's detection logic. _(security, testing, glob)_
- **When testing automated shell script modifications, assert** - When testing automated shell script modifications, assert the full block content and verify balanced `if/fi` pairs. This prevents partial or broken script upgrades that could lead to silent failures in environments like Git hooks. _(testing, shell, git-hooks)_
- **Pin Bun versions in CI** - \*\*Scope:\*\* .github/workflows/release-binary.yml Using 'latest' for Bun in CI workflows can lead to non-reproducible builds and unexpected breakages when the runtime releases breaking changes. _(ci, bun, reproducibility)_
- **Treat duplicate hashes as data corruption** - \*\*Scope:\*\* packages/cli/src/commands/lesson.ts Treat duplicate full hashes as data corruption rather than ambiguous prefixes during lookup to ensure the system fails fast before processing inconsistent state. _(integrity, cli)_
- **Guard string operations on untrusted JSON** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Always validate that JSON fields are strings before calling methods like `.includes()` to prevent runtime crashes when encountering unexpected data types in user configuration. _(typescript, validation, json)_
- **Dynamic imports can bypass constructor fallbacks** - \*\*Scope:\*\* packages/core/src/embedders/\*\*/\*.ts, !\*\*/\*.test.\* Loading SDKs dynamically inside methods prevents fallback logic that triggers on construction failure. Ensure critical dependency checks occur during instantiation if they influence provider selection. _(architecture, error-handling)_
- **Always release a filesystem lock before spawning** - Always release a filesystem lock before spawning a subprocess that intends to acquire the same lock to avoid deadlocks. This is critical when a parent process performs a write and then triggers a secondary sync or background task that shares the same locking mechanism. _(concurrency, patterns, architecture)_
- **Orchestrators must dynamically adjust max_tokens based** - Orchestrators must dynamically adjust `max\_tokens` based on the specific model used, as limits vary significantly within a single provider family (e.g., 4K for Haiku vs 16K for Opus). Hardcoding a single value causes API failures on smaller models or unnecessary truncation on larger ones. _(anthropic, llm, orchestrator)_
- **When implementing custom environment variable loaders,** - When implementing custom environment variable loaders, explicitly strip surrounding quotes from values to prevent configuration errors. Standard parsers often handle this, but custom implementations (like MCP loaders) must manually ensure values are clean for runtime use. _(configuration, env, nodejs)_
- **Distinguish empty from skipped-only states** - \*\*Scope:\*\* packages/cli/src/commands/test-rules.ts Check both total and skipped counts before triggering 'no data' guidance or early returns. This ensures that directories containing only TODO placeholders still emit warnings to the developer instead of being incorrectly reported as empty. _(dx, logic, cli)_
- **Bypass id-match lint via bracket notation** - \*\*Scope:\*\* packages/cli/src/index-lite.ts Using bracket notation for object keys can satisfy id-match lint rules for specific field names without requiring explicit eslint-disable comments. _(linting, typescript, dx)_
- **Use generic references in documentation** - \*\*Scope:\*\* docs/\*\*/\*.md Reference requirement IDs rather than hard-coded threshold values in documentation to ensure content remains accurate when specific metrics change. _(documentation, maintenance)_
- **Enforce pack compatibility via engines contract** - \*\*Scope:\*\* docs/wiki/pack-ecosystem.md Using the `engines` field in `package.json` allows rule packs to define strict version requirements for the host CLI. This ensures the ecosystem can validate compatibility before loading third-party packs, preventing runtime failures. _(npm, versioning, governance)_
- **Prefer exit codes over re-throwing CLI errors** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use `log.error` and `process.exitCode` in CLI command handlers instead of re-throwing exceptions. This aligns with project patterns for clean output and proper exit status management. _(cli, error-handling)_ _(archived: Over-broad: throw $ERR matches every throw statement. The intent is to flag re-throws in CLI handlers, but the pattern cannot distinguish re-throws from intentional error construction. upgradeTarget: compound (needs inside: catch constraint per Proposal 226). See #1218.)_
- **Using callback-based logging for core functions allows** - Using callback-based logging for core functions allows business logic to remain pure and I/O-independent while still providing real-time feedback to the user interface. _(architecture, testing)_
- **Manual lessons must use the '## Lesson <separator> <Heading>' structure** - Manual lessons must use a `## Lesson <separator> <Heading>` structure (where `<separator>` is an em-dash, en-dash, or hyphen) and include a `Tags` field to ensure compatibility with automated parsing and discovery tools. The parser accepts all three separator forms equivalently. _(documentation, tooling)_
- **Avoid labeling a tool suite as "deterministic" or "fast"** - Avoid labeling a tool suite as "deterministic" or "fast" if it contains AI-powered components. Property descriptions should be attributed to specific commands (e.g., `totem lint`) to ensure users understand which parts of the system provide hard guarantees versus AI reasoning. _(documentation, terminology, architecture)_
- **Verify CLI availability in shared git hooks before execution** - \*\*Pattern:\*\* ^[ \t]\*(?!(?:if|command|type|hash|\[|&&|\|\|)\b)\s\*(npx|pnpm|npm|yarn|eslint|prettier|lint-staged|tsc|vitest|jest|oxlint|biome|stylelint)\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* .husky/\*\*/\*, .githooks/\*\*/\*, scripts/hooks/\*\*/\*, \*\*/\*.sh, \*\*/\*.bash
  \*\*Severity:\*\* error

Verify CLI availability in shared git hooks before execution. _(architecture, curated)_

- **CLI command modules should use dynamic imports for core** - CLI command modules should use dynamic imports for core library values to prevent unnecessary overhead at startup. This ensures heavy packages are only loaded when a specific command handler is actually executed. _(architecture, cli, performance)_ _(archived: Hallucinated scope: pattern references '@core/' npm scope, which does not exist in this repository. No package.json declares it; no source file imports from it. Same failure mode as already-archived 0d0bbae4392c0255 ('@mcp-b/core'). Rule will never fire on real code. Archived via #1517.)_
- **When delegating complex logic to new helper modules,** - When delegating complex logic to new helper modules, specific tests must assert that parameters are forwarded correctly to the new implementation. This prevents behavioral drift and ensures that filters or boundaries are not lost during the delegation jump. _(testing, refactoring, maintenance)_
- **Detect incomplete bootstrap during init** - \*\*Scope:\*\* packages/cli/src/commands/init.ts The `init` command should verify the existence of all critical artifacts, such as compiled rules, before reporting success. Failing to detect an incomplete bootstrap leaves the user with a broken installation that lacks a clear path to repair. _(cli, ux)_
- **Using 'git merge-base --is-ancestor' allows validation** - Using 'git merge-base --is-ancestor' allows validation gates to skip re-execution if only non-target files have changed since the last successful check. _(git, dx, performance)_
- **Static analysis tools should read file content using git** - \*\*Pattern:\*\* \b(?:fs\.)?read(?:File|FileSync)\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* scripts/\*\*/\*.js, scripts/\*\*/\*.ts, tools/\*\*/\*.js, tools/\*\*/\*.ts
  \*\*Severity:\*\* warning

Static analysis tools should read file content using git. _(style, curated)_

- **Prefer replacer functions over back-references** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Using a replacer function instead of a string back-reference (like `$&`) avoids unintended interpretation of special sequences in substitution-sensitive contexts. _(regex, security, javascript)_ _(archived: Over-broad astGrepPattern `$STR.replace($PATTERN, $REPLACEMENT)` matches every two-arg `.replace()` call in `packages/core/src`, not just cases where the replacement string contains a back-reference like `$&`, `$1`, etc. The underlying lesson (from PR #1501) is accurate — prefer a replacer function when the replacement may contain special sequences — but the rule as compiled cannot encode that content-level check with a simple ast-grep pattern. Would produce many false positives on legitimate `.replace()` calls that use literal strings or already use a function replacer. Auto-compiled on the 2026-04-16 postmerge (1477/1496/1501/1503/1505/1506 cycle). Archived via the mmnto-ai/totem#1345 filter. Kept in the ledger as a compile-worker failure mode: the LLM could not distinguish the back-reference content within the replacement string and produced a generalization that covers all two-arg replace calls.)_
- **Always stage specific files instead of using 'git add -A'** - Always stage specific files instead of using 'git add -A' in automated workflows. This prevents the accidental inclusion of unrelated local changes in an agent-generated atomic commit. _(git, automation)_
- **Using a command-specific TAG constant for all log calls** - Using a command-specific TAG constant for all log calls ensures consistent output formatting and allows for easier log filtering across the CLI. _(logging, cli, dx)_
- **Global config paths must be absolute** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* The `totemDir` in a global configuration must be an absolute path to ensure rules are correctly resolved regardless of the current working directory. Relative paths in global profiles resolve relative to the project root where the command is executed, causing lookup failures. _(cli, config, node)_
- **Use TotemError for CLI validation** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts, !\*\*/\*.test.\* Use TotemError instead of TotemConfigError for CLI-layer validation to maintain proper architectural boundaries between the CLI and core packages. _(cli, architecture)_ _(archived: Pattern `new TotemConfigError($$$ARGS)` fires on every CLI-layer use, contradicting the declined GCA finding on PR mmnto-ai/totem#1629. TotemConfigError is used in 10+ CLI files (7x in compile.ts alone) for flag-conflict validation per the canonical compile.ts:486 --upgrade/upgradeBatch precedent. The source lesson reflects GCA's hallucinated-rule-citation argument; adopting it as a rule would codify the false claim as project policy. Taxonomy refinement for CLI vs core error classes is tracked in mmnto-ai/totem#1630, not via a blanket ban on TotemConfigError.)_
- **Resolve substrate files relative to configRoot** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Use the repository's configRoot instead of the current working directory (cwd) when looking up persistent substrate files to ensure consistent behavior across different execution contexts. _(cli, filesystem)_ _(archived: Pattern fires on every path.join(process.cwd(), ...) including legitimate test-source reads (lesson.test.ts, search.test.ts) and install-test tmp dirs. Lesson scope is substrate-file lookups in command code where configRoot is the right base; compiled rule lost that nuance and over-matches across the codebase.)_
- **Core libraries should avoid direct console.warn calls** - Core libraries should avoid direct console.warn calls to maintain architectural purity and follow strict style guides; use injectable handlers or status objects instead. _(architecture, logging, dx)_
- **Use explicit markers like <manual_content> to prevent** - Use explicit markers like <manual*content> to prevent automated text-processing tools from stripping intended technical terms or maintainer-authored prose. *(documentation, regex, automation)\_
- **When deduplicating multiple findings into a single row,** - When deduplicating multiple findings into a single row, the group must inherit the highest severity (error) to ensure critical issues are not masked by warnings. _(linting, logic)_
- **Avoid inlining tokens or API keys in configuration files** - Avoid inlining tokens or API keys in configuration files like `.mcp.json` or `settings.json`. Agents and MCP servers automatically inherit environment variables from the parent shell, making gitignored `.env` files the appropriate location for credentials. _(security, configuration, environment)_
- **User-supplied regex patterns in CLI tools should be** - User-supplied regex patterns in CLI tools should be validated for complexity to prevent ReDoS or execution hangs, even if the risk is primarily self-inflicted. _(security, regex)_
- **Do not automatically append trailing slashes to path** - Do not automatically append trailing slashes to path boundaries, as this prevents filtering for specific files rather than directories. Letting callers control the trailing slash enables both directory-wide and file-specific search scopes. _(api-design, filesystem, search)_
- **Engine-boot helpers must inherit structured errors** - \*\*Applies-to:\*\* boundary \*\*Tags:\*\* review-guidance, error-handling, pack-substrate, adr-097, bootstrap \*\*Scope:\*\* packages/cli/src/utils/bootstrap-engine.ts ### Context ADR-097 § 5 Q5 mandates synchronous fail-loud at engine boot. The `bootstrapEngine` CLI helper at `packages/cli/src/utils/bootstrap-engine.ts` is a thin wrapper around `loadInstalledPacks()` that fires immediately after `loadConfig()` in `lint`, `shield`, `compile`, and `test-rules`. ### The decline GCA flagged `bootstrapEngine` for not wrapping `loadInstalledPacks()` in a `try/catch` that rethrows as `new TotemError('BOOTSTRAP\_FAILED', ...)`. The styleguide §3 general guidance ("use `TotemError` for clear errors") seemed to apply on the surface. ### Why the wrap is wrong `loadInstalledPacks()` already throws structured, actionable errors at every failure path: - Malformed manifest JSON → "installed-packs manifest at `<path>` is not valid JSON. Re-run `totem sync` to regenerate." with `Error.cause` chain to the JSON parse failure - Schema validation failure → field-level diagnostic naming the offending key - Missing pack file → "Pack `<name>` is registered in installed-packs.json at `<path>` but the path does not exist. Re-install the pack or re-run `totem sync`." - Pack `require()` throw → "Pack `<name>` at `<path>` could not be loaded." with `Error.cause` - Peer-dep mismatch → structured ADR-097 § 5 Q6 error naming declared range + actual engine version - Pack `register()` callback throw → "Pack `<name>` registration callback threw. The pack at `<path>` must be fixed or removed." with `Error.cause` - Pack `register()` returning a Promise → "Pack `<name>` registration callback returned a Promise — registration must be synchronous per ADR-097 § 5 Q5." Wrapping these in a generic `TotemError('BOOTSTRAP\_FAILED', 'Failed to bootstrap engine: ' + err.message, ...)` collapses six distinct, pack-named, recovery-actionable errors into one opaque "BOOTSTRAP*FAILED" code with a flattened message string — losing the pack-name and the cause chain that makes the failure actionable. ### The architectural pattern Engine-boot helpers that \*\*delegate to a function which already produces structured errors\*\* must inherit those errors verbatim. The fail-loud-at-boundary policy is the helper letting the underlying error propagate, not catching and re-shaping it. This is distinct from §3's general guidance, which applies to CLI-layer flag-conflict validation and config-invalid surfaces (e.g., `--refresh-manifest` + `--force` conflict in `compile.ts:486` → `TotemConfigError` with explicit code). Those are surfaces where the CLI authors the error from scratch. ### Test of correctness If the helper's `try/catch` is removed, the user-facing error is \*more\* informative (pack name + path + cause chain) rather than less. That's the signal that the wrap was lossy. ### Reference - ADR-097 § 5 Q5 (synchronous fail-loud at engine boot) - `packages/core/src/pack-discovery.ts` (the structured-error author) - `.gemini/styleguide.md` § 6 entry (added during this PR's bot-review pass) - mmnto-ai/totem PR #1795 (the substrate-wiring PR where this came up) \*\*Source:\*\* mcp (added at 2026-05-02T04:19:54.446Z) *(review-guidance, error-handling, pack-substrate, adr-097, bootstrap)\_
- **Include a space or delimiter when concatenating disjoint** - \*\*Pattern:\*\* (\$\{[^}]+\}\$\{[^}]+\}|\.join\(['"]{2}\))
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* error

Include a space or delimiter when concatenating disjoint. _(architecture, curated)_

- **SHA-based flag files break on commit** - Stateful flag files tied to Git SHAs frequently invalidate during rebases or branch switches, creating significant developer friction compared to stateless checks. _(git, dx, architecture)_
- **When injecting vectordb lessons into orchestrator prompts** - \*\*Pattern:\*\* \bif\s\*\(.\*?\b(budget|limit|max|capacity|length|chars)\b.\*?\)\s\*break\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/orchestrator/\*\*/\*.ts, \*\*/totem/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

When injecting vectordb lessons into orchestrator prompts. _(style, curated)_

- **When wrapping external errors or providing fallbacks,** - \*\*Pattern:\*\* \bnew\s+(?!Totem)Error\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx
  \*\*Severity:\*\* warning

When wrapping external errors or providing fallbacks. _(architecture, curated)_

- **Swallowing errors in core modules hides silent failures,** - Swallowing errors in core modules hides silent failures, like corrupt caches, while direct console logging couples the library to a specific environment. Using optional onWarn callbacks allows core logic to report diagnostic issues without dictating how the presentation layer displays them. _(architecture, observability, error-handling)_
- **Failing to call clearTimeout after a spawned child process** - Failing to call `clearTimeout` after a spawned child process resolves or errors keeps the Node.js event loop active unnecessarily. Always clear the timer within the process 'close' and 'error' listeners to ensure the process can exit promptly and manage resources cleanly. _(nodejs, child-process, performance)_
- **Project conventions require a universal 'Totem Error' tag** - Project conventions require a universal 'Totem Error' tag for error logs and command-specific tags like 'Init' for status logs. Even when existing files use generic tags, new logs should follow the command-specific pattern to ensure logs are filterable and contextually accurate. _(logging, style-guide, dx)_
- **Layered strategy root resolution precedence** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts The strategy root resolver follows a four-layer precedence (Env > Config > Sibling > Submodule) to allow flexible local development without breaking legacy submodule support. _(architecture, configuration, filesystem)_
- **Scope task inputs to actual file reads** - \*\*Scope:\*\* turbo.json Avoid adding global configuration files to every task's inputs if they are only consumed by specific tasks (e.g., linting). This prevents unnecessary cache invalidation and redundant test execution when unrelated governance or config files change. _(turbo, performance, dx)_
- **Applying custom patterns before built-in ones prevents** - Built-in DLP patterns run before custom user-defined patterns to ensure high-confidence secrets are always caught. Custom patterns use the `[REDACTED\_CUSTOM]` tag to distinguish their redactions from built-in `[REDACTED]` tags, maintaining provenance in the output. _(dlp, architecture)_
- **Implementing staleness checks as non-blocking warnings** - Implementing staleness checks as non-blocking warnings during linting preserves the 'zero-LLM' invariant, ensuring the tool remains functional without mandatory AI calls. _(architecture, performance, linting)_
- **Normalizing shallow patterns like .ts to /.ts ensures** - Normalizing shallow patterns like `\*.ts` to `\*\*/\*.ts` ensures consistent behavior across tools like SARIF and picomatch that may not treat non-prefixed patterns as recursive. _(globs, portability)_
- **Refresh manifests on pure input drift** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Ensure manifest files are refreshed when input hashes change even if the primary output content remains identical. Failure to do so can wedge integrity checks, such as pre-push hooks, that rely on strict manifest-to-input alignment. _(architecture, integrity, cli)_
- **Use explicit monorepo test globs** - \*\*Scope:\*\* packages/pack-agent-security/compiled-rules.json Broad exclusions like `!\*\*/test/\*\*` may fail to exclude nested package test directories in a monorepo. Use explicit patterns like `packages/\*\*/test/\*\*` to ensure security rules don't inadvertently lint consumer test trees. _(glob, monorepo, security)_ _(archived: fileGlobs are scoped to packages/pack-agent-security/compiled-rules.json itself. The rule pattern matches the literal broad-exclude glob `"!\*\*/test/"`, but the file already uses the explicit `packages/\*\*/test/\*\*` form — i.e. the rule is self-referentially scoped to the artifact it lives in and will never match. Authorial guidance misclassified as an enforcement pattern.)_
- **Writing to a temporary file and then renaming it prevents** - Writing to a temporary file and then renaming it prevents partial or corrupted reads. This pattern is essential for checkpoint files that might be accessed concurrently or during a crash. _(io, resilience)_
- **Using non-unique fields like timestamps as keys** - Using non-unique fields like timestamps as keys for automated data mapping leads to cross-contamination and incorrect data associations. Automation scripts should rely on content-based hashes or UUIDs when merging or updating data across multiple files. _(automation, scripts, mapping)_
- **System calls in automation scripts often fail silently** - System calls in automation scripts often fail silently if the exit status or error property isn't explicitly checked. Always validate `spawnSync` results to prevent the process from proceeding as if a critical command like `git commit` succeeded. _(node, shell, reliability)_
- **Assert per-family coverage for compound rules** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts When testing rules with multiple sub-patterns (like obfuscation), assert that each distinct family triggers a match to prevent silent regressions in specific detection logic. _(testing, security)_
- **Reversing the search order of Git refs (e.g., remote** - Reversing the search order of Git refs (e.g., remote before local) can break existing error-handling contracts. A full audit of the error path across all re-exports is required before changing ref resolution logic to avoid stale merge-base issues. _(git, architecture)_
- **MCP tools should return plain-text for error paths** - MCP tools should return plain-text for error paths to ensure compatibility with current clients, even when success paths are XML-wrapped. This deferred standardization avoids breaking existing client parsers. _(mcp, architecture)_
- **When implementing post-processing for LLM outputs, use** - When implementing post-processing for LLM outputs, use prompt constraints as the primary filter to avoid building complex recursive parsers. A simple "safety net" sanitizer is often preferable to a robust parser if it covers all historically observed patterns while minimizing code complexity. _(llm, architecture, regex)_
- **Applying memoization to asynchronous functions prevents** - Applying memoization to asynchronous functions prevents race conditions when multiple concurrent calls are made to the same operation. This ensures that subsequent callers wait for the original promise to resolve rather than triggering redundant or conflicting updates. _(concurrency, promises, mcp)_
- **AST-based rules often use empty strings for regex patterns,** - AST-based rules often use empty strings for regex patterns, which causes `new RegExp('')` to match every line if passed to a regex engine. Always explicitly filter rules by engine type before execution to prevent these latent false-positive bugs. _(typescript, regex, architectural-patterns)_
- **CodeRabbit posts its "review complete" summary comment** - CodeRabbit posts its "review complete" summary comment before all inline findings are written. There is a 30-60 second delay while inline comments trickle in, likely due to GitHub API rate limit batching. Any automated workflow that triggers on the review summary must wait for inline comments to stabilize before scraping. \*\*Source:\*\* mcp (added at 2026-03-28T07:11:41.835Z) _(coderabbit, github-api, timing, automation)_
- **Preserve line breaks in terminal sanitizers** - \*\*Scope:\*\* packages/core/src/terminal-sanitize.ts Terminal sanitization helpers should preserve newline and tab characters because different call sites require specific multi-line formatting or flattening. _(terminal, sanitization, dx)_
- **Anchor CLI artifacts to configRoot** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Resolve internal tool directories (like .totem/) relative to the configuration file's location rather than the current working directory. This prevents path resolution failures in monorepos when commands are executed from nested subpackages where cwd differs from the project root. _(cli, monorepo, paths)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 3 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/src/commands/install.test.ts, packages/cli/src/commands/lesson.test.ts, packages/cli/src/commands/search.test.ts. reasonCode: stage4-out-of-scope-match.)_
- **When active work context is unavailable, documentation** - When active work context is unavailable, documentation tools should append staleness warnings to existing roadmap sections rather than deleting them to handle missing initialization data gracefully. _(documentation, resilience)_
- **Align probe timeouts with production budgets** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Aligning diagnostic probe timeouts with existing production values prevents internal divergence and ensures consistent behavior between troubleshooting tools and runtime logic. _(architecture, dx)_
- **Placing imports inside command function bodies prevents** - Placing imports inside command function bodies prevents the runtime from loading heavy dependencies during the initial CLI startup phase. This ensures the tool remains responsive for all commands by only loading modules relevant to the specific action being executed. _(nodejs, performance, cli)_ _(archived: Message forbids dynamic import() inside command function bodies, which is the canonical lazy-load pattern for all 25 CLI commands. Contradicts #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Extract shared logic into pure helpers** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Extracting transformation logic into pure, non-mutating helpers ensures consistency across active and no-op branches while simplifying unit testing. _(architecture, testing)_
- **Rule sets should be filtered by their specific execution** - Rule sets should be filtered by their specific execution engine before being passed to executors to prevent processing errors. This ensures that rules are only dispatched to compatible runners and optimizes the overall execution pipeline. _(architecture, performance)_
- **Distinguish failures from no-ops in diagnostics** - \*\*Scope:\*\* packages/cli/src/commands/doctor.ts Explicitly log 'failed' statuses with error details and high-visibility formatting in diagnostic tools to ensure errors are actionable rather than ignored. _(ux, logging)_
- **Major LanceDB engine upgrades (e.g., v0.19 to v2.0.0)** - Major LanceDB engine upgrades (e.g., v0.19 to v2.0.0) can introduce changes to the underlying storage format that are not caught by API-level unit tests. A full index rebuild is required post-upgrade to prevent search panics and to enable performance improvements like enhanced FTS caching. _(lancedb, indexing, migrations)_
- **Use unique temp files for atomic writes** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts Using a static '.tmp' suffix for atomic writes can cause collisions when multiple processes — or rapid same-process writes — target the same path. Use a per-write unique suffix combining at least two sources of entropy: e.g. `${process.pid}.${Date.now().toString(36)}.tmp` (PID alone can collide when one process issues rapid sequential writes within a millisecond), or a UUID. _(fs, concurrency)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 3 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/src/commands/shield.ts, packages/cli/src/commands/sync.ts, packages/cli/src/utils/pilot.ts. reasonCode: stage4-out-of-scope-match.)_
- **Implement graceful degradation for optional engines** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* In restricted 'lite' environments, skip AST-based rules with a warning instead of crashing if the WASM engine is unavailable. This ensures the CLI remains functional for regex-based rules. _(architecture, error-handling)_
- **Using split() on markdown headings often misclassifies** - Using `split()` on markdown headings often misclassifies the first section as a preamble or loses the heading text itself. Utilizing `matchAll` to capture heading indices allows for precise slicing of content blocks without losing metadata or specific section titles. _(typescript, regex, parsing)_
- **Always reset module-level state like custom warning** - Always reset module-level state like custom warning handlers in `afterEach` blocks to prevent state leakage that can cause unpredictable failures in subsequent tests. _(testing, javascript)_
- **Remap kebab-case keys at boundaries** - \*\*Scope:\*\* packages/core/src/lesson-frontmatter.ts Translate kebab-case keys used on disk to camelCase in TypeScript at the parsing boundary to maintain idiomatic code while respecting external style conventions. _(conventions, typescript, yaml)_
- **Ensure filesystem locks are released within finally blocks** - Ensure filesystem locks are released within `finally` blocks rather than just after a successful `await` or inside a `catch`. Manual release management is fragile and can leak locks if an error occurs between the critical action and the release call, causing subsequent operations to hang. _(nodejs, robustness, concurrency)_
- **The shell option in spawn() calls should be omitted** - \*\*Engine:\*\* ast-grep
  \*\*Severity:\*\* warning
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js
  \*\*Pattern:\*\* `spawn($CMD, [$$$ARGS], { $$$BEFORE, shell: true, $$$AFTER })`

The shell option in spawn() calls should be omitted when command arguments are already provided as an array. Using structured arguments provides inherent safety, while avoiding the shell reduces the attack surface for command injection. _(security, nodejs, subprocess)_

- **2026-03-06T03:34:53.287Z** - \*\*Pattern:\*\* \b(kafka|kubernetes|firestore)\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, package.json, \*\*/\*.yaml, \*\*/\*.yml
  \*\*Severity:\*\* warning

Do not reference external services (Kafka, Kubernetes, Firestore) that are not part of the project. _(style, curated)_

- **Using exact length assertions like toHaveLength() instead** - Using exact length assertions like `toHaveLength()` instead of `toBeGreaterThanOrEqual()` in parser tests catches regressions where content is incorrectly over-split or empty segments are not properly filtered. _(testing, vitest, quality)_
- **Surface specific git fallback errors** - \*\*Scope:\*\* packages/cli/src/commands/extract.ts Avoid using empty catch blocks when probing for git refs or remotes during fallbacks. Surfacing specific errors like 'missing upstream' helps users diagnose configuration issues rather than being met with a generic 'no changes found' message. _(git, dx, error-handling)_
- **Trimming output from commands like 'git ls-files -z'** - Trimming output from commands like 'git ls-files -z' or 'git show' can corrupt NUL-delimited paths or strip intentional file whitespace. Always pass trim: false to execution wrappers when the raw output format must be preserved. _(git, shell, nodejs)_
- **Prettier interprets asterisks and underscores as markdown** - Prettier interprets asterisks and underscores as markdown emphasis, which can mangle technical strings like `\*\*/\*.tsx` into `\*\*/\_.tsx`. Directories containing sensitive regex or glob patterns must be added to `.prettierignore` to preserve functional syntax. _(markdown, prettier, globs)_
- **Static top-level imports from heavy internal packages delay** - \*\*Pattern:\*\* ^import\s+(?!type\s)(?!\s\*\{[^}]\*Error).\*from\s+['"](?:../|@[\w-]+/)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

Static top-level imports from heavy internal packages delay. _(performance, curated)_

- **Using a boolean flag to track lazy initialization causes** - Using a boolean flag to track lazy initialization causes crashes when multiple concurrent calls, such as those from `Promise.all`, hit the getter before the first one completes. Storing and returning the same initialization promise ensures all callers await the same setup process and prevents null pointer exceptions. _(concurrency, typescript, lazy-loading)_
- **Avoid forcing case normalization on file path filters** - Avoid forcing case normalization on file path filters to remain consistent with case-sensitive filesystems like Linux and macOS. This prevents query performance overhead and ensures compatibility with SQL dialects, such as LanceDB/DataFusion, that may not support case-insensitive operators. _(sql, lancedb, filesystem)_
- **When directing AI agents to implement local features,** - When directing AI agents to implement local features, explicitly restrict changes to the immediate target area. This prevents the agent from performing unauthorized refactors of surrounding layouts or sibling components which can cause cascading breakages. _(ai-agent, workflow, safety)_
- **When mapping violations to rules in SARIF generation,** - \*\*Pattern:\*\* \bruleIndex\b.\*(\?\?|\|\|)\s\*0
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*sarif\*/\*\*/\*.ts, \*\*/sarif/\*\*/\*.ts
  \*\*Severity:\*\* error

When mapping violations to rules in SARIF generation. _(architecture, curated)_

- **Use bash [[=~]] not echo | grep** - Use native regex matching like `[[ $var =~ pattern ]]` instead of `echo | grep` for variable extraction in hooks. This avoids unnecessary subshells and adheres to project-specific shell constraints for Claude Code hooks. _(bash, performance)_
- **Explicitly exclude test and spec files from rules targeting** - Explicitly exclude test and spec files from rules targeting specific file formats like lockfiles. This prevents false positives when test fixtures legitimately contain or reference those formats for verification purposes. _(linting, globs, testing)_
- **CLI tools executed via pnpm dlx or npx often lack optional** - CLI tools executed via `pnpm dlx` or `npx` often lack optional peer-dependency SDKs in the temporary environment. Implement shell-based fallbacks to system binaries or local providers like Ollama to ensure functionality without requiring users to manually install SDKs. _(architecture, dependencies, pnpm)_
- **When detecting markers in user-authored files, use** - \*\*Pattern:\*\* \.(includes|indexOf|match)\(\s\*['"]marker['"]
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

When detecting markers in user-authored files, use. _(style, curated)_

- **Cover bare and constructor calls** - \*\*Scope:\*\* packages/pack-agent-security/compiled-rules.json Security rules for primitives like `Function` must target both `new` expressions and bare identifier calls. Failing to check both allows attackers to bypass evaluation guards by omitting the `new` keyword. _(security, javascript)_
- **Limit manual edits to lifecycle changes** - \*\*Scope:\*\* .totem/compiled-rules.json Direct edits to compiled rule files are only permissible for lifecycle state updates like archiving; pattern or message corrections must flow through the source lesson compiler. _(totem, dx, workflow)_
- **Automatically tag extracted lessons with their source** - Automatically tag extracted lessons with their source (e.g., 'bot-review') and triage category during the capture phase. This metadata is essential for downstream filtering and helps the learning pipeline distinguish between human-authored and bot-generated insights. _(metadata, learning-loop)_
- **Include failure cases in few-shot prompts** - \*\*Scope:\*\* packages/cli/src/commands/compile-templates.ts Incorporating concrete examples from previous benchmark failures (e.g., async/await in forEach) prevents the model from repeating known architectural mistakes. _(prompt-engineering, llm, testing)_
- **Resolve unstaged paths against repo root** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts When resolving AST paths for files not yet in the Git index, resolve against the repository root. This ensures pathing consistency between staged and unstaged work when falling back to the filesystem. _(git, cli, ast)_
- **When mapping violations to rules in SARIF generation,** - When mapping violations to rules in SARIF generation, failing to find a rule index should trigger a hard error rather than falling back to a default index (e.g., 0). Silent fallbacks attribute violations to the wrong rule definitions, making generated security reports misleading. _(sarif, error-handling)_
- **Prefer regex over split for line extraction** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Using `/^[^\n]\*/.exec(str)` instead of `split('\n')[0]` avoids false-positive lint triggers on common array-access idioms while remaining semantically identical. _(dx, linting)_ _(archived: Over-broad astGrepPattern `$STR.split('\n')[0]` fires on any legitimate first-line extraction idiom. The underlying lesson was accurate (prefer regex for error-message parsing where the string may contain dots/newlines), but the rule as compiled does not encode that context. This is exactly the class of rule mmnto/totem#1352 was filed to archive yesterday. Auto-compiled on the 2026-04-11 PM postmerge (1.14.3/1.14.4/1.14.5 cycle). Archived via the mmnto/totem#1345 filter. Kept in the ledger so the compile worker prompt rewrite can use it as a negative training example.)_
- **When a tool invokes itself via a hook, pass a specific flag** - When a tool invokes itself via a hook, pass a specific flag or environment variable to distinguish the automated run from a manual one. This allows the handler to adjust logging, telemetry, or ledger recording for the background context. _(cli, telemetry, architecture)_
- **Guard command line string construction** - \*\*Scope:\*\* packages/core/src/sys/\*\*/\*.ts, !\*\*/\*.test.\* When building command strings for error messages, ensure the logic handles empty argument arrays to avoid trailing or double spaces in the output. _(dx, formatting)_
- **Gate auto-capture behind codebase verifiers** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Strategic features that emit automated content should remain opt-in until multi-stage classifiers and codebase-aware verifiers can prevent low-quality outputs. _(architecture, llm, quality-control)_
- **Using a boolean flag to track lazy initialization causes** - \*\*Pattern:\*\* \b(?:is)?[iI]nitialized\s\*(?::\s\*boolean|=\s\*(?:true|false))\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx
  \*\*Severity:\*\* warning

Using a boolean flag to track lazy initialization causes. _(architecture, curated)_

- **Decouple CLI logic from process exit** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Command implementation functions should return result objects instead of calling `process.exit` or setting `process.exitCode`. This prevents side effects when commands are invoked programmatically by other internal tools. _(cli, architecture)_ _(archived: Pattern process.exit($CODE) fires on the legitimate handleError() path in index.ts (CLI entry's terminal error path); lesson scope was deep callees like doctorCommand, not the CLI entry's error handler. Over-broad pattern.)_
- **Define state machine for lifecycle flags** - \*\*Scope:\*\* .claude/skills/preflight/SKILL.md State flags should only be consumed when a gate produces an actionable answer that will not change on the next query to prevent logic errors in complex gates. _(state-management, logic)_
- **Map minor bot findings to nit severity** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts, !\*\*/\*.test.\* When mapping external bot findings to internal schemas, categorize non-critical or minor severities as 'nit' rather than 'low' to maintain semantic clarity for cosmetic or non-blocking issues. _(dx, bot-review, schema)_ _(archived: Pattern severity:\s\*['"]low['"] scoped to packages/cli/\*\*/\*.ts is over-broad. The lesson targets bot-review-parser severity mapping specifically (CR/GCA finding normalization), but the pattern fires on any 'low' severity literal across the entire CLI surface (shell findings, telemetry levels, audit results, etc.). Source lesson scope needs narrowing to packages/cli/src/parsers/\*\* before re-compile.)_
- **Avoid using dynamic imports in shared utility modules** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Avoid using dynamic imports in shared utility modules that are already part of the main entry-point's import tree. While dynamic imports help CLI startup speed, they are most effective when placed inside specific command handlers to defer loading of heavy dependencies that aren't globally required. _(nodejs, cli, performance)_ _(archived: Globs target packages/cli/src/commands/\*\* but the message says "avoid dynamic imports in shared utility modules". Pattern fires on every canonical await import() in command handlers. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Hardcoded default values for properties like rule** - Hardcoded default values for properties like rule categories should be defined as shared constants in the core schema definition. This prevents logic drift and "magic string" inconsistencies between the reporting engine and the CLI display layers. _(architecture, maintainability, refactoring)_
- **Require multiple markers for standalone detection** - \*\*Scope:\*\* packages/cli/src/utils/governance.ts Standalone repository detection should require multiple markers (e.g., both proposals and ADR directories) rather than a single folder. Permissive detection leads to incorrect scaffolding paths in complex monorepos. _(cli, governance)_
- **Defensive guards in multi-source batch loops should use** - Defensive guards in multi-source batch loops should use warnings rather than throwing or silently swallowing errors. This informs the user of partial failures, such as a misconfigured or inaccessible repository, while allowing the command to proceed with available data. _(error-handling, resilience, logging)_
- **Narrow hook execution using if fields** - \*\*Scope:\*\* .claude/settings.json Use the `if` field in Claude Code hook configurations to filter commands before spawning a subshell, preventing measurable latency during high-frequency tool use cycles. _(claude-code, hooks, performance)_
- **Automated gates like pre-commit or pre-push hooks** - Automated gates like pre-commit or pre-push hooks should always use deterministic modes (e.g., `shield --deterministic`) to avoid the high latency and operational cost of LLM calls. This ensures the developer experience remains fast while maintaining a consistent enforcement layer that doesn't rely on non-deterministic model outputs. _(devtools, performance, automation)_
- **When parsing diff --git headers, extract the destination** - When parsing `diff --git` headers, extract the destination (`b/`) path and handle quoted strings to correctly support renames and filenames with spaces. Relying on the `a/` path or failing to account for quotes will cause ignore patterns and file-specific logic to fail silently. _(git, regex, cli)_
- **Avoid using live suppression markers like totem-context:** - Avoid using live suppression markers like `totem-context:` in files that are already globally excluded from a rule's scope. Use standard comments for explanation instead; this prevents the suppression engine from potentially masking other unrelated rules that might apply to the same lines. _(architecture, totem)_
- **Apply regex shadowing rules only to known attack surfaces** - Apply regex shadowing rules only to known attack surfaces like adapters and MCP code rather than entire codebases. Broad enforcement forces developers to replace simple regex matches with brittle string operations for non-sensitive parsing tasks. _(security, regex, refactoring)_
- **When using advanced git commands like reset to stage demo** - When using advanced git commands like `reset` to stage demo violations, include inline comments to explain the intent. This prevents user confusion while maintaining a seamless copy-paste experience for the "60-second superpower" onboarding goal. _(docs, git, onboarding, dx)_
- **Centralizing temporary directory cleanup into a helper** - Centralizing temporary directory cleanup into a helper with retry logic prevents Windows-specific file system flakes caused by race conditions or locked files during teardown. _(testing, fs, windows)_
- **Use discriminated unions for resolution** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts Returning a discriminated union like StrategyRootStatus for path resolution allows callers to safely pattern-match on success without type assertions. _(typescript, api-design)_
- **When wrapping external errors or providing fallbacks,** - When wrapping external errors or providing fallbacks, ensure project-specific prefixes like `[Totem Error]` appear at the start of the message. This maintains compliance with style guides and ensures errors are easily identifiable and searchable for end users. _(error-handling, conventions, library-design)_
- **Use sequential agents for batched PRs** - When multiple tickets are being bundled into a single PR, dispatch agents sequentially on the same branch rather than in parallel worktrees. Worktree isolation creates uncommitted changes across multiple directories that must be manually assembled via diff extraction and cherry-picking — the cleanup overhead exceeds the parallelism benefit. Reserve worktree isolation for truly independent work shipping in separate PRs. \*\*Source:\*\* mcp (added at 2026-03-28T23:07:34.749Z) _(workflow, agents, git)_
- **Providing an explicit command glossary in system prompts** - Providing an explicit command glossary in system prompts prevents LLMs from conflating deterministic tools with AI-powered alternatives. This prevents persistent documentation errors that can recur across multiple release cycles when models misinterpret command roles. _(prompts, documentation, context-clarity)_
- **Lessons documenting architectural traps or patterns** - Lessons documenting architectural traps or patterns are significantly less effective if they lack a concrete remediation path. Requiring a "Fix:" section in every lesson ensures the guidance is actionable and provides clear instructions for resolving violations identified by automated tools. _(documentation, architecture, standards)_
- **Honor source scope over LLM emission** - \*\*Scope:\*\* packages/core/src/compile-lesson.ts Source-declared scope declarations must take precedence over LLM-generated globs to prevent the silent loss of manual exclusion patterns like test file filters. _(compiler, llm, glob)_
- **Introducing new event types to a shared ledger can silently** - Introducing new event types to a shared ledger can silently alter existing bypass or usage metrics. Explicitly filtering event types in metric calculations preserves original semantics when the data model expands. _(analytics, ledger)_
- **PID-based process liveness checks (process.kill(pid, 0))** - \*\*Engine:\*\* ast-grep
  \*\*Severity:\*\* warning
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js
  \*\*Pattern:\*\* `process.kill($PID, 0)`

PID-based process liveness checks (process.kill(pid, 0)) fail across PID namespaces (Docker containers, CI runners). A container's PID 1 will always appear alive from the host. For cross-namespace safety, combine PID checks with stale timestamps — treat locks as dead if both the PID check fails OR the timestamp exceeds a generous threshold. Tags: concurrency, containers, trap _(manual)_

- **Background git hooks require both application-level flags** - Background git hooks require both application-level flags and shell-level stderr redirection to prevent Node.js stack traces from polluting the terminal during git operations. _(git, shell, ux)_
- **Assign synthetic file locations (e.g., '(review body)')** - Assign synthetic file locations (e.g., '(review body)') to findings not tied to specific lines to prevent deduplication logic from incorrectly collapsing them into inline findings. _(logic, deduplication)_
- **When shield finds false positives on synchronous adapter** - When shield finds false positives on synchronous adapter methods (e.g., flagging missing `await` on `replyToComment` which returns `void`), check the return type in `packages/cli/src/adapters/pr-adapter.ts` before adding `await`. Call sites are in `packages/cli/src/commands/triage-pr.ts` and `packages/cli/src/services/deferred-issuer.ts`. The Gemini shield model frequently assumes adapter calls are async network operations when they're actually synchronous `safeExec` wrappers. \*\*Source:\*\* mcp (added at 2026-03-28T07:11:27.941Z) _(shield, false-positive, async, adapter)_
- **The use of isolated catch blocks returning empty result** - The use of isolated catch blocks returning empty result sets for optional linked indexes ensures that external configuration or connection failures never block primary local operations. This prioritizes system availability over exhaustive correctness when dealing with non-critical federated data sources. _(architecture, search, resilience)_
- **Git output wraps file paths in double quotes if they** - Git output wraps file paths in double quotes if they contain spaces or special characters. Parsers must detect and strip these quotes to correctly resolve the actual file system path during automated tasks. _(git, filesystem, parsing)_
- **Check for the presence of the 'g' flag before appending it** - \*\*Engine:\*\* ast-grep
  \*\*Severity:\*\* warning
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, !\*\*/\*.test.ts
  \*\*Pattern:\*\* `new RegExp($SRC, $FLAGS + 'g')`

Check for the presence of the 'g' flag before appending it. _(architecture, curated)_

- **Dynamic imports should be limited to CLI command entry** - Dynamic imports should be limited to CLI command entry points to avoid security scanner flags and maintain clean dependency graphs in core utility layers. Standard top-level imports should be preferred for internal library logic to ensure predictable module resolution and simpler testing. _(security, architecture, nodejs)_ _(archived: Globs include packages/cli/src/commands/\*\* (only index.ts excluded), but the message flags dynamic imports "detected outside CLI command entry points". Globs contradict intent and fire on every canonical lazy-load line. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Raw child process output can be a Buffer or null; adding** - Raw child process output can be a Buffer or null; adding type guards before string operations like trim() prevents runtime crashes in strictly typed environments. _(typescript, node.js, exec)_
- **When using stdio: 'pipe' with the GitHub CLI, set** - When using `stdio: 'pipe'` with the GitHub CLI, set `GH\_PROMPT\_DISABLED=1` to prevent indefinite hangs caused by the process waiting for terminal input that is no longer accessible. _(cli, node.js, github-cli)_
- **Use cause property for error wrapping** - \*\*Scope:\*\* packages/core/src/sys/git.ts When re-throwing errors, avoid concatenating messages and instead use the 'cause' property to preserve the original error structure and context. _(typescript, error-handling)_
- **Manually prune retired git submodule directories** - Git does not automatically delete formerly-tracked submodule directories or their internal metadata from the filesystem after they are removed from .gitmodules. _(git, dx)_
- **Core library code should avoid direct calls to console** - \*\*Pattern:\*\* \bconsole\.(log|warn|error|info|debug|trace)\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/core/\*\*/\*.ts, packages/core/\*\*/\*.js, !\*\*/\*.test.ts, !\*\*/\*.spec.ts
  \*\*Severity:\*\* warning

Core library code should avoid direct calls to console. _(style, curated)_

- **Documentation generators should be configured to pull** - Documentation generators should be configured to pull metrics like rule counts dynamically rather than using pinned or hardcoded values. This prevents manual update errors and ensures that automated documentation runs do not revert figures to stale states. _(documentation, automation, maintenance)_
- **Standard shell string manipulation is insufficient** - Standard shell string manipulation is insufficient for robust JSON parsing in hooks; using `jq` ensures reliable data extraction from structured configuration files. _(bash, json, automation)_
- **Custom .env parsers must strip CRLF and quotes** - \*\*Pattern:\*\* \bprocess\.env\[[^\]]+\]\s\*=\s\*(?![^;\n]\*(\?\?|\|\||process\.env))
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/cli/\*\*/\*.ts, \*\*/cli/\*\*/\*.js, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Custom .env parsers must strip CRLF and quotes. _(architecture, curated)_

- **Map unknown CodeRabbit severities to nit** - \*\*Scope:\*\* packages/cli/src/commands/recurrence-stats.ts Default unknown or non-standard CodeRabbit severity strings to 'nit' rather than 'low' to ensure minor findings are correctly categorized in summary reports. _(coderabbit, logic)_
- **Decouple product gates from workflow** - Decoupling mandatory product checks from workflow-specific gates prevents local environment state from blocking routine developer actions like rebasing. _(architecture, workflow)_
- **Filter upgrade diagnostics by rule engine** - \*\*Scope:\*\* packages/cli/src/commands/doctor.ts Diagnostics targeting regex-to-AST upgrades must explicitly filter for rules using the 'regex' engine. AST-based rules often lack context telemetry (landing in 'unknown'), and including them in non-code ratio checks leads to false positive flags for rules that are already structural. _(regex, ast-grep, telemetry)_
- **Stub nested methods in library shims** - \*\*Scope:\*\* packages/cli/build/shims/lancedb.js When shimming complex libraries for lite tiers, ensure nested methods like Index.fts() are explicitly stubbed to throw clear tier-specific errors instead of generic TypeErrors. _(architecture, testing, lancedb)_
- **Use structural checks for feature-gated hashing** - \*\*Scope:\*\* packages/core/src/compile-manifest.ts When gating deterministic hashing on new features, use structural checks (like checking for specific object keys) rather than substring matching to avoid false positives in the gating logic. _(hashing, backward-compatibility)_
- **Default missing metadata to inclusive values** - \*\*Scope:\*\* packages/core/src/types.ts Defaulting missing or empty categorization fields to an 'any' value ensures backwards compatibility and prevents filtering logic from accidentally excluding records due to empty matches. _(metadata, architecture, filtering)_
- **Use regex for non-identifier properties** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts Property names that are not valid JS identifiers (e.g., `foo-bar`) must use regex fallbacks because ast-grep may parse them as expressions like subtraction. This prevents syntax-based false positives when matching property access. _(ast-grep, javascript, regex)_
- **Filter rules by engine before execution** - Filter rule sets by their execution engine (e.g., AST-grep vs regex) before passing them to specialized executors. This avoids unnecessary overhead and prevents logic errors, as different engines may expect different properties or use placeholder values for irrelevant fields. _(performance, architecture)_
- **Operations like saving metrics or telemetry are secondary** - Operations like saving metrics or telemetry are secondary to the main command and should never cause it to fail. Wrapping these side effects in try-catch blocks ensures "resilient continuation," where the tool logs a warning but completes its primary task. _(error-handling, resilience, cli)_
- **Use unique temp files for atomic writes** - \*\*Scope:\*\* packages/cli/src/commands/recurrence-stats.ts When performing atomic writes via temp-and-rename, include a process PID or random suffix in the temp filename to prevent collisions during concurrent executions. _(filesystem, concurrency)_ _(archived: Under-scoped regex + weaker-than-convention message per CR finding on mmnto-ai/totem#1754 (https://github.com/mmnto-ai/totem/pull/1754#discussion\_r3165648989). Pattern only catches inline quoted-string arguments (e.g., writeFileSync('/path.tmp')) and misses the actual production case in packages/cli/src/commands/recurrence-stats.ts:423 where the temp path is a template-literal variable (`const tmp = \`${outputPath}.${process.pid}.${Date.now()}.${crypto.randomUUID()}.tmp\``). Variable-assignment tracking is structurally outside regex's reach. Re-authoring as ast-grep with compound trace-and-inspect rule tracked in mmnto-ai/totem#1755.)_
- **Auto-formatters must ignore files whose integrity** - Auto-formatters must ignore files whose integrity is verified by hashes, as reformatting changes the file content and invalidates manifest attestation in CI. _(dx, ci, formatting)_
- **Avoid generic empty-array AST-grep patterns** - \*\*Scope:\*\* packages/pack-agent-security/\*\*/\*.ts Generic patterns like `const $VAR = []` are too broad and trigger on all empty array declarations; use more specific identifiers to avoid high false-positive rates. _(ast-grep, linting)_
- **Increase timeouts for Windows CI I/O** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.test.ts Windows CI environments often experience intermittent timeouts with default 5s limits due to slow temporary directory I/O. Increasing the suite-level timeout to 15s for file-heavy tests prevents these flaky failures. _(ci, windows, testing)_
- **Dynamic string construction signals broken rules** - Using workarounds like `'+'.repeat(3)` to bypass linting is a strong signal of an over-broad rule. These rules should be archived or refined rather than leaving workarounds in the codebase that increase friction for future authors. _(dx, linting, patterns)_
- **Enforce exact package publish surface** - \*\*Scope:\*\* packages/pack-agent-security/test/structure.test.ts Using 'expect.arrayContaining' for package.json files allows accidental artifacts to be published; use exact equality or length checks to strictly lock the shippable surface. _(testing, npm, security)_
- **CLAUDE.md compliance experiment (2026-03-14) proved** - CLAUDE.md compliance experiment (2026-03-14) proved that verbose project memory files suppress MCP tool usage. A 325-line CLAUDE.md with architecture docs, naming tables, and feature descriptions caused Claude Code to never call search*knowledge despite a BLOCKING instruction at line 288. An empty CLAUDE.md also failed — the MCP tool description alone is insufficient. A lean CLAUDE.md (~40 lines) with a concise instruction using the full MCP tool name (mcp\*\*totem-dev\*\*search_knowledge) works reliably. Key rules: keep agent config files lean, use full MCP tool names, don't describe tools as features (it makes the agent think it's reading documentation instead of instructions). This applies to all agent config files, not just CLAUDE.md. *(compliance, claude-md, mcp, agent-config, trap, experiment)\_
- **Explicitly stating that a tool resides in the developer** - Explicitly stating that a tool resides in the developer workflow rather than the application runtime prevents architectural confusion regarding deployment and dependencies. This distinction is vital for context-injection tools that might otherwise be mistaken for production library components. _(architecture, documentation, onboarding)_
- **Include tickets in suppression comments** - \*\*Scope:\*\* .github/workflows/release-binary.yml Directives like totem-ignore must include a tracking ticket reference to ensure technical debt is documented and traceable rather than indefinitely suppressed. _(linting, governance)_
- **Combining Full-Text Search (FTS) and vector embeddings** - Combining Full-Text Search (FTS) and vector embeddings requires Reciprocal Rank Fusion (RRF) to normalize and merge disparate scoring systems. This tactic prevents semantic similarity from overwhelming exact keyword matches, leading to more robust retrieval across diverse query types. _(search, retrieval, embeddings)_
- **Dynamic imports should be limited to CLI command entry** - \*\*Pattern:\*\* \bimport\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, packages/cli/src/adapters/\*\*/\*.ts, packages/cli/src/utils.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

Dynamic imports should be limited to CLI command entry. _(style, curated)_

- **Synchronize priority sequences for consistent triage** - \*\*Scope:\*\* docs/active*work.md Priority lists in planning documents must match across all sections so that the `totem triage` command and human developers follow a single, consistent execution sequence. *(documentation, triage, dx)\_
- **GCA may suggest reverting dynamic imports back to static** - \*\*Pattern:\*\* import\s+(?!type\s).\*\s+from\s+['"]@mmnto/totem['"]
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

GCA may suggest reverting dynamic imports back to static. _(performance, curated)_

- **Short, sequential startup tasks often do not require** - Short, sequential startup tasks often do not require encapsulation into dedicated functions if they are limited in scope (e.g., under 15 lines). Deferring abstraction until complexity increases or reuse is required prevents unnecessary boilerplate and keeps the entry point's execution flow immediately visible. _(clean-code, refactoring, yagni)_
- **Separate utilities for trusted and untrusted content allow** - Separate utilities for trusted and untrusted content allow for performance optimizations on local data while enforcing strict entity escaping on hostile network fetches. This prevents prompt injection and XML breakout while maintaining readability for internal diffs. _(security, xml, architecture)_
- **Gate rules only against supported engines** - \*\*Scope:\*\* packages/core/src/compile-smoke-gate.ts Explicitly skip compile-time smoke gates for rule engines (like Tree-sitter 'ast') that the gate mechanism does not yet support to prevent valid rules from being hard-rejected. _(compiler, validation)_
- **Optimization paths that process file deltas must still** - Optimization paths that process file deltas must still apply the project's ignore patterns to avoid analyzing sensitive or irrelevant files like lockfiles. Bypassing these filters during incremental reviews can lead to false positives or processing of vendored code. _(git, cli, logic)_
- **Use path.relative(process.cwd(),** - \*\*Engine:\*\* ast-grep
  \*\*Severity:\*\* warning
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js
  \*\*Pattern:\*\* `$OBJ.replace(process.cwd(), $REPLACEMENT)`

Use path.relative(process.cwd(). _(style, curated)_

- **Implementing a trap for EXIT, INT, and TERM signals ensures** - Implementing a `trap` for EXIT, INT, and TERM signals ensures that temporary files are reliably cleaned up even if a developer interrupts a long-running hook. _(devops, shell, dx)_
- **Using job-level 'if' conditions for required status checks** - Using job-level 'if' conditions for required status checks can cause branch protection to hang on 'pending' when a job is skipped; use internal step-level bypasses instead. _(github-actions, branch-protection)_
- **Tests for automated file-splicing logic should assert** - Tests for automated file-splicing logic should assert the entire normalized file content to ensure no stale fragments or accidental truncations occur. _(testing, dev-tools)_
- **Converting top-level static imports of heavy internal** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Converting top-level static imports of heavy internal packages to dynamic imports significantly reduces CLI startup latency. This ensures that only the necessary modules are loaded for the specific command being executed. _(nodejs, performance, cli)_ _(archived: Over-broad: astGrepPattern `import $NAME from '$PKG'` matches every top-level default import in packages/cli/src/commands/\*\* with no way to distinguish heavy internal packages from cheap built-ins. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Use strict boundaries (like (\/|$)) or the URL class** - Use strict boundaries (like `(\/|$)`) or the URL class when detecting local providers to avoid bypasses like `localhost.evil.com`. Relying on prefix matching for loopback addresses creates a security vulnerability where remote attackers can spoof local-only bypasses. _(security, networking, regex)_
- **When constructing LIKE clauses from user input, explicitly** - When constructing `LIKE` clauses from user input, explicitly escape `%`, `\_`, and `\` in addition to standard quote escaping. Failure to do so allows users to bypass intended filters via wildcard injection or trigger unexpected matching behavior. _(security, sql, lancedb)_
- **Positioning the translation of natural language** - Positioning the translation of natural language instructions into AST queries as "compiling rules" distinguishes the tool from subjective AI reviewers. This framing emphasizes deterministic enforcement and speed over the hallucinations and latency inherent in LLM-based analysis. _(positioning, architecture, static-analysis)_
- **Require specific names for failing tests (e.g., "rejects** - Require specific names for failing tests (e.g., "rejects empty catch blocks") instead of generic descriptions like "works correctly" during task planning. This forces the agent to define a concrete failure condition that proves the implementation actually solves the intended problem. _(tdd, testing, prompt-engineering)_
- **Consolidating environment variables and timeouts** - Consolidating environment variables and timeouts for external tools into shared helpers prevents configuration drift across different adapter implementations. _(architecture, dx, github-cli)_
- **Defer git root resolution in layers** - \*\*Scope:\*\* packages/core/src/strategy-resolver.ts Probing for the git root should be deferred until a resolution layer actually requires it, preventing premature errors when absolute path overrides are provided via environment variables or configuration. _(architecture, git)_
- **Use ledgers for deferred breaking changes** - Record low-impact breaking changes in a 'deferred-major ledger' to maintain visibility of technical debt without triggering immediate major version bumps. This allows for bundling multiple substantive changes into a single meaningful major release later. _(semver, governance, process)_
- **Sync help text with runtime constants** - \*\*Scope:\*\* packages/cli/src/index.ts Use named constants for magic numbers like truncation thresholds to ensure consistency between runtime enforcement and CLI help documentation. _(cli, dx)_
- **Auto-formatters like Prettier can mangle technical metadata** - Auto-formatters like Prettier can mangle technical metadata by escaping underscores and asterisks in Markdown files, which breaks glob matching logic. Validation logic should explicitly check for these escaped characters (`\\_`, `\\*`) to ensure scope patterns remain valid for tools. _(markdown, prettier, globs, validation)_
- **Hoist immutable adapter capability checks** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Move adapter capability checks outside of loops when the adapter is instantiated once, as repeated checks inside the loop are redundant and slightly impact performance. _(optimization, logic)_
- **Decoupling fast, deterministic state readers from slower** - Decoupling fast, deterministic state readers from slower validation wrappers improves CLI responsiveness. This allows users to verify system state without triggering expensive linting or LLM processes. _(architecture, cli, performance)_
- **Centralize model IDs in CLI initialization** - \*\*Scope:\*\* packages/cli/src/commands/init-detect.ts Avoid duplicating model ID literals when constructing both configuration objects and display blocks; using constants prevents version drift when defaults are updated. _(cli, refactoring, dry)_
- **Avoid applying strict linting rules, such as empty catch** - Avoid applying strict linting rules, such as empty catch block prohibitions, to dev-only diagnostic or "throwaway" scripts. These scripts often prioritize resilience and simplicity over production-grade error handling, making strict audits a source of false positives. _(linting, ast-grep, scripts)_
- **Specific LLM models, such as Gemini's text-embedding-004,** - \*\*Pattern:\*\* text-embedding-004
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.py, \*\*/\*.env, \*\*/\*.yaml, \*\*/\*.yml
  \*\*Severity:\*\* error

Specific LLM models, such as Gemini's text-embedding-004. _(architecture, curated)_

- **Restrict dynamic imports to CLI command entry points** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Restrict dynamic imports to CLI command entry points to avoid security scanner noise while maintaining a clean dependency graph. Utility and adapter layers should use standard top-level imports to ensure structural clarity and pass automated code scanning audits. _(security, architecture, dependency-management)_ _(archived: Globs `packages/cli/src/\*\*/\*.ts, !packages/cli/src/commands/\*\*/\*.ts` are over-broad: they match the CLI root entry files packages/cli/src/index.ts and index-lite.ts, which is precisely where ADR-072 §3 (PR #945) places lazy-loads of command handlers. Rule fires on every canonical `const { cmd } = await import('./commands/foo.js')` line in the two CLI bin entry files. Canonical utility-layer coverage retained via rules a1fd35ee696110b0 (utils/adapters/lib) and f6739f9ad356067a (utils/lib/helpers), which use correctly narrow globs. Archived via #1517.)_
- **Filter ignored patterns before checking for an empty diff** - Filter ignored patterns before checking for an empty diff to ensure branch-diff fallbacks trigger correctly when only ignored files change. Checking after the emptiness check causes the tool to perceive a non-empty diff but scan zero content, resulting in a silent pass. _(git, validation, logic-flow)_
- **Explicitly verify that glob entries are strings** - Explicitly verify that glob entries are strings before calling methods like .startsWith to prevent runtime crashes when processing arrays that might contain non-string types. _(typescript, validation, globs)_
- **Hardcoded vendor-shaped secrets in test fixtures** - Hardcoded vendor-shaped secrets in test fixtures can trigger false positives in security scanners; construct these strings at runtime via concatenation to avoid detection. _(security, testing)_
- **Loading large Tree-sitter WASM binaries at the module level** - Loading large Tree-sitter WASM binaries at the module level can cause significant cold-start penalties in CLI tools. Implementing lazy loading for these components ensures that the performance of unrelated commands is not degraded by unnecessary binary initialization. _(wasm, performance, nodejs)_
- **Project conventions require log.error to use a mandatory** - Project conventions require `log.error` to use a mandatory 'Totem Error' tag for system-wide consistency, while other levels like `log.warn` or `log.info` must use command-specific tags (e.g., 'Init'). Mixing these up or using generic tags for warnings breaks the automated formatting and traceability defined in the architectural style guide. _(logging, style-guide, observability)_
- **Treat vector indexes as local-only caches that are excluded** - Treat vector indexes as local-only caches that are excluded from version control and rebuilt via synchronization commands. This avoids repository bloat and constant merge conflicts inherent in committing frequently changing binary database artifacts. _(git, architecture, vector-db)_
- **When resolving dot-notation paths, validate** - When resolving dot-notation paths, validate that intermediate values are objects and use `Object.hasOwn()` to prevent runtime errors on primitives and unauthorized prototype-chain access. _(security, typescript)_
- **Prevent silent failures in short-circuit modes** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* In commands with short-circuit flags, any failure in the active phase must prevent success logs and ensure a non-zero exit code to avoid misleading the user about the operation's success. _(cli, error-handling)_
- **Explicitly exclude nested monorepo test paths** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Broad test exclusions like '\*\*/test/\*\*' may fail in complex monorepos; use explicit patterns like 'packages/\*\*/test/\*\*' to ensure rules don't leak into consumer test suites. _(monorepo, glob, configuration)_
- **2026-03-03T01:51:33.783Z** - \*\*Pattern:\*\* \.(includes|match|indexOf|search)\(\s\*['"`].\*-o\s+json.\*['"`]\s\*\)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.py, \*\*/\*.sh
  \*\*Severity:\*\* error

Do not hardcode CLI flags like "-o json" in string matching; use structured argument parsing. _(architecture, curated)_

- **Provide explicit recovery hints for missing directories** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts Throw specific errors like `NO\_LESSONS\_DIR` with actionable recovery hints instead of generic parse errors when required resources are missing. This improves developer experience by guiding the user toward the correct initialization or extraction command. _(cli, errors)_
- **Using Array.prototype.reduce to categorize items** - Using `Array.prototype.reduce` to categorize items into multiple buckets (like errors and warnings) is more efficient than calling `.filter()` multiple times. This approach avoids redundant iterations over the collection, which is critical as the number of rules and violations scales. _(typescript, performance, optimization)_
- **Requiring multiple manual overrides before promoting** - Requiring multiple manual overrides before promoting a local exemption to a shared suppression prevents one-off local hacks from polluting team-wide configuration. This creates a natural threshold for identifying persistent false positives. _(automation, workflow)_
- **Git commands used for programmatic parsing should be** - Git commands used for programmatic parsing should be prefixed with `LC\_ALL=C` to ensure consistent, locale-independent output. This prevents parsing failures when the user's environment uses a non-English language. _(git, i18n, parsing)_
- **Narrow LLM output enums to prevent forgery** - \*\*Scope:\*\* packages/core/src/compiler-schema.ts Use narrow enums for LLM-facing fields to prevent the model from emitting internal-only status codes or bypassing system-level validation logic. _(security, zod, llm)_
- **Guard against dropping metadata-less items** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Ensure items with missing or whitespace-only metadata are ignored by specific filtering passes so they can be evaluated by subsequent fallback logic. _(logic, safety)_
- **When batch functions process complex objects as input keys,** - When batch functions process complex objects as input keys, returning an indexed array is often cleaner and safer than using a Map. Map keys involving objects rely on reference equality, which can cause retrieval failures if those objects are cloned or recreated during the processing pipeline. _(patterns, collections, ast-grep)_
- **Metacharacters must be escaped when interpolating dynamic** - Metacharacters must be escaped when interpolating dynamic strings into regular expressions to prevent regex injection attacks. This ensures that dynamic input is treated as a literal string rather than being interpreted as executable regex syntax. _(security, regex)_
- **Repeatedly parsing the same file content for multiple** - Repeatedly parsing the same file content for multiple structural rules creates significant performance overhead. Parse the file once to create an AST root and execute all engine patterns against that cached object to minimize redundant parsing. _(ast-grep, performance, parsing)_
- **When identifying directory-based glob patterns (like** - \*\*Pattern:\*\* \.(includes\(['"]/['"]\)(?!\s\*,\s\*1)|indexOf\(['"]/['"]\)\s\*(?:>=?\s\*0|!==\s\*-1))
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js
  \*\*Severity:\*\* error

When identifying directory-based glob patterns (like. _(architecture, curated)_

- **Restrict dynamic import security rules to core and adapter** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Restrict dynamic import security rules to core and adapter packages while exempting CLI command entry points. This eliminates recurring linter noise in command files where dynamic loading is often required for performance or modularity. _(security, architecture, linting)_
- **Perform explicit null and type checks on the results** - \*\*Engine:\*\* ast-grep
  \*\*Severity:\*\* warning
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, !\*\*/registry.ts
  \*\*Pattern:\*\* `JSON.parse($A) as $B`

Perform explicit null and type checks on the results of `JSON.parse` for lock files before accessing properties like `pid`. Direct type assertions (`as LockData`) can mask `TypeError` risks if a lock file is concurrently truncated, malformed, or empty. Note: `JSON.parse(x) as unknown` followed by Zod safeParse is a valid defensive pattern — the ast-grep pattern cannot distinguish this case, so validated files are scope-excluded. _(typesafety, nodejs, json)_

- **Passing large data payloads via stdin instead** - Passing large data payloads via stdin instead of command-line arguments avoids reaching `ARG\_MAX` limits, which are significantly more restrictive on Windows. _(cli, windows)_
- **The ignorePatterns field in totem.config.ts is shared** - The `ignorePatterns` field in `totem.config.ts` is shared between `totem sync` and `totem shield`. Using it to suppress validation violations for specific directories will inadvertently prevent those files from being indexed into the vector database. _(configuration, indexing, validation)_
- **Explicitly exclude test files (e.g., !\*\*/\*.test.ts)** - Explicitly exclude test files (e.g., `!\*\*/\*.test.ts`) from linting rule scopes to prevent false positives in code where specific patterns are intentional. _(linting, dx)_
- **Preserve original error context via cause** - \*\*Scope:\*\* packages/core/\*\*/\*.ts, !\*\*/\*.test.\* When wrapping runtime exceptions into custom classes like TotemParseError, use the 'cause' property to preserve the original stack trace and enable semantic error classification. _(typescript, error-handling)_ _(archived: Incidental compile that hitched a ride on the #1484 pack-scaffold manifest refresh. Source lesson is good (error-cause propagation is a real invariant in the codebase), but the compiled ast-grep pattern `new $ERROR($$$ARGS)` matches every class instantiation in the scoped globs — `new Map(...)`, `new Set(...)`, `new Date(...)`, `new RegExp(...)`, and so on — not just error wrapping. Both CR and GCA flagged on #1503. Pattern needs a catch-context + missing-cause refinement (ADR-088 Phase 1 #1479 verify-retry loop will catch this class at compile time). Archive now; re-compile the source lesson via `totem compile --upgrade e2341ed9229f9a60` once Phase 1 gates land.)_
- **Relying on file paths and line numbers to associate** - Relying on file paths and line numbers to associate findings with PR comments is ambiguous; preserve direct comment or thread IDs throughout the pipeline for reliable action mapping. _(github-api, architecture)_
- **Publishing private cohort members** - \*\*Scope:\*\* packages/pack-rust-architecture/package.json Flipping a package to public within a versioned cohort triggers a publish if the version is missing from the registry, as changeset publish handles workspace dependency resolution without requiring a new changeset. _(npm, changesets, ci)_
- **Mixed batches of fast local tasks and slow remote tasks** - Mixed batches of fast local tasks and slow remote tasks can bottleneck parallelism because fast tasks occupy concurrency slots. Partitioning tasks by type ensures the concurrency limit applies to the actual heavy workload. _(performance, concurrency)_
- **Retain .strategy as legacy fallback** - \*\*Scope:\*\* docs/wiki/cross-repo-mesh.md While the sibling-clone pattern is now preferred, the legacy .strategy submodule pattern must be documented as a supported fallback rather than fully retired. _(git, compatibility)_
- **When redacting tokens like sk-proj- and sk-, the longest** - When redacting tokens like `sk-proj-` and `sk-`, the longest patterns must be evaluated first to prevent shorter prefixes from matching and leaving sensitive fragments exposed. _(security, secrets, regex)_
- **Use delimiters in multi-field cache keys** - \*\*Scope:\*\* packages/cli/src/utils.ts When constructing a cache key from multiple input fields, the architectural concern is \*\*boundary preservation\*\*: adjacent fields must remain distinguishable from each other after concatenation, otherwise different inputs can collide into the same cache key. The class of bug is "ambiguous serialization" — the same flat byte sequence can represent multiple distinct inputs because the field boundaries weren't preserved at the serialization layer. This is a design-time architectural decision for any function that hashes multi-field inputs, not a syntactic pattern that grep or AST-grep can reliably catch. The right fix is a code-review checklist for cache key constructors, not a compiled rule that flags every adjacent string concatenation. Reviewers should ask: "if I swap two fields' contents, can the resulting key remain identical?" If yes, the constructor needs explicit delimiter discipline (a separator byte that cannot appear in field values, like `\0`, or a length-prefixed encoding). This is a conceptual/architectural pattern, not a compilable rule. _(caching, security, architecture)_
- **Mirror template patterns in documentation** - \*\*Scope:\*\* docs/wiki/governing-ai-agents.md Documentation examples for hooks should mirror the exact `stdio` and `timeout` configurations used in production templates to prevent configuration drift and debugging confusion. _(documentation, dx)_
- **Hardening hook upgrade tests with balanced if/fi** - Hardening hook upgrade tests with balanced if/fi verification ensures that script injections are syntactically complete and will not break the host shell environment. _(testing, shell, automation)_
- **Guard external JSON field types** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.ts, !\*\*/\*.test.\* Apply runtime type guards to fields extracted from external files like package.json even after safe-reading. This prevents invalid data types from corrupting downstream objects if the file structure is malformed. _(typescript, defensive-programming)_
- **Prefix hook diagnostics with script identifiers** - \*\*Scope:\*\* .claude/hooks/\*\*/\*.js, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use `[<script-name>]` instead of `[Totem Error]` for stderr diagnostics in hook helpers. The global error prefix is reserved for thrown exceptions, while script identifiers help distinguish non-fatal diagnostic output. _(logging, hooks, conventions)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 54 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: .claude/hooks/pre-compact.sh, .gemini/hooks/BeforeTool.js, .gemini/hooks/SessionStart.js, .gemini/styleguide.md, .github/copilot-instructions.md (+ 49 more). reasonCode: stage4-out-of-scope-match.)_
- **To validate precedence between competing directives, test** - To validate precedence between competing directives, test them on the same line rather than separate lines to ensure conflict resolution logic is actually triggered. _(testing, logic, regex)_
- **When redirecting a deprecated flag to a new command, ensure** - When redirecting a deprecated flag to a new command, ensure all associated options are forwarded to maintain full functional parity for legacy callers. _(cli, refactoring)_
- **Distinguish link-names from boundary-names** - \*\*Scope:\*\* docs/wiki/cross-repo-mesh.md Filesystem-derived link names like 'totem-strategy' differ from stable runtime boundary names like 'strategy' used in auto-injection paths. _(mcp, architecture)_
- **Prefer archiving over shipping partial coverage** - Archive rules with incomplete patterns rather than shipping partial coverage of an invariant. Incomplete sensors are worse than no sensors because they provide a false sense of security. _(linting, dx)_
- **Trust explicit classification over content heuristics** - \*\*Scope:\*\* packages/core/src/compile-lesson.ts Routing logic should trust explicit flags like `compilable: true` rather than re-scanning body text for keywords to avoid accidental rejection of valid patterns. _(compiler, architecture)_
- **Simple string replacement or backtick-based splitting often** - Simple string replacement or backtick-based splitting often mangles non-prose elements like link targets, anchors, and YAML frontmatter. To prevent corruption, use an AST parser or a robust masking strategy that protects these structured spans before applying prose-level sanitization. _(markdown, documentation, regex)_
- **Explicitly enable non-code node processing for telemetry** - \*\*Scope:\*\* packages/core/src/rule-engine.ts Rule engines often skip non-code nodes like comments or strings by default; these must be explicitly processed if telemetry needs to track rule matches in those contexts. _(ast, rule-engine)_
- **Full binary distribution of the CLI is currently limited** - Full binary distribution of the CLI is currently limited to a 'Lite-tier' because LanceDB dependencies create significant blockers for full standalone packaging. _(architecture, distribution, lancedb)_
- **Restrict manual edits to lifecycle changes** - \*\*Scope:\*\* .totem/compiled-rules.json Manual edits to compiled rule files are reserved for lifecycle state changes like archiving. Content corrections, such as pattern or message updates, must be performed in the source lesson and recompiled. _(totem, workflow)_
- **Brace expansion (e.g., \\\*.{ts,js}) is not universally** - Brace expansion (e.g., `\*.{ts,js}`) is not universally supported and can cause some glob engines to silently match zero files. To ensure reliability across different runners, expand these patterns into an explicit array of separate strings. _(glob, devtools, syntax)_
- **Sync hook templates with registry** - \*\*Scope:\*\* packages/cli/src/commands/init-templates.ts Removing a command from the registry without updating hook templates causes 'unknown command' errors in new sessions. Always verify `init-templates.ts` when deprecating CLI features. _(cli, maintenance)_
- **Preserve additive fields in union success paths** - \*\*Scope:\*\* packages/mcp/\*\*/\*.ts When evolving a schema into a discriminated union, keeping original fields in the success branch maintains backward compatibility for consumers who read those fields directly without checking the discriminator. _(api-design, typescript, schema)_
- **When testing CLI logic that modifies process.exitCode,** - When testing CLI logic that modifies process.exitCode, the exitCode must be reset in a global teardown to prevent state leakage between independent test cases. _(testing, node)_
- **Verify ownership before scrubbing config** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* When removing configuration entries during eject, use explicit markers to verify tool ownership instead of substring matching to prevent accidental deletion of user-defined hooks. _(cli, eject, json)_
- **Validate paths using path.resolve and path.relative** - Validate paths using path.resolve and path.relative to ensure agent-driven file operations stay within the workspace. This prevents directory traversal attacks where an agent might access sensitive system files. _(security, node.js, agents)_
- **Applying .passthrough() to Zod schemas for global** - Applying .passthrough() to Zod schemas for global registries ensures forward compatibility when different versions of the CLI access the same shared state. _(zod, architecture)_
- **Using require() inside vi.mock callbacks can lead** - Using `require()` inside `vi.mock` callbacks can lead to resolution failures in pure ESM environments due to Vitest's hoisting logic. Developers should use `vi.importActual` or async imports to ensure dependencies are resolved in an ESM-safe manner. _(testing, esm, vitest)_
- **Relying on filename patterns to distinguish** - Relying on filename patterns to distinguish between different item types is fragile as storage structures evolve. Implementing explicit metadata fields within the objects themselves makes filtering logic more robust and easier to maintain during storage migrations. _(patterns, architecture, maintenance)_
- **Thread system prompts through all orchestrators** - \*\*Scope:\*\* packages/cli/src/orchestrators/\*.ts Adding a system prompt field to a shared interface requires updating all provider implementations to prevent silent context loss during LLM calls. _(orchestrator, architecture)_
- **git ls-files with relative paths fails from subdirs** - Git commands like `ls-files` using relative paths can produce inconsistent results or fail when executed from subdirectories. Using `git -C "$REPO\_ROOT"` or absolute paths ensures the script behaves correctly regardless of the caller's current working directory. _(shell, git, automation)_
- **Reformatting files like compiled-rules.json invalidates** - Reformatting files like compiled-rules.json invalidates checksums stored in manifests, leading to CI attestation failures. Always exclude these files from Prettier to maintain build integrity. _(ci, dx, formatting)_
- **Retain internal guards for defense-in-depth** - \*\*Scope:\*\* .claude/settings.json, .claude/hooks/\*.sh Maintain internal regex guards within hook scripts even when using external `if` filters to ensure the gate remains effective if the configuration is downgraded or misconfigured. _(hooks, shell, reliability)_
- **Using 'pnpm run version' instead of the bare 'pnpm version'** - Using 'pnpm run version' instead of the bare 'pnpm version' command is necessary to correctly trigger the Changesets workflow and update changelogs. _(pnpm, release)_
- **Prioritize TS over TSX for parsing** - \*\*Scope:\*\* packages/core/src/compile-smoke-gate.ts When inferring extensions for code snippets, prioritize .ts over .tsx because TSX does not support angle-bracket type assertions (e.g., <Type>value), making it a subset rather than a superset of TypeScript syntax. _(typescript, ast-grep, parsing)_
- **Matching error message substrings couples logic** - Matching error message substrings couples logic to the exact wording of utility errors, making it brittle. Use exported error codes or discriminated properties to create resilient and type-safe error-handling branches. _(errors, patterns)_
- **Use containment coefficient for diff matching** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Jaccard similarity fails for small patterns against large diffs because the union size dilutes the score; asymmetric containment coefficient remains stable regardless of diff size. _(math, algorithms, git)_
- **Ensure model name validation regexes explicitly allow** - \*\*Pattern:\*\* \bmodel\w\*\b.\*(['"\/])\^?\[[a-zA-Z0-9\-\_]+\][\*+]\$?\1
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* warning

Ensure model name validation regexes explicitly allow. _(style, curated)_

- **Split enforcement and administrative loaders** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Separating runtime enforcement loaders from administrative file loaders allows silencing items in production while preserving their lifecycle history for telemetry and management tools. _(architecture, dx, data-lifecycle)_
- **Backticks must be escaped consistently across all SQL** - Backticks must be escaped consistently across all SQL construction functions, including boundary prefix handling and WHERE clause building. Aligning this logic across input types ensures defense-in-depth against injection attempts that exploit syntax inconsistencies. _(security, sql, escaping)_
- **Map PR metadata to env vars for secure shells** - Mapping PR metadata to env vars is the preferred security pattern for shell scripts to prevent injection without requiring the 'pull-requests: read' permissions needed for gh api calls. _(github-actions, security)_
- **NEVER inline secrets, tokens, or API keys into agent config** - NEVER inline secrets, tokens, or API keys into agent config files (.mcp.json, .gemini/settings.json, MCP server configs, etc.). AI agents pattern-match against MCP server documentation examples that show inline tokens — this is how PATs end up hardcoded in config files. Secrets must live ONLY in gitignored `.env` files. Agents and MCP servers inherit environment variables from the shell automatically via process.env — no explicit `env` blocks needed in config files. _(security, secrets, agent-config, mcp, init, trap)_
- **Archive over-broad blocking rules** - \*\*Scope:\*\* packages/pack-agent-security/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Archive global rules that block legitimate scaffolding due to over-broad patterns, documenting the rationale in an 'archivedReason' field while tracking narrow replacements separately. _(linting, governance, workflow)_
- **Lesson: Lesson headings are strictly limited to 60** - Lesson: Lesson headings are strictly limited to 60 characters to serve as efficient SARIF identifiers and vector search labels. This design choice prevents unnecessary token consumption in LLM prompts while maintaining high retrieval quality during knowledge discovery. _(vector-search, performance, metadata)_
- **Use negative filters for legacy compatibility** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* When introducing status fields to legacy datasets, use negative filters (e.g., `!== 'archived'`) instead of positive ones to ensure records lacking the field remain active by default. _(logic, backward-compatibility, filtering)_
- **Allow null branches for detached HEADs** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.test.\* Git state extractors must treat the current branch as optional (string or null) to prevent test failures in CI environments that use detached HEAD states. _(git, testing, ci)_ _(archived: Pre-existing variant of the same test-fixture authorial-guidance defect class as a24ec7272f1f670e and de7ee11b427d201e. fileGlobs scope to packages/mcp/src/\*\*/\*.test.ts(x), but the pattern `currentBranch:\s\*['"][^'"]+['"]` fires on every test that mocks git state with a literal currentBranch — which is how git-mocking tests normally set up fixtures. Surfaced by GCA review on #1526 as a companion to the wave-1 archives.)_
- **Sampling a single record to compare its stored vector** - Sampling a single record to compare its stored vector length against the current embedder is a reliable way to detect provider changes (e.g., OpenAI to Gemini). This proactive check prevents cryptic runtime errors and allows the store to trigger a clean auto-healing cycle when embedding dimensions no longer match the index. _(lancedb, embeddings, vector-database)_
- **Archive rules to preserve telemetry** - \*\*Scope:\*\* .totem/compiled-rules.json Archiving broken rules by setting `status: 'archived'` silences enforcement while preserving historical trigger and suppression data per ADR-074. This allows for future rule refinement without losing the context of past violations. _(architecture, telemetry, maintenance)_
- **Filter diff candidates before selection** - \*\*Scope:\*\* packages/cli/src/commands/extract.ts When cascading through git diff sources (staged, working tree, unpushed), filter out lockfiles and ignored files before selecting a source. Selecting the first non-empty raw diff can cause lockfile-only changes to short-circuit the logic and prevent the tool from finding meaningful code changes in later fallbacks. _(git, logic)_
- **LLMs are notoriously poor at character counting; use** - \*\*Pattern:\*\* \b\d+\s\*(?:characters?|chars?|words?)\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, \*\*/\*.py, \*\*/\*.md, \*\*/\*.txt
  \*\*Severity:\*\* warning

LLMs are notoriously poor at character counting; use. _(style, curated)_

- **The Git -- separator treats all subsequent arguments** - \*\*Pattern:\*\* \bgit\s+.\*\s--\s+.\*(\.\.\.?|[\^~])
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*.sh, \*.bash, \*.yml, \*.yaml, Makefile, \*\*/\*.ts, \*\*/\*.js, \*\*/\*.py
  \*\*Severity:\*\* error

The Git -- separator treats all subsequent arguments. _(architecture, curated)_

- **Normalize badExample snippets before validation** - \*\*Scope:\*\* packages/core/src/compiler.ts LLM-generated code snippets must have backtick or fence wrappers stripped before validation to prevent parse failures in automated smoke gates. _(llm, validation)_
- **Check for the presence of the global ('g') flag** - \*\*Pattern:\*\* new\s+RegExp\s\*\(\s\*[^,]+\s\*,\s\*[^,]\*\.flags\s\*\+\s\*['"][^'"]\*g
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx
  \*\*Severity:\*\* error

Check for the presence of the global ('g') flag. _(architecture, curated)_

- **Generating IDs from violation properties like file, line,** - Generating IDs from violation properties like file, line, and content—rather than timestamps or random numbers—ensures stability across runs. This determinism is critical for tracking unique violations over time and enables reliable assertions in automated tests. _(sarif, testing, architecture, crypto)_
- **Use dynamic await import() inside CLI command handlers** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Use dynamic await import() inside CLI command handlers for large internal packages instead of top-level static imports. This ensures that fast operations like version checks or help commands remain responsive by avoiding unnecessary module loading. _(performance, cli, dx)_
- **When generating reports based on current Git status,** - When generating reports based on current Git status, capture the deterministic state before writing the output file. This prevents the report itself from being included in the snapshot of uncommitted changes. _(git, io)_
- **Automated hook upgrades should target specific delimited** - Automated hook upgrades should target specific delimited spans between markers rather than overwriting the entire file. This prevents the accidental deletion of user-appended logic or configurations from other hook managers. _(git-hooks, dx, architecture)_
- **Use cross-spawn for Windows shim resolution** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use the `cross-spawn` package instead of enabling `shell: true` to resolve `.cmd` and `.bat` shims on Windows. This prevents shell-injection vulnerabilities where `cmd.exe` interprets metacharacters like `&`, `|`, and `>` in argument values. _(security, node, windows)_
- **Using a prefix glob like src/compiler\* effectively targets** - Using a prefix glob like `src/compiler\*` effectively targets multiple related flat files (source, tests, and schemas) when they share a naming convention but lack a common subdirectory. _(github-actions, devops)_
- **Define explicit negative scope in descriptions** - \*\*Scope:\*\* .github/pull*request_template.md Including an 'Out of Scope' section in pull requests prevents scope creep during review and maintains focus on bisectable changes. *(github, process, documentation)\_
- **Git post-checkout hooks receive a string of forty zeros** - Git post-checkout hooks receive a string of forty zeros as the previous SHA during an initial clone or checkout. Hook scripts must explicitly handle this null-SHA case to prevent failures in commands like git diff that require valid object references. _(git, hooks, bash)_
- **Restrict Zod validation to external or untrusted inputs;** - Restrict Zod validation to external or untrusted inputs; use simple type assertions for small internal CLI structures to reduce complexity and startup latency. _(typescript, validation)_
- **Consolidating enforcement logic from disparate commands** - Consolidating enforcement logic from disparate commands into a shared runner ensures that architectural rules are applied consistently across different entry points. This reduction in code duplication simplifies maintenance and prevents drift between similar CLI features. _(refactoring, architecture, dry)_
- **Relying on error name strings for matching is fragile** - Relying on error name strings for matching is fragile if underlying error classes or naming conventions change. Using instanceof combined with specific error codes provides a more robust and type-safe way to branch logic for expected failures. _(typescript, error-handling)_
- **Sanitize user-provided text before persisting to files** - \*\*Pattern:\*\* \b(?:write|append)File(?:Sync)?\s\*\(\s\*['"][^'"]\*\.(?:md|log)['"]\s\*,\s\*(?![^,]\*\b(?:stripAnsi|sanitize|replace)\b)[^,)\s]+
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* error

Sanitize user-provided text before persisting to files. _(security, curated)_

- **Keep internal cache or flag filenames unchanged** - Keep internal cache or flag filenames unchanged during command renames to prevent breaking existing local state while updating user-facing logs. _(refactoring, compatibility)_
- **Static top-level imports from heavy internal packages delay** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Static top-level imports from heavy internal packages delay startup for every CLI invocation, including simple flags like --help. Moving these to dynamic await imports inside the command function ensures dependencies are only loaded when the specific command is executed. _(performance, cli, typescript)_
- **When a general best practice conflicts with an intentional** - When a general best practice conflicts with an intentional repository exception, the lesson should reference the tracking issue to prevent reviewers from flagging valid technical debt. _(documentation, process)_
- **Input sanitization must be applied to success logs** - Input sanitization must be applied to success logs and terminal feedback, not just persistent data stores, to prevent terminal injection attacks via user-controlled strings. _(security, cli)_
- **Markdown field extractors should allow zero-length matches** - Markdown field extractors should allow zero-length matches to ensure that present but empty headings are explicitly detected and validated rather than ignored. _(regex, parsing, markdown)_
- **Standardize catch block error naming** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Always capture catch block exceptions using the project-mandated 'err' variable name, even when the error is intentionally swallowed, to facilitate debugging. _(typescript, conventions)_
- **Wrap store count queries in try-catch blocks during sync** - Wrap store count queries in try-catch blocks during sync flows to prevent non-critical reporting failures from crashing an otherwise successful ingestion. _(resilience, lancedb)_
- **Use 'set -f' (noglob) when passing cached glob patterns** - Use 'set -f' (noglob) when passing cached glob patterns to git commands to prevent the shell from expanding them into local filenames before Git processes the pathspec. _(git, shell, security)_
- **Ensure SARIF parity for standalone binaries** - \*\*Scope:\*\* packages/cli/src/index-lite.ts The `totem-lite` binary must support the same `--format sarif` flag as the main CLI to provide consistent CI integration in environments without Node.js. _(ci-cd, cli)_
- **Prefer negative filters for compatibility** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Using negative filters like `!== 'archived'` instead of positive ones like `=== 'active'` ensures that legacy records lacking the new status field remain functional by default. _(typescript, architecture, migration)_
- **Ensure monorepo exclusions are root-relative** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts Path exclusions for tools like `git ls-files` fail in monorepo subpackages if they are not relative to the repository root. Defer path computation until the repo root is resolved to ensure consistent behavior across different package depths. _(monorepo, git, path-resolution)_
- **Standard markdown labels often place the colon inside** - Standard markdown labels often place the colon inside the bold markers (e.g., \*\*Pattern:\*\*), which differs from standard programming key-value formats. Parsers must account for delimiters appearing before formatting tokens to avoid capture failures on common bolding patterns. _(markdown, regex, parsing)_
- **Memory protection limits must be applied consistently** - Memory protection limits must be applied consistently to all external files being ingested, regardless of their location or extension. Neglecting root-level configuration files while guarding subdirectory files creates an inconsistent security posture and potential out-of-memory vectors. _(nodejs, performance, security)_
- **Differentiate engine unavailability from general errors** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* When catching initialization failures for optional engines, verify the error message contains engine-specific identifiers like 'WASM'. Blindly catching all errors as 'unavailable' can mask unrelated architectural defects. _(error-handling, wasm)_
- **Automated hook upgrades should target specific delimited** - Automated hook upgrades should target specific delimited blocks rather than overwriting the entire file to avoid destroying custom user logic or other hook managers. _(git-hooks, dx)_
- **Frontmatter delimiters must be anchored to the start** - Frontmatter delimiters must be anchored to the start of the line to prevent '---' sequences within YAML scalars from being misinterpreted as the end of the block. _(regex, parsing, yaml)_
- **Sanitize untrusted diffs in prompts** - \*\*Scope:\*\* packages/cli/src/commands/extract-templates.ts Code diffs included in LLM prompts must be treated as untrusted input and sanitized to prevent prompt injection. Developers might intentionally or accidentally include instruction-like text in comments or strings within a diff that could hijack the model's behavior. _(llm, security)_
- **2026-03-06T09:08:26.567Z** - \*\*Pattern:\*\* "(hook|PreToolUse|command|scripts?)":\s\*\"[^\"]\*(\\||\\b(grep|awk|sed|xargs)\\b|&&)[^\"]\*\"
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*.json
  \*\*Severity:\*\* error

Hook configurations must not contain shell injection patterns (pipes, grep, etc.). _(architecture, curated)_

- **CLI command actions must wrap asynchronous logic** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts CLI command actions must wrap asynchronous logic in a try/catch block that delegates to a centralized error handler. This ensures consistent error reporting across the tool and prevents unhandled promise rejections during dynamic imports or async operations. _(cli, error-handling, nodejs)_
- **Manually suppress "unused export" errors in styleguide** - \*\*Pattern:\*\* ^\+?\s\*export\b(?!.\*eslint-disable)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/styleguide/\*\*/\*.ts, \*\*/styleguide/\*\*/\*.tsx, \*\*/styleguide/\*\*/\*.js, \*\*/styleguide/\*\*/\*.jsx, \*\*/\*.styleguide.ts, \*\*/\*.styleguide.tsx, \*\*/\*.styleguide.js, \*\*/\*.styleguide.jsx
  \*\*Severity:\*\* warning

Manually suppress "unused export" errors in styleguide. _(style, curated)_

- **When loading optional configuration or cache files,** - When loading optional configuration or cache files, differentiate between `ENOENT` (missing file) and validation or corruption errors. This allows the system to silently initialize defaults for missing files while still reporting actionable warnings to the user when existing files are unreadable. _(nodejs, error-handling, validation)_
- **Lazy-load core libraries in CLI commands** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Static imports of core libraries in CLI command files delay startup; use dynamic imports within handlers to ensure the CLI remains responsive. _(performance, cli, typescript)_ _(archived: Hallucinated package name. Pattern references `@mcp-b/core`, which does not exist in this repository (the canonical core package is `@mmnto/totem`). Rule would never fire on any real code in the repo. Auto-compiled on the 2026-04-11 PM postmerge. Archived via the mmnto/totem#1345 filter. Kept in the ledger as a LLM hallucination data point: the compile worker drifted to a fabricated package name despite the source lesson referencing the correct `@mmnto/totem` import. Feeds the `quality > quantity` empirical record referenced in the Sonnet 4.6 routing analysis (Strategy #73).)_
- **Incremental logic must apply the same ignore patterns** - Incremental logic must apply the same ignore patterns as full-scan paths to prevent processing excluded files like lockfiles or vendored code. This ensures consistency between fast-path and standard review cycles. _(architecture, git, performance)_
- **Omit shell:true when spawn args are arrays** - Omit the `shell: true` option in `spawn()` calls when arguments are already provided as a parameterized array. Removing the shell layer eliminates shell injection vulnerabilities and reduces execution overhead. _(security, nodejs, subprocess)_
- **Lesson headings must be restricted to 60 characters** - Lesson headings must be restricted to 60 characters or fewer to function as stable, unique identifiers in SARIF reports. Exceeding this limit causes validation failures in automated analysis pipelines that rely on these identifiers for tracking violations over time. _(sarif, validation, documentation)_
- **Document implicit model tag resolutions** - \*\*Scope:\*\* docs/reference/supported-models.md When a configuration defaults to a base model name, explicitly document which specific variant the provider's 'latest' tag resolves to so benchmarks remain representative. _(llm, ollama, documentation)_
- **Stub all accessed dependency methods** - \*\*Scope:\*\* packages/cli/build/shims/lancedb.js When shimming a heavy dependency for a lite build, stub all methods called by the core (e.g., Index.fts()) to throw clear 'unsupported' errors instead of generic TypeErrors. _(architecture, dx)_
- **Preserve raw buffers in spawn errors** - \*\*Scope:\*\* packages/core/src/sys/\*\*/\*.ts, !\*\*/\*.test.\* Capture raw `stdout` and `stderr` buffers before trimming for human-readable messages to ensure programmatic consumers have access to the original, unmutated output. _(node, error-handling)_
- **Reporting malformed records via an onWarn callback instead** - Reporting malformed records via an onWarn callback instead of silent catch blocks allows debugging of corrupted NDJSON streams without interrupting the main execution flow. _(observability, telemetry)_
- **Diagnostic hints must precisely identify the underlying** - Diagnostic hints must precisely identify the underlying execution method, as execFileSync avoids the shell-parsing overhead and security risks associated with execSync. _(node, process, dx)_
- **Never use git add -A or git add .** - Never use `git add -A` or `git add .` when committing version bumps or release changesets. The working directory may contain agent worktree copies, runtime artifacts (ledger events, lock files), or cache files that should not be committed. Always stage specific files by name: `git add packages/\*/package.json packages/\*/CHANGELOG.md .changeset/`. \*\*Source:\*\* mcp (added at 2026-03-28T05:11:46.444Z) _(git, release, trap, worktree, ci)_
- **Ensure linting occurs as the final step of every small task** - Ensure linting occurs as the final step of every small task cycle rather than once at the end of a feature implementation. Frequent validation prevents linting errors from accumulating, which are significantly more time-consuming to resolve in bulk. _(workflow, linting, productivity)_
- **When implementing automatic recovery that deletes** - When implementing automatic recovery that deletes a database, ensure a failed deletion (e.g., due to OS file locks) doesn't recursively trigger the same healing logic. Wrapping the post-healing reconnection attempt in a try/catch that throws a distinct, terminal error prevents the system from entering a loop if the environment prevents the reset. _(recovery, error-handling, database)_
- **Guard parsers against hook format changes** - \*\*Scope:\*\* packages/cli/src/commands/install-hooks.test.ts When parsing multi-block git hooks in tests, use named constants for expected block counts to make termination logic explicit and prevent brittle failures as the hook format evolves. _(testing, git-hooks, clean-code)_
- **The LLM documentation generator consistently hallucinates** - The LLM documentation generator consistently hallucinates that issue #515 (Claude Code hooks for spec preflight and shield pre-push) was shipped and is a live feature. It was closed as not implemented. Every `totem docs` run re-introduces false references to #515. Manual verification of generated docs must check for this specific hallucination pattern. The hooks feature is tracked under #520 (automatic enforcement strategy) and has NOT been implemented. _(documentation, hallucination, totem-docs, shield-515, trap)_
- **Use totem-context for semantic lint overrides** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Prefer 'totem-context:' over generic ignore directives to provide inline rationale for lint suppressions, which helps document the 'why' behind the override. _(linting, documentation)_
- **Initialize working sets from existing data** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts Initialize working sets as a copy of existing data even during forced updates to prevent data loss if transient failures like network timeouts or rate limits occur mid-process. _(durability, cli)_
- **Batch telemetry-heavy operations to reduce cycles** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Consolidate multiple upgrade or compile targets into a single pass to avoid redundant N-cycle loads of configuration, rules, and metrics. _(performance, cli)_
- **Regex lint rules must exclude fenced code blocks** - # Regex lint rules must exclude fenced code blocks in markdown files ## What happened The "issue number" rule (`/#\d+/`) matched hex color codes like `#4b3a75` inside mermaid diagram code blocks in `README.md`, producing 4 false positive errors that blocked push. ## Root cause Regex-based lint rules run line-by-line without awareness of fenced code block context. Any pattern that matches common code syntax (hex colors, CSS selectors, shell comments) will false-positive inside markdown code blocks. ## Rule When writing regex lint rules that could match inside code examples, either: 1. Scope the rule to exclude `\*.md` files 2. Add the file to `ignorePatterns` if it's a marketing/docs file 3. Consider adding fenced-block awareness to the lint engine `// totem-context:` suppresses both lint and shield in code files, but markdown has no line-comment syntax so it cannot be used there. Use `ignorePatterns` for markdown exclusions. \*\*Example Hit:\*\* `classDef observe fill:#4b3a75,stroke:#9b72cf` — hex colors match `#\d+` \*\*Example Miss:\*\* `Closes #1026` — actual issue reference, should match \*\*Source:\*\* mcp (added at 2026-03-27T19:55:45.579Z) _(lint, regex, markdown, false-positive, code-blocks)_
- **Deliberately export internal constants so co-located test** - Deliberately export internal constants so co-located test files can assert against them without requiring complex mocking or duplication. _(testing, architecture)_
- **Require mechanical root cause in PRs** - \*\*Scope:\*\* .github/pull*request_template.md Mandating a 'Mechanical Root Cause' section forces authors to describe the underlying mechanism rather than just symptoms, which improves architectural clarity and prevents stale context. *(github, process, documentation)\_
- **Swallowing errors within internal validation checks (like** - Swallowing errors within internal validation checks (like schema or dimension validation) prevents top-level handlers from identifying database corruption. Propagating these errors allows a unified connection handler to identify "healable" states and consistently decide when to trigger a full index reset. _(database, architecture, error-handling)_
- **Standard string length checks like .min(1) fail to catch** - Standard string length checks like `.min(1)` fail to catch whitespace-only inputs, which can lead to empty-looking entries in data stores. Always apply `.trim()` before length assertions in Zod schemas to ensure meaningful content is provided. _(validation, zod, dx)_
- **Guard against broad error swallowing** - \*\*Scope:\*\* packages/core/src/ast-grep-wasm-shim.test.ts In async import tests, inspect caught errors to only swallow expected environment-specific failures while re-throwing actual regressions or unexpected import errors. _(testing, wasm, typescript)_
- **Shell execution wrappers that automatically trim output** - Shell execution wrappers that automatically trim output must check result types before processing. Commands using 'inherit' or 'ignore' stdio may return undefined or Buffers, causing runtime errors if string methods are called directly. _(shell, nodejs)_
- **In systems where content hashes are derived from headings,** - In systems where content hashes are derived from headings, updating a heading to improve readability will break downstream mappings and external references. If headings are used as identifiers, plan for a migration strategy before performing bulk style updates. _(identifiers, hashing, maintenance)_
- **Strictly anchor IP and domain regexes** - \*\*Scope:\*\* packages/pack-agent-security/compiled-rules.json Security rules matching IPs or domains must use boundary guards (e.g., [^\w-]) rather than simple substrings to prevent partial matches or false positives from sibling domains. _(security, regex)_
- **Bump major version for discriminated unions** - \*\*Scope:\*\* .changeset/\*.md Changing a response shape to a discriminated union is a breaking change for consumers. Release changesets must reflect a major version bump to prevent runtime failures in downstream clients. _(mcp, versioning, api-design)_ _(archived: Pattern '^['\"]?[\w@/-]+['\"]?:\s\*(patch|minor)\s\*$' fires on EVERY routine changeset entry, not just discriminated-union changes. Lesson's intent was discriminated-union-as-breaking-change but the regex captures all minor/patch bumps; would generate massive false-positives on any changeset PR. Archive pending pattern-tightening to detect actual discriminated-union shape changes (likely needs ast-grep against TS source, not regex against changeset MD).)_
- **Prevent data loss during partial compiles** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts When implementing a single-item 'upgrade' flow, ensure the logic doesn't truncate the global collection or overwrite the persistence file with only the partial result. Global flags or array truncations used for targeting can lead to catastrophic data loss of the rest of the collection during the save phase. _(cli, persistence, safety)_
- **Do not replace Zod validation with static type assertions** - Do not replace Zod validation with static type assertions for untrusted inputs; assertions provide zero runtime safety and can lead to security vulnerabilities. _(security, typescript)_
- **Avoid diff archaeology during voice refreshes** - Writing fresh copy instead of restoring old wording prevents the re-introduction of discarded tones or corporate jargon during documentation updates. _(documentation, process)_
- **Applying '// totem-ignore' within code-like string fixtures** - Applying '// totem-ignore' within code-like string fixtures prevents the compiler from aggressively flagging intentional test data as errors or linting violations. _(testing, linting)_
- **Implement cleanup for database connections** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Even if a store currently lacks a close method, wrapping connections in try-finally blocks with feature-detection for cleanup methods prevents resource exhaustion in long-running processes. _(database, resources)_
- **Refactor rule engines to surface warnings via callbacks** - Refactor rule engines to surface warnings via callbacks when files are skipped because they reside outside the project directory. This improves transparency by preventing silent failures when rules are unexpectedly not applied to target files. _(rule-engine, debugging, observability)_
- **When re-throwing errors in a CLI orchestrator, always** - \*\*Pattern:\*\* throw\s+new\s+Error\(\s\*['"\`](?![^'"\`]\*\[Totem Error\])
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/\*\*/\*.ts
  \*\*Severity:\*\* warning

When re-throwing errors in a CLI orchestrator, always. _(style, curated)_

- **Specific numbers are more persuasive than vague qualitative** - Specific numbers are more persuasive than vague qualitative claims in documentation, even if they require manual updates. Tangibility is often more valuable for building user trust than maintaining "perfect" hygiene through generalized phrasing. _(documentation, positioning, maintenance)_
- **Manual content injection must be scoped to the README** - Manual content injection must be scoped to the README to prevent "source of truth" ambiguity across generated files. Duplicating sections across multiple markdown files creates maintenance overhead and is currently a known bug in the `totem docs` generator. _(documentation, maintenance, totem-docs)_
- **Prefer engine execution for citations** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Run the full rule engine instead of simple glob matching when predicting findings to ensure accurate file:line citations and severity levels. _(architecture, dx)_
- **Audit root cause helpers for vulnerabilities** - \*\*Scope:\*\* global When a security vulnerability is identified in a specific file, extend the audit to the lowest-level helper enabling that behavior. Fixing the symptom in one file leaves other call sites using the same helper exposed. _(security, process)_
- **Write manifests before main execution logic** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts Writing the state manifest before invoking the primary sync logic ensures the local resolution state is updated even when the secondary phase is short-circuited. _(orchestration, cli)_
- **Pure core utilities may use empty catch blocks** - Pure core utilities may use empty catch blocks as a last-resort safety net if validation occurs upstream and the package lacks logging dependencies. _(typescript, error-handling)_
- **Prefer totem-context on the preceding line; totem-ignore only works same-line** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Both `totem-ignore` (substring match) and `totem-context:` (with justification) suppress lint rules when placed on the same line as the violation. On the preceding line, the engine only honors `totem-ignore-next-line` or `totem-context:` — a plain `// totem-ignore:` on the preceding line does NOT suppress the next line. Prefer `// totem-context: <reason>` inline so both same-line and adjacent-line cases work; reserve `// totem-ignore` for same-line use without justification. _(dx, totem)_
- **Windows requires shell:true for git binary resolution** - \*\*Pattern:\*\* execFileSync\s\*\(\s\*['"]git['"](?![^)]\*shell:\s\*(?:true|IS_WIN))
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* warning

Windows requires shell:true for git binary resolution. _(architecture, curated)_

- **Git's porcelain output uses C-style escaping for paths** - Git's porcelain output uses C-style escaping for paths containing special characters or quotes. These must be explicitly decoded (e.g., handling backslashes and quotes) to obtain the actual filesystem path. _(git, parsing)_
- **Lazy load CLI display templates** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Use dynamic imports for display tags and templates inside command handlers to keep the CLI startup graph lightweight. Static imports of these constants can degrade performance by loading unnecessary modules during entry point initialization. _(cli, performance, dx)_
- **When outputting text sourced from external files, PR** - When outputting text sourced from external files, PR content, or LLMs to the terminal, use sanitization functions to prevent terminal injection attacks. This prevents malicious content from executing escaped sequences that could manipulate the terminal state or compromise the user's environment. _(security, cli, terminal)_
- **Use deterministic mutually exclusive checkboxes** - \*\*Scope:\*\* .github/pull*request_template.md Replacing ambiguous checklist items with mutually exclusive options (e.g., 'Tests added' vs 'N/A with explanation') ensures a deterministic signal for reviewers and automation. *(github, dx, automation)\_
- **2026-03-05T04:05:14.473Z** - \*\*Pattern:\*\* JSON\.parse\(.\*(exec|spawn|stdout|stderr)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, !\*\*/\*.test.ts, !\*\*/\*.spec.ts
  \*\*Severity:\*\* error

Do not JSON.parse raw stdout/stderr from child processes without error handling. _(architecture, curated)_

- **Implement per-item catch in batch pipelines** - \*\*Scope:\*\* packages/cli/src/commands/recurrence-stats.ts Use per-PR catch blocks in history-scanning pipelines to ensure transient errors or rate limits on a single item do not abort the entire multi-PR analysis. _(resilience, github-api)_
- **Following ADR-027, autonomous self-healing systems** - Following ADR-027, autonomous self-healing systems should downgrade rule severity (e.g., error to warning) rather than deleting them. This preserves architectural history and intent while resolving immediate developer friction from noisy rules. _(architecture, automation)_
- **Block leading hyphens in Git ranges** - \*\*Scope:\*\* packages/core/src/sys/git.ts Validate that user-provided Git ref ranges do not start with a hyphen to prevent flag injection, even when using safe execution with argument arrays. _(git, security)_
- **Enforce structural compilation over context escapes** - \*\*Scope:\*\* packages/cli/src/commands/compile-templates.ts Compilation must succeed if structural combinators can express the guard, preventing the LLM from using 'context-required' as an escape hatch for complex patterns. _(llm, compiler, ast-grep)_
- **Maintain air-gapped enforcement invariant** - \*\*Scope:\*\* README.md The core enforcement layer must remain network-independent to ensure it can run natively in air-gapped environments without source code exfiltration. _(security, architecture)_
- **Registry updates should occur after pruning to ensure** - Registry updates should occur after pruning to ensure metrics like total chunk counts reflect the final state of the database. _(cli, consistency)_
- **Avoid premature task-specific model overrides** - \*\*Scope:\*\* packages/cli/src/commands/init-detect.ts Do not automatically configure specialized model variants (e.g., large 26b models) during initialization if they aren't guaranteed to be present on the user's machine. Deferring complex routing to a dedicated orchestrator prevents friction caused by missing local dependencies. _(orchestration, llm, config)_
- **Differentiate filesystem errors from syntax errors** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Throw on filesystem permission errors to prevent silent failures, but swallow JSON syntax errors during best-effort cleanup tasks like ejection to allow the process to continue. _(error-handling, fs, json)_
- **Initialize WASM engines lazily** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Top-level WASM initialization adds overhead to every CLI command, including `help`. Move initialization to specific command handlers to improve startup performance and prevent unnecessary failures. _(performance, wasm, dx)_
- **Use dynamic import() within CLI command handlers instead** - Use dynamic `import()` within CLI command handlers instead of top-level static imports to minimize startup latency and improve responsiveness. _(cli, performance)_ _(archived: Over-broad: astGrepPattern `import $NAME from '$MODULE'` fires on every top-level default import across packages/cli/\*\*. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Understand STRATEGY_ROOT resolution order** - \*\*Scope:\*\* docs/wiki/cross-repo-mesh.md The strategy resolver prioritizes environment variables, then configuration files, then sibling directories, with legacy submodules as the final fallback. _(configuration, architecture)_
- **When surfacing findings from bot review bodies, they** - When surfacing findings from bot review bodies, they must be deduplicated against inline comments to prevent redundant reporting of the same issue in the UI. _(github, automation)_
- **Lesson headings must not exceed 60 characters** - Lesson headings must be strictly limited to 60 characters because they serve as unique identifiers in SARIF output formats. Maintaining this precise technical constraint ensures compatibility with static analysis reporting standards. _(sarif, validation)_
- **Enforce exclusivity for manifest refresh** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts Enforce strict exclusivity between --refresh-manifest and --force because refreshing assumes the current state is authoritative while forcing a recompile explicitly invalidates it. _(cli, logic)_
- **Thread context to isolate concurrent state** - \*\*Scope:\*\* packages/core/src/rule-engine.ts Replacing module-level variables with a threaded context prevents state bleeding, such as deprecation warning latches, across concurrent or federated evaluations. _(concurrency, state-management)_
- **Evaluate breaking changes by consumer impact** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.ts Structural payload changes can be treated as minor if the success path is additive and the data is primarily consumed as human-rendered text rather than programmatic JSON. _(versioning, api-design)_
- **External submodules used as consumer sandboxes should be** - External submodules used as consumer sandboxes should be added to project-specific ignore patterns. This prevents analysis and linting tools from incorrectly processing external code as part of the primary repository's source. _(git, submodules, configuration)_
- **Restricting dynamic imports to CLI command entry points** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Restricting dynamic imports to CLI command entry points allows utility and adapter layers to use standard top-level imports. Overly broad security rules force developers into unnecessary workarounds that degrade code readability without improving safety. _(security, architecture, cli)_ _(archived: Globs `packages/cli/src/\*\*/\*.ts, !packages/cli/src/commands/\*\*/\*.ts` are over-broad: they match the CLI root entry files packages/cli/src/index.ts and index-lite.ts, which is precisely where ADR-072 §3 (PR #945) places lazy-loads of command handlers. Rule fires on every canonical `const { cmd } = await import('./commands/foo.js')` line in the two CLI bin entry files. Canonical utility-layer coverage retained via rules a1fd35ee696110b0 (utils/adapters/lib) and f6739f9ad356067a (utils/lib/helpers), which use correctly narrow globs. Archived via #1517.)_
- **Use unit separators for Git parsing** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.ts, !\*\*/\*.test.\* Avoid using common characters like pipes as delimiters in Git log output, as they can collide with commit titles. Use non-printable unit separators to ensure robust parsing of user-generated content. _(git, parsing)_
- **Guard against future exception wrapping changes** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* When catching wrapped errors (like custom exceptions wrapping ENOENT), include a fallback for the raw underlying error. This prevents silent failures if future refactors change how low-level system errors are wrapped or surfaced. _(error-handling, typescript, resilience)_
- **Consolidate dynamic imports in CLI handlers** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Destructure all required helpers from a single dynamic import at the top of the handler to improve performance and avoid contradictory linting rules. _(cli, dx, performance)_ _(archived: Pattern `const { $VAR } = await import($MODULE)` matches every dynamic import in the CLI package, not just cases where multiple dynamic imports could be consolidated. The underlying lesson was about consolidating multiple dynamic-import destructures into a single call, but the rule does not encode the multiplicity condition. Would produce thousands of false positives on every CLI command file. Auto-compiled on the 2026-04-11 PM postmerge. Archived via the mmnto/totem#1345 filter. Kept in the ledger as an example of the compile worker producing a syntactically valid but semantically broken generalization.)_
- **Always close file descriptors in finally blocks** - Always close file descriptors in finally blocks when spawning detached child processes to prevent resource leaks if the spawn operation itself throws an error. _(node, fs, performance)_
- **Lazy load heavy CLI command dependencies** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Use dynamic `await import()` inside CLI handlers to load heavy core logic only when the command is executed. This prevents slow startup times caused by parsing unused dependencies during initial CLI boot. _(cli, performance)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 301 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: .claude/hooks/session-context.js, packages/cli/build/esbuild-lite.mjs, packages/cli/src/adapters/gh-utils.test.ts, packages/cli/src/adapters/gh-utils.ts, packages/cli/src/adapters/github-cli-pr.test.ts (+ 296 more). reasonCode: stage4-out-of-scope-match.)_
- **CLI command entrypoints should catch validation errors** - CLI command entrypoints should catch validation errors and print clean, user-facing messages instead of throwing raw JavaScript errors. Reserve throwing for internal library functions to ensure the CLI remains professional and user-friendly. _(cli, error-handling)_
- **Prefer Error cause over concatenation** - \*\*Scope:\*\* packages/core/src/sys/git.ts When re-throwing errors, use the 'cause' property instead of string concatenation to preserve the original error context and satisfy style guidelines. _(typescript, error-handling)_ _(archived: Duplicate of db1a795f — same astGrepPattern (new Error($MSG + $ERR)), same fileGlobs (packages/core/src/sys/git.ts), same goodExample shape (cause property). Two related lessons from the same PR (mmnto-ai/totem#1727 / mmnto-ai/totem#1729) compiled into structurally identical rules. Keeping db1a795f as the canonical.)_
- **When fetching with a limit across multiple sources,** - When fetching with a limit across multiple sources, applying the limit to each source before merging results in up to limit \\\* N items. Truncate the final sorted array to ensure the output strictly honors the user's requested limit. _(api, aggregation, logic)_
- **Implement case-insensitive matching for unique identifiers** - Implement case-insensitive matching for unique identifiers and filters (like hashes) to improve command-line ergonomics. This prevents "not found" errors caused by inconsistent casing when users copy-paste IDs from different UI contexts. _(ux, cli, searching)_
- **Documenting a problem is insufficient for effective** - Documenting a problem is insufficient for effective guidance; every architectural lesson should include an explicit "Fix:" instruction. This transitions the documentation from a list of warnings to an actionable checklist that guides resolution. _(documentation, dx, patterns)_
- **Classify additive schema changes as minor** - A breaking schema change can be downgraded to a minor bump if the success path remains additive and the field is consumed as rendered text rather than parsed JSON. This prevents devaluing major version signals for isolated changes with negligible programmatic impact. _(semver, schema, api-design)_
- **Issue numbers are only unique within a single repository;** - Issue numbers are only unique within a single repository; when aggregating multiple sources, use qualified syntax like owner/repo#number. This prevents CLI commands from accidentally targeting the wrong issue when numbers collide across configured projects. _(github, multi-repo, ux)_
- **Pass generated outputs through a schema or sorter to ensure** - Pass generated outputs through a schema or sorter to ensure consistent property ordering across runs. This prevents unnecessary Git diff noise caused by non-deterministic field ordering in automated commits. _(git, dx, json)_
- **Auto-generated rules can contain empty patterns** - Auto-generated rules can contain empty patterns or incorrect severity levels that trigger false-positive CI failures. A manual audit or validation step is required between rule compilation and enforcement to prevent systemic noise. _(linting, automation, ci-cd)_
- **Ensure resilient continuation in session hooks** - \*\*Scope:\*\* .claude/hooks/\*\*/\*.js, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Session-start hooks must use `process.stderr.write` and continue instead of throwing in inner catch blocks. This ensures the session boot never crashes and allows the agent to function with partial context if specific data sources fail. _(architecture, hooks, error-handling)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 38 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: .gemini/hooks/BeforeTool.js, packages/cli/src/adapters/gh-utils.ts, packages/cli/src/commands/compile.ts, packages/cli/src/commands/doctor.ts, packages/cli/src/commands/first-lint-promote-runner.ts (+ 33 more). reasonCode: stage4-out-of-scope-match.)_
- **GitHub Actions shell injection via template expressions** - \*\*Pattern:\*\* (?:^\s\*-?\s\*run\b|^(?!\s\*[\w-]+:\s)\s+).\*\$\{\{\s\*(github\.event|inputs)\..\*\}\} \*\*Engine:\*\* regex \*\*Scope:\*\* .github/workflows/\*.yml, .github/workflows/\*.yaml \*\*Severity:\*\* error GitHub Actions shell injection via template expressions. _(security, curated)_
- **Try local branch references before remote-tracking ones** - Try local branch references before remote-tracking ones (origin/branch) when calculating diffs to maintain consistency, unless a full audit of stale merge-base risks is performed. _(git, architecture)_
- **When transitioning schemas, the parser should only commit** - When transitioning schemas, the parser should only commit to the new format if validation succeeds, falling back to legacy parsing on failure to prevent data loss or breakage. _(architecture, parsing, resilience)_
- **Verify daemon status for local services** - \*\*Scope:\*\* packages/cli/src/commands/init-detect.ts Checking for a CLI on the PATH is insufficient for functional readiness of local LLM providers; verify the server is actually running via a heartbeat check before auto-configuring it as a dependency. _(cli, ollama, dx)_
- **Warnings should include the same rich metadata (such** - Warnings should include the same rich metadata (such as regex patterns and lesson headings) as error messages to remain actionable. Restricting detailed context to only "blocking" errors makes warnings harder to debug and resolve. _(cli, ux, maintainability)_
- **Setting open-pull-requests-limit to 0 in dependabot.yml** - \*\*Pattern:\*\* open-pull-requests-limit\s\*:\s\*['"]?[1-9]\d\*['"]?
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* .github/dependabot.yml
  \*\*Severity:\*\* error

Setting open-pull-requests-limit to 0 in dependabot.yml. _(architecture, curated)_

- **Static top-level imports from heavy core packages** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Static top-level imports from heavy core packages can significantly slow down CLI startup for every command, including help flags. Using dynamic `await import()` inside the specific command's execution function ensures that resource-intensive dependencies are only loaded when required. _(performance, cli, nodejs)_
- **When masking secrets with assignment patterns, use capture** - When masking secrets with assignment patterns, use capture groups and a replacer function to redact only the sensitive value. Replacing the entire regex match removes the key and assignment syntax, making the resulting data harder to categorize or debug. _(regex, security, typescript)_
- **Place invariants and test requirements directly** - Place invariants and test requirements directly within individual implementation tasks rather than at the top of a specification. This ensures critical constraints remain in the AI agent's active context window at the exact moment of execution. _(prompt-engineering, ai-agents, context-window)_
- **Bias prompts toward structural patterns** - \*\*Scope:\*\* packages/cli/src/commands/compile-templates.ts Prioritizing ast-grep in system prompts and providing a syntax cheat sheet prevents LLMs from defaulting to brittle regex for structural code analysis. _(prompt-engineering, ast-grep, regex)_
- **Isolate per-item errors in batch processing** - \*\*Scope:\*\* packages/core/src/first-lint-promote.ts Wrap individual task execution in try-catch blocks during batch processing to prevent a single failure from aborting the entire operation. _(patterns, reliability)_
- **LLMs are unreliable for calculating precise line proximity;** - LLMs are unreliable for calculating precise line proximity; implementing deduplication in a deterministic language like TypeScript ensures consistent results for overlapping comments. _(llm, typescript, deduplication)_
- **Explicitly validate the existence of embedder** - Explicitly validate the existence of embedder configurations in linked projects before attempting a connection to prevent runtime crashes. In multi-repo environments, you cannot assume all linked nodes share the same maturity level or configuration requirements. _(configuration, validation, embeddings)_
- **Synchronize manifest metadata during cache pruning** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* When rewriting a data file due to a cache drain, the corresponding manifest must be updated with new hashes and counts to maintain state consistency. _(cli, metadata, provenance)_
- **Unified-diff prefixes (like '+', '-', or ' ') must be** - Unified-diff prefixes (like '+', '-', or ' ') must be stripped from source lines before synthesizing regex patterns to ensure the resulting rules match actual source code rather than patch hunks. _(compiler, regex, git)_
- **Regex patterns designed to protect code blocks must include** - Regex patterns designed to protect code blocks must include tilde fences (`~~~`) alongside standard backticks (```). Overlooking tilde fences leads to the accidental transformation of code content that the developer intended to preserve. _(markdown, regex, parsing)_
- **Normalize signatures for cross-PR clustering** - \*\*Scope:\*\* packages/core/src/recurrence-stats.ts Stripping paths, line references, code fences, and URLs from finding bodies creates stable signatures for clustering recurring issues across different PR contexts. _(clustering, normalization)_
- **Static analysis tools should read file content using git** - Static analysis tools should read file content using `git show :path` to access the staged index version rather than the local disk. This ensures the analysis accurately reflects the actual commit content and ignores unstaged "dirty" changes. _(git, ast, static-analysis)_
- **Manual re-implementation of domain object transformations** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Manual re-implementation of domain object transformations (e.g., mapping internal Violations to TotemFindings) creates maintenance risk and logic drift. Use canonical transformation functions from core packages instead of local mapping logic. In CLI contexts, use dynamic imports (await import) to bridge package boundaries while maintaining performance and a single source of truth. _(architecture, typescript, monorepo)_
- **Instead of hardcoding .git/hooks, use 'git rev-parse** - Instead of hardcoding .git/hooks, use 'git rev-parse --git-path hooks' to support custom hook paths and worktrees correctly. _(git, cli)_
- **To support mixed file formats in a single directory, use** - To support mixed file formats in a single directory, use presence-checks for "signature fields" (like `\*\*Pattern:\*\*`) to trigger specific validation gates. This allows specialized metadata checks for one format without causing false-positive failures in other valid but differently-structured files. _(architecture, validation, linting)_
- **Silent skipping of files during path traversal containment** - Silent skipping of files during path traversal containment checks causes confusion and hides configuration issues. Providing an optional warning callback ensures visibility into excluded files without coupling library logic to specific logging frameworks. _(security, logging, path-traversal)_
- **A confirmation prompt for LLM-generated writes** - A confirmation prompt for LLM-generated writes is an insufficient safeguard if it only identifies the target file path. Users require a bounded diff or content preview to make an informed decision and prevent the accidental write of incorrect or low-quality content. _(ux, safety, llm)_
- **Include trailing glob when overriding Turbo inputs** - \*\*Scope:\*\* turbo.json In Turbo v2, defining an 'inputs' array for a task overrides the default package-level file hashing entirely. You must include a trailing '\*\*' to ensure that changes to local package source code still invalidate the cache. _(turbo, monorepo, ci)_
- **Align exclusion paths with scanner output roots** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Exclusion paths must be resolved relative to the same root as the scanner output (e.g., `repoRoot` for `git ls-files`). Using `configRoot` or `cwd` in monorepos causes path mismatches and false-positive matches. _(git, monorepo, paths)_
- **When detecting markers in user-authored files, use** - When detecting markers in user-authored files, use line-start regex (`/^marker/m`) instead of simple string search. This prevents file corruption during migration if a user happens to include the marker string within their content body. _(regex, parsing, migration)_
- **Core library modules should use optional callbacks** - Core library modules should use optional callbacks like onWarn instead of hardcoded console methods to remain agnostic of the execution environment. _(architecture, logging)_
- **Wrap fallback instructions or meta-commentary in XML tags** - Wrap fallback instructions or meta-commentary in XML tags like <context*note> to maintain structural consistency with other data blocks and reduce LLM parsing ambiguity. *(llm, prompt-engineering, xml)\_
- **Sanitize untrusted PR content by escaping closing tags** - Sanitize untrusted PR content by escaping closing tags to prevent attackers from breaking out of XML envelopes and injecting malicious instructions. This is critical when processing metadata from external authors. _(security, xml)_
- **Ensure new context variables like configRoot are propagated** - Ensure new context variables like configRoot are propagated to all nested orchestrator and utility calls. Failure to thread this context causes silent fallbacks to CWD, leading to inconsistent cache resolution in sub-commands like shield. _(architecture, refactoring, cache)_
- **README and curated wiki pages must never be LLM-generated** - # README and curated wiki pages must never be LLM-generated ## What happened The `totem docs` command was configured to regenerate README.md. The LLM output consistently failed to match the handcrafted "NASA-by-Google" marketing tone, introduced stale pinned content, and weakened the sales pitch. The README was removed from the `docs` array in totem.config.ts to protect it. ## Rule Protected documents (README.md, workflow wiki pages, COVENANT.md, CHANGELOG.md) must be handcrafted and explicitly excluded from `totem docs` LLM generation. Only forward-looking tracker documents (roadmap.md, active*work.md) should be LLM-maintained. Use `docs:inject` (deterministic) for values like rule counts and CLI tables. \*\*Source:\*\* mcp (added at 2026-03-27T21:24:30.029Z) *(documentation, readme, totem-docs, deterministic, strategy)\_
- **Validate JSON shapes during configuration scrubbing** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Perform defensive shape validation on parsed JSON (e.g., checking if roots are objects) before manipulation to ensure the CLI degrades gracefully instead of crashing on unexpected structures. _(json, defensive-programming)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 43 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/build/esbuild-lite.mjs, packages/cli/src/commands/add-secret.test.ts, packages/cli/src/commands/compile-refresh-manifest.test.ts, packages/cli/src/commands/config-drift.test.ts, packages/cli/src/commands/config.test.ts (+ 38 more). reasonCode: stage4-out-of-scope-match.)_
- **Validate mutually exclusive LLM output fields** - \*\*Scope:\*\* packages/core/src/compiler-schema.ts Use Zod `superRefine` to enforce mutual exclusivity between success flags and error metadata, preventing ambiguous model responses that pair patterns with reason codes. _(zod, validation, llm)_
- **Silently ignoring Git checkout errors in cleanup blocks** - Silently ignoring Git checkout errors in cleanup blocks can leave users stranded on temporary branches without notice. Always log a warning with recovery instructions if a branch restoration fails during a command's finalization. _(git, ux, cli)_
- **Inherit stdio for startup hooks** - \*\*Scope:\*\* .gemini/hooks/\*.js, packages/cli/src/commands/init-templates.ts Using `pipe` for child process stdio in hooks can swallow output if the command logs to stderr. Use `inherit` to ensure startup context actually reaches the agent session terminal. _(node, cli, dx)_ _(archived: Over-matching: pattern targets the string-shorthand form `stdio: 'pipe'` but the defect it was generalized from used the array form `stdio: ['ignore', 'pipe', 'pipe']`, so the regex does not match the actual bug sites in .gemini/hooks/SessionStart.js or init-templates.ts. `stdio: 'pipe'` is also a legitimate Node.js pattern when the caller wants to capture stdout via execSync's return value. The lesson is valid guidance but the structural rule form cannot express it without false positives; revisit as an astGrepYamlRule compound rule after ADR-091 Stage 4 Codebase Verifier ships.)_
- **Distinguish CLI existence from service availability** - \*\*Scope:\*\* packages/cli/src/commands/init-detect.ts Checking for a binary on the PATH confirms installation but not that the local service is active. For a true zero-config experience, use lightweight API pings (like a HEAD request) to verify the service is reachable before configuring it as a default. _(cli, ollama, dx)_
- **Using input strings as Map keys in batch processing** - Using input strings as Map keys in batch processing functions causes data loss when duplicate inputs are provided. Returning an array of results mapped to input indices ensures every call is uniquely handled and preserved. _(architecture, api-design, typescript)_
- **When forbidding a native module or pattern, the rule** - When forbidding a native module or pattern, the rule must explicitly exclude the directory containing the approved wrapper implementation. This prevents circular linting failures while enforcing the pattern across the rest of the codebase. _(architecture, linting)_
- **Throw on undefined in canonical serialization** - \*\*Scope:\*\* packages/core/src/compile-manifest.ts Canonical stringification should throw on undefined to prevent silent data drift in hashing pipelines, adhering to the 'Fail Loud' architectural principle. _(json, hashing)_ _(archived: Over-broad: pattern JSON.stringify($OBJ) matches any single-argument JSON.stringify call in compile-manifest.ts, including the legitimate primitive-serialization call inside canonicalStringify itself (line 103). The lesson intent is specifically about the canonicalStringify function, not all JSON.stringify calls in the file. upgradeTarget: compound (Proposal 226) — a compound rule with inside: function canonicalStringify(...) { $$$ } could constrain the pattern to calls that bypass canonicalStringify, catching the real anti-pattern without firing on the helper's own implementation. Phase 4 recompile candidate once #1408 and #1409 ship.)_
- **The use of dynamic imports inside CLI command handlers** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts The use of dynamic imports inside CLI command handlers ensures that heavy dependencies and core logic are only loaded when that specific command is executed. This architectural pattern prevents unnecessary overhead and maintains a fast initial boot time for the tool across all other commands. _(cli, performance, nodejs)_ _(archived: Noise rule: astGrepPattern `import($MODULE)` fires on every canonical dynamic import in command handlers with a message saying the pattern is "required". No action for the developer. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **The author declined replacing multiple .filter() calls** - The author declined replacing multiple `.filter()` calls with a single-loop partition because readability is more important for small data sets (e.g., <20 items). Micro-optimizing for performance at this scale adds unnecessary code complexity without meaningful gain. _(typescript, performance, refactoring)_
- **Retaining redundant filtering at both the diff-block** - Retaining redundant filtering at both the diff-block and line-extraction levels serves as a low-cost defense-in-depth strategy. This "belt-and-suspenders" approach prevents regressions during refactoring or hardening phases without significant performance impact. _(architecture, patterns, performance)_
- **Ensure background hooks use piped stdio and disabled** - Ensure background hooks use piped stdio and disabled prompts to prevent terminal pollution or hung processes during automated git lifecycle events. _(git, cli, security)_
- **Prefer incomplete metadata over empty metadata** - When restoring large sets of legacy metadata, providing incomplete or truncated descriptions is often preferable to leaving fields entirely empty. This "better than nothing" approach provides a baseline for linting and a foundation for future LLM-assisted refinement. _(workflow, documentation, technical-debt)_
- **Subagents should be limited to mechanical implementation** - Subagents should be limited to mechanical implementation and testing while architectural decisions and MCP tool calls remain in the main controller. This is necessary because subagents typically lack the session history and tool access required to make high-level design decisions safely. _(architecture, agents, mcp)_
- **Performing content.split('\n') inside a loop over line** - \*\*Pattern:\*\* \.split\(['"]\\n['"]\)\s\*\[
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx
  \*\*Severity:\*\* error

Performing content.split('\n') inside a loop over line. _(architecture, curated)_ _(archived: Duplicate of dc656c9238a0f80e (same lesson, regex variant). Both fire on any .split('\n') without loop context. See #1352.)_

- **Reject non-positive PIDs and infinite timestamps** - Reject non-positive PIDs and infinite timestamps in lockfiles to prevent accidental signaling of process groups via process.kill(0) and broken staleness math. _(node, security, process)_
- **Validate numeric input before parseInt** - When accepting user input that should be a pure integer (CLI args, PR numbers), validate with `String(Number(val)) === val` or `/^\d+$/` before calling `parseInt`. The `parseInt` function silently accepts trailing non-numeric characters (e.g., `parseInt("123abc")` returns `123`). This is a code review guideline, not a lint-time pattern — `parseInt` itself is a valid function. _(typescript, validation)_
- **Enforce provider-specific cache TTL constraints** - \*\*Scope:\*\* packages/core/src/config-schema.ts Anthropic prompt caching only supports specific TTL values (300s or 3600s); enforcing these in the schema prevents runtime API failures. _(anthropic, validation)_
- **Use hidden commands for graceful retirement** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Wiring retired commands as hidden entries allows throwing explicit errors with recovery hints, preventing user confusion from generic 'unknown command' failures. _(cli, dx)_
- **Strip LLM-generated markdown wrappers** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* LLM-generated patterns often include backticks or code fences that cause silent failures in rule engines if not stripped during parsing. _(llm, markdown, parsing)_
- **Use centralized utilities for regex escaping** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts Building regex patterns from dynamic configuration requires using a centralized `escapeRegex` utility. This prevents regex injection vulnerabilities and ensures that characters like `.` or `$` in configuration strings are treated as literals. _(security, dx)_
- **Verify probe resilience against dependency failures** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* When implementing best-effort probes, include regression tests that mock dependency rejections rather than just network failures. This confirms the wrapper correctly handles unexpected internal errors or import failures without bubbling them to the user. _(testing, resilience)_
- **Differentiate between hard-blocking invariants** - Differentiate between hard-blocking invariants (Security/Architecture) and informative warnings (Style/Performance) to balance safety with developer velocity. This "seatbelt, not bouncer" approach prevents non-critical style preferences from unnecessarily halting CI pipelines. _(linting, ci, developer-experience)_
- **File system watchers should monitor for "rename" events** - File system watchers should monitor for "rename" events rather than just "created" or "modified" to support editors that use atomic saves. Failure to handle renames often leads to stale caches and missed updates during development. _(nodejs, fs, toolchain)_
- **For data structures with few fields (e.g., < 10), use type** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts For data structures with few fields (e.g., < 10), use type assertions rather than Zod to avoid unnecessary dependency overhead and dynamic imports. This maintains a balance between type safety and code weight in performance-sensitive areas like the CLI. _(typescript, zod, architecture)_
- **Prefer kind over pattern for inside combinators** - \*\*Scope:\*\* packages/core/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Using 'inside: { pattern: ... }' can silently fail to match at runtime even when passing validation; use 'inside: { kind: ... }' for reliable structural matching. _(ast-grep, typescript)_
- **Use .cjs for Claude Code hooks** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* In projects using `type: module`, Claude Code hooks must use the `.cjs` extension because they are executed via Node.js `require()`, which rejects ESM `.js` files. _(claude, node, esm)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 1 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/src/commands/init.test.ts. reasonCode: stage4-out-of-scope-match.)_
- **Avoid stamping cache on forecasts** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Do not update the reviewed-content-hash cache during estimation or empty-diff runs, as forecasts are not equivalent to verified reviews and could allow push-gate bypasses. _(cli, caching, security)_
- **Implementing runtime binary resolution for git hooks** - Implementing runtime binary resolution for git hooks enables language-agnostic execution and avoids environment-specific path dependencies in monorepos. _(git-hooks, architecture, dx)_
- **Validate single-backtick wrappers before stripping** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Unconditionally stripping single backticks can corrupt patterns with internal backticks; use a strict regex to ensure the characters are actually external wrappers. _(regex, parsing, llm)_
- **Binaries like git may fail to resolve correctly when using** - Binaries like `git` may fail to resolve correctly when using `execFileSync` on Windows unless `shell: true` is explicitly enabled. This ensures the environment correctly locates the executable within the command shell context. _(nodejs, windows, security)_
- **Exclude test files from XSS rules** - \*\*Scope:\*\* packages/cli/src/assets/baseline-nodejs-security.ts Rules targeting dangerous sinks like innerHTML should exclude test files to allow for legitimate testing of sanitization logic or error handling. _(security, testing, javascript)_
- **Simple string lookups like indexOf('[{') fail to detect** - Simple string lookups like `indexOf('[{')` fail to detect pretty-printed JSON; using a regex search for `\[\s\*{` ensures the parser correctly identifies the start of an array regardless of whitespace. _(llm, json, parsing)_
- **Lesson — GCA decline protocol: Pack publish-flips** - # Lesson — GCA decline protocol: Pack publish-flips and `workspace:\*` references \*\*Context:\*\* PR #1780 flipped `@mmnto/pack-rust-architecture` from `private: true` to `private: false` (one-line change) to unblock ADR-097 § Stage 1's alpha-pilot consumer trigger (`liquid-city` consuming the pack via `extends:`). GCA flagged the flip on two grounds — both declined. ## Decline 1 — "Security-sensitive packages must remain private until Sigstore signing exists" GCA cited a "General Rule" requiring packages of architectural-governance content to remain `private: true` until cryptographic signing infrastructure exists. \*\*Why declined:\*\* Hallucinated rule citation. Zero hits for `private: true | cryptographic | Sigstore | signing` anywhere in `.gemini/styleguide.md` at the time of the review. The Sigstore + in-toto verification gate is tracked separately in `mmnto-ai/totem#1492` and is open / tier-2 / pre-implementation. Alpha-pilot publishes during ADR-097 § Stage 1 are explicitly exempted in the canonical gating ticket (`mmnto-ai/totem#1779`) — the exemption is the deliberate strategic decision per dev-Gemini synthesis 2026-05-01: "alpha-soak inside a workspace vacuum is deferred friction, not validation." When `#1492` ships, both `@mmnto/pack-\*` packages re-flow through the gate as part of normal pack-publish discipline. ## Decline 2 — "`workspace:\*` reference produces invalid registry package" GCA claimed making the pack public while it has `"@mmnto/totem": "workspace:\*"` in `devDependencies` would produce an invalid package on the registry. \*\*Why declined:\*\* Empirically falsified by the live cohort. `@mmnto/cli@1.23.0` (published ~4 hours before PR #1780 opened, via the same `changeset publish` pipeline) has `"@mmnto/totem": "workspace:\*"` in source `dependencies`, but `npm view @mmnto/cli@1.23.0 dependencies` returns `'@mmnto/totem': '1.23.0'`. The pnpm + changesets publish pipeline transforms the workspace protocol at `pnpm publish` time — automatic, not a publish-blocker. The same transform applies to every fixed-group cohort member. Additionally, the rust pack's `workspace:\*` is in `devDependencies`, which registry consumers don't install regardless of the source spec. ## Pattern reinforced — GCA decline protocol (per GEMINI.md) When declining a GCA finding: 1. \*\*Update `.gemini/styleguide.md` §6\*\* with the specific declined pattern so the rule is in the styleguide on the next review pass. 2. \*\*Capture the architectural reasoning as a lesson with the `review-guidance` tag\*\* (this lesson type) so the knowledge base records the rationale for future cross-agent context. 3. \*\*Post ONE consolidated `@gemini-code-assist` issue comment\*\* addressing all findings as a numbered list, in the order GCA raised them. Sub-thread direct-replies are not the protocol path when a substrate/styleguide change is made — they are reserved for the no-substrate-change case (quota-preservation when no re-eval is needed). This is the first `review-guidance` lesson in the corpus — establishing the precedent. The wider protocol-hygiene sweep across all three repos is queued separately. ## When to apply When a GCA finding is incorrect or contradicted by the project's own state (live cohort behavior, ticket-authorized exemptions, missing styleguide entries), do not just reply — codify the decline so future reviews don't re-raise it. The bot's per-comment prompts evaluate against PR snapshots without full repo context, which makes hallucinated rule citations and out-of-date corpus claims a recurring class. \*\*Source:\*\* mcp (added at 2026-05-01T18:29:29.673Z) _(review-guidance, gca, pack-distribution, pnpm-workspace, sigstore, publish-pipeline, adr-097)_
- **Verify provider support for context caching** - \*\*Scope:\*\* docs/wiki/context-caching.md Context caching is currently limited to Anthropic; Gemini support is deferred despite its presence in configuration schemas. _(ai, performance)_
- **Core library modules should accept an optional onWarn** - Core library modules should accept an optional `onWarn` callback instead of logging directly or silently swallowing errors. This pattern maintains a strict separation between core logic and presentation while ensuring that callers can observe and report internal failures like corrupt caches. _(error-handling, architecture, observability)_
- **When a required context source is empty, use a safety** - When a required context source is empty, use a safety fallback that preserves existing data with a staleness warning rather than performing destructive deletions. _(llm, resilience, documentation)_
- **When a required external dependency or model is missing,** - When a required external dependency or model is missing, error messages should provide the specific command needed to resolve the issue (e.g., 'ollama pull ...'). This significantly reduces user friction and the need for manual troubleshooting. _(error-handling, dx, dependencies)_
- **Patterns matching JavaScript string literals must include** - Patterns matching JavaScript string literals must include backticks to account for template literals. Neglecting backticks leaves the rule blind to modern JS string syntax. _(javascript, regex, guardrails)_
- **Lazy-load CLI command constants** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use dynamic imports for display tags and templates inside command handlers to keep CLI startup and module initialization lightweight. _(cli, performance)_
- **Replacing direct process.exit(1) calls with thrown custom** - Replacing direct process.exit(1) calls with thrown custom errors makes command logic composable and unit-testable. Centralize exit code handling at the top-level application boundary to maintain control over the execution lifecycle. _(cli, testing, node)_
- **Projects using native bindings (Rust, N-API, WASM)** - Projects using native bindings (Rust, N-API, WASM) and heavy filesystem I/O must run CI across all target platforms to catch OS-specific bugs. This prevents platform-specific issues, such as Windows-specific process signal handling, from reaching production. _(ci, native-bindings, cross-platform)_
- **Tests should invoke the actual command handler rather** - Tests should invoke the actual command handler rather than mirroring validation logic to ensure regressions in the real validation path are caught. _(testing, validation)_
- **Wrap external calls in timeouts** - \*\*Scope:\*\* .claude/hooks/\*\*/\*.sh Wrap all git and external invocations in `timeout` or `gtimeout` to ensure the hook never hangs the parent process during execution. _(bash, performance, git)_
- **Wrap fallback instructions or meta-context in XML tags** - Wrap fallback instructions or meta-context in XML tags like `<context\_note>` to maintain structural consistency and reduce LLM ambiguity when mixing data and instructions. _(llm, prompt-engineering)_
- **Implement verification shadow for rule promotion** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use a `verification\_shadow` field to allow new rules to execute and emit signals without affecting the final decision, facilitating a safe promotion path for new logic. _(architecture, api-design)_
- **Explicitly bind and discard catch variables** - \*\*Scope:\*\* packages/core/src/compile-manifest.ts Binding exceptions as 'err' and using 'void err' in catch blocks makes intentional fallbacks self-documenting and prevents violations of repo safety rules regarding empty catch blocks. _(typescript, conventions)_
- **Prioritize data-only architecture for security packs** - \*\*Scope:\*\* packages/pack-agent-security/\*\*/\* Maintaining security packs as data-only JSON (without loaders or Zod) simplifies distribution and preserves the 'simple pack' design even when specs suggest more complex loaders. _(architecture, security)_
- **Isolate monorepo-specific security allowlists** - Avoid bloating shared ignore templates with internal paths to prevent leaking repository structure to consumers. Use test-level allowlists in the monorepo to handle legitimate security rule violations for internal tools. _(architecture, security)_
- **Unroll error cause chains for shell execution** - \*\*Scope:\*\* packages/core/src/sys/\*\*/\*.ts, !\*\*/\*.test.\* Use `describeSafeExecError` to unroll error cause chains instead of manual message concatenation in wrappers. This complies with project error-handling rules and prevents obscuring the root cause of execution failures. _(errors, shell)_ _(archived: Over-broad: $ERR.message + $CAUSE matches any string concatenation involving .message, not just error re-throws. upgradeTarget: compound (Proposal 226 -- needs inside: catch constraint).)_
- **When applying global error prefixes, check for existing** - When applying global error prefixes, check for existing tags to avoid redundant output like '[Error] [Error] message' for already-tagged custom errors. _(cli, logging, ux)_
- **Use fixed literal tags for log.error calls** - Using fixed literal tags like 'Totem Error' in log calls, rather than variable constants, ensures that error reporting remains consistent and easily filterable across different CLI modules. This standardization helps automated log parsers and developers quickly identify failure points. _(logging, cli, dx)_
- **Explicit type assertions are often unnecessary when using** - Explicit type assertions are often unnecessary when using the nullish coalescing operator (`??`) with a literal fallback. TypeScript's inference engine automatically resolves the type to the narrowest possible union, so adding `as 'type'` creates redundant code. _(typescript, typing)_
- **When identifying files by naming conventions (e.g.,** - When identifying files by naming conventions (e.g., matching `\*.test.\*` or `\*.spec.\*`), perform the match against the file's basename rather than the full path. Using `path.includes()` on a full path can lead to false positives if a directory segment matches the infix, misclassifying non-target files. _(architecture, logic, globbing)_
- **Triage changes to skip design ceremony** - \*\*Scope:\*\* .claude/skills/preflight/SKILL.md Use a triage checklist to distinguish tactical edits from architectural changes, allowing simple fixes to skip formal design documentation and maintain velocity. _(process, dx)_
- **Lazy load heavy modules in CLI handlers** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts, !\*\*/\*.test.\* CLI commands should use dynamic imports for heavy modules like 'node:fs', 'node:path', or 'zod' inside the command handler to minimize startup latency and improve tool responsiveness. _(cli, performance, dx)_
- **Prioritize incompatibility guards over validation** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Execute mutual incompatibility checks between flags before running individual flag validation. This ensures users see errors about conflicting features rather than misleading downstream constraints or missing value errors. _(cli, ux)_
- **Use discriminated unions for resolution results** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts Returning a StrategyRootStatus union instead of nullable fields forces callers to handle the 'unresolved' state explicitly, preventing runtime type assertions. _(typescript, api-design)_
- **Lazy load WASM for CLI performance** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Initialize heavy engines like WASM only when required by specific commands rather than at top-level startup. This prevents unnecessary overhead and latency for simple CLI operations that do not require AST parsing. _(performance, wasm)_
- **Validate CLI flag values strictly** - When parsing CLI flags that should be integers, validate strictly before conversion. `parseInt("5foo")` silently returns `5`, hiding typos. Use `Number()` or check `String(num) === raw` after parsing. This is a code review guideline — do not lint-flag all `parseInt` calls. _(cli, typescript, validation)_
- **Prefer local Sonnet for compilation** - \*\*Scope:\*\* docs/wiki/cloud-compilation.md Local Sonnet is the recommended compilation path due to a significant correctness gap (~90%) compared to cloud Gemini Pro (~73%). _(ai, performance)_
- **Top-level imports of heavy classes or modules** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Top-level imports of heavy classes or modules can significantly degrade CLI startup performance. Use dynamic imports inside command function bodies to ensure the tool remains responsive for fast operations that don't require those dependencies. _(performance, nodejs, cli)_ _(archived: Over-broad: astGrepPattern `import $NAME from '$MODULE'` fires on every top-level default import in packages/cli/src/commands/\*\*. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Environment variable keys like PATH are case-insensitive** - Environment variable keys like `PATH` are case-insensitive on Windows, meaning test assertions must check for both 'Path' and 'PATH' to avoid platform-specific failures. _(windows, testing)_
- **Mirror local cleanup in cloud paths** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts Ensure cloud compilation paths mirror local worker behavior by explicitly removing stale entries when a lesson is marked non-compilable to prevent old rules from remaining active. _(cloud, consistency)_
- **Implement strict validation for text length and tag counts** - Implement strict validation for text length and tag counts when parsing LLM outputs to prevent hallucinations or malformed data from polluting the knowledge base. This acts as a final gate before untrusted AI output is persisted to version-controlled surfaces. _(llm, validation, parsing)_
- **Stale totem-context: suppression markers should be** - Stale `totem-context:` suppression markers should be converted to plain comments if a file is subsequently excluded from a rule's scope via configuration. Retaining live suppression markers on excluded files creates a 'suppression debt' that may unintentionally mask other rule violations on those same lines. _(totem, maintenance, architecture)_
- **Including rule help links and explicit tool identification** - Including rule help links and explicit tool identification in SARIF outputs significantly improves triage efficiency for developers using automated security or linting integrations. _(sarif, dx, security)_
- **Avoid opinionated policy in core runners** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Core runners should avoid enforcing specific CI policies like minimum rule counts, allowing consumers to implement their own guardrails externally. _(architecture, cli, ci)_
- **Prevent eval bypasses via concatenation** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Security rules for dynamic evaluation must ensure the argument is a single literal string to prevent bypasses using string concatenation or template interpolation. _(security, javascript, ast-grep)_ _(archived: Second-wave duplicate of c0f652d54da5bed0. Pattern duplicates the dynamic-code-evaluation coverage in pack-agent-security rule a0b737fd43fb943e, which handles the same non-literal-argument case (binary_expression / template_string / identifier) via its own constraint.)_
- **Silent failures in 'best-effort' operations like staleness** - Silent failures in 'best-effort' operations like staleness checks or documentation assembly hinder observability and debugging. Use non-blocking logging instead of empty catch blocks to ensure IO failures are traceable without crashing the primary command execution. _(cli, error-handling)_
- **Preserve consistent ESLint adapter scopes** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts Maintain uniform file exclusion patterns across all ESLint adapter handlers to ensure predictable behavior, even when AI reviewers suggest broadening the scope for specific rules. _(architecture, eslint)_
- **When implementing content filters, regression tests** - When implementing content filters, regression tests must cover both inline markers and directory-level bypasses (e.g., docs/manual/\*) to ensure global policies don't overwrite trusted files. _(testing, documentation, architecture)_
- **Incremental validation must confirm the previous commit** - Incremental validation must confirm the previous commit is a direct ancestor before evaluating deltas. This prevents applying partial reviews to divergent branches where the base state is unverified. _(git, validation, performance)_
- **Use a shared glob matching implementation across CLI** - Use a shared glob matching implementation across CLI and core packages to ensure that ignore patterns behave identically in all environments. This prevents "CI noise" where submodule changes or ignored files trigger false failures due to divergent path-matching logic. _(ci, consistency, globs)_
- **Ensure ignore patterns filter the actual diff content** - Ensure ignore patterns filter the actual diff content of AI-generated changes rather than just file paths. This prevents false positives in protected areas like submodules where automated strategies might otherwise trigger unintended warnings. _(ai-shield, git, submodules)_
- **Incrementing usage counters only after a successful** - Incrementing usage counters only after a successful operation prevents users from exhausting their session quota with failed validation attempts or non-fatal errors. This ensures the rate limit accurately reflects actual resource consumption rather than total attempts. _(security, rate-limiting, architecture)_
- **Applying broad security rules against dynamic imports** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Applying broad security rules against dynamic imports in CLI tools often creates noise in command and entry-point files. Narrowing these rules to target only core logic and adapters maintains security coverage while preventing developer friction in non-critical command-line interfaces. _(security, architecture, linting)_
- **Apply Zod validation primarily at system boundaries, such** - Apply Zod validation primarily at system boundaries, such as configuration files and API inputs, rather than for internal data structures. Overusing Zod for small internal parsers or data transformers adds unnecessary overhead and complexity to the codebase. _(typescript, validation, zod)_
- **Empty catch blocks during file discovery can lead** - Empty catch blocks during file discovery can lead to incomplete data sets that trigger incorrect downstream logic, such as downgrading rule severity based on "missing" tests. Explicit error handling is necessary to distinguish between a missing directory and a failure to read valid configurations. _(architecture, testing, nodejs)_
- **Prioritize human design review over bot cycles** - \*\*Scope:\*\* .claude/skills/preflight/SKILL.md A brief human design review is significantly more cost-effective than multiple bot-driven code review rounds for resolving architectural ambiguities. _(process, ai-collaboration)_
- **Archive flawed rules to preserve telemetry** - \*\*Scope:\*\* .totem/compiled-rules.json Deprecated or flawed rules should be archived in-place with a status and reason rather than deleted. This preserves historical telemetry and maintains manifest count integrity. _(totem, telemetry, linting)_
- **Escape backticks in SQL predicates** - Ensure backticks are included in escaping logic alongside single quotes and wildcards when building SQL predicates or `LIKE` clauses. This prevents identifier-based injection attacks in databases that use backticks for quoting. _(security, sql, database)_
- **Avoid fake absolute paths in results** - \*\*Scope:\*\* packages/core/src/store/lance-search.ts Reusing relative file paths as absolute paths when metadata is missing violates result contracts. This causes agents to attempt file operations against the wrong repository root, leading to read failures. _(core, search, contract)_
- **When defining automation skills, provide the full** - When defining automation skills, provide the full executable shell command rather than a descriptive summary or partial command. This eliminates ambiguity and ensures the agent can execute the task immediately without needing to interpret how to perform the action. _(automation, dx, cli)_
- **Avoid suppression events for runtime failures** - \*\*Scope:\*\* packages/core/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* The 'suppress' event should not be repurposed for runtime execution failures as it lacks the appropriate interface and misrepresents the architectural intent of suppression. _(architecture, events)_ _(archived: Hallucinated API surface — pattern emit('suppress', $$$ARGS) does not match Totem call sites. Our event API is onRuleEvent('suppress', ...) on RuleEventCallback (compiler-schema.ts:147), never emit(). Sonnet generated a generic event-emitter shape that has zero coverage in the codebase. Lesson is valid but needs source refinement before recompile to anchor to onRuleEvent or a concrete failure-event API once #1408 lands. upgradeTarget: compound — a compound rule could constrain to events.ts call sites but the underlying API mismatch must be fixed first.)_
- **When implementing prompt-level or post-processing filters,** - When implementing prompt-level or post-processing filters, ensure both singular and plural forms (e.g., "guarantee" and "guarantees") are explicitly covered. Inconsistent coverage allows prohibited terms to bypass filters simply by changing grammatical number, often introducing grammatical errors during replacement. _(llm, prompts, validation)_
- **Use the core package's glob matching logic** - Use the core package's glob matching logic when pre-filtering Git diffs in CI/CD commands to maintain behavioral parity. Reusing central matching logic prevents "CI noise" where submodules or ignored patterns are incorrectly processed by divergent local logic. _(architecture, devops, glob)_
- **When dynamically generating XML fragments, the tag name** - When dynamically generating XML fragments, the tag name itself must be validated against a strict regex to prevent attackers from injecting malformed markup via the tag parameter. Escaping content alone is insufficient if the surrounding tag can be manipulated. _(security, xml, validation)_
- **Trigger manifest staleness on semver-minor drift** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\* Detecting stale manifests based on semver-minor mismatches while tolerating patch drift provides helpful UX nudges without being overly restrictive for users. _(versioning, ux)_
- **Technical documentation must replace absolute claims** - Technical documentation must replace absolute claims like "guarantee" or "comprehensive" with specific, evidence-backed descriptions of tested behavior. This ensures factual accuracy and credibility in high-compliance sectors where technical claims are strictly scrutinized. _(documentation, compliance)_
- **Using multiple diverse LLMs to triangulate a project's core** - Using multiple diverse LLMs to triangulate a project's core identity can reveal a clearer, more accurate framing than the creator's initial feature-focused vision. This ensures the value proposition reflects how the tool is actually perceived and utilized by AI agents in practice. _(branding, documentation, llm-strategy)_
- **Use cheap deterministic deduplication passes** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Precede expensive embedding-based similarity checks with a cheap O(n) exact-match pass on normalized headings to reduce vector database overhead. _(performance, optimization, embeddings)_
- **Harden regex patterns against ReDoS** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Combine a character length cap (e.g., 512 chars) with safety checks like `isRegexSafe` during schema validation to prevent catastrophic backtracking at runtime. _(security, regex, zod)_
- **Enforce a standard string prefix for all application-thrown** - Enforce a standard string prefix for all application-thrown errors to ensure they are easily filterable in logging and monitoring tools. This distinguishes expected application failures from generic runtime exceptions. _(error-handling, observability)_
- **Allow inline literals for test timeouts** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.test.ts The general prohibition against magic numbers is waived for test infrastructure configuration like timeouts. Inline literals are preferred here because the 'timeout' key provides sufficient self-documentation. _(testing, dx, styleguide)_
- **Bump major version for schema changes** - \*\*Scope:\*\* .changeset/\*.md Breaking changes to public API shapes, such as switching a field to a discriminated union, must be marked as a major version bump in changesets to ensure downstream consumers handle the new structure. _(changesets, semver, mcp)_ _(archived: Pattern '^'[^']+': (minor|patch)$' fires on EVERY routine changeset entry. Same over-broad class as c3c6ccd3 ('Bump major version for discriminated unions'). Lesson intent was schema-change-as-breaking-change but regex doesn't distinguish breaking shape changes from any minor/patch bump. Archive pending pattern-tightening; likely needs ast-grep on the source TS schema files referenced by the changeset, not regex on the changeset MD.)_
- **Standardize exception messages with a consistent prefix** - Standardize exception messages with a consistent prefix (e.g., `[Totem Error]`) to help users distinguish between internal logic failures and external system errors. This is especially critical in multi-server or MCP environments where identifying the specific source of a log entry is difficult. _(patterns, error-handling, dev-experience)_
- **Avoid using partial matchers like toContain when testing** - Avoid using partial matchers like `toContain` when testing secret masking or data sanitization. Exact string assertions are necessary to ensure the logic preserves surrounding context and does not redact more information than intended. _(testing, security, jest)_
- **Explicit type assertions are often unnecessary when using** - \*\*Pattern:\*\* \?\?\s\*(['"][^'"]\*['"]|\d+|true|false)\s+as\s+
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx
  \*\*Severity:\*\* warning

Explicit type assertions are often unnecessary when using. _(architecture, curated)_

- **Standardize exception messages with a consistent prefix** - \*\*Pattern:\*\* \bnew\s+\w\*Error\(\s\*['"`](?!\[Totem Error\])
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Standardize exception messages with a consistent prefix. _(architecture, curated)_ _(archived: Conflicts with internal error wrapper pattern: bare Error in helpers (safeExec, handleGhError) is intentional because TotemError handles prefixing automatically. The regex cannot distinguish user-facing from internal errors, and forces workarounds (#1329 string concatenation bypass). See #1355.)_

- **Avoid live-repo coupling in tests** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Tests using the live repository root are coupled to working-tree size and can flake as the project grows. Use fixture-based repositories for deterministic cross-platform testing and explicit edge-case coverage. _(testing, git, ci)_
- **Always iterate through all regex matches (e.g.,** - \*\*Pattern:\*\* \.(match|exec)\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/src/adapters/\*\*/\*.ts, packages/mcp/src/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Always iterate through all regex matches (e.g.. _(architecture, curated)_

- **Prefer kind in ast-grep inside constraints** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Using 'inside: { pattern: ... }' in ast-grep rules can cause silent zero-matches in smoke gates; use 'inside: { kind: ... }' for reliable structural matching. _(ast-grep, linting)_
- **Use --body-file for LLM text in CLI** - \*\*Pattern:\*\* \b--body\b(?!-file)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*.sh, \*.bash, \*.yml, \*.yaml, packages/cli/\*\*/\*.ts
  \*\*Severity:\*\* error

Use --body-file for LLM text in CLI. _(security, curated)_

- **Updating comment-matching regex to support trailing inline** - Updating comment-matching regex to support trailing inline directives ensures that suppressions are captured even when developers append them to code lines rather than using full-line comments. _(regex, dx)_
- **Trim trailing semicolons from declaration text** - \*\*Scope:\*\* packages/core/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* When capturing text from declaration-pattern nodes, trailing semicolons should be trimmed to prevent syntax noise in downstream processing. _(ast-grep, dx)_ _(archived: Inverted polarity — pattern $TEXT.replace(/;+$/, '') flags the fix action rather than the bug. The lesson teaches that declaration-pattern text() output should be trimmed; flagging .replace(/;+$/, '') would fire on every site that correctly applies the trim. Lesson body is conceptual (DX guidance) without a clear bug-side pattern to anchor a flat rule. upgradeTarget: compound — a compound rule could match SgNode.text() consumer sites without a sibling .replace, but until then the lesson is documentation, not enforcement.)_
- **Manual fixes to auto-generated files are temporary and will** - Manual fixes to auto-generated files are temporary and will be overwritten during the next compilation cycle. To prevent regressions, refine the source lesson or metadata that triggers the duplicate or overly broad rule. _(build-systems, rule-generation, maintenance)_
- **While using shell: true fixes Windows ENOENT errors** - While using `shell: true` fixes Windows ENOENT errors for command shims, manually appending `.cmd` to the executable is a safer pattern that avoids shell injection risks and process overhead. _(windows, node.js, security)_ _(archived: Superseded by rule 09a2284e (cross-spawn tripwire). Wrong remediation: '.cmd appending' is brittle across corepack/WSL/native binaries. Correct fix is cross-spawn, which the new rule enforces. Also over-broad globs (\*\*/\*.ts) vs the replacement's scoped sys/ target.)_
- **Use fatal flag for security refinements** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Set `fatal: true` in Zod refinements for security gates to ensure the validation chain short-circuits immediately, preventing subsequent unsafe or expensive refinements from executing. _(zod, security, validation)_
- **Include low-level socket APIs in network rules** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Security rules for network exfiltration must cover low-level constructors like `net.Socket` and its `connect` method in addition to high-level APIs like `fetch` or `axios` to prevent bypasses. _(security, nodejs)_ _(archived: Second-wave duplicate of fc2d6c1f6e298d28 (which itself duplicated 4c219e8ad6230689). All three archives target variants of `new net.Socket(...)` compiled from the same authorial-guidance lesson. Fires on every legitimate net.Socket construction.)_
- **Simple regex patterns for file extensions often fail** - Simple regex patterns for file extensions often fail to match brace-expanded globs like `\*\*/\*.{ts,tsx}`, requiring explicit expansion to ensure full linting coverage. _(regex, glob, linting)_
- **When transitioning from a monolithic file** - When transitioning from a monolithic file to a directory-based structure, implement a dual-read/single-write strategy to ensure backward compatibility. This allow the system to process legacy data while ensuring all new records are created in the updated format. _(architecture, migrations, storage)_
- **Fail fast on unresolved upgrade hashes** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts Detect and error on requested upgrade hashes that do not resolve to lessons to prevent stale targets from being silently pruned as no-ops. _(validation, cli)_
- **AI tool metadata must treat MCP-related fields as optional** - \*\*Pattern:\*\* \bmcp[a-zA-Z0-9\_]\*(?!\?)\s\*:
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

AI tool metadata must treat MCP-related fields as optional. _(architecture, curated)_

- **Confine dynamic imports to CLI command handlers to maintain** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Confine dynamic imports to CLI command handlers to maintain a clean dependency graph and prevent shared utility layers from triggering security scanner flags. _(architecture, cli, performance)_ _(archived: Globs `packages/cli/src/\*\*/\*.ts, !packages/cli/src/commands/\*\*/\*.ts` are over-broad: they match the CLI root entry files packages/cli/src/index.ts and index-lite.ts, which is precisely where ADR-072 §3 (PR #945) places lazy-loads of command handlers. Rule fires on every canonical `const { cmd } = await import('./commands/foo.js')` line in the two CLI bin entry files. Canonical utility-layer coverage retained via rules a1fd35ee696110b0 (utils/adapters/lib) and f6739f9ad356067a (utils/lib/helpers), which use correctly narrow globs. Archived via #1517.)_
- **Alpha-pilot publish exemption from Sigstore gating** - \*\*Scope:\*\* packages/pack-\*/package.json This is a \*\*bounded exemption\*\*, not a general policy. During ADR-097 § Stage 1 alpha-pilot publishes only — and only while the Sigstore + in-toto verification gate is open, ticketed (currently `mmnto-ai/totem#1492`), and pre-implementation — pack publish-flips (`private: true → false`) may proceed without the cryptographic-signing gate satisfied. The exemption is conditional on (a) the alpha-pilot phase being active, (b) the gate ticket being explicitly open and tracked, and (c) the gating ticket itself authorizing the deferral. When `#1492` ships, every pack package (including those that flipped during alpha) re-flows through the gate as part of normal publish discipline. Outside this exception, security gates must be satisfied before publish. _(security, review-guidance, alpha-pilot)_
- **When implementing feature deprecations with aliases, ensure** - When implementing feature deprecations with aliases, ensure precedence tests include both old and new directives on the same line to verify the override logic correctly favors the new version. _(testing, regex)_
- **Prefer totem lint over the deprecated totem shield** - Prefer `totem lint` over the deprecated `totem shield --deterministic` for zero-LLM structural validation. This preserves the architectural distinction between AI-powered "shielding" and fast, deterministic "linting" as defined in the project's style guide. _(cli, documentation, deprecation)_
- **Core library modules should accept an optional onWarn** - Core library modules should accept an optional onWarn callback to surface diagnostics without hardcoding console dependencies. This allows callers to capture or report warnings from silent catch blocks that would otherwise be swallowed. _(architecture, diagnostics, logging)_
- **Never split error messages on periods** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Technical error messages frequently contain code patterns or file paths with dots; splitting on '.' truncates critical debugging context that users need to identify the failure. _(dx, error-handling)_ _(archived: Pattern `$STR.split('.')` fires on all dot splits: filename extension parsing (`filename.split('.')`), semantic version parsing (`'1.14.5'.split('.')`), dot-notation handling, and any arbitrary string manipulation with `.`. The underlying lesson was specific to splitting error messages containing code patterns with dots (the regression fixed in mmnto/totem#1349), but the rule is indiscriminate. Auto-compiled on the 2026-04-11 PM postmerge. Archived via the mmnto/totem#1345 filter. Kept in the ledger as the canonical example of 'the rule should have been narrower than the pattern the LLM chose'.)_
- **Sanitize git-sourced metadata like branch names, status,** - \*\*Pattern:\*\* \bgit\s+(?:branch|status|diff|log|describe|show)\b(?!.\*(?:stripAnsi|replace|sed|tr|\|))
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.sh, \*\*/\*.bash
  \*\*Severity:\*\* error

Sanitize git-sourced metadata like branch names, status. _(security, curated)_

- **Testing hook upgrades by checking only for a marker** - Testing hook upgrades by checking only for a marker can leave stale shell fragments undetected. Assert the full normalized file content to ensure the replacement logic is clean and does not leave orphaned code. _(testing, git-hooks)_
- **Promote migration guides to markdown headings** - \*\*Scope:\*\* docs/\*\*/\*.md Using markdown headings for migration blocks improves discoverability and provides stable anchor links for cross-referencing in long reference documents. _(documentation, dx, markdown)_
- **When a hook is intended to run unconditionally, use** - When a hook is intended to run unconditionally, use an explicit `\*\*/\*` glob pattern instead of an empty string. This clarifies intent for future maintainers and ensures the configuration isn't mistaken for a path-specific hook with a missing value. _(claude-code, glob, best-practices)_
- **Using .includes() to identify target files like READMEs** - Using `.includes()` to identify target files like READMEs is prone to false positives from directory paths or similar filenames. Use `path.basename()` with case-insensitivity to ensure logic only applies to the exact intended file. _(nodejs, path-handling, documentation)_
- **CLI entrypoints print clean errors, libraries throw** - \*\*Pattern:\*\* \bthrow\s+
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/src/index.ts, packages/cli/src/bin/\*\*/\*.ts, packages/cli/src/cli.ts, \*\*/cli.ts
  \*\*Severity:\*\* warning

CLI entrypoints print clean errors, libraries throw. _(style, curated)_

- **The github.event.pull_request context is immutable** - The github.event.pull*request context is immutable for a specific workflow run, meaning manual re-runs will not reflect title or body edits made after the initial trigger. *(github-actions, ci)\_
- **Use broad matching or normalization when scanning** - Use broad matching or normalization when scanning for existing hooks to prevent duplicate injections when the command name or invocation style changes. _(git-hooks, automation)_
- **Avoid over-broad git diff header regex** - \*\*Scope:\*\* .totem/compiled-rules.json Regex patterns targeting git diff headers like `+++ b/` must specifically check for quotes or spaces to avoid flagging legitimate test fixtures that mock plain file paths. Over-broad patterns break tests that use literal diff strings, forcing developers to use dynamic string workarounds. _(git, regex, testing)_
- **Use process.exitCode for CLI exits** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/index.ts, !\*\*/commands/\*.ts, !\*\*/\*.test.\* Prefer setting `process.exitCode` over calling `process.exit(1)` to allow the Node.js process to terminate gracefully. This ensures that cleanup logic, log flushing, and child process termination can complete before the process shuts down. _(cli, node, dx)_
- **CLI tools must check for an existing .git directory** - CLI tools must check for an existing .git directory before running initialization commands. Blindly executing git init can corrupt existing repository structures or submodules already present in the target directory. _(cli, git, toolchain)_
- **Relying solely on system prompts to exclude internal data** - Relying solely on system prompts to exclude internal data like issue references is insufficient for reliable output sanitization. Implementing a programmatic post-processing step provides a deterministic safety net against LLM hallucinations or prompt leaks in public-facing documentation. _(llm, documentation, sanitization)_
- **Git output can vary by system locale, causing parsing logic** - Git output can vary by system locale, causing parsing logic to fail. Forcing a neutral locale like `LC\_ALL=C` ensures consistent output format across different environments. _(git, i18n, parsing)_
- **Lesson headings must be restricted to 60 characters** - Lesson headings must be restricted to 60 characters or fewer because they serve as unique identifiers in SARIF reports. Exceeding this limit causes validation failures in automated analysis pipelines that rely on these identifiers for tracking. _(sarif, metadata, documentation)_
- **2026-03-06T18:48:00.895Z** - \*\*Pattern:\*\* \bnode\s+[^"'\s]+\.js\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* package.json, \*\*/\*.sh, Makefile
  \*\*Severity:\*\* error

Use the package.json bin entry or pnpm exec instead of raw node path.js invocations. _(architecture, curated)_

- **Using Array.prototype.find inside a loop results in O(N\\\*M)** - Using `Array.prototype.find` inside a loop results in O(N\\\*M) complexity, which can degrade performance as the number of rules grows. Indexing data into a `Map` before the loop ensures O(1) lookups and scales linearly. _(typescript, performance, optimization)_
- **Separate read from parse in cleanup** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* In best-effort cleanup operations, allow file read or permission errors to fail loudly while swallowing JSON syntax errors to ensure the process is resilient to malformed files without hiding system failures. _(cli, error-handling, json)_
- **Model Context Protocol (MCP) tools should prioritize** - Model Context Protocol (MCP) tools should prioritize plain-text error signals over XML-wrapped structures when client compatibility requires it. Forcing consistent XML structures on error paths can break downstream MCP consumers that expect specific boolean flags or raw text. _(mcp, architecture, error-handling)_
- **Functions with 'OrExit' suffixes must actually terminate** - Functions with 'OrExit' suffixes must actually terminate the process on failure rather than returning empty results. Misleading names cause callers to skip necessary error handling for empty states. _(dx, naming-conventions)_
- **Align read and write cache hashing** - \*\*Scope:\*\* packages/cli/src/utils.ts Inconsistent hashing logic between the read and write paths of a response cache results in permanent cache misses even when the content is identical. _(caching, bug-prevention)_
- **Totem Ecosystem Orientation** - \*\*Audience:\*\* Any agent operating in a Totem-governed repository (Claude, Gemini, future LLMs) \*\*Purpose:\*\* Structural orientation — agentic roles, repo composition, tenets, and source-of-truth pointers — so agents derive correct context at session-start without re-discovering ecosystem shape from scratch. \*\*Compile classification:\*\* Yellow (per Tenet 9) — subjective interpretation, NOT compiled to regex/AST. \*\*Source of truth:\*\* This lesson summarizes the canonical artifacts at the references below; if discrepancy, the canonical artifact wins. Re-derive from sources, do not cache assumptions from this lesson. ## §1 What Totem is (and is NOT) \*\*Totem is the deterministic substrate for multi-agent software development on a repository.\*\* Per ADR-090, Totem owns: - \*\*Memory:\*\* lessons, vector index, `totem extract`, `totem search` - \*\*Enforcement:\*\* compiled rules (`.totem/compiled-rules.json`), `totem lint`, ast-grep engine, pre-push gates - \*\*Audit:\*\* Trap Ledger (`events.ndjson`), override records, signoff artifacts - \*\*Interfaces:\*\* MCP servers exposing the above to any compliant agent \*\*Totem does NOT own orchestration:\*\* routing, capability negotiation, session lifecycle, live-edit conflict resolution. Those belong to the agent framework (MCP, Agent SDK), version control (git), or the agent runtime. The orchestration layer is fast-moving and competitive; Totem competes at the empty Convention and State Layer instead. If you (the agent) are tempted to add a feature that "decides which agent runs next" or "resolves conflicts between agents," stop — that's orchestration, not substrate. Apply the Scope Decision Test (ADR-090 §Scope Decision Test). ## §2 The Four-Layer Framework Totem development organizes around four layers (mmnto-ai/totem-strategy:governance-os-thesis/the-totem-framework.md): | Layer | Role | Tools | Failure mode if missing | |---|---|---|---| | \*\*Executive\*\* | Orchestration & strategy — defines \*Why\* and \*What\* | Long-term persistent chat, `mmnto-ai/totem-strategy` repo, ADRs, design tenets | Implementation drift; no architectural compass | | \*\*Execution\*\* | Implementation — translates specs to working code | IDEs, terminals, compilers, local test suites | Strategy without execution; ideas don't ship | | \*\*Governance\*\* | Deterministic enforcement — substrate that catches drift | Totem CLI (`lint`, `shield`), pre-push hooks, compiled rules | Lessons forgotten across sessions; same mistakes repeat | | \*\*Verification\*\* | Probabilistic review — async spot-check on PRs | PR review bots (CodeRabbit, Greptile, Gemini Code Assist) | Deterministic blind spots not caught; semantic violations slip | \*\*Agents operate across layers as needed\*\*, gated by lane (see §4). The vendor (Claude vs Gemini) does NOT determine layer — Tenet 16 (model-stack-agnosticism). A Claude agent can be in Executive lane (strategy-Claude); a Gemini agent can be in Execution lane (dev-Gemini implementing cohort bumps). ## §3 The Repos The Totem ecosystem is N-repo and growing (`feedback\_ecosystem\_is\_n\_repo\_growing`). Current canonical repos: | Repo | Role | Primary writers | Primary consumers | |---|---|---|---| | `mmnto-ai/totem` | The product — Totem CLI, MCP servers, lesson packs, core engine | totem-Claude, totem-Gemini | Every consumer repo | | `mmnto-ai/totem-strategy` | Governance-OS — ADRs, proposals, design tenets, governance-os-thesis. \*\*Independent Totem instance dogfooding the product to govern its own strategy.\*\* | strategy-Claude, strategy-Gemini, dev-Gemini (tooling) | Anyone needing architectural context | | `mmnto-ai/totem-substrate` | Inter-agent handoff + journal substrate (`.handoff/` + `.journal/`). Per ADR-100 v0.1: `.handoff/` + `.journal/` only. Direct-commit-to-main for routine writes; PR for tooling changes. | All agents (handoffs are 1:1 per ADR-098 v0.3) | All agents at session-start (hooks read inbox) | | `mmnto-ai/totem-status` | Dashboard — TUI/JSON/daemon surface. `LatestUnread` slice shipped v0.1; `LatestProcessed`, agent queue (v0.2), and Visor (LanceDB introspection) in flight. | status-Claude, status-Gemini | Humans (TUI) + agents (MCP/session-start) | | `mmnto-ai/liquid-city` | Dogfood game (Godot top-down, GTA2/Hotline Miami/L4D mashup). Slice ladder: 1 (single-template MST), 2 (procgen MST), 3 (multi-template), 4 (Godot template-export tooling) in flight. | lc-Claude, lc-Gemini, user (parallel dev) | Future players; current dogfood validation | | `satur8d/skynet-sports`, `arghap11`, others | Adjacent dogfood + private dev | Various | Various | \*\*Pack ecosystem\*\* (per ADR-085 + ADR-097, v0.1 alpha-pilot fully closed 2026-05-03): `@mmnto/pack-\*` NPM packages distribute language/architecture rules, capability rules, and bot interpretive knowledge. Pack ecosystem extends the @mmnto/totem core with specialized lesson sets. ## §4 The Agents — Lanes and Ownership Agents are organized by `<lane>-<vendor>` composite identifier (per ADR-098 Q7). Vendor is Claude or Gemini; lane indicates ownership domain. | Agent | Lane | Primary repos | What they own | |---|---|---|---| | \*\*strategy-Claude\*\* | Executive — orchestration synthesis, governance, tactical disposition | `mmnto-ai/totem-strategy` (write); cross-repo (read) | Orchestration role; ADR/proposal authoring; cross-stream synthesis; routing decisions; mechanical-disposition work (triage, hygiene, ticketing) | | \*\*strategy-Gemini\*\* | Executive — strategic synthesis | `mmnto-ai/totem-strategy` (write) | Strategic synthesis (proposals, ADRs at strategic layer, research); see `reference\_strategy\_role\_split` (Claude→mechanical; Gemini→strategic) | | \*\*totem-Claude\*\* | Execution + Governance — totem core implementation | `mmnto-ai/totem` (write) | Totem CLI, MCP, core engine implementation; lesson pack authoring; `totem` cohort releases | | \*\*totem-Gemini\*\* | Execution + Governance — totem-core synthesis | `mmnto-ai/totem` (write) | Strategic synthesis on totem-core architecture; spec authoring; cross-repo concerns | | \*\*dev-Gemini\*\* | Execution — cross-repo tooling | All repos (cohort bumps); substrate-tooling work | Cohort version bumps across consumer repos; engineering-lens cross-stream review; substrate hook implementations | | \*\*lc-Claude\*\* | Execution — liquid-city impl | `mmnto-ai/liquid-city` (write) | Slice impl PRs; Godot GDScript / template export tooling; postmerge artifacts | | \*\*lc-Gemini\*\* | Executive — liquid-city design | `mmnto-ai/liquid-city` (write) | Design-doc / spec review; greenlight on slice direction | | \*\*status-Claude\*\* | Execution — totem-status impl | `mmnto-ai/totem-status` (write) | TUI/Go implementation; dashboard slices | | \*\*status-Gemini\*\* | Executive + Execution — totem-status design + impl | `mmnto-ai/totem-status` (write) | Architectural framing for dashboard; slice authoring | \*\*The user is the Flight Controller\*\* (per Tenet 13). They route sensors to actuators, make hard tradeoffs the substrate cannot, and gate cross-stream / liquid-city / load-bearing decisions. \*\*Agents do NOT enter another agent's primary repo without coordination.\*\* Examples: - Liquid-city is off-limits for non-LC agents while user + lc-Claude work in parallel (`feedback\_liquid\_city\_user\_parallel\_dispatch\_coord`) - Cross-stream commits and greenlights need explicit user approval + cross-stream-agent verification (`feedback\_cross\_stream\_commit\_gate`) - Substrate writes require surgical `git add <path>` to avoid concurrent-write conflicts with other agents' WIP ## §5 The Handoff Pipeline Inter-agent coordination flows through mmnto-ai/totem-substrate:.handoff/<target-agent>/inbox/<UTC-TZ>-<from-agent>.md (per ADR-098). Current frontmatter schema (`adr-098-v0.3`): `yaml --- schema: adr-098-v0.3 from: <vendor-and-lane composite> to: <vendor-and-lane composite> timestamp: <UTC ISO-like, e.g., 2026-05-06T1845Z> expected-action: <what recipient should do> --- ` \*\*Lifecycle:\*\* recipient processes message, moves from `inbox/` to `processed/`. Both subdirs are pre-created and git-tracked per ADR-098 v0.3 amendment. Direct-commit-to-main on substrate for routine handoffs; surgical `git add <path>` to avoid sweeping concurrent agents' WIP. \*\*Session-start hooks\*\* (.claude/hooks/SessionStart.cjs, .gemini/hooks/SessionStart.js) read agent's inbox automatically and prepend pending dispatches to orientation pass. \*\*Signoff skill\*\* writes journal + handoffs at end-of-session. \*\*Broadcast vs point-to-point\*\* (`feedback\_handoff\_broadcast\_vs\_point\_to\_point`): same paragraph to 3+ agents → `.handoff/\_broadcast/`; "Agent X, do Y" or thread reply → per-agent inbox. ## §6 The Tenets — Load-Bearing Pair All 16 tenets matter (mmnto-ai/totem-strategy:design-tenets.md), but two are load-bearing for orchestration discipline: \*\*Tenet 15 (The Axiom Mandate):\*\* Totem's core value is the \*deterministic substrate\* — regex, filesystem checks, schema validations, git hooks, content hashes. Prose rules drift; substrate-encoded rules survive across model versions, vendor changes, and prompt instability. \*\*When designing a feature, ask first: "Can this be encoded as regex, schema, hook, or filesystem invariant?" If yes, encode it there — even if an LLM version would be more elegant.\*\* \*\*Tenet 16 (Model-Stack Agnosticism):\*\* The deterministic safety harness must work regardless of vendor (Claude, Gemini, OpenAI, local). No tenet, rule, or core feature may assume a specific provider. Vendor-locked features (provider-specific schemas, prompts, memory caches) are reference implementations only — never core constraints. Vendor-specific work ships as Packs (e.g. @mmnto/pack-claude-attestation), never baked into core. \*\*Together:\*\* the substrate is permanent and vendor-neutral; LLM-prose is volatile and vendor-locked. The substrate is the product. ## §7 Re-derivation Discipline This lesson is a \*\*summary\*\*, not a snapshot. If discrepancy with canonical artifacts, the artifact wins. \*\*Whenever you (agent) are about to act on orientation derived from this lesson, verify against current state:\*\* - For repo state: read the actual repo file - For ticket state: `gh issue/pr view` - For substrate state: `ls .handoff/` + `git log` on substrate - For tenet text: re-read mmnto-ai/totem-strategy:design-tenets.md - For ADR state: check `Status:` line in the ADR file (Accepted, Proposed, Superseded) \*\*`feedback\_empirical\_vs\_cached\_drift` fires N=6+ times across the ecosystem.\*\* This lesson is itself a candidate for the same failure mode if treated as authoritative without re-derivation. The vector DB pipeline + `totem-status` Visor exist precisely to catch staleness; use them. ## §8 Source-of-truth pointers For every fact above, the canonical source: | Topic | Source | |---|---| | Totem scope (substrate vs orchestrator) + multi-agent state | mmnto-ai/totem-strategy:adr/adr-090-multi-agent-substrate.md | | Four-layer framework | mmnto-ai/totem-strategy:governance-os-thesis/the-totem-framework.md | | Pack ecosystem | mmnto-ai/totem-strategy:adr/adr-085-totem-pack-ecosystem.md, mmnto-ai/totem-strategy:adr/adr-097-pack-language-archetype.md | | Universal lessons | mmnto-ai/totem-strategy:adr/adr-011-universal-lessons.md | | Handoff pipeline | mmnto-ai/totem-strategy:adr/adr-098-inter-agent-handoff-substrate.md | | Substrate repo extraction | mmnto-ai/totem-strategy:adr/adr-100-substrate-repo-extraction.md | | Totem-sync separation | mmnto-ai/totem-strategy:adr/adr-101-totem-sync-architectural-separation.md | | Design tenets (all 16) | mmnto-ai/totem-strategy:design-tenets.md | | Strategy-vs-Gemini role split | mmnto-ai/totem-strategy:audits/internal/2026-04-25-issue-routing-triage.md (per `reference\_strategy\_role\_split`) | | Substrate-friction synthesis | mmnto-ai/totem-strategy:audits/internal/2026-05-06-substrate-friction-cross-stream-synthesis.md (mmnto-ai/totem-strategy#236) | | Derived standing state proposal | mmnto-ai/totem-strategy:proposals/active/264-derived-standing-state.md | | Liquid-city dogfood positioning | `feedback\_liquid\_city\_is\_godot\_game` (memory) + mmnto-ai/liquid-city:.totem/specs/ | ## §9 What's locked vs fluid \*\*Locked (don't change without ADR amendment):\*\* - Tenets 1–16 (mmnto-ai/totem-strategy:design-tenets.md) - Substrate scope per ADR-090 - Handoff pipeline schema per ADR-098 v0.3 - Pack ecosystem governance per ADR-085 + ADR-097 - Substrate repo scope: `.handoff/` + `.journal/` only per ADR-100 v0.1 \*\*Fluid (evolving, expect change):\*\* - Slice-by-slice product roadmap (totem-status v0.2, liquid-city slice 4+) - Tier 0/1/2/3 work prioritization (per substrate-friction synthesis at mmnto-ai/totem-strategy#236) - Cross-stream sequencing thresholds (Proposal 264-derived; cutover criterion ADR pending) - Vendor-specific implementation details (hook syntax, MCP slot config) — agnostic intent, divergent implementation per vendor - Pack roadmap beyond v0.1 alpha-pilot When uncertain whether something is locked or fluid: check the ADR `Status:` line and recent journals. ## §10 What this lesson does NOT cover Out of scope for this lesson: - \*\*Vendor-specific implementation details\*\* — Claude hook file naming (`.cjs`), Gemini hook file naming (`.js`), MCP config locations. Agents derive these from their own vendor's harness. - \*\*Specific in-flight PR/issue state\*\* — that's Proposal 264 territory (derived standing state from git/PR/inbox) - \*\*Specific lesson packs and their content\*\* — agents query via `totem search` for framework-specific lessons - \*\*User-specific state\*\* — what user is currently working on, current priorities, dogfood validation status. Belongs in dynamic state surface, not structural orientation. _(orientation, architecture, yellow-rule, multi-agent, ecosystem)_
- **Cache original file content and reset the Git index** - Cache original file content and reset the Git index if an automated fix-and-commit sequence fails. This ensures the user's working tree remains clean and predictable after a failed automation attempt. _(git, reliability, dx)_
- **Orchestrators must dynamically adjust max_tokens based** - \*\*Pattern:\*\* \bmax\_?[tT]okens\b\s\*:\s\*\d+
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*orchestrator\*/\*\*/\*.ts, \*\*/orchestrators/\*\*/\*.ts, \*\*/\*orchestrator\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Orchestrators must dynamically adjust max*tokens based. *(security, curated)\_

- **2026-03-07T21:45:57.754Z** - \*\*Pattern:\*\* (?:\brun:|^\s\*[^:\s]+\s+).\*\$\{\{\s\*inputs\..\*\}\}
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* .github/workflows/\*.yml, .github/workflows/\*.yaml
  \*\*Severity:\*\* error

GitHub Actions workflow inputs must be sanitized before use in shell commands. _(security, curated)_

- **2026-03-03T03:20:15.923Z** - \*\*Pattern:\*\* \b(latency|tokens?|duration|ms|count)\b\s\\\*\|\|
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Use nullish coalescing (??) instead of logical OR (||) for numeric metrics to prevent valid 0 values from triggering fallbacks. _(security, curated)_

- **Validate plain JSON values for hashing** - \*\*Scope:\*\* packages/core/src/compile-manifest.ts Canonical serialization for hashing must strictly validate that inputs are plain JSON types to prevent non-deterministic output from complex objects like Dates or class instances. _(json, hashing)_
- **Synchronize versions via Changeset fixed groups** - \*\*Scope:\*\* .changeset/config.json The 'fixed' property in Changeset configuration forces all packages in a group to bump versions together. This ensures internal consistency across a monorepo even when a specific package has no direct changesets. _(changesets, release)_
- **Sensors, not actuators for hooks** - Follow the 'Sensors, Not Actuators' pattern by using session hooks to inject context rather than forcing specific tool calls. This provides the agent with necessary background information while maintaining its autonomy to decide how to use it. _(architecture, llm-context)_
- **Always use 'cd ... || exit 1' in shell scripts** - Always append `|| exit 1` to `cd` commands within shell scripts. This ensures the script terminates immediately if a directory change fails, preventing subsequent commands from running in an unintended or invalid directory context. _(bash, devops)_
- **Use tracer bullets for pipeline validation** - Prioritize end-to-end installation capability for new architectural components to validate the substrate's primary boundary early in the pilot phase, serving as a 'tracer bullet'. _(architecture, dx)_
- **Implementing simplified glob matching logic in auxiliary** - Implementing simplified glob matching logic in auxiliary scripts creates behavioral drift compared to the core engine's enforcement. Delegating to a shared implementation ensures that maintenance audits accurately reflect production behavior regarding negations and complex patterns. _(globbing, architecture, consistency)_
- **Selective rethrow for best-effort I/O** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts Best-effort I/O tasks like telemetry should swallow expected system errors (ENOENT, EACCES) but rethrow unexpected ones to prevent silent architectural drift. _(error-handling, telemetry, node)_
- **Ensure override paths update content-hash cache** - \*\*Scope:\*\* packages/cli/src/commands/shield.ts Manual override paths must update the reviewed content-hash cache to match the state of a passing review, otherwise users remain blocked by downstream push-gates. _(cli, cache, logic)_
- **Require dual-folder presence for standalone detection** - \*\*Scope:\*\* packages/cli/src/utils/governance.ts Standalone repository detection should require the presence of all expected governance folders (e.g., proposals AND ADRs) to prevent false positives in complex project structures. _(cli, governance)_
- **Do not abstract repetitive logic into generic utilities** - Do not abstract repetitive logic into generic utilities until the pattern has appeared at least three times in separate domains. Premature abstraction often introduces unnecessary complexity and reduces prototyping velocity. _(architecture, clean-code)_
- **Claude Opus 4.7 rejects sampling parameters** - \*\*Scope:\*\* docs/reference/supported-models.md, packages/cli/src/orchestrators/anthropic-orchestrator.ts Claude Opus 4.7 returns 400 errors if temperature, top*p, or top_k are provided in the Messages API. These parameters must be stripped from orchestrator calls to prevent request failures when using this model. *(anthropic, llm, api)\_ _(archived: Incomplete pattern (CodeRabbit finding on #1520): astGrepPattern `client.messages.create({ $$$ARGS, temperature: $VAL, $$$REST })` matches only calls that pass temperature, but the rule message says Opus 4.7 rejects all three of temperature, top_p, and top_k. Calls passing only top_p or top_k slip through. Archived rather than shipped incomplete; full coverage requires a compound rule authored in the source lesson.)_
- **When identifying directory-based glob patterns (like** - When identifying directory-based glob patterns (like `dir/\*.ts`), ensure the separator check excludes index 0. This prevents the logic from misinterpreting repo-relative paths as root-anchored, which can bypass intended security or scope constraints. _(glob, security, matching)_
- **Update document status to prevent triage drift** - \*\*Scope:\*\* docs/active*work.md Failing to update status labels (e.g., changing 'in review' to 'merged') creates 'triage drift' where automated tools and agents misrepresent the project's actual progress. *(documentation, triage)\_
- **Prune stale cache entries during no-op runs** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Cache pruning should occur even when no new work is required to prevent entries from deleted or edited source files from persisting indefinitely. _(cli, caching)_
- **Reword docs to avoid over-broad lint rules** - \*\*Scope:\*\* docs/wiki/\*.md Documentation describing forbidden patterns may trigger over-broad lint rules; reword the prose to avoid the pattern rather than disabling the rule if the rule is still valid for code. _(documentation, linting)_
- **Avoid re-exporting internal building blocks or heuristics** - Avoid re-exporting internal building blocks or heuristics from a package root as stable entry points. Exposing lower-level helpers makes future logic tuning semver-sensitive and complicates the public API maintenance. _(architecture, api-design, semver)_
- **Diagnostic hints must accurately reference the specific** - Diagnostic hints must accurately reference the specific underlying implementation, such as distinguishing between `execFileSync` and `execSync`. This prevents developer confusion when troubleshooting behavior or performance characteristics specific to certain execution variants. _(dx, dev-tools)_
- **Reusing regex objects with the global flag in loops leads** - Reusing regex objects with the global flag in loops leads to bugs because the `lastIndex` property persists between calls. Always instantiate fresh regex instances or manually reset the index to zero before execution to ensure consistent matching. _(typescript, regex, parsing)_
- **The Gemini CLI and Gemini Code Assist (GCA) do not** - \*\*Pattern:\*\* \bgemini\.md\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.md, \*\*/\*.sh, \*\*/\*.yml, \*\*/\*.yaml, package.json, \*\*/\*.txt
  \*\*Severity:\*\* error

The Gemini CLI and Gemini Code Assist (GCA) do not. _(architecture, curated)_

- **Exported configuration structures like command groups** - Exported configuration structures like command groups should use ReadonlySet or readonly arrays to prevent accidental runtime mutations. This ensures that help output remains consistent and cannot be silently corrupted by other modules. _(typescript, architecture)_
- **Prevent silent rule compilation failures** - A multi-layer fallback architecture with explicit failure reporting prevents the compiler from silently producing zero-match rules from valid inputs, a failure mode identified in stress tests. _(architecture, compilation, validation)_
- **Track line numbers in security allowlists** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Allowlisting security violations by filename alone is insufficient; tracking line numbers or match counts prevents new violations from being introduced into already-exempted files. _(testing, security, regression)_
- **When execution utilities wrap errors, handlers must check** - When execution utilities wrap errors, handlers must check both the wrapper and the underlying cause to reliably match specific error patterns like rate limits or missing binaries. _(error-handling, node.js)_
- **CLI command entrypoints should catch validation errors** - \*\*Pattern:\*\* \bthrow\s+new\s+(?!Totem)\w\*Error\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

CLI command entrypoints should catch validation errors. _(style, curated)_

- **Using empty catch blocks is acceptable for non-critical,** - Using empty catch blocks is acceptable for non-critical, best-effort features like hint extraction to prevent surfacing confusing I/O warnings that do not impact core functionality. _(architecture, error-handling)_
- **Check the process status (e.g., via process.kill(pid, 0))** - Check the process status (e.g., via `process.kill(pid, 0)`) before unlinking a stale lock to prevent Time-of-Check to Time-of-Use (TOCTOU) races. This prevents a process from accidentally deleting a valid lock acquired by a peer that just replaced the stale one. _(concurrency, filesystem, nodejs)_
- **Support dash variants in heading parsers** - \*\*Scope:\*\* packages/mcp/src/tools/\*\*/\*.ts, !\*\*/\*.test.\* When parsing human-entered headings, account for em-dash (—), en-dash (–), and hyphens (-) to ensure compatibility across different operating systems and keyboard shortcuts. _(parsing, ux)_
- **Batch cloud processing loops must log specific error** - Batch cloud processing loops must log specific error strings and unique identifiers for each failure to prevent losing diagnostic context during triaging. _(cloud, logging, diagnostics)_
- **When parsing git diff output, target the b/ destination** - When parsing `git diff` output, target the `b/` destination path and account for quoted strings to ensure accuracy. This prevents failures when handling file renames or paths containing spaces, which standard simple regexes often miss. _(git, regex, cli)_
- **Lightweight pattern validators must explicitly handle** - Lightweight pattern validators must explicitly handle escaped backslashes in string literals to avoid misidentifying the end of a string and causing runtime validation failures. _(validation, ast-grep, regex)_
- **In SARIF reporting, the count of enforced rules** - In SARIF reporting, the count of enforced rules should match the unique definitions provided in the tool driver to prevent metadata inconsistencies. Reporting the length of the raw rule list when definitions are deduplicated leads to confusing scan results in security dashboards. _(sarif, devops, security)_
- **When reverting problematic compiled rules, identify** - When reverting problematic compiled rules, identify and blocklist untracked lesson hashes that are not yet in the active rule set. This prevents the compiler from re-generating the same regressions during forced recompilation attempts. _(linting, version-control, automation)_
- **Resolve persistent directories like caches relative** - Resolve persistent directories like caches relative to the configuration file's location rather than process.cwd(). This prevents the creation of orphaned or redundant directories when the tool is executed from different project subdirectories. _(cli, paths, architecture)_
- **File-level comments require a higher similarity threshold** - File-level comments require a higher similarity threshold (e.g., 0.8 Jaccard) than line-proximate comments to prevent merging distinct architectural feedback. _(algorithms, deduplication)_
- **Prefer path.join for path security** - \*\*Scope:\*\* packages/core/src/strategy-resolver.ts Use path.join instead of path.resolve when combining base paths with potentially untrusted inputs. path.resolve can treat an absolute-looking input as a new root, enabling path injection vulnerabilities. _(security, node.js)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 41 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/src/assets/compiled-baseline.test.ts, packages/cli/src/commands/config-drift.test.ts, packages/cli/src/commands/docs.ts, packages/cli/src/commands/doctor.ts, packages/cli/src/commands/extract-shared.ts (+ 36 more). reasonCode: stage4-out-of-scope-match.)_
- **Export core types in WASM shims** - \*\*Scope:\*\* packages/core/src/ast-grep-wasm-shim.ts WASM shims replacing native NAPI modules must export equivalent core types (like SgRoot or SgNode) to prevent type-checking failures in downstream consumers. _(typescript, wasm, ast-grep)_
- **Concatenating severity strings with comment bodies** - Concatenating severity strings with comment bodies before keyword matching causes misclassification, such as 'minor' severity labels accidentally triggering 'nit' keyword matches. _(logic, categorization)_
- **Dynamic imports used for CLI startup performance should be** - Dynamic imports used for CLI startup performance should be restricted to command entry points to maintain a clean dependency graph and pass security scans in utility layers. _(architecture, performance)_
- **Detect tools via marker files, not directory names** - Detect installed tools by checking for their canonical marker files or specific config files rather than relying solely on directory names. This avoids false positives from unrelated folders and ensures detection works for tools that use individual files as signals. _(environment-detection, automation, tools)_
- **When matching function calls with ast-grep, multiple** - When matching function calls with ast-grep, multiple patterns or combinators are required to capture both inline literals and variable-based arguments. A single pattern like `spawn($CMD, [$$$ARGS])` will fail to match calls using variable references for arguments. _(ast-grep, pattern-matching)_
- **Using simple substring matching like "git" && "commit"** - Using simple substring matching like `\*"git"\* && \*"commit"\*` in shell hooks can trigger false positives on unrelated commands; order-sensitive regex ensures the gate only activates for actual Git subcommands. _(bash, git, regex)_
- **Avoid using non-unique fields like headings to identify** - Avoid using non-unique fields like headings to identify items for deletion or pruning operations. Matching by full raw content or unique hashes prevents accidental data loss when multiple items share the same metadata. _(data-integrity, pruning, identification)_
- **Standard Unix environment flags like '1' or 'true'** - Standard Unix environment flags like '1' or 'true' in configuration objects do not require extraction to constants, as they are conventional patterns rather than opaque business logic literals. _(conventions, dx, code-style)_
- **Route compilation to high-performance models** - Claude Sonnet 4.6 significantly outperforms Gemini Pro in structural pattern generation, reducing latency from ~20s to ~2s while improving correctness from 73% to 90%. _(llm, performance, benchmarking)_
- **Avoid using Zod's .url() validator for configurations where** - \*\*Pattern:\*\* \.url\(\)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* error

Avoid using Zod's .url() validator for configurations where. _(architecture, curated)_

- **Use unique temp names for atomic writes** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts, !\*\*/\*.test.\* When performing atomic writes using a 'write-then-rename' strategy, include a random suffix (for example, crypto.randomUUID()) in the temporary filename to prevent collisions during concurrent executions; process.pid and/or a timestamp may be added as extra entropy but PID/time-only combinations can still collide. _(fs, concurrency, node)_
- **Match documentation to actual CLI output** - \*\*Scope:\*\* README.md, docs/wiki/\*.md Documentation examples must reflect actual product output even if they violate style guides; updating prose without changing the underlying source strings creates misleading examples. _(documentation, cli, dx)_
- **Injecting architectural constraints and lessons directly** - Injecting architectural constraints and lessons directly into implementation steps, rather than providing them as a separate block, closes the "knowing vs doing" gap. This ensures the agent or developer accounts for specific rules at the exact moment they execute a task. _(prompt-engineering, llm, architecture)_
- **Using runtime binary resolution for hooks instead** - Using runtime binary resolution for hooks instead of hardcoded paths enables language-agnostic support and simplifies the distribution of generated helper scripts. _(architecture, hooks, dx)_
- **Rename state files to avoid naming collisions** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Avoid using filenames for committable state that conflict with existing telemetry cache modules to maintain a clear distinction between persistent and ephemeral data. _(architecture, naming)_
- **Avoid falling back to the raw input string when a split** - Avoid falling back to the raw input string when a split results in a single item; using the processed array ensures that normalization steps like trimming and filtering are consistently applied. _(typescript, parsing, clean-code)_
- **Utilize jq instead of standard string manipulation tools** - Utilize `jq` instead of standard string manipulation tools like `grep` or `sed` to ensure reliable data extraction from structured JSON configuration files. _(shell, devops)_
- **Use dynamic imports for JSON serialization and printing** - Use dynamic imports for JSON serialization and printing logic within error handlers to avoid unnecessary boot-time performance penalties for standard CLI execution. _(performance, cli)_
- **Guard hook exit code invariants** - \*\*Scope:\*\* .claude/hooks/\*\*/\*.sh Hooks must coerce all runtime failures to exit 1 to prevent blocking critical operations like compaction, which are only halted by an exit 2. _(bash, automation, reliability)_
- **Even when the MCP SDK defaults to stdio, explicitly** - Even when the MCP SDK defaults to `stdio`, explicitly declaring the transport type in tool configurations ensures consistency and reduces ambiguity for different client implementations. _(mcp, configuration, dx)_
- **Tree-sitter S-expression queries often lack predicates** - Tree-sitter S-expression queries often lack predicates to check child counts, making empty multi-line blocks difficult to detect. Use regex to target common single-line patterns until the engine supports custom predicates for node counts. _(tree-sitter, ast, regex)_
- **Use byte-level binary size checks** - \*\*Scope:\*\* packages/cli/build/compile-lite.sh Comparing file sizes in megabytes via integer division can allow binaries near the threshold to bypass limits; use byte-to-byte comparisons for accurate enforcement. _(shell, ci, build)_
- **Resilient continuation for transient federated link failures** - \*\*Scope:\*\* packages/mcp/\*\*/\*.ts, !\*\*/\*.test.\* When a federated link fails transiently (file lock, stale handle during a parallel `totem sync`, network blip, brief unavailability), the architectural choice is between \*\*eviction\*\* — remove the broken store from the active pool until server restart — and \*\*resilient continuation\*\* — keep the store in the pool and attempt a targeted reconnect on every query. Eviction is the obvious-looking optimization (fewer failing queries, less log spam) but has a critical failure mode: any transient issue causes \*\*permanent context loss\*\* until the MCP server restarts. A subsequent fix in the linked repository cannot be picked up without restart. The agent silently loses access to a real source of context based on a temporary failure. The correct pattern is \*\*resilient continuation\*\*: 1. Leave the failing link in `linkedStores` even after a search failure 2. On each subsequent query, attempt a targeted `reconnect()` + retry 3. Surface per-query runtime warnings to the agent so the failure stays visible 4. Let the next call try again — the underlying issue may have cleared Trades some log spam for resilience. Per Tenet 4 (Fail Loud, Never Drift), session-persistent state should not be mutated by transient failures. The PR #1295 review cycle established this pattern after an earlier eviction-based revision was rejected by the GCA + CR review for exactly this reason. This is a conceptual/architectural pattern, not a compilable rule. _(mcp, search, resilience, architecture)_
- **Centralize repeated filesystem cleanup options into named** - Centralize repeated filesystem cleanup options into named constants or shared helpers to enable global tuning of retry parameters and avoid magic numbers. _(testing, refactoring, dx)_
- **Ensure all thrown errors, including those for missing** - \*\*Pattern:\*\* throw\s+.\*['"`](?!\s\*\[Totem Error\])
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx, \*\*/\*.mjs, \*\*/\*.cjs
  \*\*Severity:\*\* warning

Ensure all thrown errors, including those for missing. _(style, curated)_

- **Issue numbers are only unique within a single repository;** - \*\*Pattern:\*\* (^|[^a-zA-Z0-9-\_./])#\d+
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/\*\*/\*.ts, apps/cli/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Issue numbers are only unique within a single repository;. _(architecture, curated)_

- **Avoid pinning transient publish states** - \*\*Scope:\*\* packages/pack-rust-architecture/test/structure.test.ts Structural tests should not pin the private field of a package to allow for future public flips without breaking invariants, as the field is inherently transient. _(testing, architecture)_
- **When redirecting stdio to a file for a detached process** - When redirecting stdio to a file for a detached process using fs.openSync, the file descriptor must be explicitly closed in the parent process to prevent resource leaks. _(node, fs, spawn)_
- **Prevent context-less rule pollution** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Defaulting LLM rule capture to OFF prevents 'warning waves' where context-less regex rules trigger violations on unrelated files across the codebase. _(llm, rules, cli)_
- **Limit SARIF output to error-severity findings** - \*\*Scope:\*\* packages/core/src/run-compiled-rules.ts Restricting SARIF output to error-severity findings prevents PR reviews from being overwhelmed by probationary warnings, effectively reducing alert fatigue in security dashboards. _(sarif, ci-cd, dx)_
- **Prevent boundary routing fallbacks on error** - \*\*Scope:\*\* packages/mcp/\*\*/\*.ts, !\*\*/\*.test.\* Falling back to a global search when a specific boundary link is broken can return misleading results from the primary repository. Explicitly checking for initialization errors before the fallback prevents silent drift in agent context. _(mcp, routing, security)_
- **Identical regex patterns should remain as distinct rules** - Identical regex patterns should remain as distinct rules when they target different file scopes or require different severity levels. This approach provides granular control, such as enforcing a strict error in core modules while allowing a warning in test files for the same code pattern. _(linting, architecture, patterns)_
- **Consolidate dynamic imports in command functions** - \*\*Scope:\*\* packages/cli/src/commands/shield.ts Grouping multiple utility functions into a single dynamic import block at the start of a command function reduces boilerplate and improves maintainability in lazy-loaded CLI environments. _(cli, performance, architecture)_
- **Manually editing compiled rule files** - Manually editing compiled rule files like `compiled-rules.json` is a temporary fix that is overwritten during the next build cycle. To permanently resolve issues, you must modify the source lessons or implement deduplication logic within the compiler itself. _(totem-compile, automation, hotfix)_
- **The text-embedding-004 identifier is frequently unavailable** - \*\*Pattern:\*\* \btext-embedding-004\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, \*\*/\*.json, \*\*/\*.yaml, \*\*/\*.yml
  \*\*Severity:\*\* warning

The text-embedding-004 identifier is frequently unavailable. _(style, curated)_

- **Apply guards to manual patterns** - \*\*Scope:\*\* packages/core/src/compile-lesson.ts Manual rule authoring pipelines must include the same validation guards as automated ones. This ensures that manually created patterns do not bypass critical checks like the self-suppression guard. _(compiler, validation, dx)_
- **Per-query error handling in AST engines prevents** - Per-query error handling in AST engines prevents environment-specific syntax, such as TypeScript-only nodes, from causing a total failure when analyzing compatible files like JavaScript. _(ast, typescript, error-handling)_
- **Naming fields like totalChunks (total in store) vs** - Naming fields like totalChunks (total in store) vs chunksProcessed (this run) prevents ambiguity for API consumers regarding sync progress. _(api-design, naming)_
- **Always verify that glob entries are strings before calling** - Always verify that glob entries are strings before calling methods like startsWith, as heterogeneous arrays in rule configurations can cause runtime failures during linting. _(typescript, safety, globs)_
- **Log diff source discriminators for transparency** - \*\*Scope:\*\* packages/cli/src/git.ts When using implicit fallback chains for data resolution, log the chosen source to stderr so the operator's mental model matches the actual system state. _(dx, git, logging)_
- **Assert raw strings for byte-identity** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.test.\* Structural equality checks via JSON.parse fail to detect formatting or property-order drifts. Assert against raw serialized strings when the contract requires byte-identical legacy output. _(testing, serialization)_
- **Avoid inlining tokens or API keys in configuration files** - \*\*Pattern:\*\* "(?:api[\_-]?key|token|secret|password)"\s\*:\s\*".+"
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.mcp.json, \*\*/settings.json, \*\*/.vscode/settings.json
  \*\*Severity:\*\* error

Avoid inlining tokens or API keys in configuration files. _(security, curated)_

- **README.md should be excluded from deterministic lint — it's** - # README.md should be excluded from deterministic lint — it's marketing copy ## What happened The README was rewritten as a "Storefront" with mermaid diagrams. Deterministic lint rules designed for source code (issue number patterns, import checks) false-positived on diagram syntax, CSS hex colors, and example code blocks. ## Rule Marketing-facing documentation (`README.md`) should be in `ignorePatterns` for `totem lint`. It contains: - Mermaid diagrams with CSS-like syntax - Example code blocks showing deliberate "wrong" patterns - Shell output examples with `#` comments These will always conflict with rules designed for source code. Shield (LLM) can still review it meaningfully; lint (regex) cannot. \*\*Source:\*\* mcp (added at 2026-03-27T19:56:00.512Z) _(readme, lint, ignorePatterns, documentation, false-positive)_
- **Treat active work context as the absolute ground truth** - Treat active work context as the absolute ground truth for forward-looking sections; if an item is missing from the context, it should be aggressively rewritten as completed or removed. _(llm, documentation, prompt-engineering)_
- **Using push(...parts) is safer than an if/else block** - Using `push(...parts)` is safer than an `if/else` block for single vs. multiple items because it eliminates redundant logic and ensures the same transformation pipeline is applied regardless of item count. _(typescript, clean-code)_
- **2026-03-02T09:18:21.092Z** - \*\*Pattern:\*\* \bos\.tmpdir\(\)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*.ts, \*.js, !\*.test.ts, !\*.spec.ts
  \*\*Severity:\*\* error

Do not use os.tmpdir() for agent-readable files; use workspace-local paths instead. _(architecture, curated)_

- **Avoid duplicating interface definitions across modules even** - Avoid duplicating interface definitions across modules even if they are structurally identical; use a single source of truth to prevent silent type contract failures during refactoring. _(typescript, dx)_
- **Exclude state files from verifier inputs** - \*\*Scope:\*\* packages/cli/src/commands/first-lint-promote-runner.ts Explicitly exclude state files from the verifier's input set to prevent circularity or the inclusion of metadata as part of the codebase being analyzed. _(architecture, testing)_
- **Moving instructions from the error message string** - Moving instructions from the error message string to a dedicated `recoveryHint` property enables consistent CLI formatting for user fixes. This separation allows the error renderer to automatically label solutions with a "Fix:" prefix while keeping the primary error message focused strictly on the failure. _(error-handling, ux, cli)_
- **Standardized logging utilities should always be used over** - Standardized logging utilities should always be used over `console.error` to ensure consistent output formatting and integration with the project's tagging system. Using the internal `log` utility is necessary to satisfy architectural requirements for error reporting and user feedback consistency. _(logging, style-guide)_
- **Narrow GHA injection rules to execution contexts** - \*\*Scope:\*\* .github/workflows/\*.yml, .github/workflows/\*.yaml GitHub Actions substitutes expressions in `env:` and `with:` blocks before shell execution, making them safe from injection. Lint rules should target execution keys like `run` or `shell` to avoid false positives in safe YAML contexts. _(github-actions, security)_
- **The LLM documentation generator consistently hallucinates** - \*\*Pattern:\*\* \b#515\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.md, \*\*/\*.mdx, \*\*/\*.txt
  \*\*Severity:\*\* warning

The LLM documentation generator consistently hallucinates. _(architecture, curated)_

- **Update post-compaction hooks to explicitly restate** - Update post-compaction hooks to explicitly restate mandatory execution gates like "tests must pass" and "TDD mandatory." Agents often lose awareness of strict constraints after context truncation, leading to skipped validation steps if the discipline is not reinforced in the fresh context. _(claude, workflow, automation)_
- **Reference rule IDs over hard-coded metrics** - \*\*Scope:\*\* docs/wiki/\*.md Use rule identifiers (e.g., FR-C01) instead of hard-coded numeric thresholds in documentation to maintain accuracy when configuration values are updated. _(documentation, maintenance)_
- **Validate embedding dimensions across federated stores** - \*\*Scope:\*\* packages/mcp/src/context.ts Vector search across federated stores requires identical embedding dimensions. Validating provider and model dimensions during initialization prevents runtime errors during semantic score merging. _(mcp, embeddings, validation)_
- **Path resolution logic should prioritize user-configured** - Path resolution logic should prioritize user-configured directories over hardcoded defaults like '.totem'. This ensures the tool remains functional in repositories with custom project structures. _(configuration, io)_
- **Lesson: LLMs consistently misattribute roles** - Lesson: LLMs consistently misattribute roles between deterministic "linting" and AI-powered "shielding" commands in documentation. Manual verification or specific architectural lessons are required to counteract recurring AI confusion between these distinct layers of the codebase immune system. _(documentation, llm, qa)_
- **Avoid using console methods directly in core library** - \*\*Pattern:\*\* \bconsole\.(log|warn|error|info|debug|trace)\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/core/\*\*/\*.ts, libs/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

Avoid using console methods directly in core library. _(style, curated)_

- **When required context is missing, instruct the LLM** - When required context is missing, instruct the LLM to preserve existing data with a staleness note rather than deleting it to ensure resilience against missing files. _(llm, resilience)_
- **Messages consisting entirely of stopwords or short words** - Messages consisting entirely of stopwords or short words can result in empty keyword arrays and identical hashes. Implementing a fallback to the full normalized message prevents unintended pattern collisions when keywords cannot be extracted. _(hashing, logic)_
- **Extract repetitive cleanup patterns, such as directory** - Extract repetitive cleanup patterns, such as directory removal with specific retry settings, into shared test utilities to eliminate magic numbers and enable global parameter tuning. _(testing, dx)_
- **Store the actual resolved vector size in the registry** - Store the actual resolved vector size in the registry rather than 'auto' placeholders to provide accurate diagnostic information about the embedding configuration. _(embeddings, metadata)_
- **Even when core rules are moved to a deterministic pipeline,** - Even when core rules are moved to a deterministic pipeline, a single automated step using LLM-based generation can still introduce regressions in the final artifact. Manual revert steps for generated files must be retained until the entire compilation pipeline is LLM-free. _(automation, llm, regressions)_
- **Automated diagnostic checks should verify that local** - Automated diagnostic checks should verify that local secrets files are excluded from version control to prevent accidental credential leakage. _(security, git, dlp)_
- **Provision npm scopes before first publish** - \*\*Scope:\*\* \*\*/package.json, .github/workflows/\*.yml, .changeset/config.json npm scopes must be manually provisioned before a CI/CD workflow attempts to publish, as tools like changesets will fail with E404 if the namespace does not exist on the registry. Surface this guidance when developers modify `package.json`, changeset config, or release workflows — those are the artefacts that trigger the publish path. _(npm, devops, ci-cd)_
- **Mock public APIs at package boundaries** - \*\*Scope:\*\* packages/cli/src/adapters/\*.test.ts When testing across package boundaries, mock the public API of the imported package rather than its internal dependencies. Vitest may fail to intercept internal imports if the consumer package resolves to a pre-built distribution file. _(testing, vitest, monorepo)_
- **Vector search for discovery should be strictly decoupled** - Vector search for discovery should be strictly decoupled from AST matching for enforcement. Never conflate probabilistic "fuzzy" matches with deterministic "hard" rules, as this distinction is critical for maintaining credibility with security-minded users. _(architecture, security, ai)_
- **Proactively remove references to planned features from user** - \*\*Pattern:\*\* \b(coming soon|planned (feature|for)|future release|roadmap|under development|slated for|later development phases)\b \*\*Engine:\*\* regex \*\*Scope:\*\* \*\*/\*.md, \*\*/\*.mdx, docs/\*\*/\*, guides/\*\*/\*, !docs/roadmap.md, !docs/wiki/roadmap.md, !docs/active*work.md \*\*Severity:\*\* warning Proactively remove references to planned features from user-facing guides. Excludes the project's own roadmap files (`docs/roadmap.md`, `docs/wiki/roadmap.md`) and internal tracking (`docs/active\_work.md`), where the literal word "roadmap" and references to upcoming work are by-design. *(style, curated)\_
- **Applying a "lean root" pattern to instruction files** - Applying a "lean root" pattern to instruction files prevents "Lost in the Middle" attention bias where agents forget rules buried in long documents. Moving details to linked sub-documents preserves reasoning capacity by loading specific context only when it becomes relevant to the task. _(prompts, context-management, architecture)_
- **When manually parsing CLI arguments, verify that a flag's** - \*\*Engine:\*\* ast-grep
  \*\*Severity:\*\* warning
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, !\*\*/\*.test.ts
  \*\*Pattern:\*\* `$A[$A.indexOf($B) + 1]`

When manually parsing CLI arguments, verify that a flag's. _(architecture, curated)_

- **Skip ReDoS checks for structural patterns** - \*\*Scope:\*\* scripts/benchmark-compile.ts Structural engines like ast-grep are inherently immune to ReDoS, allowing them to bypass the complex safety validation required for regex-based patterns. _(security, regex, ast-grep)_
- **Implementing a minimum character limit (e.g., 4) for custom** - Implementing a minimum character limit (e.g., 4) for custom secrets prevents the system from redacting common short strings like 'id' or 'key' that are not sensitive. _(dlp, validation)_
- **The @ast-grep/napi findAll method accepts both string** - \*\*Engine:\*\* ast-grep
  \*\*Severity:\*\* warning
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js
  \*\*Pattern:\*\* `$NODE.findAll(typeof $X === 'string' ? $Y : $Z)`

The @ast-grep/napi `findAll` method accepts both string patterns and `NapiConfig` objects natively. Avoid redundant `typeof` checks or manual branching when passing rules to the engine, as it handles the polymorphism internally. _(ast-grep, typescript, api-design)_

- **Design availability probes to never throw** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\* Availability probes should catch all network and status errors to return a simple boolean. This prevents diagnostic tools or fallback chains from crashing due to environmental network issues. _(api-design, error-handling)_
- **Performance-optimized paths that analyze diff deltas** - Performance-optimized paths that analyze diff deltas must still apply global ignore patterns to prevent the inadvertent processing of excluded files like lockfiles. _(architecture, git)_
- **AI tool metadata must treat MCP-related fields as optional** - AI tool metadata must treat MCP-related fields as optional to accommodate agents like GitHub Copilot that support instruction files but lack Model Context Protocol capabilities. _(architecture, mcp, copilot)_
- **Operations like store.count() can throw after heavy inserts** - Operations like store.count() can throw after heavy inserts or FTS rebuilding; wrapping these in try/catch prevents reporting a successful sync as a failure. _(database, lancedb)_
- **Using split() on markdown headings often misclassifies** - \*\*Pattern:\*\* \.split\(\s\*(?:\/\^?#+|['"]\^?#+)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* warning

Using split() on markdown headings often misclassifies. _(architecture, curated)_

- **Match error and success response formats where possible** - Error responses should match the success-path response format where client compatibility allows. Inconsistent structures can break downstream automated consumers. Exception: MCP tools may intentionally use plain-text error responses for client compatibility. _(error-handling, xml, api)_
- **Maintain consistent test file exclusions** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts Keep test file exclusions consistent across all adapter handlers to satisfy the 'Solo Dev Litmus Test' for predictability. Avoid refactoring these systemic patterns piecemeal in feature PRs to prevent inconsistent rule application. _(architecture, testing, eslint)_
- **Extract logic that wraps unknown errors** - Extract logic that wraps unknown errors into domain-specific exceptions with recovery hints into a centralized helper. This ensures consistent error reporting across different implementations and prevents the double-wrapping of custom error types. _(architecture, error-handling, dx)_
- **Verify lifecycle state enforcement** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Ensure that lifecycle state changes are verified through the full execution pipeline to prevent 'placebo' features where metadata updates have no actual runtime effect. _(testing, lifecycle)_
- **Test regex escaping with character classes** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Validate regex escaping by interpolating the output into a character class in a test to ensure metacharacters do not trigger range behavior. _(testing, regex)_
- **Guard against late-surfacing dynamic import failures** - \*\*Scope:\*\* packages/core/src/embedders/\*\*/\*.ts Dynamic imports placed inside execution methods rather than constructors can bypass initialization-time fallback logic, deferring environment errors until the first call. _(architecture, error-handling)_
- **Set LLM temperature to zero during build** - Set LLM temperature to zero during build or rule-compilation steps to prevent non-deterministic output that would invalidate manifest hashes and break CI attestation. _(security, llm, devops)_
- **Synchronize caches in override paths** - \*\*Scope:\*\* packages/cli/src/commands/shield.ts Override completion paths must update the same state caches as passing paths to prevent users from being blocked by stale gate checks. _(cli, cache, state-management)_
- **Reference correct phases in workflow documentation** - \*\*Scope:\*\* .claude/skills/preflight/SKILL.md Accurately identifying the specific phase where triage decisions occur prevents developers from skipping necessary steps or misinterpreting the workflow. _(documentation, dx)_
- **Avoid bypassing visibility checks with bracket notation** - \*\*Pattern:\*\* \[['"][a-zA-Z\_]\w\*['"]\]\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx
  \*\*Severity:\*\* warning

Avoid bypassing visibility checks with bracket notation. _(style, curated)_

- **2026-03-06T03:36:17.521Z** - \*\*Pattern:\*\* \.(where|delete)\s\*\(\s\*(?:'[^']\*"[^"]+"[^']\*'|"[^"]\*\\"[^"]+\\"[^"]\*"|`[^`]\*"[^"]+"[^`]\*`)\s\*\)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/core/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

SQL WHERE/DELETE clauses must use parameterized queries, not string interpolation. _(architecture, curated)_

- **GitHub Closes keyword only applies to the first issue** - \*\*Pattern:\*\* \b(?:[Cc]loses?|[Cc]losed|[Ff]ix(?:es|ed)?|[Rr]esolves?|[Rr]esolved)\s+#\d+\s\*,\s\*#\d+ \*\*Engine:\*\* regex \*\*Scope:\*\* \*\*/CHANGELOG.md, .github/\*\*/\*.md, .changeset/\*.md \*\*Severity:\*\* warning # GitHub `Closes` keyword only applies to the first issue in a comma-separated list ## What happened PR #1022 used `Closes #1006, #1005, #1007, #989, #991` in the body. Only #1006 was auto-closed on merge. The remaining 4 issues stayed open and had to be manually closed a session later. ## Root cause GitHub requires the closing keyword to be repeated for each issue reference. `Closes #1006, #1005, #1007` only closes #1006. The correct syntax is `Closes #1006, closes #1005, closes #1007`. The same trap applies to `Fixes` and `Resolves`. ## Rule When writing PR bodies, changelog entries, or changesets that reference multiple issues, repeat the keyword for every issue number: `Closes #1006, closes #1005, closes #1007, closes #989, closes #991` \*\*Example Hit:\*\* `Closes #100, #200, #300` — only #100 gets closed \*\*Example Miss:\*\* `Closes #100, closes #200, closes #300` — all three get closed \*\*Source:\*\* mcp (added at 2026-03-27T17:43:36.175Z); salvaged as a Pipeline 1 manual pattern on 2026-04-06 after inline-example verification failed during the 1.13.0 postmerge compile (mmnto/totem#1234). _(github, pr-workflow, closes-keyword, auto-close, trap)_
- **Refresh manifests on pure input hash drift** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Ensure manifests are updated when input hashes change even if output is identical, preventing verification failures in downstream hooks. _(architecture, integrity)_
- **LLM compilation should be last resort for rule gen** - When generating enforcement rules from lessons, prefer deterministic methods over LLM generation. The priority stack should be: (1) Programmatic AST extraction from code examples — parse the example with Tree-sitter and mechanically derive the pattern, zero LLM required. (2) Template classification — the LLM classifies intent against a library of known pattern templates and fills parameters, reducing its job from syntax generation to classification. (3) LLM free-form generation — only when no code example or matching template exists. (4) Explicit failure with reasoning — if all paths fail, tell the user why. During the 1.6.0 stress test, the LLM compiler produced 0/6 usable rules from well-written lessons on a clean external repo, while the deterministic enforcement engine (totem lint) was rock solid. Classification is what LLMs excel at; syntax generation is where they hallucinate. \*\*Source:\*\* mcp (added at 2026-03-28T17:12:19.312Z) _(compiler, architecture, stress-test)_
- **Using Zod's .passthrough() on registry schemas allows older** - Using Zod's `.passthrough()` on registry schemas allows older versions of the CLI to remain compatible with newer metadata fields added by updated versions. _(schema, zod)_
- **Reference root dependencies with $TURBO_ROOT** - \*\*Scope:\*\* turbo.json Use the '$TURBO*ROOT/' prefix in turbo.json to declare dependencies on files outside the package workspace, such as agent instructions or repository hooks. This ensures tests reading these files via root-relative paths are correctly cached. *(turbo, monorepo)\_
- **Export interfaces for custom error fields** - \*\*Scope:\*\* packages/core/src/sys/\*\*/\*.ts, !\*\*/\*.test.\* Export interfaces for additional fields attached to custom Errors to allow downstream consumers to perform type-safe error handling without casting to any. _(typescript, dx)_
- **Do not use movie references or metaphorical names (e.g.,** - Do not use movie references or metaphorical names (e.g., `INCEPTION\_TOP`) for code constants. Descriptive names like `WOBBLING\_TOP\_SPINNER` ensure immediate comprehension for all developers without requiring external cultural context. _(style-guide, naming)_
- **Every stage of a multi-gate security hook must explicitly** - Every stage of a multi-gate security hook must explicitly check for its own prerequisites to provide clear 'how-to-fix' guidance. Relying on silent failures in downstream commands creates an inconsistent and confusing user experience. _(devops, security, ux)_
- **When using Tree-sitter in WebAssembly environments, objects** - When using Tree-sitter in WebAssembly environments, objects like queries, trees, and parsers must be explicitly cleaned up using the .delete() method. This is required because the JavaScript garbage collector cannot see or manage memory allocated within the WASM heap, leading to leaks if not manually handled. _(wasm, tree-sitter, memory-management)_
- **The fileGlobs array can contain objects for ast-grep rules,** - The fileGlobs array can contain objects for ast-grep rules, so utility functions must verify entries are strings before calling string-specific methods like startsWith. _(typescript, glob, ast-grep)_
- **Curated lessons are exempt from hash-name filenames** - When reviewing a PR that adds a file under `.totem/lessons/` with a descriptive name (e.g., `lesson-agent-orientation.md`, `lesson-error-cause-chain.md`, `dev-environment-setup.md`), DO NOT flag the filename as violating the `lesson-XXXXXXXX.md` hash-name convention documented in `.gemini/styleguide.md` §11. The hash-name convention describes the OUTPUT of the `totem extract` pipeline — when an extracted lesson's filename uses 8 chars of `sha256(file\_content)`. It is NOT a universal directory mandate. Curated lessons (manually authored by maintainers, often Yellow / non-compilable) use descriptive kebab-case names and have been the established convention since the project shipped, with 14+ examples in tree as of `mmnto-ai/totem#1836`. The export pipeline (`exportLessons` in `compile.ts`) reads heading + body from the file, not from the filename, so both naming conventions coexist without pipeline impact. Verification before flagging: `ls .totem/lessons/ | grep -v '^lesson-[a-f0-9]\{8\}\.md$'` returns the curated set. If the file under review fits the curated shape (descriptive name, often Yellow classification, manually authored), the filename is correct — do not flag. Origin: `mmnto-ai/totem#1836` R3 GCA finding (HIGH) on `lesson-agent-orientation.md` filename. Declined empirically: §11 documents hash-naming for hash-named files (cite the formula `sha256(full\_file\_content).substring(0, 8)`), not a universal mandate, and 14+ pre-existing curated lessons demonstrate the precedent. Styleguide §11 amended in same PR to add an explicit "Curated lessons are exempt from hash-named filenames" subsection. _(review-guidance, lesson-files, naming-conventions, gca-decline, curated)_
- **Prefer Monitor over Bash sleep loops** - \*\*Scope:\*\* CLAUDE.md Using the Monitor tool instead of shell polling loops prevents unnecessary cache context consumption during wait periods. Shell-based 'sleep; check' patterns burn tokens and context window on every iteration. _(claude, tooling, performance)_
- **Prompt-level guardrails often fail to override evidence** - Prompt-level guardrails often fail to override evidence found in raw source data like git logs. Stripping misleading references at the data level before and after LLM processing is more effective than relying on negative instructions or glossaries. _(llm, documentation, git)_
- **Spying on underlying implementation details** - Spying on underlying implementation details like `console.error` instead of the project's public logging utility makes tests fragile to internal changes. Targeting the higher-level API ensures tests remain robust even if the logging library's transport mechanism or internal implementation changes. _(testing, mocking, logging)_
- **Using 'git merge-base --is-ancestor' allows a tool** - Using 'git merge-base --is-ancestor' allows a tool to distinguish between simple new commits and complex rebases. This prevents unnecessary invalidation of status flags when the current HEAD is a direct descendant of the previously verified commit. _(git, performance)_
- **Use file-level locking when updating global workspace** - Use file-level locking when updating global workspace registries to prevent race conditions and data corruption during concurrent synchronizations. _(concurrency, registry, node.js)_
- **When deferring a bot optimization suggestion as "premature"** - When deferring a bot optimization suggestion as "premature" (e.g., combining regex into one pass for a single-entry array), document the trigger condition for when it becomes worthwhile. Without this, deferred patterns accumulate silently and are rediscovered from scratch later. Tag deferred optimizations with a concrete threshold: "revisit when list exceeds N entries." _(deferred-optimization, code-review, process, trap)_
- **Lazy-load CLI commands per ADR-072** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* CLI commands must use `await import()` for lazy-loading as mandated by ADR-072 §3. Rules that forbid dynamic imports in command bodies contradict this canonical reference and must be archived. _(cli, architecture, performance)_
- **Wrap untrusted lesson content in XML delimiters** - Injecting untrusted lesson content directly into a system prompt creates a risk of instruction leakage or prompt injection. Wrapping this data in explicit XML delimiters and instructing the model to treat the blocks as data ensures that instructions within the content are not interpreted as system commands. _(security, llm, prompt-engineering)_
- **Rationale for additive schema changes as minor** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.ts Changing a schema to a discriminated union can be treated as a minor version if the success path is additive and the field is primarily consumed as human-readable text rather than by programmatic JSON parsers. _(versioning, api-design)_
- **Choosing simpler patterns that align with enforced codebase** - Choosing simpler patterns that align with enforced codebase styles is better than complex regex that covers unused syntax. This reduces the technical debt of maintenance without sacrificing practical accuracy in specific environments. _(regex, maintainability, linting)_
- **Material updates to system prompts should be accompanied** - Material updates to system prompts should be accompanied by an explicit version increment to ensure cached prompt states are invalidated. This prevents the persistence of stale logic or incorrect command definitions in downstream workflows. _(prompts, versioning, reflex)_
- **Rename general callbacks when scope narrows** - Rename general-purpose callbacks like `onWarn` if their scope narrows to specific events like file skipping due to architecture changes. Precise naming prevents developer confusion regarding whether a callback handles core execution failures or peripheral metadata warnings. _(api-design, refactoring, dx)_
- **Prefer semantic limits over line counts** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use character and directive counts instead of line counts for LLM instruction limits, as LLMs consume tokens and semantic density rather than physical lines. _(llm, dx, testing)_
- **Use byte-level binary size checks** - \*\*Scope:\*\* packages/cli/build/\*.sh, .github/workflows/\*.yml, .github/workflows/\*.yaml \*\*Pattern:\*\* `\[\[?\s\*"?\$[A-Z\_]\*MB[A-Z\_]\*"?\s+-(?:gt|ge|lt|le|eq|ne)\s+\d+` \*\*Engine:\*\* regex \*\*Severity:\*\* error When enforcing binary size limits — including shell blocks embedded in GitHub Actions workflow YAML — never compare a megabyte-truncated variable (e.g. `$MB` or `$SIZE\_MB`) against a numeric limit. Integer division truncates, so a 90.9 MB binary becomes `MB=90` and slips past a `[ "$MB" -gt 90 ]` check. Define byte-valued threshold variables (e.g. `HARD\_LIMIT=$((90 \* 1024 \* 1024))`) and compare the raw byte count (`$SIZE`, `$BYTES`) against them. Computing `MB` for display is fine; comparing it is not. \*\*Example Hit:\*\* `if [ "$MB" -gt 90 ]; then echo too big; fi` \*\*Example Miss:\*\* `if [ "$SIZE" -gt "$HARD\_LIMIT" ]; then echo too big; fi` _(bash, ci, build, workflow)_
- **Junie requires specific file locations for auto-detection,** - Junie requires specific file locations for auto-detection, specifically placing MCP configurations at .junie/mcp/mcp.json (gitignored) and tool-specific guidelines at .junie/guidelines.md. _(junie, configuration, jetbrains)_
- **Decouple submodule bumps from documentation refreshes** - \*\*Scope:\*\* .strategy Isolate submodule pointer updates from high-level documentation changes (like active work logs) to allow the pointer movement to be audited independently without unrelated noise. _(git, workflow, documentation)_
- **Standard glob matchers often handle brace expansion** - Standard glob matchers often handle brace expansion inconsistently across different environments or library versions. Manually expanding groups like `{ts,tsx}` into discrete patterns before processing ensures comprehensive file coverage and prevents silent omissions in analysis pipelines. _(glob, nodejs, automation)_
- **Assert per-family coverage for compound rules** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Aggregate match counts in tests can hide regressions in specific sub-patterns; verify that every distinct logic family (e.g., `atob`, `Buffer`, `fromCharCode`) in a compound rule triggers at least one match. _(testing, security)_
- **Restrict property regex to member-access contexts** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts When converting property restrictions to regex, patterns must explicitly match dot or bracket notation (e.g., `obj.prop` or `obj['prop']`). This prevents false positives where a forbidden property name appears as a standalone variable or part of a different identifier. _(regex, javascript, eslint)_
- **Node's spawn() emits resolution errors via the 'error'** - Node's spawn() emits resolution errors via the 'error' event on the child process, meaning a standard try/catch block will fail to capture asynchronous failures like command-not-found. _(node, spawn, error-handling)_
- **GitHub comments are capped at 65,535 characters; truncating** - GitHub comments are capped at 65,535 characters; truncating both total table rows and individual cell strings prevents silent API failures on large linting outputs. _(github-api, markdown)_
- **In CLI modules with mixed exports, only dependencies** - In CLI modules with mixed exports, only dependencies required by synchronous functions should remain as static imports. Utilities used exclusively by async handlers should be dynamically imported or injected to prevent bloating the eager dependency graph during startup. _(performance, architecture)_
- **Offload build/test to subagents for context** - Offloading high-volume text tasks like build and test verification to subagents can save significant context window space (e.g., 30-40KB) for the primary agent. This allows the main agent to focus on high-level strategy and code generation without being overwhelmed by verbose diagnostic output. _(ai, workflow, performance)_
- **Material updates to system prompts should include explicit** - Material updates to system prompts should include explicit version identifiers to help correlate changes in agent behavior with specific prompt iterations. This allows developers to debug regressions in output quality or adherence to strict execution gates that otherwise appear as random model fluctuations. _(prompt-engineering, observability, agents)_
- **When implementing custom error handlers that suppress stack** - When implementing custom error handlers that suppress stack traces for cleaner output, always include a debug environment variable to restore full traces for developers. This ensures that the improved end-user UX does not hinder troubleshooting of legitimate internal failures. _(cli, debugging, errors)_
- **Using synchronous file operations like fs.readFileSync** - Using synchronous file operations like `fs.readFileSync` inside an asynchronous execution loop blocks the Node.js event loop and degrades system throughput. Always use `fs.promises.readFile` when the surrounding context is already asynchronous. _(nodejs, performance, io)_
- **When refactoring a single instruction file into a root file** - When refactoring a single instruction file into a root file plus sub-documents, update consistency tests to recursively read and concatenate all fragments before comparison. This ensures that cross-agent rule validation remains effective even when the documentation structure diverts from a simple single-file pattern. _(testing, nodejs, documentation)_
- **Distinguish lint format from json flags** - \*\*Scope:\*\* README.md The --format flag is exclusive to the lint command, while other CLI commands use a standard --json flag for scripting output. _(cli, dx)_
- **Guard review cache against forecast runs** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Deterministic estimates or forecasts must not stamp the push-gate review cache. Stamping the cache during a prediction run would allow subsequent push-gates to skip mandatory LLM verification. _(cli, caching, security)_
- **Dynamic imports prevent heavy dependencies from degrading** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Dynamic imports prevent heavy dependencies from degrading the CLI's global startup latency. Restricting these imports to command entry points ensures that utility and adapter layers remain straightforward while the CLI remains responsive. _(cli, architecture, performance)_ _(archived: Globs `packages/cli/src/\*\*/\*.ts, !packages/cli/src/commands/\*\*/\*.ts` are over-broad: they match the CLI root entry files packages/cli/src/index.ts and index-lite.ts, which is precisely where ADR-072 §3 (PR #945) places lazy-loads of command handlers. Rule fires on every canonical `const { cmd } = await import('./commands/foo.js')` line in the two CLI bin entry files. Canonical utility-layer coverage retained via rules a1fd35ee696110b0 (utils/adapters/lib) and f6739f9ad356067a (utils/lib/helpers), which use correctly narrow globs. Archived via #1517.)_
- **Do not manually edit machine-generated artifacts** - \*\*Pattern:\*\* ^.+$
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/compiled-rules.json
  \*\*Severity:\*\* error

Do not manually edit machine-generated artifacts. _(architecture, curated)_ _(archived: Over-broad fileGlob. Pattern `^.+$` plus glob `\*\*/compiled-rules.json` fires on every line of every `compiled-rules.json` anywhere in the repo, including hand-authored pack scaffolds (e.g. packages/pack-agent-security/compiled-rules.json added in #1484). Original intent was to protect only the root-level machine-generated `.totem/compiled-rules.json` from manual edits. Archived pending a narrowed replacement rule scoped to `.totem/compiled-rules.json` only.)_

- **Preserve totem-context prefix for lint suppression** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* The `// totem-context:` prefix is a load-bearing directive for lint suppression; AI suggestions to replace it with 'SAFETY INVARIANT' should be merged into the comment body to maintain lint-clean status. _(dx, linting, adr-071)_ _(archived: Pattern fires on every '// SAFETY INVARIANT' comment but lesson's real scope is the narrower case where a totem-context: directive is already present (e.g. anthropic-orchestrator.ts:76, gemini-orchestrator.ts:71, mcp/src/context.ts:367 are all legitimate bare-SAFETY-INVARIANT uses with no underlying lint rule to suppress))_
- **Use engines for version-tool-immune constraints** - \*\*Scope:\*\* packages/\*\*/package.json The `engines` field is npm-canonical for constraints and immune to Changesets fixed-group auto-bumps, preventing unintended major version cascades in sibling packages. _(npm, changesets, architecture)_
- **When searching for numeric IDs like ticket numbers, always** - When searching for numeric IDs like ticket numbers, always use word boundaries or non-digit anchors. This prevents false positives where a short ticket ID (e.g., '12') incorrectly matches a substring of a longer ID (e.g., '123'). _(regex, grep)_
- **Convert top-level static imports to dynamic import() calls** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Convert top-level static imports to dynamic `import()` calls inside command handler functions to reduce CLI startup latency. This ensures the Node.js runtime only loads heavy dependency graphs and utility modules when the specific command requiring them is actually executed. _(cli, performance, nodejs)_ _(archived: Over-broad: astGrepPattern `import $NAME from '$MODULE'` fires on every top-level default import in packages/cli/src/commands/\*\*. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Automated gates like pre-commit or pre-push hooks** - \*\*Pattern:\*\* \bshield\b(?!.\*--deterministic)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* .pre-commit-config.yaml, .husky/\*\*/\*, package.json, lint-staged.config.\*, .lintstagedrc\*, Makefile, \*.sh
  \*\*Severity:\*\* error

Automated gates like pre-commit or pre-push hooks. _(architecture, curated)_

- **Switching embedding providers without rebuilding the index** - Switching embedding providers without rebuilding the index often results in cryptic Rust panics in vector databases like LanceDB. Implementing a health check that compares expected versus stored dimensions on the first query allows the system to provide actionable recovery instructions. _(lancedb, embeddings, mcp)_
- **Using child.kill() on Windows when shell: true is enabled** - Using `child.kill()` on Windows when `shell: true` is enabled only terminates the `cmd.exe` wrapper, leaving the actual application as a zombie process. To prevent process leaks during timeouts, use `taskkill /T /F` to ensure the entire process tree is destroyed. _(windows, nodejs, process-management)_
- **Log optional component failures at the warn level rather** - Log optional component failures at the `warn` level rather than using dimmed or silent logs to ensure that environmental misconfigurations are discoverable. Even when a system is designed for graceful degradation, failures should be visible enough to aid debugging. _(logging, observability, cli)_
- **In the DataFusion SQL dialect, backslashes are treated** - In the DataFusion SQL dialect, backslashes are treated as literal characters rather than escape sequences, so string literals must be sanitized by doubling single quotes. _(sql, datafusion, security)_
- **Framing the architecture as Sensors versus Actuators** - Framing the architecture as Sensors versus Actuators clarifies that the tool provides codebase measurements while users implement the specific enforcement logic. This prevents confusion regarding where the boundary of the tool ends and user-defined policy begins. _(architecture, design-patterns)_
- **Sanitize ANSI codes in logged messages** - \*\*Scope:\*\* packages/cli/src/commands/first-lint-promote-runner.ts Strip ANSI escape codes and control characters from user-provided strings before logging to prevent terminal injection and maintain log file integrity. _(security, logging)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 46 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/build/esbuild-lite.mjs, packages/cli/src/commands/add-lesson.ts, packages/cli/src/commands/config.ts, packages/cli/src/commands/doctor.ts, packages/cli/src/commands/drift.ts (+ 41 more). reasonCode: stage4-out-of-scope-match.)_
- **Separate fast, pattern-based checks into a "lint" command** - Separate fast, pattern-based checks into a "lint" command while reserving "shield" for thorough AI-powered analysis. Naming commands based on user intent (speed vs. depth) rather than underlying implementation (static rules vs. LLM) reduces cognitive load and aligns with industry-standard terminology. _(architecture, dx, naming)_
- **Do not filter out non-bot comments before grouping findings** - Do not filter out non-bot comments before grouping findings into threads, as human replies provide the necessary context to determine if a bot's suggestion was resolved or rejected. _(github-api, logic)_
- **Injecting manual content into all prompt contexts causes** - Injecting manual content into all prompt contexts causes LLMs to redundantly include that content in every generated document regardless of relevance. Scoping content injection to specific target files prevents pollution of internal documentation with sections intended only for user-facing docs. _(llm, prompt-engineering, documentation)_
- **AI agent memory config architectures differ significantly** - \*\*Pattern:\*\* \.gemini/gemini\.md|\.mcp\.json|\bgemini\.md
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.json, \*\*/\*.yaml, \*\*/\*.yml, \*\*/\*.md, \*\*/\*.sh, .gemini/\*\*/\*, .junie/\*\*/\*, .github/workflows/\*\*/\*
  \*\*Severity:\*\* warning

AI agent memory config architectures differ significantly. _(style, curated)_

- **When using dependency injection that mutates module-global** - When using dependency injection that mutates module-global state, wrap the execution in a try-finally block to restore the original state and prevent callback leakage across tests. _(testing, logging, architecture)_
- **False positives often stem from overly broad or duplicate** - False positives often stem from overly broad or duplicate rules produced during compilation rather than bugs in the underlying glob matching utility. Always inspect the generated rule artifacts to confirm scope and quantity before troubleshooting core matching functions. _(debugging, glob-matching, totem-compile)_
- **Include rule context in skipped metadata** - \*\*Scope:\*\* packages/core/src/rule-tester.ts, packages/cli/src/commands/test-rules.ts Skipped items should carry identifying metadata like hashes and headings to enable accurate downstream filtering. This ensures CLI warnings remain relevant to the user's active filter instead of cluttering the output with unrelated stubs. _(testing, cli, metadata)_
- **Always restore global or module-level handlers, such** - Always restore global or module-level handlers, such as custom warning listeners, in an afterEach block to prevent cross-test state leakage. _(testing, typescript, architecture)_
- **Wrap interactive prompts within batch loops in try/catch** - Wrap interactive prompts within batch loops in try/catch blocks to prevent a prompt library failure or environment error from crashing the entire command. This ensures the CLI can skip the problematic item and continue processing the rest of the batch. _(cli, error-handling, ux)_
- **Avoid refactoring production for test ergonomics** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Prioritize production code cleanliness over test ergonomics by using global spies (e.g., vi.spyOn) instead of forcing dependency injection for simple probes. _(testing, architecture)_
- **Avoid naive substring matching when extracting counts** - Avoid naive substring matching when extracting counts or metrics from source code; anchor regexes to object properties (e.g., `lessonHash\s\*:`) to prevent counting occurrences in comments, imports, or type definitions. _(regex, documentation, metrics)_
- **Use canonical CLI command forms** - \*\*Scope:\*\* docs/wiki/\*.md Prefer canonical noun-verb command forms (e.g., `totem lesson extract`) in documentation over deprecated bare aliases to avoid reinforcing legacy or hidden interfaces. _(cli, documentation)_
- **Rule engines that use concrete source code patterns,** - Rule engines that use concrete source code patterns, like `ast-grep`, are significantly easier for LLMs to generate accurately than abstract syntax trees or regex. This structural similarity reduces the hallucination rate when AI agents are tasked with creating custom linting or transformation rules. _(llm, ast-grep, dx)_
- **Moving static imports of heavy internal packages** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Moving static imports of heavy internal packages into dynamic `await import()` calls inside specific command handlers significantly reduces CLI startup latency. This ensures that dependencies are only loaded into memory when the user actually executes that specific command. _(nodejs, cli, performance)_
- **Verify caching via full round-trip tests** - \*\*Scope:\*\* packages/cli/src/utils.test.ts Tests should execute actual write-then-read cycles against a temporary directory to catch logic mismatches between the cache writer and reader that local hash reconstruction might miss. _(testing, caching)_
- **Allow inline literals for test timeouts** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.test.ts The 'no magic numbers' rule does not apply to test infrastructure configuration like timeouts; keeping them inline avoids unnecessary indirection while the key name provides sufficient documentation. _(dx, styleguide, testing)_
- **Gate architectural work with design docs** - \*\*Scope:\*\* .claude/skills/preflight/SKILL.md Architectural changes require a short design doc to catch data model and failure mode issues that otherwise lead to expensive multi-round review cycles. _(architecture, process, dx)_
- **Verify gate ordering in short-circuit tests** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.test.ts Tests for mutex flags should explicitly assert that downstream side-effects, like configuration loading, were never triggered to verify the validation gate's position. _(testing, architecture)_
- **When reviewing PR diffs that add a new return-statement** - When reviewing PR diffs that add a new return-statement to a function with an existing typed return interface, do not suggest adding fields to the return object based on cross-surface name similarity (e.g., "the manifest tracks `rule\_count`" or "the `LintResult` expects `ruleCount`"). Verify the actual TypeScript interface bytes before recommending a field addition. The compiler is the authority: if a field is genuinely required, `tsc` rejects the omission at compile time, and a green test suite on the diff is empirical proof the type is satisfied. Two surfaces with similar names — one a write-side manifest field, one a runtime result type — are not contracts that need to be reconciled inside the result type. Empirical example (mmnto-ai/totem#1832 R1): GCA recommended adding `ruleCount: 0` to a `RunCompiledRulesResult` early-return object on the grounds that `compile-manifest.json` carries `rule\_count`. The interface at `run-compiled-rules.ts:36-49` defines five fields (`violations | findings | rules | output | regexTimeouts`); no `ruleCount` field exists, the manifest field is write-side telemetry only, and the count is already exposed via `rules.length`. Decline protocol: cite the interface line range with bytes, point at the type-checker as authority, and capture the rule in `.gemini/styleguide.md` §6 so the same hallucination does not surface on future reviews of the same module. \*\*Source:\*\* mcp (added at 2026-05-06T00:08:46.825Z) _(review-guidance, gca-decline, type-system, interface-contracts, lint-runner)_
- **Hash dirs with git ls-files for cross-platform stability** - Hashing directory contents via `git ls-files -s` and `git hash-object` provides immunity to CRLF/LF line-ending drift across Windows, Linux, and macOS. This creates a more reliable cryptographic lock for CI fixtures than standard filesystem-based hashing. _(git, ci, cross-platform)_
- **Use /loop for state-change reactions** - \*\*Scope:\*\* CLAUDE.md Utilize self-paced /loop commands for reacting to future state changes like CI status. This offloads scheduling to the harness rather than forcing the agent to manually check and react. _(claude, workflow, automation)_
- **2026-03-05T04:05:19.420Z** - \*\*Pattern:\*\* const\s+\w+\s\*=\s\*/(?![^])https\?:
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

URL regex patterns must anchor with ^ to prevent partial matches on malicious input. _(architecture, curated)_

- **Refine security rules at the source definition** - \*\*Scope:\*\* packages/pack-agent-security/test/\*\*/\*.ts Always address rule flaws by refining the source patterns or specs rather than manually editing `compiled-rules.json`, as manual changes are overwritten during the compilation cycle. _(architecture, security)_
- **Guard telemetry against unrelated execution flows** - \*\*Scope:\*\* packages/cli/src/commands/run-compiled-rules.ts Ensure telemetry collectors are guarded by specific context checks so that unrelated execution paths (like AST rules) do not pollute 'unknown' metric buckets intended for other flows. _(telemetry, architecture)_
- **Hardcoding specific filenames like active_work.md** - Hardcoding specific filenames like active*work.md in document-processing logic limits flexibility; use configuration flags to define behavior for different document targets. *(architecture, clean-code, configuration)\_
- **2026-03-06T04:31:54.888Z** - \*\*Pattern:\*\* \b(totem\s+learn|learn\()
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/triage/\*\*, \*\*/triage.\*, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

The totem learn command is deprecated; use totem extract instead. _(style, curated)_

- **Validate mutually exclusive phase flags** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts Hard-erroring when flags configure a skipped phase prevents silent no-ops and ensures users understand the boundaries between independent execution phases. _(cli, ux, validation)_
- **Account for slow Windows CI I/O** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.test.ts Orchestrator tests involving heavy file I/O or temporary directories may require increased timeouts (e.g., 15,000ms) on Windows CI to prevent intermittent failures caused by slow disk operations. _(ci, windows, testing)_
- **Generating IDs from violation properties like file, line,** - \*\*Pattern:\*\* \bid\s\*[:=]\s\*.\*\b(Date\.now|Math\.random|uuid|randomUUID)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Generating IDs from violation properties like file, line. _(architecture, curated)_

- **Named constants for file permission literals** - Defining named constants for file permissions (such as 0o644) instead of using inline magic numbers improves code readability and ensures compliance with internal security policies. This makes the intent of file access levels explicit and easier to audit across the codebase. _(security, filesystem, coding-standards)_
- **Detect existing hook managers and provide manual guidance** - \*\*Pattern:\*\* \.git\/hooks
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.js, \*\*/\*.ts, \*\*/\*.sh, \*\*/\*.bash, \*\*/\*.py, \*\*/\*.rb, \*\*/\*.go, !\*\*/\*.test.ts, !\*\*/\*.spec.ts
  \*\*Severity:\*\* warning

Detect existing hook managers and provide manual guidance. _(architecture, curated)_

- **Totem is Agent Governance, not an AI documentation writer** - # Totem is Agent Governance, not an AI documentation writer ## What happened The `totem docs` command was being positioned alongside `lint`, `shield`, and `extract` as a core feature. This confused the product pitch — solo devs thought they needed LLM API keys to use Totem. The real core product is the deterministic Enforce tier (lessons → compile → lint → hooks) which requires zero AI at runtime. ## Rule Never pitch `totem docs` as a core feature in user-facing copy (README, landing pages, quickstart guides). The core pitch is: "Write what you learned. It never happens again." — referring to the Enforce tier. Doc generation is a Tier 4 power-user feature for maintaining roadmap/active*work documents only. See ADR-078 for the official 5-tier product model. \*\*Source:\*\* mcp (added at 2026-03-27T21:24:26.248Z) *(product-positioning, messaging, readme, totem-docs, strategy)\_
- **Use major-minor cohorts for manifest versioning** - \*\*Scope:\*\* packages/core/\*\*/\*.ts Stamping manifests with a major.minor 'cohort' allows the engine to detect stale configurations while maintaining compatibility across patch-level engine updates. _(schema, versioning, dx)_
- **Normalize file paths for SQL LIKE clauses** - When using file paths in SQL `LIKE` clauses, normalize backslashes and explicitly escape `%` and `\_` characters to prevent accidental wildcard matching. This ensures a boundary search for a directory like `packages/core/` does not unintentionally match `packages/core-utils/`. _(sql, lancedb, security)_
- **When catching and re-logging errors that originate** - \*\*Pattern:\*\* (['"`])\[[^\]]+\].\*?\b(err|error)\.message\b(?!.\*\.replace)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx
  \*\*Severity:\*\* warning

When catching and re-logging errors that originate. _(style, curated)_

- **Defensively handle wrapped and raw ENOENT errors** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* When catching errors from utilities that wrap ENOENT, catch both the custom error class and the raw error to prevent silent failures if the utility is refactored. _(error-handling, node.js, fs)_
- **Avoid bypassing visibility checks with bracket notation** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Avoid bypassing visibility checks with bracket notation to call private initialization methods. Use a public static factory method to encapsulate asynchronous setup and dynamic imports, providing a clean and type-safe way to instantiate classes. _(typescript, architecture, async)_
- **When executing child processes via execSync with stdio:** - When executing child processes via `execSync` with `stdio: 'inherit'`, the child process's output is already streamed directly to the terminal. Adding explicit error messages in the parent's `catch` block often results in duplicate log output, cluttering the user's view of the actual failure reasons. _(nodejs, cli, ux)_
- **Minor version bumps (e.g., 1.4.x to 1.5.0) must be** - Minor version bumps (e.g., 1.4.x to 1.5.0) must be categorized under 'Minor Changes' rather than 'Patch Changes' to maintain semantic consistency across monorepo packages. _(release, semver, documentation)_
- **Detect project roots via local existence** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Use `fs.existsSync` to check for `.git` in the current directory; this correctly identifies both standard directories and the `.git` files used in worktrees, while avoiding incorrect parent-repo detection from traversal helpers. _(git, filesystem)_ _(archived: Pattern targets hallucinated function names (findGitRoot, findProjectRoot, findRoot, gitRoot, findUp) that don't exist in the codebase. The actual canonical traversal name is resolveGitRoot, which the pattern doesn't match. Rule wouldn't fire on real code.)_
- **Validate bash syntax during testing** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts Use `bash -n` in the test suite to catch syntax errors that would trigger an exit 2 before runtime EXIT traps can be installed. _(bash, testing, ci)_
- **Restricting attestation workflows to specific code paths** - Restricting attestation workflows to specific code paths prevents false CI failures on documentation-only PRs that do not produce the expected build artifacts. _(github-actions, ci-cd)_
- **Guard against conflicting upgrade and force flags** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts Explicitly reject the combination of --upgrade and --force flags to prevent accidental cache corruption. Since --force bypasses all cache checks, it contradicts the surgical nature of an upgrade and risks unintended side effects on the rest of the rule cache. _(cli, validation, safety)_
- **Escape metacharacters in RegExp interpolation** - Always escape metacharacters when interpolating dynamic strings into a `RegExp` constructor to ensure they are treated as literal matches. This prevents regex injection where malicious input could manipulate matching logic or trigger catastrophic backtracking. _(security, regex, javascript)_
- **Verify closure capture against compiler context** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Reviewer LLMs often lack outer-scope context and may incorrectly flag captured variables as ReferenceErrors. Verify these findings with `tsc` or empirical tests before modifying the architecture to satisfy the bot. _(dx, llm, typescript)_
- **Use deprecated aliases when renaming exported constants** - Use deprecated aliases when renaming exported constants to allow internal architectural alignment without breaking downstream consumers before a major release. _(api-design, typescript)_
- **Increment version constants whenever the content** - Increment version constants whenever the content of injected code blocks changes so that CLI tools can detect and refresh stale scaffolding in existing projects. _(dx, automation)_
- **Set exit codes instead of exiting** - \*\*Scope:\*\* packages/mcp/src/smoke-test.ts Calling process.exit(1) can terminate a Node.js process before stdout/stderr buffers are fully flushed. Setting process.exitCode and returning from the main function ensures all logs are captured in smoke tests. _(dx, cli, node)_
- **README files and curated wiki pages must be human-authored** - README files and curated wiki pages must be human-authored to ensure accuracy and maintain a high-quality source of truth. LLM-generated prose in these files can introduce subtle hallucinations that mislead contributors. _(documentation, policy, llm)_
- **Always verify that both stdin and stdout are TTY-enabled** - Always verify that both stdin and stdout are TTY-enabled before launching interactive prompts to prevent crashes or hanging in non-interactive environments. _(cli, ux)_
- **Target specific agent attack surfaces** - Zero-trust governance should enforce error-level severity on unauthorized process spawning, dynamic eval with non-literal arguments, and hardcoded network calls to mitigate prompt-injection risks. _(security, governance, prompt-injection)_
- **Warn on non-critical hook failures** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Post-scaffold hooks like git add or documentation injection should warn-and-continue rather than crashing to prevent leaving artifacts in a half-finished state. _(cli, ux, resilience)_ _(archived: Pattern `throw\_statement` inside `catch\_clause` fires on every re-throw in packages/\*\*/\*.ts, not just the post-scaffold-hook catches the lesson targets. Directly contradicts `lesson-fail-open-catch-ban` (bans silent-swallow semantics for non-terminal handlers). Terminal-handler refinement tracked in #1614. The lesson itself is valid guidance for scaffold-orchestrator code paths, but the context constraint (post-scaffold hooks only) cannot be captured structurally via ast-grep. Sibling class to #1598 (compile-worker context-sensitive lesson extraction gap). Archived during PR #1615 postmerge 2026-04-22.)_
- **Sanitize dynamic ast-grep identifiers** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts Identifiers starting with '$' or named '\_' trigger ast-grep meta-variable matching, leading to significant over-matching. Use a safety guard to fall back to regex for these specific patterns when generating rules dynamically. _(ast-grep, security)_
- **Git output parsing should account for localized strings** - Git output parsing should account for localized strings and special characters in filenames to ensure the tool remains reliable across different developer environments. _(git, cli)_
- **Wrap user-controlled fields like PR descriptions** - \*\*Pattern:\*\* (?=.\*\$\{.\*(?:description|comment|body|user\_?input|userInput).\*\})(?!.\*untrusted[ \_-]content)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/prompts/\*\*/\*, \*\*/ai/\*\*/\*, \*\*/llm/\*\*/\*, \*\*/\*prompt\*
  \*\*Severity:\*\* error

Wrap user-controlled fields like PR descriptions. _(security, curated)_

- **GitHub API responses often contain \r\n line endings, so** - GitHub API responses often contain `\r\n` line endings, so regex-based dividers must use `\r?\n` to prevent parsing failures on Windows-style or mixed line endings. _(github-api, regex, node.js)_
- **Doc regen LLMs persist phantom references** - LLM-powered document regeneration creates a self-reinforcing hallucination loop: the LLM reads its own prior output as context, sees stale issue numbers or closed ticket references, and faithfully reproduces them in the new version. Each regen cycle reinforces the phantom data. Fix: include explicit negative constraints in the doc target description (e.g., "only reference OPEN issues") and validate generated docs against live issue state. _(architecture, llm, documentation)_
- **Differentiating between \*/.ext and dir/\*.ext in LLM prompts** - Differentiating between `\*\*/\*.ext` and `dir/\*.ext` in LLM prompts prevents ambiguous output and ensures the model generates portable glob patterns that work across different environments. _(llm-prompting, globs)_
- **The project has transitioned from a 5-tier product model** - The project has transitioned from a 5-tier product model to a 3-tier capability model (Lite, Standard, Full), which defines the official architectural and feature boundaries. _(architecture, strategy)_
- **Narrow AST-grep constructor patterns** - \*\*Scope:\*\* packages/pack-agent-security/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Generic patterns like 'new $ERROR($$$ARGS)' match all class instantiations including Set or Date; use catch-block context and argument checks to target error wrapping specifically. _(ast-grep, linting, errors)_
- **Explicitly delete success flags when violations are found** - Explicitly delete success flags when violations are found or when the environment state (like HEAD SHA) cannot be determined to prevent stale state from bypassing gates. _(architecture, testing)_
- **Validate inputs before performing side effects** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Validating slugs and checking for collisions before any disk writes or process spawns prevents the creation of orphaned or corrupted artifacts. _(architecture, validation)_
- **Filesystem lockfile implementations must handle corrupted** - Filesystem lockfile implementations must handle corrupted lock files (empty, invalid JSON) separately from missing files. A corrupted file causes fs.writeFile with 'wx' flag to throw EEXIST, but readLock returns null — creating an unrecoverable retry loop. Check file age (mtime) before deleting to avoid TOCTOU races with concurrent writers. Tags: concurrency, filesystem, trap _(manual)_
- **Allow null branches for detached HEADs** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.test.ts Git state mocks and types must allow `currentBranch` to be null to correctly handle detached HEAD states frequently encountered in CI environments. _(git, ci, testing)_ _(archived: Pattern is a single-quote-only variant of a24ec7272f1f670e. Same test-scoped fileGlobs (packages/mcp/src/\*\*/\*.test.ts), same misfire on legitimate test-fixture construction, same authorial-guidance scope mismatch.)_
- **When scanning directories for feature detection** - When scanning directories for feature detection in monorepos, explicitly handle known missing paths (like ENOENT) while logging or rethrowing other system errors. Swallowing all errors in a catch block can mask permission issues or structural problems that prevent correct tool configuration. _(nodejs, filesystem, error-handling)_
- **Use stable names for linked indexes** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.ts Auto-injected links should use stable names (e.g., 'strategy') to maintain consistent boundary routing regardless of the physical source path or resolution method. _(architecture, mcp)_
- **Preserve cohort versions during package renames** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Renaming a package mid-lifecycle without a version bump preserves cohort coherence, even though the new package's registry history will start at the current version. _(versioning, changesets, npm)_
- **Include both quote styles in AST patterns** - \*\*Scope:\*\* packages/pack-agent-security/compiled-rules.json AST-grep patterns matching specific string literals (e.g., encoding types) must explicitly define both single and double quote variants to ensure robust detection. _(ast-grep, dx)_
- **Git diff headers wrap file paths containing spaces** - \*\*Pattern:\*\* (['"\/])\^?\+\+\+\s+b\\?\/
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.py, \*\*/\*.sh, \*\*/\*.go, \*\*/\*.rs
  \*\*Severity:\*\* error

Git diff headers wrap file paths containing spaces. _(architecture, curated)_ _(archived: Over-broad regex. The pattern matches any string literal containing "+++ b/" or "--- a/" regardless of whether the file path actually contains spaces, so it fires on every legitimate git-diff test fixture in core/cli/mcp test files. Multiple test files across the repo already have this pattern unchallenged because they predate the rule — only new test code trips it. Archived via the mmnto/totem#1345 loadCompiledRules filter after the self-healing loop was unlocked. Superseded by the broader ast-grep validation work tracked in mmnto/totem#1339. Kept in the manifest (not deleted) so telemetry on its historical triggers stays intact.)_

- **2026-03-08T00:56:41.780Z** - \*\*Pattern:\*\* expect\(.\*\.length\)\.(toBeGreaterThan|toBeLessThan)(OrEqual)?\(\d+\)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*.test.ts, \*.spec.ts
  \*\*Severity:\*\* warning

Avoid testing array length with comparison matchers; use toHaveLength for clarity. _(style, curated)_

- **Synchronous file operations are often preferable in CLI** - \*\*Pattern:\*\* \bfs\.(promises|readFile|writeFile|readdir|mkdir|rm|stat|access|appendFile|copyFile|rename|unlink)\b|['"]fs/promises['"]
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/\*\*/\*.ts, packages/cli/\*\*/\*.js, bin/\*\*/\*.ts, bin/\*\*/\*.js
  \*\*Severity:\*\* warning

Synchronous file operations are often preferable in CLI. _(performance, curated)_

- **Implementing bypass logic via GitHub Actions contains()** - Implementing bypass logic via GitHub Actions `contains()` expressions instead of shell-based parsing prevents potential shell injection surfaces. This ensures that PR metadata cannot be manipulated to execute arbitrary code during security gate checks. _(github-actions, security, devops)_
- **Reconnect all handles after sync operations** - \*\*Scope:\*\* packages/mcp/\*\*/\*.ts, !\*\*/\*.test.\* Database sync operations in linked repositories can leave stale pointers in the main process. Iterating and reconnecting all handles (primary and linked) ensures search results remain consistent without requiring a server restart. _(lancedb, mcp, resilience)_
- **Validate path resolution with chdir** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Simulate nested execution in tests by using process.chdir and mocking the configuration path to verify that path resolution logic correctly anchors to the config root. This ensures the tool remains robust in monorepo environments where the execution context is unpredictable. _(testing, monorepo, paths)_
- **Automated prose cleanup tools should be configured** - Automated prose cleanup tools should be configured to detect and exclude maintainer-authored manual snippets or specific documentation directories. This prevents deterministic replacement logic from accidentally "fixing" intentional human phrasing or technical manual content. _(documentation, dx, automation)_
- **AI agents often lose awareness of strict workflow** - AI agents often lose awareness of strict workflow requirements like mandatory TDD after context truncation or compaction. Explicitly restating that tests must pass before work advances in the post-compaction output strengthens agent discipline and prevents regression in development patterns. _(agents, workflow, tdd)_
- **Environment variables from the host machine can leak** - Environment variables from the host machine can leak into test runners, causing non-deterministic behavior or false positives. Tests must explicitly clear or mock sensitive environment variables (like API keys) to ensure they are not using host-level configuration. _(testing, environment, isolation)_
- **Mock package boundaries for cross-package tests** - \*\*Scope:\*\* packages/\*\*/\*.test.\* Vitest mocks of internal dependencies do not intercept imports within pre-built distribution files; mock the public package boundary instead to ensure interceptors bind correctly. _(testing, vitest)_
- **NEVER inline secrets, tokens, or API keys into agent config** - \*\*Pattern:\*\* "(?:[Aa]pi[Kk]ey|[Aa]pi\_?[Kk]ey|[Tt]oken|[Ss]ecret|[Pp]assword|[Aa]ccess\_?[Tt]oken|[Pp]at)"\s\*:\s\*"[^"]+"
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.mcp.json, \*\*/.gemini/settings.json, \*\*/mcp-config.json, \*\*/claude_desktop_config.json
  \*\*Severity:\*\* error

NEVER inline secrets, tokens, or API keys into agent config. _(security, curated)_

- **Audit root cause helpers for vulnerabilities** - When a security vulnerability is identified in a specific file, audit the lowest-level helper that enables it to address the root cause across the entire codebase. _(security, process)_
- **Always include POSIX shell rules** - \*\*Scope:\*\* packages/cli/src/commands/init.ts POSIX shell rules are included in all baseline packs because the tool's own git hooks are implemented in shell, ensuring infrastructure safety across all projects. _(shell, architecture, security)_
- **Avoid hardcoding "magic numbers" or specific counts** - Avoid hardcoding "magic numbers" or specific counts when automating file reverts in skills. Utilizing `git checkout HEAD` to restore a file to its last committed state is more robust than relying on static metrics that will inevitably drift as the project evolves. _(git, automation, maintainability)_
- **Material updates to LLM system prompts should include** - Material updates to LLM system prompts should include explicit version identifiers or timestamps within the prompt header. This enables tracking of behavior changes over time and ensures that agent deployments can be pinned to specific, validated logic versions. _(prompt-engineering, devops, versioning)_
- **Omit defensive XML escaping for prompt injection** - \*\*Pattern:\*\* \b(escapeXml|escapeHtml|encodeXml|formatXmlResponse)\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/\*\*/\*.ts, apps/cli/\*\*/\*.ts, \*\*/cli/\*\*/\*.ts
  \*\*Severity:\*\* error

Omit defensive XML escaping for prompt injection. _(security, curated)_

- **Use exit codes for CLI errors** - \*\*Scope:\*\* packages/cli/src/commands/\*.ts, !\*\*/\*.test.\* Prefer setting `process.exitCode` and logging via `log.error` over re-throwing exceptions in CLI command handlers. This aligns with standard CLI patterns and ensures clean output for the end user. _(cli, dx)_ _(archived: Duplicate of 95e66fb1 (same throw $ERR pattern, narrower scope). Both over-broad. upgradeTarget: compound. See #1218.)_
- **2026-03-08T00:11:33.219Z** - \*\*Pattern:\*\* process\.env\.[A-Z0-9\_]+\s\*(?:!==|!=)\s\*(?:undefined|null|['"]['"])
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx, \*\*/\*.js, \*\*/\*.jsx, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Environment variable checks must validate non-whitespace content, not just undefined/null. _(architecture, curated)_

- **Treat usage and token statistics as optional fields** - \*\*Pattern:\*\* \busage\s\*\.\s\*(prompt_tokens|completion_tokens|total_tokens)\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.tsx, \*\*/\*.jsx, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Treat usage and token statistics as optional fields. _(security, curated)_

- **Stabilize host-dependent integration tests** - \*\*Scope:\*\* packages/mcp/src/\*\*/\*.ts Use conditional runtime skips for integration tests that depend on optional host-level resources like strategy clones to prevent false failures. _(testing, mcp)_
- **When intercepting agent tool inputs via hooks, use specific** - When intercepting agent tool inputs via hooks, use specific regex patterns that look for both the command and its sub-arguments (e.g., `git` AND `push|commit`) to prevent false positives. Broad keyword matching can accidentally trigger hooks on natural language phrases that happen to contain reserved command names. _(regex, devtools, security)_
- **Redirecting hook command output to /dev/null prevents users** - Redirecting hook command output to /dev/null prevents users from diagnosing why a push was blocked; hooks should instead provide specific diagnostic hints or commands. _(git, dx, ux)_
- **When normalizing diverse SDK errors for internal retry** - \*\*Pattern:\*\* throw\s+new\s+\w\*Error\s\*\(\s\*.\*\b(e|err|error)\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/services/\*\*/\*, \*\*/clients/\*\*/\*, \*\*/integrations/\*\*/\*, \*\*/sdk/\*\*/\*, \*\*/adapters/\*\*/\*
  \*\*Severity:\*\* warning

When normalizing diverse SDK errors for internal retry. _(style, curated)_

- **Use a Personal Access Token (PAT) for automated PR creation** - Use a Personal Access Token (PAT) for automated PR creation if the organization restricts the default GITHUB*TOKEN from performing those actions. *(github-actions, security)\_
- **Preserve raw spawn output in errors** - \*\*Scope:\*\* packages/core/src/sys/exec.ts Store raw stdout and stderr in custom error objects before trimming them for human-readable messages. This ensures downstream consumers can access original whitespace or formatting if needed for programmatic parsing. _(dx, node)_
- **Implement graceful degradation for optional engines** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* When a heavy dependency like a WASM AST engine is unavailable, the system should skip dependent features with a warning rather than crashing. This allows 'lite' binaries to remain functional for non-AST tasks. _(architecture, dx)_
- **Verify directory existence during resolution** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts Each layer in a path resolution chain must be verified as a real directory using fs.statSync to prevent fall-through logic from accepting invalid or non-existent paths. _(fs, validation)_
- **Handle dollar signs in identifier boundaries** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts Standard word boundaries (`\b`) fail for JavaScript identifiers containing `$`. Using `(?:^|[^\w$])` as a prefix ensures that regex patterns correctly isolate identifiers without failing on valid special characters common in JS libraries. _(regex, javascript)_
- **Simple key-value string parsers often fail on standard YAML** - Simple key-value string parsers often fail on standard YAML list syntax like `[val1, val2]`. Explicitly checking for and stripping square brackets ensures that manually parsed frontmatter remains compatible with common configuration patterns without requiring a heavy external parser dependency. _(yaml, parsing, robustness)_
- **References to tools or Architecture Decision Records (ADRs)** - References to tools or Architecture Decision Records (ADRs) located in private submodules should not be flagged as broken. These resources are available in the full environment even if they are invisible to public-facing linting or search tools. _(git, architecture)_
- **Signal failure when safety filters drop all results** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* In non-interactive modes, if safety filters reject all generated output, the CLI must explicitly set a non-zero exit code before returning. This prevents CI/CD pipelines from incorrectly reporting success when the tool failed to produce valid results due to suspicion or validation checks. _(cli, ci-cd, error-handling)_
- **Always check which directory you're in after working** - # Always check which directory you're in after working in the strategy submodule ## What happened After committing and pushing to `.strategy/` (the git submodule), subsequent commands ran in the submodule directory instead of the main repo root. This caused `git branch` to show strategy branches, `git checkout` to fail finding main repo branches, and branch operations to target the wrong repository. ## Rule After any operation in `.strategy/`, immediately return to the repo root (`cd "$(git rev-parse --show-toplevel)"`) before running git commands. The submodule is a separate git repo with its own HEAD, branches, and remote. Commands that work in the submodule context will silently produce wrong results in the main repo context. \*\*Source:\*\* mcp (added at 2026-03-27T22:17:31.282Z) _(git, submodule, strategy, working-directory, trap)_
- **Use a case-insensitive regex with optional internal** - Use a case-insensitive regex with optional internal whitespace (e.g., /<\/\s\*tag\s\*>/i) when matching closing tags. Rigid literal matches are easily bypassed by LLMs or parsers, leading to prompt injection vulnerabilities. _(security, regex, llm)_
- **Escape triple backticks in Markdown regex** - \*\*Scope:\*\* .changeset/\*.md Regex patterns containing triple backticks can break Markdown rendering if not properly escaped. Ensure complex patterns inside changeset descriptions do not prematurely terminate code blocks. _(markdown, regex)_
- **Validate untrusted packs during first execution** - \*\*Scope:\*\* docs/wiki/pack-ecosystem.md A `pending-verification` lifecycle state ensures that newly installed packs are validated locally during the first run. This zero-trust approach prevents the silent execution of unverified rules while maintaining a smooth developer experience. _(security, governance, ux)_
- **When API adapters lack explicit 'isResolved' flags, use** - When API adapters lack explicit 'isResolved' flags, use text-based reply patterns (e.g., 'Fixed' or 'Dismissed') to infer the state of a discussion thread. _(github-api, heuristics)_
- **Normalize metadata before exact matching** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Lowercase and collapse whitespace in metadata fields like headings to catch duplicates that differ only by casing or formatting. _(normalization, dx)_
- **When generating ast-grep patterns, the pattern must be** - When generating ast-grep patterns, the pattern must be emitted as a plain code string rather than wrapped in backticks or template literal syntax. ast-grep parses patterns into AST nodes via tree-sitter; wrapping them in backticks causes the engine to match a template literal string node instead of the intended structural code expression. _(architecture, ast-grep, tooling)_
- **Lazy-load heavy configurations and services only** - Lazy-load heavy configurations and services only when a specific action is confirmed by the user. This prevents the entire CLI session from aborting due to configuration errors during unrelated tasks. _(cli, dx, performance)_
- **Use advisory headings for context-blind rules** - \*\*Scope:\*\* packages/cli/src/assets/baseline-typescript-new.ts Rule headings should use advisory language like 'Ensure wrapped' when the underlying regex cannot technically verify surrounding context like try-catch blocks. _(linting, regex, dx)_
- **Combine immediate per-finding 'Learn' actions** - Combine immediate per-finding 'Learn' actions with a post-triage batch extraction prompt. This balances the need for high-precision manual insight capture with the efficiency of LLM-driven deduplication for bulk findings. _(cli, ux, dx)_
- **To maintain reliable PR thread replies, the rootCommentId** - To maintain reliable PR thread replies, the rootCommentId must be preserved throughout the finding pipeline to ensure responses are correctly anchored to the original discussion. _(api, github, architecture)_
- **AI agent hook/lifecycle events by provider (as** - AI agent hook/lifecycle events by provider (as of 2026-03-15):

## Claude Code (17+ events)

Config: Claude Code settings JSON → `hooks` object. Scripts in project hooks directories.

- \*\*SessionStart\*\* — session begins or resumes
- \*\*UserPromptSubmit\*\* — before Claude processes a user message (can block, can inject additionalContext)
- \*\*PreToolUse\*\* — before a tool call; can deny/allow via `permissionDecision` (matcher filters by tool name)
- \*\*PermissionRequest\*\* — when a permission dialog appears; can auto-allow/deny
- \*\*PostToolUse\*\* — after tool succeeds (informational)
- \*\*PostToolUseFailure\*\* — after tool fails (informational)
- \*\*Stop\*\* — when Claude finishes responding (can block to force more work)
- \*\*SessionEnd\*\* — session terminates
- \*\*SubagentStart\*\* / \*\*SubagentStop\*\* — subagent lifecycle
- \*\*PreCompact\*\* — before context compaction
- \*\*Notification\*\* — system alerts
- \*\*WorktreeCreate\*\* — worktree operations
- Plus additional events for tasks, config changes, etc.

Communication: JSON on stdin, JSON on stdout. Exit 0 = allow, Exit 2 = block (for blocking events).

## Gemini CLI (11 events)

Config: Gemini settings JSON → `hooks` object. Scripts in project hooks directories.

- \*\*SessionStart\*\* / \*\*SessionEnd\*\* — session lifecycle
- \*\*BeforeAgent\*\* — after user prompt, before agent planning
- \*\*AfterAgent\*\* — after agent loop ends per turn
- \*\*BeforeModel\*\* / \*\*AfterModel\*\* — before/after LLM request
- \*\*BeforeToolSelection\*\* — before LLM selects tools
- \*\*BeforeTool\*\* / \*\*AfterTool\*\* — before/after tool invocation (BeforeTool can block)
- \*\*PreCompress\*\* — before history summarization
- \*\*Notification\*\* — system alerts

Communication: JSON on stdin/stdout. Synchronous execution.

## GitHub Copilot (8 events)

Config: `.github/hooks/\*.json` (committed to repo).

- \*\*SessionStart\*\* — first prompt of session
- \*\*UserPromptSubmit\*\* — user sends a prompt
- \*\*PreToolUse\*\* / \*\*PostToolUse\*\* — before/after tool calls (PreToolUse can deny)
- \*\*PreCompact\*\* — before context compaction
- \*\*SubagentStart\*\* / \*\*SubagentStop\*\* — subagent lifecycle
- \*\*Stop\*\* — session ends

## JetBrains Junie

No hook system yet. Feature request tracked as JUNIE-1961 on YouTrack. _(hooks, lifecycle, claude-code, gemini-cli, copilot, junie, agent-config, reference)_

- **Limiting incremental validation to small modifications (<** - Limiting incremental validation to small modifications (< 15 lines) prevents the loss of necessary context. This maintains review quality while optimizing for minor changes. _(performance, validation, shield)_
- **Core packages should provide a logging interface and DI** - Core packages should provide a logging interface and DI contract instead of calling console methods directly to prevent unwanted stdout pollution in non-CLI environments. _(architecture, logging, adr-071)_
- **Avoid hardcoding .git/hooks paths as repositories may use** - Avoid hardcoding `.git/hooks` paths as repositories may use custom `core.hooksPath` configurations; use `git rev-parse --git-path hooks` for reliable resolution. _(git, portability)_
- **Ensure byte-stable JSON serialization** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts Apply recursive object-key sorting when serializing committable state to prevent non-deterministic property ordering from creating phantom Git diffs. This is a substrate-level discipline that should apply to all committable JSON state in the engine, not just the file that surfaced it — `canonicalStringify(value, indent)` in `compile-manifest.ts` is the canonical primitive. _(json, git)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 49 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/src/commands/add-secret.test.ts, packages/cli/src/commands/add-secret.ts, packages/cli/src/commands/compile-export-archive-filter.test.ts, packages/cli/src/commands/compile-noop-refresh.test.ts, packages/cli/src/commands/compile-refresh-manifest.test.ts (+ 44 more). reasonCode: stage4-out-of-scope-match.)_
- **Swallowing read errors during security scans can lead** - Swallowing read errors during security scans can lead to false passes; explicit failure states should be recorded if specific files in the scan list are unreadable. _(security, error-handling)_
- **Use process.argv.includes for early detection of global** - Use `process.argv.includes` for early detection of global flags like `--json` to ensure error envelopes are correctly formatted even if the primary argument parser fails. _(cli, architecture)_
- **Explicitly separate deterministic, logic-based enforcement** - Explicitly separate deterministic, logic-based enforcement from AI-powered suggestions to ensure consistent behavior in CI pipelines. This prevents "vibes-based" failures and maintains developer confidence in automated security or architectural gates. _(architecture, ai, linting)_
- **Use maxRetries and retryDelay in fs.rmSync to prevent** - Use maxRetries and retryDelay in fs.rmSync to prevent ENOTEMPTY flakes on Windows caused by filesystem locks or race conditions during rapid test teardowns. _(node, fs, windows, testing)_
- **AI agents drift from session-start instructions as context** - AI agents drift from session-start instructions as context windows compress, requiring a three-layer enforcement strategy: suggestions (CLAUDE.md), user-invoked skills, and hard hooks. This layered approach ensures process discipline is maintained even when the agent's internal context begins to degrade. _(ai-agents, architecture, workflow)_
- **Lesson metadata should use descriptive titles rather** - Lesson metadata should use descriptive titles rather than timestamps to ensure that generated rule manifests and diagnostic outputs are actionable for developers. _(dx, documentation)_
- **Using a unified "Totem Error" tag in error logs instead** - Using a unified "Totem Error" tag in error logs instead of command-specific identifiers ensures consistent output and filtering across the entire tool suite. Centralizing error identification prevents fragmented log styles and adheres to project-wide observability standards. _(logging, conventions, cli)_
- **Seed unknown buckets when refining metrics** - \*\*Scope:\*\* packages/core/src/rule-metrics.ts When splitting a single aggregate counter into granular sub-buckets, seed the 'unknown' category with the previous total to maintain historical data continuity. _(metrics, data-integrity)_
- **Account for incidental compiles during manifest refresh** - \*\*Scope:\*\* docs/active*work.md Refreshing project manifests can trigger incidental code compilation; documenting this behavior prevents confusion when documentation-only changes cause unexpected build activity. *(dx, build)\_
- **Use Jaccard similarity for deterministic coverage** - \*\*Scope:\*\* packages/core/src/recurrence-stats.ts A Jaccard similarity threshold (e.g., 0.6) on tokenized messages provides a deterministic, low-dependency heuristic for mapping findings to existing rules without requiring LLM embeddings. _(algorithms, heuristics)_
- **Prefer field scoping in ast-grep** - \*\*Scope:\*\* packages/pack-agent-security/compiled-rules.json Using descendant `has` checks for call arguments allows bypasses via mixed expressions like string concatenation. Use `field` scoping (e.g., `arguments.0`) to target the node directly for strict literal validation. _(ast-grep, security)_
- **Align tool contracts with runtime validation** - \*\*Scope:\*\* packages/mcp/src/tools/add-lesson.ts Ensure Zod schemas for tool inputs use `.nonempty()` if the logic requires at least one value, preventing a mismatch between the declared tool contract and actual runtime behavior. _(mcp, validation, zod)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 28 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: .totem/specs/1488.md, .totem/specs/1663.md, .totem/specs/1683.md, .totem/specs/1684.md, .totem/specs/1713.md (+ 23 more). reasonCode: stage4-out-of-scope-match.)_
- **Preserve error context when re-throwing** - When catching and re-throwing errors, specifically during JSON parsing, it is critical to capture and include the original error message or context. Swallowing these details makes it significantly harder to diagnose the underlying cause of file corruption or malformation. _(error-handling, debugging, json)_
- **Archive shipped proposals to prevent planning drift** - \*\*Scope:\*\* proposals/\*\*/\*.md Proposals must be archived immediately upon completion to prevent automated planning passes from incorrectly identifying shipped features as active backlog items. _(planning, process, agents)_
- **Sync summary counts with active filters** - \*\*Scope:\*\* packages/cli/src/commands/test-rules.ts Summary counts (passed, failed, skipped) must reflect the filtered subset rather than global totals. This maintains consistency between the displayed logs and the final status line when a user limits the command scope. _(cli, ux, filtering)_
- **Relying on string matching for error logic is an acceptable** - Relying on string matching for error logic is an acceptable trade-off when checking output from a co-located, internally-defined function. This avoids the complexity of structured return types for one-time health checks where the string source is tightly controlled. _(typescript, design-patterns)_
- **Warnings emitted during batch operations should include** - Warnings emitted during batch operations should include an index or a content snippet to help developers identify the specific item that failed. Generic error messages are ambiguous when multiple rules or queries are applied to the same file. _(dx, logging)_
- **2026-03-03T02:16:24.772Z** - \*\*Pattern:\*\* \bstdio\s\*:\s\*.\*\.\bfd\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/cli/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

Do not pass raw file descriptors to stdio options; use pipe or inherit instead. _(style, curated)_

- **Individual CLI commands should throw standardized errors** - Individual CLI commands should throw standardized errors with specific prefixes rather than logging and returning locally. This allows a central top-level handler to manage consistent exit codes, error formatting, and process lifecycle across the entire tool. _(cli, nodejs, patterns)_
- **Scope SARIF output to error findings** - \*\*Scope:\*\* README.md SARIF output is restricted to error-severity findings to prevent PR reviews from being overwhelmed by warnings during CI integration. _(cicd, sarif, github)_
- **Passing pre-extracted metadata to multiple consumers avoids** - Passing pre-extracted metadata to multiple consumers avoids redundant file I/O when features like hint extraction and ledger recording require the same context. _(performance, architecture)_
- **Use anchored regex for shell command matching** - When triggering actions based on shell command strings, use anchored regex (e.g., `^\s\*git\s+`) rather than loose keyword matching. Loose patterns can trigger accidentally on file paths or comments that happen to contain the command keywords (like `.git/hooks`). _(regex, security, automation)_
- **Prefer shell redirection over cat pipe** - Using redirection (`< file`) instead of `cat file |` avoids spawning an unnecessary process, which is a key best practice for keeping automation scripts lightweight. This optimization reduces resource overhead in high-frequency CI pipelines and complex shell integrations. _(shell, performance, dx)_
- **Stripping non-ASCII characters during keyword extraction** - Stripping non-ASCII characters during keyword extraction causes pattern ID collisions for non-English messages. Using Unicode property escapes ensures unique identification across different languages and character sets. _(regex, i18n)_
- **Set higher timeouts for orchestrator tests** - \*\*Scope:\*\* packages/cli/\*\*/\*.test.ts Orchestrator tests involving full CLI runs often exceed default execution limits. Set an explicit 15s timeout for these suites to prevent flaky CI failures during heavy workloads. _(testing, vitest)_
- **Use 'totem-ignore' comments within string fixtures** - Use 'totem-ignore' comments within string fixtures containing intentional errors to prevent the compiler from flagging test data as real issues. _(testing, linting)_
- **Preserve technical invariants during voice refreshes** - Stripping marketing language can accidentally remove critical technical invariants like air-gapped guarantees or integration formats; these mechanical truths must be preserved as they are load-bearing features. _(documentation, process)_
- **Detection logic with fallbacks must be validated using test** - Detection logic with fallbacks must be validated using test cases where multiple valid API keys are present simultaneously. Simply testing individual keys fails to verify that the intended priority order is correctly enforced and prevents regressions in provider selection. _(testing, configuration, environment-variables)_
- **DRY up shared logic immediately when two commands duplicate** - # DRY up shared logic immediately when two commands duplicate code ## What happened PR #1026 initially duplicated 15 lines of review body parsing logic between `triage-pr.ts` and `review-learn.ts`. GCA flagged it as high priority. The fix was straightforward — extract `extractReviewBodyFindings()` into `bot-review-parser.ts` — but would have been even simpler if done from the start. ## Rule When adding the same logic to two commands, extract it into a shared helper on the first pass. The parser layer (`packages/cli/src/parsers/`) already exists for this purpose. Don't wait for a bot to flag it — the second call site is the signal to extract. \*\*Source:\*\* mcp (added at 2026-03-27T19:56:05.581Z) _(dry, refactoring, bot-review-parser, code-quality)_
- **Utilize fs.existsSync() as a fast-path optimization** - Utilize `fs.existsSync()` as a fast-path optimization for missing files to avoid the overhead of entering `try/catch` blocks for expected non-existent data. Retain the `ENOENT` check within the `catch` block as a safety net to handle Time-of-check to time-of-use (TOCTOU) race conditions. _(nodejs, performance, fs)_
- **Use canonical totem lesson compile command** - \*\*Scope:\*\* .gemini/styleguide.md, docs/\*\*/\*.md Documentation must consistently use 'totem lesson compile' as the canonical command, treating 'totem compile' as a deprecated legacy alias. _(cli, documentation)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 38 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: .claude/docs/architecture.md, .github/copilot-instructions.md, .junie/skills/totem-rules/SKILL.md, .junie/skills/totem-rules/rules.md, .totem/specs/1480-1481.md (+ 33 more). reasonCode: stage4-out-of-scope-match.)_
- **Always generate sentinel markers even when the internal** - \*\*Pattern:\*\* \btext:\s\*['"]['"]
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/mcp/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

Always generate sentinel markers even when the internal. _(style, curated)_

- **Partition manifest and rule file writes** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Only rewrite large data files when content actually changes, while allowing manifest metadata to refresh on pure input drift. This prevents unnecessary invalidation of mtime-based downstream caches while keeping integrity checks satisfied. _(performance, caching, filesystem)_
- **Re-thrown errors must preserve the original cause** - \*\*Pattern:\*\* throw\s+new\s+\w\*Error\([^)]\*\+\s\*(?:err|e|error)\.message
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts
  \*\*Severity:\*\* warning

When catching and re-throwing errors, pass the original error as the ES2022 `cause` property instead of concatenating `.message` into a new string. Concatenation destroys the original stack trace, making debugging significantly harder. Use `throw new TotemError('context', 'hint', originalErr)` instead. _(error-handling, architecture, curated)_

- **Ban `export let` module-level mutable state** - \*\*Engine:\*\* ast-grep \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts \*\*Severity:\*\* error \*\*Pattern:\*\* `yaml rule:   kind: export\_statement   has:     kind: lexical\_declaration     pattern: let $NAME = $VALUE ` \*\*Message:\*\* Exported `let` bindings create cross-module shared mutable state, which breaks functional isolation and makes concurrent or sequenced code paths hard to reason about. Prefer `export const`, or wrap mutation behind an exported function/class that owns the state internally. `export let` makes a mutable binding reachable from every importer. Any module that imports it can observe different values at different times based on whoever mutated last, and any module can mutate it. That pattern breaks Tenet 12 (Platform of Primitives) because consumers cannot reason about the module's surface as a set of stable primitives — the surface is a shared global. The related but NARROWER concern in internal module-private `let` bindings (lazy-init caches, singleton accumulators, flags used to gate one-shot behavior) is NOT banned here: those are legitimate when the mutation is confined to one file and the reader/writer pair are well-understood. The rule is deliberately tight to avoid false positives on `let cached = null` / `let initPromise: Promise<T> | null = null` idioms that appear throughout `context.ts`, `search-knowledge.ts`, and similar surfaces. The compound rule targets `export\_statement` nodes that \*contain\* a `lexical\_declaration` matching `let $NAME = $VALUE`. The `has:` combinator walks the export statement's direct subtree to find the `let` binding inside. `const` exports are unaffected because the pattern only matches `let`. ### Bad Example `ts export let sharedCounter = 0; ` ### Good Example `ts // State stays private; mutation goes through a named API that owns the invariant. let sharedCounter = 0; export function incrementCounter(): number {   sharedCounter += 1;   return sharedCounter; } ` ## Why this needs to be compound A flat pattern `export let $NAME = $VALUE` does not match in ast-grep's TypeScript grammar because `export let` parses as an `export\_statement` wrapping a `lexical\_declaration`, not as a single flat node. The compound form — anchor on `export\_statement`, require a `lexical\_declaration` child matching `let` — navigates the parse tree to the correct target. This is a textbook use case for the `has:` combinator. \*\*Source:\*\* Pre-1.15.0 deep review (mmnto/totem#1421). Gemini's teardown flagged broader module-level mutable state as a category (tracked in #1441 for the rule-engine.ts specific findings) and proposed a three-case AST rule. That rule is tightened here to only the unambiguous "exported let" variant per the Option C guidance from the deep review thread. Zero current violations in the codebase; rule ships as forward protection ahead of 1.15.0 Pack Distribution, where third-party packs might introduce this pattern. The broader rule-engine.ts concurrency concern (#1441) requires a runtime refactor, not a static AST rule. _(tenet-12, determinism, functional-isolation, ast-grep-compound, governance)_
- **Duplicating domain object mapping logic across packages** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Duplicating domain object mapping logic across packages creates maintenance risk and logic drift. Instead of manually reconstructing objects, use canonical converter functions from shared core packages. In CLI environments, use dynamic imports for these shared utilities to maintain package boundaries and optimize startup performance. _(architecture, typescript, cli)_
- **When implementing path-based filtering for patterns** - When implementing path-based filtering for patterns like `\*.test.\*` or `\*.spec.\*`, always match against the file's basename rather than the full normalized path. Using `includes()` on a full path results in false positives when a directory segment matches the infix, incorrectly classifying non-test files within test-related directories. _(logic, filesystem, architecture)_
- **Guard string operations on configuration values** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Always verify that configuration values are strings before calling methods like .includes() to prevent runtime exceptions when encountering malformed data types in config files. _(validation, defensive-programming)_
- **When automating milestone assignment, use a safe fallback** - When automating milestone assignment, use a safe fallback for non-semver strings to prevent crashes on custom sprint naming conventions. _(semver, automation)_
- **Use canonical API terms in documentation** - \*\*Scope:\*\* docs/\*\*/\*.md User-facing documentation must use canonical, publicly documented API terms (e.g., Anthropic's 'thinking') to prevent user confusion. This applies even when internal code uses different abstraction names like 'adaptive*thinking'. *(documentation, standards)\_
- **Avoid using console methods directly in core library** - Avoid using `console` methods directly in core library modules to maintain I/O separation and portability. Provide an optional `onWarn` callback so consuming applications (like the CLI) can decide how to surface warnings within their specific UI. _(architecture, logging, core-library)_
- **Limiting incremental fast-paths to small changes (e.g., <** - Limiting incremental fast-paths to small changes (e.g., < 15 lines) ensures the model maintains high precision without losing context. Larger changes or new files should trigger a full-context review to catch cross-functional regressions. _(llm, architecture, performance)_
- **Lint rules targeting module imports must account for both** - Lint rules targeting module imports must account for both ES Module 'import' statements and CommonJS 'require' calls. Failure to include CommonJS patterns allows developers to bypass architectural restrictions using legacy syntax. _(linting, regex, javascript)_
- **2026-03-06T01:32:23.369Z** - \*\*Pattern:\*\* \bstripAnsi\s\*\(|\.replace\(\s\*\/\\(x1[bB]|u001[bB])
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/mcp/\*\*/\*.ts, !\*\*/\*.test.ts
  \*\*Severity:\*\* error

Use a tested ANSI-stripping library instead of hand-rolled regex replacements. _(security, curated)_

- **Defer git root resolution in resolvers** - \*\*Scope:\*\* packages/core/src/strategy-resolver.ts Avoid eager git root resolution in path resolvers. Deferring the probe until a specific precedence layer requires a git-relative anchor prevents unnecessary crashes in non-git environments when absolute overrides are provided via env or config. _(git, architecture)_
- **Avoid changing established terminology in agent** - Avoid changing established terminology in agent instructions if automated drift-detection tests assert exact string matches across multiple agent files. The architectural churn of updating several configuration files and tests often outweighs the benefit of minor semantic improvements like "bodies" versus "descriptions." _(documentation, testing, maintenance)_
- **Prose-based lessons extracted from discussions do not** - Prose-based lessons extracted from discussions do not require Engine or Severity fields, unlike deterministic Pattern-based lessons used for automated enforcement. This distinction avoids unnecessary metadata boilerplate for qualitative lessons that are not intended for regex-based linting. _(metadata, automation, workflow)_
- **Always use dynamic imports for heavy logic or detection** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Always use dynamic imports for heavy logic or detection modules within CLI command functions. This ensures fast CLI startup performance by preventing the eager loading of code not required for the specific subcommand being executed. _(cli, performance, nodejs)_ _(archived: Over-broad: astGrepPattern `import $NAME from '$MODULE'` fires on every top-level default import in packages/cli/src/commands/\*\* with no way to identify "heavy logic or detection modules". Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Normalize temp paths for cross-platform equality** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Using realpathSync on temporary directories ensures path-equality assertions match git output across macOS symlinks and Windows short names. _(testing, filesystem, cross-platform)_
- **Shell hooks should use word-boundary regex instead** - Shell hooks should use word-boundary regex instead of simple string matching to correctly identify commands like 'commit' or 'push'. This ensures that git flags (e.g., 'git -c ... commit') are handled correctly and prevents false positives on substrings. _(shell, git, security)_
- **Core packages should use an injectable logger interface** - Core packages should use an injectable logger interface rather than direct console calls to allow consumers like CLIs to control output routing according to architectural boundaries. _(architecture, logging)_
- **Use canonical noun-verb CLI command forms** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts, !\*\*/\*.test.\* Use `totem lesson extract` and `totem lesson compile` instead of bare aliases like `totem extract`, which are deprecated. This ensures consistency across documentation, help text, and user-facing recovery hints. _(cli, ux)_ _(archived: Over-broad: fires on canonical commands like totem lint, totem sync, totem review. Only totem extract and totem compile are deprecated bare aliases. Needs a narrower pattern targeting only extract/compile without the lesson prefix.)_
- **Sanitize untrusted metadata before logging** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Metadata sourced from external files or user input should be sanitized before logging to prevent terminal injection attacks via malicious control characters. _(security, logging)_
- **The text-embedding-004 identifier is frequently unavailable** - The `text-embedding-004` identifier is frequently unavailable or invalid for Gemini integrations; use `gemini-embedding-2-preview` as the correct identifier. This prevents initialization failures for new users where the stale model name is rejected by the API. _(gemini, llm, embeddings)_
- **Junie requires specific file locations for auto-detection,** - \*\*Pattern:\*\* \.junie\/(?!mcp\/mcp\.json|guidelines\.md)[^'"\s>]+\.(json|md)
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.js, \*\*/\*.ts, \*\*/\*.json, \*\*/\*.md, \*\*/\*.sh, \*\*/\*.yml, \*\*/\*.yaml, .gitignore
  \*\*Severity:\*\* warning

Junie requires specific file locations for auto-detection. _(architecture, curated)_

- **Guard error message sentinel prefixes** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Avoid adding standard error prefixes to low-level helpers if downstream handlers use those prefixes as sentinels to detect and skip redundant wrapping. Adding a prefix prematurely can short-circuit context-wrapping logic in higher-level adapters. _(dx, error-handling)_
- **Calling .test() on a global regex increments the lastIndex** - Calling `.test()` on a global regex increments the `lastIndex` property, which causes subsequent replacements to skip characters and can allow malicious content to bypass sanitization. _(javascript, regex, security)_
- **Static top-level imports in CLI command files increase** - Static top-level imports in CLI command files increase startup latency. Use dynamic imports inside command handlers for heavy schemas or internal packages to maintain a fast runtime path. _(cli, performance, typescript)_ _(archived: Over-broad: astGrepPattern `import { $$$IMPORTS } from '$MODULE'` fires on every top-level destructured import in packages/cli/\*\*/commands/\*\*. Cannot distinguish heavy schemas from cheap built-ins. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Neutralize C1 and carriage return characters** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\* Terminal sanitizers must explicitly target C1 control codes (U+0080–U+009F) and carriage returns (\r) to prevent attackers from rewinding or overwriting terminal lines. _(security, cli)_ _(archived: Stage 4 (mmnto-ai/totem#1682): pattern fired on 39 file(s) in the verification baseline (test files, fixture directories, or files outside fileGlobs scope) — over-broad. Offending paths: packages/cli/src/commands/doctor.test.ts, packages/cli/src/commands/import.test.ts, packages/cli/src/commands/init.test.ts, packages/cli/src/commands/install-hooks.test.ts, packages/cli/src/commands/shield-estimate.test.ts (+ 34 more). reasonCode: stage4-out-of-scope-match.)_
- **Exclude unknown buckets from telemetry ratios** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts When calculating ratios from categorical telemetry (like code vs. non-code), exclude 'unknown' buckets from both the numerator and the denominator. Including 'unknown' in the total denominator artificially dilutes the ratio, leading to false negatives in quality diagnostics. _(telemetry, math, diagnostics)_
- **Avoid prefixes in low-level error messages** - \*\*Scope:\*\* packages/core/src/sys/\*\*/\*.ts, !\*\*/\*.test.\* Adding standard error prefixes to low-level utilities can break downstream sentinel detection used to prevent redundant error wrapping and preserve operation-level context. _(dx, error-handling)_
- **Contain blast radius with per-rule try-catch** - \*\*Scope:\*\* packages/core/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Executing individual rules within a try-catch block inside batch loops prevents a single malformed rule from crashing the entire engine execution. _(architecture, reliability)_
- **Avoid hardcoding unpulled model variants** - \*\*Scope:\*\* packages/cli/src/commands/init-detect.ts Do not default to specialized model variants (e.g., high-parameter models for specific tasks) during initialization unless they are guaranteed to be present, as this breaks the zero-config experience. _(llm, orchestration, dx)_
- **Using stored metadata as a fallback (e.g., current ??** - Using stored metadata as a fallback (e.g., `current ?? stored`) during verification can mask mismatches if the library's internal defaults change between versions. Verification logic must compare the current effective configuration against the stored state to detect when an index requires a rebuild. _(validation, configuration, state-management)_
- **Bypass regex validation for AST patterns** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts Configuration parsers must skip regex-specific validation when an ast-grep engine is specified. This prevents false positives and allows the use of AST-specific syntax that would otherwise fail standard regex checks. _(ast-grep, validation, eslint)_
- **When testing expected failures, assert the specific error** - When testing expected failures, assert the specific error message or violation count instead of just checking if an error was thrown. This prevents false positives where a different, unrelated error satisfies the test. _(testing, best-practices)_
- **Re-injecting a manifest of tools, commands, and project** - Re-injecting a manifest of tools, commands, and project partitions via a `PostCompact` hook prevents the agent from losing situational awareness after context pruning. This pattern ensures project-specific capabilities remain in the agent's active memory during long-running sessions while staying within a strict token budget (e.g., <250 tokens) to avoid immediate re-compression. _(prompt-engineering, context-management, hooks)_
- **Casting an object literal to an Error type does not satisfy** - \*\*Pattern:\*\* \}\s\*as\s+Error\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.tsx
  \*\*Severity:\*\* warning

Casting an object literal to an Error type does not satisfy. _(style, curated)_

- **Anchor relative paths to git root** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts Relative environment or configuration values should anchor at the git root rather than the current working directory to ensure consistent behavior in deep monorepo structures. _(cli, configuration)_
- **Strip Markdown formatting from finding descriptions** - Strip Markdown formatting from finding descriptions before including them in Git commit summaries. This prevents malformed conventional commits that could break CI or downstream parsing. _(git, llm, parsing)_
- **Keep the primary README focused on value propositions** - Keep the primary README focused on value propositions and quick starts, moving exhaustive CLI flags and platform edge cases to a dedicated wiki. This creates a focused entry point for new users while preserving technical depth in secondary locations for advanced users. _(documentation, information-architecture, dx)_
- **Background processes spawned by Git hooks should redirect** - Background processes spawned by Git hooks should redirect both stdout and stderr to a log file to prevent Node.js stack traces from polluting the terminal mid-git-operation. While an application's quiet flag handles the UI layer, shell-level redirection is necessary to ensure OS-level containment of background output. _(git, hooks, nodejs, devops)_
- **Include PID in temporary artifacts** - \*\*Scope:\*\* .claude/hooks/\*\*/\*.sh Suffixing artifact filenames with both a timestamp and PID prevents collision races when multiple hook events trigger within the same second. _(filesystem, concurrency)_ _(archived: Over-broad compound pattern. The second alternative `mktemp (?![^ ]\*$$)` false-positives on every correct mktemp call; mktemp already guarantees unique names and does not require a $$ suffix. The first alternative `$(date[^)]\*)[^$ ]\*.tmp[...]` captures a real pattern but cannot be salvaged from the compound-alt without recompiling. Refine the source lesson to narrow scope to timestamp-only filenames that lack any uniqueness suffix, then recompile.)_
- **Avoid abrupt CLI flag removal** - \*\*Scope:\*\* packages/cli/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Renaming or removing a boolean flag without providing a deprecated alias causes CLI parsers like Commander to error on existing user scripts. _(cli, dx, commander)_
- **Update governance extractors during package renames** - \*\*Scope:\*\* packages/mcp/\*\*/\*.ts, !\*\*/\*.test.\* Renaming packages within a fixed-versioning cohort requires updating internal state extractors to prevent incomplete governance or version reporting. _(architecture, mcp, governance)_
- **Prefer in-process CLI command execution** - \*\*Scope:\*\* packages/cli/src/commands/doctor.ts When one CLI command needs to trigger another (e.g., doctor triggering compile), call the command function directly in-process rather than spawning a shell. This avoids hardcoding specific package managers and ensures the execution works across global installs and different environments. _(cli, dx, architecture)_
- **Interactions where a developer rejects or modifies an AI's** - Interactions where a developer rejects or modifies an AI's suggestion often define critical architectural boundaries and represent higher-value knowledge than standard improvements. _(llm, collaboration, architecture)_
- **Marking test callbacks as async and awaiting synchronous** - Marking test callbacks as async and awaiting synchronous functions masks the actual API signature and prevents tests from detecting accidental conversions to Promises. Ensure tests reflect the synchronous nature of utilities to catch regressions in function return types. _(testing, typescript)_
- **For CLI tools reading a small number of local files,** - For CLI tools reading a small number of local files, synchronous file system APIs are often preferable to asynchronous ones. This approach minimizes code complexity and avoids the overhead of promise management in contexts where blocking the event loop has no measurable impact on performance. _(nodejs, cli, fs)_
- **Thread explicit cwd through command chains** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Ensure `cwd` parameters are passed through to all internal command invocations to prevent silent divergence where sub-commands default to `process.cwd()`. _(cli, dx)_ _(archived: Over-broad: fires on legitimate CLI entry-point usage like const cwd = options.cwd ?? process.cwd(). The lesson applies to internal command invocations (sub-commands called from other commands), not to the top-level command entry. Needs a negative constraint like not-inside options.cwd resolution, upgradeTarget: compound (Proposal 226).)_
- **Refining rule boundaries and scoping noisy patterns** - Refining rule boundaries and scoping noisy patterns to specific directories isolates legacy technical debt from the active enforcement path. This prevents pre-existing violations from blocking current development while allowing for a prioritized and phased cleanup. _(rules, linting, technical-debt)_
- **Use surgical cache eviction for targeted updates** - \*\*Scope:\*\* packages/cli/src/commands/compile.ts To re-compile a single item in a cached batch process, surgically delete the target hash from the 'existing' and 'non-compilable' sets before the loop. This allows the target to be treated as a new item while allowing all other items to hit the cache, maintaining performance. _(caching, performance)_
- **Spy on logger contracts in tests** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Asserting against high-level logger methods rather than internal transport outputs prevents tests from breaking when output plumbing changes. _(testing, dx)_
- **Do not include empty strings in branch whitelists,** - Do not include empty strings in branch whitelists, as explicit matching ensures that environment detection failures result in a hard block rather than an accidental match. _(security, cicd)_
- **Consolidate dynamic imports in command handlers** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Destructure all required helpers from a package at the start of the command handler instead of using multiple inline dynamic imports. This avoids redundant module resolution and sidesteps contradictory linting rules regarding lazy-loading in CLI environments. _(dx, performance, cli)_ _(archived: Over-broad: fires on every destructured dynamic import in command handlers, which is the canonical architectural pattern per ADR-071. Every CLI command handler uses this pattern by design. Would flag hundreds of legitimate lines.)_
- **Leverage ast-grep for property matching** - \*\*Scope:\*\* packages/core/src/eslint-adapter.ts The ast-grep engine natively matches dot access, optional chaining, and bracket notation without complex regex gymnastics. Use it for simple identifier pairs to improve rule robustness and simplify pattern logic. _(ast-grep, eslint)_
- **Validate persisted map keys against hashes** - \*\*Scope:\*\* packages/core/src/verification-outcomes.ts When loading memoized state, verify that map keys match internal object hashes to ensure tampered or malformed entries are not utilized. _(security, persistence)_
- **Heavy dependencies or sub-command logic should be** - Heavy dependencies or sub-command logic should be dynamically imported within the command handler rather than at the top level to ensure fast CLI startup times. This prevents the main entry point from loading unnecessary modules when the user is only running basic commands or help flags. _(cli, performance, nodejs)_
- **Resolve monorepo root paths eagerly** - \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Eagerly resolve the repository root to ensure global files like '.totemignore' are correctly located relative to the root rather than subpackage directories. _(monorepo, paths)_
- **Ban fail-open catch blocks that skip re-throwing** - \*\*Engine:\*\* ast-grep \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts \*\*Severity:\*\* error \*\*Pattern:\*\* `yaml rule:   kind: catch\_clause   not:     has:       kind: throw\_statement       stopBy: end ` \*\*Message:\*\* Catch clause swallows the error without re-throwing. Tenet 4 (Fail Loud, Never Drift) forbids silent degradation. Either rethrow with `throw err` / `throw new Error(..., { cause: err })`, or if the catch is genuinely a best-effort cleanup (temp file unlink, socket close, etc.) add `// totem-context: intentional cleanup` above the try/catch to document the exception. Tenet 4 (Fail Loud, Never Drift) forbids catching an error and continuing silently. A `catch` clause that contains no `throw\_statement` anywhere in its body quietly swallows the failure, corrupting the upstream signal that the sensor-based architecture depends on. The `not.has.throw\_statement` combinator with `stopBy: end` walks the entire catch body subtree so that rethrows nested inside `if` / `switch` / helper-call paths still pass. \*\*The deliberate escape hatch:\*\* a small set of catches are legitimately swallow-on-failure because the work inside is inherently best-effort (unlinking a temp file that may already be gone, closing a handle that may already be closed). For those sites, add `// totem-context: intentional cleanup` above the `try` block. Never weaken the rule; document the exception at the call site. ### Bad Example `ts try {   fs.unlinkSync(tempPath); } catch {   // swallowed — no throw, no log, no explicit suppression } ` ### Good Example ``ts try {   await doWork(); } catch (err) {   throw new Error(`doWork failed: ${String(err)}`, { cause: err }); } `` ## Why this needs to be compound A flat ast-grep pattern cannot express "catch clause whose body does not contain a throw*statement anywhere in its descendant tree." The combinator `not: { has: { kind: throw\_statement, stopBy: end } }` anchored on `kind: catch\_clause` encodes exactly that tree-relationship. This is one of the motivating use cases for compound ast-grep rule support (ADR-087 / Proposal 226). \*\*Source:\*\* Pre-1.15.0 deep review (mmnto/totem#1421). Gemini's Repomix teardown flagged multiple fail-open `catch` sites in `packages/core/src/sys/git.ts` and `rule-engine.ts` (tracked in mmnto/totem#1440 and mmnto/totem#1442). First production compound rule shipped via the new Pipeline 1 yaml-fence path. *(tenet-4, fail-loud, ast-grep-compound, governance)\_
- **Track deferred breaking changes in a ledger** - \*\*Scope:\*\* .changeset/\*.md Use a deferred-major ledger to record breaking changes that are intentionally misclassified as minor; this preserves visibility of the technical debt until a substantive bundle of changes justifies a major release. _(governance, technical-debt)_
- **Claude Code hooks require a specific object structure** - Claude Code hooks require a specific object structure containing a `matcher` field within the hook definition to execute correctly. The `/doctor` command is the standard way to verify that these configurations meet the tool's expected internal schema. _(claude-code, hooks, configuration)_
- **When extracting plain text from markdown ASTs, ensure logic** - When extracting plain text from markdown ASTs, ensure logic handles nodes with value or alt properties (like InlineCode or Image) and recurses into children to prevent data loss. _(markdown, parsing)_
- **Creating changeset Markdown files manually** - Creating changeset Markdown files manually in the '.changeset/' directory avoids execution failures common with interactive CLI tools when stdin is piped. _(release, dx)_
- **Processing code suppressions after a rule match allows** - Processing code suppressions after a rule match allows the engine to emit events for ignored violations. Filtering out suppressed lines before running queries silently drops metrics and diagnostic data needed for suppression tracking. _(telemetry, rule-engine)_
- **Include generated artifacts in files** - \*\*Scope:\*\* packages/pack-rust-architecture/package.json The prepare script does not run on consumer installs; ensure generated artifacts like WASM binaries are explicitly listed in the files array to be included in the tarball. _(npm, dx)_
- **Throwing specific error classes like TotemParseError** - Throwing specific error classes like TotemParseError instead of manually logging and exiting ensures consistent error handling and exit behavior across the CLI. _(cli, architecture)_
- **Avoid using dynamic imports in shared utility modules** - \*\*Pattern:\*\* \bimport\s\*\(
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/shared/\*\*/\*.ts, \*\*/shared/\*\*/\*.js, \*\*/utils/\*\*/\*.ts, \*\*/utils/\*\*/\*.js, !\*\*/\*.test.ts
  \*\*Severity:\*\* warning

Avoid using dynamic imports in shared utility modules. _(performance, curated)_

- **Report metrics after data transformations** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.\* Log messages should compute counts after pruning or filtering logic to avoid reporting stale item counts in success summaries. _(dx, logging)_
- **Ensure issue numbers are non-empty digit strings** - Ensure issue numbers are non-empty digit strings before posting 'Deferred to #' markers, as malformed markers break the idempotency check. _(validation, idempotency)_
- **Run local floor probes unconditionally** - \*\*Scope:\*\* packages/cli/src/commands/doctor.ts Probing local fallbacks (like Ollama) regardless of the active provider ensures users know their 'floor' is ready before a cloud failure occurs. _(cli, ux)_
- **Core library code should avoid direct calls to console** - Core library code should avoid direct calls to `console` to prevent unexpected side effects in consuming applications. Defaulting to a no-op function for warning callbacks allows the consumer to maintain full control over where logs are routed. _(architecture, logging, typescript)_
- **Mermaid node labels cannot contain // — GitHub lexer treats** - # Mermaid node labels cannot contain // — GitHub lexer treats it as comment syntax ## What happened The architecture diagram at `docs/reference/architecture-diagram.md` failed to render on GitHub with "Lexical error on line 9. Unrecognized text." The node label `[// totem-context:<br/>or --override]` confused the mermaid parser because `//` is interpreted as comment syntax. ## Rule When writing mermaid diagram node labels, avoid `//` characters. Use plain text descriptions instead of code syntax. If you must include special characters, wrap the label in double quotes: `["label text"]`. \*\*Example Hit:\*\* `Override[// totem-context:<br/>or --override]:::action` — lexer error \*\*Example Miss:\*\* `Override["totem-context directive<br/>or --override flag"]:::action` — renders correctly \*\*Source:\*\* mcp (added at 2026-03-27T22:17:26.403Z) _(mermaid, github, documentation, rendering, trap)_
- **Split CLI commands for keyless CI** - \*\*Scope:\*\* packages/cli/\*\*/\*.ts Decomposing commands into deterministic resolution (Phase A) and side-effectful sync (Phase B) allows CI environments to validate manifests without requiring sensitive API keys. _(cli, ci, architecture)_
- **Hardcoding vendor-shaped secret literals in test fixtures** - Hardcoding vendor-shaped secret literals in test fixtures can trigger security scanners; construct these strings dynamically at runtime instead. _(security, testing)_
- **Consolidate overlapping dynamic imports** - \*\*Scope:\*\* packages/cli/src/commands/doctor.ts Consolidate multiple dynamic imports from the same module into a single destructure to improve code clarity and reduce execution overhead. _(typescript, dx)_
- **Account for Opus 4.7 tokenization overhead** - \*\*Scope:\*\* docs/reference/supported-models.md The Claude Opus 4.7 tokenizer introduces a 1.0x to 1.35x increase in token overhead compared to previous versions. This increase must be factored into context window management and cost estimation logic. _(anthropic, llm, tokenization)_
- **When generating "Lite" or minimal configuration files,** - When generating "Lite" or minimal configuration files, include commented-out examples of alternative providers or advanced settings. This prevents users from losing sight of supported features that were bypassed during the initial simplified scaffolding process. _(ux, scaffolding, configuration)_
- **Perform shell-level existence checks before invoking CLI** - \*\*Pattern:\*\* ^(npx|node|npm|pnpm|yarn|bun)\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* .husky/\*, .git/hooks/\*
  \*\*Severity:\*\* warning

Perform shell-level existence checks before invoking CLI. _(performance, curated)_

- **2026-03-03T01:52:20.000Z** - \*\*Pattern:\*\* \b(main|master)\.\.\.HEAD\b
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, \*\*/\*.sh
  \*\*Severity:\*\* warning

Do not hardcode main...HEAD in git commands; use the configurable base branch. _(style, curated)_

- **Prefer canonical noun-verb CLI commands in docs** - \*\*Scope:\*\* .claude/skills/\*\*/\*.md, docs/\*\*/\*.md Using full noun-verb command structures in automation scripts and documentation prevents future churn if short-form aliases are deprecated. _(documentation, cli, dx)_
- **Leverage Anthropic prompt caching for compilers** - \*\*Scope:\*\* packages/cli/src/commands/compile-templates.ts Structuring large system prompts to support caching can significantly reduce costs for high-frequency LLM compiler calls within a short TTL. _(llm, performance)_
- **Using empty catch blocks during regex compilation in audit** - Using empty catch blocks during regex compilation in audit scripts hides malformed or broken rules from maintainers. Surfacing these specific failures is critical for maintaining rule-set integrity and preventing silent coverage gaps. _(regex, validation, dev-tools)_
- **MCP session lifecycle limitation** - \*\*Pattern:\*\* session\.(start|end)|beforeDisconnect
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* packages/mcp/\*\*/\*.ts
  \*\*Severity:\*\* error

MCP session lifecycle limitation. _(architecture, curated)_

- **Always escape hyphens in regex utilities** - \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !\*\*/\*.test.\*, !\*\*/\*.spec.\* Regex escaping must include the hyphen to prevent unintended range behavior when the escaped string is interpolated into a character class `[...]`. _(regex, security)_
- **Prefer non-blocking warnings over startup crashes** - \*\*Scope:\*\* packages/mcp/\*\*/\*.ts, !\*\*/\*.test.\* Crashing an MCP server on boot due to external dependency failures prevents access to all local tools. Surfacing errors as warnings during the first search call maintains server availability while alerting the agent to the failure. _(mcp, dx, architecture)_
- **Eagerly importing heavy modules at the top level of CLI** - \*\*Scope:\*\* packages/cli/src/commands/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts Eagerly importing heavy modules at the top level of CLI command files increases startup latency; use dynamic `import()` within handlers to keep help and version checks fast. _(performance, cli, dx)_ _(archived: Over-broad: astGrepPattern `import $NAME from '$MODULE'` fires on every top-level default import in packages/cli/src/commands/\*\*. Archived via #1517 + ADR-072 §3 (lazy-load via await import() established in PR #945, shipped 1.5.3).)_
- **Technical documentation should avoid marketing-centric** - Technical documentation should avoid marketing-centric terms like "Local Brain" or aspirational roadmap phases to maintain clarity. Use precise technical descriptions instead of positioning-heavy analogies to ensure the docs remain useful for developers. _(documentation, product-strategy, communication)_
- **Changesets interactive CLI (pnpm changeset) crashes when** - \*\*Pattern:\*\* \bpnpm\s+changeset\b(?!\s+(version|publish|status|pre|tag|init))
  \*\*Engine:\*\* regex
  \*\*Scope:\*\* .github/workflows/\*\*/\*.yml, .circleci/config.yml, \*\*/scripts/\*.sh, \*\*/scripts/\*.bash, Makefile
  \*\*Severity:\*\* error

Changesets interactive CLI (pnpm changeset) crashes when. _(architecture, curated)_

- **Narrow catch blocks in test imports** - \*\*Scope:\*\* packages/core/src/ast-grep-wasm-shim.test.ts When importing shims that might fail due to specific environment limits, only swallow the expected error signature to avoid masking real regressions. _(testing, wasm)_
- **Forbid direct child_process — use safeExec** - \*\*Pattern:\*\* (?:from|require\()\s\*['"](?:node:)?child*process['"] \*\*Engine:\*\* regex \*\*Scope:\*\* \*\*/\*.ts, \*\*/\*.js, !packages/core/src/sys/\*\*, !\*\*/\*.test.ts, !\*\*/\*.spec.ts, !\*\*/\*.test.js, !\*\*/\*.spec.js \*\*Severity:\*\* error Direct use of `node:child\_process` is forbidden outside of the sys utilities. Use `safeExec` from `@mmnto/totem` instead. It handles cross-platform shell requirements (Windows `shell: true`), UTF-8 encoding, 10MB maxBuffer default, auto-trimming, and ES2022 error cause chains. Importing child_process directly leads to duplicated platform boilerplate and inconsistent error handling. *(architecture, security, curated)\_
- **Forbid inline JSON.parse(readFileSync) — use readJsonSafe** - \*\*Pattern:\*\* JSON\.parse\(\s\*\S\*readFileSync \*\*Engine:\*\* regex \*\*Scope:\*\* packages/core/src/\*\*/\*.ts, !packages/core/src/sys/\*\*, !\*\*/\*.test.ts, !\*\*/\*.spec.ts \*\*Severity:\*\* warning Use `readJsonSafe` from the sys utilities instead of inline `JSON.parse(fs.readFileSync(...))`. The helper differentiates ENOENT (missing file) from SyntaxError (corrupt JSON) from ZodError (schema mismatch), throwing `TotemParseError` with ES2022 cause chains. Inline parsing duplicates error handling and loses diagnostic context. _(architecture, curated)_
- **Use git adapter instead of raw git execution** - \*\*Pattern:\*\* (?:execFileSync|safeExec)\(\s\*['"`]git['"`] \*\*Engine:\*\* regex \*\*Scope:\*\* \*\*/\*.ts, !packages/core/src/sys/git.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts \*\*Severity:\*\* warning Use the git adapter functions from `@mmnto/totem` (e.g., `getGitBranch`, `getGitDiff`, `resolveGitRoot`) instead of calling git directly via `execFileSync` or `safeExec`. The shared git adapter handles cross-platform shell requirements, timeout defaults, maxBuffer limits, and structured error handling with cause chains. Raw git calls lead to duplicated boilerplate and inconsistent error behavior. _(architecture, curated)_
- **The lesson pipeline has quality gaps at every transition** - The knowledge pipeline (extract → lesson → compile → enforce) has no quality gates between steps. Each transition can degrade quality:

1.  Extract: LLM decides what's worth learning from a PR. No filter for noise.
2.  Lesson format: Fix guidance is optional. Many lessons diagnose the problem but don't tell the agent how to resolve it.
3.  Compile: LLM generates AST/regex patterns from lessons. No self-test, no contradiction check against existing rules.
4.  Curate: Manual review doesn't scale. We've reverted to the curated rule set three times.

Fix: Treat the pipeline like a compiler with type-checking at every stage. Validate required fields (heading, tags, body, Fix guidance) at write time. Validate compiled rules against test cases before promotion. Check for contradictions against the existing rule set. Each gate rejects invalid output instead of letting it flow downstream. _(architecture, compiler, knowledge-quality)_

- **Do not delete .totem/lessons.md (load-bearing for 41+ rules)** - \*\*Pattern:\*\* \b(?:git\s+rm|rm)\s+[^\n]{0,40}\.totem/lessons\.md\b \*\*Engine:\*\* regex \*\*Scope:\*\* \*\*/\*.sh, \*\*/\*.bash, \*\*/\*.zsh, \*\*/\*.md, \*\*/\*.ts, \*\*/\*.js, \*\*/\*.cjs, \*\*/\*.mjs, .claude/\*\*/\*, !\*\*/\*.test.\*, !\*\*/\*.spec.\*, !.totem/lessons/\*\*, !.totem/lessons.md, !.totem/tests/\*\* \*\*Severity:\*\* error # Do not delete `.totem/lessons.md` — it sources 41+ production rules ## What happened During the 1.13.0 postmerge cleanup (mmnto/totem#1234 follow-up, 2026-04-06), an agent tried to delete `.totem/lessons.md` because the lesson headings in that file are ISO timestamps (a parser quirk from MCP batch ingestion via the `add\_lesson` tool). The instinct was "this is corrupt cruft, delete it." The deletion was caught at the diff-review stage, but only AFTER `pnpm exec totem lesson compile` had already pruned \*\*51 rules\*\* (41 with timestamp headings + 10 adjacent) from `.totem/compiled-rules.json` because their source lessons no longer existed on disk. The change was reverted via `git checkout HEAD -- .totem/lessons.md .totem/compiled-rules.json`, but the near-miss was 41 functional production rules — `os.tmpdir()` workspace boundaries, `fs.createWriteStream($PATH)` stdio traps, regex anchoring, LanceDB schema migration, MCP session lifecycle, and dozens more. ## Why the file looks like cruft (but isn't) `.totem/lessons.md` is a single multi-lesson markdown file. Each section is delimited by `## Lesson — <heading>`. When lessons are batch-ingested via the MCP `add\_lesson` tool without an explicit human-readable heading, the heading defaults to the ingestion timestamp (e.g. `2026-03-02T09:18:21.092Z`). These look like garbage — they're identifiers, not descriptions — but the \*\*body\*\* of each section is a real, valuable lesson with concrete patterns that compile into production rules. 41 of those sections currently produce live ast-grep rules in `compiled-rules.json`. Many more are in the `nonCompilable` set as intentionally archived. None of them are recoverable from anywhere else if the file is deleted. ## The rule This lesson compiles into a Pipeline 1 (manual) regex rule that fires on any text matching `rm .totem/lessons.md`, `git rm .totem/lessons.md`, `rm -rf .totem/lessons.md`, etc. across shell scripts, markdown docs, TypeScript / JavaScript scripts, and Claude skill instructions. The rule catches the destructive command at the point of intent — when a script, documentation, skill, or commit message records the intent to delete the file — \*before\* the deletion actually runs. The rule does NOT scope to `.totem/lessons.md` itself or to other lesson files, so this lesson and any future trap descriptions can quote the dangerous command in their narrative without false-positiving. \*\*Example Hit:\*\* `git rm .totem/lessons.md` — destructive command in any script \*\*Example Miss:\*\* `rm .totem/lessons/lesson-cd27a5b0.md` — individual lesson file deletion is allowed ## What to do instead If `.totem/lessons.md` ever needs cleanup: 1. \*\*Edit, don't delete.\*\* Open the file and remove specific `## Lesson —` sections that are truly garbage. Each section is independent; deleting one doesn't affect the others. 2. \*\*Use `nonCompilable`.\*\* If a specific lesson section produces a bad rule, compute its `lessonHash` (via `hashLesson(heading, body)` from `@mmnto/totem`) and add it to `compiled-rules.json#nonCompilable` — the compile pipeline will skip it forever without you having to touch the file. 3. \*\*Heading rewrite is optional.\*\* If the timestamp headings bother you, rewrite them to human-readable titles in-place. The lesson hash will change (since hash is computed from heading + body), so the old rules will be pruned and re-compiled under the new hashes. Plan for that churn before doing it. ## Why a lint rule and not a hook Totem's thesis: deterministic constraints, not sticky notes. If an agent made (or almost made) this mistake once, the right move is to encode the constraint physically so the same agent (or the next one) cannot bypass it by forgetting to read a memory file. A pre-push hook would also work, but a compiled lint rule lives in `.totem/compiled-rules.json` alongside the other ~395 production rules and runs everywhere `totem lint` runs — local pre-push, CI, agent-driven workflows, everything. \*\*Source:\*\* Salvaged from a near-miss on 2026-04-06 during the 1.13.0 postmerge lesson extract+compile cycle. Encoded as a lint rule to satisfy totem's "use totem to govern totem" tenet (Gemini's framing). _(governance, lessons, trap, totem-self)_
- **Key security audit findings and acceptable risks** - The v1.3.1 security audit of the MCP server and shell orchestrator found no critical vulnerabilities. Key findings and mitigations:

1.  Unbounded `max\_results` in MCP search could cause memory exhaustion. Fix: capped to 100 via Zod `.max()`.
2.  `taskkill` on Windows used string interpolation via `execSync`. Fix: switched to safe child process execution (`execFileSync`/`spawn`) with array args instead of string interpolation.
3.  `child.kill()` with `shell: true` on Unix doesn't kill the process tree. Fix: `detached: true` + `process.kill(-pid)` for process group termination.
4.  Model name injection via shell orchestrator is blocked by `MODEL\_NAME\_RE = /^[\w./:\_-]+$/` — all shell metacharacters are excluded.
5.  Cross-repo `totem link` exposes linked knowledge to AI agents via MCP. Mitigated with a security warning; full RBAC deferred to cloud control plane.
6.  Lesson content in LLM prompts is a prompt injection vector, but lessons are trusted content from the same user who controls the config — acceptable risk. _(security, mcp, audit)_

- **Ban `spawn()` / `spawnSync()` with `shell: true`** - \*\*Engine:\*\* ast-grep \*\*Scope:\*\* packages/\*\*/\*.ts, !\*\*/\*.test.ts, !\*\*/\*.spec.ts, !packages/cli/src/orchestrators/shell-orchestrator.ts \*\*Severity:\*\* error \*\*Pattern:\*\* `yaml rule:   any:     - pattern: spawn($$$)       has:         kind: pair         all:           - has:               kind: property\_identifier               regex: ^shell$           - has:               kind: 'true'         stopBy: end     - pattern: spawnSync($$$)       has:         kind: pair         all:           - has:               kind: property\_identifier               regex: ^shell$           - has:               kind: 'true'         stopBy: end ` \*\*Message:\*\* `spawn` / `spawnSync` with `shell: true` opens a shell-injection vector. Use `safeExec` (which routes through `cross-spawn.sync` without a shell) from `packages/core/src/sys/exec.ts` instead. The single legitimate exception — the shell orchestrator at `packages/cli/src/orchestrators/shell-orchestrator.ts` that pipes prompts to third-party CLI tools — is scope-excluded via `!` glob and has its own input-sanitization gate. `shell: true` on Node's `child\_process.spawn` / `spawnSync` concatenates argument strings into a shell command line. If any interpolated value contains shell metacharacters (`;`, `|`, `$(...)`, backticks, newlines, etc.), it runs as code. This is the exact class of RCE that mmnto/totem#1329 closed in 1.14.5 (`safeExec` rewrite) and mmnto/totem#1429 (the shell orchestrator `{model}` token hardening in 1.14.10). The compound rule combines an `any:` disjunction over `spawn($$$)` and `spawnSync($$$)` call patterns with a `has:` descendant check for the `shell: true` pair in any options object. `stopBy: end` lets the descendant scan traverse the full argument subtree, so `shell: true` nested inside a destructured config or a spread still matches. \*\*The deliberate escape hatch (one site):\*\* `packages/cli/src/orchestrators/shell-orchestrator.ts` legitimately needs `shell: true` to invoke arbitrary CLI tools (`gemini`, `claude`, `ollama`). That file is scope-excluded via the `!` glob entry. The input-sanitization that protects it lives in the same file (`MODEL\_SAFE\_RE` allow-list + `quoteShellArg` defense-in-depth) and was added in 1.14.10. ### Bad Example `ts import { spawn } from 'node:child\_process'; spawn('ls -la', { shell: true }); ` ### Good Example `ts import { safeExec } from '../sys/exec.js'; const result = safeExec('ls', ['-la']); ` ## Why this needs to be compound A flat ast-grep pattern for `spawn(...)` matches every `spawn` call regardless of options, so it is too broad and would flag every legitimate `cross-spawn` usage. A pattern that literally spells out `spawn($CMD, { shell: true })` misses the three-argument form `spawn($CMD, $ARGS, { shell: true })` and doesn't cover `spawnSync`. The compound form — `any:` over the two call names, `has:` on `shell: true` descendants — encodes the real invariant: the danger is `shell: true` anywhere in the options, not the spawn call in isolation. \*\*Source:\*\* Pre-1.15.0 deep review (mmnto/totem#1421). Gemini's teardown identified this as the generalized form of the mmnto/totem#1329 and mmnto/totem#1429 fixes — a compound rule here prevents the bug class instead of only the specific incidents. First production compound rule using the `any:` disjunction operator. _(security, shell-injection, ast-grep-compound, governance)_

<!-- totem:generated:end -->
