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 @@ -468,7 +468,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`, `/issue`, `/docs`, `/interview`. `/review` classifies the target first, then dispatches a selected fleet; `/pull-request` finds or opens the PR for the current branch, and `/review` takes a PR target and reviews it from a worktree; `/docs` is how to maintain PRODUCT / ARCHITECTURE / IMPLEMENTATION; `/implement` takes a plan and a ticket to a pushed branch (worktree, per-commit planner → implement → gate → reviewer loop, whole-branch review, push) 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; `/issue` finds or creates the tracker issue — 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.
The primary is the dispatch director. 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`, `/issue`, `/docs`, `/interview`. `/review` classifies the target first, then dispatches a selected fleet; `/pull-request` finds or opens the PR for the current branch, and `/review` takes a PR target and reviews it from a worktree; `/docs` is how to maintain PRODUCT / ARCHITECTURE / IMPLEMENTATION; `/implement` takes a plan and a ticket to a pushed branch (worktree, per-commit planner → implement → gate → reviewer loop, whole-branch review, push) and does not steal planning from `/plan`; substantial coder work consumes a planner / `/plan` plan first; `/plan` authors an eng change plan and does not implement or file tickets; `/issue` finds or creates the tracker issue — 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: the dispatch director orchestrates natively. Designer and the other specialists 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
2 changes: 1 addition & 1 deletion docs/PRODUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ 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`, `/compact` (fold conversation context now, optional trailing instructions to the summarizer; does not wait for the 60% occupancy governor; idle success shows the fold and does not start a new turn), `/mcp` (enable, disable, or remove servers), `/handoff [optional instructions]` (folds context through the shared operator pipeline, then immediately starts the next turn with the instructions as the inbound content — default copy when omitted; unlike `/compact`, which stops after the fold, handoff always re-infers, so the operator can pivot goals without `/clear`; a handoff issued mid-tool-batch queues behind the in-flight batch and whichever boundary fires first runs the single fold), and `/yolo` (`/yolo [on|off|toggle]`, bare `/yolo` toggles), plus a `/<name>` command per available workflow. `/yolo` persists skip-permissions to the active settings file. That file is the user-global `~/.corbits/settings.json` by default, making the setting machine-wide; explicit `--config <path>` selects a different active file, and `/yolo` writes that file. An ordinary TUI launch without the same `--config` returns to the user-global source and does not modify the custom file. `--dangerously-skip-permissions` and `--yolo` are process-only aliases. Secret-guard and authz still apply. When a session starts with its active persisted setting already on, the TUI and `corbits exec` warn that permission prompts are disabled by saved settings at the active settings path and direct the operator to edit that file to re-enable them. 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`, `/issue`, `/docs`, `/interview`. 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` classifies the target first, then dispatches a selected fleet; `/pull-request` finds or opens the PR for the current branch, and `/review` takes a PR target and reviews it from a worktree; `/docs` is how to maintain PRODUCT / ARCHITECTURE / IMPLEMENTATION; `/implement` takes a plan and a ticket to a pushed branch (worktree, per-commit planner/build/reviewer loop, whole-branch review, push, hand off to `/pull-request`) — 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. `/issue` finds or creates the tracker issue: 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. `typescript` stays `use_skill` only (`user-invocable: false`); `git-worktrees` is a background library that is 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`, `/issue`, `/docs`, `/interview`. 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` classifies the target first, then dispatches a selected fleet; `/pull-request` finds or opens the PR for the current branch, and `/review` takes a PR target and reviews it from a worktree; `/docs` is how to maintain PRODUCT / ARCHITECTURE / IMPLEMENTATION; `/implement` takes a plan and a ticket to a pushed branch (worktree, per-commit planner/build/reviewer loop, whole-branch review, push, hand off to `/pull-request`) — it does not steal planning from `/plan`. Substantial coder work consumes a planner / `/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. `/issue` finds or creates the tracker issue: 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: the dispatch director orchestrates natively. `typescript` stays `use_skill` only (`user-invocable: false`); `git-worktrees` is a background library that is not listed for `use_skill`. Designer and the other specialists 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
2 changes: 1 addition & 1 deletion plugins/corbits-skills/skills/git-worktrees/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Create and tear down a worktree from origin/<default-branch>. Load

