role-os 1.0.1 → 1.1.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,70 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Added
6
+
7
+ #### Routing
8
+ - Full 31-role catalog — all roles scored by keyword, trigger phrase, packet type bias, and deliverable affinity
9
+ - Dynamic chain builder — phase-ordered assembly replacing static templates
10
+ - Routing confidence assessment (high/medium/low)
11
+ - `excludeWhen` enforcement — roles suppressed when exclusion patterns match packet content
12
+ - `detectType` false-positive prevention — "integration testing" no longer triggers integration type
13
+ - `--verbose` flag for `roleos route` — hides scoring noise by default
14
+
15
+ #### Conflict Detection
16
+ - 4-pass conflict engine: hard conflicts, sequence, redundancy, coverage gaps
17
+ - Per-role constraint registry: lateOnly, requiresBeforePacks
18
+ - Overlap pair detection
19
+ - Repair suggestions on every finding
20
+
21
+ #### Escalation Auto-Routing
22
+ - Blocked/rejected/conflict/split work auto-routes to named resolver
23
+ - Every escalation includes: target role, recovery type, required artifact, handoff context
24
+
25
+ #### Structured Evidence
26
+ - 12 evidence kinds, 4 statuses, closed 4-verdict enum (accept/accept-with-notes/reject/blocked)
27
+ - Role-aware evidence requirements for 15 roles
28
+ - Sufficiency checks with contradiction detection
29
+
30
+ #### Runtime Dispatch
31
+ - Execution manifests for multi-claude with per-role tool profiles and budgets
32
+ - 8 execution states with auto-advance
33
+ - Escalation packet generation for blocked/rejected steps
34
+
35
+ #### Proven Team Packs
36
+ - 7 battle-tested packs: feature, bugfix, security, docs, launch, research, treatment
37
+ - `roleos packs list` — show all packs with role counts
38
+ - `roleos packs suggest <packet>` — suggest best pack for a packet
39
+ - `roleos packs show <name>` — show pack details (roles, artifacts, stop conditions)
40
+ - Pack suggestion engine with confidence levels
41
+
42
+ #### Trials
43
+ - Full roster proven: 30/30 gold-task trials + 5/5 negative (wrong-task honesty) trials
44
+ - 7 pack execution trials — all packs ran full chains with honest Critic verdicts
45
+ - Trial framework: buildClusterTrials, evaluateTrialOutput, formatTrialReport
46
+
47
+ ### Changed
48
+ - 32 → 31 roles: Information Architect merged into Docs Architect
49
+ - Verdict vocabulary unified: evidence.mjs now uses accept/reject/blocked (matching review.mjs)
50
+ - "worker" terminology replaced with "role" in dispatch.mjs
51
+
52
+ ### Fixed
53
+ - `excludeWhen` was declared on 14 roles but never enforced — now active in scoreRole
54
+ - `detectType` false-positived on "integration testing" — now uses word-boundary regex
55
+ - "Not triggered: N roles" noise hidden by default (shown with --verbose)
56
+ - Handbook: Team Packs page added, reference sidebar reordered
57
+
58
+ ## 1.0.2
59
+
60
+ ### Fixed
61
+ - Fix double-nested `.claude/.claude/` directory created by `roleos init` — `starter-pack/.claude/workflows/full-treatment.md` moved to `starter-pack/workflows/`
62
+ - Read VERSION from `package.json` at runtime instead of hardcoded constant — prevents version drift between CLI and package metadata
63
+
64
+ ### Added
65
+ - `roleos init --force` — update canonical scaffolded files while always protecting user-filled `context/` files
66
+ - 4 regression tests: no double-nesting, correct workflow placement, version sync, --force context protection
67
+
3
68
  ## 1.0.0
4
69
 
5
70
  ### Added
package/README.md CHANGED
@@ -15,11 +15,11 @@
15
15
  <a href="https://mcp-tool-shop-org.github.io/role-os/"><img src="https://img.shields.io/badge/Landing_Page-live-brightgreen" alt="Landing Page"></a>
16
16
  </p>
17
17
 
18
- A portable, repo-native operating layer that routes work through role contracts, structured packets, review, and escalation so teams can do feature work, integration work, identity repair, and full repo treatment without drift, false completion, or vibes-based progress claims.
18
+ A multi-Claude operating system that staffs, routes, validates, and runs work through 31 specialized role contracts. Creates task packets, assembles the right team from scored role matching, detects broken chains before execution, auto-routes recovery when work is blocked or rejected, and requires structured evidence in every verdict.
19
19
 
