Skip to content

Feature request: expose pluggable extension points so other plugins can extend the RLCR loop #172

@nathanbeckmann

Description

@nathanbeckmann

Summary

humanize is a great foundation for an iterative implement-review-iterate loop, and the natural next step is for other Claude Code plugins to extend it — adding reviewers, gates, context-gathering passes, or convergence
checks — without forking or reaching into humanize's filesystem layout.

Today, the only extension surface is Claude Code's plugin-level hook composition (Stop/PreToolUse/etc.). That works as a foothold but isn't a real extension API: there's no schema for what an extender produces, no ownershi
p of merged output, no defined behavior when two extenders both want to block, and no surface for non-Stop lifecycle moments. This issue proposes humanize expose its own extension points that sibling plugins register again
st at install time.

Motivating example: a panel of reviewers, not just Codex

The most immediate use case is letting a sibling plugin add additional reviewers alongside Codex on every round. Imagine a multi-personality reviewer with several distinct lenses — e.g. a test-completeness personality, a s
cope-discipline personality, an architecture personality, a performance personality, a naming personality. Each lens is most useful as a separate registration into a reviewer panel that humanize aggregates, not as a single
monolithic review.

This generalizes well beyond any one reviewer:

  • Custom review personalities tuned for a specific codebase (a security personality, an API-stability personality, a docs personality, …).
  • A cargo clippy / eslint / pylint reviewer that emits findings in the same schema.
  • A license/compliance reviewer that gates convergence regardless of Codex's verdict.
  • A test-coverage gate that blocks convergence if coverage regressed.

If reviewer registration is first-class, all of these become drop-in plugins on equal footing with Codex.

Why hook composition isn't enough

A sibling plugin can register its own Stop hook today and have it fire alongside humanize's loop-codex-stop-hook.sh at the same event. This
works, but the seams show:

  1. Sibling plugins must reach into humanize's filesystem layout. To produce per-round artifacts, an extender has to locate .humanize/rlcr/<timestamp>/, parse state.md for current_round, and write next to humanize
    's round-N-review-result.md. That's an implicit ABI — humanize doesn't owe anyone stability on those paths, but extenders depend on them.

  2. Decision merging is unspecified. If humanize's Codex hook returns {"decision":"block","reason":"..."} and a sibling plugin's hook does the same, what reaches Claude's next-turn context? Both? Last-write-wins? Wi
    thout a defined merge policy, the only safe move for a sibling is to silently append findings to humanize's already-written review file and exit 0 — i.e. give up the block decision and trust humanize to relay the merged co
    ntent.

  3. No surface beyond Stop. Plan refinement, pre-round setup, convergence vote, post-round artifact contribution — none are extensible. A security plugin that wants to veto convergence has no clean way in. A planner-ext
    ension that wants to add repo-specific context to gen-plan has no clean way in.

  4. Recursion guards are per-plugin. Any hook that spawns claude --print … itself fires Stop hooks, inviting infinite recursion. Each plugin has to invent its own env-var dance to early-exit on re-entry.

  5. No unified findings schema. Codex emits [P0-P9] severities, other reviewers emit their own (BLOCKING/SHOULD-FIX/NIT, error/warning, …). Merging them for a single repair turn is the sibling plugin's problem.

Proposed extension points

humanize would expose a small set of named extension points. Sibling plugins declare which they participate in via a manifest (e.g. .claude-plugin/humanize-extension.json or similar), which humanize discovers at loop sta
rt.

A non-exhaustive sketch:

  • reviewer — register an executable that receives {diff, round_metadata, loop_dir} and returns findings in a unified schema ({severity, message, file, line, suggested_fix?}). humanize merges all reviewers' findin
    gs into a single round-N-review.md, decides block/convergence based on aggregated severity (with a configurable policy), and feeds the merged feedback to the next repair turn.
  • convergence-gate — per-round veto. Returns PASS/FAIL with reason. Loop cannot converge while any gate fails. Distinct from reviewer because the gate's job is yes/no, not finding production.
  • planner-extension — additional context/critique passes for gen-plan and refine-plan. Useful for repo-specific conventions, regulatory context, or interactive planning aids.
  • round-artifact — register additional artifacts to write into .humanize/rlcr/<ts>/ each round (with humanize owning the directory layout).
  • event-listener — pre-round, post-round, loop-start, loop-end. For plugins that observe but do not gate (e.g. metric collection, PR comment posting).

Each extension point has a defined input contract, output schema, and merge/composition policy owned by humanize. That gives sibling plugins a small, stable contract to implement and gives humanize a real ownership story f
or merged output.

What this would unlock

  • For humanize: the RLCR loop becomes a platform. Reviewers, gates, planners, and context-gatherers can evolve independently in their own plugins without anyone forking humanize.
  • For sibling plugins: small, stable contracts to implement; no reaching into humanize's internal paths; no decision-merge guesswork; recursion guards owned in one place.
  • For the ecosystem: any team can ship a Claude Code plugin that extends the RLCR loop — security gates, lint reviewers, coverage gates, repo-specific personalities — without needing to coordinate with humanize maintai
    ners.

Open questions / discussion

  • Is there appetite for this on humanize's side, or is the preferred extension model "fork and customize"?
  • If reviewer registration lands, what's the right merge policy default — strict (any BLOCKING blocks), majority vote, configurable per-loop?
  • Should extension manifests live in the plugin manifest (.claude-plugin/plugin.json) under a humanize key, or in a separate file? The former is discoverable via Claude Code's plugin metadata; the latter keeps humanize
    -specific config out of the plugin manifest.
  • For convergence gates and reviewers: should humanize expose a way for extenders to read/write loop state via an API, or do they continue to read state.md directly (with a documented schema)?

Happy to discuss further or prototype any of these as a concrete validation case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions