Repository navigation
Hard Rules Detail
Deep-dive companion to the numbered list in
AGENTS.md→ "Hard Rules". Every rule 1–23 is listed inAGENTS.md; where that list shows a short form, the section below with the same number carries the complete binding text plus rationale, incident history and decision trees — both are normative, and the longer text here wins on any detail the short form omits. Rules not listed here (1–13, 15, 17) appear in full inAGENTS.md. Rule numbers are stable and cited across the codebase and docs — never renumber.
Never dismiss a CodeQL / Secret-Scanning alert without (a) first checking the pattern docs
(see AGENTS.md → Key Conventions → Security) to see if the helper applies, and (b) recording
the technical justification in the dismissal comment. Precedent: js/stack-trace-exposure
raised on callsites that already route through sanitizeErrorMessage() is a known CodeQL
limitation (custom sanitizers not recognized) — dismiss as false positive referencing
docs/security/ERROR_SANITIZATION.md.
Never credit or advertise an AI assistant, LLM, or automation account in any commit/PR
metadata. Two forbidden forms, both equivalent — they route attribution to a bot account (or
advertise AI authorship) and hide the real author (diegosouzapw):
-
(a)
Co-Authored-Bytrailers naming an AI/bot (e.g. names containing "Claude", "GPT", "Copilot", "Bot"; emails atanthropic.com/openai.com/ bot-ownednoreply.github.comaddresses); -
(b) AI-generation footers or descriptions anywhere in a commit message, PR title/body, or
CHANGELOG — e.g.
🤖 Generated with [Claude Code], "Generated with Claude Code", "Made with ", or anyCo-authored-by: Claude/GPT/Copilotline.
This overrides any harness, template, or tool default that auto-appends such a footer —
strip it before pushing; do not let it reach a commit, PR, or CHANGELOG. Human collaborators —
including upstream PR authors and issue reporters being ported into OmniRoute — MAY and SHOULD
be credited with standard Co-authored-by: Name <email> trailers; the upstream-port workflows
(/port-upstream-features, /port-upstream-issues) depend on this.
Every fix for a reported issue must be validated by one of the following — no exceptions:
- TDD (preferred) — write a failing test reproducing the bug → fix it → confirm the test passes. The test becomes the permanent regression guard. Touch only the files the test proves need changing; nothing more.
-
Real-environment test (when TDD is not possible) — deploy to the production VPS
(
root@192.168.0.15) and run a documented live test. Record the exact command + result in the PR description. Applies to: OAuth upstream flows, Cloudflare/WS upstream behavior, UI-only regressions, hardware-dependent behavior. - "It worked locally without a test" does not count. A fix without a test or a VPS validation record is not a fix — it is a guess.
Why this matters: fixing bug A while opening bug B is worse than not fixing at all. The TDD/VPS gate enforces surgical scope — you touch only what the failing test proves is broken. Examples where this paid off: #3090 (claude-web 403), #3113 (WS HTTP fallback), #3052 (heap-guard auto-calibration).
Never develop on the shared main checkout. Every development task runs in its own git worktree
on its own dedicated branch, and you MUST confirm the base branch with the operator before
creating the worktree/branch — never assume main or the currently checked-out branch. A
git checkout in the shared checkout silently destroys other sessions' uncommitted work. Tear
down only the worktrees/branches you created (by name, never fix/*/feat/* wildcards), leave
other sessions' worktrees untouched, and end on the branch you started on (the active
release/vX.Y.Z, never main). Full protocol, commands, and incidents:
docs/ops/WORKTREE_ISOLATION.md.
PII redaction/sanitization is opt-in — never on by default. OmniRoute proxies for
self-hosted/local LLMs where the operator owns the data, so mutating request/response payloads
by default would silently corrupt legitimate traffic. The two data-mutating PII feature flags
MUST keep defaultValue: "false" in src/shared/constants/featureFlagDefinitions.ts:
PII_REDACTION_ENABLED (request-side) and PII_RESPONSE_SANITIZATION (response + streaming).
All three application points — src/lib/guardrails/piiMasker.ts (request guardrail),
src/lib/piiSanitizer.ts (response), src/lib/streamingPiiTransform.ts (SSE) — are gated on
these flags; with both off the pii-masker guardrail still runs but never mutates payloads
(data passes through untouched). Flipping either default to "true" requires explicit operator
approval. The regression guard is tests/unit/pii-opt-in-default.test.ts (asserts both
definition defaults + behavioral pass-through). Opt-in is per-operator via env or the
settings/DB override (src/lib/db/featureFlags.ts), never a silent default. See
docs/security/GUARDRAILS.md.
The FROZEN release branch belongs to the release captain; development does NOT stop (parallel-cycle model, 2026-07-04).
/generate-release opens a marker issue labeled release-freeze at the start of
reconciliation (Phase 0a), immediately cuts the next cycle's branch release/vX+1 from the
frozen tip (Phase 0a.0b — bump + living release PR + re-home of open PRs), and closes the
freeze once the release PR squash-merges to main.
Before merging any PR, every campaign workflow (/review-prs, /review-group-prs,
/merge-prs, /triage-fix-bugs, /implement-fix-bugs, /triage-features,
/implement-features, /green-prs, /port-upstream-*) MUST check:
gh issue list --repo diegosouzapw/OmniRoute --label release-freeze --state openIf a freeze is active: NEVER merge into the frozen release/vX.Y.Z named in the freeze
title; instead resolve the ACTIVE development branch (the highest release/v* by semver —
normally release/vX+1, announced in a freeze-issue comment) and retarget the PR there
(gh pr edit <N> --base release/vX+1, then VERIFY with gh pr view <N> --json baseRefName —
the edit fails silently) and merge normally. HOLD only when the highest release/v* branch IS
the frozen one (the short window before 0a.0b completes, or a pre-parallel-cycle release) —
in that case leave the PR ready and open, tell the operator, and resume when the next branch
appears or the freeze lifts. The just-shipped fixes reach release/vX+1 via the Phase 5
sync-back (scripts/release/sync-next-cycle.mjs); do not try to sync mid-release.
This is a coordination signal, not a permission lock: the release captain and the campaign
sessions share the diegosouzapw identity, so a GitHub branch-protection lock cannot
distinguish them — only this honored marker prevents the mid-release commit races that forced
full CHANGELOG re-reconciliation in v3.8.40/v3.8.41 (a parallel campaign advanced
release/vX.Y.Z by 34 commits mid-run). The release captain's own reconciliation/cycle-open
pushes are exempt — they are the release. Fixes that must land during a freeze (a
homologation finding) follow the post-merge read-only rule: land on main first via
fix/release-vX.Y.Z-*.
⛔ ONLY /generate-release may raise a release-freeze, and ONLY at its Phase 0a (start of
generating a new version) — lifted at Phase 12c after the squash-merge to main. No
campaign, session, or agent may open a release-freeze marker at any other time — a freeze is
never a mid-development coordination tool. If a session ever believes a freeze is genuinely,
unavoidably necessary outside the /generate-release flow, it MUST first ask the operator
(diegosouzapw) in chat, explicitly alert "estou criando um freeze" and get an explicit yes —
never open, extend, or re-open a release-freeze autonomously. Conversely, do not close/lift
an active /generate-release freeze to unblock campaign merges: it protects the captain's
single clean CI run and auto-lifts at Phase 12c — closing it early re-triggers the exact commit
race it prevents. Verify a freeze is legitimate before acting on it: an open release-freeze
whose title/body references an OPEN release PR (gh pr view <N> --json state) is the
authorized captain freeze — hold, don't touch. (Cycle-model proposal:
_tasks/finished/release-flow/2026-07-04_proposta-ciclo-paralelo-v2.md.)
This repo is worked by MANY parallel sessions/agents at once; never step on another's in-flight work. Two absolute bans, both recurring incidents (this rule exists because they keep happening):
-
(a) Never
git stash/git stash pop— ANYWHERE in this repo, including inside an isolated worktree, and including inside any subagent you dispatch.git stashoperates on the shared repository object store, not the per-worktree working tree — so a stash pushed or popped in one session can silently clobber or resurrect another parallel session's uncommitted changes. This is not hypothetical: 2026-07-02 a#5923quotaCache change leaked into the unrelated#2296worktree via a globalstash pop, and the same class reincided through a subagent. To compare working changes against a base ref without stashing, usegit show <ref>:<path>orgit diff <ref> -- <path>; to confirm a typecheck/lint error is pre-existing on the base, inspect the base ref directly (git show origin/release/vX.Y.Z:<path>) — never stash your tree away to "get it clean". Put this ban verbatim in the prompt of every subagent that touches git (agents don't inherit AGENTS.md's context — the recurrence was a subagent). -
(b) Never merge, push, rebase, or force-push a PR / branch / worktree that another session
is actively working. An open PR whose head is a live fix worktree in
.claude/worktrees/you did not create (e.g.fix-5852/fix-5923carrying fresh commits, even when they share yourdiegosouzapwidentity), or any branch another session owns, is off-limits — HOLD, and let the owning session merge it. Before merging or pushing to any PR you did not create this session, rungit worktree listto check for a matching in-flight worktree and re-checkgh pr view <N> --json state,headRefOid. Only the owning session merges its own in-flight PR; mid-flight merges race the owner and re-trigger the exact commit/CHANGELOG races Rule #19 and Rule #21 guard against. (Reinforces Rule #19.)
_tasks/ é um repositório git SEPARADO (remote privado diegosouzapw/_tasks_omniroute)
montado como diretório real na raiz do checkout principal. Regras absolutas:
-
(a) NUNCA mover, renomear, deletar, esvaziar ou transformar
_tasksem symlink; sessões só podem CRIAR ou EDITAR arquivos dentro dele; -
(b) NUNCA rastrear
_tasks(nem como symlink) no repo principal — o blob rastreado foi a causa-raiz de DOIS wipes (2026-08-08 e 2026-08-10:git reset --hardmaterializou o symlink rastreado por cima do diretório real e o git apagou todo o conteúdo ignorado sem aviso); -
(c) após qualquer escrita relevante,
git -C _tasks add -A && git -C _tasks commit && git -C _tasks push— o push frequente é o backup real; - (d) repetir esta proibição VERBATIM no prompt de todo subagente que toque git;
-
(e) se
_tasksaparecer como symlink quebrado, NÃO commitar nada — restaurar do remote e avisar o operador.
O gate check:tracked-artifacts (pre-commit + CI) bloqueia _tasks rastreado em qualquer forma.
See also AGENTS.md → "Planning & Research Artifacts".
OmniRoute · Website · npm · Docker Hub
- Setup Guide
- User Guide
- Features
- Quick Start (Docker)
- Electron Desktop App
- Termux (Android)
- PWA Guide
- MCP Server
- A2A Server
- Agent Protocols
- OpenCode Plugin
- Webhooks
- Cloud Agents
- Skills
- Memory
- Evals
- Gamification
- Guardrails
- Compliance
- Error Sanitization
- Public Credentials
- Route Guard Tiers
- Stealth Guide
- CLI Token Auth