Skip to content

Commit 7c1488e

Browse files
Add Lexicon skill owning director prompt drift and size (#961)
* Add Lexicon skill owning director prompt drift and size * Carve /lexicon out of spawn-director sentence in PRODUCT.md * Resolve the lexicon agents checkout portably Probe ../agents, honor AGENTS_CHECKOUT, else ask the operator instead of assuming a machine-specific default path.
1 parent f3659d6 commit 7c1488e

6 files changed

Lines changed: 183 additions & 8 deletions

File tree

‎docs/ARCHITECTURE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ Corbits Code **ships a bundled catalog** as the first-party data-only plugin `pl
431431

432432
`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.
433433

434-
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 and does not steal planning from `/plan`; substantial Builder work consumes a counsel / `/plan` plan first; `/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.
434+
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`, `/lexicon`. `/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 and does not steal planning from `/plan`; substantial Builder work consumes a counsel / `/plan` plan first; `/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`; `/lexicon` owns director-prompt drift and size against the agents repo at a pinned commit. 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.
435435

436436
#### Discovery and precedence
437437

‎docs/PRODUCT.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ That distinction sets priority.
2020

2121
**The harness is core and cannot be swapped in later**, because everything runs inside it. Fleet events waking the director, continuous dispatch while capacity is free, unprompted reporting, aggregated health, a bound grounded in real cost rather than a turn count. This is the part no one can hand us and the part a competitor cannot copy from a directory of prompts.
2222

23-
**Agent personas and skills are content.** They define who gets dispatched and to what standard. They are valuable, they are swappable, and they ship as the first-party `corbits-skills` plugin — on by default, disable-able in `/plugins`. The default action set (`/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`) is not an optional install and not something an operator has to discover.
23+
**Agent personas and skills are content.** They define who gets dispatched and to what standard. They are valuable, they are swappable, and they ship as the first-party `corbits-skills` plugin — on by default, disable-able in `/plugins`. The default action set (`/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`, `/lexicon`) is not an optional install and not something an operator has to discover.
2424

2525
**Distribution is packaging for content**, and content is not the constraint. A catalog and an install surface matter eventually; they do not gate anything the product is actually judged on.
2626

@@ -107,7 +107,7 @@ the file path and parse details.
107107

108108
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.
109109

110-
**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.
110+
**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`, `/lexicon`. 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`). `/lexicon` owns director-prompt drift and size against the agents repo at a pinned commit. 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.
111111

112112
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.
113113

@@ -155,7 +155,7 @@ Capabilities beyond the core toolset are opt-in plugins, enabled per workspace t
155155

156156
## Multi-agent (fleet agents)
157157

158-
The primary session is always **orchestrator** (single-agent mode is gone). Its identity is **Skywalker** (product name remains Corbits Code; when asked its name, answer Skywalker): classify work, DIY tiny/single-file/one-route product edits, dispatch a **closed fleet of 19 directors** for substantial work, track the fleet, and synthesize. Product mutation tools (`write_file` / `edit_file` / `delete_file`) are mounted on the primary (CORE / `SKYWALKER_TOOLS`) — path tools are the DIY surface; spawn remains the default for substantial, multi-file, parallel, or specialist work. Shell file-writes stay denied. MCP tools are not re-filtered by a product-write deny list (that list is gone). There is no static per-package write-path declaration (CL-6952 removed it — no shipped director ever set one). A concurrent dispatch landing on the same working directory as another still-running lane is recorded as a `conflict` intervention, not blocked. Operator slash recipes (`/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`) tell Skywalker which directors to spawn for substantial work; tiny/bounded edits may run on the primary.
158+
The primary session is always **orchestrator** (single-agent mode is gone). Its identity is **Skywalker** (product name remains Corbits Code; when asked its name, answer Skywalker): classify work, DIY tiny/single-file/one-route product edits, dispatch a **closed fleet of 19 directors** for substantial work, track the fleet, and synthesize. Product mutation tools (`write_file` / `edit_file` / `delete_file`) are mounted on the primary (CORE / `SKYWALKER_TOOLS`) — path tools are the DIY surface; spawn remains the default for substantial, multi-file, parallel, or specialist work. Shell file-writes stay denied. MCP tools are not re-filtered by a product-write deny list (that list is gone). There is no static per-package write-path declaration (CL-6952 removed it — no shipped director ever set one). A concurrent dispatch landing on the same working directory as another still-running lane is recorded as a `conflict` intervention, not blocked. Operator slash recipes (`/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`, `/lexicon`) tell Skywalker which directors to spawn for substantial work (`/lexicon` runs on the primary and spawns nothing); tiny/bounded edits may run on the primary.
159159

160160
| Lane | Directors |
161161
| --------- | ------------------------------------------------------------------------------------------------ |

‎plugins/corbits-skills/manifest.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
"name": "Corbits Skills",
44
"kind": "command",
55
"defaultEnabled": true,
6-
"description": "Default operator skills and slash commands (implement, refactor, review, pull-request-review, create-issue, scribe, interview, ast-grep, plan)."
6+
"description": "Default operator skills and slash commands (implement, refactor, review, pull-request-review, create-issue, scribe, interview, ast-grep, plan, lexicon)."
77
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
name: lexicon
3+
description: Diff director prompts against the agents repo at a pinned commit, report assembled prompt sizes, and file Linear issues for drift
4+
argument-hint: "[--pin <commit>] [--file-issues]"
5+
---
6+
7+
# Lexicon
8+
9+
Own prompt drift and size for the director prompts mirrored from the
10+
agents repo. Diff each same-name director prompt against the agents
11+
checkout at a pinned commit, report assembled prompt sizes, and file
12+
Linear issues for drift.
13+
14+
## What this is not
15+
16+
- Not a director. There is no `lexicon` director package, no
17+
`src/agent/directors/lexicon/` module, and no Skywalker
18+
classification route. Never call `spawn_agent(agent="lexicon")` —
19+
this skill runs as a `/lexicon` slash playbook on the primary only.
20+
- Not a fleet router. It does not assign identity or dispatch workers.
21+
- Not ponytail. That skill stays untouched.
22+
23+
## Step 1: Pin the agents commit
24+
25+
All comparisons in one run use a single pinned commit of the agents
26+
checkout — never float mid-run.
27+
28+
1. Resolve the checkout — probe `../agents` beside this repo, then
29+
`$AGENTS_CHECKOUT` when set, else ask the operator for the path.
30+
Never assume a machine-specific default.
31+
2. Record the pin: `git -C <checkout> rev-parse HEAD`.
32+
3. Read every agents-side file with `git show <pin>:<path>` so local
33+
working-tree edits cannot skew the diff.
34+
35+
## Step 2: Match same-name prompts
36+
37+
- Director side: the closed `DIRECTOR_IDS` set in
38+
`src/agent/directors/types.ts`; each prompt lives in
39+
`src/agent/directors/<id>/package.ts` as `systemPrompt`.
40+
- Agents side: `plugins/*/agents/*.md` files in the checkout, matched
41+
by file basename — `<id>.md` matches director `<id>` exactly.
42+
- Near-misses are not diffs: `critique.md` is not `critic`, and
43+
`marketing-intern.md` is not `intern`. List them as unmatched, do
44+
not force a comparison.
45+
46+
## Step 3: Diff same-name pairs
47+
48+
For each matched pair, compare the director `systemPrompt` against the
49+
agents file body at the pin. Report per director: in sync, or drifted
50+
with the drifted sections quoted on both sides. Note the ported-from
51+
commit recorded in the package comment (e.g. gaasbot's `@ 6e16b6c`)
52+
when it disagrees with the pin — a stale port marker is itself drift.
53+
54+
## Step 4: Report assembled prompt sizes
55+
56+
Reuse the canonical helper in `src/agent/prompt-sizes.ts` — do not
57+
hand-roll a new measurement:
58+
59+
- `directorPromptSizeTable()` for the full per-director x per-family
60+
table (default assembly vs Grok, pinned env).
61+
- `formatPromptSizeTable(rows)` to render it as markdown.
62+
63+
Include the rendered table in the report. Sizes move only when real
64+
prompt changes land; the env and provider inputs stay pinned.
65+
66+
## Step 5: File Linear issues for drift
67+
68+
Follow the `linear-issue-workflow` skill conventions. File one issue
69+
per drifted director (never one mega-issue across directors), using
70+
the mounted Linear MCP tools as they appear in the toolset — do not
71+
invent a Linear REST client. Each issue carries the pinned agents
72+
commit, the quoted drift from Step 3, and the size-table row from
73+
Step 4. Without `--file-issues`, report the drift and stop — do not
74+
file. Without mounted Linear MCP tools, stop and tell the operator
75+
to enable Linear MCP.
76+
77+
## Report
78+
79+
Per director: match status (matched / unmatched with reason), sync
80+
status at the pin, size rows, and the filed issue id or why nothing
81+
was filed.

‎tests/unit/corbits-skills-catalog.test.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const SKILL_DIRS = [
2828
"opsh",
2929
"plan",
3030
"idiot-proof",
31+
"lexicon",
3132
] as const;
3233

3334
/** use_skill listing + resolve; not slash. No disable-model-invocation. */
@@ -58,6 +59,7 @@ const SLASH_SKILLS = [
5859
"interview",
5960
"ast-grep",
6061
"plan",
62+
"lexicon",
6163
] as const;
6264

6365
const BANNED_TOKENS = ["TaskCreate", "@greybeard", 'intent="general"'] as const;
@@ -96,8 +98,8 @@ test("corbits-skills plugin has no agents directory", () => {
9698
expect(existsSync(join(pluginRoot, "agents"))).toBe(false);
9799
});
98100

99-
test("corbits-skills catalog lists 20 skills with name and description", async () => {
100-
expect(SKILL_DIRS).toHaveLength(20);
101+
test("corbits-skills catalog lists 21 skills with name and description", async () => {
102+
expect(SKILL_DIRS).toHaveLength(21);
101103
const entries = await readdir(join(pluginRoot, "skills"), {
102104
withFileTypes: true,
103105
});
@@ -218,7 +220,7 @@ test("Corbits-only skills do not contain GaaS tool names", async () => {
218220
}
219221
});
220222

221-
test("loadSkillCommands lists exactly the nine slash actions", async () => {
223+
test("loadSkillCommands lists exactly the ten slash actions", async () => {
222224
const cmds = await loadSkillCommands(
223225
join(import.meta.dirname, "../../plugins/corbits-skills"),
224226
);
@@ -231,6 +233,7 @@ test("loadSkillCommands lists exactly the nine slash actions", async () => {
231233
"create-issue",
232234
"implement",
233235
"interview",
236+
"lexicon",
234237
"plan",
235238
"pull-request-review",
236239
"refactor",

0 commit comments

Comments
 (0)