Skip to content

fix(copilot): run Windows helpers through Git Bash and repair fixtures - #1

Merged
nareshh74 merged 11 commits into
mainfrom
fix/copilot-windows-script-launch
Oct 6, 2026
Merged

nareshh74 merged 11 commits into
mainfrom
fix/copilot-windows-script-launch

Conversation

@nareshh74

@nareshh74 nareshh74 commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

Why (in your own words)

On Windows, Copilot invoked extensionless gstack helpers directly from PowerShell, which opened the application picker instead of running the script. Bare bash also selected WSL on the affected machine. This change makes generated Copilot skills select Git for Windows Bash explicitly and adds windows-gstack-patch to restore that instruction after upgrades. It also fixes five related test fixtures without weakening production guards, assertions, Git hardening, or deadlines.

This PR targets nareshh74/gstack:main. The user authorized publication with the known validation failures disclosed. This is not release acceptance or authorization to merge. The upstream PR garrytan#3047 remains separate.

Live evidence

Before the launch fix, direct PowerShell invocation produced empty output or hung during the reported picker incident. That is not evidence that the helper executed. No before screenshot is available.

The installed repair and startup verifier produced the following results on the affected machine. Temporary paths are omitted.

powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File contrib\skills\windows-gstack-patch\Apply-WindowsPatch.ps1
# Exit 0
SUMMARY changed=0 unchanged=59 skipped=0 planned=0

powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File contrib\skills\windows-gstack-patch\Verify-WindowsPatch.ps1
# Exit 0
EVIDENCE startup_exit=0.
EVIDENCE protocol='SKILL_START_PROTO: 1'.
EVIDENCE openwith_new=0.
SUMMARY bash=ok startup=ok protocol=ok parent_pid=ok openwith=ok

Fixture evidence separates the launch issue from unrelated runtime failures. Before repair, redaction fixtures produced 8 passes and 19 failures because implicit bare-repository discovery conflicted with safe.bareRepository=explicit. Explicit --git-dir changed that result to 27 passes and no failures. The Git policy remains enabled.

A direct Bun probe showed import.meta.main=false with a short-name fixture working directory and true with its native canonical path. Canonical fixture paths restored four planner manifest/report cases. The full-copy offline case still exceeds its original deadlines.

The commands below used explicit Git Bash on PATH. The fixture runs used the project runner's unchanged 30-second test timeout. Required generated skills, checksum-verified jq, and the Node browser-server bundle were restored before final acceptance.

Command Observed result
bun test test\host-config.test.ts --test-name-pattern 'Copilot host render' 10 passed, 0 failed, 92 filtered out.
bun test test\windows-gstack-patch.test.ts test\context-budget-ratchet.test.ts test\spawnsync-timeout-tripwire.test.ts 25 passed, 0 failed. Includes actual startup and idempotent repair.
bun test test\parity-suite.test.ts test\catalog-budget.test.ts 5 passed, 0 failed.
bun test browse\test\cookie-import-reliability.test.ts test\provider-model-defaults.test.ts test\docsync-lifecycle-interface.test.ts test\tasks-section-jq.test.ts --timeout=30000 --max-concurrency=1 88 passed, 4 existing skips, 0 failed.
bun test test\redact-prepush-target.test.ts --timeout=30000 --max-concurrency=1 27 passed, 0 failed.
bun test test\ci-paid-coordination.test.ts --timeout=30000 --max-concurrency=1 15 passed, 1 failed. Offline full-checkout deadline remains red.
bun test test\docsync-command-grammar.test.ts test\docsync-nested-writes.test.ts test\spawnsync-timeout-tripwire.test.ts --timeout=30000 --max-concurrency=1 79 passed, 56 existing skips, 1 failed. Windows command-observer case remains red.
bun test test\spawnsync-timeout-tripwire.test.ts --timeout=30000 --max-concurrency=1 3 passed, 0 failed.
bun run typecheck Passed.
bun run typecheck:test Passed. 866 known diagnostics, none new.
bun run test:windows Exit 124. All six shards timed out at unchanged 530-540 second limits. Shards reported 42 failure entries and one unhandled error. Complete pass/fail/skip totals are unavailable.
git diff HEAD and git diff origin/main...HEAD, each piped to node .github\scripts\gate-secret-scan.mjs before fixture commits Both passed. 0 high findings, 0 advisory findings.
git diff --check Passed before fixture commits.

The checks above cover the committed source. No consumed source changed after these runs. The two launch commits were already pushed. Three new test-only commits preserve the five-file diff that was tested. Independent review passed for the four original fixture changes and separately for the planner canonicalization. The comment review found no actionable added comments or suppressions.

