Local Self-Evolution Loop (LSEL) APPLY engine — the playback-only consumer of approved decision.json records that drives `.moai/hooks/lsel-apply.sh` for the GOOS-local PROPOSE→APPLY seam closure (SPEC-LSEL-LOCAL-EVOLUTION-001 M3). Reads an approved decision.json, validates the target against the frozen allowlist (.claude/lsel/frozen-allowlist.json), mechanically refuses execution-meta targets lacking a synchronous-approval marker, applies the referenced diff.patch, appends an apply-ledger.jso...
Scanned 9/2/2026
Install to Claude Code
npx -y skills add modu-ai/moai-adk --skill hns-lsel-applier --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Hns Lsel Applier?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/modu-ai-hns-lsel-applier)More formats (shields.io, HTML) on the badges page.
---
name: hns-lsel-applier
description: >
Local Self-Evolution Loop (LSEL) APPLY engine — the playback-only consumer of
approved decision.json records that drives `.moai/hooks/lsel-apply.sh` for the
GOOS-local PROPOSE→APPLY seam closure (SPEC-LSEL-LOCAL-EVOLUTION-001 M3). Reads
an approved decision.json, validates the target against the frozen allowlist
(.claude/lsel/frozen-allowlist.json), mechanically refuses execution-meta
targets lacking a synchronous-approval marker, applies the referenced
diff.patch, appends an apply-ledger.jsonl row, and commits one
lsel-<proposal-id>-tagged Conventional Commit on the feature branch. M3 scope:
APPLY bypass closure only (the frozen Go applier stays frozen — its write-flag
at internal/harness/applier.go:22 stays false; REQ-LSEL-003).
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,apply,harness,dogfood"
---
# 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).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!