Skip to content

[Bug]: Preseeded SOUL.md/IDENTITY.md/USER.md make OpenClaw auto-complete bootstrap and delete user-provided BOOTSTRAP.md before first run #91931

Description

@katerinkaivanova

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

OpenClaw can mark a brand-new managed workspace as bootstrap-complete and delete a user-provided BOOTSTRAP.md before the first user-visible onboarding run, if the workspace is preseeded with custom SOUL.md, IDENTITY.md, or USER.md.

This affects GitOps / Kubernetes / operator-style deployments where a platform seeds a workspace from managed templates before the first user interaction. In that setup, preseeded profile files are not evidence that the human onboarding flow has completed; they are just platform defaults.

Current behavior treats those files as completion evidence, writes setupCompletedAt, deletes BOOTSTRAP.md, and therefore prevents the custom first-run onboarding prompt from running.

Steps to reproduce

  1. Deploy OpenClaw with a fresh empty workspace directory.
  2. Before the first user interaction, seed the workspace with:
    • BOOTSTRAP.md containing a first-run onboarding flow
    • SKILL_USAGE.md
    • custom SOUL.md
    • custom IDENTITY.md
    • custom USER.md
  3. Start OpenClaw.
  4. Wait for ensureAgentWorkspace() / workspace bootstrap reconciliation to run.
  5. Check the workspace state and BOOTSTRAP.md.

Expected behavior

If BOOTSTRAP.md exists and setupCompletedAt is not set yet, OpenClaw should keep bootstrap pending until the bootstrap flow actually completes.

For managed/preseeded workspaces, custom SOUL.md, IDENTITY.md, and USER.md should not automatically mean “the human onboarding flow has completed”.

A user-provided BOOTSTRAP.md should remain available for the first user-visible run, so the agent can follow it and delete it only after successful onboarding.

Actual behavior

OpenClaw sees that one of SOUL.md, IDENTITY.md, or USER.md differs from the built-in template, treats that as bootstrap completion evidence, writes setupCompletedAt, and deletes BOOTSTRAP.md.

Observed workspace state:

{
  "version": 1,
  "bootstrapSeededAt": "2026-06-09T07:57:25.228Z",
  "setupCompletedAt": "2026-06-09T07:57:25.228Z"
}

BOOTSTRAP.md is missing immediately after startup, before the intended onboarding flow has completed.

In the same workspace, the intended onboarding markers are still absent:

SKILL_USAGE.md started_at: empty
cron/jobs.json: missing

OpenClaw version

2026.5.12

Operating system

Linux, Kubernetes pod, PVC-backed workspace.

Install method

Docker image deployed as a Kubernetes StatefulSet through an operator-style control plane.

Model

N/A. This happens before model-specific behavior matters. The file is deleted by workspace bootstrap reconciliation.

Provider / routing chain

N/A.

Additional provider/model setup details

No response

Logs, screenshots, and evidence

The managed platform writes workspace files after the pod becomes ready and verifies that BOOTSTRAP.md exists:

{
  "status": "ok",
  "command": [
    "sh",
    "-c",
    "test -f \"/home/openclaw/.openclaw/workspace/BOOTSTRAP.md\" && test -f \"/home/openclaw/.openclaw/workspace/SKILL_USAGE.md\" && echo OK"
  ],
  "timestamp": "2026-06-09T07:57:24.642477Z"
}

Immediately after that, OpenClaw writes completion state and BOOTSTRAP.md disappears:

{
  "version": 1,
  "bootstrapSeededAt": "2026-06-09T07:57:25.228Z",
  "setupCompletedAt": "2026-06-09T07:57:25.228Z"
}

The workspace root contains SKILL_USAGE.md, SOUL.md, IDENTITY.md, USER.md, etc., but no BOOTSTRAP.md.

The profile files differ from built-in OpenClaw templates:

SOUL.md differs=true
IDENTITY.md differs=true
USER.md differs=true
memory exists=false
.git exists=false
MEMORY.md exists=false

Impact and severity

