---
name: ask-ollie-workspace-bootstrapper
description: "Bootstrap one connected client workspace into a working intake-to-execution runtime. Discovers that workspace's own Outloop facts live, then generates, installs and verifies a tenant-local dispatcher and operator pair, a tenant-config file, one control task that names the single runtime owner, and one workspace-scoped schedule. Provider-neutral by construction: mail arrives through a replaceable adapter, the project-management task is the durable visible record, duplicate execution is prevented by outloop.execution.claim, and one operator is the single execution path for every origin. Missing optional context limits actions without cancelling independent work. Host access, identity and schedule proofs gate operational status; unresolved prerequisites are reported explicitly. Use for \"bootstrap this workspace\", \"set up the intake runtime here\", \"generate the tenant skills\"."
---

# ask-ollie-workspace-bootstrapper

**Package version: `v3.8.1-rc.4`.** The version this package records about itself, and the value every
generated artifact's build stamp carries (`references/generation-and-drift.md`). The frontmatter
`name` is frozen and is never edited.

**The runtime doctrine is frozen at this version: a change to what a generated skill does belongs in
a new version, not in commentary added here.**

## Purpose

A generator, not an executor. Run it from inside **one** connected workspace — a folder with its
own Outloop-managed instruction block (for example `CLAUDE.md` or `AGENTS.md`), its verified
resource bindings, and its own `.claude/kestrel-direct/`. A host-specific adapter resolves actual
paths and supported tools; a cloud sandbox is not the connected workstation.

It reads that workspace's real, already-granted Outloop facts and installs a runtime that turns any
authentic request — from the PM system, from mail, from a meeting — into executed, verified,
reconciled work. It never touches another workspace and never creates a cross-tenant execution
runtime.

## The runtime model — three real components, no invented fourth

This package preserves primitives documented in the supplied baseline. Verify the live host contract;
this rebuilt candidate has not been imported or runtime-tested on a customer workstation here.

| Component | What it is | What it holds |
|---|---|---|
| **The project-management task** | The durable, visible, auditable record | Origin · provider · thread and message references · `SOURCE_EXECUTION_KEY` and `PM_ROLE` where the request entered elsewhere · task state · communication state · gates · approval evidence · remaining work · evidence · final result |
| **`outloop.execution.claim`** | The lock and duplicate-execution prevention | Exactly-once ownership of one occurrence · `execution_key` · `attempt` · `max_attempts` |
| **`outloop.execution.report`** | Result, outcome code, and whether this occurrence is spent | `result` · `outcome_code` · `output_ref` · `status` · `attempts` · `escalation_required` |
| **`outloop.task.finalize`** | Verified completion, where it fits the existing contract | The closing record |

There is **no key-value store, no conditional write, no `record_version`, and no
`outloop.context.set`.** The workspace context is read-only to an agent. Nothing in this package
may claim otherwise, design against a store that does not exist, or reimplement what
`execution.claim` and `execution.report` already do.

This package also writes a **station health spool** — a small, bounded, append-only record of
run-level outcomes for runs that hold **no claim** and so have no `execution_key` to report against,
chiefly a licence outage during which every Outloop verb is denied. It is not an Outloop primitive
and not a second execution record; it holds outcome codes and identifiers only, and it syncs to
Outloop and stands down the moment the service returns. **It is shared by every workspace on the
station, so every line carries `workspace_id` and a lineage is keyed on the pair (`workspace_id`,
`outcome_code`)** — one deliberate exception, `last_alarmed_on`, is keyed on the code alone, because
suppressing nine alarms for one station-level gate is the only reason the file is shared at all.
*Non-normative here; `references/license-preflight.md` **owns all of this** and where the two
differ, it governs. Anchor:
⟪license-preflight.md ▸ **The lineage key is the pair (`workspace_id`, `outcome_code`), and this row owns it.**⟫*

