Source profileQuality 86/100

baokhang83/fluencyloop/claude-skills/feature/SKILL.md

feature

FluencyLoop Stage 2–3. Declare a feature and build it while staying fluent: creates the feature branch + design diagrams, then builds in slices, teaching the why of each real decision at the slice boundary and journaling it. Probes the concepts the work needs up front, adapts explanation depth to the developer's knowledge, and builds/maintains a per-developer knowledge base in ~/.fluencyloop. Use when starting a new unit of work in a repo that has a .fluencyloop/ directory, or when the user says

Source repository stars
38
Declared platforms
1
Static risk flags
2
Last source update
2026-08-05
Source checked
2026-08-05

Decision brief

What it does—and where it fits

This is the contributor's entry point. A feature is a branch (feature/); it owns the design diagrams and the session journals. You will: (1) declare the feature, (2) sketch its design, (3) build it in slices — teaching and journaling one or two real decisions at each slice bound…

Best for

  • Use when starting a new unit of work in a repo that has a .

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeDeclaredSource recordInstall path and trigger
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/baokhang83/fluencyloop --skill "claude-skills/feature"
Safe inspection promptEditorial

Inspect the Agent Skill "feature" from https://github.com/baokhang83/fluencyloop/blob/fe3ccf6dada2c36057a3d65b84ca150bd9b9c96e/claude-skills/feature/SKILL.md at commit fe3ccf6dada2c36057a3d65b84ca150bd9b9c96e. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    2. Design (Stage 2) — diagrams first, shown not filed

    Draft the two defaults from the intent and the codebase:

    a class diagram (the shapes and their relationships), anda sequence diagram (the main flow).Draft the two defaults from the intent and the codebase:
  2. 02

    3. Build in slices (Stage 3) — teach at the boundary

    Build the feature one meaningful slice at a time (a logical, commit-worthy chunk). Do not interrupt mid-thought. At each slice boundary:

    Review what you just built — from the slice, not the whole files. Run fluencyloopmetadata — the diff since the last journaledTeach the why — live, in the conversation. This is the during, so it happens here,
  3. 03

    4. Hand off to review — settle the recurring choice once

    When the feature is ready for a PR, tell the user they can run fluencyloop-review to assemble the reviewer-facing view from the sessions.

    A preference is already recorded — honor it silently, and do not re-ask. If it saysNo preference yet (this is the first feature) — ask exactly once, via a singlepush (+ open the PR, when gh is available) yourself at feature completion, or keep
  4. 04

    Bundled CLI (Claude Code)

    Before invoking a deterministic command, use this plugin's bundled launcher: "${CLAUDEPLUGINROOT}/bin/fluencyloop" . Every fluencyloop … command below means that exact Bash-tool command; it is never a chat instruction or a globally installed command.

    Before invoking a deterministic command, use this plugin's bundled launcher: "${CLAUDEPLUGINROOT}/bin/fluencyloop" . Every fluencyloop … command below means that exact Bash-tool command; it is never a chat instruction o…Do not hand-scaffold .fluencyloop/, .claude/skills/, designs, sessions, state, or helper scripts. The bundled CLI creates the deterministic files and returns their paths.
  5. 05

    Question delivery — preserve the pause

    When this workflow needs a real answer, choice, confirmation, or knowledge probe, use AskUserQuestion in Claude Code. Codex has no equivalent question-form tool: ask the question concisely in chat, then stop. Do not implement, write the decision, or move to the next step until t…

    When this workflow needs a real answer, choice, confirmation, or knowledge probe, use AskUserQuestion in Claude Code. Codex has no equivalent question-form tool: ask the question concisely in chat, then stop. Do not imp…Understanding checks are self-report, never quizzes. After teaching, the only permitted check is to ask the developer directly whether they understand and whether anything needs clarification: "Do you understand this ex…

Permission review

Static risk signals and limitations

Writes files

medium · line 160

The documentation asks the agent to create, modify, or delete local files.

*Show them rendered — don't just write a file and point at it.** Publish the diagrams as a

Reads files

low · line 195

The documentation asks the agent to read local files, directories, or repositories.

