---
name: HNS LSEL Applier
slug: hns-lsel-applier
category: Automation
description: HNS LSEL Applier consumes approved decision.json records to drive the local self-evolution apply hook, validating targets against a frozen allowlist and applying patches. Use it during the APPLY pass of the LSEL loop when a proposal is approved and ready to be committed.
github: "https://github.com/modu-ai/moai-adk/tree/main/.claude/skills/hns-lsel-applier"
language: Go
stars: 1176
forks: 220
install: "npx degit https://github.com/modu-ai/moai-adk/tree/main/.claude/skills/hns-lsel-applier ~/.claude/skills/hns-lsel-applier"
installs_to: ~/.claude/skills/hns-lsel-applier
source_path: .claude/skills/hns-lsel-applier/SKILL.md
collection_size: 25
category_size: 1523
collection_url: "https://dirskills.com/collections/modu-ai/moai-adk"
added: 2026-08-20T07:55:47.105Z
last_synced: 2026-08-20T07:55:47.105Z
canonical_url: "https://dirskills.com/skills/hns-lsel-applier"
---

# HNS LSEL Applier

HNS LSEL Applier consumes approved decision.json records to drive the local self-evolution apply hook, validating targets against a frozen allowlist and applying patches. Use it during the APPLY pass of the LSEL loop when a proposal is approved and ready to be committed.

**Install:**

```bash
npx degit https://github.com/modu-ai/moai-adk/tree/main/.claude/skills/hns-lsel-applier ~/.claude/skills/hns-lsel-applier
```

## README

# hns-lsel-applier — LSEL APPLY 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).

