Skip to content
Development
Skill

/hns-lsel-curator

Local Self-Evolution Loop (LSEL) curator — the CLUSTER + drain engine for the GOOS-local PROPOSE→APPLY seam closure (SPEC-LSEL-LOCAL-EVOLUTION-001). Companion-offset drain of .moai/lessons-inbox.jsonl with a drain-side severity filter that drops the ~65% Bash-timeout/sandbox

From plugin
moai-adk
1.2k74 skills21 agents19 commands3 MCP
Install
$ npx -y skills add modu-ai/moai-adk --skill hns-lsel-curator --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/hns-lsel-curator

Context preview

The summary Claude sees to decide when to auto-load this skill.

Local Self-Evolution Loop (LSEL) curator — the CLUSTER + drain engine for the GOOS-local PROPOSE→APPLY seam closure (SPEC-LSEL-LOCAL-EVOLUTION-001). Companion-offset drain of .moai/lessons-inbox.jsonl with a drain-side severity filter that drops the ~65% Bash-timeout/sandbox

SKILL.md

hns-lsel-curator.SKILL.md
name: hns-lsel-curator
description: >
  Local Self-Evolution Loop (LSEL) curator — the CLUSTER + drain engine for the
  GOOS-local PROPOSE→APPLY seam closure (SPEC-LSEL-LOCAL-EVOLUTION-001). Companion-offset
  drain of .moai/lessons-inbox.jsonl with a drain-side severity filter that drops the ~65%
  Bash-timeout/sandbox noise, event_key clustering with a frequency gate, and a
  Generative-Agents-style 1-10 importance score. Candidates stage at
  .moai/state/lsel/clusters.json. M1 = drain only (NO PROPOSE, NO APPLY, NO memory/ writes).
allowed-tools: Read, Grep, Glob, Bash
user-invocable: false
metadata:
  version: "0.1.0"
  category: "harness"
  status: "active"
  updated: "2026-08-04"
  tags: "lsel,self-evolution,drain,cluster,harness,dogfood"

hns-lsel-curator — LSEL CLUSTER + drain engine

> **Namespace:** `hns-lsel-*` is user-owned dogfood (CLAUDE.local.md §24). This skill is > NOT mirrored into `internal/template/templates/` — it lives only in this repo. Graduation > to `moai-lsel-*` + 16-language distribution is a separate SPEC (out of scope per spec.md §G). > > **M1 scope:** drain + cluster + stage candidates. NO APPROVE, NO APPLY (M3). > **M2 scope:** drain + cluster + **PROPOSE shadow** (no APPROVE, no APPLY). The PROPOSE stage > emits shadow proposals + self-critiques; APPROVE/APPLY land in M3 via the fresh > `hns-lsel-applier` path. M2 does NOT write to `memory/` — the first `feedback_*.md` topic > file is an M3+ deliverable after APPROVE.

What this skill does

The MoAI-ADK repo accumulates tool-failure stubs in `.moai/lessons-inbox.jsonl` (624 stubs at M1 start, re-measured — a moving target). The constitution names the orchestrator as the drain actor, but until this skill there was **zero mechanical drain code** — the drain existed only as a doctrine paragraph (`moai-constitution.md:147`). This skill closes that gap in user-owned surfaces, without touching the frozen Go applier (`internal/harness/applier.go:22` — its write-flag stays `false`; REQ-LSEL-003: bypass, never unfreeze).

The drain is split into a **mechanical core** (`drain.sh`, deterministic, testable) and a **model-mediated layer** (this SKILL.md + your judgment, invoked for M2+ importance refinement and proposal drafting).

The mechanical core — `drain.sh`

`drain.sh` is a portable bash + jq script that lives next to this SKILL.md. It performs the deterministic half of the drain:

drain.sh --inbox <path-to-lessons-inbox.jsonl> --state-dir <path-to-lsel-state>

Pipeline (REQ-LSEL-009 + AC-LSEL-009 / AC-LSEL-010):

