dodo-mcp 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +45 -6
  2. package/dist/cli/dataRecovery.js +38 -0
  3. package/dist/cli/dataRecovery.js.map +1 -0
  4. package/dist/cli/deployment.js +61 -0
  5. package/dist/cli/deployment.js.map +1 -0
  6. package/dist/cli/main.js +35 -1
  7. package/dist/cli/main.js.map +1 -1
  8. package/dist/config/globalConfig.js +8 -0
  9. package/dist/config/globalConfig.js.map +1 -1
  10. package/dist/errors.js +1 -1
  11. package/dist/errors.js.map +1 -1
  12. package/dist/ipc/server.js +2 -0
  13. package/dist/ipc/server.js.map +1 -1
  14. package/dist/ipc/timeouts.js +5 -0
  15. package/dist/ipc/timeouts.js.map +1 -0
  16. package/dist/platform/privateFs.js +32 -3
  17. package/dist/platform/privateFs.js.map +1 -1
  18. package/dist/platform/windowsPrivateAcl.js +90 -0
  19. package/dist/platform/windowsPrivateAcl.js.map +1 -0
  20. package/dist/security/outboundAddress.js +20 -0
  21. package/dist/security/outboundAddress.js.map +1 -0
  22. package/dist/server/aiAdmin.js +35 -10
  23. package/dist/server/aiAdmin.js.map +1 -1
  24. package/dist/server/appServer.js +11 -3
  25. package/dist/server/appServer.js.map +1 -1
  26. package/dist/server/bootstrap.js +14 -0
  27. package/dist/server/bootstrap.js.map +1 -1
  28. package/dist/server/configUi/index.html +3 -0
  29. package/dist/server/configUi/ui/dataRecovery.js +90 -0
  30. package/dist/server/configUi/ui/deployment.js +111 -0
  31. package/dist/server/configUi/ui/recovery.js +167 -0
  32. package/dist/server/configUi/workbench.css +28 -1
  33. package/dist/server/configUi/workbench.js +136 -25
  34. package/dist/server/installationRuntime.js +3 -1
  35. package/dist/server/installationRuntime.js.map +1 -1
  36. package/dist/server/instructions.js +6 -2
  37. package/dist/server/instructions.js.map +1 -1
  38. package/dist/server/ipcDispatch.js +219 -0
  39. package/dist/server/ipcDispatch.js.map +1 -1
  40. package/dist/server/localConfig.js +1 -1
  41. package/dist/server/localConfig.js.map +1 -1
  42. package/dist/server/stdioServer.js +11 -3
  43. package/dist/server/stdioServer.js.map +1 -1
  44. package/dist/services/ai/network.js +1 -18
  45. package/dist/services/ai/network.js.map +1 -1
  46. package/dist/services/ai/subagents.js +5 -2
  47. package/dist/services/ai/subagents.js.map +1 -1
  48. package/dist/services/assistance/verification.js +43 -10
  49. package/dist/services/assistance/verification.js.map +1 -1
  50. package/dist/services/changes/applier.js +472 -297
  51. package/dist/services/changes/applier.js.map +1 -1
  52. package/dist/services/git/gitService.js +150 -34
  53. package/dist/services/git/gitService.js.map +1 -1
  54. package/dist/services/jobs/jobManager.js +59 -2
  55. package/dist/services/jobs/jobManager.js.map +1 -1
  56. package/dist/services/jobs/spool.js +9 -3
  57. package/dist/services/jobs/spool.js.map +1 -1
  58. package/dist/services/multimodal/mediaService.js +6 -6
  59. package/dist/services/multimodal/mediaService.js.map +1 -1
  60. package/dist/services/recovery/configKeys.js +115 -0
  61. package/dist/services/recovery/configKeys.js.map +1 -0
  62. package/dist/services/recovery/configVault.js +361 -0
  63. package/dist/services/recovery/configVault.js.map +1 -0
  64. package/dist/services/recovery/contracts.js +24 -0
  65. package/dist/services/recovery/contracts.js.map +1 -0
  66. package/dist/services/recovery/databaseAwareness.js +179 -0
  67. package/dist/services/recovery/databaseAwareness.js.map +1 -0
  68. package/dist/services/recovery/deploymentArchive.js +129 -0
  69. package/dist/services/recovery/deploymentArchive.js.map +1 -0
  70. package/dist/services/recovery/deploymentContracts.js +70 -0
  71. package/dist/services/recovery/deploymentContracts.js.map +1 -0
  72. package/dist/services/recovery/deploymentHealth.js +143 -0
  73. package/dist/services/recovery/deploymentHealth.js.map +1 -0
  74. package/dist/services/recovery/deploymentMaintenance.js +197 -0
  75. package/dist/services/recovery/deploymentMaintenance.js.map +1 -0
  76. package/dist/services/recovery/deploymentService.js +429 -0
  77. package/dist/services/recovery/deploymentService.js.map +1 -0
  78. package/dist/services/recovery/deploymentSource.js +36 -0
  79. package/dist/services/recovery/deploymentSource.js.map +1 -0
  80. package/dist/services/recovery/dockerDeployment.js +172 -0
  81. package/dist/services/recovery/dockerDeployment.js.map +1 -0
  82. package/dist/services/recovery/drift.js +178 -0
  83. package/dist/services/recovery/drift.js.map +1 -0
  84. package/dist/services/recovery/evidence.js +127 -0
  85. package/dist/services/recovery/evidence.js.map +1 -0
  86. package/dist/services/recovery/gitCopies.js +219 -0
  87. package/dist/services/recovery/gitCopies.js.map +1 -0
  88. package/dist/services/recovery/history.js +423 -0
  89. package/dist/services/recovery/history.js.map +1 -0
  90. package/dist/services/recovery/recoveryService.js +521 -0
  91. package/dist/services/recovery/recoveryService.js.map +1 -0
  92. package/dist/services/recovery/storage.js +344 -0
  93. package/dist/services/recovery/storage.js.map +1 -0
  94. package/dist/services/schedules/scheduleService.js +9 -10
  95. package/dist/services/schedules/scheduleService.js.map +1 -1
  96. package/dist/store/db.js +71 -0
  97. package/dist/store/db.js.map +1 -1
  98. package/dist/tools/catalog.js +4 -0
  99. package/dist/tools/catalog.js.map +1 -1
  100. package/dist/tools/changeTools.js +1 -1
  101. package/dist/tools/changeTools.js.map +1 -1
  102. package/dist/tools/context.js +23 -3
  103. package/dist/tools/context.js.map +1 -1
  104. package/dist/tools/deploymentTools.js +58 -0
  105. package/dist/tools/deploymentTools.js.map +1 -0
  106. package/dist/tools/directTools.js +9 -5
  107. package/dist/tools/directTools.js.map +1 -1
  108. package/dist/tools/gitTools.js +7 -2
  109. package/dist/tools/gitTools.js.map +1 -1
  110. package/dist/tools/jobTools.js +4 -4
  111. package/dist/tools/jobTools.js.map +1 -1
  112. package/dist/tools/projectTools.js +1 -0
  113. package/dist/tools/projectTools.js.map +1 -1
  114. package/dist/tools/recoveryTools.js +79 -0
  115. package/dist/tools/recoveryTools.js.map +1 -0
  116. package/dist/tools/runtimeTools.js +1 -1
  117. package/dist/tools/runtimeTools.js.map +1 -1
  118. package/dist/tools/surface.js +101 -41
  119. package/dist/tools/surface.js.map +1 -1
  120. package/dist/tunnel/credentials.js +1 -1
  121. package/dist/tunnel/credentials.js.map +1 -1
  122. package/docs/AI_PROVIDERS.md +6 -3
  123. package/docs/ARCHITECTURE.md +88 -4
  124. package/docs/CI.md +118 -0
  125. package/docs/COMPATIBILITY.md +7 -6
  126. package/docs/EVALUATION.md +17 -12
  127. package/docs/MANUAL_ACCEPTANCE.md +59 -2
  128. package/docs/RECOVERY.md +448 -0
  129. package/docs/RELEASE_1.2.1.md +47 -0
  130. package/docs/RELEASE_1.3.0.md +64 -0
  131. package/docs/RELEASE_NOTES.md +41 -0
  132. package/docs/SECURITY.md +122 -0
  133. package/docs/TEST_REPORT.md +327 -5
  134. package/docs/WEB_CLIENTS.md +6 -1
  135. package/docs/adr/051-source-recovery-foundation.md +45 -0
  136. package/docs/adr/052-reviewed-source-restore.md +50 -0
  137. package/docs/adr/053-content-drift-and-private-git-recovery.md +29 -0
  138. package/docs/adr/054-verified-source-checkpoints.md +58 -0
  139. package/docs/adr/055-reviewed-docker-deployments.md +42 -0
  140. package/docs/adr/056-owner-data-recovery.md +47 -0
  141. package/docs/adr/README.md +7 -0
  142. package/native/private-state-windows.cs +105 -0
  143. package/package.json +7 -1
  144. package/schemas/global-config.schema.json +44 -0
  145. package/schemas/tools.compact.json +175 -15
  146. package/schemas/tools.hybrid.json +350 -16
  147. package/schemas/tools.json +4883 -816
