---
name: oat-worktree-bootstrap-auto
version: 1.5.6
description: Use when an orchestrator/subagent needs autonomous worktree bootstrap. Non-interactive companion to oat-worktree-bootstrap.
argument-hint: '<branch-name> [--base <ref>] [--path <root>] [--baseline-policy <strict|allow-failing>]'
disable-model-invocation: false
user-invocable: false
allowed-tools: Read, Write, Bash, Glob, Grep
---

# Autonomous Worktree Bootstrap

Non-interactive worktree bootstrap for orchestrator and subagent execution flows. Creates or reuses a worktree, runs baseline checks, and reports structured status — all without user prompts.

This skill is **model-invocable** (`disable-model-invocation: false`): orchestrators such as `oat-project-implement` invoke it programmatically when a parallel phase group needs autonomous worktree bootstrap. It is **not** user-invocable (`user-invocable: false`) — it has no interactive surface and is never offered as a slash command.

> ⚠️ **When not to substitute.** This skill is the **only** supported mechanism for orchestrator-driven worktree creation in OAT skills. Host-native isolation primitives — Claude Code's `Agent({ isolation: "worktree" })`, Cursor's worktree-isolated agent invocations, and equivalents in other hosts — are **not** substitutes. They may use the primary repo's checkout (often `main`) as the base regardless of the caller's current branch, silently producing a worktree at the wrong base. OAT orchestrators dispatching mid-run from a feature branch MUST go through this skill with an explicit `--base` so the resulting worktree contains the orchestrator's prior commits.

## Relationship to oat-worktree-bootstrap

This skill is the **autonomous companion** to `oat-worktree-bootstrap`. Key differences:

| Concern          | oat-worktree-bootstrap (manual)      | oat-worktree-bootstrap-auto (autonomous) |
| ---------------- | ------------------------------------ | ---------------------------------------- |
| Invocation       | User-invocable, interactive          | Agent-only, non-interactive              |
| Prompts          | Uses `AskUserQuestion` for decisions | Never uses `AskUserQuestion`             |
| Failure handling | Asks user to abort/proceed           | Policy-driven (strict or allow-failing)  |
| Status output    | Human-readable banners               | Structured machine-parseable output      |
| Logging          | Console + optional artifact          | Artifact-first, console fallback         |

Both skills share the same worktree root resolution precedence and branch naming conventions.

## Progress Indicators (User-Facing)

When this skill is executed, provide concise status updates:

- Print a phase banner once at start:

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  OAT ▸ WORKTREE BOOTSTRAP AUTO
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- Before major phases, print compact indicators, for example:
  - `[1/7] Resolving worktree root…`
  - `[2/7] Detecting bootstrap mode from resolved base…`
  - `[3/7] Creating/reusing worktree…`
  - `[4/7] Verifying resolved base in worktree HEAD…`
  - `[5/7] Running baseline checks…`
  - `[6/7] Syncing providers or recording smoke skips…`
  - `[7/7] Returning structured status…`

## Inputs

### Required

- `<branch-name>` — Target branch for the worktree.

### Optional

