nubos-pilot 1.2.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +43 -1
  2. package/agents/np-architect.md +2 -0
  3. package/agents/np-executor.md +1 -1
  4. package/agents/np-learnings-extractor.md +54 -0
  5. package/agents/np-planner.md +1 -1
  6. package/agents/np-security-reviewer.md +9 -0
  7. package/bin/np-tools/_commands.cjs +5 -0
  8. package/bin/np-tools/derive-tier.cjs +86 -0
  9. package/bin/np-tools/derive-tier.test.cjs +83 -0
  10. package/bin/np-tools/doctor.cjs +15 -2
  11. package/bin/np-tools/graph-impact.cjs +111 -0
  12. package/bin/np-tools/graph-impact.test.cjs +119 -0
  13. package/bin/np-tools/learnings.cjs +105 -0
  14. package/bin/np-tools/learnings.test.cjs +66 -0
  15. package/bin/np-tools/loop-run-round.cjs +7 -1
  16. package/bin/np-tools/scan-codebase.cjs +21 -1
  17. package/bin/np-tools/skill-audit.cjs +79 -0
  18. package/bin/np-tools/skill-audit.test.cjs +86 -0
  19. package/bin/np-tools/verify-reliability.cjs +65 -0
  20. package/bin/np-tools/verify-reliability.test.cjs +69 -0
  21. package/lib/agents.test.cjs +1 -0
  22. package/lib/checkpoint.cjs +3 -0
  23. package/lib/codebase-graph.cjs +0 -0
  24. package/lib/codebase-graph.test.cjs +174 -0
  25. package/lib/codebase-manifest.cjs +3 -0
  26. package/lib/config-defaults.cjs +13 -0
  27. package/lib/config-schema.cjs +11 -0
  28. package/lib/eval-reliability.cjs +63 -0
  29. package/lib/eval-reliability.test.cjs +56 -0
  30. package/lib/install/claude-hooks-learnings.test.cjs +82 -0
  31. package/lib/install/claude-hooks.cjs +65 -4
  32. package/lib/install/claude-hooks.test.cjs +5 -2
  33. package/lib/learnings/capture-ledger.cjs +80 -0
  34. package/lib/learnings/capture-ledger.test.cjs +54 -0
  35. package/lib/learnings/extract.cjs +191 -0
  36. package/lib/learnings/extract.test.cjs +115 -0
  37. package/lib/learnings.cjs +19 -95
  38. package/lib/memory.cjs +38 -33
  39. package/lib/messaging.cjs +12 -6
  40. package/lib/metrics-aggregate.cjs +14 -2
  41. package/lib/migrate.cjs +29 -0
  42. package/lib/migrate.test.cjs +91 -0
  43. package/lib/nubosloop-audit.cjs +104 -0
  44. package/lib/nubosloop-skill-audit.test.cjs +98 -0
  45. package/lib/nubosloop.cjs +9 -0
  46. package/lib/schemas/data/checkpoint.v1.json +13 -0
  47. package/lib/schemas/data/codebase-manifest.v1.json +22 -0
  48. package/lib/schemas/data/learnings.v1.json +28 -0
  49. package/lib/schemas/data/memory-manifest.v1.json +14 -0
  50. package/lib/schemas/data/memory-record.v1.json +16 -0
  51. package/lib/schemas/data/message.v1.json +19 -0
  52. package/lib/schemas/data/metrics-record.v1.json +11 -0
  53. package/lib/tier-classify.cjs +67 -0
  54. package/lib/tier-classify.test.cjs +67 -0
  55. package/lib/validate.cjs +301 -0
  56. package/lib/validate.test.cjs +242 -0
  57. package/np-tools.cjs +5 -0
  58. package/package.json +3 -1
  59. package/skills/np-access-control/SKILL.md +42 -0
  60. package/skills/np-accessibility-audit/SKILL.md +41 -0
  61. package/skills/np-adr/SKILL.md +37 -0
  62. package/skills/np-api-design/SKILL.md +34 -0
  63. package/skills/np-caching-strategy/SKILL.md +38 -0
  64. package/skills/np-data-modeling/SKILL.md +37 -0
  65. package/skills/np-data-privacy/SKILL.md +39 -0
  66. package/skills/np-dependency-audit/SKILL.md +47 -0
  67. package/skills/np-encryption/SKILL.md +47 -0
  68. package/skills/np-error-handling/SKILL.md +37 -0
  69. package/skills/np-incident-response/SKILL.md +38 -0
  70. package/skills/np-llm-app-architecture/SKILL.md +50 -0
  71. package/skills/np-observability/SKILL.md +39 -0
  72. package/skills/np-performance/SKILL.md +38 -0
  73. package/skills/np-queue-design/SKILL.md +32 -0
  74. package/skills/np-rag-design/SKILL.md +43 -0
  75. package/skills/np-refactoring/SKILL.md +35 -0
  76. package/skills/np-resilience-patterns/SKILL.md +39 -0
  77. package/skills/np-secure-code-review/SKILL.md +46 -0
  78. package/skills/np-secure-design/SKILL.md +44 -0
  79. package/skills/np-service-boundary/SKILL.md +35 -0
  80. package/skills/np-system-design/SKILL.md +40 -0
  81. package/skills/np-test-strategy/SKILL.md +46 -0
  82. package/skills/np-threat-model/SKILL.md +42 -0
  83. package/templates/claude/payload/hooks/np-learnings-hook.cjs +55 -0
  84. package/workflows/architect-phase.md +21 -1
  85. package/workflows/execute-phase.md +66 -4
  86. package/workflows/verify-work.md +17 -4
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: np-test-strategy
3
+ description: "Quality bar for changes that add or modify behavior and therefore need tests. Triggered for executor and verifier work on any feature, fix, or refactor that changes observable behavior. Encodes the testing checklist the change MUST satisfy before commit — not a test plan to author. Language- and framework-agnostic."
4
+ user-invocable: false
5
+ ---
6
+
7
+ # Test Strategy
8
+
9
+ A change that alters behavior ships with tests that lock that behavior in. Tests exist to catch the regression a future edit would introduce — not to inflate coverage. Aim for the cheapest test that would fail if the behavior broke.
10
+
11
+ ## Before editing
12
+ - Read the project's existing test conventions first: `node .nubos-pilot/bin/np-tools.cjs knowledge-search "test conventions <area>" --task $TASK_ID`. Match the established idiom (test framework, naming, directory layout, fixture/factory style, assertion helpers). Do not introduce a new test tool or pattern.
13
+
14
+ ## Test the behavior, not the implementation
15
+ - Assert on observable outcomes: return values, emitted events, persisted state, responses, side effects a caller can see. Never assert on private fields, call order of internals, or how the work is done.
16
+ - Name tests by the behavior under test and its condition, not by the method name.
17
+ - A test that has to change every time you refactor internals is testing the wrong thing — delete or rewrite it.
18
+
19
+ ## Pick the right level
20
+ - Unit-test pure logic and branching in isolation; this is where edge cases are cheapest to cover.
21
+ - Integration-test the seams: real DB, real serialization, real wiring between collaborators that unit tests stub away.
22
+ - Reserve e2e/end-to-end for a thin layer of critical user journeys — slow and flaky if overused.
23
+ - Push each assertion to the lowest level that can still observe the behavior.
24
+
25
+ ## Cover the full surface
26
+ - Happy path, boundary/edge inputs (empty, max, zero, null, unicode, duplicate), and failure/error paths all get a test.
27
+ - Error paths assert the right error surfaces and nothing is half-committed — see [np-error-handling].
28
+ - A bug fix gets a regression test that fails before the fix and passes after; verify it actually fails on the unpatched code first.
29
+ - A refactor adds characterization tests for any untested behavior it touches before the change — see [np-refactoring].
30
+
31
+ ## Mock only true externals
32
+ - Mock network, clock, randomness, filesystem, and third-party services — nothing else. Mocking your own collaborators couples tests to structure and hides integration bugs.
33
+ - Prefer real in-memory fakes (e.g. in-memory store) over mocks that merely re-assert the call you wrote.
34
+
35
+ ## Determinism and speed
36
+ - No real sleeps, wall-clock reads, network calls, or reliance on test execution order. Inject the clock, freeze time, seed randomness.
37
+ - Each test sets up and tears down its own state; tests pass in isolation and in any order.
38
+ - Fast by default — a slow suite stops being run.
39
+
40
+ ## Verification bar (must hold before commit)
41
+ - New or changed behavior has a test asserting its observable outcome; the test fails if the behavior is reverted.
42
+ - Happy path, at least one boundary case, and the failure/error path are each covered.
43
+ - Bug fixes include a regression test confirmed to fail before the fix.
44
+ - Tests are deterministic (no sleeps/real clock/network/order-dependence) and run at the lowest sufficient level.
45
+ - Mocks cover only true externals; no assertions on private internals.
46
+ - Suite is green and matches the project's existing test idiom; error-path coverage aligns with [np-error-handling].
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: np-threat-model
3
+ description: "Quality bar for any change that introduces or alters a trust boundary, opens a new attack surface, adds an external integration, or handles sensitive data/assets — new ingress, a webhook/callback, a queue consumer, a third-party API call, a privilege transition, a new datastore for credentials/PII. Triggered for executor and security-reviewer work on such changes. Encodes a lightweight STRIDE reasoning checklist the change MUST satisfy before commit — reasoning over the diff, not a formal report to produce. Language- and framework-agnostic."
4
+ user-invocable: false
5
+ ---
6
+
7
+ # Threat Model
8
+
9
+ A new trust boundary is a new promise an attacker will test. Threat modeling here is not a document — it is the act of reasoning over the diff before you commit it: what asset moved, who can now reach it, and what stops them from abusing it. Apply this bar whenever the change touches a boundary, surface, integration, or sensitive asset.
10
+
11
+ ## Before editing
12
+
13
+ - Read the project's existing boundaries and assumptions first: `node .nubos-pilot/bin/np-tools.cjs knowledge-search "threat model <surface>" --task $TASK_ID`. Reuse the established trust model; do not invent a parallel one.
14
+
15
+ ## Frame the change
16
+
17
+ - **Name the assets the change touches** — credentials, PII, money, tokens, audit integrity, availability of a path. If it touches none, the surface is the asset.
18
+ - **Draw the trust boundary** the diff crosses: where does untrusted input enter, where does privilege change, what is now reachable that wasn't. Everything arriving from across it is hostile until proven otherwise.
19
+ - **List the new actors** — anonymous caller, authenticated-but-not-authorized user, a compromised dependency, the integration partner itself.
20
+
21
+ ## Enumerate threats (STRIDE lens)
22
+
23
+ - **Spoofing** — can an actor claim an identity they don't hold? Is the caller, webhook, or integration authenticated and its origin verified?
24
+ - **Tampering** — can request, payload, stored asset, or in-transit data be altered? Integrity checks, signatures, parameterized sinks.
25
+ - **Repudiation** — is a security-relevant action attributable? Is there a tamper-evident audit trail for the new path?
26
+ - **Information disclosure** — can the asset leak via responses, errors, logs, timing, or an over-broad scope? Least exposure by default.
27
+ - **Denial of service** — can the new surface be exhausted (unbounded work, no rate limit, amplification via the integration)?
28
+ - **Elevation of privilege** — can the change be used to gain rights? Does any new path default-allow or cross a boundary without an authz check?
29
+
30
+ ## Rank and mitigate
31
+
32
+ - Rank each credible threat by **likelihood × impact**; spend the diff's effort on the high cells, not the theoretical tail.
33
+ - Every credible threat is either **mitigated inside this change** or recorded as an **explicit accepted-risk finding** — never silently left open.
34
+ - Mitigations live in the diff, not in a future ticket. Implement the secure default; pair concrete sink/auth hardening with [np-secure-code-review].
35
+
36
+ ## Verification bar (must hold before commit)
37
+
38
+ - The trust boundary and the assets the change touches are named, and untrusted input across it is treated as hostile.
39
+ - Each STRIDE category was applied to the new surface; every credible threat has a mitigation in the diff or an explicit accepted-risk finding.
40
+ - The new actor with the least privilege cannot reach an asset they shouldn't — spoofing and elevation paths are closed by default-deny.
41
+ - The new path is attributable (audit) and bounded (rate/quota); errors and logs disclose nothing exploitable.
42
+ - If a high-likelihood × high-impact threat cannot be mitigated within task scope, stop and surface it — do not commit around it.
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
6
+ const cp = require('node:child_process');
7
+
8
+ // ADR-0010 / ECC continuous-learning: thin Stop-hook shim. On session Stop it
9
+ // asks np-tools to (rate-limited) auto-capture reusable learnings from the
10
+ // turn's diff; on UserPromptSubmit it resets the consecutive-stop streak. All
11
+ // heavy logic lives in lib/learnings/. A learning hook must NEVER break the
12
+ // session — every failure path exits 0 silently.
13
+
14
+ const ALLOWED_VERBS = new Set(['capture', 'reset']);
15
+
16
+ function resolveNpTools() {
17
+ const candidates = [
18
+ path.join(process.cwd(), '.nubos-pilot', 'bin', 'np-tools.cjs'),
19
+ path.join(__dirname, '..', '..', '..', '.nubos-pilot', 'bin', 'np-tools.cjs'),
20
+ ];
21
+ for (const c of candidates) {
22
+ try { if (fs.statSync(c).isFile()) return c; } catch {}
23
+ }
24
+ return null;
25
+ }
26
+
27
+ function readStdin() {
28
+ return new Promise((resolve) => {
29
+ if (process.stdin.isTTY) return resolve('');
30
+ let buf = '';
31
+ process.stdin.setEncoding('utf-8');
32
+ const timer = setTimeout(() => { try { process.stdin.removeAllListeners(); } catch {} resolve(buf); }, 800);
33
+ process.stdin.on('data', (c) => { buf += c; });
34
+ process.stdin.on('end', () => { clearTimeout(timer); resolve(buf); });
35
+ process.stdin.on('error', () => { clearTimeout(timer); resolve(buf); });
36
+ });
37
+ }
38
+
39
+ (async () => {
40
+ const verb = process.argv[2];
41
+ if (!ALLOWED_VERBS.has(verb)) { process.exit(0); return; }
42
+ const npTools = resolveNpTools();
43
+ if (!npTools) { process.exit(0); return; }
44
+ const input = await readStdin();
45
+ try {
46
+ cp.spawnSync(process.execPath, [npTools, 'learnings', verb, '--stdin'], {
47
+ input,
48
+ encoding: 'utf-8',
49
+ timeout: 15000,
50
+ maxBuffer: 4 * 1024 * 1024,
51
+ cwd: process.cwd(),
52
+ });
53
+ } catch { /* never let a learning hook break the session */ }
54
+ process.exit(0);
55
+ })().catch(() => { process.exit(0); });
@@ -74,9 +74,24 @@ The architect then consumes the consensus-merged `RESEARCH.md` instead of a sing
74
74
 