@@ -261,16 +261,20 @@ gateways Report ผูก revision, dataset, dependency lock, config และ h
261
261
 
262
262
  ## Tool surfaces
263
263
 
264
- - Complete capability catalog 138 individual definitions (Core 104 + Advanced Agent Runtime 17 + Sub-agents 4 + Android ADB 13)
265
- - Full live catalog ค่าเริ่มต้น 134 definitions; owner เปิด Sub-agent MCP exposure แล้วเป็น 138
264
+ - Complete capability catalog 158 individual definitions (Core 104 + Advanced Agent Runtime 17 + Sub-agents 4 + Android ADB 13 + Source Recovery 10 + Deployment 10)
265
+ - Full live catalog ค่าเริ่มต้น 154 definitions; owner เปิด Sub-agent MCP exposure แล้วเป็น 158
266
266
  - Compact catalog 20 definitions: overview, discover และ gateways รวม `dodo_mobile`
267
267
  - Hybrid catalog 49 definitions: compact core ตามด้วย direct tools
268
268
 
269
269
  `schemas/tools.json` เป็น complete full schema ส่วน compact และ hybrid เป็น schema แยก
270
270
  พร้อม metadata ของ optional feature ค่า `exposeSubagentsToMcp=false` จะกรองสี่
271
271
  Sub-agent definitions ออกจาก Full และกรองสี่ operation names ออกจาก gateway schemas,
