@qulib/core 0.4.1 → 0.4.3

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 (135) hide show
  1. package/README.md +56 -8
  2. package/dist/analyze.d.ts.map +1 -1
  3. package/dist/analyze.js +86 -7
  4. package/dist/cli/auth-login-resolve.d.ts +14 -0
  5. package/dist/cli/auth-login-resolve.d.ts.map +1 -0
  6. package/dist/cli/auth-login-resolve.js +68 -0
  7. package/dist/cli/auth-login-run.d.ts +13 -0
  8. package/dist/cli/auth-login-run.d.ts.map +1 -0
  9. package/dist/cli/auth-login-run.js +152 -0
  10. package/dist/cli/index.js +60 -7
  11. package/dist/harness/state-manager.d.ts +10 -0
  12. package/dist/harness/state-manager.d.ts.map +1 -1
  13. package/dist/harness/state-manager.js +15 -0
  14. package/dist/index.d.ts +8 -6
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +7 -6
  17. package/dist/phases/act.js +3 -3
  18. package/dist/phases/observe.js +5 -5
  19. package/dist/phases/think.js +1 -1
  20. package/dist/schemas/automation-maturity.schema.d.ts +40 -0
  21. package/dist/schemas/automation-maturity.schema.d.ts.map +1 -1
  22. package/dist/schemas/automation-maturity.schema.js +27 -0
  23. package/dist/schemas/index.d.ts +1 -1
  24. package/dist/schemas/index.d.ts.map +1 -1
  25. package/dist/schemas/index.js +1 -1
  26. package/dist/schemas/repo-analysis.schema.d.ts +22 -0
  27. package/dist/schemas/repo-analysis.schema.d.ts.map +1 -1
  28. package/dist/schemas/repo-analysis.schema.js +1 -0
  29. package/dist/telemetry/emit.d.ts +22 -0
  30. package/dist/telemetry/emit.d.ts.map +1 -1
  31. package/dist/telemetry/emit.js +37 -0
  32. package/dist/telemetry/telemetry.interface.d.ts +1 -1
  33. package/dist/telemetry/telemetry.interface.d.ts.map +1 -1
  34. package/dist/tools/apply-auth.d.ts +4 -0
  35. package/dist/tools/apply-auth.d.ts.map +1 -0
  36. package/dist/tools/apply-auth.js +35 -0
  37. package/dist/tools/auth/apply.d.ts +4 -0
  38. package/dist/tools/auth/apply.d.ts.map +1 -0
  39. package/dist/tools/auth/apply.js +35 -0
  40. package/dist/tools/auth/block-gap.d.ts +9 -0
  41. package/dist/tools/auth/block-gap.d.ts.map +1 -0
  42. package/dist/tools/auth/block-gap.js +52 -0
  43. package/dist/tools/auth/custom-providers.d.ts +15 -0
  44. package/dist/tools/auth/custom-providers.d.ts.map +1 -0
  45. package/dist/tools/auth/custom-providers.js +62 -0
  46. package/dist/tools/auth/detect.d.ts +23 -0
  47. package/dist/tools/auth/detect.d.ts.map +1 -0
  48. package/dist/tools/auth/detect.js +526 -0
  49. package/dist/tools/auth/detector.d.ts +23 -0
  50. package/dist/tools/auth/detector.d.ts.map +1 -0
  51. package/dist/tools/auth/detector.js +526 -0
  52. package/dist/tools/auth/explore.d.ts +4 -0
  53. package/dist/tools/auth/explore.d.ts.map +1 -0
  54. package/dist/tools/auth/explore.js +346 -0
  55. package/dist/tools/auth/explorer.d.ts +4 -0
  56. package/dist/tools/auth/explorer.d.ts.map +1 -0
  57. package/dist/tools/auth/explorer.js +346 -0
  58. package/dist/tools/auth/gaps.d.ts +9 -0
  59. package/dist/tools/auth/gaps.d.ts.map +1 -0
  60. package/dist/tools/auth/gaps.js +52 -0
  61. package/dist/tools/auth/oauth-providers.d.ts +7 -0
  62. package/dist/tools/auth/oauth-providers.d.ts.map +1 -0
  63. package/dist/tools/auth/oauth-providers.js +21 -0
  64. package/dist/tools/auth/providers.d.ts +7 -0
  65. package/dist/tools/auth/providers.d.ts.map +1 -0
  66. package/dist/tools/auth/providers.js +21 -0
  67. package/dist/tools/auth/surface-analyzer.d.ts +4 -0
  68. package/dist/tools/auth/surface-analyzer.d.ts.map +1 -0
  69. package/dist/tools/auth/surface-analyzer.js +170 -0
  70. package/dist/tools/auth/surface.d.ts +4 -0
  71. package/dist/tools/auth/surface.d.ts.map +1 -0
  72. package/dist/tools/auth/surface.js +170 -0
  73. package/dist/tools/auth/user-providers.d.ts +15 -0
  74. package/dist/tools/auth/user-providers.d.ts.map +1 -0
  75. package/dist/tools/auth/user-providers.js +62 -0
  76. package/dist/tools/auth-block-gap.d.ts +6 -0
  77. package/dist/tools/auth-block-gap.d.ts.map +1 -1
  78. package/dist/tools/auth-block-gap.js +42 -9
  79. package/dist/tools/auth-detector.d.ts +19 -0
  80. package/dist/tools/auth-detector.d.ts.map +1 -1
  81. package/dist/tools/auth-detector.js +186 -8
  82. package/dist/tools/automation-maturity.d.ts.map +1 -1
  83. package/dist/tools/automation-maturity.js +76 -20
  84. package/dist/tools/explorers/browser.d.ts +3 -0
  85. package/dist/tools/explorers/browser.d.ts.map +1 -0
  86. package/dist/tools/explorers/browser.js +13 -0
  87. package/dist/tools/explorers/cypress-explorer.d.ts +8 -0
  88. package/dist/tools/explorers/cypress-explorer.d.ts.map +1 -0
  89. package/dist/tools/explorers/cypress-explorer.js +5 -0
  90. package/dist/tools/explorers/cypress.d.ts +8 -0
  91. package/dist/tools/explorers/cypress.d.ts.map +1 -0
  92. package/dist/tools/explorers/cypress.js +5 -0
  93. package/dist/tools/explorers/explorer.interface.d.ts +7 -0
  94. package/dist/tools/explorers/explorer.interface.d.ts.map +1 -0
  95. package/dist/tools/explorers/explorer.interface.js +1 -0
  96. package/dist/tools/explorers/factory.d.ts +4 -0
  97. package/dist/tools/explorers/factory.d.ts.map +1 -0
  98. package/dist/tools/explorers/factory.js +12 -0
  99. package/dist/tools/explorers/playwright-explorer.d.ts +8 -0
  100. package/dist/tools/explorers/playwright-explorer.d.ts.map +1 -0
  101. package/dist/tools/explorers/playwright-explorer.js +172 -0
  102. package/dist/tools/explorers/playwright.d.ts +8 -0
  103. package/dist/tools/explorers/playwright.d.ts.map +1 -0
  104. package/dist/tools/explorers/playwright.js +172 -0
  105. package/dist/tools/explorers/types.d.ts +7 -0
  106. package/dist/tools/explorers/types.d.ts.map +1 -0
  107. package/dist/tools/explorers/types.js +1 -0
  108. package/dist/tools/playwright-explorer.js +1 -1
  109. package/dist/tools/repo/detect-framework.d.ts +15 -0
  110. package/dist/tools/repo/detect-framework.d.ts.map +1 -0
  111. package/dist/tools/repo/detect-framework.js +153 -0
  112. package/dist/tools/repo/framework-detector.d.ts +15 -0
  113. package/dist/tools/repo/framework-detector.d.ts.map +1 -0
  114. package/dist/tools/repo/framework-detector.js +153 -0
  115. package/dist/tools/repo/scan.d.ts +19 -0
  116. package/dist/tools/repo/scan.d.ts.map +1 -0
  117. package/dist/tools/repo/scan.js +181 -0
  118. package/dist/tools/repo/scanner.d.ts +19 -0
  119. package/dist/tools/repo/scanner.d.ts.map +1 -0
  120. package/dist/tools/repo/scanner.js +181 -0
  121. package/dist/tools/repo-scanner.d.ts.map +1 -1
  122. package/dist/tools/repo-scanner.js +7 -2
  123. package/dist/tools/scoring/automation-maturity.d.ts +4 -0
  124. package/dist/tools/scoring/automation-maturity.d.ts.map +1 -0
  125. package/dist/tools/scoring/automation-maturity.js +219 -0
  126. package/dist/tools/scoring/gap-engine.d.ts +8 -0
  127. package/dist/tools/scoring/gap-engine.d.ts.map +1 -0
  128. package/dist/tools/scoring/gap-engine.js +138 -0
  129. package/dist/tools/scoring/gaps.d.ts +8 -0
  130. package/dist/tools/scoring/gaps.d.ts.map +1 -0
  131. package/dist/tools/scoring/gaps.js +138 -0
  132. package/dist/tools/scoring/public-surface.d.ts +5 -0
  133. package/dist/tools/scoring/public-surface.d.ts.map +1 -0
  134. package/dist/tools/scoring/public-surface.js +13 -0
  135. package/package.json +3 -3
package/dist/index.d.ts CHANGED
@@ -1,16 +1,18 @@
1
1
  export { analyzeApp } from './analyze.js';
2
- export { detectAuth } from './tools/auth-detector.js';
3
- export { exploreAuth } from './tools/auth-explorer.js';
4
- export { addUserProvider, removeUserProvider, listUserProviders } from './tools/user-providers.js';
5
- export { scanRepo } from './tools/repo-scanner.js';
6
- export { computeAutomationMaturity } from './tools/automation-maturity.js';
2
+ export { detectAuth, validateStorageState, evaluateStorageStateValidity, preflightStorageStateFile, waitForReturnToOrigin, } from './tools/auth/detect.js';
3
+ export type { StorageStateInvalidReason, StorageStateValidationResult, } from './tools/auth/detect.js';
4
+ export { exploreAuth } from './tools/auth/explore.js';
5
+ export { addUserProvider, removeUserProvider, listUserProviders } from './tools/auth/custom-providers.js';
6
+ export { scanRepo } from './tools/repo/scan.js';
7
+ export { computeAutomationMaturity } from './tools/scoring/automation-maturity.js';
7
8
  export { createProvider } from './llm/provider-registry.js';
8
9
  export { resolveMaxOutputTokensPerLlmCall } from './schemas/config.schema.js';
9
- export { resolveScanStateBaseDir } from './harness/state-manager.js';
10
+ export { resolveScanStateBaseDir, resolveReportDir } from './harness/state-manager.js';
10
11
  export type { AnalyzeOptions, AnalyzeResult, AnalyzeStatus } from './analyze.js';
11
12
  export type { AnalyzeProgressSink } from './harness/progress-log.js';
12
13
  export type { TelemetrySink, TelemetryEvent, TelemetryEventKind, } from './telemetry/telemetry.interface.js';
13
14
  export { NoopTelemetrySink } from './telemetry/telemetry.interface.js';
15
+ export { redactUrlForTelemetry } from './telemetry/emit.js';
14
16
  export type { LlmCallResult, LlmProvider } from './llm/provider.interface.js';
15
17
  export type { CallLlmConfigSlice } from './llm/provider.js';
