CtrlK
BlogDocsLog inGet started
Tessl Logo

spec-driven-devlopment/spec-as-source

Spec-driven development on OpenSpec, with mechanical spec-as-source enforcement: a custom 'spec-as-source' OpenSpec schema adds file-ownership (targets) and test-verification ([@test]) metadata to every capability spec, three scripts (link check, ownership check, manifest build) keep code and specs from drifting apart, plus requirement-gathering, spec-writer, work-review, and a session-handoff skill with a proactive context-warning hook.

73

Quality

92%

Does it follow best practices?

Impact

No eval scenarios have been run

SecuritybySnyk

Advisory

Suggest reviewing before use

Overview
Quality
Evals
Security
Files

SKILL.mdskills/prompt-loop/

name:
prompt-loop
description:
Refines an incoming prompt through a bounded score → interview → lock → rewrite loop until it is mechanically good enough (rubric score ≥ 9/10) to feed the SDD workflow. Trigger — automatically before openspec-propose when the request is non-trivial development work; explicitly on: refine this prompt, prompt loop, score my prompt, is this prompt ready.

Prompt Loop

Turn "is this prompt ready?" into a mechanical check. The loop scores the incoming prompt against a fixed rubric (templates/SCORING_RUBRIC.md), interviews the user on the weakest dimensions, locks confirmed answers, rewrites the prompt, and re-scores — repeating until the score crosses the threshold or the round cap is hit. The output is a refined prompt of verified quality that openspec-propose or openspec-explore can consume directly.

The loop is human-in-the-loop by nature: the user is present in every round. It never runs headless and it never produces downstream artifacts (proposal, spec, code) while refinement is still in progress.

Phase state machine

