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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
Excess dispatches report `queued` until a burst slot is free. Nested children
of an already-admitted parent bypass the burst window (not a 429 pause).
Capacity changes never cancel in-flight work.
- Builder and critic bake a compact less-is-more quality bar (`idiot-proof`:
deletion, reuse, clean only files you already touch, read first). It is not a
slash and is not listed for `use_skill`. Critic flags correctness plus hygiene
the diff introduced and still never implements. Skywalker no longer treats
that hygiene lens as over-engineering theater.

### Changed

Expand Down
2 changes: 1 addition & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ Corbits Code **ships a bundled catalog** as the first-party data-only plugin `pl

`discoverRepoPlugins` locates `plugins/` next to the source root, at `dist/plugins`, or at `dirname(execPath)/plugins`. It never scans the session cwd for the bundled catalog.

Primary is Skywalker. Bundled skill bodies are **how-to playbooks** (steps, done-definition) — not director personas and not fleet routers. Identity and who-does-what live on director system prompts. Default slashes: `/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`. `/review` is how to review a branch (base, scope, signal); `/pull-request-review` is worktree checkout then the review skill; `/scribe` is how to maintain PRODUCT / ARCHITECTURE / IMPLEMENTATION; `/implement` is the per-commit greybeard → implement → gate → critic loop; `/plan` authors an eng change plan and does not implement or file tickets; `/create-issue` remains the tracker command — Linear MCP when available, otherwise `ask_operator` for the platform and persists `Preferred issue tracker` in `.corbits/MEMORY.md`. There is no first-party dispatch skill — Skywalker orchestrates natively. Draper and emil are closed directors via `spawn_agent(agent=…)`, not slashes. There is no catch-all worker. The operator types the slash; the primary follows the playbook.
Primary is Skywalker. Bundled skill bodies are **how-to playbooks** (steps, done-definition) — not director personas and not fleet routers. Identity and who-does-what live on director system prompts. Default slashes: `/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`. `/review` is how to review a branch (base, scope, signal); `/pull-request-review` is worktree checkout then the review skill; `/scribe` is how to maintain PRODUCT / ARCHITECTURE / IMPLEMENTATION; `/implement` is the per-commit greybeard → implement → gate → critic loop; `/plan` authors an eng change plan and does not implement or file tickets; `/create-issue` remains the tracker command — Linear MCP when available, otherwise `ask_operator` for the platform and persists `Preferred issue tracker` in `.corbits/MEMORY.md`. The less-is-more quality bar (`idiot-proof`) is baked into builder and critic; it is not a slash. There is no first-party dispatch skill — Skywalker orchestrates natively. Draper and emil are closed directors via `spawn_agent(agent=…)`, not slashes. There is no catch-all worker. The operator types the slash; the primary follows the playbook.

#### Discovery and precedence

Expand Down
4 changes: 3 additions & 1 deletion docs/PLUGINS.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,9 @@ shape.
First-party recipes that are not operator slashes remain listed for
`use_skill` when they only set `user-invocable: false` (`dispatch`,
`git-rebase`, `linear-issue-workflow`, `style`, `philosophy`, `typescript`,
`opsh`). Background libs such as `git-worktrees` set both flags. The slash
`opsh`). Background libs such as `git-worktrees` set both flags. Bake-only
bodies such as `idiot-proof` also set both flags (baked into builder and
critic; not a slash and not listed for `use_skill`). The slash
command is a direct user entry
point on top.
- **First-party catalog.** `plugins/corbits-skills/` (id `corbits-skills`,
Expand Down
2 changes: 1 addition & 1 deletion docs/PRODUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ recovery line instead of dumping the file path and parse details.

The TUI has an extensible slash-command framework. Built-ins include `/help` (shortcut + command overlay), `/model` (models-only picker for connected accounts; **Alt+A** or `/connect` adds a provider), `/settings`, `/permissions`, `/plugins`, `/clear`, `/new`, `/mcp` (enable, disable, or remove servers), and `/yolo` (persists as the user-global skip-permissions default; `--dangerously-skip-permissions` still forces this process; secret-guard and authz still apply; `/yolo [on|off|toggle]`, bare `/yolo` toggles), plus a `/<name>` command per available workflow. When a session starts with the persisted default already on, the TUI shows a startup notice ("Permission prompts are disabled by your saved default…") so the silent machine-wide default is never invisible; `corbits exec` prints the equivalent warning to stderr. Plugins can register additional commands.

**Default skills** exist out of the gate as first-party slash **actions**, not director names: `/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`. Each one is a how-to playbook — the slash sends the skill body to the primary, which follows the steps. Skills do not assign identity or route the fleet; that stays on director system prompts. `/review` is how to review a branch; `/scribe` is how to maintain PRODUCT / ARCHITECTURE / IMPLEMENTATION; `/implement` is the per-commit review/build/critique loop; `/plan` authors an eng change plan (files, AC, non-goals, risks, ordered steps) and does not implement. `/create-issue` remains the tracker command: Linear MCP when available; otherwise it `ask_operator`s for the platform (GitHub etc.) and persists `Preferred issue tracker` in `.corbits/MEMORY.md` (GitHub via `gh issue create`). There is no first-party dispatch skill — Skywalker orchestrates natively. `git-rebase`, `linear-issue-workflow`, `style`, `philosophy`, `typescript`, and `opsh` stay `use_skill` only (`user-invocable: false`). Draper and emil are not slashes; they remain closed directors via `spawn_agent(agent=…)`. There is no catch-all worker. Slash names are also available to the model via `use_skill`. Disable the catalog in `/plugins` (`corbits-skills`) if you want them gone.
**Default skills** exist out of the gate as first-party slash **actions**, not director names: `/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`. Each one is a how-to playbook — the slash sends the skill body to the primary, which follows the steps. Skills do not assign identity or route the fleet; that stays on director system prompts. `/review` is how to review a branch; `/scribe` is how to maintain PRODUCT / ARCHITECTURE / IMPLEMENTATION; `/implement` is the per-commit review/build/critique loop; `/plan` authors an eng change plan (files, AC, non-goals, risks, ordered steps) and does not implement. `/create-issue` remains the tracker command: Linear MCP when available; otherwise it `ask_operator`s for the platform (GitHub etc.) and persists `Preferred issue tracker` in `.corbits/MEMORY.md` (GitHub via `gh issue create`). There is no first-party dispatch skill — Skywalker orchestrates natively. `git-rebase`, `linear-issue-workflow`, `style`, `philosophy`, `typescript`, and `opsh` stay `use_skill` only (`user-invocable: false`). The less-is-more quality bar (`idiot-proof`) is baked into builder and critic — not a slash and not listed for `use_skill`. Draper and emil are not slashes; they remain closed directors via `spawn_agent(agent=…)`. There is no catch-all worker. Slash names are also available to the model via `use_skill`. Disable the catalog in `/plugins` (`corbits-skills`) if you want them gone.

Providers are **models-first**: there is no standalone `/login` command. `/model` opens a **models-only list** (Recent, Favorites, then connected provider/model rows) — type-to-filter owns printable keys, so Connect is never a bare letter. **Alt+A** or `/connect` opens a dedicated add-provider selector over every first-class kind (OpenAI dual-path ChatGPT OAuth or API key, xAI, OpenCode Zen, Anthropic, Google, OpenCode Go, Z.AI Coding Plan, Ollama, Custom), each annotated with its live account count and never filtered out for “already connected.” **Alt+F** toggles favorite on the highlighted model. **Alt+D** persists the highlighted pair as the default without switching the live session. Advanced provider drill-down (edit/delete/tiers) stays on the advanced surface, not a bare printable key while the model list is filtering. OAuth providers open their existing browser login with a named account step so multiple accounts per kind coexist (`codex/work`, …). API-key providers use the same named-instance step before the key (auth-only form: instance name + key + fixed catalog base URL), so personal and team keys land as distinct catalog rows (`openai/default`, `anthropic/work`, …); reusing a name re-keys that instance after confirm. Custom remains a free-form single endpoint (full manual form). Successful connect refreshes the catalog and reopens the model list focused on the new account’s default model. OpenCode Go routes each model by its protocol metadata (chat completions, OpenAI responses, or Anthropic messages) and can show subscription usage in the status bar when active (rolling 5h / weekly / monthly windows when the usage API responds; omitted on auth or network failure). When Go returns a quota or rate-limit error — including some HTTP 400 responses that carry limit payloads — Corbits classifies them so quota aborts cleanly and short provider rate limits remain retryable. On a free-tier or subscription quota hit, wait for the window to reset or use OpenCode Zen free models.

Expand Down
20 changes: 20 additions & 0 deletions plugins/corbits-skills/skills/idiot-proof/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: idiot-proof
user-invocable: false
disable-model-invocation: true
description: Less is more. Reuse. Clean only files you already touch. Read first.
---

Prefer deletion over addition. Shortest working diff.

Reuse existing helpers, types, and tests. Do not copy.

In files you already touch: remove dead code, unused imports, and comments that narrate. Do not clean other files.

Read the target, its neighbors, and existing tests before editing.

No commented-out code, no shims for impossible states, no duplicated logic, no adapters for callers you own.

Comments only for non-obvious constraints.

Review: flag only what this diff introduced. Cite path. Do not fix.
13 changes: 9 additions & 4 deletions src/agent/directors/builder/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ describe("builderPackage", () => {
expect(p).toMatch(/never silently skip/i);
});

test("systemPrompt requires style and philosophy prerequisites", () => {
test("systemPrompt requires style, philosophy, and idiot-proof prerequisites", () => {
const p = builderPackage.systemPrompt;
expect(p).toContain("Prerequisites");
expect(p).toMatch(/style and philosophy/i);
expect(p).toMatch(/style, philosophy, and idiot-proof/i);
expect(p).toMatch(/use_skill is not mounted/i);
});

Expand Down Expand Up @@ -102,8 +102,13 @@ describe("builderPackage", () => {
expect(builderPackage.modelRole).toBe("implement");
});

test("optionalSkills order is style, philosophy, typescript", () => {
expect(builderPackage.optionalSkills).toEqual(["style", "philosophy", "typescript"]);
test("optionalSkills order is style, philosophy, idiot-proof, typescript", () => {
expect(builderPackage.optionalSkills).toEqual([
"style",
"philosophy",
"idiot-proof",
"typescript",
]);
});

test("primaryIntent and outOfLane reinforce lane discipline", () => {
Expand Down
4 changes: 2 additions & 2 deletions src/agent/directors/builder/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const builderPackage: DirectorPackage = {
"orchestrating or spawning other agents",
],
description: "Implementation leaf — edit, verify, report",
optionalSkills: ["style", "philosophy", "typescript"],
optionalSkills: ["style", "philosophy", "idiot-proof", "typescript"],
tools: { allow: BUILD_TOOLS },
spawn: { maySpawn: false },
tier: "leaf",
Expand All @@ -30,7 +30,7 @@ You are a disciplined implementer leaf (maySpawn:false) — not Critic, not Expl

## Prerequisites

Before substantial repo work: follow style and philosophy conventions (baked into this prompt for workers — use_skill is not mounted). Follow AGENTS.md and /docs. Apply typescript conventions when writing TypeScript.
Before substantial repo work: follow style, philosophy, and idiot-proof (baked; use_skill is not mounted). Follow AGENTS.md and /docs. Apply typescript when writing TypeScript.

## Implement and Test

Expand Down
28 changes: 15 additions & 13 deletions src/agent/directors/critic/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ describe("criticPackage", () => {
expect(p).toMatch(/invent defects from vibes/i);
});

test("systemPrompt is correctness-only / anti-over-engineering", () => {
expect(criticPackage.systemPrompt).toMatch(/correctness-only/i);
expect(criticPackage.systemPrompt).toMatch(/anti-over-engineering/i);
expect(criticPackage.systemPrompt).toMatch(
/correctness or the stated requirements\/success_criteria/i,
);
expect(criticPackage.systemPrompt).toMatch(/style nits/i);
expect(criticPackage.systemPrompt).toMatch(/file-for-later/i);
expect(criticPackage.systemPrompt).toMatch(/Do not drive over-engineering/i);
expect(criticPackage.systemPrompt).toMatch(/impossible cases/i);
test("systemPrompt is correctness plus this-diff hygiene", () => {
const p = criticPackage.systemPrompt;
expect(p).toMatch(/Correctness and this-diff hygiene/i);
expect(p).toMatch(/correctness or the stated requirements\/success_criteria/i);
expect(p).toMatch(/hygiene this diff introduced/i);
expect(p).toMatch(/dead code/i);
expect(p).toMatch(/file-for-later/i);
expect(p).toMatch(/Do not drive over-engineering/i);
expect(p).toMatch(/impossible cases/i);
expect(p).not.toMatch(/correctness-only/i);
});

test("systemPrompt flags API contract / sync→async as blocking", () => {
Expand Down Expand Up @@ -95,12 +95,14 @@ describe("criticPackage", () => {
expect(criticPackage.modelRole).toBe("review");
});

test("optionalSkills order is style, philosophy", () => {
expect(criticPackage.optionalSkills).toEqual(["style", "philosophy"]);
test("optionalSkills order is style, philosophy, idiot-proof", () => {
expect(criticPackage.optionalSkills).toEqual(["style", "philosophy", "idiot-proof"]);
});

test("primaryIntent and outOfLane match critic lane", () => {
expect(criticPackage.primaryIntent).toBe("Evidence-based code review; never fix product code");
expect(criticPackage.primaryIntent).toBe(
"Evidence-based code review including hygiene the diff introduced; never fix product code",
);
expect(criticPackage.outOfLane).toContain("implementing fixes");
expect(criticPackage.outOfLane).toContain("architecture portfolio without code evidence");
expect(criticPackage.outOfLane).toContain("visual brand");
Expand Down
17 changes: 10 additions & 7 deletions src/agent/directors/critic/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { REVIEW_TOOLS } from "../tool-sets.js";
*/
export const criticPackage: DirectorPackage = {
id: "critic",
primaryIntent: "Evidence-based code review; never fix product code",
primaryIntent:
"Evidence-based code review including hygiene the diff introduced; never fix product code",
outOfLane: [
"implementing fixes",
"architecture portfolio without code evidence",
Expand All @@ -16,14 +17,14 @@ export const criticPackage: DirectorPackage = {
"pedantic fun without evidence",
],
description: "Code quality review leaf",
optionalSkills: ["style", "philosophy"],
optionalSkills: ["style", "philosophy", "idiot-proof"],
tools: { allow: REVIEW_TOOLS },
spawn: { maySpawn: false },
tier: "leaf",
modelRole: "review",
systemPrompt: `You are CriticDirector (Critic), a specialist in Corbits Code.

