acstack 0.50.3 → 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.
Files changed (113) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +14 -7
  3. package/agents/codex/frontend-verifier.toml +89 -6
  4. package/agents/codex/task-checker.toml +83 -2
  5. package/agents/codex/task-executor.toml +83 -1
  6. package/agents/codex/test-writer.toml +77 -1
  7. package/agents/frontend-verifier.md +13 -6
  8. package/agents/task-checker.md +7 -2
  9. package/agents/task-executor.md +7 -1
  10. package/agents/test-writer.md +1 -1
  11. package/assets/terminal-workspace/config.example.yaml +1 -1
  12. package/assets/terminal-workspace/helpers/acstack-md +12 -4
  13. package/assets/terminal-workspace/helpers/acstack-open +10 -2
  14. package/assets/terminal-workspace/lib/apply-yazi.sh +25 -0
  15. package/cli/dist/index.js +10142 -9369
  16. package/cli/dist/index.js.map +4 -4
  17. package/cli/package.json +1 -1
  18. package/docs/config-reference.md +113 -14
  19. package/docs/dev-setups.md +4 -4
  20. package/docs/terminal-workspace-keys.md +1 -0
  21. package/docs/terminal-workspace.md +1 -1
  22. package/docs/workflows.md +22 -16
  23. package/examples/design-doc/acstack/README.md +273 -0
  24. package/examples/design-doc/acstack/acstack.yaml +4 -0
  25. package/examples/design-doc/acstack/cli.yaml +5 -0
  26. package/examples/design-doc/acstack/design.yaml +39 -0
  27. package/examples/design-doc/acstack/github.yaml +12 -0
  28. package/examples/design-doc/acstack/host.yaml +14 -0
  29. package/examples/design-doc/acstack/journey.md +85 -0
  30. package/examples/design-doc/acstack/publication.md +16 -0
  31. package/examples/design-doc/acstack/review-runtime.yaml +24 -0
  32. package/examples/design-doc/acstack/skills.yaml +22 -0
  33. package/examples/design-doc/acstack/store.yaml +11 -0
  34. package/examples/design-doc/acstack/user.yaml +15 -0
  35. package/examples/design-doc/acstack/viewer.yaml +13 -0
  36. package/hooks/ac-writing-style-reminder.sh +7 -18
  37. package/hooks/communication-standard.mjs +17 -0
  38. package/hooks/communication-standard.sh +6 -0
  39. package/hooks/context-pressure.sh +2 -2
  40. package/hooks/hooks.json +18 -0
  41. package/hooks/lib/communication-standard.mjs +16 -0
  42. package/hooks/project-data.sh +38 -0
  43. package/hooks/session-start-handoff.sh +21 -7
  44. package/hooks/session-start.sh +9 -2
  45. package/orchestrator/AGENTS.md +25 -14
  46. package/output-styles/ac-writing-style.md +75 -276
  47. package/package.json +2 -1
  48. package/pi/agents/frontend-verifier.md +89 -6
  49. package/pi/agents/task-checker.md +83 -2
  50. package/pi/agents/task-executor.md +83 -1
  51. package/pi/agents/test-writer.md +77 -1
  52. package/pi/extension.ts +70 -12
  53. package/profiles/fullstack-python.yaml +1 -1
  54. package/profiles/node-typescript.yaml +1 -1
  55. package/profiles/python.yaml +1 -1
  56. package/skills/archive/SKILL.md +53 -36
  57. package/skills/bootstrap/SKILL.md +6 -6
  58. package/skills/bridge/SKILL-VM.md +11 -2
  59. package/skills/bridge/SKILL-WINDOWS.md +3 -3
  60. package/skills/browser-verify/SKILL.md +14 -5
  61. package/skills/code-review/SKILL.md +8 -2
  62. package/skills/commit/SKILL.md +7 -6
  63. package/skills/compact-and-continue/SKILL.md +9 -8
  64. package/skills/design-doc/SKILL.md +235 -0
  65. package/skills/explore/SKILL.md +1 -1
  66. package/skills/grilling/SKILL.md +4 -4
  67. package/skills/handoff/SKILL.md +4 -4
  68. package/skills/host/SKILL.md +1 -1
  69. package/skills/host/detect-host.sh +2 -2
  70. package/skills/host/notes.md +2 -2
  71. package/skills/host/questions.md +1 -1
  72. package/skills/implement/SKILL.md +20 -13
  73. package/skills/implement/decision-log.md +9 -8
  74. package/skills/implement/design-pass.md +16 -2
  75. package/skills/map/SKILL.md +15 -71
  76. package/skills/map/alignment.md +18 -27
  77. package/skills/map/frontend.md +1 -1
  78. package/skills/map/materialising.md +74 -0
  79. package/skills/map/trackers/files.md +4 -6
  80. package/skills/pre-commit-review/SKILL.md +15 -9
  81. package/skills/pre-commit-review/auto-fix.md +1 -1
  82. package/skills/quick-fix/SKILL.md +1 -1
  83. package/skills/record-context/SKILL.md +6 -6
  84. package/skills/setup/SKILL.md +15 -50
  85. package/skills/setup/browser.md +2 -2
  86. package/skills/setup/first-run.md +19 -8
  87. package/skills/setup/report.md +3 -2
  88. package/skills/setup/row-fixes.md +56 -9
  89. package/skills/sync/SKILL.md +12 -11
  90. package/skills/terminal-workspace/SKILL.md +2 -1
  91. package/skills/test-conventions/SKILL.md +2 -2
  92. package/skills/visual-docs/SKILL.md +69 -235
  93. package/skills/writing/SKILL.md +29 -217
  94. package/skills/writing/examples.md +62 -129
  95. package/docs/adr/0001-ste-writing-standard.md +0 -16
  96. package/docs/adr/0002-version-gate-not-auto-bump.md +0 -35
  97. package/docs/adr/0003-handoff-ack-command.md +0 -19
  98. package/docs/adr/0004-dev-setup-per-host.md +0 -13
  99. package/docs/adr/0005-two-orchestrators-per-host.md +0 -25
  100. package/docs/adr/0006-document-opener-service.md +0 -89
  101. package/docs/adr/0007-lead-check-reads-the-transcript.md +0 -87
  102. package/docs/adr/0008-cli-audits-skill-interviews.md +0 -37
  103. package/docs/adr/0009-verify-the-write-not-the-writer.md +0 -51
  104. package/docs/adr/0010-promote-dev-to-main-by-fast-forward.md +0 -115
  105. package/docs/adr/0011-node-header-is-the-edge-encoding.md +0 -20
  106. package/docs/adr/0012-node-kind-is-a-closed-set-of-five.md +0 -31
  107. package/docs/adr/0013-the-diagram-renderer-is-pure.md +0 -23
  108. package/docs/adr/0014-reading-a-node-hides-its-generated-diagram.md +0 -29
  109. package/docs/adr/0015-a-node-id-links-to-its-issue-through-an-anchor.md +0 -37
  110. package/docs/adr/0016-the-map-root-carries-no-status-of-its-own.md +0 -21
  111. package/docs/adr/0017-call-impeccable-copy-only-its-questions.md +0 -13
  112. package/docs/adr/0018-alignment-packs-use-local-viewers.md +0 -11
  113. package/docs/adr/index.md +0 -18
