agentleFS
MotWakorbMotWakorb/enhancedchannelmanager/CLAUDE.md

enhancedchannelmanager

CLAUDE.md89 starsChanged 4 months agoCC0-1.0View on GitHub

Before reading code, editing files, or exploring the codebase for ANY code task: The first positional arg is the title, not the repo. Repo is auto-routed from .beads/. Don't pass enhancedchannelmanager as the title — that's the most common foot-gun. No exceptions. No "I'll do it later." The bead comes before the first Read, Grep, or Edit. After the work is deployed and verified, close it: bd close <bead-id> When work ships, it doesn't just close the bead it was…

  • Deletes or force-pushes
  • Installs packages
  • Commits and pushes

The file

We split this CLAUDE.md into the rules it gives an agent

11 rules. About 0 are common, 4 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Distinctive:

    Before reading code, editing files, or exploring the codebase for ANY code task:

    line 5
  2. Very specific:

    No exceptions. No "I'll do it later." The bead comes before the first Read, Grep, or Edit.

    line 18
  3. Very specific:

    After the work is deployed and verified, close it: bd close <bead-id>

    line 19
  4. Very specific:

    Rebuild the graph: only if (1) and (2) don't cover it: /graphify backend frontend docs.

    line 134
  5. Very specific:

    Always clean /app/static/assets/ before copying — docker cp only adds files, never removes stale bundles.

    line 166
  6. Distinctive:

    Coupled backend/frontend changes: When a frontend build depends on a new or changed backend route, deploy the backend first and wait for …

    line 175
  7. Very specific:

    Python packages: use uv (not pip): docker exec ecm-ecm-1 uv pip install <package>

    line 207
  8. Very specific:

    Follow docs/shipping.md. The full PR-driven flow (branch from origin/dev, push, open PR via gh pr create --base dev, wait for the 5 …

    line 211
  9. Very specific:

    Run gh pr create from the checkout being shipped.

    line 213
  10. Distinctive:

    NEVER stop before the PR is merged — an open PR is not a shipped change

    line 217
  11. Distinctive:

    NEVER say "ready to merge when you are" — YOU must drive the merge once the required checks are green

    line 218

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

Agent Instructions

STOP — Read Beads, Then Create a Bead

Before reading code, editing files, or exploring the codebase for ANY code task:

  1. Read existing beads for context on past work:
    bd list --status closed
    bd ready
  2. Create a bead for the current task:
    bd create "Brief title" --description "Why this exists and what needs to be done"
    The first positional arg is the title, not the repo. Repo is auto-routed from .beads/. Don't pass enhancedchannelmanager as the title — that's the most common foot-gun.

No exceptions. No "I'll do it later." The bead comes before the first Read, Grep, or Edit. After the work is deployed and verified, close it: bd close <bead-id>

Beads Quick Reference

bd ready                      # Find available work
bd show <id>                  # View issue details
bd update <id> --status in_progress  # Claim work
bd close <id>                 # Complete work
bd list --status closed       # View closed beads for context
bd sync                       # Sync beads data only (NOT for code commits)
  • Beads auto-route to this repo via .beads/. If you ever need to override (e.g., creating a bead targeting a different rig), use --repo enhancedchannelmanager.
  • NEVER chain bd create and bd close — run them as separate commands
  • The .git/beads-worktrees/dev worktree is only for beads issue tracking (sparse checkout of .beads/ only — no code files). Do NOT edit code there.

Close Every Bead Your Work Fulfills

When work ships, it doesn't just close the bead it was filed under. Check whether it also fulfills other beads, and close those too, naming them and the evidence in the close reason. Watch for three patterns especially: children of an epic when the epic's work ships, sibling beads absorbed by a broader fix, and beads whose premise a refactor removes.

A 2026-08-12 validity audit of all 194 open beads closed 44 of them, almost all already-shipped work that had simply never been closed. All 14 children of epic gsnw0 sat open for weeks after one commit fulfilled them against the parent only. t4d5w's own CHANGELOG entry says it absorbs bead pb2s4; pb2s4 stayed open. dfkbn, a P1, was declared closed in CHANGELOG prose but never closed in beads. Three siblings (2896r.16, 2896r.17, 70u0r) were all described by one CHANGELOG entry and all stayed open. Net effect: the backlog overstated remaining work by roughly 17 percent, and it produced a real planning error, sequencing a batch around a docs-CI chain that had already shipped.

Verification Discipline: Check the Thing, Not a Proxy

Four rules from a 2026-08-13 error retro (~/retros/2026-08-13-19_(project-d-proxy-not-referent).md). Twelve errors that session, and every judgment error among them was one substitution: checking something adjacent to the claim, then reporting the claim.

1. Smoke-test every instrument before you trust it. Run any monitor, watch loop, or external-tool invocation against a known-good AND a known-bad input before arming it. Silence from a broken instrument is indistinguishable from silence from a healthy system, so this class of failure conceals itself. Four monitors failed this way in one session: a gh pr checks --json flag that does not exist (30 minutes of confident silence while the checks had already finished); a || echo '[]' fallback that turned every error into "no results"; a [0] index on a branch-filtered API listing assumed to be newest-first, which reported on a six-week-old commit; and a 5-minute timeout on a ~15-minute publish. A codex exec call passed the prompt as an argument and piped stdin, so it blocked, did nothing, and exited 0. That exit status was very nearly read as "reviewed, no findings."

2. Report the check you ran, not the conclusion you drew. Say "grepped seven across docs/", not "verified". If the reporting sentence is broader than the command, the command was too narrow, and that gap is invisible to the PO, who calibrates trust on the phrasing. A docs sweep for a stale required-check count grepped the word "seven", reported "none remain", and missed three files using the numeral 7. scripts/check_publish.py:573 already encodes this rule for the publish gate ("Claim only what actually ran"); it generalizes.

3. Never assert a handoff without opening the target. Closing bead A because bead B covers it requires reading B. rnzu0 was closed on the claim its fix "rides with hmr0e"; hmr0e is about removing an M3U Manager link and covered none of it. Four stale e2e assertions stayed live and the bead had to be reopened. The same rule covers "already fixed": mechanism absent from current code is not defect fixed, and the difference decides whether it can return.

4. Your own verification is not exempt from verification. The rules above about agent-reported gates and shared-resource control apply to your own greps and closures too. The asymmetry is invisible from the inside: you cannot feel the difference between "I checked" and "I checked something adjacent". Two demonstrations from the retro session itself, both caught only by looking at the thing: an audit-closure count quoted from a same-day close total (46) when the real figure was 44, and a "TLS route with no auth dependency" that was an artifact of a 4-line awk window with the dependency on line 5. Prefer external adversarial review (Codex, a persona-reviewer agent) on your own judgment (closures, "verified" claims, recommendations), not only on the code. Hand the reviewer the repository, not a curated file list: curating backend routers only once produced a confident, wrong conclusion that the MCP tools did not exist. A mitigation phrased as an intention ("avoid biasing by omission") is not a mitigation.

Invoking Personas (project-engineer, qa-engineer, sre, etc.)

Personas are skills at ~/.claude/skills/<persona>/SKILL.md, NOT subagent types. To spawn them — especially in parallel — use the Agent tool with subagent_type: "general-purpose" and load the persona identity in the prompt:

Read ~/.claude/skills/<persona>/SKILL.md for your domain scope.
Read ~/.claude/skills/<persona>/identity.md (if present).
Read ~/.claude/skills/_shared/engineering-discipline.md.

You are the <Persona>. <question/task>

The canonical pattern is documented in ~/.claude/skills/spike/SKILL.md (Step 3). Do NOT try subagent_type: "project-engineer" — the registered subagent types are only general-purpose, Explore, Plan, claude-code-guide, statusline-setup.

For multi-persona workflows (team-plan, team-review, spike, grooming, standup, retro, onboard), invoke the orchestrating skill via the Skill tool — it handles the fan-out itself.

Worktree & Agent Isolation (this environment)

The Claude Code worktree mechanism is unreliable here. Three harness-level bugs, NOT fixable in-repo (see bd-j8osn; the third is enhancedchannelmanager-2lwz3):

  • cwd-trap: a worktree-spawned agent's Bash cwd resets to the MAIN checkout between calls, while Read/Edit act on the literal absolute path given. An agent that doesn't make EVERY path worktree-absolute ends up editing dev directly — silently polluting the main checkout.
  • Lock accumulation: a finished agent's worktree stays locked and is never auto-cleaned; git worktree remove then needs -f -f.
  • Stale-base: a worktree is branched from origin/main, not dev, unless a start point is given explicitly. origin/main is the repo's default branch, so this is the silent default, not an edge case. Measured 2026-08-12: a worktree agent's branch reflog read Created from origin/main at ae25ad70 (PR #748, 2026-07-26), while dev was 858 files and roughly 141k lines ahead at eecd257a. The agent's brief named a symbol added on dev by a later PR; that symbol did not exist on the worktree's base, and the agent only caught it mid-task. Nothing about this looks wrong from the outside: git status is clean, gates pass, and the diff against the worktree's own (stale) base looks small and correct. An agent that doesn't notice ships a branch written against an old API surface: the code it targeted has moved, so part of its fix can be missing or wrong, its gates passed against a tree that is not the one it will land in, and its conflicts are likelier and easy to mis-resolve toward the stale side.

    The merge itself does NOT revert dev. An earlier version of this bullet said it "reverts everything dev gained since the stale base"; that is wrong. A three-way merge takes the stale commit as its merge base and keeps dev-only work on dev's side. That was verified empirically in a throwaway repo: branch from an old commit, advance the target four commits, then merge, and all target-side work and files survive. The damage is a quietly incomplete fix plus meaningless gate results, not mass reversion, and the distinction matters because it changes the remediation. Standing rule 4 below is unaffected: verify the merge-base regardless. Full evidence in enhancedchannelmanager-2lwz3.

Standing defaults (these OVERRIDE the global "worktree-isolate every write agent" rule, which assumes a working mechanism):

  1. Default: non-worktree, sequential engineers. For typical small / single-domain changes, spawn the engineer WITHOUT isolation: "worktree" and brief it to work on a branch in the main checkout (do NOT create a worktree). No second tree ⇒ no cwd-trap, nothing left locked.
  2. Worktrees only for genuinely parallel, independent write agents. When used: brief the cwd-trap hard (every Read/Edit/Bash path worktree-absolute; verify git -C <wt> branch --show-current before any commit), and on return verify each agent's gates AND that the main checkout is clean (git status shows none of the agent's files).
  3. Clean up on merge, every time. git worktree remove -f -f <path> is part of the PR-merge step — never defer to a later sweep. Skip and flag any worktree with uncommitted tracked changes instead of force-removing it.
  4. First action in every worktree agent: verify the base, then rebase onto origin/dev. Before any other work, compare git -C <worktree> merge-base HEAD origin/dev against git rev-parse origin/dev. These agreeing is the pass condition; if they disagree, the worktree is stale and must be rebased onto origin/dev before the brief's actual task starts.
  5. Trust nothing unverified. Independently re-run the agent's claimed gates before merging, AND independently re-verify the branch's merge-base against origin/dev before merging: gates passing on a stale base proves nothing about the merge.

Frontend tooling in a worktree (writable .vite-temp) is fixed in scripts/worktree-bootstrap.sh; full caveats in docs/shipping.md → "Worktree quirks".

Sizing Vocabulary — No Calendar Estimates

Size work as Small / Medium / Large / Epic — needs decomposition (per ~/.claude/skills/grooming/SKILL.md). Do NOT give the PO calendar estimates in hours/days/weeks/months. Calendar estimates invite commitment theater and are almost always wrong.

Exception — governance cadence rules from ADRs (e.g., ADR-005's monthly-then-quarterly audit cadence) are project-defined constraints and can be quoted verbatim. Do not multiply them out into wall-time estimates. Quote the rule; let the PO do the arithmetic if they want it.

Reference Guides

GuideLocation
Architecture Diagramdocs/architecture.md
Auth Middlewaredocs/auth_middleware.md
Backend Architecturedocs/backend_architecture.md
Database Migrationsdocs/database_migrations.md
Pytest Conventionsdocs/pytest_conventions.md
Project Architecturedocs/project_architecture.md
Runbooksdocs/runbooks/
Style Guide (canonical)docs/style_guide.md
CSS Guidelinesdocs/css_guidelines.md
Beads (Issue Tracking)~/.claude/projects/<project-slug>/memory/beads.md
Dispatcharr APIdocs/dispatcharr_api.md
Discord Release Notesdocs/discord_release_notes.md
Frontend Lint Policydocs/frontend_lint.md
Testing Detailsdocs/testing.md
Shipping Workflowdocs/shipping.md
Dummy EPG Template Enginedocs/template_engine.md
DBAS Import Threat Modeldocs/security/threat_model_dbas_import.md
CodeQL Configurationdocs/security/codeql-config.md
Normalization (user + dev guide)docs/normalization.md
Channel Pipeline Rule Analyzerdocs/channel_pipeline_rule_analyzer.md
Event Sync (user + dev guide)docs/event_sync.md
Versioning Schemedocs/versioning.md
API Referencedocs/api.md
SLOsdocs/sre/slos.md
User Guide (operator-facing)docs/user_guide/
Graphify findings (past traces)graphify-out/memory/*.md
Graph audit reportgraphify-out/GRAPH_REPORT.md

Architecture Questions

For codebase-architecture questions (how X connects to Y, what a component's role is, where the hot path runs), the order of precedence is:

  1. docs/architecture.md — the hand-curated system overview + Channel Pipeline internals + MCP + external API contract.
  2. graphify-out/memory/*.md — saved Q&A from past graph traces. Each file is one question + answer. Greppable. Cheap to read.
  3. Rebuild the graph only if (1) and (2) don't cover it: /graphify backend frontend docs. Then query via graphify query "..." / graphify explain "NodeName" / graphify path "A" "B".

The raw graph.json and cross-repo-graph.json files are gitignored (large, machine-local paths). Rebuild on demand.

For coding conventions (naming, module organization, comments, error handling, regex, CSS, lint, tests), docs/style_guide.md is the canonical reference. Other guides in this table cover their own subject (CSS shared classes, lint per-rule patterns, etc.) and are cited from the style guide where they remain authoritative.

Development Workflow

Always work from the dev branch. Container name: ecm-ecm-1

Container-First Development

Edit code locally, deploy to container, iterate. Do NOT commit until told to "ship the fix."

docker cp <local-file> ecm-ecm-1:/app/<destination-path>

Frontend deploy:

scripts/deploy-frontend.sh          # build + clean stale assets + copy, in one step

The script bakes in the stale-asset cleanup below so it can't be skipped. Equivalent manual sequence (use --no-build to skip the rebuild):

cd frontend && npm run build
docker exec ecm-ecm-1 sh -c 'rm -rf /app/static/assets/*'
docker cp dist/. ecm-ecm-1:/app/static/

Always clean /app/static/assets/ before copying — docker cp only adds files, never removes stale bundles. Set ECM_CONTAINER to target a container other than ecm-ecm-1.

Backend deploy (to /app/, NOT /app/backend/):

docker cp backend/main.py ecm-ecm-1:/app/main.py
docker cp backend/routers/. ecm-ecm-1:/app/routers/
docker restart ecm-ecm-1

Coupled backend/frontend changes: When a frontend build depends on a new or changed backend route, deploy the backend first and wait for its restart to complete before deploying the frontend:

docker cp backend/main.py ecm-ecm-1:/app/main.py
docker cp backend/routers/. ecm-ecm-1:/app/routers/
docker restart ecm-ecm-1
ready=0
for attempt in $(seq 1 30); do
  if docker exec ecm-ecm-1 python -c "import os, urllib.request; port = os.environ.get('ECM_PORT', '6100'); urllib.request.urlopen(f'http://localhost:{port}/api/health/ready', timeout=2)" >/dev/null 2>&1; then
    ready=1
    break
  fi
  sleep 1
done
if [ "$ready" -ne 1 ]; then
  echo "ECM backend did not become ready; frontend was not deployed" >&2
  docker logs --tail 100 ecm-ecm-1 >&2
  exit 1
fi
scripts/deploy-frontend.sh

This order prevents the new frontend from calling an API contract that the running backend does not yet provide. The readiness loop is bounded to 30 attempts with a two-second request timeout; /api/health/ready is public, so the in-container probe needs no credentials. Roll back in reverse dependency order: restore and deploy the previous frontend build first, then restore the previous backend files and restart ecm-ecm-1. Do not roll back the backend while the dependent frontend is still live.

Python packages use uv (not pip): docker exec ecm-ecm-1 uv pip install <package>

Shipping (When User Says "Ship the Fix")

Follow docs/shipping.md. The full PR-driven flow (branch from origin/dev, push, open PR via gh pr create --base dev, wait for the 5 required checks, then gh pr merge --merge --delete-branch) lives in docs/shipping.md §6 — do not duplicate it here.

Run gh pr create from the checkout being shipped. The local preflight hook resolves the session cwd before Bash runs and cannot follow an inline cd <other-checkout> && gh pr create ...; that form is unsupported. Remove the branch worktree and check the branch out in the main checkout before opening its PR.

Non-negotiable rules:

  • Work is NOT complete until the PR merges into dev
  • NEVER stop before the PR is merged — an open PR is not a shipped change
  • NEVER say "ready to merge when you are" — YOU must drive the merge once the required checks are green

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.