diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index d9e8082cd..97b7950f4 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -338,7 +338,7 @@ Templates contain the workflows, tips, and examples that require human judgment. | `{{ASIDE_RESEARCH}}` | `resolvers/aside.ts` | Web research through `aside exec` in the user's browser, WebSearch as the fallback, then the no-search degrade | | `{{ASIDE_EXEC_PRELUDE}}` | `resolvers/aside.ts` | One-line `_aside_exec` definition: an `aside exec` call writes an egress receipt before the prompt leaves the machine (fail-open, user-facing sink: it runs unreceipted only when the egress library is missing); skills never call `aside exec` bare | | `{{UNTRUSTED_CONTENT_WARNING}}` | `resolvers/aside.ts` | The one untrusted-content rule for everything either browser hands back | -| `{{PREAMBLE}}` | `gen-skill-docs.ts` | Startup block: update check, session tracking, contributor mode, AskUserQuestion format | +| `{{PREAMBLE}}` | `resolvers/preamble.ts`, `resolvers/preamble-hoist.ts` | Startup block: update check, session tracking, contributor mode, AskUserQuestion format; tier 2+ skills get a pointer to their shared `sections/preamble.md` plus the sections that are their own | | `{{BROWSE_SETUP}}` | `gen-skill-docs.ts` | Binary discovery + setup instructions | | `{{BROWSE_FALLBACK}}` | `resolvers/browse.ts` | Aside→`$B` hand-off: binary discovery + the step-by-step equivalence table, rendered right after `{{ASIDE_SETUP}}` in every browsing skill | | `{{BASE_BRANCH_DETECT}}` | `gen-skill-docs.ts` | Dynamic base branch detection for PR-targeting skills (ship, review, qa, plan-ceo-review) | @@ -369,7 +369,8 @@ This is structurally sound — if a command exists in code, it appears in docs. The generator also owns two files that are not skill docs: `review/design-checklist.md` is rendered from `lib/design-catalog.ts` (through `scripts/resolvers/design-checklist.ts`), and `lib/dom-dump.js` is written from `lib/dom-dump-script.ts`. The checklist `/review` and `/ship` read and the DOM dump `/design-review` runs therefore cannot drift from the catalog and the script the templates describe; `test/design-checklist-sync.test.ts` pins both. The internal async `runGeneration()` driver inventories skills, Claude sections -and QA/qa-only sections on every supported host, host metadata, OpenClaw snippets, +and QA/qa-only sections on every supported host, each tier 2+ skill's shared +`sections/preamble.md` on every host, host metadata, OpenClaw snippets, the index, the agent digest, and auxiliary assets. Other skills remain inline on non-Claude hosts; QA assets resolve relative to the installed host skill. Every artifact goes through one compare-or-write function. Dry runs @@ -394,6 +395,8 @@ Most workflow skills start with a `{{PREAMBLE}}` block that runs before the skil 4. **AskUserQuestion format** — universal format: context, question, `RECOMMENDATION: Choose X because ___`, lettered options. Consistent across all skills. 5. **Search Before Building** — before building infrastructure or unfamiliar patterns, search first. Three layers of knowledge: tried-and-true (Layer 1), new-and-popular (Layer 2), first-principles (Layer 3). When first-principles reasoning reveals conventional wisdom is wrong, the agent names the "eureka moment" and logs it. See `ETHOS.md` for the full builder philosophy. +Tier 2+ skills share most of this text, so it is not repeated in each SKILL.md. `scripts/resolvers/preamble-hoist.ts` renders the skill-independent preamble sections once per host into `sections/preamble.md` beside the SKILL.md, and the SKILL.md opens with a short "Shared preamble (load first)" pointer that names the file's content id; the agent reads the file only when that id is not already in the conversation, so a session loads it once. A section moves only when the skill's render of it is byte-identical to the shared render. The start command, sections that name the skill (Question Tuning, Repo Ownership, Search Before Building, Telemetry) and skill-specific variants stay inline. Tier 1 skills keep their short preamble inline. + ### Why committed, not generated at runtime? Three reasons: diff --git a/CLAUDE.md b/CLAUDE.md index 32cac189b..bf348fd95 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -117,7 +117,9 @@ SKILL.md files are **generated** from `.tmpl` templates. To update docs: 1. Edit the `.tmpl` file (e.g. `SKILL.md.tmpl` or `browse/SKILL.md.tmpl`) 2. Run `bun run gen:skill-docs` (or `bun run build` which does it automatically) -3. Commit both the `.tmpl` and generated `.md` files +3. Commit both the `.tmpl` and generated `.md` files, including a tier 2+ skill's + `sections/preamble.md` (the shared preamble, rendered by + `scripts/resolvers/preamble-hoist.ts`; change the preamble resolvers, never that file) The same `gen:skill-docs` run writes two more generated files from `lib/`: `review/design-checklist.md` (from `lib/design-catalog.ts`, through diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ee101e0eb..675a7aca4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -805,7 +805,7 @@ When you add a new skill template, all hosts get it automatically: 2. Run `bun run gen:skill-docs --host all` 3. The dynamic template discovery picks it up, no static list to update 4. Budget it: run `bun test/helpers/capture-context-budget.ts` and commit the refreshed `test/fixtures/context-budget.json` — the context-budget ratchet fails any skill without a ceiling -5. Commit `{skill}/SKILL.md`, external host output is generated at setup time and gitignored +5. Commit `{skill}/SKILL.md` (and the generated `{skill}/sections/preamble.md` when the template's `preamble-tier` is 2 or higher), external host output is generated at setup time and gitignored ## Conductor workspaces @@ -826,7 +826,7 @@ When Conductor creates a new workspace, `bin/dev-setup` runs automatically. It d ## Things to know -- **SKILL.md files are generated.** Edit the `.tmpl` template, not the `.md`. Run `bun run gen:skill-docs` to regenerate. The same run generates `review/design-checklist.md` from `lib/design-catalog.ts` and `lib/dom-dump.js` from `lib/dom-dump-script.ts`: edit those sources, never the generated files (`test/design-checklist-sync.test.ts` fails on drift). +- **SKILL.md files are generated.** Edit the `.tmpl` template, not the `.md`. Run `bun run gen:skill-docs` to regenerate. The same run generates `review/design-checklist.md` from `lib/design-catalog.ts` and `lib/dom-dump.js` from `lib/dom-dump-script.ts`: edit those sources, never the generated files (`test/design-checklist-sync.test.ts` fails on drift). Tier 2+ skills also get a generated `sections/preamble.md`, the shared preamble rendered by `scripts/resolvers/preamble-hoist.ts`: change the preamble resolvers, never that file. - **TODOS.md is the unified backlog.** Organized by skill/component with P0-P4 priorities. `/ship` auto-detects completed items. All planning/review/retro skills read it for context. - **Browse, make-pdf, design, and `lib/` source changes need a rebuild.** If you touch `browse/src/*.ts`, `make-pdf/src/*.ts`, `design/src/*.ts`, or anything under `lib/` (the canonical `claude-bin.ts`, `error-handling.ts`, and `aside-render.ts` the binaries embed, plus `design-catalog.ts`, whose `MOCKUP_NEVER_NAMES` the design binary's mockup prompt embeds; `browse/src` re-exports the first three), run `bun run build`. `./setup` makes the same call on its own: it rebuilds when any of the three binaries is missing or when those sources, `package.json`, or `bun.lock` are newer than the browse binary (`test/setup-needs-build.test.ts` pins the decision). - **Dev mode shadows your global install.** Project-local skills take priority over `~/.claude/skills/gstack`. `bin/dev-teardown` restores the global one. diff --git a/docs/PROJECT_STRUCTURE.md b/docs/PROJECT_STRUCTURE.md index e84f7cd36..931b983d8 100644 --- a/docs/PROJECT_STRUCTURE.md +++ b/docs/PROJECT_STRUCTURE.md @@ -26,7 +26,7 @@ gstack/ │ ├── gen-agents-digest.ts # Generates the budget-capped instruction-tier digest (agents-digest/) │ ├── host-config.ts # HostConfig interface + validator │ ├── host-config-export.ts # Shell bridge for setup script -│ ├── resolvers/ # Template resolver modules (preamble, aside = the Aside driver contract + research, browse = $B fallback setup + command reference, qa = surface-aware QA/exploration, sections = lazy loading, design, design-checklist = renders review/design-checklist.md from lib/design-catalog.ts, review-dashboard / plan-gates / spec-review / review-scope, outside-voice = outside-voice primitives + the one failure policy, outside-voice-steps = second opinion / adversarial / plan and doc review, gbrain, etc.) +│ ├── resolvers/ # Template resolver modules (preamble, preamble-hoist = the shared sections/preamble.md for tier 2+ skills, aside = the Aside driver contract + research, browse = $B fallback setup + command reference, qa = surface-aware QA/exploration, sections = lazy loading, design, design-checklist = renders review/design-checklist.md from lib/design-catalog.ts, review-dashboard / plan-gates / spec-review / review-scope, outside-voice = outside-voice primitives + the one failure policy, outside-voice-steps = second opinion / adversarial / plan and doc review, gbrain, etc.) │ ├── lib/shard-engine.ts # Shared shard engine for both test lanes: spawn, group kill, strict verdicts, per-shard sandbox, logs, duration seeds, flags │ ├── skill-check.ts # Health dashboard │ ├── test-free-shards.ts # Free-lane policy on the shard engine (GSTACK_FREE_JOBS, opt-in flaky retry)