Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
368c41c
build: derive Codex protocol inputs from the locked SDK
showxu Sep 27, 2026
3621c71
feat(app-server): project SDK-adopted requests with owned lifecycles
showxu Sep 27, 2026
5595910
fix(adapter): preserve integer diagnostics and schema values
showxu Sep 27, 2026
f3fa957
fix(history): use metadata and bounded thread pages by default
showxu Sep 27, 2026
9631fb7
fix(permissions): classify native execution and continuations
showxu Sep 27, 2026
8f12975
fix(permissions): protect persisted model continuation inputs
showxu Sep 27, 2026
a52fd21
fix(exec): drain pending launches during shutdown
showxu Sep 27, 2026
cf2a490
feat(exec): retain invocation ownership until result release
showxu Sep 27, 2026
fd999c6
feat(codex): bind native resource lifetimes to their creators
showxu Sep 27, 2026
ba89c1f
fix(codex): release thread claims after confirmed retirement
showxu Sep 27, 2026
f3ae9be
fix: retain App Server work across asynchronous lifetimes
showxu Sep 27, 2026
44d63ad
feat: report complete Codex runtime work ownership
showxu Sep 27, 2026
b483339
test: report missing native workflow tools
showxu Sep 27, 2026
682bd9c
feat: expose native continuation handles on owned work
showxu Sep 27, 2026
7c5da72
feat: declare Codex work continuation selectors
showxu Sep 27, 2026
3903d25
ci: notify the official catalog after plugin releases
showxu Sep 28, 2026
7865da9
ci: adopt catalog notification cooldown handling
showxu Sep 28, 2026
cb615d7
feat: declare semantic host service actions
showxu Sep 28, 2026
d7dfe68
test: audit the Windows adapter with isolated dependency candidates
showxu Sep 28, 2026
6dc5839
fix: preserve Windows environment and crypto boundaries
showxu Sep 28, 2026
86a23db
build: provide verified SQLite for Windows dependency validation
showxu Sep 28, 2026
fc77d38
fix: compile the Windows SQLite probe before linking
showxu Sep 28, 2026
827d8d4
fix: preserve runtime receipts with native Windows process checks
showxu Sep 28, 2026
114e670
test: verify native GRDB persistence with the SQLite candidate
showxu Sep 28, 2026
d5f0897
fix: resolve Windows Codex executables in their launch context
showxu Sep 28, 2026
7f7cb52
feat: bind Windows adapter process lifetimes to swift-codex
showxu Sep 28, 2026
3bd793d
feat: run Windows adapter commands in owned process jobs
showxu Sep 28, 2026
8cb526c
feat: retain private Windows state directories through database lifet…
showxu Sep 28, 2026
53797c8
test: verify Windows command cwd by native directory identity
showxu Sep 28, 2026
bc5e86c
feat: preserve Windows managed worktree directory ownership
showxu Sep 28, 2026
3edf506
fix: express Windows file rights with importable constants
showxu Sep 28, 2026
cc3529b
ci: check native filesystem imports before SDK fixture builds
showxu Sep 28, 2026
cf0e1fc
fix: retain effective Windows directory sharing guards
showxu Sep 28, 2026
3ebf05d
test: await GRDB dispatch-owned directory release
showxu Sep 28, 2026
db8030c
feat: consume inherited Windows host MCP pipes
showxu Sep 28, 2026
7dedcc5
fix: use native pipe ownership and synchronous MCP receive
showxu Sep 28, 2026
e413d8a
test: verify inherited MCP pipes across native processes
showxu Sep 28, 2026
8b8b40f
test: observe native database directory retirement
showxu Sep 28, 2026
13d656d
test: isolate native database and callback validation
showxu Sep 28, 2026
587ede1
test: exercise linked Windows adapter protocol
showxu Sep 28, 2026
430d0a5
test: retain native adapter failure evidence
showxu Sep 28, 2026
e5677ef
fix: preserve protocol resource bytes on Windows
showxu Sep 28, 2026
15ba987
test: clean private Windows protocol state safely
showxu Sep 28, 2026
3955738
test(windows): inspect recursive adapter runtime dependencies
showxu Sep 28, 2026
cd6aed9
test(windows): verify app-local runtime loading
showxu Sep 28, 2026
7c89990
build: preserve Swift Windows runtime notice sources
showxu Sep 29, 2026
a63fce1
build(deps): adopt versioned native Codex and MCP dependencies
showxu Sep 29, 2026
8d0cee5
feat(package): deliver native Windows and macOS archives
showxu Sep 29, 2026
d529b20
fix: preserve native usage counters in redacted events
showxu Sep 29, 2026
4b92267
fix: adopt exact MCP integer transport dependencies
showxu Sep 29, 2026
95c8676
test: verify owned cleanup after startup deadlines
showxu Sep 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Protocol provenance verifies original file bytes on every platform.
Sources/CodexAdapter/Resources/Protocol/** -text
# Runtime notice provenance is bound to the original upstream bytes.
Vendor/SwiftWindowsRuntime/** -text
# Every platform archive must match the manifest stored at its release tag.
computer-mcp-plugin.toml -text
59 changes: 59 additions & 0 deletions .github/RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Release publication and catalog notification

Publish only an accepted plugin package bound to its reviewed source/tag and exact archive digest.
Keep an existing public tag and archive immutable. A candidate, draft or notification receipt does
not establish authenticated vendor or installed-host acceptance.

The upload-release workflow promotes an accepted existing candidate into a matching draft; it does not make that draft public. After the accepted release becomes public,
`notify-catalog.yml` requests a complete catalog reconciliation. It also observes public edits,
channel promotion, unpublishing and deletion; those events never authorize catalog withdrawal by
themselves. The central publisher retains verified history and applies its reviewed withdrawal
policy. It verifies actual GitHub release sources rather than trusting an event payload.

## Notification authority

The workflow pins the website's central notification action to a reviewed full commit. Publish that
central commit before enabling a plugin workflow that references it. Review and update this pin
when adopting changes to the notification contract. The caller checks its immutable repository ID,
does not check out package code, and grants its own job token no repository permissions.

Supply `CATALOG_DISPATCH_TOKEN` using existing reviewed authority with Actions write access to
`computer-mcp/computer-mcp.github.io` only. Website Contents write access is unnecessary. The action
can also receive an existing temporary token directly from a publishing job. Neither workflow
creates or persists credentials. Missing or rejected authority fails visibly; the
publisher's independent schedule still reconciles missed notifications.

## Publication and retry

A manual public release emits the release event. Publication performed with a repository's
`GITHUB_TOKEN` does not trigger ordinary release-event workflows. After that publication succeeds,
its automation must explicitly call this reusable workflow as a dependent job:

```yaml
notify-catalog:
needs: publish
uses: ./.github/workflows/notify-catalog.yml
secrets:
CATALOG_DISPATCH_TOKEN: ${{ secrets.CATALOG_DISPATCH_TOKEN }}
```

Here `publish` is the job that actually makes the accepted release public, not the candidate-build
or draft-upload job. When using an existing short-lived token within that publishing job, invoke
the same pinned central action directly after publication instead. Keep token values out of command
arguments, printed output and release metadata.

For an operator-driven publication or a missed/failed notification, explicitly dispatch:

```sh
gh workflow run notify-catalog.yml --repo computer-mcp/plugin-codex --ref main
```

This schedules notification using its configured authority; it does not publish or rewrite a
release. Inspect the notification run and its returned central `run_url`. A successful dispatch
proves request acceptance only. Verify the central run completed successfully and the public index
contains the exact expected release identities and generation. If the release is already public and
notification fails, retry notification without changing or republishing the release. Complete
reconciliation is idempotent and repairs duplicate/missed events.

See the central [catalog publication and notification contract](https://github.com/computer-mcp/computer-mcp.github.io/blob/main/docs/plugin-catalog.md)
for provenance, credentials, retry bounds and deployment semantics.
28 changes: 28 additions & 0 deletions .github/workflows/notify-catalog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Notify official plugin catalog
on:
release:
types: [published, edited, released, unpublished, deleted]
workflow_dispatch:
workflow_call:
secrets:
CATALOG_DISPATCH_TOKEN:
description: Existing receiver-scoped Actions write authority
required: true
outputs:
run_url:
description: Accepted central run; verify its deployment separately
value: ${{ jobs.notify.outputs.run_url }}
permissions: {}
jobs:
notify:
if: github.repository_id == '1368122608'
runs-on: ubuntu-latest
timeout-minutes: 3
outputs:
run_url: ${{ steps.catalog.outputs.run-url }}
steps:
- name: Request complete catalog reconciliation
id: catalog
uses: computer-mcp/computer-mcp.github.io/.github/actions/notify-catalog@fc27dd0f370d028a3e5021e3585274891f696578
with:
token: ${{ secrets.CATALOG_DISPATCH_TOKEN }}
84 changes: 57 additions & 27 deletions .github/workflows/upload-release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Upload verified release archive
name: Upload verified release archives
on:
workflow_dispatch:
inputs:
Expand All @@ -25,7 +25,8 @@ jobs:
SOURCE_RUN: ${{ inputs.source_run }}
RELEASE_TAG: ${{ inputs.release_tag }}
steps:
- name: Verify source and draft, then upload the existing archive
- name: Verify accepted source and commit-bound draft
id: source
shell: bash
run: |
set -euo pipefail
Expand All @@ -50,31 +51,60 @@ jobs:
then .[0] else error("Expected one commit-bound draft release") end
' releases.json > release.json
release_id=$(jq -r .id release.json)
gh run download "$SOURCE_RUN" --name "codex-plugin-ARM64-$source_sha" --dir artifact
cd artifact
expected=$(jq -r .archive_sha256 receipt.json)
[[ "$expected" =~ ^[0-9a-f]{64}$ ]]
printf '%s codex-plugin.zip\n' "$expected" | sha256sum --check --strict
unzip -t codex-plugin.zip
python3 - <<'PY'
import os, tomllib, zipfile
with zipfile.ZipFile("codex-plugin.zip") as archive:
manifest = tomllib.loads(archive.read("computer-mcp-plugin.toml").decode())
echo "sha=$source_sha" >> "$GITHUB_OUTPUT"
echo "release_id=$release_id" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ steps.source.outputs.sha }}
persist-credentials: false
- name: Verify and promote every declared native archive
shell: bash
env:
SOURCE_SHA: ${{ steps.source.outputs.sha }}
RELEASE_ID: ${{ steps.source.outputs.release_id }}
run: |
set -euo pipefail
python3 - <<'PYTHON'
import json, os, re, tomllib
from pathlib import Path
manifest = tomllib.loads(Path("computer-mcp-plugin.toml").read_text())
if manifest["id"] != "codex" or "v" + manifest["version"] != os.environ["RELEASE_TAG"]:
raise SystemExit("Release tag does not match the accepted plugin manifest")
PY
gh api "repos/$GH_REPO/releases/$release_id/assets" > assets.json
existing=$(jq -r '.[] | select(.name == "codex-plugin.zip") | .id' assets.json)
if [[ -n "$existing" ]]; then
jq -e --argjson id "$existing" --arg digest "sha256:$expected" '
.[] | select(.id == $id) |
.state == "starter" or (.state == "uploaded" and .digest == $digest)
' assets.json > /dev/null
if jq -e --argjson id "$existing" '.[] | select(.id == $id) | .state == "uploaded"' assets.json > /dev/null; then
exit 0
names = [item["name"] for item in manifest["compatibility"]["artifacts"]]
if not names or len(set(names)) != len(names) or any(not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_.-]*\.zip", name) for name in names):
raise SystemExit("Expected unique declared native archives")
Path("archive-names.json").write_text(json.dumps(names))
PYTHON
while IFS= read -r archive; do
name=${archive%.zip}
gh run download "$SOURCE_RUN" --name "$name-$SOURCE_SHA" --dir "artifacts/$name"
python3 Scripts/check-package.py --archive "artifacts/$name/$archive" --receipt "artifacts/$name/receipt.json" > "artifacts/$name/verification.json"
done < <(jq -r '.[]' archive-names.json)
# Upload only after every declared archive passes its exact source-bound check.
upload_asset() {
local file=$1 name=$2 content_type=$3 expected existing
expected=$(sha256sum "$file" | cut -d' ' -f1)
gh api --paginate "repos/$GH_REPO/releases/$RELEASE_ID/assets?per_page=100" --slurp | jq 'add' > assets.json
existing=$(jq -er --arg name "$name" '[.[] | select(.name == $name)] | if length <= 1 then (.[0].id // "") else error("Duplicate release asset") end' assets.json)
if [[ -n "$existing" ]]; then
jq -e --argjson id "$existing" --arg digest "sha256:$expected" '
.[] | select(.id == $id) |
.state == "starter" or (.state == "uploaded" and .digest == $digest)
' assets.json > /dev/null
if jq -e --argjson id "$existing" '.[] | select(.id == $id) | .state == "uploaded"' assets.json > /dev/null; then
return
fi
gh api "repos/$GH_REPO/releases/$RELEASE_ID" | jq -e --arg tag "$RELEASE_TAG" --arg sha "$SOURCE_SHA" '.draft and .tag_name == $tag and .target_commitish == $sha' > /dev/null
gh api --method DELETE "repos/$GH_REPO/releases/assets/$existing"
fi
gh api --method DELETE "repos/$GH_REPO/releases/assets/$existing"
fi
gh api --method POST "https://uploads.github.com/repos/$GH_REPO/releases/$release_id/assets?name=codex-plugin.zip" \
--input codex-plugin.zip -H 'Content-Type: application/zip' > uploaded.json
jq -e --arg digest "sha256:$expected" '.state == "uploaded" and .digest == $digest' uploaded.json > /dev/null
# Re-read immediately before upload; published releases are immutable.
gh api "repos/$GH_REPO/releases/$RELEASE_ID" | jq -e --arg tag "$RELEASE_TAG" --arg sha "$SOURCE_SHA" '.draft and .tag_name == $tag and .target_commitish == $sha' > /dev/null
gh api --method POST "https://uploads.github.com/repos/$GH_REPO/releases/$RELEASE_ID/assets?name=$name" \
--input "$file" -H "Content-Type: $content_type" > uploaded.json
jq -e --arg digest "sha256:$expected" '.state == "uploaded" and .digest == $digest' uploaded.json > /dev/null
}
while IFS= read -r archive; do
name=${archive%.zip}
upload_asset "artifacts/$name/$archive" "$archive" application/zip
upload_asset "artifacts/$name/receipt.json" "$name.receipt.json" application/json
done < <(jq -r '.[]' archive-names.json)
Loading
Loading