Claude Code Mastery

AI-Augmented Software Engineering · 7-Week Program

7 Weeks 14 Sessions Analytics Vidhya

Week 1 — Foundations

Getting started with Claude Code: setup, mental models, and deep codebase investigation.

Session 1

Foundations of Claude Code

29 March 2025

  • Installation & environment setup
  • First prompts and basic workflows
  • Understanding the Claude Code interface
  • CLAUDE.md configuration
Session 2

Claude Code Mental Models & Deep Investigation

4 April 2025

  • How Claude Code reads and understands codebases
  • Effective investigation strategies
  • Dependency mapping and architecture analysis
  • Bug hunting with AI assistance

Hono Codebase Detective

Mini Project 1 — Week 1 Capstone

honojs/hono v4.12.9 • 184 modules • 470 dependencies

#1 Architecture Diagram

Hono's layered module architecture. Dependencies flow downward — no circular imports exist.

flowchart TB
    subgraph Layer1["Layer 1 — Utilities"]
        u1["utils/url.ts"]
        u2["utils/html.ts"]
        u3["utils/cookie.ts"]
        u4["utils/jwt"]
        u5["utils/encode.ts"]
        u6["utils/body.ts"]
    end
    subgraph Layer2["Layer 2 — Routers"]
        r1["router.ts"]
        r2["RegExpRouter"]
        r3["TrieRouter"]
        r4["SmartRouter"]
        r5["LinearRouter"]
        r6["PatternRouter"]
    end
    subgraph Layer3["Layer 3 — Core"]
        c1["types.ts"]
        c2["request.ts"]
        c3["context.ts"]
        c4["http-exception.ts"]
    end
    subgraph Layer4["Layer 4 — Engine"]
        e1["compose.ts"]
        e2["hono-base.ts"]
        e3["hono.ts"]
    end
    subgraph Layer5["Layer 5 — Helpers"]
        h1["cookie"]
        h2["html"]
        h3["streaming"]
        h4["ssg"]
        h5["websocket"]
        h6["conninfo"]
    end
    subgraph Layer6["Layer 6 — Middleware"]
        m1["jwt"]
        m2["cors"]
        m3["csrf"]
        m4["logger"]
        m5["basic-auth"]
        m6["bearer-auth"]
        m7["compress"]
        m8["secure-headers"]
    end
    subgraph Layer7["Layer 7 — Adapters"]
        a1["Bun"]
        a2["Deno"]
        a3["CF Workers"]
        a4["AWS Lambda"]
        a5["Vercel"]
        a6["Netlify"]
    end
    subgraph Layer8["Layer 8 — Client"]
        cl1["client.ts"]
    end
    Layer1 --> Layer2
    Layer1 --> Layer3
    Layer2 --> Layer4
    Layer3 --> Layer4
    Layer4 --> Layer5
    Layer4 --> Layer6
    Layer5 --> Layer6
    Layer4 --> Layer7
    Layer5 --> Layer7
    Layer4 --> Layer8
    style Layer1 fill:#8d99ae,color:#fff
    style Layer2 fill:#ff9f1c,color:#fff
    style Layer3 fill:#4361ee,color:#fff
    style Layer4 fill:#4361ee,color:#fff
    style Layer5 fill:#f15bb5,color:#fff
    style Layer6 fill:#2ec4b6,color:#fff
    style Layer7 fill:#9b5de5,color:#fff
    style Layer8 fill:#fee440,color:#000
    

#2 Request Lifecycle

How a GET request flows through Hono: client → adapter → router → middleware → handler → response.

sequenceDiagram
    participant Client
    participant Adapter as Platform Adapter
    participant Hono as Hono / HonoBase
    participant Router as SmartRouter
    participant Compose as compose.ts
    participant MW as Middleware Stack
    participant Handler as Route Handler
    participant Ctx as Context
    Client->>Adapter: HTTP GET /api/users
    Adapter->>Hono: fetch(request, env)
    Hono->>Ctx: new Context(req, env)
    Hono->>Router: router.match(GET, /api/users)
    alt RegExpRouter handles pattern
        Router-->>Hono: [[handler, paramIndexMap], paramStash]
    else Fallback
        Router->>Router: TrieRouter.match()
        Router-->>Hono: [[handler, params]]
    end
    Hono->>Compose: compose(middleware, onError, onNotFound)
    loop For each middleware
        Compose->>MW: middleware[i](context, next)
        MW->>Compose: await next()
    end
    Compose->>Handler: handler(context)
    Handler->>Ctx: c.json(users)
    loop Unwind middleware stack
        MW->>MW: Post-processing
    end
    Compose-->>Hono: context.res
    alt Error thrown
        alt instanceof Error and onError
            Compose->>Hono: onError(err, context)
        else
            Compose->>Compose: re-throw
        end
    end
    Hono-->>Adapter: Response
    Adapter-->>Client: HTTP 200 JSON
    

#3 Context State Diagram

State transitions of the Context object during request processing.

stateDiagram-v2
    [*] --> Created: new Context(req, env)
    Created --> HeadersSet: c.header()
    Created --> StatusSet: c.status()
    HeadersSet --> HeadersSet: more headers
    HeadersSet --> StatusSet: c.status()
    StatusSet --> HeadersSet: c.header()
    StatusSet --> Finalized: c.json / c.text / c.html
    HeadersSet --> Finalized: c.json / c.text / c.html
    Created --> Finalized: c.json / c.text / c.html
    Created --> Redirected: c.redirect()
    Redirected --> Finalized: 301/302 Response
    Finalized --> ResponseSent: return to adapter
    Created --> ErrorState: throw Error
    Finalized --> ErrorState: post-processing throws
    ErrorState --> ErrorHandled: onError()
    ErrorHandled --> Finalized: overwrites res
    ErrorState --> Unhandled: no onError
    Unhandled --> [*]: propagates
    Created --> NotFound: no route
    NotFound --> Finalized: 404
    ResponseSent --> [*]: delivered
    

#4 Module Dependency Map

Interactive force-directed graph of all 184 modules and 470 import relationships. Drag nodes, zoom, and search.

184 modules · 470 dependencies

Directories

core
middleware
router
utils
adapter
helper
jsx
client

#5 Bug Audit Summary

Findings from AI-assisted source code review of honojs/hono v4.12.9.

