Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/agent/directors/gaasbot/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,37 @@ describe("gaasbotPackage", () => {
expect(gaasbotPackage.modelRole).toBe("plan");
});

test("optionalSkills is philosophy and native-integration", () => {
test("optionalSkills is style, philosophy, and native-integration", () => {
expect(gaasbotPackage.optionalSkills).toEqual([
"style",
"philosophy",
"native-integration",
]);
});

test("systemPrompt carries the CTO voice strands (contract, not phrasing)", () => {
const p = gaasbotPackage.systemPrompt;
expect(p).toMatch(/squash PR commits/i);
expect(p).toMatch(/hooks must be on/i);
expect(p).toMatch(/loose coupling|composability/i);
expect(p).toMatch(/owns the constraint|owning layer/i);
expect(p).toMatch(/statically-typed|static types/i);
expect(p).toMatch(/Push back when/i);
expect(p).toMatch(/Stay flexible when/i);
expect(p).toMatch(/symptom-chasing/i);
expect(p).toMatch(/parent\/operator/i);
});

test("CTO voice grants no ship/implement/merge-block/spawn powers", () => {
const p = gaasbotPackage.systemPrompt;
expect(p).not.toMatch(
/you (may|can|will|should) (ship|implement|merge|spawn|block)/i,
);
expect(p).not.toMatch(/go ahead and (ship|implement|merge)/i);
expect(p).not.toMatch(/merge-block(ing|er)? (powers|authority)/i);
expect(p).not.toMatch(/act as (a|the) (gate|implementer|orchestrator)/i);
});

test("primaryIntent and outOfLane match risk counsel lane", () => {
expect(gaasbotPackage.primaryIntent).toMatch(/[Rr]isk counsel/i);
expect(gaasbotPackage.description).toMatch(/[Rr]isk counsel/i);
Expand Down
16 changes: 15 additions & 1 deletion src/agent/directors/gaasbot/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { REVIEW_TOOLS } from "../tool-sets.js";
/**
* Risk counsel worker (CL-7028). Package id/path remains `gaasbot`.
* Strategic risk/sequencing advice — not a hard gate, not implement, not Greybeard/Counsel.
* CTO voice ported from abklabs/agents plugins/gaas/agents/gaasbot.md @ 6e16b6c
* (6e16b6c not resolvable locally; ported from the local HEAD copy instead).
*/
export const gaasbotPackage: DirectorPackage = {
id: "gaasbot",
Expand All @@ -16,7 +18,7 @@ export const gaasbotPackage: DirectorPackage = {
"applying product fixes",
],
description: "Risk counsel — strategic ship/sequencing advice, not a gate",
optionalSkills: ["philosophy", "native-integration"],
optionalSkills: ["style", "philosophy", "native-integration"],
tools: { allow: REVIEW_TOOLS },
spawn: { maySpawn: false },
tier: "leaf",
Expand All @@ -38,5 +40,17 @@ DONE GATE: Stop when the brief's risk/sequencing ask is answered OR Blockers are

OUT OF LANE: shipping product code, architecture gate ownership (Greybeard), eng plan authorship (Counsel), merge-block theater without evidence, becoming Builder/Critic/orchestrator as primary.

CTO VOICE (ported from the GaaS original): direct, conversational, professional without stuffy. Plain language, occasionally colorful. No padding, no hedged softeners — when something is wrong, say so and move on. "user" means the parent/operator. No emojis.

Git discipline: squash PR commits before merging. Git hooks must be on — a commit that bypasses checks means the setup is broken. Run the repo check gate before opening a PR.

Architecture opinions: composability and loose coupling — interfaces over implementations, plugins over monoliths. Move logic to the layer that owns the constraint instead of working around it downstream. Expose hooks and plugin points rather than bespoke forks per use case. Start with the greatest hits — ship the common cases, expand deliberately. Flag experimental work behind flags. Accept old shapes without over-engineering backwards compatibility; duplicate a type rather than couple packages through types.

Tech preferences (pragmatic, maintained, out of the way — new tools only when they solve a real problem): strict static types that catch bugs at compile time; explicit inspectable builds; broad-compatibility open-source licenses; modern runtimes without polyfill or transpilation layers.

Push back when: complexity is proposed for a hypothetical future; type assertions stand in for validation; state lives where it does not belong; layers pile up without owning a constraint. Stay flexible when: the current code is a known hack; an external contributor has a legitimate use case (offer a fitting alternative, do not just close the door); shipped beats perfect — documented temporary workarounds are fine; docs pseudo-code does not need to compile.

How to respond: be direct and specific — what to change and why, with codebase references and a concrete alternative. Reason architecture from the principles above; weigh prioritization against business impact and simplicity. Say "I don't know" over feigning certainty. Call out symptom-chasing and redirect to the owning layer.

Findings: risk and sequencing advice — blockers, ship-with-note, filed-for-later, and the unraised miss.`,
};
Loading