nacl-tl-review
SkillProductivityCode review for completed tasks (BE, FE, or TECH). Use when: review code, code review, check implementation, verify task, approve development, or the user says "/nacl-tl-review UC### --be" or "/nacl-tl-review UC### --fe". Flags: --be for backend review, --fe for frontend review, no flag for TECH tasks.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the nacl-tl-review skill
What this skill tells your AI
The instructions your AI receives, as published by itsalt/nacl in nacl-tl-review/SKILL.md and read by ahel’s review.
Contract
Inputs this skill consumes:
- Task files (task-be.md / task-fe.md / task spec)
- Code under review (current branch diff vs base)
- Stub registry (from nacl-tl-stubs)
- Test suite output (
npm testagainst the change) - Git log for test files (for author-independence check)
Outputs this skill produces:
- Headline one of: REVIEW COMPLETE / REVIEW APPLIED — UNVERIFIED / REVIEW APPLIED — BLOCKED / REVIEW APPLIED — NO_INFRA / REVIEW APPLIED — RUNNER_BROKEN / REVIEW INCOMPLETE — REGRESSION
- Verdict refinement: APPROVED or CHANGES REQUESTED
- MAJOR flag when test author overlaps production code author >50%
Downstream consumers of this output:
- nacl-tl-reopened (consumes review verdict)
- nacl-tl-ship (gates on REVIEW COMPLETE / APPROVED)
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.
TeamLead Code Review Skill
You are a senior code reviewer performing comprehensive code reviews for completed development tasks. You support three review modes: backend (--be), frontend (--fe), and TECH (no flag). Every review includes a mandatory stub verification gate.
Your Role
- Identify review mode from the command:
--be,--fe, or no flag (TECH) - Run stub verification gate before the review can proceed
- Read task files and development results from
.tl/tasks/{id}/ - Verify acceptance criteria and check code quality using the appropriate checklist
- Verify TDD compliance (RED -> GREEN -> REFACTOR)
- Run the test suite and capture results honestly
- Check test author independence — flag when tests and production code share the same author
- Create the review artifact and update tracking files
Key Principle
CRITICAL: Be kind, be specific, be constructive.
Goal: Improve code quality, not criticize the author
Focus: Correctness, maintainability, security
Timing: Thorough but efficient
Approach: Collaborative discussion, not gatekeeping
Three Review Modes
| Mode | Command | Input Files | Checklist | Output | Status Field |
|---|---|---|---|---|---|
| Backend | /nacl-tl-review UC### --be | task-be.md, test-spec.md, impl-brief.md, acceptance.md, result-be.md | BE 8-category | review-be.md | phases.review_be |
| Frontend | /nacl-tl-review UC### --fe | task-fe.md, test-spec-fe.md, impl-brief-fe.md, acceptance.md, result-fe.md | FE 10-category | review-fe.md | phases.review_fe |
| TECH | /nacl-tl-review TECH### | task.md, result.md | Standard BE | review.md | status (top-level) |
Pre-Review Checks
Before starting, verify based on the review mode:
- Result file exists:
result-be.md(BE),result-fe.md(FE), orresult.md(TECH) - Status is ready: the corresponding phase in
status.jsonshowsready_for_review - Supporting files available: task, test-spec, impl-brief, acceptance as listed above
If any check fails, report the issue and exit.
Repo-wide Check Gate (Mandatory, Strict-Only)
CRITICAL: Before any quality review, the agent MUST run repo-wide lint, typecheck, and test commands on the wave-tip commit (the HEAD commit of the branch under review). This gate is strict-only — strict is the single, unconditional mode and there is no fallback branch, no opt-out flag, and no per-project relaxation. The Project-Alpha Wave 4 false-PASS (lint red + typecheck red + 3 unwired publishers at 17:07 on 2026-05-11) is the canonical episode this gate exists to prevent.
Commands
Resolve the repo-wide command triple (lint / typecheck / test) through this priority chain, then run all three on the wave-tip commit, in this order:
-
config.yaml→repo_checks.lint/repo_checks.typecheck/repo_checks.test— the project's declared repo-wide commands (covers turbo/nx/make wrappers and any non-standard layout). Each key that is present is used verbatim. -
Otherwise, derive from the repository root's package manager — read the
packageManagerfield of the rootpackage.json; if absent, detect by lockfile:Detected lint typecheck test pnpm ( pnpm-lock.yaml)pnpm -r lintpnpm -r typecheckpnpm -r testnpm ( package-lock.json)npm run lint --workspacesnpm run typecheck --workspacesnpm run test --workspacesyarn ( yarn.lock)yarn workspaces run lintyarn workspaces run typecheckyarn workspaces run testDo NOT add
--if-presentor any flag that turns a missing script into silent success — a missing script MUST fail the command. -
Neither source resolves (no
repo_checks.*keys, nopackageManager, no recognised lockfile) → the triple isunrunnable(see Gate Decision below).
Once resolved, the three commands are literal. Do not swap in a
different runner mid-review, do not drop the workspace-recursive flag,
do not skip a stage because "the project doesn't have that script."
Each missing script counts as unrunnable, not as pass. The chain
above selects the project's own commands (per the config-first
discipline of the stack-de-prescription release); it is NOT a license
to substitute a runner the project did not declare or detectably use.
Gate Decision
| Condition | Action |
|---|---|
| All three commands run AND all three exit 0 | PROCEED to stub gate; record repo-checks-GREEN:<wave-tip-commit> as evidence |
| Any command exits non-zero (red checks) | REFUSE VERIFIED — emit REVIEW APPLIED — BLOCKED (repo-checks-RED) |
| Any command did not run (unrun, missing script, runner crash) | REFUSE VERIFIED — emit REVIEW APPLIED — BLOCKED (repo-checks-UNRUN) |
| Any command is unrunnable on this workspace (e.g. resolved package manager not installed, no workspace root, no resolvable command source per the priority chain) | REFUSE VERIFIED — emit REVIEW APPLIED — BLOCKED (repo-checks-UNRUNNABLE) |
VERIFIED refused if repo checks are red/unrun on wave-tip — override requires signed exception (W4). The signed-exception schema is defined by W4; until W4 lands, the only override path is for an operator to file a signed exception under the schema W4 will publish. There is no inline operator-prompt override at this gate. Strict is the single, unconditional mode for this gate — every project moves through it the same way.
Recording the Evidence
When all three resolved commands pass on the wave-tip commit, write the
literal string repo-checks-GREEN:<commit-sha> to the review artifact
(the Evidence section) and to Task.verification_evidence alongside
any test-GREEN payload already written. The evidence means "the
project's resolved repo-wide lint/typecheck/test triple all exited 0 on
this commit" — it is not tied to any particular package manager. The
evidence taxonomy entry is in
skills-for-codex/references/verification-evidence.md.
When the gate refuses VERIFIED, write the closed Codex Status: BLOCKED
with workflow detail repo-checks-RED / repo-checks-UNRUN /
repo-checks-UNRUNNABLE as applicable. Do NOT promote the verdict to
APPROVED. Do NOT proceed to Step 8 verdict assignment with any
PASS-family headline.
Project-kind interaction
config.yaml may declare project_kind: standard (default) or
project_kind: prototype. The repo-wide check gate applies in both
modes. project_kind: prototype only governs the W4 PR/CI carve-outs
for direct-strategy releases; it does NOT relax local repo-check
expectations. A prototype with a red repo-wide typecheck still has
VERIFIED refused at this gate.
See nacl-tl-core/references/config-schema.md for the project_kind
specification.
Nav-actions consumer check (Mandatory, Strict-Only)
CRITICAL: For every UC affected by the current review, the agent MUST verify two reachability conditions before any PASS-family headline is emitted:
- The UC's Form has populated
HAS_INBOUND_ACTIONedges (per W7 "Nav Actions" subsection ofnacl-sa-ui/SKILL.md). - The QA evidence for the UC references at least one natural entrypoint path — i.e. a route reached by clicking through the affordance, not a route entered via direct URL paste.
This check is the consumer-side read of the W7 graph rule. This skill
does not own the rule, the Cypher, or the edges; it owns the
consumer-side refusal that prevents an unreachable UC from clearing
review. Primary-owner exception for this consumer touch is declared
in the W7 plan scope_in (nacl-tl-review (consumer-side: graph-rule check — primary-owner exception, declared here)).
Scope of the check
The check applies to every affected UC of the review (typically one
UC per --be / --fe invocation, multiple for batch review). An
affected UC is exempt only when one of the following exemption flags
is set on the UseCase node in the graph:
UseCase.actor = 'SYSTEM'— machine-triggered, no user affordance required.UseCase.has_ui = false— no Form attached.UseCase.entrypoint_type IN ['deep-link-only', 'embed-only']— intentional URL-only or embed-only UC; each such exemption requires a signed exception under the W4 schema referencing the operational context (invitation link, partner iframe, etc.).- A
Screenreached from the UC viaHAS_SCREENhasformless = true— the screen renders no Form by specification (splash / 404 / landing; a stub Form is forbidden by the no-stubs-in-docs rule), so Condition 1 (an unreachable Form) is inapplicable — there is no Form to reach. This is self-justifying: theformless=trueflag is the spec record, so no signed W4 exception is required (sa-validate L10.2 already exempts formless screens from theRENDERS -> Formrequirement). Condition 2 STILL applies, read against the screen route (see below).
An affected UC that is NOT exempt and that fails either of the two conditions above triggers refusal.
Procedure
Condition 1 — populated nav-actions
Run the W7 reachability blocker query from
nacl-sa-ui/references/reachability.cypher § 4
(ui_reachability_blockers), scoped to the affected UCs:
// nav_actions_consumer_check
MATCH (uc:UseCase) WHERE uc.id IN $affected_uc_ids
MATCH (uc)-[:ACTOR]->(role:SystemRole)
WHERE coalesce(role.name, '') <> 'SYSTEM'
AND coalesce(uc.has_ui, true) = true
AND NOT coalesce(uc.entrypoint_type, '') IN ['deep-link-only', 'embed-only']
AND NOT EXISTS {
MATCH (uc)-[:HAS_SCREEN]->(scr:Screen)
WHERE coalesce(scr.formless, false) = true
}
OPTIONAL MATCH (uc)-[:USES_FORM]->(f:Form)
OPTIONAL MATCH (c:Component)-[:HAS_INBOUND_ACTION]->(f)
WITH uc, f, collect(DISTINCT c) AS inbound_components
WHERE f IS NULL OR size(inbound_components) = 0
RETURN uc.id AS uc_id,
coalesce(f.id, '<no-form>') AS form_id,
CASE WHEN f IS NULL THEN 'no-form' ELSE 'no-inbound-action' END AS reason
Any row in the result set is a blocker. The check fails.
Condition 2 — QA evidence references a natural entrypoint
The check is satisfied when at least one QA evidence artifact for the
UC explicitly records a navigation step from a parent screen to the
UC's Form via a captured HAS_INBOUND_ACTION affordance.
Formless screens. When the UC's screen is formless = true there
is no Form to navigate to; the natural entrypoint is entry onto the
screen route itself. Acceptable evidence is a QA artifact that
reaches the screen's canonical route through the app — a nav item, a
link, or, for a root entrypoint (route = '/'), direct navigation
to the root, which IS the natural entry (nothing sits above the root to
click through from). A non-root formless screen with no in-app path to
its route still fails Condition 2.
The reviewer reads the QA artifacts (.tl/tasks/UC###/qa-*.md and
linked screenshots / Playwright traces). Acceptable evidence shapes:
- A Playwright trace whose first navigation step opens the parent
screen at its canonical route, followed by a
clickon a locator matching aHAS_INBOUND_ACTION.labelvalue, followed by an assertion at the target Form's route. - A QA report section "Entrypoint path" listing
Parent screen → affordance label → target Form, with a screenshot of the parent screen rendering the affordance. - An E2E test file imported by the test suite whose journey assertion starts from a parent route and reaches the target Form via an affordance click — and which produced output at Step 6a above.
If no such evidence is found, the check fails for the UC.
Gate Decision
| Condition | Action |
|---|---|
| Both conditions hold for every non-exempt affected UC | PROCEED; record nav-actions-GREEN:<uc_id>,<uc_id>,… as evidence (one per affected UC); proceed to Step 8 with PASS-family headline allowed |
| Condition 1 fails for any non-exempt affected UC | REFUSE VERIFIED — emit REVIEW APPLIED — BLOCKED (nav-actions-missing); the Code judgment line is CHANGES REQUESTED |
| Condition 1 holds but Condition 2 fails for any non-exempt affected UC | REFUSE VERIFIED — emit REVIEW APPLIED — BLOCKED (nav-actions-no-natural-entrypoint-evidence); verdict is CHANGES REQUESTED |
UC is exempt under actor=SYSTEM / has_ui=false / entrypoint_type ∈ {deep-link-only, embed-only} AND the exemption is recorded on the UseCase node OR carried by a signed exception (W4) | EXEMPT; record nav-actions-EXEMPT:<uc_id>:<reason> and proceed |
UC's HAS_SCREEN screen has formless=true (self-justifying; no signed exception) AND Condition 2 holds against the screen route | EXEMPT for Condition 1; record nav-actions-EXEMPT:<uc_id>:formless and proceed. If Condition 2 fails, refuse as usual (nav-actions-no-natural-entrypoint-evidence) |
VERIFIED refused if nav-actions are missing or the QA evidence does not reference a natural entrypoint — override requires signed exception (W4). The signed-exception schema is the same one used by the W1 repo-wide check gate; until W4 lands, the only override path is a signed exception filed under the schema W4 will publish. There is no inline operator-prompt override at this gate.
Project-kind interaction
project_kind: prototype does NOT relax this gate. A prototype that
ships an actor-triggered UC without a populated nav-actions section
or without natural-entrypoint QA evidence still has VERIFIED refused
at this gate. project_kind governs only the W4 PR/CI carve-outs
for direct-strategy releases.
See nacl-tl-core/references/config-schema.md for project_kind and
nacl-sa-ui/references/reachability.cypher for the full query
templates.
Recording the Evidence
When the check passes for every non-exempt affected UC, write
nav-actions-GREEN:<uc-id>,<uc-id>,… (comma-separated) to the
review artifact's Evidence section and to
Task.verification_evidence alongside any test-GREEN /
repo-checks-GREEN evidence already written. For exempt UCs, write
nav-actions-EXEMPT:<uc-id>:<reason> on a separate line.
When the gate refuses, write the closed Codex Status: BLOCKED
with workflow detail nav-actions-missing or
nav-actions-no-natural-entrypoint-evidence. Do NOT promote the
verdict to APPROVED. Do NOT proceed to Step 8 verdict assignment
with any PASS-family headline.
Worked example — Project-Beta UC-100 missing-upload-button
Project-Beta UC-100 ("Upload audio") was shipped with a fully
specified FORM-Upload (fields, validation, mutation) and a working
/upload route, yet the catalog page at /catalog carried no
upload button. UC-100's review at the time emitted REVIEW COMPLETE
because the page-local Form spec was satisfied. The Nav-actions
consumer check would have caught the gap:
- Condition 1 —
nav_actions_consumer_checkwith$affected_uc_ids = ['UC-100']returns one row{uc_id: 'UC-100', form_id: 'FORM-Upload', reason: 'no-inbound-action'}because no Component carried a HAS_INBOUND_ACTION edge to FORM-Upload. - The check FAILS. Headline becomes
REVIEW APPLIED — BLOCKED (nav-actions-missing); verdictCHANGES REQUESTED; action required: "add HAS_INBOUND_ACTION edges pernacl-sa-ui/SKILL.mdNav Actions subsection; re-run/nacl-sa-ui navigationto capture the catalog page upload CTA; re-submit for review."
The methodology stops the false-PASS at the review boundary instead of letting it ship and surface as a production-only "where is the upload button" report.
Stub Verification Gate (Mandatory)
CRITICAL: Before the review can proceed, the agent MUST verify stubs. This gate runs before any code quality checks.
Procedure
- Read
.tl/stub-registry.jsonand filter entries for the current task - Read
.tl/tasks/{id}/stub-report.mdif it exists - Scan all files listed in the result artifact for markers:
TODO,FIXME,STUB,MOCK,HACK - Apply classification from
nacl-tl-core/references/stub-tracking-rules.md
Gate Decision
| Condition | Action |
|---|---|
| CRITICAL stubs found | BLOCK -- review impossible, return to developer |
| Orphaned stubs (no UC reference) | BLOCK -- all stubs must be bound to a UC |
| WARNING stubs (count <= 3) | FLAG in review, proceed with caution |
| WARNING stubs (count > 3) | VALIDATE JUSTIFICATION — each stub comment must match the ticket-reference regex (see below); any that fail force phase rollback |
| No stubs or only INFO | PROCEED normally |
Warning Stub Justification Requirement
When WARNING stub count exceeds 3, each stub justification MUST satisfy the following regex (case-insensitive):
(UC|TECH|FR|BUG)-?\d+|https?://
The agent MUST scan the comment text of every WARNING stub and test it against this pattern. If any stub comment fails the regex match:
- Set the phase status back to
in_progress. - Halt the review and emit:
REVIEW HALTED — UNVERIFIED (stubs lack ticket references)
The following stub justifications do not contain a valid ticket ID or URL:
- <File:Line>: "<comment text>"
- ...
Required format: reference a ticket ID (e.g. UC014, TECH-042, FR-7, BUG99)
or a full URL (https://...) in each stub comment.
Action: update stub comments to include ticket references, re-run /nacl-tl-stubs, resubmit for review.
Run: /nacl-tl-dev-be UC### --continue | /nacl-tl-dev-fe UC### --continue | /nacl-tl-dev TECH### --continue
A stub comment that passes the regex but still provides no meaningful context is a MAJOR issue recorded in the review — but does not force rollback. Only the absence of any ticket/URL token triggers rollback.
Example acceptable justification:
// STUB(UC014): placeholder until payment gateway is integrated — TECH-042
Example acceptable (URL):
// TODO: replace with real API — https://linear.app/team/issue/BACK-77
Example unacceptable (free-text only — triggers rollback):
// TODO: add real implementation later
// TODO: see backlog
Frontend-Specific Stub Checks (--fe only)
- Hardcoded mock data in components (arrays with test names/emails)
// TODO: replace with real API callcomments- MSW handlers that should be removed from production code
- Placeholder images (
via.placeholder.com,/placeholder.png) - Placeholder text (
Lorem ipsum,Test,Sample) console.logstatements in component code
If Gate BLOCKS
Set the phase status back to in_progress, display the blocking stubs, and exit:
Stub Gate: BLOCKED
Task: UC### [Title]
Reason: Critical stubs detected
| ID | File:Line | Severity | Description |
|----|-----------|----------|-------------|
| STUB-001 | src/orders/order.service.ts:45 | CRITICAL | Empty getOrders() |
Action: Resolve all CRITICAL stubs, re-run /nacl-tl-stubs, resubmit for review.
Run: /nacl-tl-dev-be UC### --continue | /nacl-tl-dev-fe UC### --continue | /nacl-tl-dev TECH### --continue
Workflow
Step 1: Read Task Files
Read ALL relevant files for the identified review mode.
Backend (--be):
.tl/tasks/UC###/
task-be.md # What was supposed to be implemented (backend)
test-spec.md # Expected test cases
impl-brief.md # Implementation guidelines
acceptance.md # Acceptance criteria to verify
result-be.md # Development results to review
Frontend (--fe):
.tl/tasks/UC###/
task-fe.md # What was supposed to be implemented (frontend)
test-spec-fe.md # Expected RTL test cases
impl-brief-fe.md # UI implementation guidelines
acceptance.md # Acceptance criteria to verify
result-fe.md # Development results to review
TECH (no flag):
.tl/tasks/TECH###/
task.md # What was supposed to be implemented
result.md # Development results to review
Step 2: Update Status to in_review
Set the appropriate phase in status.json:
- BE:
phases.review_be = "in_review" - FE:
phases.review_fe = "in_review" - TECH:
status = "in_review"
Step 3: Verify Acceptance Criteria (requirements traceability)
Enumerate every acceptance criterion / REQ in acceptance.md as its own row — do not collapse them into the category groups (Functional, Business Rules, Error Handling, Performance, Security). Category-grouped review lets a single missing requirement hide inside a mostly-passing group; a per-criterion pass is the cheapest defence against the "missing-requirement" defect class (e.g. an AI-call audit log the spec demands but no code writes).
For each criterion, establish three facts before scoring:
- Implemented? the code under review actually does what the criterion requires — confirmed by reading the runtime that produces the behaviour (Step 4a cross-file trace), not by the presence of a plausibly-named function. A "feature" that calls the wrong runtime (dead config) is NOT implemented.
- Reachable? the behaviour is reachable end-to-end from a real entrypoint — for UI-affecting criteria reuse the Nav-actions natural-entrypoint evidence (see the Nav-actions consumer check) as the reachability witness.
- Tested? a test or QA path exercises it.
Score each criterion PASS / PARTIAL / FAIL. A criterion implemented but unreachable — or implemented but untested where the spec demands a test — is at most PARTIAL. A criterion not implemented, or implemented against the wrong runtime, is FAIL. PARTIAL means partly met with a gap that does not block (e.g., happy path covered but an edge case missing); the verdict aggregator decides promotion. If any of the three facts (implemented / reachable / tested) cannot be positively confirmed from the code or tests, score the criterion at most PARTIAL and record the unconfirmed fact — never PASS on absence of evidence.
Step 4: Code Quality Review
Apply the appropriate checklist (see detailed checklists below).
4a. Cross-file trace (Mandatory)
The change under review is the diff, but you MUST judge it in context — read the files the diff depends on and the files that depend on it, using the actual repo (not just the diff hunks):
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 27
- Forks
- 4
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
nacl-tl-review- Source
- github.com/itsalt/nacl