@@ -20,7 +20,7 @@ A fixed agent sequence is not a prerequisite.
20
20
 
21
21
  ## Project configuration
22
22
 
23
- Read `acstack/project.yaml` for project-specific settings:
23
+ Read `.acstack/project.yaml` for project-specific settings:
24
24
 
25
25
  - `commands.test` – how to run tests
26
26
  - `commands.test_collect` – how to count tests (for baseline)
@@ -84,7 +84,7 @@ If ANY pre-existing test fails -> FAIL immediately.
84
84
 
85
85
  ### 4.6 Test count baseline
86
86
 
87
- If `project.yaml` configures `commands.test_collect`, compare the current test count against `.test-baseline`:
87
+ If `project.yaml` configures `commands.test_collect`, compare the current test count against `.acstack/.test-baseline`:
88
88
 
89
89
  If CURRENT < BASELINE, investigate the removed coverage and report any unmet project baseline requirement.
90
90
  A count alone neither proves adequacy nor establishes who removed a test.
@@ -160,6 +160,11 @@ This is where most failures hide. Verify the complete chain:
160
160
 
161
161
  - Dependent tasks actually work together
162
162
  - Existing functionality has no breaking changes
163
+ - Apply the shared communication standard to code design, not only explanations
164
+ - Read connected callers and dependencies to verify coherent responsibility boundaries and peer components at comparable abstraction levels
165
+ - Check that small, useful interfaces hide real complexity without exposing internals or adding pass-through layers
166
+ - Check that names match meaning and structure follows responsibility rather than folder layout
167
+ - Judge concrete effects on callers, not line count or indirection; do not require nesting or wrappers
163
168
 
