@boyingliu01/xp-gate 0.32.1 → 0.32.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 (69) hide show
  1. package/adapters/gate-3.sh +483 -28
  2. package/adapters/gate-4.sh +20 -0
  3. package/adapters/gate-7.sh +4 -0
  4. package/adapters/powershell.sh +33 -7
  5. package/bin/xp-gate.js +48 -2
  6. package/gate-3.sh +37 -2
  7. package/gate-4.sh +8 -0
  8. package/hooks/gate-3.sh +37 -2
  9. package/hooks/gate-4.sh +8 -0
  10. package/hooks/post-commit +82 -0
  11. package/hooks/pre-commit +19 -0
  12. package/hooks/pre-push +21 -2
  13. package/lib/__tests__/doctor-audit-ledger.test.js +61 -0
  14. package/lib/__tests__/gate-audit.test.ts +144 -0
  15. package/lib/__tests__/shared-utils.test.js +22 -0
  16. package/lib/doctor.js +59 -1
  17. package/lib/gate-audit.ts +215 -7
  18. package/lib/mattpocock-license-verdict.json +1 -1
  19. package/lib/shared-utils.js +4 -1
  20. package/mock-policy/AGENTS.md +3 -3
  21. package/mutation/AGENTS.md +3 -3
  22. package/package.json +1 -1
  23. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  24. package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
  25. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
  26. package/plugins/claude-code/skills/sprint-flow/references/phase-3-build.md +21 -0
  27. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
  28. package/plugins/dsh/README.md +51 -2
  29. package/plugins/dsh/client/client.js +760 -0
  30. package/plugins/dsh/lib/client.js +760 -0
  31. package/plugins/dsh/lib/delphi-settings.d.ts +52 -0
  32. package/plugins/dsh/lib/delphi-settings.d.ts.map +1 -0
  33. package/plugins/dsh/lib/delphi-settings.js +76 -0
  34. package/plugins/dsh/lib/hooks.d.ts +14 -1
  35. package/plugins/dsh/lib/hooks.d.ts.map +1 -1
  36. package/plugins/dsh/lib/hooks.js +44 -5
  37. package/plugins/dsh/lib/index.d.ts +63 -0
  38. package/plugins/dsh/lib/index.d.ts.map +1 -1
  39. package/plugins/dsh/lib/index.js +126 -21
  40. package/plugins/dsh/package.json +13 -3
  41. package/plugins/dsh/scripts/copy-client.cjs +37 -0
  42. package/plugins/dsh/skills/delphi-review/AGENTS.md +3 -3
  43. package/plugins/dsh/skills/sprint-flow/AGENTS.md +3 -3
  44. package/plugins/dsh/skills/sprint-flow/references/phase-3-build.md +21 -0
  45. package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +3 -3
  46. package/plugins/dsh/src/client.test.ts +231 -0
  47. package/plugins/dsh/src/contract.test.ts +25 -1
  48. package/plugins/dsh/src/delphi-settings.test.ts +101 -0
  49. package/plugins/dsh/src/delphi-settings.ts +111 -0
  50. package/plugins/dsh/src/hooks.test.ts +48 -0
  51. package/plugins/dsh/src/hooks.ts +45 -5
  52. package/plugins/dsh/src/index.test.ts +3 -2
  53. package/plugins/dsh/src/index.ts +147 -25
  54. package/plugins/opencode/package.json +1 -1
  55. package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
  56. package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
  57. package/plugins/opencode/skills/sprint-flow/references/phase-3-build.md +21 -0
  58. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
  59. package/plugins/qoder/plugin.json +1 -1
  60. package/plugins/qoder/skills/delphi-review/AGENTS.md +3 -3
  61. package/plugins/qoder/skills/sprint-flow/AGENTS.md +3 -3
  62. package/plugins/qoder/skills/sprint-flow/references/phase-3-build.md +21 -0
  63. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
  64. package/principles/AGENTS.md +3 -3
  65. package/scripts/sync-package-content.js +1 -1
  66. package/skills/delphi-review/AGENTS.md +3 -3
  67. package/skills/sprint-flow/AGENTS.md +3 -3
  68. package/skills/sprint-flow/references/phase-3-build.md +21 -0
  69. package/skills/test-specification-alignment/AGENTS.md +3 -3
