Skip to content

Commit 887f742

Browse files
coneilenCopilot
andcommitted
Make Windows builds reproducible
Bootstrap checksum-pinned Zig toolchains, Swift 6.3.3, and public detached provider revisions; make Windows workflows consume that setup; and complete the Windows SwiftPM source set and path portability. Signed-off-by: Colin Neilens <coneilen@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent b978338 commit 887f742

15 files changed

Lines changed: 242 additions & 128 deletions

File tree

.github/workflows/windows-hardening.yml

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ on:
1212
pull_request:
1313
paths:
1414
- ".github/workflows/windows-hardening.yml"
15+
- "Package.swift"
16+
- "Package.resolved"
17+
- "MailroomKit/**"
18+
- "GraphcodeKit/**"
19+
- "graphcode-cli/**"
20+
- "graphcoded/**"
21+
- "graphcode-windows/**"
22+
- "windows-tests/**"
1523
- "Tools/windows/**"
1624
- "investigation/windows-implementation-plan.md"
1725
- "Tools/windows/validation-matrix.md"
@@ -43,47 +51,15 @@ jobs:
4351
runs-on: windows-2022
4452
steps:
4553
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
46-
- name: Install exact Swift toolchain
54+
- name: Bootstrap exact Windows dependencies
4755
shell: pwsh
48-
run: |
49-
winget install --id Swift.Toolchain --exact --version 6.3.3 `
50-
--silent --accept-package-agreements --accept-source-agreements
51-
- name: Install exact Zig toolchains
52-
shell: pwsh
53-
run: |
54-
$ErrorActionPreference = "Stop"
55-
$root = Join-Path $env:GITHUB_WORKSPACE ".ci-tools"
56-
New-Item -ItemType Directory -Force $root | Out-Null
57-
function Install-Zig([string] $version, [string] $sha256) {
58-
$archive = Join-Path $root "zig-$version.zip"
59-
Invoke-WebRequest "https://github.com/ziglang/zig/releases/download/$version/zig-x86_64-windows-$version.zip" -OutFile $archive
60-
if ((Get-FileHash $archive -Algorithm SHA256).Hash -ne $sha256) { throw "Zig checksum mismatch: $version" }
61-
Expand-Archive $archive -DestinationPath $root -Force
62-
$expanded = Join-Path $root "zig-x86_64-windows-$version"
63-
$destination = Join-Path $root "zig-$version"
64-
Move-Item $expanded $destination -Force
65-
Join-Path $destination "zig.exe"
66-
}
67-
"GRAPHCODE_ZIG0152=$(Install-Zig 0.15.2 3A0ED1E8799A2F8CE2A6E6290A9FF22E6906F8227865911FB7DDEDC3CC14CB0C)" >> $env:GITHUB_ENV
68-
"GRAPHCODE_ZIG0160=$(Install-Zig 0.16.0 68659EB5F1E4EB1437A722F1DD889C5A322C9954607F5EDCF337BC3684A75A7E)" >> $env:GITHUB_ENV
69-
- name: Checkout pinned providers
70-
shell: pwsh
71-
run: |
72-
git clone --no-checkout https://github.com/coneilen/winghostty.git Winghostty-worktrees/host-integration
73-
git -C Winghostty-worktrees/host-integration checkout --detach f5abc059e4ca58b376eb209313aca7784659c679
74-
git clone --no-checkout https://github.com/coneilen/zmx.git zmx-worktrees/attach
75-
git -C zmx-worktrees/attach checkout --detach 858727af10cdf43d66cb3733cff58dc90ec4b3dd
56+
run: ./Tools/windows/bootstrap.ps1 -ToolRoot .ci-tools -ProviderRoot .ci-providers
7657
- name: Run complete release gate
7758
shell: pwsh
78-
env:
79-
GRAPHCODE_WINGHOSTTY_ROOT: ${{ github.workspace }}\Winghostty-worktrees\host-integration
80-
GRAPHCODE_ZMX_ROOT: ${{ github.workspace }}\zmx-worktrees\attach
8159
run: ./Tools/windows/validate.ps1 -Task all
8260
- name: Run real hardening matrix after release products
8361
shell: pwsh
8462
env:
85-
GRAPHCODE_WINGHOSTTY_ROOT: ${{ github.workspace }}\Winghostty-worktrees\host-integration
86-
GRAPHCODE_ZMX_ROOT: ${{ github.workspace }}\zmx-worktrees\attach
8763
GRAPHCODE_HARDENING_TARGET: ${{ github.workspace }}\Tools\windows\Tests\EnvironmentFixture.ps1
8864
run: ./Tools/windows/Tests/Hardening.Tests.ps1 -Environment
8965

.github/workflows/windows-port-validation.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ on:
55
pull_request:
66
paths:
77
- ".github/workflows/windows-port-validation.yml"
8+
- "Package.swift"
9+
- "Package.resolved"
10+
- "MailroomKit/**"
811
- "GraphcodeKit/**"
12+
- "graphcode-cli/**"
13+
- "graphcoded/**"
14+
- "graphcode-windows/**"
15+
- "windows-tests/**"
916
- "Tools/windows/**"
1017
- "investigation/**"
1118

@@ -18,11 +25,9 @@ jobs:
1825
steps:
1926
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
2027

21-
- name: Install Swift 6.3.3
28+
- name: Bootstrap exact Windows dependencies
2229
shell: pwsh
23-
run: |
24-
winget install --id Swift.Toolchain --exact --version 6.3.3 `
25-
--silent --accept-package-agreements --accept-source-agreements
30+
run: ./Tools/windows/bootstrap.ps1 -ToolRoot .ci-tools -ProviderRoot .ci-providers
2631

