acstack 0.48.0 → 0.48.2
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/assets/terminal-workspace/config.example.yaml +16 -2
- package/assets/terminal-workspace/setup.sh +283 -6
- package/cli/package.json +1 -1
- package/docs/workflows.md +1 -1
- package/orchestrator/AGENTS.md +2 -2
- package/package.json +1 -1
- package/skills/bootstrap/SKILL.md +2 -2
- package/skills/grilling/SKILL.md +7 -5
- package/skills/implement/SKILL.md +8 -5
- package/skills/map/SKILL.md +2 -2
- package/skills/pre-commit-review/SKILL.md +4 -2
- package/skills/quick-fix/SKILL.md +1 -1
- package/skills/setup/row-fixes.md +5 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "acstack",
|
|
3
3
|
"description": "Agentic coding stack where planning grows only as far as needed: a map of decisions, tasks, checks, and handoffs behind a pluggable tracker.",
|
|
4
|
-
"version": "0.48.
|
|
4
|
+
"version": "0.48.2",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "ac8318740"
|
|
7
7
|
},
|
|
@@ -236,6 +236,19 @@ pi:
|
|
|
236
236
|
# retro. Needs the agentic-retro plugin installed first, and apply says so
|
|
237
237
|
# when it is not.
|
|
238
238
|
agentic_retro: true
|
|
239
|
+
# Zentui supplies the accent-rail editor and Starship footer. The footer
|
|
240
|
+
# format keeps model/provider/thinking visible on the right, including in
|
|
241
|
+
# compact mode.
|
|
242
|
+
zentui: true
|
|
243
|
+
# Hide pi-lens's LSP status footer and diagnostics widget rows.
|
|
244
|
+
hide_lens_lsp_status: true
|
|
245
|
+
# Extra pi-lens tools installed onto PATH for ecosystems used across repos.
|
|
246
|
+
# These are machine-wide, not project dependencies.
|
|
247
|
+
lens_extra_tools:
|
|
248
|
+
python: true # black, mypy, pyright
|
|
249
|
+
docker: true # hadolint, Dockerfile language server
|
|
250
|
+
github_actions: true # actionlint, zizmor
|
|
251
|
+
terraform: true # terraform-ls, tflint, terragrunt
|
|
239
252
|
# Written into ~/.pi/agent/settings.json. Empty leaves pi's own value alone.
|
|
240
253
|
# Every other key in that file stays as you set it, and disable puts back
|
|
241
254
|
# any value of yours that apply replaced.
|
|
@@ -247,8 +260,9 @@ pi:
|
|
|
247
260
|
mermaid: streaming
|
|
248
261
|
# pi's anonymous install and update reporting. Kept off by this setup.
|
|
249
262
|
install_telemetry: false
|
|
250
|
-
# A pi theme name.
|
|
251
|
-
|
|
263
|
+
# A pi theme name. alex-mid-grey is written by this setup and shades
|
|
264
|
+
# user messages.
|
|
265
|
+
theme: alex-mid-grey
|
|
252
266
|
|
|
253
267
|
neovim:
|
|
254
268
|
# The one component that is off by default, because it writes into a neovim
|
|
@@ -38,7 +38,13 @@ PI_SUBAGENT_CFG="$PI_DIR/extensions/subagent/config.json"
|
|
|
38
38
|
PI_RETRO_EXT="${PI_HOME:-$HOME/.pi}/agent/extensions/agentic-retro.ts"
|
|
39
39
|
PI_ACSTACK="npm:acstack"
|
|
40
40
|
PI_BILLION="npm:billion-context"
|
|
41
|
+
BILLION_CONFIG="$HOME/.config/billion-context/billion-context.json"
|
|
41
42
|
PI_SLASH_ANYWHERE="npm:pi-slash-anywhere"
|
|
43
|
+
PI_ZENTUI="npm:pi-zentui"
|
|
44
|
+
PI_ZENTUI_CFG="$PI_DIR/zentui.json"
|
|
45
|
+
PI_THEME_DIR="$PI_DIR/themes"
|
|
46
|
+
PI_THEME="$PI_THEME_DIR/alex-mid-grey.json"
|
|
47
|
+
PI_LENS_CFG="$HOME/.pi-lens/config.json"
|
|
42
48
|
# A line starting with # is a heading in markdown, and the model reads it. An
|
|
43
49
|
# HTML comment carries the same marker and renders as nothing.
|
|
44
50
|
PI_MD_BEGIN="<!-- >>> acstack terminal-workspace >>> -->"
|
|
@@ -180,6 +186,57 @@ PY
|
|
|
180
186
|
say "$name installed to $BIN/$name"
|
|
181
187
|
}
|
|
182
188
|
|
|
189
|
+
install_plain_github_binary() { # install_plain_github_binary <name> <repo> <asset-match>
|
|
190
|
+
local name="$1" repo="$2" match="$3"
|
|
191
|
+
if [ "${INSTALL_FORCE:-0}" != "1" ] && have "$name"; then
|
|
192
|
+
say "$name already installed"; return 0
|
|
193
|
+
fi
|
|
194
|
+
local json url tmp
|
|
195
|
+
json=$(curl -sSf "https://api.github.com/repos/$repo/releases/latest" 2>/dev/null)
|
|
196
|
+
[ -z "$json" ] && { say "$name: could not reach the GitHub release API"; return 1; }
|
|
197
|
+
url=$(MAPFLOW_JSON="$json" py "$match" <<'PY'
|
|
198
|
+
import json, os, sys
|
|
199
|
+
try:
|
|
200
|
+
d = json.loads(os.environ["MAPFLOW_JSON"])
|
|
201
|
+
except ValueError:
|
|
202
|
+
raise SystemExit
|
|
203
|
+
for a in d.get("assets", []):
|
|
204
|
+
if sys.argv[1] in a["name"]:
|
|
205
|
+
print(a["browser_download_url"]); break
|
|
206
|
+
PY
|
|
207
|
+
)
|
|
208
|
+
[ -z "$url" ] && { say "$name: no matching release asset, install manually"; return 1; }
|
|
209
|
+
tmp=$(mktemp)
|
|
210
|
+
if ! curl -fsSL "$url" -o "$tmp"; then
|
|
211
|
+
rm -f "$tmp"; say "$name: download failed"; return 1
|
|
212
|
+
fi
|
|
213
|
+
mkdir -p "$BIN"; cp "$tmp" "$BIN/$name"; chmod +x "$BIN/$name"
|
|
214
|
+
rm -f "$tmp"
|
|
215
|
+
say "$name installed to $BIN/$name"
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
install_npm_tool() { # install_npm_tool <command> <package>
|
|
219
|
+
local command="$1" package="$2"
|
|
220
|
+
if have "$command"; then say "$command already installed"; return 0; fi
|
|
221
|
+
have npm || { say "$command: npm not installed, skipping"; return 0; }
|
|
222
|
+
if npm install -g "$package" >/dev/null 2>&1; then
|
|
223
|
+
say "$command installed with npm"
|
|
224
|
+
else
|
|
225
|
+
say "$command install failed, run: npm install -g $package"
|
|
226
|
+
fi
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
install_uv_tool() { # install_uv_tool <command> <package>
|
|
230
|
+
local command="$1" package="$2"
|
|
231
|
+
if have "$command"; then say "$command already installed"; return 0; fi
|
|
232
|
+
have uv || { say "$command: uv not installed, skipping"; return 0; }
|
|
233
|
+
if uv tool install "$package" >/dev/null 2>&1; then
|
|
234
|
+
say "$command installed with uv"
|
|
235
|
+
else
|
|
236
|
+
say "$command install failed, run: uv tool install $package"
|
|
237
|
+
fi
|
|
238
|
+
}
|
|
239
|
+
|
|
183
240
|
write_helpers() {
|
|
184
241
|
mkdir -p "$BIN"
|
|
185
242
|
# Helpers this script used to write and no longer does. Upgrading otherwise
|
|
@@ -3184,6 +3241,30 @@ apply_harlequin() {
|
|
|
3184
3241
|
|| say "harlequin install failed, run: uv tool install harlequin"
|
|
3185
3242
|
}
|
|
3186
3243
|
|
|
3244
|
+
apply_lens_extra_tools() {
|
|
3245
|
+
# A small machine-wide pi-lens toolbelt for common project ecosystems.
|
|
3246
|
+
# Pi-lens can fall back to npx or prompt for some tools, but putting these
|
|
3247
|
+
# on PATH makes them available in any repo without per-project setup.
|
|
3248
|
+
if [ "$(cfg_get pi.lens_extra_tools.python false)" = "true" ]; then
|
|
3249
|
+
install_uv_tool black black
|
|
3250
|
+
install_uv_tool mypy mypy
|
|
3251
|
+
install_npm_tool pyright pyright
|
|
3252
|
+
fi
|
|
3253
|
+
if [ "$(cfg_get pi.lens_extra_tools.docker false)" = "true" ]; then
|
|
3254
|
+
install_plain_github_binary hadolint hadolint/hadolint Linux-x86_64
|
|
3255
|
+
install_npm_tool docker-langserver dockerfile-language-server-nodejs
|
|
3256
|
+
fi
|
|
3257
|
+
if [ "$(cfg_get pi.lens_extra_tools.github_actions false)" = "true" ]; then
|
|
3258
|
+
install_binary actionlint rhysd/actionlint linux_amd64
|
|
3259
|
+
install_uv_tool zizmor zizmor
|
|
3260
|
+
fi
|
|
3261
|
+
if [ "$(cfg_get pi.lens_extra_tools.terraform false)" = "true" ]; then
|
|
3262
|
+
install_binary terraform-ls hashicorp/terraform-ls linux_amd64
|
|
3263
|
+
install_binary tflint terraform-linters/tflint linux_amd64
|
|
3264
|
+
install_plain_github_binary terragrunt gruntwork-io/terragrunt linux_amd64
|
|
3265
|
+
fi
|
|
3266
|
+
}
|
|
3267
|
+
|
|
3187
3268
|
apply_ghdash() {
|
|
3188
3269
|
have gh || { say "gh not installed, skipping dashboard"; return 0; }
|
|
3189
3270
|
gh extension list 2>/dev/null | grep -q gh-dash || gh extension install dlvhdr/gh-dash >/dev/null 2>&1
|
|
@@ -3495,7 +3576,7 @@ s = ((c.get("pi") or {}).get("settings") or {})
|
|
|
3495
3576
|
KEYS = {"hide_thinking_block": ("hideThinkingBlock", True, (True, False)),
|
|
3496
3577
|
"mermaid": ("markdown.mermaid", "streaming", ("off", "final", "streaming")),
|
|
3497
3578
|
"install_telemetry": ("enableInstallTelemetry", False, (True, False)),
|
|
3498
|
-
"theme": ("theme", "
|
|
3579
|
+
"theme": ("theme", "alex-mid-grey", None)}
|
|
3499
3580
|
out = {}
|
|
3500
3581
|
for k, (key, default, allowed) in KEYS.items():
|
|
3501
3582
|
v = s.get(k, default)
|
|
@@ -3514,6 +3595,153 @@ print(json.dumps(out))
|
|
|
3514
3595
|
PY
|
|
3515
3596
|
}
|
|
3516
3597
|
|
|
3598
|
+
pi_zentui_wanted() {
|
|
3599
|
+
cat <<'JSON'
|
|
3600
|
+
{
|
|
3601
|
+
"components.editor.enabled": true,
|
|
3602
|
+
"components.editor.style": "accent-rail",
|
|
3603
|
+
"components.editor.styles.accent-rail.transparent": false,
|
|
3604
|
+
"components.userMessages.enabled": false,
|
|
3605
|
+
"components.footer.style": "starship",
|
|
3606
|
+
"components.footer.modelLabel": "id",
|
|
3607
|
+
"components.footer.styles.starship.segments.modelInfo": true,
|
|
3608
|
+
"components.footer.styles.starship.extensionStatuses.defaultPlacement": "off",
|
|
3609
|
+
"components.extensionStatuses.defaultVisibility": "hide",
|
|
3610
|
+
"components.extensionStatuses.visibility.pi-lens": "hide",
|
|
3611
|
+
"components.extensionStatuses.visibility.pi-lens-lsp": "hide",
|
|
3612
|
+
"components.extensionStatuses.visibility.ponytail": "hide",
|
|
3613
|
+
"components.footer.styles.starship.responsive": true,
|
|
3614
|
+
"components.footer.styles.starship.format": "$cwd( in $session_name)( on $git_branch)( $git_status)( via $runtime)$fill$model($sep$provider)($sep$thinkingLevel)($sep$context)( $auto_compaction)($sep$tokens)( $cache_read)( $cache_write)($sep$cost)( $subscription)",
|
|
3615
|
+
"components.footer.styles.starship.compactFormat": "$cwd$wrap(in $session_name)$wrap(on $git_branch) $git_status$fill$model$wrap_sep($provider)$wrap_sep($thinkingLevel)$wrap_sep$context$wrap_sep$tokens"
|
|
3616
|
+
}
|
|
3617
|
+
JSON
|
|
3618
|
+
}
|
|
3619
|
+
|
|
3620
|
+
pi_zentui_release() {
|
|
3621
|
+
cat <<'JSON'
|
|
3622
|
+
{
|
|
3623
|
+
"components.editor.enabled": null,
|
|
3624
|
+
"components.editor.style": null,
|
|
3625
|
+
"components.editor.styles.accent-rail.transparent": null,
|
|
3626
|
+
"components.userMessages.enabled": null,
|
|
3627
|
+
"components.footer.style": null,
|
|
3628
|
+
"components.footer.modelLabel": null,
|
|
3629
|
+
"components.footer.styles.starship.segments.modelInfo": null,
|
|
3630
|
+
"components.footer.styles.starship.extensionStatuses.defaultPlacement": null,
|
|
3631
|
+
"components.extensionStatuses.defaultVisibility": null,
|
|
3632
|
+
"components.extensionStatuses.visibility.pi-lens": null,
|
|
3633
|
+
"components.extensionStatuses.visibility.pi-lens-lsp": null,
|
|
3634
|
+
"components.extensionStatuses.visibility.ponytail": null,
|
|
3635
|
+
"components.footer.styles.starship.responsive": null,
|
|
3636
|
+
"components.footer.styles.starship.format": null,
|
|
3637
|
+
"components.footer.styles.starship.compactFormat": null
|
|
3638
|
+
}
|
|
3639
|
+
JSON
|
|
3640
|
+
}
|
|
3641
|
+
|
|
3642
|
+
pi_write_theme() {
|
|
3643
|
+
if [ -e "$PI_THEME" ] && ! pi_state owns file "$PI_THEME"; then
|
|
3644
|
+
say "pi: $PI_THEME already exists, so the Mapflow theme was left alone"
|
|
3645
|
+
return 0
|
|
3646
|
+
fi
|
|
3647
|
+
MAPFLOW_PI_THEME="$PI_THEME" py <<'PY'
|
|
3648
|
+
import json, os
|
|
3649
|
+
|
|
3650
|
+
target = os.environ["MAPFLOW_PI_THEME"]
|
|
3651
|
+
theme = {
|
|
3652
|
+
"$schema": "https://pi.dev/schemas/theme.schema.json",
|
|
3653
|
+
"name": "alex-mid-grey",
|
|
3654
|
+
"vars": {
|
|
3655
|
+
"surfaceMuted": "#21262D",
|
|
3656
|
+
"border": "#30363D",
|
|
3657
|
+
"borderSubtle": "#21262D",
|
|
3658
|
+
"text": "#C9D1D9",
|
|
3659
|
+
"textBright": "#E6EDF3",
|
|
3660
|
+
"muted": "#8B949E",
|
|
3661
|
+
"dim": "#6E7681",
|
|
3662
|
+
"toolStatus": "#59616B",
|
|
3663
|
+
"blue": "#58A6FF",
|
|
3664
|
+
"blueSoft": "#79C0FF",
|
|
3665
|
+
"inlineCode": "#D2A8FF",
|
|
3666
|
+
"green": "#3FB950",
|
|
3667
|
+
"red": "#F85149",
|
|
3668
|
+
"yellow": "#E0A052",
|
|
3669
|
+
"orange": "#FFA657",
|
|
3670
|
+
"purple": "#D2A8FF",
|
|
3671
|
+
"toolAccent": "#95A7FF",
|
|
3672
|
+
"toolName": "#8B85D6",
|
|
3673
|
+
"toolText": "#98A1AC",
|
|
3674
|
+
"pink": "#FF7B72",
|
|
3675
|
+
"userPromptBg": "#24272e",
|
|
3676
|
+
},
|
|
3677
|
+
"colors": {
|
|
3678
|
+
"accent": "toolAccent",
|
|
3679
|
+
"border": "border",
|
|
3680
|
+
"borderAccent": "toolStatus",
|
|
3681
|
+
"borderMuted": "borderSubtle",
|
|
3682
|
+
"success": "green",
|
|
3683
|
+
"error": "red",
|
|
3684
|
+
"warning": "yellow",
|
|
3685
|
+
"muted": "muted",
|
|
3686
|
+
"dim": "dim",
|
|
3687
|
+
"text": "text",
|
|
3688
|
+
"thinkingText": "toolText",
|
|
3689
|
+
"selectedBg": "surfaceMuted",
|
|
3690
|
+
"searchMatchBg": "#3B2E10",
|
|
3691
|
+
"searchMatchText": "textBright",
|
|
3692
|
+
"userMessageBg": "userPromptBg",
|
|
3693
|
+
"userMessageText": "textBright",
|
|
3694
|
+
"customMessageBg": "",
|
|
3695
|
+
"customMessageText": "text",
|
|
3696
|
+
"customMessageLabel": "muted",
|
|
3697
|
+
"toolPendingBg": "",
|
|
3698
|
+
"toolSuccessBg": "",
|
|
3699
|
+
"toolErrorBg": "#211414",
|
|
3700
|
+
"toolTitle": "toolName",
|
|
3701
|
+
"toolOutput": "toolText",
|
|
3702
|
+
"scrollbarTrack": "borderSubtle",
|
|
3703
|
+
"scrollbarThumb": "border",
|
|
3704
|
+
"mdHeading": "textBright",
|
|
3705
|
+
"mdLink": "blue",
|
|
3706
|
+
"mdLinkUrl": "dim",
|
|
3707
|
+
"mdCode": "inlineCode",
|
|
3708
|
+
"mdCodeBlock": "text",
|
|
3709
|
+
"mdCodeBlockBorder": "#0D1117",
|
|
3710
|
+
"mdQuote": "toolText",
|
|
3711
|
+
"mdQuoteBorder": "border",
|
|
3712
|
+
"mdHr": "borderSubtle",
|
|
3713
|
+
"mdListBullet": "muted",
|
|
3714
|
+
"toolDiffAdded": "#45B85A",
|
|
3715
|
+
"toolDiffRemoved": "#E45D57",
|
|
3716
|
+
"toolDiffContext": "dim",
|
|
3717
|
+
"syntaxComment": "dim",
|
|
3718
|
+
"syntaxKeyword": "pink",
|
|
3719
|
+
"syntaxFunction": "purple",
|
|
3720
|
+
"syntaxVariable": "text",
|
|
3721
|
+
"syntaxString": "blueSoft",
|
|
3722
|
+
"syntaxNumber": "orange",
|
|
3723
|
+
"syntaxType": "orange",
|
|
3724
|
+
"syntaxOperator": "muted",
|
|
3725
|
+
"syntaxPunctuation": "muted",
|
|
3726
|
+
"thinkingOff": "borderSubtle",
|
|
3727
|
+
"thinkingMinimal": "border",
|
|
3728
|
+
"thinkingLow": "dim",
|
|
3729
|
+
"thinkingMedium": "muted",
|
|
3730
|
+
"thinkingHigh": "blue",
|
|
3731
|
+
"thinkingXhigh": "blueSoft",
|
|
3732
|
+
"thinkingMax": "#9FCFF8",
|
|
3733
|
+
"bashMode": "green",
|
|
3734
|
+
},
|
|
3735
|
+
"export": {"pageBg": "#0D1117", "cardBg": "#161B22", "infoBg": "#1C2128"},
|
|
3736
|
+
}
|
|
3737
|
+
os.makedirs(os.path.dirname(target), exist_ok=True)
|
|
3738
|
+
json.dump(theme, open(target, "w"), indent=2, ensure_ascii=False)
|
|
3739
|
+
open(target, "a").write("\n")
|
|
3740
|
+
PY
|
|
3741
|
+
pi_state own file "$PI_THEME"
|
|
3742
|
+
say "pi: Mapflow theme written to $PI_THEME"
|
|
3743
|
+
}
|
|
3744
|
+
|
|
3517
3745
|
# npm installs pi into its global bin, which a fresh shell may not have on
|
|
3518
3746
|
# PATH. Asking npm costs a process, so only when pi is not already found.
|
|
3519
3747
|
find_pi() {
|
|
@@ -3762,10 +3990,16 @@ apply_pi() {
|
|
|
3762
3990
|
bili_client remove codex
|
|
3763
3991
|
bili_client remove claude
|
|
3764
3992
|
if [ "$(cfg_get pi.billion_context true)" = "true" ]; then
|
|
3765
|
-
|
|
3766
|
-
|
|
3993
|
+
pi_state merge "$BILLION_CONFIG" billion '{"pi.subagents": false}'
|
|
3994
|
+
if [ "$(json_field "$BILLION_CONFIG" pi.subagents)" = "False" ]; then
|
|
3995
|
+
pi_add "$PI_BILLION" "$PI_BILLION"
|
|
3996
|
+
bili_client install pi
|
|
3997
|
+
else
|
|
3998
|
+
say "pi: billion-context acp_delegate could not be disabled, so billion-context setup was skipped"
|
|
3999
|
+
fi
|
|
3767
4000
|
else
|
|
3768
4001
|
bili_client remove pi
|
|
4002
|
+
pi_state merge "$BILLION_CONFIG" billion '{"pi.subagents": null}'
|
|
3769
4003
|
pi_drop "$PI_BILLION"
|
|
3770
4004
|
fi
|
|
3771
4005
|
if [ "$(cfg_get pi.question_tool true)" = "true" ]; then
|
|
@@ -3803,6 +4037,20 @@ apply_pi() {
|
|
|
3803
4037
|
else
|
|
3804
4038
|
pi_drop npm:pi-compact-tools
|
|
3805
4039
|
fi
|
|
4040
|
+
[ "$(cfg_get pi.settings.theme alex-mid-grey)" = "alex-mid-grey" ] && pi_write_theme
|
|
4041
|
+
if [ "$(cfg_get pi.zentui true)" = "true" ]; then
|
|
4042
|
+
pi_add "$PI_ZENTUI" "$PI_ZENTUI"
|
|
4043
|
+
pi_state merge "$PI_ZENTUI_CFG" zentui "$(pi_zentui_wanted)"
|
|
4044
|
+
else
|
|
4045
|
+
pi_state merge "$PI_ZENTUI_CFG" zentui "$(pi_zentui_release)"
|
|
4046
|
+
pi_drop "$PI_ZENTUI"
|
|
4047
|
+
fi
|
|
4048
|
+
if [ "$(cfg_get pi.hide_lens_lsp_status true)" = "true" ]; then
|
|
4049
|
+
pi_state merge "$PI_LENS_CFG" pi_lens '{"ui.hideLspStatus": true, "widget.visible": false}'
|
|
4050
|
+
else
|
|
4051
|
+
pi_state merge "$PI_LENS_CFG" pi_lens '{"ui.hideLspStatus": null, "widget.visible": null}'
|
|
4052
|
+
fi
|
|
4053
|
+
apply_lens_extra_tools
|
|
3806
4054
|
|
|
3807
4055
|
# agentic-retro writes its own extension file. This setup only asks it to,
|
|
3808
4056
|
# and owns the file only when it was not there before.
|
|
@@ -3850,6 +4098,7 @@ remove_pi() {
|
|
|
3850
4098
|
pi_drop npm:pi-plugin-manager
|
|
3851
4099
|
pi_drop npm:@juicesharp/rpiv-todo
|
|
3852
4100
|
pi_drop npm:pi-compact-tools
|
|
4101
|
+
pi_drop "$PI_ZENTUI"
|
|
3853
4102
|
pi_drop npm:@juicesharp/rpiv-ask-user-question
|
|
3854
4103
|
pi_drop npm:pi-web-access
|
|
3855
4104
|
pi_drop npm:pi-lens
|
|
@@ -3858,6 +4107,7 @@ remove_pi() {
|
|
|
3858
4107
|
else
|
|
3859
4108
|
say "pi: $PI_SETTINGS does not parse, so its packages were left installed"
|
|
3860
4109
|
fi
|
|
4110
|
+
pi_state merge "$BILLION_CONFIG" billion '{"pi.subagents": null}'
|
|
3861
4111
|
if pi_state owns file "$PI_RETRO_EXT"; then
|
|
3862
4112
|
rm -f "$PI_RETRO_EXT"
|
|
3863
4113
|
pi_state disown file "$PI_RETRO_EXT"
|
|
@@ -3865,6 +4115,13 @@ remove_pi() {
|
|
|
3865
4115
|
fi
|
|
3866
4116
|
pi_state merge "$PI_SETTINGS" settings \
|
|
3867
4117
|
'{"hideThinkingBlock": null, "markdown.mermaid": null, "enableInstallTelemetry": null, "theme": null}'
|
|
4118
|
+
pi_state merge "$PI_ZENTUI_CFG" zentui "$(pi_zentui_release)"
|
|
4119
|
+
pi_state merge "$PI_LENS_CFG" pi_lens '{"ui.hideLspStatus": null, "widget.visible": null}'
|
|
4120
|
+
if pi_state owns file "$PI_THEME"; then
|
|
4121
|
+
rm -f "$PI_THEME"
|
|
4122
|
+
pi_state disown file "$PI_THEME"
|
|
4123
|
+
say "pi: Mapflow theme removed"
|
|
4124
|
+
fi
|
|
3868
4125
|
pi_state merge "$PI_KEYBINDINGS" keybindings '{"app.message.dequeue": null}'
|
|
3869
4126
|
pi_state merge "$PI_SUBAGENT_CFG" subagent '{"toolActivation": null}'
|
|
3870
4127
|
pi_state md strip
|
|
@@ -3899,6 +4156,12 @@ pi-web-access pi npm pi-web-access -
|
|
|
3899
4156
|
pi-lens pi npm pi-lens -
|
|
3900
4157
|
pi-slash-anywhere pi npm pi-slash-anywhere -
|
|
3901
4158
|
pi-compact-tools pi npm pi-compact-tools -
|
|
4159
|
+
pi-zentui pi npm pi-zentui -
|
|
4160
|
+
actionlint pi github rhysd/actionlint linux_amd64
|
|
4161
|
+
hadolint pi github hadolint/hadolint Linux-x86_64
|
|
4162
|
+
terraform-ls pi github hashicorp/terraform-ls linux_amd64
|
|
4163
|
+
tflint pi github terraform-linters/tflint linux_amd64
|
|
4164
|
+
terragrunt pi github gruntwork-io/terragrunt linux_amd64
|
|
3902
4165
|
T
|
|
3903
4166
|
}
|
|
3904
4167
|
|
|
@@ -3929,8 +4192,18 @@ installed_version() { # installed_version <name> -> a bare version, or nothing
|
|
|
3929
4192
|
harlequin) v=$(uv tool list 2>/dev/null | awk '$1=="harlequin"{print $2}') ;;
|
|
3930
4193
|
# 1.1.0
|
|
3931
4194
|
pi) find_pi; v=$(pi --version 2>/dev/null | awk '{print $NF}') ;;
|
|
4195
|
+
# actionlint version 1.7.7
|
|
4196
|
+
actionlint) v=$(actionlint -version 2>/dev/null | awk '{print $2}') ;;
|
|
4197
|
+
# Haskell Dockerfile Linter 2.12.0
|
|
4198
|
+
hadolint) v=$(hadolint --version 2>/dev/null | awk '{print $NF}') ;;
|
|
4199
|
+
# terraform-ls version 0.36.5
|
|
4200
|
+
terraform-ls) v=$(terraform-ls version 2>/dev/null | awk '{print $2}') ;;
|
|
4201
|
+
# TFLint version 0.59.1
|
|
4202
|
+
tflint) v=$(tflint --version 2>/dev/null | awk 'NR==1{print $3}') ;;
|
|
4203
|
+
# terragrunt version v0.91.2
|
|
4204
|
+
terragrunt) v=$(terragrunt --version 2>/dev/null | awk '{print $NF}') ;;
|
|
3932
4205
|
# pi installs npm packages under its own directory, not npm's global one.
|
|
3933
|
-
pi-subagents|pi-compact-tools|pi-web-access|pi-lens|pi-slash-anywhere|@juicesharp/rpiv-ask-user-question|billion-context|@juicesharp/rpiv-todo|pi-plugin-manager)
|
|
4206
|
+
pi-subagents|pi-compact-tools|pi-zentui|pi-web-access|pi-lens|pi-slash-anywhere|@juicesharp/rpiv-ask-user-question|billion-context|@juicesharp/rpiv-todo|pi-plugin-manager)
|
|
3934
4207
|
v=$(json_field "$PI_DIR/npm/node_modules/$1/package.json" version) ;;
|
|
3935
4208
|
esac
|
|
3936
4209
|
printf '%s' "${v#v}"
|
|
@@ -4080,7 +4353,7 @@ upgrade_one() { # upgrade_one <name>
|
|
|
4080
4353
|
else
|
|
4081
4354
|
say "pi update failed"
|
|
4082
4355
|
fi ;;
|
|
4083
|
-
pi-subagents|pi-compact-tools|pi-web-access|pi-lens|pi-slash-anywhere|@juicesharp/rpiv-ask-user-question|billion-context|@juicesharp/rpiv-todo|pi-plugin-manager)
|
|
4356
|
+
pi-subagents|pi-compact-tools|pi-zentui|pi-web-access|pi-lens|pi-slash-anywhere|@juicesharp/rpiv-ask-user-question|billion-context|@juicesharp/rpiv-todo|pi-plugin-manager)
|
|
4084
4357
|
if pi_npm_pin "$1"; then
|
|
4085
4358
|
say "$1 is pinned to $(pi_state pkg "npm:$1") in pi, which pi update never moves"
|
|
4086
4359
|
return 0
|
|
@@ -4097,6 +4370,10 @@ upgrade_one() { # upgrade_one <name>
|
|
|
4097
4370
|
# here rather than behind a table lookup that will never find it.
|
|
4098
4371
|
mermaid-ascii)
|
|
4099
4372
|
INSTALL_FORCE=1 install_binary mermaid-ascii AlexanderGrooff/mermaid-ascii Linux_x86_64 ;;
|
|
4373
|
+
hadolint)
|
|
4374
|
+
INSTALL_FORCE=1 install_plain_github_binary hadolint hadolint/hadolint Linux-x86_64 ;;
|
|
4375
|
+
terragrunt)
|
|
4376
|
+
INSTALL_FORCE=1 install_plain_github_binary terragrunt gruntwork-io/terragrunt linux_amd64 ;;
|
|
4100
4377
|
# The fork build comes from a local checkout, so a release archive would
|
|
4101
4378
|
# replace it with the stock binary and silently drop the patches it carries.
|
|
4102
4379
|
# outdated already skips it; naming it here has to skip it too.
|
|
@@ -4165,7 +4442,7 @@ case "$ACTION" in
|
|
|
4165
4442
|
if have pi || [ "$(cfg_get pi.enabled false)" = "true" ]; then
|
|
4166
4443
|
echo
|
|
4167
4444
|
have pi && say "pi: $(installed_version pi)" || say "pi: not installed"
|
|
4168
|
-
for id in npm:pi-subagents "$PI_ACSTACK" "$PI_BILLION" npm:@juicesharp/rpiv-todo npm:pi-plugin-manager npm:@juicesharp/rpiv-ask-user-question npm:pi-web-access npm:pi-lens "$PI_SLASH_ANYWHERE" npm:pi-compact-tools; do
|
|
4445
|
+
for id in npm:pi-subagents "$PI_ACSTACK" "$PI_BILLION" npm:@juicesharp/rpiv-todo npm:pi-plugin-manager npm:@juicesharp/rpiv-ask-user-question npm:pi-web-access npm:pi-lens "$PI_SLASH_ANYWHERE" npm:pi-compact-tools "$PI_ZENTUI"; do
|
|
4169
4446
|
src=$(pi_state pkg "$id") && say "pi package: $src" || say "pi package: $id not installed"
|
|
4170
4447
|
done
|
|
4171
4448
|
[ -e "$PI_RETRO_EXT" ] && say "pi agentic-retro extension: present" \
|
package/cli/package.json
CHANGED
package/docs/workflows.md
CHANGED
|
@@ -121,7 +121,7 @@ Nodes live in a tracker. That is the storage layer, and you can swap it.
|
|
|
121
121
|
|
|
122
122
|
- `/acstack:implement` claims `afk` work nodes from the frontier when a map exists
|
|
123
123
|
- It treats the request itself as the work item when none does
|
|
124
|
-
- Either way, parallel
|
|
124
|
+
- Either way, parallel read-only codebase-search subagents run over the relevant code before anyone writes anything
|
|
125
125
|
- The command resolves paths at claim time
|
|
126
126
|
- A node describes behaviour
|
|
127
127
|
- It can sit unstarted for weeks
|
package/orchestrator/AGENTS.md
CHANGED
|
@@ -55,7 +55,7 @@ ACStack runs on Claude Code, Codex, and pi. The skills name each capability once
|
|
|
55
55
|
- **Launch a subagent** – start a child agent with its own context, by its ACStack name (`test-writer`, `task-executor`, `task-checker`, `frontend-verifier`)
|
|
56
56
|
- Claude Code: the Agent tool, with `subagent_type` set to that name
|
|
57
57
|
- pi: the `subagent` tool from `pi-subagents`
|
|
58
|
-
-
|
|
58
|
+
- **Read-only codebase-search subagent** – Claude Code's `Explore`, pi's `scout`
|
|
59
59
|
- `debugger` names a debugging agent
|
|
60
60
|
- On a host without a matching built-in agent, launch a general subagent with that brief
|
|
61
61
|
- **Agent team** – parallel full sessions, each owning one scope and launching its own subagents
|
|
@@ -502,7 +502,7 @@ Launch each agent by the name below (see Host tools for how your host takes it).
|
|
|
502
502
|
| Implement task | `task-executor` | CANNOT modify tests |
|
|
503
503
|
| Verify implementation | `task-checker` | Mock skepticism, full regression, TDD isolation |
|
|
504
504
|
| Verify frontend UI | `frontend-verifier` | Real browser, screenshots, non-negotiable |
|
|
505
|
-
| Find/locate something | `Explore`
|
|
505
|
+
| Find/locate something | `Explore` / `scout` | Read-only codebase search; `scout` on pi |
|
|
506
506
|
| Debug/investigate | `debugger` | Built-in debugging agent |
|
|
507
507
|
|
|
508
508
|
---
|
package/package.json
CHANGED
|
@@ -41,7 +41,7 @@ Your job is to:
|
|
|
41
41
|
|
|
42
42
|
## Phase 1: independent exploration (passes 1-3)
|
|
43
43
|
|
|
44
|
-
Launch **3 parallel
|
|
44
|
+
Launch **3 parallel read-only codebase-search subagents** at once. Use `Explore` on Claude Code and `scout` on pi. Each gets a different exploration strategy:
|
|
45
45
|
|
|
46
46
|
### Pass 1 – entry points strategy
|
|
47
47
|
|
|
@@ -90,7 +90,7 @@ Launch a single subagent to merge the 3 independent drafts per domain. It resolv
|
|
|
90
90
|
|
|
91
91
|
## Phase 3: validation (passes 5-7)
|
|
92
92
|
|
|
93
|
-
Launch 3 parallel
|
|
93
|
+
Launch 3 parallel read-only codebase-search subagents to validate ALL domains independently. Each checks that FRs match actual code behavior.
|
|
94
94
|
|
|
95
95
|
## Phase 4: correction merge (pass 8)
|
|
96
96
|
|
package/skills/grilling/SKILL.md
CHANGED
|
@@ -29,9 +29,11 @@ session.
|
|
|
29
29
|
nothing else. Never ask a question whose answer depends on one still open.
|
|
30
30
|
|
|
31
31
|
2. **Facts are your job, never the user's.** Skip a question that an
|
|
32
|
-
environment fact would answer.
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
environment fact would answer.
|
|
33
|
+
|
|
34
|
+
Dispatch parallel read-only codebase-search subagents, one per distinct
|
|
35
|
+
place to look, not a fixed count. Use `Explore` on Claude Code and `scout`
|
|
36
|
+
on pi. Fold what they find into the round.
|
|
35
37
|
|
|
36
38
|
3. **Run it before you ask it.** Check whether running something could answer
|
|
37
39
|
the question – behaviour, timing, output, or performance. If it could,
|
|
@@ -106,8 +108,8 @@ the tracker's `update` and `create` operations:
|
|
|
106
108
|
Write the answer per the `writing` skill.
|
|
107
109
|
|
|
108
110
|
2. Create a node for each new question the answer surfaced, with `answers`
|
|
109
|
-
naming the node that surfaced it.
|
|
110
|
-
|
|
111
|
+
naming the node that surfaced it. Mark precise questions `open`; mark the
|
|
112
|
+
rest `fog`.
|
|
111
113
|
|
|
112
114
|
3. Invoke the `record-context` skill for each resolution – it decides whether
|
|
113
115
|
the decision earns an ADR, a glossary term, both, or neither.
|
|
@@ -98,9 +98,11 @@ Claim each node as you start it:
|
|
|
98
98
|
|
|
99
99
|
Nodes describe behaviour, not paths. **Resolve paths at claim time**.
|
|
100
100
|
|
|
101
|
-
Before any code change, dispatch parallel
|
|
102
|
-
relevant code. Use
|
|
103
|
-
|
|
101
|
+
Before any code change, dispatch parallel read-only codebase-search subagents
|
|
102
|
+
over the relevant code. Use `Explore` on Claude Code and `scout` on pi.
|
|
103
|
+
|
|
104
|
+
Use as many as there are distinct places to look, not a fixed count. Act on
|
|
105
|
+
what they find.
|
|
104
106
|
|
|
105
107
|
### 5. Execute within the claim
|
|
106
108
|
|
|
@@ -219,8 +221,9 @@ diff.
|
|
|
219
221
|
- **The tracker is the progress record** – claim on start, resolve on pass,
|
|
220
222
|
release on stall. No checkbox files, no phase fields.
|
|
221
223
|
|
|
222
|
-
- **Explore before writing** – parallel
|
|
223
|
-
code, sized to the node, before any edit.
|
|
224
|
+
- **Explore before writing** – parallel read-only codebase-search subagents
|
|
225
|
+
over the relevant code, sized to the node, before any edit. Use `Explore` on
|
|
226
|
+
Claude Code and `scout` on pi.
|
|
224
227
|
|
|
225
228
|
- **Resume is a query** – picking up where you left off means asking the
|
|
226
229
|
tracker what is workable now, not reconstructing history. A fresh session
|
package/skills/map/SKILL.md
CHANGED
|
@@ -182,8 +182,8 @@ the list, marked `skip: <reason>`.
|
|
|
182
182
|
- `hitl` nodes: run grilling rounds over them. A round is the whole hitl
|
|
183
183
|
frontier.
|
|
184
184
|
- `afk` nodes: claim and run without the user. Unlimited, and in parallel
|
|
185
|
-
when independent. Research goes to
|
|
186
|
-
|
|
185
|
+
when independent. Research goes to read-only codebase-search subagents:
|
|
186
|
+
`Explore` on Claude Code and `scout` on pi.
|
|
187
187
|
|
|
188
188
|
Implementation work follows `/acstack:implement`'s procedure – it owns
|
|
189
189
|
the claim-execute-resolve flow, the explorer dispatch, and the TDD
|
|
@@ -73,7 +73,8 @@ If no meaningful code changes exist (only docs, config, assets), report "No code
|
|
|
73
73
|
|
|
74
74
|
## Step 2: DISCOVER – Learn project conventions (parallel)
|
|
75
75
|
|
|
76
|
-
Launch **3 parallel
|
|
76
|
+
Launch **3 parallel read-only codebase-search subagents** to build a dynamic understanding of the project's current conventions.
|
|
77
|
+
Use `Explore` on Claude Code and `scout` on pi.
|
|
77
78
|
Do NOT hardcode conventions – discover them fresh each time.
|
|
78
79
|
|
|
79
80
|
**Subagent A – Living Specs & Architecture:**
|
|
@@ -177,7 +178,8 @@ Add each finding to the review as `SHOULD | PROSE`, at the `file:line` it names.
|
|
|
177
178
|
|
|
178
179
|
## Step 4: ADJACENT – Check surrounding code for rot
|
|
179
180
|
|
|
180
|
-
For each file with findings from Step 3, launch
|
|
181
|
+
For each file with findings from Step 3, launch a **read-only codebase-search subagent**.
|
|
182
|
+
Use up to 3 subagents in parallel.
|
|
181
183
|
Each subagent examines the rest of that file and its immediate imports for the same categories of issue.
|
|
182
184
|
|
|
183
185
|
```
|
|
@@ -39,7 +39,7 @@ If the user provided an error message or stack trace, note the key details (file
|
|
|
39
39
|
|
|
40
40
|
**Do NOT skip this step.** Delegate exploration to subagents:
|
|
41
41
|
|
|
42
|
-
1. **Locate the code**: Launch
|
|
42
|
+
1. **Locate the code**: Launch a read-only codebase-search subagent to find the files involved. Use `Explore` on Claude Code and `scout` on pi. Read only a file you can already name.
|
|
43
43
|
|
|
44
44
|
2. **Read the integration points**: Have the subagent read the broken function's callers and callees, not just the function. Understand:
|
|
45
45
|
- What calls this code? (upstream)
|
|
@@ -50,9 +50,11 @@ frontend and has not turned browser verification on. Turn it on:
|
|
|
50
50
|
read it. Without it, every path through spec sync skips in silence, and the
|
|
51
51
|
living specs never update.
|
|
52
52
|
|
|
53
|
-
Launch
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
Launch a **read-only codebase-search subagent** over `directories.source` to propose domains.
|
|
54
|
+
Use `Explore` on Claude Code and `scout` on pi.
|
|
55
|
+
|
|
56
|
+
Ask it for the top-level functional areas.
|
|
57
|
+
Ask for a kebab-case name, the paths that belong to it, and one line saying what it owns.
|
|
56
58
|
|
|
57
59
|
Guidance for the subagent:
|
|
58
60
|
|