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
39 changes: 39 additions & 0 deletions .claude/rules/refresh-world-model-poll-pr-gate.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,45 @@ the script** rather than fall back to one-off bash.

`poll-pr-gate-batch.ts --all-open` fires ~N `gh pr view` calls (N = open PR count, ~37 in cascade-mode). At 4× polls per cascade hour + cross-tick `gh` operations + multi-agent shared-token consumption (Otto-CLI + Otto-Desktop + Lior + Vera + Riven all draw from Aaron's user-token), the 5000 GraphQL/hour budget exhausts. Empirical anchor: 2026-05-15T22:21Z session hit `{remaining:0, used:5005}` mid-cascade. When `gh pr view` returns `GraphQL: API rate limit already exceeded`, `gh api rate_limit --jq '.resources.graphql.reset'` gives a bounded named-dependency ETA. Avoid `--all-open` more than 1-2× per cascade window.

## Rate-limit operational tiers (empirical mode-table)

Empirical from the 2026-05-16T04:15Z–05:53Z cascade window (12+ tick autonomous-loop sequence that traversed all four tiers naturally). Each tier names a discrete operational stance:

| Remaining | Tier | Operational stance |
|---|---|---|
| > 2000 | **Normal** | Full operations: `gh pr create` + `gh pr merge --auto` + `gh api graphql` thread-resolve + batch-polling. No special discipline. |
| 1000–2000 | **Cost-aware** | Reduce `--all-open` polling; prefer per-PR queries; defer non-essential `gh pr comment` and `gh pr view --json` calls. Continue normal substantive work (1 PR open per tick is fine). |
| 200–1000 | **Extreme cost-aware** | Skip batch-polling entirely. Open at most 1 PR per tick. Avoid `gh api graphql` thread sweeps. Inline `gh api rate_limit --jq` (REST, free) to monitor without burning budget. |
| 0–200 | **Pure-git** | Zero `gh` calls except `gh api rate_limit` (REST, free). All substrate landings via `git fetch` + `git push` to a branch; PR creation deferred to post-reset tick. Tick shards still committed and pushed (no GraphQL needed). |

### `gh api rate_limit` is REST (free)

`gh api rate_limit` consults the REST endpoint, not the GraphQL endpoint. Polling it does not consume the GraphQL budget being monitored. Safe to invoke every tick during cost-aware mode without further depleting the budget.
Comment on lines +37 to +42

```bash
gh api rate_limit --jq '{graphql: .resources.graphql.remaining, reset_in_min: ((.resources.graphql.reset - now) / 60 | floor)}'
```

### Pure-git tick pattern (empirical)

When the tier hits Pure-git mode:

1. `git fetch origin main` — read-only, no GraphQL
2. `git log --oneline -5 origin/main` — read-only, no GraphQL
3. Read files via `git show <ref>:<path>` — pure git
4. Author tick shard / substrate edit via Edit tool
5. `git switch -c <branch> origin/main` — pure git
6. `git add` + `git commit` + `git push` — pure git
7. `CronList` (harness tool, not gh) — verifies sentinel alive
8. **Skip `gh pr create` + `gh pr merge --auto` + thread-resolve `gh api graphql`** — all GraphQL
9. Defer PR creation to next tick when rate resets

The branch sits on origin pushed-but-unPRed; PR creation in the post-reset tick costs ~5-10 GraphQL but covers all the deferred branches at once. Net cost is the same; spread across time.

### Composes with counter-with-escalation

When rate-limit forces brief-acks (deferring substantive PR work), the [`.claude/rules/holding-without-named-dependency-is-standing-by-failure.md`](holding-without-named-dependency-is-standing-by-failure.md) counter-with-escalation counter still ticks. At brief-ack #6 the rule triggers forced decomposition. **Editing this rule, a memory file, or any other substrate via pure-git workflow IS decomposition that resets the counter** — the work is bounded, concrete, committed, pushed. Counter reset condition #3 ("Actually picking real decomposition work — Concrete artifact") is satisfied.

## Full reasoning

`memory/feedback_prefer_ts_scripts_over_dynamic_bash_for_conversation_ux_dst_in_ts_aaron_2026_05_01.md`
Expand Down
55 changes: 55 additions & 0 deletions docs/hygiene-history/ticks/2026/05/16/0537Z.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Tick 2026-05-16T05:37Z — Otto-CLI

GraphQL rate-limit at 0/5000 (reset ~05:55Z, ~18min). Audit-tool PR
creation deferred from tick 9; branch + commit + tests preserved on
remote. This tick: brief-ack #1 with named dependency, plus this
visibility shard so the trail stays continuous.

## Refresh result

| Surface | State |
|---|---|
| Cron sentinel | Alive (`bd1c7739`) |
| Peer Otto-CLI | Still detected (PIDs 2706 + 2710) |
| Peer Lior-gemini | Active (step 8 lock cleanup ongoing) |
| GraphQL rate-limit | **0/5000 remaining**, reset 1778910955 ≈ 05:55:55Z (~18min) |
| Audit-tool branch | `feat/b0553-audit-backlog-status-drift-impl-otto-cli-2026-05-16` pushed; 13 tests pass; PR pending |

## Holding-discipline: named bounded wait

Per [`.claude/rules/holding-without-named-dependency-is-standing-by-failure.md`](../../../../../../.claude/rules/holding-without-named-dependency-is-standing-by-failure.md): this tick has a SPECIFIC named dependency with a bounded ETA:

- **Dependency**: GitHub GraphQL API rate-limit reset
- **Identity**: shared AceHack user-scope token, 5000/hour budget
- **ETA**: 1778910955 Unix epoch = 2026-05-16T05:55:55Z (~18 min)
- **Why it matters**: `gh pr create` and `gh pr merge --auto` both need GraphQL; without them the audit-tool PR cannot open

This is brief-ack #1 for the session (counter-with-escalation clause); the prior 9 ticks all shipped substantive substrate without entering this state.

## What I did NOT do this tick (substrate-honest)

- **Did NOT extend the audit tool with `--prune-claims`**: tempting because it's local-only work (uses `tools/bus/claim.ts release`), but would mean a second commit on a not-yet-reviewed branch. Better to ship the first slice cleanly, get review feedback, then extend.
- **Did NOT extend `--open-close-pr`**: requires GraphQL (gh pr create); blocked anyway.
- **Did NOT poll PRs aggressively**: each `gh pr view --json` is ~3 GraphQL calls; my budget is 0; would compound the limit problem when reset finally fires.

## Substrate-or-it-didn't-happen check

| Layer | Artifact | Reached substrate? |
|---|---|---|
| Memory file | `feedback_substrate_drift_catch_pattern_*.md` | ✓ on main `f4ac1259` |
| Backlog row | B-0553 | ✓ on main `124bff17` |
| Auto-loaded rule | `.claude/rules/backlog-item-start-gate.md` step 0 | ✓ on main `268f351` |
| Implementation | `tools/hygiene/audit-backlog-status-drift.ts` + 13 tests | ✓ pushed to remote branch; PR pending |
| This shard | `docs/hygiene-history/ticks/2026/05/16/0537Z.md` | ✓ on this branch; PR will follow at rate-limit reset |

All weather has been converted to substrate. The rate-limit pause is a structural pause, not a substrate gap.

## Next tick's signal to act

If GraphQL has reset (`gh api rate_limit | grep graphql` shows `remaining > 0`):

1. `gh pr create` for the audit-tool branch (deferred from tick 9)
2. `gh pr create` for this shard branch
3. Arm auto-merge on both with explicit PR numbers
Comment on lines +49 to +53

If still rate-limited: another brief-ack with the same named-dependency framing.
Loading