{
  "checked_at": "2026-10-10T06:27:16.777144+00:00",
  "python": "3.12.10 (tags/v3.12.10:0cc8128, Apr  8 2025, 12:21:36) [MSC v.1943 64 bit (AMD64)]",
  "scope": "Python examples and configured command only; no Claude model, MCP or engine session",
  "regression": [
    {
      "asset_type": "Texture",
      "name": "T_Rock.png",
      "expected": true,
      "buggy": true,
      "fixed": true
    },
    {
      "asset_type": "Texture",
      "name": "T_Rock.PNG",
      "expected": false,
      "buggy": true,
      "fixed": false
    },
    {
      "asset_type": "Texture",
      "name": "T_HDR.exr",
      "expected": true,
      "buggy": true,
      "fixed": true
    },
    {
      "asset_type": "Texture",
      "name": "T_HDR.EXR",
      "expected": false,
      "buggy": true,
      "fixed": false
    },
    {
      "asset_type": "StaticMesh",
      "name": "SM_Rock.fbx",
      "expected": true,
      "buggy": true,
      "fixed": true
    },
    {
      "asset_type": "StaticMesh",
      "name": "SM_Rock.FBX",
      "expected": false,
      "buggy": true,
      "fixed": false
    },
    {
      "asset_type": "Texture",
      "name": "T_Rock.png.bak",
      "expected": false,
      "buggy": false,
      "fixed": false
    },
    {
      "asset_type": "Texture",
      "name": "T_Rock",
      "expected": false,
      "buggy": false,
      "fixed": false
    },
    {
      "asset_type": "Material",
      "name": "M_Rock.mat",
      "expected": false,
      "buggy": false,
      "fixed": false
    }
  ],
  "buggy_failures": [
    "T_Rock.PNG",
    "T_HDR.EXR",
    "SM_Rock.FBX"
  ],
  "fixed_passed": true,
  "mutation_detected": true,
  "cli": [
    {
      "case": "mixed",
      "command": [
        "[本地路径]",
        "asset_check.py",
        "fixtures/assets_mixed.csv",
        "--json"
      ],
      "expected_exit": 1,
      "actual_exit": 1,
      "stdout": "{\n  \"input\": \"fixtures\\\\assets_mixed.csv\",\n  \"rows\": 6,\n  \"valid\": 3,\n  \"invalid\": 3,\n  \"problems\": [\n    {\n      \"line\": 5,\n      \"asset_type\": \"StaticMesh\",\n      \"name\": \"rock.fbx\",\n      \"issues\": [\n        \"expected prefix SM_\"\n      ]\n    },\n    {\n      \"line\": 6,\n      \"asset_type\": \"Texture\",\n      \"name\": \"T_Rock_BaseColor.tga\",\n      \"issues\": [\n        \"extension not allowed (case-sensitive)\"\n      ]\n    },\n    {\n      \"line\": 7,\n      \"asset_type\": \"Material\",\n      \"name\": \"M_Rock.uasset\",\n      \"issues\": [\n        \"unsupported asset_type\"\n      ]\n    }\n  ]\n}\n",
      "stderr": "",
      "passed": true
    },
    {
      "case": "valid",
      "command": [
        "[本地路径]",
        "asset_check.py",
        "fixtures/assets_valid.csv",
        "--json"
      ],
      "expected_exit": 0,
      "actual_exit": 0,
      "stdout": "{\n  \"input\": \"fixtures\\\\assets_valid.csv\",\n  \"rows\": 3,\n  \"valid\": 3,\n  \"invalid\": 0,\n  \"problems\": []\n}\n",
      "stderr": "",
      "passed": true
    },
    {
      "case": "edges",
      "command": [
        "[本地路径]",
        "asset_check.py",
        "fixtures/assets_edges.csv",
        "--json"
      ],
      "expected_exit": 1,
      "actual_exit": 1,
      "stdout": "{\n  \"input\": \"fixtures\\\\assets_edges.csv\",\n  \"rows\": 6,\n  \"valid\": 2,\n  \"invalid\": 4,\n  \"problems\": [\n    {\n      \"line\": 3,\n      \"asset_type\": \"StaticMesh\",\n      \"name\": \"SM_.fbx\",\n      \"issues\": [\n        \"invalid name body\"\n      ]\n    },\n    {\n      \"line\": 4,\n      \"asset_type\": \"Texture\",\n      \"name\": \"\",\n      \"issues\": [\n        \"empty name\"\n      ]\n    },\n    {\n      \"line\": 5,\n      \"asset_type\": \"Texture\",\n      \"name\": \"../T_Rock_BaseColor.png\",\n      \"issues\": [\n        \"expected a filename, not a path\"\n      ]\n    },\n    {\n      \"line\": 7,\n      \"asset_type\": \"Texture\",\n      \"name\": \"T_Sky_HDR.exr\",\n      \"issues\": [\n        \"duplicate name\"\n      ]\n    }\n  ]\n}\n",
      "stderr": "",
      "passed": true
    },
    {
      "case": "uppercase",
      "command": [
        "[本地路径]",
        "asset_check.py",
        "fixtures/assets_uppercase.csv",
        "--json"
      ],
      "expected_exit": 1,
      "actual_exit": 1,
      "stdout": "{\n  \"input\": \"fixtures\\\\assets_uppercase.csv\",\n  \"rows\": 1,\n  \"valid\": 0,\n  \"invalid\": 1,\n  \"problems\": [\n    {\n      \"line\": 2,\n      \"asset_type\": \"Texture\",\n      \"name\": \"T_Rock_BaseColor.PNG\",\n      \"issues\": [\n        \"extension not allowed (case-sensitive)\"\n      ]\n    }\n  ]\n}\n",
      "stderr": "",
      "passed": true
    },
    {
      "case": "empty",
      "command": [
        "[本地路径]",
        "asset_check.py",
        "fixtures/assets_empty.csv",
        "--json"
      ],
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "INPUT_ERROR: asset list is empty\n",
      "passed": true
    },
    {
      "case": "bad_header",
      "command": [
        "[本地路径]",
        "asset_check.py",
        "fixtures/assets_bad_header.csv",
        "--json"
      ],
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "INPUT_ERROR: expected CSV columns: asset_type,name\n",
      "passed": true
    },
    {
      "case": "does_not_exist",
      "command": [
        "[本地路径]",
        "asset_check.py",
        "fixtures/assets_does_not_exist.csv",
        "--json"
      ],
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "INPUT_ERROR: [Errno 2] No such file or directory: 'fixtures\\\\assets_does_not_exist.csv'\n",
      "passed": true
    }
  ],
  "hooks": [
    {
      "case": "normal_relative",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 0,
      "actual_exit": 0,
      "stdout": "",
      "stderr": "",
      "passed": true
    },
    {
      "case": "normal_absolute",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 0,
      "actual_exit": 0,
      "stdout": "",
      "stderr": "",
      "passed": true
    },
    {
      "case": "protected_relative",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "WRITE_DENIED: protected directory is read-only\n",
      "passed": true
    },
    {
      "case": "protected_absolute",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "WRITE_DENIED: protected directory is read-only\n",
      "passed": true
    },
    {
      "case": "traversal",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "WRITE_DENIED: protected directory is read-only\n",
      "passed": true
    },
    {
      "case": "outside_project",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "WRITE_DENIED: target is outside the teaching project\n",
      "passed": true
    },
    {
      "case": "similar_prefix",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 0,
      "actual_exit": 0,
      "stdout": "",
      "stderr": "",
      "passed": true
    },
    {
      "case": "nested_cwd",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "WRITE_DENIED: protected directory is read-only\n",
      "passed": true
    },
    {
      "case": "missing_path",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "WRITE_DENIED: missing or invalid file_path\n",
      "passed": true
    },
    {
      "case": "malformed_json",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "WRITE_DENIED: invalid hook input\n",
      "passed": true
    },
    {
      "case": "missing_root",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 2,
      "actual_exit": 2,
      "stdout": "",
      "stderr": "WRITE_DENIED: CLAUDE_PROJECT_DIR is required\n",
      "passed": true
    },
    {
      "case": "unmatched_read_tool",
      "command": "python -c \"import os,runpy,sys; p=os.environ.get('CLAUDE_PROJECT_DIR'); (print('WRITE_DENIED: CLAUDE_PROJECT_DIR is required',file=sys.stderr),sys.exit(2)) if not p else runpy.run_path(os.path.join(p,'hooks','guard_write.py'),run_name='__main__')\"",
      "process_cwd": "[本地路径]",
      "event_cwd": "[本地路径]",
      "expected_exit": 0,
      "actual_exit": 0,
      "stdout": "",
      "stderr": "",
      "passed": true
    }
  ],
  "config_json_parsed": true,
  "original_inputs_unchanged": true,
  "input_hashes_before": {
    "示例\\ClaudeCode\\CC-01_asset_naming\\asset_check.py": "b5f3efd3b72e80463a1de24aa713f9372d663b0437df0ea7d11de5765cbb9645",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_bad_header.csv": "ee8f03983f764cf81a7119bd7a2eb48f001f138c1fcc2352c07a267cbae82a9a",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_edges.csv": "35a572dbed2534c3dfbf5a22e1c6e2aa7e388fbe1b2cc3ab1df280bafc1ea6fa",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_empty.csv": "9cb2c4386fa4a34cf0b05dad32268add71143bd6cdb2a100fd7528fcabb6eb81",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_mixed.csv": "258532f2fa5ac0514f1970347979377621f626a48b38db68fbbabbc2df5a1a5c",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_uppercase.csv": "f490845b70153bf30312a5067084b189c020e2c65eb8bffc1ef2ab9e7e88c579",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_valid.csv": "6a08c3a531d6105001536fa024686f67e031f17d2f9d90c3ff34fce6c42fde9a"
  },
  "input_hashes_after": {
    "示例\\ClaudeCode\\CC-01_asset_naming\\asset_check.py": "b5f3efd3b72e80463a1de24aa713f9372d663b0437df0ea7d11de5765cbb9645",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_bad_header.csv": "ee8f03983f764cf81a7119bd7a2eb48f001f138c1fcc2352c07a267cbae82a9a",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_edges.csv": "35a572dbed2534c3dfbf5a22e1c6e2aa7e388fbe1b2cc3ab1df280bafc1ea6fa",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_empty.csv": "9cb2c4386fa4a34cf0b05dad32268add71143bd6cdb2a100fd7528fcabb6eb81",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_mixed.csv": "258532f2fa5ac0514f1970347979377621f626a48b38db68fbbabbc2df5a1a5c",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_uppercase.csv": "f490845b70153bf30312a5067084b189c020e2c65eb8bffc1ef2ab9e7e88c579",
    "示例\\ClaudeCode\\CC-01_asset_naming\\fixtures\\assets_valid.csv": "6a08c3a531d6105001536fa024686f67e031f17d2f9d90c3ff34fce6c42fde9a"
  },
  "passed": true
}