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
11 changes: 6 additions & 5 deletions src/agent/directors/bruckheimer/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,13 @@ describe("bruckheimerPackage", () => {
expect(p).not.toMatch(/maySpawn:\s*true/);
});

test("systemPrompt teaches worker report shape Summary/Findings/Blockers/Paths", () => {
test("systemPrompt points at the scaffold-owned worker report envelope (no re-spec)", () => {
const p = bruckheimerPackage.systemPrompt;
expect(p).toContain("## Summary");
expect(p).toContain("## Findings");
expect(p).toContain("## Blockers");
expect(p).toContain("## Paths");
expect(p).toMatch(/Corbits report envelope/);
expect(p).not.toContain("## Summary");
expect(p).not.toContain("## Findings");
expect(p).not.toContain("## Blockers");
expect(p).not.toContain("## Paths");
expect(p).toMatch(/brief file you wrote/i);
expect(p).toContain("DONE GATE");
});
Expand Down
14 changes: 1 addition & 13 deletions src/agent/directors/bruckheimer/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,19 +129,7 @@ Use \`read_file\`, \`write_file\`, and \`edit_file\` to manage the brief. Use \`

# Report (when dispatched as a worker)

When you finish a discovery brief for a parent session, stop tooling and reply with ONLY:

## Summary
One or two sentences: what you accomplished or concluded.

## Findings
Audience, hook, win, scope cuts, glossary highlights, and anything the parent needs from the brief.

## Blockers
Open questions, assumptions, or blockers. Write "None." if clear. Name Builder / Counsel / Greybeard / Shakespeare when the ask belongs to them.

## Paths
The brief file you wrote (one path). Write "None." if you refused a brief because the bar was not met.
When you finish a discovery brief for a parent session, stop tooling and reply with ONLY the Corbits report envelope — the shared scaffold owns its shape (Summary / Findings / Blockers / Paths, in that order), so this package does not re-specify it. Findings for this lane: audience, hook, win, scope cuts, glossary highlights, and anything the parent needs from the brief. Blockers: name Builder / Counsel / Greybeard / Shakespeare when the ask belongs to them. Paths: the brief file you wrote (one path); "None." if you refused a brief because the bar was not met.

DONE GATE: Stop when audience, hook, and win are nailed and the brief is written (or you refused because the idea is not real), OR when Blockers need the parent. Do not invent architecture, ship code, author eng step-plans, or expand past discovery.

Expand Down
8 changes: 5 additions & 3 deletions src/agent/directors/intern/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ describe("internPackage", () => {
expect(p).toMatch(/execute clear (mechanical )?instructions/i);
expect(p).toMatch(/STOP/i);
expect(p).toMatch(/Blockers/i);
expect(p).toMatch(/## Summary/);
expect(p).toMatch(/## Findings/);
expect(p).toMatch(/## Paths/);
// Envelope shape is scaffold-owned: point at it, do not re-specify it.
expect(p).toMatch(/Corbits report envelope/);
expect(p).not.toMatch(/## Summary/);
expect(p).not.toMatch(/## Findings/);
expect(p).not.toMatch(/## Paths/);
expect(p).toMatch(/run_shell/);
// Role forbids debugging; body states the ban explicitly
expect(p).toMatch(/You do NOT:[\s\S]*Debug failures/);
Expand Down
14 changes: 1 addition & 13 deletions src/agent/directors/intern/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,5 @@ STOP. You are outside your role. Report Blockers for the parent (Skywalker) inst

# Report Contract

When done (or blocked), stop calling tools and reply with ONLY this markdown envelope:

## Summary
One or two sentences: what you ran or why you stopped.

## Findings
Commands run and their outputs (verbatim where useful). Observable facts only.

## Blockers
Ambiguity, failures, missing inputs, or decisions needed. Write "None." if clear. Do not invent fixes.

## Paths
Key file paths you read or changed (one per line). Write "None." if none.`,
When done (or blocked), stop calling tools and reply with ONLY the Corbits report envelope (Summary / Findings / Blockers / Paths) — the shared scaffold owns its shape, so this package does not re-specify it. See How to Report Back for what goes under Findings / Blockers.`,
};
11 changes: 6 additions & 5 deletions src/agent/directors/neckbeard/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,16 @@ describe("neckbeardPackage", () => {
expect(p).toMatch(/code \(when the brief asks\)|code review/i);
});

test("systemPrompt bakes style/philosophy and reports to parent", () => {
test("systemPrompt bakes style/philosophy and points at the shared envelope", () => {
const p = neckbeardPackage.systemPrompt;
expect(p).toMatch(/use_skill.*not mounted|not mounted.*use_skill/i);
expect(p).toMatch(/violently disagree/);
expect(p).toMatch(/report to the parent/i);
expect(p).toMatch(/## Summary/);
expect(p).toMatch(/## Findings/);
expect(p).toMatch(/## Blockers/);
expect(p).toMatch(/## Paths/);
expect(p).toMatch(/Corbits report envelope/);
expect(p).not.toMatch(/## Summary/);
expect(p).not.toMatch(/## Findings/);
expect(p).not.toMatch(/## Blockers/);
expect(p).not.toMatch(/## Paths/);
expect(p).toMatch(/ranked nits with evidence|evidence paths/i);
});

Expand Down
14 changes: 1 addition & 13 deletions src/agent/directors/neckbeard/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -569,17 +569,5 @@ Do not apply fixes. Do not become Builder, Critic, or Greybeard as your primary

# Reporting back

When done, stop calling tools and reply with ONLY this markdown envelope:

## Summary
One or two sentences: condescending overall take (Rust optional but encouraged).

## Findings
Ranked nits with evidence paths — Peak Neckbeard / Unbearable / Maddening / Insufferable. Each item cites a path (and line/symbol when available). Comic voice allowed ("Actually,", "Well technically,"); no emoji glyphs.

## Blockers
Open questions, missing docs/code, or out-of-lane routing. Write "None." if clear. If blocked, ask_director; after the cap, report remaining questions here.

## Paths
Key file paths you read (one per line). Write "None." if none.`,
When done, stop calling tools and reply with ONLY the Corbits report envelope — the shared scaffold owns its shape (Summary / Findings / Blockers / Paths, in that order), so this package does not re-specify it. Findings for this lane: ranked nits with evidence paths — Peak Neckbeard / Unbearable / Maddening / Insufferable, each citing a path (and line/symbol when available). Comic voice allowed ("Actually,", "Well technically,"); no emoji glyphs. Blockers: ... ask_director; after the cap, report remaining questions here. Paths: key file paths you read (one per line).`,
};
12 changes: 7 additions & 5 deletions src/agent/directors/testsmith/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ describe("testsmithPackage", () => {
expect(p).toMatch(/Hand off/i);
});

test("systemPrompt states Corbits report shape", () => {
test("systemPrompt points at the scaffold-owned report envelope (no re-spec)", () => {
const p = testsmithPackage.systemPrompt;
expect(p).toContain("## Summary");
expect(p).toContain("## Findings");
expect(p).toContain("## Blockers");
expect(p).toContain("## Paths");
expect(p).toMatch(/Corbits report shape/i);
expect(p).toMatch(/Corbits report envelope/);
expect(p).toMatch(/coverage map/);
expect(p).not.toContain("## Summary");
expect(p).not.toContain("## Findings");
expect(p).not.toContain("## Blockers");
expect(p).not.toContain("## Paths");
});

test("systemPrompt has no tool-schema restatement or fake caps", () => {
Expand Down
14 changes: 1 addition & 13 deletions src/agent/directors/testsmith/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,7 @@ Defer or omit:

# Corbits report shape

When done, stop tooling and reply with ONLY this envelope:

## Summary
One or two sentences: strategy and coverage scope designed.

## Findings
Permanent cases (name + boundary + setup/action/expect + risk), coverage map of each success_criteria item → cases (or blocked), and what not to test with why.

## Blockers
Open questions, missing acceptance criteria, or assumptions. Write "None." if clear.

## Paths
Files/suites you read to ground the design (one per line). Write "None." if none.
When done, stop tooling and reply with ONLY the Corbits report envelope — the shared scaffold owns its shape (Summary / Findings / Blockers / Paths, in that order), so this package does not re-specify it. Findings for this lane: permanent cases (name + boundary + setup/action/expect + risk), coverage map of each success_criteria item → cases (or blocked), and what not to test with why.

DONE GATE: Stop when every success_criteria item has permanent cases (or Blockers). Do not invent architecture or expand the brief after criteria are covered. If the brief is ambiguous, report Blockers — do not become Counsel or Greybeard.

Expand Down
117 changes: 117 additions & 0 deletions src/agent/prompts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { describe, expect, it } from "bun:test";
import {
buildChatSystemPrompt,
buildGrokLeafAntiThrashNote,
buildGuidelines,
buildPromptDisciplineBlock,
buildSubAgentSystemPrompt,
GUIDELINE_SUB_BLOCK_IDS,
} from "./prompts.js";
import { CORE_TOOL_NAMES, CATALOG_TOOL_NAMES } from "./tool-search.js";

Expand Down Expand Up @@ -138,6 +140,121 @@ describe("sub-agent report contract", () => {
expect(prompt).toMatch(/emit all four headings/);
expect(prompt).toContain('"None."');
});

it("emits the four-heading envelope exactly once (scaffold owns the shape)", () => {
const prompt = buildSubAgentSystemPrompt(undefined, undefined, undefined, {
orchestrator: false,
grokAntiThrash: false,
});
for (const heading of [
"## Summary",
"## Findings",
"## Blockers",
"## Paths",
]) {
expect(countOccurrences(prompt, heading)).toBe(1);
}
});
});

describe("guideline sub-block omit policy (CL-7654)", () => {
it("exposes the keepstyle set as ids", () => {
expect([...GUIDELINE_SUB_BLOCK_IDS]).toEqual([
"responseStyle",
"toolChoice",
"askVsProceed",
"scopeConventions",
"orchestration",
]);
});

it("keeps the full guidelines by default", () => {
const guidelines = buildGuidelines({});
for (const marker of [
"Response style:",
"Tool choice:",
"Ask vs proceed:",
"Scope and conventions:",
"Orchestration:",
]) {
expect(guidelines).toContain(marker);
}
});

it("goldens the default guidelines byte-for-byte (separator shifts fail loudly)", () => {
expect(buildGuidelines({})).toBe(`Guidelines:

Response style:
- Default to short, direct answers; skip preamble and filler.
- For substantial work, lead with the outcome, then what changed and why; use bullets or short headers only when they help scanning.
- Cite paths instead of pasting large files; fenced snippets only when essential.
- No emojis in code or docs unless the user uses them.

Tool choice:
- Prefer spawn_agent(agent=…) then idle for substantial product implementation, exploration, review, and docs — mailbox mail arrives as inbound; do not poll. Spawn remains default for substantial work, not a tool ban.
- read_file for file contents; grep or search_files to locate code; lsp for symbols, types, references, or call flow before opening large files.
- edit_file for targeted DIY tiny/single-file/one-route edits; write_file for new files or full rewrites; delete_file to remove files — never shell-write (echo/heredoc/sed/rm). Spawn builder (or a docs director) for substantial/multi-file/parallel/specialist work.
- run_shell for builds, tests, git, and one-off commands — not for shell find, head-position rg, or recursive grep -r (OOM risk), cat, or messaging the user.
- tool_search before assuming a plugin or MCP tool exists; skill_search when choosing among listed skills, use_skill to load a body.

Ask vs proceed:
- Clear, bounded coding requests: proceed autonomously; use ask_operator only when permission blocks you or the request is genuinely ambiguous (missing repro, conflicting instructions, destructive choice).
- Before ask_operator: put long rationale in a normal transcript reply first, then call ask_operator with a short question and short option labels only.
- Questions, reviews, and product/visual feedback: answer or diagnose first; do not edit until the user wants a change.
- Preserve unrelated user edits; never revert changes you did not make unless asked.
- Unexpected changes in files you did not touch: stop and ask_operator.

Scope and conventions:
- Touch only code required for the task; no drive-by refactors, formatting sweeps, or unrelated fixes.
- Follow AGENTS.md and /docs for architecture; use_skill style and philosophy when starting repo work.
- Match existing project patterns (functional style, arktype at boundaries, small focused diffs).
- Before finishing implementation work, run the repository-defined typecheck command, relevant tests, and every defined full verification command; these checks are mandatory.
- If the repository defines no typecheck command, do not invent a typecheck command: report its absence as an explicit Blocker with evidence from AGENTS.md and package scripts (or equivalent project configuration).
- In Findings, report every exact verification command and its outcome, including exit status. A bare \`pass\` without command evidence is an incomplete report.
- If a required check genuinely cannot run because of a missing runtime or dependency, sandbox restriction, or permissions, record the exact inability under Blockers; never silently skip a required check.

Orchestration:
- Break multi-step or parallel work into focused worker dispatches with distinct lenses; prefer \`spawn_agent\` (fire several in one turn when jobs are independent), then reply with who is running and end the turn — workers keep running while you are idle. Mailbox mail arrives as inbound when a worker finishes; read it and do not poll. \`list_agents\` shows the fleet without blocking; after a parked ask is surfaced, answer with \`send_input\` and do not poll \`list_agents\`.
- Pass the typed spawn contract: \`intent\`, \`success_criteria\` (done-when; required for implement/review and their default directors), \`do_not\` (scope fence), and \`report_focus\`. Free-form \`prompt\` without \`success_criteria\` fail-closes for implement/review and their default directors.
- After workers return, classify fail / incomplete-report vs parent-initiated interrupt vs operator-cancel vs clean complete. Fail-path (\`status: failed\` or salvage \`incomplete-report\`): diagnose from the report or error and MAY spawn one successor with a changed brief. Parent-initiated interrupt (\`interrupt_agent\` / \`send_input\` with \`interrupt:true\` unblocks wait with \`stop_reason: interrupted\`): the worker is often still running and often has no report — \`resume_agent\`, or idle for its mailbox mail; do not \`spawn_agent\` a successor against a still-live worker. Successor only if that session is no longer resumable. Operator-cancel (\`stop_reason\` cancelled): wait for the operator; do not auto-retry. Identical brief: refuse. Merge Summary/Findings into a coherent answer for the operator; do not paste raw fleet-agent dumps.
- Use manage_tasks for your own coordination checklist; spawning workers is \`spawn_agent\`, not manage_tasks.
- If context is compacted automatically, do not stop tasks early due to token fear; persist progress via manage_tasks and worker reports.`);
});

it("omit keeps response style, drops tool-choice / ask-vs-proceed / orchestration", () => {
const guidelines = buildGuidelines({
omit: ["toolChoice", "askVsProceed", "orchestration"],
});
expect(guidelines).toContain("Response style:");
expect(guidelines).toContain("Scope and conventions:");
expect(guidelines).not.toContain("Tool choice:");
expect(guidelines).not.toContain("Ask vs proceed:");
expect(guidelines).not.toContain("Orchestration:");
});

it("threads guidelineConfig through the chat system prompt", () => {
const full = buildChatSystemPrompt(
undefined,
undefined,
undefined,
[],
"orchestrator",
);
expect(full).toContain("Tool choice:");
expect(full).toContain("Orchestration:");
const keepstyle = buildChatSystemPrompt(
undefined,
undefined,
undefined,
[],
"orchestrator",
undefined,
{ omit: ["toolChoice", "askVsProceed", "orchestration"] },
);
expect(keepstyle).toContain("Response style:");
expect(keepstyle).not.toContain("Tool choice:");
expect(keepstyle).not.toContain("Orchestration:");
});
});

describe("wait_agents mount-gated prompt copy (CL-7678)", () => {
Expand Down
Loading
Loading