Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Add `codex-maintainer-kit audit` for OSS maintenance health scoring and prioritized next actions.
- Improve generated issue drafts with suggested labels, verification commands, and maintainer checklists.
- Add a human-reviewed release workflow for Codex-assisted maintenance releases.
- Add Java, .NET, and Swift project hint detection.
Expand Down
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Codex can help with that work, but it needs clear repository context and human r
- Detects common maintainer files such as `README.md`, `LICENSE`, `CONTRIBUTING.md`, `SECURITY.md`, `AGENTS.md`, issue templates, CI workflows, and tests.
- Detects simple project hints such as Python, JavaScript, Go, Rust, Ruby, PHP, Java, .NET, and Swift markers.
- Summarizes current Git working-tree changes.
- Generates an OSS maintenance audit with a health score, maintainer essentials checklist, and prioritized next actions.
- Generates a Markdown maintainer brief with:
- repository readiness checklist
- Codex task queue
Expand Down Expand Up @@ -55,6 +56,12 @@ The action runs this CLI and uploads `MAINTAINER_BRIEF.md`, `CODEX_TASKS.md`, an

## Usage

Generate an OSS maintenance audit:

```bash
codex-maintainer-kit audit /path/to/repo --output OSS_MAINTENANCE_AUDIT.md
```

Generate a maintainer brief:

```bash
Expand Down Expand Up @@ -117,6 +124,7 @@ Existing files are skipped unless `--force` is passed.

See:

- [examples/OSS_MAINTENANCE_AUDIT.generated.md](examples/OSS_MAINTENANCE_AUDIT.generated.md), generated from this repository
- [examples/MAINTAINER_BRIEF.example.md](examples/MAINTAINER_BRIEF.example.md)
- [examples/MAINTAINER_BRIEF.generated.md](examples/MAINTAINER_BRIEF.generated.md), generated from this repository
- [examples/CODEX_TASKS.example.md](examples/CODEX_TASKS.example.md)
Expand Down Expand Up @@ -145,13 +153,14 @@ Codex Maintainer Kit focuses on a narrower workflow: creating a practical mainte

## Maintainer Workflow

1. Run `codex-maintainer-kit brief`, or run `codex-maintainer-action` in GitHub Actions.
2. Review the generated checklist.
3. Run `codex-maintainer-kit tasks`.
4. Convert the generated task file or issue drafts into scoped maintenance work.
5. Ask Codex to make the smallest useful change.
6. Run tests and inspect the diff.
7. Merge only after human review.
1. Run `codex-maintainer-kit audit` to understand the repository's maintenance health.
2. Run `codex-maintainer-kit brief`, or run `codex-maintainer-action` in GitHub Actions.
3. Review the generated checklist.
4. Run `codex-maintainer-kit tasks`.
5. Convert the generated task file or issue drafts into scoped maintenance work.
6. Ask Codex to make the smallest useful change.
7. Run tests and inspect the diff.
8. Merge only after human review.

## Development

Expand All @@ -165,6 +174,7 @@ Run the CLI without installing:

```bash
PYTHONPATH=src python3 -m codex_maintainer_kit.cli brief . --output /tmp/maintainer-brief.md
PYTHONPATH=src python3 -m codex_maintainer_kit.cli audit . --output /tmp/oss-maintenance-audit.md
PYTHONPATH=src python3 -m codex_maintainer_kit.cli tasks . --output /tmp/codex-tasks.md
```

Expand Down
52 changes: 52 additions & 0 deletions docs/superpowers/plans/2026-06-15-audit-command.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Audit Command Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Add an `audit` command that generates a practical OSS maintenance health report.

**Architecture:** Keep scanning in `scanner.py`, add audit scoring and report rendering in a new `audit.py`, and wire the CLI in `cli.py`. The audit report reuses existing repository facts and gives maintainers a prioritized next-step summary.

**Tech Stack:** Python 3.9+, argparse, pytest.

---

### Task 1: Audit Report Contract

**Files:**
- Create: `tests/test_audit.py`
- Modify: `tests/test_cli.py`

- [ ] Write failing tests for audit item classification, summary score, Markdown rendering, and CLI file output.
- [ ] Run targeted tests and confirm they fail because `codex_maintainer_kit.audit` and the CLI command do not exist.

### Task 2: Audit Implementation

**Files:**
- Create: `src/codex_maintainer_kit/audit.py`
- Modify: `src/codex_maintainer_kit/cli.py`

- [ ] Add `AuditItem` and `AuditReport` dataclasses.
- [ ] Add `build_audit_report(scan)` with weighted checks for maintainer essentials.
- [ ] Add `render_audit_markdown(report)` with score, status summary, prioritized next actions, and Codex prompt.
- [ ] Add `codex-maintainer-kit audit` with optional `--output`.
- [ ] Run targeted tests until they pass.

### Task 3: Public Documentation

**Files:**
- Modify: `README.md`
- Modify: `CHANGELOG.md`
- Create: `examples/OSS_MAINTENANCE_AUDIT.generated.md`

- [ ] Document the `audit` command and how it fits before `brief` and `tasks`.
- [ ] Generate an example audit report from this repository.
- [ ] Update changelog with the unreleased audit feature.

### Task 4: Verification

**Files:**
- All changed files.

- [ ] Run `python3 -m pytest -p no:cacheprovider tests -q`.
- [ ] Run the new CLI command against this repository.
- [ ] Review `git diff --check` and `git status --short`.
33 changes: 33 additions & 0 deletions examples/OSS_MAINTENANCE_AUDIT.generated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# OSS Maintenance Audit

Repository: `/Users/admin/Documents/skill/codex-maintainer-kit`
Project hints: python
Git state: `clean`
Health score: **100/100** (`ready`)

## Maintainer Essentials

| Check | Status | Priority | Why it matters |
| --- | --- | --- | --- |
| LICENSE | ready | high | Users need clear reuse rights before they can adopt or contribute to the project. |
| AGENTS.md | ready | high | Codex and other agents need repository rules, commands, and human review boundaries. |
| Test suite | ready | high | Automated tests let maintainers verify AI-assisted changes before merge. |
| README | ready | medium | A useful README explains purpose, setup, usage, and the maintainer workflow. |
| CI workflow | ready | medium | CI catches regressions and gives contributors fast feedback. |
| CONTRIBUTING | ready | medium | Contribution docs reduce maintainer back-and-forth and clarify expectations. |
| SECURITY | ready | medium | Security reporting instructions keep sensitive reports out of public issues. |
| Issue templates | ready | low | Templates turn vague reports into actionable maintenance work. |
| CHANGELOG | ready | low | Release notes help users understand what changed and whether to upgrade. |
| CODE_OF_CONDUCT | ready | low | Community expectations help public projects handle collaboration consistently. |

## Prioritized Next Actions

- [ ] Run a focused Codex maintenance review for stale docs, missing edge-case tests, and small safe improvements.

## Suggested Codex Prompt

Review this OSS maintenance audit. Pick the highest-priority missing item, make the smallest useful change, run the documented verification command, and leave a concise maintainer note explaining the tradeoff and risk.

## Human Review Rule

Do not auto-merge AI-generated maintenance changes. A human maintainer must review the diff, confirm the project policy choices, and verify the result before merge.
196 changes: 196 additions & 0 deletions src/codex_maintainer_kit/audit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
from __future__ import annotations

from dataclasses import dataclass

from codex_maintainer_kit.scanner import RepositoryScan


@dataclass(frozen=True)
class AuditCheck:
key: str
label: str
weight: int
priority: str
why_it_matters: str
next_action: str


@dataclass(frozen=True)
class AuditItem:
label: str
status: str
priority: str
why_it_matters: str
next_action: str


@dataclass(frozen=True)
class AuditReport:
repository: str
project_hints: list[str]
git_state: str
score: int
status: str
items: list[AuditItem]
next_actions: list[str]


AUDIT_CHECKS = [
AuditCheck(
key="license",
label="LICENSE",
weight=14,
priority="high",
why_it_matters="Users need clear reuse rights before they can adopt or contribute to the project.",
next_action="Add LICENSE: choose the intended license and update README references if needed.",
),
AuditCheck(
key="agents",
label="AGENTS.md",
weight=12,
priority="high",
why_it_matters="Codex and other agents need repository rules, commands, and human review boundaries.",
next_action="Add AGENTS.md: document setup, test commands, coding rules, and the human review rule.",
),
AuditCheck(
key="tests",
label="Test suite",
weight=12,
priority="high",
why_it_matters="Automated tests let maintainers verify AI-assisted changes before merge.",
next_action="Add Test Suite: cover the smallest public behavior users rely on.",
),
AuditCheck(
key="readme",
label="README",
weight=11,
priority="medium",
why_it_matters="A useful README explains purpose, setup, usage, and the maintainer workflow.",
next_action="Update README: add purpose, install steps, usage examples, and verification commands.",
),
AuditCheck(
key="ci",
label="CI workflow",
weight=11,
priority="medium",
why_it_matters="CI catches regressions and gives contributors fast feedback.",
next_action="Add CI Workflow: run the documented test command on pull requests.",
),
AuditCheck(
key="contributing",
label="CONTRIBUTING",
weight=10,
priority="medium",
why_it_matters="Contribution docs reduce maintainer back-and-forth and clarify expectations.",
next_action="Add CONTRIBUTING: document setup, tests, PR expectations, and AI-assisted contribution rules.",
),
AuditCheck(
key="security",
label="SECURITY",
weight=10,
priority="medium",
why_it_matters="Security reporting instructions keep sensitive reports out of public issues.",
next_action="Add SECURITY: explain how to report vulnerabilities and what is in scope.",
),
AuditCheck(
key="issue_templates",
label="Issue templates",
weight=8,
priority="low",
why_it_matters="Templates turn vague reports into actionable maintenance work.",
next_action="Add Issue Templates: include expected behavior, context, and verification fields.",
),
AuditCheck(
key="changelog",
label="CHANGELOG",
weight=7,
priority="low",
why_it_matters="Release notes help users understand what changed and whether to upgrade.",
next_action="Add CHANGELOG: record the current release state without claiming future work.",
),
AuditCheck(
key="code_of_conduct",
label="CODE_OF_CONDUCT",
weight=5,
priority="low",
why_it_matters="Community expectations help public projects handle collaboration consistently.",
next_action="Add CODE_OF_CONDUCT: set basic contribution behavior and maintainer response expectations.",
),
]


def build_audit_report(scan: RepositoryScan) -> AuditReport:
total_weight = sum(check.weight for check in AUDIT_CHECKS)
earned_weight = sum(check.weight for check in AUDIT_CHECKS if scan.files.get(check.key, False))
score = round((earned_weight / total_weight) * 100)
items = [_build_item(scan, check) for check in AUDIT_CHECKS]
next_actions = [item.next_action for item in items if item.status == "missing"][:5]
if not next_actions:
next_actions = ["Run a focused Codex maintenance review for stale docs, missing edge-case tests, and small safe improvements."]

return AuditReport(
repository=str(scan.root),
project_hints=scan.project_hints,
git_state=scan.git_state.status,
score=score,
status=_status_for_score(score),
items=items,
next_actions=next_actions,
)


def render_audit_markdown(report: AuditReport) -> str:
lines = [
"# OSS Maintenance Audit",
"",
f"Repository: `{report.repository}`",
f"Project hints: {', '.join(report.project_hints)}",
f"Git state: `{report.git_state}`",
f"Health score: **{report.score}/100** (`{report.status}`)",
"",
"## Maintainer Essentials",
"",
"| Check | Status | Priority | Why it matters |",
"| --- | --- | --- | --- |",
]

for item in report.items:
lines.append(f"| {item.label} | {item.status} | {item.priority} | {item.why_it_matters} |")

lines.extend(["", "## Prioritized Next Actions", ""])
for action in report.next_actions:
lines.append(f"- [ ] {action}")

lines.extend(
[
"",
"## Suggested Codex Prompt",
"",
"Review this OSS maintenance audit. Pick the highest-priority missing item, make the smallest useful change, run the documented verification command, and leave a concise maintainer note explaining the tradeoff and risk.",
"",
"## Human Review Rule",
"",
"Do not auto-merge AI-generated maintenance changes. A human maintainer must review the diff, confirm the project policy choices, and verify the result before merge.",
"",
]
)
return "\n".join(lines)


def _build_item(scan: RepositoryScan, check: AuditCheck) -> AuditItem:
present = scan.files.get(check.key, False)
return AuditItem(
label=check.label,
status="ready" if present else "missing",
priority=check.priority,
why_it_matters=check.why_it_matters,
next_action=check.next_action,
)


def _status_for_score(score: int) -> str:
if score >= 90:
return "ready"
if score >= 70:
return "mostly-ready"
return "needs-work"
20 changes: 20 additions & 0 deletions src/codex_maintainer_kit/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pathlib import Path
import sys

from codex_maintainer_kit.audit import build_audit_report, render_audit_markdown
from codex_maintainer_kit.config import load_config
from codex_maintainer_kit.renderer import render_maintenance_brief
from codex_maintainer_kit.scanner import scan_repository
Expand Down Expand Up @@ -56,6 +57,8 @@ def main(argv: list[str] | None = None) -> int:
parser = _build_parser()
args = parser.parse_args(argv)

if args.command == "audit":
return _audit(args)
if args.command == "brief":
return _brief(args)
if args.command == "init":
Expand All @@ -74,6 +77,10 @@ def _build_parser() -> argparse.ArgumentParser:
)
subparsers = parser.add_subparsers(dest="command")

audit = subparsers.add_parser("audit", help="Generate an OSS maintenance health audit.")
audit.add_argument("repo", nargs="?", default=".", help="Repository path to inspect.")
audit.add_argument("--output", "-o", help="Write Markdown to this file instead of stdout.")

brief = subparsers.add_parser("brief", help="Generate a Codex-ready maintainer brief.")
brief.add_argument("repo", nargs="?", default=".", help="Repository path to inspect.")
brief.add_argument("--output", "-o", help="Write Markdown to this file instead of stdout.")
Expand All @@ -91,6 +98,19 @@ def _build_parser() -> argparse.ArgumentParser:
return parser


def _audit(args: argparse.Namespace) -> int:
scan = scan_repository(args.repo)
report = build_audit_report(scan)
markdown = render_audit_markdown(report)
if args.output:
output = Path(args.output)
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(markdown, encoding="utf-8")
else:
print(markdown)
return 0


def _brief(args: argparse.Namespace) -> int:
scan = scan_repository(args.repo)
markdown = render_maintenance_brief(scan)
Expand Down
Loading
Loading