@@ -11,7 +11,17 @@ import type { ShellDialect } from "./command.js"
11
11
  import { GATE_WHITELIST, buildCommand, detectDialect, resolveTarget } from "./command.js"
12
12
  import { runXpGate } from "./gate-runner.js"
13
13
  import type { ResolvedDelphiConfig } from "./delphi-config.js"
14
- import { DelphiSetupError, listCredentialReferences, loadDelphiConfig, toDelphiOptions } from "./delphi-config.js"
14
+ import {
15
+ DelphiSetupError,
16
+ expandEnvDetailed,
17
+ listCredentialReferences,
18
+ loadDelphiConfig,
19
+ toDelphiOptions,
20
+ } from "./delphi-config.js"
21
+ import type { DelphiOptions } from "./delphi.js"
22
+ import { DelphiConfigError } from "./delphi.js"
23
+ import type { DelphiSettingsLayer } from "./delphi-settings.js"
24
+ import { seatsFromSettings } from "./delphi-settings.js"
15
25
  import type { ReviewOutcome } from "./delphi-run.js"
16
26
  import { formatOutcome, runReview } from "./delphi-run.js"
17
27
  import { buildEvidence } from "./evidence.js"
@@ -200,46 +210,120 @@ interface ReviewRequest {
200
210
  readonly resolveApiKey: ApiKeyResolver
201
211
  readonly signal: AbortSignal | undefined
202
212
  readonly writeEvidence: boolean
213
+ /** Seats from the settings page; empty means "read .delphi-config.json". */
214
+ readonly settings: DelphiSettingsLayer | undefined
215
+ }
216
+
217
+ /**
218
+ * Build the review options from whichever source is configured.
219
+ *
220
+ * The settings page wins when it holds seats: it is the more recent edit, and a
221
+ * user who just saved three models expects the next run to use them. When it holds
222
+ * none, `.delphi-config.json` applies exactly as before — which is what keeps every
223
+ * existing project working without opening the page.
224
+ *
225
+ * Both paths end in the same `validateSeats`, so neither can produce a panel the
226
+ * skill would reject.
227
+ */
228
+ async function reviewOptions(
229
+ request: ReviewRequest,
230
+ resolveApiKey: ApiKeyResolver,
231
+ ): Promise<{ options: DelphiOptions; provider: string; described: string; cfg?: ResolvedDelphiConfig }> {
232
+ const fromSettings = seatsFromSettings(request.settings)
233
+ if (fromSettings) {
234
+ // The seat list is already validated; only the key still has to be resolved,
235
+ // and only the credential store (not this process's environment) knows it.
236
+ const key = await resolveExpressionKey(fromSettings.apiKeyExpression, resolveApiKey)
237
+ return {
238
+ options: {
239
+ baseUrl: fromSettings.baseUrl,
240
+ apiKey: key,
241
+ seats: fromSettings.seats,
242
+ thresholdPercent: fromSettings.thresholdPercent,
243
+ maxRounds: request.maxRounds ?? fromSettings.maxRounds,
244
+ },
245
+ provider: "settings",
246
+ described: fromSettings.seats.map((s) => s.model).join(", "),
247
+ }
248
+ }
249
+
250
+ // Resolve credentials BEFORE loading the config: the loader is synchronous and
251
+ // throws as soon as a referenced variable has no value. Reading the reference
252
+ // names first turns "the DSH process never inherited WHALECLOUD_API_KEY" from a
253
+ // hard failure into a lookup in the credential store.
254
+ const apiKeyOverrides: Record<string, string> = {}
255
+ for (const name of listCredentialReferences(request.cwd)) {
256
+ const value = await resolveApiKey(name)
257
+ if (value !== undefined && value.length > 0) apiKeyOverrides[name] = value
258
+ }
259
+ const cfg = loadDelphiConfig(request.cwd, process.env, undefined, apiKeyOverrides)
260
+ const options = toDelphiOptions(cfg)
261
+ return {
262
+ options: { ...options, maxRounds: request.maxRounds ?? cfg.maxRounds },
263
+ provider: cfg.provider,
264
+ described: cfg.seats.map((s) => s.model).join(", "),
265
+ cfg,
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Resolve a settings-supplied `api_key` expression to a usable token.
271
+ *
272
+ * Accepts the same two placeholder spellings the JSON loader accepts. A literal
273
+ * value is rejected rather than used: a bearer token typed into a settings field is
274
+ * a credential written to a profile file in plain text.
275
+ */
276
+ async function resolveExpressionKey(expression: string, resolveApiKey: ApiKeyResolver): Promise<string> {
277
+ const placeholder = findPlaceholderName(expression)
278
+ if (placeholder === undefined) {
279
+ if (expression.trim() !== "") {
280
+ throw new DelphiSetupError(
281
+ "The Delphi settings hold a literal api key. Use a credential reference instead, " +
282
+ 'e.g. "${WHALECLOUD_API_KEY}", so the token never lands in the profile file.',
283
+ )
284
+ }
285
+ throw new DelphiSetupError('The Delphi settings have no api key. Set it to "${YOUR_KEY_VAR}".')
286
+ }
287
+ const fromStore = await resolveApiKey(placeholder)
288
+ if (fromStore !== undefined && fromStore.length > 0) return fromStore
289
+ const fromEnv = expandEnvDetailed(expression, process.env)
290
+ if (fromEnv.value.trim() !== "") return fromEnv.value
291
+ throw new DelphiSetupError(
292
+ `API key variable ${placeholder} has no value. Set it, or store it in DSH's credential store.`,
293
+ )
294
+ }
295
+
296
+ /** The first `${VAR}` / `{env:VAR}` name in a config value, or undefined. */
297
+ function findPlaceholderName(value: string): string | undefined {
298
+ const shell = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/.exec(value)
299
+ if (shell) return shell[1]
300
+ const envStyle = /\{env:([A-Za-z_][A-Za-z0-9_]*)\}/.exec(value)
301
+ return envStyle ? envStyle[1] : undefined
203
302
  }
204
303
 
205
304
  async function runDelphiReview(subject: string, request: ReviewRequest): Promise<string> {
206
- const { addressed, maxRounds, cwd, resolveApiKey, signal, writeEvidence } = request
305
+ const { addressed, cwd, resolveApiKey, signal, writeEvidence } = request
207
306
  try {
208
- // Resolve credentials BEFORE loading the config: the loader is synchronous and
209
- // throws as soon as a referenced variable has no value. Reading the reference
210
- // names first turns "the DSH process never inherited WHALECLOUD_API_KEY" from a
211
- // hard failure into a lookup in the credential store.
212
- const apiKeyOverrides: Record<string, string> = {}
213
- for (const name of listCredentialReferences(cwd)) {
214
- const value = await resolveApiKey(name)
215
- if (value !== undefined && value.length > 0) apiKeyOverrides[name] = value
216
- }
217
- const cfg = loadDelphiConfig(cwd, process.env, undefined, apiKeyOverrides)
218
- const options = toDelphiOptions(cfg)
219
- const outcome = await runReview(
220
- { ...options, maxRounds: maxRounds ?? cfg.maxRounds },
221
- subject,
222
- addressed,
223
- signal,
224
- )
225
- const seats = cfg.seats.map((s) => s.model).join(", ")
226
- const suffix = writeEvidence
307
+ const { options, provider, described, cfg } = await reviewOptions(request, resolveApiKey)
308
+ const outcome = await runReview(options, subject, addressed, signal)
309
+ const suffix = writeEvidence && cfg !== undefined
227
310
  ? await writeWalkthroughEvidence(cwd, cfg, outcome)
228
311
  : ""
229
- return `${formatOutcome(outcome)}\n\nProvider: ${cfg.provider}\nSeats: ${seats}${suffix}`
312
+ return `${formatOutcome(outcome)}\n\nProvider: ${provider}\nSeats: ${described}${suffix}`
230
313
  } catch (e) {
231
314
  // Config problems are the common failure; report them as guidance
232
315
  // rather than a stack trace.
233
316
  if (e instanceof DelphiSetupError) return `Delphi review not started: ${e.message}`
317
+ if (e instanceof DelphiConfigError) return `Delphi review not started: ${e.message}`
234
318
  throw e
235
319
  }
236
320
  }
237
321
 
238
- function delphiReviewTool(resolveApiKey: ApiKeyResolver) {
322
+ function delphiReviewTool(resolveApiKey: ApiKeyResolver, settings: DelphiSettingsLayer | undefined) {
239
323
  return defineTool({
240
324
  name: "delphi-review",
241
325
  description:
242
- "Run a Delphi cross-review of a subject (a diff, a design, a spec) using three DISTINCT models from an external OpenAI-compatible provider configured in .delphi-config.json. Round 1 is anonymous and concurrent; later rounds feed back the aggregate until the approval ratio reaches the configured threshold (default 90%) or the round cap (default 5). Use this whenever a change needs independent multi-model review rather than a single model's opinion.",
326
+ "Run a Delphi cross-review of a subject (a diff, a design, a spec) using three DISTINCT models from an external OpenAI-compatible provider. The seats come from the plugin's settings page (Plugins -> xp-gate -> Configure) when it holds any, otherwise from .delphi-config.json. Round 1 is anonymous and concurrent; later rounds feed back the aggregate until the approval ratio reaches the configured threshold (default 90%) or the round cap (default 5). Use this whenever a change needs independent multi-model review rather than a single model's opinion.",
243
327
  parameters: {
244
328
  subject: {
245
329
  type: "string",
@@ -280,6 +364,7 @@ function delphiReviewTool(resolveApiKey: ApiKeyResolver) {
280
364
  resolveApiKey,
281
365
  signal: exec.signal,
282
366
  writeEvidence: args.writeEvidence ?? false,
367
+ settings,
283
368
  })
284
369
  },
285
370
  })
@@ -337,14 +422,36 @@ interface XpGatePluginConfig {
337
422
  readonly principlesCheck: "auto" | "off"
338
423
  /** Sprint write guard: auto = deny until APPROVED; off = no hook. */
339
424
  readonly delphiGuard: "auto" | "off"
425
+ /** Delphi seats edited on the Plugins page; empty means "use .delphi-config.json". */
426
+ readonly delphi: DelphiSettingsLayer | undefined
340
427
  }
341
428
 
429
+ /**
430
+ * One Delphi seat, as the settings page stores it.
431
+ *
432
+ * `model` is a free string rather than an enum: the catalog the page offers comes
433
+ * from the Host's configured providers, which this schema cannot enumerate, and a
434
+ * model id that is not in the catalog yet must still be accepted so an operator can
435
+ * pin a gateway alias. The invariants that matter are checked by
436
+ * `seatsFromSettings` on every run, not by the schema.
437
+ */
438
+ const DelphiSeatSchema = z.object({
439
+ role: z.string().default(""),
440
+ model: z.string().default("").description("Model id sent to the gateway, e.g. g-glm-5.3-flash."),
441
+ maxTokens: z.number().min(0).description("Per-seat token budget; raise it for reasoning models."),
442
+ })
443
+
342
444
  /**
343
445
  * Runtime schema for the keys above.
344
446
  *
345
447
  * Exported as a schema, not just a type: DSH validates against it and surfaces the
346
448
  * keys in the profile schema, so a user can discover and set them. A bare interface
347
449
  * is invisible to the harness.
450
+ *
451
+ * The `delphi` block is `.volatile()`: the settings page edits it live, and DSH
452
+ * refuses to write a path that is not beneath a volatile node. The two hook
453
+ * switches stay ordinary fields — they are read at mount and remounting a hook is
454
+ * what "off" is supposed to require.
348
455
  */
349
456
  export const Config = z.object({
350
457
  principlesCheck: z
@@ -359,6 +466,21 @@ export const Config = z.object({
359
466
  .description(
360
467
  "Sprint write guard: auto = deny edits until delphi-review is APPROVED; off = do not register the hook.",
361
468
  ),
469
+ delphi: z
470
+ .object({
471
+ baseUrl: z.string().default("").description("OpenAI-compatible gateway, e.g. https://host/gpt-proxy."),
472
+ apiKey: z
473
+ .string()
474
+ .default("")
475
+ .description("Credential reference such as ${WHALECLOUD_API_KEY}; never a literal key."),
476
+ seats: z.array(DelphiSeatSchema).default([]).description("The three Delphi reviewers."),
477
+ thresholdPercent: z.number().min(0).max(100).description("Approval bar; 3 seats at 90% means 3/3."),
478
+ maxRounds: z.number().min(1).max(20).description("Round cap before the review reports NO CONSENSUS."),
479
+ })
480
+ .volatile()
481
+ .description(
482
+ "Delphi seats edited on the Plugins page. Leave seats empty to use .delphi-config.json.",
483
+ ),
362
484
  })
363
485
 
364
486
  export function apply(ctx: Context, config: unknown = {}): void {
@@ -380,7 +502,7 @@ export function apply(ctx: Context, config: unknown = {}): void {
380
502
  ctx.tools.register(gateCheckTool(shell, dialect))
381
503
  ctx.tools.register(gatePrinciplesTool(shell, dialect))
382
504
  ctx.tools.register(gateArchTool(shell, dialect))
383
- ctx.tools.register(delphiReviewTool(resolveApiKey))
505
+ ctx.tools.register(delphiReviewTool(resolveApiKey, cfg.delphi))
384
506
  ctx.tools.register(sprintTool(shell, dialect))
385
507
 
386
508
  // Publishing the 12 bundled skills is what makes them visible to the model.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boyingliu01/opencode-plugin",
3
- "version": "0.32.1",
3
+ "version": "0.32.3",
4
4
  "type": "module",
5
5
  "main": "index.ts",
6
6
  "description": "XP-Gate quality gates + AI workflow skills + Sprint Flow TUI sidebar for OpenCode",
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, exactly 3 experts with distinct executable model IDs). Supports design, requirements, and code-walkthrough modes.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
@@ -236,6 +236,27 @@ Without these events, the Harness can only infer changes from file diffs and has
236
236
 
237
237
  ---
238
238
 
239
+ ## 工具调用效率自检(P2 硬性 — 2026-10-30 诊断)
240
+
241
+ > BUILD 阶段是工具调用最密集的阶段,也是"等待时间长"的主要来源。依据
242
+ > `docs/plans/2026-10-30-dev-speed-diagnosis.md`:工具延迟占总耗时 58%,其中 32.7% 的
243
+ > shell 调用是纯读取/搜索、calls/step 仅 1.03、`job_output` 阻塞 66.5 h。以下四条在 BUILD
244
+ > 期间是硬性自检项,不满足不得宣称 REQ 完成。
245
+
246
+ | ❌ 低效做法 | ✅ 正确做法 |
247
+ |------------|------------|
248
+ | `cat` / `Get-Content` / `sed -n` / `head` 读文件 | 用 `read` 原生工具(毫秒级,可并发) |
249
+ | `grep` / `rg` / `Select-String` / `findstr` 搜内容 | 用 `grep` 原生工具 |
250
+ | `find` / `ls` / `Get-ChildItem` 找文件 | 用 `glob` 原生工具 |
251
+ | 一个一个发独立调用(改完再想下一个) | 多个互不依赖的调用放进**同一步**并发发出 |
252
+ | 用 `job_output wait:true` / `sleep` 反复阻塞等长任务 | `run_in_background` + 完成通知,需要时短超时取一次 |
253
+ | 打包/发布/插件改动只靠 CI 发现契约破坏 | 先写契约测试(`plugins/dsh/src/contract.test.ts` 范式),本地先红 |
254
+
255
+ **验收目标**:纯读取 shell 占比 <5%(现 32.7%);calls/step ≥2.0(现 1.03);`job_output`
256
+ 调用数下降 ≥50%。这三项在 `xp-gate retro` 的 activity 统计里可复查。
257
+
258
+ ---
259
+
239
260
  ## Blind Review — Read-Only Subagent Convention (v0.18.0+, 证据型标准步骤)
240
261
 
241
262
  **Purpose**: Code review by an isolated subagent with read-only tool access. Replaces the former `freeze/unfreeze` mechanism.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xp-gate",
3
- "version": "0.32.1",
3
+ "version": "0.32.3",
4
4
  "displayName": "XP-Gate",
5
5
  "description": "Extreme Programming quality gates + AI workflow skills for Qoder. Includes 12 pre-commit gates (Gate 0-11), 8 pre-push gates, Sprint Flow (6 phases), and Delphi multi-expert review (>=90% consensus).",
6
6
  "author": {
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, exactly 3 experts with distinct executable model IDs). Supports design, requirements, and code-walkthrough modes.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
@@ -236,6 +236,27 @@ Without these events, the Harness can only infer changes from file diffs and has
236
236
 
237
237
  ---
238
238
 
239
+ ## 工具调用效率自检(P2 硬性 — 2026-10-30 诊断)
240
+
241
+ > BUILD 阶段是工具调用最密集的阶段,也是"等待时间长"的主要来源。依据
242
+ > `docs/plans/2026-10-30-dev-speed-diagnosis.md`:工具延迟占总耗时 58%,其中 32.7% 的
243
+ > shell 调用是纯读取/搜索、calls/step 仅 1.03、`job_output` 阻塞 66.5 h。以下四条在 BUILD
244
+ > 期间是硬性自检项,不满足不得宣称 REQ 完成。
245
+
246
+ | ❌ 低效做法 | ✅ 正确做法 |
247
+ |------------|------------|
248
+ | `cat` / `Get-Content` / `sed -n` / `head` 读文件 | 用 `read` 原生工具(毫秒级,可并发) |
249
+ | `grep` / `rg` / `Select-String` / `findstr` 搜内容 | 用 `grep` 原生工具 |
250
+ | `find` / `ls` / `Get-ChildItem` 找文件 | 用 `glob` 原生工具 |
251
+ | 一个一个发独立调用(改完再想下一个) | 多个互不依赖的调用放进**同一步**并发发出 |
252
+ | 用 `job_output wait:true` / `sleep` 反复阻塞等长任务 | `run_in_background` + 完成通知,需要时短超时取一次 |
253
+ | 打包/发布/插件改动只靠 CI 发现契约破坏 | 先写契约测试(`plugins/dsh/src/contract.test.ts` 范式),本地先红 |
254
+
255
+ **验收目标**:纯读取 shell 占比 <5%(现 32.7%);calls/step ≥2.0(现 1.03);`job_output`
256
+ 调用数下降 ≥50%。这三项在 `xp-gate retro` 的 activity 统计里可复查。
257
+
258
+ ---
259
+
239
260
  ## Blind Review — Read-Only Subagent Convention (v0.18.0+, 证据型标准步骤)
240
261
 
241
262
  **Purpose**: Code review by an isolated subagent with read-only tool access. Replaces the former `freeze/unfreeze` mechanism.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
@@ -1,9 +1,9 @@
1
1
  # PRINCIPLES CHECKER MODULE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Clean Code & SOLID principles checker — **Gate 4** of pre-commit. 14 rules × 9 language adapters, SARIF 2.1.0 output. Houses the **Boy Scout Rule** enforcement engine (Gate 6) and warning-baseline storage.
@@ -221,7 +221,7 @@ function syncHooks() {
221
221
 
222
222
  // #505: hook-module-resolution.sh is GENERATED, but it must still ship beside
223
223
  // pre-commit — the hook aborts with FATAL when it is missing, by design.
224
- const HOOK_FILES = ['pre-commit', 'pre-push', 'post-merge', 'adapter-common.sh', 'hook-module-resolution.sh'];
224
+ const HOOK_FILES = ['pre-commit', 'pre-push', 'post-commit', 'post-merge', 'adapter-common.sh', 'hook-module-resolution.sh'];
225
225
  let copied = 0;
226
226
 
227
227
  for (const name of HOOK_FILES) {
@@ -1,9 +1,9 @@
1
1
  # SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, exactly 3 experts with distinct executable model IDs). Supports design, requirements, and code-walkthrough modes.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/SPRINT-FLOW KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  **6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
@@ -236,6 +236,27 @@ Without these events, the Harness can only infer changes from file diffs and has
236
236
 
237
237
  ---
238
238
 
239
+ ## 工具调用效率自检(P2 硬性 — 2026-10-30 诊断)
240
+
241
+ > BUILD 阶段是工具调用最密集的阶段,也是"等待时间长"的主要来源。依据
242
+ > `docs/plans/2026-10-30-dev-speed-diagnosis.md`:工具延迟占总耗时 58%,其中 32.7% 的
243
+ > shell 调用是纯读取/搜索、calls/step 仅 1.03、`job_output` 阻塞 66.5 h。以下四条在 BUILD
244
+ > 期间是硬性自检项,不满足不得宣称 REQ 完成。
245
+
246
+ | ❌ 低效做法 | ✅ 正确做法 |
247
+ |------------|------------|
248
+ | `cat` / `Get-Content` / `sed -n` / `head` 读文件 | 用 `read` 原生工具(毫秒级,可并发) |
249
+ | `grep` / `rg` / `Select-String` / `findstr` 搜内容 | 用 `grep` 原生工具 |
250
+ | `find` / `ls` / `Get-ChildItem` 找文件 | 用 `glob` 原生工具 |
251
+ | 一个一个发独立调用(改完再想下一个) | 多个互不依赖的调用放进**同一步**并发发出 |
252
+ | 用 `job_output wait:true` / `sleep` 反复阻塞等长任务 | `run_in_background` + 完成通知,需要时短超时取一次 |
253
+ | 打包/发布/插件改动只靠 CI 发现契约破坏 | 先写契约测试(`plugins/dsh/src/contract.test.ts` 范式),本地先红 |
254
+
255
+ **验收目标**:纯读取 shell 占比 <5%(现 32.7%);calls/step ≥2.0(现 1.03);`job_output`
256
+ 调用数下降 ≥50%。这三项在 `xp-gate retro` 的 activity 统计里可复查。
257
+
258
+ ---
259
+
239
260
  ## Blind Review — Read-Only Subagent Convention (v0.18.0+, 证据型标准步骤)
240
261
 
241
262
  **Purpose**: Code review by an isolated subagent with read-only tool access. Replaces the former `freeze/unfreeze` mechanism.
@@ -1,9 +1,9 @@
1
1
  # SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
2
2
 
3
- **Generated:** 2026-10-29
4
- **Commit:** 101a0ff3
3
+ **Generated:** 2026-10-30
4
+ **Commit:** e5ca7d9d
5
5
  **Branch:** main
6
- **Version:** 0.32.1.0
6
+ **Version:** 0.32.3.0
7
7
 
8
8
  ## OVERVIEW
9
9
  Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.