Skip to content

Commit b7d4a28

Browse files
committed
Restore the interview skill 1:1 with GaaS
Replace the ask_operator rewrite with Guy's GaaS interview body, including AskUserQuestion. Keep slash /interview. Operator-ask mapping stays on native-integration.
1 parent fdeac11 commit b7d4a28

3 files changed

Lines changed: 52 additions & 63 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
1919

2020
### Changed
2121

22+
- Restore the interview skill body 1:1 with GaaS (AskUserQuestion). Operator-ask mapping stays on native-integration. Slash /interview remains.
2223
- Restore the implement skill body 1:1 with GaaS (TaskCreate, @greybeard, Acknowledgment). Tool-name mapping stays on native-integration. Slash /implement remains.
2324
- Restore the typescript skill body 1:1 with GaaS. bun:test vs tap mapping lives on native-integration. user-invocable: false stays so it remains use_skill-only.
2425
- Restore the philosophy skill body 1:1 with GaaS (including the review acknowledgment). `user-invocable: false` stays so it remains use_skill-only.
Lines changed: 42 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
---
22
name: interview
33
argument-hint: "<topic>[; <context>]"
4-
description: Conduct an iterative multiple-choice interview using ask_operator. Returns the Q&A inline. Use as a utility when a caller needs structured user input on a topic.
4+
description: Conduct an iterative multiple-choice interview using AskUserQuestion. Returns the Q&A inline. Use as a utility when a caller needs structured user input on a topic.
5+
tools:
6+
- AskUserQuestion
57
---
68

79
# Interview
810

9-
Gather structured user input on a topic via multiple-choice `ask_operator` questions. Emit the Q&A inline; the caller decides what to do with it.
11+
Use this skill to gather user input on a topic by asking multiple-choice questions in batches via `AskUserQuestion`. Return the questions and answers in the conversation. The caller decides what to do with them.
1012

11-
This is a utility, not a planner. It does not decide what to build, write any files, spawn agents, or invoke other skills.
13+
This is a utility, not a planner. It does not decide what to build, write any files, or invoke other skills.
1214

1315
## Argument
1416

@@ -17,50 +19,50 @@ This is a utility, not a planner. It does not decide what to build, write any fi
1719
- **Topic** — what the interview is about
1820
- **Context** (optional) — facts already known. Treat each as an answered dimension; do not re-ask things context settles.
1921

20-
If no topic is given, ask for one with `ask_operator` before proceeding.
22+
If no topic is given, ask for one before proceeding.
2123

2224
## Process
2325

2426
### Identify dimensions to probe
2527

26-
Enumerate the open questions worth asking 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.
28+
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.
2729

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

30-
### Ask with ask_operator
32+
### Ask in batches
3133

32-
Each question is one `ask_operator` call: `question` (string) plus `options` (array of strings). Fire independent questions together as parallel tool calls in the same turn.
33-
34-
`ask_operator` is single-select per call. The operator can also type a custom answer. There is no multi-select flag — if a dimension genuinely permits several answers, encode the realistic combinations as options, or follow up once the first answer lands.
35-
36-
**No false caps.** `ask_operator` has no skill-invented ceiling on option count, parallel questions per round, or total rounds. Batch every independent dimension you can author now. Drop to one question only when the next question's text or options cannot be written without this answer. Stop when marginal value is low (see below) — never because a made-up quota was hit. If the caller passed an explicit cap, honour it.
34+
Each round uses `AskUserQuestion`. Refer to the tool's own documentation for parameter limits and multi-select behavior.
3735

3836
**Quality bar for options:**
3937

40-
- Mutually exclusive **short labels** — not "yes / no / maybe"
38+
- Mutually exclusive and concrete — not "yes / no / maybe"
4139
- Each option a real, defensible choice — not a strawman
42-
- Trade-offs, rationale, and context go in the **preceding transcript reply**, then `ask_operator` with a brief question and brief labels. Do not put essays in the option string — `options` are strings, not `{ label, description }` objects
40+
- Descriptions surface trade-offs ("simpler but less flexible", "consistent with existing patterns")
4341
- Ground options in the topic and context — do not invent generic options when concrete ones exist
44-
- Combination options only when the dimension genuinely permits more than one answer
42+
- Multi-select only when the dimension genuinely permits it
4543
- If you have a recommendation, put it first and label it
4644

47-
Referencing a prior answer inside a later question's text is fine.
45+
**Batching:**
46+
47+
- Default 2–4 questions per round, bundling dimensions that do not depend on each other
48+
- Drop to 1 question only when the next question's text or options cannot be authored without this answer
49+
- Referencing a prior answer inside a later question's text is fine
4850

4951
### Decide when to stop
5052

5153
Stop when:
5254

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

58-
There is no fixed round cap. Stop when the marginal value of another round is low.
60+
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.
5961

6062
### Handle trouble
6163

6264
- **Contradiction with a prior answer.** Ask one clarifying question that surfaces both choices directly. Record the resolution; do not silently overwrite.
63-
- **Custom answer reveals a missing dimension.** Add it to the dimension list and continue.
65+
- **"Other" reveals a missing dimension.** Add it to the dimension list and continue.
6466
- **Topic shift.** If the user's answers reframe the topic itself, stop, emit what you have, and tell the caller the topic has changed.
6567
- **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.
6668

