@xera-ai/web 0.1.7 → 0.2.1

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 (46) hide show
  1. package/dist/{web/src/executor → executor}/index.d.ts +1 -0
  2. package/dist/{web/src/executor → executor}/playwright-args.d.ts +1 -0
  3. package/dist/index.js +78 -73
  4. package/package.json +10 -7
  5. package/src/executor/index.ts +2 -0
  6. package/src/executor/playwright-args.ts +6 -1
  7. package/src/generator/lint.ts +2 -2
  8. package/src/generator/pom-scan.ts +1 -1
  9. package/src/index.ts +7 -7
  10. package/dist/core/src/adapter/types.d.ts +0 -69
  11. package/dist/core/src/artifact/hash.d.ts +0 -3
  12. package/dist/core/src/artifact/meta.d.ts +0 -45
  13. package/dist/core/src/artifact/paths.d.ts +0 -24
  14. package/dist/core/src/artifact/status.d.ts +0 -95
  15. package/dist/core/src/auth/encrypt.d.ts +0 -3
  16. package/dist/core/src/auth/key.d.ts +0 -2
  17. package/dist/core/src/auth/refresh.d.ts +0 -8
  18. package/dist/core/src/auth/state.d.ts +0 -23
  19. package/dist/core/src/config/define.d.ts +0 -2
  20. package/dist/core/src/config/load.d.ts +0 -2
  21. package/dist/core/src/config/schema.d.ts +0 -325
  22. package/dist/core/src/index.d.ts +0 -19
  23. package/dist/core/src/jira/client.d.ts +0 -10
  24. package/dist/core/src/jira/fields.d.ts +0 -6
  25. package/dist/core/src/jira/mcp-backend.d.ts +0 -2
  26. package/dist/core/src/jira/rest-backend.d.ts +0 -7
  27. package/dist/core/src/jira/retry.d.ts +0 -7
  28. package/dist/core/src/jira/types.d.ts +0 -28
  29. package/dist/core/src/lock/file-lock.d.ts +0 -11
  30. package/dist/core/src/logging/ndjson-logger.d.ts +0 -10
  31. package/dist/{web/src/adapter.d.ts → adapter.d.ts} +0 -0
  32. package/dist/{web/src/auth-setup → auth-setup}/define.d.ts +0 -0
  33. package/dist/{web/src/auth-setup → auth-setup}/playwright-state.d.ts +0 -0
  34. package/dist/{web/src/auth-setup → auth-setup}/runner.d.ts +0 -0
  35. package/dist/{web/src/generator → generator}/gherkin-validate.d.ts +0 -0
  36. package/dist/{web/src/generator → generator}/lint.d.ts +0 -0
  37. package/dist/{web/src/generator → generator}/pom-scan.d.ts +0 -0
  38. package/dist/{web/src/generator → generator}/promote.d.ts +0 -0
  39. package/dist/{web/src/generator → generator}/selector-rules.d.ts +0 -0
  40. package/dist/{web/src/generator → generator}/typecheck.d.ts +0 -0
  41. package/dist/{web/src/index.d.ts → index.d.ts} +7 -7
  42. /package/dist/{web/src/trace-normalizer → trace-normalizer}/normalize.d.ts +0 -0
  43. /package/dist/{web/src/trace-normalizer → trace-normalizer}/parse.d.ts +0 -0
  44. /package/dist/{web/src/trace-normalizer → trace-normalizer}/scrub-rules.d.ts +0 -0
  45. /package/dist/{web/src/trace-normalizer → trace-normalizer}/scrub.d.ts +0 -0
  46. /package/dist/{web/src/trace-normalizer → trace-normalizer}/unzip.d.ts +0 -0
@@ -6,6 +6,7 @@ export interface RunPlaywrightInput {
6
6
  specPath: string;
7
7
  configPath: string;
8
8
  outputDir: string;
9
+ grep?: string;
9
10
  env?: NodeJS.ProcessEnv;
10
11
  spawn?: SpawnFn;
11
12
  }
@@ -2,5 +2,6 @@ export interface PlaywrightArgsInput {
2
2
  specPath: string;
3
3
  outputDir: string;
4
4
  configPath: string;
5
+ grep?: string;
5
6
  }
6
7
  export declare function buildPlaywrightArgs(input: PlaywrightArgsInput): string[];
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import { join } from "path";
9
9
 
10
10
  // src/executor/playwright-args.ts