PRIMARY INTENT: evidence-based code review. Find defects with evidence; never fix product code. Cite path, line or symbol, what breaks, and the concrete input or sequence that triggers it.
PRIMARY INTENT: evidence-based code review including hygiene the diff introduced. Find defects with evidence; never fix product code. Cite path, line or symbol, what breaks, and the concrete input or sequence that triggers it.

You are the review lane only — not an implementer, not an explorer, not an orchestrator. Do not ship fixes. Do not become greybeard or neckbeard as your primary job.

Expand All @@ -35,9 +36,11 @@ Evidence rules:
- Call out gaps: what you did not cover so the parent does not assume closed.
- Recommend permanent tests the suite should keep (name the scenario; do not implement them here — route to testsmith/builder).

Correctness-only / anti-over-engineering:
- Flag only gaps that affect correctness or the stated requirements/success_criteria.
- Style nits and speculative abstractions are optional / file-for-later unless the brief asks for hygiene.
Correctness and this-diff hygiene:
- Flag gaps that affect correctness or the stated requirements/success_criteria.
- Also flag hygiene this diff introduced: dead code, duplication, needless abstraction. Cite path. Do not fix.
- Style nits on untouched code stay file-for-later.
- Do not become neckbeard.
- Do not drive over-engineering: extra layers, defensive code for impossible cases, or tests for cases that cannot happen.

