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
2 changes: 1 addition & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ The primary session identity is **Skywalker** (`buildChatRole` → `createSkywal

**Provider-conditional residuals.** Per-family additions layer on top of the shared block via the same `ModelFamilyPolicy` mechanism the directors use (`src/subagent/provider-family.ts`, `src/agent/model-family-policy.ts`) — additive lines, never prompt forks. **Grok** leaves get `buildGrokLeafAntiThrashNote` (gated by `shouldApplyGrokAntiThrash` / `applyGrokFinishBias`, withheld from orchestrators): a compact finish-bias reinforcement plus a one-line reminder to route file/web work through the dedicated tools rather than `run_shell`, motivated by observed tool-routing thrash on the same harness. **Kimi** intentionally has no residual yet — `detectModelFamily` already resolves the family so callers can branch on it, but the prompt seam is left unfilled pending eval characterization of Kimi's behavior, mirroring the provisional (permissive-default) policy in `model-family-policy.ts`.

`buildChatSystemPrompt` (TUI chat) assembles: base → core tool list → name-only skills listing → live `<env>` block → appended extensions. `buildSubAgentSystemPrompt` assembles the worker prompt without a skills listing (workers bake optional skill bodies; they do not mount `use_skill` / `skill_search`). Built-in catalog tools (including `skill_search`) are advertised on the primary wire and callable directly; MCP integrations are discovered via `tool_search` rather than being enumerated. Skills follow the same lazy principle: each discovered skill contributes only its name to the primary prompt. The model calls `skill_search` for descriptions when choosing, then `use_skill` to load a body. The operator can also invoke the same skill as `/<skill-name>` (see Skills below). Skills are discovered (and deduped by name, first-wins) from enabled plugin dirs, then `.agents`/`.claude`/`.codex/skills`, in that precedence. Corbits Code ships a bundled catalog via the first-party `corbits-skills` plugin (origin `repo`); project-local skills of the same name are shadowed by an enabled plugin skill.
`buildChatSystemPrompt` (TUI chat) assembles: base → core tool list → name-only skills listing → live `<env>` block → appended extensions. `buildSubAgentSystemPrompt` assembles the worker prompt without a skills listing. Built-in catalog tools (including `skill_search`) are advertised on the primary wire and callable directly; MCP integrations are discovered via `tool_search` rather than being enumerated. Skills follow the same lazy principle: each discovered skill contributes only its name to the primary prompt. The model calls `skill_search` for descriptions when choosing, then `use_skill` to load a body. The operator can also invoke the same skill as `/<skill-name>` (see Skills below). Skills are discovered (and deduped by name, first-wins) from enabled plugin dirs, then `.agents`/`.claude`/`.codex/skills`, in that precedence. Corbits Code ships a bundled catalog via the first-party `corbits-skills` plugin (origin `repo`); project-local skills of the same name are shadowed by an enabled plugin skill.

**Overrides.** `loadSystemPromptOverrides` (`src/agent/context-extensions.ts`) resolves a project `SYSTEM.md` (repo root, then `.corbits/`) that **replaces** the static base block, and an `APPEND_SYSTEM.md` that is **appended** as an extension. These compose with `config.systemPromptExtensions` (profile config) and the auto-discovered `AGENTS.md`, all of which attach as appended sections after the base.

Expand Down
4 changes: 2 additions & 2 deletions docs/IMPLEMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ docs/

### Closed director fleet

Sixteen packages under `src/agent/directors/<id>/` register in `DIRECTOR_REGISTRY` (`registry.ts`). Wire path:
Twenty packages under `src/agent/directors/<id>/` register in `DIRECTOR_REGISTRY` (`registry.ts`). Wire path:

1. `spawn_agent(agent=…)` / `spawn_agent(intent=…)` → `resolveDirector` in `agent-fleet.ts` before tools and system prompt are built. Bare `spawn_agent` (neither field) and `intent=general` fail closed. After director resolution, `createSpawnAgentTool` fail-closes implement/review (and their default directors) without non-empty `success_criteria`.
2. `packageToProfile` maps envelope (`tools.allow`/`deny`) to `AgentProfile.capabilities` and `spawn.maySpawn` → `orchestrator`. System prompts are prefixed with a stable identity block (`formatDirectorSystemPrompt`: agent id, model role, optional skills).
Expand All @@ -168,7 +168,7 @@ Sixteen packages under `src/agent/directors/<id>/` register in `DIRECTOR_REGISTR
**Codex tool proxies.** When the active provider is Codex (`isCodexProviderName`), `createAgentToolset` and `runSubAgent` mount `apply_patch`, `shell`, and `update_plan` stringTools from `createCodexToolProxies`, all forwarding through the same posix `ToolRunner` seam (`runTool`) so permission plugins still apply. `apply_patch` parses the Codex envelope and forwards each op (`write_file` / `delete_file` / `read_file`). `shell` — the native Codex name is `shell`, not `exec_command` — normalizes Codex's `command` (string or `["bash","-lc",script]`-style argv array), `workdir`, and `timeout_ms` onto `run_shell`'s `{command, cwd?, timeout?}` and is gated by `allowShellFromCapabilities` (mirrors `allowDeleteFromCapabilities` against `run_shell`). `update_plan` maps Codex's `plan: [{step, status}]` onto `manage_tasks(action: "create")`; `pending`/`in_progress`/`completed` map to `todo`/`doing`/`done` — `manage_tasks`'s `cancelled` status has no Codex equivalent and is never produced by this proxy. Primary strips `apply_patch` after mount (Corbits DIY stays on `write_file` / `edit_file` / `delete_file`); `shell` and `update_plan` stay on primary (same classification as `run_shell` / `manage_tasks`). Build and docs worker allowlists (`BUILD_TOOLS` / `DOCS_TOOLS`) include `apply_patch` so Codex workers keep the proxy after the capability filter. `CORE_TOOL_NAMES` does not list it.

6. There is no static write-path declaration on packages or profiles (CL-6952 removed it — no shipped director ever set one). Instead, `agent-fleet.ts` tracks each running dispatch by cwd; a new mutating dispatch that lands on the same cwd as a live mutating peer (`pending_init`/`running`, and not a declared read-only `modelRole` of `explore`/`plan`/`review`/`test`) records at most one `concurrent-lane-overlap` entry per cwd wave in `intervention-log.ts` (class `conflict`). The wave flag clears when no live mutating writer remains for that cwd. Terminal-but-unsettled lanes (for example cancelled with `finishedAt` set while the run promise has not reached `finally`) are pruned from the map and do not warn. This is advisory only — it never blocks the spawn, since cwd overlap does not prove the two lanes touch the same files.
7. Spawn effort: pin > package `modelRole` default (`defaultEffortForDirector`; intern=low; plan/review/orchestrator=high; implement/explore/docs/test=medium) > orchestrator/worker binary > parent inheritance. Optional skills are listed in the identity header for awareness; workers do not mount `use_skill` (guidance is baked into package system prompts). Primary mounts `use_skill` for its own skill list.
7. Spawn effort: pin > package `modelRole` default (`defaultEffortForDirector`; intern=low; plan/review/orchestrator=high; implement/explore/docs/test=medium) > orchestrator/worker binary > parent inheritance. Optional skills are listed in the identity header for awareness; workers mount `skill_search` + `use_skill` scoped to the dispatch's `optionalSkills` and load bodies on demand (grok/kimi leaves omit `skill_search` and load brief-named skills straight through `use_skill`). Primary mounts `use_skill` for its own skill list.

Intent defaults: `intent=implement` → director `builder`; `explore` → `explorer`; `plan` → `counsel`; `review` → `critic`; general → error. Spawn: skywalker full fleet; all other directors, including greybeard, mount no fleet tools. Live `<env>` injects cwd, platform, arch, runtime, date, and git status on every chat and worker prompt.

Expand Down
3 changes: 2 additions & 1 deletion src/agent/directors/draper/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { REVIEW_TOOLS } from "../tool-sets.js";
*
* Deviations from the original (deliberate Corbits translations):
* 1. Brand references: the original loads the `brand-identity` skill and
* agents-repo `references/*.md` paths. Workers do not mount use_skill,
* agents-repo `references/*.md` paths. Skill bodies load on demand
* scoped to the dispatch's optionalSkills, and Draper declares none,
* so Draper loads only in-repo references relevant to the active
* lenses (DESIGN.md, design tokens, brand docs already in the tree)
* plus the mounted read/search/web tools.
Expand Down
16 changes: 8 additions & 8 deletions src/agent/directors/identity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ import type { ModelRole } from "./types.js";
import type { ReasoningEffort } from "../../provider/reasoning-effort.js";

/**
* Prefix every director system prompt with a stable identity block so the model
* always sees agent id, model role, and optional skills — no ambiguity about which
* package it is or how the parent should re-spawn it.
* Worker skill-use rule: skills mount on every worker (scoped to the
* dispatch's optionalSkills), so the worker searches only when the brief
* names a skill or the task leaves its lane.
*
* Skill bodies are never baked here. Workers (non-orchestrator) list skill
* names only and load bodies on demand with skill_search + use_skill, scoped
* to the dispatch's optionalSkills. Primary orchestrator (skywalker):
* use_skill is mounted — list skill names only.
*/
/**
* Worker skill-use rule: skills mount on every worker (scoped to the
* dispatch's optionalSkills), so the worker searches only when the brief
* names a skill or the task leaves its lane.
*/
export const WORKER_SKILL_SCOPING =
"Skills are available; search only when the brief names a skill or the task is outside your lane. For a small, bounded edit, do not search skills.";

/**
* Prefix every director system prompt with a stable identity block so the model
* always sees agent id, model role, and optional skills — no ambiguity about which
* package it is or how the parent should re-spawn it.
*/
export function formatDirectorSystemPrompt(pkg: DirectorPackage): string {
const names = pkg.optionalSkills;
const isPrimaryOrchestrator = pkg.tier === "orchestrator";
Expand Down
2 changes: 1 addition & 1 deletion src/agent/directors/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export interface DirectorPackage {
readonly description: string;
/** Opinionated core prompt (prompt-first). */
readonly systemPrompt: string;
/** Optional skill names (ordered). Workers bake matching first-party bodies into the prompt; the primary orchestrator keeps them use_skill-loadable. */
/** Optional skill names (ordered). Workers load matching bodies on demand with skill_search + use_skill, scoped to the dispatch's optionalSkills; the primary orchestrator keeps them use_skill-loadable. */
readonly optionalSkills?: readonly string[];
readonly tools?: ToolEnvelope;
readonly spawn: SpawnRights;
Expand Down
Loading