Skip to Content
Energon runs in the operator's Cloudflare account. Published links are open by default.
ContributeDevelop and verify

Start with the narrow test that owns your change, add integrity suites when D1 and R2 can diverge, and finish with the repository gates. If the public contract moved, also drive the affected path through the isolated local harness. This workflow applies to operator-fork changes and owner-requested upstream patches because each test layer should prove only the behavior it can actually observe.

Develop and verify

Each layer proves a different claim

No single test environment covers Energon’s whole contract. Node unit tests are fast and isolate helpers. Worker tests exercise routing with D1 and R2 bindings. Failure injection forces rare rollback branches. Mock-free mutation suites validate real binding behavior. Page tests protect DOM contracts. The verify harness starts a real local Worker and observes it as a human or agent would. For project-specific mutation and identity terms, use the glossary.

1. Set up local state

Run local migrations before starting the development server. The checked-in example identity defaults to dev@example.com; localhost skips Cloudflare Access.

npm install npx wrangler d1 migrations apply energon --local cp .dev.vars.example .dev.vars npm run dev

Do not attach verification to an unknown process on port 8787, delete .wrangler/state, or kill Wrangler/workerd by process-name pattern. That state and process may belong to another local session.

2. Start with the owning test

ChangeFirst test
Pure helper under src/npm run test:unit -- test/unit/NAME.spec.ts
helpBody, /llms.txt, Markdown HTMLnpm run test:unit -- test/unit/golden.spec.ts
openapi/v1.json, /v1 routes, or API error codesnpm run test:unit -- test/unit/openapi-drift.spec.ts
Templates, renderer, instance skillnpm run test:unit -- test/unit/skill-render.spec.ts
Hub/tokens/setup/about/stats HTML or client JSnpx vitest run test/pages.spec.ts
Router, host rules, account APInpx vitest run test/routes.spec.ts
Publish/read/delete/list/auth DB/gate/Markdownnpx vitest run test/api.spec.ts
Loose-file write, rename, or delete failuresnpx vitest run test/files.spec.ts
Site import/copy/delete rollbacknpx vitest run test/site-integrity.spec.ts
Expiry and write-claim racesnpx vitest run test/api.purge-claim.spec.ts

For example, a catalog cursor change begins with:

npm run test:unit -- test/unit/catalog.spec.ts npx vitest run test/api.spec.ts

Do not run the full suite after every small edit. Focused tests make the edit loop useful; the full gate still runs before handoff.

3. Prove D1/R2 integrity twice

An integrity change needs both controlled failure and real-binding convergence evidence.

Use failure-injection suites to force the precise branch:

  • test/files.spec.ts for loose-file R2/D1/cache failures.
  • test/site-integrity.spec.ts for import, duplicate, path delete, and whole-site restore behavior.
  • test/api.purge-claim.spec.ts for claim acquisition, stale reclaim, PATCH races, and purge ordering.

Then run the relevant mock-free suite:

  • test/d1-r2-mutation.spec.ts for rename/delete catalog, keys, and quota.
  • test/d1-r2-claim-mutation.spec.ts for claim rollback and competing replacements.
  • test/d1-r2-site-mutation.spec.ts for site PUT/import/delete abort recovery.
  • test/d1-r2-scheduled-mutation.spec.ts for sweep boundaries and stale claims.
npx vitest run test/files.spec.ts test/d1-r2-mutation.spec.ts test/d1-r2-claim-mutation.spec.ts

The injected suite proves your recovery logic is reachable. The mock-free suite proves the same invariant with actual local D1/R2 semantics. Do not treat one as a substitute for the other.

4. Change schema in all three places

Add a new numbered migration, update runtime bootstrap/legacy upgrades, and update src/schema.sql. Create indexes only after every referenced column exists.

npx wrangler d1 migrations apply energon --local npm run test:unit -- test/unit/db.spec.ts test/unit/schema-drift.spec.ts npx wrangler types npm run typecheck

Never rewrite old migrations. Comments in older migrations about stamping d1_migrations are historical human recovery notes for a verified deploy-first state. They do not permit agents to stamp migration history, run production d1 execute, or improvise repair SQL. For a production duplicate-column incident, stop and use the human-only upgrade and recovery procedure.

5. Keep the agent protocol coherent