1. **Companion offset** — read `<state-dir>/drain-offset.json` (seed `{"offset":0}` if absent). The inbox is append-only and is NEVER mutated; the offset marks consumed stubs (SPEC-HARNESS-RATCHET-REWIRE-001 D3 companion-offset pattern). 2. **Slice** — read stubs from the offset onwards (`tail -n +<offset+1>`). 3. **Drain-side severity filter** (AC-LSEL-010) — discard noise BEFORE clustering:

  • `tool_failure:Bash:UnknownFailure` — the opaque ~65% timeout/sandbox bucket (the dominant

noise share; report §2).

  • `tool_failure:Bash:SandboxViolation` — environment constraint, not a code defect.
  • any `*:TimeoutError` (Bash + MCP timeouts).

The filter is drain-side because `internal/hook/failure_observer.go` (the inbox writer) is OUTSIDE the six loop-writable surfaces (plan.md §F.1 [DECISION RESOLVED]), so the loop cannot edit the writer — it filters on read instead. 4. **Cluster** by `event_key` with frequency count, first/last seen, and up to 3 sample summaries. 5. **Singleton gate** — discard clusters with `frequency < 2` (single-occurrence noise per the constitution Lessons Protocol drain paragraph). 6. **Importance** — score each survivor with a Generative-Agents-style 1-10 gate: `importance = min(10, frequency)` (frequency as proxy; the model augments this in M2+ with a severity hint and retrieval-weighted judgment). 7. **Emit** candidates to `<state-dir>/clusters.json`; advance the companion offset.

`clusters.json` schema

{
  "drained_at": "2026-08-04T08:41:00Z",
  "offset_before": 0,
  "offset_after": 624,
  "total_read": 624,
  "noise_discarded": 533,
  "singletons_discarded": 4,
  "candidates": [
    {
      "event_key": "tool_failure:Agent:UnknownFailure",
      "frequency": 41,
      "first_seen": "...",
      "last_seen": "...",
      "sample_summaries": ["...", "...", "..."],
      "source": "tool:Agent",
      "importance": 10
    }
  ]
}

Empty-delta no-op

If the inbox has not grown past the offset, `drain.sh` writes an empty-candidate `clusters.json` and leaves the offset unchanged. Not a failure (acceptance.md §E edge case).

The model-mediated layer (you, when invoked)

`drain.sh` produces the deterministic candidate set. When this skill is invoked for a real curation pass (M2+), your job on top of the mechanical output is:

  • **Read `clusters.json`** and rank candidates by `importance` then `frequency`.
  • **Augment importance** with a severity hint the mechanical core cannot see: a recurring

`Bash:ExitError` cluster points at a real command-shape defect (high signal); a recurring `Agent:ContextCancelled` cluster may be session-teardown noise (lower signal). Record the rationale in the candidate's prose when you draft the M2 proposal — do NOT rewrite `clusters.json` (it is the mechanical artifact; your augmentation lives in the proposal).

  • **Do NOT write to `memory/` in M1.** Candidates stage in `clusters.json` only. The first

`feedback_*.md` topic file is produced by the M2 PROPOSE stage after retrieval-before-propose and self-critique (REQ-LSEL-010).

What this skill does NOT do (M1 boundaries)

  • **No APPROVE / APPLY** — the parallel user-owned applier (`hns-lsel-applier`) is M3.
  • **No edits to frozen doctrine** — `.claude/rules/moai/**`, `CLAUDE.md`,

`internal/template/templates/**`, retained agents, `moai-*` skills, and the frozen Go applier / `curator_dispatch.go` are all byt

Read more
Ships withmoai-adk

Agentic development harness for Claude Code — SPEC-driven plan/run/sync, TRUST 5 quality gates, model+effort routing, and Claude×GLM multi-LLM cost control. Single Go binary, 16 languages, zero deps.

Get the whole plugin

Other skills on moai-adk.