Appearance
Review Workflows
Post-execution audits.
np:close-project
Project-level aggregate verification. Reads every M<NNN>-VERIFICATION.md and M<NNN>-VALIDATION.md, collects blockers (missing reports, failed SCs, UNCOVERED requirements, milestone status ≠ verified), and writes .nubos-pilot/PROJECT-SUMMARY.md with one block per milestone. When no blockers remain, it sets roadmap.yaml.project_status = "completed" and completed_at = <ISO timestamp>. This is the single whole-project verification pass. It does not re-run verify-work or validate-phase; it aggregates their persisted output. Per-milestone verification still happens at execution time.
Verbs on the underlying close-project tool: init (workflow payload), check (read-only completion JSON), write-summary (emits PROJECT-SUMMARY.md), mark-completed / unmark (flips project_status).
Workflow askuser branch when blockers exist: Abort (default, fix first) | Close with blockers (writes summary, leaves project_status: active) | Force complete (flips to completed; later archive manifests record forced: true).
A completed project is then eligible for archive on the next /np:new-project invocation (Phase -1 detects project_status: completed and routes to "Archive and start fresh" with no extra confirmation prompt).
np:validate-phase <N>
Nyquist validation gap-fill. Spawns np-nyquist-auditor (tier=haiku), which checks each requirement in the milestone scope against test coverage and scores it COVERED / UNDER_SAMPLED / UNCOVERED. Output: M<NNN>-VALIDATION.md using templates/VALIDATION.md as the skeleton.
The Nyquist rule: every requirement must be observed by at least one test that exercises the implementation directly, not a mock and not a bare import. Under-sampled requirements fail silently when regressed.
bash
/np:validate-phase 1How the auditor scores
| Score | Criterion |
|---|---|
| COVERED | ≥1 test contains an assertion that directly observes the requirement's behavior. |
| UNDER_SAMPLED | Tests exist but are transitive (exercise the code path incidentally), or assertion-light (pass/fail only), or .skip / todo. |
| UNCOVERED | No test file references the requirement ID and no test asserts the observable behavior. |
For UNDER_SAMPLED / UNCOVERED entries, the auditor records suggested test names and assertion shapes under a ## Remediation Guidance section.
Output shape
markdown
---
phase: 1
slug: auth-basic-ui
audited_at: 2026-04-20T10:30:00Z
requirements_total: 12
covered: 9
under_sampled: 2
uncovered: 1
nyquist_compliant: false
status: issues_found
---
## Summary
12 requirements in scope. 9 COVERED, 2 UNDER_SAMPLED, 1 UNCOVERED —
Nyquist-compliant = false. 3 regressions could pass silently in the
current test suite.
## Covered
…
## Under-Sampled
…
## Uncovered
…
## Remediation Guidance
…Relation to np:verify-work
/np:verify-work checks that success_criteria are met by the implementation. /np:validate-phase checks that success_criteria are observed by tests. Both run post-execution, and neither edits source or proposes fixes; they write reports for humans.
A milestone that passes /np:verify-work but fails /np:validate-phase shipped working code with inadequate regression coverage. Green verify with red validate means write more tests before merging.
Optional security audit (np-security-reviewer)
When the milestone touches surfaces with security implications (auth, crypto, request handlers, file/path I/O, external HTTP calls, dependency upgrades), spawn np-security-reviewer (tier=sonnet) as an additional read-only audit pass. It walks the union of files_modified from every task in the milestone, scans 10 OWASP-aligned categories (Injection, Auth & Session, Secrets, Access Control, Crypto, SSRF / Open Redirect, Deserialization, File / Path, Logging, Dependencies), and emits M<NNN>-SECURITY.md with one block per finding classified as Pass / Risk / Defer.
Cross-references RULES.md and M<NNN>-CONTEXT.md first: explicit authorization there neutralizes a generic finding (e.g. "use jose@6 for JWT" in CONTEXT means a "no hand-rolled JWT" check against jose@6 is Pass, not Risk). It is detection-only by tool grant, with no Write or Edit, and never proposes patches inline; remediation is the planner's job in the next milestone if needed.
markdown
# M<NNN> — <name> — Security Review
**Milestone Status:** clean | risks-found | deferred
## Summary
| Category | Pass | Risk | Defer |
|---------|------|------|-------|
| … | … | … | … |
## Findings
### F-1: <short title>
- **Category:** Auth & Session
- **Status:** Risk
- **Severity:** High | Medium | Low
- **Path:** `src/auth/login.ts:42`
- **Pattern:** `bcrypt(password, 4)`
- **Mitigation hint (NOT a patch):** Increase cost to ≥ 12 per OWASP cheatsheet.
- **Authorized by:** RULES.md / M<NNN>-CONTEXT.md / noneMilestone Status resolution: any Risk → risks-found; else any Defer → deferred; else clean. There is no dedicated /np:security-phase slash-command yet. Operators or workflows that want this audit spawn the agent directly with the milestone payload.
