git:20260914.6826737 to git:20260924.49bf924

1 added, 1 removed. Audit A to A.

---
name: dinostack-codex-brief
description: Codex only. Turn exploratory product or engineering intent into a reviewed DinoStack Brief with explicit outcomes, scope, constraints, and QA criteria.
---
<!-- Generated by scripts/codex-skills.py. Do not edit directly. -->
Use this skill only in Codex. In another harness, do not execute its workflow or dispatch
instructions; use that harness’s DinoStack integration.
## Codex resource resolution
Before executing this skill, resolve the physical directory containing this loaded `SKILL.md`
(follow the installed skill-directory symlink) and bind it as `AE_SKILL_ROOT`. Set
`AE_CORE_SKILL_ROOT` to `resources` beneath that physical root and validate its
`.dinostack-skill.json` marker has `magic=DINOSTACK_CODEX_SKILL`, `adapter=codex`,
`name=dinostack-codex`, and `schema_version=1`. Resolve every logical resource through
the adjacent `RESOURCE-MAP.json`; reject missing, escaping, symlink-loop, or wrong-type targets.
Derive `AE_REPO_DIR` from the validated core marker plus its mapped `bin` resource and require the
repository signature (`content/SKILL.md`, `.codex`, and the dispatch helper); never fall back to
the process working directory. Bind `AE_PROJECT_DIR` to the absolute invoked project root before
changing directories (`git rev-parse --show-toplevel` when inside a repository, otherwise the
verified invocation directory). Project `.claude/**`, `.agentic/**`, `.gitignore`, QA, settings,
compression, and migration state resolve only beneath `AE_PROJECT_DIR`, never beneath
`AE_REPO_DIR`. Evaluate
`$AE_REPO_DIR/bin/ds-codex-dispatch runtime-bindings "<absolute-invocation-directory>"`
before any operational step. Require its `AE_REPO_DIR` and `AE_PROJECT_DIR` values to match the
independently validated paths above, then consume the same JSON object to bind
`AE_CODEX_CONFIG_DIR`, `AE_SHARED_CONFIG_DIR`, and `AE_ACTIVATION_CONFIG`; fail closed on any
mismatch. Map canonical filesystem tools to Codex filesystem reads, `rg --files`, `rg`, shell, and
`apply_patch`; ask one bounded direct question only after default derivation.
Derive `AE_SESSION_ID` by passing hook JSON to
`$AE_REPO_DIR/bin/ds-codex-session-id`. Native workflows are invoked with `$` syntax.
Other DinoStack workflows remain manual command resources loaded with
`$AE_REPO_DIR/bin/ds-codex-dispatch command <name>`; do not claim bare slash registration.
Codex `spawn_agent` accepts only `task_name`, `message`, and `fork_turns`. Put Tier and model intent
in the task brief or resolve it through role routing before the spawn; never pass Claude-only spawn
fields. When isolation is required, the conductor creates the worktree manually before spawning.
**Codex spawn contract.** Delegate with `spawn_agent` only. Before any spawn that needs an
isolated checkout, run the following from the invoked project root (`$AE_PROJECT_DIR`):
1. `git fetch origin`.
2. Resolve `BASE_BRANCH` with
`$AE_REPO_DIR/bin/ds-codex-dispatch base-branch "$AE_PROJECT_DIR"`. This applies the
canonical precedence: exactly one dedicated unfenced whole-line `BASE_BRANCH:` declaration in
project `AGENTS.md` (with an optional Markdown list prefix and optional `Declaration:` prefix),
then local `develop`, then local `development`. Multiple matching declarations are rejected as
ambiguous. If none exists, the helper fails closed; ask the operator whether to use `main`
(recommended, falling back to `master`) or establish a develop-based workflow, exactly as
required by the base-branch resolution protocol.
3. Choose a unique branch and absolute worktree path beneath `$AE_PROJECT_DIR/.agentic/worktrees/`.
4. Run `git worktree add "$AE_PROJECT_DIR/.agentic/worktrees/<branch>" -b "<branch>" "origin/$BASE_BRANCH"`.
5. Load the named role instructions with
`$AE_REPO_DIR/bin/ds-codex-dispatch agent <role>`.
6. Call `spawn_agent` with supported inputs (`task_name`, `message`, and `fork_turns`). Begin the
message with `Work only in the pre-created worktree <absolute-path>` and include the loaded role
instructions plus the execution contract. The spawned agent must use shell commands in that
worktree and must not edit the conductor checkout.
Codex spawns are asynchronous. The conductor remains responsive, uses the collaboration status and
wait operations to collect completion, and applies the existing review gates to the returned diff.
Claude hook payload fields and Claude Task behavior do not apply on Codex.
# $dinostack-codex-brief
> Run the Activation preflight from `$AE_CORE_SKILL_ROOT/METHODOLOGY.md` before proceeding. If inactive, no-op and exit.
<!--
Purpose: Interactive planning dialogue that produces a Brief artifact before architect and engineer
are spawned. Translates operator planning-intent into a committed, Skeptic-eligible Brief
at docs/planning/<slug>.md via a structured multi-turn conversation. Synthesizes the
outcome rubric (from product-discovery staged draft or inline elicitation) into the
Brief's Outcome rubric field.
Public API: $dinostack-codex-brief [topic] | $dinostack-codex-brief --from <path>
Invoked explicitly by the operator or auto-triggered by the conductor on
planning-intent signals per Section 1.
Upstream deps: $AE_REPO_DIR/content/references/planning-artifacts.md (Brief template and field guidance,
including Outcome rubric field schema);
$AE_REPO_DIR/content/sections/02-delegation.md (surface-and-proceed protocol);
$AE_REPO_DIR/content/rules/conventions.md (git worktree conventions, base-branch resolution);
$AE_PROJECT_DIR/.agentic/brief-session.json (resume state, includes rubric array);
MEMORY.md (prior-decisions scan, already in context via the `@MEMORY.md` import in CLAUDE.md);
docs/overview/_proposed/outcome-rubric.md (when product-discovery was run first).
Downstream consumers: $AE_REPO_DIR/content/commands/ds-implement-ticket.md Phase 0b (brief_path check);
$AE_REPO_DIR/content/references/planning-artifacts.md §Gate semantics (Skeptic variant selection);
architect agent (receives brief_path in execution contract);
Skeptic (receives operator-confirmed variant from Section 6; evaluates
Outcome rubric field per step 3.5 in skeptic.md).
Failure modes: Brief with empty Verification field is NOT Skeptic-eligible - conductor must
collect a real value before writing to disk. Parse failure on brief-session.json
triggers the corruption branch in Section 2 (no silent ignore). Scope-creep
or whole-pivot detection surfaces as a guardrail (Section 4), not an error.
Performance: Standard. Prior-decisions scan is capped (Section 7). No subagent spawns during
the dialogue phase itself.
-->
Interactive planning dialogue. Produces a Brief at `docs/planning/<slug>.md` via a
structured multi-turn conversation, then hands off to the architect and engineer with
`brief_path` pre-populated in the execution contract.
**Session budget note:** Brief sessions are structured multi-turn conversations that track state in `brief-session.json`. Each gray-area resolution consumes conductor turns. Complex Briefs with many gray areas can drive long sessions that accumulate stale state. The conductor SHOULD recommend `$dinostack-codex-wrap` after resolving 10+ gray areas in a single session, or when the total conductor turn count approaches the soft limit defined in `$AE_REPO_DIR/content/references/subagent-protocol.md` Section 13.
---
## Section 1 - Trigger model
### Auto-invocation on planning-intent signals
The conductor monitors operator messages for planning-intent signals. When detected, it
auto-invokes `$dinostack-codex-brief` using the surface-and-proceed pattern.
**Surface-and-proceed announcement (auto-trigger only):**
> "Starting $dinostack-codex-brief for [topic] - reply STOP to abort or skip the dialogue."
**"One turn" definition:** one operator message and the conductor's immediate response.
STOP must appear in the very next operator message after the conductor's announcement;
otherwise the conductor proceeds.
**Explicit invocation** `$dinostack-codex-brief [topic]` works identically but skips the announcement.
### Planning-intent signals (fire on any of)
- Exploratory framing: "I want to build...", "We should add...", "Let's create...",
"thinking about...", "considering..."
- Multi-step feature descriptions with no specific ticket reference
- Requests for design or plan: "can you plan...", "let's design..."
- Feature names or descriptions spanning more than one sentence with vague outcome language
### Negative-signal suppression list (do NOT fire on any of)
- Single-file questions ("how do I X in this file")
- Debugging questions ("why is this failing")
- Code-review questions ("look at this PR")
- Bug reports ("Y is broken")
- Explicit ticket references ("work on TICKET-123")
- Direct implementation requests with specific scope
Signal must be exploratory framing, not execution. When ambiguous, prefer NOT firing.
### Discovery before brief
When the problem, users, or scope are still fuzzy - or the project has no `docs/overview/vision.md` / `docs/overview/requirements.md` yet - spawn the `product-discovery` agent first. Discovery decides WHAT to build and WHY (the problem, the personas including the counterparty, the market context, the staged vision and requirements); `$dinostack-codex-brief` and the architect decide HOW. Run discovery, let the operator ratify and promote the staged intent layer, then return to `$dinostack-codex-brief` to frame the execution. Skip discovery and go straight to `$dinostack-codex-brief` only when the problem and scope are already clear.
### PRD handoff express path
If the operator passes a PRD document, the conductor skips intent-capture and jumps to
PRD extraction (Section 5). Replace the standard announcement with:
> "Found PRD - extracting Brief fields."
---
## Section 2 - Resume check
On invocation, if `$AE_PROJECT_DIR/.agentic/brief-session.json` exists:
**If `status: interrupted`** (or `dialogue_active` with `updated_at` more than 10 min ago):
> "Interrupted $dinostack-codex-brief session detected for '<slug>'. Last phase: [status], [N] gray areas answered. Resume this session or start fresh? (resume / fresh)"
- On "resume": restore state from file and re-enter dialogue at the last recorded phase.
- On "fresh": delete the file and start from Turn 1.
**Parse-failure branch:** if file is unparseable:
> "Brief session state file is corrupted. Start fresh? (yes/no - if no, please move/delete the file manually and retry)."
- On yes: delete file and start fresh.
- On no: halt.
---
## Section 3 - Dialogue protocol
### Turn 1 - Intent capture
If `$dinostack-codex-brief` received no topic argument, conductor asks:
> "What are you trying to build or solve? One or two sentences is enough to start."
Operator replies.
**Intent-layer read (runs after the reply above, or immediately after a topic argument was given - in EITHER case; this step never gates, delays, or replaces the question above).** If at least one of `docs/overview/vision.md` / `docs/overview/requirements.md` exists, conductor reads whichever exist and derives:
- Candidate Constraints: any requirements.md non-functional requirement or vision.md stated boundary relevant to the operator's stated (or given) task-level intent.
- A Problem-framing note: does the stated intent map to a North Star pillar or a scoped requirement already on file.
This does not ask a further question. It is folded, as a brief same-turn note, into the conductor's next response (the Turn 2 gray-area menu presentation, per the amendment below) - never as a standalone message that waits for a reply. The canonical note wording is defined in the Turn 2 amendment; do not restate it here.
When neither file exists: no note is generated; proceed silently.
**State write (unconditional - fires identically whether or not a topic argument was given, and whether or not the intent-layer files exist):** write `brief-session.json` with `status: intent_captured`, `topic: <the operator's reply, or the topic argument>`, and `intent_layer_derived: {problem, constraints, source}` - using `{problem: null, constraints: null, source: []}` when the intent-layer files are absent. This is one write covering all four branches (topic-given x files-present, topic-given x files-absent, no-topic x files-present, no-topic x files-absent); no branch omits any of the three fields.
Run the prior-decisions scan (Section 7) after intent is captured but before presenting
the gray-area menu.
### Slug derivation
**Slug derivation.** Convert the operator's intent statement to a slug:
1. Take the first 6-8 significant words (skip articles: a, an, the; skip pronouns: I, we, you)
2. Lowercase and join with hyphens
3. Strip non-alphanumeric characters (keep only [a-z0-9-])
4. Cap at 60 characters total (truncate at last full word)
Example: intent "I want to build an interactive planning command" -> slug `build-interactive-planning-command`.
The same slug derivation algorithm applies in `implement-ticket.md` Phase 0b (when deriving slug from ticket title, the ticket-ID prefix is also stripped). For `$dinostack-codex-brief`, no ticket prefix exists - derive directly from intent.
### Turn 2 - Gray area menu
Conductor reads the intent and generates 4-8 SCOPE-SPECIFIC gray areas inline (no
subagent spawn). These must be concrete decisions, not generic checklists.
Examples for "user authentication": session handling, error responses, multi-device
policy, recovery flow.
Examples for "CLI for db backups": output format, flag design, progress reporting,
error recovery.
When `intent_layer_derived.constraints` is non-null: prepend a note before the menu: "Already noted from docs/overview/vision.md / requirements.md: [derived constraint] - flag if it doesn't apply." Do not generate a gray area for a dimension `intent_layer_derived` already answers - this is the mechanism that reduces re-elicitation; it removes candidate gray areas, never the Turn 1 intent question itself. If suppression would take the menu below 4 items, retain the next-best candidate areas to preserve the stated 4-8 floor.
Present as a numbered menu:
> "Here are the areas where scope is still open. Pick the ones you want to talk through
> (e.g. '1, 3, 5'), or 'all' to cover everything, or 'none' to skip to the Brief draft:
> 1. [gray area]
> 2. [gray area]
> ..."
Write `brief-session.json` with `status: menu_presented` and the `gray_areas` array.
### Turn 3...N - Per-area dialogue
One exchange per selected gray area (`selected: true` in the state file):
- Conductor asks one focused question.
- Operator answers.
- Conductor may ask one follow-up if the answer is ambiguous, then moves to the next area.
- Scope-creep guardrail fires if an answer introduces a new major scope element (Section 4).
- Append each answer to `dialogue_log` in the state file.
- Update `gray_areas[i].answered: true` after each exchange.
- Write `status: dialogue_active` throughout.
### Turn N+1 - Brief draft
Conductor synthesizes the Brief from intent + dialogue, formats per the Brief template
in `$AE_REPO_DIR/content/references/planning-artifacts.md` §Brief template, and includes the **Outcome rubric** field:
- **If `docs/overview/_proposed/outcome-rubric.md` exists** (product-discovery ran before $dinostack-codex-brief): copy its lines verbatim into the rubric field and note "copied from discovery draft - confirm or adjust."
- **Otherwise**: prompt the operator inline: "List the 3-6 things that would make this 'done' - one per line, most critical first." For each criterion the operator provides, assign a `verification_type`: `deterministic` if a gate is nameable, `judgment` otherwise. Present the assigned types for confirmation before writing.
When `intent_layer_derived.problem` or `.constraints` is non-null, seed the Problem and Constraints fields from it (merged with anything surfaced in the per-area dialogue) instead of synthesizing those two fields from dialogue alone, and note inline in the draft presentation: "Problem/Constraints derived from docs/overview/vision.md + requirements.md, noted in Turn 2." Success criteria and Non-goals continue to synthesize from dialogue as today.
The outcome rubric is part of the Brief draft and subject to the same iteration rounds (max 3 adjustments). Store the confirmed rubric in `brief-session.json` under the `rubric` array (see Section 8).
Conductor presents the full Brief to the operator:
> "Here's the Brief draft. Review it and say 'looks good' to write it, or tell me what
> to adjust:
>
> # Brief: <feature name>
> ..."
Write `status: draft_presented`.
### Turn N+2 to N+k - Iteration
Operator may request changes. Conductor adjusts. Max 3 adjustment rounds; on the 4th:
> "We've revised several times - do you want to keep discussing or finalize what we have?"
Write `status: iterating` during revision rounds.
### Turn N+k - Write and hand-off
1. Conductor writes Brief to `docs/planning/<slug>.md` per the template.
2. Sets `brief-session.json` `status: complete`, `brief_path`, `brief_source: operator`.
3. Commit:
```bash
git add docs/planning/<slug>.md
git commit -m "docs(brief): add <slug> brief"
```
- 4. If `TRACKER != none` AND `ticket_driven` active (per resolution rule in `$AE_REPO_DIR/content/sections/02-delegation.md` §Ticket-offer gate; mid-session discoveries instead follow `$AE_REPO_DIR/content/references/delegation-detail.md` §Follow-up Ticket Creation Discipline): derive TICKET_TITLE from the Brief's Feature Name, TICKET_BODY from Problem + Success criteria (the ticket's Acceptance Criteria; when Success criteria is empty, write `Acceptance Criteria: not yet defined - <blocking reason>` per `$AE_REPO_DIR/content/references/conventions-detail.md` §Ticket descriptions rather than omitting it), TICKET_TYPE from the Brief type (default `feature`); then:
+ 4. If `TRACKER != none` AND `ticket_driven` active (per resolution rule in `$AE_REPO_DIR/content/sections/02-delegation.md` §Ticket-offer gate; any other ticket needs an explicit operator yes per `$AE_REPO_DIR/content/references/delegation-detail.md` §Follow-up Ticket Creation Discipline): derive TICKET_TITLE from the Brief's Feature Name, TICKET_BODY from Problem + Success criteria (the ticket's Acceptance Criteria; when Success criteria is empty, write `Acceptance Criteria: not yet defined - <blocking reason>` per `$AE_REPO_DIR/content/references/conventions-detail.md` §Ticket descriptions rather than omitting it), TICKET_TYPE from the Brief type (default `feature`); then:
- **`offer` mode:** emit `Creating ticket for this work - reply STOP to skip and proceed ad-hoc.` Wait one turn. If no STOP: invoke the Tracker Create Helper (cross-ref `$AE_REPO_DIR/content/commands/ds-implement-ticket.md` §Tracker Create Helper). If STOP: skip creation, proceed ad-hoc (architect spawn, step 6).
- **`require` mode:** invoke the Tracker Create Helper immediately (no skip path).
- On CREATE_STATUS=created: hand off to `$dinostack-codex-implement-ticket <CREATED_TICKET_ID>` with `brief_path` in the execution contract INSTEAD of spawning the architect directly (skip steps 5-6).
- On CREATE_STATUS=failed: emit the failure line; in `offer` mode proceed ad-hoc (architect spawn, step 6); in `require` mode STOP and wait for operator resolution.
- On CREATE_STATUS=skipped (`offer` mode): emit the skip line and proceed ad-hoc (architect spawn, step 6).
- On CREATE_STATUS=skipped (`require` mode): surface the conflict (`ticket_driven=require but tracker '<type>' has no create integration - proceed ad-hoc this once, or stop?`) and WAIT for operator.
5. When no ticket was created (ad-hoc path only): surface-and-proceed:
> "Brief written to docs/planning/<slug>.md and committed. Spawning architect with
> brief_path - reply STOP to halt or refine the Brief first."
6. If no STOP in one turn: spawn architect with `brief_path` in execution contract.
7. After architect returns: spawn Skeptic using the operator-confirmed variant (Section 6), plus the Global-context input set (`## Global-context inputs` block per `$AE_REPO_DIR/content/references/skeptic-protocol.md` Section 4.5): field 2 (Brief/Plan artifact) is `n/a - Skeptic-on-Brief (Brief is the artifact under review)`; field 4 (per-consumer impact table) is `n/a - Brief tier (per-consumer lives in architect plan path above)`; field 6 (diff under review) leads with the unit's stable key (§4.5) followed by " | " and the paths the Brief proposes to touch, since this is a pre-implementation review and no diff exists yet; field 7 (conductor spawn brief) is `n/a - internal scaffolding artifact (no conductor claim-bearing brief text distinct from the artifact itself)`.
8. PR opens at the end of the full engineer flow (after Skeptic sign-off on engineer
output), NOT after Brief commit.
---
## Section 4 - Scope-creep guardrail and operator pushback
### Standard scope-creep handling
When the conductor identifies a dimension exceeding stated intent, surface it as a
gray area rather than adding it silently:
> "This sounds like it might go beyond [original intent]. I'll add '[new dimension]'
> to the deferred list for now - flag it if it belongs in scope."
Add the item to the `deferred` array with `reason: scope-creep-candidate`.
### Operator pushback ("no, this IS in scope")
> Conductor: "Got it - I'll fold this in."
1. Remove item from `deferred` (set entry `status: withdrawn`).
2. Update gray-area menu: append the new dimension as a fresh entry with `answered: false`.
3. Re-prompt: "New gray area: [new dimension]. Want to address this now or revisit later?"
### Whole-pivot detection
When a new dimension materially changes the original intent:
> "This sounds like a pivot - want to restart the Brief with the new framing?
> (restart / continue with both)"
- On restart: clear `brief-session.json`, re-announce, begin from Turn 1.
- On "continue with both": add both framings to the Problem field and continue the
dialogue.
---
## Section 5 - PRD express-path
**Invocation:** `$dinostack-codex-brief --from <path>` where path is relative or absolute.
### Standard extraction
Scan for headings or labels matching: Problem / Goals / Non-goals / Constraints /
Verification (or equivalents: Objective, Acceptance Criteria, Out of Scope, Success
Metrics, Definition of Done). Map matching content to Brief fields.
Also scan for headings matching: Definition of Done / Acceptance Criteria / Success Metrics / Pass-Fail / Rubric. Extract matching items as outcome rubric candidates - assign `verification_type: deterministic` when the item names a measurable gate, `verification_type: judgment` otherwise. Cap at 6 lines. If none of these headings exist, pre-fill the Outcome rubric field with `[extracted from PRD - review required]` and prompt: "I could not find explicit acceptance criteria in this PRD. List the 3-6 things that would make this 'done', one per line."
### Fallback when no structural signals detected
1. Treat the entire PRD as the Problem field (truncate to 500 words; note remainder as
"see full PRD").
2. Pre-fill Success criteria, Non-goals, and Constraints with
`[extracted from PRD - review required]`.
3. Pre-fill Verification with
`[REQUIRES OPERATOR INPUT - cannot proceed without verification gate]`.
4. Surface to operator:
> "Auto-extraction was minimal - this PRD doesn't have structural headings I can map
> to Brief fields. I've put the full content in Problem; you need to fill in
> Verification before we can proceed (Brief cannot ship without it). Want to discuss
> the gray areas now or just edit the draft?"
**Verification field is always required.** A Brief with `[REQUIRES OPERATOR INPUT]` in
Verification is NOT Skeptic-eligible. The conductor must collect a real Verification
value before writing the Brief to disk.
---
## Section 6 - Skeptic variant selection
Conductor reads `brief-session.json` `brief_source` field.
### When `brief_source: operator` (Brief from $dinostack-codex-brief dialogue)
> "Verify completeness only: all 6 fields present, Verification field is non-empty and
> not 'cannot specify', no Open Questions remaining (a non-empty "Deferred defaults" section
> does not count as unresolved Open Questions - those do not block). The problem framing and success
> criteria have already been operator-confirmed in the $dinostack-codex-brief session - DO NOT relitigate
> framing decisions. Findings are limited to: missing field, empty Verification,
> unresolved Open Questions, or contradictions between Brief fields. Out of scope:
> framing critique, alternative solutions, scope arguments."
### When `brief_source: conductor` (auto-authored at gate, no $dinostack-codex-brief session)
Use the standard "Document synthesis, architecture, and planning" adversarial brief.
Full framing review is in scope.
---
## Section 7 - Prior-decisions scan (capped)
Runs after intent capture, before the gray-area menu.
**MEMORY.md:** already in context (via the `@MEMORY.md` import in the project root `CLAUDE.md`). NO file read.
Scan in-context content for keyword overlap with intent (substring match on
space-separated keywords from the intent statement).
**`docs/planning/`:** Glob `*.md` at top level only (or Bash `find docs/planning -maxdepth 1 -name '*.md'` when Glob is unavailable), NOT subdirectories. Use filenames
only (directory listing). Match by slug-name keyword similarity (substring match).
Read AT MOST the first 20 lines of the top 3 closest-matching files.
If no matches, skip reads entirely.
**Volume cap:** if `docs/planning/` has more than 50 `.md` entries at top level, restrict
to the 10 most recently modified by mtime before keyword matching.
Silent on no match.
---
## Section 8 - State file: `$AE_PROJECT_DIR/.agentic/brief-session.json`
Gitignored under the existing `$AE_PROJECT_DIR/.agentic/` rule. No `$AE_PROJECT_DIR/.gitignore` change needed.
### Schema
```json
{
"schema_version": 1,
"status": "<see enum>",
"topic": "<intent statement>",
"slug": "<kebab-case-feature-name>",
"worktree_path": null,
"brief_path": "<docs/planning/<slug>.md or null>",
"brief_source": "<operator | conductor>",
"created_at": "<ISO8601>",
"updated_at": "<ISO8601>",
"gray_areas": [
{"id": 1, "text": "<text>", "selected": true, "answered": false}
],
"dialogue_log": [
{
"gray_area_id": 1,
"question": "<question text>",
"answer": "<operator answer>",
"followup_question": "<string or null>",
"followup_answer": "<string or null>",
"timestamp": "<ISO8601>"
}
],
"deferred": [
{
"text": "<item>",
"reason": "<scope-creep-candidate | operator-choice>",
"status": "<active | withdrawn>"
}
],
"draft": {
"problem": "<string or null>",
"success_criteria": ["<string>"],
"non_goals": ["<string>"],
"constraints": "<string or null>",
"verification": "<string or null>"
},
"rubric": [
{
"id": 1,
"line": "<one-line observable acceptance criterion>",
"verification_type": "<deterministic | judgment>",
"confirmed": false
}
],
"intent_layer_derived": {
"problem": "<string or null>",
"constraints": "<string or null>",
"source": ["<vision.md and/or requirements.md, whichever were read>"]
}
}
```
### Status enum (exhaustive)
`intent_captured | menu_presented | dialogue_active | draft_presented | iterating | complete | interrupted`
### Field notes
- `slug`: kebab-case slug derived from the operator's intent statement per the slug-derivation
algorithm in Section 3 - Slug derivation. Must match the slug used by `implement-ticket.md`
Phase 0b for the same intent.
- `worktree_path`: reserved for future use; currently null. The conductor works directly on its current branch - no worktree is created by $dinostack-codex-brief.
- `gray_areas[].selected: bool` - true if operator chose this area in the menu-selection
step; false if deferred or skipped. Conductor only walks through areas where
`selected: true`.
- `brief_source` drives Skeptic variant selection per Section 6.
- `deferred[].status: withdrawn` marks items the operator pushed back and folded in scope.
- `intent_layer_derived`: written on EVERY Turn 1 completion, unconditionally, in the same `brief-session.json` write as `status: intent_captured` and `topic` - regardless of whether a topic argument was given and regardless of whether the intent-layer files exist. When at least one of `docs/overview/vision.md` / `docs/overview/requirements.md` exists, it carries the derived `problem`/`constraints`/`source`; otherwise it is written as `{problem: null, constraints: null, source: []}` (never omitted). Persists across an interrupted-session resume (Section 2) the same way `draft` and `rubric` do, since resume restores the full state file verbatim.