# okstra-brief-gen AI Manual

## Source

- Skill source: [`skills/okstra-brief-gen/SKILL.md`](../../../skills/okstra-brief-gen/SKILL.md)
- brief template: [`templates/reports/brief.template.md`](../../../templates/reports/brief.template.md)
- brief validator: [`validators/validate-brief.py`](../../../validators/validate-brief.py)
- lens enum SSOT: [`scripts/okstra_ctl/improvement_lenses.py`](../../../scripts/okstra_ctl/improvement_lenses.py)

## Purpose

`okstra-brief-gen` produces a task brief to feed into the okstra pipeline. A brief is a pre-discovery artifact. It is not a document that turns requirements into an implementation plan; it is a handoff document that separates the reporter's verbatim material from the AI-verified evidence/interpretation using labels, so the next phase can start without questions.

Output location:

```text
<PROJECT_ROOT>/.okstra/briefs/<task-group>/<brief-id>.md
<PROJECT_ROOT>/.okstra/briefs/<task-group>/sub/.../<brief-id>.md
```

## Three variants

| Variant | Input | Recommended next phase |
|---|---|---|
| Reporter input | files, tickets, URLs, conversation/free text | `requirements-discovery` or `error-analysis` |
| Codebase scan | scan scope, priority lenses, candidate cap, context | `improvement-discovery` |
| Error feedback | a single error cluster from the zip produced by `okstra error-zip` | `error-analysis` |

## Core invariants

1. Source Material is a verbatim-preservation area. Do not paraphrase, summarize, or reorder.
2. The AI's interpretation, file links, terminology mapping, and format conversion all go under `Augmentation` or a `> augmented:` blockquote.
3. An augmentation carries one of four labels: `evidence-link`, `format-conversion`, `terminology-mapping`, `intent-inference`.
4. `intent-inference` is paired with `intent-check:` in `Open Questions`. This relationship is checked by `validators/validate-brief.py`.
5. A `terminology-mapping` augmentation is paired with `terminology:` in `Open Questions` (validator-checked). Exception: the Step 4.5 result markers `applied glossary:` / `skipped glossary:` need no paired row.
6. Questions only the reporter can answer are collected in Step 6.5 and recorded verbatim under `## Reporter Confirmations`.
7. Ticket split/link/order relations go in the structured table of `## Related Task Graph`. Do not infer work order from parent-id alone.
8. Every okstra-owned write stays inside `<PROJECT_ROOT>/.okstra/`. External files are read only when the reporter explicitly cited them as source.
9. Every row in `Open Questions` starts with one of five prefixes: `general:`, `terminology:`, `intent-check:`, `conversion-block:`, `adr-candidate:` (validator-enforced). `adr-candidate:` is only a signal — the decision file is written by `implementation-planning` into `<PROJECT_ROOT>/.okstra/decisions/`.

## Preflight

Run as a single call.

```bash
okstra preflight --runtime claude-code
```

On `Okstra preflight: ready`, carry the fixed `Project root` line. On
`Okstra preflight: failed`, show `Reason` and `Recovery`, then stop. This skill
does not use an `npx` fallback.

## Input collection

### Reporter input

More than one source type is allowed, but each source is stored as a separate block under `Source Material`.

- File: read the entire file and insert it as-is.
- Issue tracker ticket: detect Linear/Jira/GitHub/Notion and use MCP or the `gh` CLI. If no access tool is available, ask the user to paste the body or skip.
- Link URL: fetch it. On failure / login wall / body truncation, ask the user to paste.
- User input: if conversation context is sufficient, use conversation synthesis; if thin, take a single free-text input.

If a ticket has children/sub-tasks, ask once at the parent how to handle the tree.

- Full tree: generate a brief per descendant.
- Parent only: put child keys/URLs in Related Artifacts and leave a `parent-of` edge in `Related Task Graph`.
- Selected: recurse only into the chosen direct-child branch.

During recursion, manage the visited set as `<tracker>:<ticket-id>`, and on re-run reseed from the existing brief frontmatter's `ticket-id` + `source-type`.
When Full tree or Selected produces multiple briefs, copy the same `Related Task Graph` into every generated brief. That way, even if only one child brief is passed to a downstream phase, the split topology, predecessor/successor relations, and de-duplication signals are preserved.

