# AGENTS.md — Timmy Time Development Standards for AI Agents Read [`CLAUDE.md`](CLAUDE.md) for architecture patterns and conventions. --- ## Communication Protocol **Before making changes, always:** 1. Read CLAUDE.md and AGENTS.md fully 2. Explore the relevant src/ modules to understand existing patterns 3. Explain what you're changing and **why** in plain English 4. Provide decision rationale - don't just make changes, explain the reasoning **For Timmy's growth goals:** - Improve reasoning in complex/uncertain situations: think step-by-step, consider alternatives - When uncertain, state uncertainty explicitly rather than guessing - Document major decisions in DECISIONS.md --- ## Non-Negotiable Rules 1. **Tests must stay green.** Run `python3 -m pytest tests/ -x -q` before committing. 2. **No direct pushes to main.** Branch protection is enforced on Gitea. All changes reach main through a Pull Request — no exceptions. Push your feature branch, open a PR, verify tests pass, then merge. Direct `git push origin main` will be rejected by the server. 3. **No cloud dependencies.** All AI computation runs on localhost. 4. **No new top-level files without purpose.** Don't litter the root directory. 5. **Follow existing patterns** — singletons, graceful degradation, pydantic-settings. 6. **Security defaults:** Never hard-code secrets. 7. **XSS prevention:** Never use `innerHTML` with untrusted content. --- ## One-Agent-Per-Issue Convention **An issue must only be worked by one agent at a time.** Duplicate branches from multiple agents on the same issue cause merge conflicts, redundant code, and wasted compute. ### Labels When an agent picks up an issue, add the corresponding label: | Label | Meaning | |-------|---------| | `assigned-claude` | Claude is actively working this issue | | `assigned-gemini` | Gemini is actively working this issue | | `assigned-kimi` | Kimi is actively working this issue | | `assigned-manus` | Manus is actively working this issue | ### Rules 1. **Before starting an issue**, check that none of the `assigned-*` labels are present. If one is, skip the issue — another agent owns it. 2. **When you start**, add the label matching your agent (e.g. `assigned-claude`). 3. **When your PR is merged or closed**, remove the label (or it auto-clears when the branch is deleted — see Auto-Delete below). 4. **Never assign the same issue to two agents simultaneously.** ### Auto-Delete Merged Branches `default_delete_branch_after_merge` is **enabled** on this repo. Branches are automatically deleted after a PR merges — no manual cleanup needed and no stale `claude/*`, `gemini/*`, or `kimi/*` branches accumulate. If you discover stale merged branches, they can be pruned with: ```bash git fetch --prune ``` --- ## Merge Policy (PR-Only) **Gitea branch protection is active on `main`.** This is not a suggestion. ### The Rule Every commit to `main` must arrive via a merged Pull Request. No agent, no human, no orchestrator pushes directly to main. ### Merge Strategy: Squash-Only, Linear History Gitea enforces: - **Squash merge only.** No merge commits, no rebase merge. Every commit on main is a single squashed commit from a PR. Clean, linear, auditable. - **Branch must be up-to-date.** If a PR is behind main, it cannot merge. Rebase onto main, re-run tests, force-push the branch, then merge. - **Auto-delete branches** after merge. No stale branches. ### The Workflow ``` 1. Create a feature branch: git checkout -b fix/my-thing 2. Make changes, commit locally 3. Run tests: tox -e unit 4. Push the branch: git push --no-verify origin fix/my-thing 5. Create PR via Gitea API or UI 6. Verify tests pass (orchestrator checks this) 7. Merge PR via API: {"Do": "squash"} ``` If behind main before merge: ``` 1. git fetch origin main 2. git rebase origin/main 3. tox -e unit 4. git push --force-with-lease --no-verify origin fix/my-thing 5. Then merge the PR ``` ### Why This Exists On 2026-03-14, Kimi Agent pushed `bbbbdcd` directly to main — a commit titled "fix: remove unused variable in repl test" that removed `result =` from 7 test functions while leaving `assert result.exit_code` on the next line. Every test broke with `NameError`. No PR, no test run, no review. The breakage propagated to all active worktrees. ### Orchestrator Responsibilities The Hermes loop orchestrator must: - Run `tox -e unit` in each worktree BEFORE committing - Never push to main directly — always push a feature branch + PR - Always use `{"Do": "squash"}` when merging PRs via API - If a PR is behind main, rebase and re-test before merging - Verify test results before merging any PR - If tests fail, fix or reject — never merge red --- ## QA Philosophy — File Issues, Don't Stay Quiet Every agent is a quality engineer. When you see something wrong, broken, slow, or missing — **file a Gitea issue**. Don't fix it silently. Don't ignore it. Don't wait for someone to notice. **Escalate bugs:** - Test failures → file with traceback, tag `[bug]` - Flaky tests → file with reproduction details - Runtime errors → file with steps to reproduce - Broken behavior on main → file IMMEDIATELY **Propose improvements — don't be shy:** - Slow function? File `[optimization]` - Missing capability? File `[feature]` - Dead code / tech debt? File `[refactor]` - Idea to make Timmy smarter? File `[timmy-capability]` - Gap between SOUL.md and reality? File `[soul-gap]` Bad ideas get closed. Good ideas get built. File them all. When the issue queue runs low, that's a signal to **look harder**, not relax. ## Dogfooding — Timmy Is Our Product, Use Him Timmy is not just the thing we're building. He's our teammate and our test subject. Every feature we give him should be **used by the agents building him**. - When Timmy gets a new tool, start using it immediately. - When Timmy gets a new capability, integrate it into the workflow. - When Timmy fails at something, file a `[timmy-capability]` issue. - His failures are our roadmap. The goal: Timmy should be so woven into the development process that removing him would hurt. Triage, review, architecture discussion, self-testing, reflection — use every tool he has. --- ## Agent Roster ### Gitea Permissions All agents that push branches and create PRs require **write** permission on the repository. Set via the Gitea admin API or UI under Repository → Settings → Collaborators. | Agent user | Required permission | Gitea login | |------------|--------------------|----| | kimi | write | `kimi` | | claude | write | `claude` | | gemini | write | `gemini` | | antigravity | write | `antigravity` | | hermes | write | `hermes` | | manus | write | `manus` | To grant write access (requires Gitea admin or repo admin token): ```bash curl -s -X PUT "http://143.198.27.163:3000/api/v1/repos/rockachopa/Timmy-time-dashboard/collaborators/" \ -H "Authorization: token " \ -H "Content-Type: application/json" \ -d '{"permission": "write"}' ``` ### Build Tier **Local (Ollama)** — Primary workhorse. Free. Unrestricted. Best for: everything, iterative dev, Docker swarm workers. **Kimi (Moonshot)** — Paid. Large-context feature drops, new subsystems, persona agents. Avoid: touching CI/pyproject.toml, adding cloud calls, removing tests. **DeepSeek** — Near-free. Second-opinion generation, large refactors (R1 for hard problems). Avoid: bypassing review tier for security modules. ### Review Tier **Claude (Anthropic)** — Architecture, tests, docs, CI/CD, PR review. Avoid: large one-shot feature dumps. **Gemini (Google)** — Docs, frontend polish, boilerplate, diff summaries. Avoid: security modules, Python business logic without Claude review. **Manus AI** — Security audits, coverage gaps, L402 validation. Avoid: large refactors, new features, prompt changes. --- ## Docker Agents Container agents poll the coordinator's HTTP API (not in-memory `SwarmComms`): ``` GET /internal/tasks → list tasks open for bidding POST /internal/bids → submit a bid ``` `COORDINATOR_URL=http://dashboard:8000` is set by docker-compose. ```bash make docker-build # build image make docker-up # start dashboard make docker-agent # add a worker ``` --- ## File Conventions | Pattern | Convention | |---------|-----------| | New route | `src/dashboard/routes/.py` + register in `app.py` | | New template | `src/dashboard/templates/.html` extends `base.html` | | New subsystem | Add to existing `src//` — see module map in CLAUDE.md | | New test | `tests//test_.py` (mirror source structure) | | Secrets | Via `config.settings` + startup warning if default | | DB files | Project root or `data/` — never in `src/` | --- ## Search Capability (SearXNG + Crawl4AI) Timmy has a self-hosted search backend requiring **no paid API key**. ### Tools | Tool | Module | Description | |------|--------|-------------| | `web_search(query)` | `timmy/tools/search.py` | Meta-search via SearXNG — returns ranked results | | `scrape_url(url)` | `timmy/tools/search.py` | Full-page scrape via Crawl4AI → clean markdown | Both tools are registered in the **orchestrator** (full) and **echo** (research) toolkits. ### Configuration | Env Var | Default | Description | |---------|---------|-------------| | `TIMMY_SEARCH_BACKEND` | `searxng` | `searxng` or `none` (disable) | | `TIMMY_SEARCH_URL` | `http://localhost:8888` | SearXNG base URL | | `TIMMY_CRAWL_URL` | `http://localhost:11235` | Crawl4AI base URL | Inside Docker Compose (when `--profile search` is active), the dashboard uses `http://searxng:8080` and `http://crawl4ai:11235` by default. ### Starting the services ```bash # Start SearXNG + Crawl4AI alongside the dashboard: docker compose --profile search up # Or start only the search services: docker compose --profile search up searxng crawl4ai ``` ### Graceful degradation - If `TIMMY_SEARCH_BACKEND=none`: tools return a "disabled" message. - If SearXNG or Crawl4AI is unreachable: tools log a WARNING and return an error string — the app never crashes. --- ## Roadmap **v2.0 Exodus (in progress):** Voice + Marketplace + Integrations **v3.0 Revelation (planned):** Lightning treasury + `.app` bundle + federation