272
- instructions และ `dodo_discover` ของ Compact/Hybrid โดยจำนวน gateway names ยังคง
273
- 19/49 การเลือก surface หรือ feature exposure ไม่เปลี่ยน permission
272
+ instructions และ `dodo_discover` ของ Compact/Hybrid โดยจำนวน tool definitions ยังคง
273
+ 20/49 การตั้งค่า `disabledDiscoverOperations` กรอง operation เพิ่มจาก discover และ
274
+ gateway enum, ตัด Hybrid direct duplicate และไม่สร้าง gateway ที่ว่าง จึงทำให้ catalog
275
+ runtime ต่ำกว่าค่าสูงสุดได้ Full direct catalog ไม่รับผลจากค่านี้ ทุก variant cache ด้วย
276
+ canonical feature key และคำนวณ overview/stats จาก catalog ที่ serve จริง การเลือก
277
+ surface หรือ feature exposure ไม่เปลี่ยน permission
274
278
 
275
279
  ## Personal และ managed access mode
276
280
 
@@ -369,3 +373,83 @@ Owner UI อยู่ `configUi/workbench.js/.css` ใช้ authenticated same-
369
373
  `aiAdmin.ts` บน private listener เท่านั้น CLI/advanced web controls ใช้ IPC dispatcher,
370
374
  setup/config validation ชุดเดิม ไม่มี secret fallback หรือการเปิด permission อัตโนมัติ
371
375
  รายละเอียด [ADR-045](adr/045-ai-providers-multiproject.md)