`Related Task Graph` table schema:

| Column | Meaning |
|---|---|
| From | task key, brief id, tracker id, or URL |
| Relation | `parent-of`, `child-of`, `depends-on`, `blocks`, `blocked-by`, `follow-up-of`, `split-from`, `duplicates`, `related-to` |
| To | task key, brief id, tracker id, or URL |
| Direction | `directed` or `undirected` |
| Source | tracker linked issue, task-list checkbox, reporter statement, manual split, prior okstra task |
| Impact | meaning the downstream phase must preserve |

`depends-on`, `blocks`, parent/child, follow-up, and split relations are `directed`. `duplicates` and `related-to` are `undirected`. Do not create a relation with no source.

### Codebase scan

Collected values:

- `scan_scope`: a list of real paths inside the project.
- `priority_lenses`: 1–4 of the `LENSES` enum.
- `out_of_scope`: optional.
- `candidate_cap`: 1–12, default 8.
- context, desired outcome, constraints.

Verify path existence, the lens enum subset, and the candidate-cap range before writing. Final validation is done by `validate-brief.py`, which checks `scope: codebase`, `Scan Scope`, and `Priority Lenses`.

### Error feedback

The input is the zip produced by `okstra error-zip --out <path>`.

Processing:

1. Confirm the zip contains `report.md` and `errors/anonymized.jsonl`.
2. Pick exactly one cluster from the frequent-cluster table.
3. Move only the chosen cluster's anonymized records into Source Material.
4. Do not mix different errorTypes into one brief.
5. Set the next-step guidance to `error-analysis`.

## task-group and filename

For task-group, show existing-group recommendations first. Call `okstra task-list --text`, read the distinct fixed `Task group` values in `Updated at` order, and offer the 2 most recent + enter-directly. If `Status` is `error`, report `Failure stage` and `Failure reason`, then stop. If `Task count` is `0`, ask for free text. In tracker recursion, task-group must be obtained before building any child path.

File path rule:

```text
depth 0: .okstra/briefs/<task-group>/<ticket-id>-<file-title>.md
depth 1: .okstra/briefs/<task-group>/sub/<ticket-id>-<file-title>.md
depth N: .okstra/briefs/<task-group>/<sub/ repeated N>/<ticket-id>-<file-title>.md
```

The frontmatter's `depth` must equal the number of `sub/` segments in the path. The validator checks this.

On collision, the default is Skip. You may offer Append suffix or Overwrite. Do not silently perform a bulk overwrite in tracker multi-generation.

## Domain alignment

First look at okstra's internal memory.

- `<PROJECT_ROOT>/.okstra/glossary.md`
- `<PROJECT_ROOT>/.okstra/decisions/`
- the related task's `history/fix-cycles.jsonl`

Read external domain docs only when the reporter explicitly cited them as source material. Record conflicting/ambiguous terms under `Augmentation > Domain alignment` with `terminology-mapping`, and put a `terminology:` row in `Open Questions`.

When a file path or symbol is mentioned, find the actual in-repo reference with `Read`/`Grep` and record it as `evidence-link`. If it cannot be mapped, do not guess — leave a `conversion-block:` row.

## Sharpening pass

Do not run a full interview. Ask only about gaps that source and codebase cannot fill.

Default budget:

- at most 1 question per section the source skill designates as fill-in.
- at most 2 questions for terminology/fuzzy disambiguation.
- at most 6 questions overall.
- codebase-scan up to 8 questions.

Prefer codebase-first checks over questions. Put remaining gaps in `_(none)_` or `Open Questions`.

## template writing rules

The template `templates/reports/brief.template.md` is the SSOT. Follow the section order, frontmatter keys, top blockquote shape, and HTML comment guidance.

Reporter input and Error feedback:

- keep `## Source Material`.
- keep `## Problem / Symptom`.
- omit `## Scan Scope`, `## Priority Lenses`.

Codebase scan:

- `scope: codebase` in frontmatter.
- omit `## Source Material`, `## Problem / Symptom`.
- keep `## Scan Scope`, `## Priority Lenses`.

