Skip to content

patch: Coverage gaps vs. current templates; consider per-template manifest #42

@rdwj

Description

@rdwj

fips-agents patch check and the per-category subcommands rely on hardcoded glob patterns in src/fips_agents_cli/tools/patching.py (MCP_FILE_CATEGORIES, AGENT_FILE_CATEGORIES, *_NEVER_PATCH). Those patterns have drifted behind what the template repos actually ship. A patch check against a current agent project reports "up to date" for several files that have demonstrably changed in the template.

This issue is part audit, part proposal.

Audit — files shipped by each template that no patch category covers

Tree comparisons done against:

  • fips-agents/agent-template (templates/agent-loop/ and templates/workflow/)
  • fips-agents/mcp-server-template
  • local gateway-template, ui-template peers

Agent / workflow template

Not surfaced by patch check — silently invisible:

  • .claude/rules/agent-development.md (and .claude/rules/workflow-development.md). The claude category globs .claude/commands/**/* only.
  • evals/__init__.py, evals/assertions.py, evals/discovery.py, evals/mock_factory.py, evals/run_evals.py, evals/README.md — the entire eval harness.
  • prompts/system.md, rules/citation_required.md, skills/summarize/SKILL.md — starter content. These are user-customizable and probably want to live in AGENT_NEVER_PATCH rather than a category, but they need to live somewhere.
  • .containerignore, .gitignore, .memoryhub.yaml — root dotfiles.
  • tools/.gitkeep, src/__init__.py — minor.

User-customized paths that lack defense-in-depth in AGENT_NEVER_PATCH (today they're not in any category, so patch leaves them alone, but a future pattern broadening could clobber add-injected files):

  • tools/** (target of fips-agents add code-executor)
  • examples/** (target of fips-agents add vision)
  • prompts/**, rules/**, skills/**

MCP server template

Two real bugs:

  1. Typo in core patterns at tools/patching.py:32: \"src/*/__ init__.py\" has a literal space between __ and init__. The pattern matches nothing — package __init__.py files are never offered as patches.
  2. No claude category for MCP, but the MCP template ships .claude/commands/*.md (create-tools.md, deploy-mcp.md, exercise-tools.md, implement-mcp-item.md, plan-tools.md, update-docs.md, write-system-prompt.md). Updates to those slash commands are unreachable via patch.

Other gaps:

  • core patterns miss src/main.py (the entry point) and src/core/__init__.py.
  • docs patterns miss AGENTS.md, CONTRIBUTING.md, DEVELOPMENT_PROCESS.md, OPENSHIFT_DEPLOYMENT.md.
  • build patterns miss .dockerignore, .gitignore, .gitleaks.toml, .github/CODEOWNERS.
  • LICENSE and requirements.txt are not in any bucket.

Gateway / UI templates

get_categories_for_type() raises ValueError for gateway, ui, sandbox. So fips-agents patch check is non-functional for those project types today. The Go templates have an obvious shape (chart/, Makefile, Containerfile, cmd/, internal/, go.mod, go.sum) and could support patching with categories analogous to the agent template. Worth deciding whether to add now or defer.

Patch subcommand review

commands/patch.py registers generators, core, docs, build, chart, claude, all, check unconditionally. When a subcommand is invalid for the current project type, patch_category() returns a clear "Available: ..." error. That's fine and matches the documented behavior in CLAUDE.md. No subcommand changes are needed beyond whatever new categories we add.

If we add new categories per the audit above:

  • Agent / workflow gain: evals (the harness; ask before patch).
  • MCP gains: claude (slash commands; safe to overwrite).

Proposal — ship a .fips-template.yaml in each template repo

The hardcoded constants in tools/patching.py are awkward because:

  • The CLI repo and the template repos drift independently. A new file added to a template doesn't show up in patch check until someone updates the CLI and ships a release.
  • Adding gateway / ui / sandbox patch support means more constants and more branching in get_categories_for_type().
  • The current "never patch" lists are easy to forget when the template grows.

A small manifest file shipped at the template root (or in the monorepo subdir) would make patch data-driven:

# .fips-template.yaml
type: agent
patch:
  categories:
    chart:
      description: Helm chart templates
      patterns:
        - chart/templates/**/*
        - chart/Chart.yaml
      ask_before_patch: true
    evals:
      description: Eval harness
      patterns:
        - evals/__init__.py
        - evals/assertions.py
        - evals/discovery.py
        - evals/mock_factory.py
        - evals/run_evals.py
        - evals/README.md
      ask_before_patch: true
    claude:
      description: Claude Code slash commands and rules
      patterns:
        - .claude/commands/**/*
        - .claude/rules/**/*
      ask_before_patch: false
    # docs, build, ...
  never_patch:
    - src/agent.py
    - agent.yaml
    - chart/values.yaml
    - src/fipsagents/**
    - tools/**
    - examples/**
    - prompts/**
    - rules/**
    - skills/**
    - tests/**/*.py
    - README.md
    - pyproject.toml
    - .env*

Loader behavior: _clone_template_for_patch already returns the comparison root; the patcher reads <root>/.fips-template.yaml after clone. Fall back to the current hardcoded constants when the manifest is absent (legacy templates or projects pinned to old commits).

Net effect:

  • Each template owns the truth about what is patchable. Agent-template adds a file → next patch check surfaces it without a CLI release.
  • gateway-template, ui-template, code-sandbox opt in by shipping a manifest.
  • The CLI's MCP_FILE_CATEGORIES / AGENT_FILE_CATEGORIES become fallbacks, not the source of truth.

Suggested split

Three commits / PRs, in order of risk:

  1. Fix the typo and the missing patterns in the existing constants (src/*/__ init__.pysrc/*/__init__.py, add .claude/rules/**/* to agent claude, expand agent AGENT_NEVER_PATCH, add MCP claude category, fill in MCP docs / build / core gaps). Lowest risk, immediate user value.
  2. Add an evals category for agent / workflow. Touches the agent template by way of ask_before_patch UX, but no template-side change required.
  3. Move to per-template manifests. Larger lift — touches every template repo. Probably worth a design issue of its own first.

Steps 1 and 2 unblock the immediate gap. Step 3 is the correct long-term shape but is not blocking.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions