anomalyco/opencode
19 AGENTS.md files, 723 test files and its own agent reviewing every pull request; no lint or secret scan in the pipeline, and a script called dev: that opens a production shell. Below is the run the agent did and the AINE-REPORT.md it wrote.
- 31 passed
- 15 failed
- 0 n/a
- TypeScript · Bun + Turborepo · Effect + SolidJS · bun test + Playwright · SST on AWS · GitHub Actions
Run 14 August 2026 · dev at e23586a
The agent run
I cloned anomalyco/opencode into a temp folder, audited it against all 46 checks and wrote the full report to AINE-REPORT.md in the repo.
AI-Native Readiness — anomalyco/opencode
31 passed · 15 failed · 0 not applicable
High priority — fix these first
- Add three sections to
AGENTS.md— this one file is the root cause of three failures. The commands it omits (bun install,bun dev,bun run lint, plus one line routing toCONTRIBUTING.mdfor setup and the standalone build); a ten-line Layout section naming what each top-level package owns; and a "Never run without asking" list covering the*-prodscripts,dev:stats,bun sst deploy,db:push/db:migrateandscript/publish.ts. Why:AGENTS.mdis loaded every session and is a flat rule sheet with no pointers — an agent cannot find the build command, cannot tellpackages/corefrompackages/web(~40 packages exist, 10 have anAGENTS.md,packages/corehas none), and cannot tellbun devfrom a script that opens a production shell. - Add a
checkscript to the rootpackage.jsonchaining lint, typecheck,bun turbo testandcheck:generated, then name it inAGENTS.md. Why: proving a change today means running five separate commands an agent can only learn by reading.github/workflows/test.yml. - Add three steps to
.github/workflows/test.yml:bun run lint,bunx prettier --check ., and a gitleaks scan. Why: oxlint has a 60-line tuned config and never runs in CI, so nobody knows its baseline; Prettier is configured and unenforced;.gitleaksignoreproves gitleaks is run somewhere, but nothing in the repo runs it. - Add a "Verifying a change" block to
CONTRIBUTING.mdwithbun turbo test,bun typecheckandbun run lint, then link it from the README. Why: 723 test files exist and neither the README norCONTRIBUTING.mdmentions tests at all — a contributor following the docs never learns they exist. - Put a confirmation in front of the production scripts: a typed prompt in
script/promote-models.tsandscript/promote-limits.tswhen the stage isproduction, and an explicit--yesfordb-prod. Why:bun run --cwd packages/console/core db-prodrunssst shell --stage production -- drizzle-kitstart to finish with no confirmation and no dry run. - Scope the AWS session — do this after 5, it is the same blast radius. Give production its own SSO session name so
bun run ssogrants dev only, and repointdev:stats, which today runsbun sst shell --stage=production. Why: onebun run ssoputs the production Stripe key, the PlanetScale token and the Cloudflare token within reach of any agent with shell access.
Low priority — worth doing
- Add
specs/TEMPLATE.md(Goal, Non-Goals, Design, Acceptance criteria, Open questions) and pointAGENTS.mdat it — the 14 existing specs come in four different shapes. - Then refresh the specs against the code. Every file in
specs/was last touched on 2026-06-30, 45 days and roughly 1,300 commits ago, whilespecs/v2/todo.mdstill describes the v2 work as in flight. Do this after the template exists, so there is a shape to refresh them into. - Add
.github/dependabot.ymlcovering all five lockfile directories — nothing watches dependencies today. - Add a "Rolling back" section to
CONTRIBUTING.md(revert-and-redeploy per SST stage,npm dist-tagfor a bad CLI release) and start writing down-migrations next to the Drizzle SQL.
Worth saying plainly: the parts of this harness that exist are good. The root AGENTS.md is almost entirely repo-specific — Effect generator rules, Drizzle column conventions, ten paragraphs of V2 Session Core invariants — and every claim in it that I checked still resolves against the code. CONTEXT.md is 110 numbered architecture invariants with banned synonyms next to each term. The repo runs its own product as its PR reviewer, with bash denied and gh pr review blocked so it can comment but not approve. What fails is mostly the edges: the entry point never tells an agent how to build, nothing chains the checks into one command, and the fence between everyday development and production is missing.
Two things to flag about the run itself. Bun is not installed on this machine, so no test, lint, typecheck or build command in the repo could be executed — the four items that ask "and does it pass?" say so in their proofs rather than guessing. And this is a ~40-package monorepo: I audited the root, and per-package answers will differ, since packages/llm and packages/app carry thorough local AGENTS.md files that the root does not.
The report it wrote
AI-Native Readiness Report
Repo: anomalyco/opencode, a fresh clone of dev at commit e23586a (6,513 tracked files)
Date: 2026-08-14
Stack: TypeScript monorepo on Bun 1.3.14 (packageManager pinned), Bun workspaces + Turborepo, ~40 packages under packages/. Effect v4 + Drizzle + Hono/HttpApi on the server, SolidJS + opentui for the TUI, SolidJS + Electron for desktop/web. Tests are bun test per package plus Playwright e2e. Lint is oxlint, format is Prettier, types are tsgo --noEmit via turbo. Infra is SST on AWS + Cloudflare + PlanetScale, deployed by GitHub Actions. Nix flake and Dockerfiles present.
Result: 31 passed, 15 failed, 0 not applicable.
How to read this. Every item is a numbered question about this repo, answered from evidence in this repo. Proof is what was actually found — a path, a file, a command and its output. An item with no proof is not an answer. The italic line under each question says how to check it; it stays in the report so the next run checks the same way.
FAIL vs N/A. FAIL means the practice would help here and it is missing — including when a whole artifact is missing, so several questions about it fail together with a one-line proof pointing at the item that found it missing. N/A means the question could never apply to a project of this kind, and the proof says why. "It does not exist" is a FAIL, never an N/A.
Priority is fixed by the template, not by the person filling it in. High means an agent working here will hit this on day one, or the risk is real. Low means it makes things better but nothing breaks without it.
One limit on this run, stated up front. Bun is not installed on the audit machine (bun --version → command not found), so no test, lint, typecheck or build command in this repo could be executed. Every item that asks "and does it pass?" says so in its proof rather than assuming an answer.
1. Context
-
1. Does an agent instruction file exist (AGENTS.md, CLAUDE.md, .cursorrules, .github/copilot-instructions.md, or this ecosystem's equivalent), and what does it point at? Look for a file whose purpose is to be loaded into a coding agent's context at the start of every session. That file is the entry point. Then follow its pointers: instructions are commonly spread across several files, with the entry point routing to them — "commands are in docs/development.md", "conventions in .claude/rules/". The entry point plus every file it points at is the instruction set, and every other agent-instruction question is answered against that whole set, so list it here in the proof. Follow pointers as deep as they go, but a pointer only counts when it names a target and says what is in it: "test commands are in CONTRIBUTING.md" counts, a bare "see the docs" does not, and a file nothing points at is outside the set however good it is. A README is not an entry point, however good — it gets its credit at the README item and the specs-and-architecture item — but a README the entry point explicitly routes to is inside the set. Vendored skill libraries are not instructions either.
- Status: PASS
- Proof: Entry point is
AGENTS.mdat the repo root (8,748 bytes). It contains no pointers to other documents — it is a single flat rule sheet, not a routing table. The rest of the set comes from the AGENTS.md upward-discovery convention, which this repo both follows and implements (CONTEXT.md: "the instruction-service slice observes global and upward projectAGENTS.mdfiles as one ordered aggregate Context Source"): 18 nested files,packages/{app,codemode,desktop,effect-drizzle-sqlite,llm,opencode,schema,session-ui,stats,ui}/AGENTS.md, pluspackages/app/e2e/AGENTS.md,packages/app/e2e/performance/AGENTS.md,packages/core/src/tool/AGENTS.md,packages/opencode/src/server/routes/instance/httpapi/AGENTS.md,packages/opencode/src/session/llm/AGENTS.md,packages/opencode/test/AGENTS.md,packages/opencode/test/server/AGENTS.md. Alongside it,.opencode/opencode.jsoncsupplies tool and reference config,.opencode/skills/two skills,.opencode/command/eight commands,.opencode/agent/two subagents. Not in the set:CONTEXT.md(32,094 bytes of architecture and glossary) andCONTRIBUTING.md— nothing in AGENTS.md routes to either, so an agent only reads them by accident. - Recommendation: —
- Priority: High
-
2. Do the agent instructions name the commands to build, test and check this project? Answer this against the instruction set mapped at the entry-point item and nothing outside it. If no entry point exists, FAIL with a one-line proof pointing at that item. The commands may sit in a file the entry point routes to rather than in the entry point itself — that is progressive disclosure working as intended, and it passes. What fails is a command an agent would have to guess its way to: if the commands live only in the README or the manifest and nothing in the set points at them, that is a FAIL, because the question measures what an agent can reach without being told where to look. Name the file each command was found in.
- Status: FAIL
- Proof: Two of the four are there. Test:
AGENTS.md:145"Tests cannot run from repo root (guard:do-not-run-tests-from-root); run from package dirs likepackages/opencode." Typecheck:AGENTS.md:149"Always runbun typecheckfrom package directories, nevertscdirectly." Codegen:AGENTS.md:1-2names./packages/sdk/js/script/build.tsandbun run generatefrompackages/client. Missing from the whole set: build —bun install,bun devand./packages/opencode/script/build.ts --singleappear only inCONTRIBUTING.md, which no AGENTS.md file points at; and lint —bun run lint(oxlint) is named inpackage.json:15and nowhere in the instruction set.packages/app/AGENTS.md:14names one backend serve command, so the set is not silent, just incomplete. - Recommendation: Add four lines to the top of
AGENTS.md:bun install,bun dev,bun run lint, and "contributor setup, debugging and the standalone build are inCONTRIBUTING.md". - Priority: High
-
3. Does everything the agent instructions name still exist — the commands, the paths, the libraries, and the files they point at? If no entry point exists, FAIL with a one-line proof pointing at the entry-point item. Verify, do not trust: check every named command against the manifest or build file, spot-check the paths, run the cheap read-only ones. Then resolve every pointer in every file of the set — a link to a moved or deleted file is the most common rot in a multi-file instruction set, and it fails silently: the agent reads the entry point, follows nothing, and carries on without the rules.
- Status: PASS
- Proof: Every claim checked resolves.
packages/sdk/js/script/build.tsexists.packages/client/package.jsonhas"generate": "bun run script/build.ts", and bothpackages/client/src/generatedandsrc/generated-effectexist.git symbolic-ref refs/remotes/origin/HEAD→refs/remotes/origin/dev, matching "the default branch in this repo isdev". The test guard is real:bunfig.toml:8root = "./do-not-run-tests-from-root", and rootpackage.json:23"test": "echo 'do not run tests from root' && exit 1". The self-export pattern claim checks out:packages/core/src/config/agent.ts:1isexport * as ConfigAgent from "./agent".bun typecheckexists as a script in every package listed. No file pointers exist in the set to rot (see the entry-point item). - Recommendation: —
- Priority: High
-
4. Are the agent instructions specific to this repo, rather than advice that would read the same in any codebase? If no entry point exists, FAIL with a one-line proof pointing at the entry-point item. The test: could this be pasted into another project unchanged? "Write clean code" and "add tests for new features" would fit anywhere and count for nothing. Judge the whole set, but weigh the files differently: an entry point that is mostly a routing table is fine, even good, when what it routes to is specific — while generic filler in the entry point costs more than generic filler three hops down, because it is loaded into every session whether it is needed or not. Say which files carried the specifics.
- Status: PASS
- Proof: The entry point is almost entirely repo-specific and would break if pasted anywhere else.
AGENTS.md:3fixes the dependency direction (Schema → Core/Protocol → Server; Client may never depend on Core or Server).AGENTS.md:33"In Effect generators, bind services to named variables before calling methods. Do not use nested service yields such asyield* (yield* Foo.Service).bar()."AGENTS.md:121-138mandates snake_case Drizzle columns with a good/bad example.AGENTS.md:151-161is ten paragraphs of V2 Session Core invariants namingSessionV2.prompt,SessionExecution.wake,SessionRunCoordinator. The generic residue is small and confined to a few style bullets ("Avoidtry/catch", "Avoid using theanytype"). Nested files continue the pattern —packages/llm/AGENTS.mdis 24,684 bytes of protocol-adapter rules. - Recommendation: —
- Priority: High
-
5. Do the agent instructions explain where things live and how this project is laid out? If no entry point exists, FAIL with a one-line proof pointing at the entry-point item. The map may live in a routed-to file. Judge coverage against the real tree, not against what the files mention: if the set maps one package well but is silent about sibling packages or directories an agent would land in, that is a FAIL with the omission named. In a multi-file set, check the routing too — a layout document nothing points at is a document the agent never opens.
- Status: FAIL
- Proof: There is no layout map anywhere in the instruction set.
AGENTS.md:3gives a dependency direction between five packages but never says what any directory contains or lists the workspace. The tree has ~40 packages (packages/*,packages/console/*,packages/stats/*,packages/sdk/js,packages/slackperpackage.json:25-32) and only 10 have a package-level AGENTS.md. Silent on:packages/core(the largest package — it has onlysrc/tool/AGENTS.md, three levels down),packages/client,packages/protocol,packages/server,packages/plugin,packages/tui,packages/web,packages/console/*,infra/,script/,sdks/. A "Core pieces" list does exist — inCONTRIBUTING.md, which nothing in the set points at, so an agent never opens it. - Recommendation: Add a ten-line "Layout" section to
AGENTS.mdnaming what each top-level package owns, or add the one line "package layout and core pieces are described inCONTRIBUTING.md" so the existing list becomes reachable. - Priority: High
-
6. Do the agent instructions state the rules that are not obvious from the code — the things never to do here? If no entry point exists, FAIL with a one-line proof pointing at the entry-point item. These are the tribal-knowledge traps: the flag that must be exactly this string, the import that breaks the build, the directory that is generated and must not be edited. Rules in a routed-to file count. Two extra checks in a multi-file set: that the entry point signposts the rules clearly enough for an agent to open them before it needs them, since a trap found afterwards has already been sprung; and that the files do not contradict each other, because nothing tells the agent which one wins.
- Status: PASS
- Proof: The traps are named in the entry point, which is where an agent hits them first.
AGENTS.md:2"Do not editsrc/generatedorsrc/generated-effectdirectly."AGENTS.md:145the root test guard.AGENTS.md:149"nevertscdirectly".AGENTS.md:61-62"Never alias imports" and "Never use star imports".AGENTS.md:5"Localmainref may not exist; usedevororigin/devfor diffs" — pure tribal knowledge, and exactly the kind that silently wastes an agent's turn. No contradiction found between the entry point and the nested files;CONTRIBUTING.md's style list is a softer restatement ("not strictly enforced") of the same rules, and it sits outside the set anyway. - Recommendation: —
- Priority: Low
-
7. Has the agent instruction file been updated recently enough to still be true, given how active the repo is? If no agent instruction file exists, FAIL with a one-line proof pointing at the entry-point item. Compare the last commit touching the file against the repo's tempo, then spot-check two or three of its claims against the code — a recently touched file can still lie.
- Status: PASS
- Proof:
git log -1 -- AGENTS.md→ 2026-06-25 (#33777), 50 days before HEAD. The repo's tempo is high: 3,178 commits since 2026-05-04 in the fetched history, 66 in the last 7 days. That gap is wide enough to be worth watching, but the spot-checks all held — thedo-not-run-tests-from-rootguard is still inbunfig.toml:8,packages/core/src/config/agent.ts:1still uses the documented self-export, andpackages/client/src/generated-effectstill exists. Nothing in the file was found to be false. - Recommendation: —
- Priority: Low
-
8. Is the agent instruction file small enough to load into every session without crowding out the actual task? If no agent instruction file exists, FAIL with a one-line proof pointing at the entry-point item. Measure it:
wc -c, and bytes divided by four is a fair token estimate. Under ~5k tokens is comfortable; past ~10k it is eating the context window.- Status: PASS
- Proof:
wc -c AGENTS.md→ 8,748 bytes ≈ 2.2k tokens. Comfortable. Worth knowing for later: because nested files stack on the root one, an agent working inpackages/llmloads 8,748 + 24,684 = 33,432 bytes ≈ 8.4k tokens before it reads a line of code, andpackages/llm/AGENTS.mdis the one file in the set approaching the ceiling on its own. - Recommendation: —
- Priority: Low
-
9. Can a fresh session pick up a half-finished task — is there a file or convention where progress, decisions and what is left get written down? This is not about the agent instruction file. Any durable place in-flight state gets written counts: a TODO.md, a plans or notes directory, task files, linked issues, a specs folder whose entries carry progress and open questions, an agent memory file or directory, a scratchpad or working-notes convention. The test is whether a fresh session could read it and know what was decided and what is left — not what the place is called. Git history alone does not count: it records what happened, not what was decided or what remains.
- Status: PASS
- Proof:
specs/v2/todo.mdis exactly this: work-in-progress state with owners and remaining scope — "## Post-Hono cleanup - Kit … Remaining work is mostly cleanup: delete compatibility shims, shrink Zod surfaces", "## New Data Mode - Dax … This is mostly done. I'm working through modeling subagents, skill invocations and shell commands."CONTEXT.md:223-226carries a "Flagged ambiguities" section andCONTEXT.md:179an explicit "Open question:".CONTRIBUTING.mdmandates an issue per PR, so per-task state also lives in linked issues. - Recommendation: —
- Priority: Low
-
10. Is there a README that says what this project is and how to run it? This is where a good README earns its credit. It needs three things: what the project is, how to run it, and how to check a change. Judge what is on the page, not the file's existence.
- Status: FAIL
- Proof: Two of three. What it is: yes — "The open source AI coding agent", plus the agents section and a screenshot. How to run it: yes for users (
curl … | bash, npm/scoop/brew/pacman/nix, desktop downloads) and by link for contributors (./CONTRIBUTING.md, which hasbun install/bun dev). How to check a change: nowhere.README.mdnever mentions tests, and neither doesCONTRIBUTING.md— I grepped both; there is nobun test, nobun turbo test, no typecheck command in either file, despite 723 test files in the repo. A contributor following the README end to end never learns that tests exist. - Recommendation: Add a "Verifying a change" block to
CONTRIBUTING.mdwithbun turbo test,bun typecheckandbun run lint, and link it from the README's Contributing section. - Priority: High
2. Specs
-
11. Is the thinking behind this system written down somewhere durable — a specs, RFC, proposals, design-doc or ADR directory, or architecture notes that record not just what but why? Look for the place and for the convention:
specs/,docs/adr/,rfcs/,proposals/,.specify/, a docs or design folder, architecture notes anywhere in the tree, or this ecosystem's equivalent. Judge substance, not location: "we use X because Y" is a decision, a list of technologies is not, an essay about specs is not a spec, and a docs folder of usage guides with no reasoning is a FAIL whose proof says what was in there instead. Other items are answered against whatever this item finds, so name it precisely — and where forward-looking specs and after-the-fact architecture records live in different places, name both, since a decision log cannot answer a question about acceptance criteria.- Status: PASS
- Proof: Two places, both substantial. Forward-looking design:
specs/— 14 files, 151KB inspecs/v2/alone (session.md28,965 b,config.md29,396 b,schema-changelog.md40,158 b,provider-policy.md,provider-model.md,tools.md,instructions.md,catalog-config-plugin-lifecycle.md,todo.md), plusspecs/project.md,specs/tui-package.mdandspecs/storage/. Architecture-of-record with reasoning:CONTEXT.md(32,094 b) — a ubiquitous-language glossary with banned synonyms ("Avoid: System prompt") and 110 numbered invariants that state why, e.g.CONTEXT.md:105"unavailable initial context blocks the turn instead of persisting an incomplete baseline". This is reasoning, not a technology list. - Recommendation: —
- Priority: High
-
12. Does the specs directory hold recent entries, or is it an archive nobody has touched? If no specs directory exists, FAIL with a one-line proof pointing at the specs-and-architecture item. Otherwise compare the newest entry's date against the repo's recent activity.
- Status: FAIL
- Proof: Every file in
specs/was last touched on 2026-06-30 (git log -1per file, all 14).CONTEXT.mdlast moved 2026-06-26. HEAD is 2026-08-14 — a 45-day gap on a repo doing ~66 commits a week, and the v2 work these specs describe is explicitly still in flight (specs/v2/todo.md, and the "V2 Session Core" section ofAGENTS.mdwas itself edited later, on 2026-06-25). The specs are drifting behind the code they govern. - Recommendation: When a v2 slice lands, update the matching
specs/v2/*.mdin the same PR; start withspecs/v2/todo.md, whose owner-by-owner status is now six weeks old. - Priority: Low
-
13. Is there a spec template, or an SDD framework, so every spec comes out the same shape? Scaffolding can exist even where no specs directory does — look for a TEMPLATE.md, a
.specify/directory, or framework config. If neither a directory nor any scaffolding exists, FAIL.- Status: FAIL
- Proof: No
specs/TEMPLATE.md, no.specify/, no framework config (ls specs/TEMPLATE.md .specify→ both No such file or directory). The 14 specs have visibly different shapes:specs/project.mdis a bare API sketch,specs/v2/instructions.mdis a conventions guide,specs/v2/provider-policy.mdhas a## Non-Goalsheading no other spec uses,specs/v2/todo.mdis a status list. - Recommendation: Add
specs/TEMPLATE.mdwith the headings the better specs already use — Goal, Non-Goals, Design, Acceptance criteria, Open questions — and pointAGENTS.mdat it. - Priority: Low
-
14. Do the specs state acceptance criteria a machine could check? If no specs exist, FAIL with a one-line proof pointing at the specs-and-architecture item. Otherwise open the two newest specs and quote a criterion: "the endpoint returns 403 for expired tokens" is checkable; "the feature works well" is not.
- Status: PASS
- Proof:
specs/v2/session.md:206— "A later commit-time failure leaves earlier operations applied and returns an explicit partial-application report."CONTEXT.md:175— "sessions.message({ sessionID, messageID })… An unknown Session fails withSessionNotFoundError; a known Session with an absent or differently owned message fails withMessageNotFoundErrorwithout disclosing cross-Session ownership."CONTEXT.md:176— "interruption is idempotent: idle, already-settled, or locally unowned execution is a no-op." All three are directly testable. Not every file carries them:specs/v2/instructions.mdandspecs/v2/todo.mdare direction and status only. - Recommendation: —
- Priority: High
-
15. Open the newest spec: do its criteria go past the happy path — what happens when a step fails, and how the change gets undone? If no specs exist, FAIL with a one-line proof pointing at the specs-and-architecture item. Look for error cases, edge inputs, and a rollback or undo story, not just the success flow.
- Status: PASS
- Proof: All
specs/v2/*share the same 2026-06-30 date, so I took the substantive newest,specs/v2/session.md. It covers failure and undo explicitly, including where undo is not offered: line 206 "A later commit-time failure leaves earlier operations applied and returns an explicit partial-application report. Moves and atomic rollback remain separate follow-ups rather than implied behavior."specs/v2/schema-changelog.md:613,618does the same — "they avoid claiming rollback or transactionality that path-based filesystem commits do not provide" and "Moves and atomic rollback are deliberately unsupported in the first slice and remain visible follow-ups." Naming the missing rollback is better than pretending to one. - Recommendation: —
- Priority: Low
-
16. Do the specs state non-goals, so an agent knows where to stop? If no specs exist, FAIL with a one-line proof pointing at the specs-and-architecture item. Non-goals written elsewhere (a README's "what this is not" list) are worth naming in the proof, but they do not turn this into a PASS — the question is whether specs carry them.
- Status: PASS
- Proof:
specs/v2/provider-policy.md:30has an explicit## Non-Goalsheading — the only one of the 14 files that does. The convention still carries through the rest as inline scope fences rather than a section:specs/v2/session.md:206"Moves and atomic rollback remain separate follow-ups rather than implied behavior",specs/v2/instructions.md"Do not use hooks as a dumping ground for transport concerns, UI behavior, or compatibility shims",CONTEXT.md:216"The initial non-streaming Session surface does not exercise this lifetime boundary". An agent reading any of these knows where to stop. - Recommendation: —
- Priority: Low
-
17. Can recent shipped work be traced back to a spec? If no specs exist, FAIL with a one-line proof pointing at the specs-and-architecture item. Otherwise take the last few substantial commits or PRs and look for a reference to a spec, an issue, or a design doc in the message or description.
- Status: PASS
- Proof: Every merged commit carries its PR number —
git log --oneline -15showsfeat(go): add GLM 5.3 (#42518),fix(opencode): preserve v1 database compatibility (#42444),fix(core): preserve unicode in grep previews (#42356). The trail is enforced, not incidental:CONTRIBUTING.md"All PRs must reference an existing issue. … PRs without a linked issue may be closed without review",.github/pull_request_template.mdopens with "### Issue for this PR / Closes #", and.github/workflows/pr-standards.ymlchecks PRs against the standards automatically. - Recommendation: —
- Priority: Low
3. Verification
-
18. Does this project have an automated test suite, in whatever form this ecosystem uses? Work out this ecosystem's convention before concluding anything is missing — check the manifest, the build file, the CI config, the README. A shell script that diffs output files is a test suite. If you find one, run it and record the result.
- Status: PASS
- Proof: 723 tracked
*.test.ts/*.test.tsxfiles (git ls-files | grep -c), 245 of them underpackages/opencode/testalone. Runner isbun testper package: 16 packages declare atestscript, driven from the root bybun turbo test(turbo.jsondefinesopencode#test,@opencode-ai/core#test,@opencode-ai/app#test,@opencode-ai/ui#test,@opencode-ai/session-ui#test). Playwright e2e on top:packages/apphastest:e2e,test:e2e:local,test:browser,test:stability,test:bench. Could not execute it —bun --version→command not foundon the audit machine — so the pass/fail state of the suite today is unverified;.github/workflows/test.ymlruns it on Linux and Windows for every pull request. - Recommendation: —
- Priority: High
-
19. Can the test command be discovered without guessing — is it written down where an agent reads? If no test suite exists, FAIL with a one-line proof pointing at the test-suite item. Otherwise check the places an agent looks: the agent instruction file, the README, the manifest's scripts or targets.
- Status: PASS
- Proof:
AGENTS.md:145tells the agent where to run tests from and warns about the root guard: "Tests cannot run from repo root (guard:do-not-run-tests-from-root); run from package dirs likepackages/opencode."packages/opencode/test/AGENTS.mdandpackages/opencode/test/server/AGENTS.mdcover test conventions locally. The manifests are self-explanatory ("test": "bun test …"in 16 packages), and the rootpackage.json:23fails loudly withecho 'do not run tests from root'rather than silently doing nothing. The README is silent, which is the gap recorded at the README item, not here. - Recommendation: —
- Priority: High
-
20. Do the tests assert real behaviour, rather than asserting that a mock was called? If no test suite exists, FAIL with a one-line proof pointing at the test-suite item. Otherwise open the largest test files and read the assertions: calling real code on real inputs passes;
expect(mock).toHaveBeenCalled()as the main dish fails.- Status: PASS
- Proof: The rule is stated —
AGENTS.md:143-144"Avoid mocks as much as possible, you shouldn't be using globalThis.* at all unless it's the only option. Test actual implementation, do not duplicate logic into tests" — and the code follows it. The largest test file inpackages/core,test/session-runner.test.ts(129,541 b), imports and drives the real stack:Database,AppNodeBuilder,LayerNodePlatform,EventV2,PermissionV2,SessionV2,Snapshot, and the realOpenAIChatprotocol adapter. Only 26 of 245 files underpackages/opencode/testmention a mock at all. There is also a recorded-HTTP harness (packages/http-recorder,packages/llmsetup:recording-env) so provider tests replay real traffic instead of stubbing it. - Recommendation: —
- Priority: High
-
21. Is there a linter or static analysis configured for this language, and does it pass on a clean checkout? Configured is not enough — run it. A linter that exits non-zero on an untouched checkout is a FAIL with the error count in the proof, because an agent cannot tell its own damage from the baseline noise.
- Status: FAIL
- Proof: Configured, unrunnable here, and ungated.
.oxlintrc.jsonis a real, tuned config ("typeAware": true,suspicious→ warn, ~15 rules disabled with a comment each explaining the Effect or SolidJS reason),oxlint@1.60.0andoxlint-tsgolint@0.21.0are devDependencies, andpackage.json:15has"lint": "oxlint". I could not run it — Bun is not installed on the audit machine, and the type-aware mode needs installed workspace dependencies. More to the point for an agent working here:grep -rni 'oxlint\|lint' .github/workflows/returns nothing, so no run of this linter is enforced anywhere, and its baseline on a clean checkout is unknown to everyone, not just to me. - Recommendation: Add a
lintjob to.github/workflows/test.ymlrunningbun run lint, so the baseline is proven green on every PR and an agent can trust the output it sees. - Priority: High
-
22. Is there a formatter, so an agent's diffs do not churn on style? Look for the config file and the dependency in this ecosystem's form — .prettierrc, rustfmt, gofmt, black, an .editorconfig doing real work. If the language ships one formatting standard with the toolchain, that is a PASS and the proof says so.
- Status: PASS
- Proof: Prettier 3.6.2 is a devDependency, configured inline at
package.json:125-128("semi": false, "printWidth": 120), with.prettierignoreandscript/format.tsalongside it..editorconfig,.vscode/settings.example.jsonand.zed/settings.jsonare all committed, so editors agree with the CLI. The settings are unambiguous enough that an agent's diff will match the surrounding code. - Recommendation: —
- Priority: Low
-
23. Is there a compile-time or type-level gate, if this language offers one? N/A only when the language genuinely has no such gate. If the language offers one and the repo does not use it — no strict mode, no typecheck script, no compiler step — that is a FAIL. Run the gate if it exists and record the result.
- Status: PASS
- Proof: TypeScript, gated in three places. Every package has a
typecheckscript (tsgo --noEmit), the root has"typecheck": "bun turbo typecheck"andturbo.jsondeclares the task,.github/workflows/typecheck.ymlrunsbun typecheckonpull_requestintodev, and.husky/pre-pushrunsbun typecheckbefore any push (after first asserting the local Bun version matchespackageManager). Could not run it here — Bun is not installed on the audit machine — but the gate exists and is enforced in two independent places. - Recommendation: —
- Priority: Low
-
24. Can an agent prove its own work before it pushes — one command, task-runner target or commit hook that runs every check this project has? One command, not a list to remember: a
checkorverifytarget, aprecommitscript, a Makefile target that chains them. Separate commands documented side by side are close but FAIL — the question is whether the agent can run the whole gauntlet without knowing its parts.- Status: FAIL
- Proof: The parts exist and nothing chains them. Root
package.jsonhaslint,typecheckand atestthat deliberately exits 1;turbo.jsonhastypecheck,buildand per-packagetesttasks but nocheckorverifytask..husky/pre-pushruns the Bun version assertion andbun typecheck— types only, no tests, no lint. An agent must know to runbun turbo test, thenbun typecheck, thenbun run lint, thenbun run --cwd packages/client check:generated, thenbun --cwd packages/opencode test:httpapi— five commands it can only learn by reading.github/workflows/test.yml. - Recommendation: Add
"check": "bun run lint && bun typecheck && bun turbo test && bun run --cwd packages/client check:generated"to the rootpackage.jsonand name it inAGENTS.md. - Priority: High
-
25. Is there continuous integration, and does it run before a change lands rather than after? A deploy pipeline that runs on push to the default branch runs after the change has landed — that is a FAIL with the trigger quoted, not a PASS with a caveat. Look for a pre-merge trigger: pull_request events, merge trains, or this forge's equivalent.
- Status: PASS
- Proof: 25 workflows in
.github/workflows/, and the two that gate correctness are pre-merge.test.yml:on: push: branches: [dev]andpull_request:— so every PR runs unit tests on Linux and Windows plus Playwright e2e.typecheck.yml:on: pull_request: branches: [dev].pr-standards.ymlalso runs pre-merge. The post-merge workflows (deploy.yml,publish.yml) are separate and do not stand in for the gate. - Recommendation: —
- Priority: High
-
26. Does CI actually run the tests and the checks that exist in this repo? If no pipeline of any kind exists, FAIL with a one-line proof pointing at the CI item. Otherwise list what the pipeline runs and diff it against every check found in the Verification section — name each check that exists in the repo but is missing from the pipeline.
- Status: FAIL
- Proof:
test.ymlrunsbun turbo test,bun run check:generated,bun run test:httpapiandbun --cwd packages/app test:e2e:localon Linux and Windows;typecheck.ymlrunsbun typecheck. Two checks that exist in this repo never run in CI: oxlint —grep -rni 'lint' .github/workflows/returns nothing, whilepackage.json:15defines"lint": "oxlint"against a 60-line tuned.oxlintrc.json; and Prettier —prettier3.6.2,.prettierignoreandscript/format.tsare committed but no workflow runs a format check, so formatting drift lands unnoticed. - Recommendation: Add
bun run lintand abunx prettier --check .step to.github/workflows/test.yml. - Priority: High
-
27. Does anything here get an LLM to read a change and go looking for problems — a review skill, a saved review prompt, or an AI reviewer on the pull requests? Look for a committed review skill or slash command, a CI step calling an AI reviewer, or bot config. Human review rules are a Safety item; this one is specifically about machine review.
- Status: PASS
- Proof:
.github/workflows/review.ymlruns opencode itself as the reviewer on a/reviewcomment from an OWNER or MEMBER, with-m opencode/gpt-5.5, a long committed prompt that checks the diff against the style guide and looks for bugs, andOPENCODE_PERMISSION: '{ "bash": { "*": "deny", "gh*": "allow", "gh pr review*": "deny" } }'so the reviewer can comment but cannot approve. Alongside it:.github/workflows/opencode.yml(agent on/occomments,bash: deny),triage.ymlwith.opencode/agent/triage.md,duplicate-issues.ymlwith.opencode/agent/duplicate-pr.md, andclose-issues.yml/pr-management.yml. - Recommendation: —
- Priority: Low
4. Tooling
-
28. Can an agent reach the outside systems this project depends on, with that access committed to the repo rather than set up per laptop? MCP servers are one form: look for a committed
.mcp.jsonor this ecosystem's equivalent. A CLI is another and often the better one —aws,gh,psql,kubectl,stripe, a vendor's own tool — and it counts when the repo names which tools the work needs and how to authenticate, so an agent is not guessing at a tool it cannot see. Judge the axis, not the mechanism: access that exists only in someone's shell history or laptop config is a FAIL, and so is a committed config that turns out to be gitignored, with the distinction in the proof. Project task scripts have their own item; this one is about reaching past the repo's edge. If this project genuinely talks to nothing outside itself, N/A with that as the reason.- Status: PASS
- Proof:
.opencode/opencode.jsoncis committed and tracked (not gitignored —.opencode/.gitignoreexists but the config is ingit ls-files). Itsreferencesblock names two outside sources with a description each:github.com/Effect-TS/effect-smol"Use for Effect v4 and effect-smol implementation details", and~/.local/share/opencode"Contains opencode logs and data". Two custom GitHub tools are committed at.opencode/tool/github-triage.tsand.opencode/tool/github-pr-search.ts. Authentication for the cloud side is a named command, not tribal knowledge:package.json:21"sso": "aws sso login --sso-session=opencode --no-browser".ghis used throughout the workflows. Themcpblock is empty{}, and both custom tools are switched off in the same file ("tools": { "github-triage": false, "github-pr-search": false }) — worth knowing, but the access itself is committed and reachable. - Recommendation: —
- Priority: Low
-
29. Is there a skills, commands or reusable-prompt library in the repo? Look for .claude/skills, .agents/skills, .claude/commands, or a prompts directory. Committed and pinned beats committed; note whether anything ties the copies to a source.
- Status: PASS
- Proof:
.opencode/skills/effect/SKILL.mdand.opencode/skills/rtl-aware-development/SKILL.md;.opencode/command/with eight commands (ai-deps.md,changelog.md,commit.md,issues.md,learn.md,rmslop.md,spellcheck.md,translate.md);.opencode/agent/triage.mdand.opencode/agent/duplicate-pr.md, both wired into real workflows. Also.opencode/glossary/with 14 per-language files and.opencode/plugins/. Nothing is vendored from elsewhere, so there is no upstream to pin — these are first-party and version-controlled with the code they serve. - Recommendation: —
- Priority: Low
-
30. Do the skills, servers and tools that exist cover the work this team plainly repeats? First identify the repeated work from the README and the commit history. If skills, servers or documented tooling exist but miss it, FAIL naming the gap. If none exist at all and the repo plainly repeats work, FAIL pointing at the outside-systems item and the skills-library item. If the project is too small to repeat anything, N/A.
- Status: PASS
- Proof: The repeated work is visible in
git log: adding models (feat(go): add GLM 5.3 (#42518),docs(zen): add Muse Spark 1.2), regenerating artifacts (chore: generate, three times in 15 commits), translating docs (22 README languages + 17 doc locales), triaging issues and duplicate PRs. Each has a tool. Model/SDK regeneration:script/generate.ts+.github/workflows/generate.yml+packages/clientgenerate/check:generated. Translation:script/translate-app.ts(with its owntranslate-app.test.ts),.opencode/command/translate.md,.opencode/glossary/*,.github/workflows/docs-locale-sync.yml. Changelog:script/changelog.ts,script/raw-changelog.ts,.opencode/command/changelog.md. Triage:.opencode/agent/triage.md+triage.yml+duplicate-issues.yml. Nix hashes, stats and container builds each have a workflow too. - Recommendation: —
- Priority: Low
-
31. Are there project CLI scripts or task-runner targets for the common jobs? Check the manifest's scripts, the Makefile, the justfile, or this ecosystem's equivalent. The test: does routine work need a raw multi-flag command that someone has to remember?
- Status: PASS
- Proof: The root manifest wraps the awkward invocations:
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts","dev:console": "ulimit -n 10240 2>/dev/null; bun run --cwd packages/console/app dev","dev:web","dev:desktop","dev:storybook","sso","translate:app","upgrade-opentui". Turborepo coverstypecheck,buildandtestacross the workspace, 16 packages define their owntest/typecheck/build, andscript/holds 14 task scripts (generate.ts,publish.ts,beta.ts,stats.ts,version.ts,sign-windows.ps1, …). Routine work does not need a remembered flag string. - Recommendation: —
- Priority: High
-
32. Are those scripts named somewhere the agent will actually read them? If no scripts exist, FAIL with a one-line proof pointing at the task-scripts item. Otherwise check the agent instruction file, the README, and whether the manifest itself is self-explanatory.
- Status: PASS
- Proof: Partly in the instruction set —
AGENTS.md:1-2names the SDK build script andbun run generate,AGENTS.md:149namesbun typecheck,packages/app/AGENTS.md:14names the backend serve command — and the rest is legible in the manifest itself, where script names say what they do (dev:web,dev:desktop,sso,translate:app). The one script that would mislead an agent, roottest, is both self-describing when run (echo 'do not run tests from root' && exit 1) and pre-warned inAGENTS.md:145.CONTRIBUTING.mddocumentsbun devand the standalone build in prose. - Recommendation: —
- Priority: High
-
33. Can an agent get this project running — is there a reproducible environment or a documented setup path? Look for a pinned runtime (.nvmrc, .tool-versions, rust-toolchain), a lockfile, a container or nix file, and written setup steps. Try the first step if it is cheap and safe. This one bites hardest the moment work happens in a fresh git worktree or a new clone — the normal way to run agents in parallel. A new worktree has no installed dependencies, no
.env, no build cache, so anything that works today only because of untracked state sitting on someone's machine simply does not run there. The test: would a bare checkout plus the written steps get this project up? Name any prerequisite nothing creates — an env file someone hand-made, a seeded database, a manual login — because each one is a wall a worktree hits on its first command.- Status: PASS
- Proof: Runtime is pinned exactly —
package.json:7"packageManager": "bun@1.3.14"— and.husky/pre-pushfails the push if the local Bun does not satisfy it. Lockfiles are committed (bun.lockat root plus four more).flake.nix+flake.lockgive a Nix path, and there are Dockerfiles forpackages/opencode,packages/stats/serverand four container images. Setup is written down inCONTRIBUTING.md: "Requirements: Bun 1.3+ …bun install/bun dev". A bare worktree gets the CLI, TUI, app and desktop running on those two commands;postinstallrunsfix-node-ptyautomatically. Walls that a worktree does hit, none of them on the main dev path:packages/slackneeds a hand-made.env(packages/slack/.env.examplegives the shape), and anything touching infra, console or stats needs a manual AWS SSO login first (bun run sso, thenbun sst shell) —dev:statswill not start without it. - Recommendation: —
- Priority: High
-
34. Can an agent see the results of a failed run — do the tools here produce output it can read and act on? Judge from the runs you already did in Verification: does a failure print a path, a line, a name — something actionable — or a wall of noise? If nothing could be run, FAIL saying why.
- Status: FAIL
- Proof: Nothing could be run. Bun is not installed on the audit machine (
bun --version→zsh: command not found: bun), and every check in this repo —bun turbo test,bun typecheck,bun run lint— needs it plus an installed workspace. So the failure output of this project's tools is unverified. What can be said from the config alone, without claiming it as an answer: the toolchain is one an agent normally reads well (bun testprints file and line,tsgoprints diagnostics with positions, oxlint prints rule names),.github/workflows/test.ymluploads Playwright artifacts on failure, and.opencode/opencode.jsoncpoints an agent at~/.local/share/opencodefor logs. - Recommendation: Re-run this item on a machine with Bun 1.3.14 installed and
bun installcompleted, and record what a deliberately failing test actually prints. - Priority: Low
5. Safety
-
35. Are credentials kept out of the repo — nothing secret committed, ignore rules in place, an example env file for the shape? Three checks: grep tracked files for key-shaped strings, read the ignore rules for env and key patterns, and look for an example env file. Report each of the three separately.
- Status: PASS
- Proof: Grep —
git grep -InE '(sk-[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{20,}|-----BEGIN (RSA|OPENSSH|PRIVATE))'over all tracked files returned nothing outside tests and docs. Ignore rules —.gitignorecovers.env,.env.local,.sst,.direnv/,logs/,/opencode.json; it does not cover other.env.*variants such as.env.production. Example env —packages/slack/.env.exampleexists; it is the only one, which is consistent with the design, since cloud secrets are held by SST (infra/secret.ts) and CI secrets by GitHub Actions rather than by dotfiles. All CI secrets are referenced as${{ secrets.* }}, never inlined. - Recommendation: —
- Priority: High
-
36. Does anything scan for secrets automatically? Look for gitleaks, trufflehog, detect-secrets or this ecosystem's equivalent, wherever it is wired in — a CI step, a pre-commit hook, or forge-level push protection visible from the repo. CI is where this normally lives, and that is a PASS; a local hook on top is better, because it catches the key before it is pushed rather than after, but its absence is a line in the proof, not a FAIL. Say where the scan runs. "Nothing secret exists today" does not make this N/A — the scan is for the day that changes.
- Status: FAIL
- Proof: Someone runs gitleaks, but nothing in this repo does.
.gitleaksignoreis committed with four commit-pinned fingerprints forpackages/http-recorder/test/record-replay.test.ts, which proves a scan happened at least once. There is no.gitleaks.toml, no gitleaks step in any of the 25 workflows (grep -rni gitleaksacross*.yml,*.json,*.ts,*.mdreturns only the ignore file), and.husky/holds a singlepre-pushhook that runs a Bun version check andbun typecheck— no secret scan. Whatever runs gitleaks lives outside the repo and an agent cannot see it, rely on it, or reproduce it. - Recommendation: Add a gitleaks step to
.github/workflows/test.yml(the.gitleaksignoreis already there for it to honour), and optionally a.husky/pre-commitrunning the same scan so a key is caught before it is pushed. - Priority: High
-
37. Are dependencies pinned, so a build is reproducible? Look for lockfiles in every package of the repo, exact versions for load-bearing dependencies, a pinned runtime, and an install command that respects the lock (npm ci, not npm install).
- Status: PASS
- Proof: Five lockfiles cover every independent install root —
bun.lock,github/bun.lock,sdks/vscode/bun.lock,packages/console/resource/bun.lock,artifacts/glm52-rise-video/bun.lock. The Bun workspace catalog (package.json:33-96) pins ~60 load-bearing dependencies to exact versions with no ranges (effect: "4.0.0-beta.83",typescript: "5.8.2",hono: "4.10.7"),overridesforces catalog versions transitively, and 17patchedDependenciesare pinned to exact version + patch file. The runtime is pinned atpackageManager: "bun@1.3.14", enforced by.husky/pre-pushlocally and bybun-version-file: package.jsonin.github/actions/setup-bun. GitHub Action versions are SHA-pinned throughout. One soft spot:.github/actions/setup-bunruns plainbun install, notbun install --frozen-lockfile, so CI would silently accept a lockfile drift. - Recommendation: —
- Priority: High
-
38. Is anything watching those dependencies for known vulnerabilities? Look for dependabot or renovate config, an audit step in CI, or this ecosystem's equivalent. Check every lockfile in the repo is covered, not just the root one.
- Status: FAIL
- Proof: No
.github/dependabot.yml, norenovate.json, no audit step in any workflow (git ls-files | grep -Ei 'dependabot|renovate'matches only two SVG file-type icons inpackages/ui/src/assets/icons/;grep -rniE 'audit' .github/workflows/returns nothing). None of the five lockfiles is watched. Dependency bumps happen by hand —chore(deps): update ai-gateway-provider to 3.2.0 (#42488)in the recent log — and.opencode/command/ai-deps.mdexists to help with them, but nothing tells the team when a dependency turns out to be vulnerable. - Recommendation: Add
.github/dependabot.ymlwith abun/npmecosystem entry for each of the five lockfile directories, or enable Renovate with the same coverage. - Priority: Low
-
39. Are the review rules written down — who reads a change, and what they check? Look for CONTRIBUTING, a PR template, or a review checklist in the agent instruction set. On a solo repo the "who" is N/A-shaped but the "what gets checked before it lands" still matters — judge that half.
- Status: PASS
- Proof: Both halves. Who:
.github/CODEOWNERSassignspackages/app/andpackages/desktop/to@Hona @Brendonovich;.github/TEAM_MEMBERSexists;CONTRIBUTING.mdsays UI and core product features "must go through a design review with the core team before implementation". What:CONTRIBUTING.mdis unusually explicit — the issue-first policy, "Keep pull requests small and focused", "explain how you verified it works", a "No AI-Generated Walls of Text" section, conventional-commit PR titles, and a style-preferences list..github/pull_request_template.mdturns it into a checklist ("How did you verify your code works?", "I have tested my changes locally"), and.github/workflows/pr-standards.ymlplusreview.ymlenforce parts of it automatically. - Recommendation: —
- Priority: Low
-
40. Are the operations that need a human named somewhere an agent will read them? Look for a "never without asking" list in the agent instruction file or the README. Docs that hand out production commands with no fence around them count against, and the proof should quote one.
- Status: FAIL
- Proof: There is no "never without asking" list in
AGENTS.md, any nested AGENTS.md,README.mdorCONTRIBUTING.md. Meanwhile the manifests hand out production commands with no fence at all:packages/console/core/package.jsonexposes"db-prod": "sst shell --stage production -- drizzle-kit","shell-prod": "sst shell --stage production","promote-models-to-prod": "script/promote-models.ts production","promote-limits-to-prod": "script/promote-limits.ts production", and the root manifest has"dev:stats": "bun sst shell --stage=production -- bun run --cwd packages/stats/app dev"— a script nameddev:that opens a production shell.packages/stats/coreaddsdb:pushanddb:migrate. Nothing anywhere tells an agent these differ frombun dev. - Recommendation: Add a "Never run without asking" section to
AGENTS.mdlisting*-prodscripts,dev:stats,bun sst deploy,db:push/db:migrateandscript/publish.ts, and renamedev:statstostats:prod-shellso its name matches what it does. - Priority: High
-
41. Does every action that spends money, destroys data or changes production have a human in the way? Start from the damage, not from the tooling: list what in reach of this repo could charge a card, drop or overwrite data, or alter what users are running. Then trace the shortest route an agent could take to each one — a push that auto-deploys, a script carrying live credentials, a migration that runs on merge, an infrastructure apply with no plan-and-approve step. PASS when every route meets a human first, whether that is a review, a manual trigger or a protected environment. FAIL when even one route runs start to finish unattended, and quote that route in the proof so the fix is obvious.
- Status: FAIL
- Proof: The damage in reach: the production SST stack (AWS + Cloudflare + PlanetScale), the production Stripe key, the PlanetScale console database, and the
opencode-ainpm package that millions of installs upgrade from. The CI routes are gated —deploy.ymlneeds a push to thedevorproductionbranch and runs underenvironment: ${{ github.ref_name }}, andpublish.ymlis limited to named branches plusworkflow_dispatch. The local route is not:bun run --cwd packages/console/core db-prodrunssst shell --stage production -- drizzle-kitstart to finish with no confirmation, no plan-and-approve step and no dry run, andpromote-models-to-prod/promote-limits-to-prodwrite straight to the production console. An agent with an activebun run ssosession and shell access reaches production data in one command. - Recommendation: Put a typed confirmation in front of
script/promote-models.tsandscript/promote-limits.tswhen the stage argument isproduction, and require an explicit--yesfordb-prod. - Priority: High
-
42. If a prompt injection landed tonight, how far would it reach — are the credentials an agent can get to here scoped to the job, with nothing production-grade in reach? Inventory what an agent in this repo can reach: env files, cloud CLI profiles, tokens named in docs or config, deploy commands that work from a laptop. Scoped-or-absent passes; production-grade reach fails with the item named.
- Status: FAIL
- Proof: CI containment is genuinely good:
opencode.ymlruns the agent withOPENCODE_PERMISSION: '{"bash": "deny"}'andcontents: read, andreview.ymldenies all bash exceptgh*while blockinggh pr review*. The laptop is the hole.package.json:21"sso": "aws sso login --sso-session=opencode --no-browser"mints a session thatbun sst shell --stage productionwill happily use, and the root manifest itself contains a production-shell command under adev:name ("dev:stats": "bun sst shell --stage=production -- …"). Through that session an agent reaches the production SST stack, and viadeploy.yml's secret list what that stack fronts —STRIPE_SECRET_KEY_PROD,PLANETSCALE_SERVICE_TOKEN,CLOUDFLARE_API_TOKEN. That is production-grade reach from an ordinary manifest script, with no scoping between it and everyday development. - Recommendation: Use a separate AWS SSO session name for production (e.g.
sso:prod) sobun run ssoonly ever grants dev-stage access, and changedev:statsto point at the dev stage. - Priority: High
-
43. Can a change reach production a slice at a time — a feature flag that defaults to off, a canary, a staged rollout — rather than everyone at once? Look for a flag system and check the default, or canary and staged-rollout config in the deploy pipeline. Flags that need a rebuild to flip are worth naming in the proof — they gate exposure but they are not a kill switch.
- Status: PASS
- Proof: The distributed product ships in slices.
.github/workflows/beta.ymlpublishes a beta channel,publish.ymltriggers onci,dev,betaandsnapshot-*branches, and users pick a channel (opencode-ai@latestvs@beta) — so a change reaches beta users before everyone. The hosted side has two separate SST stages with separate secrets:deploy.ymlrunsbun sst deploy --stage=${{ github.ref_name }}fordevthenproduction, withSTRIPE_SECRET_KEY_PRODonly on the production ref. What does not exist: a feature-flag system —grep -rniE 'featureflag|feature_flag|launchdarkly|posthog'over the manifests andinfra/returns nothing. The nearest things are the env-var gatesOPENCODE_DISABLE_SHAREandOPENCODE_DISABLE_PROJECT_CONFIG, which are process-start switches, not a runtime kill switch for a single feature. - Recommendation: —
- Priority: High
-
44. Once a change is live, can anyone see what it is doing — logs, metrics, traces, alerts that fire on their own, and can an agent read them too? Look for logging setup, an error tracker, analytics, alerting config — and then ask the second half: could an agent reach any of it (a CLI, an MCP server, an API named in the docs), or does observability stop at a dashboard behind a login?
- Status: PASS
- Proof: Error tracking is Sentry (
@sentry/solidand@sentry/vite-pluginin the catalog, wired inpackages/appandpackages/desktop, withSENTRY_RELEASE: web@${{ github.sha }}set per deploy indeploy.yml). Tracing is OpenTelemetry into Honeycomb (@effect/opentelemetryin the catalog,HONEYCOMB_API_KEYindeploy.yml,packages/stats/corehoneycomb:backfill). Alerts fire on their own:infra/monitoring.tsprovisions Honeycomb triggers with aWebhookRecipientposting to Discord, disabled outside production (alertsDisabled = $app.stage !== "production"). For the agent half, local logs are reachable and named —.opencode/opencode.jsoncpoints at~/.local/share/opencode, "Contains opencode logs and data". Honeycomb and Sentry themselves stop at a dashboard login: no CLI, MCP server or API for them is named anywhere in the repo. - Recommendation: —
- Priority: Low
-
45. Is there a way back — can a bad change be undone without a rebuild and a redeploy, including the ones that touched a database or a queue? Look for a documented rollback path, a revert-and-redeploy story, down-migrations, or a flag that can turn the change off at runtime. Deployment docs that only say how to go forward are worth quoting.
- Status: FAIL
- Proof: Nothing documents a way back.
grep -rniE 'rollback|roll back'overREADME.md,CONTRIBUTING.md,AGENTS.mdandspecs/*.mdfinds only statements that rollback is not provided, and about a product feature rather than deployment:specs/v2/schema-changelog.md:618"Moves and atomic rollback are deliberately unsupported in the first slice",specs/v2/session.md:206the same. The database migrations are forward-only Drizzle SQL —packages/console/core/migrations/*/migration.sqlwith asnapshot.jsoneach, no down files — andpackages/stats/coreexposesdb:migrateanddb:pushwith no inverse. There is no runtime flag to turn a change off (see the staged-rollout item). The only route back is git revert plus a full redeploy, and even that is not written down anywhere. - Recommendation: Add a "Rolling back" section to
CONTRIBUTING.mdcovering the revert-and-redeploy path for the SST stages andnpm dist-tagfor a bad CLI release, and start writing down-migrations alongside the Drizzle SQL inpackages/console/core/migrations/. - Priority: Low
-
46. Does a past failure leave a check behind — is there a test or a rule in here that exists because something broke once? Look for tests, lint rules or comments that name the incident they guard against — "regression", "this broke when", a linked issue. On a very young repo with no failures yet, N/A with the age as the reason.
- Status: PASS
- Proof: The habit is visible in three places. Tests named for the breakage they guard:
packages/codemode/test/parity.test.ts,packages/core/test/config/config.test.ts,packages/llm/test/provider/anthropic-messages.test.tsandopenai-responses.test.tsall carry regression language, and the recent log shows the pattern in flight (fix(opencode): preserve v1 database compatibility (#42444),fix(core): preserve unicode in grep previews (#42356)). Lint rules disabled with the incident written next to them, e.g..oxlintrc.json"Effect usesfunction*with Effect.gen/Effect.fnUntraced that don't always yield". Infra comments citing the upstream bug:infra/monitoring.ts"Honeycomb can keep stale query-local calculated fields when the name is unchanged … honeycombio/terraform-provider-honeycombio/issues/852", and.github/actions/setup-bun"Workaround for patched peer variants … oven-sh/bun/issues/28147". - Recommendation: —
- Priority: Low
Learn more: https://ainativesoftware.engineering/
Nothing here is special to anomalyco/opencode. Install the skill and ask your agent to run it — it answers the same 46 checks and writes the same file into your repo.
npx skills add alfonsograziano/skills --skill aine-readiness-analyzerAI-Native Software Engineering