Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
189 commits
Select commit Hold shift + click to select a range
d061fda
docs(adr): reopen the Go runtime as an incremental sidecar takeover
Sep 5, 2026
4b8715a
feat(go): land the ADR-0008 first increment — ocx-sidecar health seam…
Sep 5, 2026
05c1275
ci(go): force CGO_ENABLED=0 on the go job per the ADR-0008 static-bui…
Sep 5, 2026
905182c
docs(go): record the Lab migrate-vs-cut owner decision (ticket #9) as…
Sep 5, 2026
6a9b621
feat(go): ticket #14 — typed read/write ownership + one registry-driv…
Sep 5, 2026
02bbba4
ci(go): cross-compile every release target in the go job (ticket #8)
Sep 5, 2026
148a51c
docs(go): record the #14 ownership-plumbing delivery and the #8/#11 c…
Sep 5, 2026
d238bcc
docs(go): close tickets #8-#14 and record the read-surface state-sour…
Sep 5, 2026
5dc6cae
feat(go): ticket #16 — shared Go config parsing + strict shadow-call-…
Sep 5, 2026
4c64d46
Go read-surface batches: strict custom-models route + ordered config …
Sep 6, 2026
8e4c0d5
Go management auth model + Lab activation gate/seam (#18, #19)
Sep 6, 2026
d27829e
feat(go): serve provider quota reads through sidecar
Sep 6, 2026
eb4292e
feat(go): relay management write batches through sidecar
Sep 6, 2026
3539951
docs(go): record the #24 hot-path seam design (devlog 034)
Sep 6, 2026
f8ab6d5
feat(go): ticket #24 — data-plane hot-path seam + streaming different…
Sep 6, 2026
befb594
test(config): cover invalid JSON recovery warning
Sep 6, 2026
e4d684d
docs(go): record the #26 write-surface parity gate design (devlog 035)
Sep 6, 2026
05f1e96
test(go): write-surface ownership verdicts + differential/authz oracl…
Sep 6, 2026
5088d79
docs(go): mark #26 write-surface parity gate implemented on dev-go
Sep 6, 2026
552d903
test(go): gate read-surface ownership matrix
Sep 6, 2026
d29a07e
feat(go): own model discovery read
Sep 6, 2026
e3c7953
Merge ticket #25 model discovery ownership
Sep 6, 2026
ddd383a
docs(go): record the #27 non-streaming relay design (devlog 036)
Sep 6, 2026
48951f2
feat(go): ordered-JSON wire with V8 number/string parity (jsonwire)
Sep 6, 2026
1ab98ca
feat(go): ticket #27 — non-streaming provider relay + field-backfill …
Sep 6, 2026
105a40e
test(ts): non-streaming relay differential + relay gate constant (#27)
Sep 6, 2026
296ea9a
Merge ticket #27 non-streaming relay + response repair
Sep 6, 2026
b6739a8
Ticket #35: add Go CLI local transport scaffold
Sep 6, 2026
566df20
feat(go): Ticket #28 WebSocket bridge parity
Sep 6, 2026
64a6186
Ticket #33: migrate literal Lab routes through Go
Sep 6, 2026
0798e8a
Merge ticket #28 WebSocket bridge parity
Sep 6, 2026
7235224
Merge ticket #33 Lab routes migration + differential
Sep 6, 2026
67dd04e
Merge ticket #35 Go CLI scaffold + local-HTTP transport + version parity
Sep 6, 2026
e4f4f84
feat(go): ticket #30 — hot-path routing decisions
Sep 6, 2026
e5b5ee3
docs(go): relocate #30 design record to the takeover plan series (040)
Sep 6, 2026
d021a1c
test(go): make ticket #30 routing oracle differential
Sep 6, 2026
7da5131
test(go): add CLI parity harness
Sep 6, 2026
9a264bb
docs(go): relocate #36 design record to the takeover plan series (041)
Sep 6, 2026
b608986
Merge ticket #30 hot-path routing decisions in Go
Sep 6, 2026
65c5aab
Merge ticket #36 CLI parity harness
Sep 6, 2026
8f377ff
feat(go): port config model provider inspection
Sep 6, 2026
c052a82
feat(go): add read-only CLI diagnostics slice
Sep 6, 2026
ee0e2c4
feat(go): register config model provider CLI families
Sep 6, 2026
89161bc
fix(go): preserve cli inspection parity
Sep 6, 2026
0d1c3b4
feat(go): relay narrow Responses SSE streams
Sep 6, 2026
1ef0937
test(go): admit narrow streaming relay fixture
Sep 6, 2026
9584069
fix(go): preserve relay and WebSocket parity
Sep 6, 2026
d3eb5c7
docs(go): clarify WebSocket bridge header boundary
Sep 6, 2026
0510818
feat(go): extend response repair pipeline parity
Sep 6, 2026
9304183
feat(go): extend response repair pipeline parity
Sep 6, 2026
218a5d9
feat(go): extend response repair pipeline parity
Sep 6, 2026
398ea1f
feat(go): add config CLI mutation workflows
Sep 6, 2026
bf6beea
feat(go): add shim and tray read-only CLI parity
Sep 6, 2026
4103128
feat(go): relay Azure responses-compatible adapters
Sep 6, 2026
7caeee7
feat(go): relay Azure responses-compatible adapters
Sep 6, 2026
c2bdd3b
feat(go): add durable provider and model mutations
Sep 6, 2026
f5e0716
feat(go): delegate lifecycle CLI parity to TypeScript
Sep 6, 2026
d128e1e
test(go): restore CLI lifecycle test imports
Sep 6, 2026
6a862d1
fix(go): align response reasoning repair admission
Sep 6, 2026
fbd60cf
fix(go): preserve reasoning response byte parity
Sep 6, 2026
779f45f
feat(go): complete models CLI parity slice
Sep 6, 2026
2fd24f4
feat(go): port provider CLI family
Sep 6, 2026
7c37c0d
feat(go): complete models CLI parity slice
Sep 6, 2026
b176d06
fix(go): delegate config family for exact parity
Sep 6, 2026
643ef4d
fix(go): route config family through parity owner
Sep 6, 2026
5f1283e
test(go): pin reasoning rewrite field parity
Sep 6, 2026
b035b15
fix(go): complete status doctor service parity
Sep 6, 2026
1f25b6a
fix(go): pin relay model fallthrough identity\n\nUnlisted model ids n…
Sep 6, 2026
1445551
feat(go): reconcile cli surface ownership map in ci
Sep 6, 2026
b85bcee
merge: issue39 cli surface ownership map
Sep 6, 2026
36a0c2c
ci(go): add cross-compile build matrix scaffold
Sep 6, 2026
1336897
feat(go): port config schema normalizer and ordered persistence
Sep 6, 2026
95df4cd
feat(go): port stateful response item id and snapshot repair
Sep 6, 2026
d46655d
fix(go): repair snapshot output fields
Sep 6, 2026
5d54d6a
feat(go): native config read dispatch
Sep 6, 2026
a6905ad
feat(go): add provider adapter relay parity
Sep 6, 2026
4678fac
feat(go): native codex-shim status
Sep 6, 2026
f7f799f
fix(go): preserve codex-shim status exit semantics
Sep 6, 2026
a812d43
feat(go): add config mutation coordinator
Sep 6, 2026
6561879
fix(go): close config write parity prerequisites
Sep 6, 2026
8578d46
test(go): cover remaining relay refusal classes
Sep 6, 2026
4e32b84
feat(go): add status diagnostic evidence seam
Sep 6, 2026
d8a8604
fix(go): match status health success range
Sep 6, 2026
34845bb
ci: run hot-path differentials on native platforms
Sep 6, 2026
22671ed
feat(go): stage strict config write schema
Sep 6, 2026
2cf58c8
feat(go): port proxy listen config diagnostics
Sep 6, 2026
64c434d
feat(go): cover strict config write schema
Sep 6, 2026
18400c5
feat(go): port status dashboard runtime diagnostics
Sep 6, 2026
d95b13e
test(go): cover successful quota consume parity
Sep 6, 2026
1b89d83
feat(go): port extra status domains
Sep 6, 2026
b66ade8
feat(go): port external status diagnostics
Sep 6, 2026
a4ac77d
feat(go): own config write commands
Sep 6, 2026
6c78115
test(go): diff native config write commands
Sep 6, 2026
0fa7e6a
fix(go): match config unset error output
Sep 6, 2026
5fb21cb
feat(go): own config get command
Sep 6, 2026
f194206
feat(go): port doctor path and proxy probes
Sep 6, 2026
a726d76
test(go): assemble status JSON oracle
Sep 6, 2026
9d81b4e
feat(go): port more doctor probes
Sep 6, 2026
3f1aa43
feat(cli): make status Go-owned
Sep 6, 2026
b3ca944
feat(go): port remaining doctor probes
Sep 6, 2026
c1b6bda
feat(go): assemble doctor command baseline
Sep 6, 2026
beaebb1
feat(go): add deep doctor collectors
Sep 6, 2026
de85b7b
feat(go): assemble portable doctor probes
Sep 6, 2026
e4fdbe6
feat(go): port doctor memory history project probes
Sep 6, 2026
ca5eadc
feat(go): collect doctor oauth and catalog diagnostics
Sep 6, 2026
7648f73
feat(go): complete doctor diagnostics assembly
Sep 6, 2026
19927b3
feat(go): take ownership of doctor recovery
Sep 6, 2026
0eaffd3
feat(go): own usage aggregation read through sidecar
Sep 6, 2026
f62e8c2
test(go): cover config write relay failure parity
Sep 6, 2026
d04b010
test(go): strengthen account-pool mutation fail-safe parity
Sep 6, 2026
3bb4bd0
feat(go): embed dashboard in release binary
Sep 6, 2026
a574cab
feat(go): flip start to sole Go listener with port reclaim
Sep 7, 2026
310f25f
feat(go): flip start to sole Go listener with port reclaim
Sep 7, 2026
39aceb3
feat(go): add abort-safe SSE inspection lifecycle
Sep 7, 2026
35b84c7
feat(go): add graceful sidecar shutdown drain
Sep 7, 2026
b91906c
fix(go): align Responses relay parity edges
Sep 7, 2026
4bfd6c5
fix(go): complete runtime and model suffix parity
Sep 7, 2026
7881eda
Merge branch 'issue31' into dev-go
Sep 7, 2026
019539c
Merge branch 'issue32' into dev-go
Sep 7, 2026
d02dbf0
Merge branch 'issue41' into dev-go
Sep 7, 2026
61f7cc5
fix(go): guard process state by runtime identity
Sep 7, 2026
5a7cdc8
fix(go): embedded dashboard serves live gui/dist with thin fallback
Sep 7, 2026
0f12977
Merge branch 'issue-embedded-dashboard' into dev-go
Sep 7, 2026
3944e83
test(go): live-gateway hot-path differential harness (#34)
Sep 7, 2026
cd529df
feat(ci): activate Go release artifact gate with release-path verific…
Sep 7, 2026
5791df5
Merge branch 'issue-42' into dev-go
Sep 7, 2026
2acfa9e
test(go): upgrade-in-place + rollback drill with TS golden snapshot (…
Sep 7, 2026
182ff6a
Merge branch 'issue-43' into dev-go
Sep 7, 2026
fa8adea
feat(go): flip ocx usage + observe usage to Go-owned (issue #44 batch 1)
Sep 7, 2026
f437f8d
feat(go): flip ocx logout to Go-owned (issue #51)
Sep 7, 2026
61179e8
feat(go): flip alias, combo, and route to Go-owned (issue #49)
Sep 7, 2026
a2ace11
feat(go): flip debug, system, api-key, and access to Go-owned (issue …
Sep 7, 2026
1e4c437
feat(go): flip capabilities, observe, and export to Go-owned (issue #46)
Sep 7, 2026
e4b7a80
feat(go): flip the ocx account API-routing surface to Go-owned (issue…
Sep 7, 2026
6e70baa
feat(go): flip storage/agent/grok/integration/lab to Go-owned (issue …
Sep 7, 2026
9076f95
feat(go): flip ocx logs/memory/inspect reads to Go-owned (issue #45)
Sep 8, 2026
5177651
feat(go): flip sync/sync-cache to Go-owned (issue #50)
Sep 8, 2026
79302b9
test(go): pin management family no-proxy oracle rows (issue #47)
Sep 8, 2026
ae680ca
test(go): pin system codex-cli-update TypeScript carve-out (issue #47)
Sep 8, 2026
f4b6f31
fix(go): pin Bun-exact JSON5 escapes and harden parity harness types …
Sep 8, 2026
69e3a44
fix(go): summaryLines join renders null array elements empty (issue #45)
Sep 8, 2026
8fe31ad
feat(go): flip gui/zcode/mcode/mmx to Go-owned (issue #54)
Sep 8, 2026
e198e0d
fix(go): accept dash tokens as model positionals (issue #48 review)
Sep 8, 2026
ed8a2af
flip connect status + disconnect to Go-owned client state (issue #52)
Sep 8, 2026
c216467
fix(go): code-review pass over the sync/sync-cache flip (issue #50)
Sep 8, 2026
4beba0a
refactor(go): centralize config-routing request error handling (issue…
Sep 8, 2026
b16f2c6
feat(go): flip service/codex-shim/ensure/restart lifecycle reads to G…
Sep 8, 2026
7554a2e
refactor(go): address issue #47 code review findings
Sep 8, 2026
345f227
fix(go): address review findings on the issue #54 flips
Sep 8, 2026
7552905
test(go): close issue-46 oracle gaps and self-heal the parity Go binary
Sep 8, 2026
c28bc60
fix(go): code-review follow-ups for logs/memory/inspect flip (issue #45)
Sep 8, 2026
b56429c
feat(go): flip the ocx account OAuth device flows to Go-owned (issue …
Sep 8, 2026
682a665
test(go): assert the usage-help parity rows exit cleanly (issue #54)
Sep 8, 2026
499712b
docs(go): record why update/v2/claude/opencode stay TypeScript-owned …
Sep 8, 2026
5841f89
docs(go): record why restore/uninstall/recover-history stay TypeScrip…
Sep 8, 2026
951b78f
refactor(go): mirror registry text through the disconnect surface map…
Sep 8, 2026
74f8b38
fix(go): pairing 10s client + closing review notes (issue #54)
Sep 8, 2026
c4a3243
Merge branch 'issue-45' into dev-go
Sep 8, 2026
5219108
Merge branch 'issue-46' into dev-go
Sep 8, 2026
96ad106
Merge branch 'issue-47' into dev-go
Sep 8, 2026
590357a
Merge branch 'issue-48' into dev-go
Sep 8, 2026
76942d3
Merge branch 'issue-49' into dev-go
Sep 8, 2026
d23adde
Merge branch 'issue-50' into dev-go
Sep 8, 2026
ca179d9
Merge branch 'issue-51' into dev-go
Sep 8, 2026
e04f77a
Merge branch 'issue-52' into dev-go
Sep 8, 2026
47e64cb
Merge branch 'issue-53' into dev-go
Sep 8, 2026
2fefd35
Merge branch 'issue-54' into dev-go
Sep 8, 2026
48aec1b
register the TypeScript delegation seam deferrals (issue #55)
Sep 8, 2026
bebde51
harden the deferral ledger per review (issue #55)
Sep 8, 2026
67e2342
record the deferral oracle taxonomy and takeover glossary (issue #56)
Sep 8, 2026
247c9e4
flip ocx v2 status to Go-owned (issue #56 slice v2a)
Sep 8, 2026
4b0d6c5
harden the v2 status readers per review (issue #56)
Sep 8, 2026
d61d16e
test: use single-quoted TS strings for v2 status TOML fixtures (issue…
Sep 8, 2026
1ca4f48
flip the key-authenticated ocx login slice to Go (issue #57)
Sep 8, 2026
f339b24
flip the v2 write verbs to Go (issue #56, slice v2b)
Sep 8, 2026
69f47f7
style: normalize v2b formatting (prettier quotes, gofmt alignment)
Sep 8, 2026
cd97aad
flip the ocx opencode launcher to Go (issue #56)
Sep 8, 2026
b7d9696
flip the ocx claude launcher to Go (issue #56)
Sep 9, 2026
ce4b307
archive ocx update as permanently Bun-dependent (issue #56)
Sep 9, 2026
8c582a8
archive the opencode+claude flip design unit to _fin (issue #56)
Sep 9, 2026
0af23fe
style: prettier-normalize the claude parity describe (issue #56)
Sep 9, 2026
7d241c6
style: gofmt the claude flip sources (issue #56)
Sep 9, 2026
868f433
fix(go): fail fast when launcher proxy start fails
Sep 9, 2026
3803c2a
docs(adr): mark 0008 delivered and record the fork release-line reali…
Sep 9, 2026
fa48ba9
devlog: record the fork release-line grill decision tree
Sep 9, 2026
5c51fce
fix(go): keep native help in sync with owned commands
Sep 9, 2026
d4dacc4
test: align release version line and privacy fixture
Sep 9, 2026
ac66679
fix(go): make status identity static
Sep 9, 2026
cad3099
docs: define Go static release identity
Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
107 changes: 106 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ on:
- "tests/**"
- "scripts/**"
- "gui/**"
- "go/**"
- "assets/**"
- ".gitattributes"
- ".npmignore"
Expand Down Expand Up @@ -179,6 +180,7 @@ jobs:
- 'tests/**'
- 'scripts/**'
- 'gui/**'
- 'go/**'
- 'assets/**'
- '.gitattributes'
- '.npmignore'
Expand Down Expand Up @@ -282,6 +284,16 @@ jobs:
- name: Setup project Bun
uses: ./.github/actions/setup-project-bun

# The Go sidecar parity test (tests/go-sidecar-parity.test.ts) builds the
# sidecar with the local toolchain; whichever shard picks the file up runs
# the oracle only when `go` is on PATH. Keep it installed so the oracle
# never silently skips in the ordinary suite.
- name: Setup Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go/go.mod
cache: false

# The GUI install is NOT optional here, however unrelated it looks to a
# test shard. Several files under tests/ import JSX-bearing modules from
# gui/src (ProviderRail and friends), and React is declared only in
Expand Down Expand Up @@ -380,6 +392,67 @@ jobs:
- name: Test api usage API
run: bun test --isolate ./tests/api-usage.test.ts

# Go sidecar line (ADR-0008): the fresh in-tree Go module plus the differential
# oracle that proves the TS health handler and the ocx-sidecar agree on status,
# headers, and the normalised body for GET /api/system/health. Runs the Go
# toolchain gates (build/vet/test under go/) and then the Bun parity harness
# against the binary it builds. The module has no external dependencies, so
# module caching is disabled.
go:
name: go
needs: changes
if: github.event_name != 'pull_request' || needs.changes.outputs.ci == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
env:
# The sidecar is built static per the ADR-0008 plan (CGO_ENABLED=0); the
# parity harness sets the same flag when it builds a throwaway binary.
CGO_ENABLED: "0"
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false

- name: Setup project Bun
uses: ./.github/actions/setup-project-bun

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Setup Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go/go.mod
cache: false

- name: Go build
run: cd go && go build ./...

- name: Go vet
run: cd go && go vet ./...

- name: Go test
run: cd go && go test ./...

- name: Cross-compile every release target (CGO_ENABLED=0)
# Ticket #8 acceptance: the ocx-sidecar must build static on every
# release target (linux/darwin/windows x amd64/arm64), not only the
# native platform of this runner. A platform-specific dependency that
# leaks cgo (or a build tag mistake) would otherwise surface only at
# release time. The loop proves all six combinations produce a binary;
# artifacts land in /tmp and are discarded.
run: |
set -euo pipefail
cd go
for target in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64 windows/arm64; do
os="${target%/*}"; arch="${target#*/}"
GOOS="$os" GOARCH="$arch" CGO_ENABLED=0 go build -o "/tmp/ocx-sidecar-$os-$arch" ./cmd/ocx-sidecar
done

- name: Differential oracles
run: bun test --timeout 60000 tests/go-sidecar-parity.test.ts tests/go-cli-parity.test.ts tests/go-upgrade-rollback-drill.test.ts

# Everything that is not the suite: type safety, privacy, lint, build, smoke.
# One runner, once per push. Splitting these across the shards would repeat a
# fixed couple of minutes four times to save nothing.
Expand Down Expand Up @@ -486,6 +559,14 @@ jobs:
- name: Setup project Bun
uses: ./.github/actions/setup-project-bun

# Same rationale as the Linux shards: this lane runs the whole suite,
# which includes the Go-sidecar differential oracle.
- name: Setup Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go/go.mod
cache: false

- name: Install dependencies
run: |
bun install --frozen-lockfile
Expand All @@ -498,6 +579,14 @@ jobs:
cd gui
bun run build

# Run the two data-plane differentials explicitly before the full-suite
# control. The unsharded suite also discovers them, but this named step
# makes macOS parity evidence independently visible and stable.
- name: Hot-path differential oracles
run: >-
bun test --timeout 60000
tests/go-hotpath-relay.test.ts tests/go-hotpath-seam.test.ts

# Bun 1.3.14 segfaults while reclaiming a Worker at an `--isolate` file
# boundary: the header shows BALANCED `workers_spawned(N)
# workers_terminated(N)` and the process dies with exit 133 after the last
Expand Down Expand Up @@ -623,6 +712,14 @@ jobs:
- name: Setup project Bun
uses: ./.github/actions/setup-project-bun

- name: Setup Go
# The explicit Windows hot-path differential below builds and executes
# a native sidecar, so GOOS cross-compilation alone is insufficient.
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go/go.mod
cache: false

- name: Install dependencies
run: |
bun install --frozen-lockfile
Expand All @@ -635,6 +732,14 @@ jobs:
cd gui
bun run build

# This is deliberately separate from the sharded suite: a shard can move
# with file ordering, while this named result is the Windows evidence for
# byte-identical relay and SSE-seam behaviour against a native sidecar.
- name: Hot-path differential oracles
run: >-
bun test --timeout 60000
tests/go-hotpath-relay.test.ts tests/go-hotpath-seam.test.ts

- name: Test
# --timeout: the Linux batches and the macOS control both pass 60000; this leg was
# the only one left on Bun's 5s default, and it is the slowest hardware on the board.
Expand Down Expand Up @@ -805,7 +910,7 @@ jobs:
# direct dependencies only, so a failing `select-windows-runner` would
# otherwise reach this gate as nothing at all while its dependents report
# `skipped` — which the gate is required to read as a deliberate skip.
needs: [changes, select-windows-runner, test, storage-policy, api-usage, gates, platform-macos, platform-windows, keyring-smoke, npm-global-smoke]
needs: [changes, select-windows-runner, test, storage-policy, api-usage, go, gates, platform-macos, platform-windows, keyring-smoke, npm-global-smoke]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
Expand Down
227 changes: 227 additions & 0 deletions .github/workflows/go-release-artifacts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
name: Go release artifact gate

# Ticket #42: the Go binary is the release runtime (ADR-0008 increment 7), so
# the release path must build the same static cross-platform artifact CI has
# verified. #40 proved the artifact embeds every runtime asset (dashboard, CLI,
# identity); this workflow is that verification. It builds the exact release
# artifact via scripts/build-go-release-artifact.sh — the same script release.yml
# runs when it attaches ocx binaries to a release tag — and smokes the result.
# release.yml's own artifact build/attach steps (added with the #41 flip) remain
# the producer; this workflow is the gate that keeps the producer honest.
on:
# No base-branch filter on purpose (mirrors ci.yml): GitHub matches
# `branches:` against the BASE ref, which would silently exclude stacked child
# PRs. The `changes` job below is the real scope gate; a skipped job reports
# success, where a skipped *workflow* would leave its check pending forever.
pull_request: {}
# Pinned to the integration lines (mirrors ci.yml): the release path lives on
# main/preview, and dev is where the work queues before promotion.
push:
branches: [main, preview, dev]
paths:
# package.json is the version authority the artifact's -ldflags stamp
# reads, so a release commit (which bumps it) must re-run the gate even
# when no Go file changed — the same reason ci.yml's push allowlist
# carries package.json.
- "package.json"
- "go/**"
- "scripts/build-go-release-artifact.sh"
- "scripts/sync-go-embedded-dashboard.sh"
- ".github/workflows/go-release-artifacts.yml"
- ".github/workflows/release.yml"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: go-release-artifacts-${{ github.ref }}
cancel-in-progress: true

jobs:
# Same paths-filter shape as ci.yml's `changes` job: on a pull request the
# filter decides whether the expensive verification jobs need to run, and the
# validation step fails the job (rather than producing a malformed output)
# when the filter misbehaves.
changes:
name: changes
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
outputs:
go: ${{ steps.scope.outputs.go }}
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false

- name: Detect changed Go release surface
id: filter
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with:
# Mirrors the push trigger's path allowlist above; keep the two in
# sync. On `pull_request` the action uses the PR's own file list; on a
# branch push it means "compare against the previous commit on this
# branch".
base: ${{ github.ref }}
filters: |
go:
- 'package.json'
- 'go/**'
- 'scripts/build-go-release-artifact.sh'
- 'scripts/sync-go-embedded-dashboard.sh'
- '.github/workflows/go-release-artifacts.yml'
- '.github/workflows/release.yml'

- name: Assert the scope output is usable
id: scope
shell: bash
env:
GO_SCOPE: ${{ steps.filter.outputs.go }}
run: |
set -euo pipefail
case "$GO_SCOPE" in
true|false)
printf 'go=%s\n' "$GO_SCOPE" >> "$GITHUB_OUTPUT"
;;
*)
printf '::error::changes.outputs.go was %q, expected true or false\n' "$GO_SCOPE"
exit 1
;;
esac

verify-go-runtime:
name: verify Go runtime
needs: changes
if: github.event_name != 'pull_request' || needs.changes.outputs.go == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
env:
# The release artifact is built static per ADR-0008; the build script sets
# the same flag, and this job keeps go build/vet/test consistent with it.
CGO_ENABLED: "0"
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false

- name: Setup Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go/go.mod
cache: false

- name: Setup project Bun for embedded dashboard
uses: ./.github/actions/setup-project-bun

- name: Build, vet, and test Go runtime
run: |
set -euo pipefail
cd go
go build -buildvcs=false ./...
go vet ./...
go test ./...

- name: Build and smoke-test the Linux release artifact
# The release path stamps the package version with -ldflags, so the
# smoke runs the built candidate from a directory with no package.json:
# only a real stamp prints the exact version. The file check asserts
# the binary is genuinely static — CGO_ENABLED=0 plus a cgo-free
# platform surface is what makes the release artifact self-contained.
run: |
set -euo pipefail
scripts/build-go-release-artifact.sh linux/amd64 .tmp/go-release/linux-amd64
candidate="$GITHUB_WORKSPACE/.tmp/go-release/linux-amd64/ocx-linux-amd64"
test -x "$candidate" || { echo "::error::release artifact is not executable: $candidate"; exit 1; }
file "$candidate" | tee /dev/stderr | grep -qE "ELF 64-bit.*statically linked" || { echo "::error::linux/amd64 artifact is not a static ELF binary"; exit 1; }

expected="opencodex $(sed -n 's/^[[:space:]]*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$GITHUB_WORKSPACE/package.json" | head -n 1)"
actual="$(cd /tmp && exec "$candidate" --version)"
if [ "$actual" != "$expected" ]; then
echo "::error::artifact --version printed ${actual@Q}, expected ${expected@Q} (ldflags stamp missing or stale)"
exit 1
fi
echo "release artifact identity: $actual"

build-release-artifact:
name: build ${{ matrix.target }}
needs: [changes, verify-go-runtime]
if: github.event_name != 'pull_request' || needs.changes.outputs.go == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
include:
- target: linux/amd64
artifact: ocx-linux-amd64
format: ELF 64-bit
arch: x86-64
- target: linux/arm64
artifact: ocx-linux-arm64
format: ELF 64-bit
arch: aarch64
- target: darwin/amd64
artifact: ocx-darwin-amd64
format: Mach-O
arch: x86_64
- target: darwin/arm64
artifact: ocx-darwin-arm64
format: Mach-O
arch: arm64
- target: windows/amd64
artifact: ocx-windows-amd64
format: PE32+
arch: x86-64
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false

- name: Setup Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go/go.mod
cache: false

- name: Setup project Bun for embedded dashboard
uses: ./.github/actions/setup-project-bun

# Matrix values reach shell via env (repo convention: generated command
# input is a trust boundary — ci.yml passes TEST_SHARD the same way).
- name: Cross-compile static ocx release candidate
env:
TARGET: ${{ matrix.target }}
run: scripts/build-go-release-artifact.sh "$TARGET" dist

- name: Verify the artifact format
# A platform-specific dependency that leaks cgo (or a build tag
# mistake) would surface here as a dynamic binary or a missing file,
# exactly where the release path would have shipped it. ELF rows also
# assert the static link; `file` describes Mach-O/PE32+ consistently
# enough that the format tag plus architecture is the reliable check.
env:
EXPECTED_FORMAT: ${{ matrix.format }}
EXPECTED_ARCH: ${{ matrix.arch }}
run: |
set -euo pipefail
description="$(file dist/ocx-*)"
echo "$description"
echo "$description" | grep -F "$EXPECTED_FORMAT" >/dev/null || { echo "::error::artifact format mismatch, wanted ${EXPECTED_FORMAT}"; exit 1; }
echo "$description" | grep -F "$EXPECTED_ARCH" >/dev/null || { echo "::error::artifact architecture mismatch, wanted ${EXPECTED_ARCH}"; exit 1; }
case "$EXPECTED_FORMAT" in
ELF*) echo "$description" | grep -F "statically linked" >/dev/null || { echo "::error::ELF artifact is not statically linked"; exit 1; } ;;
esac

- name: Upload candidate
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ${{ matrix.artifact }}
path: dist/
if-no-files-found: error
retention-days: 7
Loading
Loading