API contract check (blocking when brief specifies signatures):
Expand All @@ -47,7 +50,7 @@ API contract check (blocking when brief specifies signatures):
- Prefer reading tests/callers; a tiny sync call that would hang on a Promise is evidence.
- Rank these as blocking, not style nits.

Before substantial review work: follow style and philosophy conventions (baked; use_skill is not mounted on workers). Read the code under review.
Before substantial review work: follow style, philosophy, and idiot-proof (baked; use_skill is not mounted). Read the code under review.

OUT OF LANE → refuse or reclassify under Blockers:
- implementing fixes (route to builder)
Expand Down
11 changes: 9 additions & 2 deletions src/agent/directors/identity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe("formatDirectorSystemPrompt", () => {
expect(text.startsWith("Identity: agent id `builder`")).toBe(true);
expect(text).toContain('spawn_agent(agent="builder")');
expect(text).toContain("Model role: implement.");
expect(text).toContain("style, philosophy, typescript");
expect(text).toContain("style, philosophy, idiot-proof, typescript");
expect(text).toContain(DIRECTOR_REGISTRY.builder.systemPrompt);
});

Expand All @@ -30,7 +30,7 @@ describe("formatDirectorSystemPrompt", () => {
expect(text).toContain("Optional skills: none by default");
});

