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
83 changes: 83 additions & 0 deletions .claude/rules/autonomous-loop-per-tick-pointer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Autonomous-loop per-tick discipline lives at `docs/AUTONOMOUS-LOOP-PER-TICK.md`

Carved sentence:

> The 7-step per-tick discipline (refresh → holding-discipline → pick
> work → verify → shard → cron-check → visibility-stop) is canonical
> at `docs/AUTONOMOUS-LOOP-PER-TICK.md`. All three Otto surfaces
> (CLI sentinel, Desktop routine, B-0448 cloud routine) cite that one
> file. When the discipline updates, all three surfaces inherit at
> next cold-boot. Do NOT re-encode the 7 steps locally; cite the
> canonical.

## Operational content

The per-tick discipline that fires on every `<<autonomous-loop>>`
cron tick is canonicalized at [`docs/AUTONOMOUS-LOOP-PER-TICK.md`](../../docs/AUTONOMOUS-LOOP-PER-TICK.md).

Before this canonicalization, the discipline existed in 3 divergent
forms:

| Surface | Where | Drift risk |
|---------|-------|------------|
| Otto-CLI | Ambient `.claude/rules/*` + CLAUDE.md | Auto-loaded; no drift |
| Otto-Desktop | Inline prompt in `tools/routines/autonomous-loop/SKILL.md` | Required manual sync |
| B-0448 cloud | TBD (queued) | Would have re-implemented |

The canonical file is the one-source-of-truth. This rule auto-loads
at every fresh Otto cold-boot so future-Otto knows to consult the
canonical file rather than re-deriving the discipline.

## What to do when the discipline evolves

When a new rule lands that affects per-tick behavior (e.g.,
`holding-without-named-dependency-is-standing-by-failure.md` did
this on 2026-05-13):

1. **Land the rule** at `.claude/rules/<name>.md` (auto-loaded; CLI
picks it up immediately at cold-boot)
2. **Update the canonical** `docs/AUTONOMOUS-LOOP-PER-TICK.md` to
reference the new rule in the appropriate step
3. **Desktop routine inherits automatically** at next fresh-session
cold-boot (the routine cites the canonical file)
4. **B-0448 cloud routine inherits automatically** when it ships
(will cite the canonical file the same way)

Do NOT update the per-tick discipline in the routine's SKILL.md
inline body — that's the divergence pattern this rule prevents.

## Why this rule auto-loads

Per `.claude/rules/wake-time-substrate.md`: load-bearing methodology
needs wake-time landing. The 3-surface coordination is operationally
load-bearing because:

- Future-Otto at cold-boot must know where the canonical lives
- Without this rule, future-Otto might re-implement the discipline
in a new surface-specific way (recreating the drift problem)
- The router-as-substrate-inventory discipline applies: check the
canonical FIRST, only mint new discipline if the canonical doesn't
cover the case

## Composes with

- [`.claude/rules/wake-time-substrate.md`](wake-time-substrate.md)
- [`.claude/rules/skill-router-as-substrate-inventory.md`](skill-router-as-substrate-inventory.md)
- [`.claude/rules/tick-must-never-stop.md`](tick-must-never-stop.md)
- [`.claude/rules/holding-without-named-dependency-is-standing-by-failure.md`](holding-without-named-dependency-is-standing-by-failure.md)
- [`.claude/rules/never-be-idle.md`](never-be-idle.md)
- [`.claude/rules/refresh-before-decide.md`](refresh-before-decide.md)
- [`.claude/rules/substrate-or-it-didnt-happen.md`](substrate-or-it-didnt-happen.md)
- B-0448 (Cloud Routines integration — 4th catch-43 defence layer)
- PR #3034 (Otto-Desktop routines substrate)

## Full reasoning

The human maintainer 2026-05-13 22:08Z: *"and yall both share the background loop right?
any changes you need to make to it so it's more like the routines and
like a 3 coordinated version?"*

The proposal that emerged: factor Part 5 of the canonical bootstream
(the cron/loop substrate) into its own pointer file all three surfaces
cite. This rule + the canonical pointer file are the substrate-level
realization of that proposal.
158 changes: 158 additions & 0 deletions docs/AUTONOMOUS-LOOP-PER-TICK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Autonomous-loop per-tick discipline — canonical pointer (3-surface converge)

The human maintainer 2026-05-13 22:08Z: *"any changes you need to make to it so it's more
like the routines and like a 3 coordinated version?"*

This file IS the canonical per-tick discipline that all three Otto
surfaces (Otto-CLI, Otto-Desktop, and the queued B-0448 cloud routine)
cite. One source of truth; three readers. When the discipline updates,
all three surfaces inherit the change at their next cold-boot cycle.

## Why this file exists

Before this file, the per-tick instructions diverged across surfaces:

