From 0a73162d14e09bf41d0006394260eee325bf5188 Mon Sep 17 00:00:00 2001
From: bigboateng
Date: Wed, 22 Jul 2026 14:07:08 +0100
Subject: [PATCH 1/5] Add Windows Pitot agent E2E coverage
---
.github/scripts/pitot_e2e_report.py | 11 ++++---
.github/workflows/pitot-e2e-agent.yml | 12 +++++--
.../15-pitot/pitot-distribution/UPSTREAM.json | 2 +-
.../2026-07-22-windows-agent-e2e.md | 3 ++
labs/15-pitot/public-readme-preview/README.md | 2 +-
labs/15-pitot/tests/e2e_unified_runner.sh | 15 ++++++---
labs/15-pitot/tests/run_e2e_report.py | 2 +-
labs/15-pitot/tests/test_e2e_reporting.py | 32 +++++++++++++++++--
8 files changed, 62 insertions(+), 17 deletions(-)
create mode 100644 labs/15-pitot/pitot-distribution/release-notes/2026-07-22-windows-agent-e2e.md
diff --git a/.github/scripts/pitot_e2e_report.py b/.github/scripts/pitot_e2e_report.py
index a9a2dc9b7..649538fb9 100644
--- a/.github/scripts/pitot_e2e_report.py
+++ b/.github/scripts/pitot_e2e_report.py
@@ -22,7 +22,7 @@
"gemini": "Pitot E2E — Gemini",
"opencode": "Pitot E2E — OpenCode",
}
-PLATFORMS = ("ubuntu", "macos")
+PLATFORMS = ("ubuntu", "macos", "windows")
MAX_ARTIFACT_BYTES = 1_000_000
@@ -118,8 +118,8 @@ def render_comment(
"",
"Intelligence Flow is the verification source; Pitot's public README carries the latest `main` status.",
"",
- "| Agent | Ubuntu | macOS | Result | Evidence |",
- "|---|---|---|---|---|",
+ "| Agent | Ubuntu | macOS | Windows | Result | Evidence |",
+ "|---|---|---|---|---|---|",
]
icons = {"passing": "✅ Passing", "failing": "❌ Failing", "pending": "⏳ Pending"}
for agent in WORKFLOWS:
@@ -128,10 +128,11 @@ def render_comment(
url = run_urls.get(agent)
label = agent.capitalize() if agent != "opencode" else "OpenCode"
linked_label = f"[{label}]({url})" if url else label
- evidence = "Both platforms are required" if status != "pending" else "Waiting for both platform artifacts"
+ evidence = "All platforms are required" if status != "pending" else "Waiting for all platform artifacts"
lines.append(
f"| {linked_label} | {result_cell(platforms.get('ubuntu'))} | "
- f"{result_cell(platforms.get('macos'))} | {icons[status]} | {evidence} |"
+ f"{result_cell(platforms.get('macos'))} | {result_cell(platforms.get('windows'))} | "
+ f"{icons[status]} | {evidence} |"
)
lines.extend(["", f"Source commit: `{head_sha[:12]}`", ""])
return "\n".join(lines)
diff --git a/.github/workflows/pitot-e2e-agent.yml b/.github/workflows/pitot-e2e-agent.yml
index 6d8b4bd01..f37b2f22a 100644
--- a/.github/workflows/pitot-e2e-agent.yml
+++ b/.github/workflows/pitot-e2e-agent.yml
@@ -25,6 +25,8 @@ jobs:
platform: ubuntu
- runner: macos-latest
platform: macos
+ - runner: windows-latest
+ platform: windows
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v7
@@ -35,12 +37,16 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: "20"
+ - uses: actions/setup-python@v6
+ with:
+ python-version: "3.11"
- name: Install Claude CLI
if: inputs.agent == 'claude'
shell: bash
run: |
npm install -g "@anthropic-ai/claude-code@$CLAUDE_CLI_VERSION"
- claude_bin="$(npm prefix -g)/bin/claude"
+ claude_bin="$(command -v claude)"
+ [[ -n "$claude_bin" ]]
installed_version="$("$claude_bin" --version)"
echo "Using $claude_bin ($installed_version)"
[[ "$installed_version" == "$CLAUDE_CLI_VERSION"* ]]
@@ -49,7 +55,7 @@ jobs:
if: inputs.agent == 'codex'
run: npm install -g @openai/codex
- name: Install Cursor CLI
- if: inputs.agent == 'cursor'
+ if: inputs.agent == 'cursor' && runner.os != 'Windows'
run: curl https://cursor.com/install -fsS | bash
- name: Run ${{ inputs.agent }} E2E
id: e2e
@@ -59,7 +65,7 @@ jobs:
env:
PITOT_SOURCE_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: >-
- python3 labs/15-pitot/tests/run_e2e_report.py
+ python labs/15-pitot/tests/run_e2e_report.py
--agent "${{ inputs.agent }}"
--platform "${{ matrix.platform }}"
--output "${{ runner.temp }}/pitot-e2e/result.json"
diff --git a/labs/15-pitot/pitot-distribution/UPSTREAM.json b/labs/15-pitot/pitot-distribution/UPSTREAM.json
index 488c9bcd7..d0e55c282 100644
--- a/labs/15-pitot/pitot-distribution/UPSTREAM.json
+++ b/labs/15-pitot/pitot-distribution/UPSTREAM.json
@@ -1,7 +1,7 @@
{
"files": {
"CONTRIBUTING.md": "0613b71aa497f8ca7d7296bf34ade87bfc7237a664d2e812d9b77b3b6befb0ad",
- "README.md": "ae604a6d27656532985838f9a988e163652c568bb3d2d110c413b86527f77f10",
+ "README.md": "20cacdc35bd17d34c8451f8eb87b8bb7a788ca3d3c6c1283e36bfc901f0a4479",
"adapters/adapters.go": "0d5b03d3e8fd1f302a7b92781038500c8df9a3e3b6eb9e08b243169cda1d81c4",
"assets/pitot-boundary.png": "8a0ddb7d81831d94e14813f50ea4ca8670d77417f339ed2f91f0c653bf52f41d",
"assets/pitot-boundary.svg": "0c3871d70c84748573f231842091deb38a6def2862403ca34e8cc4493b9c9ebf",
diff --git a/labs/15-pitot/pitot-distribution/release-notes/2026-07-22-windows-agent-e2e.md b/labs/15-pitot/pitot-distribution/release-notes/2026-07-22-windows-agent-e2e.md
new file mode 100644
index 000000000..61129844c
--- /dev/null
+++ b/labs/15-pitot/pitot-distribution/release-notes/2026-07-22-windows-agent-e2e.md
@@ -0,0 +1,3 @@
+### Verify every coding-agent integration on Windows
+
+Pitot's per-agent E2E matrix and pull-request report now require Windows alongside Ubuntu and macOS. Windows results use the same structured, commit-bound evidence artifacts, while host setup preserves real CLI verification where supported and the existing active-hook subprocess boundary where a Windows CLI installer is unavailable.
diff --git a/labs/15-pitot/public-readme-preview/README.md b/labs/15-pitot/public-readme-preview/README.md
index c7c990042..ae4306338 100644
--- a/labs/15-pitot/public-readme-preview/README.md
+++ b/labs/15-pitot/public-readme-preview/README.md
@@ -14,7 +14,7 @@
-Verified upstream in Intelligence Flow on Ubuntu and macOS.
+Verified upstream in Intelligence Flow on Ubuntu, macOS, and Windows.
One language-neutral boundary for Claude Code, Cursor, Codex, Gemini, OpenCode, and compatible runtimes.
diff --git a/labs/15-pitot/tests/e2e_unified_runner.sh b/labs/15-pitot/tests/e2e_unified_runner.sh
index 20f2dcf8a..ce0575ed6 100755
--- a/labs/15-pitot/tests/e2e_unified_runner.sh
+++ b/labs/15-pitot/tests/e2e_unified_runner.sh
@@ -12,7 +12,11 @@ echo "===> [E2E] Starting $HOST + Pitot Hook Integration Test"
# 1. Compile the local Go 'pitot' binary
echo "===> Compiling pitot binary..."
-go build -o labs/15-pitot/tests/pitot labs/15-pitot/pitot/cmd/pitot/main.go
+PITOT_BINARY="labs/15-pitot/tests/pitot"
+if [ "${RUNNER_OS:-}" = "Windows" ]; then
+ PITOT_BINARY="${PITOT_BINARY}.exe"
+fi
+go build -o "$PITOT_BINARY" labs/15-pitot/pitot/cmd/pitot/main.go
# 2. Host-specific setup and mocking
SERVER_PID=""
@@ -24,7 +28,7 @@ cleanup() {
if [ -n "$SERVER_PID" ]; then
kill "$SERVER_PID" 2>/dev/null || true
fi
- rm -f labs/15-pitot/tests/pitot
+ rm -f "$PITOT_BINARY"
if [ -n "${MOCK_HOME:-}" ]; then
rm -rf "$MOCK_HOME"
fi
@@ -44,8 +48,11 @@ fi
CODEX_PATH="" # Codex CLI path placeholder
-# Get absolute path of the compiled pitot binary
-PITOT_ABS_PATH=$(pwd)/labs/15-pitot/tests/pitot
+# Get an absolute path that the host process can execute on each runner OS.
+PITOT_ABS_PATH="$(pwd)/$PITOT_BINARY"
+if [ "${RUNNER_OS:-}" = "Windows" ] && command -v cygpath &>/dev/null; then
+ PITOT_ABS_PATH="$(cygpath -m "$PITOT_ABS_PATH")"
+fi
# Spin up mock API server on port 8080 for all tests
echo "===> Starting local mock API server..."
diff --git a/labs/15-pitot/tests/run_e2e_report.py b/labs/15-pitot/tests/run_e2e_report.py
index 86364735d..dc58cc5c7 100644
--- a/labs/15-pitot/tests/run_e2e_report.py
+++ b/labs/15-pitot/tests/run_e2e_report.py
@@ -13,7 +13,7 @@
AGENTS = {"claude", "cursor", "codex", "gemini", "opencode"}
-PLATFORMS = {"ubuntu", "macos"}
+PLATFORMS = {"ubuntu", "macos", "windows"}
RESULT_PATTERN = re.compile(r"^PITOT_E2E_RESULT mode=(real_cli|hook_subprocess)$", re.MULTILINE)
diff --git a/labs/15-pitot/tests/test_e2e_reporting.py b/labs/15-pitot/tests/test_e2e_reporting.py
index 5ece87435..3726e2067 100644
--- a/labs/15-pitot/tests/test_e2e_reporting.py
+++ b/labs/15-pitot/tests/test_e2e_reporting.py
@@ -59,6 +59,11 @@ def test_hook_marker_passes(self):
self.assertEqual(result["status"], "pass")
self.assertEqual(result["verification_mode"], "hook_subprocess")
+ def test_windows_result_is_supported(self):
+ result = runner.result_for("opencode", "windows", 0, "PITOT_E2E_RESULT mode=hook_subprocess\n")
+ self.assertEqual(result["platform"], "windows")
+ self.assertEqual(result["status"], "pass")
+
def test_missing_or_duplicate_marker_fails(self):
self.assertEqual(runner.result_for("codex", "ubuntu", 0, "ok\n")["status"], "fail")
duplicate = "PITOT_E2E_RESULT mode=real_cli\n" * 2
@@ -71,6 +76,13 @@ def test_nonzero_command_fails_even_with_marker(self):
class ReporterContractTests(unittest.TestCase):
+ def test_workflow_matrix_covers_every_reported_platform(self):
+ workflow = (ROOT / ".github/workflows/pitot-e2e-agent.yml").read_text()
+ runners = {"ubuntu": "ubuntu-latest", "macos": "macos-latest", "windows": "windows-latest"}
+ self.assertEqual(set(reporter.PLATFORMS), set(runner.PLATFORMS))
+ for platform, image in runners.items():
+ self.assertIn(f"runner: {image}\n platform: {platform}", workflow)
+
def test_validates_exact_artifact_schema(self):
value = _result()
self.assertIs(reporter.validate_result(value, agent="claude", platform="ubuntu"), value)
@@ -99,13 +111,24 @@ def test_rejects_untrusted_commit_and_run_url(self):
with self.assertRaises(ValueError):
reporter.validate_result(value, agent="claude", platform="ubuntu")
- def test_aggregate_requires_both_platforms(self):
+ def test_aggregate_requires_all_platforms(self):
self.assertEqual(reporter.aggregate({"ubuntu": _result(), "macos": None}), "pending")
self.assertEqual(
reporter.aggregate(
{
"ubuntu": _result(),
"macos": _result(platform="macos", mode="hook_subprocess"),
+ "windows": None,
+ }
+ ),
+ "pending",
+ )
+ self.assertEqual(
+ reporter.aggregate(
+ {
+ "ubuntu": _result(),
+ "macos": _result(platform="macos", mode="hook_subprocess"),
+ "windows": _result(platform="windows", mode="hook_subprocess"),
}
),
"passing",
@@ -115,6 +138,7 @@ def test_aggregate_requires_both_platforms(self):
{
"ubuntu": _result(),
"macos": _result(platform="macos", status="fail", mode=None),
+ "windows": _result(platform="windows", mode="hook_subprocess"),
}
),
"failing",
@@ -122,16 +146,20 @@ def test_aggregate_requires_both_platforms(self):
def test_rendered_comment_is_sticky_and_shows_modes(self):
results = {
- agent: {"ubuntu": None, "macos": None} for agent in reporter.WORKFLOWS
+ agent: {platform: None for platform in reporter.PLATFORMS}
+ for agent in reporter.WORKFLOWS
}
results["claude"] = {
"ubuntu": _result(),
"macos": _result(platform="macos", mode="hook_subprocess"),
+ "windows": _result(platform="windows", mode="hook_subprocess"),
}
body = reporter.render_comment(results, {"claude": "https://example.test/run"}, "b" * 40)
self.assertIn(reporter.MARKER, body)
self.assertIn("Pass · real CLI", body)
self.assertIn("Pass · hook verified", body)
+ self.assertIn("Windows", body)
+ self.assertIn("All platforms are required", body)
self.assertIn("OpenCode", body)
From 0b0d9d042a8248cbaea616a12d03fa6e3b84864d Mon Sep 17 00:00:00 2001
From: bigboateng
Date: Wed, 22 Jul 2026 14:12:08 +0100
Subject: [PATCH 2/5] Fix Windows Pitot Bash resolution
---
.github/workflows/pitot-e2e-agent.yml | 10 +++++++++-
labs/15-pitot/tests/test_e2e_reporting.py | 3 +++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/pitot-e2e-agent.yml b/.github/workflows/pitot-e2e-agent.yml
index f37b2f22a..0ba379853 100644
--- a/.github/workflows/pitot-e2e-agent.yml
+++ b/.github/workflows/pitot-e2e-agent.yml
@@ -40,6 +40,14 @@ jobs:
- uses: actions/setup-python@v6
with:
python-version: "3.11"
+ - name: Resolve Bash runtime
+ shell: bash
+ run: |
+ bash_path="$(command -v bash)"
+ if [[ "${{ runner.os }}" == "Windows" ]]; then
+ bash_path="$(cygpath -m "$bash_path")"
+ fi
+ echo "PITOT_BASH=$bash_path" >> "$GITHUB_ENV"
- name: Install Claude CLI
if: inputs.agent == 'claude'
shell: bash
@@ -69,7 +77,7 @@ jobs:
--agent "${{ inputs.agent }}"
--platform "${{ matrix.platform }}"
--output "${{ runner.temp }}/pitot-e2e/result.json"
- -- bash "labs/15-pitot/tests/e2e_${{ inputs.agent }}_cli_test.sh"
+ -- "$PITOT_BASH" "labs/15-pitot/tests/e2e_${{ inputs.agent }}_cli_test.sh"
< /dev/null
- name: Upload structured E2E result
if: always()
diff --git a/labs/15-pitot/tests/test_e2e_reporting.py b/labs/15-pitot/tests/test_e2e_reporting.py
index 3726e2067..ef05da19e 100644
--- a/labs/15-pitot/tests/test_e2e_reporting.py
+++ b/labs/15-pitot/tests/test_e2e_reporting.py
@@ -82,6 +82,9 @@ def test_workflow_matrix_covers_every_reported_platform(self):
self.assertEqual(set(reporter.PLATFORMS), set(runner.PLATFORMS))
for platform, image in runners.items():
self.assertIn(f"runner: {image}\n platform: {platform}", workflow)
+ self.assertIn('bash_path="$(cygpath -m "$bash_path")"', workflow)
+ self.assertIn('-- "$PITOT_BASH"', workflow)
+ self.assertNotIn('-- bash "labs/15-pitot/tests/e2e_', workflow)
def test_validates_exact_artifact_schema(self):
value = _result()
From 41fd72d77840f7d27b24e889604d3c2c5269e60e Mon Sep 17 00:00:00 2001
From: bigboateng
Date: Wed, 22 Jul 2026 14:14:22 +0100
Subject: [PATCH 3/5] Handle Windows agent output encoding
---
labs/15-pitot/tests/run_e2e_report.py | 9 ++++++++-
labs/15-pitot/tests/test_e2e_reporting.py | 22 ++++++++++++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/labs/15-pitot/tests/run_e2e_report.py b/labs/15-pitot/tests/run_e2e_report.py
index dc58cc5c7..a483c06b9 100644
--- a/labs/15-pitot/tests/run_e2e_report.py
+++ b/labs/15-pitot/tests/run_e2e_report.py
@@ -66,7 +66,14 @@ def main() -> int:
if not command:
parser.error("a command is required after --")
- completed = subprocess.run(command, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ completed = subprocess.run(
+ command,
+ text=True,
+ encoding="utf-8",
+ errors="replace",
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
sys.stdout.write(completed.stdout)
result = result_for(args.agent, args.platform, completed.returncode, completed.stdout)
args.output.parent.mkdir(parents=True, exist_ok=True)
diff --git a/labs/15-pitot/tests/test_e2e_reporting.py b/labs/15-pitot/tests/test_e2e_reporting.py
index ef05da19e..8ff2849b0 100644
--- a/labs/15-pitot/tests/test_e2e_reporting.py
+++ b/labs/15-pitot/tests/test_e2e_reporting.py
@@ -3,6 +3,8 @@
import importlib.util
from pathlib import Path
import subprocess
+import sys
+import tempfile
import unittest
@@ -74,6 +76,26 @@ def test_nonzero_command_fails_even_with_marker(self):
self.assertEqual(result["status"], "fail")
self.assertIsNone(result["verification_mode"])
+ def test_runner_replaces_non_utf8_command_output(self):
+ with tempfile.TemporaryDirectory() as temp:
+ output = Path(temp) / "result.json"
+ completed = subprocess.run(
+ [
+ sys.executable,
+ str(ROOT / "labs/15-pitot/tests/run_e2e_report.py"),
+ "--agent", "claude",
+ "--platform", "windows",
+ "--output", str(output),
+ "--",
+ sys.executable,
+ "-c", "import sys; sys.stdout.buffer.write(b'\\x96')",
+ ],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ self.assertNotEqual(completed.returncode, 0)
+ self.assertTrue(output.is_file())
+
class ReporterContractTests(unittest.TestCase):
def test_workflow_matrix_covers_every_reported_platform(self):
From 6bb826bc57e24bc9ea055c4980292384ad48b757 Mon Sep 17 00:00:00 2001
From: bigboateng
Date: Wed, 22 Jul 2026 14:16:03 +0100
Subject: [PATCH 4/5] Write Windows agent logs as UTF-8
---
labs/15-pitot/tests/run_e2e_report.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/labs/15-pitot/tests/run_e2e_report.py b/labs/15-pitot/tests/run_e2e_report.py
index a483c06b9..157d7901b 100644
--- a/labs/15-pitot/tests/run_e2e_report.py
+++ b/labs/15-pitot/tests/run_e2e_report.py
@@ -74,7 +74,7 @@ def main() -> int:
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
- sys.stdout.write(completed.stdout)
+ sys.stdout.buffer.write(completed.stdout.encode("utf-8", errors="replace"))
result = result_for(args.agent, args.platform, completed.returncode, completed.stdout)
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(json.dumps(result, indent=2, sort_keys=True) + "\n", encoding="utf-8")
From 980600ac2871c2764a764be3bbcf3e229ac5f393 Mon Sep 17 00:00:00 2001
From: bigboateng
Date: Wed, 22 Jul 2026 14:18:56 +0100
Subject: [PATCH 5/5] Fix Pitot artifact download redirects
---
.github/scripts/pitot_e2e_report.py | 17 ++++++++++++-
labs/15-pitot/tests/test_e2e_reporting.py | 29 +++++++++++++++++++++++
2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/.github/scripts/pitot_e2e_report.py b/.github/scripts/pitot_e2e_report.py
index 649538fb9..0fd008ff1 100644
--- a/.github/scripts/pitot_e2e_report.py
+++ b/.github/scripts/pitot_e2e_report.py
@@ -26,6 +26,20 @@
MAX_ARTIFACT_BYTES = 1_000_000
+class ArtifactRedirectHandler(urllib.request.HTTPRedirectHandler):
+ def redirect_request(self, request, file_pointer, code, message, headers, new_url):
+ redirected = super().redirect_request(request, file_pointer, code, message, headers, new_url)
+ if redirected is None:
+ return None
+ source = urllib.parse.urlparse(request.full_url)
+ target = urllib.parse.urlparse(new_url)
+ if target.scheme != "https":
+ raise ValueError("artifact redirect must use HTTPS")
+ if source.netloc != target.netloc:
+ redirected.remove_header("Authorization")
+ return redirected
+
+
def validate_result(
value: object,
*,
@@ -167,7 +181,8 @@ def download(self, url: str) -> bytes:
url,
headers={"Authorization": f"Bearer {self.token}", "User-Agent": "pitot-e2e-reporter"},
)
- with urllib.request.urlopen(request, timeout=30) as response:
+ opener = urllib.request.build_opener(ArtifactRedirectHandler())
+ with opener.open(request, timeout=30) as response:
data = response.read(MAX_ARTIFACT_BYTES + 1)
if len(data) > MAX_ARTIFACT_BYTES:
raise ValueError("artifact exceeds size limit")
diff --git a/labs/15-pitot/tests/test_e2e_reporting.py b/labs/15-pitot/tests/test_e2e_reporting.py
index 8ff2849b0..f64d204b0 100644
--- a/labs/15-pitot/tests/test_e2e_reporting.py
+++ b/labs/15-pitot/tests/test_e2e_reporting.py
@@ -6,6 +6,7 @@
import sys
import tempfile
import unittest
+import urllib.request
ROOT = Path(__file__).resolve().parents[3]
@@ -98,6 +99,34 @@ def test_runner_replaces_non_utf8_command_output(self):
class ReporterContractTests(unittest.TestCase):
+ def test_artifact_redirect_strips_cross_host_credentials(self):
+ request = urllib.request.Request(
+ "https://api.github.com/repos/operatorstack/intelligence-flow/actions/artifacts/1/zip",
+ headers={"Authorization": "Bearer secret"},
+ )
+ redirected = reporter.ArtifactRedirectHandler().redirect_request(
+ request,
+ None,
+ 302,
+ "Found",
+ {},
+ "https://artifact.example.test/signed.zip",
+ )
+ self.assertIsNotNone(redirected)
+ self.assertIsNone(redirected.get_header("Authorization"))
+
+ def test_artifact_redirect_rejects_http_downgrade(self):
+ request = urllib.request.Request("https://api.github.com/artifact")
+ with self.assertRaisesRegex(ValueError, "must use HTTPS"):
+ reporter.ArtifactRedirectHandler().redirect_request(
+ request,
+ None,
+ 302,
+ "Found",
+ {},
+ "http://artifact.example.test/signed.zip",
+ )
+
def test_workflow_matrix_covers_every_reported_platform(self):
workflow = (ROOT / ".github/workflows/pitot-e2e-agent.yml").read_text()
runners = {"ubuntu": "ubuntu-latest", "macos": "macos-latest", "windows": "windows-latest"}