Repository navigation
bug(launcher): auto-provision setup fails on CodeGraph "path escapes allowed roots" — infinite first-run loop #1388
Description
Activity
I have installed gentle-shell standalone today. Every time I run it is a first run setup. This is the output:
gentle-shell: first run in /Users/<user>/.gentle-shell/agent: installing the Gentle AI companion packages (one time; set GENTLE_SHELL_NO_AUTO_SETUP=1 to skip) gentle-shell: provisioning /Users/<user>/.gentle-shell/agent with the gentle-ai companion packages WARNING: installing with --scope=global (default). Agent config files (system prompts, skills/, agents/, etc.) will be written to each selected agent's global config directory and will affect ALL workspaces for those agents on this machine. To install only into the current workspace, rerun with --scope=workspace. [pi-web-access] Dynamic tool activation requires Pi 0.86.1 or newer; web tools remain eagerly available. Installing npm:gentle-pi... up to date, audited 305 packages in 562ms 159 packages are looking for funding run `npm fund` for details found 0 vulnerabilities Installed npm:gentle-pi [pi-web-access] Dynamic tool activation requires Pi 0.86.1 or newer; web tools remain eagerly available. Installing npm:gentle-engram... up to date, audited 305 packages in 507ms 159 packages are looking for funding run `npm fund` for details found 0 vulnerabilities Installed npm:gentle-engram [pi-web-access] Dynamic tool activation requires Pi 0.86.1 or newer; web tools remain eagerly available. Installing npm:pi-mcp-adapter... up to date, audited 305 packages in 528ms 159 packages are looking for funding run `npm fund` for details found 0 vulnerabilities Installed npm:pi-mcp-adapter npm notice run npx npm notice run 'pi-engram' init Pi agent dir: /Users/<user>/.gentle-shell/agent Kept npm:pi-mcp-adapter in settings.json Kept npm:gentle-engram@0.1.15 in settings.json Wrote Engram MCP server in mcp.json Set ENGRAM_URL for an existing engram serve instance, or ENGRAM_BIN for a custom engram binary path. [pi-web-access] Dynamic tool activation requires Pi 0.86.1 or newer; web tools remain eagerly available. Installing npm:pi-web-access... up to date, audited 305 packages in 510ms 159 packages are looking for funding run `npm fund` for details found 0 vulnerabilities Installed npm:pi-web-access [pi-web-access] Dynamic tool activation requires Pi 0.86.1 or newer; web tools remain eagerly available. Installing npm:pi-btw... up to date, audited 305 packages in 507ms 159 packages are looking for funding run `npm fund` for details found 0 vulnerabilities Installed npm:pi-btw Error: execute install pipeline: capture Pi CodeGraph child "/Users/<user>/.pi/agent/agents/sdd-proposal.md": Pi CodeGraph path "/Users/<user>/.pi/agent/agents/sdd-proposal.md" escapes allowed roots gentle-shell: automatic setup failed (exit 1); starting anyway and retrying next run. Run `gentle-shell setup` to see the full output. [pi-web-access] Dynamic tool activation requires Pi 0.86.1 or newer; web tools remain eagerly available.It is non blocking. Gentle Shell start with all tools. But, it happen every time and every project directory that I run it.
gentle-shell setupgive same output.No
~/.gentle-shell/config.jsonexist.Environment
Component Version gentle-pi 3.6.0 gentle-ai v3.7.0 Pi 0.87.1 Node v24.20.0 OS macOS 27 From workaround only
Disable auto-setup — set GENTLE_SHELL_NO_AUTO_SETUP=1 in your shell environment.work.Confirmed, this diagnosis is spot on.
What is happening
During
runSetupFlowinbin/gentle-shell.mjs, the launcher spawns:gentle-ai install --agent pi --scope global
with
PI_CODING_AGENT_DIRpointing to the resolved home (e.g.~/.gentle-shell/agent).- All companion packages (
gentle-pi,gentle-engram,pi-web-access, etc.) install cleanly into~/.gentle-shell/agent. - However, the
gentle-aiinstaller pipeline resolves global agent files against the default~/.pi/agent/agents/path, while CodeGraph's allowed root is bounded byPI_CODING_AGENT_DIR(~/.gentle-shell/agent). - CodeGraph's path confinement guard detects that
~/.pi/agent/is outside~/.gentle-shell/agent/and aborts withescapes allowed roots(exit code 1). - Because the installer exited non-zero,
runSetupFlownever executesrecordProvisioned(), leaving~/.gentle-shell/config.jsonunwritten. This triggers the setup flow again on every subsequent launch.
Immediate Workaround
Since the companion packages are already installed, setting
GENTLE_SHELL_NO_AUTO_SETUP=1in your environment skips the loop while keeping all tools functional.Fix Direction
The upstream fix belongs in
gentle-ai's installer pipeline: whenPI_CODING_AGENT_DIRis set in the environment, the CodeGraph capture step for global agents must resolve againstPI_CODING_AGENT_DIRinstead of hardcoding~/.pi/agent/.- All companion packages (
Adding to @carlosmoradev's diagnosis with the exact root cause in
gentle-ai:There are two coupled issues in
internal/agents/pi/adapter.go:-
Shared CodeGraph Manifest:
CodeGraphPaths()hardcodesManifestto~/.gentle-ai/pi-codegraph.json. If Pi was previously run withoutPI_CODING_AGENT_DIR, the manifest already holds children under~/.pi/agent/agents/.... Whengentle-shellruns withPI_CODING_AGENT_DIR=~/.gentle-shell/agent,piCodeGraphAllowedRoots()restricts allowed roots to~/.gentle-shell/agentand~/.gentle-ai. During reconciliation,journal.validate()encounters the old~/.pi/agentchild path from the shared manifest, sees it outside the allowed roots, and aborts withescapes allowed roots. -
Split-brain in
AgentConfigPath:AgentConfigPath(homeDir)returns~/.pi/agentdirectly and ignoresPI_CODING_AGENT_DIR. OnlyCodeGraphPaths()was checking the environment variable.
We are preparing the fix in
gentle-aito isolate the manifest and alignAgentConfigPathwithPI_CODING_AGENT_DIR.-
- addedbugSomething isn't workingSomething isn't workingstatus:approvedIssue approved by maintainer; PR may be openedIssue approved by maintainer; PR may be opened
on Sep 25, 2026 Upstream PR opened with the isolation fix and regression test: Gentleman-Programming/gentle-ai#4985
Hit this on Linux too (Fedora, brew; gentle-shell 3.7.0 / gentle-ai 3.7.0 / pi 0.87.1). Sharing some diagnostics that slightly contradict the root-cause analysis in the issue description — worth checking before the fix lands:
Evidence
- The agent files were correctly written to
~/.gentle-shell/agent/agents/(verified byte-identical to thegentle-pipackage assets). Only the CodeGraph capture step failed. - Running
PI_CODING_AGENT_DIR=~/.gentle-shell/agent gentle-ai install --agent pi --scope globaldirectly did not fix it, nor did upgrading gentle-ai 2.9.1 → 3.7.0. - The failing child path changes on every run (
sdd-apply.md, thensdd-onboard.md, thensdd-spec.md…). Go map iteration is randomized, so this means every recorded child fails the roots check, not a specific one — the reported path is just whichever comes first.
Actual root cause (in my case)
A stale journal manifest at
~/.gentle-ai/pi-codegraph.json, written by a previous gentle-ai install against the default Pi home (~/.pi/agent). It records children under both/home/<user>/.pi/agent/agents/…and/home/<user>/.pi/agents/…. When the install pipeline later runs with the isolated home, the journal's allowed roots are scoped to~/.gentle-shell/agent, and the capture step rejects every path recorded in that legacy manifest (piJournal.capture()overmanifest.Childrenininternal/components/communitytool/pi_codegraph.go). The recorded targets didn't even exist anymore.Workaround that fully fixed it
mv ~/.gentle-ai/pi-codegraph.json ~/.gentle-ai/pi-codegraph.json.legacy-bak gentle-shell setup # → Verification checks: 4 passed, 0 failed
Suggestion for the fix
The pipeline should skip (or quarantine) manifest entries whose paths fall outside the current allowed roots instead of failing the whole install — the per-agent-dir hashed manifest naming (
pi-codegraph-<hash>.jsoninCodeGraphPaths) already prevents new cross-contamination, but legacy default-home journals still break the flow.Reacted by torce- The agent files were correctly written to
Confirm workaround in #1388 (comment), fix: rename
pi-codegraph.json.gentle-setupsuccessful.config.jsoncreated. No more 'first-round setup' loop in next gentle-shell launch. No need ofGENTLE_SHELL_NO_AUTO_SETUPflag.Reacted by Alberto Eizaguerri SerranoAnother occurrence on macOS, with the legacy manifest confirmed as the trigger.
Environment
Component Version gentle-pi / gentle-shell 3.7.0 (npm global, stable) gentle-ai (pinned, package-local) v3.7.0 Pi 0.85.1 Node v26.10.0 OS macOS 27.0, arm64 What I ran
npm i -g gentle-pigentle-shell setup --dry-run(clean, exit 0)gentle-shell setup(one attempt, isolated home, default flags)
Observed
All companion packages installed, then the run exited 1:
Error: execute install pipeline: capture Pi CodeGraph child "<default pi home>/agents/jd-judge-a.md": Pi CodeGraph path "<default pi home>/agents/jd-judge-a.md" escapes allowed rootsState left behind in the isolated home:
- No provisioned marker in the launcher
config.json. - No
mcp.json, even though the log printedWrote Engram MCP server in mcp.json. - No
agents/orskills/directories, onlynpm/andsettings.json. npm:gentle-pistill declared andnpm:gentle-engramdeclared twice (unpinned and@0.1.16), since the post-install cleanup never ran.
The default Pi home was not modified (its
settings.jsonchecksum is identical before and after).Matches the legacy manifest diagnosis
A
pi-codegraph.jsonwritten on 2026-09-18 by an earlier default-home install exists in the shared gentle-ai directory, and the rejected child is one of the agent files from that default home.Expected
Setup skips or quarantines manifest entries outside the current allowed roots and finishes provisioning.
The fix in gentle-ai#4985 is merged but not in a published release yet, so 3.7.0 stable still reproduces.
Another confirmation on Linux (WSL2), same legacy-manifest trigger, plus one detail on what the successful rerun leaves behind.
Environment
Component Version gentle-pi / gentle-shell 3.7.0 (npm global) gentle-ai (pinned, package-local) v3.7.0 Pi 0.87.1 OS WSL2, Linux 6.18, x86_64 Observed
gentle-shell setup(manual) installed every companion package and then failed with:Error: execute install pipeline: capture Pi CodeGraph child "<home>/.pi/agent/agents/gentle-ai-worker.md": Pi CodeGraph path "<home>/.pi/agent/agents/gentle-ai-worker.md" escapes allowed roots<home>/.gentle-ai/pi-codegraph.jsonhad been written on 2026-09-10 by a default-homegentle-ai install, withmcpPathunder<home>/.pi/agent/mcp.jsonand 23 children under<home>/.pi/agent/agents/. The isolated home was left withoutmcp.jsondespite theWrote Engram MCP server in mcp.jsonline, and withnpm:gentle-pistill declared, matching the state described above.Workaround confirmed
Moving the legacy manifest aside and rerunning
gentle-shell setupcompletes withVerification checks: 4 passed, 0 failed, writesmcp.jsonand runs the post-install cleanup that removesnpm:gentle-pi.One extra data point: after the successful rerun, no new
pi-codegraph.jsonwas written for the isolated home, so restoring the legacy manifest afterwards keeps the default Pi home's journal intact without conflicting with anything. The isolated home'smcp.jsononly gets theengramserver, notcodegraph.Confirmed — reproduces on macOS with the current 3.7.0 stack. Adding environment evidence since the original report is WSL2/x86_64.
Environment
Component Version gentle-pi (npm package, installed by launcher) 3.7.0 gentle-ai (package-local binary) v3.7.0 Pi 0.99.2 Node v22.15.1 OS macOS 26.6.2 (arm64) Observed
Fresh machine, no
~/.gentle-shell/present. Ran the gentle-shell launcher from the git checkout atgentle-shell@ d5bedca9(v3.7.0-311). The auto-setup installed the companion npm packages successfully, then failed at the CodeGraph capture step:Error: execute install pipeline: capture Pi CodeGraph child "/Users/<user>/.pi/agent/agents/sdd-design.md": Pi CodeGraph path "/Users/<user>/.pi/agent/agents/sdd-design.md" escapes allowed roots gentle-shell: automatic setup failed (exit 1); starting anyway and retrying next run.Details consistent with this report:
- The rejected child is a different file (
agents/sdd-design.mdvsagents/gentle-ai-verify.mdin the original report), which supports the analysis that the guard fires for any child under Pi's real global agents dir while the capture's allowed roots are scoped to the launcher home. - The infinite first-run loop reproduces: three consecutive launches each re-ran the full setup ("first run ... provisioning") and failed at the same step, because the provisioning marker is only written on success.
- Pi 0.99.2 was in place before the failure (the new Pi >= 0.99.1 gate is not a factor here).
Workaround from this issue (manually writing the
provisionedentry in~/.gentle-shell/config.json) was not applied at the time of writing; the loop is the currently observed state.- The rejected child is a different file (
Another reproduction, plus one consequence that is not described in this thread yet: after the failed automatic setup, a source checkout of gentle-shell silently runs the published npm
gentle-piinstead of its own package.Environment: gentle-shell launcher from a git checkout of main @ cc36bd8 (same launcher code at 1162ce9), package-local gentle-ai v3.7.0, Pi 0.99.1, Linux (WSL2). Fresh custom home inside
$HOME, launcher config isolated withGENTLE_SHELL_CONFIG.Run 1 (auto-setup) fails as reported here:
gentle-shell: first run in <home>/.gs-test/agent: installing the Gentle AI companion packages (one time; set GENTLE_SHELL_NO_AUTO_SETUP=1 to skip) Error: execute install pipeline: capture Pi CodeGraph child "<home>/.pi/agent/agents/sdd-archive.md": Pi CodeGraph path "<home>/.pi/agent/agents/sdd-archive.md" escapes allowed roots gentle-shell: automatic setup failed (exit 1); starting anyway and retrying next run. Run `gentle-shell setup` to see the full output.No provisioning marker is written, and the test home's
settings.jsonis left with:["npm:gentle-pi", "npm:gentle-engram", "npm:gentle-engram@0.1.16", "npm:pi-web-access", "npm:pi-btw", "npm:pi-mcp-adapter"]Run 2 (
GENTLE_SHELL_NO_AUTO_SETUP=1, same home): Pi loads the extension from<home>/.gs-test/agent/npm/node_modules/gentle-pi(version 3.7.0 from npm) instead of the checkout the launcher runs from. The only output is the generic setup-failed line on run 1 and Pi'speerDependencieswarnings for the installed packages; nothing says that the launcher's own package is being skipped.Why: on failure the post-install removal of
npm:gentle-pinever runs (bin/gentle-shell.mjs:862-864), and a home whosesettings.jsondeclares gentle-pi makes the launcher defer to the declared package instead of injecting its own (runtime/gentle-shell-launcher.mjs:637and:938-940).User-visible effect (observed in an earlier run of the same setup):
/gentle:yolois unknown, the model answers as the bare provider identity instead of "el Gentleman" (the harness-append fix from #1497 is not in 3.7.0), and on exit onlypi --session <id>is printed without the gentle-shell resume line. Anyone evaluating main with a fresh home can therefore be testing 3.7.0 without noticing. After removingnpm:gentle-pifrom the home'ssettings.jsonand starting withGENTLE_SHELL_NO_AUTO_SETUP=1, the checkout's own package loads and those features work.Suggestion: when automatic setup fails, still run the
npm:gentle-piremoval, or print a warning when the home's declared gentle-pi differs from the launcher's own package and is about to be used instead.Verified on a current main checkout (
1f35ab1e) with a controlled reproduction, both sides of the fix line:- Control, pinned gentle-ai 3.7.0 (via the documented
GENTLE_SHELL_GENTLE_AI_BIN/GENTLE_SHELL_GENTLE_AI_PINoverrides): planted a legacy shared manifest at<tmp-home>/.gentle-ai/pi-codegraph.jsonwhose child targets<tmp-home>/.pi/agent/agents/legacy-agent.md(schema taken from the reconcile journal). Auto-setup fails with the exact reported error (capture Pi CodeGraph child ... escapes allowed roots), exit 1, no provisioning marker, and the home is left declaringnpm:gentle-piwith the published copy innode_modules. Infinite retry confirmed. - Fix, pinned gentle-ai 4.0.0 (same fixture, no overrides): manual
setupexits 0 and removesnpm:gentle-pi; the automatic first run exits 0, writes the marker (gentleAi 4.0.0/gentlePi 4.0.0), and the second launch skips provisioning entirely (no first-run lines). The legacy manifest is never read; with a custom agent dir the isolatedpi-codegraph-<hash>.jsonpath applies.
So the first published gentle-ai release carrying #4985 is 4.0.0 (answering @itrejomx's note that the fix was merged but unreleased): the loop is closed for every home once gentle-pi 4.0.0 with that pin reaches users, and pre-existing legacy manifests are harmless because the custom-dir manifest path is isolated.
One failure-path consequence first reported by @osantis is now filed separately as #1647: when setup does fail, the
npm:gentle-piremoval never runs and the home silently ends up running the published package instead of the launcher's own copy. That residue is independent of the 4.0.0 fix (it needs any install failure, not this one).- Control, pinned gentle-ai 3.7.0 (via the documented
Bug description
Running
gentle-shellon a fresh or un-provisioned home enters an infinite first-run loop. The auto-provisioning setup (introduced in #1351) installs all companion packages successfully but then fails at the CodeGraph capture step with:Because the setup exits non-zero, the provisioning marker in
~/.gentle-shell/config.jsonis never written, so every subsequentgentle-shelllaunch retries the same failing setup.Steps to reproduce
~/.gentle-shell/config.json(or delete it).gentle-shell(orgentle-shell setup).gentle-shellagain — same output, same failure.Expected behavior
Setup completes, writes the provisioning marker to
~/.gentle-shell/config.json, and subsequent launches skip the auto-provision step.Actual behavior
Setup fails at CodeGraph capture because
--scope globalwrites agents into~/.pi/agent/agents/(Pi's own default agent dir) while CodeGraph's allowed roots are scoped to~/.gentle-shell/agent/(thePI_CODING_AGENT_DIRthe launcher sets). The path mismatch triggers the "escapes allowed roots" guard.Root cause analysis
The auto-provision flow in
runSetupFlowspawns:with
PI_CODING_AGENT_DIR=~/.gentle-shell/agent. The--scope globalflag causes gentle-ai to write managed agents into the user's real~/.pi/agent/agents/directory instead of thePI_CODING_AGENT_DIRtarget. The subsequent CodeGraph capture step then tries to index those files but rejects them because~/.pi/agent/is outside the allowed root (~/.gentle-shell/agent/).PR #587 fixed a similar
PI_CODING_AGENT_DIRalignment for subagent asset installation and model routing, but the CodeGraph capture pipeline step was not covered by that fix.Environment
Workaround
Until this is fixed, either:
Create the provisioning marker manually — write
~/.gentle-shell/config.jsonwith:{ "provisioned": { "/home/<user>/.gentle-shell/agent": { "gentleAi": "3.7.0", "gentlePi": "3.7.0", "at": "2026-09-24T00:00:00.000Z" } } }(Replace paths/versions with your actual values.)
Disable auto-setup — set
GENTLE_SHELL_NO_AUTO_SETUP=1in your shell environment.Related
feat(launcher): provision Gentle Shell's own home automatically on first run(introduced the auto-provision flow)fix(subagents): honor PI_CODING_AGENT_DIR for assets(fixed the same mismatch for subagent assets, but not for CodeGraph capture)