Merge codex/gstack-2 into gstack2-runtime-integration

Reconcile the four integrated v2 runtime implementations (unified execution
result contract, execution profiles, capability readiness, GitHub security)
with main's browser-provider hardening.

Conflict resolutions:
- runtimeContract() generator: keep new execution-result + doctor-capability
  paragraphs, adopt main's `[matching browser flags]` fallback wording;
  regenerate the six RUNTIME.md.
- package.json: keep the strict isolated test:gstack2 runner and marked 18.0.6
  security bump; adopt main's playwright-core alias.
- bun.lock: regenerated via bun install.
- release-hardening.test.ts: adopt main's browser-provider assertions
  (resolveServerLaunchTarget, --browser managed smoke loop).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sinabina
2026-07-21 13:15:03 -07:00
co-authored by Claude Opus 4.8
160 changed files with 4397 additions and 522 deletions
+4 -4
View File
@@ -70,11 +70,11 @@ RUN curl --retry 5 --retry-delay 5 --retry-connrefused -fsSL https://bun.sh/inst
RUN npm i -g @anthropic-ai/claude-code
# Playwright system deps (Chromium) — needed for browse E2E tests
RUN npx playwright install-deps chromium
RUN npx playwright-core install-deps chromium
# Linux has neither Helvetica nor Arial. make-pdf's print CSS stacks fall back
# to Liberation Sans (metric-compatible Arial clone, SIL OFL 1.1) so PDFs don't
# render in DejaVu Sans. playwright install-deps happens to pull this in today,
# render in DejaVu Sans. playwright-core install-deps happens to pull this in today,
# but the dep is implicit and could change — install explicitly so upgrades
# can't silently regress rendering.
#
@@ -100,12 +100,12 @@ RUN bun install --frozen-lockfile && rm -rf /tmp/*
# Install Playwright Chromium to a shared location accessible by all users
ENV PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers
RUN npx playwright install chromium \
RUN npx playwright-core install chromium \
&& chmod -R a+rX /opt/playwright-browsers
# Verify everything works
RUN bun --version && node --version && claude --version && jq --version && gh --version \
&& npx playwright --version \
&& npx playwright-core --version \
&& fc-match "Liberation Sans" | grep -qi "Liberation" \
|| (echo "ERROR: fonts-liberation not installed — make-pdf PDFs will render in DejaVu Sans" && exit 1)
@@ -2,11 +2,19 @@
import fs from "node:fs/promises";
import path from "node:path";
const [directory, repository = process.env.GITHUB_REPOSITORY, version = "2.0.0"] = process.argv.slice(2);
const [
directory,
repository = process.env.GITHUB_REPOSITORY,
version = "2.0.0",
releaseTag = `v${version}`,
] = process.argv.slice(2);
if (!directory || !repository) {
console.error("Usage: create-runtime-release-manifest.mjs <artifact-dir> <owner/repo> [version]");
console.error("Usage: create-runtime-release-manifest.mjs <artifact-dir> <owner/repo> [version] [release-tag]");
process.exit(2);
}
if (!/^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/.test(releaseTag)) {
throw new Error(`Invalid runtime release tag: ${releaseTag}`);
}
const targets = [
"darwin-arm64",
@@ -35,8 +43,8 @@ const capabilityComponents = {
ios: ["ios"],
};
const commonComponents = ["core", "browser-code", "browser-headless", "browser-visible", "design", "diagram", "pdf"];
const release = `https://github.com/${repository}/releases/download/v${version}`;
const certificateIdentity = `https://github.com/${repository}/.github/workflows/release-artifacts.yml@refs/tags/v${version}`;
const release = `https://github.com/${repository}/releases/download/${releaseTag}`;
const certificateIdentity = `https://github.com/${repository}/.github/workflows/release-artifacts.yml@refs/tags/${releaseTag}`;
const targetRecords = {};
for (const target of targets) {
+1 -1
View File
@@ -66,7 +66,7 @@ jobs:
fc-match -f '%{family[0]}\t%{color}\n' ':lang=und-zsye:charset=1F600' || true
- name: Install Playwright Chromium
run: bunx playwright install chromium
run: bunx playwright-core install chromium
- name: Build binaries
run: bun run build
+24 -17
View File
@@ -2,7 +2,9 @@ name: Release runtime artifacts
on:
push:
tags: [v2.0.0]
tags:
- v2.0.0
- v2.0.0-rc.*
workflow_dispatch:
permissions:
@@ -51,8 +53,6 @@ jobs:
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22.23.1
- uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
- name: Install frozen dependencies
run: bun install --frozen-lockfile --ignore-scripts
shell: bash
@@ -70,6 +70,7 @@ jobs:
--version 2.0.0 \
--install-now \
--yes \
--browser managed \
--capabilities "$CAPABILITIES"
active_slot=$(node -e 'const fs=require("fs"),p=process.argv[1];const v=JSON.parse(fs.readFileSync(p,"utf8")).current;if(typeof v!=="string"||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(v))process.exit(1);process.stdout.write(v)' "$GSTACK_HOME/versions/current.json")
active="$GSTACK_HOME/versions/$active_slot"
@@ -112,32 +113,28 @@ jobs:
"$GSTACK_HOME/bin/browse" stop >/dev/null 2>&1 || true
}
trap browser_cleanup EXIT
smoke_url=$(node -e 'const fs=require("fs"),p=require("path").join(process.env.GITHUB_WORKSPACE,".gstack-runtime-smoke.html");fs.writeFileSync(p,"<!doctype html><title>GStack runtime smoke</title>\n");process.stdout.write(require("url").pathToFileURL(p).href)')
PATH="$clean_path" GSTACK_NODE="$node_command" BROWSE_PARENT_PID=0 \
"$GSTACK_HOME/bin/browse" goto about:blank
"$GSTACK_HOME/bin/browse" goto "$smoke_url"
PATH="$clean_path" GSTACK_NODE="$node_command" BROWSE_PARENT_PID=0 \
"$GSTACK_HOME/bin/browse" status
browser_cleanup
trap - EXIT
stage="$RUNNER_TEMP/runtime-components"
mkdir -p "$stage" "$GITHUB_WORKSPACE/release-output"
# GNU tar treats a Windows drive colon in an archive path as a
# remote-host separator. Keep archive output in Git Bash's POSIX view.
release_dir="$(pwd -P)/release-output"
mkdir -p "$stage" "$release_dir"
node .github/scripts/stage-runtime-components.mjs "$active" "$stage"
for component_dir in "$stage"/*; do
test -d "$component_dir" || continue
component=$(basename "$component_dir")
archive="$GITHUB_WORKSPACE/release-output/gstack-runtime-2.0.0-$TARGET-$component.tar.gz"
archive="$release_dir/gstack-runtime-2.0.0-$TARGET-$component.tar.gz"
tar -czf "$archive" -C "$component_dir" gstack
node -e 'const fs=require("fs"),c=require("crypto"),p=process.argv[1];const b=fs.readFileSync(p);fs.writeFileSync(p+".sha256",c.createHash("sha256").update(b).digest("hex")+" "+require("path").basename(p)+"\n")' "$archive"
done
shell: bash
- name: Keyless-sign component archives
run: |
set -euo pipefail
for archive in release-output/*.tar.gz; do
cosign sign-blob --yes --bundle "$archive.sigstore.json" "$archive"
done
shell: bash
- name: Attest component archive provenance
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2
with:
@@ -169,8 +166,16 @@ jobs:
merge-multiple: true
- uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
- name: Keyless-sign component archives
run: |
set -euo pipefail
for archive in release-output/*.tar.gz; do
cosign sign-blob --yes --bundle "$archive.sigstore.json" "$archive"
done
shell: bash
- name: Create strict six-target manifest
run: node .github/scripts/create-runtime-release-manifest.mjs release-output "$GITHUB_REPOSITORY" 2.0.0
run: node .github/scripts/create-runtime-release-manifest.mjs release-output "$GITHUB_REPOSITORY" 2.0.0 "$GITHUB_REF_NAME"
- name: Checksum and keyless-sign manifest
run: |
@@ -188,11 +193,13 @@ jobs:
- name: Publish immutable release assets
env:
GH_TOKEN: ${{ github.token }}
PRERELEASE_FLAG: ${{ contains(github.ref_name, '-rc.') && '--prerelease' || '' }}
run: |
set -euo pipefail
gh release create "$GITHUB_REF_NAME" \
--verify-tag \
--title "GStack runtime 2.0.0" \
--notes "Signed optional runtime artifacts for the six portable GStack skills." \
$PRERELEASE_FLAG \
--title "GStack runtime $GITHUB_REF_NAME" \
--notes "Signed optional runtime artifacts for the six portable GStack skills. This release adds an explicit managed-versus-installed Chromium consent gate before browser preview or installation." \
release-output/*
shell: bash
+2 -2
View File
@@ -65,14 +65,14 @@ jobs:
- name: Preview without mutating state
run: |
set -e
bash ./setup --dry-run --capabilities browser
bash ./setup --dry-run --capabilities browser --browser managed
test ! -e "$GSTACK_HOME" || (echo "dry-run mutated GSTACK_HOME" && exit 1)
shell: bash
- name: Explicitly install the browser capability
run: |
set -e
bash ./setup --install-now --yes --capabilities browser
bash ./setup --install-now --yes --capabilities browser --browser managed
test -f "$GSTACK_HOME/versions/current.json"
test -f "$GSTACK_HOME/bin/gstack.cmd"
shell: bash