Skip to content

v1.91.290.0 feat(harness): gstack registers its skills in whatever agent harness it is installed into (GSTA-135) - #3526

Merged
capy-ai[bot] merged 11 commits into
mainfrom
gsta-135/harness-registration
Oct 28, 2026
Merged

capy-ai[bot] merged 11 commits into
mainfrom
gsta-135/harness-registration

Conversation

@garrytan

@garrytan garrytan commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner
{
  "schema_version": 1,
  "pr": 3526,
  "head": "bd8907d6f53465c5e3679af20005fd0267fa436a",
  "version": "1.91.286.0",
  "base": "main",
  "gate": {
    "pregate.json/remote_gate": {
      "pass": 21309,
      "fail": 0,
      "skip": null
    }
  },
  "session_kind": "unattended",
  "pregate": "requires-remote cleared @c75a298190b3 (1 checks, current for bd8907d6f534)",
  "requires_remote": [
    "free-tests.yml/cso-macos-launcher: https://github.com/garrytan/gstack/actions/runs/40617923919",
    "free-tests.yml/macos-named-regressions: https://github.com/garrytan/gstack/actions/runs/40617923919",
    "windows-free-tests.yml/windows-free-shard: https://github.com/garrytan/gstack/actions/runs/40617923868",
    "windows-setup-e2e.yml/windows-setup: https://github.com/garrytan/gstack/actions/runs/40617923874",
    "pregate.json/remote_gate: remote-gate tree=c75a298190b3 tests=21309"
  ],
  "issues": {
    "fixes": [],
    "refs": [
      3526
    ],
    "flakes": []
  },
  "docs": {
    "status": "updated",
    "scope": "README.md, docs/ (hosts, install, uninstall, OPENCLAW, ADDING_A_HOST, capy-install, troubleshooting § Agent harnesses), AGENTS.md, CONTRIBUTING.md"
  },
  "review_loop": {
    "passes": 2,
    "blocking_found": 4,
    "deferred": 0,
    "noted": 13,
    "fixed": 7,
    "scope": "frozen"
  }
}

What changed

./setup --host openclaw: before, instructions to wire gstack in by hand; after, 62 skills registered in OpenClaw's own skills folder through one router skill

./setup --host openclaw used to print instructions for wiring gstack in by hand. It now registers gstack's 62 skills in OpenClaw's own skills folder through one router skill, and prints the ledger and the command that removes them.

