acstack 0.53.0 → 0.54.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 (87) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +11 -11
  3. package/agents/codex/frontend-verifier.toml +8 -7
  4. package/agents/codex/task-checker.toml +1 -1
  5. package/agents/codex/task-executor.toml +1 -1
  6. package/agents/codex/test-writer.toml +1 -1
  7. package/agents/frontend-verifier.md +8 -7
  8. package/agents/task-checker.md +1 -1
  9. package/agents/task-executor.md +1 -1
  10. package/agents/test-writer.md +1 -1
  11. package/assets/playwriter-bridge/doctor.ps1 +1 -1
  12. package/assets/playwriter-bridge/register-tasks.ps1 +4 -4
  13. package/assets/terminal-workspace/config.example.yaml +2 -2
  14. package/assets/terminal-workspace/helpers/acstack-bridge +3 -1
  15. package/assets/terminal-workspace/helpers/acstack-db +1 -1
  16. package/assets/terminal-workspace/helpers/acstack-md +4 -2
  17. package/assets/terminal-workspace/helpers/acstack-md-lib +2 -2
  18. package/assets/terminal-workspace/helpers/acstack-open +1 -1
  19. package/assets/terminal-workspace/lib/apply-herdr-numbers.sh +1 -1
  20. package/assets/terminal-workspace/lib/apply-tools.sh +1 -1
  21. package/assets/terminal-workspace/lib/apply-tuicr.sh +2 -2
  22. package/assets/terminal-workspace/lib/commands.sh +1 -1
  23. package/assets/terminal-workspace/lib/helper-install.sh +1 -1
  24. package/assets/terminal-workspace/setup.sh +6 -1
  25. package/cli/dist/index.js +698 -510
  26. package/cli/dist/index.js.map +4 -4
  27. package/cli/package.json +1 -1
  28. package/docs/config-reference.md +129 -87
  29. package/docs/dev-setups.md +4 -4
  30. package/docs/terminal-workspace.md +7 -6
  31. package/docs/workflows.md +13 -12
  32. package/examples/design-doc/acstack/README.md +3 -3
  33. package/examples/design-doc/acstack/journey.md +1 -1
  34. package/examples/design-doc/acstack/publication.md +1 -1
  35. package/hooks/context-pressure.sh +6 -2
  36. package/hooks/lib/read-guard.mjs +25 -21
  37. package/hooks/project-data.sh +5 -34
  38. package/hooks/session-start-handoff.sh +11 -22
  39. package/hooks/session-start.sh +5 -6
  40. package/orchestrator/AGENTS.md +30 -25
  41. package/package.json +1 -1
  42. package/pi/agents/frontend-verifier.md +8 -7
  43. package/pi/agents/task-checker.md +1 -1
  44. package/pi/agents/task-executor.md +1 -1
  45. package/pi/agents/test-writer.md +1 -1
  46. package/pi/extension.ts +39 -57
  47. package/profiles/fullstack-python.yaml +1 -1
  48. package/profiles/node-typescript.yaml +1 -1
  49. package/profiles/python.yaml +1 -1
  50. package/skills/archive/SKILL.md +20 -18
  51. package/skills/bootstrap/SKILL.md +6 -6
  52. package/skills/bridge/SKILL-VM.md +5 -5
  53. package/skills/bridge/SKILL-WINDOWS.md +1 -1
  54. package/skills/browser-verify/SKILL.md +6 -6
  55. package/skills/commit/SKILL.md +8 -8
  56. package/skills/compact-and-continue/SKILL.md +11 -9
  57. package/skills/design-doc/SKILL.md +8 -5
  58. package/skills/explore/SKILL.md +1 -1
  59. package/skills/grilling/SKILL.md +4 -3
  60. package/skills/handoff/SKILL.md +4 -4
  61. package/skills/host/SKILL.md +2 -2
  62. package/skills/host/detect-host.sh +8 -4
  63. package/skills/host/herdr.md +1 -1
  64. package/skills/host/install-herdr-block.sh +1 -1
  65. package/skills/host/notes.md +5 -4
  66. package/skills/host/questions.md +1 -1
  67. package/skills/host/report.md +2 -2
  68. package/skills/implement/SKILL.md +6 -5
  69. package/skills/implement/decision-log.md +10 -15
  70. package/skills/implement/design-pass.md +2 -2
  71. package/skills/map/SKILL.md +5 -3
  72. package/skills/map/frontend.md +2 -2
  73. package/skills/map/materialising.md +5 -3
  74. package/skills/map/trackers/files.md +6 -4
  75. package/skills/pre-commit-review/SKILL.md +3 -3
  76. package/skills/quick-fix/SKILL.md +1 -1
  77. package/skills/record-context/SKILL.md +6 -6
  78. package/skills/setup/SKILL.md +20 -11
  79. package/skills/setup/browser.md +2 -2
  80. package/skills/setup/first-run.md +14 -16
  81. package/skills/setup/report.md +4 -3
  82. package/skills/setup/row-fixes.md +7 -8
  83. package/skills/sync/SKILL.md +14 -12
  84. package/skills/terminal-workspace/SKILL.md +4 -4
  85. package/skills/terminal-workspace/headless-clipboard.md +1 -1
  86. package/skills/terminal-workspace/turn-off-and-update.md +1 -1
  87. package/skills/test-conventions/SKILL.md +2 -2
