# Dimension: Template Sync

Evaluate how well `.github/workflows/erp-kit-*.yml` and `.github/actions/erp-kit-*/` align with the templates shipped by erp-kit. Differences are **not automatically penalised**; the agent classifies each drift as a legitimate project customisation (no penalty) or stale content (penalty).

## Inputs

- `REPO_ROOT`

## Procedure

### 1. Verify the CLI tool is available

Run:

```bash
npx erp-kit internal gh-actions sync-check --help
```

If the command exits non-zero or reports `command not found`, return `{ "score": null, "status": "tool-unavailable", "findings": [{ "severity": "info", "message": "gh-actions sync-check command not available in this erp-kit version; dimension skipped." }] }`. This avoids penalising older erp-kit versions that predate the tool.

### 2. Collect drift

Run:

```bash
npx erp-kit internal gh-actions sync-check
```

Capture the exit code and parse the output. Two error types are reported per file:

- `missing` — the consumer is missing a file that erp-kit ships
- `modified` — the consumer's file content differs from the shipped template

If exit code is 0 (no drift), return `{ "score": 100, "findings": [] }` and stop.

### 3. For each drift, gather context

For each reported path, capture three things so the LLM can judge intent:

1. The shipped template content: `cat node_modules/@tailor-platform/erp-kit/templates/<rel>` where `<rel>` is derived from the drift path (e.g. `.github/workflows/erp-kit-check.yml` → `templates/workflows/erp-kit-check.yml`).
2. The local content: `cat <REPO_ROOT>/<drift-path>` (skip if `missing`).
3. The line-level diff: `diff -u <shipped> <local>` (skip if `missing`).

### 4. Classify each drift

For every drift item, classify as one of:

- **legitimate** — the divergence reflects intentional project customisation. Examples:
  - Project-specific environment variables added (`TAILOR_TENANT_ID`, etc.)
  - Job names rewritten for clarity
  - Extra steps that the project owns (e.g. internal deploy)
  - Pinned action SHAs that intentionally lag erp-kit's defaults
- **stale** — the divergence looks like an `update` was missed. Examples:
  - The local file is missing a step that erp-kit added (e.g. `gh-actions:sync-check`)
  - The local file references commands that erp-kit has since renamed
  - A file is `missing` entirely
- **unclear** — neither obviously project-driven nor obviously stale. Default to a partial penalty.

Use the line-level diff and the surrounding code to judge intent. When the diff touches lines that look generic (timeouts, action versions, default env), lean toward **legitimate**. When it removes lines that look like recent erp-kit additions (new steps, new commands), lean toward **stale**.

### 5. Score

Start at 100 and subtract per-drift:

| Classification | Subtract per item |
| -------------- | ----------------- |
| legitimate | 0 |
| unclear | 5 |
| stale | 15 |

Two additional rules:

- Each `missing` file counts as **stale** with a `-20` penalty (replacing the `-15`). A file going entirely absent is a clearer signal of forgotten update than a content modification.
- Cap the total subtraction at 80 (i.e. the minimum score is 20 even if everything is stale) so the dimension still contributes some signal.

Clamp to `[0, 100]`.

### 6. Output

Return JSON shaped like:

```json
{
  "dimension": "templates",
  "score": 75,
  "findings": [
    {
      "severity": "info",
      "message": ".github/workflows/erp-kit-app-ci.yml: 4 line diff adds TAILOR_TENANT_ID env. Classified legitimate, no penalty."
    },
    {
      "severity": "warning",
      "message": ".github/workflows/erp-kit-check.yml: missing gh-actions:sync-check step. Looks like a recent erp-kit update was missed. Run pnpm erp-kit update workflows."
    },
    {
      "severity": "error",
      "message": ".github/actions/erp-kit-fetch-tailor-token/action.yml: file is missing. Run pnpm erp-kit update workflows."
    }
  ]
}
```

`severity` mapping in the report:

- legitimate → `info` (collapsible)
- unclear → `warning`
- stale (modified) → `warning`
- stale (missing) → `error`

The aggregator surfaces errors and warnings prominently; info entries are summarised.
