Skip to Content
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 deployment-repository 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
Contribution templates or PR policynpm run test:unit -- test/unit/pr-title.spec.ts test/unit/contribution-policy.spec.ts
Templates, renderer, Energon skillnpm run test:unit -- test/unit/skill-render.spec.ts
Well-known skill route and AGENT_SKILLS_DISCOVERYnpm run test:unit -- test/unit/agent-skills.spec.ts
Upload helper templates/skill/scripts/energon_publish.py.tmpl (needs python3)npm run test:unit -- test/unit/publish-helper.spec.ts
Svelte pages/components or UI renderingnpm run check:ui and npx vitest run test/pages.spec.ts
Upload stagingnpm run test:unit -- src/ui/uploads.spec.ts
Agent connection requests, approvals, and deliverynpx vitest run test/connections.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
Site deployment sessions, commit, and receiptsnpx vitest run test/site-deployments.spec.ts test/site-deployment-api.spec.ts
Whole-site grantsnpx vitest run test/deployment-grants.spec.ts
ZIP reader and staged preparationnpx vitest run test/site-zip-reader.spec.ts test/site-storage.spec.ts
Version-keyed site cachenpx vitest run test/site-cache.spec.ts test/site-routed-cache.spec.ts
Older-site conversionnpx vitest run test/site-version-migrate.spec.ts test/site-admin-conversion.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 site version publication 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 /v1 route tables 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, write password, TTL, or write policy and does not rename. Guest PUT is not a /v1 path. Site routes are keyed by id. If a verification recipe says otherwise, update the recipe rather than documenting stale behavior.

The renderer’s outputs can be summarized as the Energon plugin tree plus real-host marketplace catalogs and updated this Energon’s origins, policy, and SOP. Do not hand-edit plugins/{name}/, and do not install the publish skill under this repository’s .agents/skills or .claude/skills directories because those locations autoload it while you are changing the Worker. Only verify-energon, cut-release, update-from-upstream, and backup-this-energon belong there.

6. Pair page contracts with user-path proof

test/pages.spec.ts checks server-rendered navigation, copy, catalog data, safe hydration, and asset isolation. Svelte checks template bindings; legacy inline DOM checks apply only where that code remains. Neither proves pixels, responsive behavior, or whether a person can complete the flow.

For UI changes, read upstream DESIGN.md  and the UI implementation guide . Shared controls live in src/ui/components/, pages in src/ui/pages/, and supplied tokens/styles/assets in src/ui/design/. Keep generated files out of hand edits.

npm run check:ui npm run specimen:ui python3 -m http.server 18788 --bind 127.0.0.1 --directory .context/ui-specimen

The specimen shows local component examples without application API calls. Wrangler’s custom build and both Vitest configurations run build:ui automatically. npm run typecheck includes the UI check. Browser verification still needs the real local Worker for forms, dialogs, upload staging, and persistence.

The .agents/skills/verify-energon/ harness complements it by launching an isolated Wrangler Energon 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. .agents/skills/verify-energon/ is canonical; .claude/skills/verify-energon and .cursor/skills/verify-energon are compatibility symlinks.

export ENERGON_VERIFY_RUN="contributor-check" export ENERGON_VERIFY_PORT="18787" .agents/skills/verify-energon/bin/up set -a source "/tmp/energon-verify/$ENERGON_VERIFY_RUN/state.env" set +a

bin/up launches, runs Doctor, and prepares one token. Follow every Default bullet in the matching feature recipe; run Extra bullets only when the changed sub-feature requires them. Reuse that run and token. Prefer HTTP for the default paths, saving request/status/body with bin/save and a later read-only view. Browser extras also require a screenshot showing the signed-in identity and resulting state. Doctor discovers the configured token environment and prefix, and the launcher keeps localhost identity even on a deployment repository with custom routes. 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:

.agents/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, search existing issues and pull requests, then provide reproduction evidence without secrets. Focused pull requests are welcome under the upstream contribution policy; new API surfaces, migrations, and non-obvious hub flows should begin with an issue. 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.

Use a Conventional Commit PR title such as fix(hub): validate catalog filters. Keep the template headings What, Why, Verify, How to test, Risk, and Authorship; additional sections are allowed. How to test must give numbered commands or URLs and expected results that a triage agent can follow without asking. Name the actual model in Authorship; a human-authored patch may say None.

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