From 4682a235ab33e6733301f89c8bea1bf0a8ea12c1 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Wed, 6 May 2026 13:53:37 -0700 Subject: [PATCH] import from local vendored copy (2026-05-06) --- .github/workflows/ci.yml | 5 ++ .gitignore | 21 ++++++ .molecule-ci/scripts/requirements.txt | 1 + .molecule-ci/scripts/validate-plugin.py | 46 ++++++++++++ CLAUDE.md | 93 +++++++++++++++++++++++++ README.md | 19 +++++ adapters/__init__.py | 0 adapters/claude_code.py | 2 + commands/retro.md | 41 +++++++++++ known-issues.md | 54 ++++++++++++++ plugin.yaml | 14 ++++ runbooks/local-dev-setup.md | 69 ++++++++++++++++++ skills/cron-retro/SKILL.md | 69 ++++++++++++++++++ 13 files changed, 434 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .molecule-ci/scripts/requirements.txt create mode 100644 .molecule-ci/scripts/validate-plugin.py create mode 100644 CLAUDE.md create mode 100644 README.md create mode 100644 adapters/__init__.py create mode 100644 adapters/claude_code.py create mode 100644 commands/retro.md create mode 100644 known-issues.md create mode 100644 plugin.yaml create mode 100644 runbooks/local-dev-setup.md create mode 100644 skills/cron-retro/SKILL.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c8fb9d3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,5 @@ +name: CI +on: [push, pull_request] +jobs: + validate: + uses: Molecule-AI/molecule-ci/.github/workflows/validate-plugin.yml@main diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2af45b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Credentials — never commit. Use .env.example as the template. +.env +.env.local +.env.*.local +.env.* +!.env.example +!.env.sample + +# Private keys + certs +*.pem +*.key +*.crt +*.p12 +*.pfx + +# Secret directories +.secrets/ + +# Workspace auth tokens +.auth-token +.auth_token diff --git a/.molecule-ci/scripts/requirements.txt b/.molecule-ci/scripts/requirements.txt new file mode 100644 index 0000000..3aecde9 --- /dev/null +++ b/.molecule-ci/scripts/requirements.txt @@ -0,0 +1 @@ +pyyaml>=6.0 diff --git a/.molecule-ci/scripts/validate-plugin.py b/.molecule-ci/scripts/validate-plugin.py new file mode 100644 index 0000000..318239f --- /dev/null +++ b/.molecule-ci/scripts/validate-plugin.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Validate a Molecule AI plugin repo.""" +import os, sys, yaml + +errors = [] + +if not os.path.isfile("plugin.yaml"): + print("::error::plugin.yaml not found at repo root") + sys.exit(1) + +with open("plugin.yaml") as f: + plugin = yaml.safe_load(f) + +for field in ["name", "version", "description"]: + if not plugin.get(field): + errors.append(f"Missing required field: {field}") + +v = str(plugin.get("version", "")) +if v and not all(c in "0123456789." for c in v): + errors.append(f"Invalid version format: {v}") + +runtimes = plugin.get("runtimes") +if runtimes is not None and not isinstance(runtimes, list): + errors.append(f"runtimes must be a list, got {type(runtimes).__name__}") + +content_paths = ["SKILL.md", "hooks", "skills", "rules"] +found = [p for p in content_paths if os.path.exists(p)] +if not found: + errors.append("Plugin must contain at least one of: SKILL.md, hooks/, skills/, rules/") + +if os.path.isfile("SKILL.md"): + with open("SKILL.md") as f: + first_line = f.readline().strip() + if first_line and not first_line.startswith("#"): + print("::warning::SKILL.md should start with a markdown heading (e.g., # Plugin Name)") + +if errors: + for e in errors: + print(f"::error::{e}") + sys.exit(1) + +print(f"✓ plugin.yaml valid: {plugin['name']} v{plugin['version']}") +if found: + print(f" Content: {', '.join(found)}") +if runtimes: + print(f" Runtimes: {', '.join(runtimes)}") diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..0f146ec --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,93 @@ +# molecule-workflow-retro — Weekly Retrospective Generator + +`molecule-workflow-retro` provides the `/retro` slash command — a weekly +retrospective generator. It reads from `molecule-cron-learnings` JSONL files +and synthesises a structured retro: what went well, what didn't, and action items. + +**Version:** 1.0.0 +**Runtime:** `claude_code` + +--- + +## Repository Layout + +``` +molecule-workflow-retro/ +├── plugin.yaml — Plugin manifest +├── skills/ +│ └── cron-retro/ +│ └── SKILL.md — Retro synthesis skill +└── commands/ + └── retro.md — /retro slash command +``` + +--- + +## What It Does + +### The /retro Command + +Run `/retro` in any Claude Code session to generate a weekly retrospective. +It reads learnings from `~/.claude/projects//cron-learnings.jsonl` +and produces: + +- **What went well**: Patterns across positive learnings +- **What didn't**: Patterns across negative learnings +- **Action items**: Concrete next steps for the next week + +### Prerequisites + +Install `molecule-cron-learnings` first — the retro reads learnings that must +be written by the cron-learnings plugin each tick. + +--- + +## Development + +### Prerequisites + +- Python 3.11+ +- `gh` CLI authenticated +- Write access to `Molecule-AI/molecule-ai-plugin-molecule-workflow-retro` + +### Setup + +```bash +git clone https://github.com/Molecule-AI/molecule-ai-plugin-molecule-workflow-retro.git +cd molecule-ai-plugin-molecule-workflow-retro + +python3 -c "import yaml; yaml.safe_load(open('plugin.yaml'))" +``` + +### Pre-Commit Checklist + +```bash +python3 -c "import yaml; yaml.safe_load(open('plugin.yaml'))" + +python3 -c " +import re, sys +with open('plugin.yaml') as f: + content = f.read() +patterns = [r'sk.ant', r'ghp.', r'AKIA[A-Z0-9]'] +if any(re.search(p, content) for p in patterns): + print('FAIL: possible credentials found') + sys.exit(1) +print('No credentials: OK') +" +``` + +--- + +## Release Process + +1. Review changes: `git log origin/main..HEAD --oneline` +2. Bump `version` in `plugin.yaml` (semver) +3. Commit: `chore: bump version to X.Y.Z` +4. Tag and push: `git tag vX.Y.Z && git push origin main --tags` +5. Create GitHub Release with changelog + +--- + +## Known Issues + +See `known-issues.md` at the repo root. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1e141dd --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# molecule-workflow-retro + +Molecule AI plugin. Install via the Molecule AI platform plugin system. + +## Usage + +### In org template (org.yaml) +```yaml +plugins: + - molecule-workflow-retro +``` + +### From URL (community install) +``` +github://Molecule-AI/molecule-ai-plugin-molecule-workflow-retro +``` + +## License +Business Source License 1.1 — © Molecule AI. diff --git a/adapters/__init__.py b/adapters/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/adapters/claude_code.py b/adapters/claude_code.py new file mode 100644 index 0000000..cc58993 --- /dev/null +++ b/adapters/claude_code.py @@ -0,0 +1,2 @@ +"""Claude Code adaptor — uses the generic rule+skill+hooks installer.""" +from plugins_registry.builtins import AgentskillsAdaptor as Adaptor # noqa: F401 diff --git a/commands/retro.md b/commands/retro.md new file mode 100644 index 0000000..78f11bc --- /dev/null +++ b/commands/retro.md @@ -0,0 +1,41 @@ +--- +name: retro +description: Generate a weekly retrospective digest — PRs merged, gate failures, code-review severity trend, time-to-merge, issues picked up. Posts as a GitHub issue. +--- + +# /retro + +Weekly retrospective on cron + agent activity. Default cadence: Sundays +23:00 local. Manual invocation on demand. + +## Steps + +1. Compute over the prior 7 days: + - Merged PR count (total + by category) + - Issues closed (with PR-link for each) + - Time-to-merge: median, p90, max — exclude docs PRs + - Gate failure breakdown (which gates, how often) + - Code-review findings: total 🔴/🟡/🔵, trend vs prior week + - Mechanical fixes pushed (count) + - Skips by reason: design-judgment / CI-down / scope-too-open / noteworthy-CEO-needed + - Code volume: net LOC added/removed + - Test count delta (Go + Python + Vitest + Jest) + - New runtime / library / tool added or removed + +2. Format per the `cron-retro` skill template. + +3. Post as a new GitHub issue titled + `Cron retro: (week N)` with labels `meta`, `retro`. + +4. If trends are bad (gate failure rate up, 🔴 findings appearing, + time-to-merge >50% increase), flag prominently in the body and + @-mention the workspace owner. + +5. Skip new-issue creation if the prior 7 days had < 3 merged PRs; + post a one-liner in the latest weekly retro issue's comments instead. + +## Standing rules +- careful-mode applies — don't mass-close stale issues, don't delete + prior retros +- The retro is observational, not actionable — propose 2-3 follow-ups + for the user but never auto-create them diff --git a/known-issues.md b/known-issues.md new file mode 100644 index 0000000..1885d8e --- /dev/null +++ b/known-issues.md @@ -0,0 +1,54 @@ +# Known Issues — molecule-workflow-retro + +--- + +## Active Issues + +*(None currently open. This section is updated when issues are filed.)* + +--- + +## Recently Resolved + +*(No recently resolved issues.)* + +--- + +## How to Update This File + +When a new issue is identified: +1. Add it under **Active Issues** using the template below +2. Include: symptom, cause (if known), workaround +3. When fixed, move to **Recently Resolved** and note the fix version + +### Issue Template + +```markdown +## [TICKET-NUMBER] + +**Severity:** P0 / P1 / P2 / P3 +**Status:** Workaround / Fix in progress / Fix available +**Affected versions:** All / vX.Y.Z+ + +**Symptoms:** +**Cause:** +**Workaround:** +**Fix (if available):** +``` + +--- + +## Severity Definitions + +| Level | Description | +|---|---| +| P0 | Retro produces no output despite learnings existing | +| P1 | Retro reads wrong workspace's learnings | +| P2 | Action items missing or miscategorised | +| P3 | Cosmetic or documentation issue | + +--- + +## Reporting + +Use the Molecule-AI/internal issue tracker. Tag with `plugin-molecule-workflow-retro`. diff --git a/plugin.yaml b/plugin.yaml new file mode 100644 index 0000000..58ad993 --- /dev/null +++ b/plugin.yaml @@ -0,0 +1,14 @@ +name: molecule-workflow-retro +version: 1.0.0 +description: Provides /retro slash command — weekly retrospective generator. Recommends installing molecule-skill-cron-learnings first. +author: Molecule AI +tags: [molecule, guardrails] + +runtimes: + - claude_code + +skills: + - cron-retro + +commands: + - retro diff --git a/runbooks/local-dev-setup.md b/runbooks/local-dev-setup.md new file mode 100644 index 0000000..1cd67cd --- /dev/null +++ b/runbooks/local-dev-setup.md @@ -0,0 +1,69 @@ +# Local Development Setup + +This runbook covers setting up a local development environment for +`molecule-workflow-retro`. + +--- + +## Prerequisites + +- Python 3.11+ +- `gh` CLI authenticated +- Write access to `Molecule-AI/molecule-ai-plugin-molecule-workflow-retro` + +--- + +## Clone & Bootstrap + +```bash +git clone https://github.com/Molecule-AI/molecule-ai-plugin-molecule-workflow-retro.git +cd molecule-ai-plugin-molecule-workflow-retro +``` + +--- + +## Validating Plugin Structure + +```bash +python3 -c "import yaml; yaml.safe_load(open('plugin.yaml'))" +echo "plugin.yaml OK" +``` + +--- + +## Testing the Retro Skill + +The harness wrapper is provided by the Molecule AI platform at runtime. +To test: + +1. Install `molecule-cron-learnings` first (prerequisite) +2. Install `molecule-workflow-retro` in a test workspace +3. Add mock learnings to `~/.claude/projects//cron-learnings.jsonl`: + ```jsonl + {"tick": "2026-04-21T00:00Z", "role": "sdk-lead", "learnings": ["CI timeout was 2min — too short for integration tests"]} + {"tick": "2026-04-21T01:00Z", "role": "sdk-lead", "learnings": ["PR template now has Testing section"]} + ``` +4. Run `/retro` and verify output has three sections (went well, didn't, actions) + +--- + +## Troubleshooting + +### Retro has no learnings to synthesise + +- Verify `molecule-cron-learnings` is installed and writing to the JSONL file +- Check the path `~/.claude/projects//cron-learnings.jsonl` exists +- If the project directory is wrong, check the workspace config + +### Empty action items + +- The retro needs at least one "what didn't" learning to generate action items +- Add more learnings or check the learnings parser + +--- + +## Related + +- `molecule-cron-learnings` — prerequisite; writes learnings each tick +- `skills/cron-retro/SKILL.md` — retro synthesis skill +- `commands/retro.md` — /retro slash command diff --git a/skills/cron-retro/SKILL.md b/skills/cron-retro/SKILL.md new file mode 100644 index 0000000..579ae3e --- /dev/null +++ b/skills/cron-retro/SKILL.md @@ -0,0 +1,69 @@ +--- +name: cron-retro +description: Weekly retrospective digest of cron activity — PRs merged, gates failed, issues picked, code-review findings by severity, time-to-merge, regression trend. Posts to a dedicated GitHub issue. Inspired by gstack's /retro. +--- + +# cron-retro + +The cron runs hourly and ships a lot. Without a periodic summary, drift happens silently — Gate 4 starts failing more often, code-review noise climbs, time-to-merge balloons, and nobody notices for weeks. + +## When to run + +- Every Sunday at 23:00 local (`0 23 * * 0` cron expression) +- On-demand by the CEO + +## What to compute (over the prior 7 days) + +From `gh pr list --state merged --search "merged:>=YYYY-MM-DD"` and our local `cron-learnings.jsonl`: + +1. **Merged PR count** — total + by category (auth/security, refactor, feat, fix, docs, infra) +2. **Issues closed** — count, with PR-link for each +3. **Time-to-merge distribution** — median, p90, max. Excluding docs PRs (they merge instantly). +4. **Gate failure breakdown** — which gates failed how often. Patterns? +5. **Code-review findings** — total 🔴 / 🟡 / 🔵 across all PRs. Trend vs prior week. +6. **Mechanical fixes pushed** — how often did the cron fix a gate failure on-branch? +7. **Skips by reason** — categorize: design-judgment, CI-down, scope-too-open, noteworthy-CEO-needed +8. **Code volume** — net LOC added/removed (Garry Tan publishes these in his retros — keep us honest) +9. **Test count delta** — Go + Python + Vitest + Jest from start to end of week +10. **New runtime / library / tool added or removed** — anything strategic + +## Format + +Post a new GitHub issue titled `Cron retro: 2026-04-14 → 2026-04-21 (week N)` with body: + +```markdown +# Week summary +- Merged: X PRs (Y closed issues) +- Median TTM: 3h12m (excluding docs) +- Code-review findings: 0 🔴 / 4 🟡 / 18 🔵 (vs last week: 0 / 6 / 24) +- Mechanical fixes pushed: 5 +- Skips: 2 design-judgment, 1 CI-down + +# Trend signals +- ↑ Frontend test coverage (+12 vitest, +1 file) +- ↓ Time-to-merge for auth PRs (down from 8h median to 3h — likely + because Gate-4 doc-sync subagent now catches missing .env entries) +- ⚠ Gate 7 (Playwright) failed 3 times this week vs 0 last week — + probably the canvas dev-server stale-chunk issue. Action item. + +# Code volume +- 12,847 lines added, 8,213 removed across 23 commits + +# Notes +- Closed #6, #13, #17, #23 — 4 issues from the launch backlog +- 2 issues remain in the SaaS-launch Tier 1 list (multi-tenancy, Fly Machines) +- New skills added this week: cross-vendor-review, careful-mode, cron-learnings, cron-retro + +# Action items for next week +- [ ] Investigate Gate 7 flakes (likely fix: persistent canvas dev daemon) +- [ ] Pick up issue #19 (workspace restart context) +- [ ] PR #58 needs CEO review (configurable tier limits — behavior change) +``` + +## Why this exists + +What gets measured improves. gstack publishes weekly retros and credits them with knowing where to invest. We have no analog. This is the smallest viable analog: one issue per week, generated automatically, costs nothing to ignore, valuable when the metrics start drifting. + +## Implementation note + +This skill should be invoked from a separate cron job (not the hourly triage cron). Suggested cron expression: `7 23 * * 0` — Sunday 23:07 local.