| Parameter                    | Default                 | Description                                                                                                                                                                                                                                                                                                                                                                                                |
| ---------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--base <ref>`               | `origin/main`           | Base ref to branch from. **Callers running inside a worktree-on-a-feature-branch (e.g., an `oat-project-implement` orchestrator dispatching mid-run) MUST pass `--base` explicitly** — either the orchestrator's current branch name or the resolved current HEAD SHA. The default `origin/main` is the **wrong** choice for orchestrators dispatching mid-run; using it will land the worktree at `main`. |
| `--path <root>`              | Resolved via precedence | Explicit worktree root override                                                                                                                                                                                                                                                                                                                                                                            |
| `--baseline-policy <policy>` | `strict`                | Baseline check failure policy                                                                                                                                                                                                                                                                                                                                                                              |

### Baseline Policy

| Policy          | Behavior                                                                                                   |
| --------------- | ---------------------------------------------------------------------------------------------------------- |
| `strict`        | Fail fast on any baseline check failure. Return error status immediately.                                  |
| `allow-failing` | Continue on baseline failures. Emit structured warnings. Log failures to project artifacts when available. |

The baseline policy never downgrades smoke containment failures. A missing,
unsafe, or malformed smoke marker, or failure of the smoke-safe
repository bootstrap path, is always fatal.

## Process

Initialize `BOOTSTRAP_MODE=normal` at process entry so even failures before base
inspection return an explicit mode. Only Step 1.5 may change it to `smoke`.

### Step 1: Resolve Worktree Root

Use the same resolution precedence as `oat-worktree-bootstrap`:

1. Explicit `--path <root>` (highest priority)
2. `OAT_WORKTREES_ROOT` environment variable
3. `.oat/config.json` → `worktrees.root`
4. First existing directory (ordered):
   a. `${REPO_ROOT}/.worktrees`
   b. `${REPO_ROOT}/worktrees`
   c. `../${REPO_NAME}-worktrees`
5. Fallback: `../${REPO_NAME}-worktrees`

If the resolved root is project-local (`.worktrees` or `worktrees`), verify it is gitignored.

### Step 1.5: Resolve Base and Detect Bootstrap Mode

Resolve the base commit and inspect that commit, not the caller's checkout or
the eventual target, before any worktree creation command:

```bash
RESOLVED_BASE_SHA=$(git -C "$REPO_ROOT" rev-parse "$BASE_REF")
BOOTSTRAP_MODE=normal
SMOKE_MARKER_ENTRY=$(
  git -C "$REPO_ROOT" ls-tree "$RESOLVED_BASE_SHA" -- ".oat/smoke-bootstrap.json"
)
if [[ -n "$SMOKE_MARKER_ENTRY" ]]; then
  BOOTSTRAP_MODE=smoke
fi
```

`BOOTSTRAP_MODE` is derived state, not a caller override. Set
`BOOTSTRAP_MODE=smoke` only when the resolved base commit tracks the marker
path. An absent path selects `normal`; a base-resolution or tree-inspection
error is a bootstrap error. This detection must complete before Step 2.

### Step 2: Create or Reuse Worktree

- Validate branch name: `^[a-zA-Z0-9._/-]+$`
- Resolve target path: `{root}/{branch-name}`
- In normal mode, preserve existing behavior:
  - If the branch exists locally:
    `git -C "$REPO_ROOT" worktree add "$TARGET_PATH" "$BRANCH_NAME"`
  - If the branch does not exist:
    `git -C "$REPO_ROOT" worktree add "$TARGET_PATH" -b "$BRANCH_NAME" "$BASE_REF"`
  - If a worktree already exists at the target path, reuse it after validating
    that its branch matches.
- In smoke mode, disable repository hooks only for each create/reuse command
  invocation. Never mutate persistent Git configuration:

  ```bash
  # Existing branch
  git -c core.hooksPath=/dev/null -C "$REPO_ROOT" worktree add \
    "$TARGET_PATH" "$BRANCH_NAME"

  # New branch
  git -c core.hooksPath=/dev/null -C "$REPO_ROOT" worktree add \
    "$TARGET_PATH" -b "$BRANCH_NAME" "$BASE_REF"

  # Reused target validation uses the same invocation-scoped suppression.
  git -c core.hooksPath=/dev/null -C "$TARGET_PATH" \
    rev-parse --abbrev-ref HEAD
  ```

  Do not run `git config core.hooksPath ...`; the suppression must remain
  invocation-scoped.

After smoke-mode creation or reuse, require the tracked marker in the target
before any propagation, sync, status, or test command:

```bash
git -C "$TARGET_PATH" ls-files --error-unmatch -- ".oat/smoke-bootstrap.json"
SMOKE_MARKER="$TARGET_PATH/.oat/smoke-bootstrap.json"
test -d "$TARGET_PATH/.oat"
test ! -L "$TARGET_PATH/.oat"
test -f "$SMOKE_MARKER"
test ! -L "$SMOKE_MARKER"
```

Any failed check is a fatal containment failure with
`reason: smoke-marker-invalid`, regardless of baseline policy. Do not fall
through to normal mode.

Immediately after those marker checks, register the child from the parent
orchestrator before running any command inside it:

```bash
SMOKE_MANIFEST=$(
  node -e \
    "const marker=require(process.argv[1]); process.stdout.write(marker.manifestPath)" \
    "$SMOKE_MARKER"
)
node "$TARGET_PATH/tools/smoke/runner/journal.mjs" register \
  --manifest "$SMOKE_MANIFEST" \
  --marker "$SMOKE_MARKER" \
  --worktree "$TARGET_PATH"
