# Nacl Tl Hotfix

> |

- **Type:** Skill
- **Install:** `agentstack add skill-itsalt-nacl-nacl-tl-hotfix`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ITSalt](https://agentstack.voostack.com/s/itsalt)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [ITSalt](https://github.com/ITSalt)
- **Source:** https://github.com/ITSalt/NaCl/tree/main/nacl-tl-hotfix

## Install

```sh
agentstack add skill-itsalt-nacl-nacl-tl-hotfix
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

## Contract

**Inputs this skill consumes:**
- nacl-tl-fix output (six-status vocabulary; PASS required for unattended merge
  to main; non-PASS requires explicit user override)

**Outputs this skill produces:**
- HOTFIX COMPLETE — fix verified, PR created with auto-merge label
- HOTFIX BLOCKED — {NO_INFRA | RUNNER_BROKEN | UNVERIFIED} — halt with reason
- HOTFIX HALTED — REGRESSION — new bug filed
- PR to main (only if fix status was PASS, or user explicitly overrode)

**Downstream consumers of this output:**
- GitHub auto-merge (consumes PR label)
- Deploy pipeline (downstream of merge to main)

**Contract change discipline:**
If this skill's output contract changes — status vocabulary, headline format,
exit codes, or report-field names — every downstream consumer in the list
above must be audited and updated in the same release. The 0.10.0→0.10.1
regression (nacl-tl-reopened broke when nacl-tl-fix changed its output) was
caused by skipping this discipline. Do not ship contract changes without
auditing consumers.

---

## NOT for /goal

Emergency hotfix requires human judgment on urgency, scope, and whether to target main directly. The skill touches the production branch, creates PRs with auto-merge, and optionally pushes directly to main — decisions that require the operator to be present and explicitly confirm at Step 6. Autonomous execution on a production branch is out of scope for /goal regardless of fix status.

**Refusal code:** `REFUSE_HOTFIX_JUDGMENT`
**Background:** `docs/guides/goal-command.md`

---

# TeamLead Hotfix -- Emergency Fix to Main

## Your Role

You are the **hotfix specialist**. When a critical bug hits production and the fix cannot wait for a feature branch to merge, you create a clean hotfix branch from `main`, apply the fix, open a PR with auto-merge, and restore the user to their original branch.

You are the ONLY skill authorized to target `main` from another branch. `/nacl-tl-ship` always commits to the current branch -- it never switches.

## Key Principle

```
Hotfix branch from fresh main → apply fix → validate → PR with auto-merge → restore source branch
Never push directly to main without explicit --push-direct-to-main + double confirmation.
```

## Safety Rules

1. **PR by default.** Direct push to main ONLY with `--push-direct-to-main` flag AND explicit double confirmation from the user.
2. **NEVER modify the feature branch.** The hotfix branch is created from `main`. The source feature branch is only restored to its pre-hotfix state.
3. **NEVER skip tests.** If tests fail on the hotfix branch, STOP. The user must resolve.
4. **NEVER auto-rebase other branches.** Only advise. Only rebase the source branch with explicit `--rebase-feature` flag.
5. **ALWAYS restore the user to their original branch** at the end, regardless of success or failure.
6. **ALWAYS create the hotfix branch from a fresh `main`** (`git pull` first). Never from the feature branch.
7. **On any failure, clean up:** delete the local hotfix branch, restore the original state (pop stash if applicable, checkout source branch).

---

## Invocation

```
/nacl-tl-hotfix --apply                        # uncommitted changes → hotfix PR to main
/nacl-tl-hotfix --cherry-pick     # existing commit → hotfix PR to main
/nacl-tl-hotfix "description"                  # write fix from scratch on hotfix branch
/nacl-tl-hotfix ... --push-direct-to-main               # skip PR, push directly to main (double confirmation)
/nacl-tl-hotfix ... --rebase-feature           # after hotfix, rebase source feature branch from main
/nacl-tl-hotfix ... --dry-run                  # analysis only, no git operations
/nacl-tl-hotfix ... --yes                      # skips non-safety prompts (task-list selection, module-detection confirmation). Does NOT bypass the pre-merge non-PASS gate at Step 6.
```

### Configuration Resolution

| Data | Source priority |
|------|---------------|
| Main branch | `git.main_branch` > `modules.[name].git_base_branch` > fallback `"main"` |
| Branch prefix | hardcoded `"hotfix/"` (NOT `git.branch_prefix` which is for features) |
| Build command | `modules.[name].build_cmd` > workspace `package.json` `scripts.build`. **No `npm run build` fallback.** Missing → `HOTFIX HALTED — NO_INFRA (scripts.build undeclared)` (P2). |
| Test command | `modules.[name].test_cmd` > workspace `package.json` `scripts.test`. **No `npm test` fallback.** Missing → `HOTFIX HALTED — NO_INFRA (scripts.test undeclared)` (P2). |
| Test filter | `modules.[name].test_filter_flag` (e.g. `--testPathPattern`, `--filter`) > unset. If unset, the regression-test step runs the full declared test command rather than inventing a runner flag. |
| Module path | `modules.[name].path` > detect from package.json |
| YouGile columns | `yougile.columns.*` |
| Deploy production | `deploy.production.*` |

---

## Workflow: 9 Steps

### Step 1: TRIAGE -- announce: "Step 1: TRIAGE"

**Goal:** Determine the scenario and validate preconditions.

1. Read `config.yaml` for git settings, deploy config, module config.
2. Determine current branch:
   ```bash
   current_branch=$(git rev-parse --abbrev-ref HEAD)
   ```
3. Determine the scenario:
   - If `--apply` flag: **Scenario 1** (uncommitted changes). Verify `git status --porcelain` shows changes.
   - If `--cherry-pick ` flag: **Scenario 2** (existing commit). Verify commit exists: `git cat-file -t `.
   - If description string provided (no flags): **Scenario 3** (write fix from scratch).
   - If none of the above: error with usage help.
4. Record the source branch name (for later restore).
5. Verify `{main_branch}` is reachable:
   ```bash
   git fetch origin {main_branch}
   ```

Present triage summary to user:
```
Scenario: {1: uncommitted changes | 2: cherry-pick | 3: from scratch}
Source branch: {branch_name}
Main branch: {main_branch} (fetched: OK)
Changes: {file count | commit hash | "will be authored"}
```

### Step 2: PREPARE -- announce: "Step 2: PREPARE"

**Goal:** Preserve the feature branch state and create the hotfix branch.

**Scenario 1 (uncommitted changes):**
```bash
git stash push -m "hotfix-stash-$(date +%s)"
```
Record the stash reference.

**Scenario 2 (existing commit):**
No stash needed. Record the commit hash to cherry-pick.

**Scenario 3 (from scratch):**
No stash needed. The fix will be written on the hotfix branch.

**All scenarios — create hotfix branch from fresh `{main_branch}`:** the slug comes from the
single-authority formatter (same lowercase/hyphens/≤50 rule as `/nacl-tl-ship`; pinned by
`nacl-core/scripts/branch.test.sh`). (Hotfix branches from `{main_branch}` by design — the
base-branch GUARD does not apply here.)
```bash
git checkout {main_branch}
git pull origin {main_branch}
slug=$(bash nacl-core/scripts/branch.sh slug "$description")
git checkout -b "hotfix/${slug}"
```

Example: `hotfix/cast-lectureid-uuid-generation-query`

### Step 3: APPLY FIX -- announce: "Step 3: APPLY FIX"

**Goal:** Get the fix code onto the hotfix branch.

**Scenario 1 (from stash):**

Before applying the stash, invoke `/nacl-tl-regression-test` against the current hotfix branch
(which still has main's code — the stash has NOT been applied yet). Provide:
- Bug description from the user's hotfix invocation
- Affected source file(s) (infer from `git stash show -p stash@{0}` file list)
- Current behavior (broken) and Expected behavior (fixed)

The regression test MUST be RED on main's code before the stash is applied. If the test is GREEN
(does not capture the bug), halt and ask the user to sharpen the bug description before retrying.
Record the test path as `regression_test_path`.

```bash
git stash apply stash@{0}
```
If conflicts:
- Report which files conflict and the conflict details.
- STOP and present to user with instructions.
- Do NOT attempt to auto-resolve code conflicts.

**Scenario 2 (cherry-pick):**

Before cherry-picking, invoke `/nacl-tl-regression-test` against the current hotfix branch
(which still has main's code — the cherry-pick has NOT been applied yet). Provide:
- Bug description from the user's hotfix invocation
- Affected source file(s) (infer from `git diff ~1  --name-only`)
- Current behavior (broken) and Expected behavior (fixed)

The regression test MUST be RED on main's code before the cherry-pick is applied. If the test is
GREEN (does not capture the bug), halt and ask the user to sharpen the bug description.
Record the test path as `regression_test_path`.

```bash
git cherry-pick  --no-commit
```
Using `--no-commit` to allow inspection before committing.

If cherry-pick fails:
```bash
git cherry-pick --abort
# Fallback: generate and apply patch
git diff ~1  | git apply --3way
```
If both fail: STOP and report the dependency issue (the fix likely depends on code that only exists in the feature branch).

**Scenario 3 (from scratch):**
Delegate to `/nacl-tl-fix` with the user's description. Wait for fix to complete.

Capture `/nacl-tl-fix`'s `Status:` field explicitly from its Step 8 report. This is
mandatory — the production main bar is higher than a feature branch.

Branch on the status immediately:
- **PASS** — proceed to Step 4.
- **BLOCKED / UNVERIFIED / NO_INFRA / RUNNER_BROKEN** — the fix is not cleanly verified.
  Record the status and reason. Continue to Step 3.5 then Step 4.
  **The mandatory user gate for all non-PASS statuses is at Step 6 — do not prompt here.**
  (Step 6 gate is unconditional: it always prompts fresh, even when `--yes` was supplied.)
- **REGRESSION** — the fix introduced new failures or its regression test is still RED. HALT:
  ```
  HOTFIX HALTED — REGRESSION
  Fix introduced new test failures not present in baseline, or the regression test
  for this bug is still failing after the fix.
  Do NOT ship. Return to /nacl-tl-fix Step 6f to correct the fix.
  ```
  Record the new failures in YouGile task chat as advisory (user decides whether to
  open a new task). Do NOT proceed.

### Step 3.5: VERIFY REGRESSION-TEST SEAM -- announce: "Step 3.5: VERIFY REGRESSION-TEST SEAM"

**Goal:** Confirm that a regression test was actually written and ran RED→GREEN. This step applies
to ALL scenarios.

**Scenario 3:** Parse the `/nacl-tl-fix` Step 8 report for both of the following fields:

```
Regression test:  [path of new test (Path A) | "covered by existing test: [path]" (Path B) | ...]
RED→GREEN:        [✓ confirmed at 6e and 6g (Path A) | ✓ existing test transitioned (Path B) | ...]
```

- If `Regression test:` field is missing, empty, or reads `"none — UNVERIFIED"`: emit:
  ```
  HOTFIX HALTED — UNVERIFIED (regression-test seam not honored)
  /nacl-tl-fix did not produce a regression test (Path B "UNVERIFIED" or field absent).
  Cannot confirm the fix is verifiable. Return to /nacl-tl-fix Step 6 with sharper inputs.
  ```
  HALT. Do NOT proceed.
- If `RED→GREEN:` field is missing or reads `✗`: emit:
  ```
  HOTFIX HALTED — UNVERIFIED (regression-test seam not honored)
  /nacl-tl-fix reported a test path but RED→GREEN evidence is absent or negative.
  The test did not prove the fix works. Return to /nacl-tl-fix Step 6e/6g.
  ```
  HALT. Do NOT proceed.
- Otherwise: record `regression_test_path` (exact absolute path from the field) and
  `red_green_evidence` (the summary from the RED→GREEN line). Continue to Step 4.

**Scenarios 1 and 2:** `regression_test_path` was recorded in Step 3 above (the test written
before the stash/cherry-pick was applied). Confirm it is non-empty. If it is empty (the
regression test invocation was skipped or failed to produce a path), halt:
```
HOTFIX HALTED — UNVERIFIED (regression-test seam not honored)
No regression test path was recorded for Scenario {1|2}. Cannot proceed without test evidence.
```

### Step 4: VALIDATE -- announce: "Step 4: VALIDATE"

**Goal:** Verify the fix works on the main branch codebase, including a named regression-test run, and classify any remaining failures against a captured `main` baseline (P3).

#### Step 4.0: CAPTURE MAIN BASELINE (worktree)

Before running the postfix suite, capture a `{main_branch}` baseline using
`git worktree add` (no stash juggling on the active hotfix branch):

```bash
baseline_dir=$(mktemp -d -t hotfix-baseline.XXXXXX)
git worktree add "$baseline_dir" "$(git rev-parse {main_branch})"
( cd "$baseline_dir/[module_path]" && [test_cmd] ) > "$baseline_dir/baseline.log" 2>&1 || true
```

Parse the failing-test set from `baseline.log` into `baseline_failures` (a set of
test identifiers). The `|| true` is required — the baseline is permitted to be
non-clean; we only care about *which* tests fail there.

The baseline worktree MUST be removed at the end of the skill regardless of
outcome (success, halt, or error). The cleanup step (Step 7 / Cleanup on Failure)
runs:

```bash
git worktree remove -f "$baseline_dir" 2>/dev/null || true
rm -rf "$baseline_dir"
```

If `git worktree add` fails (worktree already exists, disk full, etc.):
emit `HOTFIX HALTED — NO_INFRA (baseline worktree unavailable)` and abort
before applying the fix on the hotfix branch.

#### Step 4.1: REGRESSION TEST (postfix, named)

Run the regression test by file path (from `regression_test_path` recorded in
Step 3.5). Use the declared test command plus the configured `test_filter_flag`
(see Configuration Resolution). If `test_filter_flag` is unset, run the full
declared test command — do NOT invent a generic `--test-name-pattern` flag (P2):

```bash
if [ -n "$test_filter_flag" ]; then
  cd [module_path] && [test_cmd] $test_filter_flag "[regression_test_path]"
else
  # No declared filter syntax for this runner; run the full suite.
  cd [module_path] && [test_cmd]
fi
```

The regression test MUST be GREEN. If it is RED (still failing after the fix
was applied), halt:
```
HOTFIX INCOMPLETE — REGRESSION
Regression test {regression_test_path} is still failing after the fix.
The fix does not address the bug. Return to Step 3 / /nacl-tl-fix Step 6f.
```
HALT. Do NOT proceed.

#### Step 4.2: POSTFIX SUITE + BASELINE COMPARISON

Run the full test suite on the hotfix branch:

```bash
cd [module_path] && [test_cmd] > postfix.log 2>&1
postfix_exit=$?
```

Parse `postfix_failures` from `postfix.log`. Compute set differences:

```
new_failures = postfix_failures − baseline_failures
transitioned = baseline_failures − postfix_failures
pre_existing = postfix_failures ∩ baseline_failures
```

Run build:
```bash
cd [module_path] && [build_cmd]
```

Classify the outcome (P3 — no claim about pre-existing failures without the captured baseline):

- `new_failures.size > 0` → **REGRESSION**.
  Halt with `HOTFIX INCOMPLETE — REGRESSION (new failures: )`. Do NOT
  proceed. Record the new failures in YouGile task chat.

- `new_failures.size == 0 AND postfix_failures.size > 0` → **BLOCKED**
  (pre-existing failures confirmed by baseline). Record `pre_existing` set
  explicitly in the report — these are the same tests that fail on `main`,
  not regressions from this hotfix. Continue to Step 5 with status BLOCKED;
  Step 6 gate fires.

- `postfix_failures.size == 0 AND build OK` → **PASS** (continue normally).

- `[test_cmd]` returned NO_INFRA / RUNNER_BROKEN (e.g. zero tests collected,
  runner crashed) → emit `HOTFIX BLOCKED — {NO_INFRA | RUNNER_BROKEN}`. The
  hotfix code itself may be correct, but cannot be verified. Step 6 gate fires.

**Do NOT** claim a failure is "pre-existing", "unrelated", or "may not be
related" without `baseline_failures` set membership confirming it.

If the failure is a dependency issue (code from feature branch not on {main_branch}):
STOP with advisory:
```
This fix depends on code from {source_branch} that does not exist on {main_branch}.
Options:
  (a) Include the dependency in the hotfix
  (b) Merge the full feature branch first
  (c) Write a standalone fix for {main_branch}
```

Show impact summary:
```bash
git diff --stat {main_branch}..HEAD
```

### Step 4.3: WRITE EVIDENCE TO GRAPH -- announce: "Step 4.3: WRITE EVIDENCE"

**Goal:** Stamp `Task.verification_evidence` for every affec

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ITSalt](https://github.com/ITSalt)
- **Source:** [ITSalt/NaCl](https://github.com/ITSalt/NaCl)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-itsalt-nacl-nacl-tl-hotfix
- Seller: https://agentstack.voostack.com/s/itsalt
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
