@hover-dev/core 0.16.0 → 0.18.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 (181) hide show
  1. package/README.md +26 -55
  2. package/dist/agentDirectives.d.ts +55 -0
  3. package/dist/agentDirectives.d.ts.map +1 -0
  4. package/dist/agentDirectives.js +276 -0
  5. package/dist/engine.d.ts +28 -0
  6. package/dist/engine.d.ts.map +1 -0
  7. package/dist/engine.js +27 -0
  8. package/dist/memory/businessMemory.d.ts +29 -0
  9. package/dist/memory/businessMemory.d.ts.map +1 -0
  10. package/dist/memory/businessMemory.js +125 -0
  11. package/dist/playwright/launchChrome.d.ts +18 -0
  12. package/dist/playwright/launchChrome.d.ts.map +1 -1
  13. package/dist/playwright/launchChrome.js +46 -3
  14. package/dist/qa/candidates.d.ts +32 -0
  15. package/dist/qa/candidates.d.ts.map +1 -0
  16. package/dist/qa/candidates.js +20 -0
  17. package/dist/qa/intensity.d.ts +33 -0
  18. package/dist/qa/intensity.d.ts.map +1 -0
  19. package/dist/qa/intensity.js +25 -0
  20. package/dist/qa/qaReport.d.ts +19 -0
  21. package/dist/qa/qaReport.d.ts.map +1 -0
  22. package/dist/qa/qaReport.js +50 -0
  23. package/dist/sessions/sessions.d.ts +125 -0
  24. package/dist/sessions/sessions.d.ts.map +1 -0
  25. package/dist/sessions/sessions.js +175 -0
  26. package/dist/specs/authFixture.d.ts +30 -0
  27. package/dist/specs/authFixture.d.ts.map +1 -0
  28. package/dist/specs/authFixture.js +145 -0
  29. package/dist/specs/detectSharedFlows.d.ts +1 -1
  30. package/dist/specs/detectSharedFlows.d.ts.map +1 -1
  31. package/dist/specs/detectSharedFlows.js +20 -21
  32. package/dist/specs/generatePageObject.d.ts +1 -1
  33. package/dist/specs/generatePageObject.d.ts.map +1 -1
  34. package/dist/specs/healPrompt.d.ts +19 -0
  35. package/dist/specs/healPrompt.d.ts.map +1 -0
  36. package/dist/specs/healPrompt.js +48 -0
  37. package/dist/specs/humanSteps.d.ts +4 -8
  38. package/dist/specs/humanSteps.d.ts.map +1 -1
  39. package/dist/specs/humanSteps.js +6 -1
  40. package/dist/specs/optimizeSpec.d.ts +15 -8
  41. package/dist/specs/optimizeSpec.d.ts.map +1 -1
  42. package/dist/specs/optimizeSpec.js +71 -41
  43. package/dist/specs/pageObjectManifest.d.ts +3 -1
  44. package/dist/specs/pageObjectManifest.d.ts.map +1 -1
  45. package/dist/specs/pageObjectManifest.js +24 -19
  46. package/dist/specs/replayGrounded.d.ts +45 -0
  47. package/dist/specs/replayGrounded.d.ts.map +1 -0
  48. package/dist/specs/replayGrounded.js +155 -0
  49. package/dist/specs/runFailures.d.ts +34 -0
  50. package/dist/specs/runFailures.d.ts.map +1 -0
  51. package/dist/specs/runFailures.js +93 -0
  52. package/dist/specs/seeds.d.ts +16 -15
  53. package/dist/specs/seeds.d.ts.map +1 -1
  54. package/dist/specs/seeds.js +86 -54
  55. package/dist/specs/sidecar.d.ts +34 -6
  56. package/dist/specs/sidecar.d.ts.map +1 -1
  57. package/dist/specs/sidecar.js +79 -9
  58. package/dist/specs/specStep.d.ts +21 -0
  59. package/dist/specs/specStep.d.ts.map +1 -0
  60. package/dist/specs/specStep.js +1 -0
  61. package/dist/specs/text.d.ts +8 -6
  62. package/dist/specs/text.d.ts.map +1 -1
  63. package/dist/specs/text.js +10 -7
  64. package/dist/specs/writeSpec.d.ts +62 -1
  65. package/dist/specs/writeSpec.d.ts.map +1 -1
  66. package/dist/specs/writeSpec.js +596 -21
  67. package/package.json +9 -29
  68. package/dist/agents/aider.d.ts +0 -16
  69. package/dist/agents/aider.d.ts.map +0 -1
  70. package/dist/agents/aider.js +0 -161
  71. package/dist/agents/argv.d.ts +0 -11
  72. package/dist/agents/argv.d.ts.map +0 -1
  73. package/dist/agents/argv.js +0 -23
  74. package/dist/agents/claude.d.ts +0 -3
  75. package/dist/agents/claude.d.ts.map +0 -1
  76. package/dist/agents/claude.js +0 -195
  77. package/dist/agents/codex.d.ts +0 -19
  78. package/dist/agents/codex.d.ts.map +0 -1
  79. package/dist/agents/codex.js +0 -216
  80. package/dist/agents/cursor.d.ts +0 -18
  81. package/dist/agents/cursor.d.ts.map +0 -1
  82. package/dist/agents/cursor.js +0 -220
  83. package/dist/agents/detect.d.ts +0 -46
  84. package/dist/agents/detect.d.ts.map +0 -1
  85. package/dist/agents/detect.js +0 -80
  86. package/dist/agents/gemini.d.ts +0 -17
  87. package/dist/agents/gemini.d.ts.map +0 -1
  88. package/dist/agents/gemini.js +0 -186
  89. package/dist/agents/index.d.ts +0 -6
  90. package/dist/agents/index.d.ts.map +0 -1
  91. package/dist/agents/index.js +0 -5
  92. package/dist/agents/invoke.d.ts +0 -12
  93. package/dist/agents/invoke.d.ts.map +0 -1
  94. package/dist/agents/invoke.js +0 -96
  95. package/dist/agents/qwen.d.ts +0 -17
  96. package/dist/agents/qwen.d.ts.map +0 -1
  97. package/dist/agents/qwen.js +0 -172
  98. package/dist/agents/registry.d.ts +0 -19
  99. package/dist/agents/registry.d.ts.map +0 -1
  100. package/dist/agents/registry.js +0 -34
  101. package/dist/agents/shared.d.ts +0 -28
  102. package/dist/agents/shared.d.ts.map +0 -1
  103. package/dist/agents/shared.js +0 -35
  104. package/dist/agents/types.d.ts +0 -186
  105. package/dist/agents/types.d.ts.map +0 -1
  106. package/dist/agents/types.js +0 -23
  107. package/dist/index.d.ts +0 -3
  108. package/dist/index.d.ts.map +0 -1
  109. package/dist/index.js +0 -2
  110. package/dist/mcp/sourceFence.d.ts +0 -23
  111. package/dist/mcp/sourceFence.d.ts.map +0 -1
  112. package/dist/mcp/sourceFence.js +0 -75
  113. package/dist/mcp/sourceServer.d.ts +0 -3
  114. package/dist/mcp/sourceServer.d.ts.map +0 -1
  115. package/dist/mcp/sourceServer.js +0 -116
  116. package/dist/playwright/cdpStatus.d.ts +0 -29
  117. package/dist/playwright/cdpStatus.d.ts.map +0 -1
  118. package/dist/playwright/cdpStatus.js +0 -119
  119. package/dist/playwright/preflight.d.ts +0 -31
  120. package/dist/playwright/preflight.d.ts.map +0 -1
  121. package/dist/playwright/preflight.js +0 -82
  122. package/dist/playwright/preflightCache.d.ts +0 -27
  123. package/dist/playwright/preflightCache.d.ts.map +0 -1
  124. package/dist/playwright/preflightCache.js +0 -21
  125. package/dist/playwright/raiseWindow.d.ts +0 -10
  126. package/dist/playwright/raiseWindow.d.ts.map +0 -1
  127. package/dist/playwright/raiseWindow.js +0 -158
  128. package/dist/playwright/resolveMcpConfig.d.ts +0 -55
  129. package/dist/playwright/resolveMcpConfig.d.ts.map +0 -1
  130. package/dist/playwright/resolveMcpConfig.js +0 -66
  131. package/dist/plugin-api.d.ts +0 -235
  132. package/dist/plugin-api.d.ts.map +0 -1
  133. package/dist/plugin-api.js +0 -52
  134. package/dist/runSession.d.ts +0 -42
  135. package/dist/runSession.d.ts.map +0 -1
  136. package/dist/runSession.js +0 -81
  137. package/dist/scripts/bench-multi-tab.d.ts +0 -2
  138. package/dist/scripts/bench-multi-tab.d.ts.map +0 -1
  139. package/dist/scripts/bench-multi-tab.js +0 -192
  140. package/dist/scripts/bench-ttfb.d.ts +0 -2
  141. package/dist/scripts/bench-ttfb.d.ts.map +0 -1
  142. package/dist/scripts/bench-ttfb.js +0 -127
  143. package/dist/scripts/start-chrome.d.ts +0 -3
  144. package/dist/scripts/start-chrome.d.ts.map +0 -1
  145. package/dist/scripts/start-chrome.js +0 -23
  146. package/dist/service/cdpHandlers.d.ts +0 -44
  147. package/dist/service/cdpHandlers.d.ts.map +0 -1
  148. package/dist/service/cdpHandlers.js +0 -85
  149. package/dist/service/cdpHint.d.ts +0 -48
  150. package/dist/service/cdpHint.d.ts.map +0 -1
  151. package/dist/service/cdpHint.js +0 -216
  152. package/dist/service/conventions.d.ts +0 -8
  153. package/dist/service/conventions.d.ts.map +0 -1
  154. package/dist/service/conventions.js +0 -42
  155. package/dist/service/saveHandlers.d.ts +0 -52
  156. package/dist/service/saveHandlers.d.ts.map +0 -1
  157. package/dist/service/saveHandlers.js +0 -75
  158. package/dist/service/types.d.ts +0 -58
  159. package/dist/service/types.d.ts.map +0 -1
  160. package/dist/service/types.js +0 -26
  161. package/dist/service.d.ts +0 -50
  162. package/dist/service.d.ts.map +0 -1
  163. package/dist/service.js +0 -1065
  164. package/dist/skills/writeSkill.d.ts +0 -27
  165. package/dist/skills/writeSkill.d.ts.map +0 -1
  166. package/dist/skills/writeSkill.js +0 -13
  167. package/dist/specs/extractPageObjects.d.ts +0 -18
  168. package/dist/specs/extractPageObjects.d.ts.map +0 -1
  169. package/dist/specs/extractPageObjects.js +0 -98
  170. package/dist/specs/listSpecs.d.ts +0 -52
  171. package/dist/specs/listSpecs.d.ts.map +0 -1
  172. package/dist/specs/listSpecs.js +0 -139
  173. package/dist/specs/optimizationSuggestion.d.ts +0 -26
  174. package/dist/specs/optimizationSuggestion.d.ts.map +0 -1
  175. package/dist/specs/optimizationSuggestion.js +0 -28
  176. package/dist/specs/optimizeSpecWithAgent.d.ts +0 -11
  177. package/dist/specs/optimizeSpecWithAgent.d.ts.map +0 -1
  178. package/dist/specs/optimizeSpecWithAgent.js +0 -40
  179. package/dist/specs/writeCaseCsv.d.ts +0 -28
  180. package/dist/specs/writeCaseCsv.d.ts.map +0 -1
  181. package/dist/specs/writeCaseCsv.js +0 -134
