feat: componentize GStack 2 runtime and release integrity

This commit is contained in:
Sinabina
2026-07-20 14:16:23 -07:00
parent b0ea2296d1
commit f14445bb00
270 changed files with 9681 additions and 51572 deletions
+8 -8
View File
@@ -213,13 +213,13 @@ backend. The candidate distinguishes hardware UDID from CoreDevice UUID,
returns bounded 504 responses for a suspended app, asserts the expected bundle
around coordinate mutations, preserves typed snapshot/mutation/restoration,
and keeps bridge symbols debug-only. Device signing, provisioning, and
CoreDevice compatibility are setup gates, not product failures. A live
signed-device pass is still required before release. The earlier target's
preflight evidence is 9 pass / 0 fail / 1 deploy skip and 29 assertions; its
direct smoke returned `signing_unavailable`. The latest explicitly selected
target returned `device_not_wired` because iOS 16.7.10 exposes no supported
CoreDevice service. Neither attempt installed or launched an app, and no pass
artifact was written.
CoreDevice compatibility are setup gates, not product failures. Earlier
`signing_unavailable`, `device_not_wired`, and partial session-acquire results
remain retained as failures. After explicit re-authorization, the live lane
passed 12/12 harness checks and all five required iterations on a wired paired
`iPhone17,1`, including Release-symbol exclusion, ten screenshots, session
cleanup, tunnel shutdown, and workspace cleanup. The redacted artifact is
[`evidence/ios-physical-device-2026-07-20T17-49-19-302Z.json`](./evidence/ios-physical-device-2026-07-20T17-49-19-302Z.json).
PDF rendering and Mermaid/Excalidraw remain internal capabilities. GStack does
not add Typst, hosted document rendering, alternate diagram services, local
@@ -254,7 +254,7 @@ means the replacement still lacks its required release evidence.
| 19 | State identity crosses worktrees | **Implemented:** repo plus stable worktree identity selects state. | Linked-worktree core test passes. |
| 20 | Partial ship failures are not reliably idempotent | **Implemented at runtime primitive:** claimed effects become uncertain and are not automatically repeated. | Crash/resume and completed-effect tests pass. End-to-end ship resume remains pending. |
| 21 | Parser failures become empty success | **Implemented in iOS device discovery:** parse/tool failures are typed errors. | `tunnel-bootstrap.test.ts` malformed-JSON regression passes in the focused daemon suite. |
| 22 | Setup failures become product failures | **Partly implemented:** iOS discovery/setup categories and runtime doctor return actionable setup state. | Automated categories exist; live signing/build/install/launch/tunnel passed, while session acquisition and the five-check loop remain open and user-waived. |
| 22 | Setup failures become product failures | **Implemented for the tested paths:** iOS discovery/setup categories and runtime doctor return actionable setup state. | Earlier setup failures stayed typed and unpromoted; the separately authorized live lane later passed signing through five iterations and cleanup. |
| 23 | Runtime network activity is not obvious | **Implemented for Context runtime:** selection, mode, and consent are explicit; status/doctor report them; zero lookup/fetch before Context selection+consent. | Context contract: 22 pass / 0 fail / 139 assertions, including persisted non-export fallbacks; verified-key official-endpoint live smoke passed. |
| 24 | Context restore selects another worktree | **Implemented for canonical state resume:** current repo+worktree project ID scopes inspection/resume. | Linked-worktree identity test passes; compatibility end-to-end restore test pending. |
| 25 | Preambles repeat large sections in every skill | **Implemented structurally:** six thin lazy dispatchers share infrastructure and load one preserved module on demand. | Current generated six-name/description catalog is 982 characters, about 246 token-equivalents versus the correctly parsed baseline of about 1,100 (77.6% lower). Re-measure if frontmatter changes. |
+11 -3
View File
@@ -162,6 +162,14 @@ activates the version, and writes stable POSIX and Windows launchers under
Windows and includes the CoreDevice/iOS bundle only on Darwin. Add the bin
directory to `PATH` if the short `gstack` command is desired.
Official bundles capture the pinned Bun 1.3.14 executable inside the immutable
runtime and expose it as `$GSTACK_HOME/bin/bun`; browser/design/PDF launchers do
not use host-global Bun. Node remains the bootstrap/launcher floor. On Windows,
Git for Windows Bash is required only for retained shell helpers and is a
separate doctor check. Python 3 is an optional prerequisite only for specialist
flows that name it. Doctor reports both tools independently of native
browser/design/PDF readiness.
Twenty-five focused installer tests pass with 341 assertions. They cover
manifests, paths with spaces,
source-root symlinks, internal-link/path-escape rejection, failed build/
@@ -181,9 +189,9 @@ nor model weights and reports the L4 capability unavailable.
| Platform | Source-level target | Candidate evidence |
|---|---|---|
| macOS | Node runtime + local browser + physical iOS where applicable | Runtime installer 25/341 and the deterministic clean macOS arm64 bundle audit pass. The final native job passed 150/0 with 1,189 assertions. The uninterrupted broad singleton run is green at 6,255 pass / 226 expected skips / 0 fail and 25,509 assertions across 384 files. The signed-device gate is open but user-waived; no further device access is authorized. |
| Linux | Node runtime + local browser | Final native Ubuntu passed 150/0 with 1,189 assertions across 16 files. A clean Linux arm64 container also passed the production-only runtime/browser lifecycle. |
| Native Windows | Node runtime; curated free tests; browser fallback where retained | Final native Windows passed 150/0 with 1,145 assertions across 16 files and standard-installer discovery found exactly six skills. The local Windows-safe singleton lane also passed 2,829 / 57 expected skips / 0 fail with 8,648 assertions across all 214 selected files. |
| macOS | Node runtime + local browser + physical iOS where applicable | Runtime installer 25/341 and the deterministic clean macOS arm64 bundle audit pass. The final native job passed 150/0 with 1,189 assertions. The uninterrupted broad singleton run is green at 6,255 pass / 226 expected skips / 0 fail and 25,509 assertions across 384 files. The physical lane later passed 12/12 harness checks and five-of-five live iterations on an explicitly authorized wired paired `iPhone17,1`; this is device-specific evidence, not universal iOS coverage. Artifact: [`ios-physical-device-2026-07-20T17-49-19-302Z.json`](./evidence/ios-physical-device-2026-07-20T17-49-19-302Z.json). |
| Linux | Node runtime + local browser | Official release artifacts currently target glibc on x64 and arm64; musl is rejected before network and is not claimed. Final native Ubuntu passed 150/0 with 1,189 assertions across 16 files. A clean glibc Linux arm64 container also passed the production-only runtime/browser lifecycle. |
| Native Windows | Node bootstrap/launcher; managed Bun; native browser/design/PDF. Git for Windows Bash only for retained shell helpers; Python 3 only for labeled specialist flows. | Doctor verifies and discloses Bun, Bash, and Python separately. Final native Windows passed 150/0 with 1,145 assertions across 16 files and standard-installer discovery found exactly six skills. The local Windows-safe singleton lane also passed 2,829 / 57 expected skips / 0 fail with 8,648 assertions across all 214 selected files. The older run predates the managed-Bun release artifact, so the new six-target release workflow remains the evidence gate for that layer. |
| Dev Container | Pure skills and optional runtime; browser only when container supports it | The declared image built; the GStack 2 suite passed 150/0 with 1,188 assertions across 16 files, followed by the clean runtime install/browser smoke and state-preserving uninstall. |
Native CI run [`29615621805`](https://github.com/time-attack/gstack/actions/runs/29615621805)
+21 -40
View File
@@ -6,8 +6,7 @@ The harness is intentionally fail-closed. A setup problem is not a product failu
## Current validation status
The earlier target was validated locally at the July 17, 2026 checkpoint with
Xcode 26.6:
The live lane was validated locally on July 20, 2026 with Xcode 26.6:
| Identifier kind | Example form | Used for |
|---|---|---|
@@ -16,46 +15,28 @@ Xcode 26.6:
Exact local identifiers are deliberately not committed. Successful evidence stores only a SHA-256 fingerprint derived from both identifiers and omits the user-assigned device name.
The daemon suite is green at 95 pass / 0 fail and 229 assertions. For that
earlier target, the physical E2E preflight records 9 pass / 0 fail / 1 deploy
skip and 29 assertions. Its host, pairing/trust, Developer Mode, wired
transport, `devicectl`, `xcodegen`, and DevToolsSecurity gates pass. The
unsigned Release build also passes and contains no DebugBridge module symbols
or artifacts.
The daemon suite is green at 95 pass / 0 fail and 229 assertions. The final
physical lane passed 12/12 harness checks and all five required live iterations
on an explicitly authorized wired, paired `iPhone17,1` with Developer Mode
enabled. The existing Apple development identity signed the reserved fixture;
the harness did not generate or fabricate a profile. The Release guard found no
DebugBridge symbols. Safe in-place install, launch, CoreDevice IPv6 bootstrap,
boot-token rotation, five session acquire/release cycles, ten 1206×2622 PNG
screenshots, accessibility reads, coordinate taps, bundle checks, state
cleanup, tunnel shutdown, and temporary-workspace cleanup all passed. The
fixture was not uninstalled and app data was not deleted.
The earlier direct physical-device smoke was externally blocked at automatic
signing. It returned typed code `signing_unavailable`, category `setup_gate`. The
underlying Xcode diagnostic is:
The redacted atomic evidence is
[`evidence/ios-physical-device-2026-07-20T17-49-19-302Z.json`](./evidence/ios-physical-device-2026-07-20T17-49-19-302Z.json).
It stores only a SHA-256 fingerprint of the local identifiers, plus the device
model and non-secret verification results.
```text
Signing for "FixtureApp" requires a development team.
```
That is a setup gate, not a DebugBridge failure. No app was installed or
launched, and no pass artifact was written. The deploy skip and typed smoke
failure must not be represented as a physical-device pass.
The next user-selected target was a legacy iPhone (`iPhone10,6`) on iOS
16.7.10. Its lockdown/USB pairing validates, but `devicectl` reports
`pairingState=unsupported`, no wired CoreDevice transport, and pairing fails
with CoreDevice error 1011. The harness therefore returns typed code
`device_not_wired` before build or deploy. Because CoreDevice is the locked
backend, substituting a legacy or third-party device driver would not satisfy
this gate; a CoreDevice-compatible iPhone is required.
The user then explicitly authorized the other connected, CoreDevice-compatible
iPhone. That run passed pairing, signing, build, install, launch, and tunnel
setup. The full five-check loop did not complete: `POST /session/acquire`
closed the socket before returning a session. At harness stop, the fixture app
was left installed with its data intact and no console/device session remained
attached. This is a retained operator observation, not a pass artifact; no pass
artifact was written.
The user then explicitly stopped and waived further iPhone testing. No more
device access is authorized for this checkpoint. The preflight, Release guard,
typed setup-gate failures, and partial signed deployment above remain valid
evidence, but the waiver does not convert them into a P0 pass: the five-check
loop did not complete and no pass artifact exists.
Earlier attempts remain part of the record and are not relabeled by the later
pass: one target returned `signing_unavailable`; an `iPhone10,6` on iOS 16.7.10
returned `device_not_wired` / CoreDevice error 1011; and one authorized run
reached tunnel setup before its first session-acquire socket closed. Those were
correctly classified as setup or partial evidence and produced no pass
artifact.
## Hardware UDID versus CoreDevice UUID
+3 -3
View File
@@ -2,17 +2,17 @@
Parity is executable, not a prose claim. Run `bun run scripts/gstack2/run-parity.ts` or the dedicated Bun tests.
The pinned release inventory passes **4,681 checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 16 regression ports, and **78 assets**.
The pinned release inventory passes **4,697 checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 16 regression ports, and **78 assets**.
The suite verifies:
- exactly six discoverable public skills and 55 internal legacy modules;
- 55 canonical templates plus 16 carved section templates at base `bb57306d98c97011b0919c6132705a15b1579781`;
- normalized legacy-body SHA-256 equality between source rendering and generated references;
- immutable full 1.x render hashes plus canonical specialist-render equality, with the excluded onboarding wrapper and lazy section references asserted explicitly;
- preservation of nine behavioral contract dimensions per module;
- 25 structured non-keyword routing fixtures with active/skipped modules, depth, mutation, and web context;
- 16 upstream judgment-port regression fixtures and anchors;
- all linked asset copies against their pinned Git blobs;
- frontmatter and `agents/openai.yaml` schema for each public skill.
Golden normalization removes only generated provenance wrappers, bug-fix overlays, and irrelevant whitespace. It never removes legacy workflow prose, gates, questions, evidence requirements, artifacts, or exit behavior.
Golden normalization removes only generated provenance wrappers, bug-fix overlays, and irrelevant whitespace. Canonical rendering separately excludes the retired shared onboarding wrapper and packages large specialist phases as lazy references; parity checks both decisions explicitly without claiming full-body byte equality.
File diff suppressed because it is too large Load Diff
+6
View File
@@ -17,6 +17,12 @@ unit test is not a substitute for the remaining live egress audit listed in
| Physical iPhone | local Mac/device bridge | optional pre-existing Tailscale path only when explicitly configured | device session to a cloud-device farm or alternate driver provider |
| Telemetry | off in the GStack 2 contract | minimal legacy telemetry only after its independent opt-in | code, prompts, paths, repo/branch names, user content |
Skill update discovery and installation belong to the user-invoked Agent
Skills installer (`npx skills update`). GStack preambles make no passive
release request. The retained `gstack-update-check` compatibility helper exits
before state or network access unless the operator explicitly passes
`--force`; `update_check` also defaults to false.
Network installation is not Context.dev consent. Browser navigation is not
Context.dev consent. A key present in the environment is not consent. The
Context client requires persisted selection `context`, mode `context`, and
+118
View File
@@ -0,0 +1,118 @@
# Release integrity
GStack has two explicit version identities during the 2.0 migration:
- `VERSION` and `package.json.version` are the repository/package release
counter. They remain byte-equal and retain the existing four-slot format so
the 1.x compatibility ship queue does not silently fail open.
- `package.json.gstack.runtimeVersion`, `runtime/index.js`,
`runtime/install.js`, and every standards-installed bootstrap declare the
managed-runtime protocol release `2.0.0`. The official artifact tag and
manifest use that value.
They are intentionally different namespaces. CI fails if either identity
drifts inside its own namespace.
## Runtime release
The `Release runtime artifacts` workflow builds the complete managed bundle on
six native targets:
```text
darwin-arm64 darwin-x64
linux-arm64 linux-x64 (glibc)
windows-arm64 windows-x64
```
Each archive has one `gstack/` root and no symlinks. CI records an exact byte
count and SHA-256, signs the archive keylessly with Cosign, emits a Sigstore
bundle, and also creates a GitHub build-provenance attestation. The release
manifest contains only official GitHub Release URLs and the fixed workflow
certificate identity.
Browser-capable archives include the Playwright-managed Chromium directory at
`.gstack-runtime-browsers`. The builder runs `playwright install chromium`
only—never `--with-deps` or `sudo`—copies physical files into the immutable
slot, and launch-smokes that exact Chromium on every native release runner.
The stable capability launcher sets `PLAYWRIGHT_BROWSERS_PATH` to the active
slot; it does not rely on an operator's global Playwright cache.
Each official artifact also owns its Bun executable. Release CI pins Bun
1.3.14, copies that physical executable into
`.gstack-runtime-tools/bun[.exe]`, records its relative path and probed version
in `.gstack-bundle.json`, and exposes it through the stable `$GSTACK_HOME/bin/bun`
launcher. The tagged Bun license inventory and source/relink notice are
vendored under `runtime/licenses/` and their expected hashes are release-gated.
The native release smoke removes the `setup-bun` directory from `PATH`, supplies
only an explicit `GSTACK_NODE`, runs the stable managed-Bun launcher, and opens
`about:blank` through the installed browser before cleanup. Compiled browser
clients use their adjacent `server-node.mjs` on every platform, so browser,
design, and PDF readiness does not depend on a host-global Bun installation.
The bootstrap always verifies the manifest schema, target, exact byte count,
and SHA-256 before extraction. If Cosign is already installed it additionally
verifies the Sigstore bundle, certificate identity, and GitHub Actions OIDC
issuer. Cosign is not downloaded or required on an end-user machine.
The official Linux archives are glibc builds. The bootstrap detects a musl
host before any network request and returns a typed unsupported-platform error;
it does not download a glibc archive that cannot validate on Alpine. Musl is
not claimed by the current six-artifact release matrix.
Runtime tool requirements are capability-scoped. Node is the bootstrap and
stable-launcher floor. On Windows, retained shell-based helpers additionally
require Git for Windows Bash; doctor reports that check explicitly. Python 3 is
only required by specialist flows that label it as a prerequisite. Missing
Bash or Python does not change the native browser/design/PDF payload or turn
those capabilities into host-global Bun consumers.
## npm package
The npm tarball is a small runtime-control/bootstrap package, not a second
GStack installer. Its allowlist contains the Node-only runtime control plane,
the `gstack` launcher, documentation, license, and version marker. It excludes
the six skills and large compiled capability payloads. Skills come from the
Agent Skills installer; optional capability payloads come from the verified
runtime release only after approval.
CI packs the tarball, installs it into an isolated directory, invokes
`gstack --version`, initializes isolated state through `gstack setup`, and
invokes `gstack-runtime-bootstrap --help`. It also enforces conservative packed
size and entry-count ceilings.
## Dependency audit policy
`puppeteer-core` was unused and removed. Playwright remains the only browser
manager. Bun's current audit command does not distinguish production from
development dependencies, so CI gates critical advisories across the entire
lockfile and reports the complete audit. At the 2026-07-20 checkpoint, the
remaining high advisories are under the retained development-only Claude Agent
SDK and Hugging Face evaluation stack; neither is copied into the managed
runtime. They must be re-audited before changing those test SDKs or promoting
the release status.
## Static-analysis disposition
- Shell syntax and high-confidence ShellCheck errors are gated on setup and
release/build boundaries. Runtime JavaScript is syntax-checked with the
supported Node floor. Workflow actions are pinned and actionlint remains its
own gate.
- Added production/docs lines are scanned by GStack's deterministic redaction
engine. Removed lines do not block credential cleanup. Known synthetic-secret
fixture/evaluation paths are excluded so the gate stays meaningful; those
paths retain dedicated redaction tests.
- The repository has no TypeScript compiler dependency or `tsconfig.json`.
Calling Bun transpilation a typecheck would be false, while enabling `tsc`
across the legacy mixed JS/TS/generated tree is a separate migration. This
candidate records typecheck as not yet enforceable rather than a green gate.
- There is no repository formatter or general source-linter configuration.
Introducing one during release hardening would mechanically rewrite
byte-pinned generated and parity corpora. Actionlint, ShellCheck, runtime
syntax, existing tests, and generated-freshness checks are enforced now; a
formatter/linter migration remains explicit follow-up work.
- No `CODEOWNERS` file is invented. Git history identifies contributors but
does not prove the current GitHub user/team with review authority in the
`time-attack` organization. Repository administrators must name a real team
and enable required CODEOWNER review together; until then ownership review
is an open governance control, not a fabricated file.
+3 -3
View File
@@ -2,7 +2,7 @@
Pinned baseline: `bb57306d98c97011b0919c6132705a15b1579781`.
GStack 2 exposes exactly six public Codex skills: `plan`, `design`, `qa`, `debug`, `review`, and `ship`. The 55 legacy templates remain mechanically rendered as internal reference modules; all 16 carved section templates are inlined with the canonical Codex resolver path. Thirty-one primary modules are mandatory specialist inputs, and 24 supporting modules remain reachable through compatibility routing.
GStack 2 exposes exactly six public skills: `plan`, `design`, `qa`, `debug`, `review`, and `ship`. The specialist bodies from 55 legacy templates remain provenance-pinned internal reference modules. The retired 1.x shared onboarding wrapper is excluded from canonical execution, and all 16 carved specialist sections are package-local lazy references loaded only at their original workflow point. Thirty-one primary modules are mandatory specialist inputs, and 24 supporting modules remain reachable through compatibility routing.
The fixed public modes are: Design = `Explore | Generate | Critique | Implement`; QA = `Report | Fix`; Debug = `Diagnose-only | Fix`; Review = `Normal | Security | Performance | Deep`; Ship = `Prepare | Land | Deploy | Monitor | Resume`. Richer legacy modes are internal aliases only.
@@ -74,6 +74,6 @@ The fixed public modes are: Design = `Explore | Generate | Critique | Implement`
## Mechanical versus judgment changes
- `MECHANICAL_PORT`: canonical Codex resolver expansion, section inlining, safety prose, and path rewrites only.
- `BUG_FIX`: the mechanical body plus a clearly delimited judgment overlay sourced from one of the 16 upstream PRs and its regression fixture.
- `JUDGMENT_PRESERVING_CARVE`: pinned specialist workflow with the retired shared onboarding wrapper excluded, retired invocations resolved to six public routes, host/runtime paths normalized, and large carved phases loaded lazily from package-local pinned references.
- `BUG_FIX`: the canonical carved body plus a clearly delimited judgment overlay sourced from one of the 16 upstream PRs and its regression fixture.
- Asset relocation is byte-for-byte from the pinned Git blob and is indexed per tree.
+23 -25
View File
@@ -1,11 +1,11 @@
# GStack 2 status
**Status at the 2026-07-17 documentation checkpoint: `BLOCKED`.**
**Status at the 2026-07-20 documentation checkpoint: `BLOCKED`.**
The candidate contains substantial implementation, but it is not a released or
verified GStack 2. `DONE` is prohibited until every P0 gate is backed by the
required evidence layer. Current blockers include the waived physical-iPhone P0
gate and the failed live v3 installed-host adversarial gate, including
required evidence layer. The physical-iPhone P0 gate is now green. The current
blocker is the failed live v3 installed-host adversarial gate, including
incomplete representative host UI/process coverage. Native CI is green on
macOS, Ubuntu, Windows, and the Dev Container. No release-branch push, draft
PR, or PR-ready claim is authorized by this status.
@@ -57,8 +57,8 @@ PR, or PR-ready claim is authorized by this status.
three retained Claude Haiku live samples are classified `REGRESSION`; they
are preserved as noisy supplemental evidence, never cherry-picked as a
primary gate or represented as green.
- [x] The current macOS GStack 2 suite is green at commit `a8a5fa1a`: 150 pass
/ 0 fail and 1,189 assertions across 16 files.
- [x] The current macOS GStack 2 suite is green: 151 pass / 0 fail and 1,194
assertions across 16 files.
- [x] Optional host-neutral runtime implemented with canonical paths,
repo/worktree state identity, locks, atomic writes, effect claims,
doctor/config/state/cleanup, migrations, upgrade/rollback, and uninstall.
@@ -75,6 +75,15 @@ PR, or PR-ready claim is authorized by this status.
production-only install with the development SDK absent, completed a local
browser journey and Sharp full-page screenshot, and uninstalled while
preserving state.
- [x] The current candidate additionally captures a runtime-owned Bun 1.3.14
executable under `.gstack-runtime-tools`, records its path/version in the
bundle manifest, vendors the tagged license/source notices, and routes the
compiled browser to adjacent `server-node.mjs` on every platform. Focused
tests cover managed-Bun launch with host Bun absent. The older native-CI and
bundle-size evidence above predates this payload; the new six-target signed
release workflow must execute before this layer is called verified. Windows
Bash and specialist Python checks are reported separately and are not native
browser/design/PDF dependencies.
- [x] Filesystem lifecycle coverage passes for clean install/uninstall,
paths with spaces, source symlinks with internal-link rejection, read-only
destination reporting on macOS, interrupted-pointer rollback, crash-journal
@@ -98,20 +107,14 @@ PR, or PR-ready claim is authorized by this status.
fail / 398 assertions; and diagram 51 pass / 0 fail / 1 skip / 120
assertions. The opt-in paid diagram lane recorded two skips and is not live
provider evidence.
- [x] Physical-iOS preflight recorded 9 pass / 0 fail / 1 deploy skip and 29
assertions. The direct smoke then returned typed code
`signing_unavailable`, category `setup_gate`; it installed no app and wrote no
pass artifact. A later attempt against the explicitly selected iPhone10,6 on
iOS 16.7.10 returned `device_not_wired`; legacy USB pairing validates, but
CoreDevice pairing is unsupported. After the user explicitly authorized the
other connected phone, pairing/signing/build/install/launch/tunnel setup
passed, but `POST /session/acquire` closed its socket before the five-check
loop completed. At harness stop, no device session remained attached and the
fixture app was left installed. These are retained operator observations;
no pass artifact exists.
- [x] The user explicitly stopped and waived further physical-iPhone testing.
No more device access is authorized. The earlier partial/setup-gate evidence
remains retained, but it is not a physical-device P0 pass.
- [x] After the user re-authorized the connected test phone, the physical-iOS
lane passed 12/12. The existing Apple-signed wildcard development profile and
matching private key signed the reserved fixture; no fabricated profile was
needed. Release guard, safe in-place install, launch, CoreDevice bootstrap,
boot-token rotation, all five session acquire/release cycles, ten live
screenshots, accessibility elements, coordinate taps, bundle checks, state
cleanup, tunnel shutdown, and temporary-workspace cleanup passed. Artifact:
[`evidence/ios-physical-device-2026-07-20T17-49-19-302Z.json`](./evidence/ios-physical-device-2026-07-20T17-49-19-302Z.json).
- [x] Installed-host adversarial evidence is retained without relabeling:
v1 **failed**; immutable v2 **failed** even though QA passed because the
classifier produced false negatives for debug, review, and ship; v3 offline
@@ -153,11 +156,6 @@ PR, or PR-ready claim is authorized by this status.
the immutable one-shot result is **3/4**, with review failing compound
inspection. Do not retry or relabel it. The six hosts remain **Verified at
the installer layer only**; representative UI/process coverage is incomplete.
- [ ] The physical-iPhone five-check loop remains incomplete and is explicitly
waived by the user. No further device access is authorized. The unsigned
Release guard and earlier preflight/setup-gate observations remain useful
partial evidence. A signed fixture was later installed and launched, but its
session-acquire request failed; no pass artifact exists and P0 remains open.
- [ ] Finish final evidence-linked disposition for every infrastructure item;
see the 25-row table in [ARCHITECTURE.md](./ARCHITECTURE.md). Current focused
evidence does not replace the remaining live gates.
@@ -179,7 +177,7 @@ PR, or PR-ready claim is authorized by this status.
| Context integration | [CONTEXT-DEV.md](./CONTEXT-DEV.md) | Automated contract 22/139 green; verified-key official-endpoint live smoke passed |
| Host matrix | [HOST-COMPATIBILITY.md](./HOST-COMPATIBILITY.md) | 470/470 checks; Codex runtime-absent run passed; live v3 failed; other UI launches pending |
| Privacy boundary | [PRIVACY.md](./PRIVACY.md) | Implemented contract; full retained-tool egress audit pending |
| Physical iOS | [IOS-PHYSICAL-DEVICE.md](./IOS-PHYSICAL-DEVICE.md) | Partial setup evidence only; user stopped/waived further device testing; no P0 pass artifact |
| Physical iOS | [IOS-PHYSICAL-DEVICE.md](./IOS-PHYSICAL-DEVICE.md), [live artifact](./evidence/ios-physical-device-2026-07-20T17-49-19-302Z.json) | 12/12 harness tests and five-of-five live iterations passed on a wired paired iPhone |
| Upgrade/recovery | [UPGRADE-AND-ROLLBACK.md](./UPGRADE-AND-ROLLBACK.md) | Runtime installer 25 pass / 341 assertions; deterministic clean macOS arm64 bundle audit recorded |
## Interpretation rules
+5 -5
View File
@@ -1,6 +1,6 @@
# GStack 2.0 test evidence
## Candidate checkpoint — 2026-07-17
## Candidate checkpoint — 2026-07-20
These results describe the working tree at the documentation checkpoint. They
are deliberately narrower than the P0 release matrix. Commands that need a
@@ -10,7 +10,7 @@ pass from deterministic, offline, or filesystem-only evidence.
| Command / probe | Observed result | What it proves / does not prove |
|---|---|---|
| Earlier focused macOS `bun test test/gstack2-*.test.ts` candidate run | **Exit 0: 136 pass / 0 fail**, 1,128 assertions across 15 files. Log: `/tmp/gstack2-test-command-candidate-final2.log`. | Historical focused checkpoint retained rather than overwritten. |
| Current macOS `bun run test:gstack2`, commit `a8a5fa1a` | **Exit 0: 150 pass / 0 fail**, 1,189 assertions across 16 files. | Current generated freshness, routing, runtime, privacy, installer, upgrade, parity, and adversarial-harness surface is green. Native and broad evidence are recorded separately. |
| Current macOS `bun run test:gstack2` | **Exit 0: 151 pass / 0 fail**, 1,194 assertions across 16 files. | Current generated freshness, routing, runtime, privacy, installer, upgrade, parity, and adversarial-harness surface is green. Native and broad evidence are recorded separately; this working-tree result is not attributed to the earlier native-CI commit. |
| `bun test --timeout 30000 test/gstack2-skills.test.ts test/gstack2-skills-routing.test.ts` after regeneration | **Exit 0: 3 pass / 0 fail**, 81 assertions. | The pinned corpus/parity test and both 25-scenario structured-routing tests are green. This remains structural/fixture evidence, not specialist live execution. |
| `bun run scripts/gstack2/run-parity.ts`, 2026-07-17 rerun | **Exit 0: 4,681 checks passed**; 55 modules, 16 sections, 25 scenarios, 16 regressions, 78 assets. | Current source/render/provenance/contract/asset/fixture parity is green. It is deterministic parity, not live-host behavior. |
| Earlier regenerated structural parity checkpoint | **Exit 0: 2,403 checks passed** with the then-current 55/16/25/16/45 inventory. | Historical candidate checkpoint before later thin-prelude and asset coverage; superseded by the current 4,681-check rerun. |
@@ -24,8 +24,8 @@ pass from deterministic, offline, or filesystem-only evidence.
| Six-skill catalog measurement after regeneration | Six names/descriptions total 982 characters, about 246 four-character token-equivalents; baseline correctly parsed catalog was about 1,100. | 77.6% reduction, above the 75% gate. Re-measure if frontmatter changes. The buggy 4,214 baseline estimate is not used. |
| `bun test ios-qa/daemon/test` | **95 pass / 0 fail**, 229 assertions. | Covers daemon regressions including malformed device JSON, hardware-UDID/CoreDevice selection, bounded proxy timeout, and expected-bundle mutation header. It is not a signed-app live pass. |
| Focused DebugBridge/template build tests | **33 pass / 0 fail** in the candidate run, including Swift debug compilation/XCTest and Release symbol absence. | Static/build evidence for debug-only bridge wiring; still not an installed physical-app journey. |
| Physical-iOS E2E preflight | **9 pass / 0 fail / 1 deploy check skipped**, 29 assertions. | The earlier connected-device/setup and unsigned Release checks pass. The deploy skip leaves the signed-device P0 gate open. |
| Direct physical-device smoke | **Incomplete, not a pass:** one target returned `signing_unavailable`; the legacy iPhone10,6 target returned `device_not_wired` / CoreDevice error 1011; the subsequently authorized CoreDevice-compatible phone passed pairing, signing, build, install, launch, and tunnel setup but `POST /session/acquire` closed its socket before the five-check loop completed. | The harness process was stopped at the user's request. At harness stop, the signed fixture was left installed with data intact and no device session remained attached. These are retained operator observations; no pass artifact was written. Further iPhone testing is waived and unauthorized for this checkpoint. |
| Earlier physical-iOS setup attempts | **Incomplete, not passes:** the preflight recorded 9 pass / 0 fail / 1 deploy check skipped and 29 assertions; one target returned `signing_unavailable`; the legacy iPhone10,6 target returned `device_not_wired` / CoreDevice error 1011; a later authorized phone reached tunnel setup but its first session-acquire socket closed. | Immutable historical setup/partial evidence. The later pass does not erase or relabel these attempts. |
| Physical-device smoke, 2026-07-20 | **PASS:** 12/12 harness checks and all five required live iterations. Release symbols were absent; signing, safe in-place install, launch, CoreDevice bootstrap, boot-token rotation, five session acquire/release cycles, ten screenshots, accessibility reads, coordinate taps, bundle checks, state cleanup, tunnel shutdown, and temporary-workspace cleanup passed. | Closes the physical-iPhone evidence layer for the tested wired paired `iPhone17,1`; it is not a claim about every iPhone or iOS release. Redacted artifact: [`ios-physical-device-2026-07-20T17-49-19-302Z.json`](./evidence/ios-physical-device-2026-07-20T17-49-19-302Z.json). |
| Context.dev contract (`gstack2-runtime-context.test.ts`) | **22 pass / 0 fail**, 139 assertions. | Persists explicit host/local-browser/none choices without consent, rejects private/credential URLs and request material plus private DNS, proves zero lookup/fetch before mode+consent, validates documented endpoint paths and exact failure taxonomy, and makes search typed unsupported without network. |
| `gstack context smoke --url https://www.context.dev --json` | **PASS:** the official `/web/scrape/markdown` endpoint returned `ok: true` and credit metadata. | The verified key entered through protected stdin/environment worked. The temporary secrets file was mode `0600`, the isolated home was removed, and the safe output did not contain the key. Committed redacted artifact: [`evals/context-dev/live-smoke-2026-07-17.json`](../../evals/context-dev/live-smoke-2026-07-17.json). |
| Standard installer matrix | **PASS: 470/470 checks**, 16 install cases, two removal cases, `skills` CLI 1.5.19. | Project/global installs pass for six hosts, selected-skill and opt-in compatibility-alias cases, copies, and hashes. This remains installer/filesystem evidence. Committed artifact: [`evals/installation/install-matrix.json`](../../evals/installation/install-matrix.json). |
@@ -70,7 +70,7 @@ macOS + Linux + native Windows + Dev Container
local browser live journey + cancellation/leak cleanup (passed)
PDF strict + diagram suites
Context.dev verified-key public-page smoke
physical signed-iPhone five-check loop + Release symbol check (waived; partial evidence is not a pass)
physical signed-iPhone five-check loop + Release symbol check (passed on 2026-07-20; retain earlier failures separately)
upgrade/fail/recover/rollback/uninstall end-to-end
```
+12 -2
View File
@@ -6,11 +6,15 @@ remains Markdown-only; runtime dependencies are never smuggled into that path.
## Skill updates
Install and update the canonical Agent Skills source with the same standard
installer that placed it:
Install the canonical Agent Skills source, then use that installer's tracked
source and lock metadata for discovery, updates, and removal:
```bash
npx skills add time-attack/gstack
npx skills update # interactive scope
npx skills update -p # project installs only
npx skills update -g # global installs only
npx skills remove # interactive removal
```
Use that installer's update/remove commands and scope. It owns project/global
@@ -18,6 +22,12 @@ placement, host destination paths, and selected-skill choices. GStack must not
re-detect hosts during an update or enroll a host/skill the user did not
previously select.
The current installer exposes update rather than a separate dry-run/check
command. GStack skill preambles do not phone GitHub for releases. The retained
`gstack-update-check --force` path exists only for an explicitly requested 1.x
compatibility check; it is never run passively by GStack 2. Optional runtime
activation remains the separate reviewed-source transaction documented below.
Before accepting an update, list the source and confirm that the defaults are
still exactly `plan`, `design`, `qa`, `debug`, `review`, and `ship`. Pure
judgment must remain usable even if the optional runtime update fails.
@@ -0,0 +1,48 @@
# ADR 0001: public infrastructure tools
- Status: accepted for the GStack 2 candidate
- Date: 2026-07-20
- Scope: installation, first-use UX, browser binaries, release integrity, and
updater ownership
## Decision
Use public tools only where they have a narrow, replaceable responsibility:
| Responsibility | Decision | Boundary |
|---|---|---|
| Skill discovery, host placement, project/global scope, selection, update, and removal | [Vercel Agent Skills CLI](https://github.com/vercel-labs/skills), pinned to 1.5.19 in verification | Canonical and exclusive skill lifecycle. GStack never silently enrolls a host. |
| Interactive terminal prompts | [Clack](https://github.com/bombshell-dev/clack), if adopted after the current zero-dependency prompt surface needs richer TTY UX | Presentation only; consent state, policy, transactions, and non-TTY flags stay in GStack. No dependency is added merely for styling. |
| Local browser binaries | [Playwright](https://playwright.dev/docs/browsers) | Existing local Chromium manager only. No cloud-browser provider. |
| Cross-platform launchers | [Bun compile](https://bun.sh/docs/bundler/executables) | Build-time native launcher production; the runtime remains host-neutral. |
| Release signing and verification metadata | [Sigstore Cosign](https://docs.sigstore.dev/cosign/signing/signing_with_blobs/) in release CI | CI signs immutable archives keylessly. Every client verifies byte count and SHA-256; Cosign verification is additional when already installed, never a mandatory end-user install. |
| Release attestations | [GitHub artifact attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/use-artifact-attestations) | Provenance for release artifacts, with actions pinned to immutable commits and `id-token: write` limited to the signing job. |
GStack owns the product-specific remainder: the signed runtime manifest,
capability consent, atomic install journal, rollback, doctor output, and the
first-use prompt that appears only when a chosen skill needs an unavailable
capability.
## Rejected as mandatory dependencies
- `oclif`: a second CLI framework would not solve skill placement, consent, or
transactional updates and would expand the runtime dependency surface.
- `eget`: convenient binary download UX, but it does not encode GStack's fixed
artifact host, manifest, capability, rollback, or privacy policies.
- `mise` and `aqua`: useful optional environment/package managers, but requiring
either would add a package manager in front of the standard Agent Skills
installer.
- hosted browsers, device farms, alternate iOS drivers, ComfyUI, model weights,
and GPU runtimes: outside the accepted architecture.
## Consequences
The standard installer can evolve independently without GStack maintaining six
host adapters. The optional runtime has one auditable release format and no
automatic setup. Public-tool telemetry and network behavior must be disclosed
at the point of use; upstream Agent Skills telemetry can be disabled with
`DISABLE_TELEMETRY=1` or `DO_NOT_TRACK=1`.
The repository keeps tests for the pinned installer behavior and release
contract. A future tool swap must preserve those contracts instead of leaking
the tool's own nouns into the six-skill public surface.
@@ -0,0 +1,277 @@
{
"schemaVersion": 1,
"kind": "gstack-ios-qa-physical-device",
"passed": true,
"generatedAt": "2026-07-20T17:49:19.302Z",
"requiredIterations": 5,
"passedIterations": 5,
"toolchain": {
"developerDir": "/Applications/Xcode.app/Contents/Developer",
"xcodeVersion": "Xcode 26.6",
"xcodeBuildVersion": "Build version 17F113",
"xcodegenVersion": "Version: 2.45.4",
"devicectlPath": "/Applications/Xcode.app/Contents/Developer/usr/bin/devicectl",
"devToolsSecurity": "enabled"
},
"device": {
"identifierSha256": "0f99cfc90afe9f65b2657efde10b259bfe6d1e12e8b4ee18a9123ff1a367bdda",
"model": "iPhone17,1",
"platform": "iOS",
"transportType": "wired",
"pairingState": "paired",
"developerModeStatus": "enabled"
},
"bundleId": "com.gstack.iosqa.fixture.gstack2",
"signing": {
"automatic": true,
"explicitTeamFromEnvironment": true
},
"installSafety": {
"existingBundle": "related_fixture",
"appDataDeleted": false,
"appUninstalled": false
},
"releaseGuard": {
"built": true,
"debugBridgeSymbolsAbsent": true,
"executableSha256": "796a3e70e0a9a414018738e606b1bbf40d30de9d552eb497b41c2ac5cba4c6b8"
},
"bootstrap": {
"transport": "CoreDevice IPv6",
"daemonBootstrap": true,
"tokenRotated": true,
"stateServerPort": 9999
},
"iterations": [
{
"iteration": 1,
"passed": true,
"checks": {
"health_bundle": {
"passed": true,
"bundleBefore": "com.gstack.iosqa.fixture.gstack2",
"bundleAfter": "com.gstack.iosqa.fixture.gstack2"
},
"token_rotation": {
"passed": true,
"originalBootTokenRejected": true
},
"session_acquire": {
"passed": true,
"sessionIdIssued": true,
"released": true
},
"screenshot_elements": {
"passed": true,
"elementCountBefore": 2,
"elementCountAfter": 2,
"screenshotBefore": {
"sha256": "79c12380fb2d917da3be02c642866ed6d0cb0b69daa835966e8c4791e153cb15",
"bytes": 101454,
"width": 1206,
"height": 2622
},
"screenshotAfter": {
"sha256": "3cbeef4d8909457b95321d94197a830ca394ba744d0a6e3d89058c98b5b6e72e",
"bytes": 102531,
"width": 1206,
"height": 2622
}
},
"coordinate_tap_state_cleanup": {
"passed": true,
"buttonLabelBefore": "Tap (0)",
"buttonLabelAfter": "Tap (1)",
"activeBundleBefore": "com.gstack.iosqa.fixture.gstack2",
"activeBundleAfter": "com.gstack.iosqa.fixture.gstack2",
"stateCleanup": "unchanged"
}
}
},
{
"iteration": 2,
"passed": true,
"checks": {
"health_bundle": {
"passed": true,
"bundleBefore": "com.gstack.iosqa.fixture.gstack2",
"bundleAfter": "com.gstack.iosqa.fixture.gstack2"
},
"token_rotation": {
"passed": true,
"originalBootTokenRejected": true
},
"session_acquire": {
"passed": true,
"sessionIdIssued": true,
"released": true
},
"screenshot_elements": {
"passed": true,
"elementCountBefore": 2,
"elementCountAfter": 2,
"screenshotBefore": {
"sha256": "53b4df2d0be8fdc02e9f27f878b717783869c3de17dd7883bdae2eb3fff3e7b6",
"bytes": 100757,
"width": 1206,
"height": 2622
},
"screenshotAfter": {
"sha256": "eb3d92cc191c017d1d5f83b0812959facb17679931f31cb0c2e922997b86c17a",
"bytes": 102447,
"width": 1206,
"height": 2622
}
},
"coordinate_tap_state_cleanup": {
"passed": true,
"buttonLabelBefore": "Tap (1)",
"buttonLabelAfter": "Tap (2)",
"activeBundleBefore": "com.gstack.iosqa.fixture.gstack2",
"activeBundleAfter": "com.gstack.iosqa.fixture.gstack2",
"stateCleanup": "unchanged"
}
}
},
{
"iteration": 3,
"passed": true,
"checks": {
"health_bundle": {
"passed": true,
"bundleBefore": "com.gstack.iosqa.fixture.gstack2",
"bundleAfter": "com.gstack.iosqa.fixture.gstack2"
},
"token_rotation": {
"passed": true,
"originalBootTokenRejected": true
},
"session_acquire": {
"passed": true,
"sessionIdIssued": true,
"released": true
},
"screenshot_elements": {
"passed": true,
"elementCountBefore": 2,
"elementCountAfter": 2,
"screenshotBefore": {
"sha256": "4656fc665904354173d8a427508e718f82cac1925fe9ad99b8f864fbb21a3157",
"bytes": 101174,
"width": 1206,
"height": 2622
},
"screenshotAfter": {
"sha256": "33249251e1616368eafdaea731765bac837deea42faa34372850d1119c69c53e",
"bytes": 101832,
"width": 1206,
"height": 2622
}
},
"coordinate_tap_state_cleanup": {
"passed": true,
"buttonLabelBefore": "Tap (2)",
"buttonLabelAfter": "Tap (3)",
"activeBundleBefore": "com.gstack.iosqa.fixture.gstack2",
"activeBundleAfter": "com.gstack.iosqa.fixture.gstack2",
"stateCleanup": "unchanged"
}
}
},
{
"iteration": 4,
"passed": true,
"checks": {
"health_bundle": {
"passed": true,
"bundleBefore": "com.gstack.iosqa.fixture.gstack2",
"bundleAfter": "com.gstack.iosqa.fixture.gstack2"
},
"token_rotation": {
"passed": true,
"originalBootTokenRejected": true
},
"session_acquire": {
"passed": true,
"sessionIdIssued": true,
"released": true
},
"screenshot_elements": {
"passed": true,
"elementCountBefore": 2,
"elementCountAfter": 2,
"screenshotBefore": {
"sha256": "51f8f4accf7672ffb8b6514573e01e5eac920fbd1969ee9e461af4deca61d517",
"bytes": 101364,
"width": 1206,
"height": 2622
},
"screenshotAfter": {
"sha256": "fdc38ca399448b6ae9e0d7c8f0309b41c760493e050fad540d334e0c7c75fd9c",
"bytes": 100190,
"width": 1206,
"height": 2622
}
},
"coordinate_tap_state_cleanup": {
"passed": true,
"buttonLabelBefore": "Tap (3)",
"buttonLabelAfter": "Tap (4)",
"activeBundleBefore": "com.gstack.iosqa.fixture.gstack2",
"activeBundleAfter": "com.gstack.iosqa.fixture.gstack2",
"stateCleanup": "unchanged"
}
}
},
{
"iteration": 5,
"passed": true,
"checks": {
"health_bundle": {
"passed": true,
"bundleBefore": "com.gstack.iosqa.fixture.gstack2",
"bundleAfter": "com.gstack.iosqa.fixture.gstack2"
},
"token_rotation": {
"passed": true,
"originalBootTokenRejected": true
},
"session_acquire": {
"passed": true,
"sessionIdIssued": true,
"released": true
},
"screenshot_elements": {
"passed": true,
"elementCountBefore": 2,
"elementCountAfter": 2,
"screenshotBefore": {
"sha256": "a69d045e493ca32f15646deed3e59da2873841171cde618236c03483299c40f9",
"bytes": 100881,
"width": 1206,
"height": 2622
},
"screenshotAfter": {
"sha256": "025a192e2e542836141fb85ef350d22e30362df1fbd4ddd15bae35b86a7b6f59",
"bytes": 102183,
"width": 1206,
"height": 2622
}
},
"coordinate_tap_state_cleanup": {
"passed": true,
"buttonLabelBefore": "Tap (4)",
"buttonLabelAfter": "Tap (5)",
"activeBundleBefore": "com.gstack.iosqa.fixture.gstack2",
"activeBundleAfter": "com.gstack.iosqa.fixture.gstack2",
"stateCleanup": "unchanged"
}
}
}
],
"cleanup": {
"sessionsReleased": true,
"tunnelKeepaliveStopped": true,
"temporaryWorkspaceRemoved": true
}
}