peaks-loop 4.0.14 → 4.0.16

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 (39) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/config/eslint/.peaks-rules.cjs +8 -1
  3. package/dist/cli/commands/_register.js +2 -1
  4. package/dist/cli/commands/code-review-commands.d.ts +2 -30
  5. package/dist/cli/commands/code-review-commands.js +43 -65
  6. package/dist/cli/commands/lint-commands.d.ts +21 -0
  7. package/dist/cli/commands/lint-commands.js +146 -0
  8. package/dist/cli/commands/outer-cache-commands.js +13 -6
  9. package/dist/cli/commands/security-audit-commands.d.ts +1 -1
  10. package/dist/cli/commands/security-audit-commands.js +1 -1
  11. package/dist/services/code-review/ecc-bridge.d.ts +2 -7
  12. package/dist/services/config/config-service.d.ts +2 -19
  13. package/dist/services/config/config-service.js +0 -52
  14. package/dist/services/config/config-types.d.ts +4 -24
  15. package/dist/services/config/config-types.js +1 -10
  16. package/dist/services/lint/detect-eslint.d.ts +10 -0
  17. package/dist/services/lint/detect-eslint.js +59 -0
  18. package/dist/services/lint/detect-ocr-18.d.ts +10 -0
  19. package/dist/services/lint/detect-ocr-18.js +40 -0
  20. package/dist/services/lint/eslint-runner.d.ts +58 -0
  21. package/dist/services/lint/eslint-runner.js +307 -0
  22. package/dist/services/lint/ocr-multilang-adapter.d.ts +34 -0
  23. package/dist/services/lint/ocr-multilang-adapter.js +143 -0
  24. package/dist/services/session/binding-store.d.ts +6 -6
  25. package/dist/services/session/caller-binding-service.d.ts +7 -0
  26. package/dist/services/session/caller-binding-service.js +11 -7
  27. package/dist/services/session/session-binding-bridge.d.ts +17 -1
  28. package/dist/services/session/session-binding-bridge.js +185 -29
  29. package/dist/services/session/session-manager.js +37 -0
  30. package/dist/services/skills/skill-presence-service.js +13 -1
  31. package/package.json +5 -12
  32. package/skills/bee/peaks-rd/SKILL.md +1 -1
  33. package/skills/bee/peaks-rd/references/jsts-eslint-gate.md +197 -0
  34. package/skills/bee/peaks-rd/references/ocr-multilang-1.8.md +132 -0
  35. package/skills/bee/peaks-rd/references/parallel-review-fanout.md +1 -1
  36. package/skills/peaks-code/SKILL.md +1 -1
  37. package/dist/services/code-review/ocr-service.d.ts +0 -129
  38. package/dist/services/code-review/ocr-service.js +0 -372
  39. package/skills/bee/peaks-rd/references/ocr-integration.md +0 -229
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peaks-loop",
3
- "version": "4.0.14",
3
+ "version": "4.0.16",
4
4
  "description": "Loop Engineering CLI — workflow primitive / loop guards / evaluators / slice orchestration",
5
5
  "author": "SquabbyZ",
6
6
  "keywords": [
@@ -93,6 +93,7 @@
93
93
  "node": ">=20.0.0"
94
94
  },
95
95
  "dependencies": {
96
+ "@alibaba-group/open-code-review": "^1.8.9",
96
97
  "@colbymchenry/codegraph": "0.7.10",
97
98
  "better-sqlite3": "^12.11.1",
98
99
  "commander": "^12.1.0",
@@ -100,17 +101,9 @@
100
101
  "headroom-ai": "0.22.4",
101
102
  "yaml": "^2.9.0",
102
103
  "zod": "^3.25.76",
103
- "peaks-loop-shared": "0.0.45",
104
- "peaks-loop-shared-channel": "0.0.22",
105
- "peaks-loop-mut": "0.1.18"
106
- },
107
- "peerDependencies": {
108
- "@alibaba-group/open-code-review": "1.3.1"
109
- },
110
- "peerDependenciesMeta": {
111
- "@alibaba-group/open-code-review": {
112
- "optional": true
113
- }
104
+ "peaks-loop-mut": "0.1.19",
105
+ "peaks-loop-shared-channel": "0.0.23",
106
+ "peaks-loop-shared": "0.0.47"
114
107
  },
