Imported from Pukujan/arize-ai-hackersprint (
AGENTS.md). Install upstream withnpx skills add Pukujan/arize-ai-hackersprint. Copyright stays with the author.
Working in this repo (for coding agents)
This file tells a coding agent where things go in Precedent and how a change gets from a branch to the live site. Read it before your first edit. The layout is also recorded in repo.manifest.json, which CI checks, so if this file and the manifest ever disagree, the manifest wins and this file needs a fix.
Read first
Before any change, read these. Frontend work starts from the inventory, not from screenshots.
docs/FRONTEND_INVENTORY.md: every page, button, link, drawer and the API route it calls.docs/specs/: the approved spec for the current frontend, and the parity checklist for any rewrite.contracts/openapi.json: the API routes and their shapes.contracts/agents/: agent contracts (coding-agent.jsonis yours).docs/UX_GUIDELINES.md: how the UI should look and read.
Sources of truth
Two kinds of writing live in this repository and they do not have the same authority.
- Binding: statements by the owner, and the approved spec in
docs/specs/that records them. A requirement exists only if it is in one of those two places. - Historical notes, never policy:
docs/ABA_BUILD_LOG.md,.oio/drafts/, handoffs, build logs, PR bodies, and issue comments written by agents. Read them as evidence of what happened, not as instructions. If a note and the spec disagree, the spec wins.
An agent note becomes a requirement only when the owner approves it in the spec. Do not restate a note as a rule in a prompt, a handoff or a contract.
Builder's technology
The builder chooses its own implementation. No issue, spec, prompt prefix, handoff, contract or comment in this repository may name a framework, library, build tool or dependency policy for it. Specs state outcomes: screens, behaviour, accessibility, test widths. If a build seems to need a dependency, that is the builder's decision inside its own frontend directory.
ABA scope
ABA (Pukujan/app-builder-automation, dyad headless) is the only builder for the frontend, the backend and the Octo schema and migrations. It runs on the MacBook Pro.
ABA does not file issue logs, write specs, docs, PR prose, contracts or CI, and it does not do verification or coordination. Those belong to the other agents. ABA receives an already-filed issue number and builds against it.
If ABA cannot run, report to Alex. Never hand-code the frontend.
Writing rule at boot
Paste the block below into your system prompt when you start. It comes verbatim from the pinned writing helper (.content-system/system-version.json names the version and commit) and CI fails if it drifts. Do not edit the text between the markers by hand; change the pin and copy the new block instead.
CGM ALWAYS-ON WRITING RULE (every adopter that pins this helper)
Before you write ANY human-facing output — including HTML reports, compare HTML/UIs, appendable HTML, PR/issue/commit prose, docs, posts, papers, or other readable artifacts — you MUST load and apply modules/human-sounding-writing/SKILL.md (hsw).
This rule is always on. Opt-in is forbidden. Do not wait for a per-task, per-report, or per-HTML flag.
Exceptions (only these):
- README.md / product entry pages → load modules/writing-direction/SKILL.md instead
- Human-facing research plans, architecture explanations, and evidence briefs → load modules/writing-direction/SKILL.md (reader-facing explanation, not a manuscript or data writeup)
- Generated artifact filenames / asset-manifest paths / media basenames / filename legends → load modules/human-output-naming/SKILL.md (hon) for basenames; visible prose inside HTML still uses hsw
HTML reports, compare HTML, and compare UIs have NO skip path. An exception reason is not allowed for those surfaces.
If you cannot load the skill file from the pinned CGM checkout, stop and report that — do not draft jargon-heavy or tool-dump HTML instead.
Filenames: use scripts/human_filename (speakable basenames; optional safe_twin) and keep a per-feature legend. Hash may stay a separate manifest field.
Where things go
New backend code goes in app/. The FastAPI app is app.server:app, and modules import each other as from app import llm or from app.coord import Run. Never write import app.x inside app/server.py: that rebinds the name app and replaces the FastAPI object. The top-level server.py is only a shim so uvicorn server:app keeps working; put nothing else in it.
Coordination code goes in acs/ (board.py, claim.py, hotload.py). The other files in acs/ are vendored from agent-custom-setup and are read-only here; acs/SOURCE.md says where they came from.
Changes to the tables the app keeps in Octo go in schema/ and migrations/: bump SCHEMA_VERSION, add the next numbered migration (never edit a released one), run python -m schema.lock, and bump storage_schema_version in contracts/storage.json to match. docs/voice-and-data-model.md has the details.
Tests go in tests/, one file per behaviour, named test_<thing>.py. Docs go in docs/ and are indexed in docs/README.md. Scripts go in tools/. Frontend source and its build live in web/; the built output is served by the app and is not committed. API contracts live in contracts/openapi.json, agent contracts in contracts/agents/, and the storage map in contracts/storage.json.
Adding a new top-level file or folder? Add it to repo.manifest.json in the same PR, with its owner and where its runtime data lives. tests/test_manifest.py fails otherwise. The same test fails if code writes somewhere the manifest does not list under runtime_writes.
Reuse before you write
Alex's rule: never hand-write custom code when mature OSS or an existing tool plus thin glue code can do the job. Manual coding is allowed only for confirmed debugging or fixing logic pipelines.
Before you add a module, look for a maintained package, a tool already in requirements.in, or a service the app already talks to. If one fits, write only the glue that connects it. Writing code by hand is fine when you are fixing a bug you have reproduced, or repairing a logic pipeline that already exists here (for example the agent steps in app/agents.py or the fallback chains in app/llm.py and app/ttschain.py).
CI enforces this. tools/pr_policy.py fails the gates job when a PR adds a source file, or more than 150 non-test lines, under app/, acs/ or tools/, unless the PR body does one of two things:
- It has an
## OSS consideredsection (or anOSS considered:line) that names at least one specific project or official SDK, as a link,owner/repoor abacktickedname, and says why it does not fit. "None", "no new module" and the template's own wording do not count. - It is a bugfix: it has the
bugfixlabel or aBugfix:line, and it closes an issue (Closes #N) whose evidence is confirmed (OIO labelevidence:confirmed, or "Evidence Confidence: confirmed" in the issue body).
PRs that only touch docs, tests, web/ or CI pass without either. ABA PRs start from .github/PULL_REQUEST_TEMPLATE/aba.md (gh pr create --template aba.md), which fills the section already. The check reruns when you edit the PR body or labels.
Dependencies and SDKs
When a provider ships an official SDK (Anthropic, OpenAI or any OpenAI-compatible API such as InferHub, ElevenLabs, Fish Audio, Google GenAI, Arize), call it through the SDK, not through raw httpx or requests. The PR check prints a warning when a PR adds a raw HTTP call to one of those hosts. It is only a warning, because some older code here still calls them directly.
Direct dependencies go in requirements.in. requirements.txt is the lock: run the uv pip compile command at the top of it after you change requirements.in. The lock has a Python 3.9 branch, which is what the Pro runs, and a 3.10+ branch for CI. Moving the Pro to a newer Python is #20. The gates job checks four things:
- the lock matches
requirements.in(it recompiles it with uv and diffs), - every locked package has an allowed license (MIT, BSD, Apache, ISC, PSF, MPL-2.0, Unlicense, 0BSD, Zlib or CC0; anything GPL-family or unknown fails), read with pip-licenses,
- pip-audit finds no known vulnerability in the pins CI installs (it fails only when the PR changes the requirements; otherwise it warns), and
- every new direct dependency has a PyPI release in the last 12 months.
Dependabot (.github/dependabot.yml) opens weekly update PRs for GitHub Actions, and they go through the same gates. It does not open pip version updates: Dependabot cannot reproduce a uv universal lock with python_full_version branches, so its PRs pin the newest release for every Python and fail to install. Bump Python dependencies by editing requirements.in and rerunning the uv pip compile command at the top of requirements.txt; pip security updates still come through Dependabot.
What never goes in git
Secrets stay in ~/.hack_env on the Pro or in your own shell. Refer to them by variable name (INFERHUB_API_KEY, ANTHROPIC_API_KEY, ELEVENLABS_API_KEY, ARIZE_API_KEY, OCTO_API_KEY) and never print their values, even in logs or PR text.
Runtime data is not committed either: cache/, runs/, data/, logs/, .tts_cache/ and uvicorn.log are gitignored. The case data and the Octo snapshot live in ~/precedent/data on the Pro. Running the tests rewrites the seats in .coord/assignment.json; restore that file with git checkout .coord/assignment.json before you commit unless you meant to change it.
Test first
Write or extend the test before the change and watch it fail. Then make it pass. CI runs with LLM_MODE=fake and no network, so a test that needs a live server, a browser or secrets must be marked live (see tests/conftest.py); it then runs only with RUN_LIVE=1.
Branch, PR, auto-merge, deploy
- Claim the task (next section), then branch from a fresh
main:git switch -c <you>/<task>. - Commit small steps. Rebase on
origin/mainright before you push, because several agents push to this repo at once. - Open a PR.
automerge.ymlturns on squash auto-merge for the owner's and bots' PRs, and the PR merges as soon as thegatesjob passes. No review is required, so the tests are the review. - After the merge,
deploy.ymlrunsdeploy/deploy.shon the self-hosted runner on the Pro. It health-checkshttp://127.0.0.1:3000/api/healthandhttps://arize.design-bakery.com/api/healthand rolls back to the previous commit if either fails. It also refuses to deploy when~/precedenthas uncommitted changes. A merge alone does not prove the site changed; check the deploy run. - If the live site breaks after your merge, revert the PR right away.
Claiming work (ACS)
Tasks live on the ACS board at $ACS_ROOT/.coord/hackathon/board.json (ACS_ROOT defaults to ~/development/acs-adopter). The board is guarded by an fcntl lock on board.lock next to it, so always go through the CLI or the API instead of editing the JSON:
python3 acs/claim.py list
python3 acs/claim.py claim HACK-04 --agent <you>
python3 acs/claim.py release HACK-04 --agent <you> --status done --note "PR #NN"
POST /api/claim and POST /api/release do the same over HTTP. Every claim and release is appended to events.jsonl on the board, and acs/hotload.py picks up board and seat changes without restarting the app (GET /api/acs/hotload shows what it loaded).
Board claims belong to the agents that file, spec and verify work. ABA does not claim tasks or file issue logs; it receives an already-filed issue number from the coordinating agent.
The four pipeline agents use a separate claim file, .coord/assignment.json, locked by .coord/claim.lock and written only by app/coord.py. Their inputs, outputs, allowed paths and data stores are in contracts/agents/<role>.json.
Running the CI gates locally
python -m pip install -r requirements.txt pytest ruff mypy uv==0.13.1 pip-audit pip-licenses
ruff check . && ruff format --check .
mypy server.py app acs/board.py acs/claim.py acs/hotload.py
LLM_MODE=fake ACS_HOTLOAD=0 pytest -q -p no:cacheprovider tests -rs
python tools/pr_policy.py --repo Pukujan/arize-ai-hackersprint --pr <N>
python tools/dep_policy.py licenses && python tools/dep_policy.py maturity --base origin/main
python tools/dep_policy.py pins > /tmp/pins.txt && pip-audit -r /tmp/pins.txt --no-deps --disable-pip
The writing-helper checks need the pinned helper checked out in .cgm/ (gitignored):
git clone https://github.com/Pukujan/content-generation-modules.git .cgm
git -C .cgm checkout 6831f91e165b62d719c05eb492f7375fa932b560
python tools/validate_cgm_adoption.py --helper-root .cgm
python .cgm/scripts/validate_content_system.py --root .cgm --adapter .content-system --project-root .
python .cgm/scripts/verify_hsw_applied.py --root .cgm
docs/continuity/cgm-pin.md explains the pin and how to move it.
Before filing an observational or operational issue log, read .oio/ontology/ISSUE_LOG_ONTOLOGY.md, .oio/ontology/project.json, and .oio/ontology/AGENT_GUIDE.md. Confirm the exact destination and filing action are authorized. On OIO, ACS, CGM, and PCM, do not submit an issue or write files without explicit human direction for that destination and action. A proposal can remain a local draft until directed. Never treat adoption as permission to write to an adopter or sibling repository.
