Development¶
The package map as it is at merge time, the tests, and linting. Back to the README.
Files¶
The holophyte/ package is the factory; factory.py is its entry point.
Each module, one line:
holophyte/__init__.py— the package docstring: which module owns what.holophyte/cli.py— the argument parser and mode dispatch:--report,--requeue,--file-ticket,--sweep [--act],--supervise,--serveand the loop itself.holophyte/target.py— where a target's state lives (HOLOPHYTE_HOME, the<slug>directory, legacy adoption) and theTargetvalue.holophyte/config.py—config.tomland every table it can set, checked at startup.holophyte/gates.py— the verify gate: a ticket's command in, a red or green fail-loud report out.holophyte/agents.py— the agent routes and theagent()call, one turn of a role.holophyte/review.py— reviewer output as structured findings and a verdict.holophyte/findings.py—FINDINGS.mdas a bounded window over the store's rows.holophyte/report.py—--report: estimate vs actual per finished run (actual, estimate, ratio, rounds, outcome) with mean and median ratio, a read-only query over the store that claims no ticket, cuts no worktree and calls no one.holophyte/runs.py— the store seam: a run's progress as store rows.holophyte/board.py— Linear as the notice board: the ticket mirror, its pushes,--file-ticketand the escalation. Ticket status lives in the store and is projected onto a Linear workflow state bymirror_push()— one way, last write wins, never read back — so the provider'sset_stateis the only writer of that state, and the mapping table besidemirror_pushsays which state each status shows as.holophyte/supervisor.py— the stale-run sweep, its report, the lock and the--superviseloop.holophyte/serve.py—--serve PORT|HOST:PORT, the read-only HTTP daemon.holophyte/loop.py— the loop: worktree setup and reuse,run_task,main,report,requeueand the self-merge re-exec.holophyte/reexec.py—reexec_self, the shared self re-exec the loop and the supervisor both restart themselves through.
The store is its own package:
store/__init__.py— the v2 durable state store, one WAL-mode SQLite file: schema, claims and leases, ticket and run-phase transitions, review rounds, interventions, and the state-graph renderer.store/read.py— typed read views over the store: one query, one row type, no SQL elsewhere.
At the root:
factory.py— the entry point: importsclifrom the package and calls it. Holds nodeforclassof its own.provider.py— theProviderprotocol the loop talks to a board through.linear_provider.py— the Linear GraphQL client: claim/fetch_task/ set_state/comment, ready-ticket and blocker resolution, issue creation.review_runner.py— exact-SHA staging and the model-neutral local reviewer boundary (see Reviewing).ticket_template.py— parser/validator for the ticket shape;python3 ticket_template.py TICKET.md [...]exits 0 iff the ticket is pickable-ready.ticketTemplate.md— the ticket shape. Verify commands go in the "Verify command(s)" section (exit 0 = pass, relative paths only); estimate is the budget in minutes. The optional "Contract checks" section declaresrelative/path: exact literallines the gate asserts verbatim, so a required value (a port, a URL) cannot drift while the commands still pass.docker/reviewer.Dockerfile— pinned minimal reviewer image.FINDINGS.md(generated) — a rendered window over the store, not a log: the factory regenerates it at each close-out fromruns/reviewRoundsas the newest 25 entries below a<!-- store-rendered below -->marker, with everything older counted in one archive line and kept in the store. Text above the marker is frozen pre-store history and is never rewritten; Linear ticket comments stay the full per-ticket archive.tests/— the stdlib unittest suite, onetest_*.pyper surface, withtests/fake_agent.py,tests/procs.pyandtests/waiting.pyas shared helpers. Run it withHOLOPHYTE_HOME=$(mktemp -d) python3 -m unittest discover -s tests.
Linting¶
ruff check . from the repo root; it exits 0 when the tree is clean. Run it
alongside the tests — the developer verify path is:
ruff check .
python3 -m unittest discover -s tests
The configuration lives in ruff.toml: line length
88, target py311, and rule sets E, F, W, I, C90 (pycodestyle
errors and warnings, pyflakes, import ordering, McCabe complexity). Nothing is formatted, only checked.
Every enabled rule is a promise the factory keeps forever, so the selection
stays small, and a violation that has to stand is suppressed with a per-line
# noqa: <CODE> rather than a file-level or blanket ignore.
Cyclomatic complexity above 12 is a lint failure (ruff C901); an exemption
is a per-function noqa: C901 that names its reason and the ticket that
retires it.
ruff is a developer tool, not a dependency: install it on the host with
pip install --user ruff (or uv tool install ruff). It is never vendored.