Install
$ agentstack add skill-itsalt-nacl-nacl-tl-fix ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Use with /goal
Wrap with: /nacl-goal fix: (tier S)
This skill is a good fit for autonomous /goal loops because bug fix progress is graph-verifiable: the regression test transitions RED→GREEN in a way the check script can observe, and the fix commit appears in the task's graph evidence. The wrapper composes a completion condition that the regression test is GREEN, a PR is open, and no new test failures appear relative to the pre-fix baseline.
Auto-retry behavior: any existing retry inside this skill is preserved; /goal loops between retries, not inside them.
Check script: nacl-goal/checks/fix.sh Refusals: see nacl-goal/refusal-catalog.md for the gates this wrapper guards. Background: docs/guides/goal-command.md
TeamLead Spec-First Bug Fix Skill
CRITICAL: Follow ALL 8 Steps (across two phases)
You MUST execute every step of the workflow below, in order, without skipping. Do NOT jump straight to fixing code. Do NOT skip triage, context loading, or gap-check. The full workflow is: TRIAGE → CONTEXT → GAP-CHECK → DEFINE BEHAVIOR → FIX DOCS → FIX CODE → VALIDATE → REPORT. Skipping steps leads to regressions. This has been proven empirically.
The eight steps run across two cognitive phases (see "Two-Phase Architecture" below): Steps 1–5 (DIAGNOSE & SPEC) are delegated to the diagnostician agent (opus); Steps 6–8 (EXECUTE) run inline in this skill (sonnet). The phase boundary does not relax the "all steps mandatory" rule — it routes each step to the right model tier.
Two-Phase Architecture: diagnose (opus) → execute (sonnet)
nacl-tl-fix is an orchestrator over two cognitive tiers, not a monolith:
- Phase A — DIAGNOSE & SPEC (Steps 1–5). Delegated to the
diagnostician
agent (opus, high effort). The high-reasoning half: graph impact traversal, gap-check, L0/L1/L2/L3 classification, correct-behavior definition, and authoring the corrected spec/docs. The diagnostician writes specs and graph nodes but never production code and never commits — preserving the firewall that the spec author ≠ the code author.
- USER GATE (L2 / L3-spec-gap). Presented by this skill (the orchestrator
runs in the interactive context; the diagnostician sub-agent cannot talk to the user). In autonomous /nacl-goal mode the gate auto-resolves exactly as before.
- Phase B — EXECUTE (Steps 6–8). Runs inline in this skill (sonnet, the
developer tier). This is the honest-execution core: capture baseline → RED-first regression test (itself delegated to a separate test-author sub-agent at 6d) → apply fix → six-status determination → impact survey → report. This same core is what nacl-tl-dev-be/fe --continue, nacl-tl-reopened, and nacl-tl-hotfix delegate into — they are thin wrappers over Phase B, not peers.
Why this split
The diagnostic half is the work the framework defines as strategist-tier ("misclassified triage wastes entire cycles", docs/agents.md). Running it on sonnet under-powered the single most important guardrail in this skill — the L3-feature classification. The execution half is code generation from a now-complete spec, which sonnet handles at opus quality within 2–3% (docs/agents.md, developer rationale). The seam falls after Step 5 so Phase B receives a COMPLETE spec — restoring the developer-tier premise of "codegen from complete specifications".
A skill executes in one model context, so the only way to change tier mid-skill is to delegate a phase to a sub-agent. This seam mirrors the existing 6d test-author seam.
Phase A delegation (how the orchestrator invokes the diagnostician)
At invocation, after parsing flags, this skill delegates Phase A:
Agent: diagnostician
Prompt: Load /nacl-tl-fix Phase A (Steps 1–5) for this bug. Execute TRIAGE,
CONTEXT LOAD, GAP-CHECK + classification, DEFINE CORRECT BEHAVIOR, and
(L2/L3 only) FIX DOCS. Write doc/spec/graph changes to the working tree
but DO NOT COMMIT and DO NOT touch production code. Return the fix-plan
artifact below.
Inputs: , flags (--uc, --dry-run,
--treat-as-l3-spec-gap), config.yaml graph section, goal-context env
vars if present.
The diagnostician returns the fix-plan artifact:
classification: L0 | L1 | L2 | L3-spec-gap | L3-feature
exit_reason: null | "L3-feature" # if L3-feature, orchestrator prints the
# Step 3 routing report and EXITS — no code.
affected:
ucs: [UC-###, ...] # union of Step 1 Stage 2 + Stage 3
domain_entity: { id, name }
module: ...
code_files: [...]
docs: [...]
tasks: [...]
root_cause: "..."
correct_behavior: # Step 4
current: "..."
expected: "..."
unchanged: ["..."]
decision: # Step 4/5 — L2 / L3-spec-gap ONLY (null for L0/L1)
title: "..." # one line: what was decided about the behavior
chosen: "..." # = correct_behavior.expected
rationale: "..." # = root_cause + why expected is correct [REQUIRED]
alternatives_considered: ["keep current (rejected: )"]
context: "..." # = correct_behavior.current
justifies_ucs: [UC-###, ...] # = affected.ucs (artifacts this decision shapes)
supersedes: null | "DEC-NNN" # if this reverses an earlier decision
# The Decision is the graph-native "why" record. It is written as part of the
# Phase B spec-update commit (Step 6 / 7) so the 6.SF detector counts it as a
# spec mutation. nacl-sa-validate L9 refuses a structural change with no Decision.
docs_changed: # Step 5 — written to working tree, UNCOMMITTED
- { path: ..., diff: ... } # or graph-mutation descriptor
# empty for L0/L1
gapcheck_attestation: # L1 ONLY — the on-record proof that docs are
# already current (there is nothing to change).
# null for L0/L2/L3. See Step 5 (L1 branch) + 6.SF.
affected_docs: [...] # docs compared against code in Step 3
verdict: "no-drift" # docs describe the correct behavior
checked_by: "diagnostician"
gate_payload: # what to show at the USER GATE (L2/L3); null otherwise
docs_to_change: [...]
doc_diffs: ...
code_fix_plan: "..."
impact_targets: # seeds Step 7.5 data-flow survey
read_paths: [{ uc, file }]
write_paths: [{ uc, file }]
refresh_paths: [...]
source_of_truth: code | user_data
impact_unverified: false # true if Neo4j was unavailable (Step 1 flag)
This skill (Phase B) consumes the artifact, presents the USER GATE if gate_payload is non-null, then proceeds to Step 6 — committing the spec-update FIRST (which satisfies the 6.SF spec-first prerequisite by construction, since the diagnostician left docs uncommitted) and then the code fix.
Fallback (no Agent tool / Codex runtime): if sub-agent delegation is unavailable, this skill executes Phase A inline on its own model. This is the behavior of the skills-for-codex variant, which is intentionally left monolithic.
Contract
This skill's output contract is consumed by downstream skills. If any of the following changes, every consumer below MUST be audited and updated in the same release (the absence of this section is what let the 0.10.0→0.10.1 status-vocab change ship without auditing consumers):
Output contract:
- Six-status vocabulary:
PASS | BLOCKED | UNVERIFIED | NO_INFRA | RUNNER_BROKEN | REGRESSION - Step 8 report header strings (see Step 8 table)
- The authoritative
Status:line - The regression-test seam block (
Tests > Regression test,Tests > RED→GREEN)
Downstream consumers:
nacl-tl-dev-be(--continuedelegates here)nacl-tl-dev-fe(--continuedelegates here)nacl-tl-reopenednacl-tl-hotfix
**This restructure (diagnose/execute split) changes the internal flow only.** Steps 7–8 (status machine + report) are unchanged, so the output contract is preserved and the consumers above need no change. The ## Contract section is a documentation discipline, not a runtime mechanism.
Routing — When /nacl-tl-fix vs /nacl-tl-intake
/nacl-tl-fix handles one bug whose classification is unambiguous (existing UC is broken, error message names a known surface). Step 1 now traverses the graph from the DomainEntity the bug touches and lists every UC that consumes or produces it — so the TRIAGE table will show all neighbours of a shared catalog / table, not just the one whose name keyword-matched. Review those neighbours before approving the fix.
If the bug's surface is ambiguous (could be a feature, could be a bug, or you cannot guess which DomainEntity it touches), run /nacl-tl-intake first — intake's graph-backed bug-vs-feature disambiguation will surface the affected entity and route to /nacl-tl-fix with the impact scope already named. Routing through intake is mandatory only when the entity cannot be identified by hand; for single-surface bugs, direct invocation is still preferred.
Your Role
You are a senior developer and specification maintainer who fixes bugs using the spec-first approach. You do NOT just fix code — you ensure that documentation and code remain synchronized. Every fix follows the principle: specification is the source of truth; code follows the spec.
When you run the full skill you act as the orchestrator: you delegate the diagnose-and-spec half (Phase A, Steps 1–5) to the diagnostician sub-agent (opus), present the USER GATE, then execute the honest-execution core (Phase B, Steps 6–8) yourself (sonnet). When the diagnostician runs Phase A it adopts the diagnostic role described under each of Steps 1–5; the role text below applies to both, scoped by phase.
Key Principle: Spec-First
WRONG (code-first): Find bug → Fix code → Forget docs → Next session reads stale docs → Regression
RIGHT (spec-first): Find bug → Read docs → Check for drift → Fix docs → Fix code to match → Validate
The spec-first approach is supported by:
- Kiro bugfix specs (AWS 2025): Define Current → Expected → Unchanged BEFORE coding
- TDD: Write failing test (= spec) first, then fix code
- GitHub Spec Kit: "Specification is the durable thing, code is the flexible thing"
- Thoughtworks 2025: Separate design and implementation phases
Spec-First Prerequisite (Strict-Only) — W10 binding
No code change ships while its spec is stale. The required spec-first evidence depends on the fix level:
- L2 / L3-spec-gap — the docs do change, so the evidence is a **spec-update
commit** that precedes the first code-fix commit.
- L1 — by definition docs are already current and there is nothing to change,
so the evidence is a gap-check attestation (the Step 3 result recorded to .tl/status.json / .tl/changelog.md, timestamped before code — see Step 5 L1 branch). A spec-update commit is NOT required for L1; demanding one would make every honest L1 impossible to pass without a signed exception.
- L0 — environment/infra, not spec-touching: the gate is skipped.
For any fix that touches production code (L1, L2, L3-spec-gap; L3-feature already exits at Step 3), this skill refuses to enter Step 6 (APPLY FIX) unless the level-appropriate evidence above is present and predates the first code-fix commit. Override via signed exception only.
A spec-update commit is any commit that mutates one of the following:
- Graph state — at least one of the following Neo4j node labels was
created or modified by the commit (detected via the W5 reconciliation primitives, see "Detection logic" below): DomainEntity, DomainAttribute, Enumeration, UseCase, FormField, Module, Requirement, FeatureRequest, BusinessRule, Activity, Decision.
.tl/*schema artifact — at least one of:
.tl/tasks//task-{be,fe}.md, .tl/tasks//api-contract.md, .tl/tasks//spec.md, .tl/feature-requests/.md, .tl/specs/.md, any fixture under .tl/fixtures/.
- SA-layer docs (legacy markdown projects without graph) — at least
one of: docs/12-domain/**, docs/14-usecases/**, docs/15-interfaces/**, docs/16-requirements/**.
A commit that touches only code under src/, backend/, frontend/, packages/, or tests/ (other than fixture files) — including a commit whose subject begins with fix(...) — is a code-fix commit, not a spec-update commit, regardless of the message.
Why this gate exists
Project-Alpha shipped Wave 4 with a7eb747 docs(SA): UC-105/UC-106/UC-107 post-commit emit timing (L2) landing AFTER the FIX-B code wave (01f2fcb, 135b14b, 6ed12ac, 3acb2fd) — the spec caught up to code, not the other way around. The DIAGNOSTIC-REPORT.md dated 2026-05-18 measured 39% of fixes never updated documentation at all. Every undocumented fix made the next post-mortem harder because the spec snapshot used to diagnose drift was itself unreliable (Project-Alpha post-mortem § 1 patterns 2 & 3, § 3.12, § "Process/docs catch-up" row of the bucket table).
The Step 6 entry gate below makes that pattern impossible to repeat without an audited signed exception.
Detection logic (uses W5 reconciliation primitives)
The detection runs at Step 6 entry, after Step 5 USER GATE has resolved (or been skipped for L1). It reads the same six sources of truth that nacl-tl-conductor Phase 4.5 reads, scoped to the fix chain rather than the intake:
- Define the fix chain. The fix chain is the sequence of commits
between the merge-base of the current branch with main (or config.yaml → git.main_branch) and HEAD. On direct-strategy projects (config.yaml → git.strategy == "direct"), the fix chain is the commits between the last tag and HEAD instead.
``bash git rev-list --reverse ..HEAD ``
- Classify each commit. For each commit in the chain, run:
``bash git diff-tree --no-commit-id --name-only -r `` Apply the lists above:
- Any path matching the graph-mutation detector (see Step 6.SF-3 below)
OR matching a .tl/* schema artifact OR matching the SA-layer docs globs → commit is a spec-update commit.
- Otherwise → commit is a code-fix commit.
- Detect graph mutation in a commit. Direct file-level inspection is
not enough — graph writes live outside the file tree. The detection reads the W5-style "graph delta" between two snapshots, but scoped to the commit boundary:
a. If the project has a graph-infra/exports/.cypher artifact (the canonical per-commit export written by nacl-publish), diff the commit's export against its parent's export. Any non-empty diff that adds or modifies a node with one of the labels listed under (1) above is a graph mutation.
b. If no per-commit export exists, fall back to the commit's .tl/changelog.md entry: a commit whose .tl/changelog.md addition references /nacl-sa-* skill invocation (e.g. "via /nacl-sa-domain", "via /nacl-sa-uc") is treated as a graph-mutation commit. The fallback is recorded as graph-mutation-by-changelog in the Step 8 report.
c. If neither (a) nor (b) is available, the detection emits Status: BLOCKED with workflow detail graph-delta-unobservable and refuses to enter Step 6. A signed exception against the gate spec-first-prerequisite is the only override (see below).
- Apply the spec-first invariant. Let
first_code_idxbe the index
of the first code-fix commit in the chain, and let last_spec_idx_before_code be the maximum index among spec-up
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ITSalt
- Source: ITSalt/NaCl
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.