Skip to content

claude-wake

claude-wake #1268

Workflow file for this run

# Wake workflow for Sigma at home (cn-sigma).
#
# Trigger: opening an issue whose title contains "claude-wake", and four
# scheduled crons at :12 :27 :42 :57 (staggered against cnos's :08 :23
# :38 :53 so the two wakes don't race the channel and no two bodies
# fire the same minute — combined ~7.5 min effective cadence at the
# channel level).
#
# Authority: CLAUDE_CODE_OAUTH_TOKEN (operator's Claude Pro/Max
# subscription token, generated via `claude setup-token`, stored as a
# repo secret). Same value the operator uses at cnos.
#
# Substrate: anthropics/claude-code-action@v1 — auth path verified
# end-to-end in cnos#435..#438; OIDC permission + token format both
# pinned in cnos commit a42b3d35 and round-4 green (cnos#438).
#
# Composition: "Activate and attach as <agent-home-url>" — invokes the
# two peer skills in cnos.core/skills/agent/{activate,attach}/SKILL.md.
# At cn-sigma's body, PWD origin matches the prompt URL → attach skill
# detects mode = home. Home procedure iterates over each registered
# activation in .cn-sigma/state/activations.md (currently cnos, bumpt), walks
# each foreign log from last_read_foreign_log to hub HEAD, writes one
# per-activation thread entry, and advances each cursor.
name: claude-wake
on:
issues:
types: [opened]
schedule:
# Four independently-scheduled hourly crons. Each cron line is
# scheduled separately by GH; partial slot drops don't open a full
# hour-long gap. Combined effect ~4 wakes/hour expected; with even
# 75% drop rate we still get ~1 wake/hour guaranteed. Minutes chosen
# complementary to cnos (:08/:23/:38/:53) — no two bodies fire the
# same minute, channel race-free, ~7.5 min effective cadence at the
# channel level. Per cnos directive 2026-06-02T21:57Z; RCA at
# 2026-06-02T20:35Z (off-peak avoids :00/:30 congestion).
- cron: '12 * * * *'
- cron: '27 * * * *'
- cron: '42 * * * *'
- cron: '57 * * * *'
permissions:
contents: write
issues: write
pull-requests: write
id-token: write
# Serialize wakes — never run two in parallel. Concurrent wakes would
# race on the writer-surfaces (.cn-sigma/threads/activations/{name}/) and
# .cn-sigma/state/activations.md cursor advances, producing duplicate
# entries or push conflicts. cancel-in-progress: false queues new
# triggers behind any in-flight wake.
concurrency:
group: claude-wake
cancel-in-progress: false
jobs:
wake:
if: ${{ github.event_name == 'schedule' || contains(github.event.issue.title, 'claude-wake') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
show_full_output: true
bot_name: "sigma@cn-sigma.cnos"
bot_id: "41898282"
settings: |
{
"permissions": {
"allow": ["Read", "Write", "Edit", "MultiEdit", "Glob", "Grep", "Bash"]
}
}
prompt: |
Execute the activate + attach skills (cnos.core/skills/agent/{activate,attach}/SKILL.md) for hub https://github.com/usurobor/cn-sigma.
Required actions (do not skip even if cursors appear current):
1. Read .cn-sigma/state/activations.md.
2. For EACH registered activation (cnos, bumpt): fetch its foreign log at <hub>:.cn-sigma/logs/, walk commits from last_read_foreign_log to HEAD, append a per-activation thread entry at .cn-sigma/threads/activations/<name>/YYYYMMDD.md summarizing new commits, and update last_read_foreign_log in activations.md.
3. Commit + push all changes (per-activation entries + activations.md cursor updates) to main.
4. If a foreign-log HEAD equals last_read_foreign_log (no new commits), still append a heartbeat entry with class: heartbeat and cursor: holds.
Do not exit early. The walk is the work.
# Walk per-activation home channels for substantive events and post
# to Telegram via notify-telegram.sh. Runs AFTER Sigma's
# claude-code-action step (which wrote/committed today's channel
# entries). Cursor is per-activation in notification-cursors.yaml;
# only events newer than the cursor are emitted. Scans all sorted
# channel files (cross-day retry).
#
# Sync FIRST and only notify if sync succeeded — external POSTs
# must reflect current home channel state.
- name: Notify (wake-walker → Telegram)
if: always()
env:
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
run: |
if git pull --rebase origin main; then
.cn-sigma/scripts/notify-walk.sh
else
echo "[notify] sync failed; skipping Telegram notify (external POSTs require synced state)"
fi
# Commit + push notification cursor advances. Separate step so the
# walker stays pure (state mutation only) and persistence is wake-yaml
# responsibility. If cursor push fails, the next wake's pull picks up
# the un-advanced cursor and the same entry posts again — at-least-once
# delivery semantics.
#
# Uses explicit GITHUB_TOKEN auth in the remote URL because checkout's
# default extraheader auth gets rejected on `git push` even though it
# works for `git pull/fetch` (GitHub no longer accepts basic password
# auth for pushes from Actions).
- name: Persist notification cursor
if: always()
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
if git diff --quiet .cn-sigma/state/notification-cursors.yaml; then
echo "[notify-cursor] no advance"
exit 0
fi
git -c user.email="sigma@cn-sigma.cnos" -c user.name="Sigma" \
add .cn-sigma/state/notification-cursors.yaml
git -c user.email="sigma@cn-sigma.cnos" -c user.name="Sigma" \
commit -m "notify-walk: advance notification cursors"
git push "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" HEAD:main || \
echo "[notify-cursor] push failed; cursor committed locally only; next wake may re-post (at-least-once)"
# Notify the coherer session that the wake completed.
# PR #9 (coherer-watch) is the long-lived notification surface;
# see .cn-sigma/state/coherer-watch.md for mechanism. PR comments fire
# PR-activity webhooks that surface to subscribe_pr_activity in
# the coherer's session.
- name: Notify coherer
if: always()
run: |
git fetch origin main --quiet || true
HEAD_SHA=$(git rev-parse --short=8 origin/main)
LAST_SUBJECT=$(git log -1 --pretty=%s origin/main)
gh pr comment 9 --body "wake @ ${HEAD_SHA}: ${LAST_SUBJECT}"
env:
GH_TOKEN: ${{ github.token }}