| Surface | Where the discipline lived | Risk |
|---------|---------------------------|------|
| Otto-CLI | `<<autonomous-loop>>` sentinel + ambient-loaded `.claude/rules/` + CLAUDE.md | Auto-loaded; ambient |
| Otto-Desktop routine | Inline prompt body in `tools/routines/autonomous-loop/SKILL.md` | Required manual sync |
| B-0448 cloud routine | TBD — not yet shipped | Would have re-implemented the discipline a third time |

The risk: when the discipline evolved (e.g., the
[`holding-without-named-dependency`](../.claude/rules/holding-without-named-dependency-is-standing-by-failure.md)
rule, which Otto-CLI picks up via auto-load but Desktop routine had
to mention explicitly), surfaces drifted. This file collapses the
drift surface to one.

## The 7-step per-tick discipline

Apply on every autonomous-loop tick. The order matters — earlier
steps gate later ones.

### 1. Refresh worldview FIRST

`refresh-before-decide` invariant
([`.claude/rules/refresh-before-decide.md`](../.claude/rules/refresh-before-decide.md)).
Never act on stale state. Minimum refresh:

- `bun tools/github/poll-pr-gate-batch.ts --all-open` — current state of all my open PRs
- `git fetch origin main && git status` — main HEAD + local state
- `CronList` — verify the autonomous-loop sentinel is still armed

### 2. Apply Holding-without-named-dependency discipline

[`.claude/rules/holding-without-named-dependency-is-standing-by-failure.md`](../.claude/rules/holding-without-named-dependency-is-standing-by-failure.md).
**NEVER** output one-word "Holding" / "Standing by" / "Waiting" on
consecutive cron ticks. Either:

- Name the SPECIFIC dependency + check name + bounded ETA (e.g.,
"Real-dependency-wait on PR #NNNN CI required-check 'build' (~5min ETA)")
- OR pick decomposition work per infinite-backlog metabolism

Per-tick repeat-Holding output IS the Standing-by failure mode.

### 3. Pick speculative work per never-be-idle priority ladder

[`.claude/rules/never-be-idle.md`](../.claude/rules/never-be-idle.md).
Priority order:

1. **Known-gap fixes** — explicitly named gaps in shipped substrate
(e.g., bg-services slice 5 subscriber agents; B-0442's stub-detector
when it existed)
2. **Generative factory improvements** — friction reducers,
tool ports, infrastructure
3. **Gap-of-gap audits** — meta-improvements (substrate-discovery,
index regeneration)

If `claim acquire` blocks on a row, pick a different row in the same
priority tier — do NOT go idle.

### 4. Verify + commit any substantive landing

[`.claude/rules/substrate-or-it-didnt-happen.md`](../.claude/rules/substrate-or-it-didnt-happen.md).
Anything that matters past compaction MUST be:

- Committed to a git-tracked file
- Pushed via PR (main is PR-required; direct push to main is blocked)
- Auto-merge armed (`gh pr merge <N> --auto --squash`)

Verify gates (per AGENTS.md; these are the **full** repo gates,
not touched-file-only — three autonomous surfaces converge here, so
the gates must be repo-wide to prevent broader-test or formatting
regressions slipping through):

