acstack 0.0.0-stage → 0.47.1

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.
Files changed (143) hide show
  1. package/.claude-plugin/plugin.json +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +389 -2
  4. package/THIRD_PARTY_NOTICES +14 -0
  5. package/TROUBLESHOOTING.md +225 -0
  6. package/agents/codex/frontend-verifier.toml +352 -0
  7. package/agents/codex/task-checker.toml +345 -0
  8. package/agents/codex/task-executor.toml +157 -0
  9. package/agents/codex/test-writer.toml +149 -0
  10. package/agents/frontend-verifier.md +351 -0
  11. package/agents/task-checker.md +344 -0
  12. package/agents/task-executor.md +156 -0
  13. package/agents/test-writer.md +148 -0
  14. package/assets/playwriter-bridge/build-launcher.ps1 +32 -0
  15. package/assets/playwriter-bridge/doctor.ps1 +450 -0
  16. package/assets/playwriter-bridge/launcher-src.cs +131 -0
  17. package/assets/playwriter-bridge/opener.js +330 -0
  18. package/assets/playwriter-bridge/opener.ps1 +63 -0
  19. package/assets/playwriter-bridge/register-tasks.ps1 +328 -0
  20. package/assets/playwriter-bridge/relay.ps1 +50 -0
  21. package/assets/playwriter-bridge/stop.ps1 +125 -0
  22. package/assets/playwriter-bridge/sync.ps1 +271 -0
  23. package/assets/playwriter-bridge/tunnel.ps1 +325 -0
  24. package/assets/playwriter-bridge/vm-free-port.sh +166 -0
  25. package/assets/terminal-workspace/client-keybindings.md +87 -0
  26. package/assets/terminal-workspace/config.example.yaml +334 -0
  27. package/assets/terminal-workspace/setup.sh +4404 -0
  28. package/cli/README.md +47 -0
  29. package/cli/bin/acstack.js +3 -0
  30. package/cli/dist/index.js +25984 -0
  31. package/cli/dist/index.js.map +7 -0
  32. package/cli/package.json +59 -0
  33. package/docs/adr/0001-ste-writing-standard.md +16 -0
  34. package/docs/adr/0002-version-gate-not-auto-bump.md +35 -0
  35. package/docs/adr/0003-handoff-ack-command.md +19 -0
  36. package/docs/adr/0004-dev-setup-per-host.md +13 -0
  37. package/docs/adr/0005-two-orchestrators-per-host.md +25 -0
  38. package/docs/adr/0006-document-opener-service.md +89 -0
  39. package/docs/adr/0007-lead-check-reads-the-transcript.md +87 -0
  40. package/docs/adr/0008-cli-audits-skill-interviews.md +37 -0
  41. package/docs/adr/0009-verify-the-write-not-the-writer.md +51 -0
  42. package/docs/adr/0010-promote-dev-to-main-by-fast-forward.md +115 -0
  43. package/docs/adr/0011-node-header-is-the-edge-encoding.md +20 -0
  44. package/docs/adr/0012-node-kind-is-a-closed-set-of-five.md +31 -0
  45. package/docs/adr/0013-the-diagram-renderer-is-pure.md +23 -0
  46. package/docs/adr/0014-reading-a-node-hides-its-generated-diagram.md +29 -0
  47. package/docs/adr/0015-a-node-id-links-to-its-issue-through-an-anchor.md +37 -0
  48. package/docs/adr/0016-the-map-root-carries-no-status-of-its-own.md +21 -0
  49. package/docs/adr/0017-call-impeccable-copy-only-its-questions.md +13 -0
  50. package/docs/adr/index.md +17 -0
  51. package/docs/config-reference.md +572 -0
  52. package/docs/dev-setups.md +164 -0
  53. package/docs/migrate-0.8.md +28 -0
  54. package/docs/playwriter-bridge-windows.md +15 -0
  55. package/docs/terminal-workspace-keys.md +137 -0
  56. package/docs/terminal-workspace.md +1780 -0
  57. package/docs/workflows.md +309 -0
  58. package/hooks/ac-writing-style-reminder.sh +86 -0
  59. package/hooks/context-pressure.sh +583 -0
  60. package/hooks/hooks.json +50 -0
  61. package/hooks/session-start-handoff.sh +165 -0
  62. package/hooks/session-start.sh +214 -0
  63. package/orchestrator/AGENTS.md +532 -0
  64. package/output-styles/ac-writing-style.md +286 -0
  65. package/package.json +50 -4
  66. package/pi/agents/frontend-verifier.md +357 -0
  67. package/pi/agents/task-checker.md +348 -0
  68. package/pi/agents/task-executor.md +160 -0
  69. package/pi/agents/test-writer.md +154 -0
  70. package/pi/extension.ts +723 -0
  71. package/profiles/fullstack-python.yaml +29 -0
  72. package/profiles/node-typescript.yaml +23 -0
  73. package/profiles/python.yaml +24 -0
  74. package/skills/archive/SKILL.md +160 -0
  75. package/skills/bootstrap/SKILL.md +109 -0
  76. package/skills/bridge/HANDOFF.md +93 -0
  77. package/skills/bridge/SKILL-VM.md +292 -0
  78. package/skills/bridge/SKILL-WINDOWS.md +526 -0
  79. package/skills/bridge/SKILL.md +121 -0
  80. package/skills/browser-verify/SKILL.md +229 -0
  81. package/skills/code-review/SKILL.md +44 -0
  82. package/skills/commit/SKILL.md +106 -0
  83. package/skills/compact-and-continue/SKILL.md +241 -0
  84. package/skills/explore/SKILL.md +149 -0
  85. package/skills/grilling/SKILL.md +134 -0
  86. package/skills/handoff/SKILL.md +250 -0
  87. package/skills/handoff/launch-herdr.md +197 -0
  88. package/skills/handoff/launch-without-herdr.md +30 -0
  89. package/skills/handoff/lead-check.md +59 -0
  90. package/skills/handoff/outcomes.md +162 -0
  91. package/skills/handoff/running-agent.md +50 -0
  92. package/skills/handoff/watch.md +115 -0
  93. package/skills/host/SKILL.md +247 -0
  94. package/skills/host/detect-host.sh +297 -0
  95. package/skills/host/herdr.md +79 -0
  96. package/skills/host/install-herdr-block.sh +467 -0
  97. package/skills/host/install-orca.sh +512 -0
  98. package/skills/host/notes.md +97 -0
  99. package/skills/host/orca.md +160 -0
  100. package/skills/host/questions.md +163 -0
  101. package/skills/host/report.md +42 -0
  102. package/skills/implement/SKILL.md +230 -0
  103. package/skills/implement/decision-log.md +62 -0
  104. package/skills/implement/design-pass.md +32 -0
  105. package/skills/implement/relaxed-tdd.md +28 -0
  106. package/skills/map/SKILL.md +250 -0
  107. package/skills/map/frontend.md +227 -0
  108. package/skills/map/trackers/files.md +74 -0
  109. package/skills/map/trackers/github.md +180 -0
  110. package/skills/map/visuals.md +387 -0
  111. package/skills/new-worktree/SKILL.md +155 -0
  112. package/skills/new-worktree/detect-orchestrator.sh +328 -0
  113. package/skills/new-worktree/detect-orchestrator.test.sh +894 -0
  114. package/skills/new-worktree/herdr.md +84 -0
  115. package/skills/new-worktree/orca.md +101 -0
  116. package/skills/pre-commit-review/SKILL.md +242 -0
  117. package/skills/pre-commit-review/auto-fix.md +19 -0
  118. package/skills/pre-commit-review/interactive.md +35 -0
  119. package/skills/quick-fix/SKILL.md +125 -0
  120. package/skills/record-context/SKILL.md +106 -0
  121. package/skills/setup/SKILL.md +250 -0
  122. package/skills/setup/browser.md +123 -0
  123. package/skills/setup/design-review.md +97 -0
  124. package/skills/setup/first-run.md +114 -0
  125. package/skills/setup/report.md +68 -0
  126. package/skills/setup/row-fixes.md +196 -0
  127. package/skills/setup/terminal-workspace.md +153 -0
  128. package/skills/sync/SKILL.md +171 -0
  129. package/skills/teardown-worktree/SKILL.md +245 -0
  130. package/skills/teardown-worktree/detector.md +39 -0
  131. package/skills/teardown-worktree/herdr.md +113 -0
  132. package/skills/teardown-worktree/orca.md +61 -0
  133. package/skills/terminal-workspace/SKILL.md +249 -0
  134. package/skills/terminal-workspace/components.md +36 -0
  135. package/skills/terminal-workspace/config-choices.md +69 -0
  136. package/skills/terminal-workspace/emulator-keys.md +48 -0
  137. package/skills/terminal-workspace/headless-clipboard.md +175 -0
  138. package/skills/terminal-workspace/turn-off-and-update.md +104 -0
  139. package/skills/test-conventions/SKILL.md +59 -0
  140. package/skills/visual-docs/SKILL.md +246 -0
  141. package/skills/writing/SKILL.md +231 -0
  142. package/skills/writing/examples.md +153 -0
  143. 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