The step vocabulary
One project, one wording
Every step your project knows lives in a derived index, built from your files and your recorded caches, never maintained by hand:
The two sources matter:
- Files contribute the wording, including steps a teammate wrote yesterday that nobody has recorded yet. If completion only knew about recorded steps, two people writing files in parallel would still diverge.
- Caches contribute the status. Each suggestion carries a badge: ● recorded (replays at zero tokens), ● divergent (same text, different recordings: worth a look), ○ written but not recorded yet. You can see which steps are already paid for while you type.
saffron steps lists and searches this vocabulary from the CLI,
each step printed with its badge, usage count, and owning StepSet;
saffron steps --json exports it for tooling, and
saffron steps --snippets writes .vscode/saffron.code-snippets for
native VS Code completion with zero extension code (regenerate after
recording sessions).
Duplicate wording
Two layers attack pain #1 from both sides:
- Prevention (IDE): as you type a new step, near-duplicates of existing wording get a warning: "similar to 'I navigate to the home page': recorded, used in 4 scenarios", with a one-click rename. The suggestion popup helps the author who pauses; the warning catches the author who doesn't.
- Cure (runner, shipped): if a duplicate slips through and gets
recorded, Saffron compares the new recording against the index. Two
wordings that produced identical action lists are a duplicate
proven by behavior, not guessed by string similarity, the proposal
arrives with a rename feature-edit to the canonical wording plus an
adaptation note;
saffron accept --with-feature-editapplies it. Each duplicate costs exactly one recording, then the vocabulary converges. (No-op steps and divergent canonicals are excluded.)
That second trick is only possible in Saffron: Cucumber never observes what a step does, so it can never prove two wordings are the same.
Writing feature files with AI
The same vocabulary is served to machines, because in practice a lot of feature files are now written with an AI assistant in the loop:
saffron author <prose-file>(shipped), hand Saffron a plain-paragraph description; it drafts the.saffronfile with the step index injected as the required vocabulary and reports how many drafted lines reuse it. Live-validated: from two paragraphs it produced a file that reused every existing wording verbatim, invoked the existing StepSet instead of repeating its steps, and used doc strings for the note content: for $0.12, and recording it would be almost fully seeded. Review the draft, thensaffron runit.saffron mcp(shipped): a stdio MCP server exposingsearch_steps,list_step_setsandproject_status. Point your AI IDE (Claude Code, Cursor, Copilot) at it and any assistant writing files in your project speaks your vocabulary too: assistants can't read completion popups, so they get the index as context instead. Claude Code example:claude mcp add saffron -- npx saffron mcp.