16
18
  export type { HarnessConfig, AuthConfig, RouteInventory, GapAnalysis, RepoAnalysis, DetectedAuth, AuthExploration, AuthPath, AuthPathRequirements, CostIntelligence, LlmUsageRecord, RepeatedAiPattern, DeterministicMaturity, PublicSurface, AutomationMaturity, AutomationMaturityDimension, FrameworkDetectionResult, DetectedFrameworkPrimary, } from './schemas/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnG,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjF,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,YAAY,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,GACnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC9E,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,YAAY,EACV,aAAa,EACb,UAAU,EACV,cAAc,EACd,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,QAAQ,EACR,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,2BAA2B,EAC3B,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,4BAA4B,EAC5B,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1G,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACvF,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjF,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,YAAY,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,GACnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC9E,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,YAAY,EACV,aAAa,EACb,UAAU,EACV,cAAc,EACd,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,QAAQ,EACR,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,2BAA2B,EAC3B,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  export { analyzeApp } from './analyze.js';
2
- export { detectAuth } from './tools/auth-detector.js';
3
- export { exploreAuth } from './tools/auth-explorer.js';
4
- export { addUserProvider, removeUserProvider, listUserProviders } from './tools/user-providers.js';
5
- export { scanRepo } from './tools/repo-scanner.js';
6
- export { computeAutomationMaturity } from './tools/automation-maturity.js';
2
+ export { detectAuth, validateStorageState, evaluateStorageStateValidity, preflightStorageStateFile, waitForReturnToOrigin, } from './tools/auth/detect.js';
3
+ export { exploreAuth } from './tools/auth/explore.js';
4
+ export { addUserProvider, removeUserProvider, listUserProviders } from './tools/auth/custom-providers.js';
5
+ export { scanRepo } from './tools/repo/scan.js';
6
+ export { computeAutomationMaturity } from './tools/scoring/automation-maturity.js';
7
7
  export { createProvider } from './llm/provider-registry.js';
8
8
  export { resolveMaxOutputTokensPerLlmCall } from './schemas/config.schema.js';
9
- export { resolveScanStateBaseDir } from './harness/state-manager.js';
9
+ export { resolveScanStateBaseDir, resolveReportDir } from './harness/state-manager.js';
10
10
  export { NoopTelemetrySink } from './telemetry/telemetry.interface.js';
11
+ export { redactUrlForTelemetry } from './telemetry/emit.js';
@@ -3,10 +3,10 @@ import { writeJsonReport } from '../reporters/json-reporter.js';
3
3
  import { writeMarkdownReport } from '../reporters/markdown-reporter.js';
4
4
  import { logDecision } from '../harness/decision-logger.js';
5
5
  import { emitTelemetry } from '../telemetry/emit.js';