20
20
  ## What it does
21
21
 
22
- Role OS prevents the specific failures that generic AI workflows produce:
22
+ Role OS is the professional way to use multi-Claude. It prevents the specific failures that generic AI workflows produce:
23
23
 
24
24
  - **Drift** — roles stay in lane. Product doesn't redesign. Frontend doesn't redefine scope. Backend doesn't invent product direction.
25
25
  - **False completion** — the done definition is concrete. Work that hides gaps, skips verification, or solves a different problem gets rejected.
@@ -29,9 +29,15 @@ Role OS prevents the specific failures that generic AI workflows produce:
29
29
  ## How it works
30
30
 
31
31
  1. **Create a packet** — define what needs to exist when the work is done
32
- 2. **Route through a chain** — the smallest set of specialized roles needed
33
- 3. **Each role produces a handoff** — structured output that reduces ambiguity for the next role
34
- 4. **Critic reviews against contract** — accepts, rejects, or blocks based on evidence, not impression
32
+ 2. **Route through a chain** — `roleos route` scores all 31 roles against the packet content, assembles a dynamic chain ordered by work phase, and explains why each role was chosen
33
+ 3. **Validate the team** — 4-pass conflict detection catches hard conflicts, sequence errors, redundancy, and coverage gaps before execution starts
34
+ 4. **Each role produces a handoff** — structured output with evidence items that reduce ambiguity for the next role
35
+ 5. **Critic reviews against contract** — accepts, rejects, or blocks based on structured evidence, not impression
36
+ 6. **Recovery routes automatically** — blocked or rejected work gets routed to the right resolver with a reason, recovery type, and required artifact
37
+
38
+ ## Org rollout state
39
+
40
+ Org-wide rollout state (queue, decisions, audit records, per-repo lock packets) lives in a separate private repo: [`role-os-rollout`](https://github.com/mcp-tool-shop-org/role-os-rollout). This repo is the product; that repo is operational state.
35
41
 
36
42
  ## Memory and continuity
37
43
 
@@ -47,7 +53,7 @@ Full treatment is a canonical 7-phase protocol defined in Claude project memory
47
53
 
48
54
  Order: Shipcheck first, then full treatment. No v1.0.0 without passing hard gates.
49
55
 
50
- ## 32 roles across 8 packs
56
+ ## 31 roles across 8 packs
51
57
 
52
58
  | Pack | Roles |
53
59
  |------|-------|
@@ -56,11 +62,11 @@ Order: Shipcheck first, then full treatment. No v1.0.0 without passing hard gate
56
62
  | **Design** (2) | UI Designer, Brand Guardian |
57
63
  | **Marketing** (1) | Launch Copywriter |
58
64
  | **Treatment** (7) | Repo Researcher, Repo Translator, Docs Architect, Metadata Curator, Coverage Auditor, Deployment Verifier, Release Engineer |
59
- | **Product** (4) | Feedback Synthesizer, Roadmap Prioritizer, Spec Writer, Information Architect |
65
+ | **Product** (3) | Feedback Synthesizer, Roadmap Prioritizer, Spec Writer |
60
66
  | **Research** (4) | UX Researcher, Competitive Analyst, Trend Researcher, User Interview Synthesizer |
61
67
  | **Growth** (4) | Launch Strategist, Content Strategist, Community Manager, Support Triage Lead |
62
68
 
63
- Every role has a full contract: mission, use when, do not use when, expected inputs, required outputs, quality bar, and escalation triggers.
69
+ Every role has a full contract: mission, use when, do not use when, expected inputs, required outputs, quality bar, and escalation triggers. Every role is routable — `roleos route` can recommend any of them based on packet content.
64
70
 
65
71
  ## Quick start
66
72
 
@@ -124,32 +130,57 @@ These are non-negotiable. If a change weakens any of them, reject it.
124
130
 
125
131
  ```
126
132
  role-os/
127
- README.md ← You are here
128
133
  bin/roleos.mjs ← CLI entrypoint
129
- src/ ← CLI implementation
130
- starter-pack/
131
- handbook.md How Role OS works
132
- context/ Fill these for your repo
133
- examples/ Feature, integration, identity packets
134
- agents/ 32 role contracts across 8 packs
134
+ src/
135
+ route.mjs ← 31-role routing + dynamic chain builder
136
+ conflicts.mjs 4-pass conflict detection
137
+ escalation.mjs Auto-routing for blocked/rejected/split
138
+ evidence.mjs Structured evidence + role-aware requirements
139
+ dispatch.mjs Runtime dispatch manifests for multi-claude
140
+ trial.mjs ← Role execution trial framework
141
+ packet.mjs ← Packet creation
142
+ review.mjs ← Verdict recording + escalation integration
143
+ status.mjs ← Active packet + verdict status
144
+ test/
145
+ route.test.mjs ← 49 tests (routing + disambiguation)
146
+ conflicts.test.mjs ← 13 tests (4 conflict types)
147
+ escalation.test.mjs ← 22 tests (blocked/rejected/conflict/split)
148
+ evidence.test.mjs ← 23 tests (schema + sufficiency)
149
+ dispatch.test.mjs ← 21 tests (manifests + state + escalation packets)
150
+ trial.test.mjs ← 12 tests (trial framework)
151
+ cli.test.mjs ← 22 tests (CLI integration)
152
+ .claude/
153
+ agents/ ← 31 role contracts across 8 packs
135
154
  schemas/ ← Packet, handoff, verdict formats
136
- policy/ ← Routing, permissions, escalation, done
155
+ policy/ ← Routing rules, permissions, escalation, done
137
156
  workflows/ ← Ship feature, fix bug, launch update, full treatment
157
+ context/ ← Fill these for your repo
158
+ trials/ ← Execution trial packets + results
138
159
  ```
139
160
 
140
161
  ## Security
141
162
 
142
163
  Role OS operates **locally only**. It copies markdown templates and writes packet/verdict files to your repository's `.claude/` directory. It does not access the network, handle secrets, or collect telemetry. No dangerous operations — all file writes use skip-if-exists by default. See [SECURITY.md](SECURITY.md) for the full policy.
143
164
 
144
- ## Status
165
+ ## The operating system
166
+
167
+ | Layer | What it does | Status |
168
+ |-------|-------------|--------|
169
+ | **Routing** | Scores all 31 roles against packet content, explains recommendations, assesses confidence | ✓ Shipped |
170
+ | **Chain builder** | Assembles phase-ordered chains from scored roles, packet-type biased not template-locked | ✓ Shipped |
171
+ | **Conflict detection** | 4-pass validation: hard conflicts, sequence, redundancy, coverage gaps. Repair suggestions. | ✓ Shipped |
172
+ | **Escalation** | Auto-routes blocked/rejected/split work to the right resolver with reason + required artifact | ✓ Shipped |
173
+ | **Evidence** | Role-aware structured evidence in verdicts. Sufficiency checks. 12 evidence kinds. | ✓ Shipped |
174
+ | **Dispatch** | Generates execution manifests for multi-claude. Per-role tool profiles, system prompts, budgets. | ✓ Shipped |
175
+ | **Trials** | Full roster proven: 30/30 gold-task + 5/5 negative trials. 7 pack trials complete. | ✓ Complete |
176
+ | **Team Packs** | 7 battle-tested packs for common task families. Pack suggestion engine. | ✓ Shipped |
145
177
 
146
- **v1.0.0 — Broad Surface, Same Laws**
178
+ ## Status
147
179
 
148
- - v0.1: Operational3 trials, 3 accepts, 0 role collisions
149
- - v0.2: Adoption default workflow in anchor repo, portable to second repo
150
- - v0.3: Productization starter pack, bootstrap CLI, evidence surface
151
- - v0.4: Treatment Pack 8 treatment/identity roles, full treatment staffed, portable across 2 repos
152
- - v1.0.0: 32 roles across 8 packs, full CLI, proven treatment, multi-repo portability
180
+ - v0.1–v0.4: Foundation — trials, adoption, treatment pack, starter pack
181
+ - v1.0.0: 32 roles, full CLI, proven treatment, multi-repo portability
182
+ - v1.0.2: Role OS lockdown (bootstrap truth fixes, init --force)
183
+ - **v1.1.0**: 31 roles, full routing spine, conflict detection, escalation, evidence, dispatch, 7 proven team packs. 35 execution trials (30 gold + 5 negative). 212 tests.
153
184
 
154
185
  ## License
155
186
 
package/bin/roleos.mjs CHANGED
@@ -1,12 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { readFileSync } from "node:fs";
4
+ import { join, dirname } from "node:path";
5
+ import { fileURLToPath } from "node:url";
3
6
  import { initCommand } from "../src/init.mjs";
4
7
  import { packetCommand } from "../src/packet.mjs";
5
8
  import { routeCommand } from "../src/route.mjs";
6
9
  import { reviewCommand } from "../src/review.mjs";
7
10
  import { statusCommand } from "../src/status.mjs";
11
+ import { packsCommand } from "../src/packs-cmd.mjs";
8
12
 
9
- const VERSION = "1.0.0";
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const VERSION = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8")).version;
10
15
 
11
16
  function printHelp() {
12
17
  console.log(`
@@ -14,12 +19,16 @@ roleos v${VERSION} — Role OS bootstrap CLI
14
19
 
15
20
  Usage:
16
21
  roleos init Scaffold Role OS into .claude/
22
+ roleos init --force Update canonical files (protects context/)
17
23
  roleos packet new <type> Create a new packet (feature|integration|identity)
18
- roleos route <packet-file> Recommend the smallest valid chain
24
+ roleos route <packet-file> [--verbose] Recommend the smallest valid chain
19
25
  roleos review <packet-file> <verdict> Record a review verdict
20
26
  roleos status Show active work, verdicts, and health
21
27
  roleos status --write Write .claude/status/index.md
22
28
  roleos status --json Output as JSON
29
+ roleos packs list List all available team packs
30
+ roleos packs suggest <packet-file> Suggest a pack for a packet
31
+ roleos packs show <pack-key> Show full detail for a named pack
23
32
  roleos help Show this help
24
33
 
25
34
  Verdicts: accept | accept-with-notes | reject | blocked
@@ -69,6 +78,9 @@ try {
69
78
  case "status":
70
79
  await statusCommand(args);
71
80
  break;
81
+ case "packs":
82
+ await packsCommand(args);
83
+ break;
72
84
  case "help":
73
85
  case "--help":
74
86
  case "-h":
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "role-os",
3
- "version": "1.0.1",
4
- "description": "Role OS — a repo-native operating layer where specialized roles execute work through contracts, handoffs, review, and escalation",
3
+ "version": "1.1.0",
4
+ "description": "Role OS — a multi-Claude operating system where 31 specialized roles execute work through contracts, conflict detection, escalation, and structured evidence. 7 proven team packs for common task families.",
5
+ "homepage": "https://mcp-tool-shop-org.github.io/role-os/",
6
+ "bugs": {
7
+ "url": "https://github.com/mcp-tool-shop-org/role-os/issues"
8
+ },
5
9
  "type": "module",
6
10
  "bin": {
7
11
  "roleos": "bin/roleos.mjs"
@@ -33,7 +37,13 @@
33
37
  "contracts",
34
38
  "handoffs",
35
39
  "review",
36
- "workflow"
40
+ "workflow",
41
+ "multi-agent",
42
+ "ai-workflow",
43
+ "developer-tools",
44
+ "role-contracts",
45
+ "claude",
46
+ "multi-claude"
37
47
  ],
38
48
  "publishConfig": {
39
49
  "registry": "https://registry.npmjs.org"
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Role conflict detection.
3
+ *
4
+ * Tells the operator when the staffed team is internally broken
5
+ * before work starts. Four passes: hard conflicts, sequence,
6
+ * redundancy, coverage gaps. Every finding includes a repair suggestion.
7
+ */
8
+
9
+ // ── Per-role constraints ──────────────────────────────────────────────────────
10
+
11
+ const ROLE_CONSTRAINTS = {
12
+ "Critic Reviewer": {
13
+ lateOnly: true,
14
+ requiresBeforePacks: ["engineering", "design", "treatment", "product"],
15
+ description: "review/gate role — needs something to review",
16
+ },
17
+ "Test Engineer": {
18
+ lateOnly: true,
19
+ requiresBeforePacks: ["engineering", "design"],
20
+ description: "test role — needs something to test",
21
+ },
22
+ "Coverage Auditor": {
23
+ lateOnly: true,
24
+ requiresBeforePacks: ["engineering"],
25
+ description: "coverage role — needs code to audit",
26
+ },
27
+ "Deployment Verifier": {
28
+ lateOnly: true,
29
+ requiresBeforePacks: ["engineering", "treatment"],
30
+ description: "verification role — needs something deployed to verify",
31
+ },
32
+ "Release Engineer": {
33
+ lateOnly: true,
34
+ requiresBeforePacks: ["engineering", "treatment"],
35
+ description: "release role — needs built or prepared artifacts to release",
36
+ },
37
+ "Launch Copywriter": {
38
+ requiresBeforePacks: ["engineering", "design", "product"],
39
+ description: "messaging role — needs product substance to write about",
40
+ },
41
+ "Launch Strategist": {
42
+ requiresBeforePacks: ["engineering", "design", "product"],
43
+ description: "launch role — needs product substance to plan launch around",
44
+ },
45
+ "Content Strategist": {
46
+ requiresBeforePacks: ["engineering", "design", "product"],
47
+ description: "content role — needs product substance for content planning",
48
+ },
49
+ };
50
+
51
+ // ── Overlap declarations ──────────────────────────────────────────────────────
52
+ // Roles that produce similar artifacts and rarely both need to be in the same chain.
53
+
54
+ const OVERLAP_PAIRS = [
55
+ ["Coverage Auditor", "Test Engineer", "both assess test quality — consider keeping only one unless scope is very large"],
56
+ ["Repo Researcher", "Docs Architect", "both map repo structure — Researcher maps truth, Architect builds docs from it"],
57
+ ["Launch Strategist", "Launch Copywriter", "both serve launches — Strategist plans, Copywriter writes. Both needed only for major launches"],
58
+ ["Competitive Analyst", "Trend Researcher", "both scan external landscape — consider whether one covers the need"],
59
+ ];
60
+
61
+ // ── Builder packs (roles that produce primary artifacts) ──────────────────────
62
+
63
+ const BUILDER_PACKS = new Set(["engineering", "design", "product", "treatment"]);
64
+
65
+ // ── Pack limits ───────────────────────────────────────────────────────────────
66
+
67
+ const MAX_SAME_PACK = 3;
68
+
69
+ // ── Detection engine ──────────────────────────────────────────────────────────
70
+
71
+ /**
72
+ * Detect conflicts in a staffed chain.
73
+ *
74
+ * @param {Array<{role: {name: string, pack: string, phase: number}}>} chainRoles
75
+ * @returns {Array<{type: string, severity: string, roles: string[], message: string, repair: string}>}
76
+ */
77
+ export function detectConflicts(chainRoles) {
78
+ const findings = [];
79
+ const names = chainRoles.map(r => r.role.name);
80
+ const packs = chainRoles.map(r => r.role.pack);
81
+ const roles = chainRoles.map(r => r.role);
82
+
83
+ // ── Pass 1: Hard conflicts ──────────────────────────────────────────────
84
+
85
+ // Check if review/gate roles are the only non-Orchestrator roles (no builders)
86
+ const nonCore = roles.filter(r => r.name !== "Orchestrator" && r.name !== "Critic Reviewer");
87
+ const builders = nonCore.filter(r => BUILDER_PACKS.has(r.pack));
88
+
89
+ if (builders.length === 0 && nonCore.length > 0) {
90
+ const nonCoreNames = nonCore.map(r => r.name);
91
+ findings.push({
92
+ type: "blocking",
93
+ severity: "error",
94
+ roles: nonCoreNames,
95
+ message: `Chain has no builder roles (engineering, design, product, or treatment). Only gate/growth/research roles present: ${nonCoreNames.join(", ")}.`,
96
+ repair: "Add at least one role that produces a primary artifact (e.g., Backend Engineer, UI Designer, Spec Writer).",
97
+ });
98
+ }
99
+
100
+ // ── Pass 2: Sequence conflicts ──────────────────────────────────────────
101
+
102
+ for (const [roleName, constraints] of Object.entries(ROLE_CONSTRAINTS)) {
103
+ const roleIdx = names.indexOf(roleName);
104
+ if (roleIdx === -1) continue; // role not in chain
105
+
106
+ if (constraints.requiresBeforePacks) {
107
+ // Check if any role from the required packs appears BEFORE this role
108
+ const hasPriorBuilder = roles.slice(0, roleIdx).some(
109
+ r => constraints.requiresBeforePacks.includes(r.pack)
110
+ );
111
+
112
+ if (!hasPriorBuilder && builders.length > 0) {
113
+ // There ARE builders, but they're all AFTER this role
114
+ findings.push({
115
+ type: "sequence",
116
+ severity: "warning",
117
+ roles: [roleName],
118
+ message: `${roleName} (${constraints.description}) appears before any ${constraints.requiresBeforePacks.join("/")} role in the chain.`,
119
+ repair: `Move ${roleName} later in the chain, after the roles that produce what it needs.`,
120
+ });
121
+ }
122
+
123
+ if (builders.length === 0 && !constraints.lateOnly) {
124
+ // No builders at all — this was caught in Pass 1, skip double-reporting
125
+ }
126
+ }
127
+
128
+ if (constraints.lateOnly) {
129
+ // Check if this role appears in the first half of the chain (before most work)
130
+ const midpoint = Math.floor(chainRoles.length / 2);
131
+ if (roleIdx > 0 && roleIdx < midpoint && chainRoles.length > 3) {
132
+ findings.push({
133
+ type: "sequence",
134
+ severity: "warning",
135
+ roles: [roleName],
136
+ message: `${roleName} is a late-chain role but appears in the first half (position ${roleIdx + 1} of ${chainRoles.length}).`,
137
+ repair: `Move ${roleName} toward the end of the chain where it can act on completed work.`,
138
+ });
139
+ }
140
+ }
141
+ }
142
+
143
+ // ── Pass 3: Redundancy ──────────────────────────────────────────────────
144
+
145
+ // Pack density check
146
+ const packCounts = {};
147
+ for (const pack of packs) {
148
+ packCounts[pack] = (packCounts[pack] || 0) + 1;
149
+ }
150
+ for (const [pack, count] of Object.entries(packCounts)) {
151
+ if (pack === "core") continue; // Orchestrator + Critic are always present
152
+ if (count > MAX_SAME_PACK) {
153
+ const packRoles = roles.filter(r => r.pack === pack).map(r => r.name);
154
+ findings.push({
155
+ type: "redundancy",
156
+ severity: "warning",
157
+ roles: packRoles,
158
+ message: `${count} roles from the "${pack}" pack: ${packRoles.join(", ")}. This may indicate an oversized or overlapping team.`,
159
+ repair: `Review whether all ${count} ${pack} roles are needed. Consider splitting into sub-packets if scope is broad.`,
160
+ });
161
+ }
162
+ }
163
+
164
+ // Overlap pair check
165
+ for (const [roleA, roleB, note] of OVERLAP_PAIRS) {
166
+ if (names.includes(roleA) && names.includes(roleB)) {
167
+ findings.push({
168
+ type: "redundancy",
169
+ severity: "warning",
170
+ roles: [roleA, roleB],
171
+ message: `${roleA} and ${roleB} are both in the chain — ${note}.`,
172
+ repair: `Consider whether both are needed, or if one can cover the scope.`,
173
+ });
174
+ }
175
+ }
176
+
177
+ // ── Pass 4: Coverage gaps ───────────────────────────────────────────────
178
+
179
+ const engineeringCount = roles.filter(r => r.pack === "engineering").length;
180
+ const hasTestEngineer = names.includes("Test Engineer");
181
+ const hasCritic = names.includes("Critic Reviewer");
182
+
183
+ // Engineering-heavy with no tester
184
+ if (engineeringCount >= 2 && !hasTestEngineer) {
185
+ findings.push({
186
+ type: "coverage",
187
+ severity: "warning",
188
+ roles: roles.filter(r => r.pack === "engineering").map(r => r.name),
189
+ message: `Chain has ${engineeringCount} engineering roles but no Test Engineer. Code may ship without verification.`,
190
+ repair: "Add Test Engineer to verify the engineering output before review.",
191
+ });
192
+ }
193
+
194
+ // Builders present but no critic (defensive — should be caught by always-include)
195
+ if (builders.length > 0 && !hasCritic) {
196
+ findings.push({
197
+ type: "coverage",
198
+ severity: "error",
199
+ roles: builders.map(r => r.name),
200
+ message: "Chain has builder roles but no Critic Reviewer. Work cannot be accepted without a final gate.",
201
+ repair: "Add Critic Reviewer as the final role in the chain.",
202
+ });
203
+ }
204
+
205
+ // Large chain without Orchestrator (defensive)
206
+ if (chainRoles.length > 4 && !names.includes("Orchestrator")) {
207
+ findings.push({
208
+ type: "coverage",
209
+ severity: "warning",
210
+ roles: names,
211
+ message: "Chain has 5+ roles but no Orchestrator. Complex work needs coordination.",
212
+ repair: "Add Orchestrator at the start of the chain to decompose and sequence the work.",
213
+ });
214
+ }
215
+
216
+ return findings;
217
+ }