227 lines
25 KiB
Markdown
227 lines
25 KiB
Markdown
# Repository Guidelines
|
||
|
||
- Repo: https://github.com/openclaw/openclaw
|
||
- In chat replies, file references must be repo-root relative only (example: `extensions/bluebubbles/src/channel.ts:80`); never absolute paths or `~/...`.
|
||
- Do not edit files covered by security-focused `CODEOWNERS` rules unless a listed owner explicitly asked for the change or is already reviewing it with you. Treat those paths as restricted surfaces, not drive-by cleanup.
|
||
|
||
## Project Structure & Module Organization
|
||
|
||
- Source code: `src/` (CLI wiring in `src/cli`, commands in `src/commands`, web provider in `src/provider-web.ts`, infra in `src/infra`, media pipeline in `src/media`).
|
||
- Tests: colocated `*.test.ts`.
|
||
- Docs: `docs/` (images, queue, Pi config). Built output lives in `dist/`.
|
||
- Plugins/extensions: live under `extensions/*` (workspace packages). Keep plugin-only deps in the extension `package.json`; do not add them to the root `package.json` unless core uses them.
|
||
- Plugins: install runs `npm install --omit=dev` in plugin dir; runtime deps must live in `dependencies`. Avoid `workspace:*` in `dependencies` (npm install breaks); put `openclaw` in `devDependencies` or `peerDependencies` instead (runtime resolves `openclaw/plugin-sdk` via jiti alias).
|
||
- Import boundaries: extension production code should treat `openclaw/plugin-sdk/*` plus local `api.ts` / `runtime-api.ts` barrels as the public surface. Do not import core `src/**`, `src/plugin-sdk-internal/**`, or another extension's `src/**` directly.
|
||
- Installers served from `https://openclaw.ai/*`: live in the sibling repo `../openclaw.ai` (`public/install.sh`, `public/install-cli.sh`, `public/install.ps1`).
|
||
- Messaging channels: always consider **all** built-in + extension channels when refactoring shared logic (routing, allowlists, pairing, command gating, onboarding, docs).
|
||
- Core channel docs: `docs/channels/`
|
||
- Core channel code: `src/telegram`, `src/discord`, `src/slack`, `src/signal`, `src/imessage`, `src/web` (WhatsApp web), `src/channels`, `src/routing`
|
||
- Extensions (channel plugins): `extensions/*` (e.g. `extensions/msteams`, `extensions/matrix`, `extensions/zalo`, `extensions/zalouser`, `extensions/voice-call`)
|
||
- When adding channels/extensions/apps/docs, update `.github/labeler.yml` and create matching GitHub labels (use existing channel/extension label colors).
|
||
|
||
## Docs Linking (Mintlify)
|
||
|
||
- Docs are hosted on Mintlify (docs.openclaw.ai).
|
||
- Internal doc links in `docs/**/*.md`: root-relative, no `.md`/`.mdx` (example: `[Config](/configuration)`).
|
||
- When working with documentation, read the mintlify skill.
|
||
- For docs, UI copy, and picker lists, order services/providers alphabetically unless the section is explicitly describing runtime behavior (for example auto-detection or execution order).
|
||
- Section cross-references: use anchors on root-relative paths (example: `[Hooks](/configuration#hooks)`).
|
||
- Doc headings and anchors: avoid em dashes and apostrophes in headings because they break Mintlify anchor links.
|
||
- When Peter asks for links, reply with full `https://docs.openclaw.ai/...` URLs (not root-relative).
|
||
- When you touch docs, end the reply with the `https://docs.openclaw.ai/...` URLs you referenced.
|
||
- README (GitHub): keep absolute docs URLs (`https://docs.openclaw.ai/...`) so links work on GitHub.
|
||
- Docs content must be generic: no personal device names/hostnames/paths; use placeholders like `user@gateway-host` and “gateway host”.
|
||
|
||
## Docs i18n (zh-CN)
|
||
|
||
- `docs/zh-CN/**` is generated; do not edit unless the user explicitly asks.
|
||
- Pipeline: update English docs → adjust glossary (`docs/.i18n/glossary.zh-CN.json`) → run `scripts/docs-i18n` → apply targeted fixes only if instructed.
|
||
- Before rerunning `scripts/docs-i18n`, add glossary entries for any new technical terms, page titles, or short nav labels that must stay in English or use a fixed translation (for example `Doctor` or `Polls`).
|
||
- `pnpm docs:check-i18n-glossary` enforces glossary coverage for changed English doc titles and short internal doc labels before translation reruns.
|
||
- Translation memory: `docs/.i18n/zh-CN.tm.jsonl` (generated).
|
||
- See `docs/.i18n/README.md`.
|
||
- The pipeline can be slow/inefficient; if it’s dragging, ping @jospalmbier on Discord instead of hacking around it.
|
||
|
||
## exe.dev VM ops (general)
|
||
|
||
- Access: stable path is `ssh exe.dev` then `ssh vm-name` (assume SSH key already set).
|
||
- SSH flaky: use exe.dev web terminal or Shelley (web agent); keep a tmux session for long ops.
|
||
- Update: `sudo npm i -g openclaw@latest` (global install needs root on `/usr/lib/node_modules`).
|
||
- Config: use `openclaw config set ...`; ensure `gateway.mode=local` is set.
|
||
- Discord: store raw token only (no `DISCORD_BOT_TOKEN=` prefix).
|
||
- Restart: stop old gateway and run:
|
||
`pkill -9 -f openclaw-gateway || true; nohup openclaw gateway run --bind loopback --port 18789 --force > /tmp/openclaw-gateway.log 2>&1 &`
|
||
- Verify: `openclaw channels status --probe`, `ss -ltnp | rg 18789`, `tail -n 120 /tmp/openclaw-gateway.log`.
|
||
|
||
## Build, Test, and Development Commands
|
||
|
||
- Runtime baseline: Node **22+** (keep Node + Bun paths working).
|
||
- Install deps: `pnpm install`
|
||
- If deps are missing (for example `node_modules` missing, `vitest not found`, or `command not found`), run the repo’s package-manager install command (prefer lockfile/README-defined PM), then rerun the exact requested command once. Apply this to test/build/lint/typecheck/dev commands; if retry still fails, report the command and first actionable error.
|
||
- Pre-commit hooks: `prek install` (runs same checks as CI)
|
||
- Also supported: `bun install` (keep `pnpm-lock.yaml` + Bun patching in sync when touching deps/patches).
|
||
- Prefer Bun for TypeScript execution (scripts, dev, tests): `bun <file.ts>` / `bunx <tool>`.
|
||
- Run CLI in dev: `pnpm openclaw ...` (bun) or `pnpm dev`.
|
||
- Node remains supported for running built output (`dist/*`) and production installs.
|
||
- Mac packaging (dev): `scripts/package-mac-app.sh` defaults to current arch.
|
||
- Type-check/build: `pnpm build`
|
||
- TypeScript checks: `pnpm tsgo`
|
||
- Lint/format: `pnpm check`
|
||
- Format check: `pnpm format` (oxfmt --check)
|
||
- Format fix: `pnpm format:fix` (oxfmt --write)
|
||
- Tests: `pnpm test` (vitest); coverage: `pnpm test:coverage`
|
||
- Default landing bar: before any commit, run `pnpm check` and prefer a passing result for the change being committed.
|
||
- For narrowly scoped changes, run narrowly scoped tests that directly validate the touched behavior; this is required proof for the change before commit and push decisions. If no meaningful scoped test exists, say so explicitly and use the next most direct validation available.
|
||
- Default landing bar: before any push to `main`, run `pnpm check` and `pnpm test` and prefer a green result.
|
||
- Scoped tests prove the change itself. `pnpm test` remains the default `main` landing bar; scoped tests do not replace full-suite gates by default.
|
||
- Hard gate: if the change can affect build output, packaging, lazy-loading/module boundaries, or published surfaces, `pnpm build` MUST be run and MUST pass before pushing `main`.
|
||
- Default rule: do not commit or push with failing format, lint, type, build, or required test checks when those failures are caused by the change or plausibly related to the touched surface.
|
||
|
||
## Judgment / Exception Handling
|
||
|
||
- Use judgment for narrowly scoped changes when unrelated failures already exist on latest `origin/main`.
|
||
- Before using that judgment, explicitly separate:
|
||
- failures caused by the change
|
||
- failures reproducible on current `origin/main`
|
||
- failures that are clearly unrelated to the touched surface
|
||
- Scoped exceptions are allowed only when all of the following are true:
|
||
- the diff is narrowly scoped and low blast radius
|
||
- the failing checks touch unrelated surfaces
|
||
- the failures are reproducible on current `origin/main` or are otherwise clearly pre-existing
|
||
- you explicitly explain that conclusion to Tak
|
||
- Even when using a scoped exception, narrowly scoped tests are still required as direct proof of the change unless no meaningful scoped test exists.
|
||
- Do not claim full gate compliance when using a scoped exception. State which checks are failing and why they appear unrelated.
|
||
- When using judgment because full-suite failures are unrelated or already failing on latest `origin/main`, report both:
|
||
- which scoped tests you ran as direct proof of the change
|
||
- which full-suite failures you are setting aside and why they appear unrelated
|
||
- If the branch contains only the intended scoped change and the remaining failures are demonstrably unrelated or already failing on latest `origin/main`, report that clearly and ask for a push/waiver decision instead of silently broadening scope into unrelated fixes.
|
||
- If Tak explicitly authorizes landing despite unrelated failing gates, treat that as an informed override. Do not keep repairing unrelated areas unless Tak explicitly asks for that broader work.
|
||
- Do not use judgment as a blanket bypass. If the change could plausibly affect the failing area, treat the failure as in-scope until proven otherwise. Do not use “scoped tests passed” as permission to ignore plausibly related failures.
|
||
|
||
## Coding Style & Naming Conventions
|
||
|
||
- Language: TypeScript (ESM). Prefer strict typing; avoid `any`.
|
||
- Formatting/linting via Oxlint and Oxfmt; run `pnpm check` before commits.
|
||
- Never add `@ts-nocheck` and do not disable `no-explicit-any`; fix root causes and update Oxlint/Oxfmt config only when required.
|
||
- Dynamic import guardrail: do not mix `await import("x")` and static `import ... from "x"` for the same module in production code paths. If you need lazy loading, create a dedicated `*.runtime.ts` boundary (that re-exports from `x`) and dynamically import that boundary from lazy callers only.
|
||
- Dynamic import verification: after refactors that touch lazy-loading/module boundaries, run `pnpm build` and check for `[INEFFECTIVE_DYNAMIC_IMPORT]` warnings before submitting.
|
||
- Extension SDK self-import guardrail: inside an extension package, do not import that same extension via `openclaw/plugin-sdk/<extension>` from production files. Route internal imports through a local barrel such as `./api.ts` or `./runtime-api.ts`, and keep the `plugin-sdk/<extension>` path as the external contract only.
|
||
- Extension package boundary guardrail: inside `extensions/<id>/**`, do not use relative imports/exports that resolve outside that same `extensions/<id>` package root. If shared code belongs in the plugin SDK, import `openclaw/plugin-sdk/<subpath>` instead of reaching into `src/plugin-sdk/**` or other repo paths via `../`.
|
||
- Extension API surface rule: `openclaw/plugin-sdk/<subpath>` is the only public cross-package contract for extension-facing SDK code. If an extension needs a new seam, add a public subpath first; do not reach into `src/plugin-sdk/**` by relative path.
|
||
- Never share class behavior via prototype mutation (`applyPrototypeMixins`, `Object.defineProperty` on `.prototype`, or exporting `Class.prototype` for merges). Use explicit inheritance/composition (`A extends B extends C`) or helper composition so TypeScript can typecheck.
|
||
- If this pattern is needed, stop and get explicit approval before shipping; default behavior is to split/refactor into an explicit class hierarchy and keep members strongly typed.
|
||
- In tests, prefer per-instance stubs over prototype mutation (`SomeClass.prototype.method = ...`) unless a test explicitly documents why prototype-level patching is required.
|
||
- Add brief code comments for tricky or non-obvious logic.
|
||
- Keep files concise; extract helpers instead of “V2” copies. Use existing patterns for CLI options and dependency injection via `createDefaultDeps`.
|
||
- Aim to keep files under ~700 LOC; guideline only (not a hard guardrail). Split/refactor when it improves clarity or testability.
|
||
- Naming: use **OpenClaw** for product/app/docs headings; use `openclaw` for CLI command, package/binary, paths, and config keys.
|
||
- Written English: use American spelling and grammar in code, comments, docs, and UI strings (e.g. "color" not "colour", "behavior" not "behaviour", "analyze" not "analyse").
|
||
|
||
## Release / Advisory Workflows
|
||
|
||
- Use `$openclaw-release-maintainer` at `.agents/skills/openclaw-release-maintainer/SKILL.md` for release naming, version coordination, release auth, and changelog-backed release-note workflows.
|
||
- Use `$openclaw-ghsa-maintainer` at `.agents/skills/openclaw-ghsa-maintainer/SKILL.md` for GHSA advisory inspection, patch/publish flow, private-fork checks, and GHSA API validation.
|
||
- Release and publish remain explicit-approval actions even when using the skill.
|
||
|
||
## Testing Guidelines
|
||
|
||
- Framework: Vitest with V8 coverage thresholds (70% lines/branches/functions/statements).
|
||
- Naming: match source names with `*.test.ts`; e2e in `*.e2e.test.ts`.
|
||
- Run `pnpm test` (or `pnpm test:coverage`) before pushing when you touch logic.
|
||
- Agents MUST NOT modify baseline, inventory, ignore, snapshot, or expected-failure files to silence failing checks without explicit approval in this chat.
|
||
- For targeted/local debugging, keep using the wrapper: `pnpm test -- <path-or-filter> [vitest args...]` (for example `pnpm test -- src/commands/onboard-search.test.ts -t "shows registered plugin providers"`); do not default to raw `pnpm vitest run ...` because it bypasses wrapper config/profile/pool routing.
|
||
- Do not set test workers above 16; tried already.
|
||
- If local Vitest runs cause memory pressure (common on non-Mac-Studio hosts), use `OPENCLAW_TEST_PROFILE=low OPENCLAW_TEST_SERIAL_GATEWAY=1 pnpm test` for land/gate runs.
|
||
- Live tests (real keys): `CLAWDBOT_LIVE_TEST=1 pnpm test:live` (OpenClaw-only) or `LIVE=1 pnpm test:live` (includes provider live tests). Docker: `pnpm test:docker:live-models`, `pnpm test:docker:live-gateway`. Onboarding Docker E2E: `pnpm test:docker:onboard`.
|
||
- Full kit + what’s covered: `docs/help/testing.md`.
|
||
- Changelog: user-facing changes only; no internal/meta notes (version alignment, appcast reminders, release process).
|
||
- Changelog placement: in the active version block, append new entries to the end of the target section (`### Changes` or `### Fixes`); do not insert new entries at the top of a section.
|
||
- Changelog attribution: use at most one contributor mention per line; prefer `Thanks @author` and do not also add `by @author` on the same entry.
|
||
- Pure test additions/fixes generally do **not** need a changelog entry unless they alter user-facing behavior or the user asks for one.
|
||
- Mobile: before using a simulator, check for connected real devices (iOS + Android) and prefer them when available.
|
||
|
||
## Commit & Pull Request Guidelines
|
||
|
||
- Use `$openclaw-pr-maintainer` at `.agents/skills/openclaw-pr-maintainer/SKILL.md` for maintainer PR triage, review, close, search, and landing workflows.
|
||
- This includes auto-close labels, bug-fix evidence gates, GitHub comment/search footguns, and maintainer PR decision flow.
|
||
- For the repo's end-to-end maintainer PR workflow, use `$openclaw-pr-maintainer` at `.agents/skills/openclaw-pr-maintainer/SKILL.md`.
|
||
|
||
- `/landpr` lives in the global Codex prompts (`~/.codex/prompts/landpr.md`); when landing or merging any PR, always follow that `/landpr` process.
|
||
- Create commits with `scripts/committer "<msg>" <file...>`; avoid manual `git add`/`git commit` so staging stays scoped.
|
||
- Follow concise, action-oriented commit messages (e.g., `CLI: add verbose flag to send`).
|
||
- Group related changes; avoid bundling unrelated refactors.
|
||
- PR submission template (canonical): `.github/pull_request_template.md`
|
||
- Issue submission templates (canonical): `.github/ISSUE_TEMPLATE/`
|
||
|
||
## Git Notes
|
||
|
||
- If `git branch -d/-D <branch>` is policy-blocked, delete the local ref directly: `git update-ref -d refs/heads/<branch>`.
|
||
- Agents MUST NOT create or push merge commits on `main`. If `main` has advanced, rebase local commits onto the latest `origin/main` before pushing.
|
||
- Bulk PR close/reopen safety: if a close action would affect more than 5 PRs, first ask for explicit user confirmation with the exact PR count and target scope/query.
|
||
|
||
## Security & Configuration Tips
|
||
|
||
- Web provider stores creds at `~/.openclaw/credentials/`; rerun `openclaw login` if logged out.
|
||
- Pi sessions live under `~/.openclaw/sessions/` by default; the base directory is not configurable.
|
||
- Environment variables: see `~/.profile`.
|
||
- Never commit or publish real phone numbers, videos, or live configuration values. Use obviously fake placeholders in docs, tests, and examples.
|
||
- Release flow: use the private [maintainer release docs](https://github.com/openclaw/maintainers/blob/main/release/README.md) for the actual runbook, `docs/reference/RELEASING.md` for the public release policy, and `$openclaw-release-maintainer` for the maintainership workflow.
|
||
|
||
## Local Runtime / Platform Notes
|
||
|
||
- Vocabulary: "makeup" = "mac app".
|
||
- Rebrand/migration issues or legacy config/service warnings: run `openclaw doctor` (see `docs/gateway/doctor.md`).
|
||
- Use `$openclaw-parallels-smoke` at `.agents/skills/openclaw-parallels-smoke/SKILL.md` for Parallels smoke, rerun, upgrade, debug, and result-interpretation workflows across macOS, Windows, and Linux guests.
|
||
- For the macOS Discord roundtrip deep dive, use the narrower `.agents/skills/parallels-discord-roundtrip/SKILL.md` companion skill.
|
||
- Never edit `node_modules` (global/Homebrew/npm/git installs too). Updates overwrite. Skill notes go in `tools.md` or `AGENTS.md`.
|
||
- If you need local-only `.agents` ignores, use `.git/info/exclude` instead of repo `.gitignore`.
|
||
- When adding a new `AGENTS.md` anywhere in the repo, also add a `CLAUDE.md` symlink pointing to it (example: `ln -s AGENTS.md CLAUDE.md`).
|
||
- Signal: "update fly" => `fly ssh console -a flawd-bot -C "bash -lc 'cd /data/clawd/openclaw && git pull --rebase origin main'"` then `fly machines restart e825232f34d058 -a flawd-bot`.
|
||
- CLI progress: use `src/cli/progress.ts` (`osc-progress` + `@clack/prompts` spinner); don’t hand-roll spinners/bars.
|
||
- Status output: keep tables + ANSI-safe wrapping (`src/terminal/table.ts`); `status --all` = read-only/pasteable, `status --deep` = probes.
|
||
- Gateway currently runs only as the menubar app; there is no separate LaunchAgent/helper label installed. Restart via the OpenClaw Mac app or `scripts/restart-mac.sh`; to verify/kill use `launchctl print gui/$UID | grep openclaw` rather than assuming a fixed label. **When debugging on macOS, start/stop the gateway via the app, not ad-hoc tmux sessions; kill any temporary tunnels before handoff.**
|
||
- macOS logs: use `./scripts/clawlog.sh` to query unified logs for the OpenClaw subsystem; it supports follow/tail/category filters and expects passwordless sudo for `/usr/bin/log`.
|
||
- If shared guardrails are available locally, review them; otherwise follow this repo's guidance.
|
||
- SwiftUI state management (iOS/macOS): prefer the `Observation` framework (`@Observable`, `@Bindable`) over `ObservableObject`/`@StateObject`; don’t introduce new `ObservableObject` unless required for compatibility, and migrate existing usages when touching related code.
|
||
- Connection providers: when adding a new connection, update every UI surface and docs (macOS app, web UI, mobile if applicable, onboarding/overview docs) and add matching status + configuration forms so provider lists and settings stay in sync.
|
||
- Version locations: `package.json` (CLI), `apps/android/app/build.gradle.kts` (versionName/versionCode), `apps/ios/Sources/Info.plist` + `apps/ios/Tests/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `apps/macos/Sources/OpenClaw/Resources/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `docs/install/updating.md` (pinned npm version), and Peekaboo Xcode projects/Info.plists (MARKETING_VERSION/CURRENT_PROJECT_VERSION).
|
||
- "Bump version everywhere" means all version locations above **except** `appcast.xml` (only touch appcast when cutting a new macOS Sparkle release).
|
||
- **Restart apps:** “restart iOS/Android apps” means rebuild (recompile/install) and relaunch, not just kill/launch.
|
||
- **Device checks:** before testing, verify connected real devices (iOS/Android) before reaching for simulators/emulators.
|
||
- iOS Team ID lookup: `security find-identity -p codesigning -v` → use Apple Development (…) TEAMID. Fallback: `defaults read com.apple.dt.Xcode IDEProvisioningTeamIdentifiers`.
|
||
- A2UI bundle hash: `src/canvas-host/a2ui/.bundle.hash` is auto-generated; ignore unexpected changes, and only regenerate via `pnpm canvas:a2ui:bundle` (or `scripts/bundle-a2ui.sh`) when needed. Commit the hash as a separate commit.
|
||
- Release signing/notary credentials are managed outside the repo; maintainers keep that setup in the private [maintainer release docs](https://github.com/openclaw/maintainers/tree/main/release).
|
||
- Lobster palette: use the shared CLI palette in `src/terminal/palette.ts` (no hardcoded colors); apply palette to onboarding/config prompts and other TTY UI output as needed.
|
||
- When asked to open a “session” file, open the Pi session logs under `~/.openclaw/agents/<agentId>/sessions/*.jsonl` (use the `agent=<id>` value in the Runtime line of the system prompt; newest unless a specific ID is given), not the default `sessions.json`. If logs are needed from another machine, SSH via Tailscale and read the same path there.
|
||
- Do not rebuild the macOS app over SSH; rebuilds must be run directly on the Mac.
|
||
- Voice wake forwarding tips:
|
||
- Command template should stay `openclaw-mac agent --message "${text}" --thinking low`; `VoiceWakeForwarder` already shell-escapes `${text}`. Don’t add extra quotes.
|
||
- launchd PATH is minimal; ensure the app’s launch agent PATH includes standard system paths plus your pnpm bin (typically `$HOME/Library/pnpm`) so `pnpm`/`openclaw` binaries resolve when invoked via `openclaw-mac`.
|
||
|
||
## Collaboration / Safety Notes
|
||
|
||
- When working on a GitHub Issue or PR, print the full URL at the end of the task.
|
||
- When answering questions, respond with high-confidence answers only: verify in code; do not guess.
|
||
- Never update the Carbon dependency.
|
||
- Any dependency with `pnpm.patchedDependencies` must use an exact version (no `^`/`~`).
|
||
- Patching dependencies (pnpm patches, overrides, or vendored changes) requires explicit approval; do not do this by default.
|
||
- **Multi-agent safety:** do **not** create/apply/drop `git stash` entries unless explicitly requested (this includes `git pull --rebase --autostash`). Assume other agents may be working; keep unrelated WIP untouched and avoid cross-cutting state changes.
|
||
- **Multi-agent safety:** when the user says "push", you may `git pull --rebase` to integrate latest changes (never discard other agents' work). When the user says "commit", scope to your changes only. When the user says "commit all", commit everything in grouped chunks.
|
||
- **Multi-agent safety:** do **not** create/remove/modify `git worktree` checkouts (or edit `.worktrees/*`) unless explicitly requested.
|
||
- **Multi-agent safety:** do **not** switch branches / check out a different branch unless explicitly requested.
|
||
- **Multi-agent safety:** running multiple agents is OK as long as each agent has its own session.
|
||
- **Multi-agent safety:** when you see unrecognized files, keep going; focus on your changes and commit only those.
|
||
- Lint/format churn:
|
||
- If staged+unstaged diffs are formatting-only, auto-resolve without asking.
|
||
- If commit/push already requested, auto-stage and include formatting-only follow-ups in the same commit (or a tiny follow-up commit if needed), no extra confirmation.
|
||
- Only ask when changes are semantic (logic/data/behavior).
|
||
- **Multi-agent safety:** focus reports on your edits; avoid guard-rail disclaimers unless truly blocked; when multiple agents touch the same file, continue if safe; end with a brief “other files present” note only if relevant.
|
||
- Bug investigations: read source code of relevant npm dependencies and all related local code before concluding; aim for high-confidence root cause.
|
||
- Code style: add brief comments for tricky logic; keep files under ~500 LOC when feasible (split/refactor as needed).
|
||
- Tool schema guardrails (google-antigravity): avoid `Type.Union` in tool input schemas; no `anyOf`/`oneOf`/`allOf`. Use `stringEnum`/`optionalStringEnum` (Type.Unsafe enum) for string lists, and `Type.Optional(...)` instead of `... | null`. Keep top-level tool schema as `type: "object"` with `properties`.
|
||
- Tool schema guardrails: avoid raw `format` property names in tool schemas; some validators treat `format` as a reserved keyword and reject the schema.
|
||
- Never send streaming/partial replies to external messaging surfaces (WhatsApp, Telegram); only final replies should be delivered there. Streaming/tool events may still go to internal UIs/control channel.
|
||
- For manual `openclaw message send` messages that include `!`, use the heredoc pattern noted below to avoid the Bash tool’s escaping.
|
||
- Release guardrails: do not change version numbers without operator’s explicit consent; always ask permission before running any npm publish/release step.
|
||
- Beta release guardrail: when using a beta Git tag (for example `vYYYY.M.D-beta.N`), publish npm with a matching beta version suffix (for example `YYYY.M.D-beta.N`) rather than a plain version on `--tag beta`; otherwise the plain version name gets consumed/blocked.
|