*(The sentence that stood here — "the one local file this package writes is the station health
spool" — was false. This package writes at least four: two generated skill folders,
`tenant-config.md`, and the spool. And `tenant-config.md` is written at run time as well as at
install, whenever a binding is corrected (`scheduling.md`; `failure-recovery.md`, *Feedback
learning*). It was also a sole-occupancy claim of exactly the shape S16 forbids, about a different
subject. Scoping it was cheaper than defending it.)*

**The mail provider holds no state.** No labels, no categories, no flags, no folders used as
status. Ever. State lives on the task and in the Outloop execution record.

The baseline contract reference is `references/runtime-contract.md`. Read it and compare the live
host contract before generation. Do not invent missing primitives or edit the managed contract.

## The flow it installs

```
Adapter → Workspace Resolver → execution.claim → PM task (the record, created by the claim holder)
        → Dispatcher → Operator → authorized API / provider MCP / Browser → Verification
        → execution.report → task reconciliation
```

**The claim precedes the task, and only the claim holder creates one** (`references/dispatcher.md`,
**intake step 5** — a sub-step of Step 4, never a run-order ordinal). Reversing those two steps
lets two racing dispatchers each create a task before either claims, which defeats the whole
duplicate-prevention argument (`references/runtime-contract.md` §5.2, §5.4).

Each layer must be replaceable without touching the others. That is the test. A new mail provider
is an adapter change only. A new cadence is a dispatcher change only. A new capability is an
operator change only.

## Boundaries

- **Adapter normalizes only.** Stateless. It knows the mail provider's API and nothing else — not
  tenants, not work, not what is interesting. Raw message in, canonical envelope out.
- **Workspace Resolver** maps mailbox / project / origin → the one correct `workspace_id`. It
  resolves identity; it never decides what to do.
- **The PM task** is the durable record of what we decided. It is not a mirror of the mailbox — the
  mail lives at the provider. It is visible, auditable, and a human can read it without a tool.
- **Dispatcher** decides **what is next** and **whether to run**, claims each occurrence through
  `execution.claim`, and stands down when it is not the recorded runtime owner. It **never performs
  client work.**
- **Operator** is the **single execution path**. One path for every origin — no provider condition
  anywhere in it, no separate branch for one mail provider versus another, none for mail versus
  PM-system origin.
- **Watchdog / safety-net skills intake and record only.** They detect, they write findings onto
  the task, and they stop there. They never perform platform work.

## What governs

This package installs skills that are governed by three canonical doctrine skills. **Point at them;
do not restate them.**

| Skill | Governs |
|---|---|
| `ask-ollie-authority-core` | Authority, supersession, the ghost rule, cycle keys, the manifest, hard stops. Where anything disagrees with it, it wins. |
| `outloop-access-fallback` | How Outloop and the browser combine, and the one boundary between them. |
| `email-lifecycle-core` | Email dispositions, reconciliation, the update contract, approval evidence, noise rules. |

Every generated skill loads all three by name on every run and states in its own `SKILL.md` that
they govern over anything in its own package.

**One canonical ruling, owned by `references/runtime-contract.md` §5: the source of execution is
separated from the record of documentation.** *Anchor:*
⟪runtime-contract.md ▸ **This section owns the ruling and both sentences.**⟫

> *The eight lines that follow are a **non-normative summary**. `runtime-contract.md` §5 owns this
> ruling in full; where this summary and §5 differ, §5 governs. Anchor:
> ⟪runtime-contract.md ▸ **No upstream amendment is required.**⟫*

The live runtime's assignment rule applies to a **project-management task as a request source** — an
unassigned task is not an instruction. A message that arrived through a connected mailbox and
resolved to a workspace is an **independent execution source**: it claims as `api_trigger` on the
mail source, and the PM task it creates is the audit and continuity record, not the trigger. So
`email-lifecycle-core`'s *"email-origin tasks are never gated on assignment"* is **correct as written
and confirmed by the ruling**, scoped to email-origin requests; **no upstream amendment is required.**

### One normative source, and restatements that say so

