Compare commits

...

1 Commits

Author SHA1 Message Date
Alexander Whitestone
79b841727f docs: add timmy-dispatch genome artifact (#682) 2026-04-15 02:33:19 -04:00
2 changed files with 359 additions and 0 deletions

View File

@@ -0,0 +1,320 @@
# GENOME.md — timmy-dispatch
Generated: 2026-04-15 02:29:00 EDT
Analyzed repo: Timmy_Foundation/timmy-dispatch
Analyzed commit: 730dde8
Host issue: timmy-home #682
## Project Overview
`timmy-dispatch` is a small, script-first orchestration repo for a cron-driven Hermes fleet. It does not try to be a general platform. It is an operator's toolbelt for one specific style of swarm work:
- select a Gitea issue
- build a self-contained prompt
- run one cheap-model implementation pass
- push a branch and PR back to Forge
- measure what the fleet did overnight
The repo is intentionally lightweight:
- 7 Python files
- 4 shell entry points
- a checked-in `GENOME.md` already present on the analyzed repo's `main`
- generated telemetry state committed in `telemetry/`
- no tests on `main` (`python3 -m pytest -q` -> `no tests ran in 0.01s`)
A crucial truth about this ticket: the analyzed repo already contains a genome on `main`, and it already has an open follow-up issue for test coverage:
- `timmy-dispatch#1` — genome file already present on main
- `timmy-dispatch#3` — critical-path tests still missing
So this host-repo artifact is not pretending to discover a blank slate. It is documenting the repo's real current state for the cross-repo genome lane in `timmy-home`.
## Architecture
```mermaid
graph TD
CRON[crontab] --> LAUNCHER[bin/sprint-launcher.sh]
CRON --> COLLECTOR[bin/telemetry-collector.py]
CRON --> MONITOR[bin/sprint-monitor.sh]
CRON --> WATCHDOG[bin/model-watchdog.py]
CRON --> ANALYZER[bin/telemetry-analyzer.py]
LAUNCHER --> RUNNER[bin/sprint-runner.py]
LAUNCHER --> GATEWAY[optional gateway on :8642]
LAUNCHER --> CLI[hermes chat fallback]
RUNNER --> GITEA[Gitea API]
RUNNER --> LLM[OpenAI SDK\nNous or Ollama]
RUNNER --> TOOLS[local tools\nrun_command/read_file/write_file/gitea_api]
RUNNER --> TMP[/tmp/sprint-* workspaces]
RUNNER --> RESULTS[~/.hermes/logs/sprint/results.csv]
AGENTDISPATCH[bin/agent-dispatch.sh] --> HUMAN[human/operator copy-paste into agent UI]
AGENTLOOP[bin/agent-loop.sh] --> TMUX[tmux worker panes]
WATCHDOG --> TMUX
SNAPSHOT[bin/tmux-snapshot.py] --> TELEMETRY[telemetry/*.jsonl]
COLLECTOR --> TELEMETRY
ANALYZER --> REPORT[overnight report text]
DISPATCHHEALTH[bin/dispatch-health.py] --> TELEMETRY
```
## Entry Points
### `bin/sprint-launcher.sh`
Primary cron-facing shell entry point.
Responsibilities:
- allocate a unique `/tmp/sprint-*` workspace
- fetch open issues from Gitea
- choose the first non-epic, non-study issue
- write a fully self-contained prompt file
- try the local Hermes gateway first
- fall back to `hermes chat` CLI if the gateway is down
- record result rows in `~/.hermes/logs/sprint/results.csv`
- prune old workspaces and old logs
### `bin/sprint-runner.py`
Primary Python implementation engine.
Responsibilities:
- read active provider settings from `~/.hermes/config.yaml`
- read auth from `~/.hermes/auth.json`
- route through OpenAI SDK to the currently active provider
- implement a tiny local tool-calling loop with 4 tools:
- `run_command`
- `read_file`
- `write_file`
- `gitea_api`
- clone repo, branch, implement, commit, push, PR, comment
This is the cognitive core of the repo.
### `bin/agent-loop.sh`
Persistent tmux worker loop.
This is important because it soft-conflicts with the README claim that the system “does NOT run persistent agent loops.” It clearly does support them as an alternate lane.
### `bin/agent-dispatch.sh`
Manual one-shot prompt generator.
It packages all of the context, token, repo, issue, and Git/Gitea commands into a copy-pasteable prompt for another agent.
### Telemetry/ops entry points
- `bin/telemetry-collector.py`
- `bin/telemetry-analyzer.py`
- `bin/sprint-monitor.sh`
- `bin/dispatch-health.py`
- `bin/tmux-snapshot.py`
- `bin/model-watchdog.py`
- `bin/nous-auth-refresh.py`
These form the observability layer around dispatch.
## Data Flow
### Autonomous sprint path
1. cron starts `bin/sprint-launcher.sh`
2. launcher fetches open issues from Gitea
3. launcher filters out epic/study work
4. launcher writes a self-contained prompt to a temp workspace
5. launcher tries gateway API on `localhost:8642`
6. if gateway is unavailable, launcher falls back to `hermes chat`
7. or, in the separate Python lane, `bin/sprint-runner.py` directly calls an LLM provider via the OpenAI SDK
8. model requests local tool calls
9. local tool functions execute subprocess/Gitea/file actions
10. runner logs results and writes success/failure to `results.csv`
### Telemetry path
1. `bin/telemetry-collector.py` samples tmux, cron, Gitea, sprint activity, and process liveness
2. it appends snapshots to `telemetry/metrics.jsonl`
3. it emits state changes to `telemetry/events.jsonl`
4. it stores a reduced comparison state in `telemetry/last_state.json`
5. `bin/telemetry-analyzer.py` summarizes those snapshots into a morning report
6. `bin/dispatch-health.py` separately checks whether the system is actually doing work, not merely running processes
## Key Abstractions
### Stateless sprint model
The repo's main philosophical abstraction is that each sprint run is disposable.
State lives in:
- Gitea
- tmux session topology
- log files
- telemetry JSONL streams
Not in a long-running queue or orchestration daemon.
### Self-contained prompt contract
`bin/agent-dispatch.sh` and `bin/sprint-launcher.sh` both assume that the work unit can be described as a prompt containing:
- issue context
- API URLs
- token path or token value
- branching instructions
- PR creation instructions
That is a very opinionated orchestration primitive.
### Local tool-calling shim
`bin/sprint-runner.py` reimplements a tiny tool layer locally instead of using the Hermes gateway tool registry. That makes it simple and portable, but also means duplicated tool logic and duplicated security risk.
### Telemetry-as-paper-artifact
The repo carries a `paper/` directory with a research framing around “hierarchical self-orchestration.” The telemetry directory is part of that design — not just ops exhaust, but raw material for claims.
## API Surface
### Gitea APIs consumed
- repo issue listing
- issue detail fetch
- PR creation
- issue comment creation
- repo metadata queries
- commit/PR count sampling in telemetry
### LLM APIs consumed
Observed paths in code/docs:
- Nous inference API
- local Ollama-compatible endpoint
- gateway `/v1/chat/completions` when available
### File/state APIs produced
- `~/.hermes/logs/sprint/*.log`
- `~/.hermes/logs/sprint/results.csv`
- `telemetry/metrics.jsonl`
- `telemetry/events.jsonl`
- `telemetry/last_state.json`
- telemetry snapshots under `telemetry/snapshots/`
## Test Coverage Gaps
### Current state
On the analyzed repo's `main`:
- `python3 -m pytest -q` -> `no tests ran in 0.01s`
- `python3 -m py_compile bin/*.py` -> passes
- `bash -n bin/*.sh` -> passes
So the repo is parse-clean but untested.
### Important nuance
This is already known upstream:
- `timmy-dispatch#3` explicitly tracks critical-path tests for the repo (issue #3 in the analyzed repo)
That means the honest genome should say:
- test coverage is missing on `main`
- but the gap is already recognized in the analyzed repo itself
### Most important missing lanes
1. `sprint-runner.py`
- provider selection
- fallback behavior
- tool-dispatch semantics
- result logging
2. `telemetry-collector.py`
- state diff correctness
- event emission correctness
- deterministic cron drift detection
3. `model-watchdog.py`
- profile/model expectation map
- drift detection and fix behavior
4. `agent-loop.sh`
- work selection and skip-list handling
- lock discipline
5. `sprint-launcher.sh`
- issue selection and gateway/CLI fallback path
## Security Considerations
### 1. Token handling is shell-centric and leaky
The repo frequently assumes tokens are read from files and injected into:
- shell variables
- curl headers
- clone URLs
- copy-paste prompts
This is operationally convenient but expands exposure through:
- process list leakage
- logs
- copied prompt artifacts
- shell history if mishandled
### 2. Arbitrary shell execution is a core feature
`run_command` in `sprint-runner.py` is intentionally broad. That is fine for a trusted operator loop, but it means this repo is a dispatch engine, not a sandbox.
### 3. `/tmp` workspace exposure
The default sprint workspace location is `/tmp/sprint-*`. On a shared multi-user machine, that is weaker isolation than a private worktree root.
### 4. Generated telemetry is committed
`telemetry/events.jsonl` and `telemetry/last_state.json` are on `main`. That can be useful for paper artifacts, but it also means runtime state mixes with source history.
## Dependencies
### Runtime dependencies
- Python 3
- shell utilities (`bash`, `curl`, `tmux`, `git`)
- OpenAI-compatible SDK/runtime
- Gitea server access
- local Hermes config/auth files
### Optional/ambient dependencies
- local Hermes gateway on port `8642`
- local Ollama endpoint
- Nous portal auth state
### Documentation/research dependencies
- LaTeX toolchain for `paper/`
## Deployment
This repo is not a service deployment repo in the classic sense. It is an operator repo.
Typical live environment assumptions:
- cron invokes shell/Python entry points
- tmux sessions hold worker panes
- Hermes is already installed elsewhere
- Gitea and auth are already provisioned
Minimal validation I ran:
- `python3 -m py_compile /tmp/timmy-dispatch-genome/bin/*.py`
- `bash -n /tmp/timmy-dispatch-genome/bin/*.sh`
- `python3 -m pytest -q` -> no tests present
## Technical Debt
### 1. README contradiction about persistent loops
README says:
- “The system does NOT run persistent agent loops.”
But the repo clearly ships `bin/agent-loop.sh`, described as a persistent tmux-based worker loop.
That is the most important docs drift in the repo.
### 2. Two orchestration philosophies coexist
- cron-fired disposable runs
- persistent tmux workers
Both may be intentional, but the docs do not clearly state which is canonical versus fallback/legacy.
### 3. Target repo already has a genome, but the host issue still exists
This timmy-home genome issue is happening after `timmy-dispatch` already gained:
- `GENOME.md` on `main`
- open issue `#3` for missing tests
That is not bad, but it means the cross-repo genome process and the target repo's own documentation lane are out of sync.
### 4. Generated/runtime artifacts mixed into source tree
Telemetry and research assets are part of the repo history. That may be intentional for paper-writing, but it makes source metrics noisier and can blur runtime-vs-source boundaries.
## Existing Work Already on Main
The analyzed repo already has two important genome-lane artifacts:
- `GENOME.md` on `main`
- open issue `timmy-dispatch#3` tracking critical-path tests
So the most honest statement for `timmy-home#682` is:
- the genome itself is already present in the target repo
- the remaining missing piece on the target repo is test coverage
- this host-repo artifact exists to make the cross-repo analysis lane explicit and traceable
## Bottom Line
`timmy-dispatch` is a small but very revealing repo. It embodies the Timmy Foundation's dispatch style in concentrated form:
- script-first
- cron-first
- tmux-aware
- Gitea-centered
- cheap-model friendly
- operator-visible
Its biggest weakness is not code volume. It is architectural ambiguity in the docs and a complete lack of tests on `main` despite being a coordination-critical repo.

View File

@@ -0,0 +1,39 @@
from pathlib import Path
GENOME = Path("genomes/timmy-dispatch-GENOME.md")
def _content() -> str:
return GENOME.read_text()
def test_timmy_dispatch_genome_exists() -> None:
assert GENOME.exists()
def test_timmy_dispatch_genome_has_required_sections() -> None:
content = _content()
assert "# GENOME.md — timmy-dispatch" in content
assert "## Project Overview" in content
assert "## Architecture" in content
assert "```mermaid" in content
assert "## Entry Points" in content
assert "## Data Flow" in content
assert "## Key Abstractions" in content
assert "## API Surface" in content
assert "## Test Coverage Gaps" in content
assert "## Security Considerations" in content
assert "## Dependencies" in content
assert "## Deployment" in content
assert "## Technical Debt" in content
def test_timmy_dispatch_genome_captures_repo_specific_findings() -> None:
content = _content()
assert "bin/sprint-runner.py" in content
assert "bin/telemetry-collector.py" in content
assert "bin/model-watchdog.py" in content
assert "tmux" in content
assert "results.csv" in content
assert "issue #3" in content.lower() or "issue #3" in content