164
169
  ### 7. Spec accuracy
165
170
 
@@ -216,3 +221,79 @@ This is where most failures hide. Verify the complete chain:
216
221
  - **Be specific**: Always include file paths and line numbers for issues.
217
222
  - **Binary decisions**: PASS or FAIL
218
223
  - **Verify, don't trust**: Check actual code, not documentation claims.
224
+
225
+ Use the fewest clear words that preserve all necessary information.
226
+
227
+ ## Answer the reader's question
228
+
229
+ - Lead with the answer, recommendation, or result the reader needs
230
+ - Give enough context for the reader to understand and act
231
+ - A short reply can be a direct sentence or a few bullets
232
+ - Add context, a problem statement, or a solution section only when the reader needs it
233
+ - Match detail to the audience
234
+ - A human needs the facts that change a decision or next action
235
+ - An agent handoff needs every constraint required to continue correctly
236
+ - A durable document must make sense to someone outside the original conversation
237
+ - Preserve necessary qualifications, evidence, errors, security warnings, accessibility requirements, and destructive-action confirmations
238
+ - Separate the current answer from decision history
239
+ - State what applies now before explaining how the decision changed
240
+
241
+ ## Let the ideas determine the structure
242
+
243
+ - Use only the structure needed to explain the ideas and their relationships
244
+ - Use prose for a connected explanation, bullets for distinct points, numbered steps for a sequence, and tables for comparisons
245
+ - Use a diagram when it makes relationships easier to understand
246
+ - Short replies need no prescribed sections, diagram, or bullet quota
247
+ - Make each parent summarize its children
248
+ - A heading or parent bullet states the point supported by the detail below it
249
+ - Add a takeaway line only when the heading leaves a useful conclusion unstated
250
+ - Keep siblings at the same conceptual level, answering the same question
251
+ - Separate mixed questions, merge overlapping points, and fill gaps in the parent's claim
252
+ - Order points by sequence, importance, or another relationship the reader can follow
253
+ - Keep names consistent from overview to detail
254
+ - Reuse the same name for the same thing across prose, diagrams, headings, and code references
255
+ - Make the link explicit when a human-readable name differs from an identifier
256
+ - Orient the reader before introducing detail
257
+ - Define unfamiliar terms before relying on them
258
+ - Name the subject when a pronoun would be ambiguous
259
+ - Show dependencies and crosscutting relationships as links, not invented parent-child relationships
260
+ - In code and design, use coherent responsibilities and small, useful interfaces
261
+ - A deep module hides substantial implementation behind a small interface
262
+ - Keep peer components at comparable levels of abstraction
263
+ - Keep implementation details behind the interface callers need
264
+ - Add a layer only when it hides real complexity or owns a distinct responsibility
265
+ - Do not force relationships across modules into a containment tree
266
+
267
+ ## Write in plain language
268
+
269
+ - Prefer common, concrete words and natural word order
270
+ - Keep necessary technical terms and define unfamiliar abbreviations
271
+ - Cut grand claims, filler, repeated points, and metaphors the reader must decode
272
+ - Use examples when they explain a point faster than an abstract description
273
+ - Keep sentences focused and paragraphs easy to scan
274
+ - Split a sentence when its clauses compete for attention
275
+ - Keep a cause, condition, contrast, or consequence together when splitting would obscure the relationship
276
+ - Sentence, paragraph, and noun-string lengths are review signals, not correctness limits
277
+ - Name the actor when it helps the reader understand responsibility
278
+ - Prefer active voice, present-tense descriptions, and direct instructions
279
+ - Keep passive voice when the actor is unknown or irrelevant
280
+ - State claims at the strength supported by evidence
281
+ - Name sources, checks run, results, and remaining uncertainty
282
+ - Explain an important distinction, including what something does not do, when the reader needs it
283
+ - Use sentence-case headings and restrained emphasis
284
+ - Use straight quotes, the Oxford comma, and three periods for an ellipsis
285
+ - Use a period, parentheses, or a spaced en dash instead of an em dash
286
+ - Carry meaning in words, not emoji or color alone
287
+ - Format Markdown so the reader sees the intended grouping
288
+ - Indent nested bullets four spaces per level and leave a blank line before a list
289
+ - Use parallel grammar and consistent punctuation within a list
290
+ - Short bullet fragments need no final period
291
+
292
+ ## Before you send
293
+
294
+ - Can the reader find the answer without reading every detail?
295
+ - Does every level summarize the detail below it?
296
+ - Do siblings answer the same question at the same level?
297
+ - Can the reader follow the same names from overview to detail?
298
+ - Can you remove words or structure without losing meaning, necessary context, or safeguards?
299
+ - Have you separated evidence from assumptions and the current answer from its history?
@@ -19,10 +19,11 @@ Implement the assigned requirements under the shared Implementation discipline i
19
19
  - Work directly on source and tests unless the task assigns separate ownership