A rule is **owned** by exactly one file. Other files may restate it — readability is worth
something — but a restatement must be **marked non-normative and must name its owner**, exactly as
the block above does. That is the whole convention, and it is the only thing that makes a
restatement safe.

> **Never write "this is the only place X appears" about anything.** Not about the ruling, not about
> provider names, not about anything else. Such a sentence tells the next maintainer that a class of
> defect cannot exist here, so they stop looking — and in this package **every single one of those
> sentences was false when it was written.** One claimed §5 was the sole statement of the ruling
> while the eight lines directly above it restated it and four other files touched it. Another
> claimed one file was the sole file naming a mail provider while the same file named two twelve
> lines earlier. Name the owner instead. An owner is checkable; a global absence claim is not.

**Where a reference and this file disagree, the reference is wrong and gets fixed.** Never add a
precedence note, and never add an instruction to reinterpret or work around what a reference says.

## Facts never live in logic — and the agent never writes the context

Client facts, KPIs, targets, spend ceilings, currencies, approval rules, contacts and their `Side`,
language, compliance terms and standing exceptions live **only in the Outloop Workspace Context**,
read live on every run through `outloop.context.get`.

**The agent never modifies the context.** A durable new rule or learning goes through
`outloop.learning.submit` into the existing Learning Inbox and approval flow; only the approved
Outloop mechanism then updates the context. There is no `outloop.context.set` and no generated
skill may imply there is. See `references/workspace-context-readiness.md`.

Never hard-code a per-client rule, a person, a mailbox, a platform account or a target into a
generated skill. A live read beats every static list, including `tenant-config.md` and including
this file.

**A missing KPI or an incomplete Workspace Context never blocks useful work.** It is not `BLOCKED`
and it never ends a run. **Where the absent field is one the intended mutation requires**, the run
enters **`CONTEXT_GAP_DISCOVERY`**: it reads everything that does
exist, inspects live systems read-only, derives a baseline and the most reasonable target, marks
every conclusion `PROVISIONAL_ASSUMPTION` with source, date and confidence, performs the safe
reversible work the evidence and the existing grants support — and where no safe mutation can still
be chosen, returns a diagnosis, an execution plan, a proposed KPI and one concrete next action.
An assumption never bypasses the spend ceiling, client-send approval, an irreversible action,
compliance and policy, or an explicit client instruction not to touch something.

> *The paragraph above is a **non-normative** restatement.
> `references/workspace-context-readiness.md`, *Missing KPI or incomplete context never blocks
> useful work*, **owns** the doctrine, the eight obligations, their identifiers and the state; where
> that section and this paragraph differ, that section governs. Anchors:
> ⟪workspace-context-readiness.md ▸ **A missing KPI, target or context field is not `BLOCKED`, and is never a reason to end a run.**⟫
> ⟪workspace-context-readiness.md ▸ **The state is entered when the absent field is one the intended mutation requires**⟫*
>
> **It is a SHORTER restatement, and it says so rather than dropping two obligations silently.** The
> paragraph carries six of the eight; `CGD-4` (benchmark research) and `CGD-8` (record and submit)
> are the owner's and are not summarised here. **A scoped shorter restatement is legitimate; a silent
> one is the defect** — the owner states that rule and static test **S22** enforces it, which is why
> the scope marker and one anchor per claimed obligation stand below.
> ⟦CGD: 1,2,3,5,6,7⟧
> ⟪workspace-context-readiness.md ▸ **(CGD-1)** Read all the context that **does** exist — the request, its full history, and the task.⟫
> ⟪workspace-context-readiness.md ▸ **(CGD-2)** Inspect live systems and performance, **read-only**.⟫
> ⟪workspace-context-readiness.md ▸ **(CGD-3)** Derive a baseline, and the most reasonable target, from that data.⟫
> ⟪workspace-context-readiness.md ▸ **(CGD-5)** Mark every conclusion `PROVISIONAL_ASSUMPTION`, each carrying its **source, its date and a confidence**.⟫
> ⟪workspace-context-readiness.md ▸ **(CGD-6)** Perform the permitted, safe, **reversible** work that the evidence gathered and the grants already held actually support.⟫
> ⟪workspace-context-readiness.md ▸ **(CGD-7)** Where no safe mutation can still be chosen, return **a diagnosis, an execution plan, a proposed KPI and one concrete next action with a named owner** — never "blocked".⟫