6
- import { resolveScanStateBaseDir } from '../harness/state-manager.js';
6
+ import { resolveReportDir, resolveScanStateBaseDir } from '../harness/state-manager.js';
7
7
  export async function act(analysis, config, artifacts = { writeArtifacts: true }) {
8
8
  const sessionId = artifacts.telemetrySessionId ?? 'none';
9
- const reportDir = join(process.cwd(), 'output');
9
+ const reportDir = resolveReportDir(config.outputDir);
10
10
  const logOpts = {
11
11
  persist: artifacts.writeArtifacts,
12
12
  memory: artifacts.decisionMemory,
@@ -48,7 +48,7 @@ export async function act(analysis, config, artifacts = { writeArtifacts: true }
48
48
  if (config.requireHumanReview) {
49
49
  log('\n[qulib] Human review required before applying any generated output.');
50
50
  if (artifacts.writeArtifacts) {
51
- log(' Reports: output/report.json and output/report.md');
51
+ log(` Reports: ${join(reportDir, 'report.json')} and ${join(reportDir, 'report.md')}`);
52
52
  log(` Decisions: ${join(resolveScanStateBaseDir(config.outputDir), 'decision-log.json')}`);
53
53
  }
54
54
  else {
@@ -1,10 +1,10 @@
1
1
  import { RouteInventorySchema } from '../schemas/route-inventory.schema.js';
2
2
  import { RepoAnalysisSchema } from '../schemas/repo-analysis.schema.js';
3
- import { createExplorer } from '../tools/explorer-factory.js';
4
- import { scanRepo } from '../tools/repo-scanner.js';
3
+ import { createExplorer } from '../tools/explorers/factory.js';
4
+ import { scanRepo } from '../tools/repo/scan.js';
5
5
  import { StateManager } from '../harness/state-manager.js';
6
6
  import { logDecision } from '../harness/decision-logger.js';
7
- import { emitTelemetry } from '../telemetry/emit.js';
7
+ import { emitTelemetry, redactUrlForTelemetry } from '../telemetry/emit.js';
8
8
  export async function observe(baseUrl, repoPath, config, artifacts = { writeArtifacts: true }) {
9
9
  const sessionId = artifacts.telemetrySessionId ?? 'none';
10
10
  const explorer = createExplorer(config.explorer);
@@ -15,7 +15,7 @@ export async function observe(baseUrl, repoPath, config, artifacts = { writeArti
15
15
  outputDir: config.outputDir,
16
16
  };
17
17
  emitTelemetry(artifacts.telemetry, 'phase.observe.started', sessionId, {
18
- baseUrl,
18
+ baseUrl: redactUrlForTelemetry(baseUrl),
19
19
  hasRepoPath: Boolean(repoPath),
20
20
  });
21
21
  const rawRoutes = await explorer.explore(baseUrl, config, artifacts);
@@ -29,7 +29,7 @@ export async function observe(baseUrl, repoPath, config, artifacts = { writeArti
29
29
  decision: 'exploration-complete',
30
30
  reason: `Discovered ${routes.routes.length} routes; budgetExceeded=${routes.budgetExceeded}`,
31
31
  metadata: {
32
- baseUrl,
32
+ baseUrl: redactUrlForTelemetry(baseUrl),
33
33
  scannedRoutes: routes.routes.length,
34
34
  budgetExceeded: routes.budgetExceeded,
35
35
  pagesSkipped: routes.pagesSkipped,
@@ -1,5 +1,5 @@
1
1
  import { GapAnalysisSchema } from '../schemas/gap-analysis.schema.js';
2
- import { analyzeGaps } from '../tools/gap-engine.js';
2
+ import { analyzeGaps } from '../tools/scoring/gaps.js';
3
3
  import { logDecision } from '../harness/decision-logger.js';
4
4
  import { finalizeGapAnalysisFromDraft } from './think-finalize.js';
5
5
  import { emitTelemetry } from '../telemetry/emit.js';
@@ -1,22 +1,48 @@
1
1
  import { z } from 'zod';
2
+ export declare const AutomationMaturityApplicabilitySchema: z.ZodEnum<["applicable", "not_applicable", "unknown"]>;
3
+ /**
4
+ * Maturity dimension with explicit applicability so absent capabilities are not silently
5
+ * awarded partial credit.
6
+ *
7
+ * - `applicable` — Qulib has enough signal to compute a real `score`.
8
+ * - `not_applicable` — The capability does not apply to this repo (e.g. component-test-ratio
9
+ * with no Cypress detected, auth-test-coverage when no auth signal exists).
10
+ * `score` is reported but excluded from the overall calculation.
11
+ * - `unknown` — Qulib could not collect enough signal to score honestly (e.g. zero
12
+ * interactive elements scanned for test-id hygiene). Excluded from overall.
13
+ *
14
+ * Overall score formula (in `computeAutomationMaturity`):
15
+ * numerator = Σ score_i * weight_i for i ∈ applicable dimensions
16
+ * denominator = Σ weight_i for i ∈ applicable dimensions
17
+ * overallScore = round(numerator / denominator) when denominator > 0, else 0
18
+ *
19
+ * Schema fields stay backward compatible: both `applicability` and `reason` are optional.
20
+ * Existing consumers that don't read them keep working; honest reports populate them.
21
+ */
2
22
  export declare const AutomationMaturityDimensionSchema: z.ZodObject<{
3
23
  dimension: z.ZodEnum<["test-coverage-breadth", "framework-adoption", "test-id-hygiene", "ci-integration", "auth-test-coverage", "component-test-ratio"]>;
4
24
  score: z.ZodNumber;
5
25
  weight: z.ZodNumber;
6
26
  evidence: z.ZodArray<z.ZodString, "many">;
7
27
  recommendations: z.ZodArray<z.ZodString, "many">;
28
+ applicability: z.ZodOptional<z.ZodEnum<["applicable", "not_applicable", "unknown"]>>;
29
+ reason: z.ZodOptional<z.ZodString>;
8
30
  }, "strip", z.ZodTypeAny, {
9
31
  recommendations: string[];
10
32
  dimension: "test-coverage-breadth" | "framework-adoption" | "test-id-hygiene" | "ci-integration" | "auth-test-coverage" | "component-test-ratio";
11
33
  score: number;
12
34
  weight: number;
13
35
  evidence: string[];
36
+ reason?: string | undefined;
37
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
14
38
  }, {
15
39
  recommendations: string[];
16
40
  dimension: "test-coverage-breadth" | "framework-adoption" | "test-id-hygiene" | "ci-integration" | "auth-test-coverage" | "component-test-ratio";
17
41
  score: number;
18
42
  weight: number;
19
43
  evidence: string[];
44
+ reason?: string | undefined;
45
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
20
46
  }>;
21
47
  export declare const AutomationMaturitySchema: z.ZodObject<{
22
48
  computedAt: z.ZodString;
@@ -30,20 +56,27 @@ export declare const AutomationMaturitySchema: z.ZodObject<{
30
56
  weight: z.ZodNumber;
31
57
  evidence: z.ZodArray<z.ZodString, "many">;
32
58
  recommendations: z.ZodArray<z.ZodString, "many">;
59
+ applicability: z.ZodOptional<z.ZodEnum<["applicable", "not_applicable", "unknown"]>>;
60
+ reason: z.ZodOptional<z.ZodString>;
33
61
  }, "strip", z.ZodTypeAny, {
34
62
  recommendations: string[];
35
63
  dimension: "test-coverage-breadth" | "framework-adoption" | "test-id-hygiene" | "ci-integration" | "auth-test-coverage" | "component-test-ratio";
36
64
  score: number;
37
65
  weight: number;
38
66
  evidence: string[];
67
+ reason?: string | undefined;
68
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
39
69
  }, {
40
70
  recommendations: string[];
41
71
  dimension: "test-coverage-breadth" | "framework-adoption" | "test-id-hygiene" | "ci-integration" | "auth-test-coverage" | "component-test-ratio";
42
72
  score: number;
43
73
  weight: number;
44
74
  evidence: string[];
75
+ reason?: string | undefined;
76
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
45
77
  }>, "many">;
46
78
  topRecommendations: z.ZodArray<z.ZodString, "many">;
79
+ scoreFormula: z.ZodOptional<z.ZodString>;
47
80
  }, "strip", z.ZodTypeAny, {
48
81
  label: string;
49
82
  level: number;
@@ -56,8 +89,11 @@ export declare const AutomationMaturitySchema: z.ZodObject<{
56
89
  score: number;
57
90
  weight: number;
58
91
  evidence: string[];
92
+ reason?: string | undefined;
93
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
59
94
  }[];
60
95
  topRecommendations: string[];
96
+ scoreFormula?: string | undefined;
61
97
  }, {
62
98
  label: string;
63
99
  level: number;
@@ -70,9 +106,13 @@ export declare const AutomationMaturitySchema: z.ZodObject<{
70
106
  score: number;
71
107
  weight: number;
72
108
  evidence: string[];
109
+ reason?: string | undefined;
110
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
73
111
  }[];
74
112
  topRecommendations: string[];
113
+ scoreFormula?: string | undefined;
75
114
  }>;
115
+ export type AutomationMaturityApplicability = z.infer<typeof AutomationMaturityApplicabilitySchema>;
76
116
  export type AutomationMaturityDimension = z.infer<typeof AutomationMaturityDimensionSchema>;
77
117
  export type AutomationMaturity = z.infer<typeof AutomationMaturitySchema>;
78
118
  //# sourceMappingURL=automation-maturity.schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"automation-maturity.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/automation-maturity.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;EAa5C,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQnC,CAAC;AAEH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAC5F,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
1
+ {"version":3,"file":"automation-maturity.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/automation-maturity.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,qCAAqC,wDAIhD,CAAC;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;EAe5C,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASnC,CAAC;AAEH,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAC;AACpG,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAC5F,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
@@ -1,4 +1,28 @@
1
1
  import { z } from 'zod';
2
+ export const AutomationMaturityApplicabilitySchema = z.enum([
3
+ 'applicable',
4
+ 'not_applicable',
5
+ 'unknown',
6
+ ]);
7
+ /**
8
+ * Maturity dimension with explicit applicability so absent capabilities are not silently
9
+ * awarded partial credit.
10
+ *
11
+ * - `applicable` — Qulib has enough signal to compute a real `score`.
12
+ * - `not_applicable` — The capability does not apply to this repo (e.g. component-test-ratio
13
+ * with no Cypress detected, auth-test-coverage when no auth signal exists).
14
+ * `score` is reported but excluded from the overall calculation.
15
+ * - `unknown` — Qulib could not collect enough signal to score honestly (e.g. zero
16
+ * interactive elements scanned for test-id hygiene). Excluded from overall.
17
+ *
18
+ * Overall score formula (in `computeAutomationMaturity`):
19
+ * numerator = Σ score_i * weight_i for i ∈ applicable dimensions
20
+ * denominator = Σ weight_i for i ∈ applicable dimensions
21
+ * overallScore = round(numerator / denominator) when denominator > 0, else 0
22
+ *
23
+ * Schema fields stay backward compatible: both `applicability` and `reason` are optional.
24
+ * Existing consumers that don't read them keep working; honest reports populate them.
25
+ */
2
26
  export const AutomationMaturityDimensionSchema = z.object({
3
27
  dimension: z.enum([
4
28
  'test-coverage-breadth',
@@ -12,6 +36,8 @@ export const AutomationMaturityDimensionSchema = z.object({
12
36
  weight: z.number().min(0).max(1),
13
37
  evidence: z.array(z.string()),
14
38
  recommendations: z.array(z.string()),
39
+ applicability: AutomationMaturityApplicabilitySchema.optional(),
40
+ reason: z.string().optional(),
15
41
  });
16
42
  export const AutomationMaturitySchema = z.object({
17
43
  computedAt: z.string().datetime(),
@@ -21,4 +47,5 @@ export const AutomationMaturitySchema = z.object({
21
47
  label: z.string(),
22
48
  dimensions: z.array(AutomationMaturityDimensionSchema),
23
49
  topRecommendations: z.array(z.string()),
50
+ scoreFormula: z.string().optional(),
24
51
  });
@@ -4,6 +4,6 @@ export { RouteInventorySchema, RouteSchema, A11yViolationSchema, BrokenLinkSchem
4
4
  export { GapAnalysisSchema, GapSchema, NeutralScenarioSchema, GeneratedTestSchema, TestStepSchema, FrameworkRecommendationSchema, type GapAnalysis, type Gap, type NeutralScenario, type GeneratedTest, type TestStep, type FrameworkRecommendation, } from './gap-analysis.schema.js';
5
5
  export { CostIntelligenceSchema, LlmUsageRecordSchema, LlmDataQualitySchema, LlmOperationTypeSchema, RepeatedAiPatternSchema, DeterministicMaturitySchema, type CostIntelligence, type LlmUsageRecord, type LlmDataQuality, type LlmOperationType, type RepeatedAiPattern, type DeterministicMaturity, } from './cost-intelligence.schema.js';
6
6
  export { RepoAnalysisSchema, FrameworkDetectionSchema, DetectedFrameworkPrimarySchema, FrameworkDetectionConfidenceSchema, TestFrameworkDetectedSchema, type RepoAnalysis, type FrameworkDetectionResult, type DetectedFrameworkPrimary, } from './repo-analysis.schema.js';
7
- export { AutomationMaturitySchema, AutomationMaturityDimensionSchema, type AutomationMaturity, type AutomationMaturityDimension, } from './automation-maturity.schema.js';
7
+ export { AutomationMaturitySchema, AutomationMaturityDimensionSchema, AutomationMaturityApplicabilitySchema, type AutomationMaturity, type AutomationMaturityDimension, type AutomationMaturityApplicability, } from './automation-maturity.schema.js';
8
8
  export { PublicSurfaceSchema, PublicSurfaceViolationSchema, PublicSurfaceBrokenLinkSchema, type PublicSurface, type PublicSurfaceViolation, type PublicSurfaceBrokenLink, } from './public-surface.schema.js';
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gCAAgC,EAChC,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,EAC1B,cAAc,EACd,qBAAqB,EACrB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EACb,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,KAAK,GACX,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,6BAA6B,EAC7B,KAAK,WAAW,EAChB,KAAK,GAAG,EACR,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,uBAAuB,GAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,8BAA8B,EAC9B,kCAAkC,EAClC,2BAA2B,EAC3B,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,GAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,wBAAwB,EACxB,iCAAiC,EACjC,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,GACjC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,6BAA6B,EAC7B,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gCAAgC,EAChC,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,EAC1B,cAAc,EACd,qBAAqB,EACrB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EACb,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,KAAK,GACX,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,6BAA6B,EAC7B,KAAK,WAAW,EAChB,KAAK,GAAG,EACR,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,uBAAuB,GAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,8BAA8B,EAC9B,kCAAkC,EAClC,2BAA2B,EAC3B,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,GAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,wBAAwB,EACxB,iCAAiC,EACjC,qCAAqC,EACrC,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAChC,KAAK,+BAA+B,GACrC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,6BAA6B,EAC7B,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,4BAA4B,CAAC"}
@@ -4,5 +4,5 @@ export { RouteInventorySchema, RouteSchema, A11yViolationSchema, BrokenLinkSchem
4
4
  export { GapAnalysisSchema, GapSchema, NeutralScenarioSchema, GeneratedTestSchema, TestStepSchema, FrameworkRecommendationSchema, } from './gap-analysis.schema.js';
5
5
  export { CostIntelligenceSchema, LlmUsageRecordSchema, LlmDataQualitySchema, LlmOperationTypeSchema, RepeatedAiPatternSchema, DeterministicMaturitySchema, } from './cost-intelligence.schema.js';
6
6
  export { RepoAnalysisSchema, FrameworkDetectionSchema, DetectedFrameworkPrimarySchema, FrameworkDetectionConfidenceSchema, TestFrameworkDetectedSchema, } from './repo-analysis.schema.js';
7
- export { AutomationMaturitySchema, AutomationMaturityDimensionSchema, } from './automation-maturity.schema.js';
7
+ export { AutomationMaturitySchema, AutomationMaturityDimensionSchema, AutomationMaturityApplicabilitySchema, } from './automation-maturity.schema.js';
8
8
  export { PublicSurfaceSchema, PublicSurfaceViolationSchema, PublicSurfaceBrokenLinkSchema, } from './public-surface.schema.js';
@@ -104,6 +104,7 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
104
104
  coveredPaths: string[];
105
105
  }>, "many">;
106
106
  missingTestIds: z.ZodArray<z.ZodString, "many">;
107
+ interactiveTsxFilesScanned: z.ZodOptional<z.ZodNumber>;
107
108
  cypressStructure: z.ZodObject<{
108
109
  detected: z.ZodBoolean;
109
110
  e2eFolder: z.ZodOptional<z.ZodString>;
@@ -160,20 +161,27 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
160
161
  weight: z.ZodNumber;
161
162
  evidence: z.ZodArray<z.ZodString, "many">;
162
163
  recommendations: z.ZodArray<z.ZodString, "many">;
164
+ applicability: z.ZodOptional<z.ZodEnum<["applicable", "not_applicable", "unknown"]>>;
165
+ reason: z.ZodOptional<z.ZodString>;
163
166
  }, "strip", z.ZodTypeAny, {
164
167
  recommendations: string[];
165
168
  dimension: "test-coverage-breadth" | "framework-adoption" | "test-id-hygiene" | "ci-integration" | "auth-test-coverage" | "component-test-ratio";
166
169
  score: number;
167
170
  weight: number;
168
171
  evidence: string[];
172
+ reason?: string | undefined;
173
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
169
174
  }, {
170
175
  recommendations: string[];
171
176
  dimension: "test-coverage-breadth" | "framework-adoption" | "test-id-hygiene" | "ci-integration" | "auth-test-coverage" | "component-test-ratio";
172
177
  score: number;
173
178
  weight: number;
174
179
  evidence: string[];
180
+ reason?: string | undefined;
181
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
175
182
  }>, "many">;
176
183
  topRecommendations: z.ZodArray<z.ZodString, "many">;
184
+ scoreFormula: z.ZodOptional<z.ZodString>;
177
185
  }, "strip", z.ZodTypeAny, {
178
186
  label: string;
179
187
  level: number;
@@ -186,8 +194,11 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
186
194
  score: number;
187
195
  weight: number;
188
196
  evidence: string[];
197
+ reason?: string | undefined;
198
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
189
199
  }[];
190
200
  topRecommendations: string[];
201
+ scoreFormula?: string | undefined;
191
202
  }, {
192
203
  label: string;
193
204
  level: number;
@@ -200,8 +211,11 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
200
211
  score: number;
201
212
  weight: number;
202
213
  evidence: string[];
214
+ reason?: string | undefined;
215
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
203
216
  }[];
204
217
  topRecommendations: string[];
218
+ scoreFormula?: string | undefined;
205
219
  }>>;
206
220
  }, "strip", z.ZodTypeAny, {
207
221
  scannedAt: string;
@@ -227,6 +241,7 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
227
241
  fixturesFolder?: string | undefined;
228
242
  supportFolder?: string | undefined;
229
243
  };
244
+ interactiveTsxFilesScanned?: number | undefined;
230
245
  framework?: {
231
246
  confidence: "high" | "medium" | "low";
232
247
  evidence: string[];
@@ -245,8 +260,11 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
245
260
  score: number;
246
261
  weight: number;
247
262
  evidence: string[];
263
+ reason?: string | undefined;
264
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
248
265
  }[];
249
266
  topRecommendations: string[];
267
+ scoreFormula?: string | undefined;
250
268
  } | undefined;
251
269
  }, {
252
270
  scannedAt: string;
@@ -272,6 +290,7 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
272
290
  fixturesFolder?: string | undefined;
273
291
  supportFolder?: string | undefined;
274
292
  };
293
+ interactiveTsxFilesScanned?: number | undefined;
275
294
  framework?: {
276
295
  confidence: "high" | "medium" | "low";
277
296
  evidence: string[];
@@ -290,8 +309,11 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
290
309
  score: number;
291
310
  weight: number;
292
311
  evidence: string[];
312
+ reason?: string | undefined;
313
+ applicability?: "unknown" | "applicable" | "not_applicable" | undefined;
293
314
  }[];
294
315
  topRecommendations: string[];
316
+ scoreFormula?: string | undefined;
295
317
  } | undefined;
296
318
  }>;
297
319
  export type RepoAnalysis = z.infer<typeof RepoAnalysisSchema>;
@@ -1 +1 @@
1
- {"version":3,"file":"repo-analysis.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/repo-analysis.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,8BAA8B,8HAUzC,CAAC;AAEH,eAAO,MAAM,kCAAkC,sCAAoC,CAAC;AAEpF,eAAO,MAAM,2BAA2B,0FAOtC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;EAKnC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AACtF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEhF,eAAO,MAAM,eAAe;;;;;;;;;;;;EAI1B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;EAIzB,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;EASjC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
1
+ {"version":3,"file":"repo-analysis.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/repo-analysis.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,8BAA8B,8HAUzC,CAAC;AAEH,eAAO,MAAM,kCAAkC,sCAAoC,CAAC;AAEpF,eAAO,MAAM,2BAA2B,0FAOtC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;EAKnC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AACtF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEhF,eAAO,MAAM,eAAe;;;;;;;;;;;;EAI1B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;EAIzB,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;EASjC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -52,6 +52,7 @@ export const RepoAnalysisSchema = z.object({
52
52
  routes: z.array(RepoRouteSchema),
53
53
  testFiles: z.array(TestFileSchema),
54
54
  missingTestIds: z.array(z.string()),
55
+ interactiveTsxFilesScanned: z.number().int().min(0).optional(),
55
56
  cypressStructure: CypressStructureSchema,
56
57
  framework: FrameworkDetectionSchema.optional(),
57
58
  automationMaturity: AutomationMaturitySchema.optional(),
@@ -1,3 +1,25 @@
1
1
  import type { TelemetryEvent, TelemetryEventKind, TelemetrySink } from './telemetry.interface.js';
2
2
  export declare function emitTelemetry(sink: TelemetrySink | undefined, kind: TelemetryEventKind, sessionId: string, metadata: TelemetryEvent['metadata'], durationMs?: number): void;
3
+ /**
4
+ * Strip the query string and fragment from a URL before emitting it in telemetry.
5
+ *
6
+ * Telemetry must not carry credentials, share tokens, or any other secret-shaped
7
+ * material that callers may embed in query strings (e.g. `?token=...`, `?key=...`).
8
+ * Returns `origin + pathname` only for valid `http:` / `https:` URLs, and additionally
9
+ * strips any `user:pass@` userinfo from the origin.
10
+ *
11
+ * If the input is not a valid `http(s)` URL, this helper returns the literal string
12
+ * `'[redacted-non-url]'` rather than echoing the original input. Two reasons:
13
+ *
14
+ * 1. `new URL(...)` parses many `scheme:rest` shapes that are not real URLs
15
+ * (e.g. `mailto:`, custom `user:pass@host`, `data:`). Those still produce a
16
+ * non-empty `origin + pathname` and would echo the right-hand side back.
17
+ * 2. The exported helper makes no assumption about caller provenance: a non-URL
18
+ * string passed in may itself be secret-shaped (a raw token, a path with
19
+ * embedded credentials, etc.), so the only safe fallback is to discard the
20
+ * value entirely.
21
+ *
22
+ * Telemetry never throws on malformed input.
23
+ */
24
+ export declare function redactUrlForTelemetry(url: string): string;
3
25
  //# sourceMappingURL=emit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/telemetry/emit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAElG,wBAAgB,aAAa,CAC3B,IAAI,EAAE,aAAa,GAAG,SAAS,EAC/B,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,EACpC,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI,CASN"}
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/telemetry/emit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAElG,wBAAgB,aAAa,CAC3B,IAAI,EAAE,aAAa,GAAG,SAAS,EAC/B,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,EACpC,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI,CASN;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAczD"}
@@ -9,3 +9,40 @@ export function emitTelemetry(sink, kind, sessionId, metadata, durationMs) {
9
9
  ...(durationMs !== undefined && { durationMs }),
10
10
  });
11
11
  }
12
+ /**
13
+ * Strip the query string and fragment from a URL before emitting it in telemetry.
14
+ *
15
+ * Telemetry must not carry credentials, share tokens, or any other secret-shaped
16
+ * material that callers may embed in query strings (e.g. `?token=...`, `?key=...`).
17
+ * Returns `origin + pathname` only for valid `http:` / `https:` URLs, and additionally
18
+ * strips any `user:pass@` userinfo from the origin.
19
+ *
20
+ * If the input is not a valid `http(s)` URL, this helper returns the literal string
21
+ * `'[redacted-non-url]'` rather than echoing the original input. Two reasons:
22
+ *
23
+ * 1. `new URL(...)` parses many `scheme:rest` shapes that are not real URLs
24
+ * (e.g. `mailto:`, custom `user:pass@host`, `data:`). Those still produce a
25
+ * non-empty `origin + pathname` and would echo the right-hand side back.
26
+ * 2. The exported helper makes no assumption about caller provenance: a non-URL
27
+ * string passed in may itself be secret-shaped (a raw token, a path with
28
+ * embedded credentials, etc.), so the only safe fallback is to discard the
29
+ * value entirely.
30
+ *
31
+ * Telemetry never throws on malformed input.
32
+ */
33
+ export function redactUrlForTelemetry(url) {
34
+ let parsed;
35
+ try {
36
+ parsed = new URL(url);
37
+ }
38
+ catch {
39
+ return '[redacted-non-url]';
40
+ }
41
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
42
+ return '[redacted-non-url]';
43
+ }
44
+ // Strip any user:pass@ from the origin. `URL.origin` already omits userinfo,
45
+ // but rebuilding from `protocol + host` makes the intent explicit and removes
46
+ // any chance of credentials leaking through future Node URL changes.
47
+ return `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
48
+ }
@@ -1,4 +1,4 @@
1
- export type TelemetryEventKind = 'scan.started' | 'scan.completed' | 'scan.blocked' | 'phase.observe.started' | 'phase.observe.completed' | 'phase.think.started' | 'phase.think.completed' | 'phase.act.started' | 'phase.act.completed' | 'llm.call.started' | 'llm.call.completed' | 'llm.call.failed' | 'gap.detected' | 'auth.detected' | 'repo.scanned';
1
+ export type TelemetryEventKind = 'scan.started' | 'scan.completed' | 'scan.blocked' | 'phase.observe.started' | 'phase.observe.completed' | 'phase.think.started' | 'phase.think.completed' | 'phase.act.started' | 'phase.act.completed' | 'llm.call.started' | 'llm.call.completed' | 'llm.call.failed' | 'gap.detected' | 'auth.detected' | 'auth.storage-state.validated' | 'repo.scanned';
2
2
  export interface TelemetryEvent {
3
3
  kind: TelemetryEventKind;
4
4
  timestamp: string;
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.interface.d.ts","sourceRoot":"","sources":["../../src/telemetry/telemetry.interface.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,gBAAgB,GAChB,cAAc,GACd,uBAAuB,GACvB,yBAAyB,GACzB,qBAAqB,GACrB,uBAAuB,GACvB,mBAAmB,GACnB,qBAAqB,GACrB,kBAAkB,GAClB,oBAAoB,GACpB,iBAAiB,GACjB,cAAc,GACd,eAAe,GACf,cAAc,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CACnC;AAED,eAAO,MAAM,iBAAiB,EAAE,aAE/B,CAAC"}
1
+ {"version":3,"file":"telemetry.interface.d.ts","sourceRoot":"","sources":["../../src/telemetry/telemetry.interface.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,gBAAgB,GAChB,cAAc,GACd,uBAAuB,GACvB,yBAAyB,GACzB,qBAAqB,GACrB,uBAAuB,GACvB,mBAAmB,GACnB,qBAAqB,GACrB,kBAAkB,GAClB,oBAAoB,GACpB,iBAAiB,GACjB,cAAc,GACd,eAAe,GACf,8BAA8B,GAC9B,cAAc,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CACnC;AAED,eAAO,MAAM,iBAAiB,EAAE,aAE/B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Browser, BrowserContext } from '@playwright/test';
2
+ import type { AuthConfig } from '../schemas/config.schema.js';
3
+ export declare function createAuthenticatedContext(browser: Browser, auth: AuthConfig | undefined, timeoutMs: number): Promise<BrowserContext>;
4
+ //# sourceMappingURL=apply-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-auth.d.ts","sourceRoot":"","sources":["../../src/tools/apply-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,UAAU,GAAG,SAAS,EAC5B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC,CAsCzB"}
@@ -0,0 +1,35 @@
1
+ import { resolve } from 'node:path';
2
+ export async function createAuthenticatedContext(browser, auth, timeoutMs) {
3
+ if (!auth) {
4
+ return browser.newContext();
5
+ }
6
+ if (auth.type === 'storage-state') {
7
+ const storagePath = resolve(process.cwd(), auth.path);
8
+ return browser.newContext({ storageState: storagePath });
9
+ }
10
+ const context = await browser.newContext();
11
+ const page = await context.newPage();
12
+ try {
13
+ await page.goto(auth.loginUrl, { timeout: timeoutMs, waitUntil: 'domcontentloaded' });
14
+ await page.fill(auth.selectors.username, auth.credentials.username);
15
+ await page.fill(auth.selectors.password, auth.credentials.password);
16
+ await page.click(auth.selectors.submit);
17
+ const urlFragment = auth.successIndicator.urlContains;
18
+ if (urlFragment) {
19
+ await page.waitForURL((url) => url.toString().includes(urlFragment), {
20
+ timeout: timeoutMs,
21
+ });
22
+ }
23
+ const visibleSelector = auth.successIndicator.selectorVisible;
24
+ if (visibleSelector) {
25
+ await page.waitForSelector(visibleSelector, {
26
+ timeout: timeoutMs,
27
+ state: 'visible',
28
+ });
29
+ }
30
+ }
31
+ finally {
32
+ await page.close();
33
+ }
34
+ return context;
35
+ }
@@ -0,0 +1,4 @@
1
+ import type { Browser, BrowserContext } from '@playwright/test';
2
+ import type { AuthConfig } from '../../schemas/config.schema.js';
3
+ export declare function createAuthenticatedContext(browser: Browser, auth: AuthConfig | undefined, timeoutMs: number): Promise<BrowserContext>;
4
+ //# sourceMappingURL=apply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/tools/auth/apply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAEjE,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,UAAU,GAAG,SAAS,EAC5B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC,CAsCzB"}
@@ -0,0 +1,35 @@
1
+ import { resolve } from 'node:path';
2
+ export async function createAuthenticatedContext(browser, auth, timeoutMs) {
3
+ if (!auth) {
4
+ return browser.newContext();
5
+ }
6
+ if (auth.type === 'storage-state') {
7
+ const storagePath = resolve(process.cwd(), auth.path);
8
+ return browser.newContext({ storageState: storagePath });
9
+ }
10
+ const context = await browser.newContext();
11
+ const page = await context.newPage();
12
+ try {
13
+ await page.goto(auth.loginUrl, { timeout: timeoutMs, waitUntil: 'domcontentloaded' });
14
+ await page.fill(auth.selectors.username, auth.credentials.username);
15
+ await page.fill(auth.selectors.password, auth.credentials.password);
16
+ await page.click(auth.selectors.submit);
17
+ const urlFragment = auth.successIndicator.urlContains;
18
+ if (urlFragment) {
19
+ await page.waitForURL((url) => url.toString().includes(urlFragment), {
20
+ timeout: timeoutMs,
21
+ });
22
+ }
23
+ const visibleSelector = auth.successIndicator.selectorVisible;
24
+ if (visibleSelector) {
25
+ await page.waitForSelector(visibleSelector, {
26
+ timeout: timeoutMs,
27
+ state: 'visible',
28
+ });
29
+ }
30
+ }
31
+ finally {
32
+ await page.close();
33
+ }
34
+ return context;
35
+ }
@@ -0,0 +1,9 @@
1
+ import type { Gap } from '../../schemas/gap-analysis.schema.js';
2
+ import type { StorageStateInvalidReason } from './detector.js';
3
+ export declare function buildAuthBlockGap(url: string): Gap;
4
+ export declare function buildStorageStateInvalidGap(input: {
5
+ url: string;
6
+ reasonCode: StorageStateInvalidReason;
7
+ reason: string;
8
+ }): Gap;
9
+ //# sourceMappingURL=block-gap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"block-gap.d.ts","sourceRoot":"","sources":["../../../src/tools/auth/block-gap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,sCAAsC,CAAC;AAChE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAmB/D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAYlD;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,yBAAyB,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,GAAG,CAqBN"}