hex-discuss — Pre-Plan Discussion Mode
hex-discuss talks a problem through before anything is decided: it elaborates
the ask, argues with the answers, checks disputed facts in the background while
the conversation keeps going, and keeps what was settled in a discussion
artifact. It builds nothing and writes no plan, ADR, or spec — the run ends at
a drain, the explicit handoff that closes the discussion and names the
command to run next.
It is a hex skill, not a fifth orchestrator: no classify.md, no
overlays.md, no tier-*.md, and no tier vocabulary of its own. The
dispatcher/tier-file split is vacuous here, not deviated from — there are no
tier files to dispatch to.
Shared contracts:
protocol.md ·
workers.md ·
models.md ·
memory.md.
If hex-core is not installed: grim add ghcr.io/michael-herwig/arcana/hex-core:latest.
Argument syntax
/hex-discuss <topic | path | slug>. Free text becomes intake slot 1 and is
never re-asked; a path into the resolved discussions home, or the slug of
an existing artifact, resumes that artifact
(The discussion artifact).
Entry and exit
Entered only by explicit user invocation or by this skill's own description
match on a user's discuss request — never self-triggered from another hex
skill's flow (the hex-init precedent). The frontmatter leaves
claude.disable-model-invocation unset: the description match is the entry
path. Entry then resolves the discussion's home and either opens the existing
artifact or writes the stub
(The discussion artifact). Exit is only an explicit
drain (Handoff) or an explicit user abort. There is no third exit:
no turn budget, no idle timeout, no "this looks finished" self-exit. An abort
leaves State: parked, re-enterable later under the same slug.
Conversation
Intake
The opening turn asks once, as one composite ask with three slots: (1) the
problem in the user's own words, not a restatement or a guess; (2) a
source-material inventory — "dump anything": tickets, example apps, references,
code; (3) the outcome shape — plan, ADR, spec, or just clarity. Any subset is
answerable: the run proceeds with what it has and never re-asks a skipped slot.
Slot 3 pre-sets the drain target (Handoff); slot 2 seeds the
artifact's ## Related section and grounds every researcher prompt.
A second composite intake ask is a contract violation. A gap an unanswered slot leaves resurfaces later as a single design question with an attached recommendation under the cadence below — never as a re-ask of the form.
Entry wave
The opening turn is answer-first: substance — engagement with intake slot 1 — is
composed and emitted before anything dispatches; the shared contract reads that inform the
reply gate the dispatch, never the reply itself. With slot 1 present, the wave —
codebase recon plus a prior-art web scan, seeded from that text — fires this same turn,
right after the substance, inside the default 3-concurrent gear, one slot free (degraded:
inline per § Worker coordination); without it (bare invocation or a vague description-match
entry) the intake ask itself is the opening turn's substance, and the wave defers, firing
once when slot 1 lands, seeded from it — slot 1 is never re-asked. Only an
already-dispatched wave is non-repeatable: a resume never re-fires it, but one
parked before slot 1 landed still gets it when slot 1 does; lanes stay available on demand.
Automatic spend never exceeds the default gear and is always announced, anything above it
user-initiated; rule (d)'s blindness binds it. references/research-lanes.md is the lane
catalog's normative home. The mandated one-liners follow as independent lines, never a
block, then one drain-affordance sentence, never repeated — said once at entry: this skill
never offers to end the discussion.
Question cadence
Inventory questions — facts the user simply has, like which service or which branch — batch into one composite ask. Design questions — anything whose answer is a choice — ship in dependency-batched sets of ≤3, each option still carrying its own attached recommendation. Never a numbered list outside that batch shape. More than 3 pending → the 3 highest-priority ship, the rest carry to the next batch. Never spend a question on what the artifact or the repo already answers.
A design question ships as chips — selectable options plus a free-text escape, rendered through the client's native structured-choice prompt where one exists and a numbered list otherwise, a capability and never a named harness tool. An open prose question is the exception and justifies itself — used only where an option set would prejudge the answer.
Where should the session cache live?
1. Redis — recommended: the ops runbook covers it, TTL eviction is free.
2. A Postgres table — one less service to run, but you own the sweeper.
3. Something else (say what).
— checked that: Redis TTL eviction is amortized O(1) [redis.io/docs/expire]
Grill ruleset
Four rules, all four normative — not a menu.
- (a) Rebuttal gate. Categorize every pushback before answering it. New evidence — a benchmark, a constraint, a fact not previously on the table — updates the position, and the update states what changed. Repeated opinion — the same argument again — holds, and restates the evidence the position rests on. Never concede on repetition alone: only a later message adding something new moves the position.
- (b) Anti-theater. Never manufacture an objection to look rigorous. On agreement about a decision-relevant point, name the strongest remaining counter-argument once and move on — neither a second invented objection nor a later re-raise of the same one.
- (c) Scoped elicitation. Pick at most two fitting techniques per thread from premortem, inversion, first-principles, and force-rank, and apply them inline. Never present the catalog. A third technique on the same thread is a contract violation. Force-rank rather than a red-team/blue-team debate.
- (d) Researcher blindness. A research prompt states the question neutrally — the evidence for and against each option on the named axis — and never reveals which side the user or this skill favors, including when the user has already stated a preference. Binds every research prompt this skill sends, the automatic entry wave's two lanes included.
Research
Research runs in the background — no conversational turn waits on it. Spawns are one of three classes — (a) entry recon spawn (automatic, Entry wave), (b) opt-in lane spawn (user-selected, below), (c) disputed-fact spawn (skill-initiated) — of which (a) and (c) fire never on an opinion, and never on a question the repo answers, which is read instead; (b) alone may target a judgment question, user-opted and spend-confirmed.
Default gear: at most 3 concurrent researcher spawns
(workers.md), fast-balanced at every tier
in models.md — no self-escalation, disclosed
like any other (models.md rule 1) — bound by
protocol.md § Worker coordination
— concurrency cap, batching, degraded lines, no exemption.
Lane multi-select replaces the old two-gear offer — no retired vocabulary survives. Once,
immediately after the entry wave dispatches, the turn offers a multi-select over research
lanes, seeded with the default lanes (references/research-lanes.md catalogs them); spawns
run within § Worker coordination's effective concurrency cap, running spend total in the chip
text, hard cap 12 researchers per expansion — demand above 12 truncates to 12, announced
once. Skip → no re-offer until the user asks again — a landed leads: entry only widens
the offerable lane set; chips never re-surface unprompted. A landed result surfaces at the
next turn boundary as a one-line aside, flagged as new, never spliced mid-turn; a result that
changes a live thread feeds the next question; its leads: entries join the offerable lane
set, deduplicated first-seen-wins. A researcher returning nothing useful folds in with no
aside; one failing to return is surfaced once as a one-line transport note — a dead worker
is never normalized into "no result found." Findings longer than a paragraph persist per
lane as research artifacts, each written against the header contract in
hex-init/assets/templates/research.md.
Stop rule
The interview ends when the restate can be filled without a gap — never at a question count, and never at a turn budget. A question answered in a few turns drains inline, deleting the entry stub, so the run nets zero discussion files — the entry wave may already have landed research artifacts before that inline drain fires, and those persist in the shared research home, listed in the terminal report. An inline drain is still gated — it passes the restate-gate like every other drain.
The discussion artifact
Home: the project's documented convention if it names one, else
.agents/discussions/<slug>.md — the resolution order every hex artifact class
uses (memory.md).
Creating that row in hex.md › Pointers is post-gate
(Constraints); one file per discussion, its slug derived from
the topic and stable for the discussion's life. Every write this skill makes —
the artifact to the discussions home above, each per-lane research artifact to
its own research home — holds to the path conditions of
archive.md § Containment:
inside its own resolved home, no .. segment, never absolute. No silent
clobber: entry with a slug already present at State: active or
State: parked resumes that artifact and never overwrites it; a slug
colliding with a drained (handed-off) artifact takes a date suffix instead.
Lazy materialization has one declared exception: entry on a new slug writes a
header-only stub — State: active plus Updated:, nothing else — disclosed
once as the combined — discussion notes: <path> · recon: N dispatched line
(Announce form). Entry
that resumes an existing active or parked artifact opens it and never
re-stubs, but does refresh the header: a fresh Updated: always, plus
State: back to active when resuming from parked. That refresh is a header
update, not a re-stub, and it re-arms the hex-state rule's
no-code-or-config-edits stance for the resumed conversation; an abort later
returns the artifact to parked. Everything below the header stays lazy: a
section appears on its first content — a research result landing, a captured
requirement, or the user saying "capture" — so ## Research appears when the
first result lands, and an empty section is never scaffolded. Section order
is fixed, presence is not, and a small discussion draining inline deletes its
own stub. The section menu is documented in exactly one place, the template
../hex-init/assets/templates/discussion.md;
this file never restates the menu. Fallback where /hex-init never ran and
no template exists: the header contract alone — State: and Updated: on one
line, an optional participants line, nothing else required.
No C-/S- IDs in a discussion artifact — a hard prohibition, not a style
note. Requirements stay provisional prose:
protocol.md § Traceability IDs
makes IDs originate in the spec, and a second origin would collide with the
fold-back join key
archive.md depends on. A
consuming orchestrator assigns IDs; it never inherits them.
Drain-readiness bar, checked at the restate-gate. The
artifact must be self-contained (a fresh session needs no access to the source
conversation), name the files and interfaces it touches, state what is out of
scope, carry unresolved points under ## Open questions, and end with a
## Verification section naming how the eventual work is checked. Every path
it names is repo-root-relative (.agents/adrs/…, hex/hex-core/…). An
artifact failing the bar is not drained with a warning: the gate names the
gap and returns to the conversation until it is closed.
## Open questions are carried, not blocking: they become the receiving
orchestrator's docket, and one left unanswered there is a review finding, not a
discuss defect. Each entry may carry the house marker pair —
[NEEDS CLARIFICATION: <question>] with a Recommended: <answer> — <reason>
line beneath it, the shape hex-init's plan and spec templates already define
— a live question is answered in the room, a marker handed forward to a gate
its asker will not attend.
The restate-gate
The single approval gate, sitting at the exit before any drain: at entry nothing is yet committed, and the irreversible act is handing a downstream orchestrator a mandate. The lane-expansion offer is a spend confirmation, not a second approval gate — there is exactly one approval gate per run, and every drain passes it, inline drains included.
Before any drain, emit a six-part structured restate — Outcome (what will be
built or decided) · User (who it is for) · Why now (the trigger) · Success (how
it is judged) · Constraint (what bounds it) · Out of scope (what it
deliberately is not). Name in the same message what has already been written —
the discussion artifact and every research artifact, by path, plus any
hex.md › Pointers re-point made this run — and what the drain will touch: the
proposed-artifact list, the artifact's own header update, the two hex.md rows
from Constraints, and, for an inline drain, the stub deletion.
A resumed artifact whose Updated: predates this session also gets a one-line
staleness note: recorded decisions may have drifted since, and the receiving
claim diff is the real check. The restate scales: a short inline drain
collapses each part to a clause on one line — no part dropped — but the
separate explicit yes is never skipped.
Then ask for a separate, explicit yes. Answering a clarifying question is never consent, and a soft confirmation is not consent: on "sounds good" or "yeah ok", do not drain — ask for the explicit yes, and name that you are asking for it. The wording is hex's own and varies naturally between discussions; never recite a script. A pattern of instant unqualified yeses may be gently flagged once — never repeated, never a block. A "no" returns to the conversation with the disputed part named, not a re-ask of the whole restate.
Whenever an artifact survives the drain, the drain appends a Ratified: line —
date and drain target — to the header, the durable record of the consent event,
and fills the optional Confidence: line where the provenance exists: who
ratified, and which research vintages back the decisions. An inline drain
leaves no artifact and no Ratified: line, so its outcome can never be
fast-path input to /hex-architect.
Handoff
The handoff contract
applies in substance: every drain ends with the terminal-state report and,
where a next command exists, the Next: line. Its orchestrator-only fields —
classification, tier, overlays — do not apply.
Four drain targets, adding zero new write paths. After the yes:
- → plan —
Next: /hex-plan "<title>, per <artifact path>" - → ADR —
Next: /hex-architect <artifact path> - → spec — emit the plan command above plus a line stating that the spec
is reached by
/hex-review's Fold-Back on the converged plan. This skill never writes a spec and never invokes a fold, soarchive.md's envelope stays the only fold path. - → project context — a durable convention the discussion surfaced is
recorded post-gate as a promotion candidate in
hex.md › Memory(Constraints), where the next/hex-initre-audit picks it up and proposes it against the matching audit item, with consent (audit.md) — the drain setsState: handed-off → context, writesRatified: <date> → context, and states that re-audit as its next step,Next: /hex-init. Notprotocol.md§ Upkeep step's mechanism, which routes a preference tohex.md › Preferences; a project convention belongs in project context, written only by/hex-init. This skill never writes CLAUDE.md or AGENTS.md.
Neither downstream command carries a tier: this skill has none of its own, so
the receiving orchestrator's classifier resolves it, and a tier appears only
when the user named one at the restate. The exception is the → ADR target,
whose fast path refuses the two lowest tiers on arrival — the restate states
the high floor instead of emitting a dead-end command.
Terminal states: parked, or
handed-off → plan | architect | context | dropped — a State: vocabulary
whose single home is the template hex-init/assets/templates/discussion.md,
which defines it while this file only consumes it. dropped is a valid
success — a discussion concluding the thing should not be built is reported
as a successful outcome with the reasoning preserved, never as an abort, and
carries no Next: line: nothing runs next. Every drain closes on:
## Discussion Complete: <topic>
- State: `handed-off → plan | architect | context | dropped`, or `parked`
- Written: <discussion artifact>, <research artifacts>, `hex.md` Memory and
Pointers rows — every path this run touched
- Next: `/hex-plan "<title>, per <path>"` · `/hex-architect <path>` ·
`/hex-init` (→ context); no `Next:` line for `dropped` or `parked`
Announce form
This skill prints no announce block. The contract is a shape, not a whitelist: every disclosure the shared contracts mandate renders as one line, never a block, and none is repeated. Nothing mandatory is dropped — only the block is, and a later mandated disclosure adds a line, never a block. The currently known set, explicitly not closed:
- A research aside when a result lands:
— checked that: <one-line finding> [<source>] — discussion notes: <path> · recon: N dispatched, printed once at entry, the stub write and the wave's dispatch count combined on one line, never two: writes no file and spawns no worker silently.- A lane expansion's batch split, with the cap's source
(
protocol.md§ Worker coordination). Degraded: inline workers — no subagent spawning— research runs inline, one spawn at a time instead of concurrently, and the mode loses its differentiator. Printed once at the first degraded spawn — this mode's only gate is the drain, too late for a spend disclosure — so it lands where rule 1's model line does.- The resolved literal model at the first spawn of a role — the disclosure
models.mdrule 1 mandates, carried under this quiet form, and where amodels.overridesescalation becomes visible. - A
Limits:line, printed once, when ahex.md › Preferenceslimit is in force. - The second degraded axis when it composes:
Degraded: single session model — no per-spawn override; matrix advisory, as its own line, perprotocol.md's one-line-per-degraded-axis rule. - The transport note for a researcher that failed to return, surfaced once.
No phase announcements, no thread-board recital, no resolved-config table — unless the user asks, which is always honored.
Constraints
The write surface is four destinations — the discussion artifact, research
artifacts, hex.md › Memory, and hex.md › Pointers — across five writes, and
when is as binding as what. Pre-gate, only:
- the discussion artifact itself;
- research artifacts in the convention-resolved research home;
- re-pointing a
hex.md › Pointersrow found drifted on consumption —memory.md§ Staleness maintenance, made in the same run and never deferred, and named at the restate alongside the rest of what has already been written.
Post-gate, at the drain alongside the handoff:
- the drain's own header update —
State:to its terminal value, plus theRatified:line and, where the provenance exists, the optionalConfidence:line (the restate-gate); hex.md › Memory— the discussion hand-off record, the artifact index, and promotion candidates from Handoff;hex.md › Pointers— creating the discussions-home row.
These are ordinary upkeep writes deferred past the gate: nothing outside the
discussion's footprint exists before consent. This skill writes no code,
config, plan, ADR, or spec, and never hex.md › Preferences, which is
user-owned.
Undoing an abandoned pre-gate discussion means deleting the discussion file and
the research artifacts it lists under ## Research; the research home is
shared with every other hex skill and is never removed wholesale. The two
hex.md rows exist only after the gate and revert by deleting two lines.
Federation: this skill sits outside the satellite halt's scope
(memory.md) — it
resolves no plan and writes no plan or federation state.
The rule is a hardening, never a precondition: hex-discuss must be complete
and correct with the rule absent, and the rule-less run is this skill's own
degraded mode, reached automatically. A client hosting no ownable rule file
loses persistence convenience, never capability — everything above is
skill-body behavior. After a lapse, recovery is re-reading the discussion
artifact — whose header carries the state, not the stance — plus this file and,
where the rule landed, its hex-state line; or a fresh session, and never
re-invoking this skill, which returns "already loaded" rather than a fresh
copy. No hex file may make a rule's presence a condition of any other
behavior.
Client portability: references/reach.md (C-721).
Research lanes and the researcher spawn contract: references/research-lanes.md (C-701 second split).
$ARGUMENTS