2732
- name: Verify validation runner contract
2833
shell: pwsh

.github/workflows/windows-shell.yml

Lines changed: 10 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ on:
55
pull_request:
66
paths:
77
- ".github/workflows/windows-shell.yml"
8+
- "Package.swift"
9+
- "Package.resolved"
10+
- "MailroomKit/**"
11+
- "GraphcodeKit/**"
12+
- "graphcode-cli/**"
13+
- "graphcoded/**"
14+
- "windows-tests/**"
815
- "graphcode-windows/**"
16+
- "Tools/windows/bootstrap.ps1"
917
- "Tools/windows/windows-shell.ps1"
1018
- "Tools/windows/uia-live-gate.ps1"
1119
- "Tools/windows/validate.ps1"
@@ -29,59 +37,14 @@ jobs:
2937
steps:
3038
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
3139

32-
- name: Install exact Zig toolchains
40+
- name: Bootstrap exact Windows dependencies
3341
shell: pwsh
34-
run: |
35-
$ErrorActionPreference = "Stop"
36-
$toolRoot = Join-Path $env:GITHUB_WORKSPACE ".ci-tools"
37-
New-Item -ItemType Directory -Force -Path $toolRoot | Out-Null
38-
39-
function Install-Zig([string] $version, [string] $sha256) {
40-
$archive = Join-Path $toolRoot "zig-$version.zip"
41-
$directory = Join-Path $toolRoot "zig-$version"
42-
Invoke-WebRequest `
43-
-Uri "https://github.com/ziglang/zig/releases/download/$version/zig-x86_64-windows-$version.zip" `
44-
-OutFile $archive
45-
if ((Get-FileHash $archive -Algorithm SHA256).Hash -ne $sha256) {
46-
throw "Zig $version archive checksum mismatch"
47-
}
48-
Expand-Archive -LiteralPath $archive -DestinationPath $toolRoot -Force
49-
$expanded = Join-Path $toolRoot "zig-x86_64-windows-$version"
50-
Move-Item -LiteralPath $expanded -Destination $directory -Force
51-
return (Join-Path $directory "zig.exe")
52-
}
53-
54-
$zig0152 = Install-Zig `
55-
"0.15.2" `
56-
"3A0ED1E8799A2F8CE2A6E6290A9FF22E6906F8227865911FB7DDEDC3CC14CB0C"
57-
$zig0160 = Install-Zig `
58-
"0.16.0" `
59-
"68659EB5F1E4EB1437A722F1DD889C5A322C9954607F5EDCF337BC3684A75A7E"
60-
"GRAPHCODE_ZIG0152=$zig0152" >> $env:GITHUB_ENV
61-
"GRAPHCODE_ZIG0160=$zig0160" >> $env:GITHUB_ENV
62-
63-
- name: Checkout exact Winghostty provider
64-
shell: pwsh
65-
run: |
66-
git clone --no-checkout https://github.com/coneilen/winghostty.git Winghostty-worktrees/host-integration
67-
git -C Winghostty-worktrees/host-integration checkout --detach f5abc059e4ca58b376eb209313aca7784659c679
68-
69-
- name: Checkout exact zmx provider
70-
shell: pwsh
71-
run: |
72-
git clone --no-checkout https://github.com/coneilen/zmx.git zmx-worktrees/attach
73-
git -C zmx-worktrees/attach checkout --detach 858727af10cdf43d66cb3733cff58dc90ec4b3dd
42+
run: ./Tools/windows/bootstrap.ps1 -ToolRoot .ci-tools -ProviderRoot .ci-providers
7443

