Agent Skills: graph-automation

Build the automation infrastructure for a knowledge-graph-style skill — package with SQLite build, CI workflow for rebuilds on merge, and an update mechanism that analyses PRs and propagates changes. Adapts patterns to the specific graph variant.

UncategorizedID: josh-cooper/.claude/graph-automation

Install this agent skill to your local

pnpm dlx add-skill https://github.com/josh-cooper/.claude/tree/HEAD/skills/graph-automation

Skill Files

Browse the full folder contents for graph-automation.

Download Skill

Loading file tree…

skills/graph-automation/SKILL.md

Skill Metadata

Name
graph-automation
Description
Build the automation infrastructure for a knowledge-graph-style skill — package with SQLite build, CI workflow for rebuilds on merge, and an update mechanism that analyses PRs and propagates changes. Adapts patterns to the specific graph variant.

What this skill does

Given an existing knowledge-graph-style skill (produced by /graph-skill-factory or hand-written), builds the automation infrastructure that makes the graph a live, queryable artifact:

  1. Package — A workspace package with a build script that parses the graph's markdown files into a versioned SQLite database.
  2. CI workflow — A GitHub Actions workflow that rebuilds the database on merge and persists it to object storage.
  3. Update mechanism — A skill and/or workflow that analyses merged PRs, determines if the graph needs updating, runs Claude Code to make changes, and opens a PR.

This skill provides detailed patterns and code snippets. You adapt them to the project's conventions, the graph variant's specific taxonomy, and any contextual requirements the user specifies.

Prerequisites

Before running this skill, the graph skill itself must already exist — the files that define what the graph documents (SKILL.md, pipeline.md, spec file). You need to understand:

  • The graph's vocabulary (what files are called: component.md, design.md, etc.)
  • The graph's taxonomy (what frontmatter fields exist: concerns.tech_stack, concerns.data_classification, etc.)
  • The graph's document structure (what sections the deep-write doc has: Architecture, Security, Operations, etc.)
  • Where the graph content lives in the project (e.g., packages/architecture-docs/components/)

Read the graph's SKILL.md and pipeline.md to extract these before proceeding.


Phase 1: Package setup

Create a workspace package for the graph. It needs a build script, minimal dependencies, and to be wired into the monorepo's build system.

What to create

  1. package.json — Name, build script, dependencies.
  2. scripts/build-tree.ts — The build script (see build-patterns.md for the full pattern).
  3. tsconfig.json — Standard TypeScript config if the project uses one.
  4. Wire it into the monorepo (add to pnpm-workspace.yaml if needed, add to turbo pipeline if applicable).

Package.json pattern

{
  "name": "@repo/<graph-package-name>",
  "version": "0.0.1",
  "private": true,
  "description": "<what this graph documents>",
  "scripts": {
    "build": "tsx scripts/build-tree.ts"
  },
  "devDependencies": {
    "@types/better-sqlite3": "^7.6.13",
    "@types/node": "^25.5.0",
    "better-sqlite3": "^12.8.0",
    "gray-matter": "^4.0.3",
    "tsx": "^4.20.5",
    "typescript": "^5.9.3"
  }
}

Adapt: Package name, description. Dependencies are stable across all variants — better-sqlite3 for the database, gray-matter for frontmatter parsing, tsx for TypeScript execution.

What to verify

  • pnpm install succeeds with the new package
  • pnpm build --filter=@repo/<name> produces dist/tree.db
  • The database contains the expected tables (see build-patterns.md)

Phase 2: Build script

The build script is the core artifact. Read ${CLAUDE_SKILL_DIR}/build-patterns.md for the complete pattern with code snippets.

The script does 4 passes over the graph's markdown files:

  1. Parse & index — Glob node files, parse frontmatter, extract taxonomy fields, parse deep-doc sections, insert into SQLite.
  2. Wikilinks — Extract [[wikilinks]] from all content, resolve to node IDs, record as edges.
  3. Validation — Run variant-specific checks (e.g., access inheritance, data classification consistency, required fields).
  4. Taxonomy — Count occurrences of each taxonomy value for filtering and audit.

