@4pm/cli 1.14.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,22 +1,20 @@
1
1
  {
2
- "_about": "Autonomous workflow config. autonomous-tick.sh READS this file EVERY cron tick, so edits take effect from the next tick. Keys starting with '_' are comments and are ignored by the script.",
2
+ "_about": "Autonomous workflow config (ADR-0152 + ADR-0319). autonomous-tick.sh READS this file EVERY cron tick, so edits take effect from the next tick. Keys starting with '_' are comments and are ignored by the script.",
3
3
  "paused": true,
4
- "_paused": "true = PAUSED: the tick still runs but skips immediately, without invoking Claude. A quick brake without removing the crontab entry.",
5
- "max_session_pct": 80,
6
- "max_weekly_pct": 90,
7
- "_quota": "Only run when session_pct < max_session_pct AND weekly_pct < max_weekly_pct (read from the usage skill).",
4
+ "_paused": "true = PAUSED: the tick still runs but skips immediately, without waking the daemon. A quick brake without removing the crontab entry.",
8
5
  "cron_schedule": "*/5 * * * *",
9
6
  "_cron_schedule": "Standard 5-field cron. When you change this, the tick rewrites the crontab line pointing at autonomous-tick.sh on the next run (only if the crontab already has the autonomous line — install it once manually first).",
10
- "command": "/auto-cycle",
11
- "_command": "The headless slash-command each tick invokes.",
12
- "model": "",
13
- "_model": "Empty = Claude Code's default model. Or set an id (e.g. 'claude-sonnet-4-6') to force a cheaper/faster model for the autonomous loop.",
7
+ "command": "auto-run",
8
+ "_command": "The cli subcommand each tick runs. `4pm auto-run` asks the running `4pm start` daemon to run one cycle through its live session (ADR-0319).",
9
+ "profile": "",
10
+ "_profile": "Optional profile name for `4pm auto-run --profile <name>`. Empty = the cli resolves the single linked profile (set this only on a worker serving multiple projects).",
11
+ "_quota_moved": "The session/weekly token gate + account selection moved OUT of this shell into the cli (ADR-0319) — they need the daemon's live usage snapshot. Configure quota-based profile failover in the cli's own config, not here.",
14
12
  "quiet_hours": "",
15
13
  "_quiet_hours": "Empty = run ALL DAY. Or 'HH:MM-HH:MM' (e.g. '00:00-06:00') to SKIP within that window; a window crossing midnight is valid (e.g. '22:00-06:00').",
16
14
  "max_ticks_per_day": -1,
17
- "_max_ticks_per_day": "-1 = NO limit. >0 = cap on the number of ticks that actually invoke Claude in one (local) day. The count is stored under ticks{day,count} in .claude/.autonomous.histories.json.",
15
+ "_max_ticks_per_day": "-1 = NO limit. >0 = cap on the number of ticks that actually wake the daemon in one (local) day. The count is stored under ticks{day,count} in .claude/.autonomous.histories.json.",
18
16
  "stop_on_consecutive_failures": 3,
19
- "_stop_on_consecutive_failures": "After N consecutive FAILED command runs -> set paused=true to stop safely. 0 = off. The count is stored under consecutive_fails in .claude/.autonomous.histories.json (reset on success).",
17
+ "_stop_on_consecutive_failures": "After N consecutive FAILED runs (no daemon / dispatch error) -> set paused=true to stop safely. 0 = off. The count is stored under consecutive_fails in .claude/.autonomous.histories.json (reset on success).",
20
18
  "log_retention_days": 14,
21
19
  "_log_retention_days": "Logs are written per DAY: .claude/logs/autonomous-tick-YYYY-MM-DD.log. Delete log files older than N days. 0 = keep forever.",
22
20
  "notify_webhook": "",
@@ -1,9 +1,9 @@
1
1
  # Set up a 10-minute cron for `autonomous-tick.sh`
2
2
 
3
3
  How to install the **autonomous cycle** on **WSL (Ubuntu)**: cron calls
4
- [`autonomous-tick.sh`](autonomous-tick.sh) every **10 minutes**; each run does one `claude -p /auto-cycle`
5
- cycle then exits. A file lock (`.claude/.autonomous.lock`) ensures **no two runs overlap** (a later tick
6
- that sees the lock skips).
4
+ [`autonomous-tick.sh`](autonomous-tick.sh) every **10 minutes**; each run does one **`4pm auto-run`**
5
+ cycle (the running `4pm start` daemon executes it — ADR-0319) then exits. A file lock
6
+ (`.claude/.autonomous.lock`) ensures **no two runs overlap** (a later tick that sees the lock skips).
7
7
 
8
8
  > All commands below run in a **WSL shell** (Ubuntu) unless noted as PowerShell/Windows. Call the project
9
9
  > root `$PROJECT` (e.g. `~/projects/<your-project>`).
@@ -18,9 +18,10 @@ cd "$PROJECT"
18
18
  Every line must print a path/version (not "not found"):
19
19
  ```bash
20
20
  command -v cron || echo "missing cron"
21
- command -v claude || echo "missing claude (install natively in WSL)"
21
+ command -v 4pm || echo "missing 4pm cli (install natively in WSL; a '4pm start' daemon must be running)"
22
22
  command -v git || echo "missing git"
23
23
  command -v python3 || echo "missing python3"
24
+ command -v gh || command -v glab || echo "missing gh/glab (needed for the PR step)"
24
25
  ```
25
26
 
26
27
  ## 2. Make the tick executable + install the cron line
@@ -1,34 +1,36 @@
1
1
  # Autonomous mode — how it's assembled
2
2
 
3
3
  > **Sample project — defines the workflow only, does NOT run on its own.** The files below describe an
4
- > unattended work loop, intended to run on **WSL** (an isolated environment where the AI can be given
5
- > full permissions).
4
+ > unattended work loop (ADR-0152 + **ADR-0319**), intended to run on **WSL** (an isolated environment
5
+ > where the AI can be given full permissions). Under ADR-0319 the cycle runs **through the 4PM cli**,
6
+ > not a raw `claude -p`.
6
7
 
7
8
  ## The pieces
8
9
  | File | Role |
9
10
  |------|------|
10
- | `.claude/hooks/autonomous-tick.sh` | Cron tick (every ~10 min); a lock so **busy ⇒ skip, idle ⇒ run**; calls `claude -p /auto-cycle`. |
11
- | `.claude/commands/auto-cycle.md` | Defines **one cycle**: token gate → sync `${ai_dev_branch}$` → generate tasks → do one task → test → merge into `${ai_dev_branch}$`. |
12
- | `.claude/skills/check-usage/check_usage.py` | The `check-usage` skill: prints token % and writes `output/last-usage-check.json` (deleted + recreated each run) for the token gate to read. |
13
- | `.claude/.autonomous.approvals.json` | Approval source of truth (ADR-0152): `{ "<TSK-id>": {approved, by, at} }` — the web VERIFY tab writes it; `/auto-cycle` reads it. |
14
- | `USER_TODO.md` | The user writes requests here; the cycle reads then clears it. |
11
+ | `.claude/hooks/autonomous-tick.sh` | Cron tick (every ~5–10 min): a run lock + the CHEAP local gates (pause / quiet-hours / max-ticks / **has-work**), then runs **`4pm auto-run`**. No token spend when there's no approved work. |
12
+ | `4pm auto-run` (cli) | Asks the running **`4pm start`** daemon to run **one** cycle over the control socket; the cycle rides the daemon's live WS session (failover ADR-0182, metering ADR-0072, folder-scope ADR-0181, timeout ADR-0243). |
13
+ | cli `buildAutonomousCyclePrompt` | The cli-owned cycle instructions (was `.claude/commands/auto-cycle.md`, now retired): sync branch → analyse **approved** USER_TODO → fold **approved** USER_QA → do ONE approved task → **PR** into the base branch. |
14
+ | `.claude/.autonomous.approvals.json` | Approval source of truth (ADR-0152): `{ "<REQ/QA/TSK-id>": {approved, by, at} }` — the web AI-content grids write it; the cycle reads it. |
15
+ | `USER_TODO.md` / `USER_QA.md` | User requests / the AI's questions back — each row approved before the cycle acts on it (ADR-0319). |
15
16
  | `AI_TODO.md` / `AI_PROGRESS.md` / `AI_DONE.md` | The task books: queue → in progress → done (ID `TSK-{group:0000}-{task:0000}`). |
16
- | `.claude/templates/<NAME>.{empty,sample}.md` | Canonical templates for the 5 books. The "has work" gate + `/auto-cycle` **compare against `*.empty.md`** to tell empty/has-work and reset correctly (see `README.md` in that folder). |
17
+ | `.claude/templates/<NAME>.{empty,sample}.md` | Canonical templates for the books. The has-work gate + the cycle **compare against `*.empty.md`** to tell empty/has-work and reset correctly. |
17
18
  | `.claude/settings.json` | The "bypass all" permission profile for autonomous mode (see the note below). |
18
19
 
19
20
  ## Lifecycle (1 tick)
20
21
  ```
21
- cron ~10min → autonomous-tick.sh
22
- ├─ locked? → log "skip", exit (wait for the next tick)
23
- └─ idle → claude -p /auto-cycle
24
- 0. usage: session<80% & weekly<90%? (no → stop)
25
- 1. checkout/fetch/pull the `${ai_dev_branch}$` branch
26
- 2. USER_TODO.md → generate tasks into AI_TODO.md (with IDs) → clear USER_TODO.md
27
- 3. pick one APPROVED task (approvals + dependencies) → AI_PROGRESS.md, remove from AI_TODO.md, commit
28
- 4. task/TSK-… branch → implement → commit → run the project's tests
29
- 5. back to `${ai_dev_branch}$` → merge task (resolve conflicts if any) → AI_DONE.md, remove from AI_PROGRESS.md, commit
30
- 6. report on the `conversation` branch (CONVERSATION.md, ≤50 entries) for later agents
31
- 7. recheck usage → stop
22
+ cron ~5–10min → autonomous-tick.sh
23
+ ├─ locked? / paused? / quiet-hours? / max-ticks? → log "skip", exit
24
+ ├─ has-work? (approved USER_TODO/USER_QA/AI_TODO, or AI_PROGRESS non-empty) — no → skip (daemon NOT woken)
25
+ └─ 4pm auto-run → the running daemon runs ONE cycle:
26
+ 1. sync the primary repo's current branch (base branch — ADR-0292)
27
+ 2. analyse APPROVED USER_TODO requests → AI_TODO tasks (unclear ⇒ ask via USER_QA)
28
+ 3. fold APPROVED USER_QA answers back into AI_TODO
29
+ 4. take ONE approved task (deps met) → AI_PROGRESS, commit
30
+ 5. implement + test on task/TSK-… branch
31
+ 6. rebase + push + open a PULL REQUEST into the base branch (no direct merge)
32
+ 7. update the books (AI_DONE), commit + push the base branch
33
+ └─ record success/failure (N consecutive failures → pause); the EXIT trap releases the lock
32
34
  ```
33
35
 
34
36
  ## Install on WSL
@@ -40,13 +42,11 @@ crontab -e
40
42
  # watch:
41
43
  tail -f .claude/logs/autonomous-tick-$(date +%F).log
42
44
  ```
43
- Requirements: `claude` logged in (has `~/.claude/.credentials.json`), plus `git` and `python3`, and the
44
- project's test tooling (per `CLAUDE.md`).
45
+ Requirements: the **`4pm`** cli on PATH with a **running `4pm start` daemon** serving this project (it
46
+ holds the AI credentials + WS session), plus `git`, `python3`, and `gh`/`glab` for the PR step.
45
47
 
46
48
  ## Note on permissions (important)
47
- - Claude Code only auto-loads `.claude/settings.json` and `.claude/settings.local.json`. To make a
48
- full-permission profile take effect, one of:
49
- 1. The tick already passes `--permission-mode bypassPermissions --dangerously-skip-permissions` (in use).
50
- 2. Or copy the profile into `.claude/settings.local.json`.
51
- 3. Or point `CLAUDE_CONFIG_DIR` at the profile dir when running headless.
49
+ - The daemon runs the cycle as a **write-capable agent** (`--permission-mode bypassPermissions`,
50
+ ADR-0271) so file + git/`gh`/`glab` writes run headless. It stays bounded by the folder-scope guard
51
+ (ADR-0181) + the AI-run timeout (ADR-0243).
52
52
  - Only enable full permissions in an isolated environment (WSL/CI). Never on a machine with sensitive data.
@@ -1,177 +1,23 @@
1
1
  ---
2
- description: Autonomous cycle — pull a request from USER_TODO, do ONE small approved task, test it, merge into ${ai_dev_branch}$. (The token gate is checked by autonomous-tick.sh BEFORE Claude is invoked.)
3
- allowed-tools: Bash(*), Read(*), Edit(*), Write(*), Glob(*), Grep(*)
2
+ description: (Retired — ADR-0319) The autonomous cycle now runs through the 4PM cli, not `claude -p /auto-cycle`.
4
3
  ---
5
4
 
6
- # /auto-cycle — one autonomous work cycle
5
+ # /auto-cycle — retired (ADR-0319)
7
6
 
8
- You are running **unattended** (headless, triggered by cron every ~10 min via
9
- `.claude/hooks/autonomous-tick.sh`). Do **exactly one full cycle** with the steps below, then **stop**.
10
- The integration branch is named **`${ai_dev_branch}$`** (the placeholder is resolved at runtime — see
11
- `AI_PLACEHOLDER.md`); a task branch is **merged straight into `${ai_dev_branch}$`** (no PR).
7
+ The autonomous work cycle is **no longer** a `claude -p /auto-cycle` slash command. Under **ADR-0319**
8
+ it runs through the 4PM cli instead:
12
9
 
13
- > Survival rule: **each cycle does exactly ONE small task** to avoid running out of tokens mid-way. If a
14
- > step fails, log it as a row in the **Incidents** table of `AI_DONE.md`, **clean the lock (Step 8)**, then stop — don't
15
- > push on.
16
- >
17
- > **Lock (`.claude/.autonomous.lock`):** whether the cycle ends normally or on error, you MUST delete
18
- > the lock file before stopping so the next cron tick isn't blocked by a stale lock (Step 8) —
19
- > mandatory, even on an early error exit.
20
- >
21
- > **Token gate:** the quota check (session/weekly) moved to the `autonomous-tick.sh` wrapper — it runs
22
- > first and only invokes Claude when quota is sufficient. So by the time `/auto-cycle` starts, the gate
23
- > has already passed; don't re-check at the top.
24
- >
25
- > **Books & templates (MUST compare):** the 5 book files at the repo root — `USER_TODO.md`,
26
- > `AI_TODO.md`, `AI_PROGRESS.md`, `AI_DONE.md`, `USER_QA.md` — have canonical templates in
27
- > `.claude/templates/` (`<NAME>.empty.md` = EMPTY state, `<NAME>.sample.md` = example WITH DATA; see
28
- > `.claude/templates/README.md`). Rules:
29
- > - **Is a file empty / has work?** → compare against `<NAME>.empty.md` (empty ⇔ equal to the empty
30
- > template after trimming trailing whitespace + leading/trailing blank lines). Don't guess by skimming.
31
- > - **When clearing / resetting** a file → overwrite with the **exact** `<NAME>.empty.md`
32
- > (`cp .claude/templates/<NAME>.empty.md <NAME>`). The tick's "has work" gate relies on this match.
33
- > - **When adding data** → keep the header/blockquote, fill in per `<NAME>.sample.md`.
34
- >
35
- > **Language:** write books/docs/code in the language the project's `CLAUDE.md` specifies (default
36
- > English). Don't switch languages on your own.
10
+ - The cron tick (`.claude/hooks/autonomous-tick.sh`) runs **`4pm auto-run`**, which asks the already
11
+ running **`4pm start`** daemon to run **one** cycle through its live WS session — so the cycle reuses
12
+ the cli's profile/quota failover (ADR-0182), token metering (ADR-0072), folder-scope guard (ADR-0181)
13
+ and AI-run timeout (ADR-0243).
14
+ - The cycle **instructions** now live in the cli (`21-apps/31-cli/src/core/autonomous-cycle.ts` →
15
+ `buildAutonomousCyclePrompt`), not in this file. In short: sync the primary repo's current branch →
16
+ analyse **approved** `USER_TODO` requests into `AI_TODO` tasks (unclear ⇒ ask via `USER_QA`) → fold
17
+ **approved** `USER_QA` answers back → take ONE approved task → implement + test on a `task/TSK-…`
18
+ branch → open a **pull request** into the base branch (no direct merge) → update the books.
37
19
 
38
- ---
39
-
40
- ## Step 1 — Sync the `${ai_dev_branch}$` branch
41
- 1. If not on `${ai_dev_branch}$`:
42
- - `git fetch origin`
43
- - If it doesn't exist yet: `git checkout -b ${ai_dev_branch}$ origin/${ai_dev_branch}$` (if the remote
44
- has it) or `git checkout -b ${ai_dev_branch}$ main` (create from main).
45
- - Otherwise: `git checkout ${ai_dev_branch}$`.
46
- 2. `git pull --ff-only origin ${ai_dev_branch}$` (skip if the remote has no such branch yet).
47
-
48
- ## Step 2 — Intake user requests → generate tasks
49
- 1. Read `USER_TODO.md` and **compare with `.claude/templates/USER_TODO.empty.md`**. If **equal** (only
50
- the empty template remains) → **no** new request → skip task generation.
51
- 2. **If anything is unclear / needs a user decision** (ambiguous, missing info, contradictory, or the
52
- user said "ask if unclear, don't decide on your own"):
53
- - **Do NOT guess** and generate tasks. Append a **row** to `USER_QA.md` per
54
- `.claude/templates/USER_QA.sample.md` (columns `Date | Original request | Question / options | Answer`):
55
- fill the date, the original request, and what's unclear + (if possible) options to choose from; leave
56
- the **Answer** column blank for the user.
57
- - **Clear `USER_TODO.md`** back to the empty template (Step 2.4) — do NOT generate tasks this cycle.
58
- The user will read `USER_QA.md`, clarify, and re-post the request into `USER_TODO.md` for a later cycle.
59
- - Append a row to the **Incidents** table in `AI_DONE.md` that this cycle stopped waiting for an answer, then go to
60
- Step 8 (clean the lock) and **stop**.
61
- 3. If the request is clear enough: split it into small tasks doable in ~1 cycle. Write them into
62
- `AI_TODO.md` per `.claude/templates/AI_TODO.sample.md` (**7-column table:
63
- `| ID | Priority | Approved | Depends | Group | Task description | Notes |`**), each with an
64
- **ID `TSK-{groupid:0000}-{taskid:0000}`** (group = one request/batch, task = a sub-task).
65
- - **`Priority` column**: judge it — `High` / `Medium` / `Low` (default `Medium`).
66
- - **`Approved` column**: leave BLANK. This is a display-only mirror — the source of truth for approval
67
- is `.claude/.autonomous.approvals.json` (the user ticks it in the web VERIFY tab — ADR-0152). Do NOT
68
- fill it in yourself and do NOT read it to decide (see Step 3).
69
- - **`Depends` column**: if a task must wait for another, list the `TSK-…` ids here (comma-separated);
70
- leave empty otherwise. Step 3 skips a task whose dependencies aren't in `AI_DONE.md` yet.
71
-
72
- **ID rules (MANDATORY):**
73
- - **Each analysis of `USER_TODO.md` → one NEW `groupid`.** All sub-tasks split from that batch share
74
- this `groupid`, differing only by `taskid`.
75
- - **`groupid` must be UNIQUE and INCREASING** across all history (including groups already DONE and
76
- cleared from `AI_TODO.md`). Since the books are cleared each cycle, **check git history** for the
77
- largest `groupid` ever used, then take `max + 1`:
78
- ```bash
79
- MAXG=$( { git log -p -- AI_TODO.md AI_DONE.md AI_PROGRESS.md 2>/dev/null; \
80
- cat AI_TODO.md AI_DONE.md AI_PROGRESS.md 2>/dev/null; } \
81
- | grep -oE 'TSK-[0-9]{4}-[0-9]{4}' | sed -E 's/TSK-([0-9]{4}).*/\1/' \
82
- | sort -rn | head -1 ); MAXG=${MAXG:-0}
83
- NEWG=$(printf '%04d' $((10#$MAXG + 1)))
84
- ```
85
- - **`taskid` starts at `0001` and increases WITHIN the group**: `TSK-{NEWG}-0001`, `TSK-{NEWG}-0002`, …
86
- 4. **Clear `USER_TODO.md`** by overwriting with the exact empty template
87
- (`cp .claude/templates/USER_TODO.empty.md USER_TODO.md`) — so old tasks aren't recreated next cycle AND
88
- the tick's "has work" gate correctly sees it as empty.
89
-
90
- ## Step 3 — Pick ONE APPROVED task (with satisfied dependencies) and start it
91
- > **VERIFY gate (MANDATORY):** the source of truth for approval is `.claude/.autonomous.approvals.json`
92
- > (ADR-0152), NOT the `Approved` column in `AI_TODO.md`. A task is **approved** when approvals has
93
- > `"<TSK-id>": { "approved": true, … }`. A task not in approvals (or `approved:false`) = NOT permitted →
94
- > **skip it, leave it queued**.
95
-
96
- 1. Read `.claude/.autonomous.approvals.json` (JSON `{ "<TSK-id>": {approved, by, at}, … }`; missing file
97
- ⇒ nothing approved) and `AI_TODO.md`. **Filter tasks meeting BOTH**:
98
- - **Approved**: `approved === true` in approvals.
99
- - **Dependencies met**: every `TSK-…` in the `Depends` column is already in `AI_DONE.md` (done). If a
100
- dependency isn't done yet → **skip** (wait for a later cycle), even if approved.
101
- Pick the next task: **run group by group** (smallest group with an eligible task first), **within a
102
- group prefer `Priority` High → Medium → Low**, then line order.
103
- - **If NO eligible task** (empty, or all waiting for approval / dependencies — including tasks just
104
- generated in Step 2): **take no task**. Append a row to the **Incidents** table in `AI_DONE.md`
105
- (e.g. "this cycle only generated tasks / waiting for VERIFY approval / waiting for dependencies"),
106
- then go to Step 8 (clean the lock) and **stop**.
107
- 2. Move that task into `AI_PROGRESS.md` (with a start timestamp, per
108
- `.claude/templates/AI_PROGRESS.sample.md`), **remove it from `AI_TODO.md`**. If `AI_TODO.md` is now
109
- empty → `cp .claude/templates/AI_TODO.empty.md AI_TODO.md`.
110
- 3. Commit on `${ai_dev_branch}$`: `git add -A && git commit -m "chore(auto): start TSK-xxxx-xxxx"`.
111
-
112
- ## Step 4 — Implement the task on its own branch
113
- 1. Create the branch: `git checkout -b task/TSK-xxxx-xxxx`.
114
- 2. Implement the task **following the project's architecture + the conventions in `CLAUDE.md`**. Add or
115
- update tests as appropriate for the change.
116
- 3. **Test** by running the project's test command (see `CLAUDE.md` / the project's scripts — e.g.
117
- `scripts/test.*`, `npm test`, `pnpm test`, `pytest`, …). If the project defines an integration-test /
118
- evidence harness, use it and keep the produced report/evidence so it can be reviewed later.
119
- 4. **Wait for the tests to finish** and check the result before continuing.
120
- 5. Commit (include any produced report/evidence so the integration branch carries it):
121
- `git add -A && git commit -m "feat(TSK-xxxx-xxxx): <short description>"`.
122
-
123
- ## Step 5 — Merge into `${ai_dev_branch}$`, update the books
124
- 1. `git checkout ${ai_dev_branch}$`
125
- 2. `git merge --no-ff task/TSK-xxxx-xxxx`
126
- - **On CONFLICT** (parallel agents may have moved the integration branch — MEMO #40): `git status`
127
- shows `UU` files. **Resolve them yourself**: edit each conflicted file into a correct merged result
128
- (remove every `<<<<<<< ======= >>>>>>>` marker), `git add <file>`, then `git commit --no-edit` to
129
- finish the merge. If a conflict is too complex to be sure → `git merge --abort`, write a question
130
- into `USER_QA.md`, go to Step 8 and stop (don't guess).
131
- 3. Record the task by **appending a row to the Done table** in `AI_DONE.md` (Timestamp, ID, Task description, Files, Notes — per `.claude/templates/AI_DONE.sample.md`; keep the table header intact).
132
- **Remove it from `AI_PROGRESS.md`**: if nothing is in progress after removal, reset with
133
- `cp .claude/templates/AI_PROGRESS.empty.md AI_PROGRESS.md`. Likewise, if `AI_TODO.md` is now empty →
134
- `cp .claude/templates/AI_TODO.empty.md AI_TODO.md`.
135
- 4. Commit: `git add -A && git commit -m "chore(auto): finish TSK-xxxx-xxxx, merge into ${ai_dev_branch}$"`.
136
- 5. (Optional) `git push origin ${ai_dev_branch}$`.
137
-
138
- ## Step 6 — Recheck the token budget
139
- 1. Re-run the **check-usage** skill: `python .claude/skills/check-usage/check_usage.py`, then **wait 3s**
140
- (`sleep 3`) for the result file to be written.
141
- 2. Print a summary: task done, tokens remaining.
142
-
143
- ## Step 7 — Commit & push `${ai_dev_branch}$`
144
- 1. `git checkout ${ai_dev_branch}$`
145
- 2. `git add -A && git commit -m "chore(auto): update books after the autonomous cycle"` (skip if no change).
146
- 3. `git push origin ${ai_dev_branch}$`.
147
-
148
- ## Step 7.5 — Report on the `conversation` branch (share context with later agents — MEMO #40)
149
- > Multiple Claude instances take different tasks in parallel; a later agent needs to know what an earlier
150
- > one did. Use a dedicated branch named **`conversation`** holding **only** the file `CONVERSATION.md`
151
- > (no source or docs), keeping **at most the 50 most recent reports** (trim older ones when over).
152
-
153
- 1. Save the context (task ID + summary + list of files changed this cycle).
154
- 2. `git stash -u` if there are uncommitted changes (usually none — the books were committed in Step 7).
155
- 3. Switch to the conversation branch (create it orphan if missing):
156
- - `git fetch origin` → `git checkout conversation` (exists) or
157
- `git checkout --orphan conversation && git rm -rf . 2>/dev/null` (create fresh, clean).
158
- - `git pull --ff-only origin conversation` (skip if the remote has none).
159
- 4. Append an entry to the **end** of `CONVERSATION.md`:
160
- ```
161
- ## <yyyy-MM-dd HH:mm> · TSK-xxxx-xxxx
162
- - Did: <short summary>
163
- - Files: <paths, comma-separated>
164
- - Merged into: ${ai_dev_branch}$ (<conflict / no conflict>)
165
- ```
166
- If the number of `##` entries exceeds **50** → drop the oldest ones down to 50.
167
- 5. `git add CONVERSATION.md && git commit -m "chore(conversation): TSK-xxxx-xxxx" && git push origin conversation`.
168
- 6. Return to the integration branch: `git checkout ${ai_dev_branch}$` (and `git stash pop` if you stashed in 2).
20
+ Approval is the source of truth in `.claude/.autonomous.approvals.json` (ADR-0152), keyed per row id
21
+ (`REQ-…` / `QA-…` / `TSK-…`), set from the web AI-content grids.
169
22
 
170
- ## Step 8 — Clean the lock (ALWAYS run, even on error/early exit)
171
- > This is the **final action of every cycle** — run it whether the cycle succeeded, hit an error, or was
172
- > blocked at the token gate. Goal: never let a stale lock block the next cron tick.
173
- 1. Delete the lock file: `rm -f .claude/.autonomous.lock` (run in the project root).
174
- - The lock IS the file `.autonomous.lock`: `autonomous-tick.sh` creates it at start and treats "the
175
- file exists" = a run is in progress. Deleting it here releases the lock for the next tick.
176
- - This is `/auto-cycle`'s responsibility; the wrapper only has a safety-net trap in case the cycle dies.
177
- 2. **STOP** (the next cron tick will trigger the next cycle).
23
+ This file is kept only as a pointer; it is not executed.