> **Token discipline.** This body deliberately avoids the literal identifier of the
> frozen Go applier's write-flag and the literal name of the orchestrator-only
> user-question channel. Both are referenced by location and role (e.g. "the write-flag
> at `internal/harness/applier.go:22`", "the orchestrator's synchronous user gate") so
> the REQ-LSEL-003 invariant-grep and the E4 subagent-boundary grep over LSEL surfaces
> read zero literal matches. The invariants themselves are stated in plain English.

## What this skill does

The LSEL loop's PROPOSE→APPLY seam was dead in production: `Applier.Apply` never ran
(`manifest.jsonl` absent), `CuratorDispatch` had 0 production callers, and the frozen
Go applier's write-flag at `internal/harness/applier.go:22` (kept `false`) is the
apply dead-switch (REQ-LSEL-003 — M3 keeps it `false` by BYPASS, never unfreeze). The
M3 closure routes APPLY through a parallel **user-owned** applier that writes only to
the six evolvable surfaces (spec.md §B.3), while the frozen Go applier stays
byte-for-byte frozen. Design SSOT:
`.moai/reports/moai-local-self-evolution-design-20260804.html` §4 ("동결된 Go applier를
우회하는 병렬 사용자 소유 applier를 세운다" — build a parallel user-owned applier that
bypasses the frozen Go one) + §7 (the two-round critique moved the allowlist OUT of
the evolvable skill files into a frozen meta file, and added execution-meta files to
the forced-gate set).

The APPLY engine is the **playback hook** `.moai/hooks/lsel-apply.sh` plus this skill's
model-mediated judgment (target validation nuance, approval-marker provenance, blast-
radius reasoning the mechanical hook cannot see). The hook is the load-bearing safety
floor; this skill is the consumer-facing surface that decides WHICH approved decision
to feed it next and how to interpret refusal.

## The APPLY pipeline

`lsel-apply.sh <decision.json>` performs five steps. Steps 1-2 are the safety floor;
steps 3-5 are the playback.

1. **Frozen-allowlist hard-reject** (REQ-LSEL-001 / AC-LSEL-001). The target path in
   `decision.json` is matched against the `frozen_patterns` regex list in
   `.claude/lsel/frozen-allowlist.json`. A match → REFUSE: a row is appended to
   `.moai/logs/lsel-reject.log` naming the rejected path and category `frozen-path`,
   NO file is written, and the hook exits 2.
2. **Execution-meta forced-gate** (REQ-LSEL-002 / AC-LSEL-005 D3 self-amending-
   handcuffs). If the target matches one of the four `execution_meta` categories —
   (i) the frozen allowlist meta file itself, (ii) an applier/curator skill body
   (`hns-lsel-applier/`, `hns-lsel-curator/`), (iii) the apply hook
   (`.moai/hooks/lsel-*.sh`), (iv) the `settings.local.json` hook-registration
   subblock — the hook checks `decision.json` for a synchronous-approval marker (a
   `synchronous_approval` object with `decision: "approved"`, produced by the
   orchestrator's synchronous user gate). No marker → REFUSE: reject-log row with
   category `execution-meta`, exit 3, no write. With marker → proceeds (the refusal
   is keyed on the absent marker, NOT on the category match alone). The refusal
   semantics mirror the M2 `csa_refusal_test.sh` fixture exactly.
3. **Apply the diff.patch** via `git apply` (playback of an already-approved decision).
   Only the paths declared in the patch are staged — never `git add -A` (working-tree
   hygiene).
4. **Append the apply-ledger row** to `.moai/state/lsel/apply-ledger.jsonl`:
   `{proposal_id, target_surface, ts, result:"applied", commit_sha, category}`. This
   is the manifest the frozen Go applier never produced, finally real in user-owned
   space.
5. **Commit** the staged change as ONE `feat(lsel-<proposal-id>): ...` Conventional
   Commit on the current (feature) branch (REQ-LSEL-004). The ledger row's
   `commit_sha` is backfilled from the commit's short SHA.

A no-arg invocation is a clean no-op (exit 0) so an empty approved-queue does not
derail a loop pass.

## The model-mediated layer (you, when invoked)

When this skill is invoked to drive an APPLY pass, your job on top of the mechanical
hook is:

- **Read the proposal's `proposal.md` + `self-critique.md`** at
  `.moai/state/lsel/proposals/<id>/`. A proposal with `status: blocked` (any
  UNRESOLVED self-critique objection) MUST NOT be fed to the hook — return a blocker
  report instead.
- **Confirm the approval marker's provenance.** The `synchronous_approval` object must
  carry a real orchestrator-produced approval artifact (the synchronous user-question
  channel the orchestrator owns per CLAUDE.md §8). A marker the loop fabricated for
  itself is the self-amending-handcuffs failure mode (REQ-LSEL-002); the hook's
  mechanical check is the floor, your provenance judgment is the ceiling. This skill
  is a subagent mechanism and NEVER invokes the orchestrator-only user-question
  channel; return a blocker report and let the orchestrator run the gate.
- **Re-verify the frozen-allowlist invariant** by grepping the write-flag at
  `internal/harness/applier.go:22` — it MUST stay `false`. If M3's bypass ever drifts
  toward unfreezing the Go applier, return a blocker (AP-LSEL-002).

## What this skill does NOT do

- **No unfreezing of the Go applier** — the write-flag at
  `internal/harness/applier.go:22` stays `false` (REQ-LSEL-003). The bypass is
  parallel and user-owned; the frozen applier is reference-only.
- **No edits to frozen doctrine** — `internal/template/templates/**`,
  `.claude/rules/moai/**`, `CLAUDE.md`, retained agents, `moai-*` skills, the frozen
  Go applier / `curator_dispatch.go`, and `.moai/config/sections/**` are
  byte-for-byte untouched. The allowlist hard-rejects them (step 1).
- **No new-apply / self-approve / allowlist-amend primitive** in `lsel-apply.sh`
  (REQ-LSEL-008). The hook only consumes already-approved decisions; it does not
  author proposals or bless them. The M4 `verify.sh` runs only AFTER an apply has
  committed — it does not create a new apply; it never self-approves.
- **No user-question invocation** — subagent boundary (CLAUDE.md §8). Return a
  blocker report; the orchestrator runs the synchronous gate.

---

## VERIFY stage (M4 — REQ-LSEL-013 / AC-LSEL-015)

After an apply commits a proposal, VERIFY proves the apply was safe. VERIFY has
**two layers** — both MANDATORY:

### (a) Mechanical layer — `verify.sh` (bash-testable)

`verify.sh --proposal-dir <p> --repo-root <r> [--timeout SECS] [--feedback-file <f>]`
runs the proposal's frontmatter `verify_command` with a **timeout-retry-once**
policy and auto-reverts on a second failure:

- **2-attempt policy.** Attempt 1 runs. On SUCCESS → `verified:true`, stop. On
  TIMEOUT-class failure → attempt 2 (flaky tolerance — report §10 P3: "retry
  once on timeout so a correct proposal isn't flipped by noise"). On
  NON-TIMEOUT-FAIL → attempt 2 (allows the "second non-timeout failure" of
  AC-LSEL-015 clause 3 to materialize before revert fires).
- Attempt 2: SUCCESS → `verified:true`. Any failure (timeout OR non-timeout) →
  `verified:false` + **auto `git revert lsel-<proposal-id>`** + the proposal's
  `feedback_*.md` is marked `verified: false`.
- The outcome is appended to the apply ledger as a
  `{"stage":"verify","verified":true|false,...}` row — the load-bearing signal.

### (b) MANDATORY `/moai gate` superset (model-mediated)

**`/moai gate` (lint+format+type+test) is MANDATORY after every apply — it is
NOT optional.** A bash hook cannot invoke a Claude Code slash command directly,
so the gate runs MODEL-SIDE: when this skill drives an APPLY pass, the
orchestrator/model runs `/moai gate` after the mechanical apply + verify. The
proposer-authored `verify_command` alone is **circular** (report §11 mustFix
B#6 / AP-LSEL-004): a proposer can author a verify_command that its own change
satisfies. `/moai gate` is the independent check — lint, format, type-check,
and the test suite exercise surfaces the proposal never touched. Treat a
mechanical verify_command PASS without a green `/moai gate` as an unverified
apply.

### Model-mediated layer (you, when invoked)

- After `lsel-apply.sh` commits and `verify.sh` reports, **run `/moai gate`**
  (the MANDATORY superset). If the gate fails, the apply is unverified even if
  `verify.sh` reported `verified:true` — treat it as a VERIFY failure and revert.
- A revert (whether auto-fired by `verify.sh` or gate-driven) MUST be surfaced
  to the orchestrator as a blocker report — the orchestrator, not this skill,
  confirms a revert with the user. Never run `/moai gate`'s user-facing surface
  from inside this subagent mechanism; return a blocker report.

### Verification (run before declaring an APPLY+VERIFY pass complete)

```bash
# M4 VERIFY characterization test (AC-LSEL-015) — hermetic temp repo:
.claude/skills/hns-lsel-applier/verify_test.sh

# the verify ledger row carries the outcome:
grep '"stage":"verify"' .moai/state/lsel/apply-ledger.jsonl
```

## Verification (run before declaring an APPLY pass complete)

```bash
# 1. APPLY characterization test (AC-001/002/005/008/013) — hermetic temp repo:
.claude/skills/hns-lsel-applier/apply_test.sh

# 2. Rollback-rehearsal SHIP GATE (AC-014):
.claude/skills/hns-lsel-applier/rollback_rehearsal_test.sh

# 3. REQ-LSEL-003 frozen-flag re-verify (post-apply). The frozen Go applier's
#    write-flag at internal/harness/applier.go:22 MUST read `false`, and no LSEL
#    surface (skills/hooks/state/allowlist) references that identifier as mutable.
#    (The literal identifier is intentionally not written here; find it at line 22
#    of the frozen file and grep LSEL surfaces for it — expect zero hits.)
sed -n '22p' internal/harness/applier.go   # MUST show the `= false` write-flag line

# 4. The apply ledger carries the new row:
tail -1 .moai/state/lsel/apply-ledger.jsonl
```

## Cross-references

- **SPEC:** `.moai/specs/SPEC-LSEL-LOCAL-EVOLUTION-001/{spec,plan,acceptance,progress}.md`
- **Design report (SSOT):** `.moai/reports/moai-local-self-evolution-design-20260804.html`
  §4 (user-owned parallel applier), §7 (allowlist relocation + execution-meta forced
  gate), §10 P3, §11 mustFix A#1/A#5/A#8.
- **Frozen applier (reference only):** `internal/harness/applier.go:22` (the frozen
  write-flag), `internal/harness/curator_dispatch.go`.
- **Curator (PROPOSE stage, M2):** `.claude/skills/hns-lsel-curator/SKILL.md`
  (CSA forced-gate doctrine + the Tier-4 DEAD finding).
- **CSA refusal fixture:** `.claude/skills/hns-lsel-curator/csa_refusal_test.sh`
  (the refusal rule this hook enforces mechanically).
- **Namespace guard:** `internal/template/split_namespace_test.go`,
  `internal/template/internal_content_leak_test.go` (must NOT flag a `hns-lsel-applier`
  leak — this skill is dogfood, never templated).