#SeverityFileFindingStatus
1MEDIUMcompose.ts:53Error handling only catches Error instances. Non-Error throws bypass onError and propagate uncaught.By Design
2LOWcompose.ts:34next() called multiple times throws generic Error with no middleware context.Confirmed
3MEDIUMsmart-router/SmartRouter silently swallows UnsupportedPathError from RegExpRouter on fallback.By Design
4LOWhono-base.tsDefault errorHandler returns plain text with no request ID for production debugging.Enhancement
5HIGHutils/jwt/JWT implements crypto from scratch via Web Crypto API. Custom crypto carries higher risk.Risk
6MEDIUMmiddleware/jwt/JWT middleware depends on internal custom crypto. Edge cases depend on custom code correctness.Risk
7LOWpackage.jsonHome directory package.json had two concatenated JSON objects (malformed). Broke npm system-wide.Fixed
8LOW.gitignoreOriginally only had node_modules/. Missing .env, dist/, .claude/, *.log.Fixed

Week 2 — Prompt Engineering

Mastering prompt engineering and spec-driven development with Claude Code.

Session 3

Advanced Prompt Engineering

4–7 April 2026

  • YAML prompt libraries with role, task, and output_schema
  • Role-based prompting: spec-writer, architect, reviewer, test-generator
  • Output schema enforcement via JSON Schema
  • Self-critique loops: generate → review → fix cycles
Session 4

Spec-Driven Development

7–11 April 2026

  • Formal specs with SHALL/MUST normative language (RFC 2119)
  • Gherkin scenarios: happy path, error cases, edge cases
  • OpenAPI contracts with endpoint definitions
  • Traceability matrices: requirement → code → test

The Spec-Driven Feature Factory

URL Shortener built spec-first with full requirement traceability

7 FRs • 5 NFRs • 10 Gherkin scenarios • 23 tests passing

#1 Project Overview

Four-part spec-driven development pipeline: prompts → spec → implementation → tests.

Part 1

YAML Prompt Library

  • 4 structured YAML templates: spec-writer, architect, code-reviewer, test-generator
  • Each with role, task, output_schema, tags, and {{ variable }} parameterization
Part 2

Spec & Diagrams

  • Formal spec with 7 FRs, 5 NFRs, 10 Gherkin scenarios
  • OpenAPI 3.0 contract. SHALL/MUST normative language (RFC 2119)
  • 3 Mermaid diagrams: sequence, ER, state
Part 3

Implementation & Self-Critique

  • Hono + TypeScript with REQ-ID traceability comments
  • In-memory store, URL validator, short code generator
  • 2-cycle self-critique loop (security score: 6→9/10)
  • JSON schema-enforced output from Claude
Part 4

Tests & Traceability

  • 23 vitest tests across 5 test files (100% pass)
  • Traceability matrix: REQ → code → test
  • 12-question reflection report with real data
  • Security scan: zero secrets in source

Deliverables Checklist

  • ✓ prompts/ — 4 YAML prompt templates
  • ✓ specs/url-shortener.yaml — full formal specification
  • ✓ specs/diagrams/ — 3 Mermaid diagrams
  • ✓ src/ — Hono/TypeScript implementation with REQ-ID comments
  • ✓ tests/ — auto-generated vitest suite (23 tests)
  • ✓ docs/traceability-matrix.md — requirement → code → test mapping
  • ✓ docs/self-critique-log.md — generate → review → fix cycles
  • ✓ REPORT.md — answers to all 12 questions

#2 Request Flow

URL shortening and redirect flow — POST /shorten and GET /:code lifecycle.

sequenceDiagram
    participant Client
    participant API as Hono API
    participant Validator as URL Validator
    participant Store as Data Store
    participant Analytics as Analytics Recorder

    rect rgb(22, 27, 34)
    Note over Client,Analytics: POST /shorten Flow
    Client->>API: POST /shorten { url, expiresAt? }
    API->>API: Check rate limit (60 req/min per IP)
    alt Rate limit exceeded
        API-->>Client: 429 Too Many Requests + Retry-After
    end
    API->>Validator: Validate URL format, length, scheme
    alt Invalid URL
        Validator-->>API: Validation failed
        API-->>Client: 400 { error: { code: 400, message } }
    end
    Validator->>Validator: Check blocklist
    alt Blocklisted domain
        Validator-->>API: Domain blocked
        API-->>Client: 403 { error: { code: 403, message } }
    end
    API->>Store: Check for existing URL
    alt Duplicate URL
        Store-->>API: Existing record found
        API-->>Client: 409 { existing shortUrl }
    end
    API->>API: Generate unique short code (6-8 chars)
    API->>Store: Save { shortCode, originalUrl, createdAt, expiresAt }
    Store-->>API: Saved
    API-->>Client: 201 { shortUrl, originalUrl, shortCode, createdAt, expiresAt }
    end

    rect rgb(22, 27, 34)
    Note over Client,Analytics: GET /:code Redirect Flow
    Client->>API: GET /:code
    API->>Store: Lookup by shortCode
    alt Not found
        Store-->>API: null
        API-->>Client: 404 { error: { code: 404, message } }
    end
    Store-->>API: URL record
    API->>API: Check expiresAt
    alt Expired
        API-->>Client: 410 { error: { code: 410, message: "URL has expired" } }
    end
    alt Deleted
        API-->>Client: 410 { error: { code: 410, message: "URL has been deleted" } }
    end
    API->>Analytics: Record event { timestamp, referrer, ipHash }
    Analytics-->>API: Recorded
    API-->>Client: 301 Location: originalUrl
    end
        

#3 Data Model

Entity relationships: urls and analytics_events tables.

