docs: workflow SSOT on fork main#58
Conversation
Consolidate intake, soup dogfood, and agent permissions into feature-work-lifecycle.md only. Other tooling docs link here instead of duplicating mermaid flows or restart-hub vs use-driver rules. Adds feature-work-lifecycle.md and peer-stack.md on fork main. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 10eff81f1c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| | `scripts/tooling/hapi-pr-emoji-batch.sh` | Classify upstream PRs → ✅/🔁/⚠️ (parallel gh; `--table` for humans) | | ||
| | `scripts/tooling/hapi-pr-session-emoji.sh` | Meta PR watcher sweep: rename HAPI session titles from batch classify (`--sweep`) | | ||
| | `scripts/tooling/hapi-remote-agent-budget.sh` | Pre-flight before bulk remote agent spawns (count + mem/swap gates) | |
There was a problem hiding this comment.
Add the tooling scripts before referencing them
These entries point agents at repo-relative scripts, and the new example below runs ./scripts/tooling/hapi-pr-session-emoji.sh --sweep, but this commit does not include any of scripts/tooling/hapi-pr-emoji-batch.sh, scripts/tooling/hapi-pr-session-emoji.sh, or scripts/tooling/hapi-remote-agent-budget.sh (checked scripts/tooling/). On a fresh checkout, following the documented meta watcher flow fails immediately instead of classifying or renaming PR sessions.
Useful? React with 👍 / 👎.
|
|
||
| ### HAPI web session chat (canonical — tiann/hapi#956) | ||
|
|
||
| `bun scripts/tooling/hapi-display-image.mjs <session-prefix> <absolute-path> [title]` |
There was a problem hiding this comment.
Commit the media helper before requiring it
The peer-stack handoff makes bun scripts/tooling/hapi-display-image.mjs ... the documented path for inline proof, but scripts/tooling/hapi-display-image.mjs is not in this checkout. Since the lifecycle now requires inline PNG/MP4 evidence before operator dogfood, agents following these instructions cannot complete the gate unless the helper is committed or the doc points to an existing command.
Useful? React with 👍 / 👎.
| --worktree ~/coding/hapi/worktrees/scratchlist-exit-after-send | ||
|
|
||
| # Playwright on real session UI | ||
| bun run test:e2e:peer e2e/scratchlist-exit-after-queue-peer.spec.ts |
There was a problem hiding this comment.
Define the peer e2e script before documenting it
This command is now the documented peer-stack smoke path, but the root package.json only defines test:e2e and test:e2e:ui; there is no test:e2e:peer script. On a fresh checkout, agents following the new handoff instructions fail before Playwright runs, so the mandatory peer-stack evidence gate cannot be completed as written.
Useful? React with 👍 / 👎.
| With ~30 agents on this repo, two callers can land on `hapi-driver-rebuild` or `hapi-use-worktree` simultaneously — one rewrites the driver tree mid-merge while the other reads it, or two stack switches race on the symlink and hub restart. | ||
|
|
||
| Both scripts now take a `flock` on `~/.hapi/locks/{rebuild,switch}.lock` and publish state to `~/.hapi/driver-status.json` (atomic rewrite, schema v1). A second concurrent invocation exits **75** (`EX_TEMPFAIL`) with a pointer at the first. | ||
| Both scripts now take a single `flock` on `~/.hapi/locks/stack.lock` (shared with `hapi-restart-hub`) and publish state to `~/.hapi/driver-status.json` (atomic rewrite, schema v1). A second concurrent rebuild **or** switch **or** hub restart exits **75** (`EX_TEMPFAIL`) with a pointer at the first. |
There was a problem hiding this comment.
Stop claiming a shared stack lock until scripts use it
This says rebuild, switch, and hub restart all share one stack.lock, but the current implementation in scripts/tooling/lib/driver-status.sh still acquires separate rebuild.lock and switch.lock, while hapi-restart-hub.sh only takes the switch lock. In the documented concurrent rebuild + restart scenario, agents can still restart the hub while the driver tree is being rewritten, exactly the race this paragraph says is fixed.
Useful? React with 👍 / 👎.
| - Post-swap: `verify-soup-web-dist.mjs` — fail rolls back to `dist.prev` | ||
| - Audit anytime: `hapi-verify-web-dist` |
There was a problem hiding this comment.
Ship the web-dist verifier before making it a gate
This new guarantee depends on verify-soup-web-dist.mjs / hapi-verify-web-dist, but neither exists under scripts/, and hapi-driver-rebuild.sh currently swaps dist.next into dist without invoking any verifier or rollback. When a web build succeeds but the bundle is stale or missing expected strings, agents following this doc will either get command not found or assume an auto-rollback happened when it did not.
Useful? React with 👍 / 👎.
| hapi-peer-stack up --name scratchlist-959 \ | ||
| --worktree ~/coding/hapi/worktrees/scratchlist-exit-after-send |
There was a problem hiding this comment.
Add the peer-stack launcher before making it the default
The new default demo topology starts with hapi-peer-stack up, but there is no hapi-peer-stack script or binary in this checkout (checked scripts/ and the repo). Fresh feature peers following the new default flow cannot bring up the isolated hub at all, before they even reach the Playwright or evidence steps.
Useful? React with 👍 / 👎.
|
|
||
| 3. **Process killed mid-drain (STALE lock)** — switch pid died at ~570s (before the 600s proceed-anyway timeout), leaving `switch.state=running` + orphan `stack.lock`. Likely cause: agent tool/MCP session teardown or a new shell command in the same agent turn killing the background tree despite `setsid nohup`. **Mitigation:** launch watch from an **external** tmux/SSH session for real set-and-forget; do not depend on agent-background for multi-minute drains. | ||
|
|
||
| 4. **No retry on activation failure (watch exits)** — after stale lock, new watch polls reached `WORKING=0` but `hapi-use-driver` failed with `driver stack busy`; `exec` replaced the watch process, which exited on error. Operator had to manually clear lock and relaunch. **Fix:** watch runs activation in a subshell and **resumes polling** on failure; `driver_stack_autoclear_stale` clears dead-pid status before each wait. |
There was a problem hiding this comment.
Do not claim watch retries until implemented
This says activation failures are retried, but scripts/tooling/hapi-watch-activate-driver.sh still uses exec hapi-use-driver at both activation sites, so any driver stack busy or other activation failure replaces the watcher and exits instead of resuming the poll loop. Operators following the documented set-and-forget promotion path will still need manual relaunch after exactly this failure mode.
Useful? React with 👍 / 👎.
|
|
||
| ## Port ownership gate (2026-06-20) | ||
|
|
||
| Before `hapi-use-driver`, watch now calls `lib/hub-port-guard.sh`: |
There was a problem hiding this comment.
Add the port guard before documenting it
This new safety gate is not present in the repository: there is no scripts/tooling/lib/hub-port-guard.sh, and hapi-watch-activate-driver.sh does not check port ownership before calling hapi-use-driver. If a feature worktree hub is already bound to :3006, the documented watch path will still proceed into the crash-loop scenario this section says is blocked.
Useful? React with 👍 / 👎.
Summary
docs/tooling/feature-work-lifecycle.mdis the sole workflow doc (both mermaid charts, soup dogfood, agent matrix, ship/done).feature-work-lifecycle.mdandpeer-stack.mdto fork main (previously mirror-only).Test plan
Made with Cursor