Files
Claude-Code-Workflow/.claude/skills/investigate/specs/debug-report-format.md
catlog22 67ff3fe339 feat: add investigate, security-audit, ship skills (Claude + Codex)
- Add 3 new Claude skills: investigate (Iron Law debugging), security-audit
  (OWASP Top 10 + STRIDE), ship (gated release pipeline)
- Port all 3 skills to Codex v4 format under .codex/skills/ using
  Deep Interaction pattern (spawn_agent + assign_task phase transitions)
- Update README/README_CN acknowledgments: credit gstack
  (https://github.com/garrytan/gstack) as inspiration source

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 10:31:13 +08:00

6.7 KiB

Debug Report Format

Defines the structured JSON schema for debug reports generated by the investigate skill.

When to Use

Phase Usage Section
Phase 5 Generate final report Full schema
Phase 3 (escalation) Diagnostic dump includes partial report Partial schema

JSON Schema

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Debug Report",
  "type": "object",
  "required": [
    "bug_description",
    "reproduction_steps",
    "root_cause",
    "evidence_chain",
    "fix_description",
    "files_changed",
    "tests_added",
    "regression_check_result",
    "completion_status"
  ],
  "properties": {
    "bug_description": {
      "type": "string",
      "description": "Concise description of the bug symptom",
      "minLength": 10
    },
    "reproduction_steps": {
      "type": "array",
      "description": "Ordered steps to reproduce the bug",
      "items": { "type": "string" },
      "minItems": 1
    },
    "root_cause": {
      "type": "string",
      "description": "Confirmed root cause with technical detail",
      "minLength": 20
    },
    "evidence_chain": {
      "type": "array",
      "description": "Ordered evidence from Phase 1 through Phase 3, each prefixed with phase number",
      "items": { "type": "string" },
      "minItems": 1
    },
    "fix_description": {
      "type": "string",
      "description": "What was changed and why",
      "minLength": 10
    },
    "files_changed": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["path", "change_type", "description"],
        "properties": {
          "path": {
            "type": "string",
            "description": "Relative file path"
          },
          "change_type": {
            "type": "string",
            "enum": ["add", "modify", "remove"]
          },
          "description": {
            "type": "string",
            "description": "Brief description of changes to this file"
          }
        }
      }
    },
    "tests_added": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["file", "test_name", "type"],
        "properties": {
          "file": {
            "type": "string",
            "description": "Test file path"
          },
          "test_name": {
            "type": "string",
            "description": "Name of the test function or describe block"
          },
          "type": {
            "type": "string",
            "enum": ["regression", "unit", "integration"],
            "description": "Type of test added"
          }
        }
      }
    },
    "regression_check_result": {
      "type": "object",
      "required": ["passed", "total_tests"],
      "properties": {
        "passed": {
          "type": "boolean",
          "description": "Whether the full test suite passed"
        },
        "total_tests": {
          "type": "integer",
          "description": "Total number of tests executed"
        },
        "new_failures": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Tests that failed after the fix but passed before"
        },
        "pre_existing_failures": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Tests that were already failing before the investigation"
        }
      }
    },
    "completion_status": {
      "type": "string",
      "enum": ["DONE", "DONE_WITH_CONCERNS", "BLOCKED"],
      "description": "Final status per Completion Status Protocol"
    },
    "concerns": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "description": { "type": "string" },
          "impact": { "type": "string", "enum": ["low", "medium"] },
          "suggested_action": { "type": "string" }
        }
      },
      "description": "Non-blocking concerns (populated when status is DONE_WITH_CONCERNS)"
    },
    "timestamp": {
      "type": "string",
      "format": "date-time",
      "description": "ISO-8601 timestamp of report generation"
    },
    "investigation_duration_phases": {
      "type": "integer",
      "description": "Number of phases completed (1-5)",
      "minimum": 1,
      "maximum": 5
    }
  }
}

Field Descriptions

Field Source Phase Description
bug_description Phase 1 User-reported symptom, one sentence
reproduction_steps Phase 1 Ordered steps to trigger the bug
root_cause Phase 3 Confirmed cause with file:line reference
evidence_chain Phase 1-3 Each item prefixed with "Phase N:"
fix_description Phase 4 What code was changed and why
files_changed Phase 4 Each file with change type and description
tests_added Phase 4 Regression tests covering the bug
regression_check_result Phase 5 Full test suite results
completion_status Phase 5 Final status per protocol
concerns Phase 5 Non-blocking issues (if any)
timestamp Phase 5 When report was generated
investigation_duration_phases Phase 5 How many phases were completed

Example Report

{
  "bug_description": "API returns 500 when user profile has null display_name",
  "reproduction_steps": [
    "Create user account without setting display_name",
    "Call GET /api/users/:id/profile",
    "Observe 500 Internal Server Error"
  ],
  "root_cause": "ProfileSerializer.format() calls displayName.trim() without null check at src/serializers/profile.ts:42",
  "evidence_chain": [
    "Phase 1: TypeError: Cannot read properties of null (reading 'trim') in server logs",
    "Phase 2: Same pattern in 2 other serializers (address.ts:28, company.ts:35)",
    "Phase 3: H1 confirmed — displayName field is nullable in DB but serializer assumes non-null"
  ],
  "fix_description": "Added null-safe access for displayName in ProfileSerializer.format()",
  "files_changed": [
    {
      "path": "src/serializers/profile.ts",
      "change_type": "modify",
      "description": "Added optional chaining for displayName.trim() call"
    }
  ],
  "tests_added": [
    {
      "file": "src/serializers/__tests__/profile.test.ts",
      "test_name": "should handle null display_name without error",
      "type": "regression"
    }
  ],
  "regression_check_result": {
    "passed": true,
    "total_tests": 142,
    "new_failures": [],
    "pre_existing_failures": []
  },
  "completion_status": "DONE",
  "concerns": [],
  "timestamp": "2026-03-29T15:30:00+08:00",
  "investigation_duration_phases": 5
}

Output Location

Reports are written to: .workflow/.debug/debug-report-{YYYY-MM-DD}-{slug}.json

Where:

  • {YYYY-MM-DD} is the investigation date
  • {slug} is derived from the bug description (lowercase, hyphens, max 40 chars)