When a /v1 route, field, header, error, limit, or decision rule changes, review these together:

  1. Canonical HTTP schema in openapi/v1.json.
  2. Runtime JSON in src/auth.ts helpBody.
  3. Runtime plain text in src/llms.ts.
  4. Agent workflow and reference under templates/skill/.
  5. Runtime golden fixtures under test/golden/.
  6. Rendered plugin output under plugins/.
npm run test:unit -- test/unit/openapi-drift.spec.ts UPDATE_GOLDENS=1 npm run test:unit -- test/unit/golden.spec.ts npm run skill:render npm run test:unit -- test/unit/skill-render.spec.ts git diff -- openapi test/golden templates plugins

The drift test compares OpenAPI operations with the router and help.routes, checks application error codes, and protects the unauthenticated discovery boundary. Review the remaining diff semantically: separate snapshots can all pass while two documents disagree about a method or field. For example, loose-file rename is implemented as PUT /v1/files/{id} with X-Filename; PATCH changes password, TTL, or write policy and does not rename. If a verification recipe says otherwise, update the recipe rather than documenting stale behavior.

The renderer’s outputs can be summarized as the instance plugin tree plus real-host marketplace catalogs and updated instance identity. Do not hand-edit plugins/{name}/, and do not install the skill under this repository’s .agents/skills or .claude/skills directories because those locations autoload it while you are changing the Worker.

6. Pair page contracts with user-path proof

test/pages.spec.ts checks signed-in page structure, expected copy, navigation, and that every JavaScript element lookup has matching markup. It does not judge pixels, responsive behavior, or whether a person can complete the flow.

The .cursor/skills/verify-energon/ harness complements it by launching an isolated Wrangler instance with real local D1/R2, proving process and port ownership, and driving HTTP or browser behavior. Use both when a hub control or workflow moves.

export ENERGON_VERIFY_RUN="contributor-check" export ENERGON_VERIFY_PORT="18787" .cursor/skills/verify-energon/bin/launch .cursor/skills/verify-energon/bin/doctor .cursor/skills/verify-energon/bin/mint-token contributor-check

After Doctor succeeds, follow the matching file under .cursor/skills/verify-energon/features/. Save the request/status/body and a second read-only view. Browser drives also require a screenshot showing the signed-in identity and resulting catalog state. The harness calls the real local Worker; do not use SELF.fetch or direct binding access as user proof.

Cleanup targets only this run’s process group, port, and isolated persist directory, while preserving evidence:

.cursor/skills/verify-energon/bin/cleanup

If a named route, public URL shape, header, token prefix/environment, element id, ARIA label, or proof string changes, update the feature map in the same change. A stale map is fixed to match verified runtime behavior; it is never treated as authority over the product.

7. Run the full gate

Before handoff, schema/shared-type changes always receive the full gate. It is also the safe final check for any coherent change:

npx wrangler types npm run typecheck npm run lint npm test npm run fuzz:regression npm run skill:render -- --check

CI uses Node 22 and runs npm ci, Wrangler type generation, typecheck, lint, unit tests, ZIP fuzz regression, and Worker tests. Production deployment is a separate opt-in job after tests; contributors must not run deployment or remote database commands as part of ordinary verification.

For ZIP parser changes, fuzz:regression replays the committed corpus. A local coverage-guided campaign is npm run fuzz:zip -- -max_total_time=60; minimize a crash, add it to the committed corpus, and add a focused unit regression with the fix.

Verification failures

Do not call a change verified because one layer is green. Persistence work needs injected and mock-free suites; UI work needs page contracts and a user-path drive; /v1 work needs the OpenAPI drift test plus semantic review across runtime docs, templates, goldens, and rendered output. Never invent a token, touch production D1 state, reuse the default local database for verification, or conceal a product failure by editing the feature map.

Report or hand off

For an upstream bug, open an issue with reproduction evidence and no secrets. Do not open an unsolicited pull request. For a vulnerability, use private reporting and include the tested revision, reproduction, and impact without tokens, credentials, passwords, customer content, or other people’s email addresses.

When handing off an authorized code change, state which focused tests ran, which cross-layer invariants they cover, whether the user path was driven, and the full-gate result. Read Architecture and integrity when deciding which boundaries changed, Contribute to Energon for the repository policy, and Security model before reporting an auth or sharing defect.

Last updated on