{
  "article_slug": "3d-pathfinding-in-godot",
  "artifact": "3D Pathfinding Starter for Godot",
  "check_count": 21,
  "checks": [
    {
      "id": "main_scene_loads",
      "observed": {
        "summary": "The authored starter scene loads as a PackedScene."
      },
      "passed": true
    },
    {
      "id": "authored_nodes_exist",
      "observed": {
        "summary": "The scene contains the region, agent, grounded body, obstacle, target, and path-line nodes before Play."
      },
      "passed": true
    },
    {
      "id": "baked_navmesh_is_saved",
      "observed": {
        "summary": "The NavigationRegion3D references a saved bake with vertices and polygons."
      },
      "passed": true
    },
    {
      "id": "bake_parameters_match_tutorial",
      "observed": {
        "summary": "The saved bake uses the tutorial's radius, height, climb, slope, and voxel settings."
      },
      "passed": true
    },
    {
      "id": "three_radius_contract_is_explicit",
      "observed": {
        "summary": "Physics, bake, and avoidance radii are authored separately as 0.48, 0.50, and 0.55 metres."
      },
      "passed": true
    },
    {
      "id": "grounded_controller_contract",
      "observed": {
        "summary": "The CharacterBody3D controller has floor snapping and a floor angle compatible with the ramp and bake."
      },
      "passed": true
    },
    {
      "id": "avoidance_nodes_are_enabled",
      "observed": {
        "summary": "The player agent and moving NavigationObstacle3D both participate in local avoidance."
      },
      "passed": true
    },
    {
      "id": "navigation_map_synchronizes",
      "observed": {
        "summary": "The NavigationServer3D map completes its initial synchronization and owns a region."
      },
      "passed": true
    },
    {
      "id": "upper_platform_has_a_route",
      "observed": {
        "summary": "The saved navmesh returns a route from the lower floor to the raised platform."
      },
      "passed": true
    },
    {
      "id": "target_is_explicitly_clamped",
      "observed": {
        "summary": "The authored upper target resolves to a nearby point on the navigation map."
      },
      "passed": true
    },
    {
      "id": "character_follows_the_path",
      "observed": {
        "summary": "The grounded character advances several metres along the agent path."
      },
      "passed": true
    },
    {
      "id": "moving_obstacle_publishes_velocity",
      "observed": {
        "summary": "The moving avoidance obstacle reports non-zero velocity while crossing the route."
      },
      "passed": true
    },
    {
      "id": "visible_path_is_drawn",
      "observed": {
        "summary": "The runtime path-line mesh contains a rendered surface."
      },
      "passed": true
    },
    {
      "id": "moving_obstacle_does_not_rewrite_navmesh_path",
      "observed": {
        "summary": "Local avoidance changes safe velocity without rebuilding the global navmesh path."
      },
      "passed": true
    },
    {
      "id": "grounded_body_traverses_the_ramp",
      "observed": {
        "summary": "The CharacterBody3D reaches the raised floor while remaining grounded."
      },
      "passed": true
    },
    {
      "id": "agent_reports_target_reachable",
      "observed": {
        "summary": "NavigationAgent3D reports the authored target as reachable."
      },
      "passed": true
    },
    {
      "id": "click_target_uses_closest_navmesh_point",
      "observed": {
        "summary": "Click targets are clamped explicitly with map_get_closest_point()."
      },
      "passed": true
    },
    {
      "id": "raycast_is_consumed_in_physics_step",
      "observed": {
        "summary": "Mouse input is buffered and the physics ray query is consumed in _physics_process()."
      },
      "passed": true
    },
    {
      "id": "safe_velocity_drives_the_body",
      "observed": {
        "summary": "The avoidance callback's safe velocity drives the CharacterBody3D."
      },
      "passed": true
    },
    {
      "id": "obstacle_velocity_is_supplied",
      "observed": {
        "summary": "The moving obstacle publishes its velocity to NavigationObstacle3D."
      },
      "passed": true
    },
    {
      "id": "extracted_package_reruns_cleanly",
      "passed": true,
      "observed": {
        "extracted_workspace_check_count": 20,
        "check_ids_match_workspace": true,
        "scene_smoke_passed": true,
        "engine": "4.7.1-stable (official)"
      }
    }
  ],
  "engine": {
    "build": "official",
    "hash": "a13da4feb8d8aefc283c3763d33a2f170a18d541",
    "hex": 263937,
    "major": 4,
    "minor": 7,
    "patch": 1,
    "status": "stable",
    "string": "4.7.1-stable (official)",
    "timestamp": 0
  },
  "failed": [],
  "failed_count": 0,
  "measurement_gap": "Deterministic tutorial correctness only. No FPS, throughput, crowd-capacity, optimality, production-readiness, or hard dynamic-blocker claim.",
  "passed": true,
  "passed_count": 21,
  "scene_smoke": {
    "authored_before_play": true,
    "navmesh_polygons": 27,
    "navmesh_vertices": 26,
    "passed": true,
    "scene": "res://scenes/main.tscn"
  },
  "scope": [
    "saved NavigationMesh bake and authored NavigationRegion3D",
    "grounded CharacterBody3D route following over a ramp",
    "explicit click-target clamping to the navigation map",
    "separate physics, bake, and avoidance radii",
    "visible global path and optional local avoidance",
    "runnable authored scene"
  ],
  "published_files": {
    "source_zip": {
      "path": "/downloads/pathfinding/3d-pathfinding-starter-godot-source.zip",
      "bytes": 13833,
      "sha256": "bcfb590993cfd025b810f745bf0303d39061cdf6c177f0c27bf66be637104d1c"
    },
    "source_manifest": [
      {
        "path": ".gitignore",
        "bytes": 23,
        "sha256": "ff32e4481fa5c550a52438396b67628d268b3b02650a67649e7a55275a89bd49"
      },
      {
        "path": "LICENSE",
        "bytes": 1066,
        "sha256": "162b2144048b30b68057a3259769ef2c83b8c86539f31fb6f542bea7c0292ef2"
      },
      {
        "path": "README.md",
        "bytes": 1470,
        "sha256": "11d4bb42c0fe0b98f98f6b65eed54cc2c79706228f88d308cdba6ea3541b50c4"
      },
      {
        "path": "project.godot",
        "bytes": 1051,
        "sha256": "b71e8a245b107e7b42388c2aefa3b98f343192b7c3507f916efd5bb896429b65"
      },
      {
        "path": "export_presets.cfg",
        "bytes": 1206,
        "sha256": "ec84f17407af060b14abf312364616ad16af1d2b0c83c24fbe99404ae16bfdff"
      },
      {
        "path": "navigation/starter_navmesh.tres",
        "bytes": 1420,
        "sha256": "cc31eb4c978055034b8459206304416c01228983d57f0a8d718877297572bcdd"
      },
      {
        "path": "scenes/main.tscn",
        "bytes": 11043,
        "sha256": "8e4c4b1c53c60d837a41066f836866254e99e0d00bb2a1ac3346ef1dba247551"
      },
      {
        "path": "scripts/demo_controller.gd",
        "bytes": 3517,
        "sha256": "361123004f2edc3ed113b06b57a248d3c6ea786aba3346ce5ec2a400ee3b20d7"
      },
      {
        "path": "scripts/demo_controller.gd.uid",
        "bytes": 20,
        "sha256": "548962d4af26bf5d853cdd9c881247cbdfddcaeceacee6690dbb14b3dc52990c"
      },
      {
        "path": "scripts/moving_obstacle.gd",
        "bytes": 1003,
        "sha256": "ed540081c47c4866c00a50d8b0b3f93186b24d181c3377124d357ca6ee14a462"
      },
      {
        "path": "scripts/moving_obstacle.gd.uid",
        "bytes": 19,
        "sha256": "0228d7f7c043eb6c2bb2fdc1c9e73c24d7d5b6c3fc2e0b2e15aaa3251bd8e828"
      },
      {
        "path": "scripts/player_agent.gd",
        "bytes": 4096,
        "sha256": "b5fbbdb879554275046a1cbb57f67548e7369b7553793daea23c23e859186e8a"
      },
      {
        "path": "scripts/player_agent.gd.uid",
        "bytes": 20,
        "sha256": "05fa02404a74e0cdcc5be487ba39adab510f58fcb99d1f2383ffff6a33e08a49"
      },
      {
        "path": "tools/verify_artifact.gd",
        "bytes": 10133,
        "sha256": "f82f712c79b90692483de87e67faf37a8e838aa065f977c8706c5c6bca287793"
      },
      {
        "path": "tools/verify_artifact.gd.uid",
        "bytes": 20,
        "sha256": "2e6a1f40a10287dff0d21c57fc3651a34837fac88eddccc27c6218553fc52c52"
      }
    ]
  },
  "extracted_package_rerun": {
    "passed": true,
    "workspace_check_count": 20,
    "published_check_count": 21,
    "check_ids_match_workspace": true,
    "scene_smoke_passed": true,
    "engine": "4.7.1-stable (official)"
  },
  "snippet_verification": {
    "article_slug": "3d-pathfinding-in-godot",
    "article_route": "/blog/3d-pathfinding-in-godot/",
    "checked_at_utc": "2026-07-17T03:38:19Z",
    "comparison": "Line endings normalized to LF; every executable article block must otherwise equal one contiguous source excerpt byte-for-byte.",
    "block_count": 7,
    "executable_block_count": 6,
    "exact_excerpt_count": 6,
    "excluded_non_executable_count": 1,
    "passed": true,
    "checks": [
      {
        "id": "scene_tree_diagram",
        "heading": "Build the starter in this order",
        "result": "excluded_non_executable",
        "passed": true
      },
      {
        "id": "navigation_readiness",
        "heading": "Wait until the navigation map is usable",
        "result": "exact_contiguous_excerpt",
        "passed": true,
        "source_path": "scripts/player_agent.gd",
        "source_sha256": "b5fbbdb879554275046a1cbb57f67548e7369b7553793daea23c23e859186e8a",
        "excerpt_sha256": "e907f8cab528aa21ee924a854f96e8bca0049ba31f2ac1945cbfb21325816270",
        "article_code_sha256": "e907f8cab528aa21ee924a854f96e8bca0049ba31f2ac1945cbfb21325816270"
      },
      {
        "id": "physics_step_click_raycast",
        "heading": "Raycast the click during the physics step",
        "result": "exact_contiguous_excerpt",
        "passed": true,
        "source_path": "scripts/demo_controller.gd",
        "source_sha256": "361123004f2edc3ed113b06b57a248d3c6ea786aba3346ce5ec2a400ee3b20d7",
        "excerpt_sha256": "cfd962456c5e53ca0a5f45c976086d8b54597544eb52c00ccaa30f644a576587",
        "article_code_sha256": "cfd962456c5e53ca0a5f45c976086d8b54597544eb52c00ccaa30f644a576587"
      },
      {
        "id": "target_clamping",
        "heading": "Clamp the requested target to the navmesh",
        "result": "exact_contiguous_excerpt",
        "passed": true,
        "source_path": "scripts/player_agent.gd",
        "source_sha256": "b5fbbdb879554275046a1cbb57f67548e7369b7553793daea23c23e859186e8a",
        "excerpt_sha256": "97077b28be893844994c76bbf4c8848532946b45e45404827d96621a82922193",
        "article_code_sha256": "97077b28be893844994c76bbf4c8848532946b45e45404827d96621a82922193"
      },
      {
        "id": "grounded_path_following",
        "heading": "Move the CharacterBody3D yourself",
        "result": "exact_contiguous_excerpt",
        "passed": true,
        "source_path": "scripts/player_agent.gd",
        "source_sha256": "b5fbbdb879554275046a1cbb57f67548e7369b7553793daea23c23e859186e8a",
        "excerpt_sha256": "259e9de27eba6b45260d8c43195cf413d3d785c2f8eab58c12b14b868107d3d1",
        "article_code_sha256": "259e9de27eba6b45260d8c43195cf413d3d785c2f8eab58c12b14b868107d3d1"
      },
      {
        "id": "moving_obstacle_velocity",
        "heading": "Avoidance changes velocity, not the path",
        "result": "exact_contiguous_excerpt",
        "passed": true,
        "source_path": "scripts/moving_obstacle.gd",
        "source_sha256": "ed540081c47c4866c00a50d8b0b3f93186b24d181c3377124d357ca6ee14a462",
        "excerpt_sha256": "eda28c40ba62c960de441beb3d97dcf0653f48bc99f96b6a12e3c7639642f4e2",
        "article_code_sha256": "eda28c40ba62c960de441beb3d97dcf0653f48bc99f96b6a12e3c7639642f4e2"
      },
      {
        "id": "safe_velocity_callback",
        "heading": "Drive the body with the safe velocity",
        "result": "exact_contiguous_excerpt",
        "passed": true,
        "source_path": "scripts/player_agent.gd",
        "source_sha256": "b5fbbdb879554275046a1cbb57f67548e7369b7553793daea23c23e859186e8a",
        "excerpt_sha256": "271bd3e15610021d18ef1139527fa99fdf836438045d10a8bd38e4fb98ba031f",
        "article_code_sha256": "271bd3e15610021d18ef1139527fa99fdf836438045d10a8bd38e4fb98ba031f"
      }
    ]
  }
}