@@ -1,71 +1,103 @@
1
1
  /**
2
- * Community translation seeds (Stage 6, approach A): human-written worked
3
- * examples that teach the optimization pass (F7) new patterns by few-shot,
4
- * NOT by deterministic match+template. A seed is a rough `signature` (tool
5
- * names, used only to pick relevant seeds) + a concrete `example`
6
- * (input steps → output code) the LLM generalizes from.
2
+ * Translation seeds: human-written worked examples that teach the optimization
3
+ * pass (F7) a multi-step Playwright pattern by few-shot — NOT by deterministic
4
+ * match+template. A seed is a rough `signature` (tool names, used only to pick
5
+ * relevant seeds) + a concrete `example` (input steps → output code) the LLM
6
+ * generalizes from.
7
7
  *
8
- * Sources: a small built-in set + the project's <projectRoot>/.hover/rules/.
9
- * Adding a pattern = dropping an example JSON in .hover/rules/ — no core change.
10
- *
11
- * Built-in seeds deliberately cover patterns the deterministic translator does
12
- * NOT hardcode (popup is already hardcoded in writeSpec, so it's not here).
8
+ * These ship inlined as the `BUILTIN_SEEDS` constant below. They used to be
9
+ * JSON files under `packages/core/seeds/optimization/` plus a `.hover/rules/`
10
+ * "author your own seed" mechanism and a `.hover/seeds.json` opt-out — all
11
+ * removed: that user-facing surface added burden for a small curated catalogue
12
+ * that feeds an optional, manually-invoked pass. To add a pattern, append a
13
+ * `SeedRule` here.
13
14
  */