**The readiness ladder is a boundary on mutations, never on the run** — same owner, same section's
ladder. A low tier narrows what may be changed; it never stops a run from reading, researching,
diagnosing, recording or reporting.

## What a bootstrap creates

1. `ask-ollie-dispatcher-t0XX/` — tenant-local dispatcher, scoped to this workspace's own intake
   surface. Carries the adapter and resolver as bounded reference files so a provider swap is a
   one-file change.
2. `performance-marketing-operator-t0XX/` — tenant-local operator, the single execution path.
   General-purpose: it executes whatever the workspace's context and the request describe. **The
   name is a frozen legacy identifier only.** Its content carries zero advertising, campaign,
   creative, platform or client assumption, and that is verified by grep before it is saved.
3. `tenant-config.md` — bindings and evidence tags only (LIVE / DOC / UNCONFIRMED). Bindings, not
   facts.
4. **One runtime-ownership control task**, created automatically in this workspace's connected PM
   system — see `references/intake-ownership.md`. No manual step, ever.
5. One **workspace-scoped** schedule invoking only this workspace's own dispatcher.

`t0XX` is this workspace's own Outloop tenant id, resolved live. **The folder's name or leading
number is an advisory label, never the tenant id.** Identify a workspace by its resolved id and its
PM project binding, never by display name and never by folder number. If the resolved id collides
with an established local naming suffix, generate per the resolved id and **flag the collision** —
do not rename anything.

The three names are frozen: `ask-ollie-workspace-bootstrapper` · `ask-ollie-dispatcher-t0XX` ·
`performance-marketing-operator-t0XX`.

## Install flow

**Install Step 0 — dependency check.** *(A step of this install flow, not of a scheduled run; run-order
ordinals are owned by `references/dispatcher.md`'s* Run order *and the two sequences never share a
numbering. Anchor: ⟪dispatcher.md ▸ **This file OWNS the order in which a scheduled run does things, and this section is that order.**⟫)*
Confirm `ask-ollie-authority-core`, `outloop-access-fallback` and
`email-lifecycle-core` are all present. If any one is missing, return the precise code —
`DEPENDENCY_MISSING: email-lifecycle-core` — and **stop. Create no partial skills.** Without the
doctrine, generated skills point at nothing. See `references/generation-and-drift.md`.

1. **Confirm actual host access and workspace identity.** Resolve this workspace's managed contract
   and Local Bridge. Complete the install-stage safe transport check using the live protocol; generation requires it. No host
   access or unanswered bridge means `runtime_blocked_not_connected`; report evidence, not success.
2. **Discover** live facts using `references/workspace-context-readiness.md` and
   `references/workspace-resolution.md`. Do not re-ask known facts. Mark unknown facts UNCONFIRMED;
   ask only for a required identity, timezone, access or approval that cannot be resolved safely.
   Discover permitted MCP/browser routes dynamically; do not use the connector list to judge Outloop.
3. **Compute the readiness tier** and record it. It is recomputed every run thereafter.
4. **Generate** both skills plus `tenant-config.md`, each carrying the build stamp
   (`references/generation-and-drift.md`). Copy the reference files each generated skill needs into
   its own package so it never depends on this one staying installed.
5. **Install**, then reopen the installed files — from their installed path, never the in-memory
   copy — and verify them against the acceptance list in `references/behavioral-tests.md`. The
   re-read must show **the build stamp this run wrote**: `generated_from_package`, `package_version`
   and `package_sha256` byte-identical to the generated values (acceptance item 39). A mismatch is a
   failed install, not a drift finding.
6. **Resolve or create the runtime-ownership control task** under bootstrap authorization, then read
   it back. Reuse the existing record and active owner when rerunning; do not duplicate it.
