diff --git a/AGENTS.md b/AGENTS.md index e974968b564..3294dbe0684 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,7 +30,8 @@ - `src/plugins/*` = plugin discovery, manifest validation, loader, registry, and contract enforcement - `src/gateway/protocol/*` = typed Gateway control-plane and node wire protocol - Progressive disclosure lives in local boundary guides: - - bundled-plugin-tree `AGENTS.md` + - repo root `AGENTS.md` + - bundled-plugin-tree `extensions/AGENTS.md` - `src/plugin-sdk/AGENTS.md` - `src/channels/AGENTS.md` - `src/plugins/AGENTS.md` @@ -68,7 +69,7 @@ - `hooks.internal.entries` is the canonical public hook config model. `hooks.internal.handlers` is compatibility-only input and must not be re-exposed in public schema/help/baseline surfaces. - Bundled plugin contract boundary: - Public docs: `docs/plugins/architecture.md`, `docs/plugins/manifest.md`, `docs/plugins/sdk-overview.md` -- Definition files: `src/plugins/contracts/registry.ts`, `src/plugins/types.ts`, `src/plugins/public-artifacts.ts` + - Definition files: `src/plugins/contracts/registry.ts`, `src/plugins/types.ts`, `src/plugins/public-artifacts.ts` - Rule: keep manifest metadata, runtime registration, public SDK exports, and contract tests aligned. Do not create a hidden path around the declared plugin interfaces. - Extension test boundary: - Keep extension-owned onboarding/config/provider coverage under the owning bundled plugin package when feasible. @@ -76,37 +77,25 @@ - Shared helpers under `test/helpers/**` are part of that same boundary. Do not hardcode repo-relative `extensions/**` imports there, and do not keep plugin-local deep mocks in shared helpers just because multiple tests use them. - When core tests or shared helpers need bundled plugin public surfaces, use `src/test-utils/bundled-plugin-public-surface.ts` for `api.ts`, `runtime-api.ts`, `contract-api.ts`, `test-api.ts`, plugin entrypoint `index.js`, and resolved module ids for dynamic import or mocking. - If a core test is asserting extension-specific behavior instead of a generic contract, move it to the owning extension package. +- Scoped guides still matter: + - `extensions/AGENTS.md` expands extension/plugin boundary rules. + - `src/channels/AGENTS.md` expands core channel boundary and hot-path rules. + - `src/plugin-sdk/AGENTS.md` expands public SDK contract rules. + - `src/plugins/AGENTS.md` expands plugin loading, registry, and manifest rules. + - `src/gateway/protocol/AGENTS.md` expands typed Gateway protocol rules. + - `test/helpers/AGENTS.md` and `test/helpers/channels/AGENTS.md` expand shared test helper boundary rules. +- Plugin architecture direction: + - Keep a manifest-first control plane: discovery, validation, enablement, setup hints, and activation planning should stay metadata-driven by default. + - Keep runtime execution separate: actual provider/channel/tool execution should resolve through narrow targeted loaders, not broad registry materialization. + - Host loads plugins; plugins do not load host internals. Prefer a small versioned host/kernel seam plus documented SDK entrypoints over ambient reachability. + - Treat broad runtime registries and mutable global plugin state as transitional compatibility surfaces, not the target architecture. + - If a setup or config flow truly needs plugin runtime, make that explicit instead of silently importing runtime code on the cold path. -## Docs Linking (Mintlify) +## Scoped Workflow Guides -- 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 the user 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 (generated publish locales) - -- Foreign-language docs are not maintained in this repo. The generated publish output lives in the separate `openclaw/docs` repo (often cloned locally as the sibling `openclaw-docs` directory); do not add or edit localized docs under `docs//**` here. -- Those localized docs are autogenerated. Treat this repo's English docs plus glossary files as the source of truth, and let the publish/translation pipeline update `openclaw/docs`. -- Pipeline: update English docs here → adjust the matching `docs/.i18n/glossary..json` entries → let the publish-repo sync + `scripts/docs-i18n` run in `openclaw/docs` / local `openclaw-docs` clone → 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 lives in generated `docs/.i18n/*.tm.jsonl` files in the publish repo. -- See `docs/.i18n/README.md`. -- The pipeline can be slow/inefficient; if it’s dragging, ping @jospalmbier on Discord instead of hacking around it. - -## Control UI i18n (generated in repo) - -- Control UI foreign-language locale bundles are generated in this repo; do not hand-edit `ui/src/i18n/locales/*.ts` for non-English locales or `ui/src/i18n/.i18n/*` unless a targeted generated-output fix is explicitly requested. -- Source of truth is `ui/src/i18n/locales/en.ts` plus the generator/runtime wiring in `scripts/control-ui-i18n.ts`, `ui/src/i18n/lib/types.ts`, and `ui/src/i18n/lib/registry.ts`. -- Pipeline: update English control UI strings and locale wiring here → run `pnpm ui:i18n:sync` (or let `Control UI Locale Refresh` do it) → commit the regenerated locale bundles and `.i18n` metadata. -- If the control UI locale outputs drift, regenerate them; do not manually translate or hand-maintain the generated locale files by default. +- `docs/AGENTS.md` owns Mintlify docs, docs links, and docs i18n rules. +- `ui/AGENTS.md` owns Control UI i18n and generated locale rules. +- `scripts/AGENTS.md` owns script-runner, local-check lock, and test/lint wrapper rules. ## exe.dev VM ops (general) @@ -316,7 +305,7 @@ - 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). +- Code style: add brief comments for tricky logic; keep files under ~700 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. diff --git a/docs/AGENTS.md b/docs/AGENTS.md new file mode 100644 index 00000000000..751f993a18c --- /dev/null +++ b/docs/AGENTS.md @@ -0,0 +1,28 @@ +# Docs Guide + +This directory owns docs authoring, Mintlify link rules, and docs i18n policy. + +## Mintlify Rules + +- Docs are hosted on Mintlify (`https://docs.openclaw.ai`). +- Internal doc links in `docs/**/*.md` must stay root-relative with no `.md` or `.mdx` suffix (example: `[Config](/configuration)`). +- Section cross-references should use anchors on root-relative paths (example: `[Hooks](/configuration#hooks)`). +- Doc headings should avoid em dashes and apostrophes because Mintlify anchor generation is brittle there. +- README and other GitHub-rendered docs should keep absolute docs URLs so links work outside Mintlify. +- Docs content must stay generic: no personal device names, hostnames, or local paths; use placeholders like `user@gateway-host`. + +## Docs Content Rules + +- For docs, UI copy, and picker lists, order services/providers alphabetically unless the section is explicitly describing runtime order or auto-detection order. +- Keep bundled plugin naming consistent with the repo-wide plugin terminology rules in the root `AGENTS.md`. + +## Docs i18n + +- Foreign-language docs are not maintained in this repo. The generated publish output lives in the separate `openclaw/docs` repo (often cloned locally as `../openclaw-docs`). +- Do not add or edit localized docs under `docs//**` here. +- Treat English docs in this repo plus glossary files as the source of truth. +- Pipeline: update English docs here, update `docs/.i18n/glossary..json` as needed, then let the publish-repo sync and `scripts/docs-i18n` run in `openclaw/docs`. +- 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. +- `pnpm docs:check-i18n-glossary` is the guard for changed English doc titles and short internal doc labels. +- Translation memory lives in generated `docs/.i18n/*.tm.jsonl` files in the publish repo. +- See `docs/.i18n/README.md`. diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/docs/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/extensions/AGENTS.md b/extensions/AGENTS.md index 1c2dcff51bc..0232e37f00d 100644 --- a/extensions/AGENTS.md +++ b/extensions/AGENTS.md @@ -51,6 +51,15 @@ third-party plugins see. provider needs OpenAI-style Anthropic tool payload compat, Gemini schema cleanup, or an XAI compat patch, use a named shared helper instead of inlining the policy knobs again. +- Keep control-plane metadata separate from runtime logic. Discovery, config + validation, setup hints, onboarding hints, and activation planning should be + expressible from manifest/descriptors whenever possible. +- If setup truly requires runtime execution, make that explicit in the plugin's + declared setup/runtime surface instead of letting metadata flows import + runtime code accidentally. +- Do not rely on eager global registry seeding or import-time side effects to + make a plugin “available”. Plugin availability should come from manifest + ownership plus targeted activation. ## Expanding The Boundary diff --git a/scripts/AGENTS.md b/scripts/AGENTS.md new file mode 100644 index 00000000000..258d5bcfda7 --- /dev/null +++ b/scripts/AGENTS.md @@ -0,0 +1,26 @@ +# Scripts Guide + +This directory owns local tooling, script wrappers, and generated-artifact helper rules. + +## Wrapper Rules + +- Prefer existing wrappers over raw tool entrypoints when the repo already has a curated seam. +- For tests, prefer `scripts/run-vitest.mjs` or the root `pnpm test ...` entrypoints over raw `vitest run` calls. +- For lint/typecheck flows, prefer `scripts/run-oxlint.mjs` and `scripts/run-tsgo.mjs` when adding or editing package scripts or CI steps that should honor repo-local runtime behavior. + +## Local Heavy-Check Lock + +- Respect the local heavy-check lock behavior in `scripts/lib/local-heavy-check-runtime.mjs`. +- Do not bypass that lock for real heavy commands just to make a local loop look faster. +- Metadata-only or explicitly narrow commands may skip the lock when the existing helper logic says that is safe. +- If you change the lock heuristics, add or update the narrow tests under `test/scripts/`. + +## Generated Outputs + +- If a script writes generated artifacts, keep the source-of-truth generator, the package script, and the matching verification/check command aligned. +- Prefer additive generator/check pairs like `*:gen` and `*:check` over one-off undocumented scripts. + +## Scope + +- Keep script-runner behavior, wrapper expectations, and generated-artifact guidance here. +- Leave repo-global verification policy in the root `AGENTS.md`. diff --git a/scripts/CLAUDE.md b/scripts/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/scripts/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/src/plugin-sdk/AGENTS.md b/src/plugin-sdk/AGENTS.md index d91b125886a..7968f928d45 100644 --- a/src/plugin-sdk/AGENTS.md +++ b/src/plugin-sdk/AGENTS.md @@ -22,6 +22,10 @@ can affect bundled plugins and third-party plugins. ## Boundary Rules +- Host loads plugins; plugins should not reach through the SDK into arbitrary + host internals. +- Prefer a small versioned host/kernel seam plus narrow documented SDK + entrypoints over broad convenience barrels. - Prefer narrow, purpose-built subpaths over broad convenience re-exports. - Do not expose implementation convenience from `src/channels/**`, `src/agents/**`, `src/plugins/**`, or other internals unless you are @@ -52,6 +56,12 @@ can affect bundled plugins and third-party plugins. - Keep transport/runtime policy and plugin-facing helpers aligned. If the same behavior is used in plugin registration and in core runtime paths, expose one shared helper instead of letting the two paths drift. +- SDK subpaths should help callers resolve one capability or runtime need at a + time. Do not grow new surfaces that require broad runtime registry access as + the default path. +- If a proposed SDK export mainly exists to let setup/config/control-plane code + execute plugin runtime, that is usually a boundary smell. Prefer metadata or + descriptor-driven control-plane seams first. ## Verification diff --git a/src/plugins/AGENTS.md b/src/plugins/AGENTS.md index a414a5db256..eb64bc75a51 100644 --- a/src/plugins/AGENTS.md +++ b/src/plugins/AGENTS.md @@ -18,6 +18,10 @@ assembly, and contract enforcement. ## Boundary Rules +- Keep control-plane and runtime-plane concerns separate: + discovery, manifest parsing, config validation, setup/onboarding hints, and + activation planning belong to the control plane; actual plugin execution + belongs to runtime resolution. - Preserve manifest-first behavior: discovery, config validation, and setup should work from metadata before plugin runtime executes. - Keep loader behavior aligned with the documented Plugin SDK and manifest @@ -31,6 +35,9 @@ assembly, and contract enforcement. needs the heavy module. - If a loader or registry change affects plugin authors, update the public SDK, docs, and contract tests instead of relying on incidental internals. +- Prefer explicit activation planning from manifest/descriptor ownership over + “load everything in this scope” behavior. Broad registry materialization + should be the exception, not the design center. - Do not normalize "plugin-owned" into "core-owned" by scattering direct reads of `plugins.entries..config` through unrelated core paths. Prefer generic helpers, plugin runtime hooks, manifest metadata, and explicit auto-enable @@ -52,6 +59,12 @@ assembly, and contract enforcement. - When a provider hook grows a nested chain of wrapper composition or repeated compat flags, treat that as a regression signal. Extract the shared helper or composer instead of letting one more plugin carry a near-copy. +- Treat mutable global runtime registry state as compatibility scaffolding, not + the desired source of truth for request-time execution. Prefer immutable or + request-scoped handles when adding new runtime flows. +- If setup, discovery, or doctor flows need plugin runtime, make that need + explicit and narrow. Do not let cold control-plane paths quietly import broad + runtime surfaces. ## Verification diff --git a/ui/AGENTS.md b/ui/AGENTS.md new file mode 100644 index 00000000000..765a89b9018 --- /dev/null +++ b/ui/AGENTS.md @@ -0,0 +1,19 @@ +# Control UI Guide + +This directory owns Control UI-specific guidance that should not live in the repo root. + +## i18n Rules + +- Foreign-language locale bundles in `ui/src/i18n/locales/*.ts` are generated output. +- Do not hand-edit non-English locale bundles or `ui/src/i18n/.i18n/*` unless a targeted generated-output fix is explicitly requested. +- The source of truth is `ui/src/i18n/locales/en.ts` plus the generator/runtime wiring in: + - `scripts/control-ui-i18n.ts` + - `ui/src/i18n/lib/types.ts` + - `ui/src/i18n/lib/registry.ts` +- Pipeline: update English strings and locale wiring here, then run `pnpm ui:i18n:sync` and commit the regenerated locale bundles plus `.i18n` metadata. +- If locale outputs drift, regenerate them. Do not manually translate or hand-maintain generated locale files by default. + +## Scope + +- Keep UI-specific rules here. +- Leave repo-global architecture, verification, and git workflow rules in the root `AGENTS.md`. diff --git a/ui/CLAUDE.md b/ui/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/ui/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file