376
+
377
+ ## Journal write intent and owner recovery
378
+
379
+ The applier uses one mutation lock for forward and inverse plans. The shared
380
+ project queue also covers private owner rollback. Every original before-image is
381
+ saved and verified before the first source write; sources are checked again
382
+ after backup, before each syscall and before publication where applicable.
383
+ Creation uses exclusive hard-link publication from a same-directory temporary
384
+ file, preventing a late-arriving destination from being replaced. Modification
385
+ uses atomic rename. Neither is a multi-file atomic transaction.
386
+
387
+ Persisted journal states remain compatible: `pending` → `backed_up` → `written`
388
+ (write intent, recorded **before** syscall) → `done` (verified after-state).
389
+ A syscall can succeed without its next SQLite update succeeding. Compensation
390
+ therefore examines every attempted step, including the currently failing one,
391
+ and restores only a verified owned after-state from verified backups.
392
+
393
+ A rollback creates a private inverse plan with reversed operation order and
394
+ swapped before/after hashes. Its own backups contain pre-restore bytes.
395
+ `journal-v2:<changesetId>` records direction/source linkage in the existing
396
+ private metadata store; it grants no authority. Boot reconciliation verifies both
397
+ ends of moves, current hashes and backup integrity, then finalizes bookkeeping
398
+ in a transaction. All-before state is failed; mixed/unknown state is blocked for
399
+ recovery. No source bytes are rewritten at startup.
400
+
401
+ MCP rollback checks changeset ownership in the applier, so Full/Compact/agent
402
+ paths cannot diverge. Authenticated owner administration exposes
403
+ `recover.rollback` through the existing dispatcher, with strict arguments
404
+ `changesetId`, `idempotencyKey`, `workspaceId`, `workspaceEpoch`. Web callers also
405
+ send the selected project's reviewed context headers. The owner session is
406
+ revalidated after queuing. This low-level operation is not a whole-project
407
+ snapshot restore; the reviewed snapshot interface is described by ADR-052 below.
408
+
409
+ Git staging now holds the real index lock while using a separate candidate
410
+ index. A repository-wide, NUL-delimited staged-path inspection runs before and
411
+ after staging, with relative-diff filtering disabled. Success publishes the
412
+ candidate index only if the original still matches. Normal failure removes the
413
+ candidate; uncertain commit outcomes retain it for owner inspection. No stash,
414
+ reset, clean, remote push or private checkpoint commit is performed.
415
+
416
+ ## Source Recovery foundation
417
+
418
+ Leased project runtimes own default-on scoped content snapshots, SQLite references
419
+ and reservations, and a CAS independent of resource GC. Source mutations capture
420
+ and verify before effects; protected async job startup holds the shared queue.
421
+ See [ADR-051](adr/051-source-recovery-foundation.md). Reviewed session/restore flow: [ADR-052](adr/052-reviewed-source-restore.md).
422
+
423
+ ## Recovery R03
424
+
425
+ `RecoveryDrift` persists expected manifests independently of snapshots. Applier advances expected entries inside the same transaction as final verified journal commit. Target writes compare hashes; commands scan the source scope; job termination observes changes before releasing its mutation ticket. Idle scans are bounded and coalesced. Private owner acknowledgement uses exact content digest + workspace/epoch and revalidates authority after asynchronous reads.
426
+
427
+ `RecoveryGitCopies` builds independent bare repositories from verified CAS bytes, private indexes and create-only refs; it never stages or rewrites working Git. Optional owner-selected storage pins canonical directory identity. Git reservations/copies share recovery quotas; source retention prunes matching owned copies. Verification checkpoints require fresh owned verification evidence before publication. See [ADR 053](adr/053-content-drift-and-private-git-recovery.md).
428
+
429
+
430
+ ## Recovery R04
431
+
432
+ RecoveryEvidence binds pre-run source manifests to existing verify_changes jobs and recipe digests. Live inspection checks the full Recovery source scope and current recipes/runtime; observed stale state is sticky. Safe evidence projections omit logs and environment values. Revisioned owner pointers, tombstones and audit events are separate from immutable manifests and execution permissions. Retention preview and prune use the same protected-reference calculation. The dashboard is bundled as ui/recovery.js. See [ADR 054](adr/054-verified-source-checkpoints.md).
433
+
434
+ ## deployment provenance
435
+
436
+ `RecoveryDeployments` binds immutable plans to verified manifests, recipe evidence,
437
+ project/epoch and owner target revisions. `DockerDeploymentAdapter` uses protected
438
+ JobManager invocations, binary private spool and bounded sealed archives. Typed
439
+ Docker argv never consumes repo Compose hooks. `DeploymentMaintenance` is private
440
+ owner administration with durable preview hashes, re-observation and uncertain
441
+ receipts; it is not an MCP definition. HTTP/CLI reuse the same service and live
442
+ context checks. See [ADR 055](adr/055-reviewed-docker-deployments.md) and the
443
+ [usage and limits](RECOVERY.md#reviewed-docker-deployment).
444
+
445
+ ## database/config recovery
446
+
447
+ `RecoveryDatabases` adds owner-registered SQLite migration metadata and explicit
448
+ manifest-bound compatibility rules. `RecoveryHistory` checks them at preview,
449
+ apply and after the pre-restore checkpoint. No database mutation adapter is exposed.
450
+ `RecoveryConfigVault` stores AEAD ciphertext and journaled redacted restore plans
451
+ in separate private tables; `OSRecoveryKeys` stores only keys in OS credential
452
+ providers. Owner IPC, HTTP and CLI share the same services/queue/context checks.
453
+ Bundled `ui/dataRecovery.js` handles both opt-ins without changing MCP catalog or
454
+ source-secret guards. See [ADR 056](adr/056-owner-data-recovery.md) and
455
+ [usage/limits](RECOVERY.md#database-awareness-and-encrypted-private-config).
package/docs/CI.md ADDED
@@ -0,0 +1,118 @@
1
+ # Native Linux และ Windows CI
2
+
3
+ `platform-gates` ใช้ GitHub Actions บน self-hosted runners โดยตรง **ไม่ใช้ Docker**
4
+ ทดสอบ Node 22 และ 24 ทั้งสองระบบ การ Online หมายถึงรับ job ได้ ยังไม่ใช่ผลทดสอบ PASS
5
+
6
+ | Job | Runner labels | เริ่มเมื่อ |
7
+ |---|---|---|
8
+ | Linux native | self-hosted, Linux, X64, linux-ci | Run workflow เลือก linux/all |
9
+ | Windows native | self-hosted, Windows, X64, windows-ci 02 | push main หรือ Run workflow เลือก windows/all |
10
+
11
+ ไม่มี pull_request trigger สำหรับโค้ดที่ยังไม่ผ่านการตรวจ เพราะ self-hosted job
12
+ ใช้สิทธิ์ OS ของบัญชี runner เลือกเฉพาะ ref ที่เจ้าของตรวจแล้ว GitHub token เป็น
13
+ contents:read, checkout ไม่เก็บ credential และไม่มี npm publish step
14
+
15
+ ## สั่งรัน
16
+
17
+ GitHub → Actions → platform-gates → Run workflow → เลือก branch และ platform
18
+ หรือใช้ GitHub CLI ที่ login แล้ว:
19
+
20
+ ```sh
21
+ gh workflow run platform-gates.yml --ref main -f platform=all
22
+ gh run list --workflow platform-gates.yml --limit 5
23
+ ```
24
+
25
+ โค้ดที่ยังไม่ commit/push ในเครื่องจะไม่อยู่ใน CI เลือกสาขาทดสอบที่ push แล้วได้ด้วย
26
+ `--ref <reviewed-branch>` แทน main อย่านำผลคนละ revision มาอ้างแทนกัน
27
+
28
+ เมื่อ full gate timeout ก่อนสร้าง JSON report สามารถเลือก `windows-diagnostics`
29
+ พร้อม `evidence_run` เช่น `35496561994-1` เพื่ออ่านความคืบหน้าที่เก็บไว้บน runner
30
+ ผลแสดงเฉพาะชื่อไฟล์ทดสอบที่อยู่ใน repo และตัวเลข ไม่ส่ง log ทั้งก้อนออกมา
31
+ คำสั่งตรวจหลักฐานสำเร็จไม่ได้แปลว่า application tests ผ่าน
32
+
33
+ `windows-focus` ใช้ Node 24 และ worker เดียว ทดสอบชุดที่เลือกใน `scripts/windows-focus.mjs`
34
+ พร้อม native ACL preflight เพื่อวินิจฉัย Windows failures ผ่าน npm script `ci:windows:focus`
35
+ ผลนี้ไม่แทน `windows` ซึ่งยังต้องรัน full gate ทั้ง Node 22/24 ก่อนรับรอง candidate
36
+
37
+ ## เตรียม Linux runner
38
+
39
+ ใช้บัญชี non-root และต้องมี Git, Python 3, make, g++, ffmpeg, ffprobe และ espeak-ng
40
+ ใน PATH Workflow ไม่ติดตั้ง system packages หรือแก้ permission เครื่องโดยอัตโนมัติ
41
+ เจ้าของเตรียมรายการดังกล่าวด้วย package manager ของ Linux distribution ที่ใช้อยู่
42
+
43
+ Workflow ใช้ `npm ci` และ Playwright รุ่นที่อยู่ใน lockfile เพื่อติดตั้ง Chromium
44
+ จากนั้นเปิด headless Chromium ด้วย `chromiumSandbox:true` และถ่ายภาพ fixture จริง
45
+ ก่อนรัน build/tests ต้องมี Chromium system libraries และ user namespaces/sandbox
46
+ ที่ใช้งานได้ หากไม่พร้อมจะหยุดพร้อมข้อความ ไม่มีการใส่ `--no-sandbox` เพื่อให้ผ่าน
47
+ ดู [Playwright CI requirements](https://playwright.dev/docs/ci) สำหรับ OS/libraries
48
+ ที่รุ่นนั้นรองรับ โดยตรวจ Linux distribution ของ runner ก่อนเตรียมเครื่อง
49
+
50
+ Media tests บน Linux ถูกบังคับด้วย `DODO_TEST_REQUIRE_LINUX_MEDIA=1`
51
+ จึงไม่ข้าม speech/ffmpeg tests เพราะ dependency หาย
52
+
53
+ ## Windows: Online แต่ job ล้มก่อน step แรก
54
+
55
+ หาก annotation มี `PowerShellPreAmpersandEscape` / `InitializeSecretMasker`
56
+ และไม่มี steps เป็นอาการใน GitHub runner ที่รายงานกับ locale ภาษาไทย
57
+ ยังไม่ได้ทดสอบ DODO ดู [actions/runner#4686](https://github.com/actions/runner/issues/4686)
58
+
59
+ สำหรับ runner ที่เปิดด้วย `run.cmd`: หยุดหน้าต่างเดิมด้วย Ctrl+C แล้วเปิด PowerShell
60
+ แบบ Administrator ใน **โฟลเดอร์ runner ที่ติดตั้งจริง** จากนั้นรัน:
61
+
62
+ ```powershell
63
+ $env:DOTNET_SYSTEM_GLOBALIZATION_INVARIANT = "1"
64
+ $env:DOTNET_SYSTEM_GLOBALIZATION_PREDEFINEDCULTURESONLY = "false"
65
+ .\run.cmd
66
+ ```
67
+
68
+ ค่ามีผลเฉพาะ process นี้ ไม่ใช่การเปลี่ยน locale ของเครื่อง เมื่อเปิดหน้าต่างใหม่ต้อง
69
+ ตั้งอีกครั้ง Workflow คืน globalization ปกติให้ขั้นทดสอบ ไม่ใช้ workaround
70
+ บังพฤติกรรม locale ของ DODO หาก runner รันเป็น service การตั้งค่าใน PowerShell
71
+ อีกหน้าต่างจะไม่เปลี่ยน environment ของ service ต้องให้เจ้าของจัดการ service นั้น
72
+ และอย่าเปิด runner ตัวเดียวกันซ้อนกันทั้ง service กับ run.cmd
73
+
74
+ Windows gate ต้องใช้ enabled Administrator token เพื่อทดสอบ owner/DACL/reparse
75
+ บน NTFS โดยไม่ลดข้อกำหนดของ security tests
76
+
77
+ ## หลักฐานและสถานะ
78
+
79
+ Gate รัน build, typecheck, lint, full tests, packaging, DodoBench, production audit,
80
+ immutable tarball และ fresh install โดยไม่เผยแพร่ npm
81
+ `test:all` มีเวลา aggregate สูงสุด 60 นาทีบน Windows และ 30 นาทีบนระบบอื่น เพราะ
82
+ native Windows มีต้นทุนตรวจ NTFS ACL และชุด Recovery เพิ่มขึ้น ไม่ลด assertions
83
+ และ failure ใด ๆ ยังคงทำให้ gate ไม่ผ่าน ราย test/hook มีขอบเขตเวลาแยกกัน:
84
+ ค่าเริ่มต้น 60 วินาที ส่วน scenario ที่ทำสำเนา Git/CAS หลายรอบของ 15 ไฟล์และตรวจ
85
+ restore/replay ทั้งวงจรให้ 180 วินาทีบน Windows โดยคง deadline ของแต่ละ operation
86
+ ผลละเอียดอยู่บน runner ใน `<runner-workspace>/.dodo-ci-evidence/<run-id>-<attempt>/<platform>-node-<major>/`
87
+ นอก checkout เพื่อไม่ถูก checkout cleanup ลบ จึงไม่ push/pack การ rerun ใช้ directory
88
+ ใหม่ ไม่เขียนทับ report เก่า Linux ย้ายสำเนา evidence แบบเก่าที่อยู่ใน checkout
89
+ ออกไปก่อน cleanup หากยังมีอยู่ ไม่เขียนทับสำเนาที่มีแล้ว
90
+
91
+ GitHub log/artifact รับเฉพาะ summary ที่เลือก scalar fields ไว้แล้ว ไม่อัปโหลด raw
92
+ test output, keys หรือ state DB กรณี test fail แสดงเฉพาะ path ของ test ใน repo,
93
+ ลำดับ assertion (เริ่มที่ 0), หมายเลขบรรทัด และชนิด failure ไม่แสดงชื่อ test,
94
+ expected/actual values, ข้อความ error หรือ stack ของเครื่อง รายละเอียด probe
95
+ ที่ fail เก็บไว้ให้เจ้าของอ่านบนเครื่อง สรุป failure ก่อนหน้าแสดง revision/run ID
96
+ ชัดเจน ไม่ปะปนกับผลรอบปัจจุบัน
97
+
98
+ - `AUTOMATED_PASS`: gate ของ revision/platform นั้นผ่านครบ
99
+ - `AUTOMATED_FAIL`: gate ล้มเหลว ดู step/summary และ private evidence
100
+ - ล้มก่อน step แรก: runner startup failure ไม่ใช่ผลทดสอบ application
101
+ - `MANUAL_NOT_RUN`: ยังไม่ได้ทำ manual acceptance; CI ผ่านไม่เปลี่ยนสถานะนี้เอง
102
+
103
+ Linux Docker evidence เดิมยังเป็นประวัติการทดสอบเดิม ไม่ใช้แทน native Linux CI
104
+ ตามนโยบายปัจจุบัน Strict gate รวมได้เฉพาะ clean revision/lock/source fingerprint
105
+ ตรงกัน และ Linux origin เป็น `github-actions-native`
106
+
107
+ ## Release evidence
108
+
109
+ Strict release gate ต้องมี macOS, native Linux และ native Windows ที่ตรง version,
110
+ clean revision, source fingerprint และ lockfile ไม่รับผล Docker แทน native CI
111
+ ใช้ allowlisted summary จาก workflow ได้โดยไม่ต้องคัดลอก private logs ออกมา
112
+ Windows รัน dedicated random-item Credential Manager fixture และลบเฉพาะ item นั้น
113
+ Linux Secret Service บนเครื่อง headless ที่ไม่ได้เปิด fixture ยังคง NOT_RUN
114
+
115
+ Fresh-install smoke เริ่ม server ใหม่ด้วย private fixture เดิมเพื่อตรวจ receipt และ
116
+ stale epoch หาก Node fetch pool คืน socket ที่เพิ่งปิด จะ retry เฉพาะ JSON-RPC
117
+ `initialize` เมื่อเป็น connection-reset/socket-close แบบจำกัดจำนวนครั้ง ไม่มีการ
118
+ retry `tools/call`, คำสั่งที่มีผลข้างเคียง หรือ OAuth exchange โดยอัตโนมัติ
@@ -29,10 +29,10 @@ Effectful tools และ jobs ยังทำงานใน active workspace
29
29
  ## Tool surfaces
30
30
 
31
31
  - HTTP default: Compact 20 tools
32
- - STDIO default: Full 134 tools; เปิด Sub-agent MCP exposure แล้วเป็น 138
32
+ - STDIO default: Full 154 tools; เปิด Sub-agent MCP exposure แล้วเป็น 158
33
33
  - explicit Hybrid: 49 tools
34
34
 
35
- Complete capability schema มี 138 operations ค่าเริ่มต้น `exposeSubagentsToMcp=false`
35
+ Complete capability schema มี 158 operations ค่าเริ่มต้น `exposeSubagentsToMcp=false`
36
36
  ซ่อน `subagent_spawn/status/result/control` จาก MCP เท่านั้น หน้าเว็บ Chat & Tasks ยัง
37
37
  ใช้ได้ Compact/Hybrid คงจำนวน 20/49 tool names แต่กรอง operation enum, instructions
38
38
  และ discover index ให้ตรงกับ live runtime หลังเปลี่ยนค่าต้อง restart และให้ client
@@ -95,10 +95,11 @@ Directory guard ไม่ใช่ OS sandbox, repository instructions ไม่
95
95
  ## Evaluation evidence
96
96
 
97
97
  DodoBench local fixture ใช้ยืนยัน contract บน platform/revision ที่ report ระบุเท่านั้น
98
- ผลของ macOS ไม่แทน Linux และ Linux Docker ไม่แทน Windows native Release gate ต้องมี
99
- หลักฐาน macOS local และ Linux Docker ที่ revision/lock digest ตรงกัน Docker image
100
- ติดตั้ง Playwright Chromium เพื่อรัน browser case จริง Dedicated self-hosted GitHub
101
- Actions รัน Linux Docker และ Windows native candidate เฉพาะ trusted main/manual
98
+ ผลของ macOS ไม่แทน Linux และ Linux ไม่แทน Windows native Release gate ต้องมี
99
+ หลักฐาน macOS local และ Linux native CI ที่ clean revision/source fingerprint/lock digest ตรงกัน
100
+ Dedicated self-hosted GitHub Actions รัน Linux และ Windows โดยตรงบน Node 22/24
101
+ ไม่ใช้ Docker; ตรวจ Chromium sandbox และ media dependencies บน Linux ก่อนรันทดสอบ
102
+ Workflow รับเฉพาะ trusted main/manual ดู [CI](CI.md) สำหรับ prerequisites และการสั่งรัน
102
103
  Windows manual acceptance ยังคง `MANUAL_NOT_RUN` จนกว่าจะทดสอบบน Windows 11 จริง
103
104
 
104
105
  ## AI Providers / Multi-project
@@ -47,21 +47,21 @@ write → read → edit → read-back ผ่าน Compact gateway
47
47
 
48
48
  ## Platform gates
49
49
 
50
- macOS รันจาก owner checkout ส่วน Linux gate เดียวกันรันได้ทั้ง local Docker และ
51
- dedicated self-hosted GitHub Actions runner:
50
+ macOS รันจาก checkout ส่วน Linux และ Windows ใช้ dedicated self-hosted GitHub
51
+ Actions runner โดยตรง ไม่ใช้ Docker:
52
52
 
53
53
  ```bash
54
54
  # macOS บน checkout ปัจจุบัน
55
55
  npm run release:gate
56
56
 
57
- # Linux จริงใน Docker image แยก พร้อม Playwright Chromium
58
- npm run test:linux:docker
57
+ # Linux และ Windows native CI / Node 22, 24
58
+ gh workflow run platform-gates.yml --ref main -f platform=all
59
59
  ```
60
60
 
61
- Docker build ไม่รับ `.git`, `.npmrc`, `.env`, model, release evidence หรือเอกสารพัฒนา
62
- private เข้า build context ตัว runner ส่งเฉพาะ revision/dirty state ที่อ่านจาก host Git
63
- เข้า release gate และ DodoBench ผ่าน environment attestation ที่รับได้เฉพาะใน Linux
64
- container จากนั้นตรวจ report กลับว่าตรงกับ revision และ lock digest เดิม
61
+ Linux workflow ตรวจ prerequisites, ติดตั้ง dependencies จาก lockfile และ Chromium
62
+ แล้วพิสูจน์ว่า Chromium เปิดด้วย sandbox ได้ก่อนรัน gate อ่าน [CI](CI.md)
63
+ สำหรับการเตรียมเครื่อง ใช้ `npm run release:gate:ci` เช่นเดียวกับ Windows
64
+ ตรวจ Git HEAD ตรง GITHUB_SHA และ source สะอาดก่อนทดสอบ
65
65
 
66
66
  `.github/workflows/platform-gates.yml` ใช้ self-hosted labels `linux-ci` และ
67
67
  `windows-ci 02` ทดสอบ Node 22/24 เฉพาะ push ที่ `main` กับ manual dispatch ไม่มี
@@ -73,10 +73,15 @@ container จากนั้นตรวจ report กลับว่าตร
73
73
  revision กับ `package-lock.json` เดียวกัน Windows ถูกระบุเป็น
74
74
  `DEFERRED_MANUAL_NOT_RUN` และไม่ถูกนับเป็น supported release platform ในช่วงนี้
75
75
  Manual external-AI, owner workspace และ Windows 11 อยู่แยกเป็น `MANUAL_NOT_RUN`
76
- Strict gate รับ Linux evidence เฉพาะ `docker-host-git` จาก clean checkout พร้อม
77
- fresh-install PASS จึงไม่รับ candidate ที่มี uncommitted source หรือ report จาก runner
78
- ชนิดอื่น Report บันทึก origin ว่ามาจาก local หรือ GitHub Actions ตามจริง ไม่มีคำสั่ง
79
- เหล่านี้ publish npm
76
+ Strict gate รับ Linux evidence เฉพาะ `local-git` และ origin `github-actions-native`
77
+ จาก clean checkout พร้อม fresh-install PASS และ suites ที่ผ่านจริง ต้องตรงทั้ง
78
+ revision/source fingerprint/lock digest จึงไม่รับ uncommitted source หรือ Docker
79
+ report เก่ามาแทน native CI Report บันทึก origin ตามจริง ไม่มีคำสั่งเหล่านี้ publish npm
80
+
81
+ ผลทดสอบและ private diagnostics อยู่ใน runner ใต้ `.dodo-ci-evidence/` ข้าง checkout
82
+ แยกตาม run ID/attempt/platform/Node ไม่เขียนทับหลักฐานจากการ rerun หรือ checkout cleanup
83
+ อัปโหลดเฉพาะ allowlisted summary และตำแหน่ง failure ใน test source
84
+ ไม่ส่ง raw test logs หรือ private state ขึ้น artifact
80
85
 
81
86
  ## Security invariants
82
87
 
@@ -296,10 +296,10 @@ manual external-client acceptance
296
296
  Automated catalog/API/Chromium/fresh-package fixtures: **AUTOMATED_PASS**
297
297
 
298
298
  1. เปิด Local Config → Settings และตรวจว่าสวิตช์ “เปิดให้ MCP clients เห็น Sub-agent tools” ปิดเป็นค่าเริ่มต้น
299
- 2. ตรวจ Full live catalog มี 121 tools; Compact/Hybrid มี 19/49 ชื่อและ discover หา `subagent_spawn` ไม่พบ
299
+ 2. ตรวจ Full live catalog มี 154 tools; Compact/Hybrid มี 20/49 ชื่อและ discover หา `subagent_spawn` ไม่พบ
300
300
  3. ตรวจ Chat & Tasks ยังสร้างและดูงานได้จากหน้าเว็บ
301
301
  4. เปิดสวิตช์ ยืนยันผ่าน dialog แล้วตรวจข้อความว่าต้อง restart/rescan
302
- 5. restart fixture เท่านั้น แล้วตรวจ Full มี 125 และ Compact discover/gateway มี `subagent_spawn/status/result/control`
302
+ 5. restart fixture เท่านั้น แล้วตรวจ Full มี 158 และ Compact discover/gateway มี `subagent_spawn/status/result/control`
303
303
  6. ปิดสวิตช์อีกครั้ง restart และตรวจว่า run history ยังอยู่ แต่ MCP definitions ถูกซ่อน
304
304
 
305
305
  การ restart server จริงและ rescan ผ่าน ChatGPT/remote client จริง: **MANUAL_NOT_RUN**
@@ -363,3 +363,60 @@ credentials ผ่าน private UI ผลต้องแยกตาม provide
363
363
  Live OpenAI, Gemini, Claude, MiniMax, GLM, Kimi, Ollama: MANUAL_NOT_RUN สำหรับงานนี้
364
364
  จนกว่าจะมีหลักฐานจาก account/model จริง Browser automation และ synthetic Keychain
365
365
  round-trip เป็น AUTOMATED_PASS ไม่ใช้แทน MANUAL_PASS ของ provider
366
+
367
+ ## Recovery R00–R02
368
+
369
+ Automation uses separate fixture projects, including Chromium desktop/narrow
370
+ owner policy controls. Manual owner-device use and native Windows are
371
+ `MANUAL_NOT_RUN`. R02 adds automated fixture HTTP/owner browser/restore/crash
372
+ coverage. Before a release, an owner should create a fixture checkpoint, edit two
373
+ files, preview one-file and session undo, inspect exact-mirror deletions, verify
374
+ read-back, and inspect journal status after reconnect. Test backup opt-out,
375
+ external-edit conflict and restart with fresh context. Do not exercise this manual
376
+ gate on a production database or count automated browser tests as MANUAL_PASS.
377
+
378
+ ## R03 — MANUAL_NOT_RUN on owner projects
379
+
380
+ In disposable projects: capture dirty/staged/untracked source; externally overwrite files while preserving size/mtime; verify target writes refuse and unrelated edits remain available. Review paginated drift, reject stale digest/epoch, then explicitly acknowledge or preview/restore. Verify emergency snapshots do not replace the baseline. Run a command that changes source and check unknown-author attribution after job completion. Confirm independent Git refs/objects, unchanged working index/HEAD/branch, and no hooks/filter markers. Remove the selected backup volume: expect refusal without fallback. Delete source and working `.git` while retaining root identity: preview/restore source only. Root replacement, real removable volumes, native Windows/Android and owner live projects require separate manual acceptance. Browser fixture automation is reported as AUTOMATED_PASS only after it runs.
381
+
382
+
383
+ ## Recovery R04
384
+
385
+ Fixture browser automation covers project registration, default-on recovery, actual recipe evidence, owner names/pins, stale files, restore read-back and quota-blocked UI on desktop/narrow screens. Before a release, an owner should separately test their own project/storage and restart/reconnect workflow, inspect retained pins/names, and re-run required recipes after source/config changes. Live owner projects, Windows/Android and production/database recovery are MANUAL_NOT_RUN for this phase. Do not label a manual owner name as tested or production-known-good.
386
+
387
+ ## Docker deployment and recovery
388
+
389
+ AUTOMATED_PASS (disposable local daemon fixture, native Node): real build/image
390
+ source verification, deploy/health/stabilization, failure preserving known-good,
391
+ reviewed image rollback, source restore without restarting service, unchanged
392
+ SQLite rows/migration metadata/private fixture config in an existing named volume,
393
+ image pin/review conflicts and exact cleanup. These results are separate from
394
+ native Windows/Linux release gates and do not certify a user's daemon/context.
395
+
396
+ MANUAL_NOT_RUN: owner production, remote Docker contexts, Windows/Linux Docker
397
+ engines, long-duration stabilization and manual browser deployment. Before opting
398
+ in, review the target's daemon authority and use a disposable project/service to
399
+ exercise interrupted build/deploy, live observation, probe cleanup, reconnect,
400
+ expired approval and reviewed rollback. Source/database recovery remain distinct.
401
+
402
+ ## database/config recovery — MANUAL_NOT_RUN on owner data
403
+
404
+ Use disposable SQLite and a synthetic private `.env`, never production secrets.
405
+ Enable the migration adapter through the project page; verify unbound UNKNOWN,
406
+ owner-rule COMPATIBLE, and mismatched IDs blocking restore without changing rows.
407
+ Check external migration drift during a source restore, and explicitly review the
408
+ warning-only alternative if selected. Database undo/PITR remains unsupported.
409
+
410
+ For each OS credential provider, opt in a synthetic file, verify actual key-store
411
+ access, encrypted backup, redacted preview and exact read-back. Rotate; verify old
412
+ copies still need old keys. Lock/refuse the OS store and confirm no fallback.
413
+ Stop dependent fixture services before in-place restore. Test restart/reconnect
414
+ using the recorded receipt; UNKNOWN must not repeat writes. Review retention,
415
+ missing-file disable and recovery from the encrypted before-copy. Confirm no
416
+ secrets in MCP, public routes, browser storage, logs, source snapshots or tarball.
417
+
418
+ Automated browser/protocol tests are AUTOMATED_PASS only when reported. A real
419
+ Keychain fixture round-trip is not a manual Windows Credential Manager or Linux
420
+ Secret Service pass. Android encryption-provider support is NOT_SUPPORTED. Record
421
+ each OS and owner-production/manual case independently; no generic DB rollback
422
+ or disaster-recovery success is implied.