Skip to content
Back to skills

Validation Authority

ASecurity

Treat upstream validators as authoritative. Align local config to them. Use when validation fails unexpectedly, before modifying validator behavior, or when tempted to change upstream tool code.

  • 47 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 27, 2026
data-aipythongoshellgitdocumentation

Works with

  • cli

Security analysis

A100/100

Scanned September 30, 2026

npx -y skills add rjmurillo/ai-agents --skill validation-authority --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Validation Authority?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Validation Authority
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rjmurillo-validation-authority/badge)](https://www.skillsdirectory.com/skills/rjmurillo-validation-authority)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: validation-authority
description: Treat upstream validators as authoritative. Align local config to them. Use when validation fails unexpectedly, before modifying validator behavior, or when tempted to change upstream tool code.
license: MIT
metadata:
  version: 1.0.0
  source: Session 366 retrospective
  id: Validation-Authority-001
  routing:
    role: conditional-adjunct
    invoker: build
    trigger: build Phase 2b writes the decision record after analysis-provenance classifies a validation target
    user-facing: true
---

# Validation Authority

When integrating external validators (PSScriptAnalyzer, markdownlint, ESLint, etc.), respect upstream defaults. Modify local configuration to match upstream behavior. Do not modify upstream tool code.

## Triggers

Say `validation failed unexpectedly`, `should I change the validator`, or
`is this validator authoritative`. Activate when:

- Validation fails unexpectedly
- Before modifying validator behavior or configuration
- When tempted to change upstream tool source code
- When adding a new external validator to the project
- When suppressing validator warnings without rationale

## Decision Tree

```
Validation failure occurred
        |
        v
Is the validator upstream (external tool)?
        |               |
       YES              NO (local/custom)
        |               |
        v               v
Modify LOCAL config   Modify tool as needed
to align with tool    (you own the code)
        |
        v
Document override rationale
in config comments
```

## Process

1. **Classify the validator**: Determine if the tool is upstream (external) or local (project-owned).
2. **Identify the conflict**: Find the specific rule or default causing the failure.
3. **Check upstream defaults**: Read the tool's documentation for the default behavior.
4. **Align local config**: Update project configuration files to match or explicitly override upstream defaults.
5. **Document overrides**: Add comments explaining why any override differs from the upstream default.

## Trigger Table

| Scenario | Action | Example |
|----------|--------|---------|
| PSScriptAnalyzer rule fails | Update `.psscriptanalyzerrc.psd1` | Suppress `PSAvoidUsingWriteHost` with rationale |
| markdownlint rule fails | Update `.markdownlint.yaml` | Disable `MD013` line-length for generated docs |
| ESLint rule conflicts | Update `.eslintrc` | Override `no-console` for CLI tools |
| Upstream tool has a bug | Flag the bug to the owner with a repro, add workaround in config | Pin tool version, suppress specific rule |
| Tool default changed after upgrade | Review and align local config to new default | Update config after major version bump |

## Adjunct Mode: Build Phase 2b (issue #5387)

`/build` Phase 2b invokes this skill after `analysis-provenance` classifies
every path `validation_trigger.py` flagged as a validation target. This mode
writes the decision record; it does not replace the general decision-tree
guidance above, which still applies whenever a human asks how to treat an
upstream validator.

1. For each target, combine `analysis-provenance`'s category, owner, and
   evidence with a diagnosis of what actually happened:
   `implementation-defect` (the local check has a real bug), `local-config-defect`
   (only the project's own config needs to change), `stale-generated-output`
   (a generated mirror drifted from its template or source), `baseline-update`
   (a ratchet or baseline needs new entries), `upstream-defect` (the vendored
   or upstream tool itself is wrong), or `unknown` (evidence is insufficient).
2. Name the one `permitted_change_location` Phase 3 may edit. `GENERATED`
   always permits only the canonical source, never the mirror. `VENDOR` and
   `UPSTREAM` never permit the target itself; point at the local override or
   config instead. `unknown` diagnosis or `UNKNOWN` category permits nothing:
   the record blocks further semantic edits until ownership evidence exists.
3. For `baseline-update`, cite the existing policy that authorizes the
   refresh (`baseline_justification.policy_source`, a path that exists on
   disk), state the reason, and justify every added entry individually.
4. Write the record to `<record-path>` (see "Validation Change Record" below
   for where that resolves) and run
   `python3 "${COPILOT_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-.claude}}/skills/validation-authority/scripts/validation_record.py" --record <record-path> --changed-path <path>`
   for every changed path. Exit `0` clears Phase 3 to edit the permitted
   locations; exit `1` names the blocking targets; exit `2` is a
   configuration error in the record or the invocation.

## Scripts

| Script | Purpose | Exit codes |
|--------|---------|------------|
| `validation_record.py` (this skill's script directory) | Checks the Phase 2b decision record: field shape, provenance/authority rules, and changed-path coverage. Emits a JSON summary of target count, counts by category, and defects. | `0` record passed, `1` the record has defects, `2` config error (unreadable file, invalid JSON, or the sibling `build` trigger could not be loaded when `--changed-path` needed it) |

## Validation Change Record

`<record-path>` above means: resolve a scratch directory the way
`paths.artifact_dir` does, take its `scratch/` subdirectory, then
`validation-authority-record.json` inside it. That directory is agent PR
scratch space in the consumer's own workspace (git-ignored in this repo's own
checkout); the PR body carries the record's summary instead of a commit.

```json
{
  "trigger": { "...": "the validation_trigger.py output, carried through unchanged" },
  "targets": [
    {
      "target": "<path>",
      "component": "<human label for the tool or config>",
      "provenance": {
        "category": "LOCAL | GENERATED | VENDOR | UPSTREAM | UNKNOWN",
        "owner": "<non-empty>",
        "evidence": "<non-empty>",
        "canonical_source": "<required, and equal to permitted_change_location, when category is GENERATED>"
      },
      "authority": {
        "contract": "<non-empty; the validator's own exit-code or pass/fail contract>",
        "diagnosis": "implementation-defect | local-config-defect | stale-generated-output | baseline-update | upstream-defect | unknown",
        "permitted_change_location": "<non-empty; never the target itself for VENDOR or UPSTREAM>",
        "escalation": "<required, non-empty, when diagnosis is upstream-defect>"
      },
      "baseline_justification": {
        "policy_source": "<repository-relative path to an existing file; required when diagnosis is baseline-update>",
        "reason": "<non-empty>",
        "added_entries": [{ "justification": "<non-empty per entry>" }]
      }
    }
  ]
}
```

Rules `validation_record.py` enforces:

1. Every target needs `target`, `component`, `provenance`, and `authority`.
   `trigger` holds the trigger's JSON object, and its `decision` is `activate`
   or `skip`. A `skip` that lists effects or targets is a contradiction. When
   the trigger activated, the record needs at least one target, and each path
   the trigger named needs a record target.
2. `UNKNOWN` category or `unknown` diagnosis is always a blocking defect: stop
   semantic edits and request ownership evidence.
3. `GENERATED` needs `provenance.canonical_source`, and
   `authority.permitted_change_location` must equal it.
4. `VENDOR` or `UPSTREAM`: `authority.permitted_change_location` must not
   equal `target`. `upstream-defect` needs a non-empty `authority.escalation`.
5. `baseline-update` needs `baseline_justification` with a `policy_source`
   that is a relative path to an existing file inside the repository, a non-empty `reason`, and a non-empty `justification` on
   every entry in `added_entries`.
6. With `--changed-path` supplied: every path the sibling `build` trigger's
   path cues alone would flag needs a record target; a `VENDOR` or `UPSTREAM`
   target must not itself be a changed path; a changed `GENERATED` target
   needs its canonical source changed too, never edited as a standalone
   mirror.
7. Paths compare after normalization: `./a/b.py`, `a\\b.py`, and `a/b.py` are
   the same target.
8. One run reports every defect: field defects and coverage defects together.

## Anti-Patterns

| Avoid | Why | Instead |
|-------|-----|---------|
| Forking upstream tools to change behavior | Creates maintenance burden, diverges from community | Configure locally, file upstream issues |
| Patching tool source to suppress warnings | Hides real issues, breaks on updates | Use tool's suppression mechanism |
| Disabling entire rule categories | Loses protection the rules provide | Suppress specific rules with rationale |
| Suppressing without rationale | Future maintainers cannot evaluate the override | Always document why in config comments |
| Copying tool defaults into local config | Config drift when upstream updates | Only override what you need to change |

## Verification

After applying this skill:

- [ ] Validator is classified as upstream or local
- [ ] Local config aligns with upstream defaults
- [ ] Any overrides include documented rationale
- [ ] No upstream tool source code was modified
- [ ] Reconciliation: paste the validator's exit status line (e.g., `echo "exit=$?"` output after running the validator command) to confirm the updated config passes; a claim of "validation passes" without pasted output does not count

## Examples

### Example 1: PSScriptAnalyzer Rule Failure

**Problem**: `PSAvoidUsingWriteHost` fails on a CLI script that intentionally uses `Write-Host`.

**Wrong approach**: Modify PSScriptAnalyzer source or remove the rule globally.

**Correct approach**:

```powershell
# .psscriptanalyzerrc.psd1
# Rationale: CLI scripts use Write-Host for user-facing output
@{
    Rules = @{
        PSAvoidUsingWriteHost = @{
            Enable = $false
        }
    }
}
```

### Example 2: markdownlint Conflict

**Problem**: `MD013` (line length) fails on auto-generated documentation.

**Wrong approach**: Fork markdownlint to increase default line length.

**Correct approach**:

```yaml
# .markdownlint.yaml
# Rationale: Generated docs have long lines from tool output
MD013:
  line_length: 200
  tables: false
```

### Example 3: New Tool Integration

**Problem**: Adding `ruff` to a Python project. Several existing files fail.

**Wrong approach**: Disable all failing rules immediately.

**Correct approach**:

1. Run `ruff check` with defaults to see all violations.
2. Fix violations that align with project standards.
3. Suppress remaining rules per-file with `# noqa` and rationale.
4. Document any project-wide overrides in `pyproject.toml`.

## Related Skills

| Skill | Relationship |
|-------|--------------|
| [style-enforcement](../style-enforcement/SKILL.md) | Enforces style rules that this skill governs |
| [code-qualities-assessment](../code-qualities-assessment/SKILL.md) | Quality assessment, not validator config |
| [doc-accuracy](../doc-accuracy/SKILL.md) | Detects contradictions between docs/config and behavior |

## Timelessness: 9/10

External tool integration is a universal software engineering concern. The principle of respecting upstream authority applies to any validator, linter, or static analysis tool regardless of language or framework.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…