75
75
  After the architect emits `M<NNN>-ARCHITECTURE.md`, the orchestrator spawns ONE `np-critic` instance with the architecture file + `M<NNN>-CONTEXT.md` as inputs. The critic verifies that every locked decision in CONTEXT has a corresponding architecture entry and that no `Deferred` items leaked into the architecture. Findings of category `unmet-criterion`, `locked-decision-violation`, or `information-missing` route per `lib/nubosloop.cjs::routeFindings`. A single Build-Fixer-style round on the architect closes the loop. Beyond one round the workflow exits with `stuck` and the user resolves manually — architecture decisions don't merit unbounded looping.
76
76
 
77
+ ## Skills (Nubos library)
78
+
79
+ Nubos ships a design-time skill library under `.claude/skills/np-*/` (present only on Claude Code). These are the **quality bar for the architecture decisions you are about to commit** — each skill's "Verification bar" is the standard each ADR-style decision is held to. Before spawning `np-architect`, classify the milestone (read `M<NNN>-CONTEXT.md` + `M<NNN>-RESEARCH.md`) and inject the matching skill triggers into the architect's spawn prompt. Skills **stack** — include every row the milestone matches (cap at the most relevant ~4 if more match; always keep the security row when it applies).
80
+
81
+ | Milestone signal | Skills to trigger |
82
+ |---|---|
83
+ | Designs a new system, module, or significant feature | `np-system-design` (with `np-adr` for an architecturally significant, hard-to-reverse choice) |
84
+ | Introduces or moves a module/service boundary, splits a service, or chooses sync vs async | `np-service-boundary` |
85
+ | Any structural decision that is costly to reverse — datastore, sync/async, new dependency, auth model, public contract | `np-adr` |
86
+ | New external surface, new trust boundary, new privilege model, or handling of sensitive assets | `np-secure-design` (with `np-threat-model`) |
87
+ | Authorization model — roles, permissions, policies, resource ownership | `np-access-control` |
88
+ | Design depends on an unreliable dependency, async/queue processing, or a cache | `np-resilience-patterns`, `np-queue-design`, `np-caching-strategy` (each as it applies) |
89
+ | Persisted data shape, or personal/sensitive data | `np-data-modeling`, `np-data-privacy` (as they apply) |
90
+ | Purely additive milestone with no structural/security decision | None — skip the skill block (and reconsider whether the architect pass is needed at all) |
91
+
77
92
  ## Spawn np-architect
