mirror of
https://github.com/garrytan/gstack.git
synced 2026-07-07 08:37:52 +02:00
Merge remote-tracking branch 'origin/main' into garrytan/trunk-land-skill
# Conflicts: # CHANGELOG.md # VERSION # package.json
This commit is contained in:
+365
@@ -44,6 +44,371 @@ If you only want to merge, run `/land` and stop. Got ten PRs green and ready? Ru
|
||||
#### For contributors
|
||||
- `lib/merge.ts` holds the pure regime logic (detection precedence, submit planning, landing classification, handoff schema + validation); `test/gstack-merge.test.ts` (30) and `test/gstack-merge-cli.test.ts` (11) pin it. A generated-doc scrub test fails CI if `/land`'s SKILL.md ever grows deploy/canary machinery. The merge SHA → revert handoff and the never-blind-retry invariant (cli/cli#3442, cli/cli#13380) moved into `/land` with their tests.
|
||||
|
||||
## [1.58.1.0] - 2026-06-14
|
||||
|
||||
## **Local evals stop lying. Spawned `claude` test children run in a sealed clean room,**
|
||||
## **and in Conductor every decision is a plain-text brief you answer with a letter.**
|
||||
|
||||
Two things shipped here. First, the local E2E harness is now hermetic by default:
|
||||
every spawned agent (claude -p, the real-PTY plan-mode runner, the Agent SDK
|
||||
runner, plus the codex and gemini runners) gets an allowlist-scrubbed environment,
|
||||
a fresh seeded `CLAUDE_CONFIG_DIR`, a temp `GSTACK_HOME`, and `--strict-mcp-config`.
|
||||
Before this, a dev machine leaked the operator's `~/.claude` config, MCP servers
|
||||
(gbrain, Conductor), skills, `~/.gstack` decision logs, and `CONDUCTOR_*`/`CLAUDECODE`
|
||||
env into every child, so local eval results disagreed with CI for reasons that had
|
||||
nothing to do with the code under test. Now local signal matches CI. Set
|
||||
`EVALS_HERMETIC=0` to debug against real operator state.
|
||||
|
||||
Second, in a Conductor session gstack no longer fights Conductor's flaky
|
||||
AskUserQuestion tool. It detects the session and renders every decision as a prose
|
||||
brief, a labeled question with a recommendation, per-option completeness scores, and
|
||||
"reply with a letter," enforced by a PreToolUse hook that denies the tool and
|
||||
redirects to prose. Destructive confirmations demand an explicit typed answer.
|
||||
|
||||
Agents that launch long eval runs get `gstack-detach`: a SIGTERM-proof, idle-sleep-proof
|
||||
wrapper (fresh session + `caffeinate`) with a machine-wide lock so concurrent
|
||||
worktrees serialize instead of saturating the model API, run-scoped logs, and a
|
||||
guaranteed `EXIT=` sentinel so a poller never mistakes silence for success.
|
||||
|
||||
### The numbers that matter
|
||||
|
||||
Measured against the gate eval suite on a contaminated dev box (gbrain MCP up, live
|
||||
Conductor session, sibling worktrees). Reproduce: `bun test` (free unit + wiring
|
||||
tripwire) and `EVALS=1 EVALS_TIER=gate bun test test/skill-e2e-hermetic-canary.test.ts`.
|
||||
|
||||
| Metric | Before | After | Δ |
|
||||
|--------|--------|-------|---|
|
||||
| Spawned-child env | full operator `process.env` | allowlist-scrubbed | sealed |
|
||||
| Runners hermeticized | 0 of 5 | 5 of 5 | +5 |
|
||||
| Operator MCP servers visible to child | all (gbrain, Conductor) | 0 (`--strict-mcp-config`) | isolated |
|
||||
| Config isolation proof | none | poisoned-operator sentinel canary | falsifiable |
|
||||
| Long eval runs surviving a turn-boundary SIGTERM | no | yes (`gstack-detach`) | survives |
|
||||
|
||||
The clean room is falsifiable, not asserted: a `hermetic-sentinel` gate canary
|
||||
plants a poisoned operator config (a user `CLAUDE.md` + an MCP server) and fails if
|
||||
the child can see any of it, and a free static tripwire fails CI if any runner
|
||||
reverts to a raw `process.env` spread.
|
||||
|
||||
### What this means for contributors
|
||||
|
||||
Run evals locally and trust the result. You no longer have to push to CI to find
|
||||
out whether a failure was real or just your machine bleeding context into the agent.
|
||||
Three latent bugs the old harness hid surfaced the moment the suite ran clean and
|
||||
are fixed: a coverage-judge that scored carved skills against half a document, an
|
||||
ios-qa daemon test that collided on a shared pidfile under concurrency, and an
|
||||
operational-learning fixture missing a lib it imports. Start a run with
|
||||
`bun run eval:bg:gate`; flip `EVALS_HERMETIC=0` only when you deliberately want your
|
||||
real `~/.claude` in the loop.
|
||||
|
||||
### Itemized changes
|
||||
|
||||
#### Added
|
||||
- **Hermetic E2E environment** (`test/helpers/hermetic-env.ts`): allowlist env
|
||||
builder (process basics, network/proxy vars, named `ANTHROPIC_*` auth, per-runner
|
||||
`extraAllow`), pure `promotedEnv()` shared with `lib/conductor-env-shim.ts`, a
|
||||
sync-memoized singleton temp dir (`<runRoot>/.claude` keeps the plan-file path
|
||||
contract), a seeded `.claude.json` for non-interactive first run, and pid-aware GC
|
||||
of crashed runs. Default-on; `EVALS_HERMETIC=0` restores the legacy env AND drops
|
||||
`--strict-mcp-config`.
|
||||
- **Two gate-tier isolation canaries** (`test/skill-e2e-hermetic-canary.test.ts`):
|
||||
`hermetic-canary` asserts env redirect + scrub + zero MCP servers + nonzero
|
||||
API-key cost from the Bash tool_result (not model prose); `hermetic-sentinel`
|
||||
proves the child cannot see a planted poisoned operator config.
|
||||
- **Static wiring tripwire** (`test/hermetic-wiring.test.ts`): free-tier invariants
|
||||
that fail CI if any of the five runners drops `hermeticChildEnv()`, the gated
|
||||
`--strict-mcp-config`, or leaks `process.env` through a callsite override.
|
||||
- **`gstack-detach`** + `eval:bg` / `eval:bg:all` / `eval:bg:gate` / `eval:bg:periodic`
|
||||
scripts: detached, SIGTERM-proof, `caffeinate`-wrapped eval runs with a machine-wide
|
||||
lock, per-run logs under `~/.gstack-dev/eval-runs/`, a watchdog, and an `EXIT=`
|
||||
sentinel.
|
||||
- **Conductor prose AskUserQuestion**: when a Conductor session is detected, every
|
||||
decision renders as a prose brief (labeled question, recommendation, per-option
|
||||
completeness, reply-with-a-letter), enforced by a PreToolUse hook that denies the
|
||||
tool and redirects. Auto-decide preferences still apply first; destructive
|
||||
confirmations require an explicit typed answer. Installed for Conductor even in
|
||||
non-interactive setup, with an upgrade migration for existing installs.
|
||||
|
||||
#### Changed
|
||||
- All five E2E runners (`session-runner`, `claude-pty-runner`, `agent-sdk-runner`,
|
||||
`codex-session-runner`, `gemini-session-runner`) spawn children through
|
||||
`hermeticChildEnv()`. The Agent SDK runner now receives a COMPLETE hermetic env
|
||||
via `Options.env` (the old "never pass env: to the SDK" rule was partial-env
|
||||
replacement; a complete env is safe).
|
||||
- `hermetic-env.ts` is a global touchfile, so any change to it selects every E2E +
|
||||
judge test.
|
||||
- CLAUDE.md documents hermetic-by-default local evals and retires the stale SDK env
|
||||
warning.
|
||||
|
||||
#### Fixed
|
||||
- The workflow LLM-judge now re-appends body-carved `sections/*.md` after the marker
|
||||
slice, so carved skills (document-release) are judged on the full workflow the
|
||||
agent executes instead of a half-document.
|
||||
- ios-qa daemon scenarios use unique pidfiles, fixing `already_running` collisions
|
||||
under `bun test --concurrent`.
|
||||
|
||||
## [1.58.0.0] - 2026-06-12
|
||||
|
||||
## **Your documents grow diagrams. Mermaid and excalidraw fences render as real pictures,**
|
||||
## **and make-pdf now ships single-file HTML and Word output from the same markdown.**
|
||||
|
||||
Put a ` ```mermaid ` fence in your markdown and `make-pdf` renders it as a crisp
|
||||
vector diagram, fully offline, with the source preserved for round-trips. A broken
|
||||
fence prints a loud red diagnostic block with the parse error, never silent raw
|
||||
code. The new `/diagram` skill goes the other way: describe a flow in English and
|
||||
get a triplet back, the mermaid source, an editable `.excalidraw` file you can open
|
||||
at excalidraw.com in the hand-drawn style, and rendered SVG + PNG. Images got the
|
||||
same care: local paths inline automatically and never truncate, phone photos
|
||||
downscale to print resolution instead of blowing up the file, and a wide small-text
|
||||
diagram promotes itself onto a vertically centered landscape page inside an
|
||||
otherwise portrait document. One markdown file now exports three ways:
|
||||
`--to pdf | html | docx`, where html is one self-contained file with zero network
|
||||
references. Type is bigger across the board (12pt body, 56pt cover titles), TOC
|
||||
links actually jump, and `--strict` turns missing, remote, out-of-tree, or
|
||||
oversized images into hard CI failures.
|
||||
|
||||
### The numbers that matter
|
||||
|
||||
Measured on this repo's README (5,940 words, lists, code, screenshots, one
|
||||
diagram fence) and the free gate suite. Reproduce: `make-pdf generate README.md
|
||||
--cover --toc` and `bun test make-pdf/test/`.
|
||||
|
||||
| Metric | Before | After | Δ |
|
||||
|--------|--------|-------|---|
|
||||
| A mermaid fence in your PDF | raw code block | vector diagram | rendered |
|
||||
| Output formats from one markdown | 1 (pdf) | 3 (pdf, html, docx) | +2 |
|
||||
| Network requests at render time | up to 1 per remote image | 0 by default | sealed |
|
||||
| Wide-diagram handling | shrunk into portrait | own centered landscape page | rotated |
|
||||
| Free make-pdf gate tests | 121 | 189 | +68 |
|
||||
| README → 29-page PDF with diagram | n/a | 4.4s | one command |
|
||||
|
||||
The sealed-network number is the one to notice: the mermaid and excalidraw
|
||||
runtimes are vendored into a 9.2MB sha-pinned bundle, so rendering works on a
|
||||
plane and a tracking pixel in pasted markdown fetches nothing.
|
||||
|
||||
### What this means for your documents
|
||||
|
||||
The diagram you describe in English stays editable forever: `/diagram` writes the
|
||||
source, you embed the source in markdown, and every export renders it fresh. Stop
|
||||
pasting screenshots of diagrams into documents. Run `/diagram` for the picture,
|
||||
` ```mermaid ` for the document, and `--to html` when the reader doesn't want a PDF.
|
||||
|
||||
### Itemized changes
|
||||
|
||||
#### Added
|
||||
- ` ```mermaid ` and ` ```excalidraw ` fences render as inline vector SVG in pdf
|
||||
and html output (docx embeds them as 300dpi PNGs). Fence options: `title="..."` (caption + aria-label),
|
||||
`render=false` (keep as code), `page=landscape|portrait` (orientation override).
|
||||
Render failures produce a visible diagnostic block with the parse error.
|
||||
- `/diagram` skill: English in, editable triplet out (`.mmd` source,
|
||||
`.excalidraw` scene, SVG + PNG). Flowcharts convert to fully editable
|
||||
excalidraw scenes; other mermaid types render with an explicit limitation note.
|
||||
- `lib/diagram-render/`: vendored offline bundle (mermaid 11.12.2, excalidraw
|
||||
0.18.0, exact pins), deterministic build, committed dist with sha256 + source
|
||||
fingerprint, drift tests, THIRD-PARTY-LICENSES.
|
||||
- `--to pdf|html|docx` output formats. HTML is one self-contained file (inline
|
||||
SVG diagrams, data-URI images, zero network refs, screen-readable). DOCX is a
|
||||
content-fidelity export with diagrams embedded as 300dpi PNGs and alt text.
|
||||
- Per-image directives: `{width=full|50%|3in}` and
|
||||
`{page=landscape|portrait}`.
|
||||
- Conservative auto-landscape: wide, small-text, diagram-like images get their
|
||||
own vertically centered landscape page (aspect ≥ 1.8, width over ~2.5x the
|
||||
content box, diagram-ish alt word). Directives override in both directions.
|
||||
- `--strict` for CI: missing images, remote images, out-of-tree image reads,
|
||||
oversized files, and non-regular files fail the run instead of degrading to
|
||||
placeholders.
|
||||
- `docs/howto-diagrams-and-formats.md`: the full walkthrough, fences to formats.
|
||||
|
||||
#### Changed
|
||||
- Typography scale: 12pt body, 26pt h1, 56pt poster cover with 13pt meta, 12pt
|
||||
TOC entries, larger code and tables. Auto-hyphenation is off so copy-paste
|
||||
yields clean words.
|
||||
- Local images inline as data URIs with byte-probed dimensions and never
|
||||
truncate; oversized photos downscale to print resolution at inline time;
|
||||
repeated images are read once.
|
||||
- TOC links resolve in every format (headings get real anchor ids); the screen
|
||||
layer hides print-only page-number dots in HTML output.
|
||||
- Remote images are blocked with a visible placeholder unless `--allow-network`
|
||||
is passed; out-of-tree image reads (including via symlink) warn loudly.
|
||||
- `make-pdf preview` prints a note when the document contains fences or local
|
||||
images that only `generate` renders fully.
|
||||
|
||||
#### Fixed
|
||||
- Relative image paths render correctly in PDFs (previously resolved against the
|
||||
wrong base and could show as broken boxes).
|
||||
- Fenced code inside lists survives the render byte-for-byte; indented fences
|
||||
keep their list placement.
|
||||
- Documents containing `$&`-style sequences in diagram labels render exactly;
|
||||
Windows drive-letter image paths resolve as local files; malformed
|
||||
percent-encoded image URLs degrade gracefully instead of failing the run.
|
||||
- Per-side margins (`--margin-left` etc.) are honored on documents containing
|
||||
landscape pages.
|
||||
|
||||
#### For contributors
|
||||
- 68 new free-tier gates (fence extraction, image policy, landscape promotion
|
||||
with negative fixtures, format contracts, bundle drift) plus a paid gate-tier
|
||||
/diagram triplet test and a periodic authoring-quality judge.
|
||||
- make-pdf-gate CI now covers `lib/diagram-render/**` and the drift test; the
|
||||
committed bundle is pinned to LF in .gitattributes.
|
||||
- Fixed the `operational-learning` E2E fixture (bin scripts now ship with the
|
||||
lib module they import).
|
||||
|
||||
## [1.57.10.0] - 2026-06-10
|
||||
|
||||
## **Codex review now runs by default everywhere it matters.**
|
||||
## **One switch governs it, and it falls back to Claude when Codex is missing or unauthed.**
|
||||
|
||||
Codex cross-model review used to be inconsistent. `/review` and `/ship` ran it
|
||||
automatically, but plan reviews hid it behind a "Want an outside voice?" question
|
||||
you had to say yes to every time, `/document-release` never ran it at all, and every
|
||||
entry point only checked whether the `codex` binary existed, not whether it was
|
||||
logged in. Now `codex_reviews` is one master switch (default `enabled`) that governs
|
||||
Codex review across `/review`, `/ship`, `/plan-ceo-review`, `/plan-eng-review`,
|
||||
`/plan-design-review`, `/plan-devex-review`, `/document-release`, and `/autoplan`.
|
||||
The plan-review outside voice runs automatically. `/document-release` gets a new
|
||||
Codex pass that checks your docs against what actually shipped. Every call site now
|
||||
detects install AND auth separately, and degrades to a Claude subagent with a clear
|
||||
one-line reason instead of silently skipping. Turn the whole thing off with one
|
||||
command: `gstack-config set codex_reviews disabled`.
|
||||
|
||||
### The numbers that matter
|
||||
|
||||
Verified by the gate-tier E2E evals that exercise these exact paths
|
||||
(`codex-offered-ceo-review`, `codex-offered-eng-review`, `document-release`,
|
||||
`codex-review-findings`), all green this run.
|
||||
|
||||
| Metric | Before | After | Δ |
|
||||
|--------|--------|-------|---|
|
||||
| Skills where Codex review runs by default | 2 | 8 | +6 |
|
||||
| Prompts to get a plan-review outside voice | 1 (opt-in each time) | 0 (automatic) | -1 |
|
||||
| Codex readiness detection | install only | install + auth | sharper |
|
||||
| Master switches to disable it all | 0 (per-skill only) | 1 (`codex_reviews`) | +1 |
|
||||
| `/document-release` Codex doc audit | none | doc-vs-diff pass | new |
|
||||
|
||||
When Codex is installed but not logged in, you used to get nothing on the paths that
|
||||
checked only `command -v codex`. Now you get a named reason ("Codex installed but not
|
||||
authenticated, using Claude subagent") and the review still happens. A typo on the
|
||||
switch (`gstack-config set codex_reviews disabledd`) is rejected and your existing
|
||||
setting is preserved, so a fat-finger can never silently turn paid Codex calls on or
|
||||
off.
|
||||
|
||||
### What this means for you
|
||||
|
||||
If you run gstack day to day, you stop deciding whether to get a second model's eyes
|
||||
on every plan and every release. It is just there, on by default, the way the strong
|
||||
reviewers already worked on diffs. If you do not have Codex set up, nothing breaks:
|
||||
you get the Claude outside voice instead, with a one-line note telling you how to add
|
||||
Codex for true cross-model coverage. If you want it gone, one command turns off all
|
||||
eight surfaces at once.
|
||||
|
||||
### Itemized changes
|
||||
|
||||
#### Added
|
||||
- **`codex_reviews` as the master switch** for Codex review across `/review`, `/ship`,
|
||||
`/document-release`, all four plan reviews, and `/autoplan` (`bin/gstack-config`).
|
||||
Default `enabled`. Invalid values on `set` are rejected with the existing value
|
||||
preserved, so a typo cannot flip paid Codex calls.
|
||||
- **`/document-release` Codex doc audit** (`generateCodexDocReview`): reviews the
|
||||
docs you touched against the release diff for stale claims, undocumented new
|
||||
surface, and over/under-sold CHANGELOG entries. Informational, with an explicit
|
||||
apply-fixes decision point. Never auto-edits docs.
|
||||
- **`codexPreflight()` shared helper** (`scripts/resolvers/constants.ts`): one
|
||||
self-contained bash block that reads the switch, sources the probe, checks install
|
||||
and auth, and emits a single canonical mode (`ready` / `not_installed` /
|
||||
`not_authed` / `disabled`).
|
||||
|
||||
#### Changed
|
||||
- **Plan-review outside voice is default-on**, not opt-in. The "Want an outside
|
||||
voice?" question is gone; it runs automatically and falls back to a Claude subagent
|
||||
when Codex is unavailable. Incorporating its findings still requires your explicit
|
||||
approval (cross-model tension is presented, never auto-applied).
|
||||
- **Adversarial review detects auth, not just install** (`generateAdversarialStep`):
|
||||
distinct "not installed" vs "not authenticated" guidance. The 200-line threshold
|
||||
for the heavier structured `codex review` is unchanged.
|
||||
- **`/autoplan` honors `codex_reviews=disabled`** in its Phase 0.5 preflight, so the
|
||||
switch is truly global.
|
||||
|
||||
#### Fixed
|
||||
- Three `gstack-config` tests asserted `get`/`list` print empty for unset keys; the
|
||||
tool falls back to the documented defaults table. Assertions now match real behavior.
|
||||
|
||||
#### For contributors
|
||||
- Size-budget guards widened for the default-on outside-voice prose, each with a
|
||||
rationale comment (`test/helpers/carve-guards.ts`, `test/helpers/parity-harness.ts`).
|
||||
- Static guards added: plan reviews must not carry the opt-in question and must render
|
||||
the default-on voice; `/document-release` must carry the doc review; the codex host
|
||||
strips all of it (`test/skill-validation.test.ts`).
|
||||
|
||||
## [1.57.9.0] - 2026-06-09
|
||||
|
||||
## **Your gstack checkout stays clean when gbrain is installed.**
|
||||
## **Brain-aware skill blocks render to an untracked spot, never into tracked source.**
|
||||
|
||||
Before this, finishing a Conductor or dev-workspace setup with gbrain installed
|
||||
rewrote 16 planning and review SKILL.md files in place, adding 326 lines of
|
||||
brain-aware blocks straight into tracked source. Your working tree came back dirty,
|
||||
one stray `git add` away from committing a token regression for everyone who does
|
||||
not run gbrain. Now `gen-skill-docs --out-dir` renders the brain-aware variant into
|
||||
an untracked per-workspace directory, and `bin/dev-setup` repoints the workspace's
|
||||
skill symlinks at it. The dev workspace gets the full gbrain experience (context-load
|
||||
and save-to-brain blocks live at runtime), while the tracked SKILL.md files stay
|
||||
byte-for-byte canonical. To turn the blocks on across all your projects' Claude
|
||||
sessions, `gstack-config gbrain-refresh` now renders them into your global install,
|
||||
guarded so it never mutates a symlinked or non-gstack directory.
|
||||
|
||||
### The numbers that matter
|
||||
|
||||
Structural facts of the change, verifiable from the diff plus `bun run gen:skill-docs`
|
||||
(zero drift) and the new behavioral test (`test/gen-skill-docs-out-dir.test.ts`).
|
||||
|
||||
| When gbrain is installed | Before | After |
|
||||
|---|---|---|
|
||||
| Tracked SKILL.md files dirtied by dev-setup | 16 (+326 lines) | 0 |
|
||||
| Where brain-aware blocks render in a dev workspace | in-place, tracked source | `.claude/gstack-rendered/`, untracked |
|
||||
| Brain-aware blocks across other projects | re-run `./setup` or hand-edit | `gstack-config gbrain-refresh` (idempotent) |
|
||||
| "Is gbrain usable" check | per-caller JSON grep, can read stale state | `gstack-gbrain-detect --is-ok` (one live gate) |
|
||||
|
||||
The section-path rewrite is surgical: only `~/.claude/skills/gstack/<skill>/sections/`
|
||||
references move to the render dir, so `bin/` and `docs/` references still resolve to
|
||||
the install.
|
||||
|
||||
### What this means for you
|
||||
|
||||
If you develop gstack with gbrain on, `git status` is clean again after setup, and
|
||||
you can stop fishing brain-block drift out of your commits. After a
|
||||
`git reset --hard` deploy of your install, re-run `gstack-config gbrain-refresh` to
|
||||
restore the machine-wide blocks (it is idempotent, and the deploy note in CLAUDE.md
|
||||
spells this out).
|
||||
|
||||
### Itemized changes
|
||||
|
||||
#### Added
|
||||
- `gen-skill-docs --out-dir <dir>`: render the Claude SKILL.md + sections into a
|
||||
separate directory instead of in place, rewriting only the section-base path so
|
||||
section reads resolve to the render. Default (no flag) output is unchanged.
|
||||
- `gstack-gbrain-detect --is-ok`: live-detection exit-code gate (0 iff gbrain is
|
||||
usable), so setup, dev-setup, and gstack-config share one check.
|
||||
- `gstack-config gbrain-refresh` now renders brain-aware blocks into the global
|
||||
install (`~/.claude/skills/gstack`), guarded against symlinked or non-gstack
|
||||
targets and self-documenting about the `reset --hard` re-run cycle.
|
||||
|
||||
#### Changed
|
||||
- `bin/dev-setup` renders the brain-aware variant into `.claude/gstack-rendered`
|
||||
(gitignored) and repoints workspace skill symlinks at it; the worktree stays
|
||||
canonical. `GSTACK_SKIP_GBRAIN_REGEN` is passed inline to the nested setup, never
|
||||
exported.
|
||||
- `setup` honors `GSTACK_SKIP_GBRAIN_REGEN` (skips the in-place brain regen on dev
|
||||
trees) and writes detection state to a PID-unique tmp so concurrent workspaces
|
||||
cannot clobber it.
|
||||
- `scripts/dev-skill.ts` refreshes the workspace render on template change, only
|
||||
when the render dir already exists.
|
||||
- `bin/dev-teardown` removes the untracked render.
|
||||
|
||||
#### For contributors
|
||||
- New tests: `test/gen-skill-docs-out-dir.test.ts` (behavioral: worktree unchanged,
|
||||
blocks rendered, section paths rewritten), `test/dev-setup-render-isolation.test.ts`
|
||||
and `test/gbrain-refresh-install-render.test.ts` (static tripwires), plus
|
||||
`--is-ok` coverage in `test/gbrain-detect-shape.test.ts`.
|
||||
|
||||
## [1.57.8.0] - 2026-06-09
|
||||
|
||||
## **`browse` is now the one Chromium on the box, for offline rendering too.**
|
||||
|
||||
Reference in New Issue
Block a user