115
108
  "devDependencies": {
116
109
  "@changesets/cli": "2.31.1",
@@ -84,7 +84,7 @@ See `references/rd-runbook.md` for the full 9-step runbook (steps #0–#8) with
84
84
 
85
85
  You cannot declare a phase complete from memory. Each gate below is a `ls` or `grep` command you **MUST run** and whose output you **MUST see** before proceeding. CLI enforcement: the gates are ALSO enforced by `peaks request transition`, which fails with `code: PREREQUISITES_MISSING` if any are absent.
86
86
 
87
- Gate index: A (project-scan), A2 (tech-doc path verification), A3 (CLAUDE.md + .claude/rules), B (tech-doc + request artifact), B2 (unit tests on changed surface), B3 (code-review.md), B4 (security-review.md), B5 (lint — no unfilled placeholders), B6 (request-type-sanity), B7 (repair-status — 3-cycle cap), B8 (diff-vs-scope), B9 (perf-baseline).
87
+ Gate index: A (project-scan), A2 (tech-doc path verification), A3 (CLAUDE.md + .claude/rules), B (tech-doc + request artifact), B2 (unit tests on changed surface), B3 (code-review.md), B4 (security-review.md), B5 (lint — no unfilled placeholders + JS/TS ESLint 卡控 via `peaks lint check`. First-time project setup: run `peaks lint baseline` to generate the project-level `.peaks/lint/baseline.json`. Per-slice flow uses `peaks lint check` (= diffOnly: true + baseline waiver + redLineMode: 'baseline-aware'). LLM red-line reference lives at `.peaks/memory/lint-redline-summary.md` (auto-written by `peaks lint check --red-line`); read it BEFORE writing JS/TS so the next slice sees prior sibling-violation context. Project-aware baseline: each project regenerates its own baseline; cross-project reuse is low-value — see `references/jsts-eslint-gate.md` §7), B6 (request-type-sanity), B7 (repair-status — 3-cycle cap), B8 (diff-vs-scope), B9 (perf-baseline).
88
88
 
89
89
  → see `references/rd-transition-gates.md` for the per-gate contract + `ls` / `grep` shell snippets.
90
90
 
@@ -0,0 +1,197 @@
1
+ ---
2
+ title: JS/TS ESLint Gate (Gate B5 卡控)
3
+ rid: 2026-08-06-eslint-jsts-gate
4
+ session: 2026-08-06-session-cacde8
5
+ status: shipped-4.0.16
6
+ ---
7
+
8
+ # JS/TS ESLint Gate (Gate B5 卡控)
9
+
10
+ ## Section 1 — what the runner does
11
+
12
+ `peaks lint` is a read-only ESLint verifier for the peaks-rd Gate B5
13
+ surface. It calls `npx` with four pinned packages (no `devDependencies`
14
+ added to peaks-loop) and parses the JSON envelope emitted by
15
+ `--format json`.
16
+
17
+ Pinned packages (slice PRD-002; aligned with the rules resolved by
18
+ `config/eslint/.peaks-rules.cjs`):
19
+
20
+ | Package | Pin | Source |
21
+ |---|---|---|
22
+ | `eslint` | 10.8.0 | npm registry |
23
+ | `@typescript-eslint/parser` | 8.66.0 | npm registry |
24
+ | `@typescript-eslint/eslint-plugin` | 8.66.0 | npm registry |
25
+ | `eslint-plugin-import` | 2.32.0 | npm registry |
26
+
27
+ The runner lives at `src/services/lint/eslint-runner.ts` and exports
28
+ `runEslint({ cwd, scope?, configPath?, fix?, write?, timeoutMs? })`.
29
+
30
+ ## Section 2 — 5-state detect table
31
+
32
+ `detect-eslint` returns one of:
33
+
34
+ | State | Meaning | Behavior |
35
+ |---|---|---|
36
+ | `ready` | npx is on PATH and the registry resolves all 4 pins | run lint |
37
+ | `eslint-missing` | lint exited with no findings (likely a toolchain error) | warn |
38
+ | `config-error` | config did not parse | block |
39
+ | `npx-failed` | npx is not on PATH | warn |
40
+ | `detection-failed` | unexpected detection exception | warn |
41
+
42
+ The wrapper returns `state: 'ok' | 'eslint-missing' | 'npx-failed' |
43
+ 'execution-failed'` (lint cannot reach `config-error` because the
44
+ runner is config-agnostic; the consumer supplies `--config <path>`).
45
+
46
+ ## Section 3 — Layer 3 dynamic loading
47
+
48
+ `config/eslint/.peaks-rules.cjs` allows the L3 (framework) layer to be
49
+ loaded dynamically by `npx --package <pkg> -- eslint`. peaks-loop
50
+ itself never installs the L3 packages; the user opts in per-project.
51
+ If a project needs `eslint-plugin-react`, it is up to the user to
52
+ either:
53
+
54
+ - run `npm i -D eslint-plugin-react` and update
55
+ `config/eslint/.peaks-rules.cjs` to extend the relevant config, or
56
+ - call `peaks lint --scope src/` after pre-installing the plugin
57
+ in their environment.
58
+
59
+ ## Section 4 — soft-fail table
60
+
61
+ | Runner state | Gate B5 verdict |
62
+ |---|---|
63
+ | `ok` with zero findings | pass |
64
+ | `ok` with findings | warn (findings printed; never block) |
65
+ | `npx-failed` / `eslint-missing` | warn — Gate B5 still passes |
66
+ | `execution-failed` | warn — user must inspect the toolchain |
67
+
68
+ peaks-rd never blocks a slice on lint; per the G-lint-2 red line,
69
+ peaks lint is a verifier, not a formatter.
70
+
71
+ ## Section 5 — Gate B5 transitions
72
+
73
+ - `rd:qa-handoff` reads the lint envelope. A missing `peaks lint`
74
+ run is acceptable if the project is non-JS/TS (Gate B5 is per-language).
75
+ - peaks-rd's own 4-dim lint (placeholder hunt) runs alongside ESLint.
76
+ - The unified verdict is the worst of the two lint families (ESLint
77
+ warn never escalates to block).
78
+
79
+ ## Section 6 — Configuration precedence
80
+
81
+ `config/eslint/.peaks-rules.cjs` composes its rule set by extending
82
+ four upstream configs in this order (last-wins on rule overrides):
83
+
84
+ 1. `eslint:recommended` — base ES syntax + best practices.
85
+ 2. `plugin:@typescript-eslint/recommended-type-checked` — TS rules
86
+ that require type info. Requires `@typescript-eslint/parser` to
87
+ resolve with `project: true`.
88
+ 3. `plugin:import/recommended` — module-boundary / import-resolution
89
+ rules. Reports unresolved imports as errors.
90
+ 4. `plugin:import/typescript` — TypeScript-aware import resolver
91
+ layered on top of `import/recommended`.
92
+
93
+ User-level `.eslintrc.cjs` (or `--config <path>`) overrides extend in
94
+ priority order: the closer the config is to the source file, the
95
+ higher its precedence. `peaks lint` honours the `--config` flag
96
+ so projects that carry a non-default config can point the runner at
97
+ it without copying into the peaks-loop repo.
98
+
99
+ The `import/recommended` and `import/typescript` layers in particular
100
+ make the wrapper sensitive to the project's `tsconfig.json` `paths`
101
+ config. A monorepo with `baseUrl` + `paths` aliases must keep its
102
+ tsconfig in scope; otherwise `import/no-unresolved` reports
103
+ spurious errors that downgrade Gate B5 to a noisy warn.
104
+
105
+ `recommended-type-checked` likewise depends on a resolvable
106
+ `tsconfig.json`; projects that ship a non-default config must pass
107
+ it via `--config` so ESLint can locate the program files for type
108
+ introspection. Without a reachable tsconfig the type-aware rules
109
+ silently no-op, which the runner reports as zero type-checked
110
+ findings (not as an error).
111
+
112
+ The L3 framework plugins (react / vue / svelte / nestjs) are NOT
113
+ included in the four pinned packages. `peaks lint` will not
114
+ auto-resolve them; the project's own devDependencies must list the
115
+ plugin and the local `.peaks-rules.cjs` must extend its config.
116
+ This keeps the peaks-loop devDeps surface flat while still letting
117
+ per-project opt-in.
118
+
119
+ ## Section 7 — Project-aware baseline (PRD-002b D6 + S1)
120
+
121
+ `.peaks/lint/baseline.json` is a **project-level** file. Each project
122
+ generates its own baseline via `peaks lint baseline`; downstream
123
+ projects **do not** inherit peak-loop's baseline even when they share
124
+ the same language (TypeScript) — language similarity ≠ project
125
+ structure / toolchain / coding style.
126
+
127
+ | Project type | Baseline source | Why |
128
+ |---|---|---|
129
+ | `peaks-loop` itself | Ship as reference + fixture | TS CLI; reference value high |
130
+ | Downstream React TS | MUST run `peaks lint baseline` | Different framework / hooks / component patterns |
131
+ | Downstream Python / Go / Java | Language-specific toolchain (future slice) | Cross-language; zero reference value today |
132
+
133
+ The baseline.json schema (internal contract, not public):
134
+
135
+ ```jsonc
136
+ {
137
+ "version": 1,
138
+ "generatedAt": "2026-08-06T...",
139
+ "toolVersion": "peaks-loop-4.0.16+",
140
+ "violations": [
141
+ { "ruleId": "max-lines", "file": "src/x.ts", "line": 401,
142
+ "severity": "error", "message": "..." }
143
+ ]
144
+ }
145
+ ```
146
+
147
+ `peaks lint baseline` writes this file at the cwd (default
148
+ `.peaks/lint/baseline.json`); the file is gitignored by default —
149
+ projects that want to ship it (peak-loop itself) use `git add -f`.
150
+
151
+ ## Section 8 — Red-line (LLM development red line; PRD-002b S2)
152
+
153
+ The lint envelope carries a `redLine` section whenever
154
+ `redLineMode='baseline-aware'` (the default). It aggregates
155
+ baseline.json violations by `ruleId`, sorted by count desc, with the
156
+ top 5 file:line buckets per rule. Sample shape:
157
+
158
+ ```jsonc
159
+ {
160
+ "redLine": [
161
+ { "ruleId": "max-lines-per-function", "count": 7,
162
+ "topFiles": [
163
+ { "file": "src/services/foo.ts", "count": 3 },
164
+ { "file": "src/services/bar.ts", "count": 2 }
165
+ ] }
166
+ ]
167
+ }
168
+ ```
169
+
170
+ LLM workflow:
171
+
172
+ 1. Before writing JS/TS, read `.peaks/memory/lint-redline-summary.md`
173
+ (auto-generated by `peaks lint check --red-line` or
174
+ `peaks lint baseline --red-line`).
175
+ 2. If `redLine[0].ruleId === 'max-lines-per-function'` shows 5+
176
+ existing occurrences, the LLM MUST split any function ≥ 30 lines
177
+ it would otherwise write; this prevents the violation count from
178
+ climbing while存量 stays at baseline.
179
+ 3. The red-line is **low value when baseline is empty** (project
180
+ bootstrap) and **high value when baseline is saturated** (≥ 5
181
+ per rule). The CLI prints a one-line warning when the red-line
182
+ would help; the LLM should still consult it on every Gate B5.
183
+
184
+ The red-line is informational, not blocking — Gate B5 still passes
185
+ when redLine has entries. Its job is to keep存量 violation counts
186
+ flat as new code lands, not to escalate存量 work.
187
+
188
+ ## Cross-references
189
+
190
+ - PRD: `.peaks/_runtime/2026-08-06-session-cacde8/prd/requests/002-2026-08-06-eslint-jsts-gate-and-ocr-multilang-rebuild.md`
191
+ - Sediment: `.peaks/memory/2026-08-06-eslint-jsts-gate-and-ocr-multilang-rebuild-sediment.md`
192
+ - Skills: `skills/bee/peaks-rd/SKILL.md` Gate B5 paragraph
193
+ - Skills: `skills/peaks-code/SKILL.md` Quality-gate commands cheat sheet
194
+ - Config: `config/eslint/.peaks-rules.cjs`
195
+ - Runner: `src/services/lint/eslint-runner.ts`
196
+ - Detect: `src/services/lint/detect-eslint.ts`
197
+ - CLI: `src/cli/commands/lint-commands.ts`
@@ -0,0 +1,132 @@
1
+ ---
2
+ title: OCR 1.8.x Multi-language Reviewer Adapter
3
+ rid: 2026-08-06-ocr-multilang-1-8
4
+ session: 2026-08-06-session-cacde8
5
+ status: shipped-4.0.16
6
+ ---
7
+
8
+ # OCR 1.8.x Multi-language Reviewer Adapter
9
+
10
+ ## Section 1 — per-platform optionalDependencies (1.8.x postinstall fix)
11
+
12
+ `@alibaba-group/open-code-review@1.8.9` replaces the 2.0.3-era
13
+ GitHub Releases HTTPS download with per-platform `optionalDependencies`
14
+ (`@alibaba-group/ocr-{darwin,linux,win32}-{arm64,x64}`). `npm install`
15
+ hits the registry only; postinstall runs the embedded Node installer
16
+ (`scripts/install.js`) and resolves the platform binary locally.
17
+
18
+ Sandbox evidence (2026-08-06, `npm@10.9.4`):
19
+
20
+ ```
21
+ npm install @alibaba-group/open-code-review@1.8.9
22
+ added 2 packages in 5s
23
+ npm info run @alibaba-group/open-code-review@1.8.9 postinstall { code: 0, signal: null }
24
+ ```
25
+
26
+ No HTTPS to `github.com` is required. The 2.0.3 install pain (which
27
+ drove the 2.8.2 peerDep downgrade) no longer applies.
28
+
29
+ ## Section 2 — 8-language routing
30
+
31
+ | `--language` | file extension filter (ocr 1.8.9) |
32
+ |---|---|
33
+ | `python` | `*.py` |
34
+ | `go` | `*.go` |
35
+ | `java` | `*.java` |
36
+ | `rust` | `*.rs` |
37
+ | `cpp` | `*.cc` / `*.cpp` / `*.h` / `*.hpp` |
38
+ | `csharp` | `*.cs` |
39
+ | `ruby` | `*.rb` |
40
+ | `php` | `*.php` |
41
+
42
+ `--language java` maps to Java review. The wrapper rejects any other
43
+ language with `state: 'language-unsupported'` and a supported list in
44
+ `nextActions`.
45
+
46
+ ## Section 3 — 5-state detect table
47
+
48
+ `detect-ocr-18` returns one of:
49
+
50
+ | State | Meaning | Behavior |
51
+ |---|---|---|
52
+ | `ready` | npx + ocr 1.8.9 both resolve | run review |
53
+ | `ocr18-missing` | npx or ocr package cannot resolve | warn |
54
+ | `binary-missing` | platform binary optionalDep missing | warn |
55
+ | `llm-config-missing` | Delegation Mode not requested and no key | warn |
56
+ | `detection-failed` | unexpected detection exception | warn |
57
+
58
+ The runtime wrapper returns `language-unsupported` as a 6th state
59
+ when the caller supplies a non-mapped language.
60
+
61
+ ## Section 4 — Delegation Mode
62
+
63
+ `peaks code-review ocr-18-delegate-preview` runs `ocr delegate preview`
64
+ with no LLM key. The wrapper returns the spec the host agent must
65
+ fill in (file list + rule references); the host agent's own LLM
66
+ performs the analysis. This is the fallback path when the user does
67
+ not have an Anthropic/OpenAI key configured.
68
+
69
+ ## Section 5 — soft-fail policy
70
+
71
+ `run-ocr-18` never blocks a slice. When ocr 1.8.x is not ready, the
72
+ wrapper returns `state: 'ocr18-missing'` (or appropriate) and
73
+ peaks-rd records a TXT note `code-review-ocr18-degraded-to-inline`.
74
+
75
+ ## Section 6 — Gate B3 routing
76
+
77
+ - JS/TS / TSX / JSX: `peaks lint` + ECC bridge.
78
+ - Python / Go / Java / Rust / C++ / C# / Ruby / PHP:
79
+ `peaks code-review run-ocr-18 --language <lang>`.
80
+ - Mixed monorepo: per-language routing, findings merged.
81
+
82
+ ## Section 7 — Why per-language routing matters
83
+
84
+ OCR 1.8.x is the multi-language reviewer in the peaks-rd Gate B3
85
+ router; ECC bridge stays the JS/TS path. The split is intentional and
86
+ informed by AACR-bench (Alibaba's multi-language review benchmark):
87
+
88
+ - **Precision vs. recall trade-off.** ECC bridge is tuned for JS/TS
89
+ idioms and ships tighter precision for that surface; on Python or
90
+ Java codebases it under-recalls (false-negative on async/lifetime
91
+ bugs). OCR 1.8.x is the inverse: broad language coverage with
92
+ per-language rule packs.
93
+ - **Enterprise-class checks per language.** OCR 1.8.x's Java pack
94
+ reports NPE / SQL injection / XSS / thread-safety patterns that
95
+ have no analogue in the JS/TS ECC skill set. Routing a Java
96
+ project through ECC would silently drop these findings.
97
+ - **Layered output normalization.** Each language's OCR output is
98
+ flattened into the peaks-loop `Ocr18Finding` envelope (filePath,
99
+ line, ruleId, severity, message) so downstream Gate B3 merge
100
+ works uniformly across all 8 languages.
101
+ - **Failure isolation.** When OCR 1.8.x is missing for one language
102
+ on a given host, only that language degrades to inline review;
103
+ other languages still get the full Gate B3 path.
104
+
105
+ A Python project therefore routes to OCR 1.8.x (not ECC) because
106
+ (a) the Python rule pack has the broadest coverage in 1.8.9, and
107
+ (b) routing it through ECC would mask Python-specific findings.
108
+
109
+ For monorepos, the router scans the changed file extensions to pick
110
+ a per-language reviewer. A commit that touches `.py` and `.ts`
111
+ sources gets a parallel ECC + OCR-1.8 invocation; the resulting
112
+ finding arrays are merged at Gate B3 with severity sort and
113
+ duplicate suppression (same `filePath:line:ruleId` collapses to a
114
+ single entry).
115
+
116
+ When Delegation Mode is enabled, the host agent receives a JSON
117
+ spec listing files and candidate rules, applies the user's own LLM
118
+ key, and returns structured findings that the wrapper normalises
119
+ back into the same `Ocr18Finding` envelope — so downstream Gate B3
120
+ merge code does not need a separate code path for the delegation
121
+ flow.
122
+
123
+ ## Cross-references
124
+
125
+ - PRD: `.peaks/_runtime/2026-08-06-session-cacde8/prd/requests/002-2026-08-06-eslint-jsts-gate-and-ocr-multilang-rebuild.md`
126
+ - Sediment: `.peaks/memory/2026-08-06-eslint-jsts-gate-and-ocr-multilang-rebuild-sediment.md`
127
+ - Skills: `skills/bee/peaks-rd/SKILL.md` Gate B3 paragraph
128
+ - Skills: `skills/peaks-code/SKILL.md` Quality-gate commands cheat sheet
129
+ - Runner: `src/services/lint/ocr-multilang-adapter.ts`
130
+ - Detect: `src/services/lint/detect-ocr-18.ts`
131
+ - CLI: `src/cli/commands/code-review-commands.ts`
132
+ - ECC bridge (production JS/TS path): `src/services/code-review/ecc-bridge.ts`
@@ -46,7 +46,7 @@ Note: sub-agent 1 (code-reviewer) and sub-agent 3 (karpathy-reviewer) write to `
46
46
  - Inspect for: correctness, type safety, error handling, mutation patterns, file-size, naming, dead code, regressions, contract drift.
47
47
  - Output: `.peaks/_runtime/<sessionId>/rd/code-review.md` with sections: Summary, Findings, Required Fixes, Recommended, Verdict.
48
48
  - Required for Gate B3.
49
- - **v2.11.0 Tier 7 (Group D):** the code-reviewer dispatch goes through the **ECC bridge** (`src/services/code-review/ecc-bridge.ts`). The parent RD loop invokes the Agent tool with `subagent_type: "everything-claude-code:code-review"` and receives a structured envelope `{ passed, violations[], gateAction }`. The bridge adapter (`adaptEccEnvelopeToRdCodeReview`) renders that envelope into the canonical `rd/code-review.md` markdown shape that Gate B3 reads (`mustContain: ['## Findings', 'CRITICAL']`). The pre-Tier-7 5-state detect (`detectEcc`: ready / plugin-missing / agent-missing / dispatch-failed / envelope-malformed) soft-fails to inline review on any non-ready state — TXT note `code-review-ecc-degraded-to-inline`. Same soft-fail philosophy as `ocr-service.ts` and `detectOcr`.
49
+ - **v2.11.0 Tier 7 (Group D):** the code-reviewer dispatch goes through the **ECC bridge** (`src/services/code-review/ecc-bridge.ts`). The parent RD loop invokes the Agent tool with `subagent_type: "everything-claude-code:code-review"` and receives a structured envelope `{ passed, violations[], gateAction }`. The bridge adapter (`adaptEccEnvelopeToRdCodeReview`) renders that envelope into the canonical `rd/code-review.md` markdown shape that Gate B3 reads (`mustContain: ['## Findings', 'CRITICAL']`). The 5-state detector (`detectEcc`: ready / plugin-missing / agent-missing / dispatch-failed / envelope-malformed) soft-fails to inline review on any non-ready state — TXT note `code-review-ecc-degraded-to-inline`.
50
50
 
51
51
  **Sub-agent 2 — qa-test-cases-writer (always runs for feature / refactor / bugfix):**
52
52
  - Read the git diff and the PRD acceptance criteria.
@@ -208,7 +208,7 @@ Read `references/refactor-mode.md` first. Default MVP: `peaks-code refactor`. Re
208
208
 
209
209
  ## Peaks-Loop Quality-gate commands (CLI cheat sheet)
210
210
 
211
- Five CLI commands harden the workflow against silent skips: `peaks request lint`, `peaks request repair-status`, `peaks scan request-type-sanity`, `peaks scan libraries`, `peaks slice check` (plus `peaks request transition`). See `references/quality-gate-cheatsheet.md`.
211
+ Five CLI commands harden the workflow against silent skips: `peaks request lint`, `peaks request repair-status`, `peaks scan request-type-sanity`, `peaks scan libraries`, `peaks slice check` (plus `peaks request transition`). For JS/TS project lint enforcement (Gate B5 expansion), use `peaks lint [--scope <path>] [--format json]` (ESLint read-only verifier; layer-3 dynamic loading via `npx --package`; soft-fail when ESLint is missing — does not block the slice). See `references/quality-gate-cheatsheet.md`.
212
212
 
213
213
  ## Peaks-Loop Completion handoff
214
214
 
@@ -1,129 +0,0 @@
1
- import type { OcrLlmConfig } from '../config/config-types.js';
2
- export type OcrDetectState = 'ready' | 'package-missing' | 'binary-missing' | 'config-missing' | 'detection-failed';
3
- export interface OcrDetectResult {
4
- readonly state: OcrDetectState;
5
- readonly packageInstalled: boolean;
6
- readonly binaryPath: string | null;
7
- readonly version: string | null;
8
- /**
9
- * The peaks-loop config path that holds `peaksConfig.ocr.llm`.
10
- * The user pastes the `peaks code-review config-template` output
11
- * here. Empty string when peaks-loop has not been bootstrapped.
12
- */
13
- readonly configPath: string;
14
- readonly configValid: boolean;
15
- readonly missingKeys: readonly string[];
16
- readonly warnings: readonly string[];
17
- readonly nextActions: readonly string[];
18
- }
19
- export interface OcrReviewInput {
20
- readonly projectRoot: string;
21
- readonly from?: string;
22
- readonly to?: string;
23
- readonly commit?: string;
24
- }
25
- export interface OcrReviewResult {
26
- readonly spawned: boolean;
27
- readonly state: OcrDetectState;
28
- readonly exitCode: number | null;
29
- readonly stdout: string;
30
- readonly stderr: string;
31
- readonly durationMs: number;
32
- /** Parsed JSON envelope if the ocr subprocess emitted valid JSON. */
33
- readonly parsed: unknown;
34
- readonly warnings: readonly string[];
35
- readonly nextActions: readonly string[];
36
- }
37
- export interface SubprocessRunner {
38
- run(command: string, args: readonly string[], options: {
39
- cwd?: string;
40
- timeoutMs: number;
41
- env?: NodeJS.ProcessEnv;
42
- }): {
43
- status: number | null;
44
- stdout: string;
45
- stderr: string;
46
- error?: string;
47
- };
48
- }
49
- /**
50
- * Locate the ocr launcher script (`bin/ocr.js`) inside our own
51
- * node_modules tree. Returns null when the npm package is not
52
- * present (peaks-loop was installed but its dependency tree is
53
- * corrupt, or the user removed it).
54
- *
55
- * Walks up from this file (dist/services/code-review/) to
56
- * find the project root, then checks node_modules.
57
- */
58
- export declare function resolveOcrLauncher(searchRoots: readonly string[]): string | null;
59
- /**
60
- * Resolve search roots for the ocr launcher. We look in two
61
- * places: (1) the peaks-loop install root (next to our own dist/),
62
- * (2) the user's cwd.
63
- */
64
- export declare function defaultOcrSearchRoots(currentDirPath: string, cwd: string): readonly string[];
65
- /**
66
- * Validate the `peaksConfig.ocr.llm` block the caller (CLI / test)
67
- * read out of `~/.peaks/config.json`. Returns the list of missing
68
- * required keys (`url`, `authToken`, `model`); empty array means
69
- * the block is ready to drive the ocr subprocess.
70
- *
71
- * The block is independent of the OCR package's own
72
- * `~/.opencodereview/config.json` file. peaks-loop only ever reads
73
- * from its own config; the env-var injection in `runOcrReview`
74
- * makes the legacy file irrelevant.
75
- */
76
- export declare function getOcrLlmMissingFields(llm: OcrLlmConfig | null): readonly string[];
77
- /**
78
- * Build the env-var overlay peaks-loop injects into the ocr
79
- * subprocess. Maps `peaksConfig.ocr.llm` onto the OCR package's
80
- * env-var surface (its highest-priority config source).
81
- */
82
- export declare function buildOcrEnv(llm: OcrLlmConfig): NodeJS.ProcessEnv;
83
- /**
84
- * The JSON template the user pastes into their peaks-loop config
85
- * (`peaksConfig.ocr.llm`). Returned as a stable string so the
86
- * `peaks code-review config-template` CLI command can print it
87
- * verbatim, and so the detector's `nextActions` payload embeds
88
- * the same shape the user is told to add.
89
- */
90
- export declare function getOcrConfigTemplate(): string;
91
- export interface OcrDetectOptions {
92
- readonly cwd: string;
93
- /**
94
- * The peaks-loop config path that holds `peaksConfig.ocr.llm`.
95
- * Surfaced in the detect result so the user knows where to
96
- * paste the template.
97
- */
98
- readonly peaksConfigPath: string;
99
- /**
100
- * The parsed `peaksConfig.ocr.llm` block. `null` when the user
101
- * has not yet populated the config; the detector surfaces the
102
- * `config-missing` state with a templated `nextActions`.
103
- */
104
- readonly peaksOcrConfig: OcrLlmConfig | null;
105
- readonly searchRoots?: readonly string[];
106
- readonly runner?: SubprocessRunner;
107
- }
108
- /**
109
- * Detect the full ocr install + config state. The 5 reason states
110
- * are unchanged from the soft-optional 2.0.0 contract; only the
111
- * source of `config-missing` moved from `~/.opencodereview/config.json`
112
- * to `peaksConfig.ocr.llm`.
113
- */
114
- export declare function detectOcr(options: OcrDetectOptions): OcrDetectResult;
115
- export interface OcrReviewOptions extends OcrDetectOptions {
116
- readonly input: OcrReviewInput;
117
- }
118
- /**
119
- * Run ocr review and return the structured result. Detects state
120
- * first; soft-fails when ocr isn't ready (the caller — typically
121
- * peaks-rd — proceeds without the second-opinion review).
122
- *
123
- * The LLM endpoint config from `peaksConfig.ocr.llm` is injected
124
- * as env vars (`OCR_LLM_URL` / `OCR_LLM_TOKEN` / ...), which the
125
- * ocr package treats as the highest-priority config source. This
126
- * is how peaks-loop wires the user-managed config into the ocr
127
- * subprocess without ever writing `~/.opencodereview/config.json`.
128
- */
129
- export declare function runOcrReview(options: OcrReviewOptions): OcrReviewResult;