7. **Resolve/create the schedule** under `references/scheduling.md`: prefer project scope; allow
   a global schedule only with an explicit recorded owner exception. Verify the stored host folder,
   scope, cadence/timezone and single owner, then the controlled and autonomous run receipts. A
   missing grant permits only an approved diagnostic catcher, not a false operational declaration.
8. **Report** the lifecycle state, the readiness tier, every `UNCONFIRMED` field, and the build
   stamp with its drift status.

Presenting packages is a checkpoint, never the ending. Do not pause after installation to ask
whether the schedule should be created. Do not re-run discovery afterwards.

## Responsibility split

| | Adapter | Resolver | PM task | Outloop execution record | Dispatcher | Operator |
|---|---|---|---|---|---|---|
| **Knows** | one mail provider's API | identity bindings | what we decided | who owns this occurrence | cadence, ownership, cycle | context, tools, the work |
| **Does not know** | tenants, work | what to do | who is running now | the content of the work | the content of the work | schedule, cadence, provider |
| **State** | none | none | **is the visible state** | **is the execution state** | none between runs | none between runs |
| **Executes work?** | no | no | no | no | **never** | yes — the only one |
| **Client-facing message** | carries `body_html` verbatim, out and back — never edits it | no | holds `RENDER_READBACK` | no | never composes or sends one | **emits the one canonical HTML message** — direction, alignment and LTR isolation applied by rule, then read back from the provider |
| **Swap point** | new mail provider | new PM system | new PM system | — | new cadence | new capability |

## References

| File | Carries |
|---|---|
| `runtime-contract.md` | **Read first.** The verbatim live contract, the `source_type` mapping by source, the execution key, and the canonical ruling separating execution source from documentation record. Anchor: ⟪runtime-contract.md ▸ **This section owns the ruling and both sentences.**⟫ |
| `license-preflight.md` | **Step 0** of every scheduled run (§§1–4) and the **Step 3** licence-recovery step (§5) — ordinals owned by `dispatcher.md`'s run order · `RUNTIME_UNVERIFIED_LICENSE` · **the station health spool**, the durable local sink for a run that holds no claim, **its lineage key — the pair (`workspace_id`, `outcome_code`) — and the one field deliberately keyed on `outcome_code` alone, `last_alarmed_on`** · its lossless compaction and its blocking appender lock · the recovery event. Anchors: ⟪license-preflight.md ▸ **The lineage key is the pair (`workspace_id`, `outcome_code`), and this row owns it.**⟫ ⟪dispatcher.md ▸ **This file OWNS the order in which a scheduled run does things, and this section is that order.**⟫ |
| `task-record.md` | The PM task as the durable record: title rule, thread↔task rules, marker fields, the three axes, reconciliation, drain order |
| `intake-ownership.md` | The runtime-ownership control task, created automatically; the stand-down and **the station health spool it is written to**; handover and rollback |
| `workspace-context-readiness.md` | **The owner of the context-gap doctrine** — a missing KPI, target or context field never blocks useful work, **and the state it enters where the absent field is one the intended mutation requires**, `CONTEXT_GAP_DISCOVERY`, with the eight things that state requires. Plus the five readiness tiers as **a boundary on mutations, never on the run**, the minimum context contract for each, and the read-only context contract. Anchor: ⟪workspace-context-readiness.md ▸ **A missing KPI, target or context field is not `BLOCKED`, and is never a reason to end a run.**⟫ |
| `mail-adapters.md` | **Owner of every provider-specific execution detail.** Canonical envelope, per-provider mapping, thread identity, duplicate-thread safety, and the send / read-back mechanics for an HTML body. Anchor: ⟪mail-adapters.md ▸ **The boundary is a provider condition in a decision path — not a provider name.**⟫ |
| `workspace-resolution.md` | Mailbox / project → workspace, unresolved handling, tenant isolation |
| `dispatcher.md` | **The owner of the run order.** The single authoritative, numbered, ordinal sequence every scheduled run follows — **Step 0** licence preflight · **Step 0.5** grant preflight · **Step 1** ownership check · **Step 2** dependency check · **Step 3** licence-recovery incident claim (`active_runtime_owner` only) · **Step 4** intake scan · **Step 5** drain and per-item dispatch — plus **why no claim is made over the run's own firing**, the note distinguishing these ordinals from the **five other numbered sequences** that share their digits, then intake, drain, freshness, the per-item claim, and the operator envelope. **Every run-position claim in every other file cites an ordinal from here (static test S20).** Anchor: ⟪dispatcher.md ▸ **This file OWNS the order in which a scheduled run does things, and this section is that order.**⟫ |
| `operator.md` | Single execution path, manifest, verification, supersession, the corrected QA rule |
| `communication-approval.md` | Draft-first default, approval evidence, send proof, inward-first lanes, and the rendering contract — direction, alignment, bidi isolation, no Markdown, post-send read-back |
| `api-browser-routing.md` | Action-level routing between Outloop and browser/Computer Use |
| `scheduling.md` | Cadence, timezone, workspace-scoped creation, verify-from-cron, arm-pending-grant |
| `failure-recovery.md` | Denial classification, recovery order, partial work, never-a-bare-blocked |
| `migration-rollback.md` | Staged rollout, one-field handover, rollback at every stage |
| `generation-and-drift.md` | Dependency check, the build stamp, drift as a finding, naming, copied references |
| `behavioral-tests.md` | Provider-agnostic end-to-end tests, the generation acceptance list, and what needs a greenfield tenant |
| `product-requests.md` | The narrow runtime-owner primitive request and the station-level licence monitor — neither blocks V3. Anchor: ⟪product-requests.md ▸ Two narrow requests. **Neither blocks V3.**⟫ |

