diff --git a/rfcs/0016-claws.md b/rfcs/0016-claws.md index e19633e2..f2a2f123 100644 --- a/rfcs/0016-claws.md +++ b/rfcs/0016-claws.md @@ -3,9 +3,8 @@ title: Claws authors: - Gio created: 2026-07-03 -last_updated: 2026-07-19 +last_updated: 2026-08-12 status: draft -issue: rfc_pr: https://github.com/openclaw/rfcs/pull/27 --- @@ -30,9 +29,17 @@ remains agent configuration, and cron jobs remain Gateway scheduler records. The Claw owns their composition and lifecycle for the new agent; it does not replace the underlying owner surfaces. -The public lifecycle is `add`, `status`, `update`, `remove`, and `export`. -`add --dry-run` is the non-mutating preview. Artifact-level `install` and -`uninstall` remain the underlying operations for individual skills and plugins. +The public runtime lifecycle is `inspect`, `add`, `status`, `update`, `remove`, +and `export`. The public authoring lifecycle is `create`, `validate`, `dev`, and +`build`. `add --dry-run` and `dev` are non-mutating previews. Artifact-level +`install` and `uninstall` remain the underlying operations for individual +skills and plugins. + +OpenClaw's shipped Claws implementation is the reference behavior for this +contract. This RFC standardizes the portable package, authoring, and lifecycle +invariants around that working owner system. It does not transfer OpenClaw's +catalogs, runtime policy, rendering, publication, or review policy into a +central cross-harness owner. ## Motivation @@ -44,10 +51,10 @@ unrelated workspace. Adding a Claw always plans the following owned resources: -1. One new `agents.list[]` entry. +1. One new `agents.entries` member keyed by the final agent id. 2. One new workspace assigned to that agent. 3. Canonical bootstrap files and supporting files in that workspace. -4. Workspace skills and global plugin dependencies. +4. Workspace skills and exact shared plugin requirements. 5. Declared MCP servers in OpenClaw's top-level `mcp.servers` configuration. 6. Declared cron jobs stored in the Gateway scheduler and pinned to the new agent id. @@ -94,7 +101,7 @@ adopting or merging into an existing agent or managed workspace. - Embedding model, provider, thinking-level, authentication, or other operator-controlled runtime defaults. - Embedding channel account ids, group ids, credentials, or bindings. -- Setting `agents.list[].skills`; workspace-installed skills remain naturally +- Setting `agents.entries..skills`; workspace-installed skills remain naturally discoverable and must not replace inherited allowlists. - Defining a generic `connector` installation concept. Channel capabilities are supplied by normal channel plugins and configured or bound locally. @@ -116,11 +123,13 @@ principles. | Unit of ownership | One Claw describes exactly one new agent and its owned setup. | | Existing agents | `add` never merges into or updates an existing agent. Agent-id and workspace collisions fail closed. | | Lifecycle verb | The creation operation is `claws add`; `install` remains an artifact-level operation. | -| Public schema | The manifest uses grouped `agent`, `workspace`, `packages`, `mcpServers`, and `cronJobs` fields rather than a generic flat entry list. | +| Public schema | The manifest uses strict grouped `agent`, `metadata`, `workspace`, `packages`, `mcpServers`, and `cronJobs` fields rather than a generic flat entry list. | | Completeness | Every declared component is part of the Claw. Unsupported, blocked, or invalid components block `add`; there is no optional `required` flag. | | Package identity | Package name and version come from the enclosing package metadata and authenticated publish operation, following the ClawHub plugin precedent. | | Operator control | Models, providers, credentials, channel bindings, and local runtime defaults are not portable Claw settings. | -| Agent configuration | Only explicitly supported portable job settings can be copied into the new `agents.list[]` entry. | +| Agent configuration | Portable identity stays in `agent`; OpenClaw-specific operating policy stays in the strict conventional `profiles/openclaw.yml` sidecar. | +| Prompt | A non-whitespace `CLAW.md` body is the portable prompt; OpenClaw materializes it as managed `SOUL.md`. | +| First run | Package-root `BOOTSTRAP.md` is a seed-once native bootstrap input, not an ordinary managed workspace file. | | Skills | Skill packages install into the new agent's workspace and are discovered normally; the Claw does not set `agent.skills`. | | Plugins | Plugin packages use existing plugin installers, safety checks, enablement rules, and install records. | | Discovery and composition | Hosted feeds discover and govern plugin and skill packages; a Claw composes exact resolved package versions and direct MCP declarations rather than defining another catalog. | @@ -167,8 +176,12 @@ resources while retaining referenced resources by default. The implementer-facing package contract is captured in [`0016/claw-package-v1-spec.md`](0016/claw-package-v1-spec.md). The experimental human-readable envelope is captured separately in -[`0016/claw-md-v1-spec.md`](0016/claw-md-v1-spec.md). This RFC remains the -product rationale, ownership model, lifecycle, and rollout plan. +[`0016/claw-md-v1-spec.md`](0016/claw-md-v1-spec.md). OpenClaw's native profile +is captured in +[`0016/openclaw-profile-v1-spec.md`](0016/openclaw-profile-v1-spec.md), and the +authoring lifecycle is captured in +[`0016/claw-project-v1-spec.md`](0016/claw-project-v1-spec.md). This RFC remains +the product rationale, ownership model, lifecycle, and rollout plan. A published Claw follows the current ClawHub plugin precedent. Registry identity, version, and publisher ownership come from the enclosing package and the @@ -193,9 +206,12 @@ be inspected during development, but mutating local add must synthesize an explicit development identity and record its canonical source path and digest. The experimental implementation accepts the strict grouped JSON representation -and `CLAW.md`, in which YAML frontmatter carries the same typed manifest and the -Markdown body is documentation only. Export emits `CLAW.md`; JSON remains a -fully supported serialization of the same grouped schema. +and `CLAW.md`, in which YAML frontmatter carries the same typed manifest and a +non-whitespace Markdown body carries the portable agent prompt. OpenClaw +materializes that prompt as managed `SOUL.md`; grouped JSON expresses equivalent +behavior with an explicit `workspace.bootstrapFiles["SOUL.md"]` source. Export +emits `CLAW.md`; JSON remains a fully supported serialization of the same +grouped schema. Both representations are covered by the existing `OPENCLAW_EXPERIMENTAL_CLAWS=1` gate. `CLAW.md` adds only reader/export format @@ -221,38 +237,14 @@ The initial public shape is grouped by OpenClaw ownership boundary: "identity": { "name": "Triage", "emoji": "🔎" - }, - "groupChat": { - "mentionPatterns": ["@triage", "@github-triage"] - }, - "sandbox": { - "mode": "all", - "scope": "agent", - "workspaceAccess": "rw" - }, - "tools": { - "allow": ["read", "write", "edit", "web_fetch", "memory_search", "memory_get"], - "deny": ["exec", "browser", "nodes"] - }, - "heartbeat": { - "every": "30m", - "activeHours": { - "start": "08:00", - "end": "18:00" - }, - "lightContext": true, - "isolatedSession": true, - "skipWhenBusy": true, - "timeoutSeconds": 120 - }, - "humanDelay": { - "mode": "natural" } }, + "metadata": { + "com.acme.category": "developer-productivity" + }, "workspace": { "bootstrapFiles": { "AGENTS.md": { "source": "workspace/AGENTS.md" }, - "SOUL.md": { "source": "workspace/SOUL.md" }, "IDENTITY.md": { "source": "workspace/IDENTITY.md" }, "TOOLS.md": { "source": "workspace/TOOLS.md" }, "HEARTBEAT.md": { "source": "workspace/HEARTBEAT.md" } @@ -270,12 +262,6 @@ The initial public shape is grouped by OpenClaw ownership boundary: "source": "clawhub", "ref": "@acme/issue-triage-playbook", "version": "1.4.0" - }, - { - "kind": "plugin", - "source": "clawhub", - "ref": "@acme/github-actions", - "version": "2.1.0" } ], "mcpServers": { @@ -312,8 +298,9 @@ The initial public shape is grouped by OpenClaw ownership boundary: } ``` -The schema version 1 field set, validation rules, JSON representation, and -`CLAW.md` envelope are normative for the experimental implementation. +The schema version 1 field set, validation rules, JSON representation, +`CLAW.md` envelope, conventional OpenClaw profile, package-root bootstrap, and +project lifecycle are normative for the experimental implementation. Implementation slices may land separately behind the experimental gate, but a producer or consumer must not claim schema v1 conformance until it implements the complete grouped data model. Version 1 is strict: new portable fields, @@ -325,17 +312,30 @@ component and still call the agent complete. ### Agent settings boundary -Portable agent settings describe the job and its safe operating posture. The -initial allowlist should be drawn from existing OpenClaw agent configuration and -can include: - -- `id`, `name`, and `description`; -- agent identity presentation; -- group-chat mention patterns; -- sandbox boundaries; -- tool allow and deny policy; -- heartbeat behavior; -- human-delay behavior. +The portable `agent` object contains only `id`, `name`, `description`, and +identity presentation. OpenClaw-specific operating posture belongs in the +optional strict package file `profiles/openclaw.yml`, which may contain: + +- group-chat mention patterns and sandbox boundaries; +- a registered built-in tool profile plus bounded `allow` or `alsoAllow`, + `deny`, and restrictive `fs.workspaceOnly` policy; +- memory-search enablement, explicit cross-conversation memory opt-in, and the + `memory` and `sessions` sources; +- heartbeat and human-delay behavior; and +- exact native extension requirements delegated to the canonical plugin owner. + +The profile is required to contain `schemaVersion: 1` and `agent`, which may be +an empty object. OpenClaw discovers `profiles/openclaw.yml` conventionally, +validates it strictly, and binds its bytes into source integrity. Absence means +inherited OpenClaw defaults. + +For shipped compatibility, `metadata` is an optional string-to-string map that +defaults to empty. Unknown keys are opaque descriptive hints. The legacy +`metadata.openclaw.config` key may point to a safe package-relative YAML profile +and is accepted with a deprecation warning; it must not conflict with a +different conventional `profiles/openclaw.yml`. Canonical producers must omit +that pointer and use the conventional path. No other metadata key changes +runtime behavior or carries executable configuration. The following remain operator controlled and are rejected in a Claw manifest: @@ -344,14 +344,61 @@ The following remain operator controlled and are rejected in a Claw manifest: - channel account ids, group ids, and bindings; - default-agent selection and global `agents.defaults`; - `agent.skills` allowlists; -- arbitrary config fragments or unknown future agent fields. +- arbitrary config fragments, custom tool profiles, memory provider/storage + tuning, or unknown future agent fields. + +The generated `agents.entries` member inherits operator defaults. Add inserts +one member keyed by the final agent id and does not rewrite existing entries or +defaults. + +For example, the package may include this strict `profiles/openclaw.yml`: + +```yaml +schemaVersion: 1 +agent: + groupChat: + mentionPatterns: ["@triage", "@github-triage"] + sandbox: + mode: all + scope: agent + workspaceAccess: rw + tools: + allow: [read, write, web_fetch] + deny: [exec, browser, nodes] + fs: + workspaceOnly: true + memory: + search: + enabled: true + rememberAcrossConversations: true + sources: [memory, sessions] + heartbeat: + every: 30m + activeHours: + start: "08:00" + end: "18:00" + lightContext: true + isolatedSession: true + timeoutSeconds: 120 + humanDelay: + mode: natural +extensions: + - id: github-actions + kind: plugin + format: openclaw + source: clawhub + ref: "@acme/github-actions" + version: 2.1.0 +``` -The generated `agents.list[]` entry inherits operator defaults. Add appends one -entry and does not rewrite existing list members or defaults. +Every field above is accepted by the shipped strict profile schema. Heartbeat +supports only the fields listed in the profile sidecar; unknown busy-state +policy is rejected. A bounded `tools.allow` without a profile is valid. +`profile: full` requires a bounded `allow`; profiles whose resolved policy +contains an unbounded dynamic selector must be narrowed to concrete tool names. -For example, adding the illustrative manifest above with local agent id -`github-triage` appends an agent entry while preserving the operator's current -defaults and agents: +Adding the illustrative package with local agent id `github-triage` appends an +agent entry while preserving the operator's current defaults and agents: ```jsonc { @@ -359,13 +406,9 @@ defaults and agents: "defaults": { // Existing operator-owned defaults remain unchanged. }, - "list": [ - { - "id": "main", - "default": true - }, - { - "id": "github-triage", + "entries": { + "main": {}, + "github-triage": { "name": "GitHub Triage", "description": "Reviews incoming GitHub issues and prepares a daily triage summary.", "workspace": "~/.openclaw/workspace-github-triage", @@ -382,8 +425,19 @@ defaults and agents: "workspaceAccess": "rw" }, "tools": { - "allow": ["read", "write", "edit", "web_fetch", "memory_search", "memory_get"], - "deny": ["exec", "browser", "nodes"] + "profile": "full", + "allow": ["read", "write", "web_fetch"], + "deny": ["exec", "browser", "nodes"], + "fs": { + "workspaceOnly": true + } + }, + "memory": { + "search": { + "enabled": true, + "rememberAcrossConversations": true, + "sources": ["memory", "sessions"] + } }, "heartbeat": { "every": "30m", @@ -393,14 +447,13 @@ defaults and agents: }, "lightContext": true, "isolatedSession": true, - "skipWhenBusy": true, "timeoutSeconds": 120 }, "humanDelay": { "mode": "natural" } } - ] + } }, "plugins": { "entries": { @@ -439,6 +492,20 @@ existing agent workspace or a Claw-managed workspace. content belongs in `workspace.files` with explicit package-relative source and workspace-relative destination paths. +For `CLAW.md`, a non-whitespace Markdown body is an implicit managed `SOUL.md` +source. Its exact bytes participate in source integrity; its digest and action, +not prompt text, appear in the default plan. A package must not combine that +body with an explicit destination equal to, beneath, or containing `SOUL.md`. +Whitespace-only bodies create no implicit file. Markdown headings have no +command semantics. + +An optional package-root `BOOTSTRAP.md` is a seed-once input to OpenClaw's +existing first-run bootstrap owner. It is not ordinary managed workspace +content. Expected consumption and deletion are not drift; update never +recreates it, and remove may delete only a still-pending, digest-identical seed. +User-owned interview output is preserved. Ordinary workspace declarations must +not target root `BOOTSTRAP.md` or a colliding ancestor or descendant. + All paths must remain within the unpacked Claw package or the new agent workspace after realpath resolution. Symlink, hardlink, device-file, oversized, and traversal escapes fail closed. The dry-run shows each source, destination, @@ -457,7 +524,7 @@ exact version, or unsupported source blocks the complete add. Skill packages install into the new agent workspace through existing skill installers. They are discovered from the workspace normally. Add must not set -`agents.list[].skills`. +`agents.entries..skills`. Plugin packages install through existing plugin installers and safety checks. Plugin artifacts can be shared with direct user installs or other Claws. Claw @@ -470,9 +537,12 @@ releases dependency edges and retains shared artifacts. The remove plan must offer explicit cleanup choices for referenced artifacts: 1. `retain` releases only this Claw's dependency edge and is the default. -2. `remove-if-unused` invokes the canonical artifact lifecycle only when no +2. `remove-if-unused` applies only to shared skill artifacts and invokes the + canonical artifact lifecycle only when no other Claw dependency edge or known non-Claw owner remains and the artifact - is complete, unchanged, and unambiguous. + is complete, unchanged, and unambiguous. Global plugins and profile + extensions are excluded; plugin uninstall remains a separately selected + canonical plugin-owner action. 3. `remove-selected` invokes canonical removal for artifacts explicitly chosen by the operator. It must show every known affected Claw and direct owner and require stronger confirmation when dependencies remain. @@ -523,7 +593,8 @@ is not a Claw package dependency, hosted-feed entry, or provenance key. Heartbeat and cron jobs are distinct existing OpenClaw concepts: -- `agent.heartbeat` controls when and how the new agent wakes. +- `profiles/openclaw.yml` `agent.heartbeat` controls when and how the new agent + wakes. - `workspace.bootstrapFiles["HEARTBEAT.md"]` contains what the agent checks. - `cronJobs` contains exact scheduled jobs stored by the Gateway scheduler. @@ -543,7 +614,7 @@ the new agent to local channels separately. #### Experimental incubation gate -While this RFC remains draft, every Claws CLI surface is gated behind the +While Claws remain experimental, every Claws CLI surface is gated behind the process-level opt-in `OPENCLAW_EXPERIMENTAL_CLAWS=1`. When the gate is absent or false: @@ -569,7 +640,7 @@ silently carried into later releases or fleet config. When enabled, text-mode commands print a concise experimental compatibility warning before mutation, and machine-readable results include `stability: "experimental"` plus their exact output schema version. During the -draft period, the manifest schema, CLI flags, JSON result shapes, and SQLite +experimental period, CLI flags, JSON result shapes, and SQLite tables may change without backward-compatibility guarantees. Destructive commands still require their normal explicit consent; the experimental gate is not consent and does not weaken any safety check. @@ -582,6 +653,10 @@ does not itself establish those contracts. The public CLI is: ```bash +openclaw claws create [path] [--name ] [--agent-id ] +openclaw claws validate [path] +openclaw claws dev [path] [--agent-id ] [--workspace ] +openclaw claws build [path] --out openclaw claws inspect openclaw claws add --dry-run --json openclaw claws add [--agent-id ] [--workspace ] --yes --plan-integrity @@ -593,8 +668,19 @@ openclaw claws remove --yes --plan-integrity [cleanup s openclaw claws export --out ``` -`inspect` validates package metadata and the grouped manifest without reading or -mutating local lifecycle state. `add --dry-run` resolves the final agent id, +`create` writes a minimal valid `package.json` and `CLAW.md` into an absent or +empty directory without installing or applying anything. `validate` discovers +one project root and validates the exact selected package inputs without +mutation. `build` validates and creates a deterministic, no-overwrite `.tgz` +artifact containing only selected package inputs, then reopens it through the +canonical reader. `dev` validates, builds a temporary artifact, and runs the +canonical add planner offline without mutation, delivery, network execution, or +durable Claw state. The exact project contract is in +[`0016/claw-project-v1-spec.md`](0016/claw-project-v1-spec.md). + +`inspect` validates package metadata, the grouped manifest, optional native +bootstrap, and the recognized conventional profile without reading or mutating +local lifecycle state. `add --dry-run` resolves the final agent id, workspace, packages, MCP servers, and cron jobs and emits the complete action plan. `add` without `--dry-run` requires `--yes` and the exact `--plan-integrity` digest from that dry run. Update uses the source recorded in @@ -606,16 +692,21 @@ the choice is included in the plan digest. `--yes` alone never broadens a plan. Add ordering is transactional where owner APIs permit it and resumable where external installers or the scheduler cannot share one transaction: -1. Validate package metadata and manifest. +1. Validate package metadata, manifest, optional package-root bootstrap, and + recognized conventional profile. 2. Resolve exact dependencies and run install safety checks. 3. Resolve the final unused agent id and workspace. 4. Preflight all config, file, MCP, and cron collisions. -5. Create the agent entry and workspace state. -6. Write bootstrap and supporting files. -7. Install workspace skills and plugin dependencies. -8. Configure MCP servers. -9. Create agent-pinned cron jobs. -10. Persist one complete apply record and per-resource provenance. +5. Install exact shared extension requirements through the canonical plugin + owner. +6. Create the agent entry and workspace state. +7. Seed native `BOOTSTRAP.md` when present and write managed files, including + body-sourced `SOUL.md`. +8. Apply the strict OpenClaw profile and install exact workspace skill + requirements through canonical owners. +9. Configure MCP servers. +10. Create agent-pinned cron jobs. +11. Persist one complete apply record and per-resource provenance. Any failure stops later phases. Pending provenance is written before external mutation and successful resources are recorded immediately. Safe local @@ -735,7 +826,7 @@ must share the schema and fixtures rather than maintain divergent validators. - MCP config writes use validated, concurrent-write-safe config APIs. - Cron jobs require explicit consent, visible cadence/action previews, stable ownership, live-definition revalidation, and disable/remove handles. -- Config mutation preserves `agents.defaults`, existing `agents.list[]` entries, +- Config mutation preserves `agents.defaults`, existing `agents.entries` members, channel bindings, and unrelated plugin/MCP settings. - Partial adds persist enough state for diagnosis and cleanup. - Update and remove revalidate expected presence, content/config digests, and @@ -753,8 +844,8 @@ must share the schema and fixtures rather than maintain divergent validators. `acknowledge` parameter must not make the warning disappear from preview. - Claws do not introduce capability-specific resource quotas. Existing canonical owner limits apply. Claw manifests are limited to 1 MiB and package - metadata to 256 KiB; extraction, managed workspace, and plan limits remain - parser and resource-safety policy. + metadata and OpenClaw profiles to 256 KiB each; native bootstrap, extraction, + managed workspace, and plan limits remain parser and resource-safety policy. ## Rationale @@ -776,17 +867,18 @@ The earlier prototype used `openclaw.claw.v1`, a flat `entries[]` list, and `claws apply` against a caller-selected workspace. That prototype is not the accepted public compatibility contract. Before any implementation PR is made ready, it must be restacked around the grouped schema and one-new-agent -invariant. Prototype SQLite tables may be discarded or migrated during the -draft phase; no released migration promise exists until the RFC is accepted. +invariant. Prototype SQLite tables may be discarded or migrated while the feature remains +experimental; the released migration promise is set when the gate is removed. ## Rollout plan Implementation should widen the trust boundary in reviewable slices: -1. **Schema and read-only plan.** Parse package metadata and grouped manifests; - implement `inspect` and `add --dry-run`; prove agent/workspace collision - behavior and complete blockers without mutation. -2. **Agent and workspace creation.** Add one `agents.list[]` entry, derive a new +1. **Schema and read-only plan.** Parse package metadata, grouped manifests, + conventional profiles, and optional native bootstrap; implement `inspect` + and `add --dry-run`; prove agent/workspace collision behavior and complete + blockers without mutation. +2. **Agent and workspace creation.** Add one `agents.entries` member, derive a new workspace, preserve defaults and existing agents, and persist the root apply record. 3. **Workspace bootstrap and supporting files.** Add confined file writes, @@ -796,7 +888,7 @@ Implementation should widen the trust boundary in reviewable slices: uninstall when Claws reference an artifact. 5. **MCP servers.** Add validated top-level MCP configuration, collision checks, redacted digest provenance, status, and cleanup. -6. **Heartbeat and cron jobs.** Apply portable heartbeat config and create +6. **Heartbeat and cron jobs.** Apply OpenClaw profile heartbeat config and create scheduler records pinned to the new agent id with status/disable/remove proof. 7. **Status, doctor, and remove.** Diagnose complete and partial agents, drift, orphaned resources, and conservative cleanup. @@ -807,145 +899,82 @@ Implementation should widen the trust boundary in reviewable slices: 10. **ClawHub publication and feeds.** Share schema fixtures, publish a package, expose it through hosted feeds, and prove source resolution and add dry-run. -### Current OpenClaw implementation stack - -The experimental implementation is one RFC plus twelve ordered OpenClaw PRs. Each -implementation PR is based on the preceding head so reviewers can evaluate one -ownership boundary at a time: - -1. [#101328](https://github.com/openclaw/openclaw/pull/101328) - grouped schema, - inspect, and read-only add planning. -2. [#101755](https://github.com/openclaw/openclaw/pull/101755) - new agent, - workspace root, and root install provenance. -3. [#101973](https://github.com/openclaw/openclaw/pull/101973) - managed - workspace bootstrap and supporting files. -4. [#102228](https://github.com/openclaw/openclaw/pull/102228) - exact ClawHub - skill/plugin installation and shared uninstall-reference warnings. -5. [#102296](https://github.com/openclaw/openclaw/pull/102296) - plan-first - status and conservative remove. -6. [#102306](https://github.com/openclaw/openclaw/pull/102306) - agent-centric - grouped export. -7. [#102383](https://github.com/openclaw/openclaw/pull/102383) - Gateway-owned - cron jobs and scheduler provenance. -8. [#102406](https://github.com/openclaw/openclaw/pull/102406) - stdio and remote - MCP ownership, including credential-free OAuth intent. -9. [#102427](https://github.com/openclaw/openclaw/pull/102427) - lifecycle and - drift diagnostics. -10. [#102959](https://github.com/openclaw/openclaw/pull/102959) - read-only - grouped update planning. -11. [#102982](https://github.com/openclaw/openclaw/pull/102982) - consented - grouped update apply and compensation. -12. [#111391](https://github.com/openclaw/openclaw/pull/111391) - thin - `CLAW.md` YAML-frontmatter input/export adaptation with grouped JSON read - compatibility and no separate lifecycle behavior. It supersedes #106888, - which was merged only into an obsolete stack head. - -Public documentation follows the same staged boundary as the implementation. -#101328 introduces the experimental guide, navigation, opt-in, schema, inspect, -and add preview. Each later PR extends that guide only with the command or -resource behavior implemented at that stage. #111391 adds only `CLAW.md` -authoring and canonical export documentation. At every intermediate stack head, -the guide must describe no later command or ownership behavior. - -These PRs replace the old workspace-apply prototype rather than -extending its compatibility contract. Every experimental CLI PR remains behind -`OPENCLAW_EXPERIMENTAL_CLAWS=1`; command registration, help, completion, and -direct-handler tests must prove the disabled state as well as the enabled state. - -### Current ClawHub implementation stack - -ClawHub follows the OpenClaw schema and lifecycle contract in four ordered PRs: - -1. [#3089](https://github.com/openclaw/clawhub/pull/3089) - shared manifest - validation, derived summaries, and storage data model. Existing generic - publication remains closed to Claws. -2. [#3090](https://github.com/openclaw/clawhub/pull/3090) - guarded publication, - package ingestion, source-file checks, CLI authoring support, and author - guidance. It also owns the fail-closed public-read boundary while disabled - and strips full manifests from every public release serializer. Publication - retains the exact immutable artifact bytes and bounded summary, validates - every package path, requires exact manifest/source spelling, applies strict - UTF-8 and pre-parse size limits, and accepts Claw npm packs without requiring - a plugin manifest. -3. [#3091](https://github.com/openclaw/clawhub/pull/3091) - enabled search, - detail, and version APIs that expose only the latest or requested release's - bounded summary. -4. [#3092](https://github.com/openclaw/clawhub/pull/3092) - separately gated - hosted Claw feed with its own experimental wire contract, safe summaries, - and exact artifact digests, plus a repeatable published-package proof through - real OpenClaw add dry-run. The versioned route is gated before publication - lookup and has no ungated unversioned redirect. The proof bounds download, - entry count, per-file and aggregate expansion; rejects unsafe or colliding - paths, links, and special archive entries; and supports npm-pack and legacy - ZIP package roots. - -The #3092 proof is a registry-to-OpenClaw bridge: it selects an exact candidate -from the experimental Claw feed, verifies and extracts the artifact, then hands -the package directory to OpenClaw. It proves that the published package produces -a real non-mutating OpenClaw plan; native OpenClaw Claw-feed resolution remains -a separate dependent integration. - -The ClawHub runtime surfaces in this track require -`CLAWHUB_EXPERIMENTAL_CLAWS=1`. The deployment gate is independent of -`OPENCLAW_EXPERIMENTAL_CLAWS=1` in the OpenClaw client and is not a replacement -for explicit add/update consent. - -The experimental ClawHub contract accepts both `CLAW.md` and the equivalent -grouped JSON manifest behind `CLAWHUB_EXPERIMENTAL_CLAWS=1`; it does not add a -second format-specific gate. Search, detail, and feed APIs expose bounded -summaries and immutable artifact coordinates; the applying client reviews the -full declaration from the resolved artifact. +### Implementation authority and consolidation + +The implementation authority for this reconciliation is shipped OpenClaw Claws +at baseline `f8c0e1b8325b`. The portable contract follows its strict +schema, conventional profile, prompt/body mapping, native bootstrap behavior, +extension ownership, project commands, and lifecycle tests. Owner-specific +catalog, UI, plugin-mapping, policy, and publication decisions remain with +OpenClaw and ClawHub rather than becoming portable schema. + +This consolidation incorporates the useful normative content of the closed +fragmented RFC drafts: + +- [RFC PR #52](https://github.com/openclaw/rfcs/pull/52), application + composition, native bootstrap, extensions, and clients; and +- [RFC PR #56](https://github.com/openclaw/rfcs/pull/56), project authoring and + deterministic build lifecycle. + +Their useful normative content is incorporated here and in the organized RFC +0016 sidecars. Their independent RFC numbers, draft metadata, dependency +markers, and implementation-stack inventories are not part of this contract. ## Acceptance criteria The RFC implementation is acceptable when tests and real CLI proof demonstrate: -1. Inspect validates package identity and the grouped manifest without mutation. -2. Without `OPENCLAW_EXPERIMENTAL_CLAWS=1`, the `claws` command is unregistered, +1. Create produces a minimal project that validate accepts offline; validate, + dev, and build are read-only outside their declared project/artifact outputs. +2. Inspect validates package identity, the grouped manifest, recognized + conventional profile, and optional package-root bootstrap without mutation. +3. Without `OPENCLAW_EXPERIMENTAL_CLAWS=1`, the `claws` command is unregistered, absent from help and completions, and cannot be enabled by package content; the public experimental guide remains non-executable documentation. -3. Add dry-run shows one new agent, one new workspace, every file/package/MCP/ +4. Add dry-run shows one new agent, one new workspace, every file/package/MCP/ cron action, all collisions, and stable machine-readable blockers. -4. An existing agent id or workspace blocks add unless an explicit unused +5. An existing agent id or workspace blocks add unless an explicit unused override is supplied. -5. Add appends one agent without changing defaults or existing agents. -6. Canonical and supporting files are confined to the new workspace. -7. Skills install into that workspace without setting `agent.skills`. -8. Plugins use existing safety checks and preserve shared/direct ownership; +6. Add appends one agent without changing defaults or existing agents. +7. Canonical and supporting files are confined to the new workspace. +8. Skills install into that workspace without setting `agent.skills`. +9. Plugins use existing safety checks and preserve shared/direct ownership; CLI, Gateway, and Control UI uninstall paths all emit Claw-reference warnings through the shared lifecycle owner. -9. Portable stdio and remote MCP declarations write only validated top-level +10. Portable stdio and remote MCP declarations write only validated top-level config, store no secrets or completed OAuth state in provenance, and do not depend on a feed-backed connector identity. -10. Cron jobs are scheduler records pinned to the final local agent id. -11. Any declared unsupported or blocked component fails the complete add. -12. Partial failures remain visible and cleanable; they are not reported as a +11. Cron jobs are scheduler records pinned to the final local agent id. +12. Any declared unsupported or blocked component fails the complete add. +13. Partial failures remain visible and cleanable; they are not reported as a successfully added Claw. -13. Status and doctor explain agent, workspace, package, MCP, cron, and managed +14. Status and doctor explain agent, workspace, package, MCP, cron, and managed file drift. -14. Update changes only Claw-owned state, preserves local/operator edits, +15. Update changes only Claw-owned state, preserves local/operator edits, revalidates owner state before mutation, compensates only safely reversible completed owners, retains uncertain provenance, and reports uncertain or irreversible outcomes as partial. -15. Remove uses canonical owner lifecycles, selects managed resources for +16. Remove uses canonical owner lifecycles, selects managed resources for cleanup, retains referenced resources by default, offers integrity-bound `remove-if-unused` and explicitly selected referenced cleanup, warns about every known affected Claw or direct owner, and preserves modified or unrelated state. -16. Export emits `CLAW.md`, excludes secrets and operator runtime settings, +17. Export emits `CLAW.md`, excludes secrets and operator runtime settings, retains grouped JSON read compatibility, and can be added in a fresh state directory as a new equivalent agent. -17. Feed approval does not bypass dependency policy or install safety checks. -18. Every implementation stage documents its newly available surface without - claiming commands or ownership behavior from a later stage. -19. Add and update plans disclose capability escalations separately from +18. Feed approval does not bypass dependency policy or install safety checks. +19. Schema-v1 metadata accepts an opaque string map, preserves the deprecated + shipped OpenClaw profile pointer with a warning, and gives no runtime + semantics to other unknown keys. +20. A non-whitespace `CLAW.md` body is managed `SOUL.md`; package-root + `BOOTSTRAP.md` is seed-once native state; profiles, memory settings, and + native extensions follow their strict sidecar contracts. +21. Add and update plans disclose capability escalations separately from ordinary content, include them in plan integrity, and reject mutation when the reviewed capability set changes. ## Unresolved questions -- Before removing the experimental gate, should `CLAW.md` remain the default - authoring/export representation or should export return to grouped JSON? - What exact default workspace naming rule should resolve cross-platform path and case-folding collisions? - Should ordinary `agents delete` eventually delegate attached-Claw recurring @@ -957,7 +986,7 @@ The RFC implementation is acceptable when tests and real CLI proof demonstrate: bindings? - What package transports should mutating v1 support beyond ClawHub and local development packages? -- What is the minimum released SQLite migration contract before Claws leave - draft status? -- How should OpenClaw and ClawHub publish and version one shared schema and - fixture suite? +- What released SQLite migration contract is required before the experimental + gate is removed? +- How should OpenClaw and ClawHub publish and version shared conformance + fixtures without transferring either product's policy ownership? diff --git a/rfcs/0016/claw-md-v1-spec.md b/rfcs/0016/claw-md-v1-spec.md index 0e4f395e..da159d41 100644 --- a/rfcs/0016/claw-md-v1-spec.md +++ b/rfcs/0016/claw-md-v1-spec.md @@ -5,7 +5,7 @@ Claws. The RFC explains the product model, ownership boundaries, lifecycle, and rollout plan. This file defines the schema version 1 data contract shared by OpenClaw and Claw registries and its human-readable `CLAW.md` envelope. -Status: experimental draft, tied to RFC 0016. +Status: draft experimental contract, tied to RFC 0016. ## Incubation Status @@ -13,12 +13,10 @@ The experimental implementation reads `CLAW.md` and equivalent grouped JSON, and exports `CLAW.md`. Both forms use the existing `OPENCLAW_EXPERIMENTAL_CLAWS=1` gate; there is no format-specific flag. -`CLAW.md` is intentionally a thin serialization layer over the grouped schema. -It does not define separate lifecycle, ownership, provenance, or capability -semantics and introduces no new runtime dependency. Until the Claws gate is -removed, maintainers may revise or remove this envelope without preserving it -as a stable compatibility contract. Feedback remains welcome on the YAML -frontmatter boundary, Markdown-body role, portability, and authoring ergonomics. +`CLAW.md` is a portable prompt envelope over the grouped schema. A +non-whitespace body maps to the harness's managed agent-instruction primitive; +OpenClaw maps it to managed `SOUL.md`. This adds no separate lifecycle, +ownership, provenance, or capability semantics. ## Scope @@ -46,8 +44,8 @@ The enclosing package contract is defined by ## Design Goals `CLAW.md` is intended to be understandable in a code review while remaining a -strict input to lifecycle tooling. Its Markdown body can explain the agent to a -human. Its YAML frontmatter is the only executable declaration. +strict input to lifecycle tooling. Its Markdown body is the portable agent +prompt. Its YAML frontmatter carries typed resources and identity. The same data model may also be represented as JSON. Markdown and JSON are two serializations of one schema, not different capability levels. @@ -86,11 +84,12 @@ The following rules apply: 2. The opening delimiter must be followed by LF or CRLF. 3. The YAML frontmatter ends at the next line containing exactly `---`. 4. The closing delimiter must be followed by LF, CRLF, or end of file. -5. The Markdown body after the closing delimiter is documentation only. A - consumer must not derive runtime behavior, package dependencies, policy, or - lifecycle actions from it. -6. Producers should include a short heading and description in the Markdown - body, but consumers must accept an empty body. +5. A body containing at least one non-whitespace character is the portable + agent prompt. Consumers preserve its complete UTF-8 bytes when materializing + the managed instruction file. +6. OpenClaw maps that body to `SOUL.md`. An empty or whitespace-only body + creates no implicit file. +7. Markdown structure has no command, package, policy, or lifecycle semantics. ## YAML Conversion @@ -122,7 +121,8 @@ The top-level value must be an object with these fields: | Field | Type | Required | Semantics | | --- | --- | --- | --- | | `schemaVersion` | integer | Yes | Must be exactly `1`. | -| `agent` | object | Yes | Portable configuration for the one new agent. | +| `agent` | object | Yes | Portable identity for the one new agent. | +| `metadata` | string map | No | Portable descriptive hints. Defaults to empty. | | `workspace` | object | No | Bootstrap and supporting files. Defaults to empty. | | `packages` | array | No | Exact skill and plugin dependencies. Defaults to empty. | | `mcpServers` | object | No | Portable MCP declarations keyed by server name. Defaults to empty. | @@ -138,6 +138,22 @@ prevents package authors from claiming deletion authority over pre-existing or shared host resources. Operator-selected referenced cleanup is remove-plan input, not portable package content. +## Metadata and Harness Profiles + +`metadata` is a string-to-string map. Unknown keys are opaque descriptive hints +and must not be interpreted as executable configuration. Canonical producers +use globally unique or namespaced keys. + +The shipped compatibility key `metadata.openclaw.config` may point to a safe +package-relative `.yml` or `.yaml` OpenClaw profile. OpenClaw accepts it with a +deprecation warning. It must not conflict with a different conventional +`profiles/openclaw.yml`. Canonical producers omit the key and use the +conventional path. + +Harness profiles are package sidecars, not nested manifest values. OpenClaw +recognizes `profiles/openclaw.yml` and binds its exact bytes into source +integrity. Consumers do not reinterpret another harness's profile. + ## Agent `agent.id` is required. It must start with a lowercase ASCII letter, contain @@ -145,7 +161,7 @@ only lowercase ASCII letters, digits, `_`, or `-`, and contain at most 64 characters. It is the default local id; add still fails if that id or its derived workspace is already in use. -The portable agent object is: +The strict portable agent object is: | Field | Type | Required | Constraints | | --- | --- | --- | --- | @@ -156,36 +172,9 @@ The portable agent object is: | `identity.theme` | string | No | Non-empty after trimming. | | `identity.emoji` | string | No | Non-empty after trimming. | | `identity.avatar` | string | No | Non-empty portable avatar described below. | -| `groupChat.mentionPatterns` | string array | No | At least one non-empty string when present. | -| `sandbox.mode` | enum | No | `off`, `non-main`, or `all`. | -| `sandbox.scope` | enum | No | `session`, `agent`, or `shared`. | -| `sandbox.workspaceAccess` | enum | No | `none`, `ro`, or `rw`. | -| `tools.allow` | string array | No | At least one non-empty string when present. | -| `tools.deny` | string array | No | At least one non-empty string when present. | -| `heartbeat` | object | No | Exact portable heartbeat object below. | -| `humanDelay` | object | No | Exact portable human-delay object below. | - -All objects are strict. Consumers may accept empty optional objects, but -canonical producers must omit an optional object when none of its members are -present. - -`heartbeat` may contain only: - -| Field | Type | Constraints | -| --- | --- | --- | -| `every` | string | A non-negative OpenClaw duration using `ms`, `s`, `m`, `h`, or `d`; composite forms such as `1h30m` are allowed and a bare number means minutes. | -| `activeHours.start` | string | `HH:MM` in 24-hour form from `00:00` through `23:59`. | -| `activeHours.end` | string | `HH:MM` in 24-hour form from `00:00` through `24:00`; no other `24:xx` value is valid. | -| `activeHours.timezone` | string | Non-empty IANA timezone recognized by the scheduler. | -| `lightContext` | boolean | No additional constraint. | -| `isolatedSession` | boolean | No additional constraint. | -| `skipWhenBusy` | boolean | No additional constraint. | -| `timeoutSeconds` | integer | Greater than zero. | - -`humanDelay` may contain only `mode`, `minMs`, and `maxMs`. `mode`, when -present, is `off`, `natural`, or `custom`. The millisecond values are optional -non-negative integers. Version 1 imposes no relationship between them; runtime -behavior uses the declared values only when the selected mode requires them. +Runtime policy, tools, memory, heartbeat, delay, credentials, bindings, and +provider configuration are not portable `agent` fields. OpenClaw settings use +[`openclaw-profile-v1-spec.md`](openclaw-profile-v1-spec.md). `identity.avatar` may be an image data URL no larger than 2 MiB decoded or 2,796,230 characters encoded, or a workspace-relative path with a `.png`, @@ -212,6 +201,18 @@ sources. The only v1 keys are: - `TOOLS.md` - `HEARTBEAT.md` +In `CLAW.md`, a non-whitespace body implicitly targets `SOUL.md`. A manifest +with such a body must not also declare a destination equal to, beneath, or +containing `SOUL.md` under portable collision rules. Grouped JSON has no body +and uses an explicit `SOUL.md` source for equivalent behavior. + +Package-root `BOOTSTRAP.md` is separate from this map. It is a seed-once +first-run input handled by the harness's native bootstrap owner. OpenClaw treats +expected consumption as success, never recreates it during update, removes only +a still-pending digest-identical seed, and preserves user-owned interview +output. Ordinary workspace declarations must not target root `BOOTSTRAP.md` or +a colliding ancestor or descendant. + Each value has one required `source` field. `workspace.files` contains objects with required `source` and `path` fields. `source` is relative to the package root; `path` is relative to the new agent workspace. @@ -340,17 +341,12 @@ agent: id: github-triage name: GitHub Triage description: Reviews incoming issues and prepares a daily summary. - tools: - allow: [read, write, web_fetch] - deny: [exec] - heartbeat: - every: 30m +metadata: + com.acme.category: developer-productivity workspace: bootstrapFiles: AGENTS.md: source: workspace/AGENTS.md - SOUL.md: - source: workspace/SOUL.md files: - source: workspace/reference/triage-policy.md path: reference/triage-policy.md @@ -383,15 +379,37 @@ cronJobs: # GitHub Triage -Adds one GitHub triage agent and the reviewed resources it needs. +You review incoming GitHub issues, identify severity and ownership, and prepare +concise evidence-backed handoffs. +``` + +The same package may include `profiles/openclaw.yml`: + +```yaml +schemaVersion: 1 +agent: + tools: + allow: [read, write, web_fetch] + deny: [exec] + fs: + workspaceOnly: true + memory: + search: + enabled: true + rememberAcrossConversations: true + sources: [memory, sessions] + heartbeat: + every: 30m ``` ## JSON Compatibility The package contract may point `openclaw.claw` at a JSON file containing the grouped top-level object. JSON input passes through the same strict schema, -defaults, diagnostics, and lifecycle. `CLAW.md` and JSON are two serializations -of the same schema version, not different capability levels. +defaults, diagnostics, and lifecycle. `CLAW.md` and JSON carry the same portable +capability level. JSON represents the body prompt through an explicit +`SOUL.md` workspace source. Both forms use the same conventionally discovered +harness profile. ## Compatibility and Evolution @@ -425,7 +443,13 @@ A conforming consumer must: - reject duplicate YAML keys and unknown schema fields; - validate all identifiers, exact versions, paths, environment references, cron expressions, timezones, and uniqueness constraints; -- ignore the Markdown body for runtime behavior; +- treat unknown metadata keys as opaque strings and support the deprecated + shipped OpenClaw profile pointer as specified; +- map a non-whitespace Markdown body to the managed instruction primitive, + using `SOUL.md` in OpenClaw; +- reject body conflicts with explicit `SOUL.md` destinations; +- discover and strictly validate the recognized conventional harness profile; +- treat package-root `BOOTSTRAP.md` as seed-once native first-run state; - preserve original bytes for integrity calculations; - reject a `CLAW.md` file larger than 1 MiB before parsing, including when it grows during the read; @@ -443,6 +467,9 @@ A conforming producer must: - keep all referenced workspace sources inside the enclosing package; - use exact package and package-manager dependency versions and explicit cron timezones; -- place human explanation, not executable declarations, in the Markdown body; +- place the portable agent prompt in the Markdown body and avoid a duplicate + explicit `SOUL.md` source; - exclude credentials and operator-owned runtime choices; +- place supported OpenClaw settings in `profiles/openclaw.yml`; +- emit package-root `BOOTSTRAP.md` only for seed-once conversational setup; - validate the result against this specification before publication or export. diff --git a/rfcs/0016/claw-package-v1-spec.md b/rfcs/0016/claw-package-v1-spec.md index c04dbdbc..b6773dad 100644 --- a/rfcs/0016/claw-package-v1-spec.md +++ b/rfcs/0016/claw-package-v1-spec.md @@ -5,7 +5,7 @@ specification for RFC 0016, Claws. It defines how one Claw manifest and its referenced files are identified, validated, published, resolved, and handed to an OpenClaw lifecycle implementation. -Status: experimental draft, tied to RFC 0016. +Status: draft experimental contract, tied to RFC 0016. ## Scope @@ -22,6 +22,9 @@ This specification defines: The grouped manifest schema and `CLAW.md` envelope are defined by [`claw-md-v1-spec.md`](claw-md-v1-spec.md). Equivalent grouped JSON passes through the same validator and lifecycle. +The OpenClaw-native profile and project authoring contracts are defined by +[`openclaw-profile-v1-spec.md`](openclaw-profile-v1-spec.md) and +[`claw-project-v1-spec.md`](claw-project-v1-spec.md). This specification does not define: @@ -65,6 +68,7 @@ definition. It contains: - package identity in `package.json`; - one `CLAW.md` or equivalent grouped JSON manifest; +- optional conventional harness profiles and package-root `BOOTSTRAP.md`; - every workspace source file referenced by that manifest. The package composes existing skills, plugins, MCP declarations, workspace @@ -114,16 +118,19 @@ An illustrative package is: github-triage/ |-- package.json |-- CLAW.md +|-- BOOTSTRAP.md +|-- profiles/ +| `-- openclaw.yml `-- workspace/ |-- AGENTS.md - |-- SOUL.md `-- reference/ `-- triage-policy.md ``` -All manifest paths and referenced workspace sources must resolve inside the -unpacked package root. A registry must verify that every declared source exists -in the uploaded artifact before accepting a version. +All manifest paths, recognized conventional profiles, optional package-root +`BOOTSTRAP.md`, and referenced workspace sources must resolve inside the +unpacked package root. A registry must verify every selected source before +accepting a version. ## Portable Path Rules @@ -167,8 +174,13 @@ Both forms pass through the same strict schema version 1 validator. A package must not select behavior from package scripts or another undeclared manifest. Installing or inspecting a Claw package must not execute package -lifecycle scripts merely to discover its manifest. The `CLAW.md` body remains -documentation only. +lifecycle scripts merely to discover its manifest. + +A non-whitespace `CLAW.md` body is the portable prompt. OpenClaw materializes +its exact bytes as managed `SOUL.md`. Grouped JSON expresses equivalent behavior +with an explicit workspace source. An optional package-root `BOOTSTRAP.md` is a +separate seed-once native first-run input and must not be targeted through +ordinary managed workspace fields. ## Publication Validation Pipeline @@ -180,8 +192,9 @@ A conforming registry must validate a publication in this order: 4. Resolve `openclaw.claw` inside the package root. 5. Parse the selected `CLAW.md` or JSON document. 6. Validate the strict schema version 1 manifest. -7. Verify that every workspace source exists and is a safe regular file, and - that any local avatar resolves through a declared workspace destination. +7. Verify every recognized conventional profile, optional package-root + `BOOTSTRAP.md`, and workspace source as a safe regular file, and verify that + any local avatar resolves through a declared workspace destination. 8. Apply registry ownership, visibility, moderation, malware, and security scanning rules. 9. Compute and retain the immutable artifact digest over the exact distributed @@ -215,8 +228,9 @@ trusted registry or signed feed binds that digest to package identity; the digest alone proves byte equality, not publisher identity, review, or safety. A local development source must be materialized as one immutable planning -snapshot containing the exact manifest bytes and every referenced workspace -source path and byte sequence. Its development digest must cover that complete +snapshot containing the exact manifest bytes, the recognized conventional +profile, optional package-root `BOOTSTRAP.md`, and every referenced workspace +source path and byte sequence. Its development digest covers that complete snapshot plus the canonical source location. Hashing only the manifest is not sufficient. Development and registry digests identify different trust layers and must not be presented as interchangeable proofs. @@ -264,8 +278,9 @@ authoritative full declaration; a summary must not replace or contradict it. ## Read-Only Planning and Consent -Inspection validates package metadata and the manifest without reading or -mutating local lifecycle state. Add dry-run resolves the final local agent id, +Inspection validates package metadata, manifest, optional native bootstrap, and +recognized conventional profile without reading or mutating local lifecycle +state. Add dry-run resolves the final local agent id, workspace, dependencies, MCP servers, files, scheduled work, local credential prerequisites, and every external executable or downloadable artifact. It reports all actions, retained resources, conflicts, blockers, and post-add @@ -328,6 +343,8 @@ At minimum, provenance must identify: - the consented plan identity and applied manifest schema version; - generated agent configuration digest and owned field paths; - managed workspace paths and content digests; +- `CLAW.md` body-to-`SOUL.md` digest and optional native bootstrap seed state; +- recognized harness-profile integrity and applied native settings; - exact skill and plugin dependency edges, resource origin (`claw-introduced` or `pre-existing`), and current non-Claw ownership; - MCP names, managed or referenced relationship, resource origin, current @@ -370,6 +387,8 @@ A conforming add implementation must: - fail the complete add when any declared component is unsupported, blocked, invalid, or unavailable; - use existing skill and plugin installers and safety checks; +- apply the recognized strict harness profile through canonical owners; +- seed optional package-root `BOOTSTRAP.md` through the native bootstrap owner; - write only confined workspace files; - map MCP declarations to the existing MCP owner; - create scheduler records pinned to the final local agent id; @@ -410,6 +429,11 @@ It does not imply artifact uninstall during the update transaction. Irreversible or uncertain owner outcomes must be retained in current provenance and reported as `status: partial`, including in structured CLI output. +Update never recreates or rewrites a consumed package-root `BOOTSTRAP.md`. +Expected native consumption is not drift. Managed `SOUL.md`, whether sourced +from the `CLAW.md` body or an explicit JSON workspace source, follows ordinary +managed-file digest and local-edit protection. + Before changing or removing a scheduler record, update and remove must read the live record through the scheduler owner and compare its owned definition with provenance. Operator-modified jobs are conflicts and must not be overwritten or @@ -417,10 +441,11 @@ deleted. ## Resource Limits -A consumer must reject a Claw manifest larger than 1 MiB and package metadata -larger than 256 KiB before parsing. Reads must remain bounded if a file grows -after an initial metadata check. Existing canonical extraction, workspace-file, -aggregate-workspace, and plan-output limits continue to apply. +A consumer must reject a Claw manifest larger than 1 MiB, package metadata +larger than 256 KiB, or an OpenClaw profile larger than 256 KiB before parsing. +Reads must remain bounded if a file grows after an initial metadata check. +Existing canonical bootstrap, extraction, workspace-file, aggregate-workspace, +and plan-output limits continue to apply. ## Remove Semantics @@ -451,6 +476,11 @@ The operator must be offered these referenced-resource dispositions: remaining dependency or pre-existing origin requires stronger explicit confirmation but is not a hidden uninstall lock. +Global plugins and profile extension artifacts are never eligible for generic +`remove-if-unused`. Their dependency edges are released, while uninstall +requires a separately selected canonical plugin-owner operation with conflict +disclosure. + The chosen disposition and affected resource identities must be part of the integrity-bound remove plan. Non-interactive mutation must identify its cleanup mode explicitly; it must not broaden default `retain` behavior merely because a @@ -481,6 +511,10 @@ credentials, operator settings, and any resource whose ownership or expected state cannot be proven. Failed cleanup remains visible to status and diagnostics. +A pending package-root `BOOTSTRAP.md` is removed only when its bytes still match +the recorded seed digest. A consumed or modified bootstrap and all user-owned +interview output are preserved. + ## Development Sources and Export A local unpackaged manifest may be inspected and, when explicitly supported, @@ -495,10 +529,14 @@ reject links, and referenced workspace sources remain regular, non-linked files. Export creates a new package directory and must fail if the output directory -already exists. It emits `package.json`, `CLAW.md`, and confined -workspace sources. Export includes only portable supported state and excludes -secrets, resolved environment values, models, providers, bindings, sessions, -logs, caches, and unrelated global configuration. +already exists. It emits `package.json`, `CLAW.md`, confined workspace sources, +and `profiles/openclaw.yml` when supported OpenClaw settings are present. +Unchanged valid UTF-8 managed `SOUL.md` content becomes the `CLAW.md` body; +whitespace-only, non-UTF-8, conflicting, or over-limit content remains one +explicit `SOUL.md` sidecar. Export includes only portable supported state and +excludes secrets, resolved environment values, models, providers, bindings, +sessions, logs, caches, consumed bootstrap rituals, user personalization, and +unrelated global configuration. Export may preserve an original package name and version only by returning the byte-for-byte original artifact with the same digest. Any regenerated package, @@ -513,12 +551,11 @@ Package v1 is identified by a manifest with `schemaVersion: 1` and the metadata contract above. Registry transport may evolve independently as long as it still delivers the exact identity, version, digest, and package bytes. -Package and manifest v1 define the OpenClaw application profile. A different -harness may inspect the portable data or implement that complete profile, and a -future specification may define additional harness profiles. A consumer must -not claim v1 application conformance if it drops, translates approximately, or -cannot own a declared component. It may inspect such a package, but add must -fail the complete plan rather than silently degrade the Claw. +Package and manifest v1 define portable core. Conventional harness profiles +define native realization without changing that core. A consumer must not claim +v1 application conformance if it drops, approximately translates, or cannot own +a declared component. It may inspect such a package, but add must fail the +complete plan rather than silently degrade the Claw. ## Registry Conformance @@ -527,6 +564,8 @@ A conforming registry must: - authenticate publication and bind it to exact package identity; - enforce package containment and portable path collision rules; - parse and validate the selected manifest strictly; +- validate every conventional profile it claims to understand and an optional + package-root bootstrap as bounded safe content; - verify every referenced source file; - retain exact artifact length and SHA-256 integrity; - retain a bounded public summary derived from the validated artifact without @@ -540,6 +579,7 @@ A conforming registry must: A conforming applying client must: - verify package identity, containment, manifest schema, and integrity locally; +- discover and validate its conventional profile and native bootstrap; - resolve exact dependencies before planning; - expose a complete read-only plan and require explicit consent; - bind mutation to the consented artifact, destinations, actions, and expected diff --git a/rfcs/0016/claw-project-v1-spec.md b/rfcs/0016/claw-project-v1-spec.md new file mode 100644 index 00000000..cdc735b9 --- /dev/null +++ b/rfcs/0016/claw-project-v1-spec.md @@ -0,0 +1,176 @@ +# Claw Project v1 Specification + +Status: draft experimental contract, tied to RFC 0016. + +This document defines the source-project, validation, deterministic-build, and +offline-development contract implemented by shipped OpenClaw Claws. It does not +create a second runtime or mutation owner. + +## Product States + +- A **project** is mutable author source. +- A **package** is the deterministic immutable artifact built from validated + selected inputs. +- An **applied Claw** is the new agent plus managed and referenced local state + created by the canonical runtime lifecycle. + +OpenClaw owns runtime semantics and local resource owners. Project tooling owns +only project discovery, scaffolding, validation, deterministic packaging, +offline preview, and exact-artifact handoff. + +## Project Discovery and Layout + +A v1 project contains both `package.json` and `CLAW.md` at its root. +JSON-only packages remain valid package input but are not v1 authoring projects. + +Conventional optional paths are: + +```text +my-claw/ +|-- package.json +|-- CLAW.md +|-- BOOTSTRAP.md +|-- profiles/ +| `-- openclaw.yml +|-- workspace/ +`-- references/ +``` + +Discovery starts from the supplied file or directory, resolves canonical real +paths, and requires exactly one containing project root. Ambiguous nested +projects fail. `.git` and `node_modules` are project-only exclusions and cannot +supply selected package content. + +## Public Commands + +```bash +openclaw claws create [path] [--name ] [--agent-id ] [--json] +openclaw claws validate [path] [--json] +openclaw claws dev [path] [--agent-id ] [--workspace ] [--json] +openclaw claws build [path] --out [--json] +``` + +All commands remain behind `OPENCLAW_EXPERIMENTAL_CLAWS=1`. + +## Create + +`create` writes one minimal project into an absent or empty directory: + +- `package.json` with canonical name, version `0.1.0`, and + `openclaw.claw: "CLAW.md"`; and +- `CLAW.md` with schema version 1, portable agent identity, and a non-whitespace + body that becomes managed `SOUL.md`. + +The generated project must pass offline validation. Create fails rather than +merging into a non-empty destination. It does not install dependencies, add an +agent, contact ClawHub, select credentials, or mutate OpenClaw state. + +## Validate + +`validate` is read-only and validates the exact selected inputs that build +would consume: + +- canonical package name and exact version; +- `openclaw.claw` exactly equal to `CLAW.md`; +- strict `CLAW.md` schema and body-to-`SOUL.md` conflicts; +- recognized conventional OpenClaw profile, including shipped legacy-pointer + compatibility; +- optional non-empty safe UTF-8 package-root `BOOTSTRAP.md`; +- every declared workspace source and portable path collision; +- exact package and extension versions; and +- project-only excluded paths. + +A project package must not declare a non-empty `scripts` object. Validation +rejects unsafe links except the confined development-manifest symlink supported +by the canonical reader, special files, over-limit content, ambiguous roots, +selected content under `.git` or `node_modules`, and selected path collisions. + +Validation reports stable structured diagnostics and does not install, enable, +authenticate, publish, apply, or migrate durable OpenClaw state. + +## Deterministic Build + +`build` implicitly validates, requires a new `.tgz` destination whose parent +already exists, and refuses overwrite. + +The artifact: + +- is an npm-compatible archive with a `package/` root; +- contains generated canonical `package.json`, exact `CLAW.md`, optional + `BOOTSTRAP.md`, the recognized OpenClaw profile, and exact declared workspace + source bytes; +- excludes all unselected project files, `.git`, and `node_modules`; +- uses stable byte ordering, epoch timestamps, portable archive metadata, + normalized permissions, separators, and gzip settings; +- executes no package script, hook, project code, dependency resolution, or + network call; and +- is reopened through the canonical Claw reader before publication. + +If selected input changes after validation, build fails. The builder stages in +the output parent and publishes with no-replace semantics. Failure removes only +its incomplete staging output and never deletes or replaces a pre-existing +destination. + +Build returns the artifact path, SHA-256 integrity, byte length, included files, +excluded paths, and package identity. Build success is not publication, +publisher ownership, security approval, or runtime readiness. + +## Offline Development Preview + +`dev` validates and builds a temporary artifact, safely extracts it, and invokes +the canonical OpenClaw add planner against that exact built content. + +V1 dev is offline and non-mutating: + +- no agent, workspace, plugin, MCP, schedule, channel delivery, or durable Claw + state is created; +- no provider turn, network-capable tool, MCP server, or package installer is + executed; +- the result has `mutationAllowed: false` and reports the same blockers, + capability effects, and readiness requirements as the canonical planner; and +- temporary artifact and extraction paths do not become source identity or + stable plan inputs. + +If an owner cannot preflight offline, dev reports the unresolved prerequisite +or blocker rather than claiming readiness or weakening the offline boundary. + +## Package and Publication Handoff + +Publication consumes the exact already-built artifact. It must not rebuild +source, infer omitted files, execute project code, or substitute archive bytes. +The built, published, downloaded, and locally verified artifact identities must +remain linked by exact digest. + +Applying that artifact still requires canonical inspect, dry-run, consent, +owner readiness, and lifecycle behavior. Registry acceptance never bypasses +dependency policy or capability consent. + +## Security and Non-Goals + +Project tooling never resolves or injects secrets from environment or host +state. Logs and JSON results redact credentials and sensitive owner errors. + +V1 does not define: + +- package scripts, arbitrary build hooks, or setup code; +- provider-backed model evaluation or live disposable development; +- credentials, bindings, host paths, or runtime deployment; +- a second Gateway, plugin manager, scheduler, sandbox, or secret store; +- publication as an OpenClaw local-runtime command; or +- a universal cross-harness CLI. + +## Conformance + +A conforming implementation proves: + +1. Fresh create passes offline validate. +2. Validate rejects unsafe or unsupported inputs without mutation. +3. Build output is byte-for-byte deterministic for identical selected inputs + across supported Linux, macOS, Windows, and WSL environments, with one + shared golden-artifact digest. +4. The built artifact passes the canonical package reader. +5. Unselected project and secret-bearing ambient files are absent. +6. Dev produces canonical offline planning with no durable or delivery effects. +7. Build refuses overwrite and preserves pre-existing output. +8. Clean-recipient add, status, doctor, update, export, and remove continue to + use their canonical runtime owners. diff --git a/rfcs/0016/openclaw-profile-v1-spec.md b/rfcs/0016/openclaw-profile-v1-spec.md new file mode 100644 index 00000000..f24d64e3 --- /dev/null +++ b/rfcs/0016/openclaw-profile-v1-spec.md @@ -0,0 +1,191 @@ +# OpenClaw Claw Profile v1 + +Status: draft experimental contract, tied to RFC 0016. + +This document defines the OpenClaw-owned harness profile at +`profiles/openclaw.yml`. Shipped OpenClaw behavior is authoritative for this +profile. The portable manifest and package lifecycle remain defined by +`claw-md-v1-spec.md` and `claw-package-v1-spec.md`. + +## Scope + +The profile maps one portable Claw to OpenClaw-native agent policy, memory, and +extension requirements. It does not change portable schema version 1, define a +universal plugin format, or move operator-owned configuration into a package. + +Other harnesses own their own conventional profiles and native projection. They +do not need OpenClaw tool names, agent CRUD, or identical presentation. + +## Discovery and Integrity + +The canonical path is `profiles/openclaw.yml`. When present, the file: + +- is a regular, non-linked UTF-8 file inside the package; +- is at most 256 KiB; +- participates byte-for-byte in package or development-source integrity; +- uses JSON-compatible YAML and rejects duplicate keys, anchors, aliases, + merge keys, explicit tags, unknown fields, and unsupported versions; and +- is validated during inspect and before add, update, dev, or build succeeds. + +For shipped compatibility, `metadata.openclaw.config` may select a safe +package-relative `.yml` or `.yaml` profile. OpenClaw emits a deprecation warning. +If `profiles/openclaw.yml` also exists, the pointer must name that same path or +validation fails. Canonical producers use only the conventional path. + +Absence means inherited OpenClaw defaults and no profile extensions. + +## Strict Schema + +The top-level shape is: + +```yaml +schemaVersion: 1 +agent: {} +extensions: [] +``` + +`schemaVersion` and `agent` are required. `agent` may be empty. `extensions` is +optional and defaults to an empty array. Every object is strict. + +### Agent Settings + +`agent` may contain only: + +| Field | Constraints | +| --- | --- | +| `groupChat.mentionPatterns` | Non-empty array of non-empty strings. | +| `sandbox.mode` | `off`, `non-main`, or `all`. | +| `sandbox.scope` | `session`, `agent`, or `shared`. | +| `sandbox.workspaceAccess` | `none`, `ro`, or `rw`. | +| `tools.profile` | A built-in profile registered by the applying OpenClaw version. | +| `tools.allow` | Non-empty bounded grants; mutually exclusive with `alsoAllow`. | +| `tools.alsoAllow` | Non-empty bounded grants; requires `profile` and is mutually exclusive with `allow`. | +| `tools.deny` | Non-empty array. | +| `tools.fs.workspaceOnly` | Literal `true`; omission inherits host policy. | +| `memory.search.enabled` | Boolean. | +| `memory.search.rememberAcrossConversations` | Boolean explicit cross-conversation opt-in. | +| `memory.search.sources` | Non-empty subset of `memory` and `sessions`. | +| `heartbeat` | Exact heartbeat object below. | +| `humanDelay` | Exact human-delay object below. | + +The canonical memory path is `memory.search`; there is no `memorySearch` alias. +Selecting `sessions` requires `rememberAcrossConversations: true`. + +Tool grants must be bounded. Wildcards, unresolved dynamic groups, +`group:plugins`, and `bundle-mcp` are not portable consent boundaries. The +`full` profile requires an explicit bounded `allow`. If a selected profile +contains a dynamic selector, `allow` must narrow the effective set to concrete +tool names accepted by that profile. `alsoAllow` cannot be used without a +profile. Host policy remains an upper bound. + +`heartbeat` may contain only: + +| Field | Constraints | +| --- | --- | +| `every` | Valid OpenClaw duration. | +| `activeHours.start` | `HH:MM`, `00:00` through `23:59`. | +| `activeHours.end` | `HH:MM`, `00:00` through `24:00`. | +| `activeHours.timezone` | Valid IANA timezone. | +| `lightContext` | Boolean. | +| `isolatedSession` | Boolean. | +| `timeoutSeconds` | Positive integer. | + +Unknown heartbeat fields, including retired busy-state policy, are invalid. + +`humanDelay` may contain `mode`, `minMs`, and `maxMs`. `mode` is `off`, +`natural`, or `custom`; millisecond values are non-negative integers. + +Example accepted by the shipped strict schema: + +```yaml +schemaVersion: 1 +agent: + groupChat: + mentionPatterns: ["@triage"] + sandbox: + mode: all + scope: agent + workspaceAccess: rw + tools: + allow: [read, write, web_fetch] + deny: [exec] + fs: + workspaceOnly: true + memory: + search: + enabled: true + rememberAcrossConversations: true + sources: [memory, sessions] + heartbeat: + every: 30m + timeoutSeconds: 120 + humanDelay: + mode: natural +extensions: + - id: github-actions + kind: plugin + format: openclaw + source: clawhub + ref: "@acme/github-actions" + version: 2.1.0 +``` + +### Native Extensions + +Each `extensions` entry has required fields: + +| Field | Contract | +| --- | --- | +| `id` | Unique portable identifier. | +| `kind` | Exactly `plugin`. | +| `format` | `openclaw`, `claude`, `codex`, or `cursor`. | +| `source` | Exactly `clawhub`. | +| `ref` | Canonical package reference. | +| `version` | Exact semantic version. | + +`format` is an expected artifact-format assertion. OpenClaw delegates detection, +scanning, installation, mapping, readiness, update, and cleanup to its canonical +plugin owner. A mismatch, blocked artifact, unavailable package, failed +preflight, duplicate dependency, or bundle with no usable mapped component +blocks the complete plan. + +Mapped and unavailable components, artifact integrity, adapter identity, trust +findings, setup requirements, and redacted effects participate in plan +integrity. The Claw records a referenced dependency edge and origin; it does not +gain plugin deletion authority. + +Existing experimental portable `packages` entries of kind `plugin` remain +readable. Canonical producers put new OpenClaw-native extension requirements in +this profile and do not duplicate the same dependency in both locations. + +## Ownership and Lifecycle + +Inspect and dry-run expose effective settings, extension identity, detected +format, mapped and unavailable inventory, prerequisites, and redacted effects. +Add delegates agent settings to the canonical agent owner and extensions to the +canonical plugin owner. + +Update re-resolves built-in profiles and extension mapping. Any effective tool +grant, memory capability, filesystem-access, or extension increase is a +capability escalation requiring renewed exact consent. Status and doctor report +profile and extension drift without silently changing plugin enablement. + +Remove releases extension dependency edges and retains plugins by default. +Uninstall is a separately selected canonical plugin-owner operation. + +The profile cannot carry models, providers, credentials, bindings, custom tool +profiles, sender-specific policy, memory providers, remote memory endpoints, +local storage paths, or indexing tuning. + +## Conformance + +A conforming OpenClaw adapter must: + +- discover and validate the profile as specified; +- preserve inherited defaults when absent and host policy when present; +- freeze consent to bounded effective tool and memory policy; +- use canonical plugin owners for every extension; +- fail closed on unsupported settings and required extension failures; +- bind exact profile bytes and resolved effects into integrity; +- keep credentials and resolved secrets outside package and Claw state; and +- preserve referenced plugins by default during removal.