78
93
 
79
- Spawn `agents/np-architect.md` mit dem folgenden Files-to-Read-Block:
94
+ Spawn `agents/np-architect.md` mit dem folgenden Files-to-Read-Block und (sofern Skills matchen) der angehängten Skill-Direktive:
80
95
 
81
96
  ```
82
97
  <files_to_read>
@@ -88,8 +103,13 @@ Spawn `agents/np-architect.md` mit dem folgenden Files-to-Read-Block:
88
103
 
89
104
  Milestone: M<NNN>
90
105
  Task: Emit M<NNN>-ARCHITECTURE.md per the agent's Output Contract.
106
+
107
+ Use the following Nubos skills as the quality bar for your decisions: <skill-1>, <skill-2>, ...
108
+ Each is installed at .claude/skills/<skill>/SKILL.md; every architecture decision must satisfy the matching skill's "Verification bar".
91
109
  ```
92
110
 
111
+ If zero skills match, omit the skill-directive line — do not invent skills.
112
+
93
113
  Der Agent ist read-only auf Source — er schreibt EINE Datei:
94
114
  `.nubos-pilot/milestones/M<NNN>/M<NNN>-ARCHITECTURE.md`.
95
115
 
@@ -33,6 +33,8 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
33
33
  AGENT_SKILLS_EXECUTOR=$(node .nubos-pilot/bin/np-tools.cjs agent-skills executor 2>/dev/null)