## Success conditions

A bootstrap succeeds when **all** of the following read back true:

1. The dependency check (**install Step 0**, a separate install sequence from the run order)
   passed before anything was generated.
2. Both generated skills are installed and re-read, and pass the acceptance list in
   `behavioral-tests.md`.
3. `tenant-config.md` exists, with every field carrying an evidence tag.
4. The runtime-ownership control task exists in this workspace's PM system, names exactly one
   active runtime owner for this intake key, and reads back.
5. The actual schedule has verified project scope or a recorded authorized scope exception, the
   correct host folder, intended cadence and timezone. Controlled and autonomous scheduled runs
   reach this bridge and terminate with evidence; metadata/Step 0 alone is insufficient.
6. Exactly one dispatcher owns this intake surface, and no duplicate schedule exists.
7. The readiness tier is computed and recorded — **at any tier.** A low tier is a true report, not
   a failure.
8. Every generated artifact carries a checked build stamp and current status. Unknown runtime drift
   is reported honestly; a proposed installation whose content does not match its approved hash
   is not accepted. Suspected tampering or wrong-tenant content is a security boundary, not drift.

### Lifecycle states

`bootstrap_built` → `skills_installed` → `ownership_task_created` → `schedule_created` →
`runtime_operational`.

- `runtime_armed_pending_grant` — everything above, but a required grant is still missing. The
  catcher is live and self-heals on the next pass.
- `runtime_blocked_wrong_context` — invoked from outside this workspace. Name the workspace to
  open, and stop. A schedule created from the wrong context is worse than none.
- `runtime_blocked_dependency` — a governing doctrine skill is missing. Nothing was generated.
- `runtime_blocked` — no resolvable intake surface at all.
- `runtime_blocked_not_connected` — verified host bridge unavailable; no false provider proof.
- `runtime_pending_scheduling` — an arming prerequisite is unmet; `schedule_armed: false`, exact
  missing prerequisite and owner action. `references/scheduling.md` owns the arming gate.
- Legacy `runtime_armed_pending_folder_attachment` / `runtime_armed_pending_project_scoped_schedule`
  labels may describe a previously enabled trigger only with stored read-back, never new arming
  without prerequisites; report its limitation and resolve safely under the scheduling owner.
