Configurable soft workflow guardrails for Paperclip issue DAGs and agent runs.
This plugin watches active Paperclip work for mechanical workflow drift and either reports or repairs conservative cases:
blockedissues with no blocker edges.blockedissues whose blockers are all terminal, such asdoneorcancelled.blockedissues with a mix of live and terminal blockers, where stale terminal blocker edges can be trimmed.- Multiple active/queued runs for the same issue/agent pair.
- Comments indicating a child/reviewer could not mutate a parent/coordinator issue.
It intentionally does not replace Paperclip core runner guarantees. It cannot prove work quality, enforce subprocess working directories, cancel bad runs, or replace board approval. Treat it as a configurable reconciliation layer that makes workflow drift visible and, when explicitly enabled, applies small mechanical repairs.
The default configuration is conservative:
dryRun: truecomment: trueautoWake: false- all rules set to
comment
That means the plugin posts idempotent operator-visible comments about proposed repairs, but does not change issue status, mutate blockers, or wake agents until you opt into mutation.
This plugin is relevant to paperclipai/paperclip#5914 if that issue is tracking first-class workflow reconciliation / stale state cleanup in Paperclip core. The plugin is a practical soft-guardrail implementation: useful today, but not a substitute for hard core invariants or pre-run veto hooks.
npm install
npm test
npm run smoke
# Local path install while developing
npm exec paperclipai -- plugin install --local "$PWD" \
--api-base http://127.0.0.1:3100 \
--api-key "$PAPERCLIP_API_KEY"After changing local source, bump the package/manifest version and reload with Paperclip's plugin upgrade endpoint or UI.
The manifest exposes an instanceConfigSchema. The most important fields are:
{
"dryRun": true,
"comment": true,
"autoWake": false,
"blockedStatus": "blocked",
"recoveryStatus": "todo",
"terminalStatuses": ["done", "cancelled"],
"activeRunStatuses": ["queued", "starting", "running"],
"scanStatuses": ["blocked", "todo", "in_progress", "in_review"],
"commentPrefix": "WORKFLOW RECONCILER",
"rules": {
"blockedWithoutBlockers": "comment",
"onlyTerminalBlockers": "comment",
"trimTerminalBlockers": "comment",
"duplicateActiveRuns": "comment",
"parentNotificationRejected": "comment"
}
}Rule values:
off— ignore the condition.comment— post one idempotent comment when detected.mutate— apply the mechanical repair whendryRunisfalse; otherwise only comment.
Recommended rollout:
- Start with defaults for at least one full work cycle.
- If comments are accurate and low-noise, set selected blocker rules to
mutate. - Only enable
autoWakeafter mutation behavior is trusted.
Detects an issue in blockedStatus with zero blocker edges.
Mutation behavior: move the issue to recoveryStatus; optionally wake the assignee if autoWake is true.
Detects an issue in blockedStatus whose blockers are all in terminalStatuses.
Mutation behavior: move the issue to recoveryStatus, clear blocker edges, and optionally wake the assignee.
Detects an issue that still has live blockers but also has stale terminal blocker edges.
Mutation behavior: remove only terminal blocker edges and leave the issue blocked.
Detects multiple active runs for the same issue/agent pair from orchestration summaries.
Mutation behavior: none. The plugin reports only; it does not cancel runs.
Detects comments matching parentNotificationRejectedPattern, by default:
parent notification rejected|cannot mutate another agent's issue|forbidden parent
Mutation behavior: none. The plugin reports only so a coordinator/operator can reconcile the parent thread.
Paperclip mounts plugin API routes under the installed plugin id.
GET /api/plugins/:pluginId/api/status?companyId=:companyId
POST /api/plugins/:pluginId/api/issues/:issueId/reconcileUse the plugin database UUID when possible; some Paperclip builds resolve dotted plugin keys as UUIDs before falling back to plugin keys.
npm install
npm test
npm run smoke
npm pack --dry-runThe source is intentionally plain ESM JavaScript under dist/ because the current Paperclip local plugin loader imports built worker/manifest files directly. There is no build step.
- Conventional commits from this repository forward.
- Update
CHANGELOG.mdfor every release. - Tag releases as
vX.Y.Z. - Publish GitHub Releases from tags.
MIT