```

Registration is idempotent, so the repository's smoke-safe bootstrap may
register the same child again. This parent-side registration must happen before
the first child process: a package-manager, shell, or bootstrap-launch failure
must not leave an unjournaled worktree that cleanup cannot safely own.

On failure: return structured error, do not prompt.

### Step 2.5: Propagate Local-Only Config + Local Paths

**Smoke mode:** skip source config propagation and `oat local sync` entirely.
The safe init path owns the only permitted config transfer. Do not read or copy
the invoking checkout's local-only config here.

**Normal mode:** after the worktree is created or reused, copy gitignored
local-only config and sync configured local paths as before.

**Config propagation:**

```bash
SRC="$REPO_ROOT/.oat/config.local.json"
DST="$TARGET_PATH/.oat/config.local.json"
if [[ -f "$SRC" && ! -f "$DST" ]]; then
  cp "$SRC" "$DST"
fi
```

- Only copy if source exists and destination does not (never overwrite).
- `activeIdea` is stored in `config.local.json`, so it propagates automatically.

**Local paths sync:**

```bash
oat local sync "$TARGET_PATH" 2>/dev/null || true
```

- Copies configured `localPaths` (e.g., `.oat/ideas/`, `.oat/projects/local/`) into the worktree.
- Non-blocking: if sync fails or no `localPaths` are configured, bootstrap continues.

### Step 2.7: Verify Resolved Base in Worktree HEAD

Before any baseline checks run, verify the worktree actually branched from the resolved base. This catches host-native or git-internal misbehavior that would otherwise silently land the worktree at the wrong base.

1. Reuse `RESOLVED_BASE_SHA` from Step 1.5.

2. Capture the worktree HEAD:

   ```bash
   OBSERVED_HEAD_SHA=$(git -C "$TARGET_PATH" rev-parse HEAD)
   ```

3. Confirm the resolved base is reachable from the worktree HEAD:

   ```bash
   git -C "$TARGET_PATH" merge-base --is-ancestor "$RESOLVED_BASE_SHA" "$OBSERVED_HEAD_SHA"
   ```

   - Exit `0` → base is contained in the worktree HEAD; continue to Step 3.
   - Non-zero exit → base mismatch.

**On base mismatch:** treat as a bootstrap failure. Do **not** silently land at the wrong base, do **not** proceed to baseline checks. Apply the configured baseline policy to the failure:

- `smoke` → return immediately with `status: failed` and
  `reason: smoke-base-mismatch`. This is a containment failure and cannot be
  downgraded by `allow-failing`.
- `strict` → return immediately with `status: failed`, `reason: base-mismatch`, populated `expected_base_sha` and `observed_head_sha`, and the worktree path. The orchestrator is expected to cancel the dispatch and degrade.
- `allow-failing` → emit a structured warning (`reason: base-mismatch`, with `expected_base_sha` and `observed_head_sha`), append a base-mismatch entry to `implementation.md` if an active project exists, and continue to Step 3 only if the caller has explicitly opted into a degraded outcome. In all other cases prefer fail-fast — base mismatch is rarely recoverable.

### Step 3: Run Baseline Checks

Execute in the target worktree directory.

First resolve the repository bootstrap contract:

1. Read the applicable agent instructions and contributing/setup guidance.
2. Inspect repository task definitions, manifests, and lockfiles.
3. Prefer an explicit worktree bootstrap command when the repository declares
   one.
4. If no command exists, derive the minimum safe setup for a fresh worktree
   from repository context.
5. Select the repository's documented readiness check and a proportionate
   baseline verification. Do not default to a full test suite when setup
   guidance specifies a narrower readiness check.
6. Record the exact selected commands and the evidence used to choose them.

Never assume Node.js, pnpm, a dependency store, or a particular install, build,
or test command. For example, this repository declares its own `worktree:init`
procedure in `AGENTS.md` and `package.json`; that repository context, not this
skill, supplies the invocation.

**Normal mode:**

Run the selected repository bootstrap, readiness, and baseline commands. Run
`oat status --scope project` when the initialized repository contains an OAT
project.

Continue to Step 4 for normal provider directory setup, the `git_clean`
baseline check, and the all-scope sync. The `git_clean` check must run after
provider directory creation but before the all-scope sync sweep, so it measures
inherited worktree state plus setup output rather than the sync sweep's
generated output.

**Smoke mode:**

Source smoke preflight already owns dependency, build, and repository-wide test
readiness for the source commit. A nested smoke child must run only the
repository bootstrap's smoke-safe containment path: validate the marker,
register ownership in the locked manifest journal, verify the expected base,
copy and hash-check the provisioned config, and run fixture-scoped readiness
checks.

The smoke-safe path must not install dependencies, build the repository, run
repository-wide tests, or invoke provider sync. Those operations are neither
retried nor downgraded in a child. After containment succeeds, verify the
fixture project artifacts and declared writable task files, then run
`git status --porcelain`.

The first command is the safe-init boundary. Any nonzero exit is a containment
failure: return immediately with `status: failed` and
`reason: smoke-init-failed`, regardless of whether the marker is missing,
unsafe, or malformed or a journal/config/bootstrap check failed. Never
apply `allow-failing` to that result. Run the remaining read-only/local checks
only after safe init succeeds. Never run PATH-resolved `oat` in smoke mode; the
built repository-local CLI entrypoint is the only permitted OAT executable.
Invoke the repository's direct smoke-safe entrypoint, not a package-manager
wrapper that may perform installation before reaching it. In this repository
that command is `bash scripts/worktree/init.sh`, not
`pnpm run worktree:init`.
Set the child worktree itself as the process working directory. Use the
equivalent of `(cd "$TARGET_PATH" && bash scripts/worktree/init.sh)`; invoking
the child script by absolute path while the shell remains in the outer
worktree is a containment failure.

Check behavior per baseline policy:

**strict mode:**

- Any check failure → immediately return error status with failure details.

**allow-failing mode:**

- Check failure → emit structured warning, continue to next check.
- Collect all warnings and include in final status output.
- Log failure context:
  - If active project with `implementation.md` exists → append timestamped baseline-failure note.
  - Otherwise → console output only (no fallback file creation).

### Step 4: Create Provider Directories and Sync

**Smoke mode:** skip provider-directory creation, all-scope sync, staging, and
sync commits. Do not run `mkdir` for provider views, `oat sync --scope all`,
`git add`, or `git commit`. After the safe local status/test checks in Step 3,
run only the final clean check:

```bash
git status --porcelain
```

Record `provider_sync: skip` and `sync_commit: skip`, plus every structured
smoke skip listed in Step 5. Any dirty result is handled as the `git_clean`
baseline check; it does not authorize cleanup, staging, or a commit.

**Normal mode:** worktrees do not inherit gitignored provider directories.
Create them if missing, run the `git_clean` baseline check, and then run sync:

```bash
mkdir -p "{target-path}/.claude/skills"
mkdir -p "{target-path}/.cursor/rules"
git status --porcelain
oat sync --scope all
```

After sync completes, commit sync-managed output if any scoped path is dirty:

```bash
SYNC_PATHS=(.oat/sync/manifest.json .claude .cursor .codex)
SYNC_STAGE_PATHS=(existing-or-tracked sync paths)
git status --porcelain -- "${SYNC_STAGE_PATHS[@]}"
git add -A -- "${SYNC_STAGE_PATHS[@]}"
STAGED_SYNC_FILES=(staged sync-managed files from git diff --cached)
git commit -m "chore: run sync" -- "${STAGED_SYNC_FILES[@]}"
```

Use a staged-diff guard so no empty commit is created. After scoped staging,
derive the concrete staged sync-managed files from
`git diff --cached --name-only --no-renames -- "${SYNC_STAGE_PATHS[@]}"` and
commit only those file paths. Do not pass provider directory pathspecs to
`git commit`, because empty provider directories can make the commit fail. This
file-list isolation is what keeps `chore: run sync` limited to sync-managed
paths even if unrelated files were already staged. If no scoped path is dirty,
or staging produces no diff, report `sync_commit: skip`.

### Step 5: Return Structured Status

Return a structured status object (for orchestrator consumption):

```yaml
status: success | error | warning | failed
worktree_path: '{absolute-path}'
branch: '{branch-name}'
base_ref: '{base-ref}'
resolved_base_sha: '{sha resolved from base-ref}'
observed_head_sha: '{sha of worktree HEAD after add}'
bootstrap_mode: normal | smoke
checks:
  repository_bootstrap: pass | fail | skip
  repository_readiness: pass | fail | skip
  baseline_verification: pass | fail | skip
  smoke_child_readiness: pass | fail | skip
  git_clean: pass | fail | skip
  provider_sync: pass | fail | skip
  sync_commit: pass | fail | skip