- `runtime_pending_scheduled_proof` — saved schedule awaiting controlled/autonomous run evidence.

Creating files is not installing. Installing is not creating the ownership task. Creating the
ownership task is not creating the schedule. Report completion only after all four.

## Distribution

The three governing doctrine skills are present on the account this package was built on. **On a
different account their presence is not guaranteed.** A public distribution of this package must
bundle or install `ask-ollie-authority-core`, `outloop-access-fallback` and `email-lifecycle-core`
**as one package** with the bootstrapper. Until it does, install Step 0 is what stands between a
fresh account and a runtime that points at nothing.

## Never

- Never put a **provider condition in a decision path** — no `if provider == …`, no per-provider path
  through the dispatcher or the operator. Provider mechanics live in `mail-adapters.md`; provider
  *names* in tests, examples and proof reports are fine.
- Never generate a skill that assumes a specific PM system, ad platform, country, mailbox, client or
  person.
- Never write "this is the only place X appears" about anything. Name the rule's **owner** instead,
  and mark every restatement non-normative.
- Never create a PM task for an email before the mail-source claim has returned
  `EXECUTION_CLAIM_OK`. Only the claim holder creates the task.
- Never report a run that could not see as "queue clean" or "no work" — it is `UNVERIFIED`, and the
  station health spool is where it says so.
- Never write client content or a secret into the station health spool — outcome codes and
  identifiers only.
- Never `rename()` a replacement over the station health spool. Compaction holds an exclusive lock
  and rewrites in place; a rename over an inode that open writers may hold **silently drops every
  append made in that window**, which can orphan a lineage's only entry.