test("bakes real style/philosophy/typescript bodies for builder workers (CL-6803)", () => {
test("bakes real style/philosophy/idiot-proof/typescript bodies for builder workers (CL-6803)", () => {
const text = formatDirectorSystemPrompt(DIRECTOR_REGISTRY.builder);
const style = stripFrontmatter(
readFileSync(
Expand All @@ -44,6 +44,12 @@ describe("formatDirectorSystemPrompt", () => {
"utf8",
),
);
const idiotProof = stripFrontmatter(
readFileSync(
join(import.meta.dirname, "../../../plugins/corbits-skills/skills/idiot-proof/SKILL.md"),
"utf8",
),
);
const typescript = stripFrontmatter(
readFileSync(
join(import.meta.dirname, "../../../plugins/corbits-skills/skills/typescript/SKILL.md"),
Expand All @@ -53,6 +59,7 @@ describe("formatDirectorSystemPrompt", () => {
expect(text).toContain("# Baked skill guidance");
expect(text).toContain(style);
expect(text).toContain(philosophy);
expect(text).toContain(idiotProof);
expect(text).toContain(typescript);
});

Expand Down
3 changes: 2 additions & 1 deletion src/agent/directors/skywalker/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ describe("skywalkerPackage", () => {
const p = skywalkerPackage.systemPrompt;
expect(p).toContain("Verify after ship");
expect(p).toContain("tester");
expect(p).toContain("correctness/brief gaps");
expect(p).toContain("correctness/brief gaps and hygiene the diff introduced");
expect(p).toContain("That hygiene lens is not over-engineering theater");
expect(p).toMatch(/after every delegated \*\*builder\*\* implementation.*run \*\*critic\*\*/is);
expect(p).toMatch(
/substantial implementation limited to one internal file.*still requires Critic/is,
Expand Down
Loading
Loading