smoke_skips:
  local_config_propagation: true | false
  local_paths_sync: true | false
  provider_directory_creation: true | false
  provider_sync: true | false
  sync_staging: true | false
  sync_commit: true | false
warnings: [] # List of warning messages (allow-failing mode)
error: null # Error message (strict mode failure)
reason: null # e.g., base-mismatch, smoke-marker-invalid, smoke-init-failed, smoke-readiness-failed
expected_base_sha: null # Populated when reason is base-mismatch
baseline_policy: strict | allow-failing
```

`resolved_base_sha` and `observed_head_sha` are populated on **every** terminal status (success, warning, error, failed) so callers can perform belt-and-suspenders post-verification on the success path as well as diagnose the failure path.

`bootstrap_mode` is populated on every terminal status after Step 1.5.
`smoke_skips` is explicit on every terminal status: all six values are `true`
for smoke mode and `false` for normal mode.

**Status determination:**

- `success`: All checks passed and Step 2.7 base-resolution verification passed.
- `warning`: Some checks failed under `allow-failing` policy (Step 2.7 still passed).
- `error`: A baseline check failed under `strict` policy, or worktree creation failed.
- `error`: `sync_commit` failed under `strict` policy.
- `warning`: `sync_commit` failed under `allow-failing` policy.
- `failed` (with `reason: base-mismatch`): Step 2.7 base-resolution verification failed. Callers should treat this distinctly from a generic baseline error — it is a contract violation, not a flaky check.
- `failed` (with `reason: smoke-marker-invalid`): smoke mode was detected from
  the resolved base but the target marker is missing or unsafe.
- `failed` (with `reason: smoke-init-failed`): the marker is malformed or the
  safe-init containment path failed. Both smoke failure statuses are fatal
  under `strict` and `allow-failing`.
- `failed` (with `reason: smoke-readiness-failed`): fixture-scoped child
  readiness failed after containment. Stop immediately; do not dispatch a
  phase implementer, reviewer, or gate and do not degrade to sequential
  execution.

## Error Handling

| Scenario                                   | Behavior                                                                                                                        |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| Worktree creation fails                    | Return error status with git error message                                                                                      |
| Branch already checked out elsewhere       | Return error with worktree location info                                                                                        |
| Smoke marker missing or unsafe             | Return `status: failed`, `reason: smoke-marker-invalid`; never run propagation, sync, status, or tests                          |
| Smoke marker malformed or safe init fails  | Return `status: failed`, `reason: smoke-init-failed`; never downgrade under `allow-failing`                                     |
| Smoke fixture readiness fails              | Return `status: failed`, `reason: smoke-readiness-failed`; abort the run before any phase implementer, reviewer, or gate launch |
| Base mismatch (Step 2.7 fails, strict)     | Return `status: failed`, `reason: base-mismatch`, with `expected_base_sha` and `observed_head_sha`. Do not run baselines.       |
| Base mismatch (Step 2.7 fails, allow-fail) | Emit structured warning with `reason: base-mismatch`, log to artifacts, prefer fail-fast unless caller opted into degrade.      |
| Baseline check fails (strict)              | Return error with check name and failure output                                                                                 |
| Baseline check fails (allow-failing)       | Add to warnings, continue, log to artifacts                                                                                     |
| No active project                          | Skip artifact logging, use console only                                                                                         |
| Invalid branch name                        | Return error before attempting creation                                                                                         |

## Artifact Logging

When baseline failures occur under `allow-failing` policy and an active project exists:

Append to `implementation.md` under `## Implementation Log`:

