ajhahn.de
← eeco
Go 35 lines
package cockpit

// geminiRenderer emits the whole selected playbook set as one GEMINI.md — the
// Gemini CLI context convention, plain Markdown with no frontmatter. GEMINI.md
// is advisory: Gemini reads it as context but enforces tool permissions in a
// separate `.gemini/settings.json` `tools.core` layer (emitting that is C4,
// not C2), so the file leads with the ADVISORY banner and names where real
// enforcement lives. Aggregate target, like AGENTS.md.
type geminiRenderer struct{}

func (geminiRenderer) Target() string { return "gemini" }

// Enforcement reports that GEMINI.md is advisory only (enforcement lives in a
// separate settings layer). It satisfies the Fidelity interface.
func (geminiRenderer) Enforcement() Enforcement { return EnforcementAdvisory }

// AggRelPath is the single shared artifact path for the whole set.
func (geminiRenderer) AggRelPath() string { return "GEMINI.md" }

// RenderAll renders the set as one GEMINI.md document, deterministic in set
// order (renderAggregateMarkdown sorts by Name).
func (geminiRenderer) RenderAll(ps []Playbook) ([]byte, error) {
	return renderAggregateMarkdown(ps,
		"GEMINI.md — eeco-generated agent playbooks",
		"Gemini reads this file as context. Tool-permission enforcement is NOT here — it lives in "+
			"`.gemini/settings.json` (`tools.core` / `tools.exclude`), which eeco does not emit in this slice."), nil
}

// RelPath / Render satisfy Renderer for interface completeness; the aggregate
// emit path (GenerateAll) is what actually drives this target.
func (r geminiRenderer) RelPath(Playbook) string { return r.AggRelPath() }
func (r geminiRenderer) Render(p Playbook) ([]byte, error) {
	return r.RenderAll([]Playbook{p})
}