Skip to content

Commit b223065

Browse files
committed
chore(wheelhouse): cascade template@ac368a9b
Auto-applied by socket-wheelhouse sync-scaffolding into cascade-socket-bin-75697. 3 file(s) touched: - .claude/hooks/fleet/gh-token-hygiene-guard/index.mts - .claude/skills/agent-ci/SKILL.md - .claude/skills/agent-ci/reference.md
1 parent 820086f commit b223065

3 files changed

Lines changed: 114 additions & 0 deletions

File tree

.claude/hooks/fleet/gh-token-hygiene-guard/index.mts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,26 @@ function platformAuthGuidance(): readonly string[] {
635635
]
636636
}
637637
if (process.platform === 'darwin') {
638+
const noTty = !process.stdin.isTTY
638639
const osBlocked = isOsascriptBlocked()
640+
const ttyNote = noTty
641+
? [
642+
'This shell has no controlling TTY, so the Touch ID prompt',
643+
"can't surface — `sudo` needs an interactive parent to ask",
644+
'for the biometric confirmation. Common cause: running via',
645+
"a tool that spawns subprocesses without `-it` (Claude Code's",
646+
'Bash tool, CI runners, headless scripts).',
647+
'',
648+
'Workaround: run the gh refresh from your own terminal:',
649+
'',
650+
' gh auth refresh -h github.com -s workflow',
651+
'',
652+
'Touch the sensor when prompted. The session-bound grant',
653+
'will land at ~/.claude/gh-workflow-grant; the next workflow',
654+
'dispatch in this Claude session will then pass through.',
655+
'',
656+
]
657+
: []
639658
const mdmNote = osBlocked
640659
? [
641660
'An MDM (iru / Jamf / Mosyle / Kandji) is intercepting',
@@ -645,6 +664,7 @@ function platformAuthGuidance(): readonly string[] {
645664
]
646665
: []
647666
return [
667+
...ttyNote,
648668
...mdmNote,
649669
'Enable Touch ID for sudo (copy-paste verbatim — `EOF` MUST be',
650670
'at column 0, no leading whitespace, or the heredoc will hang):',

.claude/skills/agent-ci/SKILL.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
name: agent-ci
3+
description: Run this repo's GitHub Actions workflows locally in Docker with Agent CI to validate changes before pushing. Use before opening or updating a PR, after editing a workflow YAML under .github/workflows, or whenever catching a CI failure locally beats waiting on a remote runner.
4+
user-invocable: true
5+
allowed-tools: Bash, Read, Edit
6+
---
7+
8+
# agent-ci
9+
10+
Run the repo's CI pipeline locally before pushing. CI was green before you started, so any failure the local run surfaces comes from your changes.
11+
12+
RedwoodJS wrote the upstream tool and skill (MIT, https://github.com/redwoodjs/agent-ci). The fleet pins `@redwoodjs/agent-ci` in the wheelhouse catalog and runs it through `pnpm exec`, never `npx`. Edit only in `socket-wheelhouse/template/`; the cascade refreshes downstream copies.
13+
14+
## Requirements
15+
16+
- **Docker must be running** — each job runs in a container. No daemon means the run can't start; fall back to the `greening-ci` skill or remote CI.
17+
- **The dep is already installed**`@redwoodjs/agent-ci` is a fleet devDependency (`catalog:`), provisioned by `pnpm install`.
18+
19+
## Run
20+
21+
```bash
22+
pnpm exec agent-ci run --quiet --all --pause-on-failure
23+
```
24+
25+
`--all` runs the PR/push workflows for the current branch. `--pause-on-failure` stops at the first failed step and holds the container open for `retry`. Pipes are safe: when stdout is not a TTY the launcher detaches and the foreground process exits **77** the moment a step pauses, so `| tee log` and `> log.txt` work.
26+
27+
## Fix and retry
28+
29+
When a step fails the run pauses. Fix the code, then retry the paused runner — don't restart the whole pipeline:
30+
31+
```bash
32+
pnpm exec agent-ci retry --name <runner-name>
33+
```
34+
35+
Re-run from an earlier step with `--from-step <N>`. Repeat fix → retry until every job passes. Don't push to trigger remote CI when agent-ci can run it locally.
36+
37+
## Reference
38+
39+
- **Machine-readable `--json` event stream, the full requirements rationale, and the agent-ci-vs-remote-CI decision matrix**: see [reference.md](reference.md).
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# agent-ci reference
2+
3+
## Contents
4+
5+
- Machine-readable output (`--json`)
6+
- The exit-77 pause contract
7+
- Requirements rationale (Docker, install)
8+
- When to use agent-ci vs. remote CI
9+
- Command summary
10+
11+
## Machine-readable output (`--json`)
12+
13+
Add `--json` (or set `AGENT_CI_JSON=1`) to emit an NDJSON event stream on stdout — one JSON object per line. Use it for programmatic monitoring instead of grepping plaintext.
14+
15+
Events:
16+
17+
- `run.start` — carries `schemaVersion: 1` and `runId`.
18+
- `job.start`, `job.finish``status: passed | failed`.
19+
- `step.start`, `step.finish``status: passed | failed | skipped`.
20+
- `run.paused` — carries `runner` and `retry_cmd` (the exact command to resume).
21+
- `run.finish``status: passed | failed`.
22+
- `diagnostic` — non-fatal notices.
23+
24+
`--json` is independent of `--quiet`. The diff renderer is auto-suppressed under `--json` so ANSI escapes don't collide with the stream.
25+
26+
The robust agent loop: parse the stream, react to `run.paused` (fix the failure named in `runner`), then run the `retry_cmd` it carries. No plaintext parsing required.
27+
28+
## The exit-77 pause contract
29+
30+
When stdout is not a TTY (piped, redirected, captured by a parent process), the launcher detaches the run. The foreground process exits **77** the instant a step pauses. This frees the pipe — `| tee`, `> log.txt`, command substitution — while the container stays paused in the background, ready for `retry`. Exit 77 means "paused, awaiting retry," not "failed."
31+
32+
## Requirements rationale
33+
34+
- **Docker.** agent-ci executes each workflow job inside a container, the same way GitHub's runners do. Without a running Docker daemon the run cannot start. There is no degraded mode; use `greening-ci` (push and watch remote CI) instead.
35+
- **Install.** `@redwoodjs/agent-ci` is a fleet devDependency declared as `catalog:` in every repo's `package.json`, pinned in the wheelhouse `pnpm-workspace.yaml` catalog. `pnpm install` provisions it. The published package is a self-contained Node CLI (`dist/cli.js`) — it has no platform-binary dependencies and its `ssh2` native build scripts are declined in the fleet's `allowBuilds`/`allowScripts` (the CLI runs without them).
36+
37+
## When to use agent-ci vs. remote CI
38+
39+
| Situation | Use |
40+
| --- | --- |
41+
| Edited a workflow YAML (`.github/workflows/*.yml`) | agent-ci first — a malformed workflow fails the same locally and remotely, skipping the push/wait loop. |
42+
| Code change that only needs lint / typecheck / unit tests | `pnpm run check --all` — faster than spinning up containers for the pure-Node gates. |
43+
| Workflow does something the local scripts don't (matrix, container steps, action wiring, secrets-shaped env) | agent-ci. |
44+
| No Docker, or the failure needs an off-machine action (a deploy, a remote service) | push and use `greening-ci`. |
45+
46+
## Command summary
47+
48+
| Command | Purpose |
49+
| --- | --- |
50+
| `pnpm exec agent-ci run --all --pause-on-failure` | Run the branch's PR/push workflows; pause on first failure. |
51+
| `pnpm exec agent-ci run --workflow <path>` | Run a single workflow file. |
52+
| `pnpm exec agent-ci retry --name <runner>` | Resume a paused runner after a fix. |
53+
| `pnpm exec agent-ci retry --name <runner> --from-step <N>` | Resume from an earlier step. |
54+
55+
Add `--quiet` to suppress the live renderer, `--json` for the NDJSON stream.

0 commit comments

Comments
 (0)