another file, e.g. `.specify/memory/constitution.md`), read *that* file for the real

Reads files

low · line 221

The documentation asks the agent to read local files, directories, or repositories.

alternative was rejected — from those hunks. Only open a full file when the hunks don't carry

Writes files

medium · line 279

The documentation asks the agent to create, modify, or delete local files.

create) the slice's session file:

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score86/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars38SourceRepository attention, not individual Skill quality
Compatibility1 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
baokhang83/fluencyloop
Skill path
claude-skills/feature/SKILL.md
Commit
fe3ccf6dada2c36057a3d65b84ca150bd9b9c96e
License
Apache-2.0
Collected
2026-08-05
Default branch
main
View the original SKILL.md

fluencyloop-feature — declare a feature, build it fluent

This is the contributor's entry point. A feature is a branch (feature/<slug>); it owns the design diagrams and the session journals. You will: (1) declare the feature, (2) sketch its design, (3) build it in slices — teaching and journaling one or two real decisions at each slice boundary. Never gate; never lecture. Keep the developer the author.

Bundled CLI (Claude Code)

Before invoking a deterministic command, use this plugin's bundled launcher: "${CLAUDE_PLUGIN_ROOT}/bin/fluencyloop" <arguments>. Every fluencyloop … command below means that exact Bash-tool command; it is never a chat instruction or a globally installed command.

Do not hand-scaffold .fluencyloop/, .claude/skills/, designs, sessions, state, or helper scripts. The bundled CLI creates the deterministic files and returns their paths.

Question delivery — preserve the pause

When this workflow needs a real answer, choice, confirmation, or knowledge probe, use AskUserQuestion in Claude Code. Codex has no equivalent question-form tool: ask the question concisely in chat, then stop. Do not implement, write the decision, or move to the next step until the developer has answered. A chat question is a portability fallback, not permission to bury a real question in prose.

Understanding checks are self-report, never quizzes. After teaching, the only permitted check is to ask the developer directly whether they understand and whether anything needs clarification: "Do you understand this explanation, or should I clarify anything?" Then trust their answer. Never ask them to prove understanding by restating the mechanism, explaining it "in your own words," predicting behavior, selecting an answer, or answering any other topic-specific question. A pre-teaching familiarity probe and a real technical choice are still valid questions, but neither may be repurposed as verification of what the developer learned.

0. Preconditions

Run the bundled fluencyloop check --json and parse its output. If git_repo or fluency is false, run the bundled fluencyloop init --json without asking the developer. It initialises Git in the current project directory when needed, then creates FluencyLoop's state. Parse its docs_dir, and verify that it is the repository's docs/fluencyloop directory before continuing. Only stop if init itself fails. Do not hand-create .fluencyloop, docs, or .claude/skills.

Read the loop state. If .fluencyloop/state.json exists, read it first — it is the loop's single source of truth for the active feature (feature slug, branch, stage, last_session, base_ref), written by fluencyloop feature / fluencyloop session and committed with the branch. Prefer it over re-deriving from git each turn: it tells you which stage you're resuming at and which session file is open. It's absent only before the feature is declared (§1 creates it).

Load the learner's knowledge base — parse it, don't eyeball it. First fold in what prior work demonstrated: run fluencyloop calibration compact — deterministic bash that rolls the engagement ledger (§3.4) into level promotions/demotions and clears it, so this feature starts from an adapted profile rather than a reset one. Then read the per-developer calibration profile deterministically via fluencyloop calibration show --json: a dimension → level map, level ∈ {fluent, familiar, learning, new}, e.g. {"java":"fluent","reactive":"learning","k8s":"new"}. Each level maps to a starting teaching depth for that domain via the deterministic depth policy in §3 (fluent → name it and move on … new → unpack, slow down, offer to go deeper) — apply it, don't re-derive it. A dimension that isn't listed is unknown — probe it (below) rather than guessing. The profile lives globally under ~/.fluencyloop/ and is never committed — it is the only place person-specific knowledge lives (the repo journal stays person-neutral; see Rules). Missing entirely is fine — you'll build it (see §3.4); fluencyloop calibration init seeds it. Never block on it.