11
11
  function buildPlaywrightArgs(input) {
12
- return [
12
+ const args = [
13
13
  "test",
14
14
  input.specPath,
15
15
  `--config=${input.configPath}`,
@@ -17,6 +17,10 @@ function buildPlaywrightArgs(input) {
17
17
  `--output=${input.outputDir}`,
18
18
  "--trace=on"
19
19
  ];
20
+ if (input.grep) {
21
+ args.push("--grep", input.grep);
22
+ }
23
+ return args;
20
24
  }
21
25
 
22
26
  // src/executor/index.ts
@@ -29,7 +33,8 @@ async function runPlaywright(input) {
29
33
  const args = buildPlaywrightArgs({
30
34
  specPath: input.specPath,
31
35
  configPath: input.configPath,
32
- outputDir: input.outputDir
36
+ outputDir: input.outputDir,
37
+ ...input.grep && { grep: input.grep }
33
38
  });
34
39
  const spawn = input.spawn ?? defaultSpawn;
35
40
  const { exitCode } = await spawn("npx", ["playwright", ...args], {
@@ -304,6 +309,20 @@ var WebAdapter = {
304
309
  function defineAuthSetup(fn) {
305
310
  return fn;
306
311
  }
312
+ // src/auth-setup/playwright-state.ts
313
+ import { mkdirSync, writeFileSync as writeFileSync2 } from "fs";
314
+ import { join as join4 } from "path";
315
+ import { readAuthState } from "@xera-ai/core";
316
+ function stagePlaywrightState(authDir, role) {
317
+ const entry = readAuthState(authDir, role);
318
+ if (!entry)
319
+ throw new Error(`No auth state for role "${role}" in ${authDir}`);
320
+ const cacheDir = join4(authDir, ".cache");
321
+ mkdirSync(cacheDir, { recursive: true });
322
+ const stagedPath = join4(cacheDir, `${role}.json`);
323
+ writeFileSync2(stagedPath, JSON.stringify(entry.payload));
324
+ return stagedPath;
325
+ }
307
326
  // src/auth-setup/runner.ts
308
327
  import { pathToFileURL } from "url";
309
328
  import { writeAuthState } from "@xera-ai/core";
@@ -331,20 +350,6 @@ async function runAuthSetup(input) {
331
350
  await context.close();
332
351
  }
333
352
  }
334
- // src/auth-setup/playwright-state.ts
335
- import { mkdirSync, writeFileSync as writeFileSync2 } from "fs";
336
- import { join as join4 } from "path";
337
- import { readAuthState } from "@xera-ai/core";
338
- function stagePlaywrightState(authDir, role) {
339
- const entry = readAuthState(authDir, role);
340
- if (!entry)
341
- throw new Error(`No auth state for role "${role}" in ${authDir}`);
342
- const cacheDir = join4(authDir, ".cache");
343
- mkdirSync(cacheDir, { recursive: true });
344
- const stagedPath = join4(cacheDir, `${role}.json`);
345
- writeFileSync2(stagedPath, JSON.stringify(entry.payload));
346
- return stagedPath;
347
- }
348
353
  // src/generator/gherkin-validate.ts
349
354
  import { AstBuilder, GherkinClassicTokenMatcher, Parser } from "@cucumber/gherkin";
350
355
  import { IdGenerator } from "@cucumber/messages";
@@ -368,47 +373,9 @@ function validateGherkin(content) {
368
373
  return { ok: false, errors };
369
374
  }
370
375
  }
371
- // src/generator/typecheck.ts
372
- import { spawnSync } from "child_process";
373
- import { existsSync as existsSync2 } from "fs";
374
- import { dirname, join as join5 } from "path";
375
- function findNearestTsconfig(start) {
376
- let dir = start;
377
- while (true) {
378
- const candidate = join5(dir, "tsconfig.json");
379
- if (existsSync2(candidate))
380
- return candidate;
381
- const parent = dirname(dir);
382
- if (parent === dir)
383
- return null;
384
- dir = parent;
385
- }
386
- }
387
- async function typecheckTicket(ticketDir) {
388
- const tsconfig = findNearestTsconfig(ticketDir);
389
- if (!tsconfig) {
390
- return {
391
- ok: false,
392
- errors: [
393
- `No tsconfig.json found walking up from ${ticketDir}. Run \`xera init\` to scaffold one at the project root.`
394
- ]
395
- };
396
- }
397
- const proc = spawnSync("npx", ["tsc", "--noEmit", "-p", tsconfig], { encoding: "utf8" });
398
- if (proc.status === 0)
399
- return { ok: true, errors: [] };
400
- const out = `${proc.stdout ?? ""}${proc.stderr ?? ""}`;
401
- const allErrors = out.split(`
402
- `).filter((line) => /error TS\d+/.test(line));
403
- const ticketErrors = allErrors.filter((line) => line.includes(ticketDir));
404
- return {
405
- ok: false,
406
- errors: ticketErrors.length > 0 ? ticketErrors : allErrors
407
- };
408
- }
409
376
  // src/generator/lint.ts
410
- import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync } from "fs";
411
- import { join as join6 } from "path";
377
+ import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync3 } from "fs";
378
+ import { join as join5 } from "path";
412
379
 
413
380
  // src/generator/selector-rules.ts
414
381
  var AUTO_CLASS_RE = /\.(?:Mui|css|ant|chakra|MuiButton)[A-Za-z]*-[A-Za-z0-9_]*-[A-Za-z0-9_]{3,}/;
@@ -456,11 +423,11 @@ function lintSelectors(source) {
456
423
 
457
424
  // src/generator/lint.ts
458
425
  function listTsFiles(dir) {
459
- if (!existsSync3(dir))
426
+ if (!existsSync2(dir))
460
427
  return [];
461
428
  const out = [];
462
429
  for (const name of readdirSync(dir, { withFileTypes: true })) {
463
- const full = join6(dir, name.name);
430
+ const full = join5(dir, name.name);
464
431
  if (name.isDirectory())
465
432
  out.push(...listTsFiles(full));
466
433
  else if (name.name.endsWith(".ts"))
@@ -480,18 +447,18 @@ async function lintTicket(ticketDir) {
480
447
  return { ok: warnings.length === 0, warnings };
481
448
  }
482
449
  // src/generator/pom-scan.ts
483
- import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync as readdirSync2 } from "fs";
484
- import { join as join7 } from "path";
450
+ import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
451
+ import { join as join6 } from "path";
485
452
  var CLASS_RE = /export\s+class\s+([A-Z][A-Za-z0-9_]*)/g;
486
453
  function scanSharedPoms(repoRoot) {
487
- const dir = join7(repoRoot, "shared", "page-objects");
488
- if (!existsSync4(dir))
454
+ const dir = join6(repoRoot, "shared", "page-objects");
455
+ if (!existsSync3(dir))
489
456
  return [];
490
457
  const found = [];
491
458
  for (const entry of readdirSync2(dir, { withFileTypes: true })) {
492
459
  if (!entry.isFile() || !entry.name.endsWith(".ts"))
493
460
  continue;
494
- const path = join7(dir, entry.name);
461
+ const path = join6(dir, entry.name);
495
462
  const src = readFileSync4(path, "utf8");
496
463
  for (const m of src.matchAll(CLASS_RE)) {
497
464
  found.push({ className: m[1], absolutePath: path });
@@ -500,28 +467,66 @@ function scanSharedPoms(repoRoot) {
500
467
  return found;
501
468
  }
502
469
  // src/generator/promote.ts
503
- import { existsSync as existsSync5, readFileSync as readFileSync5, renameSync, writeFileSync as writeFileSync3 } from "fs";
504
- import { join as join8 } from "path";
470
+ import { existsSync as existsSync4, readFileSync as readFileSync5, renameSync, writeFileSync as writeFileSync3 } from "fs";
471
+ import { join as join7 } from "path";
505
472
  async function promotePom(input) {
506
- const fromDir = join8(input.repoRoot, ".xera", input.ticket, "page-objects");
507
- const toDir = join8(input.repoRoot, "shared", "page-objects");
473
+ const fromDir = join7(input.repoRoot, ".xera", input.ticket, "page-objects");
474
+ const toDir = join7(input.repoRoot, "shared", "page-objects");
508
475
  const file = `${input.className}.ts`;
509
- const fromPath = join8(fromDir, file);
510
- const toPath = join8(toDir, file);
511
- if (!existsSync5(fromPath)) {
476
+ const fromPath = join7(fromDir, file);
477
+ const toPath = join7(toDir, file);
478
+ if (!existsSync4(fromPath)) {
512
479
  throw new Error(`POM ${file} not found at ${fromPath}`);
513
480
  }
514
- if (existsSync5(toPath)) {
481
+ if (existsSync4(toPath)) {
515
482
  throw new Error(`POM ${file} already exists at ${toPath}. Reconcile manually before promoting.`);
516
483
  }
517
484
  renameSync(fromPath, toPath);
518
- const specPath = join8(input.repoRoot, ".xera", input.ticket, "spec.ts");
519
- if (existsSync5(specPath)) {
485
+ const specPath = join7(input.repoRoot, ".xera", input.ticket, "spec.ts");
486
+ if (existsSync4(specPath)) {
520
487
  const src = readFileSync5(specPath, "utf8");
521
488
  const updated = src.replace(new RegExp(`from\\s+['"]\\./page-objects/${input.className}['"]`, "g"), `from '../../shared/page-objects/${input.className}'`);
522
489
  writeFileSync3(specPath, updated);
523
490
  }
524
491
  }
492
+ // src/generator/typecheck.ts
493
+ import { spawnSync } from "child_process";
494
+ import { existsSync as existsSync5 } from "fs";
495
+ import { dirname, join as join8 } from "path";
496
+ function findNearestTsconfig(start) {
497
+ let dir = start;
498
+ while (true) {
499
+ const candidate = join8(dir, "tsconfig.json");
500
+ if (existsSync5(candidate))
501
+ return candidate;
502
+ const parent = dirname(dir);
503
+ if (parent === dir)
504
+ return null;
505
+ dir = parent;
506
+ }
507
+ }
508
+ async function typecheckTicket(ticketDir) {
509
+ const tsconfig = findNearestTsconfig(ticketDir);
510
+ if (!tsconfig) {
511
+ return {
512
+ ok: false,
513
+ errors: [
514
+ `No tsconfig.json found walking up from ${ticketDir}. Run \`xera init\` to scaffold one at the project root.`
515
+ ]
516
+ };
517
+ }
518
+ const proc = spawnSync("npx", ["tsc", "--noEmit", "-p", tsconfig], { encoding: "utf8" });
519
+ if (proc.status === 0)
520
+ return { ok: true, errors: [] };
521
+ const out = `${proc.stdout ?? ""}${proc.stderr ?? ""}`;
522
+ const allErrors = out.split(`
523
+ `).filter((line) => /error TS\d+/.test(line));
524
+ const ticketErrors = allErrors.filter((line) => line.includes(ticketDir));
525
+ return {
526
+ ok: false,
527
+ errors: ticketErrors.length > 0 ? ticketErrors : allErrors
528
+ };
529
+ }
525
530
  export {
526
531
  validateGherkin,
527
532
  unzipTrace,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xera-ai/web",
3
- "version": "0.1.7",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -11,16 +11,19 @@
11
11
  "types": "./dist/index.d.ts"
12
12
  }
13
13
  },
14
- "files": ["dist", "src"],
14
+ "files": [
15
+ "dist",
16
+ "src"
17
+ ],
15
18
  "scripts": {
16
19
  "build": "bun build ./src/index.ts --outdir ./dist --target bun --external @playwright/test --external @xera-ai/core --external @cucumber/gherkin --external @cucumber/messages --external fflate",
17
20
  "typecheck": "tsc --noEmit"
18
21
  },
19
22
  "dependencies": {
20
- "@cucumber/gherkin": "30.0.4",
21
- "@cucumber/messages": "27.0.2",
22
- "@playwright/test": "1.48.0",
23
- "@xera-ai/core": "^0.1.5",
24
- "fflate": "0.8.2"
23
+ "@cucumber/gherkin": "39.1.0",
24
+ "@cucumber/messages": "32.3.1",
25
+ "@playwright/test": "1.60.0",
26
+ "@xera-ai/core": "^0.4.0",
27
+ "fflate": "0.8.3"
25
28
  }
26
29
  }
@@ -10,6 +10,7 @@ export interface RunPlaywrightInput {
10
10
  specPath: string;
11
11
  configPath: string;
12
12
  outputDir: string;
13
+ grep?: string;
13
14
  env?: NodeJS.ProcessEnv;
14
15
  spawn?: SpawnFn;
15
16
  }
@@ -31,6 +32,7 @@ export async function runPlaywright(input: RunPlaywrightInput): Promise<RunPlayw
31
32
  specPath: input.specPath,
32
33
  configPath: input.configPath,
33
34
  outputDir: input.outputDir,
35
+ ...(input.grep && { grep: input.grep }),
34
36
  });
35
37
  const spawn = input.spawn ?? defaultSpawn;
36
38
  const { exitCode } = await spawn('npx', ['playwright', ...args], {
@@ -2,10 +2,11 @@ export interface PlaywrightArgsInput {
2
2
  specPath: string;
3
3
  outputDir: string;
4
4
  configPath: string;
5
+ grep?: string;
5
6
  }
6
7
 
7
8
  export function buildPlaywrightArgs(input: PlaywrightArgsInput): string[] {
8
- return [
9
+ const args = [
9
10
  'test',
10
11
  input.specPath,
11
12
  `--config=${input.configPath}`,
@@ -13,4 +14,8 @@ export function buildPlaywrightArgs(input: PlaywrightArgsInput): string[] {
13
14
  `--output=${input.outputDir}`,
14
15
  '--trace=on',
15
16
  ];
17
+ if (input.grep) {
18
+ args.push('--grep', input.grep);
19
+ }
20
+ return args;
16
21
  }
@@ -1,6 +1,6 @@
1
- import { existsSync, readFileSync, readdirSync } from 'node:fs';
1
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- import { type SelectorWarning, lintSelectors } from './selector-rules';
3
+ import { lintSelectors, type SelectorWarning } from './selector-rules';
4
4
 
5
5
  export interface LintResult {
6
6
  ok: boolean;
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync, readdirSync } from 'node:fs';
1
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
 
4
4
  const CLASS_RE = /export\s+class\s+([A-Z][A-Za-z0-9_]*)/g;
package/src/index.ts CHANGED
@@ -1,17 +1,17 @@
1
1
  export * from './adapter';
2
2
  export * from './auth-setup/define';
3
- export * from './auth-setup/runner';
4
3
  export * from './auth-setup/playwright-state';
4
+ export * from './auth-setup/runner';
5
5
  export * from './executor';
6
6
  export * from './executor/playwright-args';
7
+ export * from './generator/gherkin-validate';
8
+ export * from './generator/lint';
9
+ export * from './generator/pom-scan';
10
+ export * from './generator/promote';
11
+ export * from './generator/selector-rules';
12
+ export * from './generator/typecheck';
7
13
  export * from './trace-normalizer/normalize';
8
14
  export * from './trace-normalizer/parse';
9
15
  export * from './trace-normalizer/scrub';
10
16
  export * from './trace-normalizer/scrub-rules';
11
17
  export * from './trace-normalizer/unzip';
12
- export * from './generator/gherkin-validate';
13
- export * from './generator/typecheck';
14
- export * from './generator/lint';
15
- export * from './generator/selector-rules';
16
- export * from './generator/pom-scan';
17
- export * from './generator/promote';
@@ -1,69 +0,0 @@
1
- import type { Classification } from '../artifact/status';
2
- import type { XeraConfig } from '../config/schema';
3
- export interface GenerateInput {
4
- ticketDir: string;
5
- feature: string;
6
- story: string;
7
- config: XeraConfig;
8
- }
9
- export interface GenerateResult {
10
- artifacts: string[];
11
- warnings: string[];
12
- }
13
- export interface ExecuteInput {
14
- ticketDir: string;
15
- config: XeraConfig;
16
- runId: string;
17
- env: string;
18
- }
19
- export interface ScenarioResult {
20
- name: string;
21
- outcome: 'PASS' | 'FAIL' | 'SKIPPED';
22
- failure?: {
23
- step?: string;
24
- errorMessage?: string;
25
- domSnapshotAtFailure?: string;
26
- networkAtFailure?: Array<{
27
- method: string;
28
- url: string;
29
- status: number;
30
- }>;
31
- consoleAtFailure?: string[];
32
- screenshotPath?: string;
33
- };
34
- }
35
- export interface RunResult {
36
- runId: string;
37
- outcome: 'PASS' | 'FAIL';
38
- scenarios: ScenarioResult[];
39
- artifactsDir: string;
40
- rawReportPath: string;
41
- normalizedReportPath: string;
42
- }
43
- export interface ClassifyContext {
44
- history: Array<{
45
- ts: string;
46
- result: 'PASS' | 'FAIL';
47
- class: Classification;
48
- }>;
49
- storyHashChanged: boolean;
50
- specHashChanged: boolean;
51
- }
52
- export interface DoctorReport {
53
- ok: boolean;
54
- checks: Array<{
55
- name: string;
56
- ok: boolean;
57
- message?: string;
58
- }>;
59
- }
60
- export interface TestAdapter {
61
- readonly id: string;
62
- generate(input: GenerateInput): Promise<GenerateResult>;
63
- execute(input: ExecuteInput): Promise<RunResult>;
64
- classify?(run: RunResult, ctx: ClassifyContext): Partial<{
65
- class: Classification;
66
- rationale: string;
67
- }>;
68
- doctor(): Promise<DoctorReport>;
69
- }
@@ -1,3 +0,0 @@
1
- export declare function hashString(s: string): string;
2
- export declare function hashFile(path: string): string;
3
- export declare function hashFileIfExists(path: string): string | null;
@@ -1,45 +0,0 @@
1
- import { z } from 'zod';
2
- export declare const MetaJsonSchema: z.ZodObject<{
3
- ticket: z.ZodString;
4
- adapter: z.ZodString;
5
- xera_version: z.ZodString;
6
- prompts_version: z.ZodString;
7
- fetched_at: z.ZodOptional<z.ZodString>;
8
- story_hash: z.ZodOptional<z.ZodString>;
9
- feature_generated_at: z.ZodOptional<z.ZodString>;
10
- feature_generated_from_story_hash: z.ZodOptional<z.ZodString>;
11
- feature_hash: z.ZodOptional<z.ZodString>;
12
- script_generated_at: z.ZodOptional<z.ZodString>;
13
- script_generated_from_feature_hash: z.ZodOptional<z.ZodString>;
14
- script_warnings: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
15
- }, "strip", z.ZodTypeAny, {
16
- ticket: string;
17
- adapter: string;
18
- xera_version: string;
19
- prompts_version: string;
20
- fetched_at?: string | undefined;
21
- story_hash?: string | undefined;
22
- feature_generated_at?: string | undefined;
23
- feature_generated_from_story_hash?: string | undefined;
24
- feature_hash?: string | undefined;
25
- script_generated_at?: string | undefined;
26
- script_generated_from_feature_hash?: string | undefined;
27
- script_warnings?: string[] | undefined;
28
- }, {
29
- ticket: string;
30
- adapter: string;
31
- xera_version: string;
32
- prompts_version: string;
33
- fetched_at?: string | undefined;
34
- story_hash?: string | undefined;
35
- feature_generated_at?: string | undefined;
36
- feature_generated_from_story_hash?: string | undefined;
37
- feature_hash?: string | undefined;
38
- script_generated_at?: string | undefined;
39
- script_generated_from_feature_hash?: string | undefined;
40
- script_warnings?: string[] | undefined;
41
- }>;
42
- export type MetaJson = z.infer<typeof MetaJsonSchema>;
43
- export declare function readMeta(path: string): MetaJson | null;
44
- export declare function writeMeta(path: string, meta: MetaJson): void;
45
- export declare function updateMeta(path: string, patch: Partial<MetaJson>): MetaJson;
@@ -1,24 +0,0 @@
1
- export interface RunPaths {
2
- runDir: string;
3
- reportJsonPath: string;
4
- tracePath: string;
5
- normalizedPath: string;
6
- screenshotsDir: string;
7
- videoDir: string;
8
- }
9
- export interface ArtifactPaths {
10
- ticketDir: string;
11
- storyPath: string;
12
- featurePath: string;
13
- specPath: string;
14
- pageObjectsDir: string;
15
- runsDir: string;
16
- metaPath: string;
17
- statusPath: string;
18
- logPath: string;
19
- lockPath: string;
20
- authDir: string;
21
- runPath: (runId: string) => RunPaths;
22
- }
23
- export declare function resolveArtifactPaths(repoRoot: string, ticket: string): ArtifactPaths;
24
- export declare function generateRunId(now?: Date): string;
@@ -1,95 +0,0 @@
1
- import { z } from 'zod';
2
- declare const ClassificationEnum: z.ZodEnum<["PASS", "REAL_BUG", "SELECTOR_DRIFT", "FLAKY", "TEST_BUG"]>;
3
- export declare const HistoryEntrySchema: z.ZodObject<{
4
- ts: z.ZodString;
5
- result: z.ZodEnum<["PASS", "FAIL"]>;
6
- class: z.ZodEnum<["PASS", "REAL_BUG", "SELECTOR_DRIFT", "FLAKY", "TEST_BUG"]>;
7
- }, "strip", z.ZodTypeAny, {
8
- ts: string;
9
- result: "PASS" | "FAIL";
10
- class: "PASS" | "REAL_BUG" | "SELECTOR_DRIFT" | "FLAKY" | "TEST_BUG";
11
- }, {
12
- ts: string;
13
- result: "PASS" | "FAIL";
14
- class: "PASS" | "REAL_BUG" | "SELECTOR_DRIFT" | "FLAKY" | "TEST_BUG";
15
- }>;
16
- export declare const StatusJsonSchema: z.ZodObject<{
17
- ticket: z.ZodString;
18
- lastRun: z.ZodString;
19
- result: z.ZodEnum<["PASS", "FAIL"]>;
20
- classification: z.ZodEnum<["PASS", "REAL_BUG", "SELECTOR_DRIFT", "FLAKY", "TEST_BUG"]>;
21
- confidence: z.ZodEnum<["low", "medium", "high"]>;
22
- scenarios: z.ZodObject<{
23
- total: z.ZodNumber;
24
- passed: z.ZodNumber;
25
- failed: z.ZodNumber;
26
- skipped: z.ZodNumber;
27
- }, "strip", z.ZodTypeAny, {
28
- total: number;
29
- passed: number;
30
- failed: number;
31
- skipped: number;
32
- }, {
33
- total: number;
34
- passed: number;
35
- failed: number;
36
- skipped: number;
37
- }>;
38
- history: z.ZodDefault<z.ZodArray<z.ZodObject<{
39
- ts: z.ZodString;
40
- result: z.ZodEnum<["PASS", "FAIL"]>;
41
- class: z.ZodEnum<["PASS", "REAL_BUG", "SELECTOR_DRIFT", "FLAKY", "TEST_BUG"]>;
42
- }, "strip", z.ZodTypeAny, {
43
- ts: string;
44
- result: "PASS" | "FAIL";
45
- class: "PASS" | "REAL_BUG" | "SELECTOR_DRIFT" | "FLAKY" | "TEST_BUG";
46
- }, {
47
- ts: string;
48
- result: "PASS" | "FAIL";
49
- class: "PASS" | "REAL_BUG" | "SELECTOR_DRIFT" | "FLAKY" | "TEST_BUG";
50
- }>, "many">>;
51
- last_jira_comment_id: z.ZodOptional<z.ZodString>;
52
- }, "strip", z.ZodTypeAny, {
53
- result: "PASS" | "FAIL";
54
- ticket: string;
55
- lastRun: string;
56
- classification: "PASS" | "REAL_BUG" | "SELECTOR_DRIFT" | "FLAKY" | "TEST_BUG";
57
- confidence: "low" | "medium" | "high";
58
- scenarios: {
59
- total: number;
60
- passed: number;
61
- failed: number;
62
- skipped: number;
63
- };
64
- history: {
65
- ts: string;
66
- result: "PASS" | "FAIL";
67
- class: "PASS" | "REAL_BUG" | "SELECTOR_DRIFT" | "FLAKY" | "TEST_BUG";
68
- }[];
69
- last_jira_comment_id?: string | undefined;
70
- }, {
71
- result: "PASS" | "FAIL";
72
- ticket: string;
73
- lastRun: string;
74
- classification: "PASS" | "REAL_BUG" | "SELECTOR_DRIFT" | "FLAKY" | "TEST_BUG";
75
- confidence: "low" | "medium" | "high";
76
- scenarios: {
77
- total: number;
78
- passed: number;
79
- failed: number;
80
- skipped: number;
81
- };
82
- history?: {
83
- ts: string;
84
- result: "PASS" | "FAIL";
85
- class: "PASS" | "REAL_BUG" | "SELECTOR_DRIFT" | "FLAKY" | "TEST_BUG";
86
- }[] | undefined;
87
- last_jira_comment_id?: string | undefined;
88
- }>;
89
- export type StatusJson = z.infer<typeof StatusJsonSchema>;
90
- export type HistoryEntry = z.infer<typeof HistoryEntrySchema>;
91
- export type Classification = z.infer<typeof ClassificationEnum>;
92
- export declare function readStatus(path: string): StatusJson | null;
93
- export declare function writeStatus(path: string, status: StatusJson): void;
94
- export declare function appendHistory(path: string, entry: HistoryEntry): StatusJson;
95
- export {};
@@ -1,3 +0,0 @@
1
- export declare function generateKey(): string;
2
- export declare function encrypt(plaintext: string, keyHex: string): string;
3
- export declare function decrypt(ciphertext: string, keyHex: string): string;
@@ -1,2 +0,0 @@
1
- export declare const AUTH_KEY_ENV = "XERA_AUTH_KEY";
2
- export declare function resolveAuthKey(): string;
@@ -1,8 +0,0 @@
1
- import type { AuthStateEntry } from './state';
2
- export type { AuthStateEntry } from './state';
3
- export declare function parseDuration(d: string): number;
4
- export interface RefreshPolicy {
5
- ttl: string;
6
- refreshBuffer: string;
7
- }
8
- export declare function needsRefresh(entry: AuthStateEntry | null, policy: RefreshPolicy, now?: Date): boolean;
@@ -1,23 +0,0 @@
1
- import { z } from 'zod';
2
- export declare const AuthStateEntrySchema: z.ZodObject<{
3
- role: z.ZodString;
4
- strategy: z.ZodEnum<["storageState", "apiToken"]>;
5
- created_at: z.ZodString;
6
- expires_at: z.ZodString;
7
- payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
8
- }, "strip", z.ZodTypeAny, {
9
- strategy: "storageState" | "apiToken";
10
- role: string;
11
- created_at: string;
12
- expires_at: string;
13
- payload: Record<string, unknown>;
14
- }, {
15
- strategy: "storageState" | "apiToken";
16
- role: string;
17
- created_at: string;
18
- expires_at: string;
19
- payload: Record<string, unknown>;
20
- }>;
21
- export type AuthStateEntry = z.infer<typeof AuthStateEntrySchema>;
22
- export declare function writeAuthState(authDir: string, entry: AuthStateEntry): void;
23
- export declare function readAuthState(authDir: string, role: string): AuthStateEntry | null;
@@ -1,2 +0,0 @@
1
- import type { XeraConfig } from './schema';
2
- export declare function defineConfig(config: XeraConfig): XeraConfig;
@@ -1,2 +0,0 @@
1
- import { type XeraConfig } from './schema';
2
- export declare function loadConfig(cwd: string): Promise<XeraConfig>;
@@ -1,325 +0,0 @@
1
- import { z } from 'zod';
2
- export declare const XeraConfigSchema: z.ZodObject<{
3
- jira: z.ZodObject<{
4
- baseUrl: z.ZodString;
5
- projectKeys: z.ZodArray<z.ZodString, "many">;
6
- fields: z.ZodObject<{
7
- story: z.ZodString;
8
- acceptanceCriteria: z.ZodOptional<z.ZodString>;
9
- attachments: z.ZodDefault<z.ZodString>;
10
- }, "strip", z.ZodTypeAny, {
11
- story: string;
12
- attachments: string;
13
- acceptanceCriteria?: string | undefined;
14
- }, {
15
- story: string;
16
- acceptanceCriteria?: string | undefined;
17
- attachments?: string | undefined;
18
- }>;
19
- }, "strip", z.ZodTypeAny, {
20
- baseUrl: string;
21
- projectKeys: string[];
22
- fields: {
23
- story: string;
24
- attachments: string;
25
- acceptanceCriteria?: string | undefined;
26
- };
27
- }, {
28
- baseUrl: string;
29
- projectKeys: string[];
30
- fields: {
31
- story: string;
32
- acceptanceCriteria?: string | undefined;
33
- attachments?: string | undefined;
34
- };
35
- }>;
36
- web: z.ZodEffects<z.ZodObject<{
37
- baseUrl: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodString>, Record<string, string>, Record<string, string>>;
38
- defaultEnv: z.ZodString;
39
- auth: z.ZodDefault<z.ZodObject<{
40
- strategy: z.ZodDefault<z.ZodEnum<["storageState", "apiToken", "none"]>>;
41
- ttl: z.ZodDefault<z.ZodString>;
42
- refreshBuffer: z.ZodDefault<z.ZodString>;
43
- setupScript: z.ZodOptional<z.ZodString>;
44
- roles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
45
- envEmail: z.ZodString;
46
- envPassword: z.ZodString;
47
- }, "strip", z.ZodTypeAny, {
48
- envEmail: string;
49
- envPassword: string;
50
- }, {
51
- envEmail: string;
52
- envPassword: string;
53
- }>>>;
54
- }, "strip", z.ZodTypeAny, {
55
- strategy: "storageState" | "apiToken" | "none";
56
- ttl: string;
57
- refreshBuffer: string;
58
- roles: Record<string, {
59
- envEmail: string;
60
- envPassword: string;
61
- }>;
62
- setupScript?: string | undefined;
63
- }, {
64
- strategy?: "storageState" | "apiToken" | "none" | undefined;
65
- ttl?: string | undefined;
66
- refreshBuffer?: string | undefined;
67
- setupScript?: string | undefined;
68
- roles?: Record<string, {
69
- envEmail: string;
70
- envPassword: string;
71
- }> | undefined;
72
- }>>;
73
- testData: z.ZodDefault<z.ZodObject<{
74
- users: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
75
- fromAuth: z.ZodString;
76
- }, "strip", z.ZodTypeAny, {
77
- fromAuth: string;
78
- }, {
79
- fromAuth: string;
80
- }>>>;
81
- }, "strip", z.ZodTypeAny, {
82
- users: Record<string, {
83
- fromAuth: string;
84
- }>;
85
- }, {
86
- users?: Record<string, {
87
- fromAuth: string;
88
- }> | undefined;
89
- }>>;
90
- }, "strip", z.ZodTypeAny, {
91
- baseUrl: Record<string, string>;
92
- defaultEnv: string;
93
- auth: {
94
- strategy: "storageState" | "apiToken" | "none";
95
- ttl: string;
96
- refreshBuffer: string;
97
- roles: Record<string, {
98
- envEmail: string;
99
- envPassword: string;
100
- }>;
101
- setupScript?: string | undefined;
102
- };
103
- testData: {
104
- users: Record<string, {
105
- fromAuth: string;
106
- }>;
107
- };
108
- }, {
109
- baseUrl: Record<string, string>;
110
- defaultEnv: string;
111
- auth?: {
112
- strategy?: "storageState" | "apiToken" | "none" | undefined;
113
- ttl?: string | undefined;
114
- refreshBuffer?: string | undefined;
115
- setupScript?: string | undefined;
116
- roles?: Record<string, {
117
- envEmail: string;
118
- envPassword: string;
119
- }> | undefined;
120
- } | undefined;
121
- testData?: {
122
- users?: Record<string, {
123
- fromAuth: string;
124
- }> | undefined;
125
- } | undefined;
126
- }>, {
127
- baseUrl: Record<string, string>;
128
- defaultEnv: string;
129
- auth: {
130
- strategy: "storageState" | "apiToken" | "none";
131
- ttl: string;
132
- refreshBuffer: string;
133
- roles: Record<string, {
134
- envEmail: string;
135
- envPassword: string;
136
- }>;
137
- setupScript?: string | undefined;
138
- };
139
- testData: {
140
- users: Record<string, {
141
- fromAuth: string;
142
- }>;
143
- };
144
- }, {
145
- baseUrl: Record<string, string>;
146
- defaultEnv: string;
147
- auth?: {
148
- strategy?: "storageState" | "apiToken" | "none" | undefined;
149
- ttl?: string | undefined;
150
- refreshBuffer?: string | undefined;
151
- setupScript?: string | undefined;
152
- roles?: Record<string, {
153
- envEmail: string;
154
- envPassword: string;
155
- }> | undefined;
156
- } | undefined;
157
- testData?: {
158
- users?: Record<string, {
159
- fromAuth: string;
160
- }> | undefined;
161
- } | undefined;
162
- }>;
163
- ai: z.ZodDefault<z.ZodObject<{
164
- livePageSnapshot: z.ZodDefault<z.ZodBoolean>;
165
- confidenceThreshold: z.ZodDefault<z.ZodEnum<["low", "medium", "high"]>>;
166
- maxRetries: z.ZodDefault<z.ZodObject<{
167
- typecheck: z.ZodDefault<z.ZodNumber>;
168
- lint: z.ZodDefault<z.ZodNumber>;
169
- validateFeature: z.ZodDefault<z.ZodNumber>;
170
- }, "strip", z.ZodTypeAny, {
171
- typecheck: number;
172
- lint: number;
173
- validateFeature: number;
174
- }, {
175
- typecheck?: number | undefined;
176
- lint?: number | undefined;
177
- validateFeature?: number | undefined;
178
- }>>;
179
- }, "strip", z.ZodTypeAny, {
180
- livePageSnapshot: boolean;
181
- confidenceThreshold: "low" | "medium" | "high";
182
- maxRetries: {
183
- typecheck: number;
184
- lint: number;
185
- validateFeature: number;
186
- };
187
- }, {
188
- livePageSnapshot?: boolean | undefined;
189
- confidenceThreshold?: "low" | "medium" | "high" | undefined;
190
- maxRetries?: {
191
- typecheck?: number | undefined;
192
- lint?: number | undefined;
193
- validateFeature?: number | undefined;
194
- } | undefined;
195
- }>>;
196
- reporting: z.ZodDefault<z.ZodObject<{
197
- language: z.ZodDefault<z.ZodEnum<["en", "vi"]>>;
198
- postToJira: z.ZodDefault<z.ZodBoolean>;
199
- transition: z.ZodDefault<z.ZodObject<{
200
- onPass: z.ZodDefault<z.ZodNullable<z.ZodString>>;
201
- onFail: z.ZodDefault<z.ZodNullable<z.ZodString>>;
202
- }, "strip", z.ZodTypeAny, {
203
- onPass: string | null;
204
- onFail: string | null;
205
- }, {
206
- onPass?: string | null | undefined;
207
- onFail?: string | null | undefined;
208
- }>>;
209
- artifactLinks: z.ZodDefault<z.ZodEnum<["git", "local"]>>;
210
- }, "strip", z.ZodTypeAny, {
211
- language: "en" | "vi";
212
- postToJira: boolean;
213
- transition: {
214
- onPass: string | null;
215
- onFail: string | null;
216
- };
217
- artifactLinks: "git" | "local";
218
- }, {
219
- language?: "en" | "vi" | undefined;
220
- postToJira?: boolean | undefined;
221
- transition?: {
222
- onPass?: string | null | undefined;
223
- onFail?: string | null | undefined;
224
- } | undefined;
225
- artifactLinks?: "git" | "local" | undefined;
226
- }>>;
227
- adapters: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
228
- }, "strip", z.ZodTypeAny, {
229
- jira: {
230
- baseUrl: string;
231
- projectKeys: string[];
232
- fields: {
233
- story: string;
234
- attachments: string;
235
- acceptanceCriteria?: string | undefined;
236
- };
237
- };
238
- web: {
239
- baseUrl: Record<string, string>;
240
- defaultEnv: string;
241
- auth: {
242
- strategy: "storageState" | "apiToken" | "none";
243
- ttl: string;
244
- refreshBuffer: string;
245
- roles: Record<string, {
246
- envEmail: string;
247
- envPassword: string;
248
- }>;
249
- setupScript?: string | undefined;
250
- };
251
- testData: {
252
- users: Record<string, {
253
- fromAuth: string;
254
- }>;
255
- };
256
- };
257
- ai: {
258
- livePageSnapshot: boolean;
259
- confidenceThreshold: "low" | "medium" | "high";
260
- maxRetries: {
261
- typecheck: number;
262
- lint: number;
263
- validateFeature: number;
264
- };
265
- };
266
- reporting: {
267
- language: "en" | "vi";
268
- postToJira: boolean;
269
- transition: {
270
- onPass: string | null;
271
- onFail: string | null;
272
- };
273
- artifactLinks: "git" | "local";
274
- };
275
- adapters: string[];
276
- }, {
277
- jira: {
278
- baseUrl: string;
279
- projectKeys: string[];
280
- fields: {
281
- story: string;
282
- acceptanceCriteria?: string | undefined;
283
- attachments?: string | undefined;
284
- };
285
- };
286
- web: {
287
- baseUrl: Record<string, string>;
288
- defaultEnv: string;
289
- auth?: {
290
- strategy?: "storageState" | "apiToken" | "none" | undefined;
291
- ttl?: string | undefined;
292
- refreshBuffer?: string | undefined;
293
- setupScript?: string | undefined;
294
- roles?: Record<string, {
295
- envEmail: string;
296
- envPassword: string;
297
- }> | undefined;
298
- } | undefined;
299
- testData?: {
300
- users?: Record<string, {
301
- fromAuth: string;
302
- }> | undefined;
303
- } | undefined;
304
- };
305
- ai?: {
306
- livePageSnapshot?: boolean | undefined;
307
- confidenceThreshold?: "low" | "medium" | "high" | undefined;
308
- maxRetries?: {
309
- typecheck?: number | undefined;
310
- lint?: number | undefined;
311
- validateFeature?: number | undefined;
312
- } | undefined;
313
- } | undefined;
314
- reporting?: {
315
- language?: "en" | "vi" | undefined;
316
- postToJira?: boolean | undefined;
317
- transition?: {
318
- onPass?: string | null | undefined;
319
- onFail?: string | null | undefined;
320
- } | undefined;
321
- artifactLinks?: "git" | "local" | undefined;
322
- } | undefined;
323
- adapters?: string[] | undefined;
324
- }>;
325
- export type XeraConfig = z.infer<typeof XeraConfigSchema>;
@@ -1,19 +0,0 @@
1
- export declare const VERSION = "0.1.0";
2
- export type * from './adapter/types';
3
- export * from './config/schema';
4
- export * from './config/define';
5
- export * from './config/load';
6
- export * from './artifact/paths';
7
- export * from './artifact/hash';
8
- export * from './artifact/meta';
9
- export * from './artifact/status';
10
- export * from './logging/ndjson-logger';
11
- export * from './lock/file-lock';
12
- export * from './jira/types';
13
- export * from './jira/client';
14
- export * from './jira/fields';
15
- export * from './jira/retry';
16
- export * from './auth/encrypt';
17
- export * from './auth/key';
18
- export * from './auth/state';
19
- export * from './auth/refresh';
@@ -1,10 +0,0 @@
1
- import type { JiraClient } from './types';
2
- export interface CreateJiraClientOptions {
3
- baseUrl: string;
4
- preferMcp?: boolean;
5
- rest?: {
6
- email: string;
7
- apiToken: string;
8
- };
9
- }
10
- export declare function createJiraClient(opts: CreateJiraClientOptions): Promise<JiraClient>;
@@ -1,6 +0,0 @@
1
- export interface JiraFieldInfo {
2
- id: string;
3
- name: string;
4
- hasContent: boolean;
5
- }
6
- export declare function rankStoryCandidates(fields: JiraFieldInfo[]): JiraFieldInfo[];
@@ -1,2 +0,0 @@
1
- import type { JiraClient } from './types';
2
- export declare function createMcpBackend(_baseUrl: string): Promise<JiraClient | null>;
@@ -1,7 +0,0 @@
1
- import type { JiraClient } from './types';
2
- interface RestCreds {
3
- email: string;
4
- apiToken: string;
5
- }
6
- export declare function createRestBackend(baseUrl: string, creds: RestCreds): JiraClient;
7
- export {};
@@ -1,7 +0,0 @@
1
- export interface RetryOptions {
2
- maxAttempts: number;
3
- baseMs: number;
4
- factor: number;
5
- shouldRetry?: (err: unknown) => boolean;
6
- }
7
- export declare function withRetry<T>(fn: () => Promise<T>, opts: RetryOptions): Promise<T>;
@@ -1,28 +0,0 @@
1
- export interface JiraTicket {
2
- key: string;
3
- summary: string;
4
- story: string;
5
- acceptanceCriteria?: string;
6
- attachments: Array<{
7
- filename: string;
8
- url: string;
9
- }>;
10
- raw: Record<string, unknown>;
11
- }
12
- export interface JiraFieldMap {
13
- story: string;
14
- acceptanceCriteria?: string;
15
- }
16
- export interface JiraClient {
17
- readonly backend: 'mcp' | 'rest';
18
- fetchTicket(key: string, fields: JiraFieldMap): Promise<JiraTicket>;
19
- postComment(key: string, body: string): Promise<{
20
- id: string;
21
- }>;
22
- transitionStatus(key: string, statusName: string): Promise<void>;
23
- listFields(sampleKey: string): Promise<Array<{
24
- id: string;
25
- name: string;
26
- hasContent: boolean;
27
- }>>;
28
- }
@@ -1,11 +0,0 @@
1
- export interface LockData {
2
- pid: number;
3
- hostname: string;
4
- started_at: string;
5
- run_id: string;
6
- }
7
- export declare function acquireLock(path: string, runId: string): boolean;
8
- export declare function releaseLock(path: string): void;
9
- export declare function readLock(path: string): LockData | null;
10
- export declare function isLockStale(path: string): boolean;
11
- export declare function forceUnlock(path: string): void;
@@ -1,10 +0,0 @@
1
- export interface LogEntry {
2
- ts: string;
3
- [key: string]: unknown;
4
- }
5
- export declare class NdjsonLogger {
6
- private readonly path;
7
- constructor(path: string);
8
- log(payload: Record<string, unknown>): void;
9
- static readAll(path: string): LogEntry[];
10
- }
File without changes
File without changes
@@ -1,17 +1,17 @@
1
1
  export * from './adapter';
2
2
  export * from './auth-setup/define';
3
- export * from './auth-setup/runner';
4
3
  export * from './auth-setup/playwright-state';
4
+ export * from './auth-setup/runner';
5
5
  export * from './executor';
6
6
  export * from './executor/playwright-args';
7
+ export * from './generator/gherkin-validate';
8
+ export * from './generator/lint';
9
+ export * from './generator/pom-scan';
10
+ export * from './generator/promote';
11
+ export * from './generator/selector-rules';
12
+ export * from './generator/typecheck';
7
13
  export * from './trace-normalizer/normalize';
8
14
  export * from './trace-normalizer/parse';
9
15
  export * from './trace-normalizer/scrub';
10
16
  export * from './trace-normalizer/scrub-rules';
11
17
  export * from './trace-normalizer/unzip';
12
- export * from './generator/gherkin-validate';
13
- export * from './generator/typecheck';
14
- export * from './generator/lint';
15
- export * from './generator/selector-rules';
16
- export * from './generator/pom-scan';
17
- export * from './generator/promote';