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,32 @@
1
+ # The audit and polish pass
2
+
3
+ Step 5 in `SKILL.md` runs the pipeline in eight numbered steps. `SKILL.md`
4
+ states when steps 5 to 7 run. This file holds how to run them.
5
+
6
+ 5. **`/impeccable audit`** – report design findings on the changed frontend
7
+ files. The audit edits nothing. It needs no browser.
8
+
9
+ You type the command yourself. impeccable's plugin loads it into your chat
10
+ as a markdown playbook.
11
+
12
+ Read the design gate with `~/.claude/acstack/bin/acstack design-gate`.
13
+
14
+ The file list is the one the checker derived in its section 5.5, from
15
+ `git status --porcelain -- <frontend.directory>`.
16
+
17
+ 6. **`/impeccable polish`** – fix the same files. Polish reads the audit
18
+ findings as its backlog. It edits source.
19
+
20
+ You type this command yourself too.
21
+
22
+ Tell polish to leave a factual claim in copy untouched. Tell it to list
23
+ every such claim in its report.
24
+
25
+ Only `polish` runs from the audit's "Recommended Actions". Tell the audit
26
+ to name each other command against the finding that earned it.
27
+
28
+ Name `harden`, `clarify`, `adapt`, `optimize`, and `onboard` in your
29
+ completion report, so the user can pick one later.
30
+
31
+ 7. **task-checker subagent, second run** – polish changed the code, so verify
32
+ it again. This run happens only when polish ran.
@@ -0,0 +1,28 @@
1
+ # Relaxed TDD
2
+
3
+ This file holds what changes in step 5 of `SKILL.md` when
4
+ `acstack/project.yaml` sets `workflow.tdd.strict: false`. Read it only then.
5
+
6
+ `workflow.tdd.strict: false`, relaxed TDD, runs step 2 before step 1. It
7
+ skips nothing. Relaxed TDD means nobody writes the tests first, and the
8
+ first three subagents still run.
9
+
10
+ The frontend-verifier's gate is the same under either setting.
11
+
12
+ The format step stays immediately before the checker, so under relaxed
13
+ it formats the new tests as well.
14
+
15
+ Relaxed costs the test-writer some of its independence, and you state that
16
+ cost rather than hide it. The implementation already sits in the working
17
+ tree when the test-writer runs. Tell it to write the tests from the node's
18
+ requirements, and to leave the implementation unread.
19
+
20
+ Under strict there is no implementation for it to read, which is the
21
+ stronger guarantee.
22
+
23
+ The checker's gate moves with the setting. Under `true` the new tests failed
24
+ before the executor and pass after it.
25
+
26
+ Under `false` nothing can show them failing without the implementation. The
27
+ checker then holds the new tests to existing and passing. It holds the full
28
+ suite to passing, and the test count to not dropping.
@@ -0,0 +1,250 @@
1
+ ---
2
+ name: map
3
+ description: The entry point for planned work. A map is a graph of question and work nodes. Charts one if none exists – an opening grill, meaning a round of interview questions, that fixes the destination and surfaces the fog, meaning what cannot yet be stated precisely – and works the frontier, the nodes ready to be worked now, if one does. No tiers and no routing – the graph is however big the fog made it, and nothing declares which. Invoke whenever decisions need settling before work can start, the request is foggy or underspecified, or a map already exists and has open nodes. Use implement instead when the way is already clear.
4
+ argument-hint: "[map name, or the request to chart]"
5
+ ---
6
+
7
+ ## User input
8
+
9
+ ```text
10
+ $ARGUMENTS
11
+ ```
12
+
13
+ You **MUST** consider the user input before proceeding (if not empty).
14
+
15
+ # Map
16
+
17
+ ## Tracker
18
+
19
+ Nodes live behind a pluggable tracker. A backend declares four operations –
20
+ create, read, update, list. ACStack builds everything else from those four:
21
+ frontier, claim, resolve and walk.
22
+
23
+ Two backends ship, each declared in this skill's directory:
24
+
25
+ | Backend | Doc | When |
26
+ | ------- | --- | ---- |
27
+ | GitHub issues | `trackers/github.md` | first choice when `gh` holds a login for the repo's GitHub remote |
28
+ | Files | `trackers/files.md` | the fallback – no auth, offline, any remote |
29
+
30
+ `workflow.maps.tracker` in `acstack/project.yaml` (`github` or `files`) records
31
+ the project's choice. If the key names a backend, read the matching doc and use
32
+ its operations. If the key is absent, pick at materialisation time – the moment
33
+ you first write the map's nodes down.
34
+
35
+ Recommend `github` when the repo qualifies, `files` otherwise. Confirm the
36
+ choice with the user. Then write the key, so later sessions need not re-decide.
37
+
38
+ ## Which mode
39
+
40
+ One command runs two modes, and what already exists picks between them. Check
41
+ the configured tracker for existing maps – `ls acstack/maps/` on the files
42
+ backend, `gh label list --search "map:" --json name` on GitHub.
43
+
44
+ If `$ARGUMENTS` names a map, or exactly one exists, work its frontier – the
45
+ nodes ready to work now. If none exists, chart. If several exist and
46
+ `$ARGUMENTS` does not pick one, ask.
47
+
48
+ There are no tiers and no complexity judgement.
49
+
50
+ One question is a small map or no map at all. Fifty questions is a long
51
+ effort. Nothing declares which.
52
+
53
+ ## Charting
54
+
55
+ 1. **Fix the destination first.** Grill for what done looks like (invoke the
56
+ `grilling` skill). The destination is the root of everything that follows –
57
+ settle it before any other question.
58
+
59
+ 2. **Load the frontend branch on a frontend destination.** `frontend.md`
60
+ beside this skill holds five more rules. Read it when the destination
61
+ touches `frontend.directory`, the path in `acstack/project.yaml` where the
62
+ frontend lives. Every other map skips it.
63
+
64
+ 3. **Open with a breadth-first grill.** Work the conversation frontier in
65
+ rounds per the grilling skill. Explore the codebase for facts as you go –
66
+ facts are your job, never the user's. Try a throwaway prototype before you
67
+ ask the user anything (grilling's "Run it before you ask it").
68
+
69
+ 4. **Apply the fog test to what surfaced.** A question you can state precisely
70
+ now is `open`. One you cannot state is `fog` – record it without forcing it
71
+ sharp. The test is whether you can *state* the question precisely, not
72
+ whether you can answer it.
73
+
74
+ ### Progressive materialisation
75
+
76
+ The machinery appears only when it has to persist. After the opening grill:
77
+
78
+ - **No fog surfaced** – the way was already clear. No map. Say so and proceed
79
+ to the work.
80
+
81
+ - **At most one session's worth** – settle it in conversation. Invoke
82
+ `record-context` on each decision. No map – there is nothing to resume.
83
+
84
+ - **More than one session's worth** – materialise the map and work the
85
+ frontier across sessions.
86
+
87
+ The test is mechanical. Will the fog outlive this session?
88
+
89
+ ### Materialising
90
+
91
+ Pick the tracker (see Tracker above), then create the nodes with its `create`
92
+ operation. First the root:
93
+
94
+ ```bash
95
+ # files backend – github.md has the equivalent
96
+ ~/.claude/acstack/bin/acstack node create --map <name> --title "<destination>" \
97
+ --kind destination --label "<at most four words>" \
98
+ --body "<the destination, as settled>"
99
+ ```
100
+
101
+ - The root is the destination. Pass no `--status` flag, so it opens.
102
+
103
+ The root's state follows its subtree. It stays open while any node below
104
+ it is open, fog or claimed. `archive` resolves it when the map clears.
105
+ Nothing else writes the root's status, and the frontier never returns it.
106
+
107
+ - The root counts as pinned without the flag, and on GitHub it carries the
108
+ `root-node` label. The walk returns pinned nodes in full at the start of
109
+ every session, so every session orients to the root.
110
+
111
+ - On GitHub, every node body opens with a header line that encodes its edges.
112
+ `trackers/github.md` holds the format. The files backend writes none.
113
+
114
+ - Every node carries a `kind` and a `label`, both required. A `label` is the
115
+ node's short name for a diagram. `trackers/files.md` holds the kinds, the
116
+ caps, and the contract the CLI enforces.
117
+
118
+ - Every node body carries a diagram, two at most. A childless `notes` node is
119
+ the one exception.
120
+
121
+ `visuals.md` holds which visual each kind gets, where it sits in the body,
122
+ and the rules a hand-drawn one follows. Read it before the first body.
123
+
124
+ - Standing preferences for the effort become one resolved node. Style rules
125
+ and constraints the grill surfaced go there. Create it with
126
+ `--answers <root id> --kind notes --label "<at most four words>" --pinned`.
127
+
128
+ - Every other surfaced question becomes a node. Give it `open` or `fog` per
129
+ the fog test.
130
+
131
+ Pass `--answers <id>` to name the node whose resolution surfaced it. That
132
+ link is the node's provenance, the trail back to the root. Pass
133
+ `--blocked-by` only where you genuinely cannot settle one node before
134
+ another.
135
+
136
+ - `mode` defaults to `hitl` – human in the loop, meaning a person answers it.
137
+
138
+ A node earns `afk` – away from keyboard, meaning an agent settles it alone
139
+ – only by containing no decision. Research earns it, and so does work
140
+ whose questions are all settled. Get this wrong and an agent quietly
141
+ decides something that was the human's.
142
+
143
+ - Write every title and body per the `writing` skill.
144
+ - Nodes describe behaviour, not file paths. A node can sit on the frontier for
145
+ weeks while the codebase moves – you resolve the paths at claim time.
146
+
147
+ - Draw every parent's diagram once every node exists, per Regenerating
148
+ diagrams below. A parent draws its subtree, so nothing can draw one earlier.
149
+ The root is a parent too, and it draws the whole map.
150
+
151
+ - On the files backend, suggest adding `acstack/maps/` to `.gitignore`
152
+ (`trackers/files.md` gives the reason).
153
+
154
+ ## Working the frontier
155
+
156
+ All commands below are the files backend's shape – on GitHub, compose the
157
+ same queries per `trackers/github.md`.
158
+
159
+ Before step 1, copy the bold title of each numbered step below into your todo
160
+ list word for word, ahead of any task-specific items. A step you skip stays in
161
+ the list, marked `skip: <reason>`.
162
+
163
+ 1. **Orient.** The packaging walk (`acstack node walk --map <name>`) – the root
164
+ and pinned nodes in full, everything else gisted, meaning title and status
165
+ only. Zoom in with `node read <id>` when a gist matters – it drops the
166
+ generated diagram blocks, and `--visuals` puts them back. Do not load
167
+ every body.
168
+
169
+ Also check `node list --map <name> --status claimed`. A claim marks a node
170
+ someone is working, so a dead session's claim hides it from the frontier
171
+ forever. If a claim exists and you know of no session working it, ask the
172
+ user and release it (`--status open`).
173
+
174
+ 2. **Query the frontier.** `acstack node frontier --map <name>` – open nodes
175
+ with no unresolved blockers, shallowest provenance depth first, number
176
+ only as a tiebreak. Provenance depth is how many `answers` links separate
177
+ a node from the root, so the broadest questions come first. The query never
178
+ returns the root.
179
+
180
+ 3. **Route by `mode` – the only field the machine routes on** (`kind` picks
181
+ the node's diagram shape, never its route):
182
+ - `hitl` nodes: run grilling rounds over them. A round is the whole hitl
183
+ frontier.
184
+ - `afk` nodes: claim and run without the user. Unlimited, and in parallel
185
+ when independent. Research goes to `Explore` subagents, with the findings
186
+ written into the resolution.
187
+
188
+ Implementation work follows `/acstack:implement`'s procedure – it owns
189
+ the claim-execute-resolve flow, the explorer dispatch, and the TDD
190
+ pipeline. Do not restate that flow here. Invoke it.
191
+
192
+ 4. **Claim, then resolve** – `afk` nodes only. A `hitl` resolution happens
193
+ inside the grilling round, with no claim step. Both are compositions over
194
+ `update`:
195
+
196
+ ```bash
197
+ ~/.claude/acstack/bin/acstack node update <id> --map <name> --status claimed
198
+ ~/.claude/acstack/bin/acstack node update <id> --map <name> --status resolved \
199
+ --append-body "## Answer
200
+
201
+ <what was decided or done, and why>"
202
+ ```
203
+
204
+ The pipeline's state lives inside the claim, not on the node – there is no
205
+ phase field to maintain. If the work stalls or fails, release the claim
206
+ (`--status open`) and the node is plainly open again.
207
+
208
+ 5. **After every resolution**, in order:
209
+ - Invoke `record-context`
210
+ - Create nodes for anything the resolution surfaced
211
+ - Create the critique node when the resolved node changed the frontend,
212
+ per `frontend.md`
213
+ - Regenerate the diagram on the resolved node's parent (see Regenerating
214
+ diagrams)
215
+ - Recompute the frontier
216
+
217
+ The regeneration comes after the new nodes exist. A surfaced node hangs
218
+ off the node you just resolved, inside that same subtree.
219
+
220
+ A shallow node arriving late jumps the queue – that is correct, something
221
+ big just opened up.
222
+
223
+ 6. **Graduate fog as it sharpens.** When you can state a fog node precisely,
224
+ run `update <id> --status open` – one field, one write. Rewrite the title
225
+ and body to the sharp statement if they drifted.
226
+
227
+ Never filter on leaf position or "has a resolved question above it". Work
228
+ nodes can hang anywhere, including straight off the root – a bug is work with
229
+ no question above it.
230
+
231
+ ## Regenerating diagrams
232
+
233
+ A parent's diagram draws its subtree, so any status change below it leaves
234
+ that diagram wrong. Regenerate on the resolved node's parent after every
235
+ resolution, and on every parent at each frontier recompute. The map skill's
236
+ `visuals.md` holds the commands and the write rules (Regenerating a parent's
237
+ diagram).
238
+
239
+ ## Done
240
+
241
+ The map clears when the frontier is empty and no fog remains. The durable
242
+ residue is what the map leaves behind – the living specs through commit-time
243
+ sync, the ADRs and glossary entries through `record-context`. You have already
244
+ extracted it along the way.
245
+
246
+ Report what the map settled. Point at anything the map left `out-of-scope`.
247
+
248
+ Then invoke `archive` to close the map out. It re-checks the gate itself and
249
+ refuses if anything is still open. It verifies the residue actually landed,
250
+ resolves the root, and asks before disposing of the nodes.
@@ -0,0 +1,227 @@
1
+ # Frontend destinations
2
+
3
+ A map whose destination changes the frontend carries five rules that no other
4
+ map loads, and this file holds all five.
5
+
6
+ `SKILL.md` decides when to read this file. The destination has to touch
7
+ `frontend.directory`, the path in `acstack/project.yaml` where the frontend
8
+ lives.
9
+
10
+ Two plugins appear in the rules below.
11
+
12
+ - **impeccable** reviews a shipped user interface against the product's own
13
+ design rules
14
+ - **open-designer** writes a design a human can look at before anyone builds it
15
+
16
+ ACStack needs neither. Each rule below says which plugin it needs, and what
17
+ happens when that plugin is absent.
18
+
19
+ The diagram names the direction questions, meaning the ones a finished design
20
+ answers by existing.
21
+
22
+ ```mermaid
23
+ flowchart TD
24
+ P["Read PRODUCT.md for framing"] --> Q["Ask impeccable's design questions"]
25
+ Q --> F{"A finalized design matches the screen?"}
26
+ F -->|yes| L["Link the design, drop the direction questions"]
27
+ F -->|no| I{"open-designer installed?"}
28
+ I -->|yes| V["Node: design the screen in the viewer"]
29
+ I -->|no| A["Ask the direction questions in the grill"]
30
+ L --> C["Critique the screen after the work ships"]
31
+ V --> C
32
+ A --> C
33
+ ```
34
+
35
+ ## Read PRODUCT.md before the opening grill
36
+
37
+ `PRODUCT.md` is impeccable's product brief. It states the product's users, its
38
+ purpose, and its positioning. impeccable's `init` playbook writes it, and
39
+ ACStack never writes it.
40
+
41
+ - **Read it before the opening grill** when the file exists, and read it for
42
+ framing alone
43
+ - **Never ask the user anything the file already states**
44
+ - **Look in impeccable's own resolution order** – `PRODUCT.md`, then
45
+ `Product.md`, then `product.md`, at the project root
46
+ - When the root holds none, impeccable also checks `.agents/context/` and
47
+ `docs/`
48
+ - **Ask the map's own questions when no `PRODUCT.md` exists**, and carry on
49
+ - **This rule needs no plugin installed**, because reading a file needs nothing
50
+ running
51
+
52
+ The resolution order comes from impeccable 4.2.0.
53
+
54
+ ## Ask impeccable's design questions
55
+
56
+ Every frontend destination surfaces the same questions, and impeccable already
57
+ wrote them. Charting copies them into `hitl` question nodes during the opening
58
+ grill. A `hitl` node is one a human answers.
59
+
60
+ **ACStack never runs `/impeccable shape`.** It copies the questions. That is
61
+ what keeps the map working when impeccable is absent. This rule needs no
62
+ plugin installed.
63
+
64
+ The questions come from impeccable's `shape` playbook, version 4.2.0, at
65
+ `reference/shape.md` inside the impeccable plugin.
66
+
67
+ **Purpose, people, outcome** is impeccable's first shape round.
68
+
69
+ - "What is this surface or feature for, and what problem must it solve?"
70
+ - "Who specifically reaches it, in what situation and state of mind?"
71
+ - "What is the primary thing they must understand or do? What would success look like?"
72
+ - "What is uniquely true here that a neighboring product or generic template could not claim?"
73
+
74
+ **Material, behavior, boundaries** is impeccable's second shape round.
75
+ impeccable asks it only when a material decision is still open.
76
+
77
+ - "What real content, evidence, data, and assets must the experience carry? What are realistic minimum, typical, and maximum ranges?"
78
+ - "Which states and transitions matter: first-run, empty, loading, error, success, permissions, overflow, or expert use?"
79
+ - "What is the intended fidelity, breadth, and interactivity: exploration, production-ready screen, full flow, or broader surface?"
80
+ - "What must remain untouched? What would make the result feel wrong even if it looked polished?"
81
+ - "Which platform, framework, performance, accessibility, localization, or delivery constraints are binding?"
82
+
83
+ **The visual world** adds one more question. It comes from impeccable's
84
+ `new-work.md` rather than from `shape.md`, because impeccable resolves the
85
+ design direction in a later phase. ACStack words the question itself, since
86
+ impeccable does not state it as one line.
87
+
88
+ - Does this screen inherit the product's existing visual world, extend it, or
89
+ replace it?
90
+
91
+ ### Two groups of questions
92
+
93
+ Two rules below act on these groups.
94
+
95
+ - **The direction questions** are the visual world question, and "What is the
96
+ intended fidelity, breadth, and interactivity"
97
+ - A design answers both by existing
98
+ - **The states questions** are "Which states and transitions matter" and the
99
+ content-and-ranges question
100
+ - A design answers neither
101
+
102
+ Two rules govern how you ask.
103
+
104
+ - **Skip any question `PRODUCT.md` already answers**, since the file states the
105
+ users, the purpose, and the positioning
106
+ - **Ask 2 to 3 related questions per round**, which is impeccable's own cadence
107
+ - Never dump the whole set at once
108
+
109
+ ## Link a finalized design instead of asking direction
110
+
111
+ An open-designer design is a set of standalone HTML pages a human picks
112
+ between. A finalized page is one the human chose.
113
+
114
+ Designs live under `.open-designer/designs/<name>/`, one directory per design,
115
+ each holding an `index.json`. `index.json` finalizes a page by holding an
116
+ entry at `chosen.pages[<page id>]`. Nothing else marks it – there is no status
117
+ field and no finalized flag.
118
+
119
+ ```bash
120
+ jq -r '.chosen.pages // {} | keys[]' .open-designer/designs/<name>/index.json
121
+ ```
122
+
123
+ - **`chosen.pages` is an object keyed by page id**, and each value is an object
124
+ holding `variantId`, `tweaks`, and an optional `state`
125
+ - **A design finalizes one page at a time**, so each finalized page needs its
126
+ own key in `chosen.pages`
127
+ - **An `index.json` carrying `chosen.variantId` and no `chosen.pages` is the old
128
+ single-page shape**, which finalizes that design's one page
129
+
130
+ `index.json` gives a page two names. `id` is the name the design's author typed,
131
+ and `label` is an optional human-readable name.
132
+
133
+ - **Match the destination against both**, since every page carries an `id` and
134
+ only some carry a `label`
135
+ - **Ask in the grill when the match is unclear**, and offer the finalized pages
136
+ as the options
137
+ - **Ask when two pages match**, and never pick one
138
+ - **Treat no match as no finalized design**, which sends charting to the viewer
139
+ rule below
140
+
141
+ A match changes two things about the destination.
142
+
143
+ - **Drop the direction questions**, since the chosen page already answers them
144
+ - **Name the design in the destination node** by its `index.json` path and its
145
+ page id
146
+
147
+ Keep the states questions either way. A finalized page shows one state of one
148
+ screen, and the map still needs the rest.
149
+
150
+ This rule needs no plugin installed, because a finalized design is a file on
151
+ disk. The layout comes from open-designer 0.7.4.
152
+
153
+ ## Send the human to the viewer when no design exists
154
+
155
+ With no finalized design and open-designer installed, charting creates one
156
+ `hitl` node that sends a human to the viewer.
157
+
158
+ open-designer registers a key in `~/.claude/plugins/installed_plugins.json`
159
+ that starts with `open-designer@`. Check for that key.
160
+
161
+ ```bash
162
+ grep -q '"open-designer@' ~/.claude/plugins/installed_plugins.json
163
+ ```
164
+
165
+ The registry key is `<plugin>@<marketplace>`. The marketplace half is wherever
166
+ the user installed from, so match the half before the `@` alone.
167
+
168
+ Four rules shape the viewer node.
169
+
170
+ - **Its `kind` is `work` and its `mode` is `hitl`**, so it carries no `afk`
171
+ label
172
+ - **Its title says what the human does** – design the screen in the viewer
173
+ - **Its body names the command**, `/open-designer:design`
174
+ - **Every direction question is `blocked-by` that node**, since the design
175
+ answers them
176
+ - `trackers/github.md` and `trackers/files.md` hold how each backend writes
177
+ `blocked-by`
178
+
179
+ The states questions carry no blocker, because a human can answer them while the
180
+ design is still open.
181
+
182
+ With open-designer absent, create no viewer node. The direction questions stay
183
+ open and the grill asks them.
184
+
185
+ ## Critique the screen after the work ships
186
+
187
+ Every resolved work node that changed the frontend gets one `hitl` node that
188
+ critiques the shipped screen.
189
+
190
+ **This rule needs the design gate on.** The design gate is the set of design
191
+ checks impeccable adds to ACStack's pipeline. One command answers whether it is
192
+ on.
193
+
194
+ ```bash
195
+ ~/.claude/acstack/bin/acstack design-gate
196
+ ```
197
+
198
+ It prints `on` and exits 0, or prints `off: <reason>` and exits 1. On `off`,
199
+ create no critique node.
200
+
201
+ Three rules shape the critique node.
202
+
203
+ - **Its `kind` is `research` and its `mode` is `hitl`**, because its output is
204
+ findings and a human runs it
205
+ - **Its body names the command**, `/impeccable critique <the screen>`
206
+ - **It `answers` the work node that shipped the screen**
207
+
208
+ The round after the critique resolves runs on the report.
209
+
210
+ - **`/impeccable critique` closes its report with recommended `/impeccable
211
+ <verb>` commands**, and those commands become the options in the next grill
212
+ round
213
+ - **impeccable's critique recommends only from its own list**
214
+ - `adapt`, `animate`, `audit`, `bolder`, `clarify`, `colorize`, `critique`,
215
+ `delight`, `distill`, `document`, `harden`, `layout`, `onboard`,
216
+ `optimize`, `overdrive`, `polish`, `quieter`, `shape`, and `typeset`
217
+ - **A human picks the command, never an agent** – every command that changes
218
+ what the screen is trying to be waits for a grill round
219
+ - Those commands are `adapt`, `animate`, `bolder`, `clarify`, `colorize`,
220
+ `delight`, `distill`, `harden`, `live`, `onboard`, `overdrive`, and
221
+ `quieter`
222
+ - `live` is one critique never recommends, and a human can still pick it
223
+ - **A chosen command becomes one work node that runs it**
224
+ - **That node is `afk`**, meaning an agent settles it alone, because the human
225
+ already made the decision
226
+
227
+ The command list comes from impeccable 4.2.0.
@@ -0,0 +1,74 @@
1
+ # Files tracker
2
+
3
+ The fallback backend: no auth, works offline, works on any remote. One
4
+ markdown file per node under `acstack/maps/<name>/`, managed by the ACStack
5
+ CLI. Nodes here are transient working state – scratch discarded once the map
6
+ clears.
7
+
8
+ Suggest adding `acstack/maps/` to `.gitignore` when you first create the
9
+ map.
10
+
11
+ CLI path: `~/.claude/acstack/bin/acstack`
12
+
13
+ To enumerate a project's maps: `ls acstack/maps/`.
14
+
15
+ ## The four operations
16
+
17
+ | Operation | Command |
18
+ | --------- | ------- |
19
+ | create | `acstack node create --map <name> --title <t> --kind <k> --label <l> [--status] [--mode] [--answers <id>] [--blocked-by <ids>] [--pinned] [--body <md>] [--body-file <path>]` |
20
+ | read | `acstack node read <id> --map <name> [--json] [--visuals]` |
21
+ | update | `acstack node update <id> --map <name> [--title] [--status] [--mode] [--kind] [--label] [--answers] [--blocked-by] [--pinned true\|false] [--body] [--body-file] [--append-body]` |
22
+ | list | `acstack node list --map <name> [--status <s>] [--json]` |
23
+
24
+ `create` rejects a node that omits `--kind` or `--label`. `--kind` takes one of
25
+ `destination`, `notes`, `decision`, `research`, or `work`. `--label` takes the
26
+ node's short name for a diagram, at most four words and thirty characters.
27
+
28
+ ## No body header
29
+
30
+ The GitHub backend opens every node body with a header line, because an issue
31
+ has nowhere else to put the fields. This backend writes none.
32
+
33
+ Frontmatter holds the same facts. `answers` and `blocked-by` sit there
34
+ directly, the map is the directory name, and the root is the node that
35
+ `answers` chains up to. A header here would copy data the CLI already owns
36
+ and would be free to drift from it.
37
+
38
+ `node read` prints the frontmatter, so a reader sees the same facts either
39
+ way.
40
+
41
+ ## Composed queries
42
+
43
+ The CLI builds composed queries from the four operations above, rather than
44
+ storing them.
45
+ The CLI ships the two this backend would otherwise recompute by hand every
46
+ session:
47
+
48
+ - `acstack node frontier --map <name> [--mode hitl|afk] [--json]` – open
49
+ nodes with no unresolved blockers, shallowest provenance depth first.
50
+ Provenance depth is how many `answers` links separate a node from the root.
51
+
52
+ The frontier never returns the root, the one node whose frontmatter has no
53
+ `answers`. The root is never work.
54
+
55
+ - `acstack node walk --map <name> [--full] [--json] [--visuals]` – the
56
+ packaging walk: the root first, then each node that hangs off it, depth
57
+ first. The walk prints the root and pinned nodes in full.
58
+
59
+ Claim and resolve are `update` calls:
60
+
61
+ ```bash
62
+ acstack node update <id> --map <name> --status claimed
63
+ acstack node update <id> --map <name> --status resolved --append-body "## Answer
64
+ ..."
65
+ ```
66
+
67
+ ## What `read` and `walk` strip
68
+
69
+ Both commands drop every diagram block a node body holds. A diagram block is
70
+ the rendered map that sits between the `<!-- acstack:diagram -->` markers
71
+ `node diagram` writes. `--visuals` prints the blocks. `--json` always carries
72
+ the whole body.
73
+
74
+ See `docs/adr/0014-reading-a-node-hides-its-generated-diagram.md` for why.