@@ -73,7 +75,7 @@ When the interview ends, emit the Q&A inline as a numbered list of question →
7375
7476
1. <question>: <answer>
7577
2. <question>: <answer>
76-
3. <question>: <answer (combination)> — <answer>
78+
3. <question>: <answer (multi-select)> — <answer>
7779
```
7880

7981
If the user declined some questions or punted a dimension, note it in the same list:
@@ -88,39 +90,28 @@ After emitting the findings, stop. Do not load other skills, invoke other agents
8890

8991
## Worked example
9092

91-
**Invocation:** `use_skill(name="interview")` with the topic in the conversation, or `/interview notification system; backend is Node/Postgres, internal users only, must integrate with existing auth`
93+
**Invocation:** `skill(name="interview", arguments="notification system; backend is Node/Postgres, internal users only, must integrate with existing auth")`
9294

93-
**Round 1** (three parallel `ask_operator` calls — independent dimensions, so ask together). Trade-offs belong in the transcript before the calls, not in the labels — e.g. "critical vs activity vs re-engagement; never-miss vs real-time vs per-event opt-in; in-app vs email vs webhook."
95+
**Round 1** (3 questions, bundled because none depends on the others):
9496

9597
```
96-
ask_operator({
97-
question: "What is the primary goal of the notification system?",
98-
options: [
99-
"Alert on critical events",
100-
"Keep users informed of activity",
101-
"Drive user re-engagement"
102-
]
103-
})
104-
105-
ask_operator({
106-
question: "If you had to pick one, which matters most?",
107-
options: [
108-
"Reliability of delivery (recommended)",
109-
"Latency",
110-
"User control"
111-
]
112-
})
113-
114-
ask_operator({
115-
question: "Which delivery channels do you want?",
116-
options: [
117-
"In-app",
118-
"Email",
119-
"In-app + Email",
120-
"Webhook",
121-
"All of the above"
122-
]
123-
})
98+
AskUserQuestion([
99+
{ header: "Goal", question: "What is the primary goal of the notification system?",
100+
options: [
101+
{ label: "Alert on critical events", description: "Errors, security issues, SLA breaches" },
102+
{ label: "Keep users informed of activity", description: "Mentions, replies, updates" },
103+
{ label: "Drive user re-engagement", description: "Digests, reminders, summaries" } ] },
104+
{ header: "Priorities", question: "If you had to pick one, which matters most?",
105+
options: [
106+
{ label: "Reliability of delivery", description: "Never miss a notification, even if delayed" },
107+
{ label: "Latency", description: "Real-time, even if some are dropped under load" },
108+
{ label: "User control", description: "Fine-grained per-event opt-in/out" } ] },
109+
{ header: "Channels", question: "Which delivery channels do you want?", multiSelect: true,
110+
options: [
111+
{ label: "In-app", description: "Notification center in the UI" },
112+
{ label: "Email", description: "Per-event or digest" },
113+
{ label: "Webhook", description: "Outbound HTTP to a user-configured endpoint" } ] }
114+
])
124115
```
125116

126117
**Hypothetical answers:** Alert on critical events; Reliability of delivery; In-app + Email.
@@ -136,10 +127,9 @@ ask_operator({
136127
## Anti-patterns
137128

138129
- **Interviewing yourself.** Filling in answers because they "seem obvious" — stop and ask, or note as assumption.
139-
- **Serializing independent questions.** If dimensions do not depend on each other, ask them in parallel.
140-
- **Inventing quotas.** Do not stop or thin options because of a made-up question or option count.
130+
- **One question per round, ten rounds deep.** Batch related questions.
141131
- **Asking about everything.** Prune dimensions that do not apply.
142-
- **Treating a custom answer as failure.** Custom answers are signal.
132+
- **Treating "Other" as failure.** Custom answers are signal.
143133
- **Forgetting context.** Read it. Do not re-ask things the context already settled.
144134
- **Writing files.** This skill never writes a file. The output is conversational.
145135
- **Invoking other skills or agents.** Emit findings and stop.

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -231,19 +231,17 @@ test("pull-request-review checkouts a worktree then loads the review skill", asy
231231
expect(skill).not.toContain('task(agent="critic")');
232232
});
233233

234-
test("interview skill is an ask_operator utility with no false caps", async () => {
234+
test("interview skill is 1:1 with GaaS interview", async () => {
235235
const skill = await Bun.file(join(pluginRoot, "skills/interview/SKILL.md")).text();
236-
expect(skill).toContain("ask_operator");
237-
expect(skill).toMatch(/utility/i);
238-
expect(skill).toContain("## Interview findings:");
239-
expect(skill).toContain("No false caps");
240-
expect(skill).not.toContain(USER_INVOCABLE_FALSE);
241-
expect(skill).not.toMatch(/24/);
242-
expect(skill).not.toMatch(/at most \d+/i);
243-
expect(skill).not.toMatch(/parameter limits/i);
244-
expect(skill).not.toMatch(/maxItems|minItems|inputSchema/i);
245-
expect(skill).not.toContain("write a file");
236+
expect(skill).toContain("AskUserQuestion");
237+
expect(skill).toContain("argument-hint");
238+
expect(skill).toContain("tools:\n - AskUserQuestion");
239+
expect(skill).toContain("This is a utility, not a planner");
246240
expect(skill).toContain("never writes a file");
241+
expect(skill).toContain("parameter limits");
242+
expect(skill).not.toContain("ask_operator");
243+
expect(skill).not.toContain(USER_INVOCABLE_FALSE);
244+
expect(skill).not.toContain("## Acknowledgment");
247245
});
248246

249247
test("create-issue is Linear-first without restated MCP tool contracts", async () => {

0 commit comments

Comments
 (0)