import from local vendored copy (2026-05-06)
Some checks failed
CI / validate (push) Failing after 0s

This commit is contained in:
Hongming Wang 2026-05-06 13:53:38 -07:00
commit d709f75edb
13 changed files with 491 additions and 0 deletions

5
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,5 @@
name: CI
on: [push, pull_request]
jobs:
validate:
uses: Molecule-AI/molecule-ci/.github/workflows/validate-plugin.yml@main

21
.gitignore vendored Normal file
View File

@ -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

View File

@ -0,0 +1 @@
pyyaml>=6.0

View File

@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""Validate a Molecule AI plugin repo."""
import os, sys, yaml
errors = []
# 1. plugin.yaml exists
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)
# 2. Required fields
for field in ["name", "version", "description"]:
if not plugin.get(field):
errors.append(f"Missing required field: {field}")
# 3. Version format
v = str(plugin.get("version", ""))
if v and not all(c in "0123456789." for c in v):
errors.append(f"Invalid version format: {v}")
# 4. Runtimes type
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__}")
# 5. Has content
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/")
# 6. SKILL.md formatting check
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)}")

112
CLAUDE.md Normal file
View File

@ -0,0 +1,112 @@
# molecule-ai-plugin-molecule-workflow-triage
Provides the `/triage` slash command — a full on-demand PR-triage cycle
comprising 7-gate verification, mechanical fixes, code review, cross-vendor
review, merge, docs sync, and issue pickup. Equivalent to one hourly cron tick,
triggered manually.
**Version:** 1.0.0
**Runtime:** `claude_code`
**Command:** `/triage`
**Skill:** `triage-workflow`
---
## What It Does
`/triage` runs the same workflow as the hourly cron tick, on demand:
1. **Activate guards** — load `careful-mode` REFUSE/WARN/ALLOW lists; replay last 20 cron-learnings.
2. **List open PRs and issues** — via `gh pr list` and `gh issue list`.
3. **7-gate verification per PR:**
- Gate 1: CI status
- Gate 2: Build
- Gate 3: Tests
- Gate 4: Security
- Gate 5: Design review
- Gate 6: Line review
- Gate 7: Playwright (UI PRs only)
- Supplement A: `code-review` skill
- Supplement B: `cross-vendor-review` for noteworthy PRs (auth/billing/data-deletion/migration)
4. **Mechanical fixes on-branch** — fix Gate N failures with `fix(gate-N): ...` commits. Never fix logic/design/auth on-branch.
5. **Merge** — if all gates pass + 0 🔴 from code-review + cross-vendor agreement → merge (commit only, never squash).
6. **Docs sync** — invoke `update-docs` skill after any merge.
7. **Issue pickup (cap 2)** — gates I-1..I-6, branch + implement + draft PR + `llm-judge` ≥ 4.
8. **Status report + cron-learnings** — report + append 13 lines to cron-learnings JSONL.
### When to use
- Clear PR backlog faster than hourly cadence.
- Test changes to the triage prompt itself.
- Resume after a scheduled cron has died.
---
## Repository Layout
```
molecule-workflow-triage/
├── skills/
│ └── triage-workflow/
│ └── SKILL.md # Full triage workflow definition
├── commands/
│ └── triage.md # /triage command definition
├── adapters/
│ ├── __init__.py
│ └── claude_code.py # Claude Code harness adapter
├── plugin.yaml # Plugin manifest
└── README.md
```
---
## Key Conventions
| Topic | Convention |
|---|---|
| **Merge type** | Merge commit only — never squash or rebase |
| **On-branch fixes** | Mechanical fixes only (`fix(gate-N): ...`) |
| **Merge requirement** | All 7 gates + 0 🔴 + cross-vendor agreement |
| **Issue cap** | Max 2 issues picked up per triage run |
| **llm-judge threshold** | Score ≥ 4 to mark draft PR ready |
| **Gates that block** | Security (Gate 4), Design (Gate 5), code-review 🔴 |
---
## Standing Rules (Inviolable)
- Never push to `main`.
- `careful-mode` REFUSE list **always blocks**.
- Code-review 🔴 **always blocks merge**.
- Cross-vendor disagreement on noteworthy PRs **escalates to user**.
- `llm-judge` ≤ 2 **blocks marking a draft PR ready**.
- Never fix logic/design/auth issues on-branch — file a separate issue.
---
## Recommended Plugins
`/triage` calls these skills as sub-steps. Install them first:
```yaml
plugins:
- molecule-skill-code-review # Supplement A
- molecule-skill-cron-learnings # Step 5 learnings
- molecule-skill-llm-judge # Issue pickup scoring
- molecule-skill-update-docs # Docs sync after merge
```
---
## Development
```bash
# Dry-run: list open PRs
gh pr list --state open --json number,title,author,isDraft,mergeable,statusCheckRollup --limit 10
# Check current gate status
gh pr view 123 --json statusCheckRollup,mergeable,reviewDecision
# Verify careful-mode lists
cat ~/.claude/careful-mode-refuse.txt # if using careful-bash
```

19
README.md Normal file
View File

@ -0,0 +1,19 @@
# molecule-workflow-triage
Molecule AI plugin. Install via the Molecule AI platform plugin system.
## Usage
### In org template (org.yaml)
```yaml
plugins:
- molecule-workflow-triage
```
### From URL (community install)
```
github://Molecule-AI/molecule-ai-plugin-molecule-workflow-triage
```
## License
Business Source License 1.1 — © Molecule AI.

0
adapters/__init__.py Normal file
View File

2
adapters/claude_code.py Normal file
View File

@ -0,0 +1,2 @@
"""Claude Code adaptor — uses the generic rule+skill+hooks installer."""
from plugins_registry.builtins import AgentskillsAdaptor as Adaptor # noqa: F401

50
commands/triage.md Normal file
View File

@ -0,0 +1,50 @@
---
name: triage
description: Run a full PR-triage cycle (gates 1-7 + code-review + merge if green). Equivalent to one cron tick, on demand.
---
# /triage
Manual invocation of the hourly PR-triage flow. Use when:
- You want to clear backlog faster than the hourly cadence
- You're testing a change to the triage prompt itself
- A scheduled cron has died and the queue is backing up
## Steps
### Step 0 — Activate guards + replay learnings
1. `Skill careful-mode` — load REFUSE/WARN/ALLOW lists.
2. Read last 20 lines of cron-learnings JSONL (workspace memory dir).
### Step 1 — List
```
gh pr list --state open --json number,title,author,isDraft,mergeable,statusCheckRollup
gh issue list --state open --json number,title,assignees,labels
```
### Step 2 — 7-gate verification per PR
- Gate 1 CI · Gate 2 build · Gate 3 tests · Gate 4 security · Gate 5 design · Gate 6 line review · Gate 7 Playwright if UI
- Supplement A: `Skill code-review`
- Supplement B: `Skill cross-vendor-review` on noteworthy PRs (auth/billing/data-deletion/migration/large-blast-radius)
### Step 2a — Mechanical fixes only
Fix on-branch + commit `fix(gate-N): ...` + push + poll CI. NEVER fix logic / design / auth issues.
### Step 2b — Merge
All gates pass + 0 🔴 from code-review + cross-vendor agreement → `gh pr merge N --merge --delete-branch`. Merge-commit only.
### Step 3 — Docs sync after any merge
`Skill update-docs` — measure test counts, don't guess.
### Step 4 — Issue pickup (cap 2)
For each candidate: gates I-1..I-6, self-assign, branch, implement, draft PR, run `Skill llm-judge` against issue body + PR diff. Mark ready only if score >= 4.
### Step 5 — Status report + cron-learnings
Report includes every subsection ("none" if empty). Then append 1-3 lines to cron-learnings JSONL.
## Standing rules (inviolable)
- Never push to main · Merge-commits only
- careful-mode REFUSE list ALWAYS blocks
- code-review 🔴 ALWAYS blocks merge
- cross-vendor disagreement on noteworthy PR escalates to user
- llm-judge ≤ 2 blocks marking a draft PR ready

49
known-issues.md Normal file
View File

@ -0,0 +1,49 @@
# Known Issues
Active and recently resolved issues for `molecule-workflow-triage`.
---
## Active Issues
*(None currently open. File an issue if you encounter a problem.)*
---
## Known Gotchas
### `/triage` requires several sibling plugins to be useful
**Severity:** Medium
**Detail:** `/triage` calls `code-review`, `cross-vendor-review`, `llm-judge`, `cron-learnings`, and `update-docs` as sub-steps. If those plugins are not installed, the triage will fail or degrade gracefully depending on the skill.
**Workaround:** Install all recommended plugins (see CLAUDE.md) before enabling `/triage` in a workspace.
---
### Gate 4 (security) may conflict with careful-mode REFUSE list
**Severity:** Low
**Detail:** If a PR touches code that is on the `careful-mode` REFUSE list, Gate 4 (security) will flag it AND careful-mode will refuse to operate on the file. This is intentional but can be confusing — both are blocking.
---
### Issue pickup cap of 2 may leave backlog
**Severity:** Informational
**Detail:** If many issues are backlogged, `/triage` will only self-assign and begin work on 2 per run. Use multiple `/triage` invocations or increase the cap in a custom workspace configuration.
---
### Mechanical fix commits do not trigger re-review
**Severity:** Low
**Detail:** Gate fix commits (`fix(gate-N): ...`) are pushed to the PR branch and CI is re-polled, but no review request is re-sent. If a reviewer has already approved, the existing approval stands. If a reviewer has not yet reviewed, they may miss the fix.
**Workaround:** After a mechanical fix, manually post a review comment to re-engage reviewers if needed.
---
## Recently Resolved
*(None yet.)*

11
plugin.yaml Normal file
View File

@ -0,0 +1,11 @@
name: molecule-workflow-triage
version: 1.0.0
description: Provides /triage slash command — full PR-triage cycle composing code-review, cross-vendor-review, cron-learnings. Recommends installing molecule-skill-code-review and molecule-skill-cron-learnings first.
author: Molecule AI
tags: [molecule, guardrails]
runtimes:
- claude_code
commands:
- triage

119
runbooks/local-dev-setup.md Normal file
View File

@ -0,0 +1,119 @@
# Runbook: Local Development Setup — github-app-auth Plugin
This runbook covers setting up a local development environment for the
`github-app-auth` plugin (GitHub App installation-token injection). It is a Go
plugin, not a standard molecule plugin — there is no Python validate-plugin.py
step.
---
## Prerequisites
| Requirement | Version | Notes |
|---|---|---|
| Go | 1.25+ | Must match `go.mod` |
| Git | 2.40+ | |
| GitHub App | Installed on org | Requires App ID, installation ID, private key PEM |
| `gh` CLI | 2.40+ | Optional — for manual verification |
| molecule-monorepo | Local checkout | Required for `cmd/` and `pluginloader/` packages to compile |
---
## Step 1 — Clone
```bash
git clone https://github.com/Molecule-AI/molecule-ai-plugin-github-app-auth.git
cd molecule-ai-plugin-github-app-auth
```
---
## Step 2 — Private Key
Generate or retrieve the GitHub App private key PEM file:
```bash
# Downloaded from: GitHub App Settings → Keys → Generate a private key
# Save as:
cp ~/Downloads/molecule-ai.private-key.pem /secrets/github-app.pem
chmod 600 /secrets/github-app.pem
```
Required env vars for local development:
```bash
export GITHUB_APP_ID=3398844 # Your App's numeric ID
export GITHUB_APP_INSTALLATION_ID=... # Shown on the installation page
export GITHUB_APP_PRIVATE_KEY_FILE=/secrets/github-app.pem
```
> **Security:** Never commit the PEM file. It is gitignored. Keep it on a
> tmpfs or an encrypted volume.
---
## Step 3 — Local Platform Replace Directive
The `go.mod` includes a `replace` directive pointing at a local platform checkout
(`../molecule-monorepo/platform`). For local development:
```bash
# If you have molecule-monorepo checked out adjacent to this repo:
ls ../molecule-monorepo/platform # verify it exists
# If not, remove the replace directive (needed for CI):
go mod edit -dropreplace github.com/Molecule-AI/molecule-monorepo/platform
go mod tidy
```
---
## Step 4 — Build and Test
```bash
# Test the self-contained internal package (no platform dependency):
go test ./internal/... -race -count=1
# Vet:
go vet ./internal/...
# Build the server example (requires the platform replace directive):
go build ./cmd/server-with-github-app/ -o /tmp/test-server
```
The `cmd/` and `pluginloader/` packages require the `molecule-monorepo/platform`
module — they are integration territory, validated by the platform's own CI
when the plugin is pulled in as a dependency.
---
## Step 5 — Integration Test
If running in a local platform instance:
```bash
# Start the platform with the plugin loaded
docker compose up -d --build platform
# Verify the token is injected into a workspace container
docker exec ws-test printenv GITHUB_TOKEN
# Expected: ghs_...
# Verify gh auth works inside the workspace
docker exec ws-test gh auth status
# Expected: Logged in to github.com as app/molecule-ai[bot]
```
---
## Common Issues
| Symptom | Likely Cause | Fix |
|---|---|---|
| `go: module not found: github.com/Molecule-AI/molecule-monorepo/platform` | Local platform not checked out | `go mod edit -dropreplace ...` then `go mod tidy` |
| `githubapp: AppID is required` at boot | `GITHUB_APP_ID` not set | Set the env var; confirm the App ID from the GitHub App settings page |
| `crypto/rsa: key too small` error | Private key < 2048-bit | Re-generate the key (GitHub requires 2048-bit RSA keys) |
| `401 Unauthorized` in workspace | Installation token expired or App not installed | Check `ghs_` prefix in `GITHUB_TOKEN`; verify App is installed with correct permissions |
| `GraphQL` errors even though `gh auth status` OK | App lacks required OAuth scopes | Verify App has Contents: Write, Issues: Write, PRs: Write, Metadata: Read |
| `jwt: signature is invalid` | Clock skew > 60s | Sync system clock: `timedatectl set-ntp true` |
| Platform crashes on first workspace boot | PEM file missing or unreadable at startup | Verify: `test -r $GITHUB_APP_PRIVATE_KEY_FILE && echo OK` |

View File

@ -0,0 +1,50 @@
---
name: triage-workflow
description: Orchestrates a full PR-triage cycle — 7-gate verification, code review, merge, docs sync, issue pickup.
---
# triage-workflow
On-demand manual invocation of the PR-triage flow. Equivalent to one cron tick.
## When to Use
- Clear PR backlog faster than the hourly cron cadence
- Test a change to the triage prompt itself
- A scheduled cron has died and the queue is backing up
## How It Works
### Activate guards + replay learnings
1. `Skill careful-mode` — load REFUSE/WARN/ALLOW lists
2. Read last 20 lines of cron-learnings JSONL (workspace memory dir)
### PR verification (7 gates per PR)
1. CI status
2. Build
3. Tests
4. Security
5. Design review
6. Line review
7. Playwright (UI PRs only)
Supplements: `Skill code-review`, `Skill cross-vendor-review` on noteworthy PRs.
### Mechanical fixes only
Fix on-branch, commit `fix(gate-N): ...`, push, poll CI. Never fix logic/design/auth issues on a branch that isn't yours.
### Merge conditions
All gates green + 0 🔴 from code-review + cross-vendor agreement → merge-commit only.
### Docs sync after merge
`Skill update-docs` — measure test counts, don't guess.
### Issue pickup (cap 2)
- Gates I-1..I-6
- Self-assign, branch, implement, draft PR
- Run `Skill llm-judge` against issue body + PR diff
- Mark ready only if score >= 4
## Examples
```
Skill triage-workflow
```