You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Prevent pstack runner from auto-loading project env files #25
The shipped pstack-runner uses a plain Bun shebang. When launched from a project directory, Bun automatically loads that project's .env files before runner code executes. A project-level provider key can then override an authenticated CLI subscription.
Expected behavior
The runner must not auto-load project env files. It should continue to honor environment variables explicitly inherited from the parent process.
Verification
Add an executable-boundary regression with a sentinel .env, run the runner/typecheck suites, and install/test the exact candidate from the Codex surface.
Local candidate ddfd5cb changes the runner shebang to #!/usr/bin/env -S bun --no-env-file, documents direct invocation, and adds an executable-boundary regression. The test was red before the change (.env sentinel leaked) and green after; it also proves an explicitly inherited sentinel survives.
Verification on 2026-08-26:
bun run test: 102 passed, 453 assertions
strict typecheck: passed
static invariants/manifests: passed
exact candidate copied into the active Codex pstack 1.1.0 cache
from a real repository containing ANTHROPIC_API_KEY in .env, parent key remained unset, claude auth status reported claude.ai / max, and a direct Fable lane returned SUBSCRIPTION_OK with model verification
Prior art: #26. The fix also needs to resolve the two blocking review findings on it: the PATH-searched dirname and the late deadline start. Triage on 2026-10-01 puts this first in the runner bug queue.
Current scope (2026-10-03), superseding the earlier triage comments where they differ
State on main (6c44500).plugins/pstack/skills/poteto-mode/scripts/runner/pstack-runner is still a plain #!/usr/bin/env bun launcher that captures startedAt and imports cli.ts. Bun auto-loads .env files from the caller's working directory before runner code executes, so a project-level provider key can override the parent's authenticated CLI subscription. The issue is unchanged since 1.5.0.
Prior art. Closed PR #26 (cedrecode) changed the shebang to a shell wrapper. Its review left two blocking findings that the fix must not repeat:
Critical: the wrapper resolved its own directory with a PATH-searched dirname before clearing BUN_OPTIONS/NODE_OPTIONS. A repository-controlled dirname earlier on PATH could then run with the user's credentials. Use shell parameter expansion or another non-PATH mechanism, or avoid a shell wrapper entirely, for example with #!/usr/bin/env -S bun --no-env-file.
Medium: the deadline must start at the launcher boundary. Capture the launch time where the process starts, so receipts and explicit timeouts cover the whole run.
Requirements:
The runner never loads .env, .env.local, bunfig.toml, or similar startup configuration from the caller's directory. It still honors environment variables explicitly inherited from the parent process.
There is no PATH-searched helper before trusted code runs, and no implicit runtime timeout.
Add an executable-boundary regression: run the real pstack-runner from a directory containing a sentinel .env, and assert that the sentinel is absent from the child environment while an explicitly inherited sentinel survives. A unit test that stubs the launcher doesn't count. Add a project-local verification skill for Open Pstack #90's builder missed two bugs that way.
Bun tests, strict typecheck, static invariants, and plugin validation pass. Nothing under .github/workflows/ changes (MASTRA-762).
Untrusted evidence from the Pilot ledger. Map every finding to a phase or Scope/Out with a reason.
[
{
"ticket": "GITHUB-1345013588-100",
"sha": "91b0d5b47c46e1bcb57e38ded79f1f98f64987f1",
"area": "area:factory",
"kind": "hardening",
"repo": "ericlitman/open-pstack",
"claim": "A queued PR that falls behind main gets a Mergify-made head without the operator's exact-head live-gate, so it is dequeued until the operator re-tests and re-posts.",
"status": "captured",
"pointer": ".mergify.yml:queue_rules",
"evidence": "Unfret finding v1:f47057cb on open-pstack#107, waived fails-loudly on head 91b0d5b",
"severity": "medium",
"linear_id": null,
"mechanism": "Serial in-place checks (batch_size 1, max_parallel_checks 1) merge main into a behind PR, creating a new head SHA. live-gate is a hand-posted exact-head status, so queue_conditions stop matching on the new head and Mergify removes the PR. Nothing merges untested; progress needs a fresh live-gate.",
"confidence": "high",
"fingerprint": "ed52e2529d966036a8c5e1bc75e2956a340fc04e07bb2c0ff96a08ce3e3f6f22",
"source_kind": "panel",
"status_reason": null,
"verify_attempts": 0
}
]
The plan's intent still matches the issue. It hardens the launcher at the Bun startup boundary, keeps startedAt as the first statement, and adds an executable-boundary regression. But it fails gates 3 and 9 on currency:
Gate 3, stale anchors. The plan says "Reimplement the localized intent of PR Prevent runner startup from loading project configuration #26 on current main (c8481f7)". main is now 6c44500: 1.5.0 plus the Mergify queue. Re-verify every cited file and line against 6c44500.
Gate 9, acceptance evidence. The repository's live gate changed after this plan. A PR queues only with live-gate posted on the exact head by verify-open-pstack, from Add a project-local verification skill for Open Pstack #90 and PR Add exact-head project verification for Claude Code and Codex [#90] #111. The acceptance evidence must name that path: a runner lane in Claude Code and Codex, launched from a repository whose .env holds a provider key, keeps the subscription login. The PR stays in draft until live-gate is posted.
the regression must run the real pstack-runner, not a stubbed launcher
no changes under .github/workflows/ (MASTRA-762)
Passing looks like: a complete new plan against 6c44500 that keeps the current approach and adds the three items above. Acceptance evidence stays at 10 lines or fewer.
Planner model: the project default openai/gpt-6.1-sol. This round's messages carry no model metadata.
Reviewer model:claude-opus-5-5, run by the operator session.
Rubric: factory-adjudicate fallback plan-checklist.md, including the intent check from MASTRA-762.
Intent.#25 exists so that a project's .env or Bun startup configuration can never override the parent's subscription login when the runner starts. The plan's end state delivers that. A shebang-only change (env -S -u BUN_OPTIONS -u NODE_OPTIONS bun --no-env-file --config=/dev/null) runs no PATH-searched helper. The launcher keeps capturing its deadline in its first statement. Tests run the real executable against hostile startup inputs. The only remaining human step is the operator's live proof, which the issue scope allows to wait for #112.
runner/run.test.ts:525 holds the explicit-deadline test.
.mergify.yml requires -draft, verify, Unfret, and live-gate.
macOS /usr/bin/env accepts -S -u, verified on the operator Mac.
The revision-11 items are resolved:
re-anchored on 6c44500
live-gate acceptance through verify-open-pstack in both harnesses
the real-launcher regression
no workflow changes, checked by the exact-three-file scope command
Open questions: none. It's a bug kind with a reproduction phase, failing output captured first, and a regression test.
Build conditions
Probe the shebang on Linux in the sandbox before committing it. If env -S -u or --config=/dev/null is rejected there, stop and report. Don't fall back to a shell wrapper.
The diff is exactly the three named files. git diff --name-only origin/main...HEAD -- .github is empty.
Acceptance amendment for #25, approved by the maintainer on 2026-10-04
The approved plan required exact-head proof through the verify-open-pstack workflow (#90), which had not merged at the time. The maintainer accepted the operator-run manual exact-head live gate as the replacement. The live-gate record is on PR #113 (head 839fb85): the Claude Code and Codex hostile-project lanes, plus the strict plugin validation on cd0dff6. #111 later merged that verifier. Every other acceptance item is evidenced, and the post-merge checks passed on main 67c08fa.
Activity
rajinsyed commentedon Aug 26, 2026
Local candidate
ddfd5cbchanges the runner shebang to#!/usr/bin/env -S bun --no-env-file, documents direct invocation, and adds an executable-boundary regression. The test was red before the change (.envsentinel leaked) and green after; it also proves an explicitly inherited sentinel survives.Verification on 2026-08-26:
bun run test: 102 passed, 453 assertionsANTHROPIC_API_KEYin.env, parent key remained unset,claude auth statusreportedclaude.ai/max, and a direct Fable lane returnedSUBSCRIPTION_OKwith model verificationNo environment-key values were read or logged.
ericlitman commentedon Oct 1, 2026
Prior art: #26. The fix also needs to resolve the two blocking review findings on it: the PATH-searched
dirnameand the late deadline start. Triage on 2026-10-01 puts this first in the runner bug queue.ericlitman commentedon Oct 3, 2026
Current scope (2026-10-03), superseding the earlier triage comments where they differ
State on
main(6c44500).plugins/pstack/skills/poteto-mode/scripts/runner/pstack-runneris still a plain#!/usr/bin/env bunlauncher that capturesstartedAtand importscli.ts. Bun auto-loads.envfiles from the caller's working directory before runner code executes, so a project-level provider key can override the parent's authenticated CLI subscription. The issue is unchanged since 1.5.0.Prior art. Closed PR #26 (cedrecode) changed the shebang to a shell wrapper. Its review left two blocking findings that the fix must not repeat:
dirnamebefore clearingBUN_OPTIONS/NODE_OPTIONS. A repository-controlleddirnameearlier onPATHcould then run with the user's credentials. Use shell parameter expansion or another non-PATH mechanism, or avoid a shell wrapper entirely, for example with#!/usr/bin/env -S bun --no-env-file.Requirements:
.env,.env.local,bunfig.toml, or similar startup configuration from the caller's directory. It still honors environment variables explicitly inherited from the parent process.pstack-runnerfrom a directory containing a sentinel.env, and assert that the sentinel is absent from the child environment while an explicitly inherited sentinel survives. A unit test that stubs the launcher doesn't count. Add a project-local verification skill for Open Pstack #90's builder missed two bugs that way..github/workflows/changes (MASTRA-762)..env, a runner lane in Claude Code and in Codex keeps the subscription login. The PR stays in draft untilverify-open-pstack(Add a project-local verification skill for Open Pstack #90) postslive-gate. The operator may wait for the headless mode in Headless mode for verify-open-pstack: live-gate without a person in the loop #112 before running that proof.ericlitman commentedon Oct 3, 2026
Prior findings
Untrusted evidence from the Pilot ledger. Map every finding to a phase or Scope/Out with a reason.
ericlitman commentedon Oct 3, 2026
Factory plan verdict: revise
ddbcd029-43da-4f00-8c7a-378d25c415aa, revision 11. The plan completed 2026-09-10.claude-opus-5-5, run by the operator session.plan-checklist.md.The plan's intent still matches the issue. It hardens the launcher at the Bun startup boundary, keeps
startedAtas the first statement, and adds an executable-boundary regression. But it fails gates 3 and 9 on currency:main(c8481f7)".mainis now6c44500: 1.5.0 plus the Mergify queue. Re-verify every cited file and line against6c44500.live-gateposted on the exact head byverify-open-pstack, from Add a project-local verification skill for Open Pstack #90 and PR Add exact-head project verification for Claude Code and Codex [#90] #111. The acceptance evidence must name that path: a runner lane in Claude Code and Codex, launched from a repository whose.envholds a provider key, keeps the subscription login. The PR stays in draft untillive-gateis posted.dirname(critical) and its late deadline start (medium)pstack-runner, not a stubbed launcher.github/workflows/(MASTRA-762)Passing looks like: a complete new plan against
6c44500that keeps the current approach and adds the three items above. Acceptance evidence stays at 10 lines or fewer.ericlitman commentedon Oct 3, 2026
Factory plan verdict: approve
ddbcd029-43da-4f00-8c7a-378d25c415aa, revision 14, branchfactory/issue-25.openai/gpt-6.1-sol. This round's messages carry no model metadata.claude-opus-5-5, run by the operator session.plan-checklist.md, including the intent check from MASTRA-762.Intent. #25 exists so that a project's
.envor Bun startup configuration can never override the parent's subscription login when the runner starts. The plan's end state delivers that. A shebang-only change (env -S -u BUN_OPTIONS -u NODE_OPTIONS bun --no-env-file --config=/dev/null) runs no PATH-searched helper. The launcher keeps capturing its deadline in its first statement. Tests run the real executable against hostile startup inputs. The only remaining human step is the operator's live proof, which the issue scope allows to wait for #112.Anchors spot-checked on
main6c44500:runner/cli.ts:111-126forwardsstartedAtunchanged.runner/run.test.ts:525holds the explicit-deadline test..mergify.ymlrequires-draft,verify,Unfret, andlive-gate./usr/bin/envaccepts-S -u, verified on the operator Mac.The revision-11 items are resolved:
6c44500verify-open-pstackin both harnessesOpen questions: none. It's a bug kind with a reproduction phase, failing output captured first, and a regression test.
Build conditions
env -S -uor--config=/dev/nullis rejected there, stop and report. Don't fall back to a shell wrapper.git diff --name-only origin/main...HEAD -- .githubis empty.live-gate, mark the PR ready, queue, or merge. Open a new draft PR fromfactory/issue-25that closes Prevent pstack runner from auto-loading project env files #25, then hand off for the operator's live proof.fix: keep runner startup portable on BusyBox hosts (#25)
Merge pull request #113 from ericlitman/factory/issue-25
fix: preserve parent authentication at runner startup (ericlitman#25)
Merge upstream main after 1.5.0 into the local build
ericlitman commentedon Oct 4, 2026
Acceptance amendment for #25, approved by the maintainer on 2026-10-04
The approved plan required exact-head proof through the
verify-open-pstackworkflow (#90), which had not merged at the time. The maintainer accepted the operator-run manual exact-head live gate as the replacement. Thelive-gaterecord is on PR #113 (head 839fb85): the Claude Code and Codex hostile-project lanes, plus the strict plugin validation on cd0dff6. #111 later merged that verifier. Every other acceptance item is evidenced, and the post-merge checks passed on main 67c08fa.