Skip to content

Commit 38913e4

Browse files
authored
Merge pull request #10 from instructa/codex/switchloom-0.2.1-rc
Fix native Codex role discovery for Switchloom 0.2.1
2 parents df79884 + 546f881 commit 38913e4

42 files changed

Lines changed: 1883 additions & 229 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,5 @@ jobs:
5353
run: rustup toolchain install 1.85.0 --profile minimal
5454
- name: Build CLI binaries for PTY tests
5555
run: cargo +1.85.0 build --bins
56-
- name: Test npm package
57-
run: npm run distribution:test
56+
- name: Test npm wrapper
57+
run: node --test npm/*.test.mjs
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
name: Release Candidate
2+
3+
on:
4+
push:
5+
branches:
6+
- "codex/**"
7+
workflow_dispatch:
8+
inputs:
9+
ref:
10+
description: Git ref, branch, tag, or SHA to build
11+
required: true
12+
default: main
13+
14+
permissions: {}
15+
16+
env:
17+
CANDIDATE_REF: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.ref }}
18+
19+
concurrency:
20+
group: release-candidate-${{ github.ref }}
21+
cancel-in-progress: false
22+
23+
jobs:
24+
build-native:
25+
name: Build native ${{ matrix.target }}
26+
strategy:
27+
fail-fast: false
28+
matrix:
29+
include:
30+
- target: darwin-arm64
31+
rust_target: aarch64-apple-darwin
32+
runner: macos-14
33+
- target: darwin-x86_64
34+
rust_target: x86_64-apple-darwin
35+
runner: macos-14
36+
- target: linux-x86_64
37+
rust_target: x86_64-unknown-linux-gnu
38+
runner: ubuntu-24.04
39+
- target: linux-arm64
40+
rust_target: aarch64-unknown-linux-gnu
41+
runner: ubuntu-24.04-arm
42+
runs-on: ${{ matrix.runner }}
43+
permissions:
44+
contents: read
45+
steps:
46+
- name: Checkout selected ref
47+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
48+
with:
49+
ref: ${{ env.CANDIDATE_REF }}
50+
persist-credentials: false
51+
- name: Install Rust target
52+
run: rustup target add ${{ matrix.rust_target }}
53+
- name: Verify candidate version
54+
run: |
55+
test "$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n 1)" = "0.2.1"
56+
test "$(jq -r .version package.json)" = "0.2.1"
57+
- name: Build native candidate
58+
env:
59+
SWITCHLOOM_TARGET: ${{ matrix.target }}
60+
SWITCHLOOM_CARGO_TARGET: ${{ matrix.rust_target }}
61+
run: scripts/build-release.sh
62+
- name: Stage npm native binary
63+
run: |
64+
mkdir -p "npm/native/${{ matrix.target }}"
65+
install -m 755 "target/${{ matrix.rust_target }}/release/model-routing" \
66+
"npm/native/${{ matrix.target }}/model-routing"
67+
- name: Verify native version on matching runner
68+
run: |
69+
test "$(./target/${{ matrix.rust_target }}/release/model-routing --version)" = "model-routing 0.2.1"
70+
- name: Write native provenance
71+
env:
72+
TARGET: ${{ matrix.target }}
73+
RUST_TARGET: ${{ matrix.rust_target }}
74+
RUNNER_NAME: ${{ matrix.runner }}
75+
run: |
76+
mkdir -p "native-provenance/$TARGET"
77+
sha="$(shasum -a 256 "npm/native/$TARGET/model-routing" | awk '{print $1}')"
78+
version="$(./target/$RUST_TARGET/release/model-routing --version)"
79+
git_sha="$(git rev-parse HEAD)"
80+
built_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
81+
jq -n \
82+
--arg target "$TARGET" \
83+
--arg rust_target "$RUST_TARGET" \
84+
--arg runner "$RUNNER_NAME" \
85+
--arg path "npm/native/$TARGET/model-routing" \
86+
--arg version "$version" \
87+
--arg sha256 "$sha" \
88+
--arg git_sha "$git_sha" \
89+
--arg built_at "$built_at" \
90+
'{target:$target,rust_target:$rust_target,runner:$runner,path:$path,version:$version,sha256:$sha256,git_sha:$git_sha,built_at:$built_at}' \
91+
> "native-provenance/$TARGET/provenance.json"
92+
printf '%s npm/native/%s/model-routing\n' "$sha" "$TARGET" \
93+
> "native-provenance/$TARGET/SHA256SUMS"
94+
- name: Upload native candidate
95+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
96+
with:
97+
name: switchloom-native-${{ matrix.target }}
98+
path: |
99+
npm/native/${{ matrix.target }}/model-routing
100+
native-provenance/${{ matrix.target }}/provenance.json
101+
native-provenance/${{ matrix.target }}/SHA256SUMS
102+
if-no-files-found: error
103+
104+
package-check:
105+
name: Validate npm package from native matrix
106+
needs: build-native
107+
runs-on: ubuntu-24.04
108+
permissions:
109+
contents: read
110+
steps:
111+
- name: Checkout selected ref
112+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
113+
with:
114+
ref: ${{ env.CANDIDATE_REF }}
115+
persist-credentials: false
116+
- name: Setup Node
117+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
118+
with:
119+
node-version: 24
120+
package-manager-cache: false
121+
- name: Download native candidates
122+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
123+
with:
124+
pattern: switchloom-native-*
125+
path: rc-artifacts
126+
- name: Stage native candidates and provenance
127+
run: |
128+
mkdir -p npm/native provenance-parts
129+
for target in darwin-arm64 darwin-x86_64 linux-arm64 linux-x86_64; do
130+
mkdir -p "npm/native/$target"
131+
install -m 755 "rc-artifacts/switchloom-native-$target/npm/native/$target/model-routing" \
132+
"npm/native/$target/model-routing"
133+
cp "rc-artifacts/switchloom-native-$target/native-provenance/$target/provenance.json" \
134+
"provenance-parts/$target.json"
135+
done
136+
git_sha="$(git rev-parse HEAD)"
137+
jq -s \
138+
--arg package_version "$(jq -r .version package.json)" \
139+
--arg git_sha "$git_sha" \
140+
'{schema_version:"switchloom.native_provenance.v1",package_version:$package_version,git_sha:$git_sha,generated_by:"github-actions-release-candidate",targets:.}' \
141+
provenance-parts/*.json > npm/native/provenance.json
142+
- name: Validate native provenance and npm package
143+
run: bash scripts/npm-pack-check.sh
144+
- name: Upload package provenance
145+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
146+
with:
147+
name: switchloom-native-provenance
148+
path: npm/native/provenance.json
149+
if-no-files-found: error

.github/workflows/release.yml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,38 @@ jobs:
163163
run: |
164164
version="${TAG#v}"
165165
for target in darwin-arm64 darwin-x86_64 linux-arm64 linux-x86_64; do
166+
case "$target" in
167+
darwin-arm64) rust_target="aarch64-apple-darwin"; runner="macos-14" ;;
168+
darwin-x86_64) rust_target="x86_64-apple-darwin"; runner="macos-14" ;;
169+
linux-arm64) rust_target="aarch64-unknown-linux-gnu"; runner="ubuntu-24.04-arm" ;;
170+
linux-x86_64) rust_target="x86_64-unknown-linux-gnu"; runner="ubuntu-24.04" ;;
171+
esac
166172
mkdir -p "extract/$target" "npm/native/$target"
167173
tar -xzf "assets/switchloom-$target.tar.gz" -C "extract/$target"
168174
install -m 755 "extract/$target/model-routing" "npm/native/$target/model-routing"
175+
sha="$(shasum -a 256 "npm/native/$target/model-routing" | awk '{print $1}')"
176+
version_output="$(if [ "$target" = "linux-x86_64" ]; then "./npm/native/$target/model-routing" --version; else printf 'model-routing %s' "$version"; fi)"
177+
jq -n \
178+
--arg target "$target" \
179+
--arg path "npm/native/$target/model-routing" \
180+
--arg version "$version_output" \
181+
--arg sha256 "$sha" \
182+
--arg rust_target "$rust_target" \
183+
--arg runner "$runner" \
184+
--arg git_sha "$(git rev-parse HEAD)" \
185+
--arg built_at "release-$TAG" \
186+
'{target:$target,rust_target:$rust_target,runner:$runner,path:$path,version:$version,sha256:$sha256,git_sha:$git_sha,built_at:$built_at}' \
187+
> "assets/$target.native-provenance.json"
169188
done
189+
jq -s \
190+
--arg package_version "$version" \
191+
--arg git_sha "$(git rev-parse HEAD)" \
192+
'{schema_version:"switchloom.native_provenance.v1",package_version:$package_version,git_sha:$git_sha,generated_by:"github-actions-release",targets:.}' \
193+
assets/*.native-provenance.json > npm/native/provenance.json
194+
node scripts/validate-native-provenance.mjs
170195
test "$(./npm/native/linux-x86_64/model-routing --version)" = "model-routing $version"
171196
SWITCHLOOM_NATIVE_BIN="$PWD/npm/native/linux-x86_64/model-routing" node npm/bin/model-routing.js --version
172-
npm pack --dry-run
197+
bash scripts/npm-pack-check.sh
173198
- name: Publish npm package
174199
env:
175200
TAG: ${{ github.ref_name }}

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
All notable changes to Switchloom are recorded here.
44

5+
## [0.2.1] - 2026-07-19
6+
7+
- Prepared a superseding release candidate after the `0.2.0` native Codex
8+
discovery proof gap: the published bytes generated correct repository-local
9+
role files, but the first release evidence did not prove the installed
10+
candidate could execute the complete status/uninstall lifecycle while keeping
11+
unmanaged configuration intact.
12+
- Added retained proof for a checksum-identified installed candidate running
13+
status and uninstall against a generated repository, removing only managed
14+
Switchloom artifacts and preserving an unmanaged sentinel byte-for-byte.
15+
- Strengthened the standalone Codex oracle so package receipt discovery follows
16+
the manifest version instead of hard-coding a crate name, keeping future
17+
release-candidate proofs tied to the candidate's package bytes.
18+
- Recorded the superseding native Terra High maker and Sol High reviewer proof
19+
with equal before/after global Codex config hashes, fork-free child context,
20+
package checksum provenance, and exact Planr baseline preservation.
21+
522
## [0.2.0] - 2026-07-18
623

724
- Added the strict, versioned `SetupSpecV1` contract with deterministic TOML, canonical JSON,

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "model-routing"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
edition = "2024"
55
rust-version = "1.85"
66
license = "MIT"

docs/migration-manifest.tsv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ cli-command cmd-008 planr-routing registry sign <file> --signer <id> --private-k
107107
cli-command cmd-009 planr-routing registry verify <file> --signature <path> --trusted-signer <id> --trusted-public-key-file <path> move-generalize model-routing registry verify <file> --signature <path> --trusted-signer <id> --trusted-public-key-file <path> Verify registry signature.
108108
generated-artifact art-001 .planr/agents.toml move-generalize .planr/agents.toml Optional Planr integration declaration only.
109109
generated-artifact art-002 .planr/policy.toml move-generalize .planr/policy.toml Optional Planr integration policy only.
110+
generated-artifact art-011 .codex/config.toml move-generalize .codex/config.toml Current v0.2.0 repository-local Codex role discovery config.
110111
generated-artifact art-003 .codex/agents/model-routing-luna-xhigh.toml move-generalize .codex/agents/model-routing-luna-xhigh.toml Current v0.2.0 Codex mechanical profile artifact.
111112
generated-artifact art-004 .codex/agents/model-routing-sol-high.toml move-generalize .codex/agents/model-routing-sol-high.toml Current v0.2.0 Codex reviewer profile artifact.
112113
generated-artifact art-005 .codex/agents/model-routing-sol-medium.toml move-generalize .codex/agents/model-routing-sol-medium.toml Current v0.2.0 Codex driver profile artifact.

docs/planr-hard-cut-handoff.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,50 @@
11
# Planr Hard-Cut Handoff Receipt
22

3-
Date: 2026-07-18
3+
Date: 2026-07-19
44

55
This receipt is the Goal A gate for starting the Planr Goal B hard cut. It
66
does not modify `/Users/kregenrek/projects/planr`; it records the independently
77
published Switchloom release and the exact Planr routing responsibilities that
88
now have a standalone owner or an explicit deletion action.
99

10+
## Superseding Candidate Status
11+
12+
The public `v0.2.0` release remains the latest published Switchloom release, but
13+
its original native Codex discovery evidence had a release-gating gap: the
14+
published package generated repository-local Codex role files, yet the accepted
15+
receipt did not prove the checksum-identified installed candidate executed the
16+
full status/uninstall lifecycle while preserving unmanaged repository content.
17+
18+
The current unpublished superseding candidate is `0.2.1`. It must replace
19+
`v0.2.0` before Planr Goal B starts. The canonical retained `0.2.1` candidate
20+
proof chain is:
21+
22+
- `/private/tmp/model-routing-codex-standalone.COTXUA` proves exact `0.2.1`
23+
package-byte execution, repository-local Codex role discovery, authentic Terra
24+
High maker and Sol High reviewer spawns with `fork_turns = none`, and
25+
unchanged global Codex config hash
26+
`18cbbaee5e263f8bb011a174913721a8866a4d156d62c7fc74bc2d7103abcb3c`.
27+
- The canonical `0.2.1` candidate crate hash in that receipt is
28+
`e5c2eee164433f3433f8aef2aca46624d88a46c8b4db502aa63804017b83769e`, and
29+
the installed binary hash is
30+
`7e214789885a66e4788c778fd8d7681c1a67de0aed5f728735ff678c8965049f`.
31+
- The same `0.2.1` installed binary ran `status` and `uninstall` only against
32+
the generated temporary repository. It removed seven Switchloom-managed
33+
artifacts, left `bundle_id: null` with no managed artifacts on post-status,
34+
and preserved the unmanaged sentinel file byte-identically.
35+
- `/private/tmp/model-routing-codex-standalone.yGExSi` remains a `0.2.0`
36+
behavioral precursor only. It is useful for comparing the same proof shape,
37+
but it is not the canonical `0.2.1` release-candidate proof because its crate
38+
and installed binary are `0.2.0`.
39+
- `/Users/kregenrek/projects/planr` remained at protected HEAD
40+
`d7f0afae24643d4a1e475474426c37ca00e5dbe3` with
41+
`git status --porcelain=v1 -z` SHA-256
42+
`45d1759e7ff4c3f45b15eaf3c331f82186173610427a5e0a38cdd945151d5f33`.
43+
44+
Do not use the `v0.2.0` publication as the final Goal A handoff. Publish and
45+
smoke-test the superseding `0.2.1` candidate first, then update the public
46+
release identity below to the verified public bytes.
47+
1048
## Release Identity
1149

1250
- Repository: `https://github.com/instructa/switchloom`

fixtures/routing-bundle-v1/valid-balanced-codex.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"generated_at": "2026-07-16T00:00:00Z",
77
"source": {
88
"package": "model-routing",
9-
"package_version": "0.2.0",
9+
"package_version": "0.2.1",
1010
"integration": "planr"
1111
},
1212
"policy": {
@@ -238,6 +238,13 @@
238238
"content": "name = \"model_routing_terra_medium\"\ndescription = \"Repository exploration and research.\"\nmodel = \"gpt-5.6-terra\"\nmodel_reasoning_effort = \"medium\"\nsandbox_mode = \"read-only\"\n\ndeveloper_instructions = \"\"\"\nExplore the assigned scope, report concrete evidence, and do not edit files.\n\"\"\"\n",
239239
"sha256": "458cdc1750b5fabe2fa81c502c1decf0ba346644a595ecf75bcd3ac63d471464"
240240
},
241+
{
242+
"path": ".codex/config.toml",
243+
"media_type": "application/toml",
244+
"mode": "replace",
245+
"content": "[agents.model_routing_luna_xhigh]\nconfig_file = \"./agents/model-routing-luna-xhigh.toml\"\n\n[agents.model_routing_sol_high]\nconfig_file = \"./agents/model-routing-sol-high.toml\"\n\n[agents.model_routing_sol_medium]\nconfig_file = \"./agents/model-routing-sol-medium.toml\"\n\n[agents.model_routing_sol_ultra]\nconfig_file = \"./agents/model-routing-sol-ultra.toml\"\n\n[agents.model_routing_terra_high]\nconfig_file = \"./agents/model-routing-terra-high.toml\"\n\n[agents.model_routing_terra_medium]\nconfig_file = \"./agents/model-routing-terra-medium.toml\"\n",
246+
"sha256": "38511fd94693a95ebcdb0d2ca65f414109b05835172729c35f91d70d20d3b60d"
247+
},
241248
{
242249
"path": ".planr/agents.toml",
243250
"media_type": "application/toml",

fixtures/routing-bundle-v1/valid-balanced-mixed.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"generated_at": "2026-07-16T00:00:00Z",
77
"source": {
88
"package": "model-routing",
9-
"package_version": "0.2.0",
9+
"package_version": "0.2.1",
1010
"integration": "planr"
1111
},
1212
"policy": {
@@ -174,6 +174,13 @@
174174
"content": "name = \"model_routing_terra_high\"\ndescription = \"Normal implementation and testing.\"\nmodel = \"gpt-5.6-terra\"\nmodel_reasoning_effort = \"high\"\nsandbox_mode = \"workspace-write\"\n\ndeveloper_instructions = \"\"\"\nUse the existing Planr internal worker protocol for exactly one picked Planr item. Read the pick packet, implement only that item, log changed files and real verification commands, request review through Planr, and stop. Do not create or invoke any routing-specific, goal, or loop workflow skill. Planr users enter only through $planr-goal and $planr-loop.\n\nProtocol preload: $planr-work\n\"\"\"\n",
175175
"sha256": "d19e92ab08073ebcab81f3ebbc75e4af61fae610bf6bf5002cb1d9ad21dfca26"
176176
},
177+
{
178+
"path": ".codex/config.toml",
179+
"media_type": "application/toml",
180+
"mode": "replace",
181+
"content": "[agents.model_routing_luna_xhigh]\nconfig_file = \"./agents/model-routing-luna-xhigh.toml\"\n\n[agents.model_routing_sol_high]\nconfig_file = \"./agents/model-routing-sol-high.toml\"\n\n[agents.model_routing_terra_high]\nconfig_file = \"./agents/model-routing-terra-high.toml\"\n",
182+
"sha256": "673a3abad282412014d93160a42e2366c203553ff18530951afd7394e78c11c8"
183+
},
177184
{
178185
"path": ".cursor/agents/model-routing-fable-driver.md",
179186
"media_type": "text/markdown",

0 commit comments

Comments
 (0)