acstack 0.50.4 → 0.51.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 +1 -1
- package/README.md +14 -7
- package/agents/codex/frontend-verifier.toml +89 -6
- package/agents/codex/task-checker.toml +83 -2
- package/agents/codex/task-executor.toml +83 -1
- package/agents/codex/test-writer.toml +77 -1
- package/agents/frontend-verifier.md +13 -6
- package/agents/task-checker.md +7 -2
- package/agents/task-executor.md +7 -1
- package/agents/test-writer.md +1 -1
- package/assets/terminal-workspace/config.example.yaml +1 -1
- package/assets/terminal-workspace/helpers/acstack-md +12 -4
- package/assets/terminal-workspace/helpers/acstack-open +10 -2
- package/cli/dist/index.js +10142 -9369
- package/cli/dist/index.js.map +4 -4
- package/cli/package.json +1 -1
- package/docs/config-reference.md +113 -14
- package/docs/dev-setups.md +4 -4
- package/docs/terminal-workspace.md +1 -1
- package/docs/workflows.md +22 -16
- package/examples/design-doc/acstack/README.md +273 -0
- package/examples/design-doc/acstack/acstack.yaml +4 -0
- package/examples/design-doc/acstack/cli.yaml +5 -0
- package/examples/design-doc/acstack/design.yaml +39 -0
- package/examples/design-doc/acstack/github.yaml +12 -0
- package/examples/design-doc/acstack/host.yaml +14 -0
- package/examples/design-doc/acstack/journey.md +85 -0
- package/examples/design-doc/acstack/publication.md +16 -0
- package/examples/design-doc/acstack/review-runtime.yaml +24 -0
- package/examples/design-doc/acstack/skills.yaml +22 -0
- package/examples/design-doc/acstack/store.yaml +11 -0
- package/examples/design-doc/acstack/user.yaml +15 -0
- package/examples/design-doc/acstack/viewer.yaml +13 -0
- package/hooks/ac-writing-style-reminder.sh +7 -18
- package/hooks/communication-standard.mjs +17 -0
- package/hooks/communication-standard.sh +6 -0
- package/hooks/context-pressure.sh +2 -2
- package/hooks/hooks.json +18 -0
- package/hooks/lib/communication-standard.mjs +16 -0
- package/hooks/project-data.sh +38 -0
- package/hooks/session-start-handoff.sh +21 -7
- package/hooks/session-start.sh +9 -2
- package/orchestrator/AGENTS.md +25 -14
- package/output-styles/ac-writing-style.md +75 -276
- package/package.json +2 -1
- package/pi/agents/frontend-verifier.md +89 -6
- package/pi/agents/task-checker.md +83 -2
- package/pi/agents/task-executor.md +83 -1
- package/pi/agents/test-writer.md +77 -1
- package/pi/extension.ts +70 -12
- package/profiles/fullstack-python.yaml +1 -1
- package/profiles/node-typescript.yaml +1 -1
- package/profiles/python.yaml +1 -1
- package/skills/archive/SKILL.md +53 -36
- package/skills/bootstrap/SKILL.md +6 -6
- package/skills/bridge/SKILL-VM.md +11 -2
- package/skills/bridge/SKILL-WINDOWS.md +3 -3
- package/skills/browser-verify/SKILL.md +14 -5
- package/skills/code-review/SKILL.md +8 -2
- package/skills/commit/SKILL.md +7 -6
- package/skills/compact-and-continue/SKILL.md +9 -8
- package/skills/design-doc/SKILL.md +235 -0
- package/skills/explore/SKILL.md +1 -1
- package/skills/grilling/SKILL.md +4 -4
- package/skills/handoff/SKILL.md +4 -4
- package/skills/host/SKILL.md +1 -1
- package/skills/host/detect-host.sh +2 -2
- package/skills/host/notes.md +2 -2
- package/skills/host/questions.md +1 -1
- package/skills/implement/SKILL.md +20 -13
- package/skills/implement/decision-log.md +9 -8
- package/skills/implement/design-pass.md +16 -2
- package/skills/map/SKILL.md +15 -71
- package/skills/map/alignment.md +18 -27
- package/skills/map/frontend.md +1 -1
- package/skills/map/materialising.md +74 -0
- package/skills/map/trackers/files.md +4 -6
- package/skills/pre-commit-review/SKILL.md +15 -9
- package/skills/pre-commit-review/auto-fix.md +1 -1
- package/skills/quick-fix/SKILL.md +1 -1
- package/skills/record-context/SKILL.md +6 -6
- package/skills/setup/SKILL.md +15 -50
- package/skills/setup/browser.md +2 -2
- package/skills/setup/first-run.md +19 -8
- package/skills/setup/report.md +3 -2
- package/skills/setup/row-fixes.md +56 -9
- package/skills/sync/SKILL.md +12 -11
- package/skills/terminal-workspace/SKILL.md +1 -1
- package/skills/test-conventions/SKILL.md +2 -2
- package/skills/visual-docs/SKILL.md +69 -235
- package/skills/writing/SKILL.md +29 -217
- package/skills/writing/examples.md +62 -129
- package/docs/adr/0001-ste-writing-standard.md +0 -16
- package/docs/adr/0002-version-gate-not-auto-bump.md +0 -35
- package/docs/adr/0003-handoff-ack-command.md +0 -19
- package/docs/adr/0004-dev-setup-per-host.md +0 -13
- package/docs/adr/0005-two-orchestrators-per-host.md +0 -25
- package/docs/adr/0006-document-opener-service.md +0 -89
- package/docs/adr/0007-lead-check-reads-the-transcript.md +0 -87
- package/docs/adr/0008-cli-audits-skill-interviews.md +0 -37
- package/docs/adr/0009-verify-the-write-not-the-writer.md +0 -51
- package/docs/adr/0010-promote-dev-to-main-by-fast-forward.md +0 -115
- package/docs/adr/0011-node-header-is-the-edge-encoding.md +0 -20
- package/docs/adr/0012-node-kind-is-a-closed-set-of-five.md +0 -31
- package/docs/adr/0013-the-diagram-renderer-is-pure.md +0 -23
- package/docs/adr/0014-reading-a-node-hides-its-generated-diagram.md +0 -29
- package/docs/adr/0015-a-node-id-links-to-its-issue-through-an-anchor.md +0 -37
- package/docs/adr/0016-the-map-root-carries-no-status-of-its-own.md +0 -21
- package/docs/adr/0017-call-impeccable-copy-only-its-questions.md +0 -13
- package/docs/adr/0018-alignment-packs-use-local-viewers.md +0 -11
- package/docs/adr/index.md +0 -18
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
id: acstack-design
|
|
2
|
+
name: ACStack design review
|
|
3
|
+
summary: >-
|
|
4
|
+
ACStack guides design authoring, saves browser feedback, reconciles optional
|
|
5
|
+
map contributions, and records exact-revision approval with retained evidence.
|
|
6
|
+
detail: journey.md
|
|
7
|
+
elements:
|
|
8
|
+
- user.yaml
|
|
9
|
+
- acstack.yaml
|
|
10
|
+
- skills.yaml
|
|
11
|
+
- host.yaml
|
|
12
|
+
- cli.yaml
|
|
13
|
+
- review-runtime.yaml
|
|
14
|
+
- viewer.yaml
|
|
15
|
+
- store.yaml
|
|
16
|
+
- github.yaml
|
|
17
|
+
concerns:
|
|
18
|
+
- id: offline-review
|
|
19
|
+
name: Offline review
|
|
20
|
+
elements: [review-runtime, viewer, design-source]
|
|
21
|
+
requirement: >-
|
|
22
|
+
Reviewers can inspect the design without uploading project details
|
|
23
|
+
or fetching browser assets.
|
|
24
|
+
response: >-
|
|
25
|
+
The review command and server read bounded local source files and
|
|
26
|
+
embed validated graph data with bundled browser assets, without uploading
|
|
27
|
+
the design. Agent-side reads of GitHub-bound maps still require
|
|
28
|
+
network access.
|
|
29
|
+
- id: honest-scope
|
|
30
|
+
name: Honest review status
|
|
31
|
+
elements: [skills, review-runtime, viewer]
|
|
32
|
+
requirement: >-
|
|
33
|
+
An exported review artifact must not imply that a reviewer approved
|
|
34
|
+
a map or implementation.
|
|
35
|
+
response: >-
|
|
36
|
+
Comments and exports are not approval. Approval requires reconciled
|
|
37
|
+
feedback and contributions, resolved blocking questions, and the exact
|
|
38
|
+
source, review, comments, and map-input tuple. Implementation checks
|
|
39
|
+
remain separate.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
id: github
|
|
2
|
+
name: GitHub
|
|
3
|
+
summary: Hosts a published copy of the Markdown companion when the developer chooses to share it.
|
|
4
|
+
kind: external-system
|
|
5
|
+
channels: [web]
|
|
6
|
+
detail: publication.md
|
|
7
|
+
relationships:
|
|
8
|
+
- id: publish-companion
|
|
9
|
+
from: user
|
|
10
|
+
to: github
|
|
11
|
+
direction: one-way
|
|
12
|
+
label: Optionally publishes the Markdown companion to
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
id: host
|
|
2
|
+
name: Agent session setup
|
|
3
|
+
summary: >-
|
|
4
|
+
Registers ACStack skill commands and adds rules for planning, coding,
|
|
5
|
+
and checking changes to the agent's session.
|
|
6
|
+
kind: component
|
|
7
|
+
parent: acstack
|
|
8
|
+
channels: [agent]
|
|
9
|
+
relationships:
|
|
10
|
+
- id: load-skills
|
|
11
|
+
from: host
|
|
12
|
+
to: skills
|
|
13
|
+
direction: one-way
|
|
14
|
+
label: Registers
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
## Review the design before implementation
|
|
2
|
+
|
|
3
|
+
ACStack saves design feedback, reconciles comments and optional map contributions, and records human approval of the exact reviewed inputs.
|
|
4
|
+
|
|
5
|
+
This example keeps the existing architecture: Agent skills guide the agent; the Review command and server validate source and save review evidence. The Browser review interface shows the design and collects feedback and approval. Review the responsibilities, containment, and labeled arrows before implementation.
|
|
6
|
+
|
|
7
|
+
### Author, review, reconcile, and approve
|
|
8
|
+
|
|
9
|
+
1. The developer asks the agent to prepare a design through the Agent skills registered by Agent session setup
|
|
10
|
+
2. The agent writes the entry, element YAML, and supporting Markdown in one bounded directory tree
|
|
11
|
+
3. The agent runs `acstack design-doc design.yaml --markdown /tmp/acstack-design-review.md` with an unused output path and keeps the server running
|
|
12
|
+
4. The server validates source and serves the prepared graph with bundled browser assets; the browser never reads YAML directly
|
|
13
|
+
5. The developer saves comments, chooses Send to agent, and pastes the copied prompt into the agent session
|
|
14
|
+
6. The agent reads the saved review, revises source, and uses `acstack design-review status design.yaml` to inspect feedback and optional map contributions
|
|
15
|
+
7. The agent explicitly reconciles each selected comment and current contribution, then resolves blocking human questions or marks dropped scope out of scope
|
|
16
|
+
8. The agent reopens changed source for review; the human chooses Approve this revision once reconciliation is current
|
|
17
|
+
9. The agent requires `approval.valid: true` from status before implementation, then runs the separate implementation checks
|
|
18
|
+
10. At map closeout, archive verifies implemented functional requirements in living specs, architecture decision records (ADRs), and agreed glossary terms before disposing of temporary nodes
|
|
19
|
+
|
|
20
|
+
The developer can manually publish the generated Markdown companion to GitHub. Publication does not transfer browser comments or approval, and ACStack does not track that publication automatically.
|
|
21
|
+
|
|
22
|
+
### Approval belongs to exact inputs
|
|
23
|
+
|
|
24
|
+
- Approval binds `sourceRevision`, `reviewRevision`, `commentsDigest`, and `mapInputsDigest`, not the rendered page alone
|
|
25
|
+
- Each selected comment and current contribution needs one explicit disposition: `applied`, `retained`, or `needs-human`, with a rationale
|
|
26
|
+
- Unresolved blocking decisions or a `needs-human` disposition prevent approval; comments alone never authorize implementation
|
|
27
|
+
- Source, saved feedback, or meaningful contribution changes reopen the gate; presentation regeneration alone preserves approval
|
|
28
|
+
|
|
29
|
+
- Use `design-review status` for the current tuple and contribution keys
|
|
30
|
+
- Follow `skills/design-doc/SKILL.md` for the reconciliation schema and `design-review reconcile <entry> --input <json-file>`
|
|
31
|
+
- Select earlier feedback with `--review-file <canonical-review.json>` when reconciling that history
|
|
32
|
+
- Original comments stay with their original version
|
|
33
|
+
- Previously selected histories remain review obligations after later source changes
|
|
34
|
+
|
|
35
|
+
This revised example is a new draft requiring fresh human approval.
|
|
36
|
+
|
|
37
|
+
### Map binding is optional
|
|
38
|
+
|
|
39
|
+
This portable example has no map binding. A project can add `planning: {tracker: files | github, map: <name>}` and put `Design entry: <repository-relative-path>` in its map root. Node bodies supply explicit design contributions; the map does not become the architecture graph.
|
|
40
|
+
|
|
41
|
+
Bundled browser assets require no external fetch or design upload. Agent-side reads of a GitHub-bound map still need GitHub access. The diagram's GitHub arrow describes manual Markdown publication, not tracker synchronization.
|
|
42
|
+
|
|
43
|
+
### Archive preserves evidence; legacy import is explicit
|
|
44
|
+
|
|
45
|
+
- Archive checks current approval and reconciliation before closing a bound map
|
|
46
|
+
- Archive verifies implemented requirements against source and verification evidence
|
|
47
|
+
- Archive records qualifying ADRs and glossary terms
|
|
48
|
+
- Archive retains design sources, canonical reviews, import history, original legacy artifacts, and decision logs independently of node disposal
|
|
49
|
+
|
|
50
|
+
- Use `node walk`, `node frontier`, and `node diagram` for planning; ACStack retires `map --map` and `align-viewer` without aliases
|
|
51
|
+
- Import legacy feedback only through `design-review migrate` with an explicit target mapping
|
|
52
|
+
- Treat imported approval as historical; imported comments require reconciliation and fresh exact-revision approval
|
|
53
|
+
- Startup and archive never migrate automatically
|
|
54
|
+
|
|
55
|
+
### Local source and optional GitHub publication
|
|
56
|
+
|
|
57
|
+
- Authored design files are the local YAML and supporting Markdown read by the Review command and server
|
|
58
|
+
- GitHub hosts a published copy of the generated companion only when the Project developer chooses to share it
|
|
59
|
+
- Git ignore rules control ordinary tracking; they neither publish files nor prevent local browser review
|
|
60
|
+
- Both the Authored design files and GitHub drawers explain source ownership, published copies, and ignore rules
|
|
61
|
+
|
|
62
|
+
### Containment and arrows keep their existing meaning
|
|
63
|
+
|
|
64
|
+
The ACStack plugin contains Agent skills, Agent session setup, and the CLI package. The CLI package contains the Review command and server and the Browser review interface. The Project developer, Authored design files, and GitHub remain outside the plugin.
|
|
65
|
+
|
|
66
|
+
- Each component is one entity, shown collapsed or expanded
|
|
67
|
+
- Nesting means containment; arrows connect responsible entities, never ancestors to descendants
|
|
68
|
+
- Read one-way arrows as actor, action, and target: the server reads source, and the developer optionally publishes Markdown
|
|
69
|
+
- The bidirectional review-session arrow covers the prepared graph, posted comments, and retrieved comments
|
|
70
|
+
- Concerns describe shared requirements without changing containment
|
|
71
|
+
|
|
72
|
+
### Optional repository context
|
|
73
|
+
|
|
74
|
+
- Authoring, reconciliation, approval, and migration guidance: `skills/design-doc/SKILL.md`
|
|
75
|
+
- Local review and lifecycle commands: `cli/src/commands/design-doc.ts`
|
|
76
|
+
- Bounded source validation, graph, and Markdown generation: `cli/src/lib/design-doc.ts`
|
|
77
|
+
- Contributions and exact-input approval: `cli/src/lib/design-map.ts`, `cli/src/lib/design-lifecycle.ts`
|
|
78
|
+
- Saved review history and legacy imports: `cli/src/lib/design-review.ts`, `cli/src/lib/design-migration.ts`
|
|
79
|
+
- Closeout and evidence retention: `skills/archive/SKILL.md`
|
|
80
|
+
|
|
81
|
+
- Run the review command from this example directory with a built CLI
|
|
82
|
+
- Choose `--port <port>` if another review uses the default port
|
|
83
|
+
- Use an unused path for each Markdown export
|
|
84
|
+
- Keep the companion beside source when its relative links must work on GitHub
|
|
85
|
+
- New designs default to Git-ignored `.acstack/designs/`; this repository intentionally tracks this public example
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Authored design files define the design in the local checkout; GitHub hosts a published copy only if the developer chooses to share it.
|
|
2
|
+
|
|
3
|
+
- Local files drive the review
|
|
4
|
+
- The Review command and server read the local YAML and supporting Markdown to generate the browser view and Markdown companion
|
|
5
|
+
- Revise these source files when the design changes
|
|
6
|
+
- Local browser review and saved comments work without publishing design files to GitHub
|
|
7
|
+
- GitHub hosts a published copy
|
|
8
|
+
- The Project developer can commit and push the generated companion for others to read on GitHub
|
|
9
|
+
- The developer can publish the companion alone or include the authored source files
|
|
10
|
+
- GitHub does not replace the local files read by the review server or automatically receive its saved comments
|
|
11
|
+
- This diagram's publication arrow is separate from using GitHub issues as a map tracker
|
|
12
|
+
- Git ignore rules control tracking, not publication
|
|
13
|
+
- Ignore rules exclude matching untracked files from ordinary staging
|
|
14
|
+
- Removing an ignore rule does not stage, commit, or push anything
|
|
15
|
+
- Already tracked files remain tracked even if an ignore rule later matches them
|
|
16
|
+
- New project designs under `.acstack/` stay ignored by default; this public example is tracked separately
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
id: review-runtime
|
|
2
|
+
name: Review command and server
|
|
3
|
+
summary: >-
|
|
4
|
+
Reads and validates authored YAML, serves the browser review interface,
|
|
5
|
+
saves comments, and exports Markdown.
|
|
6
|
+
kind: component
|
|
7
|
+
parent: cli
|
|
8
|
+
channels: [cli, web]
|
|
9
|
+
relationships:
|
|
10
|
+
- id: export-design
|
|
11
|
+
from: skills
|
|
12
|
+
to: review-runtime
|
|
13
|
+
direction: one-way
|
|
14
|
+
label: Guides the agent to run
|
|
15
|
+
- id: read-source
|
|
16
|
+
from: review-runtime
|
|
17
|
+
to: design-source
|
|
18
|
+
direction: one-way
|
|
19
|
+
label: Reads design source
|
|
20
|
+
- id: review-session
|
|
21
|
+
from: review-runtime
|
|
22
|
+
to: viewer
|
|
23
|
+
direction: bidirectional
|
|
24
|
+
label: Exchanges the design and comments with
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
id: skills
|
|
2
|
+
name: Agent skills
|
|
3
|
+
summary: Guide the agent through authoring and exporting a design for review.
|
|
4
|
+
kind: component
|
|
5
|
+
parent: acstack
|
|
6
|
+
channels: [agent]
|
|
7
|
+
relationships:
|
|
8
|
+
- id: author-design
|
|
9
|
+
from: user
|
|
10
|
+
to: skills
|
|
11
|
+
direction: one-way
|
|
12
|
+
label: Requests design guidance from
|
|
13
|
+
- id: export-design
|
|
14
|
+
from: skills
|
|
15
|
+
to: review-runtime
|
|
16
|
+
direction: one-way
|
|
17
|
+
label: Guides the agent to run
|
|
18
|
+
- id: load-skills
|
|
19
|
+
from: host
|
|
20
|
+
to: skills
|
|
21
|
+
direction: one-way
|
|
22
|
+
label: Registers
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
id: design-source
|
|
2
|
+
name: Authored design files
|
|
3
|
+
summary: Holds the local YAML and supporting Markdown that the review server reads.
|
|
4
|
+
kind: store
|
|
5
|
+
detail: publication.md
|
|
6
|
+
relationships:
|
|
7
|
+
- id: read-source
|
|
8
|
+
from: review-runtime
|
|
9
|
+
to: design-source
|
|
10
|
+
direction: one-way
|
|
11
|
+
label: Reads design source
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
id: user
|
|
2
|
+
name: Project developer
|
|
3
|
+
summary: Authors the design and reviews the exported artifact locally.
|
|
4
|
+
kind: actor
|
|
5
|
+
relationships:
|
|
6
|
+
- id: author-design
|
|
7
|
+
from: user
|
|
8
|
+
to: skills
|
|
9
|
+
direction: one-way
|
|
10
|
+
label: Requests design guidance from
|
|
11
|
+
- id: publish-companion
|
|
12
|
+
from: user
|
|
13
|
+
to: github
|
|
14
|
+
direction: one-way
|
|
15
|
+
label: Optionally publishes the Markdown companion to
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
id: viewer
|
|
2
|
+
name: Browser review interface
|
|
3
|
+
summary: >-
|
|
4
|
+
Receives the prepared design graph and syncs comments with the local server.
|
|
5
|
+
kind: component
|
|
6
|
+
parent: cli
|
|
7
|
+
channels: [web]
|
|
8
|
+
relationships:
|
|
9
|
+
- id: review-session
|
|
10
|
+
from: review-runtime
|
|
11
|
+
to: viewer
|
|
12
|
+
direction: bidirectional
|
|
13
|
+
label: Exchanges the design and comments with
|
|
@@ -8,11 +8,9 @@
|
|
|
8
8
|
#
|
|
9
9
|
# The reminder text is EXTRACTED from output-styles/ac-writing-style.md on every
|
|
10
10
|
# turn, never stored. A hand-typed copy drifts from the style the moment either
|
|
11
|
-
# one changes
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# 1. "## Who you are", top-level lines only, which is the persona
|
|
15
|
-
# 2. "## Before you send", in full, which is the checklist
|
|
11
|
+
# one changes. The marked communication block is the canonical standard for
|
|
12
|
+
# chat and durable writing. Extract it in full, including nested guidance;
|
|
13
|
+
# headings and checklist item counts are not an extraction contract.
|
|
16
14
|
#
|
|
17
15
|
# Output is JSON only, with suppressOutput true, so nothing reaches the user's
|
|
18
16
|
# transcript. The hook stays silent unless the active output style is this one.
|
|
@@ -66,21 +64,12 @@ awk '
|
|
|
66
64
|
}
|
|
67
65
|
function emit(s) { out = out esc(s) "\\n" }
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
/^## Who you are$/ { persona = 1; next }
|
|
73
|
-
/^## Shape: Minto pyramid$/ { persona = 0 }
|
|
74
|
-
persona && /^### / { emit(""); emit($0); next }
|
|
75
|
-
persona && /^[*-]/ { emit($0); next }
|
|
76
|
-
persona && /^\*\*/ { emit($0); next }
|
|
77
|
-
|
|
78
|
-
# "## Before you send" is the checklist, and it runs to the end of the file.
|
|
79
|
-
/^## Before you send$/ { checklist = 1; emit(""); emit($0); next }
|
|
80
|
-
checklist { emit($0); next }
|
|
67
|
+
/^<!-- acstack:communication:start -->$/ { shared = 1; next }
|
|
68
|
+
/^<!-- acstack:communication:end -->$/ { complete = shared; exit }
|
|
69
|
+
shared { emit($0) }
|
|
81
70
|
|
|
82
71
|
END {
|
|
83
|
-
if (out == "") exit 1
|
|
72
|
+
if (!complete || out == "") exit 1
|
|
84
73
|
printf "{\"suppressOutput\": true, \"hookSpecificOutput\": {\"hookEventName\": \"UserPromptSubmit\", \"additionalContext\": \"ac-writing-style reminder\\n\\n%s\"}}\n", out
|
|
85
74
|
}
|
|
86
75
|
' "$style_file" || silent
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { readCommunicationStandard } from './lib/communication-standard.mjs';
|
|
3
|
+
|
|
4
|
+
try {
|
|
5
|
+
const { hook_event_name: event } = JSON.parse(readFileSync(0, 'utf8'));
|
|
6
|
+
if (event !== 'SessionStart' && event !== 'SubagentStart') {
|
|
7
|
+
throw new Error('Expected SessionStart or SubagentStart');
|
|
8
|
+
}
|
|
9
|
+
const standard = readCommunicationStandard(process.argv[2]);
|
|
10
|
+
console.log(JSON.stringify({
|
|
11
|
+
suppressOutput: true,
|
|
12
|
+
hookSpecificOutput: { hookEventName: event, additionalContext: standard },
|
|
13
|
+
}));
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error(`acstack communication standard: ${error.message}`);
|
|
16
|
+
process.exitCode = 1;
|
|
17
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Startup context is independent of project activation and selected output style.
|
|
3
|
+
set -eu
|
|
4
|
+
root="${CLAUDE_PLUGIN_ROOT:-}"
|
|
5
|
+
[ -n "$root" ] || root="$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)"
|
|
6
|
+
exec node "$root/hooks/communication-standard.mjs" "$root"
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
# nudge when it crosses each rung rather than on every single stop.
|
|
41
41
|
#
|
|
42
42
|
# The default rungs are workflow.handoff.nudge_warn and nudge_severe from
|
|
43
|
-
# acstack/project.yaml (defaulting to 200000 / 500000), and then one rung
|
|
43
|
+
# .acstack/project.yaml (defaulting to 200000 / 500000), and then one rung
|
|
44
44
|
# every workflow.handoff.nudge_step tokens (default 100000) above the last
|
|
45
45
|
# one. Setting workflow.handoff.context_thresholds replaces the default rungs
|
|
46
46
|
# entirely with the listed ones - written either block style (one "- item"
|
|
@@ -361,7 +361,7 @@ def read_config():
|
|
|
361
361
|
"context_thresholds": None,
|
|
362
362
|
}
|
|
363
363
|
try:
|
|
364
|
-
with open(os.path.join("acstack", "project.yaml"), encoding="utf-8", errors="replace") as f:
|
|
364
|
+
with open(os.path.join(".acstack", "project.yaml"), encoding="utf-8", errors="replace") as f:
|
|
365
365
|
lines = f.read().split("\n")
|
|
366
366
|
except OSError:
|
|
367
367
|
return cfg
|
package/hooks/hooks.json
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"hooks": {
|
|
3
3
|
"SessionStart": [
|
|
4
|
+
{
|
|
5
|
+
"hooks": [
|
|
6
|
+
{
|
|
7
|
+
"type": "command",
|
|
8
|
+
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/communication-standard.sh\""
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
},
|
|
4
12
|
{
|
|
5
13
|
"hooks": [
|
|
6
14
|
{
|
|
@@ -26,6 +34,16 @@
|
|
|
26
34
|
]
|
|
27
35
|
}
|
|
28
36
|
],
|
|
37
|
+
"SubagentStart": [
|
|
38
|
+
{
|
|
39
|
+
"hooks": [
|
|
40
|
+
{
|
|
41
|
+
"type": "command",
|
|
42
|
+
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/communication-standard.sh\""
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
],
|
|
29
47
|
"Stop": [
|
|
30
48
|
{
|
|
31
49
|
"hooks": [
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
/** Read the only authored communication standard, refusing partial blocks. */
|
|
5
|
+
export function readCommunicationStandard(root) {
|
|
6
|
+
const file = join(root, 'output-styles', 'ac-writing-style.md');
|
|
7
|
+
const lines = readFileSync(file, 'utf8').split(/\r?\n/);
|
|
8
|
+
const starts = lines.flatMap((line, i) => line === '<!-- acstack:communication:start -->' ? [i] : []);
|
|
9
|
+
const ends = lines.flatMap((line, i) => line === '<!-- acstack:communication:end -->' ? [i] : []);
|
|
10
|
+
if (starts.length !== 1 || ends.length !== 1 || starts[0] >= ends[0]) {
|
|
11
|
+
throw new Error(`${file}: expected one ordered communication marker pair`);
|
|
12
|
+
}
|
|
13
|
+
const standard = lines.slice(starts[0] + 1, ends[0]).join('\n').trim();
|
|
14
|
+
if (!standard) throw new Error(`${file}: empty communication standard`);
|
|
15
|
+
return standard;
|
|
16
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Source from host hooks before reading config or writing project data.
|
|
3
|
+
acstack_has_legacy_project_data() {
|
|
4
|
+
local root="$1" name
|
|
5
|
+
for name in project.yaml domain-map.yaml; do
|
|
6
|
+
{ [ -f "$root/acstack/$name" ] || [ -L "$root/acstack/$name" ]; } && return 0
|
|
7
|
+
done
|
|
8
|
+
for name in alignment-packs design-reviews maps specs changes archive decision-logs; do
|
|
9
|
+
{ [ -d "$root/acstack/$name" ] || [ -L "$root/acstack/$name" ]; } && return 0
|
|
10
|
+
done
|
|
11
|
+
return 1
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
acstack_project_root() {
|
|
15
|
+
local root
|
|
16
|
+
root="$PWD"
|
|
17
|
+
while [ "$root" != / ]; do
|
|
18
|
+
if [ -d "$root/.acstack" ] || acstack_has_legacy_project_data "$root"; then
|
|
19
|
+
printf '%s\n' "$root"
|
|
20
|
+
return
|
|
21
|
+
fi
|
|
22
|
+
root=$(dirname "$root")
|
|
23
|
+
done
|
|
24
|
+
git rev-parse --show-toplevel 2>/dev/null || printf '%s\n' "$PWD"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
acstack_ensure_project_data() {
|
|
28
|
+
local root="$1" bundled_cli="$2"
|
|
29
|
+
if acstack_has_legacy_project_data "$root"; then
|
|
30
|
+
echo 'acstack: legacy project data found; run ~/.claude/acstack/bin/acstack project-data migrate before using it.' >&2
|
|
31
|
+
fi
|
|
32
|
+
if ! (cd "$root" && "$bundled_cli" project-data ensure >&2); then
|
|
33
|
+
echo 'acstack: project-data ensure failed; ignore policy is not confirmed installed. Skipping project activation and private writes.' >&2
|
|
34
|
+
return 1
|
|
35
|
+
fi
|
|
36
|
+
# A second config root must never hide unmigrated project data.
|
|
37
|
+
! acstack_has_legacy_project_data "$root"
|
|
38
|
+
}
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
# the load-bearing state the summary may have compressed away (next action, task
|
|
10
10
|
# ledger, agent-team file ownership, blockers).
|
|
11
11
|
#
|
|
12
|
-
# Active (pending) handoff lives at the fixed path acstack/HANDOFF.md, so this
|
|
12
|
+
# Active (pending) handoff lives at the fixed path .acstack/HANDOFF.md, so this
|
|
13
13
|
# hook reads one known file with no CLI call. The file's frontmatter records the
|
|
14
14
|
# change it belongs to. On consume, the file is MOVED into that change's own
|
|
15
15
|
# folder, accumulating a per-change history:
|
|
16
16
|
#
|
|
17
|
-
# acstack/changes/<change>/handoffs/<timestamp>.md (when the change dir exists)
|
|
18
|
-
# acstack/handoffs/<change>/<timestamp>.md (ad-hoc, or change archived)
|
|
17
|
+
# .acstack/changes/<change>/handoffs/<timestamp>.md (when the change dir exists)
|
|
18
|
+
# .acstack/handoffs/<change>/<timestamp>.md (ad-hoc, or change archived)
|
|
19
19
|
#
|
|
20
20
|
# Storing consumed handoffs inside the change dir means they travel with the
|
|
21
21
|
# change when /acstack:archive moves it. Names are timestamped with a numeric
|
|
@@ -32,6 +32,12 @@
|
|
|
32
32
|
set -u
|
|
33
33
|
|
|
34
34
|
command -v python3 >/dev/null 2>&1 || exit 0
|
|
35
|
+
source "$(dirname "${BASH_SOURCE[0]}")/project-data.sh"
|
|
36
|
+
project_root=$(acstack_project_root)
|
|
37
|
+
export ACSTACK_LEGACY_PROJECT_DATA=0
|
|
38
|
+
acstack_has_legacy_project_data "$project_root" && ACSTACK_LEGACY_PROJECT_DATA=1
|
|
39
|
+
export ACSTACK_BUNDLED_CLI="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/cli/bin/acstack.js"
|
|
40
|
+
cd "$project_root" || exit 0
|
|
35
41
|
|
|
36
42
|
# Capture the hook payload from stdin before running python. The heredoc below
|
|
37
43
|
# becomes python's stdin (the program source), so the payload must travel via an
|
|
@@ -40,7 +46,7 @@ ACSTACK_HOOK_INPUT="$(cat)"
|
|
|
40
46
|
export ACSTACK_HOOK_INPUT
|
|
41
47
|
|
|
42
48
|
python3 <<'PY'
|
|
43
|
-
import json, os, re, shutil, sys
|
|
49
|
+
import json, os, re, shutil, subprocess, sys
|
|
44
50
|
|
|
45
51
|
try:
|
|
46
52
|
data = json.loads(os.environ.get("ACSTACK_HOOK_INPUT", ""))
|
|
@@ -53,7 +59,7 @@ if not isinstance(data, dict):
|
|
|
53
59
|
if data.get("source") != "compact":
|
|
54
60
|
sys.exit(0)
|
|
55
61
|
|
|
56
|
-
active = os.path.join("acstack", "HANDOFF.md")
|
|
62
|
+
active = os.path.join(".acstack", "HANDOFF.md")
|
|
57
63
|
try:
|
|
58
64
|
with open(active, encoding="utf-8") as f:
|
|
59
65
|
raw = f.read()
|
|
@@ -115,14 +121,22 @@ if not stamp:
|
|
|
115
121
|
# Route to the change's own folder when that change dir exists, so consumed
|
|
116
122
|
# handoffs travel with the change on /acstack:archive. Otherwise fall back to a
|
|
117
123
|
# neutral top-level handoffs dir (ad-hoc work, or a change already archived).
|
|
118
|
-
change_dir = os.path.join("acstack", "changes", change)
|
|
124
|
+
change_dir = os.path.join(".acstack", "changes", change)
|
|
119
125
|
if change != "ad-hoc" and os.path.isdir(change_dir):
|
|
120
126
|
archive_dir = os.path.join(change_dir, "handoffs")
|
|
121
127
|
else:
|
|
122
|
-
archive_dir = os.path.join("acstack", "handoffs", change)
|
|
128
|
+
archive_dir = os.path.join(".acstack", "handoffs", change)
|
|
123
129
|
|
|
124
130
|
# Find a non-colliding destination: <stamp>.md, then <stamp>-2.md, -3.md, ...
|
|
125
131
|
dest = None
|
|
132
|
+
try:
|
|
133
|
+
subprocess.run([os.environ["ACSTACK_BUNDLED_CLI"], "project-data", "ensure"],
|
|
134
|
+
check=True, stdout=sys.stderr, stderr=sys.stderr)
|
|
135
|
+
if os.environ["ACSTACK_LEGACY_PROJECT_DATA"] == "1":
|
|
136
|
+
raise OSError("Legacy project data found; run ~/.claude/acstack/bin/acstack project-data migrate first")
|
|
137
|
+
except (OSError, subprocess.CalledProcessError) as error:
|
|
138
|
+
print("acstack: project-data ensure failed; ignore policy is not confirmed installed. Leaving the active handoff untouched. " + str(error), file=sys.stderr)
|
|
139
|
+
sys.exit(0)
|
|
126
140
|
try:
|
|
127
141
|
os.makedirs(archive_dir, exist_ok=True)
|
|
128
142
|
candidate = os.path.join(archive_dir, stamp + ".md")
|
package/hooks/session-start.sh
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
# Both symlinks point at ${CLAUDE_PLUGIN_ROOT}/cli/bin/acstack.js, which is a
|
|
18
18
|
# tiny node wrapper that loads ../dist/index.js.
|
|
19
19
|
#
|
|
20
|
-
# When a project is initialized (acstack/project.yaml exists), the hook also
|
|
20
|
+
# When a project is initialized (.acstack/project.yaml exists), the hook also
|
|
21
21
|
# injects the plugin's orchestrator instructions as additionalContext so installs
|
|
22
22
|
# stay version-agnostic. Otherwise prints a one-line reminder.
|
|
23
23
|
|
|
@@ -181,7 +181,14 @@ if [ -n "$plugin_root" ]; then
|
|
|
181
181
|
esac
|
|
182
182
|
fi
|
|
183
183
|
|
|
184
|
-
|
|
184
|
+
# Install the ignore baseline even when setup has not written project.yaml.
|
|
185
|
+
source "${plugin_root}/hooks/project-data.sh"
|
|
186
|
+
project_root=$(acstack_project_root)
|
|
187
|
+
if ! acstack_ensure_project_data "$project_root" "$cli_wrapper"; then
|
|
188
|
+
exit 0
|
|
189
|
+
fi
|
|
190
|
+
|
|
191
|
+
if [ ! -f "$project_root/.acstack/project.yaml" ]; then
|
|
185
192
|
echo 'acstack: no project config found. Run /acstack:setup to set up.' >&2
|
|
186
193
|
exit 0
|
|
187
194
|
fi
|
package/orchestrator/AGENTS.md
CHANGED
|
@@ -66,7 +66,17 @@ ACStack runs on Claude Code, Codex, and pi. The skills name each capability once
|
|
|
66
66
|
|
|
67
67
|
## Project configuration
|
|
68
68
|
|
|
69
|
-
All
|
|
69
|
+
- All ACStack-owned project data lives under `.acstack/` and stays local by default
|
|
70
|
+
- The root `.gitignore` is the sole tracking policy; user exceptions after its managed baseline opt individual parts in
|
|
71
|
+
- Before a configuration gate, CLI and host session startup run `~/.claude/acstack/bin/acstack project-data ensure`
|
|
72
|
+
- When creating `.acstack/` manually, run that command immediately; it needs no project config
|
|
73
|
+
- Filesystem creation alone triggers nothing; the next CLI invocation or session startup enforces the baseline, without a watcher
|
|
74
|
+
- Never force-add ignored project data, change the Git index, or create automatic tracking exceptions
|
|
75
|
+
- For legacy layouts, follow the explicit migration procedure in `docs/config-reference.md`
|
|
76
|
+
- Update installed tools first, stop old agents and reviews, migrate the selected checkout, then restart with updated tools
|
|
77
|
+
- Never silently migrate another checkout or work around legacy data by creating a partial `.acstack/` there
|
|
78
|
+
|
|
79
|
+
All project-specific commands and paths come from `.acstack/project.yaml`. Read this file before you run any build, test or lint command. If it doesn't exist, prompt the user to run `/acstack:setup`.
|
|
70
80
|
|
|
71
81
|
Key fields:
|
|
72
82
|
|
|
@@ -250,18 +260,19 @@ flowchart TD
|
|
|
250
260
|
|
|
251
261
|
Spec sync keeps living specs current, whichever workflow you ran. It runs as part of every `/acstack:commit`.
|
|
252
262
|
|
|
253
|
-
When `workflow.spec_sync` is `true` in
|
|
263
|
+
When `workflow.spec_sync` is `true` in `.acstack/project.yaml`:
|
|
254
264
|
|
|
255
265
|
1. Run `git diff --staged` to see what is changing
|
|
256
|
-
2. Map changed files to spec domains via
|
|
257
|
-
3. For each affected domain with a
|
|
266
|
+
2. Map changed files to spec domains via `.acstack/domain-map.yaml`
|
|
267
|
+
3. For each affected domain with a `.acstack/specs/[domain]/spec.md`:
|
|
258
268
|
- Analyze what the staged changes ADD, MODIFY, or REMOVE
|
|
259
269
|
- Generate lightweight ADDED/MODIFIED/REMOVED entries
|
|
260
270
|
- Update the spec.md
|
|
261
|
-
4. Stage updated
|
|
271
|
+
4. Stage updated specs only when native `.gitignore` rules allow tracking
|
|
272
|
+
- Keep ignored specs updated locally; never force-add them or change the Git index to bypass the user's choice
|
|
262
273
|
5. Flag unmapped source files. Prompt the user to map them.
|
|
263
274
|
|
|
264
|
-
|
|
275
|
+
Spec sync updates local records with every commit, including when those records stay ignored.
|
|
265
276
|
|
|
266
277
|
---
|
|
267
278
|
|
|
@@ -278,9 +289,9 @@ This is lightweight – retroactive spec documentation, not upfront planning. Sp
|
|
|
278
289
|
|
|
279
290
|
## Living specs
|
|
280
291
|
|
|
281
|
-
-
|
|
292
|
+
- `.acstack/specs/` contains the cumulative source of truth for the system
|
|
282
293
|
- `/acstack:commit` updates them automatically through spec sync; `/acstack:archive` closes out a cleared map
|
|
283
|
-
- Domain-organized per
|
|
294
|
+
- Domain-organized per `.acstack/domain-map.yaml`
|
|
284
295
|
- Format: Given/When/Then, FR-NNN requirements
|
|
285
296
|
- Bootstrap from existing codebase: `/acstack:bootstrap`
|
|
286
297
|
- Map nodes: ACStack CLI (`~/.claude/acstack/bin/acstack node create | read | update | list`, plus the composed `node frontier` and `node walk` queries)
|
|
@@ -303,13 +314,13 @@ Read-only reviewers report discrepancies to the completion owner.
|
|
|
303
314
|
|
|
304
315
|
**Before marking ANY task as complete, you MUST verify the project builds.**
|
|
305
316
|
|
|
306
|
-
Read
|
|
317
|
+
Read `.acstack/project.yaml` for the specific commands. The general pattern:
|
|
307
318
|
|
|
308
319
|
1. Run the build command if the project configures one
|
|
309
320
|
2. Run lint
|
|
310
321
|
3. Run typecheck if the project configures one
|
|
311
322
|
4. Run the full test suite – ALL tests must pass
|
|
312
|
-
5. Compare the test count against `.test-baseline`. The count must not drop.
|
|
323
|
+
5. Compare the test count against `.acstack/.test-baseline`. The count must not drop.
|
|
313
324
|
6. Run the frontend build and lint if the project configures a frontend
|
|
314
325
|
|
|
315
326
|
### When to run
|
|
@@ -329,7 +340,7 @@ Read `acstack/project.yaml` for the specific commands. The general pattern:
|
|
|
329
340
|
|
|
330
341
|
## Frontend visual verification
|
|
331
342
|
|
|
332
|
-
**This section applies only when
|
|
343
|
+
**This section applies only when `.acstack/project.yaml` sets `frontend` and `workflow.frontend_verification` is `true`.**
|
|
333
344
|
|
|
334
345
|
When a change touches frontend files, delegate real-browser verification to frontend-verifier after required checks pass. Never substitute a confidence claim for browser evidence.
|
|
335
346
|
|
|
@@ -337,7 +348,7 @@ The design pass runs before browser verification when the design gate is on, fol
|
|
|
337
348
|
|
|
338
349
|
The frontend-verifier agent:
|
|
339
350
|
|
|
340
|
-
1. Reads the project's verification knowledge base (
|
|
351
|
+
1. Reads the project's verification knowledge base (`.acstack/verification/VERIFICATION-KNOWLEDGE.md`)
|
|
341
352
|
2. Checks what frontend files changed
|
|
342
353
|
3. Starts the dev server if it's not running
|
|
343
354
|
4. Connects to a browser through the Chrome DevTools Protocol (CDP), over a remote tunnel or local headless Chromium
|
|
@@ -350,8 +361,8 @@ The frontend-verifier agent:
|
|
|
350
361
|
|
|
351
362
|
Run `/acstack:setup` to set up browser verification. This creates:
|
|
352
363
|
|
|
353
|
-
-
|
|
354
|
-
-
|
|
364
|
+
- **`.acstack/agent-browser.json`** – CDP connection config, selected by an absolute `--config` path or `AGENT_BROWSER_CONFIG`
|
|
365
|
+
- **`.acstack/verification/VERIFICATION-KNOWLEDGE.md`** – Evolving knowledge base of element patterns, gotchas, and proven verification sequences
|
|
355
366
|
|
|
356
367
|
`frontend.browser.mode` in project.yaml holds the browser environment: remote, headless, or local.
|
|
357
368
|
|