# git-worktrees

Every workflow that writes code or checks out a branch works in a worktree, not the main checkout. Load this with `use_skill("git-worktrees")` and run the commands through `bash`.
Every workflow that writes code or checks out a branch (`/implement`, `/refactor`, and `/review` of a PR) works in a worktree, not the main checkout. Load this with `use_skill("git-worktrees")` and run the commands through `bash`. Tear the worktree down after the PR merges or the change is abandoned.

## Create from origin/<default-branch>

Expand Down
122 changes: 15 additions & 107 deletions plugins/corbits-skills/skills/interview/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,128 +6,36 @@ description: Ask the operator batched multiple-choice questions and return the Q

# Interview

Use this skill to gather user input on a topic by asking multiple-choice questions in batches via `ask_operator`. Return the questions and answers in the conversation. The caller decides what to do with them.

This is a utility, not a planner. It does not decide what to build, write any files, or invoke other skills.
Gather input on a topic with multiple-choice questions in batches through `ask_operator`, then return the questions and answers inline. This is a utility: it does not decide what to build, write files, or invoke other skills or agents. The caller decides what to do with the findings.

## Argument

`<topic>[; <context>]`

- **Topic** — what the interview is about
- **Context** (optional) — facts already known. Treat each as an answered dimension; do not re-ask things context settles.

If no topic is given, ask for one before proceeding.
`<topic>[; <context>]`. The topic is what the interview is about. Context is facts already known; treat each as an answered dimension and do not re-ask it. If no topic is given, ask for one first.

## Process

### Identify dimensions to probe

Enumerate the open questions worth asking, drawn from the topic and context. Skip dimensions the context already settles. Add domain-specific ones where relevant. There is no fixed dimension list — the topic determines it.

Probe objective and priorities before details. They shape every later question, so anchoring them early prevents reshuffling halfway through.

### Ask in batches

Each round uses `ask_operator`. Refer to the tool's own documentation for parameter limits and multi-select behavior.

**Quality bar for options:**
1. **Pick dimensions.** List the open questions the topic raises, skipping what the context settles. Probe objective and priorities first, since they shape every later question.
2. **Ask in batches.** 2 to 4 questions per round, bundling independent dimensions. Use one question only when the next one cannot be written without this answer. A later question may reference an earlier answer.
3. **Stop** when every dimension is answered or out of scope, when what remains is detail the caller can decide, when the operator signals fatigue (declines, short non-answers, asks to wrap up), or when the topic has shifted. There is no fixed round cap unless the caller gave one.

- Mutually exclusive and concrete — not "yes / no / maybe"
- Each option a real, defensible choice — not a strawman
- Descriptions surface trade-offs ("simpler but less flexible", "consistent with existing patterns")
- Ground options in the topic and context — do not invent generic options when concrete ones exist
- Multi-select only when the dimension genuinely permits it
- If you have a recommendation, put it first and label it
**Option quality:** concrete and mutually exclusive, each a defensible choice rather than a strawman, with descriptions that surface trade-offs. Ground them in the topic and context. Use multi-select only when the dimension allows it. Put your recommendation first and label it.

**Batching:**
**Trouble:**

- Default 2–4 questions per round, bundling dimensions that do not depend on each other
- Drop to 1 question only when the next question's text or options cannot be authored without this answer
- Referencing a prior answer inside a later question's text is fine
- A contradiction with an earlier answer: ask one question that surfaces both choices, and record the resolution.
- "Other" reveals a missing dimension: add it and continue.
- The answers reframe the topic, or the operator has no objective at all: stop, say what you learned and why you stopped, and let the caller decide.

