CodeVetter · Repo Unpack · Extension points
garrytan/gstack
The repo is built around registries and discovery conventions. New skills are a directory + SKILL.md.tmpl picked up automatically by discoverTemplates; new hosts are a defineHost() config + one line in hosts/index.ts; new template placeholders are a RESOLVERS entry; new browse commands are additions to the READ/WRITE/META sets + COMMAND_DESCRIPTIONS + a dispatch handler; new CDP methods are allowlist entries with justification; new models are an overlay file + ALL_MODEL_NAMES entry; browser-skills and domain-skills are runtime-extensible stores; sections/*.md.tmpl let a big skill lazy-carve content.
- Add a skill: create <name>/SKILL.md.tmpl at repo root — discoverTemplates() scans root + one subdir level automatically; the generator, validator (test/helpers/skill-parser.ts), skill-check dashboard, and catalog budget all pick it up with zero wiring.
- Add a host: write hosts/<name>.ts calling defineHost() (defaults derive paths, frontmatter allowlist, resolver suppressions, runtimeRoot symlinks from the name), register it in hosts/index.ts ALL_HOST_CONFIGS + re-exports, gitignore the hostSubdir; parameterized smoke tests cover it automatically — documented step-by-step in docs/ADDING_A_HOST.md.
- Add a template placeholder: implement a resolver function taking TemplateContext and register it in the RESOLVERS record (scripts/resolvers/index.ts); optional gated entries ({resolve, appliesTo}) restrict a placeholder to named skills as a structural guardrail.
- Add a browse command: add the name to READ_COMMANDS/WRITE_COMMANDS/META_COMMANDS plus a COMMAND_DESCRIPTIONS entry in browse/src/commands.ts (load-time validation throws on mismatch), then handle it in read-commands.ts / write-commands.ts / meta-commands.ts; aliases go in COMMAND_ALIASES resolved by canonicalizeCommand().
- Add a snapshot flag: extend the SNAPSHOT_FLAGS metadata array in browse/src/snapshot.ts — the {{SNAPSHOT_FLAGS}} resolver renders it into docs from the same source.
- Extend CDP reachability: add a CdpAllowEntry {domain, method, scope, output, justification} to CDP_ALLOWLIST — deny-default means anything not listed 403s, and cdp-allowlist.test.ts lints that every entry has all four fields.
- Add a model family: drop model-overlays/<family>.md and add the name to ALL_MODEL_NAMES in scripts/models.ts; resolveModel() already maps family variants (gpt-5.4-* → gpt-5.4, claude-* → claude).
- Lazy-carve a big skill: put on-demand sections in <skill>/sections/*.md.tmpl with a manifest.json; discoverSectionTemplates renders them with the parent skill's TemplateContext.
- Browser-skills are a runtime plugin store: drop a directory with SKILL.md frontmatter (name/host/triggers/args/trusted) + script.ts into <project>/.gstack/browser-skills/, ~/.gstack/browser-skills/, or the bundled tier — no index file, discovery walks dirs; /skillify generates one from a successful /scrape.
- Domain-skills let agents persist per-site playbooks through `$B domain-skill save|promote-to-global|...` with a quarantine→active→global trust lifecycle tied to the injection classifier.
- Host lifecycle hooks live under hosts/<host>/hooks/ (e.g. hosts/claude/hooks/: AUQ capture, spawned-session directive, timeline stop, Memorable recall bridge) — the pattern for host-specific behavior that isn't skill content.
- The Chrome extension is a fixed-surface extension point: new sidebar panes or content scripts plug into extension/ (sidepanel.js, inspector.js, background.js service worker) but must respect the WS auth + token bootstrap contract pinned by BROWSER_INTERNALS.
- contrib/add-host is a contributor-only skill (/gstack-contrib-add-host) that scaffolds new hosts — an extension point that itself is never installed for users.
- Resolver suppression is a per-host extension dial: hosts opt out of resolver output via suppressedResolvers (CROSS_MODEL_RESOLVERS for outside-provider reviews, GBRAIN_RESOLVERS for brain features), and gen-skill-docs --respect-detection can un-suppress GBRAIN_* when a local gbrain is detected.