erDiagram
    urls {
        string id PK "UUID primary key"
        string original_url "Original long URL (max 2048 chars)"
        string short_code UK "Unique 6-8 alphanumeric code"
        datetime created_at "Creation timestamp"
        datetime expires_at "Optional expiration timestamp"
        boolean is_active "false if deleted"
    }

    analytics_events {
        string id PK "UUID primary key"
        string url_id FK "References urls.id"
        datetime accessed_at "Timestamp of the redirect"
        string referrer "HTTP Referer header value"
        string ip_hash "SHA-256 hash of client IP"
    }

    urls ||--o{ analytics_events : "has"
        

#4 URL Lifecycle

URL state transitions: active → expired → deleted.

stateDiagram-v2
    [*] --> Active : POST shorten creates URL
    Active --> Expired : expires_at reached
    Active --> Deleted : DELETE called
    Expired --> Deleted : cleanup or DELETE called
    Deleted --> [*]
        

#5 Traceability Matrix

Requirement → code → test → status mapping for all REQ-SHORT requirements.

REQ-IDDescriptionCode FileTest FileStatus
REQ-SHORT-001Shorten valid URL into unique short coderoutes/shorten.ts, lib/shortener.ts, lib/store.tsshorten.test.tsPASS
REQ-SHORT-002Redirect short URL to originalroutes/redirect.tsredirect.test.tsPASS
REQ-SHORT-003Track analytics per redirectroutes/redirect.ts, routes/analytics.ts, lib/store.tsanalytics.test.ts, redirect.test.tsPASS
REQ-SHORT-004Optional URL expiration (410 on expired)routes/shorten.ts, routes/redirect.tsexpiry.test.ts, redirect.test.tsPASS
REQ-SHORT-005Input validation, blocklist, duplicateslib/validator.ts, routes/shorten.tsvalidator.test.ts, shorten.test.tsPASS
REQ-SHORT-006Delete short URL (soft delete)routes/delete.ts—PARTIAL
REQ-SHORT-007Consistent error response enveloperoutes/*.ts, index.tsshorten.test.tsPASS

Total: 7 requirements • Fully covered: 6 • Partially covered: 1 • Not covered: 0

Week 3 — AI-Augmented SDLC & Governance

Building a governed AI-augmented development pipeline: slash commands, governance hooks, audit logging, and measured ROI.

Session 5

AI-Augmented SDLC

12 April 2026

  • Workflow mapping with Mermaid flowcharts
  • Automation Leverage Framework scoring
  • Custom slash commands and /ship pipelines
  • CLAUDE.md as team conventions contract
Session 6

Hooks, Governance & Logging

18 April 2026

  • PreToolUse hooks for bash, secrets, file scope
  • PostToolUse audit logging to JSONL
  • UserPromptSubmit and Stop hooks
  • Permission modes and settings.json hierarchy

The Governed AI Pipeline

A drop-in .claude/ governance layer with measured ROI

5 slash commands • 6 hooks • 4-part pipeline • 10-person team ROI

#1 Project Overview

Four-part governance pipeline: workflow analysis → slash commands → safety hooks → measured ROI.

Part 1

Workflow Mapping

  • Mermaid flowchart of ticket-to-deploy lifecycle
  • 12-step annotations with time, tools, and pain points
  • Automation Leverage Framework with ROI scoring
Part 2

Slash Command Pipeline

  • 5 custom commands: /review, /test-gen, /commit, /ship, /onboard
  • /ship chains the full pipeline into a single invocation
  • PR creation via gh CLI with structured templates
Part 3

Governance & Safety

  • 3 PreToolUse hooks: bash validator, secret scanner, scope guard
  • PostToolUse audit logging to JSONL
  • Prompt logging, session summaries, cost tracking
Part 4

Measurement & ROI

  • Baseline manual workflow vs /ship pipeline comparison
  • Before/after metrics with real task (REQ-SHORT-006)
  • Annual savings projection for 10-person team at $150/hr

Deliverables Checklist

  • ✓ .claude/commands/ — 5 slash commands
  • ✓ .claude/hooks/ — 6 hooks (3 validation + 3 logging)
  • ✓ .claude/settings.json — permissions, hooks, cost limits
  • ✓ .claude/audit/ — sample logs with 3 blocks + coverage
  • ✓ CLAUDE.md — workflow rules, conventions, cost policy
  • ✓ docs/workflow-map.md — Mermaid + annotations
  • ✓ docs/leverage-analysis.md — scoring + top 3 targets
  • ✓ docs/roi-report.md — before/after + annual projection
  • ✓ docs/governance-playbook.md — 6-week rollout
  • ✓ REPORT.md — answers to all 12 rubric questions

#2 /ship Pipeline Flow

Four-stage pipeline with hard gates — any stage failure aborts the entire run.

flowchart LR
    subgraph invoke["Developer invokes /ship"]
        A["Stage 1\n/review"]
    end

    A -->|PASS| B["Stage 2\n/test-gen"]
    A -->|"FAIL\n(error findings)"| X1["Pipeline\nAborted"]

    B -->|PASS| C["Stage 3\n/commit"]
    B -->|"FAIL\n(tests fail)"| X2["Pipeline\nAborted"]

    C -->|SUCCESS| D["Stage 4\ngh pr create"]
    C -->|"FAIL\n(hook block)"| X3["Pipeline\nAborted"]

    D --> E["PR Created\nwith review findings\n+ coverage data\n+ governance metadata"]

    style A fill:#58a6ff,color:#fff,stroke:#1f6feb
    style B fill:#bc8cff,color:#fff,stroke:#8b5cf6
    style C fill:#f778ba,color:#fff,stroke:#db61a2
    style D fill:#3fb950,color:#fff,stroke:#238636
    style E fill:#238636,color:#fff,stroke:#196c2e
    style X1 fill:#da3633,color:#fff,stroke:#b62324
    style X2 fill:#da3633,color:#fff,stroke:#b62324
    style X3 fill:#da3633,color:#fff,stroke:#b62324
        

#3 Hook Lifecycle

PreToolUse hooks run before execution (prevention), PostToolUse hooks run after (logging).

sequenceDiagram
    participant Dev as Developer
    participant CC as Claude Code
    participant Pre as PreToolUse Hooks
    participant Tool as Tool Execution
    participant Post as PostToolUse Hooks
    participant Audit as Audit Logs

    Dev->>CC: Prompt (e.g. "delete /tmp/test")

    rect rgb(22, 27, 34)
    Note over CC,Pre: PreToolUse Phase
    CC->>Pre: validate-bash.py
    alt Command is dangerous
        Pre-->>CC: exit 1 + stderr BLOCKED
        Pre->>Audit: Append to blocked.log
        CC-->>Dev: BLOCKED: rm -rf
    else Command is safe
        Pre-->>CC: exit 0 (allow)
    end
    end

    rect rgb(22, 27, 34)
    Note over CC,Tool: Tool Execution
    CC->>Tool: Execute command
    Tool-->>CC: Result
    end

    rect rgb(22, 27, 34)
    Note over CC,Post: PostToolUse Phase
    CC->>Post: audit-log.sh
    Post->>Audit: Append JSONL to audit.jsonl
    Post-->>CC: exit 0
    end

    CC-->>Dev: Result
        

#4 Settings Hierarchy

Four-tier override chain — Enterprise policies cannot be weakened by lower tiers.

flowchart TD
    E["Enterprise\nsettings.json\n(org-wide, admin-managed)"]
    P["Project\n.claude/settings.json\n(checked into repo)"]
    U["User\n~/.claude/settings.json\n(personal preferences)"]
    L["Local\n.claude/settings.local.json\n(gitignored)"]

    E -->|overrides| P
    P -->|overrides| U
    U -->|overrides| L

    style E fill:#da3633,color:#fff,stroke:#b62324
    style P fill:#58a6ff,color:#fff,stroke:#1f6feb
    style U fill:#bc8cff,color:#fff,stroke:#8b5cf6
    style L fill:#484f58,color:#fff,stroke:#30363d
        

#5 Audit Data Flow

Every action flows through hooks into JSONL logs, queryable with jq for compliance.

flowchart LR
    A1["Tool Actions\n(Bash, Edit, Write)"]
    A2["User Prompts"]
    A3["Session End"]
    A4["Blocked Actions"]

    H1["audit-log.sh"]
    H2["prompt-log.sh"]
    H3["session-summary.sh"]
    H4["PreToolUse hooks"]

    S1["audit.jsonl"]
    S2["prompts.jsonl"]
    S3["costs.jsonl"]
    S4["blocked.log"]

    R["Compliance Report"]

    A1 --> H1 --> S1
    A2 --> H2 --> S2
    A3 --> H3 --> S3
    A4 --> H4 --> S4

    S1 --> R
    S2 --> R
    S3 --> R
    S4 --> R

    style A1 fill:#58a6ff,color:#fff,stroke:#1f6feb
    style A2 fill:#bc8cff,color:#fff,stroke:#8b5cf6
    style A3 fill:#f778ba,color:#fff,stroke:#db61a2
    style A4 fill:#da3633,color:#fff,stroke:#b62324
    style S1 fill:#161b22,color:#e6edf3,stroke:#30363d
    style S2 fill:#161b22,color:#e6edf3,stroke:#30363d
    style S3 fill:#161b22,color:#e6edf3,stroke:#30363d
    style S4 fill:#161b22,color:#e6edf3,stroke:#30363d
    style R fill:#3fb950,color:#fff,stroke:#238636
        

Week 4 — MCP Engineering Intelligence

Connecting Claude Code to live business data via MCP — a real engineering operations tool with audit logging, governed tool calls, and chained workflows.

Session 7

Building MCP Workflows

19 April 2026

  • MCP server connections (GitHub, PostgreSQL)
  • Audit logging architecture
  • Tool wrapper patterns and error handling
  • Morning Brief workflow (WF-01)
Session 8

Chained MCP Workflows + Production Patterns

25 April 2026

  • Multi-tool sequential workflows
  • JSON schema enforcement on Claude output
  • Graceful degradation strategies
  • Incident Triage workflow (WF-02)

MCP Engineering Intelligence Platform

Claude Code wired to live business data via MCP — answers ops questions in under 60 seconds

4 MCP servers • 2 workflows • audit-logged • 60-second answers

#1 Project Overview

Five-task build: an audit logger underpins typed GitHub MCP wrappers, two chained workflows, and the documentation/test layer that ties governance back to the code.

Task 1

Audit Logger

  • JSONL log with SHA-256-hashed inputs
  • 6-field schema: timestamp, workflow, tool, input_hash, status, duration_ms
  • Never crashes the workflow — warn to stderr and continue
Task 2

GitHub MCP Tools

  • Three typed wrappers: PRs, issues, commits
  • Every call audit-logged with timing
  • Never raises — returns empty list on error
Task 3

Morning Brief (WF-01)

  • Daily standup digest chaining 3 MCP calls
  • Markdown with 4 fixed sections
  • Empty-source policy for missing data
Task 4

Incident Triage (WF-02)

  • Live-incident JSON triage chaining 4 MCP calls
  • Strict 7-key schema enforced on Claude output
  • Degraded-mode fallback when calls fail
Task 5

Documentation + Tests

  • CLAUDE.md (5 sections + 2 custom rules)
  • ANSWERS.md — 8 questions answered
  • 3 mocked integration tests, governance mapping

Deliverables Checklist

  • ✓ fintrack-mcp-intel/ — Analytics Vidhya scaffold
  • ✓ mcp/audit.py — AuditLogger with JSONL + SHA-256
  • ✓ mcp/github_tools.py — 3 typed wrappers
  • ✓ workflows/morning_brief.py + prompt — 4-section output
  • ✓ workflows/incident_triage.py + prompt — strict JSON
  • ✓ CLAUDE.md — system docs (5 sections + 2 custom rules)
  • ✓ ANSWERS.md — 8 questions answered
  • ✓ tests/test_workflows.py — 3 integration tests
  • ✓ All starter pytest suites passing
  • ✓ REPORT.md — reflection covering 8 governance principles

#2 Architecture Overview

CLI → BaseWorkflow.run → the two workflows → tool wrappers → MCPClient. Every tool call is timed and audit-logged before returning to the workflow.

flowchart TD
    CLI["main.py CLI
--workflow ..."] --> BW[BaseWorkflow.run] BW --> WF1["MorningBriefWorkflow
WF-01"] BW --> WF2["IncidentTriageWorkflow
WF-02"] WF1 --> GT[github_tools wrappers] WF1 --> DT["db_tools
(lab stub)"] WF2 --> GT WF2 --> DT GT -->|mcp.call| MCP[MCPClient] MCP -->|mcp_servers| GH[(GitHub MCP)] MCP -->|mcp_servers| PG[(PostgreSQL MCP)] GT --> AL[AuditLogger] AL --> LOG[("~/.fintrack/audit.log
JSONL")] style CLI fill:#58a6ff,color:#fff,stroke:#1f6feb style BW fill:#bc8cff,color:#fff,stroke:#8b5cf6 style WF1 fill:#f778ba,color:#fff,stroke:#db61a2 style WF2 fill:#f778ba,color:#fff,stroke:#db61a2 style GT fill:#3fb950,color:#fff,stroke:#238636 style DT fill:#484f58,color:#fff,stroke:#30363d style MCP fill:#bc8cff,color:#fff,stroke:#8b5cf6 style GH fill:#161b22,color:#e6edf3,stroke:#30363d style PG fill:#161b22,color:#e6edf3,stroke:#30363d style AL fill:#238636,color:#fff,stroke:#196c2e style LOG fill:#161b22,color:#e6edf3,stroke:#30363d

#3 WF-01 Morning Brief — Call Sequence

Three MCP calls chained, each audit-logged, then Claude synthesises a four-section markdown report. Empty data sources fall through to "No data returned from <source>".

sequenceDiagram
    participant Eng as Engineer
    participant CLI as main.py
    participant WF as MorningBriefWorkflow
    participant GT as github_tools
    participant DT as db_tools
    participant MCP as MCPClient
    participant GH as GitHub MCP
    participant AL as AuditLogger
    participant Claude as Claude (mcp.ask)

    Eng->>CLI: --workflow morning-brief
    CLI->>WF: execute()

    rect rgb(22, 27, 34)
    Note over WF,AL: Tool call 1 of 3
    WF->>GT: get_open_prs(repo)
    GT->>MCP: mcp.call("github_pull_requests")
    MCP->>GH: tool call
    GH-->>MCP: PRs JSON
    MCP-->>GT: result
    GT->>AL: log(success, duration_ms)
    GT-->>WF: filtered PRs
    end

    rect rgb(22, 27, 34)
    Note over WF,AL: Tool call 2 of 3
    WF->>GT: get_priority_issues(repo)
    GT->>MCP: mcp.call("github_issues")
    MCP->>GH: tool call
    GH-->>MCP: issues JSON
    MCP-->>GT: result
    GT->>AL: log(success, duration_ms)
    GT-->>WF: P0/P1 issues
    end

    rect rgb(22, 27, 34)
    Note over WF,AL: Tool call 3 of 3
    WF->>DT: get_overnight_alerts()
    DT-->>WF: alerts list
    end

    WF->>Claude: ask(prompt + 3 data sets)
    Claude-->>WF: 4-section markdown
    WF-->>CLI: result
    CLI-->>Eng: morning brief
        

#4 WF-02 Incident Triage — Call Sequence + Degraded Fallback

Four MCP calls in their own try/except so one failure cannot abort the workflow. Strict JSON parsing on Claude's response with a seven-key schema check; any parse or schema failure returns ESCALATE_FALLBACK.

sequenceDiagram
    participant Eng as On-call
    participant WF as IncidentTriageWorkflow
    participant DT as db_tools
    participant GT as github_tools
    participant Claude as Claude

    Eng->>WF: execute(service="payments")

    rect rgb(22, 27, 34)
    Note over WF,GT: Per-call try/except — graceful degradation
    WF->>DT: get_error_rate(window=30)
    DT-->>WF: 30-min baseline (or {} on error)
    WF->>GT: search_recent_commits(hours=4)
    GT-->>WF: commits (or [] on error)
    WF->>GT: get_priority_issues(labels=["bug",svc])
    GT-->>WF: bugs (or [] on error)
    WF->>DT: get_error_rate(window=5)
    DT-->>WF: 5-min snapshot (or {} on error)
    end

    WF->>Claude: ask(prompt with 5 placeholders)
    Claude-->>WF: response (raw)

    alt Valid JSON + 7 required keys present
        WF-->>Eng: IncidentReport with escalate flag
    else Invalid JSON or missing key
        WF-->>Eng: ESCALATE_FALLBACK (escalate=true)
    end
        

#5 Audit Log Lifecycle

Per-call timing, SHA-256 input hashing, append-only JSONL, never raises. Six fields per entry: timestamp, workflow, tool, input_hash, status, duration_ms.

flowchart LR
    A["github_tools call
e.g. get_open_prs()"] A --> S["start =
perf_counter()"] S --> CALL["mcp.call(tool, input)"] CALL -->|success| H1["SHA-256 of
sorted-key JSON input"] CALL -->|exception| H2["SHA-256 of input
(same hashing)"] H1 --> E1["Build entry
status=success"] H2 --> E2["Build entry
status=error"] E1 --> WRITE["Append JSONL line
~/.fintrack/audit.log"] E2 --> WRITE WRITE -->|OK| OUT["return result / []"] WRITE -->|OSError, ValueError, TypeError| STDERR["print warning
to stderr
NEVER raise"] STDERR --> OUT style A fill:#58a6ff,color:#fff,stroke:#1f6feb style S fill:#484f58,color:#fff,stroke:#30363d style CALL fill:#bc8cff,color:#fff,stroke:#8b5cf6 style H1 fill:#3fb950,color:#fff,stroke:#238636 style H2 fill:#da3633,color:#fff,stroke:#b62324 style E1 fill:#3fb950,color:#fff,stroke:#238636 style E2 fill:#da3633,color:#fff,stroke:#b62324 style WRITE fill:#238636,color:#fff,stroke:#196c2e style STDERR fill:#da3633,color:#fff,stroke:#b62324 style OUT fill:#161b22,color:#e6edf3,stroke:#30363d

#6 MCP Server Registry & Permission Tiers

Read-only is the default tier. Write access requires a separate registry entry, manager sign-off, and elevated audit retention — per Architecture Rule 4 in fintrack-mcp-intel/CLAUDE.md.

flowchart TD
    REGISTRY["Approved Server Registry
fintrack-mcp-intel/CLAUDE.md Section 2"] subgraph readonly["READ-ONLY TIER (default)"] GH["github-mcp
issues:read · pull_requests:read
contents:read · metadata:read"] PG["pg-mcp
role: readonly
analytics replica"] JIRA["jira-mcp (placeholder)
issues:read · sprints:read"] end subgraph writetier["WRITE TIER (gated)"] SLACK["slack-mcp (placeholder)
post to single channel only
requires manager sign-off
elevated audit retention"] end GATE{{"Architecture Rule 4
read-only by default
write requires sign-off"}} REGISTRY --> readonly REGISTRY --> writetier writetier -.->|enforced by| GATE style readonly fill:#0d1117,color:#e6edf3,stroke:#3fb950 style writetier fill:#0d1117,color:#e6edf3,stroke:#da3633 style GH fill:#3fb950,color:#fff,stroke:#238636 style PG fill:#3fb950,color:#fff,stroke:#238636 style JIRA fill:#484f58,color:#fff,stroke:#30363d style SLACK fill:#da3633,color:#fff,stroke:#b62324 style REGISTRY fill:#58a6ff,color:#fff,stroke:#1f6feb style GATE fill:#bc8cff,color:#fff,stroke:#8b5cf6

Week 5 — Multi-Agent Pipelines & Skills

Building a 2-agent code-review pipeline on a Python e-commerce backend, then packaging both agent prompts as versioned, parameterised Skills.

Session 9

Multi-Agent Collaboration

26 April 2025

  • Agent role design and scope boundaries
  • Sequential agent pipelines (Architect → Security)
  • Structured agent inputs and outputs
  • Fallback strategies for corrupted input
Session 10

Skills & Plugin Architecture

2 May 2025

  • SKILL.md 5-part structure
  • Parameterisation with {{VARIABLE}} placeholders
  • Versioning and changelog discipline
  • Skill libraries and discoverability

Multi-Agent Pipeline & Skills Library

Two specialised review agents and two production Skills built on a deliberately-flawed e-commerce backend

2 agents • 2 Skills • OrderFlow sample • self-reviewed

#1 Project Overview

Five-part build: an Architect agent and Security agent run in separate sessions, then both prompts are packaged as parameterised Skills with examples, tests, and a 100-point self-review.

Part 1A

Architect Agent

  • Senior architect role · scope-locked to one module
  • Outputs structured design.md (4 sections + summary)
  • Explicit exclusions: no security, no tests, no refactors
Part 1B

Security Agent

  • OWASP Top 10 specialist · JSON findings only
  • Severity-ordered, file:line-anchored findings
  • Explicit exclusions to prevent overlap with Architect
Part 2A

Skill Packaging

  • 5-part SKILL.md with Limitations + Tests + Changelog
  • Parameterised with {{SCOPE}} / {{CONTEXT}} / {{TARGET}}
  • Versioned at v1.0.0
Part 2B

Skill Testing

  • 3 runs each · typical / edge / minimal
  • Concrete example outputs saved alongside each Skill
  • Prompts hardened from observed test gaps
Part 2C

Library Index + Self-Review

  • Updated skills/README.md index for discoverability
  • 100-point self-review against REVIEW_TEMPLATE.md
  • Iteration notes for any sub-100 score

Deliverables Checklist

  • ✓ orderflow-sample/ — sanitized Analytics Vidhya scaffold
  • ✓ agent_architect_prompt.txt — 5-part Architect prompt
  • ✓ design.md — Architect Agent output (4 sections)
  • ✓ agent_second_prompt.txt — 5-part Security prompt
  • ✓ findings.json — Security Agent output (JSON)
  • ✓ fallback_notes.txt — corrupted-input observation
  • ✓ skills/architecture-review/SKILL.md — v1.0.0
  • ✓ skills/security-audit/SKILL.md — v1.0.0
  • ✓ skills/README.md — index updated with both Skills
  • ✓ REPORT.md + self-review against REVIEW_TEMPLATE rubric

#2 Pipeline Flow

Two agents in two separate Claude Code sessions. CLAUDE.md and the target source feed both; design.md is the only hand-off contract from Architect to Security; each agent's prompt is then frozen as a v1.0.0 Skill.

flowchart TD
    IN1[CLAUDE.md] --> A1[Architect Agent
Session A] IN2[processor.py] --> A1 A1 --> D[design.md] IN1 --> A2[Security Agent
Session B] IN2 --> A2 D --> A2 A2 --> F[findings.json] A1 -.packaged as.-> S1[Skill: architecture-review v1.0.0] A2 -.packaged as.-> S2[Skill: security-audit v1.0.0] S1 --> LIB[(skills/
library)] S2 --> LIB

#3 Architect Agent — Call & Output

Senior architect role, scope-locked to one module, with five DO-NOT exclusions to keep it out of security / tests / refactors. Output is a four-section markdown design doc plus a 2-sentence summary.

sequenceDiagram
    participant Caller
    participant Architect as Architect Agent
(Session A) Caller->>Architect: ROLE + SCOPE + EXCLUSIONS
+ INPUT (CLAUDE.md, processor.py)
+ OUTPUT FORMAT Note over Architect: stays in lane:
no security
no tests
no refactors Architect->>Architect: analyze boundary
+ API surface
+ data flow
+ dependencies Architect-->>Caller: design.md
(4 sections + SUMMARY)

#4 Security Agent — Call & Output

OWASP Top 10 (2021) specialist. Receives design.md as read-only context; produces ONLY a JSON object with severity-ordered, file:line-anchored findings. No prose preamble, no schema drift.

sequenceDiagram
    participant Caller
    participant Security as Security Agent
(Session B) Caller->>Security: ROLE + SCOPE + EXCLUSIONS
+ INPUT (CLAUDE.md, design.md, processor.py)
+ OUTPUT FORMAT (JSON schema) Note over Security: design.md is
context only
(do not critique) Security->>Security: each finding =
file:line + severity
+ OWASP category
+ impact + recommendation Security-->>Caller: findings.json
(12 findings, severity-ordered)

#5 Skill Library Structure

skills/README.md is the index; each Skill has a SKILL.md with full 5-part structure plus Limitations, Tests, Changelog; each Skill ships an examples/ folder with typical / edge / minimal outputs.

flowchart LR
    R[skills/README.md
Skill Index] R --> AR[architecture-review/
SKILL.md v1.0.0] R --> SA[security-audit/
SKILL.md v1.0.0] AR --> AREX[examples/
typical.md / edge.md / minimal.md] SA --> SAEX[examples/
typical.json / edge.json / minimal.json]

Week 6 — Ship It: CI/CD & Docker

Building a complete CI/CD pipeline for HealthTrack: GitHub Actions with lint, test, coverage, security, and AI-Skill review jobs; a multi-stage production Dockerfile with non-root user and HEALTHCHECK; and a docker-compose stack with api, postgres, and redis health-checked.

Session 11

GitHub Workflows & PR Automation

3 May 2026

  • GitHub Actions workflow YAML structure
  • Multi-job pipelines with needs: dependency ordering
  • Coverage thresholds, secret references, job summaries
  • PR templates and CI as a quality gate
Session 12

Docker & Deployment

9 May 2026

  • Multi-stage Dockerfile patterns and image-size discipline
  • Non-root containers and HEALTHCHECK semantics
  • docker-compose service composition and health-gated startup
  • Environment variables, .env.example, secret hygiene

Ship It — CI/CD & Docker for HealthTrack

Full GitHub Actions pipeline + multi-stage Dockerfile + 3-service compose stack

4 jobs • multi-stage Dockerfile • 3-service stack • 100-pt rubric

#1 Project Overview

Four-part build for the HealthTrack patient-vitals API: a 4-job GitHub Actions pipeline with an AI-Skill CRITICAL gate, a multi-stage non-root Dockerfile, a 3-service compose stack with health-gated startup, and an end-to-end test that proves a real PR triggers the full pipeline.

Part 1

CI Pipeline

  • 4 jobs: lint → test & security → ai-skills
  • Coverage gate at 80% · pip caching
  • AI-Skill gate blocks merge on CRITICAL findings
Part 2

Dockerfile

  • Multi-stage: builder + slim runtime
  • Non-root user · HEALTHCHECK instruction
  • Python env hardening · minimal layer count
Part 3

docker-compose

  • 3 services: api + postgres + redis
  • Health-gated startup (depends_on: condition: service_healthy)
  • .env.example committed · .env gitignored
Part 4

End-to-End Test

  • Real PR triggers full pipeline on GitHub
  • Evidence: green Actions tab + compose ps + curl /health
  • Proves the gate fires on real CRITICAL findings

Deliverables Checklist

  • ✓ .github/workflows/ci.yml
  • ✓ .github/pull_request_template.md (customised)
  • ✓ Dockerfile (multi-stage)
  • ✓ .dockerignore
  • ✓ docker-compose.yml (3 services)
  • ✓ .env.example (committed)
  • ✓ .env (gitignored)
  • ✓ /health endpoint (with database + cache sub-checks)
  • ✓ SECURITY_FIXTURES.md (teaching-fixture documentation)
  • ✓ REPORT.md (rubric reflection answers)

#2 CI Pipeline Architecture

Four jobs with explicit needs: ordering form a dependency DAG. The AI-Skill job parses the Security Audit Skill output and exits non-zero on any CRITICAL finding, blocking merge. Coverage gate at 80% and CRITICAL gate are independent — either can fail the run.

flowchart LR
    PR([PR opened / push to main]) --> LINT[lint
flake8 + black] LINT --> TEST[test
pytest --cov ≥ 80%] LINT --> SEC[security
bandit + safety] TEST --> AI[ai-skills
Security Audit Skill
on app/vitals.py] SEC --> AI AI -->|no CRITICAL| GREEN([green check
merge ready]) AI -->|CRITICAL found| BLOCK([red X
merge BLOCKED])

#3 Containerisation — Multi-Stage Dockerfile

Stage 1 (python:3.11) installs deps into /install. Stage 2 (python:3.11-slim) copies only that prefix, drops to non-root appuser UID 10001, then runs gunicorn with a urllib HEALTHCHECK. Final image: 236 MB — the builder stage and its build toolchain never reach the registry.

flowchart TB
    subgraph builder[Stage 1: builder — python:3.11]
        direction TB
        B1[Full python:3.11] --> B2[pip install --prefix=/install
-r requirements.txt] end subgraph runtime[Stage 2: runtime — python:3.11-slim] direction TB R1[python:3.11-slim] --> R2[ENV PYTHONDONTWRITEBYTECODE=1
PYTHONUNBUFFERED=1] R2 --> R3[useradd appuser UID 10001] R3 --> R4[COPY /install → /usr/local] R4 --> R5[USER appuser] R5 --> R6[EXPOSE 5000] R6 --> R7[HEALTHCHECK urllib /health] R7 --> R8[CMD gunicorn app:create_app] end B2 -. COPY --from=builder .-> R4

#4 Compose Stack & End-to-End Flow

docker-compose.yml declares api + postgres:15-alpine + redis:7-alpine. api uses depends_on with condition: service_healthy, so it never starts until both backing stores answer their first healthcheck. The sequence below traces a developer push through the CI pipeline to the merge gate.

sequenceDiagram
    participant Dev as Developer
    participant GH as GitHub
    participant CI as ci.yml
    participant Skill as Security Audit Skill
    participant Gate as Merge gate
    Dev->>GH: git push + gh pr create
    GH->>CI: trigger (pull_request)
    CI->>CI: lint
    par
        CI->>CI: test — pytest cov ≥ 80%
    and
        CI->>CI: security — bandit + safety
    end
    CI->>Skill: security-audit --scope app/vitals.py
    Skill-->>CI: JSON findings
    alt no CRITICAL
        CI->>Gate: exit 0
        Gate-->>Dev: green check — merge ready
    else CRITICAL found
        CI->>Gate: exit 1
        Gate-->>Dev: red X — merge BLOCKED
    end
        

#5 Rubric Self-Assessment

100-point rubric mapped to where each item lives in the submission and a self-graded result. validate_ci.py reports “All checks passed” across all 4 parts (Sessions A+B+C). The +10 bonus is split: PR-template customisation lands here; the AI-Skill summary in PR comments lands in Session D once the end-to-end CI run is captured.

#Rubric itemWhere it livesResult
1CI workflow at .github/workflows/ci.yml; triggers on PR + push to mainweek-6/healthtrack-api/.github/workflows/ci.ymlPASS · 15/15
24 jobs with needs: ordering; coverage ≥ 80%; CRITICAL gateci.yml jobs lint → {test, security} → ai-skillsPASS · 25/25
3Multi-stage Dockerfile; non-root; HEALTHCHECK; EXPOSE; Python env varsweek-6/healthtrack-api/DockerfilePASS · 20/20
43-service compose; healthchecks; named volumes; depends_on: condition: service_healthyweek-6/healthtrack-api/docker-compose.ymlPASS · 15/15
5.env.example committed; .env gitignored; no real secrets in git logweek-6/healthtrack-api/.env.example + .gitignorePASS · 10/10
6/health with database + cache sub-checks; 503 on degradationapp/__init__.py /health route + 3 mocked testsPASS · 10/10
7REPORT.md with concrete-evidence reflection answersweek-6/healthtrack-api/REPORT.mdPASS · 5/5
B1PR template — Performance / Migrations / Feature Flags.github/pull_request_template.mdBONUS · +5
B2AI-Skill review summary in PR comments (real CI run)Session D end-to-end testpending Session D

Week 7 — Capstone

Structured capstone project integrating all skills from the program.

Session 13

Structured Capstone Project

9 May 2025

  • Capstone project kickoff and scoping
  • End-to-end project with Claude Code
  • Integration of all learned techniques
  • Final presentations and peer review
Session 14

Capstone Implementation & Deployment

18 May 2026

  • Notification Service API — Python/Flask capstone
  • 7-phase AI-augmented SDLC: spec → code → tests → CI/CD → Docker → governance → measurement
  • REQ-007 stats endpoint + 3 test suites + 2 ADRs + pre-commit hook
  • See CAPSTONE_PLAN.md for full scope

Capstone — Notification Service API

Production-grade Flask REST API built end-to-end via the AI-Augmented SDLC

7 phases • 73 tests • 96% coverage • 110/110 rubric • Docker + CI

#1 Project Overview

Seven-phase capstone extending a notification service scaffold with REQ-007 (stats endpoint), three test suites, a 6-stage CI pipeline with coverage gate, Docker deployment, two ADRs, and a pre-commit governance hook. Integrates techniques from all prior weeks: spec-driven development (W2), governance hooks (W3), audit middleware (W4), structured prompts (W5), and CI/CD + Docker (W6).

Phase 1–2

Spec & REQ-007

  • feature_spec.yaml with REQ-001–REQ-007
  • get_stats() returns total, by_type, by_status, last_sent
  • Null-type guard · security review (2 LOW findings)
Phase 3–4

Tests & CI Gate

  • 5 unit + 5 integration + 2 regression tests for REQ-007
  • 73 total tests · 96% coverage
  • CI coverage gate --cov-fail-under=80
Phase 5

Docker Deployment

  • Multi-stage Dockerfile · non-root appuser
  • docker-compose with healthcheck + mem_limit
  • All 7 endpoints validated live in container
Phase 6–7

Governance & Report

  • ADR-002 (stats strategy) + ADR-003 (retry error, bonus)
  • Pre-commit hook: flake8 + pytest + JSONL audit log
  • REPORT.md with ROI measurement + demo checklist

Deliverables Checklist

  • ✓ Scaffold extracted + CAPSTONE_PLAN.md (Session A)
  • ✓ REQ-007 spec + implementation verified (Session A)
  • ✓ Phase 1 risk notes + Phase 2 security review (Session A)
  • ✓ REQ-007 test classes — unit + integration + regression (Session B)
  • ✓ CI coverage gate --cov-fail-under=80 (Session B)
  • ✓ Docker live validation of all 7 endpoints (Session C)
  • ✓ ADR-002 stats computation strategy (Session C)
  • ✓ ADR-003 retry-history on RuntimeError, bonus (Session C)
  • ✓ docs/metrics-report.md REQ-007 row (Session C)
  • ✓ Pre-commit hook + audit log (Session C)
  • ✓ Docker mem_limit, bonus (Session C)
  • ✓ REPORT.md + ROI measurement (Session D)
  • ✓ Dashboard mini-project panel populated (Session D)
  • ✓ Submission PDF at repo root (Session E)
  • ✓ W7 status dot → complete (Session E)

#2 Request Lifecycle

Every request flows through the audit middleware before reaching the blueprint route. The notification service validates input, delegates to the email provider, and records history. The audit logger captures the response on the way out.

flowchart TD
    Client([Client]) --> AuditIn[audit_logger.before_request]
    AuditIn --> Route[Blueprint Route]
    Route --> Validate[NotificationService.validate]
    Validate -->|valid| Send[NotificationService.send]
    Validate -->|invalid| Err400([400 Bad Request])
    Send --> Provider[email_provider]
    Provider -->|success| Record[_record_history]
    Provider -->|failure| Retry[Retry Logic]
    Retry -->|retries left| Provider
    Retry -->|exhausted| Err500([500 + retry_history])
    Record --> AuditOut[audit_logger.after_request]
    Err400 --> AuditOut
    Err500 --> AuditOut
    AuditOut --> Client
        

#3 Retry State Machine

When the email provider fails, the service retries up to MAX_RETRY_ATTEMPTS times with exponential backoff. Each attempt is logged. On exhaustion, a RuntimeError is raised with retry_history attached as an attribute (see ADR-003).

stateDiagram-v2
    [*] --> Attempt1
    Attempt1 --> Success : provider returns message_id
    Attempt1 --> Attempt2 : provider raises exception
    Attempt2 --> Success : provider returns message_id
    Attempt2 --> Attempt3 : provider raises exception
    Attempt3 --> Success : provider returns message_id
    Attempt3 --> Exhausted : provider raises exception
    Success --> AuditSuccess : record_history status=success
    AuditSuccess --> [*]
    Exhausted --> AuditFailed : record_history status=failed
    AuditFailed --> RaiseError : RuntimeError + retry_history
    RaiseError --> [*]
        

#4 Stats Computation Pipeline (REQ-007)

GET /api/notifications/stats computes metrics on-demand from the in-memory notification history (ADR-002). A single pass over the bounded list aggregates by_type, by_status, and tracks last_sent. Null-type records are mapped to “unknown” via a defensive guard.

flowchart LR
    History[_notification_history\nlist max 100] --> Iterate[get_stats iterates]
    Iterate --> ByType[by_type counter\nemail/sms/alert]
    Iterate --> ByStatus[by_status counter\nsuccess/failed]
    Iterate --> LastSent[max timestamp\nlast_sent]
    ByType --> Result[return dict\ntotal + by_type + by_status + last_sent]
    ByStatus --> Result
    LastSent --> Result
        

#5 CI/CD Pipeline

Six-stage GitHub Actions pipeline: lint gates everything, then unit tests (with coverage gate), integration tests, regression tests, and security audit run in parallel. Docker build is the final stage — it builds the image, starts the container, and curls /api/health to prove the deployment works.

flowchart TD
    Trigger([push / PR]) --> Lint[lint\nflake8 src/ tests/]
    Lint --> Unit[unit-tests\npytest --cov-fail-under=80]
    Lint --> Integration[integration-tests\npytest tests/integration/]
    Lint --> Regression[regression-tests\npytest tests/regression/]
    Lint --> Security[security\npip-audit]
    Unit --> Docker[docker-build\nbuild + run + curl /api/health]
    Integration --> Docker
    Regression --> Docker
    Security --> Docker
    Docker --> Ready([ready to merge])
        

#6 Governance Flow

The pre-commit hook fires on every commit touching week-7/capstone-py/. It runs flake8, then unit tests, then writes a JSON audit entry to .audit-log.jsonl. Any failure blocks the commit. The hook is installed at the repo root and adapted to cd into the scaffold directory first.

flowchart TD
    Commit([git commit]) --> Check{Files in\nweek-7/capstone-py?}
    Check -->|no| Skip([Skip hook])
    Check -->|yes| Flake[flake8 src/ tests/]
    Flake -->|pass| Tests[pytest tests/unit/]
    Flake -->|fail| Block([COMMIT BLOCKED])
    Tests -->|pass| Audit[Write .audit-log.jsonl]
    Tests -->|fail| Block
    Audit --> Approve([Commit approved])