@@ -12,6 +12,8 @@ import * as fs from 'node:fs';
12
12
  import * as os from 'node:os';
13
13
  import * as path from 'node:path';
14
14
  import { createHash } from 'node:crypto';
15
+ import { spawnSync } from 'node:child_process';
16
+ import { fileURLToPath } from 'node:url';
15
17
 
16
18
  export const DEFAULT_MIN_BYTES = 32768;
17
19
 
@@ -25,13 +27,13 @@ export function envSaysNotMain(env = process.env) {
25
27
 
26
28
  /**
27
29
  * The one settings function: workflow.read_guard and
28
- * workflow.read_guard_bytes from the nearest
29
- * .acstack/project.yaml above cwd. Hand-rolled like the other hooks' readers,
30
- * because no YAML library is guaranteed at hook time.
30
+ * workflow.read_guard_bytes from project.yaml in the repository's project
31
+ * folder. Hand-rolled like the other hooks' readers, because no YAML library
32
+ * is guaranteed at hook time. pi passes the folder it already resolved.
31
33
  */
32
- export function readGuardSettings(cwd) {
34
+ export function readGuardSettings(cwd, folder = projectFolder(cwd)) {
33
35
  const settings = { enabled: true, minBytes: DEFAULT_MIN_BYTES };
34
- const yaml = projectYaml(cwd);
36
+ const yaml = folder ? readText(path.join(folder, 'project.yaml')) : undefined;
35
37
  if (yaml === undefined) return settings;
36
38
  const stack = [];
37
39
  for (const raw of yaml.split('\n')) {
@@ -54,20 +56,19 @@ export function readGuardSettings(cwd) {
54
56
  return settings;
55
57
  }
56
58
 
57
- function projectYaml(cwd) {
58
- let dir = path.resolve(cwd);
59
- while (true) {
60
- const file = path.join(dir, '.acstack', 'project.yaml');
61
- if (fs.existsSync(file)) {
62
- try {
63
- return fs.readFileSync(file, 'utf8');
64
- } catch {
65
- return undefined;
66
- }
67
- }
68
- const parent = path.dirname(dir);
69
- if (parent === dir) return undefined;
70
- dir = parent;
59
+ const CLI = fileURLToPath(new URL('../../cli/bin/acstack.js', import.meta.url));
60
+
61
+ /** The project folder the CLI reports for cwd, or undefined outside a project. */
62
+ function projectFolder(cwd) {
63
+ const result = spawnSync(process.execPath, [CLI, 'project-data', 'path'], { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
64
+ return result.status === 0 ? result.stdout.trim() || undefined : undefined;
65
+ }
66
+
67
+ function readText(file) {
68
+ try {
69
+ return fs.readFileSync(file, 'utf8');
70
+ } catch {
71
+ return undefined;
71
72
  }
72
73
  }
73
74
 
@@ -118,11 +119,14 @@ function resolvePath(file, cwd) {
118
119
  * `ledger` has has(key) and add(key); add throws when it cannot record, and
119
120
  * then the read is allowed so a repeat can never be trapped.
120
121
  */
121
- export function decide({ toolName, toolInput, cwd, main, ledger, settings = readGuardSettings(cwd) }) {
122
+ export function decide({ toolName, toolInput, cwd, main, ledger, settings }) {
122
123
  try {
123
- if (!main || !settings.enabled || !ledger) return { block: false };
124
+ if (!main || !ledger) return { block: false };
124
125
  const file = wholeReadTarget(toolName, toolInput, cwd);
125
126
  if (!file) return { block: false };
127
+ // Resolved only for a whole-file read, since it costs a CLI call.
128
+ settings ??= readGuardSettings(cwd);
129
+ if (!settings.enabled) return { block: false };
126
130
  const stat = fs.statSync(file);
127
131
  if (!stat.isFile() || stat.size < settings.minBytes) return { block: false };
128
132
  const key = `${fs.realpathSync(file)}\0${stat.size}\0${stat.mtimeMs}`;
@@ -1,38 +1,9 @@
1
1
  #!/usr/bin/env bash
2
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
3
 
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"
4
+ # Print the project folder for the current repository. Fails outside Git, or
5
+ # when the CLI names a fix (legacy data, orphaned entry, conflicting modes);
6
+ # that message and any legacy-data warning reach the user on stderr.
7
+ acstack_project_folder() {
8
+ "$1" project-data path
38
9
  }
@@ -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
13
- # hook reads one known file with no CLI call. The file's frontmatter records the
12
+ # Active (pending) handoff lives at the fixed path <project folder>/HANDOFF.md;
13
+ # the hook asks the CLI for the folder once. 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
+ # <project folder>/changes/<change>/handoffs/<timestamp>.md (when the change dir exists)
18
+ # <project folder>/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
@@ -33,11 +33,8 @@ set -u
33
33
 
34
34
  command -v python3 >/dev/null 2>&1 || exit 0
35
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
36
+ project_folder=$(acstack_project_folder "${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/cli/bin/acstack.js") || exit 0
37
+ cd "$project_folder" 2>/dev/null || exit 0
41
38
 
42
39
  # Capture the hook payload from stdin before running python. The heredoc below
43
40
  # becomes python's stdin (the program source), so the payload must travel via an
@@ -46,7 +43,7 @@ ACSTACK_HOOK_INPUT="$(cat)"
46
43
  export ACSTACK_HOOK_INPUT
47
44
 
48
45
  python3 <<'PY'
49
- import json, os, re, shutil, subprocess, sys
46
+ import json, os, re, shutil, sys
50
47
 
51
48
  try:
52
49
  data = json.loads(os.environ.get("ACSTACK_HOOK_INPUT", ""))
@@ -59,7 +56,7 @@ if not isinstance(data, dict):
59
56
  if data.get("source") != "compact":
60
57
  sys.exit(0)
61
58
 
62
- active = os.path.join(".acstack", "HANDOFF.md")
59
+ active = "HANDOFF.md"
63
60
  try:
64
61
  with open(active, encoding="utf-8") as f:
65
62
  raw = f.read()
@@ -105,7 +102,7 @@ if not body.strip():
105
102
  # "map" is the current key; "change" is accepted for anchors written by
106
103
  # pre-map versions of the handoff skill. The value feeds os.path.join, so
107
104
  # sanitize it the same way as the stamp – a name with "/" or ".." must not
108
- # route the archived handoff outside acstack/.
105
+ # route the archived handoff outside the project folder.
109
106
  change = meta.get("map") or meta.get("change") or "ad-hoc"
110
107
  change = re.sub(r"[^A-Za-z0-9._-]", "-", str(change))
111
108
  if not change.strip("."):
@@ -121,22 +118,14 @@ if not stamp:
121
118
  # Route to the change's own folder when that change dir exists, so consumed
122
119
  # handoffs travel with the change on /acstack:archive. Otherwise fall back to a
123
120
  # neutral top-level handoffs dir (ad-hoc work, or a change already archived).
124
- change_dir = os.path.join(".acstack", "changes", change)
121
+ change_dir = os.path.join("changes", change)
125
122
  if change != "ad-hoc" and os.path.isdir(change_dir):
126
123
  archive_dir = os.path.join(change_dir, "handoffs")
127
124
  else:
128
- archive_dir = os.path.join(".acstack", "handoffs", change)
125
+ archive_dir = os.path.join("handoffs", change)
129
126
 
130
127
  # Find a non-colliding destination: <stamp>.md, then <stamp>-2.md, -3.md, ...
131
128
  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)
140
129
  try:
141
130
  os.makedirs(archive_dir, exist_ok=True)
142
131
  candidate = os.path.join(archive_dir, stamp + ".md")
@@ -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 (its project folder holds project.yaml), 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,14 +181,12 @@ if [ -n "$plugin_root" ]; then
181
181
  esac
182
182
  fi
183
183
 
184
- # Install the ignore baseline even when setup has not written project.yaml.
185
184
  source "${plugin_root}/hooks/project-data.sh"
186
- project_root=$(acstack_project_root)
187
- if ! acstack_ensure_project_data "$project_root" "$cli_wrapper"; then
185
+ if ! project_folder=$(acstack_project_folder "$cli_wrapper"); then
188
186
  exit 0
189
187
  fi
190
188
 
191
- if [ ! -f "$project_root/.acstack/project.yaml" ]; then
189
+ if [ ! -f "$project_folder/project.yaml" ]; then
192
190
  echo 'acstack: no project config found. Run /acstack:setup to set up.' >&2
193
191
  exit 0
194
192
  fi
@@ -205,7 +203,7 @@ if ! command -v python3 >/dev/null 2>&1; then
205
203
  exit 0
206
204
  fi
207
205
 
208
- python3 - "$claude_md" <<'PY'
206
+ python3 - "$claude_md" "$project_folder" <<'PY'
209
207
  import json, re, sys
210
208
  path = sys.argv[1]
211
209
  with open(path, 'r', encoding='utf-8') as f:
@@ -213,6 +211,7 @@ with open(path, 'r', encoding='utf-8') as f:
213
211
  # SessionStart reaches the lead session, so it keeps the lead block and drops the delegated one.
214
212
  content = re.sub(r'<!-- acstack:delegated:start -->[\s\S]*?<!-- acstack:delegated:end -->\n?', '', content)
215
213
  content = re.sub(r'<!-- acstack:lead:(start|end) -->\n?', '', content)
214
+ content += "\n\nThis repository's ACStack project folder: " + sys.argv[2] + "\n"
216
215
  print(json.dumps({
217
216
  "hookSpecificOutput": {
218
217
  "hookEventName": "SessionStart",
@@ -87,17 +87,22 @@ ACStack runs on Claude Code, Codex, and pi. The skills name each capability once
87
87
 
88
88
  ## Project configuration
89
89
 
90
- - All ACStack-owned project data lives under `.acstack/` and stays local by default
91
- - The root `.gitignore` is the sole tracking policy; user exceptions after its managed baseline opt individual parts in
92
- - Before a configuration gate, CLI and host session startup run `~/.claude/acstack/bin/acstack project-data ensure`
93
- - When creating `.acstack/` manually, run that command immediately; it needs no project config
94
- - Filesystem creation alone triggers nothing; the next CLI invocation or session startup enforces the baseline, without a watcher
95
- - Never force-add ignored project data, change the Git index, or create automatic tracking exceptions
96
- - For legacy layouts, follow the explicit migration procedure in `docs/config-reference.md`
97
- - Update installed tools first, stop old agents and reviews, migrate the selected checkout, then restart with updated tools
98
- - Never silently migrate another checkout or work around legacy data by creating a partial `.acstack/` there
99
-
100
- 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`.
90
+ - All ACStack-owned project data lives in one folder per repository, the **project folder**
91
+ - `~/.claude/acstack/bin/acstack project-data path` prints its absolute path, even before it exists
92
+ - Every worktree of a repository shares it; the session-start hook also states it in your context
93
+ - The command exits non-zero outside a Git repository, and names the fix for legacy data, orphaned entries, or conflicts
94
+ - These files write its parts as `<project folder>/project.yaml`, `<project folder>/specs/`, and so on
95
+ - **Global mode** (the default) keeps the project folder under `~/.acstack/projects/` (or `$ACSTACK_HOME/projects/`)
96
+ - The repository holds no ACStack files and needs no `.gitignore` rules
97
+ - **Tracked mode** (opt-in) keeps the records in the main checkout's committed `.acstack/`; the project folder is a link to it
98
+ - Edits to a feature branch's own `.acstack/` take effect only once they reach the main checkout
99
+ - Data moves only when the developer asks: `acstack project-data mode tracked|global`, `migrate`, or `relink <entry>`
100
+ - For legacy layouts, follow the explicit migration procedure in `docs/config-reference.md`
101
+ - Update installed tools first, stop old agents and review servers, migrate, then restart with updated tools
102
+ - Never silently migrate data or work around legacy data by creating a partial project folder
103
+ - Never change the Git index or force-add files to track project data
104
+
105
+ All project-specific commands and paths come from `<project folder>/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`.
101
106
 
102
107
  Key fields:
103
108
 
@@ -331,19 +336,19 @@ The investigator reports:
331
336
 
332
337
  Spec sync keeps living specs current, whichever workflow you ran. It runs as part of every `/acstack:commit`.
333
338
 
334
- When `workflow.spec_sync` is `true` in `.acstack/project.yaml`:
339
+ When `workflow.spec_sync` is `true` in `<project folder>/project.yaml`:
335
340
 
336
341
  1. Run `git diff --staged` to see what is changing
337
- 2. Map changed files to spec domains via `.acstack/domain-map.yaml`
338
- 3. For each affected domain with a `.acstack/specs/[domain]/spec.md`:
342
+ 2. Map changed files to spec domains via `<project folder>/domain-map.yaml`
343
+ 3. For each affected domain with a `<project folder>/specs/[domain]/spec.md`:
339
344
  - Analyze what the staged changes ADD, MODIFY, or REMOVE
340
345
  - Generate lightweight ADDED/MODIFIED/REMOVED entries
341
346
  - Update the spec.md
342
- 4. Stage updated specs only when native `.gitignore` rules allow tracking
343
- - Keep ignored specs updated locally; never force-add them or change the Git index to bypass the user's choice
347
+ 4. Stage updated specs only in tracked mode, when you commit in the main checkout
348
+ - In global mode, and from other worktrees in tracked mode, specs update in place and stay out of the commit
344
349
  5. Flag unmapped source files. Prompt the user to map them.
345
350
 
346
- Spec sync updates local records with every commit, including when those records stay ignored.
351
+ Spec sync updates the living specs with every commit, whether or not the commit includes them.
347
352
 
348
353
  ---
349
354
 
@@ -360,9 +365,9 @@ Spec sync updates local records with every commit, including when those records
360
365
 
361
366
  ## Living specs
362
367
 
363
- - `.acstack/specs/` contains the cumulative source of truth for the system
368
+ - `<project folder>/specs/` contains the cumulative source of truth for the system
364
369
  - `/acstack:commit` updates them automatically through spec sync; `/acstack:archive` closes out a cleared map
365
- - Domain-organized per `.acstack/domain-map.yaml`
370
+ - Domain-organized per `<project folder>/domain-map.yaml`
366
371
  - Format: Given/When/Then, FR-NNN requirements
367
372
  - Bootstrap from existing codebase: `/acstack:bootstrap`
368
373
  - Map nodes: ACStack CLI (`~/.claude/acstack/bin/acstack node create | read | update | list`, plus the composed `node frontier` and `node walk` queries)
@@ -385,12 +390,12 @@ Read-only reviewers report discrepancies to the completion owner.
385
390
 
386
391
  The verification owner gathers evidence for the final revision. Opening a PR does not require running every test locally.
387
392
 
388
- Read `.acstack/project.yaml` for the available commands and inspect the project's CI configuration before relying on it:
393
+ Read `<project folder>/project.yaml` for the available commands and inspect the project's CI configuration before relying on it:
389
394
 
390
395
  1. Use focused local checks by default: cover changed behavior, affected callers, and relevant integration paths
391
396
  2. Run applicable build, lint, and typecheck checks; scope them when the tooling supports it
392
397
  3. A configured command is not a requirement to run its entire suite. Run the full suite locally only when explicitly required by the user or project instructions, or when broad or uncertain impact cannot be covered adequately by narrower checks
393
- 4. When `commands.test_collect` is configured, compare the count against `.acstack/.test-baseline` if present; investigate removed coverage and honor project baseline requirements
398
+ 4. When `commands.test_collect` is configured, compare the count against `<project folder>/.test-baseline` if present; investigate removed coverage and honor project baseline requirements
394
399
  5. Run configured frontend build, lint, and tests when frontend files changed, and complete applicable design and browser gates
395
400
 
396
401
  Required CI checks must pass before merge, not before opening a PR. Defer broader checks to CI only after confirming it runs them for this change; do not assume CI runs every test.
@@ -419,7 +424,7 @@ Do not claim completion with failed or blocked required checks. Investigate, fix
419
424
 
420
425
  ## Frontend visual verification
421
426
 
422
- **This section applies only when `.acstack/project.yaml` sets `frontend` and `workflow.frontend_verification` is `true`.**
427
+ **This section applies only when `<project folder>/project.yaml` sets `frontend` and `workflow.frontend_verification` is `true`.**
423
428
 
424
429
  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.
425
430
 
@@ -427,7 +432,7 @@ The design pass runs before browser verification when the design gate is on, fol
427
432
 
428
433
  The frontend-verifier agent:
429
434
 
430
- 1. Reads the project's verification knowledge base (`.acstack/verification/VERIFICATION-KNOWLEDGE.md`)
435
+ 1. Reads the project's verification knowledge base (`<project folder>/verification/VERIFICATION-KNOWLEDGE.md`)
431
436
  2. Checks what frontend files changed
432
437
  3. Starts the dev server if it's not running
433
438
  4. Connects to a browser through the Chrome DevTools Protocol (CDP), over a remote tunnel or local headless Chromium
@@ -440,8 +445,8 @@ The frontend-verifier agent:
440
445
 
441
446
  Run `/acstack:setup` to set up browser verification. This creates:
442
447
 
443
- - **`.acstack/agent-browser.json`** – CDP connection config, selected by an absolute `--config` path or `AGENT_BROWSER_CONFIG`
444
- - **`.acstack/verification/VERIFICATION-KNOWLEDGE.md`** – Evolving knowledge base of element patterns, gotchas, and proven verification sequences
448
+ - **`<project folder>/agent-browser.json`** – CDP connection config, selected by an absolute `--config` path or `AGENT_BROWSER_CONFIG`
449
+ - **`<project folder>/verification/VERIFICATION-KNOWLEDGE.md`** – Evolving knowledge base of element patterns, gotchas, and proven verification sequences
445
450
 
446
451
  `frontend.browser.mode` in project.yaml holds the browser environment: remote, headless, or local.
447
452
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acstack",
3
- "version": "0.53.0",
3
+ "version": "0.54.0",
4
4
  "private": false,
5
5
  "description": "Agentic coding stack with first-class Claude Code and pi support: skills, orchestrator instructions, and verification agents.",
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@ You review screenshots. You report results. You do not need user approval.
28
28
 
29
29
  ## Project configuration
30
30
 
31
- Read `.acstack/project.yaml` for frontend settings:
31
+ ACStack keeps project data in the project folder, the path `~/.claude/acstack/bin/acstack project-data path` prints. Read `<project folder>/project.yaml` for frontend settings:
32
32
 
33
33
  - `frontend.directory` – frontend source directory
34
34
  - `frontend.dev_server_url` – dev server URL
@@ -39,14 +39,15 @@ Read `.acstack/project.yaml` for frontend settings:
39
39
 
40
40
  You do not read `frontend.browser.mode` or `frontend.browser.fallback`. Step 3 asks the ACStack CLI which browser mode to use, and the CLI reads both.
41
41
 
42
- If `.acstack/project.yaml` has no `frontend` section, report SKIP and exit.
42
+ If `<project folder>/project.yaml` has no `frontend` section, report SKIP and exit.
43
43
 
44
44
  ## Step 0: Read the knowledge base
45
45
 
46
46
  Before doing anything, check for a knowledge base:
47
47
 
48
48
  ```bash
49
- cat .acstack/verification/VERIFICATION-KNOWLEDGE.md 2>/dev/null
49
+ project="$(~/.claude/acstack/bin/acstack project-data path)"
50
+ cat "$project/verification/VERIFICATION-KNOWLEDGE.md" 2>/dev/null
50
51
  ```
51
52
 
52
53
  This file contains URL patterns, element patterns, gotchas, and lessons learned. Read it if it exists. If not, you'll create it in Step 7.
@@ -205,10 +206,10 @@ Track whether you launched the browser so you can clean it up in Step 8.
205
206
 
206
207
  ## Step 4: Verify with agent-browser
207
208
 
208
- Select the project's browser config explicitly from the project root:
209
+ Select the project's browser config explicitly by its absolute path:
209
210
 
210
211
  ```bash
211
- export AGENT_BROWSER_CONFIG="$(pwd)/.acstack/agent-browser.json"
212
+ export AGENT_BROWSER_CONFIG="$(~/.claude/acstack/bin/acstack project-data path)/agent-browser.json"
212
213
  ```
213
214
 
214
215
  Require the file for configured verification; do not assume root config autodiscovery.
@@ -299,13 +300,13 @@ After every verification run, update the knowledge base if you learned something
299
300
 
300
301
  ### Knowledge base
301
302
 
302
- `.acstack/verification/VERIFICATION-KNOWLEDGE.md` – URL patterns, element patterns, gotchas, lessons learned.
303
+ `<project folder>/verification/VERIFICATION-KNOWLEDGE.md` – URL patterns, element patterns, gotchas, lessons learned.
303
304
 
304
305
  If it doesn't exist, create it with what you learned during this run.
305
306
 
306
307
  ### Rules
307
308
 
308
- - All verification knowledge lives in `.acstack/verification/VERIFICATION-KNOWLEDGE.md`.
309
+ - All verification knowledge lives in `<project folder>/verification/VERIFICATION-KNOWLEDGE.md`.
309
310
  - Do NOT create knowledge files anywhere else.
310
311
  - If a selector or element pattern stops working, update the knowledge base.
311
312
  - If you discover a new pattern, add it.
@@ -19,7 +19,7 @@ You are read-only: do not edit source, tests, or specs.
19
19
  ## Establish scope and ownership
20
20
 
21
21
  Read the supplied requirements, affected paths, known risks, and available command results.
22
- Read `.acstack/project.yaml` for commands, directories, environment activation, and applicable frontend gates.
22
+ Read `project.yaml` in the project folder that `~/.claude/acstack/bin/acstack project-data path` prints for commands, directories, environment activation, and applicable frontend gates.
23
23
 
24
24
  - Distinguish focused review from ownership of completion verification
25
25
  - If the assignment is unclear, clarify it with the delegating session before duplicating checks
@@ -23,7 +23,7 @@ Implement the assigned requirements under the shared Implementation discipline i
23
23
 
24
24
  ## Project configuration
25
25
 
26
- Read `.acstack/project.yaml` for project-specific settings:
26
+ Read `project.yaml` in the project folder that `~/.claude/acstack/bin/acstack project-data path` prints for project-specific settings:
27
27
 
28
28
  - `directories.source` – where to write source code
29
29
  - `directories.tests` – test directory, subject to assigned ownership
@@ -32,7 +32,7 @@ You write tests from requirements and application programming interface (API) co
32
32
 
33
33
  ## Project configuration
34
34
 
35
- Read `.acstack/project.yaml` for project-specific settings:
35
+ Read `project.yaml` in the project folder that `~/.claude/acstack/bin/acstack project-data path` prints for project-specific settings:
36
36
 
37
37
  - `directories.tests` – where to create test files
38
38
  - `directories.source` – source code root (for mirroring structure)