Existing validation errors and functionality impact

Focused comparisons ran on both upstream main c285d88b90d39116ccfa2b901f80ea0fce0b26eb and the original base 10315cf44d1ea13e3ae4821841873afbf7807935. Each reproduced 56 of the 58 retained enclosing failures by name and primary diagnostic family. The original 67 failure lines included nine nested duplicates. One generated-host prerequisite failure resolved after documented setup. One offline CI diagnostic remains unverified because its fixture failed earlier.

This proves recurrence for those original cases, not for every failure in the final run. The comparison was focused, not full acceptance. It retained 90-second outer caps, used the project timeout in corrected controls, and may have resolved dependencies from the parent checkout. Sixty unobserved files from the original timed-out shards remain unverified.

Remaining failure Effect on gstack functionality Evidence status
Temporary output-path rejection in browse/test/temp-dirs.test.ts Valid new files below Windows TEMP can be rejected when the allowlist and component traversal use different short/long path spellings. This can block browser screenshot output to such paths. Product path failure reproduced on both upstream revisions. Not fixed here.
Atomic recovery in test/cso-lease-identity.test.ts Interrupted CSO JSON publication can fail recovery with SNAPSHOT_RACE. This affects crash recovery, not proof that every normal CSO run fails. Real unmocked recovery also fails on both upstream revisions. Exact metadata mismatch remains unresolved.
Sidecar symlink handling in test/gen-skill-docs-prune-stale.test.ts Generator may render into a linked sidecar instead of skipping it. Possible ownership/path-safety defect in generation. Disposable-fixture behavior observed. No production fix or weaker expectation applied.
Headless-to-headed browser handoff Chromium reports a ProcessSingleton profile lock and cannot complete the headed transition. Observed in final acceptance. Cleanup cause and upstream attribution remain unverified.
Offline planner full-checkout case Fixture copy, Git setup, and planning exceed existing deadlines on this workstation. This blocks the validation case. It does not demonstrate wrong planner output. Separate probe produced correct 79 planned / 56 excluded output but ran too slowly. No budget increase.
Windows documentation command observer Separator spelling fails command admission or fixture ownership-prefix checks. This blocks the observer test. It does not prove a live documentation command fails. Adjacent check remains red. An incomplete test-only repair was reverted.
Alias installation, QA fix-loop, QA-only browser probe, and CEO fixtures Setup, synthetic subprocess deadlines, or deep Git fixture paths fail. These do not establish failure of the corresponding live skills. No skips, relaxed assertions, or larger budgets added. Live behavior remains unverified.
Six full-suite shard timeouts Broad validation cannot establish complete functionality or release readiness. Some source-scan cases also hit deadlines rather than bad-source assertions. Final local acceptance is incomplete. No automatic rerun or claim of success.

The five fixture fixes and restored jq/generated prerequisites do not change production behavior. They remove misleading failures. The temporary-path and atomic-recovery defects are genuine functionality risks that this PR leaves in place.

Local Bun 1.4.2 and Node 24.21.0 differ from Windows CI's Bun 1.4.0 and Node 24.18.0. These local results do not establish identical CI behavior. Paid evaluations were not run because ANTHROPIC_API_KEY was unavailable. No full Unix suite or complete real upgrade cycle was exercised.

Windows 8.3 short-name path fixes (7b9665c, 071feca, acd7f30)

On profiles whose user directory has an 8.3 short name (for example KUMARN~1), fs.realpathSync keeps the short spelling while fs.realpathSync.native expands it. Three comparisons mixed the two:

  • scripts/gen-skill-docs.ts: the symlink-loop guard missed the sidecar alias and rewrote the source SKILL.md. Both sides now use realpathSync.native.
  • browse/src/path-security.ts: validateOutputPath rejected screenshots under os.tmpdir(). SAFE_DIRECTORIES now holds both spellings of the same directories; remote serving (TEMP_ONLY) is unchanged.
  • test/ceo-plan-mode-fixture.test.ts: the expectation now uses the long-form directory the child reports.

Installed from this branch and exercised:

$ ./setup --host copilot --global
gstack ready (copilot).   (setup exit 0)
$ ./setup --status
copilot  experimental  global  current  1.91.27.0  ~/.copilot/skills  (source: /c/learn/gstack)
copilot global: router is a real file; section links: 20 checked, all resolve

# Before 071feca7f (same command, same machine):
$ browse screenshot C:/Users/<user>/AppData/Local/Temp/x.png
Path must be within: C:\Users\KUMARN~1\AppData\Local\Temp, C:\learn\gstack
# After:
Screenshot saved: C:/Users/kumarnaresh/AppData/Local/Temp/gstack-pr-validate.png   (36408 bytes)
$ browse screenshot C:/Windows/evil.png
Path must be within: C:\Users\KUMARN~1\AppData\Local\Temp, C:\Users\kumarnaresh\AppData\Local\Temp, C:\learn\gstack