- **Never assert when one step of a run happens relative to another without citing an ordinal from
  `references/dispatcher.md`'s run order and naming it as owner — and never cite one that disagrees
  with it.** That file is the single authoritative run order. A run order claim such as "before the scan" / "before
  anything" / "runs first" / "after Step N" / "at the start of every run" claim that cites no owner
  is the defect class static test S20 exists to catch — **six** consecutive revisions regressed on
  it. Anchor:
  ⟪dispatcher.md ▸ **This file OWNS the order in which a scheduled run does things, and this section is that order.**⟫ *(S20's detector is **derived** as of v3.1.4 — any temporal relation standing within one
  sentence of a named run step — because the enumerated phrase list it replaced could only catch
  phrasings someone had already found, and did not contain "at the start of". **S20 gained a second
  command in v3.1.5**: it derives the step-name↔ordinal map from the run order table itself and
  checks that every ordinal cited against a named step is that step's own. Until then S20 checked
  that a citation was **present** and never that it was **right**, so a citation naming one step while
  carrying another step's ordinal would have passed.)*
- **Never fix one site of a shared concept without grepping the whole package for that concept.**
  Six of the eight regressions were one species: a correction applied to one site and not to its
  neighbour, leaving two files disagreeing about when something happens relative to something else.
  Round 5's regression sat **twenty lines above** the section it edited, in the same file. The run
  order and S20 are the structural half of that fix; this is the procedural half, and neither works
  alone. **The eighth regression fell outside S20's band entirely** — a restatement that named its
  owner and then said something the owner does not — which is why **every restatement that names an
  owner now carries a verbatim quoted span from the owner it names**, and why static test **S21 owns
  that check** (`references/behavioral-tests.md`). **Its population is every cross-file reference in
  the package**: each occurrence is anchored or falls in a declared named class, and the check prints
  its own uncovered set rather than asserting totality. **And an anchor pins one span, which an
  enumeration restated shorter survives** — including a member's load-bearing safety property
  reworded in place. **Static test
  S22 owns that check**: the enumeration carries stable identifiers, every restatement declares which
  members it claims, and every claim carries a member-bound anchor. Anchors:
  ⟪behavioral-tests.md ▸ **Every owner-citing restatement AGREES with the owner it names**⟫
  ⟪behavioral-tests.md ▸ **A restated ENUMERATION carries the members it claims**⟫ A discipline needs someone to
  think of the concept; a control does not.
- Never write **client-specific** facts, KPIs or approval rules into a generated skill, and **never
  write to the workspace context** — learnings go through `outloop.learning.submit`. *(The package's
  **client-independent default `client_send_policy` block** in
  `references/communication-approval.md` is not one: every value in it is identical in every
  workspace, it names no client, person, mailbox, account or target, and the live context read wins
  over it on every run. Acceptance item 6 carries the same scoping, and the readiness ladder requires
  such a block to exist at all. **What is forbidden is a client-specific value, not a
  client-independent default.**)*
- Never claim a key-value store, a conditional write, a record version or a context write exists.
- Never build a second lock over **work**, mutation retry counter, retry schedule or execution record.
  Use live claim/report ownership and budget, and distinguish mutation attempts from task-recovery
  approaches. Read back uncertain writes before another possible effect. Do not hard-code a count.
  `references/runtime-contract.md` §2 **owns the contract**; non-normative here. Anchor:
  ⟪runtime-contract.md ▸ **The budget lives in the contract, it is READ rather than assumed, and there is exactly one.**⟫.
  *(The advisory file lock that serializes station-health-spool
  compaction is not one of these — it guards one local file's bytes during a rewrite, has no owner,
  expiry or counter, and never decides who executes anything. See
  `references/license-preflight.md`.)* *(Nor is the **bounded re-poll of a non-brokered tool** in
  `references/api-browser-routing.md`: a tool Outloop cannot broker at all has no governed path and
  therefore no `execution.report` budget to double. The re-poll is bounded to the current run and
  ends when the run ends. The product of
  governed-path budgets is still 1 — static test **S11 owns this check** and names it, and acceptance
  item 10 carries the same scoping. Anchors:
  ⟪license-preflight.md ▸ **This lock is not a lease, and not a second execution lock.**⟫
  ⟪api-browser-routing.md ▸ **The bound is the run, and it is not a retry budget.**⟫)*
- Never store state on the mail provider — no label, no category, no flag, no folder as a status.
- Never run unapproved live client mutations as an installation test. Use sanitized checks first;
  a bounded approved read-only host/scheduler proof is required before operational acceptance.
- Never re-ask a fact or approval already available. Ask only the smallest genuinely unresolved
  access/identity/timezone/approval question; optional unknown facts must not cancel independent work.
- Never execute a project-management task that is not assigned to the configured Agent identity, and
  never re-take an email-origin record as a `project_management` request.
- Never let a failed auto-assignment on an email-created task cancel, delay or re-gate the email
  request it documents.
- Never invent a universal thread id, and never merge two conversations when uncertain.
- Never treat a flat global schedule listing as proof that a schedule is bound to this workspace,
  and never report a schedule verified from a rendered summary string.
- Never bypass an explicit operation/resource refusal through another route. Consume the installed
  `outloop-access-fallback` for API, provider MCP and browser order; no blanket MCP prohibition is
  introduced here. Never confuse transport silence, technical gaps and answered policy refusals.
- Never work around an inactive licence by any means, and never report "no work" during one.
- Never create or depend on a cross-tenant execution runtime, and never read or write another
  workspace's account, grant, project or files by any path.
- Never claim operational completion without the verified ownership record and scheduled execution
  proof. A pending deployment with a precise external action is an honest outcome, not success.


## Bundled deterministic helpers

Use `scripts/runtime_guards.py` to check observed route/schedule/cycle/recovery facts; it is not a live
authorizer and unknown facts must not be replaced with true. `scripts/bridge_probe.py` publishes
one bounded safe preflight only after host identity is verified. `scripts/generate_runtime.py`
produces a new scratch-only pair and refuses overwrites. Run the release's local tests before
using changed helpers. Actual host permission, provider and scheduled proofs remain mandatory.

Use `scripts/run_receipts.py` for scoped diagnostic start/phase/terminal records when compatible
with the host. These are not execution claims. A killed process can leave STARTED; the next health
check must surface the missing terminal result instead of trusting the scheduler success label.
