Skip to main content

flow-next-refine

Refine a spec or task before building: deep Q&A (business, technical, both) or a read-only research pass over external docs. Use to refine or interrogate requirements or read up on a new library.

跳到安装

来源信息

仓库
gmickel/flow-next
最近来源活动
2026年9月14日 17:40
检测到的 SKILL.md 语言
英语
星标
699
分支
55

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
12 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
flow-next-refine
description
Refine a spec or task before building: deep Q&A (business, technical, both) or a read-only research pass over external docs. Use to refine or interrogate requirements or read up on a new library.
# Flow refine Refine a task/spec: conduct an extremely thorough interview and write the refined details back, or (`--scope=research`) resolve the spec's external-library unknowns from official docs and write them back. The `interview` name remains a forwarding alias for one release. **`.flow/` is the only task tracker.** A run that recorded task state in a markdown TODO, a plan file, TodoWrite, or any other tracker has broken this — all task state is read and written via `flowctl`. ### Chart boundary Existing-spec clarification stays **primary**. Interview refines a valid spec with unresolved judgment questions. Do **not** reopen discovery as `/flow-next:chart` unless the answers reveal that the **effort itself is not yet specifiable** - only then route backward to chart. Clear work that never needed a chart stays out of chart. Unsure of the hop: `$flow-next-flow --explain`. ## Preamble **CRITICAL: flowctl is BUNDLED — NOT installed globally.** `which flowctl` will fail (expected). Define once; subsequent blocks use `$FLOWCTL`: ```bash FLOWCTL="${CODEX_HOME:-$HOME/.codex}/scripts/flowctl" [ -x "$FLOWCTL" ] || FLOWCTL="<plugin-root>/scripts/flowctl" # <plugin-root> = the directory two levels above this skill's SKILL.md file (the harness gave you that file's absolute path when the skill loaded); substitute it literally [ -x "$FLOWCTL" ] || FLOWCTL=".flow/bin/flowctl" ``` **Role**: technical interviewer, spec refiner **Goal**: extract complete implementation details through deep questioning (40+ questions typical) ## Input Full request: $ARGUMENTS Accepts a Flow spec ID, a Flow task ID, a resolvable tracker handle, a file path, or nothing — recognition rules and the fetch command per type are in "Detect Input Type" below (single copy; the write-back command per type is in `references/write-back.md`). Examples: - `/flow-next:refine fn-1-add-oauth` - `/flow-next:refine fn-1-add-oauth.3` - `/flow-next:refine fn-1` (legacy formats fn-1, fn-1-xxx still supported) - `/flow-next:refine docs/oauth-spec.md` - `/flow-next:refine fn-1-add-oauth --scope=research` (external-docs pass; no questions) If empty, ask: "What should I interview you about? Give me a Flow ID (e.g., fn-1-add-oauth) or file path (e.g., docs/spec.md)" ## Setup ### Parse `--scope=business|technical|both|research` Token-safe parsing for `--scope` / `--biz` / `--tech` lives in `flowctl scope resolve` — never re-implement inline. The subcommand strips scope tokens, preserves every other token in order (Flow IDs, paths, `--docs`, `--strategy`, ...), and emits the resolved scope plus a `defaulted` flag. The resolver's fallback when no scope flag is passed is `technical` (1.0.2 backward-compat) — but the skill does NOT silently run it: when `defaulted == true`, ask the user which pass to run after Detect Input Type (see "Scope selection when no flag passed" below). `technical` applies only when that question cannot be asked. ```bash # Run BEFORE the --docs / --strategy strip block. Conflict / invalid value # → non-zero exit; SKILL propagates. # # `--raw "$ARGUMENTS"` tokenizes via shlex INSIDE flowctl — preserves quoted # paths with spaces (e.g., `/flow-next:refine --biz "docs/my spec.md"`). # Unquoted `$ARGUMENTS` would word-split into broken tokens. RESOLVED_JSON=$("$FLOWCTL" scope resolve --json --raw "$ARGUMENTS") SCOPE=$(printf '%s' "$RESOLVED_JSON" | jq -r '.scope') # true when no scope flag was passed — gates the "Scope selection when no # flag passed" question below (older flowctl without the field → false, # preserving the silent technical default). SCOPE_DEFAULTED=$(printf '%s' "$RESOLVED_JSON" | jq -r '.defaulted // false') # `remaining_args` is a JSON array of strings. Re-join with single spaces # for downstream consumption; downstream code MUST re-tokenize via the # same safe path (shlex) if it might re-encounter quoted paths. ARGUMENTS=$(printf '%s' "$RESOLVED_JSON" | jq -r '.remaining_args | join(" ")') ``` **Scope parsing, write policy, and bank selection come from `flowctl scope resolve` / `scope write-policy` / `scope bank`.** A skill that re-implements the tokenizer, the section-ownership rules, or the bank mapping inline has broken this — the two copies drift and the inline one wins silently. **`SCOPE == research` asks no questions.** Skip the doc-aware autodetect, the scope question, the question banks, and the interview rounds: run Detect Input Type below, then read [`references/research-scope.md`](references/research-scope.md) and follow it. A business, technical, or both invocation never reads it. ### Parse `--docs` / `--no-docs` / `--strategy` / `--no-strategy` flags The four doc-aware override flags must be stripped from `$ARGUMENTS` before input-type detection so they don't get confused for a Flow ID or path. Two force variables carry the result — `""` = autodetect, `"on"` = forced on, `"off"` = forced off: ```bash RAW_ARGS="$ARGUMENTS" DOC_AWARE_FORCE="" # controls glossary + decisions STRATEGY_AWARE_FORCE="" # controls strategy independently ``` **When the invocation carried ANY of `--docs` / `--no-docs` / `--strategy` / `--no-strategy`**, STOP and read [`references/doc-aware.md`](references/doc-aware.md) § Flag parsing before proceeding — it holds the strip block (both pairs mutually exclusive, negation wins on conflict), the cascade rules, the flag matrix that is the contract for each combination, and the scope × doc/strategy interaction table. A bare invocation skips it: no flag token is present, so `RAW_ARGS` is `$ARGUMENTS` unchanged (whitespace-normalized) and both force variables stay empty (autodetect). ### Doc-aware autodetect Decide whether doc-aware mode activates. `DOC_AWARE` controls glossary + decisions; `STRATEGY_AWARE` controls the strategy-conflict behavior independently. Each has three paths (forced-on / forced-off / autodetect) per the flag matrix. The default-autodetect rule is: doc-aware mode activates when **any** of three conditions has signal — `glossary.total_terms > 0` (a) OR a decision entry exists (b) OR `strategy.sections_filled >= 1` (c). The two flag pairs override (a)+(b) and (c) independently. Counting populated entries (rather than `[[ -f <file> ]]`) is deliberate — see [`references/doc-aware.md`](references/doc-aware.md) § Why counts, not file presence. ```bash # DOC_AWARE: glossary + decisions. Probes and parses fail OPEN (|| DOC_AWARE=1). DOC_AWARE=0 if [[ "$DOC_AWARE_FORCE" == "on" ]]; then DOC_AWARE=1 elif [[ "$DOC_AWARE_FORCE" == "off" ]]; then DOC_AWARE=0 else # NO pipelines in the probe — capture raw first, rc-checked; parse separately. GLOSSARY_RAW="$("$FLOWCTL" glossary list --json 2>/dev/null)" || DOC_AWARE=1 DECISIONS_RAW="$("$FLOWCTL" memory list --track knowledge --category decisions --json 2>/dev/null)" || DOC_AWARE=1 if [ "$DOC_AWARE" = "0" ]; then TERMS="$(printf '%s' "$GLOSSARY_RAW" | jq -r '.total_terms // 0' 2>/dev/null)" || DOC_AWARE=1 DECS="$(printf '%s' "$DECISIONS_RAW" | jq -r '.entries | length // 0' 2>/dev/null)" || DOC_AWARE=1 fi if [ "$DOC_AWARE" = "0" ] && { [ "${TERMS:-0}" -gt 0 ] || [ "${DECS:-0}" -gt 0 ]; }; then DOC_AWARE=1 fi fi # STRATEGY_AWARE: strategy (independent of DOC_AWARE — autodetects on its own signal) STRATEGY_AWARE=0 if [[ "$STRATEGY_AWARE_FORCE" == "on" ]]; then STRATEGY_AWARE=1 elif [[ "$STRATEGY_AWARE_FORCE" == "off" ]]; then STRATEGY_AWARE=0 else STRATEGY_RAW="$("$FLOWCTL" strategy status --json 2>/dev/null)" || STRATEGY_AWARE=1 if [ "$STRATEGY_AWARE" = "0" ]; then STRAT_FILLED="$(printf '%s' "$STRATEGY_RAW" | jq -r '.sections_filled // 0' 2>/dev/null)" || STRATEGY_AWARE=1 fi if [ "$STRATEGY_AWARE" = "0" ] && [ "${STRAT_FILLED:-0}" -ge 1 ]; then STRATEGY_AWARE=1 fi fi if [ "$DOC_AWARE" = "1" ] || [ "$STRATEGY_AWARE" = "1" ]; then echo "DOC-AWARE GATE ACTIVE — STOP. Read references/doc-aware.md before drafting the first question." fi ``` When the sentinel prints, STOP and **read [`references/doc-aware.md`](references/doc-aware.md)** before any further step, then apply its behaviors — Phase-zero glossary scan (a), fuzzy-term sharpening (b), code-versus-assertion contradiction (c), decision-record write (d), and code-vs-strategy contradiction (e). On the default no-docs path (`DOC_AWARE=0` and `STRATEGY_AWARE=0`) the interview proceeds exactly as today — do not read the file. ## Detect Input Type **Handle-recognition rule (R16):** do NOT gate on a hard "must start with `fn-`" check. Before treating a single-token arg as a file path or freeform, route it through `$FLOWCTL show <arg> --json` — flowctl's widened resolver maps a tracker key (`wor-17` / `wor-17.M`) to its linked spec/task, so a resolvable handle is the existing spec/task, never a new idea. Patterns 1-2 below are the common case; pattern 3 generalizes them to any resolvable handle. 1. **Flow spec ID pattern**: matches `fn-\d+(-[a-z0-9-]+)?` (e.g., fn-1-add-oauth, fn-12, fn-2-fix-login-bug) - Fetch: `$FLOWCTL show <id> --json` - Read spec: `$FLOWCTL cat <id>` 2. **Flow task ID pattern**: matches `fn-\d+(-[a-z0-9-]+)?\.\d+` (e.g., fn-1-add-oauth.3, fn-12.5) - Fetch: `$FLOWCTL show <id> --json` - Read spec: `$FLOWCTL cat <id>` - Also get parent spec context: `$FLOWCTL cat <spec-id>` 3. **Resolvable tracker handle**: any single-token arg (not an `.md` path) that `$FLOWCTL show <arg> --json` resolves — e.g. a Linear key `wor-17` (spec) or `wor-17.3` (task). Use the canonical id from the JSON; a `.`-containing handle is a task (fetch parent spec too), otherwise a spec. Treat exactly like patterns 1-2; never re-create. 4. **File path**: a path-like token / `.md` extension that does NOT resolve via `flowctl show` - Read file contents - If file doesn't exist, ask user to provide valid path Done when: the argument is classified as exactly one of the four patterns, every non-`.md` single-token arg was routed through `$FLOWCTL show <arg> --json` before that classification, and the target's content (spec body, task + parent spec, or file) is in hand for the scope recommendation below. ## Scope selection when no flag passed Fires ONLY when `SCOPE_DEFAULTED=true` (no `--scope` / `--biz` / `--tech` in the invocation). An explicit scope flag always wins and skips this section entirely. Runs AFTER Detect Input Type — the spec/file content is in hand, so the recommendation is informed. Ask ONE `plain-text numbered prompt` (same blocking primitive as every interview question; the tool-unreachable fallback under "Question Format" applies): - **header**: `Interview scope` - **body**: `Which interview pass should run? business = product framing (goal, users, boundaries, outcome AC — never decides architecture, stack, or APIs); technical = implementation details (architecture, API contracts, edge cases); both = business first, then technical. Recommended: <X> — <one-sentence rationale from the target's current state>. Confidence: [judgment-call].` - **options** (frozen): `business`, `technical`, `both` Derive the recommendation from the target's current state: - Biz sections empty AND tech sections empty (new idea, fresh spec, bare file) → recommend `both` — ground the product framing before any technical decision. - Biz sections populated, tech sections empty or placeholder-only → recommend `technical` — the business layer exists; fill the technical layer. - Tech sections populated, biz sections absent (1.0.2-shape solo spec) → recommend `technical` — refine in place. Set `SCOPE` to the answer and proceed exactly as if the flag had been passed — write-policy, question bank, and pass behavior all follow the chosen scope. If the question genuinely cannot be asked (tool unreachable and no plain-text answer), fall back to `technical` and say so in the interview opener. Why this exists: a PM invoking `/flow-next:refine <spec-id>` bare used to get a silent technical interrogation — stack/API questions they don't own, with skipped answers at risk of becoming rails-derived defaults. The scope question makes the business pass discoverable at the exact moment it matters. ## Interview Process **CRITICAL REQUIREMENT**: For every question, you MUST ask via the plain-text numbered prompt described below. **Ask the user via plain text.** Render the options below as a numbered list `1.` … `N.`, followed by a final option `N+1. Other — type your own answer`. Print the question, then the numbered list, then **stop and wait for the user's next message before continuing**. Parse the reply as: a bare number `1`–`N+1` → that option; the literal text of an option label → that option; free text after `Other` → custom answer. - ONLY ask via the plain-text numbered prompt - Ask in rounds: each round carries the whole frontier (see Question Order below), split across plain-text numbered prompt calls of up to 4 questions each - Expect 40+ questions total for complex specs ### Question Format: Lead with Recommendation Every `plain-text numbered prompt` body must include the agent's recommended option AND a confidence tier. Mirrors the canonical phrasing in `flow-next-audit/SKILL.md:64` ("Lead with the recommended option and a one-sentence rationale"). Pattern: - `question.body`: "<stakes>. <options summary>. Recommended: <X> — <one-sentence rationale>. Confidence: [high | judgment-call | your-call]." - `question.options`: neutral labels (no "(recommended)" markers — recommendation goes in the body; neutral options reduce anchoring) ### Plain-language question contract (field feedback, eval-validated) Applies to EVERY question, both scopes. The interviewee must be able to read a question once and answer it confidently without asking what it means — field feedback showed jargon-dense questions disempower exactly the people the interview exists to hear (baseline legibility scored 4/10 for a second-language PM; this contract scores 7.5+ at ~30% fewer tokens). - **Open the body with ONE sentence of stakes**: what this question decides, in the audience's words. - **Write for the audience in everyday words**; prefer the common word over the term of art. A term of art you genuinely need gets a plain-word gloss in ≤1 clause at first use (e.g. "counter-metrics — things we'd hate to make worse"). - **No unexplained acronyms or tool/repo shorthand.** In business scope, no implementation vocabulary (no schemas, endpoints, config keys). - **Every option description states its consequence in plain words**: "Choose this if…" / "This means…". - **Gloss referenced acceptance criteria.** When a question cites a spec R-ID, attach a short plain-words gist at first mention — "R3 (the audit line's required fields)" — never a bare "R3" the interviewee must open the spec to decode. Gist, not quote: pasting full criterion text bloats the question body. Required content and trim order (priorities — NOT a length cap; never trade required content for brevity): - **ALWAYS keep, in this order:** the stakes sentence; the recommendation + its one-sentence rationale; the confidence tier; the gloss for any term of art used; each option's consequence. - **TRIM FIRST, until the question reads in one pass:** repetition between body and options, secondary background, hedging, restated option lists.
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看