StoryFlowSteps - Agent-oriented browser automation protocol for validating user story flows
npm install @overshift/sfsAn agent-oriented browser automation protocol for validating user story flows. SFS provides a high-level, natural language syntax for describing browser automation tests, designed to be executed by an AI agent using Playwright MCP.
- Agent-Oriented Design - Built for AI agents to understand context and make intelligent decisions
- Flexible Selectors - Supports explicit selectors with fuzzy fallback matching
- User Story Traceability - Each SFS file maps to a user story (US-XXX-001) for coverage tracking
- Natural Language Syntax - Commands read like human actions
- Multi-Environment Config - Environment layering for CI/staging/local
- Persona Management - Define user roles with environment-specific credentials
- Lifecycle Hooks - Complete session orchestration (before/after session, before/after each)
``bash`
npm install @sfs/cli
Requires Node.js >= 18.0.0
Initialize SFS in your project:
`bash`
npx sfs init
This creates:
- sfs.config.md - Base configurationexample.sfs
- - Example login flow.sfsignore
- - Coverage scan exclusions
`bash`
npx sfs run # Run all .sfs files
npx sfs run stories/US-SHOP-01a.sfs # Run specific file
npx sfs run "stories/*/.sfs" # Run with glob pattern
npx sfs run --env ci # Use CI-specific config
npx sfs run --headed # Show browser GUI
npx sfs run --verbose # Verbose output
`bash`
npx sfs validate stories/US-SHOP-01a.sfs
npx sfs validate "stories/*/.sfs"
`bash`
npx sfs coverage # Scan entire project, table output
npx sfs coverage -f json # JSON output for CI pipelines
npx sfs coverage -f summary # One-line summary
npx sfs coverage -s docs/stories # Scan only docs/stories directory
npx sfs coverage --story-pattern "JIRA-\d+" # Custom story ID pattern
By default, coverage scans the entire project (respecting .sfsignore exclusions). Use --stories
to restrict scope.SFS File Syntax
`sfs
STORY US-LOGIN-01a
ENTRYPOINT http://localhost:3000
LOCALE en-USHINT Standard login form with email and password fields
ON FAILURE capture screenshot and describe visible state
BEFORE THIS
ASSERT port 3000 is open
--- page-load ---
OBSERVE login form is visible
--- enter-credentials ---
TYPE "testuser@example.com" INTO email field >> selector:testid:email-input
TYPE "password123" INTO password field >> selector:testid:password-input
CAPTURE before-submit
--- submit-login ---
CLICK login button >> selector:testid:login-btn
WAIT FOR url contains /dashboard
--- verify-dashboard ---
OBSERVE dashboard content is visible
OBSERVE logout button is visible
DONE WHEN user is logged in and dashboard is visible
`$3
| Category | Commands |
|----------|----------|
| Interactions |
CLICK, TYPE, SELECT, DOUBLE CLICK, HOVER, SCROLL TO, UPLOAD, PRESS, CLEAR |
| Navigation | NAVIGATE TO, WAIT FOR |
| Observations | OBSERVE, CAPTURE, READ ... INTO $var |
| Tabs | TAB EXPECT NEW, TAB SWITCH TO, TAB CLOSE, TAB COUNT IS |
| Dialogs | ACCEPT DIALOG, DISMISS DIALOG |
| Assertions | ASSERT port, ASSERT env, ASSERT file |$3
Commands support explicit selectors with fuzzy fallback:
`sfs
CLICK login button # Fuzzy (agent resolves)
CLICK login button >> selector:testid:login-btn # Explicit with fallback
CLICK login button >> selector:css:.btn-login # CSS selector
CLICK login button >> selector:xpath://button[1] # XPath selector
CLICK login button >> selector:text:Log In # Text selector
`Configuration
$3
`markdown
SFS Configuration
Settings
| Setting | Value |
|---------|-------|
| ENTRYPOINT | http://localhost:3000 |
| LOCALE | en-US |
| TIMEOUT | 30s |
| ON FAILURE | capture screenshot |
| PRESERVE STATE ON FAILURE | true |
Personas
| Persona | Username | Password | Description |
|---------|----------|----------|-------------|
| user | testuser@example.com | {{TEST_USER_PASSWORD}} | Standard user |
| admin | admin@example.com | {{ADMIN_PASSWORD}} | Administrator |
| guest | | | Unauthenticated |
`$3
Control which directories are excluded from coverage scanning:
`
Comments start with #
node_modules
dist
build
vendor
*.log
docs/archive
`Bare names auto-expand to glob patterns (e.g.,
vendor becomes /vendor/). Built-in defaults (node_modules, .git, dist, build, coverage) always apply.$3
Configure custom story ID patterns in
sfs.config.md:`markdown
| STORY_ID_PATTERN | JIRA-\d+ |
`Or via CLI:
--story-pattern "JIRA-\d+"$3
Configuration files are merged in order:
`
sfs.config.md → Base configuration
sfs.config.{env}.md → Environment-specific (ci, staging)
sfs.config.local.md → Local overrides (gitignored)
`Project Structure
`
/stories/
sfs.config.md # Base config
sfs.config.ci.md # CI overrides
sfs.config.local.md # Local overrides (gitignored) US-SHOP-01/
US-SHOP-01a.sfs # Primary flow
US-SHOP-01a.edge.sfs # Edge cases
/runs/ # Test output (gitignored)
2024-02-04T14-30-00/
run.report.md
`Development
`bash
npm install # Install dependencies
npm run dev # Run in development
npm run build # Build
npm test # Run tests
npm run lint # Lint
npm run format # Format
`$3
This project uses a Definition of Done (DoD) quality gate that runs before each commit. The checks include:
Critical (must pass): build, test, lint, format
Warnings (informational): longfiles, knip, seccheck, audit
Run checks manually with npm scripts:
`bash
npm run dod # Run all checks (default)
npm run dod:all # Run all checks (explicit)
npm run dod:core # Run only critical checks (faster)
npm run dod:skip # Skip all checks
`Commit with check level control:
`bash
npm run commit:check -- -m "message" # All checks (default)
npm run commit:check:all -- -m "message" # All checks (explicit)
npm run commit:check:core -- -m "message" # Core checks only
npm run commit:check:skip -- -m "message" # Skip DoD checks
git commit --no-verify -m "message" # Skip all hooks
``- SFS Language Specification
- Configuration Specification
MIT