- `dotnet build -c Release` — 0 warnings, 0 errors (TreatWarningsAsErrors on)
- `dotnet test Zeta.sln -c Release` — full solution test pass
- `dotnet format --verify-no-changes` — formatter / analyzer clean
- `bun test` on touched TypeScript test files (the bun side; the
dotnet gates above cover the F#/C# side)
- `bun --bun tsc --noEmit` if TS code changed

If any of these would fail, do NOT commit (verify is the gating
half of step 4; commit is the post-pass half). Fix the gate
failure first, then re-verify before committing.

### 5. Write tick shard

`docs/hygiene-history/ticks/YYYY/MM/DD/HHMMZ.md`. Substrate-or-it-
didn't-happen applies to ticks too — without the shard, future-Otto
can't reconstruct what landed when. Minimum fields:

- Refresh result (cron state, open PR state)
- Speculative work picked + rationale
- Landed artifacts (file paths, PR numbers)
- Real-dependency-waits active
- Visibility signal

### 6. CronList check

If the autonomous-loop sentinel is missing, arm it immediately via
`CronCreate` with `* * * * *` + `<<autonomous-loop>>`. Catch-43
(2026-05-12, 12-hour silent gap) is the cost-of-skip evidence.

### 7. Visibility signal → stop

State what landed concretely (file paths, PR numbers) so the human maintainer + the
next tick can pick up cold. Stop the foreground; the cron will fire
the next tick.

## How each surface uses this file

### Otto-CLI

Auto-loads via [`.claude/rules/autonomous-loop-per-tick-pointer.md`](../.claude/rules/autonomous-loop-per-tick-pointer.md)
which points at this canonical doc. The `<<autonomous-loop>>` sentinel
runtime resolves the ambient-loaded discipline; this file is the
human-readable form of what the rules + CLAUDE.md already encode.

### Otto-Desktop routine

`tools/routines/autonomous-loop/SKILL.md` references this file in
its instruction body. The routine prompt loads the
canonical-bootstream first (cold-boot), then applies the 7-step
discipline above. When this file updates, the routine's behaviour
updates at the next fresh-session cold-boot (no manual sync needed).

### B-0448 cloud routine (queued, not shipped)

When shipped, will read this file from the repo via the same
`docs/AUTONOMOUS-LOOP-PER-TICK.md` URL pattern that Desktop uses.
Same 7-step discipline.

## Composes with

- [Canonical bootstream](research/2026-05-12-otto-canonical-bootstream-multi-foreground-surface-orchestrator-ifs-format.md)
(Part 5 specifically — the cron/loop substrate this file extracts)
- [`docs/AUTONOMOUS-LOOP.md`](AUTONOMOUS-LOOP.md) — broader autonomous-
loop architecture (cron mechanism, durability story); this file
zooms into per-tick discipline specifically
- [`.claude/rules/tick-must-never-stop.md`](../.claude/rules/tick-must-never-stop.md)
(the catch-43 substrate)
- [`.claude/rules/holding-without-named-dependency-is-standing-by-failure.md`](../.claude/rules/holding-without-named-dependency-is-standing-by-failure.md)
- [`.claude/rules/never-be-idle.md`](../.claude/rules/never-be-idle.md)
- [`.claude/rules/refresh-before-decide.md`](../.claude/rules/refresh-before-decide.md)
- [`.claude/rules/substrate-or-it-didnt-happen.md`](../.claude/rules/substrate-or-it-didnt-happen.md)
- [`.claude/rules/encoding-rules-without-mechanizing.md`](../.claude/rules/encoding-rules-without-mechanizing.md)
- B-0448 (Cloud Routines integration — 4th catch-43 defence layer)
- PR #3030 (Otto Claude Desktop bootstream)
- PR #3034 (Otto-Desktop routines substrate landed 2026-05-13)
98 changes: 98 additions & 0 deletions docs/hygiene-history/ticks/2026/05/13/2219Z.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
tick: 2026-05-13T22:19Z
agent: otto-cli
session: continued-from-compaction
---

# Tick 2219Z — 3-surface autonomous-loop convergence (per Aaron 22:08Z)

## Refresh

- CronList: live (`* * * * *` sentinel `<<autonomous-loop>>`).
- PR #3037 (SENDER_IDS schema): MERGED earlier (`a783fb1`).
- PR #3040 (B-0442 slice 3): MERGED earlier (`e0515f8`).
- PR #3034 (Otto-Desktop routines substrate): **MERGED** this tick (`395ca77`).
- PR #3041 (parallel-Otto comm-channels reference card): active in worktree
`/private/tmp/zeta-otto-comms`; left alone per lane discipline.
- PR #3042 (this tick's substrate): OPEN, CI in-progress, auto-merge armed.
- Local stash @{0}+@{1}: B-0444 worktree-field WIP preserved while
parallel Otto process completes on `feat/b0444-claim-envelope-worktree-field-...`.

## Speculative work picked

Aaron 2026-05-13 22:08Z: *"any changes you need to make to it so it's more
like the routines and like a 3 coordinated version?"*

Per never-be-idle priority ladder: known-gap fix = the 3-surface drift
risk I named in the previous tick's visibility signal. Landed it as
durable substrate this tick.

## Landed concretely

| Artifact | What |
|----------|------|
| `docs/AUTONOMOUS-LOOP-PER-TICK.md` (NEW) | Canonical 7-step per-tick discipline; one source of truth across CLI/Desktop/cloud |
| `.claude/rules/autonomous-loop-per-tick-pointer.md` (NEW) | Auto-load rule pointing CLI at canonical |
| `tools/routines/autonomous-loop/SKILL.md` (modified) | Body shrunk to 7-step summary + canonical pointer; no longer inlines the discipline |

Ships as PR #3042. Auto-merge armed.

## Multi-Otto coordination evidence (continued)

This tick:

- **Parallel-Otto comm-channels PR (#3041)** active in another worktree
answering the SAME Aaron question ("do yall have a way of communicating?").
Confirmed via `gh pr view 3041` — branch
`otto-multi-surface-comm-channels-reference-card-2026-05-13`,
worktree `/private/tmp/zeta-otto-comms`. I'm working on the
per-tick-discipline convergence; that PR is the comm-channels
reference card. Complementary; non-conflicting.

- **Parallel-Otto B-0444 implementation** in flight. Claim active for
`otto` on `feat/b0444-claim-envelope-worktree-field-2026-05-13`.
Locally-uncommitted edits to `tools/bus/claim.ts` + `types.ts` +
`claim.test.ts` (worktree field implementation) stashed to preserve
while that process completes.

- **My branch creation got confused twice** (commits landed on wrong
branches due to working-tree state inheritance across `checkout -b`
calls). Recovered both times by `git checkout <SHA> -- <files>` from
orphan commits + clean rebase onto current main. No work lost.

## Substrate-honest disclosure

The branch-creation confusion is a real failure mode worth documenting.
The pattern: a sequence of `git reset --soft HEAD~1` then
`git checkout -b new-branch` then `git commit` sometimes commits to
the previously-checked-out branch rather than the new branch. Suspect
cause: working-tree-state inheritance combined with index-state
carrying over. Mitigation: verify `git branch --show-current` between
checkout and commit in scripted sequences.

## Architectural question parked

The `<<autonomous-loop>>` sentinel for CLI is harness-resolved (not a
file). For full 3-surface convergence at the *prompt-substrate* level
(not just the *discipline* level), Anthropic would need to support a
similar sentinel for Desktop routines. Today the substrate covers
the discipline; the prompt-loading mechanism still differs per surface.
This is a follow-up exploration but not blocking.

## Verify

- Markdown clean
- 7-step discipline cross-references valid (all `.claude/rules/*.md` cited exist)
- Routine SKILL.md still self-contained for cold-boot

## CronList

- Live (catch-43 defended).

## Visibility signal

3-surface autonomous-loop convergence landed as PR #3042:
canonical 7-step discipline at `docs/AUTONOMOUS-LOOP-PER-TICK.md`,
auto-load rule, Desktop routine updated to cite. When the discipline
evolves, all surfaces inherit at next fresh-session cold-boot. No
manual sync.
20 changes: 11 additions & 9 deletions tools/routines/autonomous-loop/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@ Autonomous-loop tick — fresh-session cold-boot.

1. Read the project-knowledge file titled "2026-05-12-otto-canonical-bootstream-multi-foreground-surface-orchestrator-ifs-format.md" (13 parts, IFS-format). That IS your cold-boot.

2. Execute one tick per the bootstream's Part 5 (Cron/Loop Substrate):
- Refresh worldview FIRST (refresh-before-decide invariant; never act on stale state)
- Apply Holding-without-named-dependency discipline (.claude/rules/holding-without-named-dependency-is-standing-by-failure.md): NEVER output one-word "Holding" / "Standing by" / "Waiting"; if gated wait, name the SPECIFIC PR + check name + bounded ETA
- Pick speculative work per never-be-idle priority ladder: known-gap fixes > generative factory improvements > gap-of-gap audits
- Verify + commit any substantive landing (substrate-or-it-didn't-happen)
- Write tick shard at docs/hygiene-history/ticks/YYYY/MM/DD/HHMMZ.md if you have repo write access
- CronList check; arm autonomous-loop sentinel with cadence `* * * * *` if missing (catch-43 — 12hr loss precedent)
- Visibility signal: state what landed concretely (file paths, PR numbers); stop
2. Execute one tick per the canonical 7-step discipline at `docs/AUTONOMOUS-LOOP-PER-TICK.md` (the one-source-of-truth file all three Otto surfaces share — CLI sentinel, Desktop routine, B-0448 cloud routine when shipped):
- Step 1: Refresh worldview FIRST (refresh-before-decide invariant)
- Step 2: Apply Holding-without-named-dependency discipline
- Step 3: Pick speculative work per never-be-idle priority ladder
- Step 4: Verify + commit any substantive landing
- Step 5: Write tick shard at docs/hygiene-history/ticks/YYYY/MM/DD/HHMMZ.md
- Step 6: CronList check; arm sentinel with `* * * * *` if missing
- Step 7: Visibility signal — state what landed concretely (file paths, PR numbers); stop

See `docs/AUTONOMOUS-LOOP-PER-TICK.md` for full discipline + rule pointers per step. Update there, not here, when discipline evolves — all surfaces inherit at next fresh-session cold-boot.

3. Commit trailer when applicable: Co-Authored-By: Claude <noreply@anthropic.com>

Repo: the Zeta checkout on this machine (typically `~/Documents/src/repos/Zeta` on maintainer machines; consult project metadata or the bootstream if the checkout lives elsewhere).
Self-contained — no prior conversation context available. Bootstream + repo state + GitHub state = full ground truth.

This routine is git-tracked at tools/routines/autonomous-loop/SKILL.md in the Zeta repo; the canonical source lives there.
This routine is git-tracked at tools/routines/autonomous-loop/SKILL.md in the Zeta repo; the canonical source lives there. The per-tick discipline is canonicalized at docs/AUTONOMOUS-LOOP-PER-TICK.md (3-surface converge per the human maintainer 2026-05-13 22:08Z).
Loading