runAsync method ✓ 100.0%

Last updated: 2026-03-01T23:35:47.796Z

Metrics

LOC: 118 Complexity: 16 Params: 1 Coverage: 100.0% (35/35 lines, 27x executed)

Signature

runAsync(field: FormField): : Promise<PipelineResult>

Summary

Async variant — prefers detectAsync when available on a classifier (e.g. Chrome AI), falling back to the synchronous detect for all others. Cross-validation behaviour: When html-type produces a result, the pipeline does NOT stop immediately. Instead, the result is held as provisional and the TensorFlow classifier is still executed. If TensorFlow returns a different type with confidence ≥ HTML_TYPE_CROSS_VALIDATE_THRESHOLD, TensorFlow wins (semantic context beats the structural HTML hint). Otherwise the original html-type result stands. Example: <input type="date" name="birthDate"> with label "Nascimento" → html-type says "date" (100%), but TensorFlow may say "birthDate" (>50%) based on signals → TensorFlow result is used.

Architecture violations

View all

  • [warning] max-cyclomatic-complexity: 'runAsync' has cyclomatic complexity 16 (max 10)
  • [warning] max-lines: 'runAsync' has 118 lines (max 80)

Source Code

  async runAsync(field: FormField): Promise<PipelineResult> {
    const t0 = performance.now();
    const timings: PipelineResult["timings"] = [];
    const predictions: PipelineResult["predictions"] = [];
    const decisionTrace: string[] = [];

    // Holds the provisional html-type result while we wait for TF cross-validation
    let htmlTypeProvisional: ClassifierResult | null = null;

    for (const classifier of this.classifiers) {
      const ct = performance.now();
      const result = classifier.detectAsync
        ? await classifier.detectAsync(field)
        : classifier.detect(field);
      const classifierMs = performance.now() - ct;
      timings.push({ strategy: classifier.name, durationMs: classifierMs });

      if (result === null) {
        decisionTrace.push(`${classifier.name}: null — skipped`);
      } else if (result.type === "unknown") {
        decisionTrace.push(
          `${classifier.name}: unknown (${(result.confidence * 100).toFixed(0)}%) — skipped`,
        );
        predictions.push({ type: result.type, confidence: result.confidence });
      } else {
        predictions.push({ type: result.type, confidence: result.confidence });

        // html-type: store provisionally and continue to tensorflow for cross-validation
        if (classifier.name === "html-type") {
          htmlTypeProvisional = result;
          decisionTrace.push(
            `${classifier.name}: ${result.type} (${(result.confidence * 100).toFixed(0)}%) — provisional, awaiting tensorflow cross-validation`,
          );
          continue;
        }

        // tensorflow: check whether it should override the provisional html-type result
        if (classifier.name === "tensorflow" && htmlTypeProvisional !== null) {
          if (
            result.type !== htmlTypeProvisional.type &&
            result.confidence >= HTML_TYPE_CROSS_VALIDATE_THRESHOLD
          ) {
            // TensorFlow has a different, confident semantic classification → override
            decisionTrace.push(
              `${classifier.name}: ${result.type} (${(result.confidence * 100).toFixed(0)}%) — overrides html-type (semantic context)`,
            );
            // Fall through to the normal return below
          } else {
            // TensorFlow confirms html-type or is not confident enough → html-type stands
            decisionTrace.push(
              `${classifier.name}: ${result.type} (${(result.confidence * 100).toFixed(0)}%) — html-type confirmed`,
            );
            return {
              ...htmlTypeProvisional,
              method: "html-type",
              durationMs: performance.now() - t0,
              timings,
              predictions,
              decisionTrace,
            };
          }
        }

        decisionTrace.push(
          `${classifier.name}: ${result.type} (${(result.confidence * 100).toFixed(0)}%) — selected`,
        );
        return {
          ...result,
          method: classifier.name,
          durationMs: performance.now() - t0,
          timings,
          predictions,
          decisionTrace,
        };
      }

      // After tensorflow processed (null or unknown): provisional html-type stands
      if (htmlTypeProvisional !== null && classifier.name === "tensorflow") {
        decisionTrace.push(
          `html-type: ${htmlTypeProvisional.type} (100%) — confirmed (tensorflow skipped/unknown)`,
        );
        return {
          ...htmlTypeProvisional,
          method: "html-type",
          durationMs: performance.now() - t0,
          timings,
          predictions,
          decisionTrace,
        };
      }
    }

    // End of pipeline — if html-type was provisional and tensorflow wasn't in the pipeline
    if (htmlTypeProvisional !== null) {
      decisionTrace.push(
        `html-type: ${htmlTypeProvisional.type} (100%) — confirmed (no tensorflow in pipeline)`,
      );
      return {
        ...htmlTypeProvisional,
        method: "html-type",
        durationMs: performance.now() - t0,
        timings,
        predictions,
        decisionTrace,
      };
    }

    decisionTrace.push("html-fallback: unknown — no classifier matched");
    return {
      type: "unknown",
      method: "html-fallback",
      confidence: 0.1,
      durationMs: performance.now() - t0,
      timings,
      predictions,
      decisionTrace,
    };
  }

No outgoing dependencies.

No incoming dependencies.