Files
John Smith 6ae3e16aba feat(lint): add lint-ultimate action wrapping MegaLinter with envelope
Tier 1.1 of the quality expansion design. Adds the lint-ultimate
composite action that runs MegaLinter (or Super-Linter) over the
repo and emits a per-linter checks[] plus per-finding findings[]
envelope, matching the standard .agent/output.json contract.

## Changes

### Action
- .github/actions/lint-ultimate/action.yml: composite action, runs
  oxsecurity/megalinter:v7 via Docker, uploads the JSON report and
  stdout as lint-ultimate-reports artifact, uploads the envelope as
  agent-output-lint for downstream consumers.
- .github/actions/lint-ultimate/build-envelope.sh: parses
  megalinter-report.json, maps each linter category to a check[]
  entry and each finding to a findings[] entry. Falls back to an
  empty envelope when the report is missing or unreadable.

### Library
- .github/actions/agent-envelope.sh: add add_finding() helper
  mirroring add_check(). Optional fields (rule, file, line, column,
  suggested_fix) default to null; numbers coerce when non-empty.

### Library fixes (pre-existing bugs surfaced by the new test)
- GITHUB_REPOSITORY default and owner/repo prefix strip now set -u
  safe. Previously the original --arg repo_name reference threw on
  unbound-variable in any non-GitHub runner.
- GITHUB_RUN_ID now passed as --argjson (numeric or null) instead of
  --arg with tonumber? in the filter. The prior form silently
  produced empty output when run_id was unset (jq 1.8.2 quirk where
  tonumber? on null returns Empty and jq emits no output).

### Schema
- .agent/schema.json: enum agent_action extended with all twelve new
  values from the quality-check expansion design (lint-ultimate,
  coverage, actionlint, codeql, lefthook-ci, test-matrix, reviewdog,
  quality-gate, semantic-release, dependabot, docker-ci). Future
  Tier 1/2/3 PRs pick the right value.

### Tests
- tests/: ship the previously untracked harness (run-action.sh,
  run-all.sh, README.md, fixtures for all CI actions) plus the
  new megalinter-passing and megalinter-failing fixtures.
- tests/unit/test-lint-ultimate-parser.sh: parser unit test that
  runs build-envelope.sh against a fabricated megalinter-report.json
  and asserts the envelope shape. No Docker required.
- tests/golden/lint-ultimate/README.md: documents that goldens are
  generated on first real-CI run (per tests/README.md first-run
  convention) and provides a no-Docker local check.

### Matrix
- tests/run-all.sh: megalinter-passing and megalinter-failing added
  to MATRIX (paired with lint-ultimate action).

### Docs
- README.md: lint-ultimate row added to the CI Composite Actions
  table; full example block added between python-ci and ---.

## Risk

- Pre-existing agent-envelope.sh changes affect all envelope-writing
  callers; the same fixes apply everywhere (none had a green test
  before). Behavior is unchanged when GITHUB_* env vars are set
  (real CI).
- No existing tests to regress against (tests/ was untracked).
  Unit test added in this PR exercises the new parser path.

Refs: docs/superpowers/specs/2026-07-30-code-quality-expansion-design.md
2026-07-30 14:38:20 -04:00

182 lines
5.2 KiB
JSON

{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://github.com/Heretek-AI/heretek-actions/.agent/schema.json",
"title": "Heretek Actions Agent Envelope",
"description": "Standard JSON envelope produced by all Heretek Actions for agent consumption",
"type": "object",
"required": ["agent_action", "version", "status", "summary", "created_at"],
"properties": {
"agent_action": {
"description": "The action that produced this envelope",
"type": "string",
"enum": [
"agent-context",
"pr-summary",
"issue-triage",
"check-status",
"review",
"ci-rust",
"ci-js",
"ci-python",
"release",
"pre-commit",
"lint-ultimate",
"coverage",
"actionlint",
"codeql",
"lefthook-ci",
"test-matrix",
"reviewdog",
"quality-gate",
"semantic-release",
"dependabot",
"docker-ci"
]
},
"version": {
"description": "Schema version",
"type": "string",
"pattern": "^\\d+\\.\\d+$"
},
"status": {
"description": "Overall status of the action run",
"type": "string",
"enum": ["success", "failure", "partial", "skipped", "cancelled"]
},
"summary": {
"description": "Human-readable one-line summary of results",
"type": "string",
"maxLength": 200
},
"outputs": {
"description": "Action-specific structured data",
"type": "object",
"default": {}
},
"suggestions": {
"description": "Suggested actions for an agent to take based on results",
"type": "array",
"items": {
"type": "object",
"required": ["type", "reason"],
"properties": {
"type": {
"type": "string",
"enum": [
"issue:create",
"issue:close",
"issue:label",
"pr:create",
"pr:merge",
"pr:review_request",
"pr:comment",
"comment:post",
"label:add",
"label:remove",
"review:request",
"release:create",
"none"
]
},
"reason": {
"type": "string",
"description": "Why the agent should take this action",
"maxLength": 500
},
"data": {
"type": "object",
"description": "Parameters for the suggested action",
"default": {}
},
"priority": {
"type": "string",
"enum": ["high", "medium", "low"],
"default": "medium"
}
}
}
},
"checks": {
"description": "Individual check results (for CI-type actions)",
"type": "array",
"items": {
"type": "object",
"required": ["name", "status"],
"properties": {
"name": { "type": "string" },
"status": {
"type": "string",
"enum": ["pass", "fail", "warn", "skip", "error"]
},
"summary": { "type": "string", "maxLength": 200 },
"details_url": { "type": "string", "format": "uri" },
"duration_ms": { "type": "integer", "minimum": 0 }
}
}
},
"findings": {
"description": "Individual issues found (lint errors, bugs, etc.)",
"type": "array",
"items": {
"type": "object",
"properties": {
"severity": {
"type": "string",
"enum": ["error", "warning", "info", "note"]
},
"rule": { "type": "string" },
"file": { "type": "string" },
"line": { "type": "integer", "minimum": 0 },
"column": { "type": "integer", "minimum": 0 },
"message": { "type": "string" },
"suggested_fix": { "type": "string" }
},
"required": ["severity", "message"]
}
},
"release": {
"description": "Release information (for release-type actions)",
"type": "object",
"properties": {
"version": { "type": "string" },
"tag": { "type": "string" },
"published": { "type": "boolean" },
"assets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"url": { "type": "string", "format": "uri" },
"size_bytes": { "type": "integer", "minimum": 0 }
}
}
},
"release_url": { "type": "string", "format": "uri" }
}
},
"created_at": {
"description": "ISO 8601 timestamp of when this envelope was produced",
"type": "string",
"format": "date-time"
},
"duration_ms": {
"description": "Total execution time in milliseconds",
"type": "integer",
"minimum": 0
},
"repository": {
"description": "Repository context",
"type": "object",
"properties": {
"owner": { "type": "string" },
"repo": { "type": "string" },
"sha": { "type": "string" },
"ref": { "type": "string" },
"workflow": { "type": "string" },
"run_id": { "type": "integer" }
}
}
}
}