Skip to content

chore(state): clean up orphan gists + migrate routine state from gists to a dryvist/cc-routines-state repo #35

@JacobPEvans-personal

Description

@JacobPEvans-personal

Problem

The gists list at https://gist.github.com/JacobPEvans-personal is cluttered with 19 orphan state.json gists dated 2026-04-18 through 2026-05-06 — each 04:xx UTC, one per day, content {"last_polished": "...", "last_date": "..."}. These are from an old Daily Polish version that created a new gist every run instead of updating one. The current Daily Polish writes to daily-polish-state (single gist, properly named), so the 19 are dead.

Additionally, every cloud routine maintains its own *-state gist. Today there are ~4 named ones; once feat/six-new-routines lands there will be ~10 (apothecary-state, archivist-state, conductor-state, custodian-state, daily-polish-state, inspector-state, observer-state, quartermaster-state, sentinel-state, solver-state — plus the cross-routine routine-pr-budget). The gists UI becomes a wall of *-state rows that mean nothing visually.

Two-step fix

Step 1: Delete the 19 orphans (immediate, 1 command)

Requires a token tier with gist scope (e.g. gh-private or higher). From a properly-tiered shell:

gh gist list --limit 100 \
  | awk -F'\t' '$2 == "state.json" {print $1}' \
  | xargs -I{} gh gist delete {} --yes

Verify orphan count first:

gh gist list --limit 100 | awk -F'\t' '$2 == "state.json"' | wc -l
# expect: 19

The 5 named *-state gists (apothecary, daily-polish, issue-solver, weekly-scorecard, plus any others) are NOT affected — they have proper titles, not the bare state.json.

Step 2: Migrate state from gists to dryvist/cc-routines-state repo

Create a new private repo dryvist/cc-routines-state that holds one JSON file per routine. Routines read+write via createCommitOnBranch (the same signed-commit path the Solver already uses for target repos). Gists list stays clean forever.

One-time setup (user-only, requires gh-claude-dryvist and secrets-sync write)

# 1. Create the repo
gh repo create dryvist/cc-routines-state \
  --private \
  --description "State files for dryvist/claude-code-routines cloud routines. Each routine owns one JSON file. Routines read+write via createCommitOnBranch with JacobPEvans-claude App installation token."

# 2. Seed initial README (manual or via Contents API)
# 3. Add the new repo to the *github_app_repos anchor in
#    dryvist/secrets-sync/secrets-config.yml so the JacobPEvans-claude
#    App gets installation access.
# 4. Re-run secrets-sync distribution workflow.
# 5. Copy each current *-state gist content into:
#    dryvist/cc-routines-state:state/<routine>.json

Routine-prompt updates (one PR per routine, can be batched)

For each routine, replace the gist-read/write logic with Contents API equivalents against dryvist/cc-routines-state. Rough pattern:

# Read state
STATE=$(gh api repos/dryvist/cc-routines-state/contents/state/<routine>.json \
          --jq '.content' | base64 -d)

# Mutate state in /tmp/state.json...

# Write state via createCommitOnBranch (signed by JacobPEvans-claude[bot])
B64=$(base64 < /tmp/state.json | tr -d '\n')
jq -n --arg b64 "$B64" --arg sha "$BASE_SHA" '{
  query: "mutation($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { oid } } }",
  variables: {
    input: {
      branch: { repositoryNameWithOwner: "dryvist/cc-routines-state", branchName: "main" },
      expectedHeadOid: $sha,
      message: { headline: "chore(state): update <routine> state [routine:<name>]" },
      fileChanges: { additions: [{path: "state/<routine>.json", contents: $b64}] }
    }
  }
}' | gh api graphql --input -

Routines in scope (10 total):

After migration: every routine deletes its legacy *-state gist on its first run after deployment, then writes to the new repo from there on.

Why a private repo, not a branch or another gist?

  • No gist clutter. The whole point — gists list becomes just the user's actual personal gists.
  • Browsable. GitHub repo UI is built for navigating files; gist UI is built for ephemera.
  • Versioned. Every state mutation becomes a signed commit with a meaningful message. Auditable forever.
  • Same mechanics routines already use. createCommitOnBranch is already in the Solver and (after feat/six-new-routines lands) everywhere else. No new auth path.
  • Centralized backup. One repo to clone if you ever want to inspect or archive state.

A dedicated state-only branch in claude-code-routines was the runner-up option but bleeds branches into the source-of-truth repo. Separate repo is cleaner.

Out of scope

  • The 5 legitimate personal gists (proxmox scripts, AI prompts, learning resources, Splunk references, everything-as-code) — those are user content, untouched.
  • The routine-pr-budget cross-routine gist — same migration applies, gets its own file state/_pr-budget.json in the new repo.

Acceptance criteria

  • 19 orphan state.json gists deleted; total gist count drops from 28 to 9 (5 personal + 4 routine state).
  • dryvist/cc-routines-state private repo exists with README explaining purpose and JacobPEvans-claude App installed.
  • Each of the 10 routine prompts updated to read+write state from the new repo (10 small PRs, OR one batched PR per branch).
  • After all routines deploy: zero *-state gists exist; gh gist list shows only the 5 personal gists.

Suggested ordering

  1. Delete orphans (1 command, immediate).
  2. Create repo + README + secrets-sync wiring (one-time, ~15 min).
  3. Migrate routine prompts in batches: first the 6 on main (covers Solver, Observer, Daily Polish, Sentinel, Custodian), then the 5 on feat/six-new-routines as part of that branch's merge.
  4. Verify each routine's first post-deploy run deletes its legacy gist and writes to the new repo successfully.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions