Add govkit-metrics-emit skill (Tier 1 metric event producer)#2
Conversation
New skill under the govkit plugin: an org-agnostic producer that reads GovKit exhaust (feature packages, .govkit/marker.json, git history, and optional CI-run / PR exports) and emits NDJSON metric events per the AIPOS tier1_metrics_catalog v1 vocabulary. - scripts/emit_metrics.py: bundled producer (5 event types, --validate) - references/event_schema.md: event vocabulary + spec-completeness rubric - evals/evals.json: gate-readiness, aggregator-export, org-agnostic checks (fixture at /tmp/testrepo is supplied by the external eval harness) - Bump govkit plugin version 0.1.0 -> 0.2.0 so installed users receive it Validated: claude plugin validate passes; producer runs end-to-end against a fixture and reproduces the evals' expected outputs (completeness 100 / 15, AI-assisted PR detection, 10-event stream with clean --validate). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The govkit plugin now bundles Python skill scripts (govkit-metrics-emit), so ignore __pycache__/, compiled bytecode, and .pytest_cache/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR Summary by QodoAdd govkit-metrics-emit skill to emit Tier 1 metric NDJSON events
AI Description
Diagram
High-Level Assessment
Files changed (5)
|
Code Review by Qodo
1.
|
| overlap = set(c["files"]) & set(later["files"]) | ||
| for fname in overlap: | ||
| reworked += min(c["files"][fname]["added"], | ||
| later["files"][fname]["deleted"]) | ||
| if later["author"] == c["author"]: | ||
| same_author = True |
There was a problem hiding this comment.
4. Same-author rework misflag 🐞 Bug ≡ Correctness
rework_events() sets rework_author_same=true whenever any later overlapping commit is by the same author, even if that later commit contributes zero deletions (i.e., no rework under this approximation). This inflates the self-rework signal.
Agent Prompt
## Issue description
`rework_author_same` is marked true even when there is no deletion overlap (no rework counted), because the flag is set based solely on author match, not on whether rework was attributed.
## Issue Context
Under the file-overlap approximation, “rework” is represented by later deletions in files the origin commit added to.
## Fix Focus Areas
- plugins/govkit/skills/govkit-metrics-emit/scripts/emit_metrics.py[328-356]
## Suggested fix
- Only set `same_author = True` when the later commit both:
- matches the author, and
- contributes a positive deletion overlap (e.g., `later_deleted > 0` and/or `min(...) > 0`).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| def validate(events: list) -> dict: | ||
| summary = {"total": len(events), "by_event": {}, "errors": []} | ||
| for i, e in enumerate(events): | ||
| name = e.get("event") | ||
| summary["by_event"][name] = summary["by_event"].get(name, 0) + 1 | ||
| if name not in EVENT_FIELDS: | ||
| summary["errors"].append(f"event {i}: unknown event '{name}'") | ||
| continue | ||
| allowed = EVENT_FIELDS[name] | ENVELOPE_FIELDS | ||
| unknown = set(e) - allowed | ||
| if unknown: | ||
| summary["errors"].append( | ||
| f"event {i} ({name}): unknown fields {sorted(unknown)}") | ||
| missing_env = ENVELOPE_FIELDS - set(e) | ||
| if missing_env: | ||
| summary["errors"].append( | ||
| f"event {i} ({name}): missing envelope {sorted(missing_env)}") | ||
| summary["valid"] = not summary["errors"] | ||
| return summary |
There was a problem hiding this comment.
5. Validation scope mismatch 🐞 Bug ⚙ Maintainability
SKILL.md claims --validate reports pairing coverage, but validate() only checks unknown top-level fields and missing envelope keys. This can provide false confidence because required payload fields, types, and null-vs-string mismatches are not checked.
Agent Prompt
## Issue description
The documented `--validate` behavior promises more than the current implementation provides. As implemented, validation does not check required per-event fields, field types, nullability, or any "pairing coverage" concept.
## Issue Context
Users may rely on `--validate` as a quality gate before exporting events to an aggregator.
## Fix Focus Areas
- plugins/govkit/skills/govkit-metrics-emit/SKILL.md[44-49]
- plugins/govkit/skills/govkit-metrics-emit/scripts/emit_metrics.py[361-415]
## Suggested fix
Pick one:
1) Implement what the docs promise:
- Add required-field checks per event (presence + non-null where required).
- Add basic type checks (e.g., strings for timestamps/SHAs).
- Implement and report "pairing coverage" (or remove that term if not applicable).
2) Narrow the documentation to exactly what is validated today (unknown fields + envelope only).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Three defensive fixes from code review: - evaluation_prediction: accept only a dict value from the plan.md YAML block. A scalar/list (e.g. `evaluation_prediction: TBD`) no longer crashes completeness()/snapshot with AttributeError — it is treated as absent. Added a belt-and-suspenders dict guard in completeness(). - feature.package.snapshot commit_sha/ts: fall back to repo HEAD when a feature has no path-specific commit yet, keeping them non-null strings per the event vocabulary. validate() now flags null/empty commit_sha/ts, so --validate fails for a repo with no commits. Schema doc updated. - --ci-runs / --prs: load via load_json_list(), which turns a missing or unreadable file, invalid JSON, or a non-array top level into a concise stderr message and exit 2 instead of a stack trace. Verified: fixture regression unchanged (completeness 100/15, 10-event stream, valid: true); targeted repro cases for all three issues pass; claude plugin validate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Adds a second skill to the
govkitplugin:govkit-metrics-emit, an org-agnostic producer that reads GovKit exhaust (feature packages,.govkit/marker.json, git history, and optional CI-run / PR JSON exports) and emits NDJSON metric events per the AIPOStier1_metrics_catalogv1 vocabulary. Aggregation stays out of scope by design — producers stay org-agnostic.Contents:
SKILL.md— usage, the org-agnostic law, event vocabulary, interpretation guidancescripts/emit_metrics.py— the bundled producer (5 event types,--validatemode)references/event_schema.md— event field definitions + spec-completeness rubricevals/evals.json— gate-readiness, aggregator-export, and org-agnostic checksAlso:
govkitpluginversion0.1.0 → 0.2.0 so installed users receive the new skill (per CONTRIBUTING).__pycache__/,*.py[cod],.pytest_cache/) to.gitignore, since the plugin now ships Python.Validation
claude plugin validate .passes.checkout_assistantcompleteness = 100,incomplete_feature= 15 (with named missing components), PR AI-assisted detection true/false viaCo-Authored-Bytrailers, a 10-event stream (2 snapshot / 2 rework / 4 gate / 2 PR), non-gate CI runs filtered out, and--validatereturnsvalid: true.Notes
/tmp/testrepopath inevals/evals.jsonis intentional — an external eval harness populates that fixture at run time; it is not a bundled fixture.🤖 Generated with Claude Code