Each pass is a transaction. The script appends a versioned build snapshot to the database — it never drops existing data.

What adapts per variant

| Concern | What changes | Derived from | |---------|-------------|--------------| | File patterns | Which files to glob (component.md vs feature.md) | vocabulary.node.file, vocabulary.deep_doc.file | | Directory name | Where nodes live (components/ vs features/) | vocabulary.nodes_dir | | Taxonomy interface | Which frontmatter fields to extract | taxonomy.fields[*].key | | Node table columns | How to store taxonomy data | taxonomy.fields (see patterns for approaches) | | Section splitting | How to split the deep-doc | H2 headings (invariant), but section metadata keys adapt | | Validation rules | What to check in pass 3 | quality.review_criteria, taxonomy.inheritance_rule | | Deep-doc title | Default title for docs without frontmatter title | vocabulary.deep_doc_title_template |

What is invariant

  • SQLite schema structure (builds, nodes, sections, edges, taxonomy, validation tables)
  • Wikilink regex and resolution logic
  • FTS5 full-text search setup
  • Build metadata tracking (timestamp, commit SHA, counts)
  • Transaction-per-pass pattern
  • Error/warning reporting

Phase 3: CI workflow

A GitHub Actions workflow that rebuilds the database when graph content changes on main.

Workflow pattern

Read the CI patterns section below. The workflow:

  1. Triggers on push to main when graph content files change
  2. Downloads the existing database from object storage (preserves build history)
  3. Runs the build script (appends a new versioned snapshot)
  4. Uploads the updated database to object storage

What to create

A workflow file at .github/workflows/<graph-name>.yml.

Workflow snippet

name: <Graph Name> Build

on:
  workflow_dispatch:
  push:
    branches: [main]
    paths:
      - "packages/<package-dir>/<nodes-dir>/**"
      - "packages/<package-dir>/scripts/**"
      - "packages/<package-dir>/_meta/**"
      - "packages/<package-dir>/index.md"

jobs:
  build:
    name: Build <Graph Name>
    runs-on: ubuntu-latest
    env:
      DATA_WAREHOUSE_BUCKET: <s3-bucket-name>
    steps:
      - uses: actions/checkout@v4

      - uses: pnpm/action-setup@v4
        with:
          version: 9.14.2

      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: pnpm

      - run: pnpm install --frozen-lockfile

      # Download existing database (preserves build history across runs)
      - name: Download existing tree.db
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.CI_S3_ACCESS_KEY }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_S3_SECRET_KEY }}
          AWS_DEFAULT_REGION: ${{ secrets.CI_S3_REGION }}
        run: |
          mkdir -p packages/<package-dir>/dist
          S3_KEY="<s3-prefix>/tree.db"
          if aws s3 ls "s3://${DATA_WAREHOUSE_BUCKET}/${S3_KEY}" > /dev/null 2>&1; then
            aws s3 cp "s3://${DATA_WAREHOUSE_BUCKET}/${S3_KEY}" \
              packages/<package-dir>/dist/tree.db
          else
            echo "No existing tree.db — starting fresh"
          fi

      - name: Build tree.db
        run: pnpm exec turbo run build --filter=@repo/<package-name>

      # Upload updated database
      - name: Upload tree.db
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.CI_S3_ACCESS_KEY }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_S3_SECRET_KEY }}
          AWS_DEFAULT_REGION: ${{ secrets.CI_S3_REGION }}
        run: |
          aws s3 cp packages/<package-dir>/dist/tree.db \
            "s3://${DATA_WAREHOUSE_BUCKET}/<s3-prefix>/tree.db"

Adapt: Package directory, nodes directory, S3 bucket/prefix, turbo cache setup (add if the project uses it), package filter name. If the project doesn't use S3, adapt the persistence mechanism (could be a GitHub artifact, a separate repo, or any object store).

What to verify

  • Workflow triggers on the correct file paths
  • First run succeeds even without an existing database
  • Second run preserves build history from the first run
  • The database is queryable after upload

