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,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.
|