@overshift/sfs 1.1.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.
Files changed (102) hide show
  1. package/README.md +215 -0
  2. package/dist/cli/coverage-output.d.ts +3 -0
  3. package/dist/cli/coverage-output.d.ts.map +1 -0
  4. package/dist/cli/coverage-output.js +74 -0
  5. package/dist/cli/coverage-output.js.map +1 -0
  6. package/dist/cli/coverage-types.d.ts +24 -0
  7. package/dist/cli/coverage-types.d.ts.map +1 -0
  8. package/dist/cli/coverage-types.js +2 -0
  9. package/dist/cli/coverage-types.js.map +1 -0
  10. package/dist/cli/coverage.d.ts +3 -0
  11. package/dist/cli/coverage.d.ts.map +1 -0
  12. package/dist/cli/coverage.js +69 -0
  13. package/dist/cli/coverage.js.map +1 -0
  14. package/dist/cli/init-templates.d.ts +5 -0
  15. package/dist/cli/init-templates.d.ts.map +1 -0
  16. package/dist/cli/init-templates.js +108 -0
  17. package/dist/cli/init-templates.js.map +1 -0
  18. package/dist/cli/init.d.ts +7 -0
  19. package/dist/cli/init.d.ts.map +1 -0
  20. package/dist/cli/init.js +170 -0
  21. package/dist/cli/init.js.map +1 -0
  22. package/dist/cli/run.d.ts +3 -0
  23. package/dist/cli/run.d.ts.map +1 -0
  24. package/dist/cli/run.js +58 -0
  25. package/dist/cli/run.js.map +1 -0
  26. package/dist/cli/story-extractor.d.ts +7 -0
  27. package/dist/cli/story-extractor.d.ts.map +1 -0
  28. package/dist/cli/story-extractor.js +130 -0
  29. package/dist/cli/story-extractor.js.map +1 -0
  30. package/dist/cli/validate.d.ts +2 -0
  31. package/dist/cli/validate.d.ts.map +1 -0
  32. package/dist/cli/validate.js +39 -0
  33. package/dist/cli/validate.js.map +1 -0
  34. package/dist/executor/assertion-executor.d.ts +7 -0
  35. package/dist/executor/assertion-executor.d.ts.map +1 -0
  36. package/dist/executor/assertion-executor.js +206 -0
  37. package/dist/executor/assertion-executor.js.map +1 -0
  38. package/dist/executor/config-loader.d.ts +5 -0
  39. package/dist/executor/config-loader.d.ts.map +1 -0
  40. package/dist/executor/config-loader.js +48 -0
  41. package/dist/executor/config-loader.js.map +1 -0
  42. package/dist/executor/executor-types.d.ts +64 -0
  43. package/dist/executor/executor-types.d.ts.map +1 -0
  44. package/dist/executor/executor-types.js +6 -0
  45. package/dist/executor/executor-types.js.map +1 -0
  46. package/dist/executor/retry-handler.d.ts +7 -0
  47. package/dist/executor/retry-handler.d.ts.map +1 -0
  48. package/dist/executor/retry-handler.js +32 -0
  49. package/dist/executor/retry-handler.js.map +1 -0
  50. package/dist/executor/run-context.d.ts +27 -0
  51. package/dist/executor/run-context.d.ts.map +1 -0
  52. package/dist/executor/run-context.js +52 -0
  53. package/dist/executor/run-context.js.map +1 -0
  54. package/dist/executor/run-engine.d.ts +9 -0
  55. package/dist/executor/run-engine.d.ts.map +1 -0
  56. package/dist/executor/run-engine.js +140 -0
  57. package/dist/executor/run-engine.js.map +1 -0
  58. package/dist/executor/session-manager.d.ts +16 -0
  59. package/dist/executor/session-manager.d.ts.map +1 -0
  60. package/dist/executor/session-manager.js +103 -0
  61. package/dist/executor/session-manager.js.map +1 -0
  62. package/dist/executor/shell-executor.d.ts +12 -0
  63. package/dist/executor/shell-executor.d.ts.map +1 -0
  64. package/dist/executor/shell-executor.js +66 -0
  65. package/dist/executor/shell-executor.js.map +1 -0
  66. package/dist/executor/step-executor.d.ts +6 -0
  67. package/dist/executor/step-executor.d.ts.map +1 -0
  68. package/dist/executor/step-executor.js +73 -0
  69. package/dist/executor/step-executor.js.map +1 -0
  70. package/dist/index.d.ts +3 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +37 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/parser/assertion-parser.d.ts +3 -0
  75. package/dist/parser/assertion-parser.d.ts.map +1 -0
  76. package/dist/parser/assertion-parser.js +92 -0
  77. package/dist/parser/assertion-parser.js.map +1 -0
  78. package/dist/parser/command-parser.d.ts +3 -0
  79. package/dist/parser/command-parser.d.ts.map +1 -0
  80. package/dist/parser/command-parser.js +252 -0
  81. package/dist/parser/command-parser.js.map +1 -0
  82. package/dist/parser/config-parser.d.ts +16 -0
  83. package/dist/parser/config-parser.d.ts.map +1 -0
  84. package/dist/parser/config-parser.js +217 -0
  85. package/dist/parser/config-parser.js.map +1 -0
  86. package/dist/parser/sfs-parser.d.ts +3 -0
  87. package/dist/parser/sfs-parser.d.ts.map +1 -0
  88. package/dist/parser/sfs-parser.js +184 -0
  89. package/dist/parser/sfs-parser.js.map +1 -0
  90. package/dist/parser/step-parser.d.ts +3 -0
  91. package/dist/parser/step-parser.d.ts.map +1 -0
  92. package/dist/parser/step-parser.js +72 -0
  93. package/dist/parser/step-parser.js.map +1 -0
  94. package/dist/parser/types.d.ts +115 -0
  95. package/dist/parser/types.d.ts.map +1 -0
  96. package/dist/parser/types.js +3 -0
  97. package/dist/parser/types.js.map +1 -0
  98. package/dist/utils/mcp-detector.d.ts +9 -0
  99. package/dist/utils/mcp-detector.d.ts.map +1 -0
  100. package/dist/utils/mcp-detector.js +62 -0
  101. package/dist/utils/mcp-detector.js.map +1 -0
  102. package/package.json +72 -0