Affected deployments include Kubernetes/operator/GitOps setups where SOUL.md, IDENTITY.md, or USER.md are platform-provided defaults rather than user-created onboarding output.

Severity: Medium. The agent still runs, but the first-run onboarding contract is silently skipped. This can leave required setup incomplete, for example:

  • onboarding greeting not generated
  • SKILL_USAGE.md not initialized
  • onboarding reminder cron jobs not created
  • custom BOOTSTRAP.md deleted before it can be followed

Frequency: Always, for fresh workspaces that include custom SOUL.md, IDENTITY.md, or USER.md.

Consequence: first-run onboarding can be skipped silently in managed/preseeded workspaces.

Additional information

Root cause

Current src/agents/workspace.ts treats profile-file differences as bootstrap completion evidence:

async function workspaceProfileLooksConfigured(params: {
  dir: string;
  includeGitEvidence?: boolean;
}): Promise<boolean> {
  const profileFileDiffs = await Promise.all(
    WORKSPACE_ONBOARDING_PROFILE_FILENAMES.map(async (fileName) =>
      fileContentDiffersFromTemplate(path.join(params.dir, fileName), await loadTemplate(fileName)),
    ),
  );
  return (
    profileFileDiffs.some(Boolean) ||
    (await hasWorkspaceUserContentEvidence(params.dir, {
      includeGit: params.includeGitEvidence,
    }))
  );
}

WORKSPACE_ONBOARDING_PROFILE_FILENAMES includes:

SOUL.md
IDENTITY.md
USER.md

Then bootstrap reconciliation deletes BOOTSTRAP.md:

const repairedState: WorkspaceSetupState = {
  ...params.state,
  bootstrapSeededAt: params.state.bootstrapSeededAt ?? now,
  setupCompletedAt: now,
};
await writeWorkspaceSetupState(params.statePath, repairedState);
try {
  await fs.rm(params.bootstrapPath, { force: true });
  return { repaired: true, bootstrapExists: false, state: repairedState };
}

This heuristic works for local legacy workspaces where a user manually edited profile files, but it is false-positive evidence for managed/preseeded workspaces.

Existing related issue

Related but not identical:

This issue is different: the desired behavior is still one-time bootstrap. The problem is that bootstrap is auto-completed before the first run because preseeded platform templates look like user-completed profile files.

Suggested fix

Add an opt-in bootstrap completion mode for managed/preseeded workspaces, for example:

{
  "agents": {
    "defaults": {
      "bootstrap": {
        "completionEvidence": "explicit-delete"
      }
    }
  }
}

Possible modes:

profile-evidence   current default behavior
explicit-delete    if BOOTSTRAP.md exists and setupCompletedAt is unset, keep bootstrap pending; do not use SOUL.md/IDENTITY.md/USER.md diffs as completion evidence

In explicit-delete mode:

  • BOOTSTRAP.md existing means bootstrap is pending.
  • OpenClaw should not delete BOOTSTRAP.md just because profile files differ from built-in templates.
  • Completion is recorded only after BOOTSTRAP.md disappears, or through an explicit completion marker/API.
  • Existing default behavior remains unchanged for local legacy workspaces.

Alternative fix shape:

Ignore profile-file diffs as completion evidence when BOOTSTRAP.md exists and was just seeded in the current workspace lifecycle.

But an explicit config mode is safer because legacy local behavior likely depends on the current heuristic.

Workaround

Downstream can avoid the false positive by not pre-seeding custom SOUL.md, IDENTITY.md, or USER.md in brand-new workspaces. However, this is awkward for managed deployments that need platform defaults and GitOps-managed workspace templates.

Another workaround is to move platform defaults into AGENTS.md, TOOLS.md, or BOOTSTRAP.md, and let the bootstrap flow create/update SOUL.md, IDENTITY.md, and USER.md later. This works but forces deployments to structure files around OpenClaw's internal completion heuristic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.bugSomething isn't workingbug:behaviorIncorrect behavior without a crashclawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:data-lossCan lose, corrupt, or silently drop user/session/config data.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions