How the Post-Render Artifact Checker Detects Diagonal Arrows and Legend-Crossing Routes

The post-render artifact checker validates rendered SVG diagrams by analyzing path geometries to flag diagonal arrows and detect intersections between routes and legend bounding boxes.

The post-render artifact checker in the tt-a1i/archify repository ensures that generated architecture diagrams maintain strict orthogonal routing and avoid visual collisions with legend elements. After a diagram renders to HTML, the Node.js script archify/scripts/check-render-output.mjs parses the SVG markup and executes geometric validation checks that catch layout artifacts before they reach production.

Where the Post-Render Artifact Checker Lives

The validation logic resides in archify/scripts/check-render-output.mjs. The script operates on the HTML output file, extracting the <svg> block and running two primary checks: orthogonal_arrows and legend_clearance. Both checks register with the internal checks array via addCheck() (lines 28‑30), and the final JSON report includes a boolean ok flag plus detailed failure messages (lines 62‑64).

How Diagonal Arrow Detection Works

The checker identifies accidental diagonal arrows through geometric analysis of SVG path data.

Collecting Arrow Elements

First, the script gathers all potential arrow candidates. The function collectArrows() (lines 70‑79) scans the SVG for <path> and <line> elements that represent diagram connections. For each element found, the script constructs an array of line segments stored in lineSegments or pathSegments properties.

The Diagonal Classification Logic

An arrow qualifies as diagonal if it meets strict geometric criteria evaluated by isTwoPointDiagonal() (lines 100‑104). The function tests whether the arrow consists of exactly one segment whose start and end points differ in both the X and Y dimensions by more than a tolerance of 0.01 units. If any arrow satisfies this condition, the orthogonal_arrows check fails, and the script reports the offending element including its class and d attribute.

How Legend-Crossing Detection Works

The checker prevents routes from intersecting with legend elements through bounding-box collision detection.

Identifying Legend Bounding Boxes

The legend region begins at the HTML comment <!-- Legend -->. The function collectLegendBoxes() (lines 106‑126) extracts all <rect> and <text> elements from this fragment and converts them into bounding boxes with coordinates (x1, y1, x2, y2). For text elements, the script approximates width using estimatedTextWidth() (lines 162‑166), which applies heuristic calculations to unmeasured text nodes.

Collision Detection with Padding

With arrow segments and legend boxes collected, collectLegendCollisions() (lines 129‑140) performs intersection tests. The geometry validation uses segmentIntersectsBox() (lines 224‑233), which implements standard computational geometry algorithms including segmentsIntersect, orientation, and onSegment tests. Each legend box receives a 2 px padding via padBox() (lines 266‑274) to tolerate minor overlaps without flagging false positives. When any route segment intersects a padded legend box, the legend_clearance check fails, reporting the specific arrow index and the coordinates of the crossed legend element.

Running the Validation

Execute the checker against any rendered Archify diagram:


# Generate the diagram first, then validate:

node archify/scripts/check-render-output.mjs my-diagram.html

When the checker detects violations, it outputs structured JSON identifying specific failures:

Diagonal arrow violation:

{
  "ok": false,
  "file": "/path/to/my-diagram.html",
  "checks": [
    {
      "name": "orthogonal_arrows",
      "ok": false,
      "details": [
        "path 3: <path class=\"a-default\" marker-end=\"url(#arrowhead)\" d=\"M10 10 L50 30\"/>"
      ]
    }
  ]
}

Legend crossing violation:

{
  "ok": false,
  "file": "/path/to/my-diagram.html",
  "checks": [
    {
      "name": "legend_clearance",
      "ok": false,
      "details": [
        "line 5 crosses legend rect@200,10"
      ]
    }
  ]
}

Summary

  • The post-render artifact checker lives in archify/scripts/check-render-output.mjs and validates SVG output after HTML generation.
  • Diagonal detection relies on isTwoPointDiagonal() checking for single-segment arrows with simultaneous X and Y displacement above 0.01 tolerance.
  • Legend crossing detection uses collectLegendBoxes() to build bounding boxes from the <!-- Legend --> comment forward, then tests intersections with segmentIntersectsBox() using 2 px padding.
  • Failed checks return detailed JSON reports identifying specific arrow indices and crossed legend coordinates.

Frequently Asked Questions

What tolerance does the post-render artifact checker use for diagonal detection?

The checker uses a tolerance of 0.01 units in the isTwoPointDiagonal() function (lines 100‑104). An arrow only flags as diagonal if both its X and Y deltas exceed this threshold, filtering out floating-point rounding errors while catching intentional diagonal routes.

How does the checker identify which SVG elements belong to the legend?

The script searches for the HTML comment <!-- Legend --> as a sentinel marker. Everything after this comment belongs to the legend fragment, which collectLegendBoxes() (lines 106‑126) scans for <rect> and <text> elements to build collision detection bounding boxes.

What padding does the legend collision detection apply?

The padBox() function (lines 266‑274) adds 2 px of padding to each legend bounding box before intersection tests. This tolerance prevents false positives from minor overlaps while still catching significant route crossings that would impair readability.

Can the checker run as part of an automated CI pipeline?

Yes. The script exits with a non-zero status when ok is false, and outputs machine-readable JSON to stdout. You can invoke it via node archify/scripts/check-render-output.mjs <file> after any diagram generation step to enforce quality gates in continuous integration workflows.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →