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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
### Changed

- ChatGPT Codex uses the Corbits system prompt as Responses `instructions`, without fetching or injecting the official GPT-5 Codex prompt.
- Builder now bakes compact Ponytail guidance with default lite mode and uses a smaller native-runtime skill instead of the broad native-integration and TypeScript bodies by default.

## [0.3.17] - 2026-09-05

Expand Down
14 changes: 7 additions & 7 deletions docs/PLUGINS.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,13 +322,13 @@ shape.
from the lazy listing (those stay loadable via explicit `use_skill` /
`resolveSkillBody`), so the model does not auto-suggest background libraries.
First-party recipes that are not operator slashes remain listed for
`skill_search` / `use_skill` when they only set `user-invocable: false` (`dispatch`,
`git-rebase`, `linear-issue-workflow`, `style`, `philosophy`, `native-integration`, `typescript`,
`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.
`skill_search` / `use_skill` when they only set `user-invocable: false`
(`git-rebase`, `linear-issue-workflow`, `style`, `philosophy`,
`native-integration`, `typescript`, `ponytail`, `opsh`). Background libs
such as `git-worktrees` set both flags. Bake-only bodies such as
`idiot-proof` and `native-runtime` also set both flags (baked into workers;
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`,
kind `command`, `defaultEnabled: true`) is the bundled skill catalog. Origin
`repo` is auto-trusted. Auto-enable applies only when `origin === "repo"` AND
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 — it does not steal planning from `/plan`. Substantial Builder work consumes a counsel / `/plan` plan first; tiny parent-DIY stays plan-optional. `/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`, `native-integration`, `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 `skill_search` (descriptions) then `use_skill` (body). 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 — it does not steal planning from `/plan`. Substantial Builder work consumes a counsel / `/plan` plan first; tiny parent-DIY stays plan-optional. `/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`, `native-integration`, `typescript`, `ponytail`, and `opsh` stay `use_skill` only (`user-invocable: false`). Bake-only bars such as `idiot-proof` and `native-runtime` are not slashes and are 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 `skill_search` (descriptions) then `use_skill` (body). 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 lists models from the live `/zen/go/v1/models` catalog (packaged seed on fetch failure), routes each 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
27 changes: 27 additions & 0 deletions plugins/corbits-skills/skills/native-runtime/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
name: native-runtime
user-invocable: false
disable-model-invocation: true
description: Compact Corbits worker runtime invariants for baked prompts.
---

Use Corbits tool names: `read_file`, `write_file`, `edit_file`, `delete_file`,
`grep`, `search_files`, `run_shell`, `web_search`, `web_fetch`,
`manage_tasks`, and `ask_director` for worker questions.

Use file tools for file reads, edits, writes, and deletions. Never use shell
redirects, heredocs, `echo`, `cat`, stream editors, or remove commands as
substitutes for file tools. Use bounded `grep` and `search_files` instead of
unbounded recursive shell searches. Use web tools for URLs; never use curl or
wget.

Workers ask the spawning director with `ask_director`; they cannot reach the
operator. If permission denies an action, make the best effort that remains and
report the assumption or blocker.

Before implementation reports, run the repository-defined typecheck, relevant
tests, and full verification gate when present. Report every exact command with
outcome and exit status.

Finish worker turns with the required `Summary`, `Findings`, `Blockers`, and
`Paths` envelope. Do not leave implied work outside the report.
33 changes: 33 additions & 0 deletions plugins/corbits-skills/skills/ponytail/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: ponytail
user-invocable: false
description: Compact builder mode guidance for minimal safe implementation diffs.
---

Ponytail is a Builder discipline for keeping implementation diffs small without
weakening the brief.

Default to `lite`: prefer the shortest clear change, reuse existing helpers and
tests, avoid drive-by refactors, and report only decisions or trade-offs the
parent needs. Reporting only decisions and trade-offs never licenses omitting
verification evidence: the Build Gate command-evidence requirement applies in
full in every mode. `off` means ignore Ponytail and follow the rest of the brief
normally. `full` means actively prune scope, split unrelated work into Blockers,
and keep every edit tied to a success criterion. `ultra` means the same
discipline under stricter pressure: delete dead paths you touch, reject
ornamental structure, and stop as soon as acceptance criteria and required
verification are complete.

Escalation ladder: start at `lite`; move to `full` when the brief asks for
minimal surface area, context is expensive, or the diff starts spreading; move
to `ultra` only when requested or when the parent explicitly prioritizes the
smallest viable implementation. De-escalate or turn `off` when Ponytail would
hide necessary reasoning.

Safety precedence is absolute: correctness, validation, security,
accessibility, data integrity, tests, repo conventions, operator requirements,
and explicit success criteria outrank minimal LOC. A mode never weakens those
constraints.

For review or audit, treat Ponytail as a lens for critic, neckbeard, or primary
instructions; do not create a Ponytail director or agent.
26 changes: 26 additions & 0 deletions src/agent/directors/bake-skills.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,30 @@ const philosophyOnDisk = stripFrontmatter(
"utf8",
),
);
const ponytailOnDisk = stripFrontmatter(
readFileSync(
join(import.meta.dirname, "../../../plugins/corbits-skills/skills/ponytail/SKILL.md"),
"utf8",
),
);
const nativeRuntimeOnDisk = stripFrontmatter(
readFileSync(
join(import.meta.dirname, "../../../plugins/corbits-skills/skills/native-runtime/SKILL.md"),
"utf8",
),
);

describe("loadBakedSkillBody", () => {
test("returns first-party style and philosophy bodies matching SKILL.md", () => {
expect(loadBakedSkillBody("style")).toBe(styleOnDisk);
expect(loadBakedSkillBody("philosophy")).toBe(philosophyOnDisk);
});

test("returns first-party ponytail and native-runtime bodies matching SKILL.md", () => {
expect(loadBakedSkillBody("ponytail")).toBe(ponytailOnDisk);
expect(loadBakedSkillBody("native-runtime")).toBe(nativeRuntimeOnDisk);
});

test("returns undefined for unknown skill names", () => {
expect(loadBakedSkillBody("does-not-exist-xyz")).toBeUndefined();
});
Expand All @@ -45,6 +62,15 @@ describe("formatBakedOptionalSkills", () => {
expect(text).toContain("use_skill is not mounted on workers");
});

test("formats ponytail and native-runtime under Baked skill guidance", () => {
const text = formatBakedOptionalSkills(["ponytail", "native-runtime"]);
expect(text).toContain("# Baked skill guidance");
expect(text).toContain("### ponytail");
expect(text).toContain("### native-runtime");
expect(text).toContain(ponytailOnDisk);
expect(text).toContain(nativeRuntimeOnDisk);
});

test("skips missing names without inventing content", () => {
const text = formatBakedOptionalSkills(["does-not-exist-xyz"]);
expect(text).toBe("");
Expand Down
15 changes: 10 additions & 5 deletions src/agent/directors/builder/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,16 @@ describe("builderPackage", () => {
expect(p).toContain("`/implement` does not steal planning from `/plan`");
});

test("systemPrompt requires style, philosophy, and idiot-proof prerequisites", () => {
test("systemPrompt requires baked core constraints and Ponytail prerequisites", () => {
const p = builderPackage.systemPrompt;
expect(p).toContain("Prerequisites");
expect(p).toMatch(/style, philosophy, native-integration, and idiot-proof/i);
expect(p).toMatch(/style, philosophy, native-runtime, idiot-proof, and Ponytail/i);
expect(p).toMatch(/use_skill is not mounted/i);
expect(p).toMatch(
/including their TypeScript conventions when TypeScript is the task surface/i,
);
expect(p).not.toMatch(/native-integration, and idiot-proof/i);
expect(p).not.toMatch(/Apply typescript when writing TypeScript/i);
});

test("systemPrompt is implement leaf only (no orchestrate / spawn / review-as-primary)", () => {
Expand Down Expand Up @@ -112,13 +117,13 @@ describe("builderPackage", () => {
expect(builderPackage.modelRole).toBe("implement");
});

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

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 worker — edit, verify, report",
optionalSkills: ["style", "philosophy", "native-integration", "idiot-proof", "typescript"],
optionalSkills: ["style", "philosophy", "native-runtime", "idiot-proof", "ponytail"],
tools: { allow: BUILD_TOOLS },
spawn: { maySpawn: false },
tier: "leaf",
Expand All @@ -30,7 +30,7 @@ You are a disciplined implementer worker (maySpawn:false) — not Critic, not Ex

## Prerequisites

Before substantial repo work: follow style, philosophy, native-integration, and idiot-proof (baked; use_skill is not mounted). Follow AGENTS.md and /docs. Apply typescript when writing TypeScript.
Before substantial repo work: follow style, philosophy, native-runtime, idiot-proof, and Ponytail (baked; use_skill is not mounted). Follow AGENTS.md and /docs, including their TypeScript conventions when TypeScript is the task surface.

## Plan

Expand Down
45 changes: 36 additions & 9 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, native-integration, idiot-proof, typescript");
expect(text).toContain("style, philosophy, native-runtime, idiot-proof, ponytail");
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/native-integration/idiot-proof/typescript bodies for builder workers (CL-6803)", () => {
test("bakes real compact Builder skill bodies without broad native-integration or typescript", () => {
const text = formatDirectorSystemPrompt(DIRECTOR_REGISTRY.builder);
const style = stripFrontmatter(
readFileSync(
Expand All @@ -44,12 +44,9 @@ describe("formatDirectorSystemPrompt", () => {
"utf8",
),
);
const nativeIntegration = stripFrontmatter(
const nativeRuntime = stripFrontmatter(
readFileSync(
join(
import.meta.dirname,
"../../../plugins/corbits-skills/skills/native-integration/SKILL.md",
),
join(import.meta.dirname, "../../../plugins/corbits-skills/skills/native-runtime/SKILL.md"),
"utf8",
),
);
Expand All @@ -59,18 +56,48 @@ describe("formatDirectorSystemPrompt", () => {
"utf8",
),
);
const ponytail = stripFrontmatter(
readFileSync(
join(import.meta.dirname, "../../../plugins/corbits-skills/skills/ponytail/SKILL.md"),
"utf8",
),
);
const nativeIntegration = stripFrontmatter(
readFileSync(
join(
import.meta.dirname,
"../../../plugins/corbits-skills/skills/native-integration/SKILL.md",
),
"utf8",
),
);
const typescript = stripFrontmatter(
readFileSync(
join(import.meta.dirname, "../../../plugins/corbits-skills/skills/typescript/SKILL.md"),
"utf8",
),
);
expect(text).toContain("# Baked skill guidance");
expect(text).toContain("### ponytail");
expect(text).toContain("### native-runtime");
expect(text).toContain(style);
expect(text).toContain(philosophy);
expect(text).toContain(nativeIntegration);
expect(text).toContain(nativeRuntime);
expect(text).toContain(idiotProof);
expect(text).toContain(typescript);
expect(text).toContain(ponytail);
expect(text).toContain("Default to `lite`");
expect(text).not.toContain(nativeIntegration);
expect(text).not.toContain(typescript);
expect(text).not.toContain("### native-integration");
expect(text).not.toContain("### typescript");
});

test("skywalker does not bake Ponytail", () => {
const text = formatDirectorSystemPrompt(DIRECTOR_REGISTRY.skywalker);
expect(text).not.toContain("### ponytail");
expect(text).not.toMatch(/ponytail/i);
expect(text).not.toContain("Default to `lite`");
expect(text).not.toContain("Escalation ladder");
});

test("does not bake skill bodies when optionalSkills is empty", () => {
Expand Down
7 changes: 7 additions & 0 deletions src/agent/directors/skywalker/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ describe("skywalkerPackage", () => {
]);
});

test("systemPrompt has no Ponytail routing or mode internals", () => {
const p = skywalkerPackage.systemPrompt;
expect(p).not.toMatch(/ponytail/i);
expect(p).not.toContain("Default to `lite`");
expect(p).not.toContain("Escalation ladder");
});

test("primaryIntent and outOfLane", () => {
expect(skywalkerPackage.primaryIntent).toBe(
"Orchestrate; DIY tiny/bounded product edits; spawn for substantial work",
Expand Down
Loading
Loading