# Live Copilot CLI 1.0.92 run of /gstack-learn against the installed skills:
gstack-skill-start 0; gstack-context-recovery 0; gstack-slug 0; gstack-learnings-search 0; gstack-skill-end 0

Focused tests: gen-skill-docs-prune-stale 1 fail -> 4 pass; browse/test/temp-dirs 1 fail -> 0 fail; ceo-plan-mode-fixture 0/9 -> 9/9; bun run typecheck passes. Independent read-only review: PASS.

bun run test --windows-only (Git Bash on PATH, jq installed): 46 failing tests in 23 files -> 16 in 13 files; still exit 124 with four timed-out shards. Remaining: cso-lease-identity (Windows ctime differs between lstat and fstat in 17/20 local trials; fix not chosen), and timing-sensitive tests that pass in isolation or match the earlier inventory. Acceptance is not complete.

Scope

  • Changed: Copilot host instructions, generator body prefix, README Windows guidance, standalone Windows repair skill, launch regressions, and five Windows fixture corrections. The repair validates ownership, rejects links, backs up originals, replaces documents atomically, and preserves no-write reruns.
  • Verified live by: PowerShell 5.1 and explicit Git for Windows Bash on the affected machine. The helper emitted its startup protocol, created its expected session file, exited 0, and spawned no new OpenWith.exe process.
  • Did NOT test: Complete acceptance, paid agent coverage, the full Unix suite, a complete upgrade cycle, or live behavior for the unresolved synthetic QA/CEO cases. No file associations, helper renames, WSL setup, production defect repair, merge, or deployment changed.

Liveness proof (required for external contributors)

gh api user --jq .login returned nareshh74. This PR targets that user's own fork. The template's @garrytan exemption does not apply. No human liveness screenshot is attached.

Checklist

  • Liveness screenshot attached (GSTACK PR typed live into a real surface) or PR author is @garrytan (owner exemption)
  • This is not a generated-file-only diff (I edited the source/template and regenerated)
  • No ETHOS.md edits, and no changes to voice / founder perspective / YC references
  • New public command / external service / host adapter has an accepted issue linked (or N/A)
  • Linked issue or reproduction: #

No accepted issue is linked for the standalone repair skill. The reported reproduction and live evidence appear above. Acceptance remains red; this PR is for review, not a claim that the fork is release-ready.

kumarnareshh74 and others added 11 commits October 6, 2026 00:00
Prepend shell instructions to every Copilot skill, including skills without a preamble. Preserve Bash syntax and interpreter dispatch instead of opening extensionless scripts through PowerShell.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Install windows-gstack-patch outside gstack-managed directories. Validate owned documents before atomic replacement, retain recovery backups, and verify real helper execution through Git Bash.

Focused repair regressions and independent review pass. Windows acceptance remains blocked by 67 named failures and four timed-out shards; publication is not authorized with those failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Do not mistake the Windows temporary directory ancestor for a Local browser root.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use native canonical paths for owned fixture directories and drive-root paths for non-executing provider policy tests. Preserve trusted-path checks and existing deadlines.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pass --git-dir for the owned bare repositories without weakening safe.bareRepository=explicit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Accept matching unprefixed generated names in project registrations and parse CRLF frontmatter correctly. Cover content preservation, host metadata, idempotence and refusal of unrelated names.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 87e9e6d0-f8c0-45df-aa50-345aa10adff2
Describe repair of personal and project skill registrations without changing host identity or metadata. Require actual loaded project instructions, explicit exit guards and real startup verification.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 87e9e6d0-f8c0-45df-aa50-345aa10adff2
realpathSync keeps 8.3 short names (KUMARN~1) on Windows while a path
resolved through a symlinked directory comes back in long form. The
guard compared the two spellings, missed the loop, and rewrote the
source SKILL.md through the sidecar symlink. Use realpathSync.native
on both sides.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
validateOutputPath resolves components with realpathSync.native, which
expands Windows 8.3 short names, but SAFE_DIRECTORIES held only the
realpathSync (short) spelling, so valid screenshots under os.tmpdir()
were rejected. Keep both spellings of the same directories. Remote
serving (TEMP_ONLY) is unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The child reports its fixture cwd with 8.3 short names expanded, so
canonicalize the parent directory the same way.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nareshh74
nareshh74 merged commit ad8e1bd into main Oct 6, 2026
21 of 44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants