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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +11 -11
- package/agents/codex/frontend-verifier.toml +8 -7
- package/agents/codex/task-checker.toml +1 -1
- package/agents/codex/task-executor.toml +1 -1
- package/agents/codex/test-writer.toml +1 -1
- package/agents/frontend-verifier.md +8 -7
- package/agents/task-checker.md +1 -1
- package/agents/task-executor.md +1 -1
- package/agents/test-writer.md +1 -1
- package/assets/playwriter-bridge/doctor.ps1 +1 -1
- package/assets/playwriter-bridge/register-tasks.ps1 +4 -4
- package/assets/terminal-workspace/config.example.yaml +2 -2
- package/assets/terminal-workspace/helpers/acstack-bridge +3 -1
- package/assets/terminal-workspace/helpers/acstack-db +1 -1
- package/assets/terminal-workspace/helpers/acstack-md +4 -2
- package/assets/terminal-workspace/helpers/acstack-md-lib +2 -2
- package/assets/terminal-workspace/helpers/acstack-open +1 -1
- package/assets/terminal-workspace/lib/apply-herdr-numbers.sh +1 -1
- package/assets/terminal-workspace/lib/apply-tools.sh +1 -1
- package/assets/terminal-workspace/lib/apply-tuicr.sh +2 -2
- package/assets/terminal-workspace/lib/commands.sh +1 -1
- package/assets/terminal-workspace/lib/helper-install.sh +1 -1
- package/assets/terminal-workspace/setup.sh +6 -1
- package/cli/dist/index.js +698 -510
- package/cli/dist/index.js.map +4 -4
- package/cli/package.json +1 -1
- package/docs/config-reference.md +129 -87
- package/docs/dev-setups.md +4 -4
- package/docs/terminal-workspace.md +7 -6
- package/docs/workflows.md +13 -12
- package/examples/design-doc/acstack/README.md +3 -3
- package/examples/design-doc/acstack/journey.md +1 -1
- package/examples/design-doc/acstack/publication.md +1 -1
- package/hooks/context-pressure.sh +6 -2
- package/hooks/lib/read-guard.mjs +25 -21
- package/hooks/project-data.sh +5 -34
- package/hooks/session-start-handoff.sh +11 -22
- package/hooks/session-start.sh +5 -6
- package/orchestrator/AGENTS.md +30 -25
- package/package.json +1 -1
- package/pi/agents/frontend-verifier.md +8 -7
- package/pi/agents/task-checker.md +1 -1
- package/pi/agents/task-executor.md +1 -1
- package/pi/agents/test-writer.md +1 -1
- package/pi/extension.ts +39 -57
- 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 +20 -18
- package/skills/bootstrap/SKILL.md +6 -6
- package/skills/bridge/SKILL-VM.md +5 -5
- package/skills/bridge/SKILL-WINDOWS.md +1 -1
- package/skills/browser-verify/SKILL.md +6 -6
- package/skills/commit/SKILL.md +8 -8
- package/skills/compact-and-continue/SKILL.md +11 -9
- package/skills/design-doc/SKILL.md +8 -5
- package/skills/explore/SKILL.md +1 -1
- package/skills/grilling/SKILL.md +4 -3
- package/skills/handoff/SKILL.md +4 -4
- package/skills/host/SKILL.md +2 -2
- package/skills/host/detect-host.sh +8 -4
- package/skills/host/herdr.md +1 -1
- package/skills/host/install-herdr-block.sh +1 -1
- package/skills/host/notes.md +5 -4
- package/skills/host/questions.md +1 -1
- package/skills/host/report.md +2 -2
- package/skills/implement/SKILL.md +6 -5
- package/skills/implement/decision-log.md +10 -15
- package/skills/implement/design-pass.md +2 -2
- package/skills/map/SKILL.md +5 -3
- package/skills/map/frontend.md +2 -2
- package/skills/map/materialising.md +5 -3
- package/skills/map/trackers/files.md +6 -4
- package/skills/pre-commit-review/SKILL.md +3 -3
- package/skills/quick-fix/SKILL.md +1 -1
- package/skills/record-context/SKILL.md +6 -6
- package/skills/setup/SKILL.md +20 -11
- package/skills/setup/browser.md +2 -2
- package/skills/setup/first-run.md +14 -16
- package/skills/setup/report.md +4 -3
- package/skills/setup/row-fixes.md +7 -8
- package/skills/sync/SKILL.md +14 -12
- package/skills/terminal-workspace/SKILL.md +4 -4
- package/skills/terminal-workspace/headless-clipboard.md +1 -1
- package/skills/terminal-workspace/turn-off-and-update.md +1 -1
- package/skills/test-conventions/SKILL.md +2 -2
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
|
|
17
|
+
* session_compact re-inject <project folder>/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
|
* tool_call block a main agent's first whole read of a large
|
|
@@ -33,51 +33,35 @@ import * as fs from "node:fs";
|
|
|
33
33
|
import * as os from "node:os";
|
|
34
34
|
import * as path from "node:path";
|
|
35
35
|
import { fileURLToPath } from "node:url";
|
|
36
|
-
import {
|
|
36
|
+
import { spawnSync } from "node:child_process";
|
|
37
37
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
38
38
|
// @ts-ignore -- plain ESM shared with hooks/read-guard.mjs, no type declarations
|
|
39
|
-
import { decide, envSaysNotMain } from "../hooks/lib/read-guard.mjs";
|
|
39
|
+
import { decide, envSaysNotMain, readGuardSettings } from "../hooks/lib/read-guard.mjs";
|
|
40
40
|
|
|
41
41
|
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
42
42
|
const troubleshoot = path.join(packageRoot, "TROUBLESHOOTING.md");
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
function projectRoot(cwd: string): string {
|
|
56
|
-
let root = path.resolve(cwd);
|
|
57
|
-
while (true) {
|
|
58
|
-
if (fs.existsSync(path.join(root, ".acstack")) || hasLegacyProjectData(root)) return root;
|
|
59
|
-
const parent = path.dirname(root);
|
|
60
|
-
if (parent === root) break;
|
|
61
|
-
root = parent;
|
|
62
|
-
}
|
|
44
|
+
/**
|
|
45
|
+
* Ask the bundled CLI for this repository's project folder, the way the
|
|
46
|
+
* Claude Code hooks do. Null outside a Git repository, or when the CLI names a
|
|
47
|
+
* fix (legacy data, orphaned entry, conflicting modes); that message and any
|
|
48
|
+
* legacy-data warning reach the user once per cwd.
|
|
49
|
+
*/
|
|
50
|
+
const projectFolders = new Map<string, string | null>();
|
|
51
|
+
function projectFolder(ctx: ExtensionContext | undefined, cwd: string): string | null {
|
|
52
|
+
const key = path.resolve(cwd);
|
|
53
|
+
if (projectFolders.has(key)) return projectFolders.get(key)!;
|
|
54
|
+
let folder: string | null = null;
|
|
63
55
|
try {
|
|
64
|
-
|
|
56
|
+
const result = spawnSync(process.execPath, [path.join(packageRoot, "cli", "bin", "acstack.js"), "project-data", "path"], { cwd: key, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
57
|
+
const message = result.stderr.trim();
|
|
58
|
+
if (message && ctx) report(ctx, message.startsWith("acstack:") ? message : `acstack: ${message}`, result.status === 0 ? "warning" : "error");
|
|
59
|
+
if (result.status === 0) folder = result.stdout.trim() || null;
|
|
65
60
|
} catch {
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function ensureProjectData(ctx: ExtensionContext, root: string): boolean {
|
|
71
|
-
if (hasLegacyProjectData(root)) {
|
|
72
|
-
report(ctx, "acstack: legacy project data found; run ~/.claude/acstack/bin/acstack project-data migrate before using it.", "warning");
|
|
73
|
-
}
|
|
74
|
-
try {
|
|
75
|
-
execFileSync(process.execPath, [path.join(packageRoot, "cli", "bin", "acstack.js"), "project-data", "ensure"], { cwd: root, stdio: ["ignore", "pipe", "pipe"] });
|
|
76
|
-
return !hasLegacyProjectData(root);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
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");
|
|
79
|
-
return false;
|
|
61
|
+
folder = null;
|
|
80
62
|
}
|
|
63
|
+
projectFolders.set(key, folder);
|
|
64
|
+
return folder;
|
|
81
65
|
}
|
|
82
66
|
|
|
83
67
|
/** pi-subagents' background runner sets this in every child process. */
|
|
@@ -349,7 +333,7 @@ function flowList(value: string): string[] {
|
|
|
349
333
|
}
|
|
350
334
|
|
|
351
335
|
/**
|
|
352
|
-
* The workflow.handoff keys from
|
|
336
|
+
* The workflow.handoff keys from <project folder>/project.yaml. A port of read_config
|
|
353
337
|
* in hooks/context-pressure.sh, hand-rolled for the same reason: no YAML
|
|
354
338
|
* library is guaranteed to be installed.
|
|
355
339
|
*/
|
|
@@ -496,12 +480,12 @@ const HANDOFF_PREAMBLE =
|
|
|
496
480
|
"wrong assumption taken after compaction is expensive to unwind.\n\n";
|
|
497
481
|
|
|
498
482
|
/**
|
|
499
|
-
* Consume
|
|
483
|
+
* Consume <project folder>/HANDOFF.md the way hooks/session-start-handoff.sh does:
|
|
500
484
|
* only a file carrying the acstack_handoff marker, moved into a per-map
|
|
501
485
|
* archive so it is never injected twice. Returns the text to inject.
|
|
502
486
|
*/
|
|
503
|
-
export function consumeHandoff(
|
|
504
|
-
const active = path.join(
|
|
487
|
+
export function consumeHandoff(folder: string, now: Date = new Date()): string | undefined {
|
|
488
|
+
const active = path.join(folder, "HANDOFF.md");
|
|
505
489
|
const raw = readText(active);
|
|
506
490
|
if (!raw?.trim()) return undefined;
|
|
507
491
|
|
|
@@ -522,11 +506,11 @@ export function consumeHandoff(cwd: string, now: Date = new Date()): string | un
|
|
|
522
506
|
let stamp = (meta.created || "").replace(/[^A-Za-z0-9._-]/g, "-");
|
|
523
507
|
if (!stamp) stamp = now.toISOString().replace(/\.\d+Z$/, "Z").replace(/:/g, "-");
|
|
524
508
|
|
|
525
|
-
const changeDir = path.join(
|
|
509
|
+
const changeDir = path.join(folder, "changes", map);
|
|
526
510
|
const archiveDir =
|
|
527
511
|
map !== "ad-hoc" && fs.existsSync(changeDir)
|
|
528
512
|
? path.join(changeDir, "handoffs")
|
|
529
|
-
: path.join(
|
|
513
|
+
: path.join(folder, "handoffs", map);
|
|
530
514
|
try {
|
|
531
515
|
fs.mkdirSync(archiveDir, { recursive: true });
|
|
532
516
|
let dest = path.join(archiveDir, `${stamp}.md`);
|
|
@@ -664,18 +648,16 @@ export default function acstack(pi: ExtensionAPI): void {
|
|
|
664
648
|
|
|
665
649
|
const orchestratorFile = path.join(packageRoot, "orchestrator", "AGENTS.md");
|
|
666
650
|
const styleFile = path.join(packageRoot, "output-styles", "ac-writing-style.md");
|
|
667
|
-
const
|
|
668
|
-
|
|
651
|
+
const isProject = (cwd: string) => {
|
|
652
|
+
const folder = projectFolder(undefined, cwd);
|
|
653
|
+
return folder !== null && fs.existsSync(path.join(folder, "project.yaml"));
|
|
654
|
+
};
|
|
669
655
|
let warnedSubagents = false;
|
|
670
656
|
|
|
671
657
|
pi.on("session_start", async (event, ctx) => {
|
|
672
658
|
if (!delegated) linkClis(ctx);
|
|
673
|
-
|
|
674
|
-
if (
|
|
675
|
-
else {
|
|
676
|
-
unsafeProjects.add(root);
|
|
677
|
-
return;
|
|
678
|
-
}
|
|
659
|
+
projectFolders.delete(path.resolve(ctx.cwd));
|
|
660
|
+
if (projectFolder(ctx, ctx.cwd) === null) return;
|
|
679
661
|
|
|
680
662
|
if (delegated) return;
|
|
681
663
|
if (!warnedSubagents && !pi.getAllTools().some((tool) => tool.name === "subagent" || tool.name === "Agent" || tool.name === "team_agent")) {
|
|
@@ -705,7 +687,7 @@ export default function acstack(pi: ExtensionAPI): void {
|
|
|
705
687
|
|
|
706
688
|
if (isProject(ctx.cwd)) {
|
|
707
689
|
const orchestrator = readText(orchestratorFile);
|
|
708
|
-
if (orchestrator) sections["acstack-orchestrator"] = orchestratorFor(orchestrator, delegated ? "delegated" : "lead")
|
|
690
|
+
if (orchestrator) sections["acstack-orchestrator"] = `${orchestratorFor(orchestrator, delegated ? "delegated" : "lead")}\n\nThis repository's ACStack project folder: ${projectFolder(undefined, ctx.cwd)}\n`;
|
|
709
691
|
else report(ctx, `acstack: could not read ${orchestratorFile}`, "warning");
|
|
710
692
|
}
|
|
711
693
|
|
|
@@ -742,7 +724,7 @@ export default function acstack(pi: ExtensionAPI): void {
|
|
|
742
724
|
const lastText = readText(lastFile)?.trim();
|
|
743
725
|
const lastRung = lastText && /^\d+$/.test(lastText) ? Number.parseInt(lastText, 10) : undefined;
|
|
744
726
|
|
|
745
|
-
const cfg = readHandoffConfig(readText(path.join(
|
|
727
|
+
const cfg = readHandoffConfig(readText(path.join(projectFolder(undefined, ctx.cwd) ?? "/nonexistent", "project.yaml")));
|
|
746
728
|
const nudge = contextNudge(usage.tokens, usage.contextWindow, cfg, lastRung, process.env.HERDR_ENV === "1");
|
|
747
729
|
if (!nudge) return;
|
|
748
730
|
|
|
@@ -773,9 +755,9 @@ export default function acstack(pi: ExtensionAPI): void {
|
|
|
773
755
|
}
|
|
774
756
|
}
|
|
775
757
|
|
|
776
|
-
const
|
|
777
|
-
if (
|
|
778
|
-
const handoff = consumeHandoff(
|
|
758
|
+
const folder = projectFolder(ctx, ctx.cwd);
|
|
759
|
+
if (folder === null) return;
|
|
760
|
+
const handoff = consumeHandoff(folder);
|
|
779
761
|
if (handoff) {
|
|
780
762
|
pi.sendMessage({ customType: "acstack-handoff", content: handoff, display: true }, { deliverAs: "nextTurn" });
|
|
781
763
|
}
|
|
@@ -795,7 +777,7 @@ export default function acstack(pi: ExtensionAPI): void {
|
|
|
795
777
|
if (!main) return;
|
|
796
778
|
let ledger = readLedgers.get(sessionId);
|
|
797
779
|
if (!ledger) readLedgers.set(sessionId, (ledger = new Set()));
|
|
798
|
-
const result = decide({ toolName: event.toolName, toolInput: event.input, cwd: ctx.cwd, main, ledger });
|
|
780
|
+
const result = decide({ toolName: event.toolName, toolInput: event.input, cwd: ctx.cwd, main, ledger, settings: readGuardSettings(ctx.cwd, projectFolder(ctx, ctx.cwd)) });
|
|
799
781
|
if (result.block) return { block: true, reason: result.message };
|
|
800
782
|
});
|
|
801
783
|
|
package/profiles/python.yaml
CHANGED
package/skills/archive/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: archive
|
|
3
|
-
description: Close out a cleared map – one whose frontier is empty with no fog and no claims left – by verifying the durable residue, meaning what the effort leaves behind in living specs, ADRs and the glossary, was extracted, then closing the root and disposing of the nodes per workflow.maps.persist. Invoke when a map has just been cleared, when the last node on a map resolves, or when the user asks to archive or close out a map. Refuses and asks first if anything is still open. Also archives legacy
|
|
3
|
+
description: Close out a cleared map – one whose frontier is empty with no fog and no claims left – by verifying the durable residue, meaning what the effort leaves behind in living specs, ADRs and the glossary, was extracted, then closing the root and disposing of the nodes per workflow.maps.persist. Invoke when a map has just been cleared, when the last node on a map resolves, or when the user asks to archive or close out a map. Refuses and asks first if anything is still open. Also archives legacy changes/ directories from the pre-map workflow.
|
|
4
4
|
argument-hint: "[map or legacy change name]"
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -18,12 +18,15 @@ Archive verifies implemented specs, durable decisions, and retained review evide
|
|
|
18
18
|
|
|
19
19
|
## Step 1: Locate the map
|
|
20
20
|
|
|
21
|
+
ACStack keeps project data in the project folder, the path
|
|
22
|
+
`~/.claude/acstack/bin/acstack project-data path` prints.
|
|
23
|
+
|
|
21
24
|
If `$ARGUMENTS` names a map, use it. Otherwise list maps on the configured
|
|
22
|
-
tracker (`workflow.maps.tracker`): `ls
|
|
25
|
+
tracker (`workflow.maps.tracker`): `ls "$(~/.claude/acstack/bin/acstack project-data path)/maps/"` on the files backend,
|
|
23
26
|
`gh label list --search "map:" --json name` on GitHub.
|
|
24
27
|
|
|
25
28
|
If exactly one, use it. If several, ask. If `$ARGUMENTS` names a legacy
|
|
26
|
-
|
|
29
|
+
`<project folder>/changes/` directory instead, jump to Legacy below.
|
|
27
30
|
|
|
28
31
|
## Step 2: Verify no open work remains
|
|
29
32
|
|
|
@@ -83,7 +86,7 @@ On GitHub, compose the walk per `trackers/github.md`.
|
|
|
83
86
|
Check each resolution left what it should have:
|
|
84
87
|
|
|
85
88
|
1. **Living specs** – behaviour the effort built should already be in
|
|
86
|
-
|
|
89
|
+
`<project folder>/specs/` via commit-time sync. Spot-check the affected domains.
|
|
87
90
|
|
|
88
91
|
Verify against source and verification evidence, not proposals copied from map nodes.
|
|
89
92
|
Fix gaps on sight per the Spec Correction Protocol.
|
|
@@ -98,9 +101,8 @@ Check each resolution left what it should have:
|
|
|
98
101
|
Preserve enough context to trace implemented behavior back to its decisions without retaining proposals as requirements.
|
|
99
102
|
Stop if unresolved scope still needs a decision rather than an explicit out-of-scope resolution.
|
|
100
103
|
|
|
101
|
-
4. **The decision log** – read `<
|
|
102
|
-
if it exists.
|
|
103
|
-
--path-format=absolute --git-common-dir`.
|
|
104
|
+
4. **The decision log** – read `<project folder>/decision-logs/<name>.tsv`
|
|
105
|
+
if it exists.
|
|
104
106
|
|
|
105
107
|
afk runs append one row per decision an agent made alone. Hand each
|
|
106
108
|
lasting decision to `record-context`. A later row supersedes an earlier
|
|
@@ -130,12 +132,12 @@ If you reached this skill on your own after a map cleared, name what you
|
|
|
130
132
|
will delete or move. Then wait for the user's go-ahead. Deletion is
|
|
131
133
|
irreversible and they never asked for it.
|
|
132
134
|
|
|
133
|
-
`workflow.maps.persist` in
|
|
135
|
+
`workflow.maps.persist` in `<project folder>/project.yaml` decides (default `false`):
|
|
134
136
|
|
|
135
137
|
| Value | Action |
|
|
136
138
|
| ----------------- | ------------------------------------------------------------ |
|
|
137
|
-
| `false` (default) | delete
|
|
138
|
-
| `true` | move the nodes to
|
|
139
|
+
| `false` (default) | delete `<project folder>/maps/<name>/` |
|
|
140
|
+
| `true` | move the nodes to `<project folder>/archive/[YYYY-MM-DD]-[name]/nodes/` |
|
|
139
141
|
|
|
140
142
|
Default is delete because keeping the nodes leaves a second copy of every
|
|
141
143
|
decision, and the two drift. On the GitHub tracker there is nothing to
|
|
@@ -145,15 +147,15 @@ Retain these records independently of `workflow.maps.persist`:
|
|
|
145
147
|
|
|
146
148
|
- Authored design entries and referenced source files
|
|
147
149
|
- Canonical `review.json` files, posted feedback, reconciliation, and exact-revision approval evidence
|
|
148
|
-
- Imported legacy history and original
|
|
149
|
-
-
|
|
150
|
+
- Imported legacy history and original `<project folder>/alignment-packs/` artifacts
|
|
151
|
+
- `<project folder>/decision-logs/<name>.tsv` files
|
|
150
152
|
- Handoffs that contain review evidence or provenance not retained elsewhere
|
|
151
153
|
|
|
152
154
|
Never recursively delete alignment, review, decision-log, or handoff directories as archive cleanup.
|
|
153
155
|
Do not invoke a cleanup helper that erases those records.
|
|
154
156
|
|
|
155
157
|
If a retained source or review record sits inside the proposed node disposal path, stop and resolve its safe retention first.
|
|
156
|
-
|
|
158
|
+
Never change the Git index or force-add records to commit them.
|
|
157
159
|
|
|
158
160
|
## Step 6: Report
|
|
159
161
|
|
|
@@ -162,19 +164,19 @@ Respect native Git ignore rules; never force-add private records.
|
|
|
162
164
|
- Disposal: node deletion or archive path, plus retained review evidence and provenance
|
|
163
165
|
- Reminder: commit with `/acstack:commit`
|
|
164
166
|
|
|
165
|
-
## Legacy: archiving a
|
|
167
|
+
## Legacy: archiving a `<project folder>/changes/` directory
|
|
166
168
|
|
|
167
169
|
The pre-map workflow created changes that hold proposal.md, design.md and
|
|
168
170
|
tasks.md. They still archive the old way, so an upgrade never strands work:
|
|
169
171
|
|
|
170
172
|
1. Read the change's artifacts. Derive the affected domains from the file
|
|
171
|
-
paths in `tasks.md` via
|
|
173
|
+
paths in `tasks.md` via `<project folder>/domain-map.yaml`.
|
|
172
174
|
|
|
173
175
|
2. For each domain, merge what the feature ADDED, MODIFIED or REMOVED into
|
|
174
|
-
|
|
176
|
+
`<project folder>/specs/[domain]/spec.md`.
|
|
175
177
|
|
|
176
178
|
3. Write a `delta.md` into the change directory.
|
|
177
179
|
|
|
178
180
|
Then run the CLI's `acstack archive <name>`. It moves the artifacts,
|
|
179
|
-
delta included, to
|
|
180
|
-
It also removes the change from
|
|
181
|
+
delta included, to `<project folder>/changes/archive/[YYYY-MM-DD]-[change-name]/`.
|
|
182
|
+
It also removes the change from `<project folder>/changes/`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bootstrap
|
|
3
|
-
description: Multi-pass AI crawl to generate initial living specs from the existing codebase. Use when
|
|
3
|
+
description: Multi-pass AI crawl to generate initial living specs from the existing codebase. Use when the project folder's specs/ domains need their initial spec.md files bootstrapped from code.
|
|
4
4
|
argument-hint: "[domain-names (optional)]"
|
|
5
5
|
disable-model-invocation: true
|
|
6
6
|
---
|
|
@@ -15,9 +15,9 @@ Consider the user input before you proceed, if it is not empty.
|
|
|
15
15
|
|
|
16
16
|
## Purpose
|
|
17
17
|
|
|
18
|
-
This skill bootstraps cumulative living specs in
|
|
18
|
+
This skill bootstraps cumulative living specs in `<project folder>/specs/`. The project folder is the path `~/.claude/acstack/bin/acstack project-data path` prints; pass its absolute path to every subagent that reads or writes specs. It crawls the existing codebase with multiple independent AI passes. It then merges the passes and validates the results.
|
|
19
19
|
|
|
20
|
-
**IMPORTANT**: This is a one-time bootstrapping operation. Only run when
|
|
20
|
+
**IMPORTANT**: This is a one-time bootstrapping operation. Only run when `<project folder>/specs/` domains have no `spec.md` files yet.
|
|
21
21
|
|
|
22
22
|
## Your role: orchestrator only
|
|
23
23
|
|
|
@@ -33,9 +33,9 @@ Your job is to:
|
|
|
33
33
|
|
|
34
34
|
## Pre-flight check
|
|
35
35
|
|
|
36
|
-
1. Read
|
|
36
|
+
1. Read `<project folder>/domain-map.yaml` to get the list of domains and their file path mappings.
|
|
37
37
|
2. If `$ARGUMENTS` specifies domain names, filter to only those domains.
|
|
38
|
-
3. Check if any
|
|
38
|
+
3. Check if any `<project folder>/specs/*/spec.md` files already exist:
|
|
39
39
|
- If specs exist, warn the user. Ask for confirmation before overwriting.
|
|
40
40
|
- If no specs exist, proceed automatically.
|
|
41
41
|
|
|
@@ -98,7 +98,7 @@ Launch a single subagent to apply validated corrections from Phase 3.
|
|
|
98
98
|
|
|
99
99
|
## Phase 5: human review (pass 9)
|
|
100
100
|
|
|
101
|
-
Present a summary to the user. Ask: "Review the specs in
|
|
101
|
+
Present a summary to the user. Ask: "Review the specs in `<project folder>/specs/`. Want to edit any domain before finalizing?"
|
|
102
102
|
|
|
103
103
|
## Phase 6: finalization (pass 10)
|
|
104
104
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
binds `127.0.0.1:19988` on this host.
|
|
11
11
|
|
|
12
12
|
- `agent-browser` (installed per the `browser-verify` skill) pointed at
|
|
13
|
-
that endpoint via
|
|
13
|
+
that endpoint via `agent-browser.json` in the project folder.
|
|
14
14
|
|
|
15
15
|
- `vm-free-port.sh` for clearing a stuck port 19988 after a dropped
|
|
16
16
|
session.
|
|
@@ -42,17 +42,17 @@ and is driving a real Chrome on the laptop.
|
|
|
42
42
|
|
|
43
43
|
See the `browser-verify` skill for the install command.
|
|
44
44
|
|
|
45
|
-
### 2. Create
|
|
45
|
+
### 2. Create `agent-browser.json` in each configured project's folder
|
|
46
46
|
|
|
47
47
|
```json
|
|
48
48
|
{ "cdp": "19988" }
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
Select the config explicitly
|
|
51
|
+
The project folder is the path `~/.claude/acstack/bin/acstack project-data path` prints from the repository.
|
|
52
|
+
Select the config explicitly before browser commands:
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
export AGENT_BROWSER_CONFIG="$(
|
|
55
|
+
export AGENT_BROWSER_CONFIG="$(~/.claude/acstack/bin/acstack project-data path)/agent-browser.json"
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
For manual CDP checks without project configuration, use `agent-browser --cdp 19988 ...` instead; do not pass a missing config.
|
|
@@ -299,7 +299,7 @@ Two tasks run it:
|
|
|
299
299
|
Every request from a VM carries a shared secret called the opener token.
|
|
300
300
|
`register-tasks.ps1` generates it and stores it at
|
|
301
301
|
`%LOCALAPPDATA%\playwriter-bridge\opener.token`. It then pushes the token over
|
|
302
|
-
`ssh` to `~/.
|
|
302
|
+
`ssh` to `~/.acstack/opener.token` on each VM.
|
|
303
303
|
|
|
304
304
|
The token is not optional. The reverse tunnel makes 19989 reachable by
|
|
305
305
|
anything running on the VM, and this service puts pages on your screen.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: browser-verify
|
|
3
|
-
description: How to interact with a browser for frontend verification using agent-browser CLI and CDP. ALWAYS use when UI or frontend files are modified and workflow.frontend_verification is true in
|
|
3
|
+
description: How to interact with a browser for frontend verification using agent-browser CLI and CDP. ALWAYS use when UI or frontend files are modified and workflow.frontend_verification is true in the project's project.yaml. Also use before running agent-browser commands, when element refs go stale, when CDP connection fails, or when verifying UI behavior. Covers all commands (snapshot, screenshot, click, fill, type), element ref strategy, DOM staleness rules, selector priority, and remote/headless/local environment troubleshooting.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Browser helpers
|
|
@@ -13,7 +13,7 @@ For setup (installing agent-browser, creating config files, scaffolding knowledg
|
|
|
13
13
|
|
|
14
14
|
## Project configuration
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
ACStack keeps project data in the project folder, the path `~/.claude/acstack/bin/acstack project-data path` prints. Read `<project folder>/project.yaml` for:
|
|
17
17
|
|
|
18
18
|
- `frontend.directory` – frontend source directory
|
|
19
19
|
- `frontend.dev_server_url` – dev server URL
|
|
@@ -52,7 +52,7 @@ Without `--json` it prints the same two facts on one line: the mode, then the re
|
|
|
52
52
|
|
|
53
53
|
### How it decides
|
|
54
54
|
|
|
55
|
-
The host declares which modes this machine can provide. It does so on three axes in the global config at `~/.
|
|
55
|
+
The host declares which modes this machine can provide. It does so on three axes in the global config at `~/.acstack/config.json` (`$ACSTACK_HOME/config.json` when that variable is set):
|
|
56
56
|
|
|
57
57
|
- `host.browser.remote` – this machine can reach a browser on another machine
|
|
58
58
|
- `host.browser.headless` – this machine can launch headless Chromium
|
|
@@ -181,13 +181,13 @@ Omit `--headless` to see the browser. Useful during development.
|
|
|
181
181
|
|
|
182
182
|
## agent-browser command reference
|
|
183
183
|
|
|
184
|
-
For configured verification, explicitly select the absolute
|
|
184
|
+
For configured verification, explicitly select the absolute `<project folder>/agent-browser.json` path before running the commands below:
|
|
185
185
|
|
|
186
186
|
```bash
|
|
187
|
-
export AGENT_BROWSER_CONFIG="$(
|
|
187
|
+
export AGENT_BROWSER_CONFIG="$(~/.claude/acstack/bin/acstack project-data path)/agent-browser.json"
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
-
- Run this
|
|
190
|
+
- Run this only when the file exists; alternatively pass `--config` with the same absolute path
|
|
191
191
|
- Do not rely on root config autodiscovery
|
|
192
192
|
- Manual CDP quality checks remain available without project configuration or a configured browser mode
|
|
193
193
|
- For those checks, omit the missing config and use `agent-browser --cdp <port> ...` with the explicitly chosen endpoint
|
package/skills/commit/SKILL.md
CHANGED
|
@@ -45,25 +45,25 @@ For each planned commit:
|
|
|
45
45
|
|
|
46
46
|
**This step is non-negotiable.** After drafting the commit message but BEFORE creating the commit, spec sync runs automatically.
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
The project folder is the path `~/.claude/acstack/bin/acstack project-data path` prints. Read `<project folder>/project.yaml` – if `workflow.spec_sync` is `true` (or not explicitly `false`), run spec sync:
|
|
49
49
|
|
|
50
|
-
1. Read
|
|
50
|
+
1. Read `<project folder>/domain-map.yaml` (if exists)
|
|
51
51
|
2. Map staged files to spec domains
|
|
52
|
-
3. For each affected domain where
|
|
52
|
+
3. For each affected domain where `<project folder>/specs/[domain]/spec.md` exists:
|
|
53
53
|
- Analyze what the staged changes add, modify, or remove
|
|
54
54
|
- Generate lightweight ADDED/MODIFIED/REMOVED entries
|
|
55
55
|
- Update the domain's spec.md
|
|
56
56
|
4. Refresh `DESIGN.md`, per Step 2 of the `sync` skill
|
|
57
|
-
5. Stage updated specs only when
|
|
58
|
-
-
|
|
57
|
+
5. Stage updated specs only when they sit inside the current working tree
|
|
58
|
+
- That happens only in tracked mode, when you commit in the main checkout
|
|
59
|
+
- Otherwise the specs stay updated in the project folder and out of the commit
|
|
59
60
|
- Stage `DESIGN.md` and `.impeccable/design.json` too when the refresh ran
|
|
60
|
-
6.
|
|
61
|
-
7. Flag unmapped source files and prompt user to map them
|
|
61
|
+
6. Flag unmapped source files and prompt user to map them
|
|
62
62
|
|
|
63
63
|
**Skip spec sync ONLY when:**
|
|
64
64
|
|
|
65
65
|
- `workflow.spec_sync` is explicitly `false` in project.yaml
|
|
66
|
-
- No
|
|
66
|
+
- No `<project folder>/domain-map.yaml` exists
|
|
67
67
|
- Changed files don't match any domain
|
|
68
68
|
- Changes are docs/config only (no behavioral changes)
|
|
69
69
|
- No spec.md exists for affected domains (don't create from scratch here)
|
|
@@ -55,7 +55,8 @@ instead – in your final message, or through your host's agent-messaging tool
|
|
|
55
55
|
or compacts.
|
|
56
56
|
|
|
57
57
|
A child session would write the lead's quiet marker and the shared
|
|
58
|
-
|
|
58
|
+
`<project folder>/HANDOFF.md` anchor, where the project folder is the path
|
|
59
|
+
`~/.claude/acstack/bin/acstack project-data path` prints. Both belong to the lead alone.
|
|
59
60
|
|
|
60
61
|
Five facts sit behind that command, measured on Claude Code 2.1.241. Each one
|
|
61
62
|
names a way the command has already been got wrong:
|
|
@@ -99,8 +100,8 @@ something by running a command, it should run the command.
|
|
|
99
100
|
| Map state and reading order | `~/.claude/acstack/bin/acstack node walk --map <name>` (reading order of the map) |
|
|
100
101
|
| What can be worked next | `~/.claude/acstack/bin/acstack node frontier --map <name>` (what is workable now) |
|
|
101
102
|
| Files in flight | `git status --short` and `git diff` |
|
|
102
|
-
| Test baseline, last result |
|
|
103
|
-
| What the code does | the living specs in
|
|
103
|
+
| Test baseline, last result | `<project folder>/.test-baseline` and referenced check logs; reuse valid evidence under the shared policy |
|
|
104
|
+
| What the code does | the living specs in `<project folder>/specs/` |
|
|
104
105
|
|
|
105
106
|
On GitHub, `--map` refuses – pipe `gh issue list` into `--stdin` per the
|
|
106
107
|
map skill's `trackers/github.md`.
|
|
@@ -143,7 +144,7 @@ not optional.
|
|
|
143
144
|
|
|
144
145
|
## Write the anchor
|
|
145
146
|
|
|
146
|
-
Write
|
|
147
|
+
Write `"$(~/.claude/acstack/bin/acstack project-data path)/HANDOFF.md"`. The frontmatter is **mandatory and machine-read**.
|
|
147
148
|
The hook ignores any file without the marker, so it never touches a user's own
|
|
148
149
|
unrelated `HANDOFF.md`.
|
|
149
150
|
|
|
@@ -218,9 +219,10 @@ note.
|
|
|
218
219
|
Tell them to run that `/compact` line, then to type `continue`. The hook
|
|
219
220
|
re-injects the anchor and retires it, so the anchor never loads twice.
|
|
220
221
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
222
|
+
`<project folder>/HANDOFF.md` holds conversation content. In global mode, the
|
|
223
|
+
default, it sits outside the repository. In tracked mode it sits in the main
|
|
224
|
+
checkout's committed `.acstack/`, so warn the user not to commit the anchor or
|
|
225
|
+
consumed handoffs.
|
|
224
226
|
|
|
225
227
|
## Notes
|
|
226
228
|
|
|
@@ -232,8 +234,8 @@ Warn if user exceptions expose the anchor or consumed handoffs to tracking.
|
|
|
232
234
|
skill moves the work to a genuinely new session
|
|
233
235
|
|
|
234
236
|
- **Consume-once.** The hook retires the anchor as it injects it, moving it to
|
|
235
|
-
|
|
236
|
-
|
|
237
|
+
`<project folder>/handoffs/<map>/<created>.md` (legacy
|
|
238
|
+
`<project folder>/changes/<name>/handoffs/` when that directory still exists).
|
|
237
239
|
Collisions get a `-2` suffix
|
|
238
240
|
|
|
239
241
|
- **Subagents and teammates have isolated context.** This protects the
|
|
@@ -34,7 +34,8 @@ flowchart LR
|
|
|
34
34
|
|
|
35
35
|
## Author entry and element files
|
|
36
36
|
|
|
37
|
-
- Default new project designs to
|
|
37
|
+
- Default new project designs to `<project folder>/designs/<id>/design.yaml`, unless the user chooses another location
|
|
38
|
+
- The project folder is the path `~/.claude/acstack/bin/acstack project-data path` prints
|
|
38
39
|
- Keep the entry and its referenced files in one directory tree
|
|
39
40
|
- Use stable IDs matching `[a-zA-Z][a-zA-Z0-9_-]{0,79}`
|
|
40
41
|
- Give the entry `id`, `name`, `summary`, and an `elements` array of relative YAML paths
|
|
@@ -172,7 +173,9 @@ relationships:
|
|
|
172
173
|
## Reconcile and approve a map-linked design
|
|
173
174
|
|
|
174
175
|
- Invoke this workflow from map for shared behavior, component boundaries, or data-flow decisions
|
|
175
|
-
- Store `Design entry: <
|
|
176
|
+
- Store `Design entry: <path>` in the map root body
|
|
177
|
+
- Write the path relative to the project folder, such as `designs/<id>/design.yaml`, or relative to the repository for a design kept in the repository
|
|
178
|
+
- ACStack resolves it against the project folder first, then the current checkout
|
|
176
179
|
- Add `planning: {tracker: files | github, map: <name>}` to the entry
|
|
177
180
|
- Use the same contribution format in files and GitHub node bodies
|
|
178
181
|
- Put one fenced JSON array under `## Design contributions`
|
|
@@ -213,7 +216,7 @@ relationships:
|
|
|
213
216
|
- ACStack removes `map --map` and `align-viewer` without aliases
|
|
214
217
|
- Author the new design first; the old planning graph cannot define its architecture
|
|
215
218
|
- Keep map planning in `node walk`, `node frontier`, and `node diagram`
|
|
216
|
-
- Use a nonsymlink legacy directory under
|
|
219
|
+
- Use a nonsymlink legacy directory under `<project folder>/alignment-packs/`
|
|
217
220
|
- Write an explicit JSON mapping array of `{from: {type, id}, to: {type, id}}` pairs
|
|
218
221
|
- Map every commented legacy target to a valid current target
|
|
219
222
|
- Choose document context explicitly when a legacy target is ambiguous
|
|
@@ -224,7 +227,7 @@ relationships:
|
|
|
224
227
|
```
|
|
225
228
|
|
|
226
229
|
- Supply `--feedback` only for an explicit exported feedback JSON file
|
|
227
|
-
- Migration reads saved pack versions, approvals, annotations, and the corresponding
|
|
230
|
+
- Migration reads saved pack versions, approvals, annotations, and the corresponding decision log in the project folder
|
|
228
231
|
- Migration preserves original artifacts and decision logs byte-for-byte
|
|
229
232
|
- Canonical `review.json` retains imported history, source fingerprints, and original comments, quotes, authors, timestamps, and provenance
|
|
230
233
|
- Imported comments append to existing feedback; duplicate source comments import once
|
|
@@ -235,4 +238,4 @@ relationships:
|
|
|
235
238
|
- Reconcile imported feedback and obtain current exact-revision approval before implementation or archive
|
|
236
239
|
- Never migrate automatically at startup or archive
|
|
237
240
|
- Retain design sources, canonical reviews, import history, and decision logs independently of `workflow.maps.persist`
|
|
238
|
-
-
|
|
241
|
+
- Never change the Git index or force-add review records
|
package/skills/explore/SKILL.md
CHANGED
|
@@ -92,7 +92,7 @@ You have full context of the ACStack system. Use it naturally, don't force it.
|
|
|
92
92
|
### Check for context
|
|
93
93
|
|
|
94
94
|
At the start, quickly check what exists – maps on the configured tracker
|
|
95
|
-
(`ls
|
|
95
|
+
(`ls "$(~/.claude/acstack/bin/acstack project-data path)/maps/"` on the files backend) and living specs
|
|
96
96
|
(`~/.claude/acstack/bin/acstack list --specs --json`).
|
|
97
97
|
|
|
98
98
|
### When no map exists
|
package/skills/grilling/SKILL.md
CHANGED
|
@@ -65,7 +65,8 @@ session.
|
|
|
65
65
|
|
|
66
66
|
## Presentation
|
|
67
67
|
|
|
68
|
-
`workflow.grilling.questions` in
|
|
68
|
+
`workflow.grilling.questions` in `<project folder>/project.yaml` picks the mode.
|
|
69
|
+
The project folder is the path `~/.claude/acstack/bin/acstack project-data path` prints.
|
|
69
70
|
|
|
70
71
|
| Value | Behaviour |
|
|
71
72
|
| ---------------- | ------------------------------------------------------------------------------------ |
|
|
@@ -127,8 +128,8 @@ belong in git:
|
|
|
127
128
|
```markdown
|
|
128
129
|
## Answer
|
|
129
130
|
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
On the files backend, map nodes live under `<project folder>/maps/`.
|
|
132
|
+
In global mode, the default, that folder sits outside the repository, so nodes are never committed.
|
|
132
133
|
|
|
133
134
|
The durable output is the living specs, the architecture decision records and
|
|
134
135
|
the glossary. The `record-context` skill extracts each one as a node
|