```markdown
### {YYYY-MM-DD} — Baseline Warning (autonomous bootstrap)

**Worktree:** {path}
**Branch:** {branch-name}
**Policy:** allow-failing
**Failures:**

- {check_name}: {failure summary}
```

When a base mismatch is detected (Step 2.7) and an active project exists, append a distinct entry regardless of baseline policy so post-mortems can find it:

```markdown
### {YYYY-MM-DD} — Base Mismatch (autonomous bootstrap)

**Worktree:** {path}
**Branch:** {branch-name}
**Expected base SHA:** {expected_base_sha}
**Observed HEAD SHA:** {observed_head_sha}
**Base ref:** {base-ref}
```

## Policy Flags

| Flag                | Type                        | Default  | Description                                  |
| ------------------- | --------------------------- | -------- | -------------------------------------------- |
| `--baseline-policy` | `strict` \| `allow-failing` | `strict` | Controls behavior when baseline checks fail. |

**Policy details:**

| Policy          | On Failure                          | Logging                                    | Status Output     |
| --------------- | ----------------------------------- | ------------------------------------------ | ----------------- |
| `strict`        | Fail fast, return error immediately | Error in status output                     | `status: error`   |
| `allow-failing` | Continue, collect warnings          | Append to `implementation.md` (or console) | `status: warning` |