7544
- name: Verify shell contracts and pinned-provider smoke
7645
shell: pwsh
77-
env:
78-
GRAPHCODE_WINGHOSTTY_ROOT: ${{ github.workspace }}\Winghostty-worktrees\host-integration
79-
GRAPHCODE_ZMX_ROOT: ${{ github.workspace }}\zmx-worktrees\attach
8046
run: ./Tools/windows/validate.ps1 -Task windows-shell
8147

8248
- name: Validate release packaging
8349
shell: pwsh
84-
env:
85-
GRAPHCODE_WINGHOSTTY_ROOT: ${{ github.workspace }}\Winghostty-worktrees\host-integration
86-
GRAPHCODE_ZMX_ROOT: ${{ github.workspace }}\zmx-worktrees\attach
8750
run: ./Tools/windows/validate.ps1 -Task packaging

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ xcuserdata/
2222
# Zig build outputs
2323
.zig-cache/
2424
zig-out/
25+
.graphcode-tools/
26+
.ci-tools/
27+
.ci-providers/
2528

2629
# mise
2730
.mise.local.toml
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#if os(Windows)
2+
public actor AwakeAssertion {
3+
public static let shared = AwakeAssertion()
4+
5+
public static func shouldStayAwake(runningLoops: Int, enabled: Bool) -> Bool {
6+
enabled && runningLoops > 0
7+
}
8+
9+
public func apply(shouldHold: Bool, runningLoops: Int) {}
10+
}
11+
#endif

