maskweaver 0.8.3 → 0.8.4

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/README.ko.md CHANGED
@@ -24,9 +24,10 @@
24
24
  - **전문가 페르소나 (Masks)**: 전설적인 개발자들의 철학을 담은 표준 YAML 프로필.
25
25
  - **스마트 위임**: OpenCode에 최적화된 멀티 에이전트 워크플로우.
26
26
  - **프로젝트 메모리**: 코드베이스 전체에 대한 하이브리드 의미론적 검색.
27
- - **🆕 Weave 워크플로우**: AI 자체 검증이 포함된 Phase 기반 개발.
28
-
29
- ---
27
+ - **🆕 Weave 워크플로우**: AI 자체 검증이 포함된 Phase 기반 개발.
28
+ - **🔗 GDC 통합**: Graph-Driven Codebase 지원으로 리서치 품질 향상 및 설계 시점 검증 게이트 추가.
29
+
30
+ ---
30
31
 
31
32
  ## 왜 Maskweaver인가요?
32
33
 
@@ -227,9 +228,43 @@ Weave는 Maskweaver의 핵심 워크플로우입니다. 작업을 테스트 가
227
228
  | 5️⃣ E2E Tests | 테스트 | **Playwright** |
228
229
  | 6️⃣ Screenshot | 시각 | Playwright / 브라우저 캡처 |
229
230
  | 7️⃣ API Check | API | `fetch` 헬스 체크 |
