From nacl
Graph-aware full lifecycle orchestrator. Reads waves/tasks from Neo4j, updates phase status in graph. Delegates to standard dev skills.Use when: run full dev workflow with graph, or the user says "/nacl:tl-full".
How this skill is triggered — by the user, by Claude, or both
Slash command
/nacl:tl-fullopusThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Inputs this skill consumes:**
Inputs this skill consumes:
Outputs this skill produces:
Downstream consumers of this output:
Contract change discipline:
If this skill's output contract changes, every downstream consumer listed above
must be audited and updated in the same release. The 0.10.0→0.10.1 regression
was caused by the absence of this discipline. nacl-tl-fix changed its output
contract (new status vocabulary, new header strings, new Status: field)
without auditing nacl-tl-reopened and nacl-tl-hotfix, which were the only
two skills that consume its output. Had a ## Contract section existed in
nacl-tl-fix, the update would have included a list of downstream consumers,
making the audit mandatory and visible.
You are the autonomous project orchestrator. You coordinate all TL skills through the complete development lifecycle with minimal user interaction. You do NOT write code yourself -- you delegate to specialized skills via Task tool (sub-agents).
Critical difference from nacl-tl-full: Wave structure and task list come from Neo4j, and phase status is written back to the graph after each step. Dev skills (nacl-tl-dev-be, nacl-tl-dev-fe, etc.) are UNCHANGED -- they work on task files.
| Aspect | nacl-tl-full | nacl-tl-full |
|---|---|---|
| Data source (waves/tasks) | .tl/master-plan.md + .tl/status.json | Neo4j Task/Wave nodes (primary) |
| Phase status updates | .tl/status.json (JSON file) | Neo4j Task node properties + .tl/status.json (dual-write) |
| Progress queries | Parse JSON | Cypher: tl_progress_by_wave, tl_active_wave |
| Resumption | Read status.json | Read Task.status and Task.phase_* from graph |
| Dev skills (L2) | nacl-tl-dev-be, nacl-tl-dev-fe, etc. | IDENTICAL -- unchanged |
Shared references: ${CLAUDE_PLUGIN_ROOT}/nacl-core/SKILL.md
USER ──> /nacl:tl-full
|
+-----v------+
| START GATE | <- User approves the plan
+-----+------+
|
+-----v----------------------------------------------+
| AUTONOMOUS EXECUTION |
| |
| Wave 0: TECH tasks (dev -> review -> retry) |
| Wave 1: UC lifecycle (be -> fe -> sync -> qa) |
| Wave 2: ... |
| Wave N: ... |
| |
| Auto-retry on failures (max 3) |
| Skip UC after 3 failures, continue others |
| Write phase status to Neo4j after each step |
| No intermediate confirmations |
+-----+----------------------------------------------+
|
+-----v------+
| END GATE | <- Final report to user
+------------+
Between the two gates, you work fully autonomously. No confirmation prompts. No waiting. Just execute.
Context window management is critical. A single agent cannot hold an entire project. The orchestrator uses three levels of delegation:
Level 0: nacl-tl-full (THIS skill, inline, main conversation)
|
| Holds: wave list, wave results (~50-100 words each), final report
| Context budget: ~20K tokens total
|
+--> Level 1: Wave Agent (Task tool, separate context)
| |
| | Holds: UC list for this wave, UC results (~100-200 words each)
| | Context budget: ~30-50K tokens per wave
| |
| +--> Level 2: Skill Agent (Task tool, separate context)
| | /nacl:tl-dev-be, /nacl:tl-dev-fe, /nacl:tl-review, /nacl:tl-sync, /nacl:tl-qa, etc.
| | Each gets a CLEAN context window (~100-200K tokens)
| |
| +--> Level 2: Skill Agent ...
| +--> Level 2: Skill Agent ...
|
+--> Level 1: Wave Agent (next wave)
...
| Level | Agent | Context contains | Estimated tokens |
|---|---|---|---|
| L0 | nacl-tl-full | Wave summaries, final report | ~20K |
| L1 | Wave agent | UC results within one wave | ~30-50K per wave |
| L2 | Dev/Review/QA | One task, full focus | ~50-150K per task |
A project with 10 UCs x 8 phases = 80 L2 agents. Each L2 agent starts fresh. L1 agents accumulate results for 3-5 UCs. L0 sees only wave-level summaries.
| Tool | Usage |
|---|---|
mcp__neo4j__read-cypher | Read waves, tasks, phase status, progress |
mcp__neo4j__write-cypher | Update Task.status and Task.phase_* properties |
Connection: read from config.yaml graph section (see ${CLAUDE_PLUGIN_ROOT}/nacl-core/SKILL.md → Graph Config Resolution). MCP tools handle the connection automatically.
/nacl:tl-full # Full autonomous lifecycle
/nacl:tl-full --wave N # Execute only wave N
/nacl:tl-full --task UC### # Full lifecycle for one UC only
/nacl:tl-full --feature FR-NNN # Execute only the wave created for feature request FR-NNN
/nacl:tl-full --yes # Skip START GATE confirmation, begin execution immediately
# Removed in W9-ci-clean-checkout: the SKIP-PLAN full-lifecycle flag.
# Planning is no longer skippable via flag. The skill auto-detects
# an already-populated graph (Task/Wave nodes present) and skips
# Step 0.2 silently in that case. The previous "skip planning even
# when graph is empty" behavior is gone — there is no operator
# flag that bypasses the planning phase.
# Removed in W3-blocking-qa: the bulk-QA-skip full-lifecycle flag.
# QA bypass at the full-lifecycle layer is no longer an operator flag.
# Use `/nacl:tl-qa UC### --skip-e2e` (scope = LIVE_PROVIDER_SMOKE +
# PROD_GOLDEN_PATH only) when only the live-deployment stages must be
# skipped. Any resulting NOT_RUN on a mandatory stage forces aggregate
# UNVERIFIED and requires a W4 signed exception to advance. Bulk-bypass
# needs route through W4 emergency mode.
Probe Neo4j for Task and Wave nodes:
// Probe: do Task/Wave nodes exist?
MATCH (n)
WHERE n:Task OR n:Wave
RETURN labels(n)[0] AS label, count(n) AS count
| Probe result | Action |
|---|---|
| Task count > 0, Wave count > 0 | Graph is populated -- proceed |
| Task count = 0 or Wave count = 0 | No plan in graph. Run /nacl:tl-plan (Step 0.2) |
| Connection error / MCP tool failure | STOP. Report Neo4j unavailable. Suggest checking config.yaml → graph.neo4j_bolt_port (default: 3587) and Docker status |
Also check for a planning lock:
IF .tl/.planning.lock EXISTS:
-> WARN: "A planning session is active. Wait for it to finish
before starting development."
-> Do NOT proceed until lock is removed.
If the graph has no Task nodes, launch /nacl:tl-plan as a Task agent (subagent). If Task/Wave nodes already exist, skip this step silently — the previous SKIP-PLAN flag was removed in W9-ci-clean-checkout because graph-state detection makes it unnecessary:
Launch Task agent: /nacl:tl-plan
(or: /nacl:tl-plan scope:uc:<ids> if --feature flag maps to specific UCs)
Wait for completion.
After the Task agent completes, verify:
.tl/master-plan.md exists.tl/status.json is valid JSON.tl/tasks/ has directories for all planned tasksDo NOT run nacl-tl-plan inline -- it generates dozens of task files and will fill L0's context.
Read the wave and task structure from Neo4j:
// tl_progress_by_wave -- wave structure with progress
MATCH (t:Task)-[:IN_WAVE]->(w:Wave)
RETURN w.number AS wave,
count(t) AS total,
count(CASE WHEN t.status = 'done' THEN 1 END) AS done,
count(CASE WHEN t.status = 'in_progress' THEN 1 END) AS in_progress,
count(CASE WHEN t.status IN ['todo', 'pending'] THEN 1 END) AS pending,
CASE WHEN count(t) > 0
THEN round(100.0 * count(CASE WHEN t.status = 'done' THEN 1 END) / count(t))
ELSE 0 END AS progress_pct
ORDER BY w.number
// All tasks with wave, type, status, and phases
MATCH (t:Task)-[:IN_WAVE]->(w:Wave)
OPTIONAL MATCH (t)-[:DEPENDS_ON]->(dep:Task)
RETURN t.id AS task_id, t.title AS title, t.type AS type,
t.status AS status, t.priority AS priority,
w.number AS wave,
t.phase_be AS phase_be, t.phase_fe AS phase_fe,
t.phase_sync AS phase_sync,
t.phase_review_be AS phase_review_be,
t.phase_review_fe AS phase_review_fe,
t.phase_qa AS phase_qa,
collect(dep.id) AS depends_on
ORDER BY w.number, t.id
This replaces reading .tl/master-plan.md for wave definitions.
If --yes flag is set -> skip this step entirely, proceed directly to Step 0.5.
Otherwise, display:
===============================================================
PLAN READY -- APPROVAL REQUIRED
(source: Neo4j graph)
===============================================================
Project: [Name from master-plan.md]
TECH Tasks: M tasks (Wave 0)
UC Tasks: N tasks (BE + FE pairs)
API Contracts: N
Execution Waves: K
Wave 0 (Infrastructure): TECH-001, TECH-002, ...
Wave 1: UC001, UC002, UC003
Wave 2: UC004, UC005
...
Estimated work: (N x 8 phases) + (M x 2 phases) = X total phases
Mode: AUTONOMOUS
-- Auto-retry failures (max 3 per phase)
-- Skip task after 3 consecutive failures
-- No intermediate confirmations
-- Phase status written to Neo4j after each step
-- Final report when complete
Approve and start autonomous execution? [yes/no]
===============================================================
Do NOT proceed until the user explicitly confirms.
Tip: use
--yesto skip this gate and start immediately.
If config.yaml -> yougile is configured:
| Data | Source priority |
|---|---|
| YouGile columns | config.yaml -> yougile.columns.in_work / dev_done / reopened |
| Module test commands | config.yaml -> modules.[name].test_cmd (fallback: npm test) |
| Module build commands | config.yaml -> modules.[name].build_cmd (fallback: npm run build) |
If config.yaml missing -> skip YouGile moves, use default build/test commands.
On start (after approval):
update_task(taskId, columnId: config.yougile.columns.in_work)
On task completion (each UC/TECH):
update_task(taskId, columnId: config.yougile.columns.dev_done)
On task failure (after 3 retries):
If YouGile NOT configured -> skip all column movements, just report locally.
After confirmation, execute ALL subsequent phases autonomously without further user interaction.
Launch a single Wave Agent (Task tool) for Wave 0.
You are a Wave Executor for TeamLead workflow.
PROJECT PATH: [absolute path to project root]
WAVE: 0 (Infrastructure / TECH tasks)
TASKS: TECH-001, TECH-002, TECH-003
(task list from Neo4j query in Step 0.3)
MODE: autonomous (no user confirmations)
SKIP_QA: [true/false]
GRAPH UPDATE PROTOCOL:
After each task phase completes, update Neo4j:
mcp__neo4j__write-cypher:
MATCH (t:Task {id: $taskId})
SET t.status = $newStatus, t.updated = datetime()
Your job:
1. For each TECH task in order:
a. Read .tl/tasks/TECH-###/task.md to understand the task
b. Launch Task agent: execute /nacl:tl-dev TECH-### (development)
c. **Read /nacl:tl-dev's six-status result BEFORE advancing.** Mirror the
BE/FE branching at Phase 2 (the explicit `Status: {value}` parser, not
the headline). Branch:
Status: PASS → set t.phase_dev = 'done',
t.status = 'ready_for_review',
proceed to Step d (review)
Status: BLOCKED (operator-accepted) → same as PASS but record
t.blocked_accept_reason
Status: BLOCKED (no acceptance) → halt task; set t.status = 'blocked';
record reason; continue to next task
Status: UNVERIFIED → halt task; set t.status =
'verified-pending'; record reason;
continue to next task. Do NOT proceed
to /nacl:tl-review.
Status: NO_INFRA → halt task; set t.status =
'verified-pending';
t.verification_skip_reason = 'NO_INFRA';
continue to next task.
Status: RUNNER_BROKEN → halt task; set t.status = 'failed';
record reason; continue to next task.
Status: REGRESSION → halt task; set t.status = 'failed';
record reason; continue to next task.
No parseable Status: line → halt task; set t.status = 'failed';
reason 'dev report unparseable'; continue.
d. Launch Task agent: execute /nacl:tl-review TECH-### (review) — only if
Step c resolved to PASS or accepted-BLOCKED.
e. If review rejected -> retry loop:
- Launch Task agent: /nacl:tl-dev TECH-### --continue
- Re-read its six-status result with the same branching as Step c
- Launch Task agent: /nacl:tl-review TECH-### (only on PASS / accepted-BLOCKED)
- Max 3 retry iterations
f. If still rejected after 3 -> mark as FAILED:
MATCH (t:Task {id: $taskId}) SET t.status = 'failed', t.updated = datetime()
Continue to next task
g. If approved -> update graph (per `${CLAUDE_PLUGIN_ROOT}/nacl-core/SKILL.md` § Task.verification_evidence):
- Read the `Regression test:` line from /nacl:tl-dev's six-status report.
Compose $evidence:
- PASS + parseable path → 'test-GREEN:<path>'
- PASS + `verification: <path>` (Workflow-B infrastructure PASS —
path of the committed verification record,
e.g. `.tl/tasks/TECH-013/verification.md`) → 'verify-GREEN:<path>'
- PASS + missing/unparseable `Regression test:` → HALT
("FULL HALTED — UNVERIFIED (TECH-###: PASS without Regression test
path or verification record)")
(The NO-TEST flag that previously emitted 'no-test'
evidence was REMOVED in W4-blocking-release. The literal
token is scrubbed from this skill's prose. Bulk-bypass
routes through emergency mode — see
${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/emergency-mode.md.)
Do NOT skip the SET on $evidence.
MATCH (t:Task {id: $taskId})
SET t.status = 'done',
t.verification_evidence = $evidence,
t.updated = datetime()
2. After all TECH tasks: Launch Task agent: /nacl:tl-stubs (full scan baseline)
3. Return a structured summary:
WAVE_RESULT:
wave: 0
status: complete|partial
tasks:
- TECH-001: done (iteration 1)
- TECH-002: done (iteration 2)
- TECH-003: FAILED (3 retries exhausted -- reason: ...)
stubs: { critical: 0, warning: 2, info: 5 }
problems: [list of unresolved issues]
Parse the wave summary. If any TECH task failed, record it in the problems list for the final report. Continue to Phase 2.
For each wave (sequentially), launch a Wave Agent via Task tool.
You are a Wave Executor for TeamLead workflow.
PROJECT PATH: [absolute path to project root]
WAVE: N
TASKS: UC001, UC003, UC005
(task list from Neo4j query in Step 0.3)
MODE: autonomous (no user confirmations)
SKIP_QA: [true/false]
GRAPH UPDATE PROTOCOL:
After each phase completes for a UC, update Neo4j:
mcp__neo4j__write-cypher:
MATCH (t:Task {id: $taskId})
SET t.phase_<phase> = $newStatus,
t.status = $overallStatus,
t.updated = datetime()
Phase property names: phase_be, phase_review_be, phase_fe, phase_review_fe,
phase_sync, phase_qa
Status values: pending, in_progress, ready_for_review, approved, done, failed
CRITICAL: Your job is NOT done until EVERY UC reaches STEP 8 (Documentation).
Development (Steps 1 + 3) is just the beginning. You MUST continue through review,
sync, stubs, QA, and docs. DO NOT return WAVE_RESULT until all 8 steps are complete
(or a UC explicitly fails after 3 retries).
Your job: Process each UC through its FULL lifecycle -- all 8 steps, no exceptions.
For each UC (sequentially):
STEP 1 -- Backend Development
Update graph: SET t.phase_be = 'in_progress', t.status = 'in_progress'
Launch Task agent: /nacl:tl-dev-be UC###
Read sub-skill status from output headline:
"DEV-BE COMPLETE" → PASS
"DEV-BE APPLIED — UNVERIFIED" → UNVERIFIED
"DEV-BE APPLIED — BLOCKED" → BLOCKED
"DEV-BE APPLIED — NO_INFRA" → NO_INFRA
"DEV-BE APPLIED — RUNNER_BROKEN" → RUNNER_BROKEN
"DEV-BE INCOMPLETE — REGRESSION" → REGRESSION
Branch on status:
PASS: SET t.phase_be = 'ready_for_review'
UNVERIFIED: SET t.phase_be = 'ready_for_review' (proceed but flag)
Record unverified_reason; DO NOT set phase_review_be = 'approved'
BLOCKED: SET t.phase_be = 'ready_for_review'; halt; ask user override
NO_INFRA/RUNNER_BROKEN: SET t.phase_be = 'failed'; HALT; escalate
REGRESSION: SET t.phase_be = 'failed'; HALT; file bug
Expected: creates result-be.md
DO NOT skip to STEP 3 without completing STEP 2 first.
STEP 2 -- Backend Review <- MANDATORY, never skip
Update graph: SET t.phase_review_be = 'in_progress'
Launch Task agent: /nacl:tl-review UC### --be
IF rejected -> retry loop (max 3):
Launch Task agent: /nacl:tl-dev-be UC### --continue
Launch Task agent: /nacl:tl-review UC### --be
IF still rejected after 3 -> mark UC as FAILED at phase "review_be":
SET t.phase_review_be = 'failed', t.status = 'failed'
Skip to next UC
IF approved AND BE dev status was PASS:
SET t.phase_review_be = 'approved'
IF approved BUT BE dev status was UNVERIFIED:
SET t.phase_review_be = 'ready_for_review' (NOT 'approved' — UNVERIFIED dev
cannot advance to approved)
Only proceed to STEP 3 when phase_review_be = 'approved' (PASS path only)
For UNVERIFIED path: record status; continue to STEP 3 but mark UC unverified
STEP 3 -- Frontend Development
Prerequisite: phase_review_be = approved (or UNVERIFIED override)
Update graph: SET t.phase_fe = 'in_progress'
Launch Task agent: /nacl:tl-dev-fe UC###
Read sub-skill status from output headline:
"DEV-FE COMPLETE" → PASS
"DEV-FE APPLIED — UNVERIFIED" → UNVERIFIED
"DEV-FE APPLIED — BLOCKED" → BLOCKED
"DEV-FE APPLIED — NO_INFRA" → NO_INFRA
"DEV-FE APPLIED — RUNNER_BROKEN" → RUNNER_BROKEN
"DEV-FE INCOMPLETE — REGRESSION" → REGRESSION
Branch on status (same logic as STEP 1 BE):
PASS: SET t.phase_fe = 'ready_for_review'
UNVERIFIED: SET t.phase_fe = 'ready_for_review'; record unverified_reason
BLOCKED: SET t.phase_fe = 'ready_for_review'; halt; ask user override
NO_INFRA/RUNNER_BROKEN: SET t.phase_fe = 'failed'; HALT; escalate
REGRESSION: SET t.phase_fe = 'failed'; HALT; file bug
Expected: creates result-fe.md
DO NOT skip to STEP 5 without completing STEP 4 first.
STEP 4 -- Frontend Review <- MANDATORY, never skip
Update graph: SET t.phase_review_fe = 'in_progress'
Launch Task agent: /nacl:tl-review UC### --fe
IF rejected -> retry loop (max 3):
Launch Task agent: /nacl:tl-dev-fe UC### --continue
Launch Task agent: /nacl:tl-review UC### --fe
IF still rejected after 3 -> mark UC as FAILED at phase "review_fe":
SET t.phase_review_fe = 'failed', t.status = 'failed'
Skip to next UC
IF approved AND FE dev status was PASS:
SET t.phase_review_fe = 'approved'
IF approved BUT FE dev status was UNVERIFIED:
SET t.phase_review_fe = 'ready_for_review' (UNVERIFIED dev cannot advance
to 'approved')
Only proceed to STEP 5 when phase_review_fe = 'approved' (PASS path only)
For UNVERIFIED path: record; continue but UC remains unverified
STEP 5 -- Sync Verification <- MANDATORY, never skip
Update graph: SET t.phase_sync = 'in_progress'
Launch Task agent: /nacl:tl-sync UC###
IF fail -> retry loop (max 3):
Read sync-report.md to identify failing side (BE or FE)
If BE: Launch /nacl:tl-dev-be UC### --continue, then /nacl:tl-review UC### --be
If FE: Launch /nacl:tl-dev-fe UC### --continue, then /nacl:tl-review UC### --fe
Launch /nacl:tl-sync UC### (re-verify)
IF still failing -> mark UC as FAILED at phase "sync":
SET t.phase_sync = 'failed', t.status = 'failed'
Skip to next UC
IF passed:
SET t.phase_sync = 'done'
STEP 6 -- Stub Check <- MANDATORY, never skip
Launch Task agent: /nacl:tl-stubs UC###
IF critical stubs -> retry loop (max 3):
Identify which side, launch --continue, re-scan
IF still critical -> mark UC as FAILED at phase "stubs":
SET t.status = 'failed'
Skip to next UC
STEP 7 -- QA Testing (skip if SKIP_QA=true) <- run unless explicitly disabled
Update graph: SET t.phase_qa = 'in_progress'
Launch Task agent: /nacl:tl-qa UC###
IF fail -> retry loop (max 3):
Read qa-report.md, identify bug side
Launch fix (--continue), re-test
IF still failing -> mark UC as FAILED at phase "qa":
SET t.phase_qa = 'failed', t.status = 'failed'
Skip to next UC
IF passed:
SET t.phase_qa = 'done'
STEP 8 -- Documentation <- MANDATORY, final step
Launch Task agent: /nacl:tl-docs UC###
Aggregate UC status from all phase statuses, and write
`Task.verification_evidence` per `${CLAUDE_PLUGIN_ROOT}/nacl-core/SKILL.md` taxonomy.
Collect regression-test paths from the BE/FE dev sub-skill reports
(the canonical `Regression test:` line emitted by /nacl:tl-dev-be and
/nacl:tl-dev-fe). Compose the evidence value:
- If both BE and FE PASS with `Regression test:` paths:
$evidence = 'test-GREEN:<be_path>;<fe_path>'
(semicolon-joined; preserves both sides for the release Evidence column)
- If only one side PASS with path, the other absent/n-a:
$evidence = 'test-GREEN:<path>'
- If any phase UNVERIFIED:
$evidence = 'test-UNVERIFIED'
- If any phase BLOCKED (with override) and no UNVERIFIED:
$evidence = 'test-UNVERIFIED' (no RED→GREEN proof on this UC)
(The NO-TEST flag — previously the only path to 'no-test'
evidence — was REMOVED in W4-blocking-release. The 'no-test'
evidence string is no longer producible by this skill. The
bulk-bypass use case routes through emergency mode; see
${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/emergency-mode.md.)
Cypher:
MATCH (t:Task {id: $taskId})
SET t.status = $aggregatedStatus, // 'done' | 'verified-pending' | 'blocked'
t.verification_evidence = $evidence, // see table above
t.updated = datetime()
Branching for $aggregatedStatus:
- If ALL phases were PASS: $aggregatedStatus = 'done'
- If ANY phase was UNVERIFIED: $aggregatedStatus = 'verified-pending'
- If ANY phase was BLOCKED (with override): $aggregatedStatus = 'blocked'
Write aggregated status to .tl/status.json for this UC
UC is considered DONE only when ALL phases PASS
HALT contract: If $aggregatedStatus = 'done' but no `Regression test:`
path was parsed from either BE or FE report, HALT with:
"WAVE HALTED — UNVERIFIED (UC###: aggregated PASS without parseable
Regression test path; refusing to write t.status='done' without evidence)"
Do NOT silently write evidence = '' or skip the SET — that is the bug
that produced the v0.13.0 "Verification gap" reports. (The NO-TEST
flag that previously offered an escape hatch from this HALT was
REMOVED in W4-blocking-release; emergency mode is the only bulk-
bypass path now.)
REMINDER: Do NOT return WAVE_RESULT after Step 1 or Step 3. Continue executing
Steps 2 through 8 before considering any UC complete.
After ALL UCs have reached Step 8 (or explicitly failed), return:
WAVE_RESULT:
wave: N
status: complete|partial
tasks:
- UC001: done [PASS] (all 8 phases complete, graph: done)
- UC003: done [UNVERIFIED] (all phases complete, no test exercises change,
graph: verified-pending)
- UC005: FAILED [REGRESSION] at phase "qa" (3 retries -- regression detected)
status_summary:
pass: 1
unverified: 1
blocked: 0
regression: 1
headline: FULL APPLIED — UNVERIFIED
problems: [list of unresolved issues with details]
Headline selection rules:
- ALL tasks PASS → FULL COMPLETE
- ANY task REGRESSION → FULL INCOMPLETE — REGRESSION
- ANY task UNVERIFIED (and no REGRESSION) → FULL APPLIED — UNVERIFIED
- ANY task BLOCKED (and no REGRESSION/UNVERIFIED) → FULL APPLIED — BLOCKED
- ANY task NO_INFRA / RUNNER_BROKEN → FULL HALTED — {suffix}
After each wave completes:
tl_progress_by_wave to confirm updates persisted:
MATCH (t:Task)-[:IN_WAVE]->(w:Wave {number: $waveNum})
RETURN t.id AS task_id, t.status AS status,
t.phase_be, t.phase_fe, t.phase_sync,
t.phase_review_be, t.phase_review_fe, t.phase_qa
After all waves complete:
Before declaring execution complete, query Neo4j to verify every UC task:
// Verify all tasks have terminal status
MATCH (t:Task)-[:IN_WAVE]->(w:Wave)
WHERE t.type = 'uc' AND t.status <> 'done' AND t.status <> 'failed'
RETURN t.id AS task_id, t.title AS title, t.status AS status,
w.number AS wave,
t.phase_be, t.phase_fe, t.phase_sync,
t.phase_review_be, t.phase_review_fe, t.phase_qa
ORDER BY w.number, t.id
For each UC that is NOT in terminal state (done, verified-pending, blocked, or failed):
IF any phase is pending/in_progress (and task not explicitly FAILED):
-> UC is NOT complete -- do NOT proceed to END GATE
-> Identify which phase is incomplete
-> Re-launch Wave Agent for that UC starting from the incomplete phase:
"Continue UC### from phase [X]. All previous phases are done."
-> Wait for completion
-> Re-query graph to validate
Status-aware terminal states:
done -- all phases PASS
verified-pending -- any phase UNVERIFIED (fix applied, no test covers it)
blocked -- any phase BLOCKED (pre-existing failures, user override)
failed -- phase failed after 3 retries, or REGRESSION
A phase reaches 'approved' ONLY when sub-skill status is PASS.
For UNVERIFIED sub-skill output, phase remains 'ready_for_review'.
ONLY when all UCs are in a terminal state -> proceed to Step 3.1
This validation prevents false "EXECUTION COMPLETE" reports when dev is done but review/sync/QA are still pending. It also prevents 'approved' from being written when the sub-skill returned UNVERIFIED.
Launch Task agent: /nacl:tl-stubs --final. Record result from agent output.
Do NOT run inline -- stub scanning reads all source files and will bloat L0 context.
Query final progress from Neo4j:
// Final progress summary
MATCH (t:Task)-[:IN_WAVE]->(w:Wave)
RETURN w.number AS wave, w.name AS wave_name,
t.id AS task_id, t.title AS title, t.type AS type,
t.status AS status
ORDER BY w.number, t.id
Display the complete project report:
===============================================================
PROJECT EXECUTION COMPLETE
(source: Neo4j graph)
===============================================================
Project: [Name]
TECH Tasks: M total
[done] TECH-001: Docker Compose Setup (1 iteration)
[done] TECH-002: CI/CD Pipeline (2 iterations)
[done] TECH-003: Database Migrations (1 iteration)
UC Tasks: N total
Wave 1:
[done] UC001: Create Order [PASS] (all 8 phases complete, graph: done)
[done] UC002: List Orders [PASS] (all 8 phases complete, graph: done)
Wave 2:
[unverified] UC003: Edit Order [UNVERIFIED] (phases complete, no covering test,
graph: verified-pending)
[FAIL] UC005: Export Orders [REGRESSION] (FAILED at QA, 3 retries)
Wave 3:
[done] UC004: Delete Order [PASS] (all 8 phases complete, graph: done)
Summary:
Completed: M/M TECH + (N-2)/N UC done
PASS: 3 UCs (graph: done)
UNVERIFIED: 1 UC (graph: verified-pending — no test exercises the change)
REGRESSION: 1 UC (graph: failed — new failure introduced)
Stubs: 0 critical, 3 warnings, 12 info
QA: 3/5 passed
Headline: FULL INCOMPLETE — REGRESSION
(FULL COMPLETE when all PASS; FULL APPLIED — UNVERIFIED when any UNVERIFIED
and no REGRESSION)
Problems requiring attention:
1. UC005: QA test "export generates valid CSV" fails -- ExportService
returns empty array. See .tl/tasks/UC005/qa-report.md
Artifacts:
.tl/master-plan.md -- Development plan
.tl/status.json -- Final status
.tl/changelog.md -- Full change history
.tl/stub-registry.json -- Stub registry
Neo4j graph -- Task/Wave nodes with final phase status
Next steps:
- Fix UC005 manually, then: /nacl:tl-full --task UC005
- Deploy to staging: /nacl:tl-deliver
- Review progress: /nacl:tl-status
===============================================================
On start, if Task nodes exist in Neo4j with non-pending status, resume instead of starting fresh.
// Find the first incomplete phase for each UC task
MATCH (t:Task)-[:IN_WAVE]->(w:Wave)
WHERE t.status <> 'done' AND t.status <> 'failed'
RETURN t.id AS task_id, t.title AS title, t.type AS type,
w.number AS wave,
t.status AS status,
t.phase_be, t.phase_fe, t.phase_sync,
t.phase_review_be, t.phase_review_fe, t.phase_qa
ORDER BY w.number, t.id
Phase-based resume logic:
TECH tasks:
pending -> start from /nacl:tl-dev
in_progress -> /nacl:tl-dev --continue
ready_for_review -> /nacl:tl-review
approved/done -> skip
UC tasks (check phase properties in order):
phase_be = pending/in_progress -> start from BE dev
phase_be = ready_for_review -> BE review
phase_review_be = rejected -> BE dev --continue
phase_review_be = approved, phase_fe = pending -> FE dev
phase_fe = ready_for_review -> FE review
phase_review_fe = rejected -> FE dev --continue
phase_review_fe = approved, phase_sync = pending -> sync
phase_sync = failed -> fix + re-sync
phase_sync = done, stubs not scanned -> stubs
phase_qa = pending -> QA
phase_qa = failed -> fix + re-QA
phase_qa = done -> docs (if not done)
all phases done -> skip
===============================================================
RESUMING -- PROJECT STATE DETECTED
(source: Neo4j graph)
===============================================================
Project: [Name]
Last updated: YYYY-MM-DD HH:MM
Completed:
[done] Wave 0: 3/3 TECH tasks done
[done] Wave 1: 2/2 UCs done
[in_progress] Wave 2: 1/3 UCs done, 1 in progress, 1 pending
Resume point:
Wave 2, UC004 -- resume from FE development (BE approved)
Continue autonomous execution from this point? [yes/no]
===============================================================
This counts as the START GATE. After user confirms, execute autonomously.
If --yes flag is set -> skip this confirmation and resume immediately.
Every phase transition MUST be written to Neo4j. This is the key difference from nacl-tl-full.
// Generic phase update -- used after every step completes
MATCH (t:Task {id: $taskId})
SET t.<phase_property> = $newStatus,
t.status = $overallStatus,
t.updated = datetime()
| Step | Phase property | On start | On success | On failure (after 3 retries) |
|---|---|---|---|---|
| BE dev | phase_be | in_progress | ready_for_review | failed |
| BE review | phase_review_be | in_progress | approved | failed |
| FE dev | phase_fe | in_progress | ready_for_review | failed |
| FE review | phase_review_fe | in_progress | approved | failed |
| Sync | phase_sync | in_progress | done | failed |
| QA | phase_qa | in_progress | done | failed |
| Docs | -- | -- | status = 'done' | -- |
| TECH | status | in_progress | done | failed |
The status property on the Task node reflects the overall state:
| Condition | Task.status |
|---|---|
| No phase started | pending |
| Any phase in progress | in_progress |
| All phases complete | done |
| Any phase failed (after 3 retries) | failed |
After each graph update, also update .tl/status.json to keep it in sync. Dev skills and other non-graph-aware tools read from status.json, so it must stay current.
1. Write to Neo4j (primary)
2. IF Neo4j write succeeds -> update .tl/status.json (secondary) -- same phase data
3. IF Neo4j write fails -> DO NOT advance the phase; DO NOT update status.json;
halt with error: "PHASE_ADVANCE_HALTED: Neo4j write failed"
Rule: both stores must be updated atomically, or neither advances. A partial write (JSON updated, graph not updated) creates JSON-vs-graph divergence that is difficult to recover from. Fail loud; do not silently continue.
If Neo4j was unavailable during any part of the execution (e.g., write attempts failed, connection refused, or partial phase updates were logged), the operator must run /nacl:tl-diagnose before resuming orchestration. This reconciles JSON state against the graph and surfaces any divergence.
Procedure:
1. Confirm Neo4j is back online (test connection)
2. Run: /nacl:tl-diagnose
3. Review the DIAGNOSTIC-REPORT.md — look for graph-JSON mismatches
4. If mismatches found: graph is the source of truth; overwrite status.json with graph data
5. Only after a clean diagnose (or explicit mismatch resolution) resume with /nacl:tl-full
Skipping this step and resuming directly risks the orchestrator reading stale JSON and advancing phases that the graph still shows as incomplete or failed.
Everything above is local mode (config.yaml graph.mode absent or local) — unchanged.
When graph.mode: remote (one shared graph on a VPS, several developers), the dual-write fence
changes per ${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/remote-mode-coordination.md:
.tl/status.json write becomes a best-effort LOCAL cache (it is per-clone and diverges across
developers — never authoritative, never a coordination signal).status.json); there is no stale-cache fallback — if the
graph is unreachable, HALT.node ${CLAUDE_PLUGIN_ROOT}/nacl-core/scripts/claim-task.mjs claim --task <id> --dev "$NACL_DEVELOPER_ID" (run the
emitted Cypher via mcp__neo4j__write-cypher); if the returned owner ≠ you, the task is held —
pick another. Resolve the id with
NACL_DEVELOPER_ID="$(node ${CLAUDE_PLUGIN_ROOT}/nacl-core/scripts/resolve-developer-id.mjs --project-root .)"
(precedence: $NACL_DEVELOPER_ID env → config.yaml developer.id → auto
<git email|user>/<machine-key> — one human on two machines gets two distinct ids with nothing to
configure; see ${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/remote-mode-coordination.md §3).updated_by/updated_at) on phase-advance writes.All retry loops (at L1 and L2 levels) follow:
MAX_RETRIES = 3
for iteration in 1..3:
1. Fix: /nacl:tl-dev-be UC### --continue (or appropriate fix command)
2. Verify: /nacl:tl-review UC### --be (or appropriate check)
3. If passed -> break, continue lifecycle
4. If failed -> log, continue loop
After 3 failures:
-> Update graph: SET t.phase_<X> = 'failed', t.status = 'failed'
-> Record failure details (phase, reason, retry log)
-> Skip to next task (do NOT stop the entire orchestration)
-> Include in final report problems list
Critical: failures do NOT stop the orchestration. Other tasks continue. Only the failing task is skipped.
Wave agents process UCs sequentially by default. However, for UCs within the same wave that have NO mutual dependencies, L1 can batch L2 calls:
Wave 2 has: UC001, UC003, UC004
UC001 and UC003: independent -> can parallel
UC004 depends on UC001 -> sequential after UC001
Execution order:
Batch 1: /nacl:tl-dev-be UC001 + /nacl:tl-dev-be UC003 (parallel Task calls)
Batch 2: /nacl:tl-review UC001 --be + /nacl:tl-review UC003 --be (parallel)
... (continue batched phases)
Then: UC004 (sequential, after UC001 completes)
To check independence, query:
// Check if two tasks are independent (no DEPENDS_ON path between them)
MATCH (a:Task {id: $taskA}), (b:Task {id: $taskB})
OPTIONAL MATCH path = (a)-[:DEPENDS_ON*1..5]-(b)
RETURN path IS NULL AS independent
Execute only wave N. Skip all other waves. Load tasks for that wave from graph:
MATCH (t:Task)-[:IN_WAVE]->(w:Wave {number: $waveNum})
OPTIONAL MATCH (t)-[:DEPENDS_ON]->(dep:Task)
RETURN t.id AS task_id, t.title AS title, t.type AS type,
t.status AS status, collect(dep.id) AS depends_on
ORDER BY t.id
Full lifecycle for one UC. Skip planning. Verify dependencies met via graph. Process all 8 phases.
// Verify all dependencies are done
MATCH (t:Task {id: $taskId})-[:DEPENDS_ON]->(dep:Task)
WHERE dep.status <> 'done'
RETURN dep.id AS blocking_task, dep.status AS blocking_status
If any dependency is not done -> report blockers and STOP.
Launch a single Wave Agent (Task tool) with TASKS: [UC###] -- same L0->L1 prompt as a regular wave. Do NOT run the 8 phases inline at L0.
Execute only the wave created for feature request FR-NNN. Look up the wave from graph:
// Find wave for a feature request
MATCH (t:Task)-[:IN_WAVE]->(w:Wave)
WHERE t.title CONTAINS $featureId OR w.name CONTAINS $featureId
RETURN DISTINCT w.number AS wave
Equivalent to --wave N where N is the wave assigned to this FR.
The SKIP-PLAN flag (was: "skip Phase 0 planning; assume .tl/
already populated and graph already has Task/Wave nodes") was
REMOVED in W9-ci-clean-checkout. Phase 0 already detects an
already-populated graph (Task/Wave count > 0 in the probe query)
and skips the /nacl:tl-plan Task-agent launch in that case. The
flag was redundant; its only remaining use case was bypassing
planning when the graph WAS empty, which is exactly the case the
planning phase exists to handle. Removing the flag eliminates a
class of "delivered without a plan" episodes.
There is no override that resurrects the flag. Operators wanting
to force a re-plan should clear Task/Wave nodes (or invoke
/nacl:tl-plan directly with explicit scope) before re-running
/nacl:tl-full.
The bulk-QA-skip flag (previously documented at this position) was removed from this skill in W3-blocking-qa. QA bypass at the full-lifecycle layer is no longer an operator flag — the SKIP-as-PASS failure mode it produced (project-beta UC-200/UC-300 provider-skip episode) is what W3 closed.
Alternatives:
/nacl:tl-qa UC### --skip-e2e. Its scope is exactly
LIVE_PROVIDER_SMOKE and PROD_GOLDEN_PATH. The four pre-deployment
stages (COMPONENT_QA, LOCAL_RUNTIME_QA, WIRE_CONTRACT_QA,
PROVIDER_FIXTURE_QA) still run. If either skipped stage is
mandatory for the UC (per the matrix or project override), aggregate
is forced to UNVERIFIED — a W4 signed exception with
affected_gates naming the specific stage(s) is required to advance.Your job as the top-level orchestrator is minimal but critical:
Between wave executions, L0 can check progress without reading files:
// Quick progress check
MATCH (t:Task)
RETURN t.status AS status, count(t) AS count
ORDER BY
CASE t.status
WHEN 'done' THEN 1
WHEN 'in_progress' THEN 2
WHEN 'pending' THEN 3
WHEN 'failed' THEN 4
ELSE 5
END
// Active wave (lowest wave with incomplete tasks)
MATCH (t:Task)-[:IN_WAVE]->(w:Wave)
WHERE t.status <> 'done'
RETURN w.number AS active_wave, count(t) AS remaining_tasks
ORDER BY w.number
LIMIT 1
These are lightweight queries that keep L0's context clean.
If a graph write fails mid-execution, halt phase advancement (the previous "continue with status.json only" path is removed — divergence between the graph and the local status file produces the same dishonest-reporting class addressed elsewhere in this release):
taskId, phase, and the Cypher statement..tl/status.json for forensic inspection only — do NOT advance the wave.FULL HALTED — UNVERIFIED (graph write failed for Task <taskId> phase <phase>); resolve Neo4j connectivity and re-run /nacl:tl-full --task <taskId>.done in .tl/status.json — without graph confirmation the run is unverified.If the probe query in Step 0.1 fails:
"Neo4j unavailable. Check config.yaml → graph.neo4j_bolt_port (default: 3587). Use /nacl:tl-full for non-graph execution."${CLAUDE_PLUGIN_ROOT}/nacl-core/SKILL.md.If a wave agent (L1) returns no result or an error:
SET t.status = 'failed' for eachIf graph state and status.json diverge:
status.json with graph data"Resolved graph-JSON inconsistency for Task $taskId"| Topic | Path |
|---|---|
| Graph connection and schema | ${CLAUDE_PLUGIN_ROOT}/nacl-core/SKILL.md |
| TL schema (Task/Wave properties) | graph-infra/schema/tl-schema.cypher |
| Named TL queries | graph-infra/queries/tl-queries.cypher |
| Agent protocol | ${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/tl-protocol.md |
| Task file format | ${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/task-file-format.md |
| SA integration | ${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/sa-integration.md |
| Stub tracking | ${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/stub-tracking-rules.md |
| QA rules | ${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/qa-rules.md |
| Sync rules | ${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/sync-rules.md |
| Dev environment | ${CLAUDE_PLUGIN_ROOT}/nacl-tl-core/references/dev-environment.md |
# TL layer nodes:
- Task (id, title, type, status, wave, priority, phase_be, phase_fe, phase_sync,
phase_review_be, phase_review_fe, phase_qa, created, updated)
- Wave (id, number, name, status)
# TL layer edges:
- (Task)-[:IN_WAVE]->(Wave)
- (Task)-[:DEPENDS_ON]->(Task)
# Key named queries (graph-infra/queries/tl-queries.cypher):
- tl_progress_by_wave
- tl_active_wave
- tl_progress_stats
- tl_blocked_tasks
- tl_wave_tasks
# Task node property updates:
- Task.status (pending -> in_progress -> done/failed)
- Task.phase_be, Task.phase_fe, Task.phase_sync
- Task.phase_review_be, Task.phase_review_fe, Task.phase_qa
- Task.updated (datetime)
| File | Read/Write | Purpose |
|---|---|---|
.tl/master-plan.md | Read | Project name, supplementary info |
.tl/status.json | Read+Write | Dual-write target (secondary to graph) |
.tl/changelog.md | Read | History (for final report) |
.tl/stub-registry.json | Read | Stub counts (for final report) |
config.yaml | Read | YouGile columns, build/test commands |
npx claudepluginhub itsalt/nacl --plugin naclGraph-based development planning from SA specifications in Neo4j. One Cypher query per UC instead of reading ~70 markdown files. Creates paired BE+FE tasks, TECH tasks, api-contracts, and execution waves. Task file format is IDENTICAL to nacl-tl-plan (dev agents don't change). Use when: create dev plan from graph, plan implementation, generate tasks, create development schedule, generate execution waves, or the user says "/nacl:tl-plan".
Defines a 4-phase execution loop (IMPLEMENT, VALIDATE, ADVERSARIAL REVIEW, COMMIT) for orchestrating complex multi-step work units with written specs and quality gates.
Provides orchestratorX workflow handbook with planning dialogue, Mode A/B/C workflows, iteration loop, Hybrid Tree routing, requirement change handling, and Auto-Routing. Useful for managing multi-agent orchestration sessions.