mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-21 04:10:47 +02:00
269 lines
18 KiB
Markdown
269 lines
18 KiB
Markdown
# GStack 2 architecture
|
|
|
|
Status: implemented in the candidate branch, with release evidence still
|
|
pending. This document describes the candidate; it is not a 2.0 release claim.
|
|
The authoritative gate state is [STATUS.md](./STATUS.md).
|
|
|
|
## Product boundary
|
|
|
|
GStack 2 is an engineering judgment layer with exactly six public skills:
|
|
|
|
```text
|
|
plan -> design -> qa -> debug -> review -> ship
|
|
```
|
|
|
|
This is a navigation surface, not a linear workflow and not a compression of
|
|
specialists into generic prompts. Each dispatcher selects a mode from
|
|
structured stage, surface, artifact, mutation-authority, evidence, and deploy
|
|
signals. It prints the target, mode, depth, mutation boundary, active modules,
|
|
skipped modules, and web-context choice before work. It then loads only the
|
|
selected preserved module.
|
|
|
|
The canonical tree is:
|
|
|
|
```text
|
|
skills/
|
|
plan|design|qa|debug|review|ship/
|
|
SKILL.md thin dispatcher
|
|
agents/openai.yaml optional host presentation metadata
|
|
references/
|
|
legacy/*.md lazily loaded preserved specialists
|
|
ASSETS.md relocated-asset index
|
|
COMPATIBILITY.md old-name routes within this tree
|
|
assets/ copied assets with pinned blob evidence
|
|
compat/*.md internal aliases, never default skills
|
|
evals/parity/ contracts, scenarios, regressions, manifest
|
|
```
|
|
|
|
`scripts/gstack2/generate-skill-tree.ts` mechanically renders 55 pinned legacy
|
|
modules, inlines 16 carved sections, and carries 78 assets. The generator
|
|
records source Git blob IDs and normalized render hashes. It adds only reviewed
|
|
upstream bug-fix overlays, each with a PR link, stable anchor, and regression fixture. The parity
|
|
runner checks nine behavioral dimensions: question order, pressure, smart
|
|
skips, STOP/approval gates, evidence, artifacts, mutation, exit behavior, and
|
|
voice.
|
|
|
|
The public dispatcher cannot substitute for its selected module. Its
|
|
completeness invariant explicitly requires reading that module in full. See
|
|
[JUDGMENT-PROVENANCE.json](./JUDGMENT-PROVENANCE.json),
|
|
[JUDGMENT-PARITY.md](./JUDGMENT-PARITY.md), and
|
|
[SKILL-MIGRATION.md](./SKILL-MIGRATION.md).
|
|
|
|
The reproducible semantic layer adds 295 checks across 14 suites, 15
|
|
executions, 15 dimensions, 16 sections, and nine authority-policy unit cases.
|
|
Exact source preservation remains the primary oracle. These are deterministic
|
|
policy checks, not behavioral-adversarial proof. Paid live-model comparisons
|
|
are supplemental; the currently retained semantic samples are regressions and
|
|
do not support a release-pass claim.
|
|
|
|
The separate installed-host adversarial lane also has no passing live result:
|
|
v1 failed; immutable v2 failed despite QA passing because its classifier
|
|
produced false negatives for debug, review, and ship; and v3 has 18 pass / 0
|
|
fail / 111 assertions offline but has not run live and has no artifact. See the
|
|
[installed-host evidence overview](../../evals/host-adversarial/README.md).
|
|
|
|
## Specialist modes
|
|
|
|
The primary modes are summarized here; internal compatibility modes are in the
|
|
migration map.
|
|
|
|
| Skill | Public top-level modes and preserved refinements |
|
|
|---|---|
|
|
| `/plan` | exactly **Discovery, Product, Engineering, DX, Specification, Full chain**, refined to office-hours, CEO, engineering, DX, spec, or autoplan judgment |
|
|
| `/design` | **Explore, Generate, Critique, Implement**, refined to consultation, alternatives, HTML/CSS, plan/live review, physical-iOS HIG, diagram, or PDF |
|
|
| `/qa` | **Report** or **Fix**, refined by web, physical-iOS, DX, performance, or canary surface |
|
|
| `/debug` | **Diagnose-only** or **Fix**, refined to general investigation or the physical-iOS fix loop |
|
|
| `/review` | **Normal, Security, Performance, Deep**, with health and genuinely independent outside voices selected only when applicable |
|
|
| `/ship` | **Prepare, Land, Deploy, Monitor, Resume**, refined to PR, queue, docs, deploy setup, land/deploy, canary, or context restoration modules |
|
|
|
|
Old commands are opt-in aliases for the compatibility window. An alias points
|
|
to one exact module, prints the replacement invocation, and carries no copied
|
|
judgment. This prevents an alias from drifting away from the canonical source.
|
|
|
|
## Installation boundary
|
|
|
|
The standard Agent Skills tree is the unit of distribution:
|
|
|
|
```bash
|
|
npx skills add time-attack/gstack
|
|
```
|
|
|
|
The installer—not GStack—owns host detection, project/global scope, destination
|
|
paths, selected-skill installation, copies versus symlinks, updates, and
|
|
removal. GStack does not silently enroll a detected host. The former
|
|
host-placement behavior of `./setup` and ten-host generated trees is historical
|
|
compatibility/development machinery, not the 2.0 installation architecture;
|
|
the current `./setup` installs only the optional runtime described below.
|
|
|
|
The standards installer matrix passed 470/470 checks with CLI 1.5.19. It
|
|
verified project/global copies for Claude Code, Codex, Cursor, Pi, OpenClaw, and
|
|
GitHub Copilot plus selected-skill and opt-in compatibility-alias cases,
|
|
removal, spaces, source symlink, copy mode, and canonical hashes across 16
|
|
installs and two removals. The committed artifact is
|
|
[`evals/installation/install-matrix.json`](../../evals/installation/install-matrix.json).
|
|
This is installer-layer verification; it is Markdown-only placement and does
|
|
not prove a passing live installed-host judgment run.
|
|
|
|
Pure judgment is Markdown and works when the optional runtime is absent. A
|
|
capability-dependent module performs one runtime check and must degrade with an
|
|
actionable setup choice rather than make the six skills undiscoverable.
|
|
|
|
## Optional host-neutral runtime
|
|
|
|
`bin/gstack` calls a Node-built-ins runtime under `runtime/`. It does not own
|
|
skill placement and is installed once per user, not once per host. The
|
|
host-neutral `./setup` wrapper installs only this runtime/capability bundle. It
|
|
stages an explicit allowlist, rejects internal symlinks/path escapes,
|
|
hash-validates files, smoke-tests the CLI, atomically activates the version,
|
|
and writes stable POSIX/Windows launchers plus an uninstall manifest under
|
|
`$GSTACK_HOME`. Runtime capability builds use a dedicated target that does not
|
|
regenerate skills or require repository history; Windows targets use `.exe`
|
|
suffixes and Darwin-only iOS artifacts are omitted elsewhere. Its public
|
|
operations are setup, doctor, config, state
|
|
inspection/resume, Context.dev status/options/select/setup/smoke, cleanup,
|
|
upgrade/rollback, and uninstall.
|
|
|
|
The deterministic clean macOS arm64 managed-bundle audit records 110
|
|
components, 1,829 files, 450,044,315 bytes, and 50 capability launchers. This
|
|
is a platform-specific bundle measurement, not a universal byte count;
|
|
platform-native package payloads differ. Setup installs frozen production-only
|
|
dependencies; the development-only Claude Agent SDK is excluded. The
|
|
Sharp/ngrok dependency closure is included. The Hugging Face sidecar is
|
|
excluded and its package is development-only, so setup installs neither its
|
|
inference runtime nor model weights and reports the L4 capability unavailable.
|
|
|
|
A clean Linux arm64 runtime smoke installed only production dependencies with
|
|
the development SDK absent, completed a local-browser journey and Sharp
|
|
full-page screenshot, and uninstalled while preserving state. This is Linux
|
|
container evidence, not native Windows evidence.
|
|
|
|
The authoritative root is `$GSTACK_HOME` or `~/.gstack`; host-specific variables
|
|
do not redirect it. Paths are passed as values and never emitted for shell
|
|
evaluation. The state shape is human-readable:
|
|
|
|
```text
|
|
~/.gstack/
|
|
config.json
|
|
secrets.json mode 0600 where supported
|
|
migration.json
|
|
locks/
|
|
tmp/
|
|
versions/current.json
|
|
projects/<repo+worktree-id>/
|
|
state.json
|
|
timeline.jsonl
|
|
decisions.jsonl
|
|
evidence/
|
|
artifacts/
|
|
reviews/
|
|
checkpoints/
|
|
```
|
|
|
|
Repository identity is shared across linked worktrees; worktree identity is
|
|
stable and distinct. Their combination selects project state, preventing one
|
|
worktree from resuming another's run. Updates use atomic replace plus lock
|
|
leases. External actions are durably claimed before execution. A process death
|
|
after a claim marks the action uncertain on resume and refuses automatic
|
|
repetition until explicitly reconciled.
|
|
|
|
Migrations are forward-only and idempotent. Runtime upgrades copy into a staged
|
|
version, verify, switch an atomic pointer, and retain the last known good
|
|
version. A failed health check or interrupted pending pointer restores the
|
|
previous active version. This is bounded release plumbing, not a distributed
|
|
workflow engine.
|
|
|
|
## Context.dev boundary
|
|
|
|
Context.dev is the only new external service and handles only public web
|
|
content. `network.mode` and `network.consent` both start off. The client checks
|
|
both before DNS or fetch. It rejects credentials in URLs, localhost, local and
|
|
private names, private/link-local IP literals, cloud-metadata targets, and a
|
|
public hostname that resolves to a private address.
|
|
|
|
Supported candidate operations use the documented scrape-Markdown,
|
|
scrape-HTML, crawl, sitemap, and screenshot endpoints. The current general
|
|
search endpoint is deprecated, so `search()` returns a typed unsupported error
|
|
without a network request. A workflow must instead use an explicitly selected
|
|
host-native public search, the local browser, or no web research and label the
|
|
result unverified. It must not invent a replacement API.
|
|
|
|
`gstack context options` presents those choices. `gstack context select
|
|
host|local-browser|none` persists the explicit fallback while keeping
|
|
Context.dev consent false; `context setup` is the only path that selects
|
|
Context.dev and persists export consent with the protected key.
|
|
|
|
The deterministic Context contract is green at 22 pass / 0 fail and 139
|
|
assertions. No verified key was available for a live provider smoke, so provider
|
|
behavior remains blocked rather than inferred from the contract suite.
|
|
|
|
See [CONTEXT-DEV.md](./CONTEXT-DEV.md) and [PRIVACY.md](./PRIVACY.md).
|
|
|
|
## Local browser and physical iOS
|
|
|
|
The existing Chromium/Playwright daemon remains the sole browser-automation
|
|
backend. It binds loopback, requires bearer authorization for mutations,
|
|
preserves authenticated sessions locally, denies tunnel commands by default,
|
|
and treats page/console/network content as untrusted. Context.dev complements
|
|
public research; it does not replace browser QA. No cloud browser was added.
|
|
|
|
The existing DebugBridge/CoreDevice harness remains the sole physical-iOS
|
|
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 and provisioning are
|
|
remediable setup gates, not product failures. A live signed-device pass is
|
|
still required before release. Current preflight evidence is 9 pass / 0 fail /
|
|
1 deploy skip and 29 assertions. The direct smoke returned
|
|
`signing_unavailable` / `setup_gate`; no app was installed and no pass artifact
|
|
was written.
|
|
|
|
PDF rendering and Mermaid/Excalidraw remain internal capabilities. GStack does
|
|
not add Typst, hosted document rendering, alternate diagram services, local
|
|
image weights, ComfyUI, or a GPU runtime.
|
|
|
|
## Infrastructure-defect disposition
|
|
|
|
“Contained” means the defect is outside the canonical GStack 2 path, not that
|
|
legacy code was proven bug-free. “Implemented” names candidate code. “Pending”
|
|
means the replacement still lacks its required release evidence.
|
|
|
|
| # | Legacy defect | GStack 2 disposition / replacement | Replacement evidence |
|
|
|---:|---|---|---|
|
|
| 1 | Ten registered hosts; setup fully installs five | **Contained:** placement is delegated to the standard installer. | 470/470 checks across six hosts, 16 installs, two removals, project/global scopes, and selections. Passing live v3/host UI launch remains separate. |
|
|
| 2 | Kiro rewrites Codex output | **Contained:** one canonical standards tree; no Kiro rewrite in the 2.0 path. | Six-host matrix installs byte-matching canonical copies without host rewrites. |
|
|
| 3 | Gitignored external trees defeat freshness CI | **Implemented:** canonical `skills/`, `compat/`, and parity fixtures are committed. | 4,681 parity checks plus installed-file hash equality. |
|
|
| 4 | External `--dry-run` mutates files | **Contained:** external host generation/dry-run is not used for 2.0 distribution. | Canonical regeneration/parity check exists; a non-mutating canonical check mode is not yet present. |
|
|
| 5 | Single-host generation failures only warn | **Contained:** no per-host generation in the canonical path; canonical generation throws on failure. | Generator/parity suite and final build rerun are green. |
|
|
| 6 | Setup continues after failed generation | **Implemented/contained:** standard installer handles skills; runtime setup fails before activation and preserves last known good. | Failure tests plus the real two-version default lifecycle and rollback pass. |
|
|
| 7 | Removed/renamed generated skills are not pruned | **Implemented for canonical references:** regeneration removes each reference/asset tree and parity corpus before writing the fixed six. | Parity inventory test; stale-public-directory fixture pending. |
|
|
| 8 | Freshness misses generator/design/PDF changes | **Implemented:** build invokes canonical generation; parity hashes source, sections, assets, and fixtures. | Design is green at 101/0/381, PDF at 189/0/398, and the uninterrupted broad singleton run is green across all 383 files. |
|
|
| 9 | State paths bypass canonical resolver | **Implemented:** `runtime/paths.js` is authoritative for 2.0 runtime state. | `gstack2-runtime-core.test.ts`. |
|
|
| 10 | Shell-evaluated path assignments are unsafe | **Implemented:** runtime paths are JavaScript values; shell-looking input remains literal. | Core test covers spaces, `$()`, semicolon, and `$HOME` text. |
|
|
| 11 | Relinking omits carved section links | **Contained:** no per-section host relinking; sections are inlined into pinned modules. | Parity checks all 16 sections. |
|
|
| 12 | External preambles omit PDF paths | **Contained:** PDF is indexed as an internal design capability/assets route, not copied host preamble prose. | Asset parity plus 189/0/398 PDF strict tests and a visually checked four-page live render pass. |
|
|
| 13 | Production model benchmark imports test helpers | **Implemented:** the runner, pricing, providers, and optional judge live under `lib/model-benchmark/`; the production CLI imports only production modules. | `benchmark-production-boundary.test.ts` rejects imports from `test/` across `bin/` and `lib/`; focused runner and CLI tests exercise the relocated implementation. |
|
|
| 14 | Default tests omit `design/test` | **Implemented:** package default and free-test roots include `design/test`. | Design is green at 101/0/381 and is included in the uninterrupted 383-file broad pass. |
|
|
| 15 | Default tests omit `ios-qa/daemon/test` | **Implemented:** package default and free-test roots include the daemon tests. | Focused daemon run: 95 pass / 0 fail / 229 assertions; daemon tests are also included in the uninterrupted broad pass. |
|
|
| 16 | Host setup contradicts config-driven claim | **Contained:** host setup is no longer a 2.0 responsibility. | Standard installer CLI 1.5.19 passed all six configured host targets. |
|
|
| 17 | Host-generated judgment copies drift | **Implemented:** one canonical module corpus with source-blob/render hashes. | 4,681 parity checks and installed-copy hashes pass. |
|
|
| 18 | Updating one host leaves another stale | **Contained:** one tree is installed by each host's standard installer. | Project/global copies across six hosts matched canonical hashes; remote update flow remains installer-owned. |
|
|
| 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/provisioning gate pending. |
|
|
| 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 live smoke remains blocked. |
|
|
| 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. |
|
|
|
|
No defect in this table should be closed from prose alone. The final claim must
|
|
link its reproduction and passing test in [TEST-EVIDENCE.md](./TEST-EVIDENCE.md).
|
|
|
|
## Explicit non-architecture
|
|
|
|
GStack 2 does not contain a generic provider or plugin marketplace, distributed
|
|
workflow engine, mandatory cloud service, cloud browser/device farm,
|
|
Browserbase/Browser Use/Agent Device/Appium/XCUITest driver layer, mandatory
|
|
telemetry, mandatory GBrain/Docker/image generation, local model weights,
|
|
ComfyUI, or a new runtime database. Existing development-only dependencies are
|
|
not promoted into user setup or the GStack 2 architecture.
|