Load the learner's preferences. Also read ~/.fluencyloop/preferences.md — a sibling to calibration.md (global, per-developer, never committed) that records recurring workflow choices already settled once, so you never re-ask them — e.g. the completion hand-off (commit + push + open the PR vs. hand off manually, §4), gh-setup (whether to set up the gh CLI, offered once when gh is missing so the loop can automate PRs/issues), and feature-numbering (ticket id vs. PR number vs. plain sequential counter for the feature dir's numeric prefix, §1). Honor whatever it records without re-asking. If it's missing, that's fine — you'll create it the first time a recurring choice comes up.

Probe before you dive in. Continuously estimating the learner's knowledge is critical, and it starts before the first explanation. From the feature's intent and the code, list the domain concepts this work will actually require, and for each one the knowledge base doesn't already settle, ask — concisely and batched (one tab per concept in Claude Code; one concise, clearly separated chat prompt in Codex), then wait. For example, before building a Maven plugin: "Are you familiar with plugin.xml and Mojo objects (@Mojo / AbstractMojo)?" — rather than silently guessing and either boring or losing them. Record the answers into the knowledge base and let them set your opening depth.

Probe neutrally; never make explanation sound like a burden. Do not ask whether you should "keep it light," or imply that the developer needs to opt in to an explanation. Ask what they know and state that you will explain the decisions needed to reason about the code. For example: "How familiar are you with Angular standalone components and signals? I will walk through the choices as we build; tell me whether you want a refresher or a fundamentals-first explanation." Treat "I am not comfortable," "I am not familiar," or equivalent wording as new, never as permission to explain less.

A probe answer sets teaching depth, never the technical decision. What the developer knows changes how tersely you explain — it must never steer which approach you take. If they say they know Angular async pipes, that makes async pipes the cheap-to-teach option, not the one to avoid; do not swap to an unfamiliar approach "so they learn more." The choice of approach is driven by what's right for the code and the developer's intent — they are the architect — not by what they'd learn most from. Steering the design off someone's familiarity is a violation of their authorship; flag the honest tradeoff and let them choose.

Never infer fluency from authorship. That the developer wrote — or generated — the code you're touching does not mean they understand it. AI-generated / vibecoded code is exactly where the author is least fluent: they typed the intent, the model made the decisions. Git authorship tells you who committed it, not who can reason about it. So the default is to explain how it works and ask whether it is understood, not to skip on the basis of "they own this file." Fluency comes from being taught through the code (this loop), not from having produced it. Only the calibration profile or the developer's demonstrated engagement — never authorship — justifies skipping.

1. Declare the feature

Decide the feature-numbering mode — settled once, like §4's hand-off preference. Every feature dir is prefixed (<prefix>-<slug>) so features/ sorts and scans instead of reading as a flat pile. Which prefix to use is a recurring workflow choice, not a per-feature judgment call. Check ~/.fluencyloop/preferences.md (loaded in §0) for feature-numbering:

  • A preference is already recorded — honor it silently, and do not re-ask:

    • ticket — ask the developer for this feature's specific ticket/story id (e.g. JIRA-1234) and pass it as --prefix "<id>".
    • pr — declare with no --prefix (the sequential fallback numbers it for now); once the PR is opened in §4, run fluencyloop rename-feature-dir --json --pr <number> to swap the dir to carry the real PR number. The branch name never changes — only the docs dir.
    • sequential — declare with no --prefix; the built-in zero-padded counter handles it.
  • No preference yet (this is the first feature) — ask once, via the delivery rule in "Question delivery" above, in this order:

    1. "Does this feature track a story or ticket number (e.g. a JIRA id)?"Yes, use ticket numbers / No. On yes, record feature-numbering: ticket, then ask for this feature's specific id and pass --prefix "<id>".
    2. If no, and only if you can open GitHub PRs here (gh installed and authed — same check as §4): "Use the PR number as the numbering prefix instead?" — note plainly that the PR number isn't known until the PR exists, so the dir gets renamed afterward. Yes, number by PR (the dir gets renamed once the PR opens) / No, use sequential numbers. On yes, record feature-numbering: pr and proceed exactly as the pr branch above (declare with no --prefix now; rename after the PR opens in §4).
    3. Otherwise (no ticket, no gh, or declined both): record feature-numbering: sequential and declare with no --prefix.

    Persist the choice to ~/.fluencyloop/preferences.md (create it if absent — global, uncommitted, sibling to calibration.md) alongside any existing feature-handoff/gh-setup lines, e.g. feature-numbering: ticket · 2026-07-13. Never pose this question again once a mode is recorded.

