mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 22:14:25 +01:00
* feat(modules): module catalog, per-model loadouts manifest and gstack-modules render (GSTA-140 PR 1a) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(modules): cover bin/gstack-modules and the loadouts schema; allow modules/ in pregate strays Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(modules): gen:skill-docs refuses an exclusion render without --out-dir; render tests set up their own arm Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(modules): skill exclusions honor pinned sections and section references; own-property loadout lookups; llms.txt follows the selection; ownership rechecked before swap Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: bump version and changelog (v1.91.296.0) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: loadout render cost and the modules/ directory in PROJECT_STRUCTURE Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: unstamp #3554 (slot calls stamp); CHANGELOG entry back under [Unreleased] 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>
72 lines
2.9 KiB
TypeScript
72 lines
2.9 KiB
TypeScript
/**
|
|
* Model overlay resolver — reads model-overlays/{model}.md and returns it
|
|
* wrapped in a subordinate behavioral-patch section.
|
|
*
|
|
* Precedence:
|
|
* 1. Exact match: ctx.model === 'gpt-5.4' → reads model-overlays/gpt-5.4.md
|
|
* 2. INHERIT directive: if the file's first non-whitespace line is
|
|
* `{{INHERIT:claude}}`, the resolver reads model-overlays/claude.md first
|
|
* and concatenates it ahead of the rest of this file's content.
|
|
* This lets `gpt-5.4.md` build on top of `gpt.md` without duplication.
|
|
* 3. Missing file: returns empty string (graceful degradation, no error).
|
|
* 4. No ctx.model set: returns empty string.
|
|
*
|
|
* The returned block is subordinate to skill workflow, safety gates, and
|
|
* AskUserQuestion instructions. The subordination language is part of the
|
|
* wrapper heading so it appears with every overlay regardless of file content.
|
|
*/
|
|
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import type { TemplateContext } from './types';
|
|
|
|
const OVERLAY_DIR = path.resolve(import.meta.dir, '../../model-overlays');
|
|
|
|
const INHERIT_RE = /^\s*\{\{INHERIT:([a-z0-9-]+(?:\.[0-9]+)*)\}\}\s*\n/;
|
|
|
|
export function readOverlay(model: string, seen: Set<string> = new Set(), excluded: ReadonlySet<string> = new Set()): string {
|
|
if (seen.has(model)) return ''; // cycle guard
|
|
seen.add(model);
|
|
if (excluded.has(`overlay:${model}`)) return '';
|
|
|
|
const filePath = path.join(OVERLAY_DIR, `${model}.md`);
|
|
if (!fs.existsSync(filePath)) return '';
|
|
|
|
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
const match = raw.match(INHERIT_RE);
|
|
if (!match) return raw.trim();
|
|
|
|
const baseModel = match[1];
|
|
const base = readOverlay(baseModel, seen, excluded);
|
|
const rest = raw.replace(INHERIT_RE, '').trim();
|
|
|
|
if (!base) return rest;
|
|
return `${base}\n\n${rest}`;
|
|
}
|
|
|
|
export function generateModelOverlay(ctx: TemplateContext): string {
|
|
if (!ctx.model) return '';
|
|
|
|
const content = readOverlay(ctx.model, new Set(), ctx.modules?.excluded);
|
|
if (!content) return '';
|
|
|
|
const precedence = ctx.model === 'gpt-5.6-sol'
|
|
? `The following instructions disambiguate scope for the ${ctx.model} model.
|
|
They govern ambiguous completeness words such as \`complete\`, \`full\`, \`every\`,
|
|
\`exhaustive\`, \`100%\`, and \`Boil the Ocean\`, and when to stop iterating on
|
|
work the user did not ask for. Concrete skill workflow steps, STOP points,
|
|
AskUserQuestion gates, plan-mode safety, required tests, skill-mandated
|
|
re-verification and re-review loops, and /ship review gates still win.
|
|
Never use this patch to skip a concrete requirement.`
|
|
: `The following nudges are tuned for the ${ctx.model} model family. They are
|
|
**subordinate** to skill workflow, STOP points, AskUserQuestion gates, plan-mode
|
|
safety, and /ship review gates. If a nudge below conflicts with skill instructions,
|
|
the skill wins. Treat these as preferences, not rules.`;
|
|
|
|
return `## Model-Specific Behavioral Patch (${ctx.model})
|
|
|
|
${precedence}
|
|
|
|
${content}`;
|
|
}
|