34
34
  RUNTIME=$(node .nubos-pilot/bin/np-tools.cjs detect-runtime)
35
35
  WORKTREE_ISOLATION=$(node .nubos-pilot/bin/np-tools.cjs config-get workflow.worktree_isolation 2>/dev/null || echo "false")
36
+ TIER_ROUTING=$(node .nubos-pilot/bin/np-tools.cjs config-get workflow.tier_routing 2>/dev/null || echo "false")
37
+ VERIFY_RUNS=$(node .nubos-pilot/bin/np-tools.cjs config-get loop.verify_runs 2>/dev/null || echo "1")
36
38
  ```
37
39
 
38
40
  When `--verify-work` is passed, the init payload's `auto_verify: true` flag tells this workflow to chain into `/np:verify-work $PHASE` after every slice committed and `finalize-milestone` ran. Without the flag the workflow stops after finalize as before — verify-work then remains a separate manual step.
@@ -57,18 +59,44 @@ Parse JSON for: `milestone`, `milestone_id`, `milestone_dir`, `waves[]` (each wi
57
59
 
58
60
  Nubos ships a skill library under `.claude/skills/np-*/` (auto-installed by `npx nubos-pilot`, present only on Claude Code). For each task in a wave, before spawning `np-executor`, classify the task by reading its `T<NNNN>-PLAN.md` and inject the matching skill triggers into the executor's spawn prompt as a "Use these skills" directive. The executor then loads each skill's `SKILL.md` via the runtime's skill mechanism and follows its rules during implementation.
59
61
 
60
- Mapping (match the dominant signal in `files_modified` + task description):
62
+ Match the task against **both** tables below — a task can match rows in each (e.g. a new authenticated endpoint backed by a migration is UI-free but matches `np-api-design` + `np-secure-code-review` + `np-data-modeling`). Skills **stack**: trigger every row whose signal the task matches. The only exception is the UI style anchor (pick exactly one). If more than ~4 rows match, keep the most task-critical and always retain any security row (`np-secure-code-review` / `np-threat-model`) and `np-test-strategy` for behaviour changes.
63
+
64
+ **UI / frontend** (match the dominant signal in `files_modified` + task description):
61
65
 
62
66
  | Task signal | Skills to trigger |
63
67
  |---|---|
64
- | Any UI/component edit (`.tsx`, `.jsx`, `.vue`, `.svelte`, `views/**`, `components/**`, `pages/**`, `app/**`) | `np-impeccable` (polish/audit), `np-frontend-design` (build), `np-design` (review), `np-web-design-guidelines` (a11y/UX) |
68
+ | Any UI/component edit (`.tsx`, `.jsx`, `.vue`, `.svelte`, `views/**`, `components/**`, `pages/**`, `app/**`) | `np-impeccable` (polish/audit), `np-frontend-design` (build), `np-design` (review), `np-web-design-guidelines` (a11y/UX), `np-accessibility-audit` (WCAG AA bar) |
65
69
  | `components.json` present in repo OR shadcn/ui imports in modified files | `np-shadcn` (in addition to UI skills above) |
66
70
  | React/Next.js component or hook edit | `np-react-best-practices`, `np-composition-patterns` |
67
71
  | Page/route transitions, `<ViewTransition>`, `startViewTransition` | `np-react-view-transitions` |
68
72
  | React Native / Expo source (`*.tsx` under `app/`, `screens/`, `mobile/**`) | `np-react-native-skills` |
69
73
  | Restyling an existing surface (no greenfield) | `np-redesign-existing-projects` |
70
74
  | New surface needing visual direction | Pick exactly **one** style anchor: `np-high-end-visual-design` (default agency premium), `np-minimalist-ui`, `np-industrial-brutalist-ui`, or `np-stitch-design-taste` |
71
- | Non-UI task (backend, infra, tooling, docs) | None — skip the skill block entirely |
75
+
76
+ **Engineering / non-UI** (these stack — include each row the task matches):
77
+
78
+ | Task signal | Skills to trigger |
79
+ |---|---|
80
+ | Adds/changes a consumed contract — HTTP route, RPC/GraphQL handler, controller, resolver, public SDK/library function, CLI flag | `np-api-design` |
81
+ | Touches auth, authz, session, secrets, crypto, SQL/query construction, file upload, deserialization, or any untrusted input reaching a sink | `np-secure-code-review` |
82
+ | Introduces or alters a trust boundary — new ingress, webhook/callback, queue consumer, third-party integration, or a new store for credentials/PII | `np-threat-model` (with `np-secure-code-review`) |
83
+ | DB schema, migration, ORM model/entity, or any backfill/transform of persisted data | `np-data-modeling` |
84
+ | Backend/service/integration/IO path that can fail — external calls, retries, timeouts, batch work | `np-error-handling` |
85
+ | Calls an external/unreliable dependency (other service, third-party API, DB under load) | `np-resilience-patterns` (with `np-error-handling`) |
86
+ | New service/handler/job/integration path, or a new failure path that must be diagnosable | `np-observability` |
87
+ | Data access, queries, loops over collections, hot paths — anything that scales with input size | `np-performance` |
88
+ | Adds or changes a cache / memoization layer (in-memory, distributed, HTTP/CDN) | `np-caching-strategy` |
89
+ | Message queue, background job, worker, async consumer, or event handler | `np-queue-design` |
90
+ | Introduces or changes a module/service boundary, splits a service, or makes a cross-module change | `np-service-boundary` |
91
+ | Roles, permissions, policies, resource ownership, or access-rule changes (RBAC/ABAC, authz checks) | `np-access-control` (with `np-secure-code-review`) |
92
+ | Encryption, hashing, password storage, TLS, tokens, signing/HMAC, or key/secret management | `np-encryption` |
93
+ | Adds or upgrades a third-party dependency, or edits a manifest/lockfile | `np-dependency-audit` |
94
+ | Collects, stores, processes, exports, or logs personal/sensitive data (PII) | `np-data-privacy` |
95
+ | Refactor / cleanup / restructure where behaviour must be preserved | `np-refactoring` |
96
+ | Risky / hard-to-reverse / high-blast-radius change — feature flags, migration coupled to code, change to an external integration | `np-incident-response` |
97
+ | LLM / agent / prompt / tool-use / structured-output / AI feature | `np-llm-app-architecture` (add `np-rag-design` if it retrieves from a corpus) |
98
+ | Any change to logic or behaviour (almost all non-trivial tasks) | `np-test-strategy` |
99
+ | Pure docs/config with no behaviour change | None — skip the skill block |
72
100
 
73
101
  **Spawn-prompt injection format.** Append to the executor prompt verbatim (one line per matched skill):
74
102
 
@@ -78,6 +106,14 @@ Each skill is installed at .claude/skills/<skill>/SKILL.md and encodes a
78
106
  quality bar you must satisfy before invoking commit-task.
79
107
  ```
80
108
 
109
+ **Consultation audit (counterpart to Rule 9).** Whenever you inject a non-empty skill block, BEFORE spawning the executor record the expected set so the post-critics gate can verify the executor actually consulted them:
110
+
111
+ ```bash
112
+ node .nubos-pilot/bin/np-tools.cjs skill-audit expect --task "$TASK_ID" --skills "<skill-1>,<skill-2>,..."
113
+ ```
114
+
115
+ The executor stamps each skill it reads via `skill-audit ack`. At post-critics, any injected-but-unconsulted skill becomes a `skill-bar-unconsulted` finding that routes the task back to the executor (once per round, bounded by `loop.maxRounds`) — exactly like a Rule-9 search miss. Skip the `expect` call only when zero skills were injected.
116
+
81
117
  If zero skills match, omit the block — do **not** invent skills. Adding new skills under `skills/np-*/` in the source repo is sufficient: the next `npx nubos-pilot update` rolls them out and you extend this mapping in one PR.
82
118
 
83
119
  ## Pre-Flight — orphan-checkpoint guard
@@ -262,6 +298,7 @@ for WAVE_INDEX in 0 1 2 ...; do
262
298
  TASK_JSON=$(node .nubos-pilot/bin/np-tools.cjs init execute-milestone execute-task "$PHASE" "$TASK_ID")
263
299
  if [[ "$TASK_JSON" == @file:* ]]; then TASK_JSON=$(cat "${TASK_JSON#@file:}"); fi
264
300
  TASK_QUERY=$(echo "$TASK_JSON" | node -e "process.stdin.on('data', d => { const j=JSON.parse(d); console.log(j.query || j.name || ''); })")
301
+ TASK_TIER=$(echo "$TASK_JSON" | node -e "process.stdin.on('data', d => { const j=JSON.parse(d); console.log(j.tier || 'sonnet'); })")
265
302
 
266
303
  EXECUTOR_START=$(node .nubos-pilot/bin/np-tools.cjs metrics start-timestamp)
267
304
  CONSENSUS_PATTERN=""
@@ -371,7 +408,18 @@ for WAVE_INDEX in 0 1 2 ...; do
371
408
  else
372
409
  EXECUTOR_AGENT="np-build-fixer"
373
410
  fi
374
- EXECUTOR_MODEL=$(node .nubos-pilot/bin/np-tools.cjs resolve-model "$EXECUTOR_AGENT" --profile frontier)
411
+ # Model resolution. Default (tier_routing off): the executor always runs at
412
+ # the `frontier` profile — every task gets the strongest model. Opt-in
413
+ # tier-routing (config `workflow.tier_routing: true`) instead honours the
414
+ # planner's per-task `tier` under the project's configured `model_profile`
415
+ # (default `balanced`), so trivial→haiku / standard→sonnet / large→opus —
416
+ # ECC-style cost-aware routing. Round-2+ build-fixer always stays frontier:
417
+ # fixing a failing task wants the strongest model regardless of routing.
418
+ if [[ "$TIER_ROUTING" == "true" && "$ROUND" -eq 1 ]]; then
419
+ EXECUTOR_MODEL=$(node .nubos-pilot/bin/np-tools.cjs resolve-model "$TASK_TIER")
420
+ else
421
+ EXECUTOR_MODEL=$(node .nubos-pilot/bin/np-tools.cjs resolve-model "$EXECUTOR_AGENT" --profile frontier)
422
+ fi
375
423
  # → execute group (1) per ACTION CONTRACT above, then:
376
424
 
377
425
  node .nubos-pilot/bin/np-tools.cjs checkpoint transition "$TASK_ID" verifying
@@ -380,6 +428,20 @@ for WAVE_INDEX in 0 1 2 ...; do
380
428
  VERIFY_LOG="${TMPDIR:-/tmp}/np-verify-${TASK_ID}-r${ROUND}.log"
381
429
  # Orchestrator (NOT the agent) runs the task's <verify> command + stack
382
430
  # linters; redirect stdout+stderr to $VERIFY_LOG.
431
+ #
432
+ # pass@k reliability (opt-in, $VERIFY_RUNS, default 1): run the SAME verify
433
+ # command $VERIFY_RUNS times, collecting one exit code per run into a
434
+ # comma-separated list ($VERIFY_CODES, e.g. "0,1,0"). With the default of 1
435
+ # this is a single run, identical to before. Then fold the runs:
436
+ # VERIFY_EXIT=$? # when $VERIFY_RUNS == 1
437
+ # # when $VERIFY_RUNS > 1:
438
+ # REL=$(node .nubos-pilot/bin/np-tools.cjs verify-reliability --codes "$VERIFY_CODES")
439
+ # VERIFY_EXIT=$(echo "$REL" | node -e 'process.stdin.on("data",d=>console.log(JSON.parse(d).aggregate_exit_code))')
440
+ # # append the human verdict so a FLAKY task tells the build-fixer why it is red:
441
+ # echo "$REL" | node -e 'process.stdin.on("data",d=>console.log(JSON.parse(d).description))' >> "$VERIFY_LOG"
442
+ # aggregate_exit_code is 0 only when EVERY run passed (pass^k); a flaky task
443
+ # (some pass, some fail) aggregates to red and flows through the normal
444
+ # spawn-build-fixer path below — no new critic category, no spurious stuck.
383
445
  VERIFY_EXIT=$?
384
446
  # Stamp executor spawn-evidence into the audit log. EXECUTOR_TOOL_LOG is
385
447
  # the tool-name JSON array harvested from the spawn's tool_use stream
@@ -38,15 +38,28 @@ Parse: `milestone`, `milestone_id`, `milestone_dir`, `milestone_name`, `success_
38
38
 
