Files
wehub-resource-sync 426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
ci / test (push) Waiting to run
ci / lint-and-format (push) Waiting to run
ci / build (push) Waiting to run
ci / dev-startup (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
gitleaks / gitleaks (push) Waiting to run
Markdown Links / Relative Markdown Links (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Quality (Extended) / Homepage Build (PR smoke) (push) Waiting to run
Quality (Extended) / Comment-only diff guard (push) Waiting to run
Quality (Extended) / Format + Type Safety Ratchet (push) Waiting to run
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Waiting to run
Quality (Extended) / Develop Gate (lint) (push) Waiting to run
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Voice Workbench / headless workbench (mocked backends) (push) Waiting to run
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

31 KiB
Raw Permalink Blame History

elizaOS — repository guide for agents

This is the elizaOS monorepo: an open-source framework for building and deploying autonomous AI agents, plus the runtime, CLI, dashboard, cloud backend, native bridges, and first-party plugins built on top of it. The repo is self-contained — everything needed to run, test, and ship an Eliza agent lives here.

CLAUDE.md and AGENTS.md in every directory are identical — author CLAUDE.md, then copy it to AGENTS.md. Read the package-local CLAUDE.md before working inside any package or plugin; this root file is the map.

Naming

Write elizaOS (not ElizaOS). npm scope is @elizaos/*. In plain language, say Eliza agents. Exception: the Eliza Classic plugin keeps Eliza (the 1966 chatbot it reimplements).

Toolchain

  • Runtime: Bun (packageManager is pinned in package.json) on Node 24 (engines.node). ESM only ("type": "module").
  • Monorepo: Turbo drives build / typecheck / lint / test across workspaces. Workspace globs are in package.json (packages/*, plugins/*, packages/native/*, packages/os/*, packages/examples/*, packages/cloud/services/*, …).
  • Lint/format: Biome (biome.json). Ignore globs in .biomeignore.
  • Tests: Vitest, orchestrated by packages/scripts/run-all-tests.mjs.
  • TypeScript: project-references build; root tsconfig.json, tsconfig.base.json, per-package tsconfig.json.

Root commands

bun install            # workspace install (runs postinstall: submodules, patches)
bun run install:light  # install without downloading the large artifact bundle
bun run dev            # boot the API + dashboard UI (packages/app-core dev-ui)
bun run build          # turbo build across the workspace
bun run verify         # typecheck + lint (alias: bun run check) — run before "done"
bun run lint           # biome lint via turbo
bun run format         # biome format via turbo
bun run typecheck      # tsc across workspace (8 GB heap)
bun run test           # full suite (run-all-tests.mjs)
bun run test:server    # core/agent/app-core/shared/vault/elizaos/skills/scenario-runner
bun run test:client    # app/ui + lifeops/training plugins
bun run test:e2e       # end-to-end lane
bun run start          # run an agent (packages/agent start)
bun run clean          # nuke dist/.turbo/node_modules and local state
bun run reset          # clean, reinstall, rebuild
bun run cloud:mock     # boot the full local cloud stack with mocks

Scope any command to one package with --cwd: bun run --cwd packages/core test. The repo has 188 root scripts; the list above is the day-to-day set. Use bun run with no args to print them all.

Shared dev server for parallel lanes

When several worktrees are active on the same VPS, do not have every lane bind the default app UI port (2138). packages/app keeps bun run dev unchanged for single-lane local work, but concurrent agents should use the shared scripts:

cd packages/app
bun run dev:shared   # long-lived Vite server on a deterministic worktree port
bun run dev:status   # list running shared dev servers (port, worktree, pid)
bun run dev:rebuild  # explicit Vite full-reload trigger for this worktree

Ports are reserved in ~/.eliza/dev-server-registry.json (override with ELIZA_DEV_SERVER_REGISTRY) from the normalized worktree path, with registry locking and linear probing so active lanes do not collide. See packages/docs/development/shared-dev-server.md.

Removed Root Command Migrations

Removed command Use instead
bun run test:ci bun run test
bun run test:cloud:playwright bun run --cwd packages/app test:e2e
bun run test:ui:playwright bun run --cwd packages/app test:e2e
bun run test:lifeops bun run test:plugin 'plugin-personal-assistant'
bun run trajectory:inspect:test bun test packages/scripts/__tests__/trajectory-validate.test.ts
bun run audit:e2e-coverage:test bun test packages/scripts/e2e-coverage/check-e2e-coverage.test.ts
bun run test:browser-bridge bun run --cwd packages/browser-extension test
bun run test:browser-bridge:safari bun run --cwd packages/browser-extension test:smoke:safari
bun run voice:latency-report bun run --cwd packages/app-core voice:latency-report
bun run voice:interactive bun run --cwd packages/app-core voice:interactive
bun run voice:duet bun run --cwd packages/app-core voice:duet
bun run voice:create-profile bun run --cwd packages/app-core voice:create-profile
bun run smartglasses:hardware:doctor bun run --cwd packages/examples/smartglasses hardware:doctor
bun run smartglasses:hardware:status bun run --cwd packages/examples/smartglasses hardware:status-latest
bun run smartglasses:hardware:validate bun run --cwd packages/examples/smartglasses hardware:validate-latest
bun run smartglasses:hardware:prove bun run --cwd packages/examples/smartglasses hardware:prove:bleak
bun run smartglasses:hardware:prove:watch bun run --cwd packages/examples/smartglasses hardware:prove:bleak:watch
bun run smartglasses:hardware:prove:noble bun run --cwd packages/examples/smartglasses hardware:prove:noble
bun run smartglasses:hardware:prove:noble:watch bun run --cwd packages/examples/smartglasses hardware:prove:noble:watch
bun run smartglasses:dev:hardware bun run --cwd packages/examples/smartglasses dev:hardware
bun run smartglasses:dev:simulator bun run --cwd packages/examples/smartglasses dev:simulator
bun run smartglasses:simulator bun run --cwd packages/examples/smartglasses simulator
bun run smartglasses:smoke:simulator bun run --cwd packages/examples/smartglasses smoke:simulator
bun run test:ci:live bun run test:live
bun run test:lint bun run audit:test-integrity:all
bun run test:lint:no-vi-mocks bun run audit:test-integrity:no-vi-mocks
bun run test:lint:lane-coverage bun run audit:test-integrity:lane-coverage
bun run test:lint:test-integrity bun run audit:test-integrity
bun run test:lint:test-integrity:self-test bun run audit:test-integrity:self-test
bun run verify:smartglasses-software bun run audit:smartglasses-software
bun run personality:judge bun run bench:personality
bun run personality:bench:calibrate bun run bench:personality:calibrate
bun run lint:all bun run verify
bun run build:typescript node packages/scripts/run-turbo.mjs run build
bun run audit:mvp-board bun run mvp:closeout-audit
bun run mvp:board-readiness bun run mvp:closeout-audit
bun run mvp:evidence-matrix bun run mvp:closeout-audit

Repo map — where to find what

packages/        framework, shared libraries, and product surfaces
  core/          @elizaos/core — runtime, types, agent loop, memory/state, model layer
  agent/         @elizaos/agent — AgentRuntime, plugin loader, default plugin map
  app-core/      API + dashboard host; dev/build orchestration (scripts/dev-ui.mjs)
  elizaos/       the `elizaos` CLI — create / info / upgrade / version; project + plugin templates
  prompts/       shared prompt scaffolding
  shared/        cross-package utilities + brand assets
  ui/            shared React component library
  app/           web + desktop dashboard, desktop shell, and current cloud apex UI
  tui/           terminal UI
  skills/        runtime skills knowledge base (USE_SKILL)
  scenario-runner/ scenario + eval harness
  cloud/api/     managed backend API (Hono on Cloudflare Workers)
  cloud/docs-redirect/ Eliza Cloud docs redirects
  cloud/shared/  shared cloud backend: db (Drizzle), billing, services, types
  cloud/sdk/ cloud/routing/ cloud/infra/  cloud client SDK, model routing, IaC
  contracts/     on-chain contracts + ABIs
  security/ security/soc2-verify/ vault/  secrets, key management, compliance tooling
  os/ robot/                     device/OS images, OS landing, robotics
  plugin-remote-manifest/ plugin-worker-runtime/
                 remote plugin manifests, host shims, and worker runtime support
  homepage/ docs/  marketing site and docs site
  examples/      30+ standalone runnable examples (each has its own README)
  benchmarks/    30+ evaluation suites (each has its own README + harness)

plugins/         runtime plugins and app plugins
  plugin-<model>/      openai, anthropic, google-genai, groq, openrouter, xai, ollama, …
  plugin-<connector>/  discord, telegram, farcaster, slack, imessage, whatsapp, x, …
  plugin-native-*/     native device bridges (camera, contacts, calendar, location, …)
  plugin-local-inference/  on-device llama.cpp (Kokoro TTS folded in) / whisper (git submodules under native/)
  plugin-sql/ plugin-localdb/ plugin-inmemorydb/  storage adapters
  plugin-documents/ plugin-personal-assistant/ plugin-health/ …  app plugins

scripts/         repo automation        patches/   dependency patches
turbo.json knip.json  build + dead-code config

Every package and plugin carries its own CLAUDE.md / AGENTS.md (identical) and README.md. Read the package-local doc first — it lists that package's layout, exports, scripts, env vars, and gotchas.

Runtime architecture in 60 seconds

  • @elizaos/core is the framework: the agent loop, the plugin model, and the message / memory / state primitives, with a model-agnostic LLM layer. If your code depends on @elizaos/core, you are using the framework.
  • @elizaos/agent wires a runnable agent: AgentRuntime, the plugin loader, and the default plugin map.
  • A plugin is src/index.ts exporting a Plugin object that registers:
    • actions — things the agent can do (validate + handler),
    • providers — context injected into the prompt,
    • services — long-lived singletons (clients, schedulers, connectors),
    • evaluators — post-response processing,
    • plus routes, events, and model handlers.
  • @elizaos/app-core hosts the HTTP API + dashboard that runs agents.
  • The elizaos CLI is intentionally minimal: scaffolding (create), info, and template upgrades. Project/plugin scaffolds live in packages/elizaos/templates/ (min-project, min-plugin have SCAFFOLD.md contracts).

To build on the runtime from your own TypeScript with no CLI/UI, import @elizaos/core directly — see packages/examples/ (30+ standalone references).

Repo-wide conventions

  • Logger only, never console in server code. Use the structured logger, prefix messages with [ClassName], attach context objects on errors.
  • ESM only. No CommonJS.
  • No business computation in proxy/route layers. Derive values in use-cases and return DTO fields the client just renders. Clients display, never compute.
  • DTO fields are required by default; don't paper over a broken pipeline with ?? 0 or as casts.
  • Keep weak types (any / unknown / unsafe casts) out; validate at runtime boundaries and type the validated result.

GitHub project coordination

For agent/human work coordinated through GitHub Projects, read CONTRIBUTING.md before claiming work. Permanent process lives in that doc, not in a long issue-comment thread.

  • Issues are scoped work cards with acceptance criteria and evidence.
  • GitHub Projects are the live kanban state: Todo -> Claimed -> In progress -> Needs-agent-verify -> needs-human-verify -> Done.
  • Set the Project Claimed by field to your lane/agent tag when you claim a card, and keep Status accurate.
  • Discussions are for coordination, handoffs, and noisy multi-card chat; roll durable decisions back into docs, issue bodies, or Project readmes.
  • PRs carry the code and the proof required by this guide; link the issue or Project card they resolve.
  • Do not move cards to Done unless the board explicitly grants that authority to your role. Human verification owns final done for launch/QA boards.

Current Launch QA routing: Project https://github.com/orgs/elizaOS/projects/12, Discussion https://github.com/orgs/elizaOS/discussions/14292, tracker/history https://github.com/elizaOS/eliza/issues/13406.

LifeOps Personal Assistant MVP routing: Project https://github.com/orgs/elizaOS/projects/15. Product scope, the seven personas, and the per-workstream acceptance bar live in packages/docs/ongoing-development/mvp/MVP.md; in-flight design docs (per-workstream research + status snapshots) live under packages/docs/ongoing-development/. This folder adds a design-doc layer to the workflow above: discussion → design doc here → issues on the board → PR with evidence → doc updated on merge.

Evidence attaches inline in the issue/PR, not committed to the repo: MP4 video (renders inline in GitHub), JPG over PNG for screenshots, logs in a <details> block. Bug reports include a screenshot or recording of the wrong behavior. .github/issue-evidence/ is retired; the full standard is in this guide and CONTRIBUTING.md.

Error-Handling Simplification

Binding policy for all error handling (parent #12182, foundation #12263). The codebase is full of defensive sludge — empty catches, log-and-continue that fabricates a result, return <default> from catch, .catch(() => {}) on writes that matter, ?? <literal> standing in for failed/missing data — that swallows failures and makes broken pipelines look healthy. Remove it.

Doctrine — fail fast inside, handle at the boundary. Inner code throws typed errors; it does not catch-and-continue. Only designated boundaries translate those errors into a structured failure, a user-facing error state, or an escalation. This is crash-only design (Candea & Fox, "Crash-Only Software", HotOS IX 2003): transparent recovery at a designed boundary beats ad-hoc continue-on-error in every function. A failure must surface observably — either the agent sees it (and can retry / reconfigure / disable the failing feature) or it is raised to the owner/developers when systemic.

"Not loaded" must never read as "zero"/"empty". A ?? 0, ?? [], ?? "", or return 0/return [] from a catch that substitutes for failed or missing data conflates a broken pipeline with a legitimately empty result. Banned. DTO fields are required by default; fix the pipeline, don't paper over it.

Fast-fail on data paths; throw, never fabricate. Precedent: issue #9324 (closed) removed fabricated zero/marker embedding vectors in favor of throwing; plugins/plugin-embeddings/AGENTS.md:32 codifies "THROW, never fabricate".

UI three-state rule. loading / designed-empty / error are three distinguishable renders — never render healthy-empty from a catch. A 404-from-unloaded-plugin may degrade to a designed "unavailable" state (J4); 5xx/transport/parse failures set an error state. Canonical pattern: packages/ui/src/components/pages/StreamView.tsx:55-63; repaired load shape: packages/ui/src/state/usePluginsSkillsState.ts:195-220. See the view audit scripts/view-audit/output/MASTER-REPORT.md §6.A/§6.D.

Use the foundation. New/rewritten throw sites use ElizaError (packages/core/src/errors.ts, { code, context, cause, severity }). Diagnostic call sites outside the action path (providers, services, background jobs, event handlers) call runtime.reportError(scope, error, context?) — it logs, emits EventType.ERROR_REPORTED, surfaces the failure to the agent via the RECENT_ERRORS provider, and drives owner escalation on repeated systemic failure. Action/tool failures already reach the model via the planner loop — keep that.

Justified categories (J1J7) — keep, annotated // error-policy:J<N> <reason>

Every kept handler carries a grep-able // error-policy:J<N> <reason> comment so "remaining handlers each have a documented justification" is mechanically checkable. A justified handler still may not fabricate a success value: J1 returns a failure, J3 returns an explicit invalid signal, J4 renders an error/unavailable state.

  • J1 boundary translation — one outermost handler per process/transport boundary producing a structured failure.
  • J2 context-adding rethrow — must use cause.
  • J3 untrusted-input sanitizing — parse failures produce an explicit typed "invalid" result, never a fake-valid default.
  • J4 explicit user-facing degrade — designed, visually-distinguishable unavailable/error states; only expected error shapes degrade.
  • J5 unhandled-rejection suppression — with a comment naming where the rejection IS observed.
  • J6 best-effort teardown — debug/warn, teardown paths only.
  • J7 diagnostics-must-not-kill-the-loop — trajectory/telemetry writes may catch but must warn + runtime.reportError.

Everything else is slop — including every empty catch, log-and-continue that fabricates the function's result, return <default> from catch, .catch(() => {}) on writes that matter, ?? <literal> substituting for failed/missing data, optional-chaining-as-guard on required collaborators, and fallback code paths whose only purpose is masking a primary failure. Every catch without an annotation must be either newly-obvious slop or a J1 route boundary in a directory documented as such in the batch PR.

Regression guard (diff-scoped ratchet). bun run audit:error-policy-ratchet compares every production source file the branch touches against that file's own content at the merge-base with origin/develop, and fails only when a touched file adds an empty catch or server-side console.* call. It is immune to unrelated develop drift (files the branch does not touch are never counted) and is a no-op on develop itself. Run ... --report for the repo-wide totals the #12182 sweeps drive down. Logger only, never console, in server code.

Slop and Comment Cleanup

Every file is legible on its own: a purpose-explaining prose header at the top, then in-body comments that explain why the code is the way it is — the design rationale, the constraint that forced the approach, what consumes it — never a restatement of what it does. The reader can read the code; a comment earns its place only by adding what the code cannot show. No change-narration. Write for the next engineer opening this file cold in a greenfield codebase: there is no legacy to apologize for and no diff history to narrate — these comments are the codified, durable explanation of the system. The rules below are binding for new code and for the repo-wide cleanup (#12181).

  1. Header form — one /** … */ prose block at the very top (after a #! shebang; after a third-party license block in the few files that carry one; before imports). Plain prose, not a template: no @fileoverview, no @author/@date/@version. Position is the signal.
  2. First sentence states what the file does in system terms; never repeat the filename ("Local content-addressed media store for chat attachments."). Then, only as warranted, give the reader a sense of the file's place in the system: who consumes it and what it consumes (the boundary it sits on), the invariants/constraints it must uphold, why it is shaped the way it is, and gotchas to know before editing. Issue refs like (#9948) are welcome when they anchor non-obvious rationale — never as a substitute for stating it.
  3. Length scales with weight, hard ceiling ~25 lines. Barrel index.ts / tiny type files: 1 line. Typical modules: 26 lines. Load-bearing modules: 23 short paragraphs. Longer than that belongs in the package CLAUDE.md/README.md — reference it instead. Test files: 13 lines — what surface is under test and how real the harness is (live model vs deterministic proxy, real DB vs in-memory).
  4. In-body comments explain the why, never the what. The reader can see what the code does; a comment earns its place only by adding what the code cannot show — the design rationale (why this approach and not the obvious alternative), the invariant or constraint that forced it, units and boundary conditions, protocol quirks, ordering constraints, and non-obvious consequences for callers. Keep the two-tier split — /** JSDoc */ on exported symbols (for callers), // for implementation notes. Delete restatement, change-narration, status updates, migration stories, and commented-out code. Do not blanket-comment: a file whose code is clear needs a header and nothing else.
  5. Churn test = durability test. Would the comment be true and useful to someone who never saw the previous version? If it only makes sense as a diff annotation, delete it; if the fact is durable but churn-phrased, rewrite it to present tense. History lives in git.
  6. Accuracy over coverage. A wrong header is worse than no header. Read the package's CLAUDE.md first; if a file's purpose can't be determined, flag it in the PR instead of guessing.

Copy the tone from these in-repo exemplars, don't invent one: packages/agent/src/api/media-store.ts:1 (service), packages/ui/src/components/RoleGate.tsx:1 (React component), packages/scripts/run-all-tests.mjs:1 (script — but don't copy its filename-repetition opener), and .gitmodules (config prose). Never touch code, string/template literals, third-party license blocks (header goes below them), or generated files. Comment-only changes are machine-checked by bun run check:comment-only (scripts/assert-comment-only-diff.mjs): it asserts the code token stream is byte-for-byte unchanged.

App visual review — REQUIRED for UI changes in packages/app/

Any change in packages/app/ (or a shared package whose UI bleeds into it) MUST pass the screenshot + manual-review loop before it is "done":

bun run --cwd packages/app audit:app

This walks the app views (desktop + mobile, rest + hover), captures the populated UI, and auto-stubs aesthetic-audit-output/manual-review/<slug>.md per view. Use those Markdown files for human notes and eyeballing; CI enforces the computed verdicts in report.json / the Playwright run, not edited manual-review Markdown. Review every page you touched or can reach via shared layout/theme/components.

  • No computed page verdict may stay needs-work / broken when a UI task is declared done.
  • Iterate the loop ≥5× for any meaningful redesign.
  • Orange is accent only; no blue anywhere; orange-resting → darker-orange hover (never orange→black). Full package rules: packages/app/AGENTS.md.

LifeOps + health: one scheduler, structural behavior

@elizaos/plugin-personal-assistant and @elizaos/plugin-health share one scheduled-item architecture. Reminders, check-ins, follow-ups, watchers, recaps, approvals, and outputs are all ScheduledTask records routed through a single runner (plugins/plugin-scheduling/src/scheduled-task/runner.ts), which pattern-matches on structural fields (kind, trigger, shouldFire, completionCheck, pipeline, …), never on promptInstructions text. Health contributes through registries; LifeOps does not import its internals.

For the full automation vocabulary — how a workflow, trigger, task, scheduled item, coding task, and automation differ and what fires each (one clock, two consumers) — see docs/automation-glossary.md.

Do not add: a second LifeOps scheduling mechanism, a second knowledge-graph store (use EntityStore / RelationshipStore), behavior driven by promptInstructions string content, a boolean return from a connector dispatch (use the typed DispatchResult), or an identity-merge that bypasses the merge engine. Architecture, frozen contracts, and contribution paths live in plugins/plugin-personal-assistant/README.md and plugins/plugin-health/README.md.

Attachments & files: one content-addressed store, additive model

Attachment bytes live in a single content-addressed storepackages/agent/src/api/media-store.ts (${STATE_DIR}/media/<sha256>.<ext>, served at /api/media/<sha256>.<ext>). The sha256 URL is the canonical, unguessable, deduped handle; Media (packages/core/src/types/primitives.ts) is the in-message reference and is widened additively only. Bytes are served pre-auth (the hash is the capability), with nosniff + a download Content-Disposition for SVG/active types; every server-side attachment fetch must go through the SSRF guard (packages/core/src/network + media/fetch.ts).

Do not add: a second file store or storage abstraction/selector; a files/file_references DB table or a refcount/GC engine (the store already GCs via gcUnreferencedMedia + a grace window); a fileId on Media; a rewrite/rehost on the pre-auth serve path (rehost only on authenticated write); or a repurpose/removal of a ContentType enum value (it is frozen, append-only — derive fine-grained kind from mimeType at read time). Scope, deferrals, and rationale live in issue #8876.

Definition of Done — sync, PR, and human-verifiable evidence

Every fix/feature ships through a PR against develop, and a reviewer must be able to confirm it works without reading the code. This section is the binding standard. The same standard is restated in every package's CLAUDE.md / AGENTS.md and is non-negotiable.

The three laws of "done" (the whole standard expands these):

  1. Prove the real thing happened — and look at it yourself. Record the actual model trajectories (inputs and outputs from a live model, not the proxy, not a mock), the real client + server logs, the real pixels/audio, and the real domain artifacts (memories, knowledge, DB rows, scheduled tasks, wallet balance, on-chain results, generated files). Then open every artifact and review it by hand. Capturing is not reviewing; green CI is not proof.
  2. Test everything for real — no larp. Every change ships detailed, full-featured end-to-end tests that drive the real path — not the happy "front door" only. Cover error paths, edges, empty/invalid input, concurrency, roles/permissions, and adversarial input. A test asserting against a mock/stub standing in for the thing under test does not count; if the real model/device/chain/connector is hard to reach, make it reachable — that's the work. If the existing tests you touch are shallow or mocked, fixing them is part of your change. (See the standing backlog: #9943, #9950, #9954, #9958, #9967, #9970.)
  3. No residuals, no shortcuts. The goal is not "done," it is everything done. Clear blockers by the hard path — build the real architecture, stand up the real model/device/service, actually test it. No TODOs, stubs, stepping-stones, or "follow-ups." When unsure, research, weigh options, and ship the best production-ready version. Keep going until every possibility is exhausted.

The non-negotiables in practice:

  • Always PR; never push feature/fix work straight to develop. Branch as feat|fix|docs|chore/<slug>; open an issue first for anything non-trivial.
  • Always sync before opening or updating a PR. git fetch origin && git rebase origin/develop, resolve every conflict, bun install, then bun run verify. A branch that can't fast-forward onto develop is not ready.
  • Frontend-testable changes are not done without rendered proof. Any change a user can exercise in the web, desktop, mobile, or cloud UI must attach a video walkthrough; before and after full-page screenshots for desktop and mobile; backend structured logs; frontend console and network logs; and real-LLM trajectories when agent/action/provider/prompt/model behavior changes. If one row does not apply, keep it visible and write N/A - <reason> in the PR and issue evidence.
  • Attach complete, real, manually-reviewed evidence — prove the real thing happened, not a mock of it:
    • Real-LLM trajectories for agent/action/prompt/model changes — packages/scenario-runner/bin/eliza-scenarios run <scenario> --report <out> against a live model (JSON report + run viewer + native jsonl) — and read them.
    • Backend logs (structured [ClassName] …) and frontend logs (console + network) showing the actual code path firing.
    • Before/after full-page screenshots (desktop + mobile) + a video walkthrough of the whole flow — default to bun run test:matrix:review so the full matrix writes evidence/matrix-run.json and opens the unified reviewer. For scoped UI evidence, use bun run test:e2e:record:review; for app UI, use bun run --cwd packages/app audit:app.
    • Per-platform capture (screenshot + recording + logs) for native/mobile/ desktop changes — bun run --cwd packages/app capture:ios-sim / capture:android-emu / capture:linux-desktop / capture:windows-desktop, electrobun GET /api/dev/cursor-screenshot. Run native features on the real device/simulator/platform matrix, not mocked-bridge desktop Chromium. The command matrix lives in CONTRIBUTING.md.
    • Always build + deploy the latest before capturing. Capture helpers screenshot whatever is already installed/running — they do not build. Before any on-device/simulator/desktop capture, rebuild and redeploy the current tree (mobile: build:android / build:ios cap sync and reinstall — a Capacitor app bakes the web bundle into the APK/IPA at build time, so restarting the old app never picks up a renderer change). Confirm the running build is yours (versionName / a known on-screen change) — a screenshot of a stale install proves nothing.
    • Audio + narrated walkthrough for voice/transcript/TTS/STT changes.
    • Domain artifacts — the things the change produced (memory/knowledge/DB rows, scheduled tasks, wallet balance before/after, on-chain tx hashes, generated files, device output) — inspected by hand and shown.
    • Evidence is posted inline in the issue/PR itself (drag-and-drop): videos as MP4 (GitHub renders MP4 inline — convert .mov/.webm), screenshots as JPG rather than PNG where possible, long logs in a <details> block. Do not commit evidence files to the repo (.github/issue-evidence/ is retired). Each evidence type is attached or explicitly marked N/A with a reason — never left blank. If develop moved and changed behavior, re-capture evidence; stale proof is worse than none.

Contributing

Open an issue before a non-trivial PR. License: MIT (LICENSE). Security policy: SECURITY.md. Shipping workflow: CONTRIBUTING.md.