feat(scripts): add SPECIFY_NO_PERSIST env var to suppress feature.json writes (#4128) - #4129
Open
chelsealong wants to merge 1 commit into
Open
feat(scripts): add SPECIFY_NO_PERSIST env var to suppress feature.json writes (#4128)#4129chelsealong wants to merge 1 commit into
chelsealong wants to merge 1 commit into
Conversation
…n writes (github#4128) Multi-agent setups running several Spec Kit script invocations concurrently against the same checkout each set their own SPECIFY_FEATURE_DIRECTORY. Every invocation that omits --no-persist (e.g. setup-plan, setup-tasks) still writes that value to the shared .specify/feature.json, so agents can clobber each other's pinned feature directory. SPECIFY_NO_PERSIST=1|true is the environment-level equivalent of --no-persist, letting an orchestrator suppress that write across every call in the process tree without patching each call site. Assisted-by: Claude Code (model: claude-sonnet-5, autonomous)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Fixes #4128.
When multiple Spec Kit script invocations run concurrently against the same
checkout (e.g. multiple agents/subagents each working on a different
feature), each one typically sets its own
SPECIFY_FEATURE_DIRECTORY. Mostcore scripts (
setup-plan,setup-tasks) callget_feature_paths()without--no-persist, so every invocation persists itsSPECIFY_FEATURE_DIRECTORYto the shared
.specify/feature.json— the last writer wins, silentlyoverwriting another process's pinned feature directory.
--no-persist(added for #3025) already exists as a per-call opt-out, butit's a parameter each call site has to pass — scripts that don't know they
need it (like
setup-plan/setup-tasks) never do.Fix
Add
SPECIFY_NO_PERSISTas the environment-level equivalent of--no-persist/-NoPersist/no_persist=True. When set to1ortrue,it suppresses the
.specify/feature.jsonwrite inget_feature_paths()regardless of whether the calling script passes the per-call flag. An
orchestrator can set it once for a whole process tree so no script
invocation in that tree can write
feature.json, even ones that don't knowto opt out themselves.
Implemented identically in all three script variants per the project's
parity rule (
AGENTS.md):scripts/bash/common.sh—get_feature_paths()scripts/powershell/common.ps1—Get-FeaturePathsEnvscripts/python/common.py—get_feature_paths()Also documented the new variable in
docs/reference/core.md's environmentvariables table, next to
SPECIFY_FEATURE_DIRECTORY.Fully backward compatible: existing behavior when
SPECIFY_NO_PERSISTisunset is unchanged in every scenario.
Test plan
Added
tests/test_specify_no_persist.py, covering all three scriptvariants via
setup-plan(which callsget_feature_paths()without--no-persist, so it's a script that previously had no way to opt out):SPECIFY_FEATURE_DIRECTORYset, noSPECIFY_NO_PERSIST→feature.jsonis written (existing behavior, unchanged).SPECIFY_NO_PERSIST=1/true→feature.jsonwrite is suppressed, forbash, PowerShell, and Python.
specs/001-a, agent B runs withSPECIFY_FEATURE_DIRECTORY=specs/002-bandSPECIFY_NO_PERSIST=1→feature.jsonstill points at agent A'sspecs/001-a(the pin isn'tclobbered).
Confirmed the new tests fail without the fix (
git checkout HEAD~1 -- scripts/bash/common.sh scripts/powershell/common.ps1 scripts/python/common.py,then re-ran):
And pass with the fix restored:
Also ran:
shellcheck --severity=erroron all tracked.shfiles — clean.markdownlint-cli2ondocs/reference/core.md— same 2 pre-existingMD028findings as on unmodifiedmain(unrelated blockquotes furtherdown the file, confirmed by diffing lint output before/after).
pytest tests/ -q(6944 tests): 6921 passed, 9 skipped, 4 pre-existingfailures unrelated to this change (
test_presets.py,test_resolve_template_python_parity.py— template-composition/localeedge cases), confirmed present on
mainbefore this change too.No manual agent-driven testing was done for this change since it's a
core-script/docs-only change with no slash-command template modifications.
AI disclosure
This PR was written primarily by an autonomous AI coding agent (Claude Code,
Claude Sonnet 5), including the code change, tests, and this description.