Phase 4: Update mechanism

An automated process that keeps the graph current as the codebase evolves. This has two parts: a skill that Claude Code runs to analyze and update, and optionally a workflow that triggers the skill on PR merge.

Part A: Update skill

Create a variant-specific update skill (e.g., /architecture-graph-update). This skill:

  1. Analyses a merged PR — reads the diff, determines if changes are relevant to this graph variant
  2. Searches the graph — greps the tree for every term related to the changed code
  3. Builds a change plan — classifies each match as needing update, addition, or removal
  4. Executes changes — applies operations, checks neighbors, propagates until stable
  5. Opens a PR — commits changes and creates a PR with the update

The classification logic is the most variant-specific part. For a user-manual graph, the question is "does this change user-facing behavior?" For an architecture graph, it's "does this change system architecture, security posture, or operational characteristics?"

Key pattern: The update skill should output structured JSON so that automation can parse the result:

{
  "outcome": "noop | updated | error",
  "classification": "noop | relevant",
  "pr_number": 123,
  "reasoning": "Brief explanation of why the PR is or isn't relevant",
  "operations": [
    { "type": "add | update | remove", "node": "path/to/node", "fields": ["description", "security"], "source": "seed | propagation" }
  ],
  "pr_url": "https://github.com/org/repo/pull/456 or null",
  "error": "error description or null"
}

Part B: CI trigger (optional)

A workflow that runs the update skill after PRs merge:

name: <Graph Name> Update Check

on:
  pull_request:
    types: [closed]
    branches: [main]

jobs:
  check:
    if: github.event.pull_request.merged == true
    name: Check for graph updates
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Run Claude Code with the update skill
      - name: Analyse PR for graph updates
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          npx @anthropic-ai/claude-code --print \
            "/<graph-name>-update ${{ github.event.pull_request.number }}" \
            --output-format json

      # If the skill created changes, push and open a PR
      - name: Push updates
        if: steps.analyse.outputs.outcome == 'updated'
        run: |
          git checkout -b graph-update/pr-${{ github.event.pull_request.number }}
          git add packages/<package-dir>/
          git commit -m "docs: update <graph-name> for PR #${{ github.event.pull_request.number }}"
          git push origin HEAD
          gh pr create \
            --title "Update <graph-name> for #${{ github.event.pull_request.number }}" \
            --body "Automated update triggered by #${{ github.event.pull_request.number }}"

Adapt heavily. The Claude Code CLI invocation, output parsing, branch naming, commit message, and PR creation all depend on the project's conventions and CI setup. The snippet above is a starting point — the user will likely have specific requirements about how this integrates with their existing CI.

What to verify

  • The update skill correctly classifies a known-relevant PR as "relevant"
  • The update skill correctly classifies an irrelevant PR as "noop"
  • Propagation terminates (doesn't loop infinitely on circular wikilinks)
  • The generated PR has clean, reviewable changes

Sequencing

Build in this order:

  1. Package + build script — Get the database building locally first. Run it, inspect the output, iterate.
  2. CI workflow — Wire up the automated build. Merge, verify the workflow runs, check the persisted database.
  3. Update skill — Write the classification logic. Test it manually against a few real PRs before automating.
  4. Update workflow — Wire up the automated trigger. This is optional and can come later.

Each phase should be verified independently before moving to the next.


Contextual adaptation checklist

Before building, confirm these with the user:

  • [ ] Monorepo structure: Where should the package live? What's the workspace convention?
  • [ ] Build system: Turbo? Nx? Plain pnpm scripts? This affects how the build is wired up.
  • [ ] Object storage: S3? GCS? GitHub artifacts? Where should the database persist?
  • [ ] Secrets: What secret names does the CI use for object storage access?
  • [ ] Existing CI patterns: Is there a Turbo cache server? Shared setup actions? Match them.
  • [ ] Update trigger: Should updates be automatic on PR merge, manual via slash command, or both?
  • [ ] Classification heuristic: What makes a PR "relevant" to this graph? This is the most domain-specific decision.