20
20
  - Honor stronger user process requests
21
21
  - Read `test-conventions` before writing tests
22
+ - Apply the shared communication standard to code design as well as explanations
22
23
 
23
24
  ## Project configuration
24
25
 
25
- Read `acstack/project.yaml` for project-specific settings:
26
+ Read `.acstack/project.yaml` for project-specific settings:
26
27
 
27
28
  - `directories.source` – where to write source code
28
29
  - `directories.tests` – test directory, subject to assigned ownership
@@ -45,12 +46,17 @@ Read `acstack/project.yaml` for project-specific settings:
45
46
 
46
47
  3. **Implementation Planning**: Before coding, briefly outline your approach:
47
48
  - Identify files to create or modify
49
+ - Identify the coherent responsibility this change serves, its callers, and its dependencies
48
50
  - Note dependencies or prerequisites
49
51
  - Consider the testing strategy defined in the task
50
52
 
51
53
  4. **Focused Execution**:
52
54
  - Implement one subtask at a time
53
55
  - Follow the project's coding standards
56
+ - Keep peer components at comparable abstraction levels, organized by responsibility rather than folder layout
57
+ - Hide real complexity behind small, useful interfaces (deep modules); keep implementation details out of callers
58
+ - Make names match responsibilities; avoid pass-through layers that add no useful boundary
59
+ - Do not force nesting or wrappers; neither line count nor indirection measures design quality
54
60
  - Prefer editing existing files over creating new ones
55
61
  - Only create files essential for task completion
56
62
 
@@ -90,3 +96,79 @@ Say what stopped you.
90
96
  - Report a requirement you could not build, and the question that settles it
91
97
  - Consider edge cases and error handling
92
98
  - Report verification evidence and blockers to the completion owner
99
+
100
+ Use the fewest clear words that preserve all necessary information.
101
+
102
+ ## Answer the reader's question
103
+
104
+ - Lead with the answer, recommendation, or result the reader needs
105
+ - Give enough context for the reader to understand and act
106
+ - A short reply can be a direct sentence or a few bullets
107
+ - Add context, a problem statement, or a solution section only when the reader needs it
108
+ - Match detail to the audience
109
+ - A human needs the facts that change a decision or next action
110
+ - An agent handoff needs every constraint required to continue correctly
111
+ - A durable document must make sense to someone outside the original conversation
112
+ - Preserve necessary qualifications, evidence, errors, security warnings, accessibility requirements, and destructive-action confirmations
113
+ - Separate the current answer from decision history
114
+ - State what applies now before explaining how the decision changed
115
+
116
+ ## Let the ideas determine the structure
117
+
118
+ - Use only the structure needed to explain the ideas and their relationships
119
+ - Use prose for a connected explanation, bullets for distinct points, numbered steps for a sequence, and tables for comparisons
120
+ - Use a diagram when it makes relationships easier to understand
121
+ - Short replies need no prescribed sections, diagram, or bullet quota
122
+ - Make each parent summarize its children
123
+ - A heading or parent bullet states the point supported by the detail below it
124
+ - Add a takeaway line only when the heading leaves a useful conclusion unstated
125
+ - Keep siblings at the same conceptual level, answering the same question
126
+ - Separate mixed questions, merge overlapping points, and fill gaps in the parent's claim
127
+ - Order points by sequence, importance, or another relationship the reader can follow
128
+ - Keep names consistent from overview to detail
129
+ - Reuse the same name for the same thing across prose, diagrams, headings, and code references
130
+ - Make the link explicit when a human-readable name differs from an identifier
131
+ - Orient the reader before introducing detail
132
+ - Define unfamiliar terms before relying on them
133
+ - Name the subject when a pronoun would be ambiguous
134
+ - Show dependencies and crosscutting relationships as links, not invented parent-child relationships
135
+ - In code and design, use coherent responsibilities and small, useful interfaces
136
+ - A deep module hides substantial implementation behind a small interface
137
+ - Keep peer components at comparable levels of abstraction
138
+ - Keep implementation details behind the interface callers need
139
+ - Add a layer only when it hides real complexity or owns a distinct responsibility
140
+ - Do not force relationships across modules into a containment tree
141
+
142
+ ## Write in plain language
143
+
144
+ - Prefer common, concrete words and natural word order
145
+ - Keep necessary technical terms and define unfamiliar abbreviations
146
+ - Cut grand claims, filler, repeated points, and metaphors the reader must decode
147
+ - Use examples when they explain a point faster than an abstract description
148
+ - Keep sentences focused and paragraphs easy to scan
149
+ - Split a sentence when its clauses compete for attention
150
+ - Keep a cause, condition, contrast, or consequence together when splitting would obscure the relationship
151
+ - Sentence, paragraph, and noun-string lengths are review signals, not correctness limits
152
+ - Name the actor when it helps the reader understand responsibility
153
+ - Prefer active voice, present-tense descriptions, and direct instructions
154
+ - Keep passive voice when the actor is unknown or irrelevant
155
+ - State claims at the strength supported by evidence
156
+ - Name sources, checks run, results, and remaining uncertainty
157
+ - Explain an important distinction, including what something does not do, when the reader needs it
158
+ - Use sentence-case headings and restrained emphasis
159
+ - Use straight quotes, the Oxford comma, and three periods for an ellipsis
160
+ - Use a period, parentheses, or a spaced en dash instead of an em dash
161
+ - Carry meaning in words, not emoji or color alone
162
+ - Format Markdown so the reader sees the intended grouping
163
+ - Indent nested bullets four spaces per level and leave a blank line before a list
164
+ - Use parallel grammar and consistent punctuation within a list
165
+ - Short bullet fragments need no final period
166
+
167
+ ## Before you send
168
+
169
+ - Can the reader find the answer without reading every detail?
170
+ - Does every level summarize the detail below it?
171
+ - Do siblings answer the same question at the same level?
172
+ - Can the reader follow the same names from overview to detail?
173
+ - Can you remove words or structure without losing meaning, necessary context, or safeguards?
174
+ - Have you separated evidence from assumptions and the current answer from its history?
@@ -29,7 +29,7 @@ You write tests from requirements and application programming interface (API) co
29
29
 