Containment failures are outside this table's baseline-failure policy. A
missing, unsafe, or malformed smoke marker and any smoke safe-init failure are
fatal under both policies.

**Orchestrator integration:**

- When invoked by `oat-project-implement` in parallel mode, the baseline policy is passed through from the orchestration run policy.
- The orchestrator may set `--baseline-policy allow-failing` for exploratory runs and `strict` for production-quality execution.
- The bootstrap skill does not interpret HiLL checkpoints — that responsibility belongs to the orchestrator.

## Constraints

- **Never** use `AskUserQuestion` — all decisions are policy-driven.
- **Never** create fallback artifact files — log to existing artifacts or console only.
- **Never** modify implementation code — bootstrap and checks only.
- **Never** override or conflict with `oat-worktree-bootstrap` manual-safe behavior.
- **Never** propagate caller-local config, sync local paths/providers, stage, or
  commit from smoke mode.
- **Never** use a PATH-resolved `oat` executable for smoke checks.

## Success Criteria

- Worktree exists and is on the correct branch.
- Bootstrap mode was derived from the resolved base before creation.
- Baseline checks executed per policy.
- Smoke mode completed safe init without any skipped side-effect path running.
- Structured status returned for orchestrator consumption.
- Failures logged to appropriate destination without user interaction.