39
39
  ## Skills (Nubos library)
40
40
 
41
- For UI/UX-flavoured success criteria, instruct the verifier (in its spawn prompt) to load the matching Nubos skill before classifying:
41
+ Instruct the verifier (in its spawn prompt) to load the matching Nubos skill before classifying — the skill's "Verification bar" is the standard the SC is judged against, not just the SC's own wording:
42
42
 
43
43
  | SC type | Skill to use |
44
44
  |---|---|
45
45
  | Visual polish, layout, hierarchy, motion | `np-impeccable` (`.claude/skills/np-impeccable/SKILL.md`) |
46
- | Accessibility, semantic HTML, UX heuristics | `np-web-design-guidelines` |
46
+ | Accessibility, semantic HTML, keyboard/contrast | `np-web-design-guidelines`, `np-accessibility-audit` |
47
47
  | Component architecture, design-system fit | `np-design` |
48
-
49
- For borderline Pass/Fail calls in Pass 2 (deterministic evidence inconclusive **and** the SC carries real consequences), pressure-test with **`np-council`** before flipping `needs_user_confirm` `Pass`/`Fail`. Backend/infra/data SCs do not need any skill — verdict on evidence alone.
48
+ | API / endpoint / contract behaviour | `np-api-design` |
49
+ | Security, auth, input handling, secrets, crypto | `np-secure-code-review` (and `np-threat-model` if a new trust boundary) |
50
+ | Authorization — roles, permissions, ownership, access rules | `np-access-control` |
51
+ | Encryption, hashing, TLS, key/secret management | `np-encryption` |
52
+ | Personal/sensitive data handling, retention, logging | `np-data-privacy` |
53
+ | Schema / migration / data correctness | `np-data-modeling` |
54
+ | Error handling, retries, failure modes | `np-error-handling` |
55
+ | Resilience under dependency failure — timeout, circuit-breaker, fallback | `np-resilience-patterns` |
56
+ | Caching correctness / invalidation | `np-caching-strategy` |
57
+ | Async job / queue / worker behaviour — idempotency, ordering, DLQ | `np-queue-design` |
58
+ | Module/service boundary, coupling, contract integrity | `np-service-boundary` |
59
+ | Performance, latency, query/loop cost | `np-performance` |
60
+ | LLM / agent / retrieval behaviour | `np-llm-app-architecture`, `np-rag-design` |
61
+
62
+ For borderline Pass/Fail calls in Pass 2 (deterministic evidence inconclusive **and** the SC carries real consequences), pressure-test with **`np-council`** before flipping `needs_user_confirm` → `Pass`/`Fail`. An SC with no matching skill is judged on evidence alone.
50
63
 
51
64
  ## Output-Schema (pre-spawn injection)
52
65