230
- | 8️⃣ A11y | 접근성 | `axe-core` |
231
-
232
- #### 마스크 자동 선택
231
+ | 8️⃣ A11y | 접근성 | `axe-core` |
232
+ | 0️⃣ GDC Check | 설계 | `gdc check --machine` |
233
+
234
+ #### GDC 통합 (Graph-Driven Codebase)
235
+
236
+ Weave는 [GDC](https://github.com/ulgerang/gdc)(Graph-Driven Codebase)와 통합되어 리서치 품질을 향상시키고 설계 시점 검증 게이트를 추가합니다:
237
+
238
+ **리서치 강화:**
239
+ - `.gdc` 워크스페이스 자동 감지
240
+ - GDC `stats`, `graph`, `check` 결과를 `tasks/research.md`에 포함
241
+ - 그래프 엣지 기반 의존성 영향 범위(Blast Radius) 분석
242
+ - 기능 키워드와 매칭된 재사용 후보 노드
243
+ - 새 보고서 섹션: `GDC Node Coverage`, `Dependency Blast Radius`, `Existing Spec vs Implementation Drift`, `Candidate Reuse Nodes`
244
+
245
+ **Pre-Verify 게이트:**
246
+ GDC가 감지되면 `weave verify`와 `weave flow`가 자동으로 실행:
247
+ 1. `gdc sync --machine` - 스펙과 구현 동기화
248
+ 2. `gdc check --machine` - 스펙/구현 일치성 검증
249
+
250
+ GDC check의 블로킹 에러는 검증을 중단시킵니다(`strictVerify` 모드로 설정 가능).
251
+
252
+ **설정** (`maskweaver.config.json`):
253
+ ```json
254
+ {
255
+ "gdc": {
256
+ "enabled": "auto",
257
+ "strictVerify": false,
258
+ "autoSyncOnPrepare": true
259
+ }
260
+ }
261
+ ```
262
+
263
+ - `enabled`: `true` | `false` | `"auto"` (기본값: `.gdc` 디렉터리 자동 감지)
264
+ - `strictVerify`: `true`면 GDC check 실패 시 검증 차단; `false`면 경고 후 계속 진행
265
+ - `autoSyncOnPrepare`: `weave prepare` 시 `gdc sync` 실행
266
+
267
+ #### 마스크 자동 선택
233
268
 
234
269
  AI가 각 작업에 가장 적합한 전문가를 자동으로 선택합니다:
235
270
 
@@ -333,14 +368,15 @@ import { MaskLoader } from 'maskweaver/core';
333
368
  import { WeaveOrchestrator, GlobalKnowledge } from 'maskweaver/weave';
334
369
  ```
335
370
 
336
- **모듈:**
337
- - `maskweaver/core` - 가면 로딩, 검증 (YAML/JSON)
338
- - `maskweaver/memory` - 임베딩 + 벡터 검색 (5개 프로바이더)
339
- - `maskweaver/context` - 기능 기반 작업 추적
340
- - `maskweaver/verify` - 교차 가면 코드 리뷰
341
- - `maskweaver/retrospect` - 세션 효과 분석
342
- - `maskweaver/weave` - Phase 기반 개발 워크플로우
343
- - `maskweaver/plugin` - OpenCode 플러그인 엔트리 포인트
371
+ **모듈:**
372
+ - `maskweaver/core` - 가면 로딩, 검증 (YAML/JSON)
373
+ - `maskweaver/memory` - 임베딩 + 벡터 검색 (5개 프로바이더)
374
+ - `maskweaver/context` - 기능 기반 작업 추적
375
+ - `maskweaver/verify` - 교차 가면 코드 리뷰
376
+ - `maskweaver/retrospect` - 세션 효과 분석
377
+ - `maskweaver/weave` - Phase 기반 개발 워크플로우
378
+ - `maskweaver/gdc` - GDC(Graph-Driven Codebase) 통합 유틸리티
379
+ - `maskweaver/plugin` - OpenCode 플러그인 엔트리 포인트
344
380
 
345
381
  ---
346
382
 
package/README.md CHANGED
@@ -24,9 +24,10 @@ While it can be used as a standalone library, it works great with OpenCode to ad
24
24
  - **Expert Personas (Masks)**: Standardized YAML profiles for legendary developers.
25
25
  - **Smart Delegation**: Multi-agent workflows optimized for OpenCode.
26
26
  - **Project Memory**: Hybrid semantic search for your entire codebase.
27
- - **🆕 Weave Workflow**: Phase-driven development with AI self-verification.
28
-
29
- ---
27
+ - **🆕 Weave Workflow**: Phase-driven development with AI self-verification.
28
+ - **🔗 GDC Integration**: Graph-Driven Codebase support for enhanced research and design-time verification gates.
29
+
30
+ ---
30
31
 
31
32
  ## Why Maskweaver?
32
33
 
@@ -246,9 +247,43 @@ Before handing off to you, AI runs these verification layers:
246
247
  | 5️⃣ E2E Tests | Test | **Playwright** |
247
248
  | 6️⃣ Screenshot | Visual | Playwright / browser capture |
248
249
  | 7️⃣ API Check | API | `fetch` health checks |
249
- | 8️⃣ A11y | Accessibility | `axe-core` |
250
-
251
- #### Autonomous Mask Selection
250
+ | 8️⃣ A11y | Accessibility | `axe-core` |
251
+ | 0️⃣ GDC Check | Design | `gdc check --machine` |
252
+
253
+ #### GDC Integration (Graph-Driven Codebase)
254
+
255
+ Weave integrates with [GDC](https://github.com/ulgerang/gdc) (Graph-Driven Codebase) to enhance research quality and add design-time verification gates:
256
+
257
+ **Research Enhancement:**
258
+ - Automatic `.gdc` workspace detection
259
+ - GDC `stats`, `graph`, and `check` results embedded in `tasks/research.md`
260
+ - Dependency blast radius analysis from graph edges
261
+ - Candidate reuse nodes matched against feature keywords
262
+ - New report sections: `GDC Node Coverage`, `Dependency Blast Radius`, `Existing Spec vs Implementation Drift`, `Candidate Reuse Nodes`
263
+
264
+ **Pre-Verify Gate:**
265
+ When GDC is detected, `weave verify` and `weave flow` automatically run:
266
+ 1. `gdc sync --machine` - Sync specs with implementation
267
+ 2. `gdc check --machine` - Validate spec/implementation alignment
268
+
269
+ Blocking errors from GDC check will halt verification (configurable via `strictVerify` mode).
270
+
271
+ **Configuration** (`maskweaver.config.json`):
272
+ ```json
273
+ {
274
+ "gdc": {
275
+ "enabled": "auto",
276
+ "strictVerify": false,
277
+ "autoSyncOnPrepare": true
278
+ }
279
+ }
280
+ ```
281
+
282
+ - `enabled`: `true` | `false` | `"auto"` (default: auto-detect from `.gdc` directory)
283
+ - `strictVerify`: If `true`, GDC check failures block verification; if `false`, continues with warning
284
+ - `autoSyncOnPrepare`: Run `gdc sync` during `weave prepare`
285
+
286
+ #### Autonomous Mask Selection
252
287
 
253
288
  The AI automatically picks the best expert for each task:
254
289
 
@@ -352,14 +387,15 @@ import { MaskLoader } from 'maskweaver/core';
352
387
  import { WeaveOrchestrator, GlobalKnowledge } from 'maskweaver/weave';
353
388
  ```
354
389
 
355
- **Modules:**
356
- - `maskweaver/core` - Mask loading, validation (YAML/JSON)
357
- - `maskweaver/memory` - Embeddings + vector search (5 providers)
358
- - `maskweaver/context` - Feature-based work tracking
359
- - `maskweaver/verify` - Cross-mask code review
360
- - `maskweaver/retrospect` - Session effectiveness analysis
361
- - `maskweaver/weave` - Phase-driven development workflow
362
- - `maskweaver/plugin` - OpenCode plugin entry point
390
+ **Modules:**
391
+ - `maskweaver/core` - Mask loading, validation (YAML/JSON)
392
+ - `maskweaver/memory` - Embeddings + vector search (5 providers)
393
+ - `maskweaver/context` - Feature-based work tracking
394
+ - `maskweaver/verify` - Cross-mask code review
395
+ - `maskweaver/retrospect` - Session effectiveness analysis
396
+ - `maskweaver/weave` - Phase-driven development workflow
397
+ - `maskweaver/gdc` - GDC (Graph-Driven Codebase) integration utilities
398
+ - `maskweaver/plugin` - OpenCode plugin entry point
363
399
 
364
400
  ---
365
401
 
@@ -1 +1 @@
1
- {"version":3,"file":"weave.d.ts","sourceRoot":"","sources":["../../../src/plugin/tools/weave.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2BxB,wBAAgB,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAsFb;QACF,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;QAC3L,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,cAAc,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;QACjE,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;QAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACxB,WACQ;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAC9B,OAAO,CAAC,MAAM,CAAC;EA4DzB"}
1
+ {"version":3,"file":"weave.d.ts","sourceRoot":"","sources":["../../../src/plugin/tools/weave.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgCxB,wBAAgB,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAsFb;QACF,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;QAC3L,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,cAAc,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;QACjE,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;QAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACxB,WACQ;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAC9B,OAAO,CAAC,MAAM,CAAC;EA4DzB"}
@@ -23,6 +23,7 @@ import { createWeaveWorktree, listWeaveWorktrees, resolveWeaveWorktree, removeWe
23
23
  import { ensureGitRepo, stageAllChanges, listStagedFiles, hasStagedChanges, commitStagedChanges } from '../../weave/git.js';
24
24
  import { scanFilesForSecrets, loadSecretScanConfig, shouldBlockOnFindings, formatSecretScanReport } from '../../weave/security/secret-scan.js';
25
25
  import { searchTroubleshooting, recordTroubleshooting, GlobalKnowledge } from '../../weave/knowledge/global.js';
26
+ import { getEffectiveGdcConfig, runGdcMachineCommand, countGdcCheckIssues, } from '../../weave/gdc.js';
26
27
  // ============================================================================
27
28
  // Tool Factory
28
29
  // ============================================================================
@@ -292,6 +293,174 @@ function formatRefinePlanResult(title, outcome) {
292
293
  }
293
294
  return lines.join('\n');
294
295
  }
296
+ function pickLogTail(text, maxLength = 180) {
297
+ if (!text)
298
+ return '';
299
+ const lines = text.split(/\r?\n/).map(line => line.trim()).filter(Boolean);
300
+ if (lines.length === 0)
301
+ return '';
302
+ return sanitizeLessonText(lines[lines.length - 1], maxLength);
303
+ }
304
+ function formatGdcCommandLine(label, result) {
305
+ const parts = [];
306
+ parts.push(result.exitCode === 0 ? 'PASS' : `FAIL(exit=${result.exitCode})`);
307
+ if (result.timedOut)
308
+ parts.push('timeout');
309
+ if (result.transportError)
310
+ parts.push(sanitizeLessonText(result.transportError, 140));
311
+ if (result.parseError)
312
+ parts.push(`parse=${sanitizeLessonText(result.parseError, 120)}`);
313
+ const detail = pickLogTail(result.stderr || result.stdout);
314
+ if (detail)
315
+ parts.push(`detail=${detail}`);
316
+ return `- ${label}: ${parts.join(' | ')}`;
317
+ }
318
+ async function runGdcVerifyGate(basePath) {
319
+ const gdc = getEffectiveGdcConfig(basePath);
320
+ if (!gdc.enabled) {
321
+ return {
322
+ applied: false,
323
+ passed: true,
324
+ report: '',
325
+ };
326
+ }
327
+ const lines = [];
328
+ lines.push('### GDC Pre-Verify Gate');
329
+ lines.push('');
330
+ lines.push(`- mode: ${gdc.strictVerify ? 'strict' : 'lenient'}`);
331
+ lines.push(`- binary: \`${gdc.binPath}\``);
332
+ const syncResult = await runGdcMachineCommand({
333
+ basePath,
334
+ command: 'sync',
335
+ config: gdc,
336
+ });
337
+ lines.push(formatGdcCommandLine('sync', syncResult));
338
+ const syncInfraFailure = Boolean(syncResult.transportError)
339
+ || (syncResult.exitCode !== 0 && syncResult.exitCode !== 2);
340
+ const syncMachineParseFailure = Boolean(syncResult.parseError && syncResult.exitCode === 0);
341
+ if (syncInfraFailure || syncMachineParseFailure) {
342
+ if (gdc.strictVerify) {
343
+ lines.push('');
344
+ lines.push('❌ Strict mode blocks verification when GDC sync cannot be trusted.');
345
+ return {
346
+ applied: true,
347
+ passed: false,
348
+ failedAt: 'GDC Sync',
349
+ report: lines.join('\n'),
350
+ };
351
+ }
352
+ lines.push('');
353
+ lines.push('⚠️ Proceeding without strict GDC sync gate (lenient mode).');
354
+ return {
355
+ applied: true,
356
+ passed: true,
357
+ report: lines.join('\n'),
358
+ };
359
+ }
360
+ const checkResult = await runGdcMachineCommand({
361
+ basePath,
362
+ command: 'check',
363
+ config: gdc,
364
+ });
365
+ lines.push(formatGdcCommandLine('check', checkResult));
366
+ if (checkResult.exitCode === 2) {
367
+ lines.push('');
368
+ lines.push('❌ Blocking GDC check issues detected (exit code 2).');
369
+ return {
370
+ applied: true,
371
+ passed: false,
372
+ failedAt: 'GDC Check',
373
+ report: lines.join('\n'),
374
+ };
375
+ }
376
+ const checkInfraFailure = Boolean(checkResult.transportError)
377
+ || (checkResult.exitCode !== 0 && checkResult.exitCode !== 2);
378
+ if (checkInfraFailure) {
379
+ if (gdc.strictVerify) {
380
+ lines.push('');
381
+ lines.push('❌ Strict mode blocks verification when GDC check fails to run.');
382
+ return {
383
+ applied: true,
384
+ passed: false,
385
+ failedAt: 'GDC Check',
386
+ report: lines.join('\n'),
387
+ };
388
+ }
389
+ lines.push('');
390
+ lines.push('⚠️ GDC check execution failed, but lenient mode allows verification to continue.');
391
+ return {
392
+ applied: true,
393
+ passed: true,
394
+ report: lines.join('\n'),
395
+ };
396
+ }
397
+ const counts = countGdcCheckIssues(checkResult.data);
398
+ lines.push(`- check summary: errors=${counts.errors}, warnings=${counts.warnings}, info=${counts.infos}, issues=${counts.issueCount}`);
399
+ if (counts.errors > 0) {
400
+ lines.push('');
401
+ lines.push('❌ Blocking GDC check errors found. Resolve them before build/test verification.');
402
+ return {
403
+ applied: true,
404
+ passed: false,
405
+ failedAt: 'GDC Check',
406
+ report: lines.join('\n'),
407
+ };
408
+ }
409
+ if (checkResult.parseError) {
410
+ if (gdc.strictVerify) {
411
+ lines.push('');
412
+ lines.push('❌ Strict mode requires parseable GDC machine output.');
413
+ return {
414
+ applied: true,
415
+ passed: false,
416
+ failedAt: 'GDC Check Parse',
417
+ report: lines.join('\n'),
418
+ };
419
+ }
420
+ lines.push('');
421
+ lines.push('⚠️ GDC check output could not be parsed; continuing in lenient mode.');
422
+ }
423
+ lines.push('');
424
+ lines.push('✅ GDC gate passed.');
425
+ return {
426
+ applied: true,
427
+ passed: true,
428
+ report: lines.join('\n'),
429
+ };
430
+ }
431
+ async function runGdcPrepareSync(basePath) {
432
+ const gdc = getEffectiveGdcConfig(basePath);
433
+ if (!gdc.enabled || !gdc.autoSyncOnPrepare) {
434
+ return {
435
+ applied: false,
436
+ report: '',
437
+ };
438
+ }
439
+ const lines = [];
440
+ lines.push('### GDC Prepare Sync');
441
+ lines.push('');
442
+ lines.push(`- binary: \`${gdc.binPath}\``);
443
+ const syncResult = await runGdcMachineCommand({
444
+ basePath,
445
+ command: 'sync',
446
+ config: gdc,
447
+ });
448
+ lines.push(formatGdcCommandLine('sync', syncResult));
449
+ const syncInfraFailure = Boolean(syncResult.transportError)
450
+ || (syncResult.exitCode !== 0 && syncResult.exitCode !== 2);
451
+ const syncMachineParseFailure = Boolean(syncResult.parseError && syncResult.exitCode === 0);
452
+ lines.push('');
453
+ if (syncInfraFailure || syncMachineParseFailure) {
454
+ lines.push('⚠️ GDC sync failed during prepare; continuing without blocking.');
455
+ }
456
+ else {
457
+ lines.push('✅ GDC sync completed before research/plan generation.');
458
+ }
459
+ return {
460
+ applied: true,
461
+ report: lines.join('\n'),
462
+ };
463
+ }
295
464
  async function handleResearch(args, basePath) {
296
465
  const { docsPath, projectName } = args;
297
466
  if (!docsPath) {
@@ -521,6 +690,7 @@ async function handlePrepare(args, basePath) {
521
690
  }
522
691
  const resolvedDocsPath = resolveUnderBase(basePath, docsPath);
523
692
  const intakeResult = await intake({ docsPath: resolvedDocsPath });
693
+ const gdcPrepareSync = await runGdcPrepareSync(basePath);
524
694
  const researchResult = await writeResearchReport({
525
695
  docsPath: resolvedDocsPath,
526
696
  intake: intakeResult,
@@ -552,6 +722,10 @@ async function handlePrepare(args, basePath) {
552
722
  });
553
723
  const lines = [];
554
724
  lines.push('## ✅ Weave Prepare 완료\n');
725
+ if (gdcPrepareSync.applied && gdcPrepareSync.report) {
726
+ lines.push(gdcPrepareSync.report);
727
+ lines.push('');
728
+ }
555
729
  lines.push(researchResult.summary);
556
730
  lines.push('');
557
731
  lines.push(specResult.summary);
@@ -683,6 +857,24 @@ async function handleFlow(args, basePath) {
683
857
  lines.push('');
684
858
  lines.push('### 3) Verify');
685
859
  lines.push('');
860
+ const reviewLines = [
861
+ `Flow executed for ${resolvedPhaseId}.`,
862
+ `Plan gate: ${planGate.passed ? 'PASS' : 'BYPASS'} (${planGate.nonTrivial ? 'non-trivial' : 'simple'} scope).`,
863
+ ];
864
+ const gdcGate = await runGdcVerifyGate(basePath);
865
+ if (gdcGate.applied && gdcGate.report) {
866
+ lines.push(gdcGate.report);
867
+ lines.push('');
868
+ }
869
+ if (!gdcGate.passed) {
870
+ lines.push(`❌ Verification failed at: ${gdcGate.failedAt || 'GDC Gate'}`);
871
+ reviewLines.push(`Flow stopped at GDC gate for ${resolvedPhaseId}: ${gdcGate.failedAt || 'GDC Gate'}.`);
872
+ await syncWorkflowArtifacts(basePath, manager, {
873
+ phaseId: resolvedPhaseId,
874
+ reviewLines,
875
+ });
876
+ return lines.join('\n');
877
+ }
686
878
  const verification = await runAIVerification({
687
879
  projectType: args.projectType || 'unknown',
688
880
  projectPath: basePath,
@@ -692,12 +884,11 @@ async function handleFlow(args, basePath) {
692
884
  });
693
885
  const verificationReport = generateVerificationReport(verification.results);
694
886
  lines.push(verificationReport);
695
- const reviewLines = [
696
- `Flow executed for ${resolvedPhaseId}.`,
697
- `Plan gate: ${planGate.passed ? 'PASS' : 'BYPASS'} (${planGate.nonTrivial ? 'non-trivial' : 'simple'} scope).`,
698
- ];
699
887
  reviewLines.push(`Craft prepared execution context for ${resolvedPhaseId}.`);
700
888
  reviewLines.push('Phase implementation/verification proceeds outside the legacy auto loop.');
889
+ if (gdcGate.applied) {
890
+ reviewLines.push(`GDC pre-verify gate passed for ${resolvedPhaseId}.`);
891
+ }
701
892
  if (!verification.passed) {
702
893
  lines.push('');
703
894
  lines.push(`❌ Verification failed at: ${verification.failedAt || 'unknown'}`);
@@ -970,6 +1161,15 @@ async function handleWorktree(args, basePath) {
970
1161
  async function handleVerify(args, basePath) {
971
1162
  const projectType = args.projectType || 'unknown';
972
1163
  const mode = args.verifyMode || 'full';
1164
+ const gdcGate = await runGdcVerifyGate(basePath);
1165
+ const sections = [];
1166
+ if (gdcGate.applied && gdcGate.report) {
1167
+ sections.push(gdcGate.report);
1168
+ }
1169
+ if (!gdcGate.passed) {
1170
+ sections.push(`❌ Verification failed at: ${gdcGate.failedAt || 'GDC Gate'}`);
1171
+ return sections.join('\n\n');
1172
+ }
973
1173
  const verification = await runAIVerification({
974
1174
  projectType,
975
1175
  projectPath: basePath,
@@ -978,26 +1178,27 @@ async function handleVerify(args, basePath) {
978
1178
  mode,
979
1179
  });
980
1180
  const report = generateVerificationReport(verification.results);
1181
+ sections.push(report);
981
1182
  if (verification.results.length === 0) {
982
- return [
983
- report,
1183
+ sections.push([
984
1184
  '',
985
1185
  '> No verification commands detected for this project.',
986
1186
  '> Provide scripts/tools (package.json, go.mod, Cargo.toml, pyproject.toml, *.sln) or pass projectType hint.',
987
- ].join('\n');
1187
+ ].join('\n'));
1188
+ return sections.join('\n\n');
988
1189
  }
989
1190
  if (!verification.passed) {
990
- return [
991
- report,
1191
+ sections.push([
992
1192
  '',
993
1193
  `❌ Verification failed at: ${verification.failedAt || 'unknown'}`,
994
- ].join('\n');
1194
+ ].join('\n'));
1195
+ return sections.join('\n\n');
995
1196
  }
996
- return [
997
- report,
1197
+ sections.push([
998
1198
  '',
999
1199
  '✅ Verification passed.',
1000
- ].join('\n');
1200
+ ].join('\n'));
1201
+ return sections.join('\n\n');
1001
1202
  }
1002
1203
  async function handleTroubleshoot(args) {
1003
1204
  const { error, projectType } = args;
@@ -1086,6 +1287,24 @@ async function handleApprove(args, basePath) {
1086
1287
  return message;
1087
1288
  };
1088
1289
  if (!skipVerify) {
1290
+ const reportSections = [];
1291
+ const gdcGate = await runGdcVerifyGate(basePath);
1292
+ if (gdcGate.applied && gdcGate.report) {
1293
+ reportSections.push(gdcGate.report);
1294
+ }
1295
+ if (!gdcGate.passed) {
1296
+ return finalizeApprove([
1297
+ ...reportSections,
1298
+ `❌ Verification failed at: ${gdcGate.failedAt || 'GDC Gate'}`,
1299
+ '',
1300
+ invokedByCraft
1301
+ ? 'Fix the failures and rerun `weave craft`.'
1302
+ : 'Fix the failures and re-run `weave craft`.',
1303
+ 'You can also run: `weave command=verify`',
1304
+ ].filter(Boolean).join('\n\n'), [
1305
+ `Finalization blocked at GDC gate for ${resolvedPhaseId}: ${gdcGate.failedAt || 'GDC Gate'}.`,
1306
+ ]);
1307
+ }
1089
1308
  const verification = await runAIVerification({
1090
1309
  projectType: projectType || 'unknown',
1091
1310
  projectPath: basePath,
@@ -1093,7 +1312,8 @@ async function handleApprove(args, basePath) {
1093
1312
  enableScreenshots: false,
1094
1313
  mode: verifyMode || 'full',
1095
1314
  });
1096
- const report = generateVerificationReport(verification.results);
1315
+ reportSections.push(generateVerificationReport(verification.results));
1316
+ const report = reportSections.join('\n\n');
1097
1317
  if (!verification.passed) {
1098
1318
  return finalizeApprove([
1099
1319
  report,