Take the user's one-line intent. Run:

fluencyloop feature --json "<intent>"                      # sequential mode
fluencyloop feature --json --prefix "<ticket-id>" "<intent>"  # ticket mode

This creates the feature/<slug> branch (switching to it), the feature dir, and a design.md stub. Parse the JSON for slug, branch, design, sessions_dir. design and sessions_dir must be paths under docs/fluencyloop/; if either is not, stop and surface the runtime/path mismatch rather than writing fallback files. Never write design.md under .fluencyloop/.

2. Design (Stage 2) — diagrams first, shown not filed

Draft the two defaults from the intent and the codebase:

  • a class diagram (the shapes and their relationships), and
  • a sequence diagram (the main flow).

Show them rendered — don't just write a file and point at it. Publish the diagrams as a self-contained Artifact (a web page the user opens in a browser tab and actually sees) — load the artifact-design skill first. Artifacts render Mermaid natively — no CDN pull, no hand-authored SVG substitute needed. In the HTML page, put the exact same source that's going into design.md inside <pre class="mermaid">...</pre>. That specific wrapper is required: a ```mermaid fence, or a plain <pre><code> block, is left untouched by the renderer and shows up as literal text instead of a diagram. Byte-check before publishing: the file must be valid UTF-8 with no lone surrogates / U+FFFD and must JSON-round-trip (prefer pure ASCII in prose — HTML entities over literal dashes/box-drawing); publish only if the check is clean, or the deploy bounces. Then walk the user through what they're looking at and invite reactions — this is a conversation, not a handoff.

If the Artifact tool isn't available (the environment can't publish one, or the deploy keeps bouncing), say so explicitly — don't silently skip the visual-design step. If this surface can show a local self-contained inline-SVG/HTML preview, use that. Otherwise, attempt an ASCII rendering directly in chat before linking the durable document: use a fenced text block, only ASCII characters, and show the important nodes plus their relationships or message flow. This is a visual sketch derived from the diagram, not Mermaid source. If the full diagram is too complex for text, show the core topology and say what was omitted. Never paste a Mermaid fence as the substitute. Then point the user to the feature's design.md for GitHub/browser rendering.

Persist the same diagrams as Mermaid in design.md (blocks top-level, never nested in another fence, so GitHub renders them) — that's the durable, committed copy. The Artifact is the "see it now" view; design.md is the record.

GitHub's Mermaid parser is strict — a diagram that renders locally can still fail on github.com. Before committing, re-read every Note over/Note left/right of and arrow label for a bare ; — Mermaid treats ; as a statement terminator even inside note/label text, so Note over X: did the lookup; then called Y() silently truncates at the ; and the remainder parses as garbage (Parse error ... got 'INVALID'). Rewrite with a comma, dash, or <br/> line break instead of ;. If a diagram was just added or edited, paste its source into https://mermaid.live (or check for ; by eye) as a final check.

Refine once with the user's input. Check the design against the constitution — read docs/fluencyloop/constitution.md, and if it's a pointer (a Source of truth: line naming another file, e.g. .specify/memory/constitution.md), read that file for the real principles. If a shape conflicts with a principle, say so plainly; do not silently "fix" it.

Birth the constitution if it's still the empty stub. If it has no real principles yet and no plan ran to seed it, this first feature is the constitution's guaranteed backstop birth (planning is optional; this is not). From this feature's intent and the design conversation you just had, draft 3–5 initial principles — the checkable constraints and stances this work evidences, each a short title + the non-negotiable + the why (the failure it prevents). Show them, confirm, and write them into ## Principles numbered §1, §2, … (decisions will cite these numbers). Don't author cold or pad to a count — only what the work evidences; and if a real constitution already lives elsewhere (a Source of truth: pointer / SpecKit's .specify/memory/constitution.md), amend that in place rather than forking one. After birth it grows by harvest (§3).

Do not over-invest here: the design is a shape to build against, not a spec to ratify.

3. Build in slices (Stage 3) — teach at the boundary

Build the feature one meaningful slice at a time (a logical, commit-worthy chunk). Do not interrupt mid-thought. At each slice boundary:

  1. Review what you just built — from the slice, not the whole files. Run fluencyloop slice-context (add --json for the structured form) to get just this slice's changed hunks

    • metadata — the diff since the last journaled session, or the feature's base if none yet, with FluencyLoop's own files filtered out. Identify the one or two real decisions in it — a genuine fork where a reasonable alternative was rejected — from those hunks. Only open a full file when the hunks don't carry enough context to judge a decision; re-reading whole files by default is the token waste this replaces. Ignore non-decisions.

    Let the pre-filter gate the expensive pass. slice-context also emits likely_decision (with a decision_score and the decision_signals that fired — new dep/import, new API, control-flow, size). When it is false, don't spend a full teaching pass: glance at the hunks, and unless something is plainly a fork, journal the slice lightly (a one-line knowledge-transfer note, no decision block) and move on — this is how trivial slices stay near-zero cost. When it is true, run the full teach (step 2). The filter gates, it doesn't gag: a real decision you can plainly see in a low-scored slice still gets taught — but the default on a low score is light-touch, not deliberation.

  2. Teach the why — live, in the conversation. This is the during, so it happens here, as an exchange — not by writing the journal and telling the user to go read it (that's the after).

    How much you teach is a lookup, not a deliberation. Depth is a function of the developer's level in the decision's domain (from §0's profile) — apply this policy rather than re-deciding each time:

    level in the domainteach the decision like this
    fluentname it and move on — state the call in a clause; no why unless they ask.
    familiarone-line why — the decision plus its single load-bearing reason; don't unpack.
    learningunpack + ask whether it is understood — the why and the rejected alternative, then use the direct self-report check and wait.
    newunpack, slow down, offer to go deeper — build from fundamentals at a gentler pace, and explicitly offer to dig further.

    A decision spanning several domains takes the depth of its least-known one. This mapping is the payoff of calibration: it stops you deliberating about how much to teach (token-cheap) and pitches each decision to their real level (calibrated). The only things that lower depth are the calibration level and demonstrated engagementnever authorship (see below).

    For each decision, at the depth the policy sets:

    • Explain to that depth — for learning/new the why and the rejected alternative, right now; for familiar the one-line why; for fluent just name the call.
    • Anchor it to the rendered design diagram — point back to the Artifact from §2 and name the exact shape the decision concerns, so the why lands on something they can see, not just prose. If the decision changed the design, re-render and re-check the diagram.
    • Real questions must be unmistakable, never buried in prose. Any genuine question you put to the developer — a decision to sign off, a fork to choose, "which way do you want this?" — uses AskUserQuestion in Claude Code (one tab per decision/question). In Codex, ask it as a standalone, concise chat prompt and wait before continuing. (A rhetorical aside — "if that feels shaky, say so" — is not a real question; those stay inline.)
    • Pause and ask whether it is understood (where the policy calls for it — learning / new) — use only the direct self-report check above and wait for the answer before moving on. If the developer says no, ask what needs clarification and explain it; never test them with a topic-specific question. A monologue that ends in "see the journal" is the failure mode.
    • Calibrate continuously (see §0), but let the policy set depth. Hold a live estimate of what they know and update it every exchange: a quick confirmation is evidence of fluency (log a wave, §3.4); a surprised "wait, why?" or a follow-up is evidence it's shaky (log a deeper). That estimate moves the level — the depth policy above, not a fresh judgment call, then maps level → how much you teach. A sharp mismatch you may act on mid-slice (they're clearly lost on a fluent-tagged domain → drop to unpacking now), but the table is the default. Skip only what the calibration level or demonstrated engagement justifies — never skip because they authored the code. Name where knowledge ends and trust begins.
    • Tone: "This is the right call here — here's the one-line why. If A and B feel shaky, that's where to dig, but you don't need to right now to trust this." Not homework.
  3. Journal it (the byproduct, after the live teaching — not instead of it). Open (or create) the slice's session file:

    fluencyloop session --json --slug "<feature-slug>" "<slice intent>"
    

    Then record two things — you supply the content; the template's scaffolding is already there (all in comments, nothing to delete):

    • Knowledge transfer (you write this — it's irreducible) — under the session's ## Knowledge transfer headings, one bullet per component/role/mechanism: the subject, what it does and under what conditions, and status: documented / follow-up. Make it rich, not a token list: the roles and the non-obvious conditions, gotchas, and hard-won lessons (a bug's root cause, why something is done an odd way, a documented limitation) — the highest-value fluency. Separate from decisions (a role you explained is knowledge transfer even if no fork was chosen). About the work, never the person — no competence, prior knowledge, or "who learned what" (committed files, GDPR); the per-developer picture lives only in the calibration profile.

    • Decisions (the script formats them — you supply only the field values) — for each, run fluencyloop decision so the block is assembled deterministically; never hand-write the bullet schema:

      fluencyloop decision --title "chose X over Y" --where "<file/area>" --why "<the taught why>" \
        --alternative "<rejected option> — rejected: <why>" [--constitution §N] \
        [--design ../design.md#anchor] --trust unverified   # or: verified
      

      where is a file/area, never a line number; trust is about the decision, never the person — unverified unless you independently checked it.

  4. Log the engagement signal (cheap: one append, no level-guessing). Levels adapt from demonstrated engagement — you don't hand-edit them each slice. For each decision you just taught, judge how the developer engaged and append one signal per domain dimension it touched:

    Emit all of the slice's signals in a single command — pass the <dimension> <type> pairs together, so it's one shell call (one approval prompt), never one call per signal:

    fluencyloop calibration signal <dim1> <type1> [<dim2> <type2> ...]
    # e.g.  fluencyloop calibration signal maven wave junit wave spring deeper
    

    Levels and signals are different vocabularies. fluent, familiar, learning, and new are calibration levels; they are never valid signal types. A probe answer sets the opening level but emits no signal. Signal only a response after teaching: wave = waved the explanation through, deeper = asked to unpack it or showed confusion, correct = corrected the rationale or drove it. If there is no response after teaching, emit no signal. In particular, never run fluencyloop calibration signal <dimension> learning or new.

    For learning and new, first give the required substantive explanation and use AskUserQuestion for the direct self-report understanding check; then wait. Do not journal, run calibration, or continue implementation automatically. Only that later response can justify a signal. Appending is the whole job — trivial, and honest (it records what actually happened, not a guess). The deterministic fluencyloop calibration compact (run at the next feature's §0) rolls repeated signals into level changes: promote on repeated wave-throughs, demote on deeper-asks or corrections. This is how calibration adapts across features instead of resetting each session. (For a brand-new dimension, set its initial level from your §0 probe by editing the profile; ongoing movement comes from signals.) The ledger is global and uncommitted — never write person-specific knowledge into the repo.

  5. Harvest to the constitution (the growth beat — now the only ongoing way principles are added, so don't let it stay dormant). When a decision's why is a repeatable stance — a rule you'd apply again, not a one-off ("no synchronous cross-service calls in the request path", "config is validated at load, never at use") — offer to promote it to a constitution principle. Be assertive, and ask it as a form: put the candidate to the developer using the delivery rule above — name the proposed principle and offer Promote to §N vs Leave as a one-off — rather than a plain-text question they might skim past. Don't wait to be asked. On promote, append it to docs/fluencyloop/constitution.md under ## Principles as the next §N (short title + the non-negotiable + the why), and cite that §N in the decision's constitution: field. On leave, it stays a one-off — not a principle. This is how the constitution grows: harvested from real decisions, never a cold authoring pass.

Repeat per slice until the feature is built. The journal accretes as a byproduct — the developer never writes it by hand.

4. Hand off to review — settle the recurring choice once

When the feature is ready for a PR, tell the user they can run fluencyloop-review to assemble the reviewer-facing view from the sessions.

Check what's actually possible here first — run gh auth status. If gh isn't installed or authed, opening a PR isn't available yet. Don't just drop it: if preferences.md has no settled gh-setup choice, make the one-time offer to set gh up — sold on the fact that it lets you open the PR (and file plan issues) for them — using the delivery rule above (Yes, set it up (recommended) / Not now), recording gh-setup: done / gh-setup: declined. On yes, install from https://cli.github.com (pick the command that fits their OS — don't work from a hardcoded package-manager list) then gh auth login. If gh stays unavailable (declined or deferred), the hand-off is at most commit + push, and a PR can be opened later via fluencyloop-review. Only run the full commit + push + open-PR automation where gh works.

If feature-numbering: pr is recorded (§1), the moment a PR actually opens — whether you ran gh pr create here or the user opened it manually and told you the number — run fluencyloop rename-feature-dir --json --pr <number> to swap the feature's docs dir onto that number. The branch is untouched; only the dir (and design.md's recorded path references) move. If no PR ever gets opened for this feature, leave the dir as the sequential name it started with.

The hand-off is a behavioral pattern that recurs every feature — so decide it once, not once per feature. Check ~/.fluencyloop/preferences.md (loaded in §0):

  • A preference is already recorded — honor it silently, and do not re-ask. If it says automatic, go ahead and commit + push + open the PR yourself (run fluencyloop-review first) at completion; if manual, just point the user at fluencyloop-review and stop.

  • No preference yet (this is the first feature) — ask exactly once, via a single explicit confirmation using the delivery rule above rather than a per-feature prompt: from now on, should you commit

    • push (+ open the PR, when gh is available) yourself at feature completion, or keep handing off manually each time? (Drop the PR clause entirely if gh isn't available here.) Persist the answer to ~/.fluencyloop/preferences.md (create it — global, uncommitted, sibling to calibration.md) and honor it now and on every later feature. Never pose this per-feature question again. Format:
    # FluencyLoop preferences (per-developer, global, uncommitted)
    feature-handoff: automatic — commit + push + open PR at completion · 2026-07-13
    

More generally, at the end of the first feature: notice any hand-off you would otherwise repeat verbatim next time, and settle it with a single confirmation you record — never re-prompt for the same choice run after run.

Token budget (rough)

FluencyLoop is meant to be cheap to run. Treat these as smell tests, not hard caps:

  • Design (§2): skim the codebase to the shapes, not exhaustively — a few K tokens. You're sketching diagrams, not auditing.
  • Build, per slice (§3): read the slice context (the diff via slice-context), not whole files — typically a few hundred to ~2K tokens. If a slice's context balloons well past that, the slice is too big — split it. Open a full file only when a hunk lacks the context to judge a decision.
  • Review (§4): the assembled session journal (already distilled), not the code — ~1–2K.

Read loop state through the deterministic commands — slice-context --json, calibration show --json, check --json — which are cheap structured reads, not file scans or git re-derivation.

Rules

  • Never gate. You flag exposure and unverified trust; you never block building or merging.
  • Honesty over polish. A journaled why must be one the developer actually engaged with. If they waved a decision through, mark it trust: ⚠. Do not manufacture rationale.
  • Anchor every claim to code (where:) — file/area, so it survives refactoring.
  • Depth is a function of level, not whim. Probe the concepts a feature needs before diving in; then teach each decision to the depth policy in §3 (fluent → name it and move on … new → unpack, slow down, offer to go deeper). Your live estimate moves the level (logged as signals, §3.4; rolled up by calibration compact) — it does not re-decide depth ad hoc. Build and maintain the learner's profile in ~/.fluencyloop/calibration.md so fluency compounds across features. Person-specific knowledge lives only there (global, uncommitted) — never in the repo journal.
  • Settle recurring hand-offs once. A workflow choice you'd repeat verbatim every feature (e.g. auto commit + push + open PR vs. manual hand-off) is asked once, via a single confirmation, and persisted to ~/.fluencyloop/preferences.md (global, uncommitted) — then honored silently. Never re-prompt for the same choice feature after feature.
  • The developer stays the architect. Teach to keep them fluent; do not take authorship.

Alternatives

Compare before choosing