{
  "run_id": "carelessdept--ci-guard-mcp-claude-haiku-5-5-1792797963689250861",
  "checker": {
    "claims": [
      {
        "claim": "Exit code 1 when findings are at or above the threshold",
        "command": "node <guest-path> scan /tmp/ciguard-fixture --format json",
        "evidence": "\"ruleId\": \"workflow/script-injection\",\n      \"severity\": \"error\",\n      \"file\": \".github/workflows/ci.yml\",\n      \"line\": 10,\n      \"message\": \"Untrusted GitHub context is interpolated directly into a shell script.\",\n      \"suggestion\": \"Pass event fields through step env and use quoted shell variables.\"\n    }\n  ],\n  \"summary\": {\n    \"error\": 1,\n    \"warn\": 1,\n    \"info\": 0\n  },\n  \"filesScanned\": 1\n}\n",
        "expected": "exit 1 and the workflow/script-injection finding",
        "input": "/tmp/ciguard-fixture (workflow with script injection)",
        "kind": "claim",
        "outcome": "Real input produced the expected result: \"ruleId\": \"workflow/script-injection\"",
        "returncode": 1,
        "source": "Exit codes: **0** below threshold, **1** findings at or above threshold",
        "source_checked": true,
        "source_file": "README.md",
        "verdict": "yes"
      },
      {
        "claim": "MCP tool results include structuredContent with the same report",
        "command": "node <guest-path> --mcp --root /tmp/ciguard-fixture tools/call {\"tool\": \"scan_repo\", \"arguments\": {\"path\": \".\"}}",
        "evidence": "workflow/unpinned-action\\\",\\\"severity\\\":\\\"warn\\\",\\\"file\\\":\\\".github/workflows/ci.yml\\\",\\\"line\\\":9,\\\"message\\\":\\\"External action or reusable workflow is not pinned to an immutable digest.\\\",\\\"suggestion\\\":\\\"Pin actions to a full 40-character commit SHA and containers to a sha256 digest.\\\"},{\\\"ruleId\\\":\\\"workflow/script-injection\\\",\\\"severity\\\":\\\"error\\\",\\\"file\\\":\\\".github/workflows/ci.yml\\\",\\\"line\\\":10,\\\"message\\\":\\\"Untrusted GitHub context is interpolated directly into a shell script.\\\",\\\"suggestion\\\":\\\"Pass event fields through step env and use quoted shell variables.\\\"}],\\\"summary\\\":{\\\"error",
        "expected": "report containing the workflow/unpinned-action finding",
        "input": "{\"tool\": \"scan_repo\", \"arguments\": {\"path\": \".\"}}",
        "kind": "claim",
        "outcome": "Real input produced the expected result: workflow/unpinned-action",
        "source": "Responses contain text JSON plus `structuredContent` with the same report.",
        "source_checked": true,
        "source_file": "README.md",
        "verdict": "yes"
      }
    ],
    "cycle_checks": [
      {
        "claim": "Scheduled or looping main behavior",
        "command": "",
        "evidence": "Inspected README.md and src/ for cron, schedule, setInterval, loop, webhook, --once and --now entry points; none exist. ci-guard-mcp is a one-shot CLI (scan), a one-shot GitHub Action, and a stdio MCP server that answers requests on demand. No product cycle to trigger.",
        "expected": "identify the product trigger",
        "input": "source inspection",
        "kind": "cycle",
        "outcome": "Inspected README.md and src/ for cron, schedule, setInterval, loop, webhook, --once and --now entry points; none exist. ci-guard-mcp is a one-shot CLI (scan), a one-shot GitHub Action, and a stdio MCP server that answers requests on demand. No product cycle to trigger.",
        "source": "repository entry points",
        "verdict": "yes"
      }
    ],
    "details": {
      "argv": [
        "node",
        "<guest-path>",
        "--mcp",
        "--root",
        "/tmp/ciguard-fixture"
      ],
      "kind": "mcp",
      "scope": "product operation",
      "serverInfo": {
        "name": "ci-guard-mcp",
        "version": "0.2.0"
      },
      "tool_result": {
        "content": [
          {
            "text": "{\"version\":\"0.2.0\",\"findings\":[{\"ruleId\":\"workflow/unpinned-action\",\"severity\":\"warn\",\"file\":\".github/workflows/ci.yml\",\"line\":9,\"message\":\"External action or reusable workflow is not pinned to an immutable digest.\",\"suggestion\":\"Pin actions to a full 40-character commit SHA and containers to a sha256 digest.\"},{\"ruleId\":\"workflow/script-injection\",\"severity\":\"error\",\"file\":\".github/workflows/ci.yml\",\"line\":10,\"message\":\"Untrusted GitHub context is interpolated directly into a shell script.\",\"suggestion\":\"Pass event fields through step env and use quoted shell variables.\"}],\"summary\":{\"error\":1,\"warn\":1,\"info\":0},\"filesScanned\":1}",
            "type": "text"
          }
        ],
        "isError": false,
        "structuredContent": {
          "filesScanned": 1,
          "findings": [
            {
              "file": ".github/workflows/ci.yml",
              "line": 9,
              "message": "External action or reusable workflow is not pinned to an immutable digest.",
              "ruleId": "workflow/unpinned-action",
              "severity": "warn",
              "suggestion": "Pin actions to a full 40-character commit SHA and containers to a sha256 digest."
            },
            {
              "file": ".github/workflows/ci.yml",
              "line": 10,
              "message": "Untrusted GitHub context is interpolated directly into a shell script.",
              "ruleId": "workflow/script-injection",
              "severity": "error",
              "suggestion": "Pass event fields through step env and use quoted shell variables."
            }
          ],
          "summary": {
            "error": 1,
            "info": 0,
            "warn": 1
          },
          "version": "0.2.0"
        }
      },
      "tool_result_checked": true,
      "tool_schema_bytes": 2355,
      "tools": [
        "scan_repo",
        "check_env_drift",
        "audit_github_workflows",
        "check_secret_leaks"
      ],
      "working": true
    },
    "evidence_strength": "readme_checked",
    "example_checks": [
      {
        "claim": "Repository development check runs typecheck, tests and build",
        "command": "npm run check",
        "deferred": false,
        "evidence": "ks\nok 53 - v0.2.0: detects direct secret interpolation and toJSON(secrets) log exfiltration in run blocks\n  ---\n  duration_ms: 0.770257\n  type: 'test'\n  ...\n# Subtest: v0.2.0: audits GitLab CI (.gitlab-ci.yml) for script injection, pwn requests, and unpinned includes/images\nok 54 - v0.2.0: audits GitLab CI (.gitlab-ci.yml) for script injection, pwn requests, and unpinned includes/images\n  ---\n  duration_ms: 2.086947\n  type: 'test'\n  ...\n1..54\n# tests 54\n# suites 0\n# pass 54\n# fail 0\n# cancelled 0\n# skipped 0\n# todo 0\n# duration_ms 17322.349656\n\n> ci-guard-mcp@0.2.0 build\n> tsc -p tsconfig.json",
        "expected": "all 54 tests pass",
        "input": "npm run check",
        "kind": "example",
        "outcome": "command completed successfully",
        "returncode": 0,
        "source": "README.md Development and release",
        "verdict": "yes"
      },
      {
        "claim": "Scan the checkout with a warn threshold",
        "command": "node dist/cli.js scan . --fail-on warn",
        "deferred": false,
        "evidence": "50 files scanned \u00b7 0 errors \u00b7 0 warnings \u00b7 0 informational",
        "expected": "0 errors, exit 0",
        "input": "node dist/cli.js scan . --fail-on warn",
        "kind": "example",
        "outcome": "command completed successfully",
        "returncode": 0,
        "source": "README.md Development and release",
        "verdict": "yes"
      }
    ],
    "status": "PASS"
  },
  "diagnosis": null
}