Do not fabricate empty sections. When there is no value, use `_(none)_`.

## frontmatter key

Every brief carries the following keys. The key set is checked by `validate-brief.py`.

- `type`
- `brief-id`
- `parent-id`
- `ticket-id`
- `source-type`
- `task-group`
- `depth`
- `created`
- `generator`
- `reporter-confirmations`

`brief-id` must equal the filename stem. At depth 0 the `parent-id` is `self`; a descendant's `parent-id` is its direct parent's `brief-id`.

## Recommended next phase

Write it into the `Recommended next phase:` of the brief body's top blockquote.

- observable error, repro, stack trace, error-zip record: `error-analysis`
- a requirement with ambiguity or large Open Questions: `requirements-discovery`
- `scope: codebase`: `improvement-discovery`
- if ambiguous: `requirements-discovery`

Do not auto-start `okstra-run`.

## Reporter Confirmations

Collect the rows in `Open Questions` that only the reporter can answer.

- `intent-check:`
- `conversion-block:`

If a `[CONFIRMED <date> → RC-N]` marker already exists, exclude it from pending. Ask the user whether to answer now; if they answer, record it verbatim under `## Reporter Confirmations`. Do not delete the row — attach a marker.

At most 12 questions per run. If pending exceeds 12, ask only the top 12 in `conversion-block:` → `intent-check:` order, leave the rest as `partial`, then tell the user which rows remain.

Status values:

- `complete`: all pending reporter-only rows are answered. The validator checks that every `intent-check:`/`conversion-block:` row has a `[CONFIRMED …]` marker.
- `partial`: only some are answered. The validator checks that at least one row has a `[CONFIRMED …]` marker (if nothing was received, `skipped`).
- `skipped`: the user chose to defer to a downstream phase.
- `pending`: treated as a pre-handoff state; do not proceed.

## Validation

After writing, run the validator before emitting the handoff message.

Installed copy:

```bash
~/.okstra/lib/validators/validate-brief.sh "<PROJECT_ROOT>/.okstra/briefs" --briefs-root "<PROJECT_ROOT>/.okstra/briefs"
```

repo checkout:

```bash
validators/validate-brief.sh "<PROJECT_ROOT>/.okstra/briefs" --briefs-root "<PROJECT_ROOT>/.okstra/briefs"
```

On failure, fix the cited brief and re-run. Fall back to a manual checklist only when the validator is absent.
When a `Related Task Graph` is present, the validator also checks the table header, relation enum, direction enum, and directed/undirected mismatch.

## Completion message

Single brief:

```text
brief saved: <abs-path>
next: /okstra-run  (recommended task-type: <phase>)
```

Multi-brief:

```text
briefs saved (N):
  - <abs>/<task-group>/<brief>.md (depth 0, parent, recommended: <phase>)
  - <abs>/<task-group>/sub/<brief>.md (depth 1, child, recommended: <phase>)
next: /okstra-run
```

Before the hand-off block, once per task-group (Step 7a): if `<PROJECT_ROOT>/.okstra/briefs/<task-group>/group-context.md` is absent, ask whether to create the skeleton (`okstra group-context init --project-root <PROJECT_ROOT> --task-group <task-group>`; recommended for a new group) or skip. Never fill it from the tickets. When created, add `group context skeleton: <abs>/<task-group>/group-context.md   (fill before /okstra-run)` to the block — preparation refuses the group's tasks while a `<...>` placeholder line remains. The file's trailing `## Task Memory` region is okstra's (rewritten by `report-finalize` with the group's start order and each task's latest conclusion); `init` inserts the human sections above an existing region. Brief ordinals (`<TICKET>-<n>-<slug>`) are the start order okstra reads; `Related Task Graph` edges are quoted beside it as `waits for`.

## Forbidden patterns

- Summarizing or tidying Source Material before inserting it.
- Guessing tracker/URL content without tool verification.
- Writing unlabelled augmentation.
- Leaving `intent-inference` without `intent-check:`.
- Writing a decision file into external docs/ADR. okstra decisions belong only in `<PROJECT_ROOT>/.okstra/decisions/`.
- Silently overwriting an entire child tree.
- Auto-starting `okstra-run` right after brief generation.
