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.
- package/CHANGELOG.md +62 -0
- package/config/eslint/.peaks-rules.cjs +8 -1
- package/dist/cli/commands/_register.js +2 -1
- package/dist/cli/commands/code-review-commands.d.ts +2 -30
- package/dist/cli/commands/code-review-commands.js +43 -65
- package/dist/cli/commands/lint-commands.d.ts +21 -0
- package/dist/cli/commands/lint-commands.js +146 -0
- package/dist/cli/commands/outer-cache-commands.js +13 -6
- package/dist/cli/commands/security-audit-commands.d.ts +1 -1
- package/dist/cli/commands/security-audit-commands.js +1 -1
- package/dist/services/code-review/ecc-bridge.d.ts +2 -7
- package/dist/services/config/config-service.d.ts +2 -19
- package/dist/services/config/config-service.js +0 -52
- package/dist/services/config/config-types.d.ts +4 -24
- package/dist/services/config/config-types.js +1 -10
- package/dist/services/lint/detect-eslint.d.ts +10 -0
- package/dist/services/lint/detect-eslint.js +59 -0
- package/dist/services/lint/detect-ocr-18.d.ts +10 -0
- package/dist/services/lint/detect-ocr-18.js +40 -0
- package/dist/services/lint/eslint-runner.d.ts +58 -0
- package/dist/services/lint/eslint-runner.js +307 -0
- package/dist/services/lint/ocr-multilang-adapter.d.ts +34 -0
- package/dist/services/lint/ocr-multilang-adapter.js +143 -0
- package/dist/services/session/binding-store.d.ts +6 -6
- package/dist/services/session/caller-binding-service.d.ts +7 -0
- package/dist/services/session/caller-binding-service.js +11 -7
- package/dist/services/session/session-binding-bridge.d.ts +17 -1
- package/dist/services/session/session-binding-bridge.js +185 -29
- package/dist/services/session/session-manager.js +37 -0
- package/dist/services/skills/skill-presence-service.js +13 -1
- package/package.json +5 -12
- package/skills/bee/peaks-rd/SKILL.md +1 -1
- package/skills/bee/peaks-rd/references/jsts-eslint-gate.md +197 -0
- package/skills/bee/peaks-rd/references/ocr-multilang-1.8.md +132 -0
- package/skills/bee/peaks-rd/references/parallel-review-fanout.md +1 -1
- package/skills/peaks-code/SKILL.md +1 -1
- package/dist/services/code-review/ocr-service.d.ts +0 -129
- package/dist/services/code-review/ocr-service.js +0 -372
- 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.
|
|
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-
|
|
104
|
-
"peaks-loop-shared-channel": "0.0.
|
|
105
|
-
"peaks-loop-
|
|
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
|
|
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;
|