GraphcodeKit/Sources/Sessions/SessionTransplant.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,15 @@ public enum SessionTransplant {
196196
/// `/private` prefixes unresolved and produced the wrong directory for exactly
197197
/// those paths.
198198
static func claudeProjectSlug(forWorkingDirectory path: String) -> String {
199-
var buffer = [CChar](repeating: 0, count: Int(PATH_MAX))
200-
let resolved = path.withCString { realpath($0, &buffer).map { String(cString: $0) } } ?? path
201-
return String(resolved.map { $0.isLetter || $0.isNumber ? $0 : "-" })
199+
#if os(Windows)
200+
let resolved =
201+
URL(fileURLWithPath: path).standardizedFileURL.resolvingSymlinksInPath().path
202+
#else
203+
var buffer = [CChar](repeating: 0, count: Int(PATH_MAX))
204+
let resolved =
205+
path.withCString { realpath($0, &buffer).map { String(cString: $0) } } ?? path
206+
#endif
207+
return resolved.map { $0.isLetter || $0.isNumber ? String($0) : "-" }.joined()
202208
}
203209

204210
private static func findClaudeTranscript(sessionID: String) -> URL? {

Package.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,35 @@ let graphcodeKitTarget: Target = .target(
2020
"IPC",
2121
"Platform",
2222
"DaemonBootstrap.swift",
23+
"GraphExportBundle.swift",
24+
"GraphExportBundle+ZIP.swift",
2325
"GraphStore.swift",
2426
"QuickChatStore.swift",
2527
"Sessions/QuickChatSessionRegistry.swift",
2628
"ProjectPersistence.swift",
29+
"ProjectPersistence+Export.swift",
2730
"ProjectRegistry.swift",
2831
"SupportDirectory.swift",
2932
"Sessions/MessageBus.swift",
3033
"Sessions/NodeMemory.swift",
3134
"GraphcodeSettingsStore.swift",
3235
"Sessions/AgentEnvironment.swift",
3336
"Sessions/CLISessionBackend.swift",
37+
"Sessions/ClaudeSessionLog.swift",
3438
"Sessions/CodexSessionLog.swift",
3539
"Sessions/CopilotSessionLog.swift",
40+
"Sessions/CopilotTrust.swift",
41+
"Sessions/OpenCodePresencePlugin.swift",
3642
"Sessions/RemoteEnsureGate.swift",
3743
"Sessions/RemoteGraphAccess.swift",
3844
"Sessions/RemoteSocketForwarder.swift",
45+
"Sessions/RemoteTranscriptProbe.swift",
3946
"Sessions/SessionIDStore.swift",
47+
"Sessions/SessionTransplant.swift",
4048
"Sessions/ShellPredicateEvaluator.swift",
49+
"Sessions/SummaryBeatBuilder.swift",
50+
"Sessions/SummaryModelWriter.swift",
51+
"Sessions/TranscriptFreshness.swift",
4152
"Sessions/WindowsPTYProcessSession.swift",
4253
"Sessions/ZmxSessionLauncher.swift",
4354
"Sessions/PresenceHooks.swift",

Tools/windows/Tests/TerminalGate.Tests.ps1

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ Assert-Contract ($pins.schemaVersion -eq 1) "provider pin schema is not 1"
4242
Assert-Contract ($pins.winghostty.sha -eq
4343
"f5abc059e4ca58b376eb209313aca7784659c679") "Winghostty SHA is not exact"
4444
Assert-Contract ($pins.zmx.sha -eq
45-
"858727af10cdf43d66cb3733cff58dc90ec4b3dd") "zmx SHA is not exact"
45+
"029e11d2b19162fb3bdf90c8270237d303b8bfb4") "zmx SHA is not exact"
4646
Assert-Contract ($pins.winghostty.remoteUrl -eq
47-
"https://github.com/coneilen/winghostty.git") "Winghostty remote URL is not stable"
47+
"https://github.com/coneilen_microsoft/winghostty.git") "Winghostty remote URL is not stable"
4848
Assert-Contract ($pins.zmx.remoteUrl -eq
49-
"https://github.com/coneilen/zmx.git") "zmx remote URL is not stable"
50-
Assert-Contract ([bool] $pins.localFallback.enabled) "local fallback is not documented"
51-
Assert-Contract ($pins.localFallback.remoteWorkflowBlocked -eq $true) `
52-
"remote workflow scope blocker is not recorded"
49+
"https://github.com/coneilen_microsoft/zmx.git") "zmx remote URL is not stable"
50+
Assert-Contract (-not [bool] $pins.localFallback.enabled) "local fallback remains enabled"
51+
Assert-Contract ($pins.localFallback.remoteWorkflowBlocked -eq $false) `
52+
"remote workflow scope remains blocked"
5353
foreach ($localPath in @($pins.localFallback.paths)) {
5454
Assert-Contract ($localPath -notmatch "^[A-Za-z]:\\") `
5555
"provider metadata contains an environment-specific absolute path"

Tools/windows/Tests/ValidationRunner.Tests.ps1

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,16 @@ try {
6767
}
6868

6969
$windowsWorkflow = Get-Content (Join-Path $repoRoot ".github\workflows\windows-hardening.yml") -Raw
70-
if ($windowsWorkflow -notmatch "(?s)full-pinned:.*GRAPHCODE_ZMX_ROOT.*validate\.ps1 -Task all.*Hardening\.Tests\.ps1 -Environment") {
70+
if ($windowsWorkflow -notmatch "(?s)full-pinned:.*bootstrap\.ps1.*validate\.ps1 -Task all.*Hardening\.Tests\.ps1 -Environment") {
7171
throw "RED: full-pinned Windows CI does not run real hardening after provider setup"
7272
}
7373
if ($windowsWorkflow -notmatch "GRAPHCODE_HARDENING_TARGET") {
7474
throw "RED: full-pinned Windows CI does not provide an owned environment harness"
7575
}
7676
$windowsShellWorkflow = Get-Content (Join-Path $repoRoot ".github\workflows\windows-shell.yml") -Raw
77+
if ($windowsShellWorkflow -notmatch "bootstrap\.ps1") {
78+
throw "RED: Windows shell CI does not bootstrap exact dependencies"
79+
}
7780
if ($windowsShellWorkflow -notmatch "Tools/windows/uia-live-gate\.ps1") {
7881
throw "RED: Windows shell CI does not include the UI Automation live gate"
7982
}

Tools/windows/Tests/WindowsShell.Tests.ps1

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,12 @@ Assert-Contract ($pins.winghostty.sha -eq
139139
Assert-Contract ($pins.zmx.sha -eq
140140
"029e11d2b19162fb3bdf90c8270237d303b8bfb4") "zmx pin changed"
141141
Assert-Contract ($pins.winghostty.remoteUrl -eq
142-
"https://github.com/coneilen/winghostty.git") "Winghostty remote URL changed"
142+
"https://github.com/coneilen_microsoft/winghostty.git") "Winghostty remote URL changed"
143143
Assert-Contract ($pins.zmx.remoteUrl -eq
144-
"https://github.com/coneilen/zmx.git") "zmx remote URL changed"
145-
Assert-Contract ($pins.localFallback.enabled) "local provider fallback is undocumented"
144+
"https://github.com/coneilen_microsoft/zmx.git") "zmx remote URL changed"
145+
Assert-Contract (-not $pins.localFallback.enabled) "local provider fallback remains enabled"
146+
Assert-Contract (-not $pins.localFallback.remoteWorkflowBlocked) `
147+
"remote provider workflow remains blocked"
146148

147149
$metadata = Get-Content -LiteralPath (Join-Path $shellRoot "package-metadata.json") -Raw |
148150
ConvertFrom-Json

0 commit comments

Comments
 (0)