@@ -0,0 +1,184 @@
1
+ import { parseStep } from "./step-parser.js";
2
+ import { parseCommand } from "./command-parser.js";
3
+ import { parseAssertion } from "./assertion-parser.js";
4
+ export function parseSfsFile(content, _filename = "unknown") {
5
+ const lines = content.split("\n");
6
+ const errors = [];
7
+ const warnings = [];
8
+ let header;
9
+ const context = { hints: [] };
10
+ const prerequisites = {
11
+ beforeThis: [],
12
+ afterThis: [],
13
+ assertions: [],
14
+ };
15
+ const phases = [];
16
+ let exitCondition;
17
+ let currentPhase;
18
+ let inBeforeThis = false;
19
+ let inAfterThis = false;
20
+ for (let i = 0; i < lines.length; i++) {
21
+ const lineNum = i + 1;
22
+ const line = lines[i] ?? "";
23
+ const trimmed = line.trim();
24
+ // Skip empty lines and comments
25
+ if (!trimmed || trimmed.startsWith("#")) {
26
+ continue;
27
+ }
28
+ // Parse header
29
+ if (trimmed.startsWith("STORY")) {
30
+ const match = trimmed.match(/^STORY\s+(.+)$/);
31
+ if (match?.[1]) {
32
+ header = header ?? { story: "", entrypoint: "" };
33
+ header.story = match[1].trim();
34
+ }
35
+ else {
36
+ errors.push({ line: lineNum, message: "Invalid STORY syntax" });
37
+ }
38
+ continue;
39
+ }
40
+ if (trimmed.startsWith("ENTRYPOINT")) {
41
+ const match = trimmed.match(/^ENTRYPOINT\s+(.+)$/);
42
+ if (match?.[1]) {
43
+ header = header ?? { story: "", entrypoint: "" };
44
+ header.entrypoint = match[1].trim();
45
+ }
46
+ else {
47
+ errors.push({ line: lineNum, message: "Invalid ENTRYPOINT syntax" });
48
+ }
49
+ continue;
50
+ }
51
+ if (trimmed.startsWith("LOCALE")) {
52
+ const match = trimmed.match(/^LOCALE\s+(.+)$/);
53
+ if (match?.[1] && header) {
54
+ header.locale = match[1].trim();
55
+ }
56
+ continue;
57
+ }
58
+ // Parse context
59
+ if (trimmed.startsWith("HINT")) {
60
+ const match = trimmed.match(/^HINT\s+(.+)$/);
61
+ if (match?.[1]) {
62
+ context.hints.push(match[1].trim());
63
+ }
64
+ continue;
65
+ }
66
+ if (trimmed.startsWith("ON FAILURE")) {
67
+ const match = trimmed.match(/^ON FAILURE\s+(.+)$/);
68
+ if (match?.[1]) {
69
+ context.onFailure = match[1].trim();
70
+ }
71
+ continue;
72
+ }
73
+ // Parse prerequisites blocks
74
+ if (trimmed === "BEFORE THIS") {
75
+ inBeforeThis = true;
76
+ inAfterThis = false;
77
+ continue;
78
+ }
79
+ if (trimmed === "AFTER THIS") {
80
+ inAfterThis = true;
81
+ inBeforeThis = false;
82
+ continue;
83
+ }
84
+ // Parse assertions
85
+ if (trimmed.startsWith("ASSERT")) {
86
+ const assertion = parseAssertion(trimmed, lineNum);
87
+ if (assertion) {
88
+ prerequisites.assertions.push(assertion);
89
+ }
90
+ else {
91
+ errors.push({ line: lineNum, message: "Invalid ASSERT syntax" });
92
+ }
93
+ continue;
94
+ }
95
+ // Parse phase headers
96
+ if (trimmed.match(/^---\s+.+\s+---$/)) {
97
+ const match = trimmed.match(/^---\s+(.+)\s+---$/);
98
+ if (match?.[1]) {
99
+ inBeforeThis = false;
100
+ inAfterThis = false;
101
+ currentPhase = { name: match[1].trim(), steps: [] };
102
+ phases.push(currentPhase);
103
+ }
104
+ continue;
105
+ }
106
+ // Parse DONE WHEN
107
+ if (trimmed.startsWith("DONE WHEN")) {
108
+ const match = trimmed.match(/^DONE WHEN\s+(.+)$/);
109
+ if (match?.[1]) {
110
+ exitCondition = match[1].trim();
111
+ }
112
+ else {
113
+ errors.push({ line: lineNum, message: "Invalid DONE WHEN syntax" });
114
+ }
115
+ continue;
116
+ }
117
+ // Parse commands within blocks or phases
118
+ if (inBeforeThis && line.match(/^\s+/)) {
119
+ const cmd = parseCommand(trimmed, lineNum);
120
+ if (cmd) {
121
+ prerequisites.beforeThis.push(cmd);
122
+ }
123
+ continue;
124
+ }
125
+ if (inAfterThis && line.match(/^\s+/)) {
126
+ const cmd = parseCommand(trimmed, lineNum);
127
+ if (cmd) {
128
+ prerequisites.afterThis.push(cmd);
129
+ }
130
+ continue;
131
+ }
132
+ // Parse steps within phases
133
+ if (currentPhase) {
134
+ const step = parseStep(trimmed, lineNum);
135
+ if (step) {
136
+ currentPhase.steps.push(step);
137
+ }
138
+ else {
139
+ errors.push({ line: lineNum, message: `Unknown command: ${trimmed}` });
140
+ }
141
+ }
142
+ }
143
+ // Validation
144
+ if (!header?.story) {
145
+ errors.push({ line: 1, message: "Missing required STORY header" });
146
+ }
147
+ if (!header?.entrypoint) {
148
+ errors.push({ line: 1, message: "Missing required ENTRYPOINT header" });
149
+ }
150
+ if (!exitCondition) {
151
+ errors.push({
152
+ line: lines.length,
153
+ message: "Missing required DONE WHEN exit condition",
154
+ });
155
+ }
156
+ if (phases.length === 0) {
157
+ errors.push({ line: 1, message: "At least one phase is required" });
158
+ }
159
+ // Warnings
160
+ if (!header?.locale) {
161
+ warnings.push({
162
+ line: 1,
163
+ message: "No LOCALE specified (recommended for RTL/language support)",
164
+ });
165
+ }
166
+ if (context.hints.length === 0) {
167
+ warnings.push({
168
+ line: 1,
169
+ message: "No HINT context provided (recommended for agent)",
170
+ });
171
+ }
172
+ if (errors.length > 0) {
173
+ return { errors, warnings };
174
+ }
175
+ const ast = {
176
+ header: header,
177
+ context,
178
+ prerequisites,
179
+ phases,
180
+ exitCondition: exitCondition,
181
+ };
182
+ return { ast, errors, warnings };
183
+ }
184
+ //# sourceMappingURL=sfs-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfs-parser.js","sourceRoot":"","sources":["../../src/parser/sfs-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SfsStep } from "./types.js";
2
+ export declare function parseStep(line: string, lineNum: number): SfsStep | undefined;
3
+ //# sourceMappingURL=step-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-parser.d.ts","sourceRoot":"","sources":["../../src/parser/step-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAKR,MAAM,YAAY,CAAC;AAGpB,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CA+C5E"}
@@ -0,0 +1,72 @@
1
+ import { parseCommand } from "./command-parser.js";
2
+ export function parseStep(line, lineNum) {
3
+ // AS (persona switch)
4
+ if (line.startsWith("AS ")) {
5
+ const match = line.match(/^AS\s+(\S+)$/);
6
+ if (match?.[1]) {
7
+ return {
8
+ type: "persona",
9
+ persona: match[1].trim(),
10
+ raw: line,
11
+ line: lineNum,
12
+ };
13
+ }
14
+ }
15
+ // OBSERVE
16
+ if (line.startsWith("OBSERVE")) {
17
+ const match = line.match(/^OBSERVE\s+(.+)$/);
18
+ if (match?.[1]) {
19
+ return {
20
+ type: "observation",
21
+ condition: match[1].trim(),
22
+ raw: line,
23
+ line: lineNum,
24
+ };
25
+ }
26
+ }
27
+ // WAIT FOR
28
+ if (line.startsWith("WAIT FOR")) {
29
+ return parseWait(line, lineNum);
30
+ }
31
+ // CAPTURE
32
+ if (line.startsWith("CAPTURE")) {
33
+ const match = line.match(/^CAPTURE\s+(\S+)$/);
34
+ if (match?.[1]) {
35
+ return {
36
+ type: "capture",
37
+ name: match[1].trim(),
38
+ raw: line,
39
+ line: lineNum,
40
+ };
41
+ }
42
+ }
43
+ // Regular commands
44
+ return parseCommand(line, lineNum);
45
+ }
46
+ function parseWait(line, lineNum) {
47
+ // WAIT FOR <duration>
48
+ const durationMatch = line.match(/^WAIT FOR\s+(\d+)(s|ms)?$/);
49
+ if (durationMatch?.[1]) {
50
+ const unit = durationMatch[2];
51
+ return {
52
+ type: "wait",
53
+ condition: "",
54
+ duration: parseInt(durationMatch[1], 10),
55
+ unit: unit ?? "s",
56
+ raw: line,
57
+ line: lineNum,
58
+ };
59
+ }
60
+ // WAIT FOR <condition>
61
+ const conditionMatch = line.match(/^WAIT FOR\s+(.+)$/);
62
+ if (conditionMatch?.[1]) {
63
+ return {
64
+ type: "wait",
65
+ condition: conditionMatch[1].trim(),
66
+ raw: line,
67
+ line: lineNum,
68
+ };
69
+ }
70
+ return undefined;
71
+ }
72
+ //# sourceMappingURL=step-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-parser.js","sourceRoot":"","sources":["../../src/parser/step-parser.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,OAAe;IACrD,sBAAsB;IACtB,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACzC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACf,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;gBACxB,GAAG,EAAE,IAAI;gBACT,IAAI,EAAE,OAAO;aACa,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,UAAU;IACV,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC7C,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACf,OAAO;gBACL,IAAI,EAAE,aAAa;gBACnB,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;gBAC1B,GAAG,EAAE,IAAI;gBACT,IAAI,EAAE,OAAO;aACW,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,WAAW;IACX,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,UAAU;IACV,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC9C,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACf,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;gBACrB,GAAG,EAAE,IAAI;gBACT,IAAI,EAAE,OAAO;aACO,CAAC;QACzB,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,OAAe;IAC9C,sBAAsB;IACtB,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC9D,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,CAA2B,CAAC;QACxD,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,SAAS,EAAE,EAAE;YACb,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACxC,IAAI,EAAE,IAAI,IAAI,GAAG;YACjB,GAAG,EAAE,IAAI;YACT,IAAI,EAAE,OAAO;SACd,CAAC;IACJ,CAAC;IAED,uBAAuB;IACvB,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACvD,IAAI,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;YACnC,GAAG,EAAE,IAAI;YACT,IAAI,EAAE,OAAO;SACd,CAAC;IACJ,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,115 @@
1
+ export interface SfsFile {
2
+ header: SfsHeader;
3
+ context: SfsContext;
4
+ prerequisites: SfsPrerequisites;
5
+ phases: SfsPhase[];
6
+ exitCondition: string;
7
+ }
8
+ export interface SfsHeader {
9
+ story: string;
10
+ entrypoint: string;
11
+ locale?: string;
12
+ }
13
+ export interface SfsContext {
14
+ hints: string[];
15
+ onFailure?: string;
16
+ }
17
+ export interface SfsPrerequisites {
18
+ beforeThis: SfsCommand[];
19
+ afterThis: SfsCommand[];
20
+ assertions: SfsAssertion[];
21
+ }
22
+ export interface SfsPhase {
23
+ name: string;
24
+ steps: SfsStep[];
25
+ }
26
+ export type SfsStep = SfsCommand | SfsObservation | SfsWait | SfsCapture | SfsPersonaSwitch;
27
+ export interface SfsCommand {
28
+ type: "command";
29
+ verb: CommandVerb;
30
+ target?: string;
31
+ value?: string;
32
+ selector?: SfsSelector;
33
+ raw: string;
34
+ line: number;
35
+ }
36
+ export type CommandVerb = "NAVIGATE" | "CLICK" | "DOUBLE_CLICK" | "TYPE" | "CLEAR" | "SELECT" | "HOVER" | "SCROLL" | "UPLOAD" | "PRESS" | "ACCEPT_DIALOG" | "DISMISS_DIALOG" | "TAB_EXPECT_NEW" | "TAB_SWITCH" | "TAB_CLOSE" | "TAB_COUNT" | "READ" | "SHELL" | "CLEAR_COOKIES" | "CLEAR_STORAGE";
37
+ export interface SfsSelector {
38
+ type: SelectorType;
39
+ value: string;
40
+ }
41
+ export type SelectorType = "testid" | "css" | "text" | "role" | "xpath";
42
+ export interface SfsObservation {
43
+ type: "observation";
44
+ condition: string;
45
+ raw: string;
46
+ line: number;
47
+ }
48
+ export interface SfsWait {
49
+ type: "wait";
50
+ condition: string;
51
+ duration?: number;
52
+ unit?: "s" | "ms";
53
+ raw: string;
54
+ line: number;
55
+ }
56
+ export interface SfsCapture {
57
+ type: "capture";
58
+ name: string;
59
+ raw: string;
60
+ line: number;
61
+ }
62
+ export interface SfsPersonaSwitch {
63
+ type: "persona";
64
+ persona: string;
65
+ raw: string;
66
+ line: number;
67
+ }
68
+ export interface SfsAssertion {
69
+ type: AssertionType;
70
+ target: string;
71
+ value?: string;
72
+ raw: string;
73
+ line: number;
74
+ }
75
+ export type AssertionType = "file_exists" | "env_set" | "port_open" | "port_free" | "url_responds" | "url_responds_with" | "shell_succeeds" | "env_check" | "docker_ready" | "custom";
76
+ export interface SfsConfig {
77
+ settings: SfsSettings;
78
+ hints: string[];
79
+ personas: SfsPersona[];
80
+ beforeSession: SfsCommand[];
81
+ afterSession: SfsCommand[];
82
+ beforeEach: SfsCommand[];
83
+ afterEach: SfsCommand[];
84
+ }
85
+ export interface SfsSettings {
86
+ entrypoint?: string;
87
+ locale?: string;
88
+ timeout?: number;
89
+ onFailure?: string;
90
+ afterEach?: "always" | "on-pass" | "on-fail" | "never";
91
+ afterThis?: "always" | "on-pass" | "on-fail" | "never";
92
+ preserveStateOnFailure?: boolean;
93
+ }
94
+ export interface SfsPersona {
95
+ name: string;
96
+ username: string;
97
+ password: string;
98
+ description?: string;
99
+ }
100
+ export interface ParseResult {
101
+ ast?: SfsFile;
102
+ errors: ParseError[];
103
+ warnings: ParseWarning[];
104
+ }
105
+ export interface ParseError {
106
+ line: number;
107
+ column?: number;
108
+ message: string;
109
+ }
110
+ export interface ParseWarning {
111
+ line: number;
112
+ column?: number;
113
+ message: string;
114
+ }
115
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/parser/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ // SFS Abstract Syntax Tree Types
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/parser/types.ts"],"names":[],"mappings":"AAAA,iCAAiC"}
@@ -0,0 +1,9 @@
1
+ interface McpDetectionResult {
2
+ detected: boolean;
3
+ hasPlaywright: boolean;
4
+ servers: string[];
5
+ guidance: string;
6
+ }
7
+ export declare function detectMcpIntegration(projectDir?: string): Promise<McpDetectionResult>;
8
+ export {};
9
+ //# sourceMappingURL=mcp-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-detector.d.ts","sourceRoot":"","sources":["../../src/utils/mcp-detector.ts"],"names":[],"mappings":"AAGA,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAGD,wBAAsB,oBAAoB,CACxC,UAAU,GAAE,MAAsB,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAmE7B"}
@@ -0,0 +1,62 @@
1
+ import { readdir, readFile } from "fs/promises";
2
+ import { join } from "path";
3
+ // Detection currently limited to .claude/ directory (marked for future expansion)
4
+ export async function detectMcpIntegration(projectDir = process.cwd()) {
5
+ const claudeDir = join(projectDir, ".claude");
6
+ try {
7
+ const files = await readdir(claudeDir);
8
+ const servers = [];
9
+ let hasPlaywright = false;
10
+ const configFiles = files.filter((f) => f.endsWith(".json") && (f.includes("mcp") || f.includes("settings")));
11
+ for (const file of configFiles) {
12
+ try {
13
+ const content = await readFile(join(claudeDir, file), "utf-8");
14
+ const parsed = JSON.parse(content);
15
+ const mcpServers = parsed.mcpServers ?? parsed.mcp_servers;
16
+ if (mcpServers && typeof mcpServers === "object") {
17
+ for (const name of Object.keys(mcpServers)) {
18
+ servers.push(name);
19
+ if (name.toLowerCase().includes("playwright")) {
20
+ hasPlaywright = true;
21
+ }
22
+ }
23
+ }
24
+ }
25
+ catch {
26
+ // Invalid JSON or read error - skip file
27
+ }
28
+ }
29
+ if (servers.length === 0) {
30
+ return {
31
+ detected: false,
32
+ hasPlaywright: false,
33
+ servers: [],
34
+ guidance: "No MCP integration detected. This package is designed to work with browser MCP (e.g., Playwright MCP).",
35
+ };
36
+ }
37
+ if (hasPlaywright) {
38
+ return {
39
+ detected: true,
40
+ hasPlaywright: true,
41
+ servers,
42
+ guidance: `Playwright MCP detected. SFS will use it for browser automation.`,
43
+ };
44
+ }
45
+ return {
46
+ detected: true,
47
+ hasPlaywright: false,
48
+ servers,
49
+ guidance: `MCP servers found (${servers.join(", ")}), but no Playwright MCP found. Browser automation requires Playwright MCP.`,
50
+ };
51
+ }
52
+ catch {
53
+ // .claude directory doesn't exist or can't be read
54
+ return {
55
+ detected: false,
56
+ hasPlaywright: false,
57
+ servers: [],
58
+ guidance: "No MCP integration detected. This package is designed to work with browser MCP (e.g., Playwright MCP).",
59
+ };
60
+ }
61
+ }
62
+ //# sourceMappingURL=mcp-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-detector.js","sourceRoot":"","sources":["../../src/utils/mcp-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAS5B,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,aAAqB,OAAO,CAAC,GAAG,EAAE;IAElC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAE9C,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,aAAa,GAAG,KAAK,CAAC;QAE1B,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAC9B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CACvE,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;gBAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACnC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,WAAW,CAAC;gBAE3D,IAAI,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;oBACjD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;wBAC3C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACnB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;4BAC9C,aAAa,GAAG,IAAI,CAAC;wBACvB,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,yCAAyC;YAC3C,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO;gBACL,QAAQ,EAAE,KAAK;gBACf,aAAa,EAAE,KAAK;gBACpB,OAAO,EAAE,EAAE;gBACX,QAAQ,EACN,wGAAwG;aAC3G,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO;gBACL,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,IAAI;gBACnB,OAAO;gBACP,QAAQ,EAAE,kEAAkE;aAC7E,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,IAAI;YACd,aAAa,EAAE,KAAK;YACpB,OAAO;YACP,QAAQ,EAAE,sBAAsB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,6EAA6E;SAChI,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,mDAAmD;QACnD,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,aAAa,EAAE,KAAK;YACpB,OAAO,EAAE,EAAE;YACX,QAAQ,EACN,wGAAwG;SAC3G,CAAC;IACJ,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "type": "module",
3
+ "name": "@overshift/sfs",
4
+ "version": "1.1.0",
5
+ "description": "StoryFlowSteps - Agent-oriented browser automation protocol for validating user story flows",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "sfs": "dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsx src/index.ts",
14
+ "start": "node dist/index.js",
15
+ "test": "vitest",
16
+ "test:unit": "vitest run --dir tests/unit",
17
+ "test:integration": "vitest run --dir tests/integration",
18
+ "test:e2e": "vitest run --dir tests/e2e",
19
+ "test:coverage": "vitest run --coverage",
20
+ "lint": "eslint src --ext .ts",
21
+ "lint:fix": "eslint src --ext .ts --fix",
22
+ "format": "prettier --write \"src/**/*.ts\"",
23
+ "prepare": "npm run build",
24
+ "dod": "node scripts/dod.cjs",
25
+ "dod:all": "node scripts/dod.cjs all",
26
+ "dod:core": "node scripts/dod.cjs core",
27
+ "dod:skip": "node scripts/dod.cjs skip",
28
+ "commit:check": "git commit",
29
+ "commit:check:all": "git commit",
30
+ "commit:check:core": "set SFS_CHECKS=core&& git commit",
31
+ "commit:check:skip": "set SFS_CHECKS=skip&& git commit",
32
+ "semgrep": "semgrep --config semgrep.yml --config p/default --config p/security-audit --config p/secrets --config p/javascript --config p/typescript --config p/nodejs src/",
33
+ "semgrep:local": "semgrep --config semgrep.yml src/",
34
+ "semgrep:security": "semgrep --config p/security-audit --config p/secrets --config p/owasp-top-ten --config p/xss --config p/sql-injection --config p/command-injection src/",
35
+ "semgrep:auto": "semgrep --config auto src/",
36
+ "publish:npm": "node scripts/publish-to-npm.js"
37
+ },
38
+ "keywords": [
39
+ "sfs",
40
+ "storyflowsteps",
41
+ "browser-automation",
42
+ "playwright",
43
+ "testing",
44
+ "user-stories",
45
+ "e2e",
46
+ "agent"
47
+ ],
48
+ "author": "",
49
+ "license": "MIT",
50
+ "engines": {
51
+ "node": ">=18.0.0"
52
+ },
53
+ "files": [
54
+ "dist"
55
+ ],
56
+ "dependencies": {
57
+ "chalk": "^5.3.0",
58
+ "commander": "^12.1.0",
59
+ "glob": "^10.3.10"
60
+ },
61
+ "devDependencies": {
62
+ "@types/node": "^20.11.0",
63
+ "@typescript-eslint/eslint-plugin": "^6.19.0",
64
+ "@typescript-eslint/parser": "^6.19.0",
65
+ "@vitest/coverage-v8": "^1.6.1",
66
+ "eslint": "^8.56.0",
67
+ "prettier": "^3.2.4",
68
+ "tsx": "^4.7.0",
69
+ "typescript": "^5.3.3",
70
+ "vitest": "^1.2.0"
71
+ }
72
+ }