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
After running .\Pull-SDLC.ai.ps1 in a consumer repo that already has Pull-SDLC.ai.ps1 tracked at an older version, git status continues
to show Pull-SDLC.ai.ps1 as modified, forever, with no automatic
path to resolution. The sync PR (chore/sdlc-sync) opens fine but does
not include Pull-SDLC.ai.ps1, so even after that PR merges the
consumer's tracked copy stays at the old SHA.
Reproduced live in D:\Git\GmailNewsClient (May 18, 2026, against
upstream e25eca7 -- the PR #134 merge):
.\Pull-SDLC.ai.ps1
... runs cleanly ...
Existing PR updated: https://github.com/IntelliTect-Samples/GmailNewsClient/pull/317
PS> git status
On branch main
modified: Pull-SDLC.ai.ps1
Root cause
Pull-SDLC.ai.ps1 is intentionally NOT in
`` (see the script header docstring).
Self-refresh writes the new version to the working tree but never
commits anywhere -- the rewrite happens in the parent main tree, not
in the .worktrees/sdlc-sync scratch worktree, so the sync commit
inside the worktree contains the OLD Pull-SDLC.ai.ps1.
The consumer is stuck with a permanently-dirty working tree they didn't
cause and can't resolve via Pull-SDLC.ai.ps1 alone. This violates the
"just works" promise of the script.
Affected bootstrap files
Same logic applies to every bootstrap file the user dropped in to get
the script running, currently excluded from upstream-managed paths:
Pull-SDLC.ai.ps1 (the most visible / annoying case)
Pull-SDLC.ai.Tests.ps1
Cleanup-Worktree.ps1
Consolidate-Tasks.ps1 and Consolidate-Tasks.Tests.ps1
sync-manifest.json
The current Invoke-MainTreeCleanup candidate list (line ~463) names
exactly these files; treating them all as upstream-managed would unify
the rule.
Proposed approach (not for immediate implementation)
Option A -- Promote bootstrap files into ``.
Add Pull-SDLC.ai.ps1 (and siblings above) to the managed-paths list.
The diff-replay inside `.worktrees/sdlc-sync` will then write the new
versions on top of the worktree's `main` baseline, the sync commit
will include them, and the `chore/sdlc-sync` PR will carry them. After
the PR merges, the consumer's tracked `Pull-SDLC.ai.ps1` lands at the
new SHA and `git status` is clean.
Caveats to think through during the dev loop:
Self-refresh races with replay: self-refresh writes the new script to
the parent main tree before the worktree runs. After the
re-exec, the worktree starts from main (which still has the OLD
script) and the replay writes the new version, so the order works.
But the parent tree's working copy still shows Pull-SDLC.ai.ps1
modified vs HEAD until the PR merges; cleanup should leave it alone
in that window. Invoke-MainTreeCleanup's post-PR-134 safety check
(revert only when HEAD == upstream) already handles this -- once
the sync PR merges, HEAD catches up and the next run cleans up.
Self-refresh needs to keep working for the very first bootstrap run
in repos where the file isn't tracked yet -- the diff-replay handles
"file does not exist yet" already, so should be fine.
Option B -- Have the sync commit also stage these files inside the
worktree from the parent tree's working copy. Less consistent with
how other files flow through ``; rejected unless
Option A turns out to have a blocking edge case.
Secondary observation (probably a separate issue)
The May 18 run also emitted 11x warning: in the working copy of '<file>', LF will be replaced by CRLF the next time Git touches it
inside the worktree. These come from the diff-replay writing LF-stored
upstream blobs into a CRLF-flagged working tree on Windows. They're
cosmetic but noisy. Consider:
Setting core.safecrlf=false for the duration of the replay, or
Writing replay files with -NoNewline after manually normalizing,
or
Updating .gitattributes.template to declare these paths as text=auto eol=lf so git stops warning.
Out of scope for this issue; mention if a future dev loop touches the
replay writer.
Acceptance criteria
After this issue's fix lands:
In any consumer repo where Pull-SDLC.ai.ps1 is tracked at an
older version, running .\Pull-SDLC.ai.ps1 produces a sync PR
that includes the updated Pull-SDLC.ai.ps1 (and siblings above).
After that PR merges, git status is clean -- zero modified
files.
Self-refresh continues to work for first-time bootstrap (file not
yet tracked).
The pre-flight drift guard does not block on Pull-SDLC.ai.ps1
having self-refreshed content.
All existing Pester tests stay green; new tests cover the
"bootstrap file in UpstreamManagedPaths" scenarios.
Symptom
After running
.\Pull-SDLC.ai.ps1in a consumer repo that already hasPull-SDLC.ai.ps1tracked at an older version,git statuscontinuesto show
Pull-SDLC.ai.ps1as modified, forever, with no automaticpath to resolution. The sync PR (
chore/sdlc-sync) opens fine but doesnot include
Pull-SDLC.ai.ps1, so even after that PR merges theconsumer's tracked copy stays at the old SHA.
Reproduced live in
D:\Git\GmailNewsClient(May 18, 2026, againstupstream
e25eca7-- the PR #134 merge):Root cause
Pull-SDLC.ai.ps1is intentionally NOT in`` (see the script header docstring).
commits anywhere -- the rewrite happens in the parent main tree, not
in the
.worktrees/sdlc-syncscratch worktree, so the sync commitinside the worktree contains the OLD
Pull-SDLC.ai.ps1.Invoke-MainTreeCleanup, thecleanup correctly refuses to
git checkout -- Pull-SDLC.ai.ps1when
HEAD:path != UpstreamRef:path(avoiding the silentdowngrade). Good. But that means the modified state is now permanent
until the consumer hand-commits the file.
The consumer is stuck with a permanently-dirty working tree they didn't
cause and can't resolve via
Pull-SDLC.ai.ps1alone. This violates the"just works" promise of the script.
Affected bootstrap files
Same logic applies to every bootstrap file the user dropped in to get
the script running, currently excluded from upstream-managed paths:
Pull-SDLC.ai.ps1(the most visible / annoying case)Pull-SDLC.ai.Tests.ps1Cleanup-Worktree.ps1Consolidate-Tasks.ps1andConsolidate-Tasks.Tests.ps1sync-manifest.jsonThe current
Invoke-MainTreeCleanupcandidate list (line ~463) namesexactly these files; treating them all as upstream-managed would unify
the rule.
Proposed approach (not for immediate implementation)
Option A -- Promote bootstrap files into ``.
Add
Pull-SDLC.ai.ps1(and siblings above) to the managed-paths list.The diff-replay inside `.worktrees/sdlc-sync` will then write the new
versions on top of the worktree's `main` baseline, the sync commit
will include them, and the `chore/sdlc-sync` PR will carry them. After
the PR merges, the consumer's tracked `Pull-SDLC.ai.ps1` lands at the
new SHA and `git status` is clean.
Caveats to think through during the dev loop:
the parent main tree before the worktree runs. After the
re-exec, the worktree starts from
main(which still has the OLDscript) and the replay writes the new version, so the order works.
But the parent tree's working copy still shows
Pull-SDLC.ai.ps1modified vs HEAD until the PR merges; cleanup should leave it alone
in that window.
Invoke-MainTreeCleanup's post-PR-134 safety check(revert only when
HEAD == upstream) already handles this -- oncethe sync PR merges, HEAD catches up and the next run cleans up.
-Forcedocumented in the scriptheader) should NOT trip on
Pull-SDLC.ai.ps1self-refresh diffs.Either exempt the script itself from the drift check, or compare
using
--no-filtersraw bytes (same fix as fix(pull-sdlc): scratch-state auto-recovery (force-with-lease + autocrlf hash + no silent downgrade) #133).in repos where the file isn't tracked yet -- the diff-replay handles
"file does not exist yet" already, so should be fine.
Option B -- Have the sync commit also stage these files inside the
worktree from the parent tree's working copy. Less consistent with
how other files flow through ``; rejected unless
Option A turns out to have a blocking edge case.
Secondary observation (probably a separate issue)
The May 18 run also emitted 11x
warning: in the working copy of '<file>', LF will be replaced by CRLF the next time Git touches itinside the worktree. These come from the diff-replay writing LF-stored
upstream blobs into a CRLF-flagged working tree on Windows. They're
cosmetic but noisy. Consider:
core.safecrlf=falsefor the duration of the replay, or-NoNewlineafter manually normalizing,or
.gitattributes.templateto declare these paths astext=auto eol=lfso git stops warning.Out of scope for this issue; mention if a future dev loop touches the
replay writer.
Acceptance criteria
After this issue's fix lands:
Pull-SDLC.ai.ps1is tracked at anolder version, running
.\Pull-SDLC.ai.ps1produces a sync PRthat includes the updated
Pull-SDLC.ai.ps1(and siblings above).git statusis clean -- zero modifiedfiles.
yet tracked).
Pull-SDLC.ai.ps1having self-refreshed content.
"bootstrap file in
UpstreamManagedPaths" scenarios.Related
autocrlf hash + no silent downgrade)
This issue is the last remaining "just works" gap.