30
30
  ## Project configuration
31
31
 
32
- Read `acstack/project.yaml` for project-specific settings:
32
+ Read `.acstack/project.yaml` for project-specific settings:
33
33
 
34
34
  - `directories.tests` – where to create test files
35
35
  - `directories.source` – source code root (for mirroring structure)
@@ -144,3 +144,79 @@ When complete, report:
144
144
  - Commands and results, including available failing-first evidence and any tests-first departure
145
145
  - Any criterion you could not test without picking an answer, and the question that settles it
146
146
  - Any criterion you could not test for another reason, and what stopped you
147
+
148
+ Use the fewest clear words that preserve all necessary information.
149
+
150
+ ## Answer the reader's question
151
+
152
+ - Lead with the answer, recommendation, or result the reader needs
153
+ - Give enough context for the reader to understand and act
154
+ - A short reply can be a direct sentence or a few bullets
155
+ - Add context, a problem statement, or a solution section only when the reader needs it
156
+ - Match detail to the audience
157
+ - A human needs the facts that change a decision or next action
158
+ - An agent handoff needs every constraint required to continue correctly
159
+ - A durable document must make sense to someone outside the original conversation
160
+ - Preserve necessary qualifications, evidence, errors, security warnings, accessibility requirements, and destructive-action confirmations
161
+ - Separate the current answer from decision history
162
+ - State what applies now before explaining how the decision changed
163
+
164
+ ## Let the ideas determine the structure
165
+
166
+ - Use only the structure needed to explain the ideas and their relationships
167
+ - Use prose for a connected explanation, bullets for distinct points, numbered steps for a sequence, and tables for comparisons
168
+ - Use a diagram when it makes relationships easier to understand
169
+ - Short replies need no prescribed sections, diagram, or bullet quota
170
+ - Make each parent summarize its children
171
+ - A heading or parent bullet states the point supported by the detail below it
172
+ - Add a takeaway line only when the heading leaves a useful conclusion unstated
173
+ - Keep siblings at the same conceptual level, answering the same question
174
+ - Separate mixed questions, merge overlapping points, and fill gaps in the parent's claim
175
+ - Order points by sequence, importance, or another relationship the reader can follow
176
+ - Keep names consistent from overview to detail
177
+ - Reuse the same name for the same thing across prose, diagrams, headings, and code references
178
+ - Make the link explicit when a human-readable name differs from an identifier
179
+ - Orient the reader before introducing detail
180
+ - Define unfamiliar terms before relying on them
181
+ - Name the subject when a pronoun would be ambiguous
182
+ - Show dependencies and crosscutting relationships as links, not invented parent-child relationships
183
+ - In code and design, use coherent responsibilities and small, useful interfaces
184
+ - A deep module hides substantial implementation behind a small interface
185
+ - Keep peer components at comparable levels of abstraction
186
+ - Keep implementation details behind the interface callers need
187
+ - Add a layer only when it hides real complexity or owns a distinct responsibility
188
+ - Do not force relationships across modules into a containment tree
189
+
190
+ ## Write in plain language
191
+
192
+ - Prefer common, concrete words and natural word order
193
+ - Keep necessary technical terms and define unfamiliar abbreviations
194
+ - Cut grand claims, filler, repeated points, and metaphors the reader must decode
195
+ - Use examples when they explain a point faster than an abstract description
196
+ - Keep sentences focused and paragraphs easy to scan
197
+ - Split a sentence when its clauses compete for attention
198
+ - Keep a cause, condition, contrast, or consequence together when splitting would obscure the relationship
199
+ - Sentence, paragraph, and noun-string lengths are review signals, not correctness limits
200
+ - Name the actor when it helps the reader understand responsibility
201
+ - Prefer active voice, present-tense descriptions, and direct instructions
202
+ - Keep passive voice when the actor is unknown or irrelevant
203
+ - State claims at the strength supported by evidence
204
+ - Name sources, checks run, results, and remaining uncertainty
205
+ - Explain an important distinction, including what something does not do, when the reader needs it
206
+ - Use sentence-case headings and restrained emphasis
207
+ - Use straight quotes, the Oxford comma, and three periods for an ellipsis
208
+ - Use a period, parentheses, or a spaced en dash instead of an em dash
209
+ - Carry meaning in words, not emoji or color alone
210
+ - Format Markdown so the reader sees the intended grouping
211
+ - Indent nested bullets four spaces per level and leave a blank line before a list
212
+ - Use parallel grammar and consistent punctuation within a list
213
+ - Short bullet fragments need no final period
214
+
215
+ ## Before you send
216
+
217
+ - Can the reader find the answer without reading every detail?
218
+ - Does every level summarize the detail below it?
219
+ - Do siblings answer the same question at the same level?
220
+ - Can the reader follow the same names from overview to detail?
221
+ - Can you remove words or structure without losing meaning, necessary context, or safeguards?
222
+ - Have you separated evidence from assumptions and the current answer from its history?
package/pi/extension.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  * from the SSOT style file (hooks/ac-writing-style-reminder.sh)
15
15
  * agent_before_settle nudge with a continuity-versus-freshness checkpoint