Each round moves through these phases in order. A phase is entered only when its entry condition holds and left only when its exit condition holds — no skipping except where a condition explicitly says so.

  1. Analyze
    • Entry: an incoming prompt exists (the user's request, quoted verbatim).
    • Work: read the prompt as-is; identify its objective, stated scope, constraints, and every slot that would require inventing a fact.
    • Exit: the prompt is understood well enough to score — no rewriting, no questions yet.
  2. Score
    • Entry: analyze is complete, or a rewrite from a previous round exists.
    • Work: score the current prompt revision against the five rubric dimensions in templates/SCORING_RUBRIC.md, quoting evidence for every score above 0, and total the result.
    • Exit: a total 0–10 exists and the rubric's decision tree maps it to the next action. Total ≥ 9 exits the loop entirely (see Stop criterion); otherwise continue to interview.
  3. Interview
    • Entry: the last score is below 9 and the round cap is not reached.
    • Work: ask the user questions derived from the lowest-scoring dimensions of this round.
    • Exit: the open questions of this round are answered (or the user declines to answer, which is itself recorded — never filled in).
  4. Lock
    • Entry: the user answered an interview question or confirmed a summary line.
    • Work: record each confirmed decision so no later round can reopen it.
    • Exit: every answer from this round's interview is locked.
  5. Rewrite
    • Entry: this round's answers are locked.
    • Work: produce a new prompt revision that integrates the answers and carries every locked decision forward unchanged. Missing information is marked n/a or left as an open question — never invented.
    • Exit: a complete new revision exists.
  6. Re-score
    • Entry: a new revision exists.
    • Work: return to phase 2 (Score) with the new revision; this closes the round and increments the round counter.
    • Exit: same as Score.

Stop criterion (mechanical)

The loop stops on the first of these, never on a feeling of "good enough":

  • Threshold reached — a scoring round totals 9 or more out of 10: exit refinement and produce the output contract.
  • Round cap reached — the round count hits the maximum (default 5) with the total still below 9: the loop MUST stop. On cap-out, report the residual gaps — which dimensions remain below 2 and why — and ask the user whether to proceed anyway with the best revision so far or abort. Never continue past the cap and never silently proceed as if the threshold had been met.

First-round pass

If the very first scoring of the incoming prompt totals 9 or more, skip the interview, lock, and rewrite phases entirely and go straight to the output contract. A prompt that is already good does not get five rounds of ceremony.

Interview phase: the requirement-gathering discipline

The interview phase absorbs the discipline of the requirement-gathering skill. Its hard rules are restated here in full so this skill is self-sufficient even when installed alone; consult requirement-gathering for question craft, but the rules below are binding on their own:

  1. ONE question at a time. Ask exactly one question per message. Never bundle several questions together, never present a questionnaire.
  2. Wait for the answer. Do not ask the next question until the user has answered the current one. If the user declines to answer, record the decline — the slot stays open or becomes n/a; it is never filled in.
  3. No downstream artifacts before the loop completes. While refinement is in progress, never run openspec-propose, never write a spec, and never write code. The loop must reach its stop criterion — and the user must confirm the output contract — before any downstream step starts.

Deriving the questions

Questions come from the rubric, not from generic checklists. After each scoring round:

  • Sort the five dimensions by score, lowest first.
  • Formulate questions only for the dimensions that scored below 2, starting with the lowest-scoring one. The evidence lines recorded during scoring say exactly what is missing or ambiguous — turn those gaps into questions.
  • Do not ask about dimensions already at 2, and never re-ask anything the user already answered (see the lock semantics).

Session document: the loop's state

The loop's state lives in a session document, not in conversation memory. At the start of a session, instantiate templates/PROMPT_SESSION.md and keep it current from then on — it is what makes locks enforceable and rounds auditable. The document is an artifact of the conversation (kept in the change-planning area or scratch space), not a repo deliverable.

Record every round in it as it happens:

  • the original prompt, quoted verbatim once at the top and never edited;
  • per round: the prompt revision (full text), the per-dimension scores with verbatim evidence quotes, and the open questions derived from the low-scoring dimensions;
  • earlier rounds are never rewritten or deleted — they are the audit trail.

Lock semantics

The ## Locked register in the session document is the loop's memory of what the user has decided. Its rules:

  1. Locks are verbatim. When the user answers an interview question or confirms a summary line, record the exact answer or approved line under ## Locked — not a paraphrase.
  2. Locks are carried forward unchanged. Every rewrite MUST reproduce every locked decision in the new revision exactly as locked, and later interview questions MUST NOT reopen or contradict a lock.
  3. Only the user can override a lock. If the user spontaneously contradicts a previously locked decision, record the new decision as a new lock marked as superseding the old one, and keep the old entry struck-through (~~old text~~ — superseded) for audit. Never delete a lock, and never treat your own reinterpretation as an override.

Anti-invention invariant (every phase)

Always active, in every phase of the loop — analyze, score, interview, lock, rewrite, re-score, and the final output contract alike:

Any information the loop needs but does not have is marked n/a or turned into an interview question — never invented, never assumed, never filled with a plausible default.

Concretely: a rewrite that would need a fact the user never provided marks the slot n/a or queues the fact as the next question; a score is never propped up by imagined context; an output-contract section with nothing confirmed to put in it says n/a rather than something plausible. When in doubt whether something was actually stated or confirmed, it was not — ask.

Output contract: the final phase

Entered only when the loop has stopped — the threshold was reached (or the first-round pass fired), or the round cap was hit and the user chose to proceed anyway. This phase turns the session into the artifact the SDD workflow consumes:

  1. Instantiate templates/REFINED_PROMPT.md and fill every section from the session document: the final prompt revision verbatim, scope in/out, core behavior, edge cases, constraints, capabilities touched, verification expectations, the final rubric score per dimension with its evidence quotes, and the complete lock register copied verbatim (superseded entries kept struck-through). A section with nothing confirmed to put in it says n/a — the anti-invention invariant applies here as everywhere.
  2. Present the document to the user for explicit confirmation. Show the filled document and ask the user to confirm it. This confirmation is a gate, not a courtesy: no downstream step runs until the user has explicitly approved the output contract. If the user requests changes, apply them (locking any new decisions) and present again.
  3. Hand off downstream. Once confirmed, pass the document as the input of openspec-propose (or openspec-explore when the user wants to think first). The lock register travels with it precisely so that downstream steps never re-ask a locked decision — everything the user already decided is settled; downstream questions may only cover genuinely new ground.

skills

README.md

tile.json