@fairfox/polly 0.82.1 → 0.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/polly.js +22 -1
- package/dist/cli/polly.js.map +3 -3
- package/dist/tools/bdd/src/args.d.ts +21 -0
- package/dist/tools/bdd/src/bus-driver.d.ts +36 -0
- package/dist/tools/bdd/src/check-verify.d.ts +15 -0
- package/dist/tools/bdd/src/cli.d.ts +2 -0
- package/dist/tools/bdd/src/cli.js +701 -0
- package/dist/tools/bdd/src/cli.js.map +19 -0
- package/dist/tools/bdd/src/config.d.ts +9 -0
- package/dist/tools/bdd/src/extract.d.ts +2 -0
- package/dist/tools/bdd/src/index.d.ts +19 -0
- package/dist/tools/bdd/src/index.js +540 -0
- package/dist/tools/bdd/src/index.js.map +17 -0
- package/dist/tools/bdd/src/parse.d.ts +3 -0
- package/dist/tools/bdd/src/report.d.ts +6 -0
- package/dist/tools/bdd/src/run.d.ts +8 -0
- package/dist/tools/bdd/src/scaffold.d.ts +7 -0
- package/dist/tools/bdd/src/steps.d.ts +55 -0
- package/dist/tools/bdd/src/types.d.ts +145 -0
- package/dist/tools/bdd/src/witness.d.ts +23 -0
- package/dist/tools/quality/src/cli.js +304 -15
- package/dist/tools/quality/src/cli.js.map +6 -4
- package/dist/tools/quality/src/index.d.ts +2 -0
- package/dist/tools/quality/src/index.js +309 -15
- package/dist/tools/quality/src/index.js.map +6 -4
- package/dist/tools/quality/src/no-fixed-waits.d.ts +52 -0
- package/dist/tools/quality/src/no-tautology-ensures.d.ts +67 -0
- package/dist/tools/quality/src/plugins/core.d.ts +1 -1
- package/dist/tools/test/src/tiers/cli.js +21 -1
- package/dist/tools/test/src/tiers/cli.js.map +3 -3
- package/dist/tools/verify/src/cli.js +521 -1
- package/dist/tools/verify/src/cli.js.map +8 -4
- package/package.json +7 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../tools/bdd/src/parse.ts", "../tools/bdd/src/steps.ts", "../tools/bdd/src/cli.ts", "../tools/bdd/src/args.ts", "../tools/bdd/src/check-verify.ts", "../tools/bdd/src/extract.ts", "../tools/bdd/src/config.ts", "../tools/bdd/src/report.ts", "../tools/bdd/src/run.ts", "../tools/bdd/src/scaffold.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Parse `.feature` files into the runner's normalized AST.\n *\n * Thin wrapper over `@cucumber/gherkin` (parser only — no cucumber runtime):\n * we keep our own {@link ParsedFeature} shape so the rest of the tool never\n * touches the gherkin message types, and swapping the parser stays a one-file\n * change. Responsibilities beyond raw parsing:\n * - normalize And/But to the preceding concrete keyword (Given/When/Then);\n * - fold Background steps into a feature-level list;\n * - expand each Scenario Outline into one concrete scenario per Examples row.\n */\nimport { AstBuilder, GherkinClassicTokenMatcher, Parser } from \"@cucumber/gherkin\";\nimport type { GherkinDocument, Scenario } from \"@cucumber/messages\";\nimport { IdGenerator } from \"@cucumber/messages\";\nimport type { ParsedFeature, ParsedScenario, ParsedStep, StepKeyword } from \"./types.ts\";\n\nfunction newParser() {\n return new Parser(new AstBuilder(IdGenerator.uuid()), new GherkinClassicTokenMatcher());\n}\n\n/** And/But inherit the previous concrete keyword; a leading And/But defaults to Given. */\nfunction normalizeKeyword(raw: string, prev: StepKeyword | null): StepKeyword {\n const k = raw.trim().toLowerCase();\n if (k === \"given\") return \"given\";\n if (k === \"when\") return \"when\";\n if (k === \"then\") return \"then\";\n return prev ?? \"given\";\n}\n\ninterface RawStep {\n keyword: string;\n text: string;\n location?: { line?: number };\n}\n\nfunction normalizeSteps(rawSteps: readonly RawStep[]): ParsedStep[] {\n const out: ParsedStep[] = [];\n let prev: StepKeyword | null = null;\n for (const s of rawSteps) {\n const keyword = normalizeKeyword(s.keyword, prev);\n prev = keyword;\n out.push({\n keyword,\n rawKeyword: s.keyword.trim(),\n text: s.text.trim(),\n line: s.location?.line ?? 0,\n });\n }\n return out;\n}\n\nfunction tagNames(tags: ReadonlyArray<{ name: string }> | undefined): string[] {\n return (tags ?? []).map((t) => t.name.replace(/^@/, \"\"));\n}\n\n/** Substitute `<placeholder>` cells from an Examples row into step text. */\nfunction fillOutline(text: string, headers: string[], cells: string[]): string {\n let filled = text;\n headers.forEach((h, i) => {\n filled = filled.split(`<${h}>`).join(cells[i] ?? \"\");\n });\n return filled;\n}\n\n/** A plain scenario, or one concrete scenario per Scenario Outline Examples row. */\nfunction buildScenarios(sc: Scenario): ParsedScenario[] {\n const baseSteps = sc.steps ?? [];\n const tags = tagNames(sc.tags);\n const examples = sc.examples ?? [];\n\n if (examples.length === 0) {\n return [\n { name: sc.name, tags, steps: normalizeSteps(baseSteps), line: sc.location?.line ?? 0 },\n ];\n }\n\n const out: ParsedScenario[] = [];\n for (const ex of examples) {\n const headers = (ex.tableHeader?.cells ?? []).map((c) => c.value);\n for (const row of ex.tableBody ?? []) {\n const cells = (row.cells ?? []).map((c) => c.value);\n const rowSteps = baseSteps.map((s) => ({\n keyword: s.keyword,\n text: fillOutline(s.text, headers, cells),\n location: s.location,\n }));\n const label = headers.map((h, i) => `${h}=${cells[i] ?? \"\"}`).join(\", \");\n out.push({\n name: `${sc.name} [${label}]`,\n tags: [...tags, ...tagNames(ex.tags)],\n steps: normalizeSteps(rowSteps),\n line: row.location?.line ?? sc.location?.line ?? 0,\n fromOutline: true,\n });\n }\n }\n return out;\n}\n\nexport function parseFeatureText(text: string, file: string): ParsedFeature {\n const doc: GherkinDocument = newParser().parse(text);\n const feature = doc.feature;\n if (!feature) {\n return { name: \"\", description: \"\", tags: [], background: [], scenarios: [], file };\n }\n\n let background: ParsedStep[] = [];\n const scenarios: ParsedScenario[] = [];\n\n for (const child of feature.children ?? []) {\n if (child.background) {\n background = normalizeSteps(child.background.steps ?? []);\n } else if (child.scenario) {\n scenarios.push(...buildScenarios(child.scenario));\n }\n }\n\n return {\n name: feature.name,\n description: (feature.description ?? \"\").trim(),\n tags: tagNames(feature.tags),\n background,\n scenarios,\n file,\n };\n}\n\nexport async function parseFeatureFile(path: string): Promise<ParsedFeature> {\n const text = await Bun.file(path).text();\n return parseFeatureText(text, path);\n}\n",
|
|
6
|
+
"/**\n * The step-binding registry and matcher.\n *\n * `defineStep()` is the consumer-facing keystone: one call registers a binding\n * that the runner executes (`given`/`when`/`then`) AND the verify extractor\n * reads (`message`/`stateExpr`). `defineWorld()` records how to build and\n * cold-reset the real-factory world.\n *\n * Patterns use a small Cucumber-expression subset: `{string}`, `{int}`,\n * `{float}`, `{word}`. Everything else is matched literally. That covers\n * declarative steps without dragging in the full cucumber-expressions library.\n *\n * The registry lives on `globalThis`, not in a module-level array, on purpose:\n * `polly bdd` ships as two bundles (the CLI and the `@fairfox/polly/bdd`\n * library export). `build-lib` runs with `splitting: false`, so this module is\n * *inlined separately into each bundle* — a module-level array would give the\n * runner and the consumer's `defineWorld` two different registries. A single\n * global slot is the standard cross-bundle-singleton fix.\n */\nimport type { StepBinding, StepKeyword, WorldDef } from \"./types.ts\";\n\ninterface CompiledBinding {\n binding: StepBinding;\n regex: RegExp;\n}\n\ninterface RegistryState {\n bindings: CompiledBinding[];\n worldDef: WorldDef | null;\n}\n\ndeclare global {\n // An ambient global declaration — `var` is the only legal form here.\n var __pollyBddRegistry__: RegistryState | undefined;\n}\n\nfunction state(): RegistryState {\n globalThis.__pollyBddRegistry__ ??= { bindings: [], worldDef: null };\n return globalThis.__pollyBddRegistry__;\n}\n\n/** Translate a Cucumber-expression pattern into an anchored RegExp. */\nexport function compilePattern(pattern: string): RegExp {\n // Escape regex metacharacters, then re-introduce capture groups for {tokens}.\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const withGroups = escaped\n // {string} — double- or single-quoted; capture the inner text. The\n // alternation MUST be wrapped in a non-capturing group, or the `|` would\n // bind to the whole pattern and shatter any step with two+ tokens.\n .replace(/\\\\\\{string\\\\\\}/g, `(?:\"([^\"]*)\"|'([^']*)')`)\n .replace(/\\\\\\{int\\\\\\}/g, \"([-+]?\\\\d+)\")\n .replace(/\\\\\\{float\\\\\\}/g, \"([-+]?\\\\d*\\\\.?\\\\d+)\")\n .replace(/\\\\\\{word\\\\\\}/g, \"([^\\\\s]+)\");\n return new RegExp(`^${withGroups}$`);\n}\n\nexport function defineStep(binding: StepBinding): void {\n state().bindings.push({ binding, regex: compilePattern(binding.pattern) });\n}\n\nexport function defineWorld(def: WorldDef): void {\n state().worldDef = def;\n}\n\nexport function getWorldDef(): WorldDef | null {\n return state().worldDef;\n}\n\n/** Drop all registrations — used between isolated runs/tests. */\nexport function resetRegistry(): void {\n const s = state();\n s.bindings.length = 0;\n s.worldDef = null;\n}\n\nexport interface StepMatch {\n binding: StepBinding;\n args: string[];\n}\n\n/**\n * Find the binding whose pattern matches `text`. Captured groups become the\n * step arguments (the `{string}` alternation yields two groups per token, so\n * we drop the undefined half).\n *\n * When `keyword` is given, a binding that *has* the callback for that keyword\n * wins over one that merely matches the text — so the same phrase can serve as\n * a `given` precondition in one scenario and a `then` assertion in another.\n */\nexport function matchStep(text: string, keyword?: StepKeyword): StepMatch | null {\n let textOnlyFallback: StepMatch | null = null;\n for (const { binding, regex } of state().bindings) {\n const m = regex.exec(text);\n if (!m) continue;\n const args = m.slice(1).filter((g) => g !== undefined);\n if (!keyword || binding[keyword]) return { binding, args };\n textOnlyFallback ??= { binding, args };\n }\n return textOnlyFallback;\n}\n\n/** Snapshot of all registered bindings (for the verify extractor). */\nexport function registeredBindings(): StepBinding[] {\n return state().bindings.map((c) => c.binding);\n}\n",
|
|
7
|
+
"#!/usr/bin/env bun\n/**\n * `polly bdd` — author and run executable Gherkin against polly's own model.\n *\n * BDD is polly's third verification stratum. verify (TLA+) proves invariants\n * over the handler state machine; mutate (Stryker) proves the tests have teeth;\n * BDD pins down what a feature should do *from the user's perspective*, as\n * concrete examples that run across the real factory boundary. A Gherkin\n * scenario decomposes onto the same vocabulary the other two already speak:\n * Given = state signals, When = a message type, Then = an observable outcome.\n *\n * Thin verb dispatcher over the reusable functions in this directory.\n */\nimport { resolve } from \"node:path\";\nimport { parseBddArgs } from \"./args.ts\";\nimport { checkAgainstVerify } from \"./check-verify.ts\";\nimport { resolveBddConfig } from \"./config.ts\";\nimport { formatRun, toJson } from \"./report.ts\";\nimport { runFeatures } from \"./run.ts\";\nimport { scaffoldFeature } from \"./scaffold.ts\";\n\nconst HELP = `polly bdd — executable Gherkin against polly's handlers + state\n\nThree-amigos sessions produce acceptance examples from the user's perspective;\nthis runs them across the real factory boundary and cross-checks them against\nthe verification config — so the example layer, the formal layer, and the\nmutation layer all describe the same handlers and state.\n\nUsage:\n polly bdd [run] [path] Run .feature files (default: features/**/*.feature)\n polly bdd check Cross-check scenarios against specs/verification.config.ts\n polly bdd new <name> Scaffold a feature stub seeded from the verify vocabulary\n polly bdd help Show this help\n\nFlags:\n --features <glob> feature files (default: features/**/*.feature)\n --steps <glob> step modules to load (default: features/**/*.steps.ts + features/steps.ts)\n --tags <tag> only run scenarios with this tag (~tag negates)\n --json machine-readable output\n -h, --help\n\nScenarios tagged @formal cover precondition-only behaviour (requires() is a\nruntime no-op) — the runner defers them; 'polly verify' checks them, since the\nrequires() guard is extracted into the TLA+ model.`;\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: a flat verb dispatcher — the branches are the command surface.\nasync function main(): Promise<number> {\n const args = parseBddArgs(process.argv.slice(2));\n if (args.help || args.verb === \"help\") {\n console.log(HELP);\n return 0;\n }\n\n const cwd = process.cwd();\n\n switch (args.verb) {\n case \"run\": {\n const cfg = await resolveBddConfig(cwd, args);\n if (cfg.featureFiles.length === 0) {\n console.log(\"No .feature files found (looked for features/**/*.feature).\");\n return 1;\n }\n if (cfg.stepFiles.length === 0) {\n console.log(\n \"No step modules found (looked for features/**/*.steps.ts and features/steps.ts).\"\n );\n return 1;\n }\n const result = await runFeatures({\n featureFiles: cfg.featureFiles,\n stepFiles: cfg.stepFiles,\n tagFilter: args.tags,\n });\n console.log(args.json ? toJson(result) : formatRun(result, cwd));\n return result.ok ? 0 : 1;\n }\n\n case \"check\": {\n const cfg = await resolveBddConfig(cwd, args);\n const configPath = resolve(cwd, \"specs\", \"verification.config.ts\");\n const result = await checkAgainstVerify({\n featureFiles: cfg.featureFiles,\n stepFiles: cfg.stepFiles,\n configPath,\n });\n if (args.json) {\n console.log(JSON.stringify(result, null, 2));\n return result.ok ? 0 : 1;\n }\n console.log(`\\nCross-checked ${result.checked} scenario(s) against the verification config:`);\n if (result.findings.length === 0) {\n console.log(\" ✓ every When models a real message; every Given/Then names a tracked field\");\n }\n for (const f of result.findings) {\n console.log(` ${f.kind === \"error\" ? \"✗\" : \"⚠\"} ${f.scenario}\\n ${f.message}`);\n }\n console.log(result.ok ? \"\\n✓ BDD ↔ verify cross-check holds.\" : \"\\n✗ Cross-check failed.\");\n return result.ok ? 0 : 1;\n }\n\n case \"new\": {\n const name = args.rest.join(\" \").trim();\n if (!name) {\n console.log(\"usage: polly bdd new <feature name>\");\n return 1;\n }\n const configPath = resolve(cwd, \"specs\", \"verification.config.ts\");\n const res = await scaffoldFeature(cwd, name, configPath);\n if (!res.created) {\n console.log(`${res.featurePath} already exists.`);\n return 1;\n }\n console.log(`✓ wrote ${res.featurePath}`);\n console.log(\n ` seeded from ${res.messages.length} message type(s), ${res.fields.length} state field(s)`\n );\n console.log(\"\\nNext: bind the steps in features/steps.ts, then 'polly bdd run'.\");\n return 0;\n }\n\n default:\n console.log(`Unknown subcommand: ${args.verb}\\n`);\n console.log(HELP);\n return 1;\n }\n}\n\nmain()\n .then((code) => process.exit(code))\n .catch((err) => {\n console.log(`\\n❌ ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n });\n",
|
|
8
|
+
"/**\n * Argument parsing for `polly bdd`. Flat verb dispatcher, mirroring the shape\n * of `tools/mutate/src/args.ts`.\n */\nexport interface BddArgs {\n /** First positional: \"run\" | \"check\" | \"new\" (default \"run\"). */\n verb: string;\n /** Positionals after the verb (e.g. a feature path, or a new feature name). */\n rest: string[];\n /** --features <glob> override. */\n features?: string;\n /** --steps <glob> override. */\n steps?: string;\n /** --tags <expr> filter (plain tag name, optionally prefixed ~ to negate). */\n tags?: string;\n /** --json machine-readable output. */\n json: boolean;\n /** -h / --help. */\n help: boolean;\n}\n\nconst VALUE_FLAGS = new Set([\"--features\", \"--steps\", \"--tags\"]);\n\nexport function parseBddArgs(argv: string[]): BddArgs {\n const positionals: string[] = [];\n const flags = new Map<string, string>();\n const bools = new Set<string>();\n\n let i = 0;\n while (i < argv.length) {\n const a = argv[i] ?? \"\";\n if (VALUE_FLAGS.has(a)) {\n flags.set(a, argv[i + 1] ?? \"\");\n i += 2;\n } else {\n if (a.startsWith(\"-\")) bools.add(a);\n else positionals.push(a);\n i += 1;\n }\n }\n\n return {\n verb: positionals[0] ?? \"run\",\n rest: positionals.slice(1),\n features: flags.get(\"--features\"),\n steps: flags.get(\"--steps\"),\n tags: flags.get(\"--tags\"),\n json: bools.has(\"--json\"),\n help: bools.has(\"--help\") || bools.has(\"-h\"),\n };\n}\n",
|
|
9
|
+
"/**\n * The verify cross-link, half two: hold every scenario trace against the\n * verification config — the always-on, static, cheap gate (`polly bdd check`).\n * The deeper TLC reachability *witness* rides `polly verify --witness`\n * (tools/verify); this file never runs a model checker.\n *\n * Three checks, each the BDD analogue of a verify guarantee:\n * 1. every `When` message type is one the config actually models (and so has\n * a handler the model knows about) — a scenario that drives a phantom\n * message is a scenario about nothing;\n * 2. every `Given`/`Then` state expression names a field the config tracks —\n * an assertion on an unmodeled field can't be cross-checked or verified;\n * 3. every feature that filters/selects/validates carries a negative\n * complement (a scenario tagged `@negative` or `@formal`) — the mechanical\n * enforcer of the Tester's \"prove the system also says no\" rule, which is\n * exactly what mutation testing then makes teeth on.\n */\nimport { resolve } from \"node:path\";\nimport { extractTraces } from \"./extract.ts\";\nimport type { ScenarioTrace } from \"./types.ts\";\n\nexport interface Finding {\n kind: \"error\" | \"warn\";\n scenario: string;\n message: string;\n}\n\nexport interface CrossCheckResult {\n ok: boolean;\n checked: number;\n findings: Finding[];\n}\n\ninterface VerifyConfigShape {\n state?: Record<string, unknown>;\n messages?: { include?: string[]; perMessageBounds?: Record<string, number> };\n subsystems?: Record<string, { state?: string[]; handlers?: string[] }>;\n}\n\nasync function loadVerifyConfig(configPath: string): Promise<VerifyConfigShape> {\n const mod = await import(`file://${resolve(configPath)}?t=${Bun.nanoseconds()}`);\n const config = mod.verificationConfig ?? mod.default;\n if (!config) throw new Error(`no verificationConfig/default export in ${configPath}`);\n return config as VerifyConfigShape;\n}\n\n/** Union of every message type the config models. */\nfunction messageSet(config: VerifyConfigShape): Set<string> {\n const set = new Set<string>();\n for (const t of config.messages?.include ?? []) set.add(t);\n for (const t of Object.keys(config.messages?.perMessageBounds ?? {})) set.add(t);\n for (const sub of Object.values(config.subsystems ?? {})) {\n for (const h of sub.handlers ?? []) set.add(h);\n }\n return set;\n}\n\n/** Every state field key the config tracks. */\nfunction stateKeys(config: VerifyConfigShape): string[] {\n const keys = new Set(Object.keys(config.state ?? {}));\n for (const sub of Object.values(config.subsystems ?? {})) {\n for (const f of sub.state ?? []) keys.add(f);\n }\n return [...keys];\n}\n\n/** Dotted identifier paths in an expression, minus string literals and keywords. */\nfunction fieldsIn(expr: string): string[] {\n const noStrings = expr.replace(/\"[^\"]*\"|'[^']*'/g, \"\");\n const ids = noStrings.match(/[a-zA-Z_$][\\w$]*(?:\\.[a-zA-Z_$][\\w$]*)*/g) ?? [];\n const ignore = new Set([\"true\", \"false\", \"null\", \"undefined\", \"length\", \"value\"]);\n return ids.filter((id) => !ignore.has(id) && Number.isNaN(Number(id)));\n}\n\n/** A field matches a config key if either is a dotted prefix of the other. */\nfunction fieldKnown(field: string, keys: string[]): boolean {\n return keys.some((k) => k === field || field.startsWith(`${k}.`) || k.startsWith(`${field}.`));\n}\n\nconst NEGATIVE_TAGS = new Set([\"negative\", \"formal\"]);\n\nfunction checkTrace(\n trace: ScenarioTrace,\n messages: Set<string>,\n keys: string[],\n findings: Finding[]\n): void {\n const id = `${trace.feature} › ${trace.scenario}`;\n\n for (const step of [...trace.given, ...trace.when, ...trace.then]) {\n if (step.unbound) {\n findings.push({ kind: \"warn\", scenario: id, message: `step has no binding: \"${step.text}\"` });\n }\n }\n\n for (const step of trace.when) {\n if (step.message && !messages.has(step.message)) {\n findings.push({\n kind: \"error\",\n scenario: id,\n message: `When sends \"${step.message}\", which the verification config does not model`,\n });\n }\n }\n\n for (const step of [...trace.given, ...trace.then]) {\n if (!step.stateExpr) continue;\n for (const field of fieldsIn(step.stateExpr)) {\n if (!fieldKnown(field, keys)) {\n findings.push({\n kind: \"error\",\n scenario: id,\n message: `${step.keyword} asserts on \"${field}\", absent from the config's state map`,\n });\n }\n }\n }\n}\n\n/** A feature filters/selects/validates if any Then mentions an exclusion/limit notion. */\nfunction featureNeedsNegative(traces: ScenarioTrace[]): boolean {\n return traces.some((t) =>\n t.then.some((s) => /\\bnot\\b|exclud|reject|empty|invalid|limit|forbidden/i.test(s.text))\n );\n}\n\nfunction checkNegativeComplement(traces: ScenarioTrace[], findings: Finding[]): void {\n const byFeature = new Map<string, ScenarioTrace[]>();\n for (const t of traces) {\n const arr = byFeature.get(t.feature) ?? [];\n arr.push(t);\n byFeature.set(t.feature, arr);\n }\n for (const [feature, group] of byFeature) {\n const hasNegative = group.some((t) => t.tags.some((tag) => NEGATIVE_TAGS.has(tag)));\n if (!hasNegative && featureNeedsNegative(group)) {\n findings.push({\n kind: \"warn\",\n scenario: feature,\n message:\n \"feature filters/selects/validates but has no negative complement (a @negative or @formal scenario) — an over-permissive build would still pass\",\n });\n }\n }\n}\n\nexport async function checkAgainstVerify(opts: {\n featureFiles: string[];\n stepFiles: string[];\n configPath: string;\n}): Promise<CrossCheckResult> {\n const config = await loadVerifyConfig(opts.configPath);\n const messages = messageSet(config);\n const keys = stateKeys(config);\n\n const traces = await extractTraces(opts.featureFiles, opts.stepFiles);\n const findings: Finding[] = [];\n\n for (const trace of traces) checkTrace(trace, messages, keys, findings);\n checkNegativeComplement(traces, findings);\n\n return {\n ok: findings.every((f) => f.kind !== \"error\"),\n checked: traces.length,\n findings,\n };\n}\n",
|
|
10
|
+
"/**\n * The verify cross-link, half one: reduce each scenario to a {@link ScenarioTrace}\n * over the *same vocabulary the verification config speaks* — Given (initial\n * state exprs) → When (message types) → Then (state exprs).\n *\n * This is to `.feature` files what `extractCondition` (tools/analysis) is to a\n * `requires()` call: it reads the statically-declared `message`/`stateExpr`\n * metadata off each matched step binding and hands check-verify a structure it\n * can compare against the config and the TLA+ model. Steps that match no\n * binding are kept as `unbound` so gaps are visible rather than silently empty.\n */\nimport { parseFeatureFile } from \"./parse.ts\";\nimport { matchStep, resetRegistry } from \"./steps.ts\";\nimport type { ScenarioTrace, TraceStep } from \"./types.ts\";\n\nasync function loadStepModules(stepFiles: string[]): Promise<void> {\n resetRegistry();\n for (const file of stepFiles) {\n await import(`${file}?t=${Bun.nanoseconds()}`);\n }\n}\n\nfunction toTraceStep(text: string, keyword: TraceStep[\"keyword\"]): TraceStep {\n const match = matchStep(text, keyword);\n if (!match) return { text, keyword, unbound: true };\n return {\n text,\n keyword,\n message: match.binding.message,\n stateExpr: match.binding.stateExpr,\n };\n}\n\nexport async function extractTraces(\n featureFiles: string[],\n stepFiles: string[]\n): Promise<ScenarioTrace[]> {\n await loadStepModules(stepFiles);\n const traces: ScenarioTrace[] = [];\n\n for (const file of featureFiles) {\n const feature = await parseFeatureFile(file);\n for (const scenario of feature.scenarios) {\n const allSteps = [...feature.background, ...scenario.steps];\n const trace: ScenarioTrace = {\n feature: feature.name,\n scenario: scenario.name,\n tags: [...feature.tags, ...scenario.tags],\n given: [],\n when: [],\n // biome-ignore lint/suspicious/noThenProperty: `then` is Gherkin vocabulary here, not a thenable.\n then: [],\n file,\n };\n for (const step of allSteps) {\n trace[step.keyword].push(toTraceStep(step.text, step.keyword));\n }\n traces.push(trace);\n }\n }\n return traces;\n}\n",
|
|
11
|
+
"/**\n * Resolve the feature files and step modules `polly bdd` operates on, relative\n * to the cwd it was invoked from — so a consumer's project tree works the same\n * as this repo. Convention (overridable with --features / --steps):\n * - features: features/**\\/*.feature\n * - steps: features/**\\/*.steps.ts + features/steps.ts\n * A positional path narrows the feature glob to a single file or directory.\n */\nimport { resolve } from \"node:path\";\nimport { Glob } from \"bun\";\nimport type { BddArgs } from \"./args.ts\";\n\nexport interface BddConfig {\n cwd: string;\n /** Absolute paths of `.feature` files to run. */\n featureFiles: string[];\n /** Absolute paths of step-definition modules to import (side-effect registration). */\n stepFiles: string[];\n}\n\nasync function expand(cwd: string, pattern: string): Promise<string[]> {\n const out: string[] = [];\n for await (const f of new Glob(pattern).scan({ cwd, absolute: true, onlyFiles: true })) {\n out.push(f);\n }\n return out.sort();\n}\n\nexport async function resolveBddConfig(cwd: string, args: BddArgs): Promise<BddConfig> {\n // A positional path (verb's first rest arg for `run`) narrows the features.\n const pathArg = args.verb === \"run\" ? args.rest[0] : undefined;\n\n let featurePattern = args.features ?? \"features/**/*.feature\";\n if (pathArg) {\n featurePattern = pathArg.endsWith(\".feature\")\n ? pathArg\n : `${pathArg.replace(/\\/$/, \"\")}/**/*.feature`;\n }\n\n const stepPatterns = args.steps ? [args.steps] : [\"features/**/*.steps.ts\", \"features/steps.ts\"];\n\n const featureFiles = pathArg?.endsWith(\".feature\")\n ? [resolve(cwd, pathArg)]\n : await expand(cwd, featurePattern);\n\n const stepSets = await Promise.all(stepPatterns.map((p) => expand(cwd, p)));\n const stepFiles = [...new Set(stepSets.flat())];\n\n return { cwd, featureFiles, stepFiles };\n}\n",
|
|
12
|
+
"/**\n * Human- and machine-readable formatting of a {@link RunResult}.\n */\nimport type { RunResult, ScenarioResult } from \"./types.ts\";\n\nconst MARK: Record<ScenarioResult[\"outcome\"], string> = {\n pass: \"✓\",\n fail: \"✗\",\n undefined: \"?\",\n \"deferred-formal\": \"→\",\n};\n\nfunction relFile(file: string, cwd: string): string {\n return file.startsWith(cwd) ? file.slice(cwd.length + 1) : file;\n}\n\n/** The detail lines under a failed/undefined/deferred scenario. */\nfunction scenarioDetail(s: ScenarioResult): string[] {\n if (s.outcome === \"deferred-formal\") {\n return [\n \" deferred to polly verify — precondition is formal-only (requires() is a runtime no-op)\",\n ];\n }\n if (s.outcome !== \"fail\" && s.outcome !== \"undefined\") return [];\n const lines: string[] = [];\n for (const step of s.steps) {\n if (step.outcome !== \"fail\" && step.outcome !== \"undefined\") continue;\n lines.push(` ${step.outcome === \"fail\" ? \"✗\" : \"?\"} ${step.rawKeyword} ${step.text}`);\n if (step.message) lines.push(` ↳ ${step.message}`);\n }\n return lines;\n}\n\nexport function formatRun(result: RunResult, cwd: string): string {\n const lines: string[] = [];\n let currentFeature = \"\";\n\n for (const s of result.scenarios) {\n if (s.feature !== currentFeature) {\n currentFeature = s.feature;\n lines.push(`\\nFeature: ${s.feature} (${relFile(s.file, cwd)})`);\n }\n lines.push(` ${MARK[s.outcome]} ${s.scenario}`);\n lines.push(...scenarioDetail(s));\n }\n\n lines.push(\"\");\n lines.push(\n `${result.ok ? \"✓\" : \"✗\"} ${result.passed} passed, ${result.failed} failed, ` +\n `${result.undefinedSteps} undefined, ${result.deferred} deferred (formal)`\n );\n return lines.join(\"\\n\");\n}\n\nexport function toJson(result: RunResult): string {\n return JSON.stringify(result, null, 2);\n}\n",
|
|
13
|
+
"/**\n * The runtime engine: parse features, load step modules, drive each scenario\n * against the *real* factory world the consumer built in `defineWorld`.\n *\n * What this stratum can and cannot check is deliberate. Runtime BDD asserts on\n * *observable* behaviour — state-signal changes and the response a handler\n * returns. Polly's `requires()` preconditions are runtime no-ops (they exist\n * only for the TLA+ model), so a precondition-only negative (e.g. \"a guest\n * login is rejected\") is NOT runtime-observable. Tag those `@formal`: the\n * runner defers them with a clear note, and `polly verify` is where they're\n * actually checked — the `requires()` guard is extracted into the TLA+ model.\n * This is the three strata dividing the work.\n */\nimport { parseFeatureFile } from \"./parse.ts\";\nimport { getWorldDef, matchStep, resetRegistry } from \"./steps.ts\";\nimport type {\n ParsedFeature,\n ParsedScenario,\n ParsedStep,\n RunResult,\n ScenarioResult,\n StepResult,\n World,\n} from \"./types.ts\";\n\nconst FORMAL_TAG = \"formal\";\n\nexport interface RunOptions {\n featureFiles: string[];\n stepFiles: string[];\n /** Only run scenarios carrying this tag (without leading @); ~tag negates. */\n tagFilter?: string;\n}\n\n/** Import each step module so its `defineStep`/`defineWorld` side effects run. */\nasync function loadStepModules(stepFiles: string[]): Promise<void> {\n resetRegistry();\n for (const file of stepFiles) {\n // Cache-bust so repeated in-process runs re-register cleanly.\n await import(`${file}?t=${Bun.nanoseconds()}`);\n }\n}\n\nfunction tagMatches(tags: string[], filter?: string): boolean {\n if (!filter) return true;\n if (filter.startsWith(\"~\")) return !tags.includes(filter.slice(1));\n return tags.includes(filter);\n}\n\nasync function runStep(world: World, step: ParsedStep): Promise<StepResult> {\n const base = { text: step.text, rawKeyword: step.rawKeyword };\n const match = matchStep(step.text, step.keyword);\n if (!match) {\n return { ...base, outcome: \"undefined\", message: `no binding matches \"${step.text}\"` };\n }\n const fn = match.binding[step.keyword];\n if (!fn) {\n return {\n ...base,\n outcome: \"undefined\",\n message: `binding for \"${step.text}\" has no '${step.keyword}' callback`,\n };\n }\n try {\n const ret = await fn(world, ...match.args);\n // A `when` that returns the send promise gets its response captured.\n if (ret !== undefined) world.lastResponse = ret;\n return { ...base, outcome: \"pass\" };\n } catch (err) {\n world.lastError = err;\n return { ...base, outcome: \"fail\", message: err instanceof Error ? err.message : String(err) };\n }\n}\n\nasync function runScenario(\n world: World,\n feature: ParsedFeature,\n scenario: ParsedScenario,\n reset: (w: World) => void | Promise<void>\n): Promise<ScenarioResult> {\n const result: ScenarioResult = {\n feature: feature.name,\n scenario: scenario.name,\n tags: scenario.tags,\n outcome: \"pass\",\n steps: [],\n file: feature.file,\n };\n\n // Cold start: reset the world (signals → initial) and clear per-scenario scratch.\n await reset(world);\n world.vars = {};\n world.lastResponse = undefined;\n world.lastError = undefined;\n\n const steps = [...feature.background, ...scenario.steps];\n let aborted = false;\n for (const step of steps) {\n if (aborted) {\n result.steps.push({ text: step.text, rawKeyword: step.rawKeyword, outcome: \"skipped\" });\n continue;\n }\n const sr = await runStep(world, step);\n result.steps.push(sr);\n if (sr.outcome === \"fail\") {\n result.outcome = \"fail\";\n aborted = true;\n } else if (sr.outcome === \"undefined\") {\n result.outcome = result.outcome === \"fail\" ? \"fail\" : \"undefined\";\n aborted = true;\n }\n }\n return result;\n}\n\nexport async function runFeatures(options: RunOptions): Promise<RunResult> {\n await loadStepModules(options.stepFiles);\n\n const worldDef = getWorldDef();\n if (!worldDef) {\n throw new Error(\n \"no world defined. A step module must call defineWorld({ create, reset }) — see tools/bdd/README.md.\"\n );\n }\n const world = await worldDef.create();\n\n const features = await Promise.all(options.featureFiles.map((f) => parseFeatureFile(f)));\n const scenarios: ScenarioResult[] = [];\n\n for (const feature of features) {\n for (const scenario of feature.scenarios) {\n const tags = [...feature.tags, ...scenario.tags];\n if (!tagMatches(tags, options.tagFilter)) continue;\n\n if (tags.includes(FORMAL_TAG)) {\n scenarios.push({\n feature: feature.name,\n scenario: scenario.name,\n tags,\n outcome: \"deferred-formal\",\n steps: [],\n file: feature.file,\n });\n continue;\n }\n scenarios.push(await runScenario(world, feature, { ...scenario, tags }, worldDef.reset));\n }\n }\n\n const passed = scenarios.filter((s) => s.outcome === \"pass\").length;\n const failed = scenarios.filter((s) => s.outcome === \"fail\").length;\n const undef = scenarios.filter((s) => s.outcome === \"undefined\").length;\n const deferred = scenarios.filter((s) => s.outcome === \"deferred-formal\").length;\n\n return {\n scenarios,\n passed,\n failed,\n undefinedSteps: undef,\n deferred,\n ok: failed === 0 && undef === 0,\n };\n}\n",
|
|
14
|
+
"/**\n * `polly bdd new <feature>` — scaffold a `.feature` stub seeded from the\n * project's verification config, so a three-amigos session starts from polly's\n * real ubiquitous language (the message types and state fields the model\n * already tracks) instead of inventing terms. The session's job is to turn\n * those into declarative scenarios; this just lays the table.\n */\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\ninterface ConfigShape {\n state?: Record<string, unknown>;\n messages?: { include?: string[]; perMessageBounds?: Record<string, number> };\n subsystems?: Record<string, { handlers?: string[] }>;\n}\n\nasync function loadVocabulary(\n configPath: string\n): Promise<{ messages: string[]; fields: string[] }> {\n if (!existsSync(configPath)) return { messages: [], fields: [] };\n const mod = await import(`file://${resolve(configPath)}?t=${Bun.nanoseconds()}`);\n const config: ConfigShape = mod.verificationConfig ?? mod.default ?? {};\n const messages = new Set<string>();\n for (const t of config.messages?.include ?? []) messages.add(t);\n for (const t of Object.keys(config.messages?.perMessageBounds ?? {})) messages.add(t);\n for (const sub of Object.values(config.subsystems ?? {})) {\n for (const h of sub.handlers ?? []) messages.add(h);\n }\n return { messages: [...messages].sort(), fields: Object.keys(config.state ?? {}).sort() };\n}\n\nfunction slug(name: string): string {\n return name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\nexport interface ScaffoldResult {\n created: boolean;\n featurePath: string;\n messages: string[];\n fields: string[];\n}\n\nexport async function scaffoldFeature(\n cwd: string,\n name: string,\n configPath: string\n): Promise<ScaffoldResult> {\n const { messages, fields } = await loadVocabulary(configPath);\n const featurePath = resolve(cwd, \"features\", `${slug(name)}.feature`);\n\n if (existsSync(featurePath)) {\n return { created: false, featurePath, messages, fields };\n }\n\n const body = `Feature: ${name}\n # Three-amigos: state the user story, then converge on declarative scenarios.\n # As a <role> I want <capability> so that <benefit>.\n #\n # Bind each step in features/steps.ts. The dual-use binding carries formal\n # metadata so 'polly bdd check' can cross-check it against the verify config:\n # When-steps declare \\`message\\` (a modeled message type)\n # Given/Then-steps declare \\`stateExpr\\` (a tracked state field)\n #\n # Message types this project models:\n${messages.map((m) => ` # - ${m}`).join(\"\\n\") || \" # (none found — is specs/verification.config.ts present?)\"}\n # State fields this project tracks:\n${fields.map((f) => ` # - ${f}`).join(\"\\n\") || \" # (none found)\"}\n\n Scenario: <name the behaviour by its outcome>\n Given <context that is already true>\n When <a single action>\n Then <an observable outcome>\n\n @negative\n Scenario: <the negative complement — what is excluded / rejected / empty>\n Given <context>\n When <a single action>\n Then <the system observably says no>\n`;\n\n await Bun.write(featurePath, body);\n return { created: true, featurePath, messages, fields };\n}\n"
|
|
15
|
+
],
|
|
16
|
+
"mappings": "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",
|
|
17
|
+
"debugId": "2DDEB2D363C2D86864756E2164756E21",
|
|
18
|
+
"names": []
|
|
19
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BddArgs } from "./args.ts";
|
|
2
|
+
export interface BddConfig {
|
|
3
|
+
cwd: string;
|
|
4
|
+
/** Absolute paths of `.feature` files to run. */
|
|
5
|
+
featureFiles: string[];
|
|
6
|
+
/** Absolute paths of step-definition modules to import (side-effect registration). */
|
|
7
|
+
stepFiles: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveBddConfig(cwd: string, args: BddArgs): Promise<BddConfig>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fairfox/polly/bdd — author executable Gherkin against polly's own model.
|
|
3
|
+
*
|
|
4
|
+
* The CLI (`polly bdd`) is the primary entry point; this barrel exposes the
|
|
5
|
+
* pieces a consumer's step module needs (`defineStep`, `defineWorld`) plus the
|
|
6
|
+
* programmatic surface for driving the runner and the verify cross-link.
|
|
7
|
+
*
|
|
8
|
+
* The binding declared by `defineStep` is dual-use — its `given`/`when`/`then`
|
|
9
|
+
* drive the real factory bus, and its `message`/`stateExpr` are read statically
|
|
10
|
+
* by the verify extractor. See tools/bdd/README.md.
|
|
11
|
+
*/
|
|
12
|
+
export { type DispatchBus, driveBus } from "./bus-driver.ts";
|
|
13
|
+
export { type CrossCheckResult, checkAgainstVerify } from "./check-verify.ts";
|
|
14
|
+
export { extractTraces } from "./extract.ts";
|
|
15
|
+
export { parseFeatureFile, parseFeatureText } from "./parse.ts";
|
|
16
|
+
export { type RunOptions, runFeatures } from "./run.ts";
|
|
17
|
+
export { defineStep, defineWorld, matchStep, registeredBindings } from "./steps.ts";
|
|
18
|
+
export type { BusLike, ParsedFeature, ParsedScenario, ParsedStep, RunResult, ScenarioResult, ScenarioTrace, SignalLike, StepBinding, StepFn, TraceStep, World, WorldDef, } from "./types.ts";
|
|
19
|
+
export { extractWitnesses, type ScenarioWitness } from "./witness.ts";
|