Before/after as text: ./setup --host openclaw: before, instructions to wire gstack in by hand; after, gstack's 62 skills registered in OpenClaw's own skills folder through one router skill, with a ledger and the removal command
--- Before · before.txt · captured output
+++ After · after.txt · captured output
+gstack-harness: OpenClaw: 62 gstack skills reachable through one router skill at ~/.openclaw/skills (installed, 140 files written)
+  router: ~/.openclaw/skills/gstack/SKILL.md (register with --skills all to list every skill natively)
+  ledger: ~/.gstack/harness/openclaw-362cd3bbf94e.ledger
+  remove: ~/gstack/bin/gstack-harness unregister openclaw-362cd3bbf94e
-
-OpenClaw integration uses a different model — OpenClaw spawns Claude Code
-sessions natively via ACP. gstack provides methodology artifacts, not a
-full skill installation.
-
-To integrate gstack with OpenClaw:
-  1. Tell your OpenClaw agent: 'install gstack for openclaw'
-  2. Or generate artifacts: bun run gen:skill-docs --host openclaw
-     (in an install, add 'openclaw' to .gstack-installed-hosts first, or ./setup prunes them)
-  3. See docs/OPENCLAW.md for the full architecture
-
-Instruction-only tier (no install): copy the 2KB rules digest into a
-location your agent reads (e.g. append to your project's AGENTS.md).
-It carries gstack's ethos, reuse ladder, and voice rules:
-
-  ~/gstack/agents-digest/gstack-AGENTS.md
-
-Re-copy it after upgrading gstack — the digest's first line shows its version.
-
 

Why

Garry asked for this on 2026-10-27: "when gstack is installed inside OpenClaw, Hermes, qm, muse, grok bot, dots or any harness it auto resolves and figures out how to use the skills". Until now an agent working inside OpenClaw or Hermes could not find a single gstack skill until a person wired one in by hand. Running ./setup inside one of those harnesses now registers the skills the harness's own way, and gstack-uninstall takes them back out.

Blast radius

The change touches setup (a new install arm for openclaw and hermes, an automatic step only when no --host is given, and --refresh-registered), bin/gstack-uninstall (it reads the harness ledgers before removing anything), and the openclaw and hermes host configs. What makes this safe is that gstack writes only files its ledger names, inside the harness's own skills folder, and refuses symlinks, unowned entries and edited context blocks. Rung reached: script ran, with real OpenClaw 2026.10.6 and Hermes v2026.9.24 listing the skills, and ./setup plus gstack-uninstall exercised end to end in temporary homes.

Approvals

Date Asked Exact words Outcome Covers Still pending
2026-10-28 Approve the GSTA-135 autoplan: gstack registers its skills in any agent harness (OpenClaw, Hermes, QM, dots, generic; Muse Code and Grok detection) “Do it” (Garry (via GStack Minder)) approved the reviewed plan at full scope, every recommendation (d1a, d2b, d3b, d4a, d5b) none
2026-10-28 Route live discovery proofs (OpenClaw, Hermes, QM) through Harness Evals; READY may go out before they land, marked pending “Harness Evals accepted; HARN-5 owns the live proofs ... READY can go out before live proofs land, marked pending” (GStack Minder (captain)) approved live proof routing; no paid trial without Garry's yes via HARN-5's plan none

Source: gstack-approvals record for gsta-135/harness-registration (display only; not an approval citation).

Summary

gstack now knows each harness it can live in, and how that harness finds skills: OpenClaw and dots read a skills folder, Hermes reads one category folder, QM takes an org skill pack through its admin API, and Muse Code and Grok are detected and checked but never written to. bin/gstack-harness registers, refreshes, lists and removes, and every file it writes goes into a ledger with its hash. Uninstall reads that ledger with bash alone, so it still works after bun is gone. When a harness has no folder gstack can write, register generic adds a router skill and a marked context block, and --print gives a paste-in version.

Review found four ways the first version could lose data. Uninstall deleted the backups of edited skills, unregister followed a symlinked folder, a lone marker let the cut take the user's own lines, and a --context change never reached the ledger. All four are fixed. Edited files now stay beside the original as <file>.edited-<time>, and a context block is cut only when it is exactly the block gstack wrote.

Test Coverage

All new code paths have test coverage in test/harness-register.test.ts, plus the setup and uninstall journeys.
Tests: 15 → 19 in test/harness-register.test.ts (+4 new), with the setup and uninstall journeys extended to edit a skill before uninstalling.
Regression proof: the six blocker regressions fail at 808dead, pass after the fix (the edited file survives a full gstack-uninstall for openclaw and hermes; a lone, repeated or edited block is never cut; a moved --context is recorded; a symlinked folder below the destination is never followed); the no-destination ledger case failed before d7cb3c1.
Not covered by tests: the status, detect, manifest and --print CLI subcommands, which were exercised by hand only, and Muse Code and Grok status, which needs their binaries.
Tests ran: remote free tier 21309 at the reviewed tree (0 failed); the final remote run at the frozen head is recorded in the receipt.

Pre-Landing Review

Pass 1: four blocking findings (data loss and an unrecorded ledger block) were fixed, plus three informational ones: the ledger is now written before the files, --refresh-registered no longer flips a --skills all registration back to router, and the context file mode is preserved on cut. Pass 2 (range 808dead..d7cb3c1) found nothing blocking.
REVIEW_LOOP: passes=2 blocking_found=4 deferred=0 noted=13 fixed=7 scope=frozen
Gate edits: 2 listed, 2 read, 0 findings. test/setup-help.test.ts drops openclaw and hermes from the "finishes before installation preflight" set, and test/gen-skill-docs.test.ts adds them to the accept-list string. Both follow the approved contract (they are now installs, not instruction-only hosts), and test/harness-register.test.ts runs the real ./setup --host openclaw|hermes in their place.
Outside review: a gpt-6-astra Capy subagent (cross-family) completed, and its findings are included above. The Codex CLI did not run.

Review notes

These are informational and below the blocking floor, so they were listed rather than fixed:

  • A context file converted to CRLF gets a second block, and uninstall leaves the CRLF one (lib/harness-register.ts withBlock).
  • refresh() stops at the first failing registration, so one edited generic block keeps later ledgers from refreshing.
  • A ledger written on Windows holds backslash paths, so the bash reader skips its files. test/harness-register.test.ts is not in the Windows lane.
  • A hand-crafted ledger row with .. or a trailing slash is not rejected. Register never writes such rows.
  • A kept SKILL.md.edited-* makes the next register refuse the folder as unowned.
  • --context pointing at the router itself piles up .edited-* files.
  • A failed cut while moving --context is not reported, and its output reaches --json stdout.
  • Hermes resolves skills by name across categories, but the same-name check scans only the gstack category.
  • The uninstall preview doesn't list harness registrations.
  • Empty folders are left after a mode flip, and a context file's new parent folder is not recorded.
  • refresh recreates a harness root the user deleted.
  • A failed harness arm shows the host name as its destination.
  • pair-agent --local openclaw writes ~/.openclaw/skills/gstack/browse-remote.json, which is the router's folder. Pairing before registering makes register refuse, so register first, then pair.

Exploratory QA

Real harnesses: OpenClaw 2026.10.6 lists the gstack router as visible (all mode: 62 openclaw-managed skills, no duplicates), and Hermes v2026.9.24 status shows it visible. On both, the rendered preamble runs from the installed root (SKILL_START_PROTO: 1, rc=0). Live agent-session discovery for OpenClaw, Hermes and QM is pending with Harness Evals (HARN-5) and is not claimed here.

Design Review

No frontend files changed, so design review was skipped.

Eval Results

No prompt bytes changed: bun run gen:skill-docs --host all leaves git clean. eval-select falls back to full only because setup and hosts/ are global touchfiles. Paid coverage is the PR's E2E Evals plus the train gate.

Greptile Review

No Greptile comments.

Plan Completion

Plan items 1–6 and 8 are done. Item 7, the live discovery proofs, is pending with Harness Evals (HARN-5), as GStack Minder agreed. Drift: the manifest is a CLI JSON print rather than a gstack-skills.json file.

Issues

Refs #3526

Verification Results

Local runs passed: the four blocker repros, ./setup --host openclaw|hermes with gstack-uninstall, and setup run inside OpenClaw. Two things were not run: live agent sessions, which are pending with HARN-5, and the macOS and Windows lanes, which CI runs.

TODOS

No TODO items completed in this PR. TODOS.md:404 ("Recording an instruction-only host from setup") still names Hermes and OpenClaw, and should shrink to GBrain after this lands.

Documentation

Status: updated. Factual edits in 3 files, no blockers.

Scope: gsta-135/harness-registration at d7cb3c1 against base 3986182 (9 commits, 25 files; no staged, unstaged or untracked content). Audited the 8 changed docs (README.md, docs/hosts.md, docs/install.md, docs/uninstall.md, docs/OPENCLAW.md, docs/ADDING_A_HOST.md, docs/capy-install.md, docs/troubleshooting.md § Agent harnesses) against bin/gstack-harness, lib/harness-register.ts, lib/harness-qm.ts, setup, bin/gstack-uninstall, hosts/*.ts and scripts/host-config.ts. Grepped all authored docs and templates for stale OpenClaw/Hermes instruction-only claims.

Documentation health:

  • README.md: Updated. Bare ./setup now notes harness registration when run inside OpenClaw, Hermes or a Dot; agent harnesses added to the per-host notes line and to the Install details and Other agents index rows.
  • docs/install.md: Updated. Intro lists agent harness registration; the harness section notes --local skips it.
  • docs/hosts.md: Updated. Notes ./setup --local never writes under a harness folder.
  • docs/uninstall.md: Current.
  • docs/OPENCLAW.md: Current.
  • docs/ADDING_A_HOST.md: Current.
  • docs/capy-install.md: Current.
  • docs/troubleshooting.md: Current. All ten HARNESS_* sections match HARNESS_CODES anchors and messages.
  • CHANGELOG.md: Current (not edited; [Unreleased] entry awaits the parent's stamp).
  • TODOS.md: Current (not edited; item at line 404 is partly superseded, see decisions).

Coverage:

  • gstack-harness register/unregister/status: reference ✅ (hosts.md, troubleshooting.md), how-to ✅ (hosts.md table), tutorial ❌, explanation ✅ (ADDING_A_HOST.md).
  • gstack-harness detect, refresh, auto: reference only in the CLI usage header. Common gap; a reference row in hosts.md would close it.
  • --no-harness-auto / GSTACK_HARNESS_AUTO: reference ✅, how-to ✅.
  • Hermes detection marker AI_AGENT=hermes-agent: undocumented (minor).
  • Manual removal of Dot, generic and context-block registrations: missing from uninstall.md Option 2 (how-to gap).

Diagram drift: none found in the audited docs.

Suggest /document-generate for the how-to and reference gaps above.

Test plan

  • bun test test/harness-register.test.ts: 19 pass, 0 fail
  • bun test test/setup-help.test.ts test/gen-skill-docs.test.ts test/script-invocation-tripwire.test.ts: 511 pass, 0 fail
  • Guards (state-root, module-size, spawnsync, bun-entry, troubleshooting anchors, host-conformance): pass; bun run typecheck clean; bun run typecheck:test no new diagnostics
  • Remote pregate (whole free tier on Ubicloud): see the receipt

🤖 Generated with Claude Code

garrytan and others added 7 commits October 28, 2026 00:49
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@trunk-io

trunk-io Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

😎 This pull request was merged.

garrytan and others added 3 commits October 28, 2026 01:40
…t only gstack's own context block

Review blockers on #3526: uninstall deleted the edit backups under the state root;
unregister followed a symlinked folder below the destination; a lone or edited
context marker made the cut eat user lines; a re-register adding --context left an
unrecorded block. Also: ledger written before the files, --refresh-registered no
longer re-runs harness hosts through setup (gstack-harness refresh keeps their mode),
bash goes through runBashSync, and setup tests follow openclaw/hermes becoming installs.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…ease audit)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@capy-ai
capy-ai Bot marked this pull request as ready for review October 28, 2026 02:11
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@github-actions github-actions Bot changed the title feat(harness): gstack registers its skills in whatever agent harness it is installed into (GSTA-135) v1.91.290.0 feat(harness): gstack registers its skills in whatever agent harness it is installed into (GSTA-135) Oct 28, 2026
@capy-ai
capy-ai Bot merged commit 44f19d0 into main Oct 28, 2026
62 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant