import from local vendored copy (2026-05-06)
Some checks failed
CI / validate (push) Failing after 0s
Some checks failed
CI / validate (push) Failing after 0s
This commit is contained in:
commit
d709f75edb
5
.github/workflows/ci.yml
vendored
Normal file
5
.github/workflows/ci.yml
vendored
Normal 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
21
.gitignore
vendored
Normal 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
|
||||
1
.molecule-ci/scripts/requirements.txt
Normal file
1
.molecule-ci/scripts/requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
pyyaml>=6.0
|
||||
52
.molecule-ci/scripts/validate-plugin.py
Normal file
52
.molecule-ci/scripts/validate-plugin.py
Normal 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
112
CLAUDE.md
Normal 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 1–3 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
19
README.md
Normal 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
0
adapters/__init__.py
Normal file
2
adapters/claude_code.py
Normal file
2
adapters/claude_code.py
Normal 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
50
commands/triage.md
Normal 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
49
known-issues.md
Normal 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
11
plugin.yaml
Normal 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
119
runbooks/local-dev-setup.md
Normal 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` |
|
||||
50
skills/triage-workflow/SKILL.md
Normal file
50
skills/triage-workflow/SKILL.md
Normal 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
|
||||
```
|
||||
Loading…
Reference in New Issue
Block a user