### Decide when to stop

Stop when:

- Every open dimension has been answered or marked out of scope
- Remaining unknowns are details the caller can reasonably decide
- The user has signalled fatigue (declines to choose, short non-substantive "Other" answers, asks to wrap up)
- The topic has shifted into territory outside this interview's scope

There is no fixed round cap. Stop when the marginal value of another round is low. If the caller passed an explicit cap, honour it.

### Handle trouble

- **Contradiction with a prior answer.** Ask one clarifying question that surfaces both choices directly. Record the resolution; do not silently overwrite.
- **"Other" reveals a missing dimension.** Add it to the dimension list and continue.
- **Topic shift.** If the user's answers reframe the topic itself, stop, emit what you have, and tell the caller the topic has changed.
- **No objective to anchor on.** If the user is fundamentally undecided about the topic's objective itself (not just details), stop without a findings list. Tell the caller what you learned, why you stopped, and what they should consider doing instead.

### Return findings

When the interview ends, emit the Q&A inline as a numbered list of question → answer pairs. Format:
## Return

```
## Interview findings: <topic>

1. <question>: <answer>
2. <question>: <answer>
3. <question>: <answer (multi-select)> — <answer>
2. <question>: <answer (multi-select)> — <answer>
3. <question>: deferred (user said "you decide")
```

If the user declined some questions or punted a dimension, note it in the same list:

```
4. <question>: deferred (user said "you decide")
```

Do not invent a structured summary on top of this. The caller decides what to do with the findings.

After emitting the findings, stop. Do not load other skills, invoke other agents, or write any file.

## Worked example

**Invocation:** `skill(name="interview", arguments="notification system; backend is Node/Postgres, internal users only, must integrate with existing auth")`

**Round 1** (3 questions, bundled because none depends on the others):

```
ask_operator([
{ header: "Goal", question: "What is the primary goal of the notification system?",
options: [
{ label: "Alert on critical events", description: "Errors, security issues, SLA breaches" },
{ label: "Keep users informed of activity", description: "Mentions, replies, updates" },
{ label: "Drive user re-engagement", description: "Digests, reminders, summaries" } ] },
{ header: "Priorities", question: "If you had to pick one, which matters most?",
options: [
{ label: "Reliability of delivery", description: "Never miss a notification, even if delayed" },
{ label: "Latency", description: "Real-time, even if some are dropped under load" },
{ label: "User control", description: "Fine-grained per-event opt-in/out" } ] },
{ header: "Channels", question: "Which delivery channels do you want?", multiSelect: true,
options: [
{ label: "In-app", description: "Notification center in the UI" },
{ label: "Email", description: "Per-event or digest" },
{ label: "Webhook", description: "Outbound HTTP to a user-configured endpoint" } ] }
])
```

**Hypothetical answers:** Alert on critical events; Reliability of delivery; In-app + Email.

**Round 2** builds on round 1 (e.g. email cadence, failure handling). Once no obvious questions remain, emit the findings list and stop.

## Style

- Do not lecture between rounds. A short orientation sentence is fine.
- Do not summarize the user's answers back at them mid-interview.
- Do not ask leading questions.

## Anti-patterns
No summary on top of the list. Then stop: no other skills, no other agents, no files.

- **Interviewing yourself.** Filling in answers because they "seem obvious" — stop and ask, or note as assumption.
- **One question per round, ten rounds deep.** Batch related questions.
- **Asking about everything.** Prune dimensions that do not apply.
- **Treating "Other" as failure.** Custom answers are signal.
- **Forgetting context.** Read it. Do not re-ask things the context already settled.
- **Writing files.** This skill never writes a file. The output is conversational.
- **Invoking other skills or agents.** Emit findings and stop.
Do not lecture between rounds, restate answers mid-interview, ask leading questions, or answer for the operator; note an assumption instead.
Loading
Loading