okstra 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.kr.md +15 -0
- package/README.md +15 -0
- package/docs/kr/architecture.md +2 -6
- package/docs/kr/cli.md +40 -6
- package/docs/kr/performance-improvement-plan-v2.md +23 -0
- package/docs/kr/performance-improvement-plan.md +22 -0
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +4 -3
- package/runtime/agents/workers/codex-worker.md +4 -3
- package/runtime/agents/workers/gemini-worker.md +4 -3
- package/runtime/agents/workers/report-writer-worker.md +7 -2
- package/runtime/bin/okstra.sh +0 -1
- package/runtime/prompts/launch.template.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +36 -4
- package/runtime/prompts/profiles/error-analysis.md +12 -0
- package/runtime/prompts/profiles/implementation-planning.md +20 -0
- package/runtime/prompts/profiles/requirements-discovery.md +20 -0
- package/runtime/python/lib/okstra/cli.sh +1 -7
- package/runtime/python/lib/okstra/globals.sh +0 -1
- package/runtime/python/lib/okstra/usage.sh +1 -4
- package/runtime/python/okstra_ctl/render.py +3 -0
- package/runtime/python/okstra_ctl/run.py +0 -6
- package/runtime/python/okstra_ctl/run_context.py +1 -1
- package/runtime/python/okstra_ctl/wizard.py +25 -2
- package/runtime/python/okstra_token_usage/blocks.py +5 -1
- package/runtime/python/okstra_token_usage/claude.py +16 -1
- package/runtime/python/okstra_token_usage/cli.py +9 -2
- package/runtime/python/okstra_token_usage/collect.py +17 -3
- package/runtime/python/okstra_token_usage/pricing.py +159 -24
- package/runtime/python/okstra_token_usage/report.py +32 -3
- package/runtime/skills/okstra-brief/SKILL.md +532 -65
- package/runtime/skills/okstra-context-loader/SKILL.md +25 -11
- package/runtime/skills/okstra-convergence/SKILL.md +38 -14
- package/runtime/skills/okstra-history/SKILL.md +68 -37
- package/runtime/skills/okstra-logs/SKILL.md +26 -4
- package/runtime/skills/okstra-report-finder/SKILL.md +49 -22
- package/runtime/skills/okstra-report-writer/SKILL.md +62 -65
- package/runtime/skills/okstra-run/SKILL.md +35 -34
- package/runtime/skills/okstra-schedule/SKILL.md +51 -20
- package/runtime/skills/okstra-setup/SKILL.md +31 -12
- package/runtime/skills/okstra-status/SKILL.md +20 -8
- package/runtime/skills/okstra-team-contract/SKILL.md +41 -25
- package/runtime/skills/okstra-time-summary/SKILL.md +53 -16
- package/runtime/templates/reports/final-report.template.md +227 -207
- package/runtime/templates/reports/settings.template.json +7 -4
- package/runtime/validators/lib/fixtures.sh +47 -2
- package/runtime/validators/lib/validate-assets.sh +50 -24
- package/runtime/validators/validate-brief.py +385 -0
- package/runtime/validators/validate-brief.sh +35 -0
- package/runtime/validators/validate-run.py +313 -1
- package/runtime/validators/validate-workflow.sh +7 -33
|
@@ -9,11 +9,34 @@ Generate a single `task brief` markdown file under the okstra project domain
|
|
|
9
9
|
(`.project-docs/okstra/briefs/<task-group>/<task-id>.md`) so it can be fed to
|
|
10
10
|
[`okstra-run`](../okstra-run/SKILL.md) as `--task-brief`.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
`
|
|
16
|
-
with
|
|
12
|
+
**Purpose — pre-discovery artifact.** A brief is the **pre-discovery** stage
|
|
13
|
+
of an okstra task: it absorbs domain alignment, codebase evidence
|
|
14
|
+
collection, and reporter intent capture so that the downstream expert
|
|
15
|
+
phases (`requirements-discovery` / `error-analysis` /
|
|
16
|
+
`implementation-planning`) can run with **zero fill-in questions** to the
|
|
17
|
+
operator. A brief is written from a report by a domain reporter (PM, CS,
|
|
18
|
+
ops, QA, end-user, …) **or** by a developer themselves — the input
|
|
19
|
+
provenance does not change the output contract.
|
|
20
|
+
|
|
21
|
+
This is a **labelled-handoff** to the next phase, built on two
|
|
22
|
+
non-negotiables:
|
|
23
|
+
|
|
24
|
+
- **Verbatim-preserving capture** — the reporter's words are kept
|
|
25
|
+
byte-for-byte under `Source Material`. Format-only transformations
|
|
26
|
+
(e.g. Jira ADF → Markdown) and codebase cross-references are mechanical
|
|
27
|
+
and reversible; they are recorded with the `format-conversion` and
|
|
28
|
+
`evidence-link` Augmentation labels.
|
|
29
|
+
- **Labelled interpretation** — anywhere the skill resolves a reporter
|
|
30
|
+
word to a project-canonical term or infers reporter meaning that was
|
|
31
|
+
not literally stated, the addition lives in `Augmentation` with the
|
|
32
|
+
`terminology-mapping` or `intent-inference` label. Unlabelled
|
|
33
|
+
augmentation is forbidden — the label is what makes the interpretation
|
|
34
|
+
auditable and (for `intent-inference`) verifiable against the reporter.
|
|
35
|
+
|
|
36
|
+
A brief still does NOT write a PRD, decompose work into vertical slices,
|
|
37
|
+
or decide modules. Those belong to later okstra phases
|
|
38
|
+
(`requirements-discovery`, `implementation-planning`) which use
|
|
39
|
+
cross-verification and would conflict with anything decided here.
|
|
17
40
|
|
|
18
41
|
## Intended chain
|
|
19
42
|
|
|
@@ -37,11 +60,33 @@ okstra-brief
|
|
|
37
60
|
## When NOT to use
|
|
38
61
|
|
|
39
62
|
- The user already has a brief file at a known path → skip to `okstra-run`.
|
|
40
|
-
- The user wants
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
- The user wants to split work into issues
|
|
44
|
-
|
|
63
|
+
- The user wants a full PRD with user stories and implementation decisions
|
|
64
|
+
— that's beyond a brief; okstra phases generate the equivalent artifacts
|
|
65
|
+
with cross-verification.
|
|
66
|
+
- The user wants to split work into issues — within okstra that's the job
|
|
67
|
+
of `implementation-planning`.
|
|
68
|
+
|
|
69
|
+
## Artifact-home rule (okstra-wide)
|
|
70
|
+
|
|
71
|
+
**All okstra-generated artifacts live under `<PROJECT_ROOT>/.project-docs/okstra/`.**
|
|
72
|
+
This includes briefs, run manifests, reports, worker results, status,
|
|
73
|
+
sessions, and any other run output. okstra itself never writes to `.scratch/`
|
|
74
|
+
or other project paths.
|
|
75
|
+
|
|
76
|
+
All writes by this skill stay inside `.project-docs/okstra/`. When domain
|
|
77
|
+
alignment (Step 3b / Step 4.5) yields a glossary change that the user
|
|
78
|
+
approves inline, the change is written to:
|
|
79
|
+
|
|
80
|
+
- `<PROJECT_ROOT>/.project-docs/okstra/glossary.md` — okstra's internal
|
|
81
|
+
glossary. Created if absent; appended to a `## Glossary` section
|
|
82
|
+
otherwise.
|
|
83
|
+
|
|
84
|
+
External `<PROJECT_ROOT>/CONTEXT.md` / `<PROJECT_ROOT>/CONTEXT-MAP.md` /
|
|
85
|
+
`<PROJECT_ROOT>/docs/adr/` are read-only references; this skill never
|
|
86
|
+
writes to them. Decision files (when raised by `implementation-planning`)
|
|
87
|
+
also live inside okstra's subtree at
|
|
88
|
+
`<PROJECT_ROOT>/.project-docs/okstra/decisions/<NNNN>-<slug>.md`, never
|
|
89
|
+
at external `docs/adr/`.
|
|
45
90
|
|
|
46
91
|
## Authority files
|
|
47
92
|
|
|
@@ -53,9 +98,12 @@ okstra-brief
|
|
|
53
98
|
(tracker child ticket; at depth N, `sub/` is nested N times) — output
|
|
54
99
|
location for this skill. `<ticket-id>` is the raw issue-id when the source
|
|
55
100
|
is a tracker, otherwise free-text supplied by the user. `<file-title>` is
|
|
56
|
-
auto-slugified from the tracker title, otherwise from user input.
|
|
57
|
-
|
|
58
|
-
|
|
101
|
+
auto-slugified from the tracker title, otherwise from user input.
|
|
102
|
+
- okstra-internal glossary (write target of Step 4.5):
|
|
103
|
+
`<PROJECT_ROOT>/.project-docs/okstra/glossary.md`. Created if absent.
|
|
104
|
+
- okstra-internal decisions (write target of `implementation-planning`
|
|
105
|
+
via `implementation`):
|
|
106
|
+
`<PROJECT_ROOT>/.project-docs/okstra/decisions/<NNNN>-<slug>.md`.
|
|
59
107
|
|
|
60
108
|
## Step 0: Resolve project root
|
|
61
109
|
|
|
@@ -65,6 +113,11 @@ Reuse the same disk-only resolution rule as `okstra-run`:
|
|
|
65
113
|
if command -v okstra >/dev/null 2>&1; then
|
|
66
114
|
OKSTRA_CMD="okstra"
|
|
67
115
|
else
|
|
116
|
+
# `~/.okstra/bin/okstra.sh` exists on every installed machine but it is
|
|
117
|
+
# the bash run-wrapper, NOT the Node CLI — it does not implement
|
|
118
|
+
# `check-project`. Do not branch into it as a fallback. Go straight to
|
|
119
|
+
# `npx` so the user always reaches a working `check-project` even when
|
|
120
|
+
# the Node CLI is off-$PATH.
|
|
68
121
|
OKSTRA_CMD="npx -y okstra@latest"
|
|
69
122
|
fi
|
|
70
123
|
$OKSTRA_CMD check-project --cwd "$(pwd)"
|
|
@@ -104,6 +157,15 @@ in Source Material.
|
|
|
104
157
|
|
|
105
158
|
Order of operations:
|
|
106
159
|
|
|
160
|
+
0. **Task-group precondition (REQUIRED before any recursion)** — if the
|
|
161
|
+
tracker fetch may yield child tickets (which is always possible until the
|
|
162
|
+
first fetch proves otherwise), acquire `task_group` first by running Step
|
|
163
|
+
2a now. Step 2a is otherwise re-entered later for non-tracker sources;
|
|
164
|
+
when reached again it MUST reuse the value collected here without asking
|
|
165
|
+
again. Rationale: the recursion in sub-step 6 records descendant brief
|
|
166
|
+
paths under `<task-group>/sub.../`, and those paths cannot be formed
|
|
167
|
+
until `task_group` is known. Without this preflight the recursive walk
|
|
168
|
+
would either stall mid-collection or invent a placeholder group.
|
|
107
169
|
1. `AskUserQuestion` (free text):
|
|
108
170
|
`"Ticket key or URL (e.g. LIN-1234, PROJ-42, https://linear.app/..., https://your.atlassian.net/browse/...)"` →
|
|
109
171
|
`ticket_ref`.
|
|
@@ -140,26 +202,54 @@ Order of operations:
|
|
|
140
202
|
- Look at child references in the fetched ticket response:
|
|
141
203
|
- Linear: `children` / `subIssues` field
|
|
142
204
|
- Jira: `subtasks` (or `issuelinks` with the `is parent of` relation)
|
|
143
|
-
- GitHub:
|
|
144
|
-
|
|
205
|
+
- GitHub: `gh issue view --json title,body,comments,labels,state` only
|
|
206
|
+
returns the issue body and comments — child relations are NOT in that
|
|
207
|
+
JSON. Resolve children via two paths:
|
|
208
|
+
1. **task-list parsing** — scan the fetched body and comments for
|
|
209
|
+
markdown task-list checkboxes referencing other issues
|
|
210
|
+
(`- [ ] #NNN`, `- [x] owner/repo#NNN`, `- [ ] https://github.com/...`).
|
|
211
|
+
Capture each as a child candidate.
|
|
212
|
+
2. **tracked / sub-issue GraphQL** — for GitHub Projects v2
|
|
213
|
+
"tracked issues" / sub-issue relations, the REST `gh issue view`
|
|
214
|
+
response does NOT carry them. Query GraphQL explicitly, e.g.
|
|
215
|
+
`gh api graphql -f query='query($o:String!,$r:String!,$n:Int!){repository(owner:$o,name:$r){issue(number:$n){trackedIssues(first:50){nodes{number repository{nameWithOwner}}} subIssues:trackedInIssues(first:50){nodes{number repository{nameWithOwner}}}}}}' -f o=<owner> -f r=<repo> -F n=<num>`.
|
|
216
|
+
If the GraphQL request fails (auth scope missing, feature
|
|
217
|
+
unavailable on this repo, network error), **do NOT silently
|
|
218
|
+
continue with full recursion**. Disable the "Generate the full
|
|
219
|
+
tree recursively" option for this branch, default to
|
|
220
|
+
`Parent only; list children in Related Artifacts`, and surface the
|
|
221
|
+
GraphQL failure to the user in one line so they can decide whether
|
|
222
|
+
to paste child bodies manually.
|
|
145
223
|
- Notion: child pages / sub-pages
|
|
146
224
|
- If there is **one or more** child, ask **once at the top parent**:
|
|
147
225
|
- `AskUserQuestion` (single-select)
|
|
148
226
|
- **Label**: `"This ticket has sub-tickets. How should the child tree be handled?"`
|
|
149
227
|
- **Options**:
|
|
150
|
-
1. `
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
3. `Generate selected children only` — multi-select the direct
|
|
157
|
-
children; for each chosen child, apply option-1 policy
|
|
158
|
-
recursively to that branch.
|
|
228
|
+
1. `Full tree` (recommended) — walk children, grandchildren, …
|
|
229
|
+
via BFS/DFS and emit one brief per node.
|
|
230
|
+
2. `Parent only` — single brief. Children are not fetched; their
|
|
231
|
+
keys/URLs are recorded under Related Artifacts.
|
|
232
|
+
3. `Selected` — multi-select the direct children; for each chosen
|
|
233
|
+
child, apply option-1 policy recursively to that branch.
|
|
159
234
|
- For options 1 / 3, **recurse into Step 1b sub-steps 3–5** for every
|
|
160
235
|
descendant. No depth limit. Maintain a visited set of
|
|
161
236
|
`<tracker>:<ticket-id>` to prevent cycles; on revisit, do not emit a
|
|
162
237
|
new brief — only add a link back to the existing brief.
|
|
238
|
+
- **Visited-set across re-runs (rebuild from disk)** — the in-memory
|
|
239
|
+
visited set is per-run and disappears between invocations. When this
|
|
240
|
+
skill runs again over a tree that already has briefs on disk, it MUST
|
|
241
|
+
reseed the visited set by scanning
|
|
242
|
+
`<PROJECT_ROOT>/.project-docs/okstra/briefs/<task-group>/` recursively
|
|
243
|
+
and reading each brief's frontmatter `ticket-id` + `source-type`.
|
|
244
|
+
Reseed precedence:
|
|
245
|
+
1. On-disk frontmatter (`ticket-id` ≠ "") populates visited entries
|
|
246
|
+
as `<source-type>:<ticket-id>` — these win.
|
|
247
|
+
2. Step 2c collision policy (`Skip` / `Append timestamp` /
|
|
248
|
+
`Overwrite`) applies to any node whose path is already taken.
|
|
249
|
+
3. The fresh in-memory walk fills any gaps for tickets not yet on
|
|
250
|
+
disk.
|
|
251
|
+
A ticket present on disk is NOT refetched unless the user explicitly
|
|
252
|
+
answers `Overwrite` for that path.
|
|
163
253
|
- Each descendant's brief file at depth N is created under
|
|
164
254
|
`<task-group>/<sub/ nested N times>/<ticket-id>-<file-title>.md` per
|
|
165
255
|
Step 2b.
|
|
@@ -181,20 +271,21 @@ Order of operations:
|
|
|
181
271
|
3. On fetch failure or auth required (login wall, intranet-only, etc.):
|
|
182
272
|
- Ask the user via `AskUserQuestion` to paste the body.
|
|
183
273
|
- Never invent URL content.
|
|
184
|
-
4. Preserve the
|
|
185
|
-
in Source Material.
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
274
|
+
4. Preserve the fetched content (title + body + quotes/examples) **verbatim**
|
|
275
|
+
in Source Material. Do not excerpt or summarize long pages to fit a line
|
|
276
|
+
budget. If the fetch tool returns truncated content or cannot expose the
|
|
277
|
+
full body, ask the user to paste/provide the missing body before writing
|
|
278
|
+
the brief, or record the fetched text exactly and add a
|
|
279
|
+
`conversion-block:` row that names the missing portion.
|
|
189
280
|
|
|
190
281
|
### 1d. `User input`
|
|
191
282
|
|
|
192
283
|
Two sub-modes combined under one option.
|
|
193
284
|
|
|
194
285
|
- **Conversation synthesis**: do not re-interview. Synthesize from the
|
|
195
|
-
current conversation (
|
|
196
|
-
|
|
197
|
-
|
|
286
|
+
current conversation ("synthesize, don't interview"). Label Source
|
|
287
|
+
Material as `conversation synthesis` and quote key utterances verbatim
|
|
288
|
+
wherever possible.
|
|
198
289
|
- **Inline input**: if conversation context is empty or thin, take one
|
|
199
290
|
free-text `AskUserQuestion`. The received text is preserved in Source
|
|
200
291
|
Material without changing a character.
|
|
@@ -213,6 +304,9 @@ Material.
|
|
|
213
304
|
Slug rule: same as `okstra-run` Step 3 — slugify, must have at least one
|
|
214
305
|
alphanumeric character.
|
|
215
306
|
|
|
307
|
+
If `task_group` was already collected by Step 1b sub-step 0 (tracker
|
|
308
|
+
preflight), reuse that value silently — do NOT ask again.
|
|
309
|
+
|
|
216
310
|
### 2b. Filename per source type
|
|
217
311
|
|
|
218
312
|
Final brief path rule (fixed; one extra `sub/` per depth):
|
|
@@ -242,13 +336,16 @@ relations are also tracked via the brief's `parent-id` frontmatter
|
|
|
242
336
|
- `"Ticket / identifier (e.g. dev-9043, INV-1234, login-error)"` →
|
|
243
337
|
`ticket_id`
|
|
244
338
|
|
|
245
|
-
`<file-title>` resolution
|
|
339
|
+
`<file-title>` resolution (filename slug only — the verbatim rule applies
|
|
340
|
+
to Source Material body, not to the filename):
|
|
246
341
|
|
|
247
342
|
- **Issue-tracker sources**: auto-generated from the ticket title / summary —
|
|
248
343
|
do not ask the user.
|
|
249
344
|
1. Keep alphanumerics, spaces, Hangul; drop everything else
|
|
250
345
|
2. Replace spaces with `-`
|
|
251
|
-
3. Lowercase (Hangul untouched)
|
|
346
|
+
3. Lowercase (Hangul untouched) — **filename normalization only**.
|
|
347
|
+
The Source Material section MUST preserve the original title's case
|
|
348
|
+
byte-for-byte; lowercase applies strictly to the on-disk filename.
|
|
252
349
|
4. Cut to 60 chars at a word boundary (hard-cut at 60 if no boundary)
|
|
253
350
|
5. Trim leading/trailing `-`
|
|
254
351
|
- Example: Linear `LIN-1234 "Fix flaky login retry on 5xx"` →
|
|
@@ -263,44 +360,168 @@ alphanumeric character after slugification. Apply Step 2c on collision.
|
|
|
263
360
|
|
|
264
361
|
### 2c. Collision handling
|
|
265
362
|
|
|
266
|
-
If a brief file already exists, `AskUserQuestion` with (`Skip
|
|
267
|
-
`Append
|
|
268
|
-
|
|
363
|
+
If a brief file already exists, `AskUserQuestion` with (`Skip` /
|
|
364
|
+
`Append suffix` / `Overwrite`). Default recommendation: `Skip` —
|
|
365
|
+
protects briefs the user has already edited. `Append suffix` adds a
|
|
366
|
+
timestamp suffix to the filename stem.
|
|
269
367
|
|
|
270
368
|
When multiple collisions occur in tracker multi-generation mode:
|
|
271
369
|
|
|
272
370
|
- First echo the colliding file list to the user.
|
|
273
371
|
- Ask **once** with `AskUserQuestion` for a bulk policy.
|
|
274
372
|
- **Even when `Overwrite` is selected, confirm one more time for each
|
|
275
|
-
colliding file**, or warn that downgrading to `Append
|
|
276
|
-
is safer. Silent bulk overwrite is forbidden.
|
|
277
|
-
|
|
278
|
-
## Step 3: Light context scan (optional but recommended)
|
|
373
|
+
colliding file**, or warn that downgrading to `Append suffix` is safer. Silent bulk overwrite is forbidden.
|
|
279
374
|
|
|
280
|
-
|
|
375
|
+
## Step 3: Domain alignment scan (recommended)
|
|
281
376
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
377
|
+
Always check whether the project carries a domain context, then compare the
|
|
378
|
+
Source Material's terminology against it. This step exists to *surface*
|
|
379
|
+
mismatches — it never edits user-owned domain docs and never rewrites Source
|
|
380
|
+
Material.
|
|
285
381
|
|
|
286
|
-
|
|
382
|
+
### 3a. Locate domain assets
|
|
383
|
+
|
|
384
|
+
Read in this order — absent files are the normal state; skip silently and
|
|
385
|
+
never error:
|
|
386
|
+
|
|
387
|
+
1. **okstra-internal (authoritative)** — always check first:
|
|
388
|
+
- `<PROJECT_ROOT>/.project-docs/okstra/glossary.md` if present
|
|
389
|
+
- `<PROJECT_ROOT>/.project-docs/okstra/decisions/` titles if present
|
|
390
|
+
2. **External (supplementary read-only reference)** — read if present:
|
|
391
|
+
- `<PROJECT_ROOT>/CONTEXT.md` (or `CONTEXT-MAP.md` → per-context
|
|
392
|
+
`CONTEXT.md`)
|
|
393
|
+
- `<PROJECT_ROOT>/docs/adr/` titles
|
|
394
|
+
- `<PROJECT_ROOT>/.scratch/CONTEXT.md` (output of external skills like
|
|
395
|
+
grill-with-docs, if any)
|
|
396
|
+
|
|
397
|
+
If none of these exist, skip 3b/3c silently.
|
|
398
|
+
|
|
399
|
+
### 3b. Term comparison
|
|
400
|
+
|
|
401
|
+
For each domain-significant noun in Source Material, classify:
|
|
402
|
+
|
|
403
|
+
- **conflict** — the source uses a term that `CONTEXT.md` defines
|
|
404
|
+
differently. Example: source says "cancellation" meaning refund, glossary
|
|
405
|
+
says "cancellation" means order-state transition.
|
|
406
|
+
- **fuzzy / overloaded** — a term that has no canonical definition yet but
|
|
407
|
+
is being used in ≥ 2 different senses in the source(s).
|
|
408
|
+
- **aligned** — matches the glossary; no action.
|
|
409
|
+
|
|
410
|
+
### 3c. Output — translation as a first-class duty
|
|
411
|
+
|
|
412
|
+
The pre-discovery skill's job is to land every external-vocabulary noun
|
|
413
|
+
on a project-internal concrete object whenever possible.
|
|
414
|
+
|
|
415
|
+
- Each `conflict` or `fuzzy` term becomes:
|
|
416
|
+
- One entry under `Open Questions` with the prefix `terminology:`
|
|
417
|
+
(so the next phase can resolve it during `requirements-discovery`).
|
|
418
|
+
- One line under `Augmentation > Domain alignment` with the
|
|
419
|
+
`terminology-mapping` label (Step 4 label rules), recording the
|
|
420
|
+
observation (what the source said vs. what CONTEXT.md says).
|
|
421
|
+
- **File paths and symbols are resolved to absolute, in-repo references.**
|
|
422
|
+
When the source mentions a module / class / endpoint / config key, run
|
|
423
|
+
`Read` / `Grep` to locate the concrete file path (relative to
|
|
424
|
+
`<PROJECT_ROOT>`) and the canonical symbol name. Record the resolution
|
|
425
|
+
under `Augmentation > Domain alignment` with the `evidence-link` label,
|
|
426
|
+
and link the absolute path from `Related Artifacts`. This is what makes
|
|
427
|
+
the brief portable across downstream workers (Claude / Codex / Gemini)
|
|
428
|
+
that may operate in separate worktrees and need to point at the same
|
|
429
|
+
object.
|
|
430
|
+
- **Conversion-block signal** — when a reporter statement cannot be
|
|
431
|
+
mapped to project vocabulary even after codebase exploration (e.g. the
|
|
432
|
+
reporter names a UI element that does not exist by that name, or
|
|
433
|
+
describes behavior no module currently implements), do **not** guess
|
|
434
|
+
the target. Emit a `conversion-block:` entry under `Open Questions`
|
|
435
|
+
describing exactly what could not be translated, so the next phase
|
|
436
|
+
knows to query the reporter directly rather than infer.
|
|
437
|
+
- See Step 4.5 for the approval-gated path to actually write the
|
|
438
|
+
okstra-internal glossary at
|
|
439
|
+
`<PROJECT_ROOT>/.project-docs/okstra/glossary.md`. External
|
|
440
|
+
`CONTEXT.md` / `CONTEXT-MAP.md` / `docs/adr/` are never edited.
|
|
441
|
+
|
|
442
|
+
Skip 3b/3c for purely external request material with no overlap to the
|
|
443
|
+
project's domain.
|
|
287
444
|
|
|
288
445
|
## Step 4: Fill in missing fields (NO full interview)
|
|
289
446
|
|
|
290
447
|
> **Verbatim-source rule**: Source Material collected in Step 1 must never
|
|
291
448
|
> be paraphrased, summarized, or restructured. When supplementing missing
|
|
292
449
|
> information, write only into the dedicated `Augmentation` section (see
|
|
293
|
-
> Step 5); never modify Source Material by a single byte.
|
|
450
|
+
> Step 5); never modify Source Material by a single byte. **Anything
|
|
451
|
+
> learned by grilling in this step lands in `Augmentation` or `Open
|
|
452
|
+
> Questions` only.** brief is a pre-discovery artifact, not a PRD —
|
|
453
|
+
> decisions belong to later phases.
|
|
294
454
|
|
|
295
455
|
Inspect the synthesized brief draft. For each REQUIRED section below that is
|
|
296
456
|
empty or trivially thin **after** reading Source Material verbatim, ask **at
|
|
297
|
-
most one** `AskUserQuestion`
|
|
298
|
-
|
|
457
|
+
most one** `AskUserQuestion` to fill it. Never ask about sections already
|
|
458
|
+
covered by the source material.
|
|
459
|
+
|
|
460
|
+
### Sharpening pass (bounded grill)
|
|
461
|
+
|
|
462
|
+
The following rules absorb the useful parts of `grill-me` /
|
|
463
|
+
`grill-with-docs` without turning brief into a decision-making interview.
|
|
464
|
+
|
|
465
|
+
1. **Codebase-first** — if a gap can be answered by `Read` / `Grep` / file
|
|
466
|
+
inspection (e.g. "does this symbol exist?", "what does this endpoint
|
|
467
|
+
return today?"), do that **instead of** asking the user. Only ask when
|
|
468
|
+
the codebase cannot answer.
|
|
469
|
+
2. **Question carries a recommended answer** — every `AskUserQuestion`
|
|
470
|
+
issued in this step must put the recommended option **first** with the
|
|
471
|
+
suffix `(Recommended)`. Free-text fallbacks are still allowed, but the
|
|
472
|
+
recommendation must be visible.
|
|
473
|
+
3. **One at a time** — never batch multiple questions into one
|
|
474
|
+
`AskUserQuestion` call. Ask, wait for the answer, fold it into the
|
|
475
|
+
draft, then ask the next.
|
|
476
|
+
4. **Bounded budget** — at most **1** sharpening question per empty
|
|
477
|
+
required section, plus **at most 2** disambiguation questions arising
|
|
478
|
+
from Step 3b (terminology conflicts / fuzzy terms). Hard cap: **6
|
|
479
|
+
questions total** across the whole brief. Anything beyond the cap is
|
|
480
|
+
recorded under `Open Questions` instead of asked.
|
|
481
|
+
5. **Scenario probe (optional)** — when `Desired Outcome` is empty or one
|
|
482
|
+
thin line, you may use **one** of the budgeted questions to pose a
|
|
483
|
+
single boundary scenario ("if X happens, is that in scope?") with a
|
|
484
|
+
recommended yes/no. Do not run a full edge-case sweep.
|
|
485
|
+
6. **Stop conditions** — exit the sharpening pass when any of these holds:
|
|
486
|
+
(a) every required section has Source content or one Augmentation
|
|
487
|
+
entry, (b) the budget is exhausted, (c) the user signals "enough".
|
|
488
|
+
Remaining gaps → `_(none)_` for that section; remaining ambiguities →
|
|
489
|
+
`Open Questions`.
|
|
299
490
|
|
|
300
491
|
Augmentation content must always be confined to the `Augmentation` section
|
|
301
|
-
or to a `> augmented
|
|
302
|
-
clear that the content is the skill's / user's added interpretation
|
|
303
|
-
than the original source.
|
|
492
|
+
or to a `> augmented: <label>` blockquote inside the required section, so
|
|
493
|
+
it is clear that the content is the skill's / user's added interpretation
|
|
494
|
+
rather than the original source.
|
|
495
|
+
|
|
496
|
+
### Augmentation labels (REQUIRED — no unlabelled augmentation)
|
|
497
|
+
|
|
498
|
+
Every augmentation — both inline `> augmented: …` blockquotes and
|
|
499
|
+
`Augmentation` section bullet points — must carry exactly one of these
|
|
500
|
+
labels. Unlabelled augmentation is rejected as half-formed translation.
|
|
501
|
+
|
|
502
|
+
| Label | When to use | Downstream treatment |
|
|
503
|
+
|---|---|---|
|
|
504
|
+
| `evidence-link` | Cross-reference / file path / symbol resolved from the source against the actual codebase. Pure fact, verified by `Read` / `Grep`. | Trust without verification. |
|
|
505
|
+
| `format-conversion` | Format-only transform (Jira ADF → Markdown, HTML → Markdown, etc.). Semantics unchanged. | Trust without verification. |
|
|
506
|
+
| `terminology-mapping` | Reporter's word mapped to a project-canonical term (from `CONTEXT.md` or resolved during Step 3b). | Verify against `CONTEXT.md`; if mismatch, treat as a clarification candidate. |
|
|
507
|
+
| `intent-inference` | Reporter did NOT literally state this — the skill inferred meaning from context (e.g. classifying "가끔 안 됨" as "intermittent failure on a specific path"). Qualitative only — **never** invent quantitative thresholds (numbers, latencies, percentages, counts). | **Verify with the reporter before acting.** Auto-mirrored into `Open Questions`. |
|
|
508
|
+
|
|
509
|
+
**Inline form** — `> augmented: intent-inference — <one line>`.
|
|
510
|
+
**Section form** — `- intent-inference: <one line>` under `Augmentation`.
|
|
511
|
+
|
|
512
|
+
### Auto-mirroring rule
|
|
513
|
+
|
|
514
|
+
Every `intent-inference` entry must have a paired entry in `Open Questions`
|
|
515
|
+
with the prefix `intent-check:` describing what the reporter must confirm.
|
|
516
|
+
This is what makes the inference auditable end-to-end: the inference is
|
|
517
|
+
visible (Augmentation), and the verification need is visible (Open
|
|
518
|
+
Questions). If a downstream worker resolves the inference without going
|
|
519
|
+
back to the reporter, the `intent-check:` row stays open as a record of
|
|
520
|
+
unverified translation.
|
|
521
|
+
|
|
522
|
+
`terminology-mapping` and `conversion-block:` follow the same dual-record
|
|
523
|
+
discipline (Augmentation observation ↔ `Open Questions` `terminology:` /
|
|
524
|
+
`conversion-block:` row).
|
|
304
525
|
|
|
305
526
|
### Step 4 policy under multi-brief (tracker recursion) mode
|
|
306
527
|
|
|
@@ -334,6 +555,66 @@ Sections **deliberately omitted** (do NOT add them, do NOT prompt for them):
|
|
|
334
555
|
|
|
335
556
|
Those belong to later okstra phases.
|
|
336
557
|
|
|
558
|
+
## Step 4.5: Domain proposals (with approval-gated edits)
|
|
559
|
+
|
|
560
|
+
For each `conflict` / `fuzzy` term collected in Step 3b that *was not*
|
|
561
|
+
resolved by a budgeted Step 4 question, draft a glossary proposal and
|
|
562
|
+
offer it to the user. This step writes to the **okstra-internal
|
|
563
|
+
glossary** at `<PROJECT_ROOT>/.project-docs/okstra/glossary.md` only —
|
|
564
|
+
external `<PROJECT_ROOT>/CONTEXT.md` / `CONTEXT-MAP.md` are never edited
|
|
565
|
+
by this skill.
|
|
566
|
+
|
|
567
|
+
> **Decision scope**: this skill does NOT evaluate decision candidates
|
|
568
|
+
> and does NOT draft decision files. Decision creation requires context
|
|
569
|
+
> that brief lacks (the recommended option, named alternatives,
|
|
570
|
+
> trade-off analysis). Brief only emits the signal — every candidate
|
|
571
|
+
> goes to `Open Questions` with the `adr-candidate:` prefix and is
|
|
572
|
+
> evaluated by `implementation-planning` against the three-criteria
|
|
573
|
+
> gate. Approved decision files land at
|
|
574
|
+
> `<PROJECT_ROOT>/.project-docs/okstra/decisions/<NNNN>-<slug>.md`,
|
|
575
|
+
> never at external `<PROJECT_ROOT>/docs/adr/`.
|
|
576
|
+
|
|
577
|
+
### 4.5a. Draft glossary proposals
|
|
578
|
+
|
|
579
|
+
- **Glossary entry**: `proposed glossary entry: <term> = <one-line definition>`
|
|
580
|
+
— destined for `<PROJECT_ROOT>/.project-docs/okstra/glossary.md`.
|
|
581
|
+
|
|
582
|
+
### 4.5b. Approval flow (per entry)
|
|
583
|
+
|
|
584
|
+
For each draft, **first echo the target absolute path on one line** (so
|
|
585
|
+
the user sees the exact file that will be written), then `AskUserQuestion`:
|
|
586
|
+
|
|
587
|
+
- **Label**: `"Apply glossary entry?"` (keep the label short — absolute
|
|
588
|
+
paths belong in the echo line above, not in the option chip)
|
|
589
|
+
- **Options**:
|
|
590
|
+
1. `Apply (Recommended)` — write the change now.
|
|
591
|
+
2. `Skip — keep as Augmentation note only` — leave the proposal in the
|
|
592
|
+
brief's `Augmentation > Domain alignment` section, do not edit the
|
|
593
|
+
file.
|
|
594
|
+
3. `Edit first` — show the rendered content and accept a free-text
|
|
595
|
+
correction, then re-confirm.
|
|
596
|
+
|
|
597
|
+
Ask once per entry. Never batch. If the user picks `Apply`:
|
|
598
|
+
|
|
599
|
+
- Append the entry to
|
|
600
|
+
`<PROJECT_ROOT>/.project-docs/okstra/glossary.md` under an existing
|
|
601
|
+
relevant heading, or create a `## Glossary` section if none exists. If
|
|
602
|
+
the file does not exist, create it with a `## Glossary` heading and
|
|
603
|
+
the entry. Preserve all existing content byte-for-byte.
|
|
604
|
+
|
|
605
|
+
### 4.5c. Brief record
|
|
606
|
+
|
|
607
|
+
Regardless of Apply / Skip, record the outcome under `Augmentation >
|
|
608
|
+
Domain alignment`:
|
|
609
|
+
|
|
610
|
+
- `terminology-mapping: applied glossary: <term> → <PROJECT_ROOT>/.project-docs/okstra/glossary.md` or
|
|
611
|
+
- `terminology-mapping: skipped glossary: <term> = <definition>`
|
|
612
|
+
|
|
613
|
+
Decision candidates are recorded under `Open Questions` as
|
|
614
|
+
`adr-candidate: <topic>` (targeting
|
|
615
|
+
`<PROJECT_ROOT>/.project-docs/okstra/decisions/`) — not here. This keeps
|
|
616
|
+
the brief itself self-documenting about what side effects it caused.
|
|
617
|
+
|
|
337
618
|
## Step 5: Write the brief(s)
|
|
338
619
|
|
|
339
620
|
Use the same template per brief file. In tracker mode producing a parent
|
|
@@ -348,13 +629,14 @@ collide with the inner 3-backtick code block.)
|
|
|
348
629
|
---
|
|
349
630
|
type: brief
|
|
350
631
|
brief-id: <ticket-id>-<file-title> # equals the filename stem
|
|
351
|
-
parent-id: self # `self` at root
|
|
632
|
+
parent-id: self # always `self` at root; child briefs use parent's brief-id
|
|
352
633
|
ticket-id: <LIN-1234 | PROJ-42 | gh-repo-123 | notion-abcdef12 | "">
|
|
353
634
|
source-type: <file | linear | jira | github | notion | url | user-input>
|
|
354
635
|
task-group: <task-group>
|
|
355
636
|
depth: 0 # 0=parent/single, 1=child, 2=grandchild, ...
|
|
356
637
|
created: <YYYY-MM-DD>
|
|
357
638
|
generator: okstra-brief
|
|
639
|
+
reporter-confirmations: <complete | partial | pending | skipped> # set by Step 6.5
|
|
358
640
|
---
|
|
359
641
|
|
|
360
642
|
# Task Brief: <task_group>/<filename-without-ext>
|
|
@@ -364,6 +646,7 @@ generator: okstra-brief
|
|
|
364
646
|
> Tracker key (if any): <LIN-1234 | PROJ-42 | gh-repo-123 | notion-abcdef12>
|
|
365
647
|
> Parent brief (child briefs only): <relative path>
|
|
366
648
|
> Recommended next phase: <requirements-discovery | error-analysis> ← from Step 6
|
|
649
|
+
> Handoff contract: see `prompts/profiles/_common-contract.md` § "Brief handoff contract"
|
|
367
650
|
|
|
368
651
|
## Source Material (verbatim — do not modify)
|
|
369
652
|
|
|
@@ -376,7 +659,7 @@ must be annotated in the header meta.
|
|
|
376
659
|
- ref: <abs file path | LIN-1234 | https://... | "conversation synthesis">
|
|
377
660
|
- fetched-via: <Read | mcp__linear__getIssue | mcp__notion__... | gh issue view | WebFetch | user-paste>
|
|
378
661
|
- fetched-at: <YYYY-MM-DD HH:MM>
|
|
379
|
-
- format: <as-is | "Jira ADF → Markdown (semantics preserved)" | "
|
|
662
|
+
- format: <as-is | "Jira ADF → Markdown (semantics preserved)" | "tool-truncated — missing body requested from reporter">
|
|
380
663
|
|
|
381
664
|
```
|
|
382
665
|
<Paste the raw source here without changing a single character.>
|
|
@@ -391,8 +674,10 @@ must be annotated in the header meta.
|
|
|
391
674
|
<Background / scope / why now. If self-evident from Source Material, quote
|
|
392
675
|
it briefly and stop. Use the blockquote below when augmentation is needed.>
|
|
393
676
|
|
|
394
|
-
> augmented: <Interpretation added by the skill or user.
|
|
395
|
-
>
|
|
677
|
+
> augmented: <label> — <Interpretation added by the skill or user. Label
|
|
678
|
+
> MUST be one of: `evidence-link` / `format-conversion` /
|
|
679
|
+
> `terminology-mapping` / `intent-inference`. Do NOT add any extra
|
|
680
|
+
> interpretation outside this blockquote.>
|
|
396
681
|
|
|
397
682
|
## Problem / Symptom
|
|
398
683
|
|
|
@@ -416,7 +701,39 @@ none.>
|
|
|
416
701
|
|
|
417
702
|
## Open Questions
|
|
418
703
|
|
|
419
|
-
|
|
704
|
+
Prefix every row with one of these signals so the next phase knows how to
|
|
705
|
+
handle it. Free-form rows are allowed only as `general:`.
|
|
706
|
+
|
|
707
|
+
- `general: <unresolved question the user flagged>`
|
|
708
|
+
- `terminology: <reporter word> — needs canonical resolution against <PROJECT_ROOT>/.project-docs/okstra/glossary.md`
|
|
709
|
+
- `intent-check: <restated inference> — confirm with reporter`
|
|
710
|
+
(auto-paired with every `intent-inference` augmentation)
|
|
711
|
+
- `conversion-block: <reporter statement> — could not be mapped to project vocabulary; reporter query required`
|
|
712
|
+
- `adr-candidate: <topic>` — signal only; `implementation-planning`
|
|
713
|
+
evaluates and, if accepted, drafts a decision file at
|
|
714
|
+
`<PROJECT_ROOT>/.project-docs/okstra/decisions/<NNNN>-<slug>.md`.
|
|
715
|
+
|
|
716
|
+
Use `_(none)_` only if every signal is empty. `intent-check:` and
|
|
717
|
+
`conversion-block:` rows that are answered in Step 6.5 are NOT removed
|
|
718
|
+
from this list — they receive a `[CONFIRMED <YYYY-MM-DD> → RC-N]`
|
|
719
|
+
marker that links to the corresponding entry under
|
|
720
|
+
`## Reporter Confirmations`.
|
|
721
|
+
|
|
722
|
+
## Reporter Confirmations
|
|
723
|
+
|
|
724
|
+
Populated by Step 6.5. Each subsection records one reporter answer
|
|
725
|
+
verbatim, with a link back to the originating `Open Questions` row.
|
|
726
|
+
|
|
727
|
+
_(none — pending or skipped)_
|
|
728
|
+
|
|
729
|
+
<!-- when populated, the shape is:
|
|
730
|
+
### RC-1 — <intent-check: or conversion-block: row id / topic>
|
|
731
|
+
- asked: <YYYY-MM-DD HH:MM>
|
|
732
|
+
- linked-row: `<exact Open Questions row text>`
|
|
733
|
+
- answer (verbatim):
|
|
734
|
+
|
|
735
|
+
> <reporter's answer, byte-for-byte>
|
|
736
|
+
-->
|
|
420
737
|
|
|
421
738
|
## Augmentation
|
|
422
739
|
|
|
@@ -424,7 +741,47 @@ Cross-references / interpretation / context added by the user or skill that
|
|
|
424
741
|
is not in the original source. May be empty. Keep this section visually
|
|
425
742
|
separated from Source Material — never inline it inside Source Material.
|
|
426
743
|
|
|
427
|
-
|
|
744
|
+
Every entry below must start with one of the four labels:
|
|
745
|
+
`evidence-link` / `format-conversion` / `terminology-mapping` /
|
|
746
|
+
`intent-inference`. Unlabelled entries are forbidden.
|
|
747
|
+
|
|
748
|
+
### Domain alignment
|
|
749
|
+
|
|
750
|
+
Observations from Step 3b and the outcome of Step 4.5 (glossary
|
|
751
|
+
applied vs. skipped). The actual glossary edits live in
|
|
752
|
+
`<PROJECT_ROOT>/.project-docs/okstra/glossary.md` when applied; this
|
|
753
|
+
section records what happened. Decision candidates are NOT recorded
|
|
754
|
+
here — they flow through `Open Questions` as `adr-candidate:` rows for
|
|
755
|
+
`implementation-planning` to evaluate (and, if accepted, draft into
|
|
756
|
+
`<PROJECT_ROOT>/.project-docs/okstra/decisions/`).
|
|
757
|
+
|
|
758
|
+
- `terminology-mapping: <reporter word> → <okstra glossary canonical>` —
|
|
759
|
+
routine glossary alignment, paired with `terminology:` in Open Questions
|
|
760
|
+
when unresolved.
|
|
761
|
+
- `terminology-mapping: applied glossary: <term> → <PROJECT_ROOT>/.project-docs/okstra/glossary.md` /
|
|
762
|
+
`terminology-mapping: skipped glossary: <term> = <definition>` — Step
|
|
763
|
+
4.5 outcomes.
|
|
764
|
+
- Use `_(none)_` if every alignment entry is empty.
|
|
765
|
+
|
|
766
|
+
### Evidence links (file / symbol resolution)
|
|
767
|
+
|
|
768
|
+
- `evidence-link: <reporter phrase> → <relative path>:<line>` /
|
|
769
|
+
`evidence-link: <reporter phrase> → <symbol> in <relative path>`
|
|
770
|
+
- `_(none)_` if none.
|
|
771
|
+
|
|
772
|
+
### Intent inferences
|
|
773
|
+
|
|
774
|
+
Every entry here is an unverified hypothesis. Each one MUST have a paired
|
|
775
|
+
`intent-check:` row under Open Questions.
|
|
776
|
+
|
|
777
|
+
- `intent-inference: <reporter phrase> → <qualitative restatement>`
|
|
778
|
+
(qualitative only — never invent numeric thresholds)
|
|
779
|
+
- `_(none)_` if none.
|
|
780
|
+
|
|
781
|
+
### Format conversions
|
|
782
|
+
|
|
783
|
+
- `format-conversion: <ref> — <e.g. Jira ADF → Markdown, semantics preserved>`
|
|
784
|
+
- `_(none)_` if none.
|
|
428
785
|
````
|
|
429
786
|
|
|
430
787
|
### Frontmatter rules
|
|
@@ -434,7 +791,7 @@ separated from Source Material — never inline it inside Source Material.
|
|
|
434
791
|
- `brief-id` must match the filename stem (`<ticket-id>-<file-title>`)
|
|
435
792
|
exactly. If the file is moved/renamed, update both.
|
|
436
793
|
- `parent-id`:
|
|
437
|
-
- The root (depth 0) brief uses
|
|
794
|
+
- The root (depth 0) brief always uses the literal string `self`.
|
|
438
795
|
- Descendant briefs use the direct parent's `brief-id`.
|
|
439
796
|
- `depth` must equal the number of `sub/` segments in the path (consistency
|
|
440
797
|
check point). On mismatch, the file location wins — correct the
|
|
@@ -465,6 +822,110 @@ Write the chosen recommendation into the `Recommended next phase:` header
|
|
|
465
822
|
line of the brief file (Step 5). Do NOT auto-spawn `okstra-run` — leave the
|
|
466
823
|
trigger to the user.
|
|
467
824
|
|
|
825
|
+
## Step 6.5: Reporter batch confirmation (option B precondition)
|
|
826
|
+
|
|
827
|
+
This is the boundary between brief and the downstream phases: every
|
|
828
|
+
question that only the reporter can answer is collected and answered
|
|
829
|
+
**here, once**, so the next phase runs without operator fill-ins.
|
|
830
|
+
|
|
831
|
+
### 6.5a. Collect reporter-only rows
|
|
832
|
+
|
|
833
|
+
Scan the finalized brief's `Open Questions` and gather every row prefixed
|
|
834
|
+
with one of these signals — these are the only rows that the codebase
|
|
835
|
+
cannot resolve:
|
|
836
|
+
|
|
837
|
+
- `intent-check:` (auto-mirrored from `intent-inference` augmentations)
|
|
838
|
+
- `conversion-block:` (translation failed in Step 3c)
|
|
839
|
+
|
|
840
|
+
If the resulting list is empty, set `reporter-confirmations: complete` in
|
|
841
|
+
the brief's frontmatter and skip the rest of this step.
|
|
842
|
+
|
|
843
|
+
### 6.5b. Ask once: collect now or later
|
|
844
|
+
|
|
845
|
+
If the list is non-empty, run **one** `AskUserQuestion`:
|
|
846
|
+
|
|
847
|
+
- **Label**: `"This brief has <N> question(s) only the reporter can answer. Collect their answers now?"`
|
|
848
|
+
- **Options**:
|
|
849
|
+
1. `Yes — collect now (Recommended)` — proceed to 6.5c.
|
|
850
|
+
2. `No — leave for the downstream phase` — set
|
|
851
|
+
`reporter-confirmations: skipped`. The phase will promote each
|
|
852
|
+
pending row into its own `## 5. Clarification Items` as
|
|
853
|
+
`Blocks=next-phase` (`Blocks=approval` only in
|
|
854
|
+
`implementation-planning`); see each phase profile's "Brief
|
|
855
|
+
consumption" addendum.
|
|
856
|
+
|
|
857
|
+
### 6.5c. Batch the questions
|
|
858
|
+
|
|
859
|
+
For each pending row, formulate one question. Because the
|
|
860
|
+
`AskUserQuestion` tool caps options at 4 per call and questions per call
|
|
861
|
+
also at 4, split into batches of ≤ 4 questions.
|
|
862
|
+
|
|
863
|
+
**Hard cap — 12 questions per Step 6.5 run.** When the pending list
|
|
864
|
+
exceeds 12 rows, sort by priority and ask only the top 12 this round:
|
|
865
|
+
|
|
866
|
+
1. `conversion-block:` rows first (translation failure — highest
|
|
867
|
+
downstream risk).
|
|
868
|
+
2. `intent-check:` rows next, in the order they appear in `Open
|
|
869
|
+
Questions`.
|
|
870
|
+
|
|
871
|
+
Any rows beyond the cap are left unanswered in this run; set
|
|
872
|
+
`reporter-confirmations: partial` in the frontmatter and tell the user
|
|
873
|
+
which rows remain. The next `okstra-brief` re-run (or the downstream
|
|
874
|
+
phase that consumes `Blocks=next-phase`) handles the remainder.
|
|
875
|
+
|
|
876
|
+
Each question carries:
|
|
877
|
+
|
|
878
|
+
- The reporter-facing phrasing (plain language, no jargon).
|
|
879
|
+
- A recommended answer drawn from the brief's `intent-inference` /
|
|
880
|
+
`conversion-block:` content, marked `(Recommended)`.
|
|
881
|
+
- 2–3 alternative options when the answer space is naturally enumerable;
|
|
882
|
+
otherwise a free-text fallback.
|
|
883
|
+
|
|
884
|
+
### 6.5d. Record verbatim
|
|
885
|
+
|
|
886
|
+
Create a new top-level section `## Reporter Confirmations` in the brief
|
|
887
|
+
(if not present) with one subsection per answered row:
|
|
888
|
+
|
|
889
|
+
```markdown
|
|
890
|
+
## Reporter Confirmations
|
|
891
|
+
|
|
892
|
+
### RC-1 — <intent-check: or conversion-block: row id / topic>
|
|
893
|
+
- asked: <YYYY-MM-DD HH:MM>
|
|
894
|
+
- linked-row: `<exact Open Questions row text>`
|
|
895
|
+
- answer (verbatim):
|
|
896
|
+
|
|
897
|
+
> <reporter's answer, byte-for-byte>
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
Mark the linked `Open Questions` row by appending `[CONFIRMED <YYYY-MM-DD> → RC-N]` to the end of the row's line. Do NOT delete the row — the
|
|
901
|
+
`CONFIRMED` marker keeps the audit trail intact.
|
|
902
|
+
|
|
903
|
+
For every `intent-inference` augmentation whose paired `intent-check:`
|
|
904
|
+
was confirmed, add one new line directly below the `> augmented:
|
|
905
|
+
intent-inference …` blockquote:
|
|
906
|
+
|
|
907
|
+
```
|
|
908
|
+
> confirmed-by-reporter: RC-N — <one-line summary of confirmation>
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
This converts the inference from "unverified hypothesis" to "verified
|
|
912
|
+
hypothesis" without rewriting the original augmentation.
|
|
913
|
+
|
|
914
|
+
### 6.5e. Frontmatter state
|
|
915
|
+
|
|
916
|
+
Update `reporter-confirmations` in the brief frontmatter:
|
|
917
|
+
|
|
918
|
+
- `complete` — every pending row was answered.
|
|
919
|
+
- `partial` — some rows answered, some skipped within this run.
|
|
920
|
+
- `skipped` — user picked option 2 in 6.5b.
|
|
921
|
+
- `pending` — should never appear at this point; if it does, treat the
|
|
922
|
+
brief as not yet handed off and refuse to proceed.
|
|
923
|
+
|
|
924
|
+
Step 6.5 ends here. The brief now has either zero pending reporter-only
|
|
925
|
+
rows (`complete` / `partial` with remainder in the same file) or an
|
|
926
|
+
explicit `skipped` signal that downstream phases consume per the
|
|
927
|
+
"Brief consumption" addendum in `_common-contract.md`.
|
|
928
|
+
|
|
468
929
|
## Step 7: Hand off
|
|
469
930
|
|
|
470
931
|
Single brief:
|
|
@@ -492,8 +953,14 @@ started.
|
|
|
492
953
|
|
|
493
954
|
## Output Rules
|
|
494
955
|
|
|
495
|
-
-
|
|
496
|
-
-
|
|
956
|
+
- All okstra-generated artifacts live under
|
|
957
|
+
`<PROJECT_ROOT>/.project-docs/okstra/`. This skill's brief files go
|
|
958
|
+
under `.project-docs/okstra/briefs/`; its glossary writes go to
|
|
959
|
+
`.project-docs/okstra/glossary.md` (Step 4.5 approval flow).
|
|
960
|
+
- External paths (`<PROJECT_ROOT>/CONTEXT.md`,
|
|
961
|
+
`<PROJECT_ROOT>/CONTEXT-MAP.md`, `<PROJECT_ROOT>/docs/adr/`,
|
|
962
|
+
`<PROJECT_ROOT>/.scratch/`) are read-only references. This skill
|
|
963
|
+
never writes to them. Absent external files are the normal state.
|
|
497
964
|
- **Verbatim source**: never paraphrase, summarize, restructure, or reorder
|
|
498
965
|
the Source Material section. Only format conversion (ADF → MD, HTML → MD)
|
|
499
966
|
is allowed, and the conversion must be annotated in the `format:` meta.
|
|
@@ -505,10 +972,10 @@ started.
|
|
|
505
972
|
paste.
|
|
506
973
|
- Never fabricate content for empty sections; use `_(none)_`.
|
|
507
974
|
- Echo each `AskUserQuestion` outcome on one short line.
|
|
508
|
-
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
`
|
|
975
|
+
- No line budget overrides the verbatim-source rule. If source content is
|
|
976
|
+
large, preserve it exactly as separate `Source Material` entries; if a
|
|
977
|
+
tool only returns a truncated body, ask the user for the missing content
|
|
978
|
+
or emit a `conversion-block:` row. Never silently excerpt or summarize.
|
|
512
979
|
|
|
513
980
|
## Failure Modes
|
|
514
981
|
|