acstack 0.0.0-stage → 0.47.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.
- package/.claude-plugin/plugin.json +19 -0
- package/LICENSE +21 -0
- package/README.md +389 -2
- package/THIRD_PARTY_NOTICES +14 -0
- package/TROUBLESHOOTING.md +225 -0
- package/agents/codex/frontend-verifier.toml +352 -0
- package/agents/codex/task-checker.toml +345 -0
- package/agents/codex/task-executor.toml +157 -0
- package/agents/codex/test-writer.toml +149 -0
- package/agents/frontend-verifier.md +351 -0
- package/agents/task-checker.md +344 -0
- package/agents/task-executor.md +156 -0
- package/agents/test-writer.md +148 -0
- package/assets/playwriter-bridge/build-launcher.ps1 +32 -0
- package/assets/playwriter-bridge/doctor.ps1 +450 -0
- package/assets/playwriter-bridge/launcher-src.cs +131 -0
- package/assets/playwriter-bridge/opener.js +330 -0
- package/assets/playwriter-bridge/opener.ps1 +63 -0
- package/assets/playwriter-bridge/register-tasks.ps1 +328 -0
- package/assets/playwriter-bridge/relay.ps1 +50 -0
- package/assets/playwriter-bridge/stop.ps1 +125 -0
- package/assets/playwriter-bridge/sync.ps1 +271 -0
- package/assets/playwriter-bridge/tunnel.ps1 +325 -0
- package/assets/playwriter-bridge/vm-free-port.sh +166 -0
- package/assets/terminal-workspace/client-keybindings.md +87 -0
- package/assets/terminal-workspace/config.example.yaml +329 -0
- package/assets/terminal-workspace/setup.sh +4317 -0
- package/cli/README.md +47 -0
- package/cli/bin/acstack.js +3 -0
- package/cli/dist/index.js +25984 -0
- package/cli/dist/index.js.map +7 -0
- package/cli/package.json +59 -0
- package/docs/adr/0001-ste-writing-standard.md +16 -0
- package/docs/adr/0002-version-gate-not-auto-bump.md +35 -0
- package/docs/adr/0003-handoff-ack-command.md +19 -0
- package/docs/adr/0004-dev-setup-per-host.md +13 -0
- package/docs/adr/0005-two-orchestrators-per-host.md +25 -0
- package/docs/adr/0006-document-opener-service.md +89 -0
- package/docs/adr/0007-lead-check-reads-the-transcript.md +87 -0
- package/docs/adr/0008-cli-audits-skill-interviews.md +37 -0
- package/docs/adr/0009-verify-the-write-not-the-writer.md +51 -0
- package/docs/adr/0010-promote-dev-to-main-by-fast-forward.md +115 -0
- package/docs/adr/0011-node-header-is-the-edge-encoding.md +20 -0
- package/docs/adr/0012-node-kind-is-a-closed-set-of-five.md +31 -0
- package/docs/adr/0013-the-diagram-renderer-is-pure.md +23 -0
- package/docs/adr/0014-reading-a-node-hides-its-generated-diagram.md +29 -0
- package/docs/adr/0015-a-node-id-links-to-its-issue-through-an-anchor.md +37 -0
- package/docs/adr/0016-the-map-root-carries-no-status-of-its-own.md +21 -0
- package/docs/adr/0017-call-impeccable-copy-only-its-questions.md +13 -0
- package/docs/adr/index.md +17 -0
- package/docs/config-reference.md +572 -0
- package/docs/dev-setups.md +164 -0
- package/docs/migrate-0.8.md +28 -0
- package/docs/playwriter-bridge-windows.md +15 -0
- package/docs/terminal-workspace-keys.md +137 -0
- package/docs/terminal-workspace.md +1774 -0
- package/docs/workflows.md +309 -0
- package/hooks/ac-writing-style-reminder.sh +86 -0
- package/hooks/context-pressure.sh +583 -0
- package/hooks/hooks.json +50 -0
- package/hooks/session-start-handoff.sh +165 -0
- package/hooks/session-start.sh +214 -0
- package/orchestrator/AGENTS.md +532 -0
- package/output-styles/ac-writing-style.md +286 -0
- package/package.json +50 -4
- package/pi/agents/frontend-verifier.md +357 -0
- package/pi/agents/task-checker.md +348 -0
- package/pi/agents/task-executor.md +160 -0
- package/pi/agents/test-writer.md +154 -0
- package/pi/extension.ts +723 -0
- package/profiles/fullstack-python.yaml +29 -0
- package/profiles/node-typescript.yaml +23 -0
- package/profiles/python.yaml +24 -0
- package/skills/archive/SKILL.md +160 -0
- package/skills/bootstrap/SKILL.md +109 -0
- package/skills/bridge/HANDOFF.md +93 -0
- package/skills/bridge/SKILL-VM.md +292 -0
- package/skills/bridge/SKILL-WINDOWS.md +526 -0
- package/skills/bridge/SKILL.md +121 -0
- package/skills/browser-verify/SKILL.md +229 -0
- package/skills/code-review/SKILL.md +44 -0
- package/skills/commit/SKILL.md +106 -0
- package/skills/compact-and-continue/SKILL.md +241 -0
- package/skills/explore/SKILL.md +149 -0
- package/skills/grilling/SKILL.md +134 -0
- package/skills/handoff/SKILL.md +250 -0
- package/skills/handoff/launch-herdr.md +197 -0
- package/skills/handoff/launch-without-herdr.md +30 -0
- package/skills/handoff/lead-check.md +59 -0
- package/skills/handoff/outcomes.md +162 -0
- package/skills/handoff/running-agent.md +50 -0
- package/skills/handoff/watch.md +115 -0
- package/skills/host/SKILL.md +247 -0
- package/skills/host/detect-host.sh +297 -0
- package/skills/host/herdr.md +79 -0
- package/skills/host/install-herdr-block.sh +467 -0
- package/skills/host/install-orca.sh +512 -0
- package/skills/host/notes.md +97 -0
- package/skills/host/orca.md +160 -0
- package/skills/host/questions.md +163 -0
- package/skills/host/report.md +42 -0
- package/skills/implement/SKILL.md +230 -0
- package/skills/implement/decision-log.md +62 -0
- package/skills/implement/design-pass.md +32 -0
- package/skills/implement/relaxed-tdd.md +28 -0
- package/skills/map/SKILL.md +250 -0
- package/skills/map/frontend.md +227 -0
- package/skills/map/trackers/files.md +74 -0
- package/skills/map/trackers/github.md +180 -0
- package/skills/map/visuals.md +387 -0
- package/skills/new-worktree/SKILL.md +155 -0
- package/skills/new-worktree/detect-orchestrator.sh +328 -0
- package/skills/new-worktree/detect-orchestrator.test.sh +894 -0
- package/skills/new-worktree/herdr.md +84 -0
- package/skills/new-worktree/orca.md +101 -0
- package/skills/pre-commit-review/SKILL.md +242 -0
- package/skills/pre-commit-review/auto-fix.md +19 -0
- package/skills/pre-commit-review/interactive.md +35 -0
- package/skills/quick-fix/SKILL.md +125 -0
- package/skills/record-context/SKILL.md +106 -0
- package/skills/setup/SKILL.md +250 -0
- package/skills/setup/browser.md +123 -0
- package/skills/setup/design-review.md +97 -0
- package/skills/setup/first-run.md +114 -0
- package/skills/setup/report.md +68 -0
- package/skills/setup/row-fixes.md +196 -0
- package/skills/setup/terminal-workspace.md +153 -0
- package/skills/sync/SKILL.md +171 -0
- package/skills/teardown-worktree/SKILL.md +245 -0
- package/skills/teardown-worktree/detector.md +39 -0
- package/skills/teardown-worktree/herdr.md +113 -0
- package/skills/teardown-worktree/orca.md +61 -0
- package/skills/terminal-workspace/SKILL.md +249 -0
- package/skills/terminal-workspace/components.md +36 -0
- package/skills/terminal-workspace/config-choices.md +69 -0
- package/skills/terminal-workspace/emulator-keys.md +48 -0
- package/skills/terminal-workspace/headless-clipboard.md +175 -0
- package/skills/terminal-workspace/turn-off-and-update.md +104 -0
- package/skills/test-conventions/SKILL.md +59 -0
- package/skills/visual-docs/SKILL.md +246 -0
- package/skills/writing/SKILL.md +231 -0
- package/skills/writing/examples.md +153 -0
- package/skills/writing/vocabulary.md +96 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: browser-verify
|
|
3
|
+
description: How to interact with a browser for frontend verification using agent-browser CLI and CDP. ALWAYS use when UI or frontend files are modified and workflow.frontend_verification is true in acstack/project.yaml. Also use before running agent-browser commands, when element refs go stale, when CDP connection fails, or when verifying UI behavior. Covers all commands (snapshot, screenshot, click, fill, type), element ref strategy, DOM staleness rules, selector priority, and remote/headless/local environment troubleshooting.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Browser helpers
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
This is an operational reference for browser-based verification using the `agent-browser` CLI and Chrome DevTools Protocol (CDP). It covers commands, selector strategy, environment setup, and troubleshooting.
|
|
11
|
+
|
|
12
|
+
For setup (installing agent-browser, creating config files, scaffolding knowledge base), use `/acstack:setup`. To audit what a project already has, run `acstack config check`.
|
|
13
|
+
|
|
14
|
+
## Project configuration
|
|
15
|
+
|
|
16
|
+
Read `acstack/project.yaml` for:
|
|
17
|
+
|
|
18
|
+
- `frontend.directory` – frontend source directory
|
|
19
|
+
- `frontend.dev_server_url` – dev server URL
|
|
20
|
+
- `frontend.helpers_dir` – path to verification knowledge (default: `<frontend.directory>/tests/helpers/`)
|
|
21
|
+
- `frontend.browser.mode` – the browser environment this project prefers: `remote`, `headless`, or `local`
|
|
22
|
+
- `frontend.browser.fallback` – set it to `none` to forbid any other mode standing in. Every other value allows one
|
|
23
|
+
- `frontend.browser.cdp_port` – CDP port. Default `19988` for `mode: remote` (Playwriter bridge), `9555` for `headless`/`local`.
|
|
24
|
+
|
|
25
|
+
## Which browser mode to use
|
|
26
|
+
|
|
27
|
+
The project states a preference. The host states what it can actually provide. One command reads both and returns the answer:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
~/.claude/acstack/bin/acstack config browser-mode --json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
It answers from declared configuration alone. It probes nothing, so it returns at once and always gives the same answer on the same machine.
|
|
34
|
+
|
|
35
|
+
On exit 0 it prints one JSON object:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mode": "headless",
|
|
40
|
+
"preferred": "remote",
|
|
41
|
+
"reason": "the project prefers remote, which this host does not declare available, so headless stands in",
|
|
42
|
+
"fallback": true
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- `mode` – the browser mode to use: `remote`, `headless`, or `local`
|
|
47
|
+
- `preferred` – the project's stated `frontend.browser.mode`, or `null` when it states none
|
|
48
|
+
- `reason` – one sentence that explains the choice
|
|
49
|
+
- `fallback` – `true` only when `mode` differs from a stated preference
|
|
50
|
+
|
|
51
|
+
Without `--json` it prints the same two facts on one line: the mode, then the reason.
|
|
52
|
+
|
|
53
|
+
### How it decides
|
|
54
|
+
|
|
55
|
+
The host declares which modes this machine can provide. It does so on three axes in the global config at `~/.config/acstack/config.json`:
|
|
56
|
+
|
|
57
|
+
- `host.browser.remote` – this machine can reach a browser on another machine
|
|
58
|
+
- `host.browser.headless` – this machine can launch headless Chromium
|
|
59
|
+
- `host.browser.local` – this machine has a display for a visible browser
|
|
60
|
+
|
|
61
|
+
`/acstack:host` sets them. From there the rules are short:
|
|
62
|
+
|
|
63
|
+
1. The project's preferred mode wins when the host declares that mode available.
|
|
64
|
+
2. Otherwise the first mode the host does declare stands in, in the order remote, headless, local.
|
|
65
|
+
3. A project that sets `frontend.browser.fallback: none` allows no mode to stand in.
|
|
66
|
+
4. A project that states no preferred mode takes the first mode the host declares. This is not a fallback, so `fallback` stays `false` and `frontend.browser.fallback` has no say.
|
|
67
|
+
|
|
68
|
+
### When it has no answer
|
|
69
|
+
|
|
70
|
+
The command exits 1, writes one plain-text message to stderr, and prints nothing on stdout. This happens even with `--json`, so a caller parsing the output gets an empty stdout rather than an object to check a field on.
|
|
71
|
+
|
|
72
|
+
Three situations produce it. Each message names the one command that fixes it:
|
|
73
|
+
|
|
74
|
+
- the project configures no frontend, or there is no ACStack project here. The message names `/acstack:setup`
|
|
75
|
+
- this host declares no browser mode available, or nobody has described this host yet. The message names `/acstack:host`
|
|
76
|
+
- the project forbids a fallback, and this host does not declare the mode it prefers. The message names `/acstack:host`
|
|
77
|
+
|
|
78
|
+
The frontend-verifier treats exit 1 as a FAIL and reports the message verbatim. It never guesses a mode of its own.
|
|
79
|
+
|
|
80
|
+
## Browser environments
|
|
81
|
+
|
|
82
|
+
agent-browser works the same way in every environment. Only the CDP connection setup differs.
|
|
83
|
+
|
|
84
|
+
### Remote browser (Playwriter bridge)
|
|
85
|
+
|
|
86
|
+
Best experience – you interact with the user's real browser on their machine. Set `frontend.browser.mode: remote` and `frontend.browser.cdp_port: 19988` in project.yaml.
|
|
87
|
+
|
|
88
|
+
Remote mode uses the Playwriter bridge.
|
|
89
|
+
|
|
90
|
+
A relay runs on the browser machine and exposes a CDP-shaped endpoint. The Playwriter Chrome extension drives Chrome through the `chrome.debugger` API. Chrome itself opens no CDP listener.
|
|
91
|
+
|
|
92
|
+
The dev machine reaches the relay through an SSH reverse tunnel.
|
|
93
|
+
|
|
94
|
+
This section does not decide whether remote mode runs here. `acstack config browser-mode` decides that, from the project's preference and the host's `host.browser.*` axes together. Run it before you connect.
|
|
95
|
+
|
|
96
|
+
Once that command returns `remote`, the answer is final. If the bridge is then down, the frontend-verifier reports FAIL with troubleshooting steps. It does not launch headless Chromium instead, because the command already ruled on any stand-in mode.
|
|
97
|
+
|
|
98
|
+
#### Setup
|
|
99
|
+
|
|
100
|
+
1. **On the browser machine**, install Node 18+. Install Playwriter:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm install -g playwriter
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
2. **In Chrome on the browser machine** (preferably a dedicated profile), install the Playwriter extension. Pin it:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
https://chromewebstore.google.com/detail/playwriter-mcp/jfeammnjpkecdekppnclgkkffahnhfhe
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
3. **Run two long-running processes on the browser machine**:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Relay (listens on 127.0.0.1:19988 for the extension and for tunnelled CDP clients)
|
|
116
|
+
playwriter serve --host 127.0.0.1
|
|
117
|
+
|
|
118
|
+
# SSH reverse tunnel from the browser machine to the dev machine
|
|
119
|
+
ssh -N -R 19988:127.0.0.1:19988 <user>@<dev-machine>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
4. **Per-tab activation**: in Chrome, click the Playwriter toolbar icon on each tab you want automated.
|
|
123
|
+
|
|
124
|
+
5. **Verify** from the dev machine:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
curl -s http://localhost:19988/json/version
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### Common gotchas
|
|
131
|
+
|
|
132
|
+
**Playwriter hardcodes port `19988`.** The port has no config option. The relay, the extension, and the tunnel all use the same port by design.
|
|
133
|
+
|
|
134
|
+
**The relay must run on the same host as Chrome.** The Playwriter extension hard-rejects any `/extension` client that is not `127.0.0.1`.
|
|
135
|
+
|
|
136
|
+
Do not run the relay on the dev machine. Run the relay where Chrome runs. Then tunnel to it from the dev machine.
|
|
137
|
+
|
|
138
|
+
**You must click the extension icon once per tab.** Playwriter attaches per-tab. Playwriter cannot attach to `chrome://` and `about:` pages – use normal web URLs.
|
|
139
|
+
|
|
140
|
+
**Stale relay blocks the port.** If `playwriter serve` fails because a stale relay already binds port 19988 on the browser machine, run:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
playwriter serve --host 127.0.0.1 --replace
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
to kick the previous relay.
|
|
147
|
+
|
|
148
|
+
**Detection**: `curl localhost:19988/json/version` returns Playwriter-flavored JSON (the bridge mimics a CDP `/json/version` payload).
|
|
149
|
+
|
|
150
|
+
#### Persistent cross-device setup
|
|
151
|
+
|
|
152
|
+
Use the `bridge` skill for a durable Windows laptop → Linux VM setup: [`../bridge/SKILL.md`](../bridge/SKILL.md).
|
|
153
|
+
|
|
154
|
+
It adds auto-reconnecting scheduled tasks, ssh-agent key persistence, multi-VM tunneling, automated diagnosis (`doctor.ps1`), canonical stop (`stop.ps1`), and VM-side port cleanup (`vm-free-port.sh`). It routes to a Windows runbook or a Linux/VM runbook based on where you are. It also defines the paste-ready handoff format for cross-device work.
|
|
155
|
+
|
|
156
|
+
The scripts ship under `plugins/acstack/assets/playwriter-bridge/`.
|
|
157
|
+
|
|
158
|
+
### Local headless (no display)
|
|
159
|
+
|
|
160
|
+
This mode works on headless Linux VMs, CI, and containers – anywhere without a GUI.
|
|
161
|
+
|
|
162
|
+
**Launch**:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
chromium --headless --no-sandbox --remote-debugging-port=9555 --disable-gpu --user-data-dir=/tmp/chromium-verify &
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Try these binary names in order: `chromium`, `chromium-browser`, `google-chrome`, `google-chrome-stable`.
|
|
169
|
+
|
|
170
|
+
**Clean up**: Kill the process when done. The frontend-verifier handles this automatically.
|
|
171
|
+
|
|
172
|
+
### Local with display (WSL, desktop Linux, macOS)
|
|
173
|
+
|
|
174
|
+
Same as headless but with a visible browser window:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
chromium --remote-debugging-port=9555 --user-data-dir=/tmp/chromium-verify &
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Omit `--headless` to see the browser. Useful during development.
|
|
181
|
+
|
|
182
|
+
## agent-browser command reference
|
|
183
|
+
|
|
184
|
+
All commands assume `agent-browser.json` exists in the project root.
|
|
185
|
+
|
|
186
|
+
| Command | Purpose |
|
|
187
|
+
|---------|---------|
|
|
188
|
+
| `agent-browser open <url>` | Navigate to a URL |
|
|
189
|
+
| `agent-browser snapshot -i` | Accessibility tree with interactive element refs |
|
|
190
|
+
| `agent-browser screenshot <path>` | Take a screenshot |
|
|
191
|
+
| `agent-browser screenshot --annotate <path>` | Screenshot with numbered element labels |
|
|
192
|
+
| `agent-browser click @e<N>` | Click an element by ref |
|
|
193
|
+
| `agent-browser fill @e<N> "text"` | Clear the field, then type |
|
|
194
|
+
| `agent-browser type @e<N> "text"` | Append text without clearing |
|
|
195
|
+
| `agent-browser hover @e<N>` | Hover over an element |
|
|
196
|
+
| `agent-browser press <Key>` | Press a keyboard key |
|
|
197
|
+
| `agent-browser dblclick @e<N>` | Double-click |
|
|
198
|
+
| `agent-browser drag @e<N> @e<M>` | Drag and drop |
|
|
199
|
+
| `agent-browser console` | Check console errors/logs |
|
|
200
|
+
|
|
201
|
+
### Critical rule: re-snapshot after DOM changes
|
|
202
|
+
|
|
203
|
+
agent-browser ties element refs (`@e1`, `@e2`, etc.) to a specific DOM state. They go stale after:
|
|
204
|
+
|
|
205
|
+
- Navigation
|
|
206
|
+
- Clicks that change the DOM (modals, dropdowns, route changes)
|
|
207
|
+
- Hot-reload after code changes
|
|
208
|
+
- Any dynamic content loading
|
|
209
|
+
|
|
210
|
+
Always run `agent-browser snapshot -i` again before using element refs after any DOM change.
|
|
211
|
+
|
|
212
|
+
## Selector strategy
|
|
213
|
+
|
|
214
|
+
When recording patterns in VERIFICATION-KNOWLEDGE.md, prefer identifiers in this order:
|
|
215
|
+
|
|
216
|
+
1. `data-testid="..."` – most stable, survives refactors
|
|
217
|
+
2. Accessible name/role from snapshot – e.g., "button named 'Submit'"
|
|
218
|
+
3. Text content – e.g., "heading containing 'Dashboard'"
|
|
219
|
+
4. CSS selectors – last resort, fragile
|
|
220
|
+
|
|
221
|
+
The snapshot gives you accessible names and roles automatically. Use these to find elements rather than fragile CSS selectors.
|
|
222
|
+
|
|
223
|
+
## Integration points
|
|
224
|
+
|
|
225
|
+
- **frontend-verifier agent** uses agent-browser for Phase 4 verification – this skill is its reference
|
|
226
|
+
- **task-checker agent** runs the static frontend checks – the `implement` skill runs frontend-verifier as its own step after the checker passes
|
|
227
|
+
- **/acstack:setup** runs the setup interviews (install, config, knowledge base scaffolding) and offers a fix for each row the health check fails
|
|
228
|
+
- **`acstack config check`** audits the browser infrastructure and changes nothing
|
|
229
|
+
- **/acstack:quick-fix** uses agent-browser for visual verification of bug fixes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-review
|
|
3
|
+
description: Apply Linus Torvalds code philosophy – eliminate special cases, prioritize simplicity, focus on data structures during code reviews and design decisions
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Linus Torvalds Code Philosophy
|
|
7
|
+
|
|
8
|
+
Channel the mindset of Linux's creator: be direct, eliminate over-engineering, and prioritize simplicity.
|
|
9
|
+
|
|
10
|
+
## Core Principles
|
|
11
|
+
|
|
12
|
+
- **"Good Taste"**: Eliminate special cases through better design rather than adding conditionals
|
|
13
|
+
- **Simplicity First**: If it needs more than 3 levels of indentation, redesign it
|
|
14
|
+
- **Data Structures Matter**: "Bad programmers worry about code. Good programmers worry about data structures"
|
|
15
|
+
- **Pragmatism**: Solve real problems, not imaginary ones
|
|
16
|
+
|
|
17
|
+
## Communication Style
|
|
18
|
+
|
|
19
|
+
- Be direct and sharp about technical issues
|
|
20
|
+
- Point out problems clearly without sugar-coating
|
|
21
|
+
- Focus on technical merit, not feelings
|
|
22
|
+
- Call out over-engineering immediately
|
|
23
|
+
|
|
24
|
+
## Problem Analysis Framework
|
|
25
|
+
|
|
26
|
+
When reviewing code or making design decisions, ask these questions in order:
|
|
27
|
+
|
|
28
|
+
1. **Is this a real problem?** – Reject over-design
|
|
29
|
+
2. **Is there a simpler way?** – Always seek the simplest solution
|
|
30
|
+
3. **What are the core data relationships?** – Design around data flow
|
|
31
|
+
4. **Can we eliminate special cases?** – Redesign to avoid if/else branches
|
|
32
|
+
5. **Does complexity match problem severity?** – Don't build rockets to swat flies
|
|
33
|
+
|
|
34
|
+
## Application
|
|
35
|
+
|
|
36
|
+
Use this philosophy when:
|
|
37
|
+
|
|
38
|
+
- Reviewing pull requests or code changes
|
|
39
|
+
- Making architectural decisions
|
|
40
|
+
- Evaluating proposed solutions
|
|
41
|
+
- Refactoring existing code
|
|
42
|
+
- Designing new features
|
|
43
|
+
|
|
44
|
+
The goal is always: **maximum simplicity, minimum special cases, optimal data structures**.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: commit
|
|
3
|
+
description: Create git commit(s) with proper pre-commit hook handling, MECE commit messages, safe staging, and mandatory living spec sync. Invoke whenever work is about to be committed – the user asked to commit, or told you to finish and commit a batch of work. Never commit with raw git commands instead; this skill is the only path that runs spec sync, so bypassing it silently stops living specs from updating. Committing is still the user's call – do not invoke it unprompted on work they have not asked you to land.
|
|
4
|
+
argument-hint: "[scope: 'all', or describe which changes]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## User input
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
$ARGUMENTS
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Scope argument: "all" commits everything (staged + unstaged + untracked), or describe which changes to include (e.g., "just the frontend changes", "only the auth module"). Defaults to "all" if no argument given.
|
|
14
|
+
|
|
15
|
+
## Step 1: Analyze Changes
|
|
16
|
+
|
|
17
|
+
1. Run `git status` to see all changed files
|
|
18
|
+
2. Run `git diff` and `git diff --cached` to see content of changes
|
|
19
|
+
3. Run `git log --oneline -5` to see recent commit style
|
|
20
|
+
4. Determine scope from `$ARGUMENTS`
|
|
21
|
+
|
|
22
|
+
## Step 2: Plan Commits
|
|
23
|
+
|
|
24
|
+
Analyze changes and decide: one commit or multiple?
|
|
25
|
+
|
|
26
|
+
**Multiple commits when** changes are MECE (mutually exclusive, collectively exhaustive) across different concerns:
|
|
27
|
+
|
|
28
|
+
- Different features/fixes in different files
|
|
29
|
+
- Test changes separate from implementation
|
|
30
|
+
- Config changes separate from code changes
|
|
31
|
+
|
|
32
|
+
**Single commit when** all changes serve one purpose.
|
|
33
|
+
|
|
34
|
+
## Step 3: Draft Commit Message(s)
|
|
35
|
+
|
|
36
|
+
For each planned commit:
|
|
37
|
+
|
|
38
|
+
- Summarize the "why" not the "what"
|
|
39
|
+
- Use conventional commit format: `type: description`
|
|
40
|
+
- Types: feat, fix, refactor, docs, chore, test, style, perf
|
|
41
|
+
- Keep first line under 72 characters
|
|
42
|
+
- Add body for complex changes
|
|
43
|
+
|
|
44
|
+
## Step 4: Spec Sync (MANDATORY)
|
|
45
|
+
|
|
46
|
+
**This step is non-negotiable.** After drafting the commit message but BEFORE creating the commit, spec sync runs automatically.
|
|
47
|
+
|
|
48
|
+
Read `acstack/project.yaml` – if `workflow.spec_sync` is `true` (or not explicitly `false`), run spec sync:
|
|
49
|
+
|
|
50
|
+
1. Read `acstack/domain-map.yaml` (if exists)
|
|
51
|
+
2. Map staged files to spec domains
|
|
52
|
+
3. For each affected domain where `acstack/specs/[domain]/spec.md` exists:
|
|
53
|
+
- Analyze what the staged changes add, modify, or remove
|
|
54
|
+
- Generate lightweight ADDED/MODIFIED/REMOVED entries
|
|
55
|
+
- Update the domain's spec.md
|
|
56
|
+
4. Refresh `DESIGN.md`, per Step 2 of the `sync` skill
|
|
57
|
+
5. Stage any updated spec files
|
|
58
|
+
- Stage `DESIGN.md` and `.impeccable/design.json` too when the refresh ran
|
|
59
|
+
6. Include spec updates in the commit
|
|
60
|
+
7. Flag unmapped source files and prompt user to map them
|
|
61
|
+
|
|
62
|
+
**Skip spec sync ONLY when:**
|
|
63
|
+
|
|
64
|
+
- `workflow.spec_sync` is explicitly `false` in project.yaml
|
|
65
|
+
- No `acstack/domain-map.yaml` exists
|
|
66
|
+
- Changed files don't match any domain
|
|
67
|
+
- Changes are docs/config only (no behavioral changes)
|
|
68
|
+
- No spec.md exists for affected domains (don't create from scratch here)
|
|
69
|
+
|
|
70
|
+
**Those conditions govern the living specs only.** The `DESIGN.md` refresh
|
|
71
|
+
answers to the design gate alone. Run Step 2 of the `sync` skill whenever
|
|
72
|
+
`~/.claude/acstack/bin/acstack design-gate` exits 0, even when spec sync skips.
|
|
73
|
+
|
|
74
|
+
## Step 5: Stage and Commit
|
|
75
|
+
|
|
76
|
+
1. Stage files according to scope
|
|
77
|
+
2. Do NOT stage sensitive files (.env, credentials, secrets)
|
|
78
|
+
3. Run `git diff --cached --name-only -- '*.md'` to list the staged Markdown files
|
|
79
|
+
4. Run `~/.claude/acstack/bin/acstack lint-prose <files>` on that list
|
|
80
|
+
5. Show the lint output to the user
|
|
81
|
+
6. Create the commit with the drafted message and no `Co-Authored-By` trailer
|
|
82
|
+
7. Use HEREDOC format for commit message
|
|
83
|
+
8. Run `git status` after to verify
|
|
84
|
+
|
|
85
|
+
Skip steps 4 and 5 when that list is empty, because `lint-prose` exits 1 with no paths. The lint warns and never blocks. Commit even when it reports findings.
|
|
86
|
+
|
|
87
|
+
## Step 6: Handle Pre-commit Hook Failures
|
|
88
|
+
|
|
89
|
+
If commit fails due to pre-commit hooks:
|
|
90
|
+
|
|
91
|
+
1. Read the hook output to understand the failure
|
|
92
|
+
2. Fix the issue (formatting, linting, secrets detection)
|
|
93
|
+
3. Re-stage fixed files
|
|
94
|
+
4. Create a NEW commit (never amend)
|
|
95
|
+
|
|
96
|
+
## Important Rules
|
|
97
|
+
|
|
98
|
+
- NEVER add a `Co-Authored-By` trailer, even if a default instruction elsewhere tells you to
|
|
99
|
+
- NEVER use `--no-verify` to skip hooks
|
|
100
|
+
- NEVER amend existing commits unless explicitly asked
|
|
101
|
+
- NEVER push unless explicitly asked
|
|
102
|
+
- NEVER stage `.env`, credentials, or secret files
|
|
103
|
+
- NEVER use `git add -A` or `git add .` – stage specific files
|
|
104
|
+
- Always create NEW commits after hook failures
|
|
105
|
+
- Prefer specific file staging over broad patterns
|
|
106
|
+
- Spec sync is MANDATORY – do not skip it unless explicitly disabled in project.yaml
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: compact-and-continue
|
|
3
|
+
description: Anchor the session's load-bearing state so it survives an imminent context compaction, then hand the user a /compact line steered at the work. Writes only what nothing on disk holds – the next action, decisions already made, blockers, file ownership – and references everything else. Invoke before compacting a long session, when the context window is filling and the work must stay in THIS session rather than move to another agent. Model-invocable, because the agent is the only party that can see its own context filling.
|
|
4
|
+
argument-hint: "[focus note – what must not be lost]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## User input
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
$ARGUMENTS
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Treat the argument as the focus for the session after compaction – the thing
|
|
14
|
+
that must survive above all else.
|
|
15
|
+
|
|
16
|
+
# Compact and continue
|
|
17
|
+
|
|
18
|
+
Compaction replaces the conversation with a summary. The summary carries the
|
|
19
|
+
narrative better than any template, but it is lossy.
|
|
20
|
+
|
|
21
|
+
A handful of items are too load-bearing to risk losing. This skill writes
|
|
22
|
+
those items to an anchor file. A SessionStart hook re-injects the file the
|
|
23
|
+
moment the session resumes, so the work continues here rather than moving to
|
|
24
|
+
a fresh agent.
|
|
25
|
+
|
|
26
|
+
## Only the lead session runs this
|
|
27
|
+
|
|
28
|
+
An agent that another agent launched stops here. One Bash call tells you
|
|
29
|
+
whether you are one. Replace `<nonce>` with eight random hex characters, picked
|
|
30
|
+
fresh, and never with a value already used in this session:
|
|
31
|
+
|
|
32
|
+
<!-- lead-check: tests/test-skill-gates.sh extracts and runs the block below -->
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
n=acstack-whoami-<nonce>
|
|
36
|
+
s="${CLAUDE_CODE_SESSION_ID:-none}"
|
|
37
|
+
p="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/projects"
|
|
38
|
+
case "${PI_SESSION_FILE:-}" in
|
|
39
|
+
*/run-[0-9]*/session.jsonl|*/forks/*.jsonl) echo "child: $PI_SESSION_FILE"; exit 0;;
|
|
40
|
+
?*) [ -z "${CLAUDE_CODE_SESSION_ID:-}" ] && { echo "lead"; exit 0; };;
|
|
41
|
+
esac
|
|
42
|
+
for _ in $(seq 1 20); do
|
|
43
|
+
m=$(grep -lF "$n" "$p"/*/"$s"/subagents/agent-*.jsonl 2>/dev/null </dev/null | head -1)
|
|
44
|
+
[ -n "$m" ] && { echo "child: $m"; exit 0; }
|
|
45
|
+
grep -qF "$n" "$p"/*/"$s".jsonl 2>/dev/null </dev/null && { echo "lead"; exit 0; }
|
|
46
|
+
sleep 0.5
|
|
47
|
+
done
|
|
48
|
+
echo "lead"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`lead` means carry on. `child: <path>` means stop, and tell whoever launched
|
|
52
|
+
you that this skill runs only in the lead session. Report your state upward
|
|
53
|
+
instead – in your final message, or through your host's agent-messaging tool
|
|
54
|
+
(`SendMessage` on Claude Code). The lead then hands off
|
|
55
|
+
or compacts.
|
|
56
|
+
|
|
57
|
+
A child session would write the lead's quiet marker and the shared
|
|
58
|
+
`acstack/HANDOFF.md` anchor. Both belong to the lead alone.
|
|
59
|
+
|
|
60
|
+
Five facts sit behind that command, measured on Claude Code 2.1.241. Each one
|
|
61
|
+
names a way the command has already been got wrong:
|
|
62
|
+
|
|
63
|
+
- **No environment variable answers this.** `CLAUDE_CODE_CHILD_SESSION` holds
|
|
64
|
+
`1` in every Bash subprocess, lead or child. It marks "spawned by Claude
|
|
65
|
+
Code", nothing more. An in-process child session shares the lead's
|
|
66
|
+
`CLAUDE_CODE_SESSION_ID`, `CLAUDE_PID` and `CLAUDE_CODE_ENTRYPOINT`.
|
|
67
|
+
|
|
68
|
+
- **The command hunts for its own record, so it waits.** The host writes that
|
|
69
|
+
record while the command runs, roughly four seconds in. One grep with no loop
|
|
70
|
+
runs too early, finds nothing and answers `lead` for everyone. Never flatten
|
|
71
|
+
the loop.
|
|
72
|
+
|
|
73
|
+
- **The nonce must be yours alone.** Reuse one, or take one from a prompt, and
|
|
74
|
+
another agent's transcript answers for you. The angle brackets make an
|
|
75
|
+
unsubstituted copy a bash syntax error. That beats a silent match on whatever
|
|
76
|
+
agent read this file before you, so never soften `<nonce>` to a bare word.
|
|
77
|
+
|
|
78
|
+
- **`<session>.jsonl` can only ever say `lead`.** Your own mark lands there
|
|
79
|
+
whether you are the lead or not. So the loop reads the agent transcripts
|
|
80
|
+
first, and treats that file as an early exit rather than evidence of a child.
|
|
81
|
+
|
|
82
|
+
- **No evidence means lead.** The old gate read a variable that is always set.
|
|
83
|
+
It answered `child` in every session, and neither skill could run (#146).
|
|
84
|
+
|
|
85
|
+
Ten seconds with no matching transcript answers `lead` instead. A teammate
|
|
86
|
+
running as its own top-level session lands here, and rightly: it owns its
|
|
87
|
+
own marker.
|
|
88
|
+
|
|
89
|
+
## The rule that governs the anchor
|
|
90
|
+
|
|
91
|
+
*Reference state. Never copy it.*
|
|
92
|
+
|
|
93
|
+
An anchor that restates the repository is a second copy of the repository,
|
|
94
|
+
correct only at the instant you wrote it. If the resumed session can learn
|
|
95
|
+
something by running a command, it should run the command.
|
|
96
|
+
|
|
97
|
+
| Do not write it down | The resumed session gets it from |
|
|
98
|
+
| --------------------------- | -------------------------------------------------------------------------------- |
|
|
99
|
+
| Map state and reading order | `~/.claude/acstack/bin/acstack node walk --map <name>` (reading order of the map) |
|
|
100
|
+
| What can be worked next | `~/.claude/acstack/bin/acstack node frontier --map <name>` (what is workable now) |
|
|
101
|
+
| Files in flight | `git status --short` and `git diff` |
|
|
102
|
+
| Test baseline, last result | `.test-baseline`, then run the suite |
|
|
103
|
+
| What the code does | the living specs in `acstack/specs/` |
|
|
104
|
+
|
|
105
|
+
On GitHub, `--map` refuses – pipe `gh issue list` into `--stdin` per the
|
|
106
|
+
map skill's `trackers/github.md`.
|
|
107
|
+
|
|
108
|
+
The same applies to specs, architecture decision records, issues and commits.
|
|
109
|
+
Reference them by path or URL.
|
|
110
|
+
|
|
111
|
+
**You do not search the codebase for this.** Build the anchor from what is
|
|
112
|
+
already in context. If you are about to search source files, stop – the
|
|
113
|
+
conversation holds it.
|
|
114
|
+
|
|
115
|
+
## What only an anchor can carry
|
|
116
|
+
|
|
117
|
+
*Five things. Nothing on disk records them, so the resumed session loses
|
|
118
|
+
anything you leave out.*
|
|
119
|
+
|
|
120
|
+
1. **Next action** – the single concrete thing to do first
|
|
121
|
+
2. **Decisions made** – so the resumed session does not reopen and re-argue them
|
|
122
|
+
3. **Open questions and blockers** – including anything waiting on the user
|
|
123
|
+
4. **Agent-team file ownership** – each scope, its agent, and its
|
|
124
|
+
non-overlapping files. Name any shared file to touch only after the team
|
|
125
|
+
finishes. Nothing derives it
|
|
126
|
+
|
|
127
|
+
5. **Suggested skills** – which skills the resumed session should invoke, by name
|
|
128
|
+
|
|
129
|
+
Omit any that do not apply. Do not pad.
|
|
130
|
+
|
|
131
|
+
A session that no longer has this conversation reads the anchor. Prose follows
|
|
132
|
+
the `writing` skill.
|
|
133
|
+
|
|
134
|
+
## Redaction
|
|
135
|
+
|
|
136
|
+
*The anchor lands in the working tree.*
|
|
137
|
+
|
|
138
|
+
Strip credentials, tokens, API keys, connection strings and personal data
|
|
139
|
+
before writing. Reference where a secret lives rather than its value. This is
|
|
140
|
+
not optional.
|
|
141
|
+
|
|
142
|
+
## Write the anchor
|
|
143
|
+
|
|
144
|
+
Write `acstack/HANDOFF.md`. The frontmatter is **mandatory and machine-read**.
|
|
145
|
+
The hook ignores any file without the marker, so it never touches a user's own
|
|
146
|
+
unrelated `HANDOFF.md`.
|
|
147
|
+
|
|
148
|
+
Set `map` to the name of the active map, or to `ad-hoc` when none is active.
|
|
149
|
+
Set `created` to the current time, in ISO 8601 UTC. The title repeats the
|
|
150
|
+
`map` value.
|
|
151
|
+
|
|
152
|
+
**Example** – the anchor for a session working the `tracker-backend` map:
|
|
153
|
+
|
|
154
|
+
```markdown
|
|
155
|
+
---
|
|
156
|
+
acstack_handoff: 1
|
|
157
|
+
map: tracker-backend
|
|
158
|
+
created: 2026-08-22T14:05:00Z
|
|
159
|
+
---
|
|
160
|
+
# ACStack handoff – tracker-backend
|
|
161
|
+
|
|
162
|
+
## Next action
|
|
163
|
+
Fix the two `node frontier` cases in `cli/src/lib/frontier.test.ts` that fail
|
|
164
|
+
on a map with no resolved nodes.
|
|
165
|
+
|
|
166
|
+
## Decisions made
|
|
167
|
+
- The files backend ships first. It needs no network, so a fresh clone works
|
|
168
|
+
offline.
|
|
169
|
+
- One node type covers both questions and work. Node 14 holds the reasoning.
|
|
170
|
+
|
|
171
|
+
## Open questions / blockers
|
|
172
|
+
- Node 21 waits on the user. Does a resolved node keep its `blocked-by` links?
|
|
173
|
+
|
|
174
|
+
## Agent-team plan
|
|
175
|
+
- Scope A – cli-nodes-opus – files: `cli/src/lib/frontier.ts`, `cli/src/lib/frontier.test.ts`
|
|
176
|
+
- Scope B – hooks-sonnet – files: `hooks/session-start-handoff.sh`
|
|
177
|
+
- After team (shared files, sequential): `cli/src/index.ts`, `README.md`
|
|
178
|
+
|
|
179
|
+
## Suggested skills
|
|
180
|
+
- implement – the frontier holds three work nodes an agent can settle alone
|
|
181
|
+
- record-context – node 14 settled a term the glossary does not hold yet
|
|
182
|
+
|
|
183
|
+
## References
|
|
184
|
+
- Map state: `~/.claude/acstack/bin/acstack node walk` and `~/.claude/acstack/bin/acstack node frontier`
|
|
185
|
+
- Files in flight: `git status --short`
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Silence the context-pressure nudge
|
|
189
|
+
|
|
190
|
+
With the anchor written, write the quiet marker. The context-pressure Stop hook
|
|
191
|
+
reads the marker and stays silent for the rest of this session. You have
|
|
192
|
+
already arranged the compaction, so the hook has nothing left to nudge about:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
d="${ACSTACK_CONTEXT_PRESSURE_DIR:-${TMPDIR:-/tmp}/acstack-context-pressure}"
|
|
196
|
+
sid="${CLAUDE_CODE_SESSION_ID:-${PI_SESSION_ID:-}}"; [ -n "$sid" ] && mkdir -p "$d" && : > "$d/$sid.quiet" || true
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`CLAUDE_CODE_SESSION_ID` (`PI_SESSION_ID` on pi) is this session's own id, so the marker lands exactly
|
|
200
|
+
where the hook looks for it. The lead check at the top ruled out the child
|
|
201
|
+
sessions, where the variable names the lead instead.
|
|
202
|
+
|
|
203
|
+
If the variable is unset, skip this step. Tell the user that the hook keeps
|
|
204
|
+
nudging, which is noisy but harmless.
|
|
205
|
+
|
|
206
|
+
The hook clears the marker when the session compacts. It resets its state on
|
|
207
|
+
`SessionStart` with `source: compact`, so the nudge returns once the context grows
|
|
208
|
+
again.
|
|
209
|
+
|
|
210
|
+
## Hand over the compact line
|
|
211
|
+
|
|
212
|
+
A skill cannot run `/compact` itself. Write the user a `/compact` line steered
|
|
213
|
+
at this work. Name the next action, and anything they flagged in the focus
|
|
214
|
+
note.
|
|
215
|
+
|
|
216
|
+
Tell them to run that `/compact` line, then to type `continue`. The hook
|
|
217
|
+
re-injects the anchor and retires it, so the anchor never loads twice.
|
|
218
|
+
|
|
219
|
+
`acstack/HANDOFF.md` is transient working state. If `.gitignore` does not cover
|
|
220
|
+
it, say so. The file holds conversation content, so nobody should commit it.
|
|
221
|
+
|
|
222
|
+
## Notes
|
|
223
|
+
|
|
224
|
+
- **The reload fires only when the session start source is `compact`**. It
|
|
225
|
+
does not fire on a fresh start, on resuming an earlier session, or after
|
|
226
|
+
clearing the context.
|
|
227
|
+
|
|
228
|
+
A stale anchor therefore never leaks into unrelated work. The `handoff`
|
|
229
|
+
skill moves the work to a genuinely new session
|
|
230
|
+
|
|
231
|
+
- **Consume-once.** The hook retires the anchor as it injects it, moving it to
|
|
232
|
+
`acstack/handoffs/<map>/<created>.md` (legacy
|
|
233
|
+
`acstack/changes/<name>/handoffs/` when that directory still exists).
|
|
234
|
+
Collisions get a `-2` suffix
|
|
235
|
+
|
|
236
|
+
- **Subagents and teammates have isolated context.** This protects the
|
|
237
|
+
orchestrator's coordination state, which is the long-lived part. Per-scope
|
|
238
|
+
work does not need it
|
|
239
|
+
|
|
240
|
+
- The best defence against the compaction wall is delegating aggressively so
|
|
241
|
+
the orchestrator's context window stays lean. This is the backstop
|