fix(#3895): delete the mempalace-curator's model frontmatter pin — the fleet's only hardcoded model (#4048)

* test(#3895): no shipped agent may hardcode a model frontmatter pin (failing first)

* fix(#3895): delete the mempalace-curator's model frontmatter pin — the fleet's only hardcoded model

Exactly one of the 34 shipped agents carried 'model: sonnet' in its
frontmatter; every other agent resolves through the model-profile
system. The ship:post dispatch (#2684) resolves per-hook and — per
#2517 — deliberately OMITS model= on inherit so the agent inherits the
orchestrator's model; the frontmatter pin intercepted that inherit
case, silently forcing sonnet where all 33 siblings would inherit, and
operators could not durably remove it (install rewrites live copies
wholesale).

Deleting the line changes nothing for default profiles — the catalog
entry (model-catalog.json agents.gsd-mempalace-curator:
golden/balanced sonnet, budget haiku) preserves today's behavior —
while restoring model_overrides and inherit authority. Pinned by a new
agent-frontmatter guard: no shipped agent may hardcode a model pin,
and the catalog entry must keep existing so the pin's deletion can
never orphan the agent.

* chore(#3895): changeset fragment (pr number backfilled after PR creation)

* chore(#3895): backfill changeset PR number (4048)

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-08-29 14:11:39 -04:00
committed by GitHub
parent 400db94e02
commit 529480b4a5
3 changed files with 37 additions and 1 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 4048
---
gsd-mempalace-curator no longer hardcodes model: sonnet in its frontmatter — the only pin in the 34-agent fleet; it intercepted the deliberate inherit case (agents inherit the orchestrator model when resolution is inherit) and operators could not durably remove it. Default profiles keep sonnet via the model catalog; model_overrides and inherit now work (#3895)

View File

@@ -2,7 +2,6 @@
name: gsd-mempalace-curator
description: Ship-time MemPalace curation — writes the session diary, proposes/creates cross-project tunnels, mirrors extract-learnings into the temporal KG, and runs wing-scoped drawer pruning. Spawned at ship:post by the mempalace capability.
tools: Read, Bash, Grep, Glob
model: sonnet
color: cyan
---

View File

@@ -246,6 +246,38 @@ describe('AGENT: required frontmatter fields', () => {
}
});
// ─── Model resolution uniformity (#3895) ─────────────────────────────────────
describe('MODEL: no agent hardcodes a model frontmatter pin', () => {
// Exactly one shipped agent (gsd-mempalace-curator) carried `model: sonnet`
// while the other 33 resolved through the model-profile system. The pin
// intercepted #2517's deliberate inherit case — the ship:post dispatch OMITS
// model= on inherit so the agent inherits the orchestrator's model, but the
// frontmatter pin silently forced sonnet there. The catalog entry
// (model-catalog.json: golden/balanced sonnet) preserves default-profile
// behavior; operators regain model_overrides + inherit authority.
test('no shipped agent frontmatter contains a model: pin', () => {
const offenders = [];
for (const agent of ALL_AGENTS) {
const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8');
const frontmatter = content.split('---')[1] || '';
if (/^model:/m.test(frontmatter)) offenders.push(agent);
}
assert.deepEqual(
offenders, [],
`agents must resolve models via the model-profile system, not a frontmatter pin (#3895): ${offenders.join(', ')}`
);
});
test('the curator keeps its catalog entry (deleting the pin must not orphan the agent)', () => {
const catalog = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'gsd-core', 'bin', 'shared', 'model-catalog.json'), 'utf-8'));
const entry = catalog.agents && catalog.agents['gsd-mempalace-curator'];
assert.ok(entry, 'catalog entry for gsd-mempalace-curator must exist');
assert.equal(entry.golden, 'sonnet', 'golden profile preserves the pinned behavior');
assert.equal(entry.balanced, 'sonnet', 'balanced profile preserves the pinned behavior');
});
});
// ─── Color Value Validation ──────────────────────────────────────────────────
const VALID_AGENT_COLORS = new Set(['red', 'blue', 'green', 'yellow', 'purple', 'orange', 'pink', 'cyan']);