Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@ alignfirst-developer-tests/vendor/

# OpenClaw runtime state — recreated per-instance, not team-curated (a test
# instance snapshots these into the workspace; we don't track them)
alignfirst-developer-tests/workspace/HEARTBEAT.md
alignfirst-developer-tests/workspace/.openclaw/
8 changes: 4 additions & 4 deletions alignfirst-developer-tests/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,20 @@ COPY --chown=claw:claw package.json package-lock.json /opt/openclaw-test/src/
COPY --chown=claw:claw vendor/ /opt/openclaw-test/src/vendor/
COPY --chown=claw:claw openclaw.json /home/claw/.openclaw/openclaw.json

# OpenClaw 2026.8.1 verifies managed plugin dependencies and capabilities at
# OpenClaw 2026.8 verifies managed plugin dependencies and capabilities at
# gateway startup. Install the exact official artifacts instead of copying the
# local package directory, which omits its runtime dependencies. Z.AI backs the
# configured GLM model; Perplexity is auto-selected when OpenRouter is present.
RUN npm ci --include=dev && \
OPENCLAW_CONFIG_PATH=/home/claw/.openclaw/openclaw.json \
npx openclaw plugins install --force --accept-capabilities \
npm:@openclaw/codex@2026.8.1 && \
npm:@openclaw/codex@2026.8.2 && \
OPENCLAW_CONFIG_PATH=/home/claw/.openclaw/openclaw.json \
npx openclaw plugins install --force --accept-capabilities \
npm:@openclaw/zai-provider@2026.8.1 && \
npm:@openclaw/zai-provider@2026.8.2 && \
OPENCLAW_CONFIG_PATH=/home/claw/.openclaw/openclaw.json \
npx openclaw plugins install --force --accept-capabilities \
npm:@openclaw/perplexity-plugin@2026.8.1 && \
npm:@openclaw/perplexity-plugin@2026.8.2 && \
OPENCLAW_CONFIG_PATH=/home/claw/.openclaw/openclaw.json \
npx openclaw plugins registry --refresh && \
npm cache clean --force
Expand Down
13 changes: 11 additions & 2 deletions alignfirst-developer-tests/openclaw.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@
"codex": { "enabled": true },
"discord-mock": { "enabled": true },
"slack-mock": { "enabled": true }
}
},
"slots": { "memory": "none" }
},
"memory": {
"search": { "enabled": false, "rememberAcrossConversations": false }
},
"skills": {
"workshop": { "autonomous": { "mode": "off" } }
},
"update": { "checkOnStart": false },
"tools": {
"profile": "coding",
"alsoAllow": ["message", "browser"],
Expand Down Expand Up @@ -85,8 +93,9 @@
"heartbeat": {
"every": "24h",
"target": "last",
"prompt": "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply exactly NO_REPLY."
"directPolicy": "allow"
},
"compaction": { "memoryFlush": { "enabled": false } },
"blockStreamingDefault": "on",
"blockStreamingBreak": "text_end",
"blockStreamingCoalesce": { "minChars": 1, "idleMs": 100 }
Expand Down
160 changes: 80 additions & 80 deletions alignfirst-developer-tests/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion alignfirst-developer-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@paleo/openclaw-discord-mock": "file:vendor/openclaw-discord-mock.tgz",
"@paleo/openclaw-slack-mock": "file:vendor/openclaw-slack-mock.tgz",
"@paleo/openclaw-test": "file:vendor/openclaw-test.tgz",
"openclaw": "2026.8.1"
"openclaw": "2026.8.2"
},
"devDependencies": {
"@types/node": "~24.13.3",
Expand Down
11 changes: 8 additions & 3 deletions docs/alignfirst-developer/openclaw-context-engineering.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ These top-level files under `~/.openclaw/workspace/` are read on every turn and
- `SOUL.md`, `IDENTITY.md`, `USER.md` — persona / context (optional)
- `MEMORY.md` — curated long-term memory (optional)
- `BOOTSTRAP.md` — first-run ritual (optional)
- `HEARTBEAT.md` — heartbeat checklist (optional, dynamic load)

Loader: `loadWorkspaceBootstrapFiles()` in `src/agents/workspace.ts`. The bootstrap cache (`src/agents/bootstrap-cache.ts`) refreshes per turn keyed on inode/mtime, so live edits are picked up without restarting the gateway. This is why the harness can bind-mount the workspace and the playbook skill into the gateway and have playbook edits iterate without a rebuild.

Expand All @@ -39,12 +38,18 @@ Defaults in `src/agents/bootstrap-budget.ts`:

Over-budget files are truncated with a marker. Keep workspace files under these limits.

## Heartbeat sentinel: `NO_REPLY`
## Heartbeat: cron scratch and `NO_REPLY`

The workspace and alcode wake convention is `NO_REPLY`, OpenClaw's general silent-reply token. OpenClaw 2026.8.1 sends the configured heartbeat prompt verbatim as the scheduled user message and no longer adds a heartbeat-specific system-prompt section. The former `agents.defaults.heartbeat.includeSystemPromptSection` key is rejected.
The heartbeat checklist is the scratch of the system-owned `heartbeat:main` cron job (its declaration key; the listing shows it as `Heartbeat (main)`), a row in the shared SQLite store (`src/cron/heartbeat-monitor.ts`, `src/cron/scratch-store.ts`). The gateway creates the job at startup from `agents.defaults.heartbeat.every`; `openclaw cron scratch <job-id>` reads and writes the scratch. The runtime never reads a workspace `HEARTBEAT.md`; `openclaw doctor --fix` imports a leftover file into the scratch and deletes it (`src/commands/doctor-heartbeat-scratch-migration.ts`). A comment-only scratch makes the periodic tick skip its model call (`reason=empty-heartbeat-file`); a missing scratch runs the model.

The workspace and alcode wake convention is `NO_REPLY`, OpenClaw's general silent-reply token. The stock heartbeat prompt (`src/auto-reply/heartbeat.ts`) follows the scratch and ends in `NO_REPLY`, and OpenClaw sends it verbatim as the scheduled user message, so neither the harness nor the deployment seed overrides `agents.defaults.heartbeat.prompt`. The former `agents.defaults.heartbeat.includeSystemPromptSection` key is rejected.

OpenClaw still accepts the legacy `HEARTBEAT_OK` acknowledgment and suppresses token-only replies, including stray acknowledgments outside heartbeat turns. Keep new instructions on `NO_REPLY` so scheduled and event-driven wake paths share one convention.

## Background model runs disabled by the harness and the seed

Three defaults schedule model turns without a user message: the memory-core dreaming sweep (daily, rewrites `MEMORY.md`), the weekly skill-collection review (`skills.workshop.autonomous.mode` defaults to `auto`) and the pre-compaction memory flush (`agents.defaults.compaction.memoryFlush`, writes `memory/YYYY-MM-DD.md`). `memory-core` owns the `memory` plugin slot and loads regardless of `plugins.allow`; `plugins.slots.memory: "none"` removes it along with the `memory_search`/`memory_get` tools. The harness config and the deployment seed set the same opt-outs, plus `update.checkOnStart: false` (the startup update check is also an anonymous version ping).

## Practical implications

- Keep top-level workspace files lean — every turn pays the token cost.
Expand Down
38 changes: 28 additions & 10 deletions docs/alignfirst-developer/upgrading-openclaw.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ git clone --quiet --depth=1 --branch v<version> https://github.com/openclaw/open
- Read the new release's section of the clone's `CHANGELOG.md` — top section only, the file is enormous.
- Diff the surfaces our documentation describes: `git -C .local/openclaw diff v<old> v<new> --stat -- src/agents src/commands`, then the files behind any suspicious stat line.
- Re-verify the claims of [openclaw-context-engineering.md](./openclaw-context-engineering.md) against the new tag; the document names its source files. Doctor does not flag silent behavior shifts (the 2026.8 subagent bootstrap narrowing, for example) — only this re-reading catches them.
- Compare the deployment template's workspace files (`skills/alignfirst-setup-guide/assets/alignfirst-developer-template/base/infra/openclaw/workspace/`) with `WORKSPACE_BOOTSTRAP_FILENAMES` in `src/agents/workspace.ts`. A file the runtime stopped reading must leave the template and its `chattr` lists; 2026.8.1 retired `HEARTBEAT.md` this way and the check above did not catch it.
- Diff the config help between the tags: `git -C .local/openclaw diff v<old> v<new> -- 'src/config/schema.help.*.ts'`. A default that turns on a background behavior (a scheduled model run, a memory feature, a telemetry ping) appears there and nowhere doctor looks; see [Propagate](#propagate-to-the-deployment-template).

## Bump the pins

Expand All @@ -42,28 +44,44 @@ Then rebuild the harness image: `npm run env:build` in `alignfirst-developer-tes

## Run doctor in a throwaway container

Doctor is the upstream migration detector: it flags retired workspace files, retired config keys and pending state migrations. Run it against a scratch copy of the reference workspace — never the original, `--fix` rewrites files:
Doctor is the upstream migration detector: it flags retired workspace files, retired config keys and pending state migrations. Run it against scratch copies of both workspaces we ship, the harness reference and the deployment template (base files plus one surface's `AGENTS.md`) — never the originals, `--fix` rewrites files:

```sh
cd alignfirst-developer-tests
cp -r workspace /tmp/doctor-workspace
docker run --rm -v /tmp/doctor-workspace:/home/claw/.openclaw/workspace \
-e ANTHROPIC_API_KEY=x -e OPENROUTER_API_KEY=x -e ZAI_API_KEY=x \
-e ALIGNFIRST_CODE_AGENT=claude \
--entrypoint /usr/local/bin/openclaw \
alignfirst-developer-tests-openclaw-test:latest doctor --json
template=../skills/alignfirst-setup-guide/assets/alignfirst-developer-template
cp -r workspace /tmp/doctor-harness
cp -r $template/base/infra/openclaw/workspace /tmp/doctor-template
cp $template/variants/surfaces/slack/infra/openclaw/workspace/AGENTS.md /tmp/doctor-template/
for ws in /tmp/doctor-harness /tmp/doctor-template; do
docker run --rm -v $ws:/home/claw/.openclaw/workspace \
-e ANTHROPIC_API_KEY=x -e OPENROUTER_API_KEY=x -e ZAI_API_KEY=x \
-e ALIGNFIRST_CODE_AGENT=claude \
--entrypoint /usr/local/bin/openclaw \
alignfirst-developer-tests-openclaw-test:latest doctor --json
done
```

Two findings are expected noise, because no gateway ever runs in this container: the heartbeat cron materialization warning (the gateway reconciles those jobs itself at startup — `reconcileHeartbeatMonitorJobs` in `src/gateway/server-cron.ts`) and the plaintext-secrets warning (the harness injects keys through the environment on purpose). Investigate anything else.
Three findings are expected noise, because no gateway ever runs in this container: the heartbeat cron materialization warning (the gateway reconciles those jobs itself at startup — `reconcileHeartbeatMonitorJobs` in `src/gateway/server-cron.ts`), the plaintext-secrets warning (the harness injects keys through the environment on purpose) and the node-hosting precondition about the loopback bind. Investigate anything else.

## Run the regression suite
## Inspect a running gateway

`env:up` starts the worker gateways with the harness config. Ask one which jobs and plugins the release materialized on its own:

```sh
npm run env:up
docker exec alignfirst-developer-tests-w1-gateway-1 openclaw cron list --all
docker exec alignfirst-developer-tests-w1-gateway-1 openclaw plugins list
```

Expected: `heartbeat:main` as the only enabled job (the skill-collection review may be listed as disabled), and no plugin outside `openclaw.json`. A new enabled job or an unlisted plugin is a default the release turned on; find its knob in the config help diff.

## Run the regression suite

```sh
npm run e2e -- --channel all --all
npm run env:down
```

## Propagate to the deployment template

When the release retires a config key, the template's seed tolerates it (`set_json_tolerated` in `base/infra/openclaw/seed/common.sh`) — add an entry there. When it retires a workspace file or changes operator-visible behavior, update the setup-guide template docs and, for hardened installations, add a gotcha with the removal procedure (see "Legacy `TOOLS.md`" in the template's `gotchas.md`).
The seed targets the current release. When the release retires a config key the seed sets, delete or replace the line. When it retires a workspace file or changes operator-visible behavior, update the setup-guide template: it describes a fresh install on the current release, so retired files and keys leave it, and the consumers' own runbooks carry the migration. When it turns on a background behavior, add the opt-out to `base/infra/openclaw/seed/common.sh` and to `alignfirst-developer-tests/openclaw.json`, which carry the same opt-outs. Bump the `version` in the skill's `SKILL.md`.
Loading