14
- import { readFile, readdir } from 'node:fs/promises';
15
- import { join } from 'node:path';
16
15
  /**
17
- * Built-in seeds ship with core and feed EVERY project's optimization pass, so
18
- * the bar is high: a pattern qualifies as built-in ONLY if it's a *highly
19
- * certain* optimization — a fixed, app-agnostic translation whose output is
20
- * deterministic and can't mislead (e.g. download → waitForEvent pairing).
21
- *
22
- * Deliberately NOT built-in:
23
- * - Semantic / judgement-based optimizations (e.g. WHICH feedback text to
24
- * assert) — those are already standing instructions in buildOptimizePrompt,
25
- * and a bad generalization would pollute every user's spec.
26
- * - Popup/new-tab — hardcoded in the translator (writeSpec), not a seed.
27
- * Project-specific or speculative patterns live in <root>/.hover/rules/, where
28
- * the bar is the user's own call.
16
+ * Built-in optimization seeds, inlined. They feed EVERY project's optimization
17
+ * pass (the prompt builder and the relevance filter consume this directly).
29
18
  */
30
19
  export const BUILTIN_SEEDS = [
31
20
  {
32
21
  name: 'download',
33
22
  signature: ['browser_click'],
34
- note: 'a click that triggers a file download pair with waitForEvent("download")',
23
+ note: 'A click that triggers a file download pair it with waitForEvent(\'download\') so the listener is registered before the click fires.',
35
24
  example: {
36
25
  steps: [{ tool: 'browser_click', element: 'Export CSV button' }],
37
- code: "const [download] = await Promise.all([\n" +
38
- " page.waitForEvent('download'),\n" +
39
- " page.getByRole('button', { name: 'Export CSV' }).click(),\n" +
40
- "]);\n" +
41
- "expect(await download.suggestedFilename()).toContain('.csv');",
26
+ code: `const [download] = await Promise.all([
27
+ page.waitForEvent('download'),
28
+ page.getByRole('button', { name: 'Export CSV' }).click(),
29
+ ]);
30
+ expect(await download.suggestedFilename()).toContain('.csv');`,
31
+ },
32
+ },
33
+ {
34
+ name: 'file-upload',
35
+ signature: ['browser_file_upload'],
36
+ note: 'Set a file on a (often hidden) <input type=file>. The file chooser opens synchronously on click, so register waitForEvent(\'filechooser\') before the click — same race as download.',
37
+ example: {
38
+ steps: [
39
+ { tool: 'browser_click', element: 'Upload avatar button' },
40
+ { tool: 'browser_file_upload', paths: ['avatar.png'] },
41
+ ],
42
+ code: `const [chooser] = await Promise.all([
43
+ page.waitForEvent('filechooser'),
44
+ page.getByRole('button', { name: 'Upload avatar' }).click(),
45
+ ]);
46
+ await chooser.setFiles('tests/fixtures/avatar.png');
47
+ await expect(page.getByText('avatar.png')).toBeVisible();`,
48
+ },
49
+ },
50
+ {
51
+ name: 'dialog',
52
+ signature: ['browser_handle_dialog'],
53
+ note: 'A click that triggers a native dialog (alert/confirm/prompt). Register the page \'dialog\' handler BEFORE the click that fires it — otherwise Playwright auto-dismisses it and the assertion is wrong.',
54
+ example: {
55
+ steps: [
56
+ { tool: 'browser_click', element: 'Delete account button' },
57
+ { tool: 'browser_handle_dialog', action: 'accept' },
58
+ ],
59
+ code: `page.once('dialog', dialog => dialog.accept());
60
+ await page.getByRole('button', { name: 'Delete account' }).click();
61
+ await expect(page.getByText('Account deleted')).toBeVisible();`,
62
+ },
63
+ },
64
+ {
65
+ name: 'oauth-popup',
66
+ signature: ['browser_click', 'browser_tabs:select'],
67
+ note: 'Sign in through a provider popup that opens a new tab. Pair the opener click with context.waitForEvent(\'page\'), then drive the returned popup page.',
68
+ example: {
69
+ steps: [
70
+ { tool: 'browser_click', element: 'Sign in with Google button' },
71
+ { tool: 'browser_tabs', action: 'select', idx: 1 },
72
+ ],
73
+ code: `const [popup] = await Promise.all([
74
+ context.waitForEvent('page'),
75
+ page.getByRole('button', { name: 'Sign in with Google' }).click(),
76
+ ]);
77
+ await popup.getByLabel('Email').fill('user@example.com');
78
+ await popup.getByRole('button', { name: 'Next' }).click();
79
+ await popup.waitForEvent('close');
80
+ await expect(page.getByText('Signed in')).toBeVisible();`,
81
+ },
82
+ },
83
+ {
84
+ name: 'network-gated-assertion',
85
+ signature: ['browser_click', 'browser_wait_for'],
86
+ note: 'A click fires an XHR/fetch and the result is asserted. Pair the click with page.waitForResponse so the test waits for the real request to settle, instead of a guessed timeout or a race.',
87
+ example: {
88
+ steps: [
89
+ { tool: 'browser_click', element: 'Place order button' },
90
+ { tool: 'browser_wait_for', text: 'Order confirmed' },
91
+ ],
92
+ code: `const [res] = await Promise.all([
93
+ page.waitForResponse(r => r.url().includes('/api/orders') && r.request().method() === 'POST'),
94
+ page.getByRole('button', { name: 'Place order' }).click(),
95
+ ]);
96
+ expect(res.ok()).toBeTruthy();
97
+ await expect(page.getByText('Order confirmed')).toBeVisible();`,
42
98
  },
43
99
  },
44
100
  ];