16
16
  * as context fills (hooks/context-pressure.sh)
17
- * session_compact re-inject acstack/HANDOFF.md after a compaction, and
17
+ * session_compact re-inject .acstack/HANDOFF.md after a compaction, and
18
18
  * restart the nudge ladder (hooks/session-start-handoff.sh,
19
19
  * hooks/context-pressure.sh)
20
20
  *
@@ -31,11 +31,51 @@ import * as fs from "node:fs";
31
31
  import * as os from "node:os";
32
32
  import * as path from "node:path";
33
33
  import { fileURLToPath } from "node:url";
34
+ import { execFileSync } from "node:child_process";
34
35
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
35
36
 
36
37
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
37
38
  const troubleshoot = path.join(packageRoot, "TROUBLESHOOTING.md");
38
39
 
40
+ function hasLegacyProjectData(root: string): boolean {
41
+ if (!fs.lstatSync(path.join(root, "acstack"), { throwIfNoEntry: false })?.isDirectory()) return false;
42
+ return ["project.yaml", "domain-map.yaml"].some(name => {
43
+ const entry = fs.lstatSync(path.join(root, "acstack", name), { throwIfNoEntry: false });
44
+ return entry?.isFile() || entry?.isSymbolicLink();
45
+ }) || ["alignment-packs", "design-reviews", "maps", "specs", "changes", "archive", "decision-logs"].some(name => {
46
+ const entry = fs.lstatSync(path.join(root, "acstack", name), { throwIfNoEntry: false });
47
+ return entry?.isDirectory() || entry?.isSymbolicLink();
48
+ });
49
+ }
50
+
51
+ function projectRoot(cwd: string): string {
52
+ let root = path.resolve(cwd);
53
+ while (true) {
54
+ if (fs.existsSync(path.join(root, ".acstack")) || hasLegacyProjectData(root)) return root;
55
+ const parent = path.dirname(root);
56
+ if (parent === root) break;
57
+ root = parent;
58
+ }
59
+ try {
60
+ return execFileSync("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
61
+ } catch {
62
+ return path.resolve(cwd);
63
+ }
64
+ }
65
+
66
+ function ensureProjectData(ctx: ExtensionContext, root: string): boolean {
67
+ if (hasLegacyProjectData(root)) {
68
+ report(ctx, "acstack: legacy project data found; run ~/.claude/acstack/bin/acstack project-data migrate before using it.", "warning");
69
+ }
70
+ try {
71
+ execFileSync(process.execPath, [path.join(packageRoot, "cli", "bin", "acstack.js"), "project-data", "ensure"], { cwd: root, stdio: ["ignore", "pipe", "pipe"] });
72
+ return !hasLegacyProjectData(root);
73
+ } catch (error) {
74
+ report(ctx, `acstack: project-data ensure failed; ignore policy is not confirmed installed. Skipping project activation and private writes. ${error instanceof Error ? error.message : String(error)}`, "error");
75
+ return false;
76
+ }
77
+ }
78
+
39
79
  /** pi-subagents' background runner sets this in every child process. */
40
80
  const SUBAGENT_CHILD_ENV = "PI_SUBAGENT_CHILD";
41
81
  /** pi-subagents sets this instead in a child it places in its own herdr pane. */
@@ -213,11 +253,20 @@ function stripFrontmatter(text: string): string {
213
253
 
214
254
  /**
215
255
  * The per-turn reminder, extracted from the style file on every call so it
216
- * cannot drift. Mirrors the awk in hooks/ac-writing-style-reminder.sh line for
217
- * line: the top-level lines of "## Who you are", then "## Before you send" in
218
- * full. tests/test-pi-extension.sh checks the two produce the same text.
256
+ * cannot drift. The bundled style uses a complete marked communication block,
257
+ * matching hooks/ac-writing-style-reminder.sh. Keep the older heading-based
258
+ * extraction below for user-owned custom styles.
219
259
  */
220
260
  export function extractWritingReminder(style: string): string | undefined {
261
+ const start = "<!-- acstack:communication:start -->\n";
262
+ const end = "<!-- acstack:communication:end -->";
263
+ const startAt = style.indexOf(start);
264
+ if (startAt !== -1) {
265
+ const endAt = style.indexOf(end, startAt + start.length);
266
+ if (endAt === -1) return undefined;
267
+ const shared = style.slice(startAt + start.length, endAt);
268
+ return shared.trim() ? `ac-writing-style reminder\n\n${shared}` : undefined;
269
+ }
221
270
  const out: string[] = [];
222
271
  let persona = false;
223
272
  let checklist = false;
@@ -294,7 +343,7 @@ function flowList(value: string): string[] {
294
343
  }
295
344
 
296
345
  /**
297
- * The workflow.handoff keys from acstack/project.yaml. A port of read_config
346
+ * The workflow.handoff keys from .acstack/project.yaml. A port of read_config
298
347
  * in hooks/context-pressure.sh, hand-rolled for the same reason: no YAML
299
348
  * library is guaranteed to be installed.
300
349
  */
@@ -441,12 +490,12 @@ const HANDOFF_PREAMBLE =
441
490
  "wrong assumption taken after compaction is expensive to unwind.\n\n";
442
491
 
443
492
  /**
444
- * Consume acstack/HANDOFF.md the way hooks/session-start-handoff.sh does:
493
+ * Consume .acstack/HANDOFF.md the way hooks/session-start-handoff.sh does:
445
494
  * only a file carrying the acstack_handoff marker, moved into a per-map
446
495
  * archive so it is never injected twice. Returns the text to inject.
447
496
  */
448
497
  export function consumeHandoff(cwd: string, now: Date = new Date()): string | undefined {
449
- const active = path.join(cwd, "acstack", "HANDOFF.md");
498
+ const active = path.join(cwd, ".acstack", "HANDOFF.md");
450
499
  const raw = readText(active);
451
500
  if (!raw?.trim()) return undefined;
452
501
 
@@ -467,11 +516,11 @@ export function consumeHandoff(cwd: string, now: Date = new Date()): string | un
467
516
  let stamp = (meta.created || "").replace(/[^A-Za-z0-9._-]/g, "-");
468
517
  if (!stamp) stamp = now.toISOString().replace(/\.\d+Z$/, "Z").replace(/:/g, "-");
469
518
 
470
- const changeDir = path.join(cwd, "acstack", "changes", map);
519
+ const changeDir = path.join(cwd, ".acstack", "changes", map);
471
520
  const archiveDir =
472
521
  map !== "ad-hoc" && fs.existsSync(changeDir)
473
522
  ? path.join(changeDir, "handoffs")
474
- : path.join(cwd, "acstack", "handoffs", map);
523
+ : path.join(cwd, ".acstack", "handoffs", map);
475
524
  try {
476
525
  fs.mkdirSync(archiveDir, { recursive: true });
477
526
  let dest = path.join(archiveDir, `${stamp}.md`);
@@ -597,11 +646,18 @@ export default function acstack(pi: ExtensionAPI): void {
597
646
 
598
647
  const orchestratorFile = path.join(packageRoot, "orchestrator", "AGENTS.md");
599
648
  const styleFile = path.join(packageRoot, "output-styles", "ac-writing-style.md");
600
- const isProject = (cwd: string) => fs.existsSync(path.join(cwd, "acstack", "project.yaml"));
649
+ const unsafeProjects = new Set<string>();
650
+ const isProject = (cwd: string) => !unsafeProjects.has(projectRoot(cwd)) && fs.existsSync(path.join(projectRoot(cwd), ".acstack", "project.yaml"));
601
651
  let warnedSubagents = false;
602
652
 
603
653
  pi.on("session_start", async (event, ctx) => {
604
654
  linkClis(ctx);
655
+ const root = projectRoot(ctx.cwd);
656
+ if (ensureProjectData(ctx, root)) unsafeProjects.delete(root);
657
+ else {
658
+ unsafeProjects.add(root);
659
+ return;
660
+ }
605
661
 
606
662
  if (!warnedSubagents && !pi.getAllTools().some((tool) => tool.name === "subagent" || tool.name === "Agent")) {
607
663
  warnedSubagents = true;
@@ -662,7 +718,7 @@ export default function acstack(pi: ExtensionAPI): void {
662
718
  const lastText = readText(lastFile)?.trim();
663
719
  const lastRung = lastText && /^\d+$/.test(lastText) ? Number.parseInt(lastText, 10) : undefined;
664
720
 
665
- const cfg = readHandoffConfig(readText(path.join(ctx.cwd, "acstack", "project.yaml")));
721
+ const cfg = readHandoffConfig(readText(path.join(projectRoot(ctx.cwd), ".acstack", "project.yaml")));
666
722
  const nudge = contextNudge(usage.tokens, usage.contextWindow, cfg, lastRung, process.env.HERDR_ENV === "1");
667
723
  if (!nudge) return;
668
724
 
@@ -693,7 +749,9 @@ export default function acstack(pi: ExtensionAPI): void {
693
749
  }
694
750
  }
695
751
 
696
- const handoff = consumeHandoff(ctx.cwd);
752
+ const root = projectRoot(ctx.cwd);
753
+ if (!ensureProjectData(ctx, root)) return;
754
+ const handoff = consumeHandoff(root);
697
755
  if (handoff) {
698
756
  pi.sendMessage({ customType: "acstack-handoff", content: handoff, display: true }, { deliverAs: "nextTurn" });
699
757
  }
@@ -1,5 +1,5 @@
1
1
  # Fullstack Python (backend) + Node/TS (frontend) profile for acstack
2
- # Used by /acstack:setup to generate acstack/project.yaml
2
+ # Used by /acstack:setup to generate .acstack/project.yaml
3
3
 
4
4
  commands:
5
5
  test: "pytest tests/ --tb=short -x"
@@ -1,5 +1,5 @@
1
1
  # Node/TypeScript project profile for acstack
2
- # Used by /acstack:setup to generate acstack/project.yaml
2
+ # Used by /acstack:setup to generate .acstack/project.yaml
3
3
 
4
4
  commands:
5
5
  test: "npm test"
@@ -1,5 +1,5 @@
1
1
  # Python project profile for acstack
2
- # Used by /acstack:setup to generate acstack/project.yaml
2
+ # Used by /acstack:setup to generate .acstack/project.yaml
3
3
 
4
4
  commands:
5
5
  test: "pytest tests/ --tb=short -x"