diff --git a/src/workspaces/officerdev/src/apps/CommandHQ/CommandHqDetail.tsx b/src/workspaces/officerdev/src/apps/CommandHQ/CommandHqDetail.tsx
index ed93cab0..0213c923 100644
--- a/src/workspaces/officerdev/src/apps/CommandHQ/CommandHqDetail.tsx
+++ b/src/workspaces/officerdev/src/apps/CommandHQ/CommandHqDetail.tsx
@@ -11,6 +11,7 @@ import type { ChatMessage } from '../Chat/types';
import { categoryFromParam, commandHqListPath, commandHqSessionPath } from './command-hq-routes';
import { useCommandHqCategories, useCommandHqCommander, useCommandHqCommanderActions } from './useCommandHq';
import { formatCommanderCost, formatTokens } from './format';
+import { NEW_COMMANDER_GUIDE } from './newCommanderGuide';
// Right panel of the /command-hq workspace. Three states, chosen by the URL alone (no channel — panels
// read the route directly, per `docs/navigation-audit.md`):
@@ -32,6 +33,37 @@ function EmptyState() {
);
}
+/**
+ * The instructions shown in an empty new-commander pane.
+ *
+ * Deliberately plain and deliberately unfinished — see `newCommanderGuide.ts`. A `provisional` section
+ * carries a visible marker so a guide that is still being written cannot be mistaken for one that is done,
+ * which matters because this ships on every deploy whether the copy is ready or not.
+ */
+const NewCommanderGuide = () => (
+
+
+ {NEW_COMMANDER_GUIDE.map((section) => (
+
+
+ {section.title}
+ {section.provisional && (
+
+ draft
+
+ )}
+
+ {section.body.map((paragraph) => (
+
+ {paragraph}
+
+ ))}
+
+ ))}
+
+
+);
+
/**
* A commander started in THIS pane, and it keeps the same live chat for as long as the pane is open.
*
@@ -103,6 +135,9 @@ function NewCommander({
`useEmbeddableChat(params)` builds the manager from these props, and `manager.context` is what the
composer reads to decide whether to offer "exit and hand back, then re-arm". Passing it to the hook
and not to the component left that radio hidden inside a commander — the one place it exists for. */}
+ {/* Before the first message, the pane explains itself. `EmbeddableChat`'s own empty state is "Send a
+ message to start", which is true and tells a first-time user nothing about what to send. */}
+ {chat.messages.length === 0 && }
);
diff --git a/src/workspaces/officerdev/src/apps/CommandHQ/newCommanderGuide.ts b/src/workspaces/officerdev/src/apps/CommandHQ/newCommanderGuide.ts
new file mode 100644
index 00000000..4f8335ef
--- /dev/null
+++ b/src/workspaces/officerdev/src/apps/CommandHQ/newCommanderGuide.ts
@@ -0,0 +1,50 @@
+/*
+ What the pane says before a new commander has been spoken to.
+
+ ── Why this is data, and why it is a skeleton ──
+
+ The creation flow is being rebuilt. Starting a commander currently means knowing to open the background-job
+ dialog and arm a watcher from it, which is not discoverable and reads as configuration when it is really
+ just "talk to it" — so the dialog stops being the way in, and this pane explains the way in instead.
+
+ The copy is NOT written yet, by agreement: the instructions have to describe a flow that does not exist
+ yet, and writing them before the flow is decided produces text that is wrong in a way nobody notices.
+ What is here is the structure plus the parts that are already TRUE regardless of what the flow becomes —
+ what a commander is, and that it begins as an ordinary conversation.
+
+ Sections marked `provisional` render with a visible marker, so a half-written guide cannot ship looking
+ finished. Removing the flag is the last step of writing one, not a formatting choice.
+*/
+
+export type GuideSection = {
+ title: string;
+ /** One paragraph per entry. Kept as an array so a section can grow without touching the renderer. */
+ body: string[];
+ /** True until the copy is settled. Renders a marker; the whole point is that it is visible. */
+ provisional?: boolean;
+};
+
+export const NEW_COMMANDER_GUIDE: GuideSection[] = [
+ {
+ title: 'What a commander is',
+ body: [
+ 'An agent that keeps working when you are not here — it waits for something to happen, acts on it, and reports back.',
+ 'It is an ordinary conversation. You start by telling it what to watch for and what to do about it, in your own words.',
+ ],
+ },
+ {
+ title: 'Starting one',
+ provisional: true,
+ body: [
+ 'Describe the job here, as you would to anybody. Say what it should watch, where, and what to do when it fires.',
+ 'TODO: the concrete steps, once the creation flow is settled. This replaces "open the background-job dialog and arm a watcher", which nobody could be expected to guess.',
+ ],
+ },
+ {
+ title: 'While it runs',
+ provisional: true,
+ body: [
+ 'TODO: what the owner sees — where its cost shows, how to read what its spawned agents are doing, and how to stop it.',
+ ],
+ },
+];