45
- /** Built-in seeds + any in <projectRoot>/.hover/rules/*.json. Malformed files
46
- * are skipped rather than failing the whole read. */
47
- export async function readSeeds(projectRoot) {
48
- const out = [...BUILTIN_SEEDS];
49
- try {
50
- const dir = join(projectRoot, '.hover', 'rules');
51
- for (const f of await readdir(dir)) {
52
- if (!f.endsWith('.json'))
53
- continue;
54
- try {
55
- const s = JSON.parse(await readFile(join(dir, f), 'utf-8'));
56
- if (s && s.name && Array.isArray(s.signature) && s.example?.code)
57
- out.push(s);
58
- }
59
- catch {
60
- /* skip malformed seed file */
61
- }
62
- }
63
- }
64
- catch {
65
- /* no .hover/rules/ directory */
66
- }
67
- return out;
68
- }
69
101
  /** Pick seeds whose signature's base tool appears in the spec — a cheap
70
102
  * relevance filter so the prompt only carries plausibly-applicable examples. */
71
103
  export function relevantSeeds(seeds, specTools, cap = 6) {
@@ -1,4 +1,4 @@
1
- import type { SkillStep } from '../skills/writeSkill.js';
1
+ import type { SkillStep } from '../specs/specStep.js';
2
2
  import type { SpecAssertion } from './writeSpec.js';
3
3
  /** Current sidecar schema version. Bump when the shape changes so readers
4
4
  * (Stage 2 detection, Stage 7 optimization) can migrate or skip cleanly. */
@@ -15,11 +15,39 @@ export interface SpecSidecar {
15
15
  /** Alt-click assertions captured alongside the session. */
16
16
  assertions: SpecAssertion[];
17
17
  }
18
- /** Sidecar directory under the spec output dir. Dot-prefixed on purpose:
19
- * Playwright's default `*.spec.ts` glob never reaches into `.hover/`. */
18
+ /** Project-root `.hover/` directory the single home for Hover-derived data
19
+ * (sidecars, runs, rules, conventions). */
20
+ export declare function hoverDir(devRoot: string): string;
21
+ /** Sanitize an id segment for use as a directory name (conversation / run id). */
22
+ export declare function safeSeg(s: string): string;
23
+ /** Per-run home: `<devRoot>/.hover/conversations/<conversationId>/<runId>/`.
24
+ * Everything a single agent run produces — meta.json (the ledger record),
25
+ * report.md (QA), screenshots/ — lives here, grouped under its conversation so
26
+ * deleting a conversation is one `rm -rf .hover/conversations/<conversationId>`.
27
+ * (Distinct from `.hover/runs/`, which is the Playwright spec-run-results
28
+ * ledger written by ▶ Run.) */
29
+ export declare function conversationsDir(devRoot: string): string;
30
+ export declare function conversationDir(devRoot: string, conversationId: string): string;
31
+ export declare function runDir(devRoot: string, conversationId: string, runId: string): string;
32
+ /** Sidecar directory: `<devRoot>/.hover/sidecars`. Outside `__vibe_tests__/`,
33
+ * so Playwright's default `*.spec.ts` glob trivially never reaches it. */
20
34
  export declare function sidecarDir(devRoot: string): string;
21
- /** Write the structured-session sidecar at `.hover/<slug>.json`. Caller passes
22
- * the data minus the stamped fields (`version`, `createdAt`), which this
23
- * function fills. Returns the absolute path written. */
35
+ /** Pre-relocation sidecar home (`__vibe_tests__/.hover/`). Read-only fallback;
36
+ * nothing writes here anymore. */
37
+ export declare function legacySidecarDir(devRoot: string): string;
38
+ /** Write the structured-session sidecar at `.hover/sidecars/<slug>.json`.
39
+ * Caller passes the data minus the stamped fields (`version`, `createdAt`),
40
+ * which this function fills. Returns the absolute path written. */
24
41
  export declare function writeSidecar(devRoot: string, data: Omit<SpecSidecar, 'version' | 'createdAt'>): Promise<string>;
42
+ /**
43
+ * Read one sidecar by slug, with legacy fallback + lazy copy-forward: when a
44
+ * sidecar only exists at the pre-relocation `__vibe_tests__/.hover/` path it
45
+ * is parsed from there and best-effort re-written into `.hover/sidecars/` so
46
+ * the next read hits the new home. Returns `null` when absent or malformed.
47
+ */
48
+ export declare function readSidecar(devRoot: string, slug: string): Promise<SpecSidecar | null>;
49
+ /** Parse one sidecar file, or `null` when absent / not JSON. Deliberately
50
+ * lenient on shape (an empty `{}` still counts as "a sidecar exists") —
51
+ * consumers that need `steps`/`slug` filter for themselves. */
52
+ export declare function parseSidecarFile(path: string): Promise<SpecSidecar | null>;
25
53
  //# sourceMappingURL=sidecar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidecar.d.ts","sourceRoot":"","sources":["../../src/specs/sidecar.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;6EAC6E;AAC7E,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB;yCACqC;IACrC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,2DAA2D;IAC3D,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED;0EAC0E;AAC1E,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;yDAEyD;AACzD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,WAAW,CAAC,GAC/C,OAAO,CAAC,MAAM,CAAC,CAWjB"}
1
+ {"version":3,"file":"sidecar.d.ts","sourceRoot":"","sources":["../../src/specs/sidecar.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;6EAC6E;AAC7E,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB;yCACqC;IACrC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,2DAA2D;IAC3D,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED;4CAC4C;AAC5C,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED;;;;;gCAKgC;AAChC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AACD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAE/E;AACD,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAErF;AAED;2EAC2E;AAC3E,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;mCACmC;AACnC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;oEAEoE;AACpE,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,WAAW,CAAC,GAC/C,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAoB5F;AAED;;gEAEgE;AAChE,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAOhF"}
@@ -1,29 +1,62 @@
1
1
  /**
2
2
  * Structured-session sidecar for a generated spec.
3
3
  *
4
- * Every saved spec gets a companion `__vibe_tests__/.hover/<slug>.json` holding
4
+ * Every saved spec gets a companion `.hover/sidecars/<slug>.json` holding
5
5
  * the original structured `SpecStep[]` (plus assertions + metadata). The
6
6
  * `.spec.ts` is the human / CI artifact; this sidecar is the machine record
7
7
  * that downstream work reads instead of parsing generated code:
8
8
  * - F4 cross-session extraction signature-matches `steps` across sidecars.
9
9
  * - F7 optimization pass feeds the draft + this sidecar to the LLM.
10
10
  *
11
- * It lands in a dot-prefixed `.hover/` dir so Playwright's default `*.spec.ts`
12
- * glob never collects it, and it is pure data no Hover runtime import.
11
+ * Home is the project-root `.hover/` directory (the same home as
12
+ * `.hover/conventions.md`) Hover-derived data lives outside
13
+ * `__vibe_tests__/`, which stays 100% user-owned Playwright code. Sidecars
14
+ * historically lived nested at `__vibe_tests__/.hover/<slug>.json`; readers
15
+ * fall back to that legacy path and lazily copy-forward, so pre-existing
16
+ * projects keep working without a migration step.
13
17
  */
14
- import { mkdir, writeFile } from 'node:fs/promises';
18
+ import { mkdir, writeFile, readFile } from 'node:fs/promises';
15
19
  import { join } from 'node:path';
16
20
  /** Current sidecar schema version. Bump when the shape changes so readers
17
21
  * (Stage 2 detection, Stage 7 optimization) can migrate or skip cleanly. */
18
22
  export const SIDECAR_VERSION = 1;
19
- /** Sidecar directory under the spec output dir. Dot-prefixed on purpose:
20
- * Playwright's default `*.spec.ts` glob never reaches into `.hover/`. */
23
+ /** Project-root `.hover/` directory the single home for Hover-derived data
24
+ * (sidecars, runs, rules, conventions). */
25
+ export function hoverDir(devRoot) {
26
+ return join(devRoot, '.hover');
27
+ }
28
+ /** Sanitize an id segment for use as a directory name (conversation / run id). */
29
+ export function safeSeg(s) {
30
+ return (s || '').replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80) || 'unknown';
31
+ }
32
+ /** Per-run home: `<devRoot>/.hover/conversations/<conversationId>/<runId>/`.
33
+ * Everything a single agent run produces — meta.json (the ledger record),
34
+ * report.md (QA), screenshots/ — lives here, grouped under its conversation so
35
+ * deleting a conversation is one `rm -rf .hover/conversations/<conversationId>`.
36
+ * (Distinct from `.hover/runs/`, which is the Playwright spec-run-results
37
+ * ledger written by ▶ Run.) */
38
+ export function conversationsDir(devRoot) {
39
+ return join(hoverDir(devRoot), 'conversations');
40
+ }
41
+ export function conversationDir(devRoot, conversationId) {
42
+ return join(conversationsDir(devRoot), safeSeg(conversationId));
43
+ }
44
+ export function runDir(devRoot, conversationId, runId) {
45
+ return join(conversationDir(devRoot, conversationId), safeSeg(runId));
46
+ }
47
+ /** Sidecar directory: `<devRoot>/.hover/sidecars`. Outside `__vibe_tests__/`,
48
+ * so Playwright's default `*.spec.ts` glob trivially never reaches it. */
21
49
  export function sidecarDir(devRoot) {
50
+ return join(hoverDir(devRoot), 'sidecars');
51
+ }
52
+ /** Pre-relocation sidecar home (`__vibe_tests__/.hover/`). Read-only fallback;
53
+ * nothing writes here anymore. */
54
+ export function legacySidecarDir(devRoot) {
22
55
  return join(devRoot, '__vibe_tests__', '.hover');
23
56
  }
24
- /** Write the structured-session sidecar at `.hover/<slug>.json`. Caller passes
25
- * the data minus the stamped fields (`version`, `createdAt`), which this
26
- * function fills. Returns the absolute path written. */
57
+ /** Write the structured-session sidecar at `.hover/sidecars/<slug>.json`.
58
+ * Caller passes the data minus the stamped fields (`version`, `createdAt`),
59
+ * which this function fills. Returns the absolute path written. */
27
60
  export async function writeSidecar(devRoot, data) {
28
61
  const dir = sidecarDir(devRoot);
29
62
  await mkdir(dir, { recursive: true });
@@ -36,3 +69,40 @@ export async function writeSidecar(devRoot, data) {
36
69
  await writeFile(path, JSON.stringify(sidecar, null, 2) + '\n', 'utf-8');
37
70
  return path;
38
71
  }
72
+ /**
73
+ * Read one sidecar by slug, with legacy fallback + lazy copy-forward: when a
74
+ * sidecar only exists at the pre-relocation `__vibe_tests__/.hover/` path it
75
+ * is parsed from there and best-effort re-written into `.hover/sidecars/` so
76
+ * the next read hits the new home. Returns `null` when absent or malformed.
77
+ */
78
+ export async function readSidecar(devRoot, slug) {
79
+ const current = await parseSidecarFile(join(sidecarDir(devRoot), `${slug}.json`));
80
+ if (current)
81
+ return current;
82
+ const legacy = await parseSidecarFile(join(legacySidecarDir(devRoot), `${slug}.json`));
83
+ if (legacy) {
84
+ // Copy-forward, best effort — a read must never fail because the
85
+ // migration write did.
86
+ try {
87
+ const dir = sidecarDir(devRoot);
88
+ await mkdir(dir, { recursive: true });
89
+ await writeFile(join(dir, `${slug}.json`), JSON.stringify(legacy, null, 2) + '\n', 'utf-8');
90
+ }
91
+ catch {
92
+ /* leave it in the legacy home */
93
+ }
94
+ }
95
+ return legacy;
96
+ }
97
+ /** Parse one sidecar file, or `null` when absent / not JSON. Deliberately
98
+ * lenient on shape (an empty `{}` still counts as "a sidecar exists") —
99
+ * consumers that need `steps`/`slug` filter for themselves. */
100
+ export async function parseSidecarFile(path) {
101
+ try {
102
+ const sc = JSON.parse(await readFile(path, 'utf-8'));
103
+ return sc && typeof sc === 'object' ? sc : null;
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The serialized captured-step shape the whole spec pipeline (writeSpec,
3
+ * sidecar, Page-Object extraction, the session record) consumes.
4
+ *
5
+ * One entry per recorded chat message: a user prompt, an agent narration, a
6
+ * `browser_*` / control-MCP tool call (`step`), or the terminal `done` summary.
7
+ * (Formerly `SkillStep` in specs/specStep.ts, back when a run could be saved
8
+ * as a `.claude/skills/<slug>/SKILL.md` — that feature was retired; only the
9
+ * type survived, now relocated here.)
10
+ */
11
+ export interface SkillStep {
12
+ kind: 'user' | 'system' | 'step' | 'ai' | 'done';
13
+ text?: string;
14
+ tool?: string;
15
+ input?: unknown;
16
+ isError?: boolean;
17
+ turns?: number;
18
+ costUsd?: number;
19
+ summary?: string;
20
+ }
21
+ //# sourceMappingURL=specStep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specStep.d.ts","sourceRoot":"","sources":["../../src/specs/specStep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,17 +1,19 @@
1
1
  /**
2
- * Small text helpers shared across the spec/CSV emitters.
2
+ * Small text helpers for the spec emitter.
3
3
  *
4
- * Hoisted here so the two crystallization outputs (writeSpec's JSDoc header and
5
- * writeCaseCsv's Xray rows) derive a slug and a one-sentence "Expected" line the
6
- * same way — they used to carry byte-identical copies of this logic.
4
+ * Hoisted here so writeSpec's JSDoc header derives a slug and a one-sentence
5
+ * "Expected" line through one shared implementation.
7
6
  */
8
7
  /** Lowercase, hyphenate, and trim a display name into a filesystem-safe slug. */
9
8
  export declare function slugify(name: string): string;
10
9
  /**
11
10
  * The first sentence of a done-summary, trimmed. Agents sometimes ramble; the
12
11
  * Expected blocks only want the leading sentence. Splits on the gap that
13
- * follows sentence-ending punctuation (`.`, `!`, `?`); a summary with no such
14
- * punctuation comes back trimmed in full.
12
+ * follows sentence-ending punctuation — Latin (`.`, `!`, `?`) AND CJK
13
+ * (`。`, `!`, `?`) so a Chinese summary doesn't dump its whole multi-line body
14
+ * (which then broke the JSDoc block). Also cuts at the first hard line break, so
15
+ * a summary that runs straight into a `\n\n- bullet` list keeps only the lead
16
+ * sentence. A summary with no such break comes back trimmed in full.
15
17
  */
16
18
  export declare function firstSentence(summary: string): string;
17
19
  //# sourceMappingURL=text.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/specs/text.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,iFAAiF;AACjF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD"}
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/specs/text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,iFAAiF;AACjF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrD"}
@@ -1,9 +1,8 @@
1
1
  /**
2
- * Small text helpers shared across the spec/CSV emitters.
2
+ * Small text helpers for the spec emitter.
3
3
  *
4
- * Hoisted here so the two crystallization outputs (writeSpec's JSDoc header and
5
- * writeCaseCsv's Xray rows) derive a slug and a one-sentence "Expected" line the
6
- * same way — they used to carry byte-identical copies of this logic.
4
+ * Hoisted here so writeSpec's JSDoc header derives a slug and a one-sentence
5
+ * "Expected" line through one shared implementation.
7
6
  */
8
7
  /** Lowercase, hyphenate, and trim a display name into a filesystem-safe slug. */
9
8
  export function slugify(name) {
@@ -16,9 +15,13 @@ export function slugify(name) {
16
15
  /**
17
16
  * The first sentence of a done-summary, trimmed. Agents sometimes ramble; the
18
17
  * Expected blocks only want the leading sentence. Splits on the gap that
19
- * follows sentence-ending punctuation (`.`, `!`, `?`); a summary with no such
20
- * punctuation comes back trimmed in full.
18
+ * follows sentence-ending punctuation — Latin (`.`, `!`, `?`) AND CJK
19
+ * (`。`, `!`, `?`) so a Chinese summary doesn't dump its whole multi-line body
20
+ * (which then broke the JSDoc block). Also cuts at the first hard line break, so
21
+ * a summary that runs straight into a `\n\n- bullet` list keeps only the lead
22
+ * sentence. A summary with no such break comes back trimmed in full.
21
23
  */
22
24
  export function firstSentence(summary) {
23
- return summary.split(/(?<=[.!?])\s+/)[0]?.trim() ?? summary.trim();
25
+ const bySentence = summary.split(/(?<=[.!?。!?])\s+/)[0] ?? summary;
26
+ return bySentence.split(/\n/)[0]?.trim() ?? summary.trim();
24
27
  }
@@ -1,4 +1,4 @@
1
- import type { SkillStep } from '../skills/writeSkill.js';
1
+ import type { SkillStep } from '../specs/specStep.js';
2
2
  export type SpecStep = SkillStep;
3
3
  /**
4
4
  * Marker the deterministic translator leaves where a captured action is a real
@@ -24,6 +24,18 @@ export declare class SpecExistsError extends Error {
24
24
  readonly path: string;
25
25
  constructor(slug: string, path: string);
26
26
  }
27
+ /**
28
+ * A credential to keep out of the generated spec. The deterministic translator
29
+ * replaces any fill value that exactly equals `value` with a
30
+ * `process.env.<envVar>` reference — so the literal password/username never
31
+ * lands in the spec source, the JSDoc header, OR the `.hover/` sidecar. The
32
+ * value comes from the caller (the editor resolves an `@account` mention from
33
+ * its vault); core only uses it to match-and-replace, never to write.
34
+ */
35
+ export interface Redaction {
36
+ value: string;
37
+ envVar: string;
38
+ }
27
39
  export interface WriteSpecOptions {
28
40
  devRoot: string;
29
41
  name: string;
@@ -31,10 +43,51 @@ export interface WriteSpecOptions {
31
43
  steps: SpecStep[];
32
44
  assertions?: SpecAssertion[];
33
45
  overwrite?: boolean;
46
+ /** Credentials to parameterize into `process.env.<envVar>` references. */
47
+ redactions?: Redaction[];
48
+ /** The run's target URL (the active environment / dev origin). Used to
49
+ * guarantee the spec opens the app: if the captured session has NO
50
+ * navigation (the agent connected to an already-open tab and never called
51
+ * browser_navigate), a leading `page.goto()` is synthesized from this, and
52
+ * it's the fallback origin for the scaffolded playwright config. */
53
+ startUrl?: string;
54
+ /** Recon-discovered reset recipe for the run's environment (debt-2 reproducible
55
+ * state isolation). When tier 1, a shared `support/resetState.ts` helper is
56
+ * generated and called in a `beforeEach` so the spec re-enters from a clean
57
+ * client state every run. Tier 2/3 (backend-state) emit no reset here. (Engine
58
+ * shape, decoupled from the extension's ResetRecipe — only tier/keys matter.) */
59
+ resetRecipe?: {
60
+ tier: number;
61
+ storageKeys?: string[];
62
+ hook?: string;
63
+ };
64
+ /** Auth-as-fixture (debt 3): engage the fixture EVEN WHEN a user playwright.config
65
+ * already exists — i.e. the user approved Hover editing their config (Stage 4).
66
+ * Without it, an existing config keeps login inline (Hover never edits a user's
67
+ * config unprompted). When true, writeSpec also applies the setup-project edit
68
+ * to the config. No effect when no login prefix is detected. */
69
+ authFixture?: boolean;
34
70
  }
35
71
  export interface WriteSpecResult {
72
+ /** Primary written file (the first flow when split, else the single spec). */
36
73
  path: string;
37
74
  slug: string;
75
+ /** Every file written — one per `mark_flow` feature when the run was split. */
76
+ files: {
77
+ path: string;
78
+ slug: string;
79
+ flow: string;
80
+ }[];
81
+ /** Auth-as-fixture (debt 3, Stage 4): a login was detected but a USER
82
+ * playwright.config already exists, so Hover left login inline rather than
83
+ * edit their config unprompted. This is the proposed edit to offer for
84
+ * approval — on approval the caller re-saves with `authFixture: true`, which
85
+ * applies it. Absent when there's no login, no user config, or the config
86
+ * can't be safely edited (already has `projects`). */
87
+ authFixtureOffer?: {
88
+ configPath: string;
89
+ proposedConfig: string;
90
+ };
38
91
  }
39
92
  export declare function writeSpec(opts: WriteSpecOptions): Promise<WriteSpecResult>;
40
93
  /**
@@ -68,6 +121,14 @@ export declare function blockScope(lines: string[]): string[];
68
121
  * trailing role keyword is the convention Playwright MCP uses.
69
122
  */
70
123
  export declare function selectorFromDescription(desc: string, pageVar?: string): string;
124
+ /**
125
+ * browser_select_option always targets a native `<select>` — whose ARIA role
126
+ * is `combobox`. The agent's description is usually the label ("marital
127
+ * status"), with no role keyword, so selectorFromDescription would fall back to
128
+ * getByText and match the *label text*, not the control — and `.selectOption()`
129
+ * on a text node throws. Force the combobox role by accessible name instead.
130
+ */
131
+ export declare function selectorForSelect(desc: string, pageVar?: string): string;
71
132
  /**
72
133
  * Form fields from browser_fill_form have a `name` that's typically the
73
134
  * accessible name / label / aria-label. getByLabel is the right primitive.
@@ -1 +1 @@
1
- {"version":3,"file":"writeSpec.d.ts","sourceRoot":"","sources":["../../src/specs/writeSpec.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAWzD,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC;AAEjC;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,yBAAyB,CAAC;AAEzD;;0DAE0D;AAC1D,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,eAAgB,SAAQ,KAAK;aACZ,IAAI,EAAE,MAAM;aAAkB,IAAI,EAAE,MAAM;gBAA1C,IAAI,EAAE,MAAM,EAAkB,IAAI,EAAE,MAAM;CAIvE;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;CAAE;AAEhE,wBAAsB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiChF;AAuUD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAM9E;AAED;;oCAEoC;AACpC,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CAqB9E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CAQ1F"}
1
+ {"version":3,"file":"writeSpec.d.ts","sourceRoot":"","sources":["../../src/specs/writeSpec.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAatD,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC;AAEjC;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,yBAAyB,CAAC;AAEzD;;0DAE0D;AAC1D,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE9D;AA2CD,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,eAAgB,SAAQ,KAAK;aACZ,IAAI,EAAE,MAAM;aAAkB,IAAI,EAAE,MAAM;gBAA1C,IAAI,EAAE,MAAM,EAAkB,IAAI,EAAE,MAAM;CAIvE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB;;;;yEAIqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;sFAIkF;IAClF,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;qEAIiE;IACjE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAiDD,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD;;;;;2DAKuD;IACvD,gBAAgB,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AAQD,wBAAsB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAchF;AA+mBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAM9E;AAED;;oCAEoC;AACpC,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CAqB9E;AA0DD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CAMxE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CAQ1F"}