dominds 0.6.2 → 0.6.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.
Files changed (149) hide show
  1. package/dist/access-control.js +2 -2
  2. package/dist/agent-priming.js +826 -92
  3. package/dist/cli/read.js +406 -12
  4. package/dist/dialog.js +4 -0
  5. package/dist/docs/design.md +1 -0
  6. package/dist/docs/design.zh.md +1 -0
  7. package/dist/docs/dialog-system.md +12 -7
  8. package/dist/docs/dialog-system.zh.md +7 -3
  9. package/dist/docs/dominds-agent-priming.md +10 -1
  10. package/dist/docs/dominds-agent-priming.zh.md +9 -1
  11. package/dist/docs/dominds-terminology.md +8 -8
  12. package/dist/docs/fbr-implementation.md +77 -0
  13. package/dist/docs/fbr-implementation.zh.md +77 -0
  14. package/dist/docs/fbr.md +142 -141
  15. package/dist/docs/fbr.zh.md +129 -123
  16. package/dist/docs/keep-going.zh.md +162 -0
  17. package/dist/docs/showing-by-doing.md +208 -0
  18. package/dist/docs/showing-by-doing.zh.md +177 -0
  19. package/dist/docs/tellask-collab.md +250 -0
  20. package/dist/docs/tellask-collab.zh.md +254 -0
  21. package/dist/docs/txt-editing-tools.md +2 -2
  22. package/dist/docs/txt-editing-tools.zh.md +2 -2
  23. package/dist/llm/defaults.yaml +82 -4
  24. package/dist/llm/driver.js +280 -104
  25. package/dist/llm/gen/codex.js +49 -2
  26. package/dist/log.js +385 -30
  27. package/dist/mcp/supervisor.js +113 -40
  28. package/dist/minds/builtin/pangu/persona.zh.md +2 -2
  29. package/dist/minds/load.js +49 -284
  30. package/dist/minds/minds-i18n.js +2 -2
  31. package/dist/minds/promptdocs.js +263 -0
  32. package/dist/minds/system-prompt-parts.js +231 -0
  33. package/dist/minds/system-prompt.js +190 -223
  34. package/dist/persistence.js +66 -1
  35. package/dist/server/websocket-handler.js +14 -0
  36. package/dist/shared/diligence.js +40 -6
  37. package/dist/shared/utils/inter-dialog-format.js +3 -5
  38. package/dist/showing-by-doing.js +34 -31
  39. package/dist/snippets/README.en.md +3 -0
  40. package/dist/static/assets/{_baseUniq-C9vbtHF9.js → _baseUniq-C7IpU2Uk.js} +2 -2
  41. package/dist/static/assets/{_baseUniq-C9vbtHF9.js.map → _baseUniq-C7IpU2Uk.js.map} +1 -1
  42. package/dist/static/assets/{arc-hulXG01i.js → arc-1bhQqjON.js} +2 -2
  43. package/dist/static/assets/{arc-hulXG01i.js.map → arc-1bhQqjON.js.map} +1 -1
  44. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DdLIAMT5.js → architectureDiagram-VXUJARFQ-CkEi1QpB.js} +6 -6
  45. package/dist/static/assets/{architectureDiagram-VXUJARFQ-DdLIAMT5.js.map → architectureDiagram-VXUJARFQ-CkEi1QpB.js.map} +1 -1
  46. package/dist/static/assets/{blockDiagram-VD42YOAC-DACsx66C.js → blockDiagram-VD42YOAC-DaBQ5-pY.js} +7 -7
  47. package/dist/static/assets/{blockDiagram-VD42YOAC-DACsx66C.js.map → blockDiagram-VD42YOAC-DaBQ5-pY.js.map} +1 -1
  48. package/dist/static/assets/{c4Diagram-YG6GDRKO-Cd5xZlLy.js → c4Diagram-YG6GDRKO-ChUgpgkP.js} +3 -3
  49. package/dist/static/assets/{c4Diagram-YG6GDRKO-Cd5xZlLy.js.map → c4Diagram-YG6GDRKO-ChUgpgkP.js.map} +1 -1
  50. package/dist/static/assets/{channel-NQehis0Z.js → channel-CxvmwllM.js} +2 -2
  51. package/dist/static/assets/{channel-NQehis0Z.js.map → channel-CxvmwllM.js.map} +1 -1
  52. package/dist/static/assets/{chunk-4BX2VUAB-DZDPl76b.js → chunk-4BX2VUAB-CKsrU2yk.js} +2 -2
  53. package/dist/static/assets/{chunk-4BX2VUAB-DZDPl76b.js.map → chunk-4BX2VUAB-CKsrU2yk.js.map} +1 -1
  54. package/dist/static/assets/{chunk-55IACEB6-CFSRDUbl.js → chunk-55IACEB6-BAau9SFt.js} +2 -2
  55. package/dist/static/assets/{chunk-55IACEB6-CFSRDUbl.js.map → chunk-55IACEB6-BAau9SFt.js.map} +1 -1
  56. package/dist/static/assets/{chunk-B4BG7PRW-BqQQ9M_z.js → chunk-B4BG7PRW--IiJ7W1m.js} +5 -5
  57. package/dist/static/assets/{chunk-B4BG7PRW-BqQQ9M_z.js.map → chunk-B4BG7PRW--IiJ7W1m.js.map} +1 -1
  58. package/dist/static/assets/{chunk-DI55MBZ5-FiFzz1Gh.js → chunk-DI55MBZ5-B83KrPQj.js} +4 -4
  59. package/dist/static/assets/{chunk-DI55MBZ5-FiFzz1Gh.js.map → chunk-DI55MBZ5-B83KrPQj.js.map} +1 -1
  60. package/dist/static/assets/{chunk-FMBD7UC4-DqqtCyWK.js → chunk-FMBD7UC4-BlDXzeza.js} +2 -2
  61. package/dist/static/assets/{chunk-FMBD7UC4-DqqtCyWK.js.map → chunk-FMBD7UC4-BlDXzeza.js.map} +1 -1
  62. package/dist/static/assets/{chunk-QN33PNHL-F0laQQ-J.js → chunk-QN33PNHL-B596W_v7.js} +2 -2
  63. package/dist/static/assets/{chunk-QN33PNHL-F0laQQ-J.js.map → chunk-QN33PNHL-B596W_v7.js.map} +1 -1
  64. package/dist/static/assets/{chunk-QZHKN3VN-CWhEZPaV.js → chunk-QZHKN3VN-UBBCxgBb.js} +2 -2
  65. package/dist/static/assets/{chunk-QZHKN3VN-CWhEZPaV.js.map → chunk-QZHKN3VN-UBBCxgBb.js.map} +1 -1
  66. package/dist/static/assets/{chunk-TZMSLE5B-Dx9cnwUy.js → chunk-TZMSLE5B-D-wCX2wJ.js} +2 -2
  67. package/dist/static/assets/{chunk-TZMSLE5B-Dx9cnwUy.js.map → chunk-TZMSLE5B-D-wCX2wJ.js.map} +1 -1
  68. package/dist/static/assets/{classDiagram-2ON5EDUG-Dp-dyEGy.js → classDiagram-2ON5EDUG-DvtmzPcu.js} +6 -6
  69. package/dist/static/assets/{classDiagram-2ON5EDUG-Dp-dyEGy.js.map → classDiagram-2ON5EDUG-DvtmzPcu.js.map} +1 -1
  70. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-Dp-dyEGy.js → classDiagram-v2-WZHVMYZB-DvtmzPcu.js} +6 -6
  71. package/dist/static/assets/{classDiagram-v2-WZHVMYZB-Dp-dyEGy.js.map → classDiagram-v2-WZHVMYZB-DvtmzPcu.js.map} +1 -1
  72. package/dist/static/assets/{clone-C6mKvxs5.js → clone-DgJ0ZR-k.js} +2 -2
  73. package/dist/static/assets/{clone-C6mKvxs5.js.map → clone-DgJ0ZR-k.js.map} +1 -1
  74. package/dist/static/assets/{cose-bilkent-S5V4N54A-Dbwh3GoX.js → cose-bilkent-S5V4N54A-DXMyFQvy.js} +2 -2
  75. package/dist/static/assets/{cose-bilkent-S5V4N54A-Dbwh3GoX.js.map → cose-bilkent-S5V4N54A-DXMyFQvy.js.map} +1 -1
  76. package/dist/static/assets/{dagre-6UL2VRFP-BD_6e0Uk.js → dagre-6UL2VRFP-BdaUG-j_.js} +7 -7
  77. package/dist/static/assets/{dagre-6UL2VRFP-BD_6e0Uk.js.map → dagre-6UL2VRFP-BdaUG-j_.js.map} +1 -1
  78. package/dist/static/assets/{diagram-PSM6KHXK-BWt7Q59-.js → diagram-PSM6KHXK-NLiqKBzn.js} +7 -7
  79. package/dist/static/assets/{diagram-PSM6KHXK-BWt7Q59-.js.map → diagram-PSM6KHXK-NLiqKBzn.js.map} +1 -1
  80. package/dist/static/assets/{diagram-QEK2KX5R-D0BvBR_a.js → diagram-QEK2KX5R-D-0fyvY_.js} +6 -6
  81. package/dist/static/assets/{diagram-QEK2KX5R-D0BvBR_a.js.map → diagram-QEK2KX5R-D-0fyvY_.js.map} +1 -1
  82. package/dist/static/assets/{diagram-S2PKOQOG-D8uRdKXp.js → diagram-S2PKOQOG-BQ_FU59m.js} +6 -6
  83. package/dist/static/assets/{diagram-S2PKOQOG-D8uRdKXp.js.map → diagram-S2PKOQOG-BQ_FU59m.js.map} +1 -1
  84. package/dist/static/assets/{erDiagram-Q2GNP2WA-CQoifjFq.js → erDiagram-Q2GNP2WA-DyftKeuC.js} +5 -5
  85. package/dist/static/assets/{erDiagram-Q2GNP2WA-CQoifjFq.js.map → erDiagram-Q2GNP2WA-DyftKeuC.js.map} +1 -1
  86. package/dist/static/assets/{flowDiagram-NV44I4VS-CGhdeaG8.js → flowDiagram-NV44I4VS-9SGefONA.js} +6 -6
  87. package/dist/static/assets/{flowDiagram-NV44I4VS-CGhdeaG8.js.map → flowDiagram-NV44I4VS-9SGefONA.js.map} +1 -1
  88. package/dist/static/assets/{ganttDiagram-JELNMOA3-D8W0wb9H.js → ganttDiagram-JELNMOA3-k_WLhf-r.js} +3 -3
  89. package/dist/static/assets/{ganttDiagram-JELNMOA3-D8W0wb9H.js.map → ganttDiagram-JELNMOA3-k_WLhf-r.js.map} +1 -1
  90. package/dist/static/assets/{gitGraphDiagram-NY62KEGX-ChHni_jP.js → gitGraphDiagram-NY62KEGX-3eoLlCOY.js} +7 -7
  91. package/dist/static/assets/{gitGraphDiagram-NY62KEGX-ChHni_jP.js.map → gitGraphDiagram-NY62KEGX-3eoLlCOY.js.map} +1 -1
  92. package/dist/static/assets/{graph-BWoi_FgC.js → graph-vUevIs4s.js} +3 -3
  93. package/dist/static/assets/{graph-BWoi_FgC.js.map → graph-vUevIs4s.js.map} +1 -1
  94. package/dist/static/assets/{index-th_praGg.js → index-BNBG2CE1.js} +399 -68
  95. package/dist/static/assets/index-BNBG2CE1.js.map +1 -0
  96. package/dist/static/assets/{infoDiagram-WHAUD3N6-B_XKKZTV.js → infoDiagram-WHAUD3N6-CwEhVxkU.js} +5 -5
  97. package/dist/static/assets/{infoDiagram-WHAUD3N6-B_XKKZTV.js.map → infoDiagram-WHAUD3N6-CwEhVxkU.js.map} +1 -1
  98. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-ChGuQ6T9.js → journeyDiagram-XKPGCS4Q-Dtdq4G4Q.js} +5 -5
  99. package/dist/static/assets/{journeyDiagram-XKPGCS4Q-ChGuQ6T9.js.map → journeyDiagram-XKPGCS4Q-Dtdq4G4Q.js.map} +1 -1
  100. package/dist/static/assets/{kanban-definition-3W4ZIXB7-BjWe623u.js → kanban-definition-3W4ZIXB7-Bli-AycJ.js} +3 -3
  101. package/dist/static/assets/{kanban-definition-3W4ZIXB7-BjWe623u.js.map → kanban-definition-3W4ZIXB7-Bli-AycJ.js.map} +1 -1
  102. package/dist/static/assets/{layout-BPyT310w.js → layout-CGlA8c09.js} +5 -5
  103. package/dist/static/assets/{layout-BPyT310w.js.map → layout-CGlA8c09.js.map} +1 -1
  104. package/dist/static/assets/{linear-xUsVjXWq.js → linear-Da2jDWL3.js} +2 -2
  105. package/dist/static/assets/{linear-xUsVjXWq.js.map → linear-Da2jDWL3.js.map} +1 -1
  106. package/dist/static/assets/{min-xFt7zeOd.js → min-Co741hTV.js} +3 -3
  107. package/dist/static/assets/{min-xFt7zeOd.js.map → min-Co741hTV.js.map} +1 -1
  108. package/dist/static/assets/{mindmap-definition-VGOIOE7T-DT_dvf2c.js → mindmap-definition-VGOIOE7T-DvkIjoq8.js} +4 -4
  109. package/dist/static/assets/{mindmap-definition-VGOIOE7T-DT_dvf2c.js.map → mindmap-definition-VGOIOE7T-DvkIjoq8.js.map} +1 -1
  110. package/dist/static/assets/{pieDiagram-ADFJNKIX-B1DQ-OaG.js → pieDiagram-ADFJNKIX-BGuGhTu8.js} +7 -7
  111. package/dist/static/assets/{pieDiagram-ADFJNKIX-B1DQ-OaG.js.map → pieDiagram-ADFJNKIX-BGuGhTu8.js.map} +1 -1
  112. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-IHqyr3iT.js → quadrantDiagram-AYHSOK5B-DAZcrJMg.js} +3 -3
  113. package/dist/static/assets/{quadrantDiagram-AYHSOK5B-IHqyr3iT.js.map → quadrantDiagram-AYHSOK5B-DAZcrJMg.js.map} +1 -1
  114. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-CKBpht7B.js → requirementDiagram-UZGBJVZJ-CXN0DxZs.js} +4 -4
  115. package/dist/static/assets/{requirementDiagram-UZGBJVZJ-CKBpht7B.js.map → requirementDiagram-UZGBJVZJ-CXN0DxZs.js.map} +1 -1
  116. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-D2uGjv3i.js → sankeyDiagram-TZEHDZUN-B7-yAePZ.js} +2 -2
  117. package/dist/static/assets/{sankeyDiagram-TZEHDZUN-D2uGjv3i.js.map → sankeyDiagram-TZEHDZUN-B7-yAePZ.js.map} +1 -1
  118. package/dist/static/assets/{sequenceDiagram-WL72ISMW-wLFRhAKd.js → sequenceDiagram-WL72ISMW-DfBNY6h_.js} +4 -4
  119. package/dist/static/assets/{sequenceDiagram-WL72ISMW-wLFRhAKd.js.map → sequenceDiagram-WL72ISMW-DfBNY6h_.js.map} +1 -1
  120. package/dist/static/assets/{stateDiagram-FKZM4ZOC-BFGQTbx5.js → stateDiagram-FKZM4ZOC-BLo1xRVY.js} +9 -9
  121. package/dist/static/assets/{stateDiagram-FKZM4ZOC-BFGQTbx5.js.map → stateDiagram-FKZM4ZOC-BLo1xRVY.js.map} +1 -1
  122. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-DF7AjJuk.js → stateDiagram-v2-4FDKWEC3-Dq7MAD0I.js} +5 -5
  123. package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-DF7AjJuk.js.map → stateDiagram-v2-4FDKWEC3-Dq7MAD0I.js.map} +1 -1
  124. package/dist/static/assets/{timeline-definition-IT6M3QCI-ChHFOb0o.js → timeline-definition-IT6M3QCI-ySWyBF3b.js} +3 -3
  125. package/dist/static/assets/{timeline-definition-IT6M3QCI-ChHFOb0o.js.map → timeline-definition-IT6M3QCI-ySWyBF3b.js.map} +1 -1
  126. package/dist/static/assets/{treemap-KMMF4GRG-BxaNvQU4.js → treemap-KMMF4GRG-DOp4sqOh.js} +4 -4
  127. package/dist/static/assets/{treemap-KMMF4GRG-BxaNvQU4.js.map → treemap-KMMF4GRG-DOp4sqOh.js.map} +1 -1
  128. package/dist/static/assets/{xychartDiagram-PRI3JC2R-CrNKeY_-.js → xychartDiagram-PRI3JC2R-vkmh67qb.js} +3 -3
  129. package/dist/static/assets/{xychartDiagram-PRI3JC2R-CrNKeY_-.js.map → xychartDiagram-PRI3JC2R-vkmh67qb.js.map} +1 -1
  130. package/dist/static/index.html +1 -1
  131. package/dist/team.js +29 -6
  132. package/dist/tool.js +56 -0
  133. package/dist/tools/builtins.js +4 -2
  134. package/dist/tools/context-health.js +7 -7
  135. package/dist/tools/os.js +267 -30
  136. package/dist/tools/pending-tellask-reminder.js +185 -0
  137. package/dist/tools/plan.js +1 -0
  138. package/dist/tools/ripgrep.js +145 -4
  139. package/dist/tools/shell-tools.js +21 -0
  140. package/dist/tools/team-mgmt.js +4 -4
  141. package/dist/tools/toolset-manual.js +74 -0
  142. package/dist/utils/task-doc.js +16 -16
  143. package/package.json +1 -1
  144. package/dist/minds/builtin/cmdr/persona.md +0 -3
  145. package/dist/minds/builtin/dijiang/knowledge.md +0 -287
  146. package/dist/minds/builtin/dijiang/persona.md +0 -7
  147. package/dist/static/assets/index-th_praGg.js.map +0 -1
  148. package/dist/static/testing/dom-observation-utils.js +0 -425
  149. package/dist/static/testing/e2e-test-helper.js +0 -3119
package/dist/cli/read.js CHANGED
@@ -10,15 +10,24 @@
10
10
  * --no-hints Don't show hints
11
11
  * --only-prompt Show only system prompt
12
12
  * --only-mem Show only memories
13
+ * --audit Run built-in prompt audit checks
14
+ * --fail-on-audit-warning Exit non-zero when audit emits warnings
15
+ * --find <pattern> Find case-insensitive text in rendered output
13
16
  * --help Show help
14
17
  */
15
18
  Object.defineProperty(exports, "__esModule", { value: true });
16
19
  exports.main = main;
20
+ const promises_1 = require("fs/promises");
21
+ const config_1 = require("../mcp/config");
17
22
  const load_1 = require("../minds/load");
23
+ const team_1 = require("../team");
24
+ const registry_1 = require("../tools/registry");
18
25
  function printUsage() {
19
- console.log('Usage: dominds read [<member-id>] [--no-hints] [--only-prompt|--only-mem]');
26
+ console.log('Usage: dominds read [<member-id>] [--no-hints] [--only-prompt|--only-mem] [--audit] [--find <pattern>]');
20
27
  console.log('');
21
28
  console.log('Print agent system prompt and memories with filtering flags.');
29
+ console.log('`--audit` also includes static toolset checks (registry vs `.minds/mcp.yaml` declarations).');
30
+ console.log('When <member-id> is omitted, reads all visible team members.');
22
31
  console.log('');
23
32
  console.log("Note: rtws (runtime workspace) directory is `process.cwd()`. Use 'dominds -C <dir> read' to run in another rtws.");
24
33
  console.log('');
@@ -27,12 +36,297 @@ function printUsage() {
27
36
  console.log(' dominds read developer # Read specific member');
28
37
  console.log(' dominds read --only-prompt # Show only system prompts');
29
38
  console.log(' dominds read --only-mem # Show only memories');
39
+ console.log(' dominds read --only-prompt --audit');
40
+ console.log(' dominds read ux --only-prompt --find "pending Tellask"');
41
+ console.log(' dominds read --only-prompt --audit --fail-on-audit-warning');
30
42
  }
31
- async function main() {
32
- const args = process.argv.slice(2);
43
+ function normalizeForDuplicateScan(line) {
44
+ return line
45
+ .trim()
46
+ .replace(/^[-*]\s+/, '')
47
+ .replace(/[`*_]/g, '')
48
+ .replace(/\s+/g, ' ')
49
+ .toLowerCase();
50
+ }
51
+ function buildPromptAudit(systemPrompt) {
52
+ const checks = [
53
+ {
54
+ id: 'collaboration_protocol',
55
+ label: 'Has collaboration protocol section',
56
+ pass: /## (Collaboration Protocol|协作协议)/.test(systemPrompt),
57
+ },
58
+ {
59
+ id: 'response_closes_round',
60
+ label: 'Has "response closes call round" rule',
61
+ pass: /response closes that call round/.test(systemPrompt) ||
62
+ /收到回贴即表示该轮调用已结束/.test(systemPrompt),
63
+ },
64
+ {
65
+ id: 'pending_wait_guard',
66
+ label: 'Has pending tellask wait guard',
67
+ pass: /pending Tellask|pending tellask/.test(systemPrompt) ||
68
+ /存在明确 pending tellask/.test(systemPrompt),
69
+ },
70
+ {
71
+ id: 'relay_ban',
72
+ label: 'Has no-human-relay rule',
73
+ pass: /relay for executable teammate work/.test(systemPrompt) || /转发员/.test(systemPrompt),
74
+ },
75
+ {
76
+ id: 'tellask_function_boundary',
77
+ label: 'Has tellask vs function-calling boundary',
78
+ pass: /native function-calling/.test(systemPrompt) &&
79
+ (/is only for tellasking teammates\/@self\/@human/.test(systemPrompt) ||
80
+ /仅用于诉请队友\/@self\/@human/.test(systemPrompt)),
81
+ },
82
+ {
83
+ id: 'tellask_line_grammar',
84
+ label: 'Has tellask line-prefix grammar',
85
+ pass: /line-prefix grammar/.test(systemPrompt) || /逐行前缀语法/.test(systemPrompt),
86
+ },
87
+ {
88
+ id: 'fbr_phase_contract',
89
+ label: 'Has FBR phase contract',
90
+ pass: /FBR phase contract|FBR 阶段协议/.test(systemPrompt),
91
+ },
92
+ {
93
+ id: 'taskdoc_encapsulation',
94
+ label: 'Has Taskdoc encapsulation section',
95
+ pass: /Taskdoc encapsulation & access restrictions/.test(systemPrompt) ||
96
+ /差遣牒.*封装/.test(systemPrompt),
97
+ },
98
+ ];
99
+ const hasDomindsRuntime = /Dominds runtime|genuine Codex CLI/.test(systemPrompt);
100
+ const hasCodexHostIdentity = /You are GPT-5\.2 running in the Codex CLI/.test(systemPrompt) ||
101
+ /^You are Codex CLI\.$/m.test(systemPrompt);
102
+ const toolSectionMarkers = ['\n## Intrinsic Tools\n', '\n## 内置工具\n'];
103
+ let duplicateScope = systemPrompt;
104
+ for (const marker of toolSectionMarkers) {
105
+ const idx = duplicateScope.indexOf(marker);
106
+ if (idx >= 0) {
107
+ duplicateScope = duplicateScope.slice(0, idx);
108
+ break;
109
+ }
110
+ }
111
+ const lineCounts = new Map();
112
+ const representative = new Map();
113
+ for (const rawLine of duplicateScope.split('\n')) {
114
+ const line = rawLine.trim();
115
+ if (line === '' || line.startsWith('#'))
116
+ continue;
117
+ const normalized = normalizeForDuplicateScan(line);
118
+ if (normalized.length < 24)
119
+ continue;
120
+ lineCounts.set(normalized, (lineCounts.get(normalized) ?? 0) + 1);
121
+ if (!representative.has(normalized))
122
+ representative.set(normalized, line);
123
+ }
124
+ const duplicates = Array.from(lineCounts.entries())
125
+ .filter(([, count]) => count > 1)
126
+ .sort((a, b) => b[1] - a[1])
127
+ .slice(0, 12)
128
+ .map(([normalized, count]) => ({
129
+ line: representative.get(normalized) ?? normalized,
130
+ count,
131
+ }));
132
+ const warnings = [];
133
+ for (const check of checks) {
134
+ if (!check.pass)
135
+ warnings.push(`Missing: ${check.label}`);
136
+ }
137
+ if (hasDomindsRuntime && hasCodexHostIdentity) {
138
+ warnings.push('Potential host identity conflict: both Dominds runtime and Codex host identity text found.');
139
+ }
140
+ if (duplicates.length > 0) {
141
+ warnings.push(`Detected ${duplicates.length} repeated prompt lines (top duplicates shown).`);
142
+ }
143
+ return { checks, duplicates, warnings };
144
+ }
145
+ function printPromptAudit(report) {
146
+ process.stdout.write('\n## Prompt Audit\n');
147
+ for (const check of report.checks) {
148
+ const tag = check.pass ? 'OK' : 'MISS';
149
+ process.stdout.write(`- [${tag}] ${check.label}\n`);
150
+ }
151
+ if (report.duplicates.length > 0) {
152
+ process.stdout.write('- Duplicate Lines (top):\n');
153
+ for (const d of report.duplicates) {
154
+ process.stdout.write(` - x${d.count}: ${d.line}\n`);
155
+ }
156
+ }
157
+ else {
158
+ process.stdout.write('- Duplicate Lines: none\n');
159
+ }
160
+ if (report.warnings.length > 0) {
161
+ process.stdout.write('- Warnings:\n');
162
+ for (const warning of report.warnings) {
163
+ process.stdout.write(` - ${warning}\n`);
164
+ }
165
+ }
166
+ else {
167
+ process.stdout.write('- Warnings: none\n');
168
+ }
169
+ }
170
+ function listExplicitToolsets(member) {
171
+ if (!member.toolsets)
172
+ return [];
173
+ const out = [];
174
+ const seen = new Set();
175
+ for (const entry of member.toolsets) {
176
+ if (entry === '*' || entry.startsWith('!'))
177
+ continue;
178
+ if (seen.has(entry))
179
+ continue;
180
+ seen.add(entry);
181
+ out.push(entry);
182
+ }
183
+ return out;
184
+ }
185
+ async function readMcpDeclaredToolsets() {
186
+ const mcpPath = '.minds/mcp.yaml';
187
+ let raw;
188
+ try {
189
+ raw = await (0, promises_1.readFile)(mcpPath, 'utf8');
190
+ }
191
+ catch (err) {
192
+ if (typeof err === 'object' &&
193
+ err !== null &&
194
+ 'code' in err &&
195
+ err.code === 'ENOENT') {
196
+ return { kind: 'missing' };
197
+ }
198
+ return { kind: 'invalid', errorText: err instanceof Error ? err.message : String(err) };
199
+ }
200
+ const parsed = (0, config_1.parseMcpYaml)(raw);
201
+ if (!parsed.ok) {
202
+ return { kind: 'invalid', errorText: parsed.errorText };
203
+ }
204
+ return {
205
+ kind: 'loaded',
206
+ declaredServerIds: new Set(parsed.serverIdsInYamlOrder),
207
+ invalidServerIds: new Set(parsed.invalidServers.map((s) => s.serverId)),
208
+ };
209
+ }
210
+ function buildToolsetAuditReport(params) {
211
+ const registeredToolsets = new Set(Object.keys((0, registry_1.listToolsets)()));
212
+ const byMember = [];
213
+ const warnings = [];
214
+ for (const memberId of params.targetMemberIds) {
215
+ const member = params.team.getMember(memberId);
216
+ if (!member)
217
+ continue;
218
+ const explicitToolsets = listExplicitToolsets(member);
219
+ const items = [];
220
+ for (const toolsetName of explicitToolsets) {
221
+ if (registeredToolsets.has(toolsetName)) {
222
+ items.push({ toolsetName, status: 'registered' });
223
+ continue;
224
+ }
225
+ if (params.mcp.kind === 'loaded' && params.mcp.declaredServerIds.has(toolsetName)) {
226
+ if (params.mcp.invalidServerIds.has(toolsetName)) {
227
+ items.push({ toolsetName, status: 'mcp_declared_invalid' });
228
+ warnings.push(`@${member.id}: toolset '${toolsetName}' is declared in mcp.yaml but server config is invalid.`);
229
+ }
230
+ else {
231
+ items.push({ toolsetName, status: 'mcp_declared_unloaded' });
232
+ }
233
+ continue;
234
+ }
235
+ items.push({ toolsetName, status: 'missing' });
236
+ warnings.push(`@${member.id}: toolset '${toolsetName}' is neither registered nor declared in mcp.yaml.`);
237
+ }
238
+ byMember.push({ memberId: member.id, memberName: member.name, items });
239
+ }
240
+ if (params.mcp.kind === 'invalid') {
241
+ warnings.push(`Invalid .minds/mcp.yaml; cannot reliably classify unresolved MCP toolsets: ${params.mcp.errorText}`);
242
+ }
243
+ return {
244
+ mcp: params.mcp,
245
+ byMember,
246
+ warnings,
247
+ };
248
+ }
249
+ function printToolsetAudit(report) {
250
+ process.stdout.write('\n## Toolset Audit\n');
251
+ if (report.mcp.kind === 'missing') {
252
+ process.stdout.write('- MCP config: missing (`.minds/mcp.yaml` not found)\n');
253
+ }
254
+ else if (report.mcp.kind === 'invalid') {
255
+ process.stdout.write('- MCP config: invalid (`.minds/mcp.yaml` parse/read failed)\n');
256
+ }
257
+ else {
258
+ process.stdout.write(`- MCP config: loaded (declared servers: ${report.mcp.declaredServerIds.size}, invalid server configs: ${report.mcp.invalidServerIds.size})\n`);
259
+ }
260
+ if (report.byMember.length === 0) {
261
+ process.stdout.write('- Members: none\n');
262
+ }
263
+ else {
264
+ for (const memberReport of report.byMember) {
265
+ process.stdout.write(`- @${memberReport.memberId} (${memberReport.memberName}):\n`);
266
+ if (memberReport.items.length === 0) {
267
+ process.stdout.write(' - no explicit toolset declarations\n');
268
+ continue;
269
+ }
270
+ for (const item of memberReport.items) {
271
+ const label = item.status === 'registered'
272
+ ? 'OK'
273
+ : item.status === 'mcp_declared_unloaded'
274
+ ? 'DEFERRED'
275
+ : item.status === 'mcp_declared_invalid'
276
+ ? 'INVALID'
277
+ : 'MISS';
278
+ process.stdout.write(` - [${label}] ${item.toolsetName}\n`);
279
+ }
280
+ }
281
+ }
282
+ if (report.warnings.length > 0) {
283
+ process.stdout.write('- Warnings:\n');
284
+ for (const warning of report.warnings) {
285
+ process.stdout.write(` - ${warning}\n`);
286
+ }
287
+ }
288
+ else {
289
+ process.stdout.write('- Warnings: none\n');
290
+ }
291
+ }
292
+ function collectFindMatches(text, pattern) {
293
+ const normalizedPattern = pattern.toLowerCase();
294
+ const lines = text.split('\n');
295
+ const matches = [];
296
+ for (let i = 0; i < lines.length; i++) {
297
+ const line = lines[i];
298
+ if (line.toLowerCase().includes(normalizedPattern)) {
299
+ matches.push({ line: i + 1, text: line });
300
+ if (matches.length >= 60)
301
+ break;
302
+ }
303
+ }
304
+ return matches;
305
+ }
306
+ function printFindResults(pattern, blocks) {
307
+ process.stdout.write(`\n## Find: "${pattern}"\n`);
308
+ let total = 0;
309
+ for (const block of blocks) {
310
+ const matches = collectFindMatches(block.text, pattern);
311
+ if (matches.length === 0)
312
+ continue;
313
+ total += matches.length;
314
+ process.stdout.write(`- ${block.name} (${matches.length}):\n`);
315
+ for (const match of matches) {
316
+ process.stdout.write(` - L${match.line}: ${match.text}\n`);
317
+ }
318
+ }
319
+ if (total === 0) {
320
+ process.stdout.write('- no matches\n');
321
+ }
322
+ }
323
+ function parseArgs(args) {
33
324
  let memberId;
34
325
  let onlyPrompt = false;
35
326
  let onlyMem = false;
327
+ let audit = false;
328
+ let failOnAuditWarning = false;
329
+ const findPatterns = [];
36
330
  for (let i = 0; i < args.length; i++) {
37
331
  const arg = args[i];
38
332
  if (arg === '--only-prompt') {
@@ -41,6 +335,20 @@ async function main() {
41
335
  else if (arg === '--only-mem') {
42
336
  onlyMem = true;
43
337
  }
338
+ else if (arg === '--audit') {
339
+ audit = true;
340
+ }
341
+ else if (arg === '--fail-on-audit-warning') {
342
+ failOnAuditWarning = true;
343
+ }
344
+ else if (arg === '--find') {
345
+ const next = args[i + 1];
346
+ if (!next || next.startsWith('-')) {
347
+ throw new Error("Option '--find' requires a non-empty pattern argument.");
348
+ }
349
+ findPatterns.push(next);
350
+ i++;
351
+ }
44
352
  else if (arg === '--no-hints') {
45
353
  // Deprecated, but keep for compatibility
46
354
  console.warn('Warning: --no-hints is deprecated, use --only-prompt or --only-mem instead');
@@ -53,23 +361,109 @@ async function main() {
53
361
  memberId = arg;
54
362
  }
55
363
  else {
56
- console.error(`Error: unexpected argument '${arg}'`);
57
- printUsage();
58
- process.exit(1);
364
+ throw new Error(`Unexpected argument '${arg}'.`);
59
365
  }
60
366
  }
367
+ if (onlyPrompt && onlyMem) {
368
+ throw new Error("Options '--only-prompt' and '--only-mem' are mutually exclusive.");
369
+ }
370
+ return {
371
+ memberId,
372
+ onlyPrompt,
373
+ onlyMem,
374
+ audit,
375
+ failOnAuditWarning,
376
+ findPatterns,
377
+ };
378
+ }
379
+ function resolveTargetMemberIds(team, memberId) {
380
+ if (memberId)
381
+ return [memberId];
382
+ const visibleIds = Object.values(team.members)
383
+ .filter((m) => m.hidden !== true)
384
+ .map((m) => m.id)
385
+ .sort((a, b) => a.localeCompare(b));
386
+ if (visibleIds.length > 0)
387
+ return visibleIds;
388
+ const fallback = team.getDefaultResponder();
389
+ if (!fallback)
390
+ throw new Error('No team members found.');
391
+ return [fallback.id];
392
+ }
393
+ async function main() {
394
+ const args = process.argv.slice(2);
395
+ let parsed;
396
+ try {
397
+ parsed = parseArgs(args);
398
+ }
399
+ catch (err) {
400
+ console.error('Error:', err instanceof Error ? err.message : String(err));
401
+ printUsage();
402
+ process.exit(1);
403
+ return;
404
+ }
61
405
  try {
62
- const { systemPrompt, memories } = await (0, load_1.loadAgentMinds)(memberId);
63
- if (!onlyMem) {
64
- process.stdout.write(systemPrompt.trim() + '\n');
65
- }
66
- if (!onlyPrompt) {
406
+ const team = await team_1.Team.load();
407
+ const targetMemberIds = resolveTargetMemberIds(team, parsed.memberId);
408
+ const isMultiMemberRun = targetMemberIds.length > 1;
409
+ const toolsetAudit = parsed.audit
410
+ ? buildToolsetAuditReport({
411
+ team,
412
+ targetMemberIds,
413
+ mcp: await readMcpDeclaredToolsets(),
414
+ })
415
+ : undefined;
416
+ let auditWarningCount = 0;
417
+ for (let idx = 0; idx < targetMemberIds.length; idx++) {
418
+ const targetMemberId = targetMemberIds[idx];
419
+ const { agent, systemPrompt, memories } = await (0, load_1.loadAgentMinds)(targetMemberId, undefined, {
420
+ missingToolsetPolicy: parsed.audit ? 'silent' : 'warn',
421
+ });
422
+ const renderedMemoryBlocks = [];
67
423
  for (const mem of memories) {
68
424
  if ('content' in mem && typeof mem.content === 'string' && mem.content.trim()) {
69
- process.stdout.write('\n' + mem.content.trim() + '\n');
425
+ renderedMemoryBlocks.push(mem.content.trim());
426
+ }
427
+ }
428
+ if (isMultiMemberRun) {
429
+ const sep = idx === 0 ? '' : '\n\n';
430
+ process.stdout.write(`${sep}===== @${agent.id} (${agent.name}) =====\n`);
431
+ }
432
+ if (!parsed.onlyMem) {
433
+ process.stdout.write(systemPrompt.trim() + '\n');
434
+ }
435
+ if (!parsed.onlyPrompt) {
436
+ for (const content of renderedMemoryBlocks) {
437
+ process.stdout.write('\n' + content + '\n');
438
+ }
439
+ }
440
+ if (parsed.audit) {
441
+ const report = buildPromptAudit(systemPrompt);
442
+ printPromptAudit(report);
443
+ auditWarningCount += report.warnings.length;
444
+ }
445
+ if (parsed.findPatterns.length > 0) {
446
+ const blocks = [];
447
+ if (!parsed.onlyMem) {
448
+ blocks.push({ name: `@${agent.id}/system_prompt`, text: systemPrompt });
449
+ }
450
+ if (!parsed.onlyPrompt) {
451
+ for (let i = 0; i < renderedMemoryBlocks.length; i++) {
452
+ blocks.push({ name: `@${agent.id}/memory_${i + 1}`, text: renderedMemoryBlocks[i] });
453
+ }
454
+ }
455
+ for (const pattern of parsed.findPatterns) {
456
+ printFindResults(pattern, blocks);
70
457
  }
71
458
  }
72
459
  }
460
+ if (parsed.audit && toolsetAudit) {
461
+ printToolsetAudit(toolsetAudit);
462
+ auditWarningCount += toolsetAudit.warnings.length;
463
+ }
464
+ if (parsed.failOnAuditWarning && auditWarningCount > 0) {
465
+ process.exit(2);
466
+ }
73
467
  }
74
468
  catch (err) {
75
469
  console.error('Error loading agent minds:', err instanceof Error ? err.message : String(err));
package/dist/dialog.js CHANGED
@@ -628,6 +628,9 @@ class Dialog {
628
628
  async funcCallRequested(funcId, funcName, argumentsStr) {
629
629
  await this.dlgStore.funcCallRequested(this, funcId, funcName, argumentsStr);
630
630
  }
631
+ async webSearchCall(payload) {
632
+ await this.dlgStore.webSearchCall(this, payload);
633
+ }
631
634
  // Tellask call events (streaming mode - `!?@...` blocks)
632
635
  async callingStart(validation) {
633
636
  await this.dlgStore.callingStart(this, validation);
@@ -1014,6 +1017,7 @@ class DialogStore {
1014
1017
  async callingFinish(_dialog, _callId) { }
1015
1018
  // Function call event (non-streaming mode - single event)
1016
1019
  async funcCallRequested(_dialog, _funcId, _funcName, _argumentsStr) { }
1020
+ async webSearchCall(_dialog, _payload) { }
1017
1021
  /**
1018
1022
  * Load current course number from persisted metadata
1019
1023
  * This method should be implemented by subclasses to read from storage
@@ -555,6 +555,7 @@ dominds dialog start --taskdoc-path tasks/auth-system.tsk
555
555
  - rtws hard rules:
556
556
  - `*.tsk/**` is encapsulated Taskdoc state and is hard-denied for all general file tools.
557
557
  - `.minds/**` is reserved rtws state (team config/memory/assets) and is hard-denied for all general file tools; manage it via dedicated tools like `team-mgmt`.
558
+ - DevOps context: ad-hoc temp scripts are a taboo. If a tool script is needed, align with teammates and the human, then formalize it in the rtws before use.
558
559
 
559
560
  **Collaboration Example**:
560
561
 
@@ -553,6 +553,7 @@ dominds dialog start --taskdoc-path tasks/auth-system.tsk
553
553
  - rtws 硬性规则:
554
554
  - `*.tsk/**` 是封装的差遣牒状态,所有通用文件工具都硬性拒绝。
555
555
  - `.minds/**` 是保留的 rtws 状态(团队配置/内存/资产),所有通用文件工具都硬性拒绝;通过 `team-mgmt` 等专用工具进行管理。
556
+ - DevOps 场景:忌讳临时脚本。如需工具脚本,应与队友和人类对齐后,在 rtws 中正式设计/命名/规范化再使用。
556
557
 
557
558
  **协作示例:**
558
559
 
@@ -164,8 +164,9 @@ flowchart TD
164
164
  - Uses `subdialog.supdialog` reference (no registry lookup)
165
165
  - No registration - supdialog relationship is inherent
166
166
  - Supdialog is always the direct parent in the hierarchy
167
- - `!?@tellasker` is the canonical Type A syntax: it always routes to the tellasker (the dialog that issued the current Tellask)
168
- is identical to the subdialog's `agentId` (common for Fresh Boots Reasoning self-subdialogs).
167
+ - `!?@tellasker` is the canonical Type A syntax: it always routes to the tellasker (the dialog that issued the current Tellask).
168
+ - This matters especially when the supdialog’s `agentId` is identical to the subdialogs `agentId` (common when a sideline
169
+ is created via `!?@self`), where an explicit `!?@<supdialogAgentId>` is easier to get wrong by accident.
169
170
  - The explicit `!?@<supdialogAgentId>` form is accepted as a semantic fallback for backwards compatibility, but is more
170
171
  error-prone in FBR/self-subdialog cases.
171
172
 
@@ -193,6 +194,7 @@ Result:
193
194
  - `!?@self` is an explicit “same persona” call that targets the **current dialog’s agentId** (not a separate teammate).
194
195
  - This is an **unambiguous** syntax for self-tellasks and helps avoid accidental `@teammate`→`@teammate` self-tellasks caused by
195
196
  echoing/quoting prior call headlines.
197
+ - In Dominds, `!?@self` Tellasks are treated as FBR and are driven under a stricter, tool-less policy; see [`fbr.md`](./fbr.md).
196
198
  - **FBR itself should be common**, but the `!tellaskSession`-addressed variant should be rare. Prefer `!?@self` (TYPE C, transient)
197
199
  for most FBR usage. Use `!?@self !tellaskSession ...` only when you explicitly want a resumable, long-lived “fresh boots session”
198
200
  for a multi-step sub-problem.
@@ -269,14 +271,17 @@ Result (second call):
269
271
 
270
272
  **Fresh Boots Reasoning (FBR) self-tellask syntax (default; most common)**: `!?@self`
271
273
 
272
- - `!?@self` targets the current dialog’s agentId and creates a **new ephemeral subdialog** with the same persona/config.
274
+ - `!?@self` targets the current dialog’s agentId and creates a **new ephemeral subdialog** routed to the same agentId.
275
+ - The sideline dialog created by `!?@self` is FBR and is driven under a stricter, tool-less policy; see [`fbr.md`](./fbr.md).
273
276
  - Use this for most Fresh Boots Reasoning sessions: isolate a single sub-problem, produce an answer, and return.
274
277
 
275
278
  **Behavior**:
276
279
 
277
280
  1. Current dialog **suspends**
278
281
  2. Create **NEW subdialog** with the specified agentId
279
- 3. Drive the new subdialog (it is FULL-FLEDGED - can make supcalls, teammate Tellasks, function tool calls)
282
+ 3. Drive the new subdialog:
283
+ - For general Type C, the subdialog is full-fledged (supcalls, teammate Tellasks, tools per config).
284
+ - For `!?@self`, runtime applies the FBR tool-less policy (no tools; restricted Tellasks).
280
285
  4. Subdialog response flows back to parent
281
286
  5. Parent **resumes** with subdialog's response
282
287
 
@@ -284,7 +289,7 @@ Result (second call):
284
289
 
285
290
  - **No registry lookup** - always creates a new subdialog
286
291
  - **Not registered** - no persistence across Tellasks
287
- - The subdialog itself is fully capable (can make supcalls, teammate Tellasks, function tool calls)
292
+ - The subdialog itself is fully capable **except** for `!?@self` FBR, which is tool-less and Tellask-restricted (see `fbr.md`).
288
293
  - Only difference from TYPE B: no registry lookup/resume capability
289
294
  - Used for one-off, independent tasks
290
295
 
@@ -1100,7 +1105,7 @@ sequenceDiagram
1100
1105
  Driver-->>Sub: resume subdialog with response in context
1101
1106
  ```
1102
1107
 
1103
- #### TYPE B: Registered Subdialog Tellask (`Tellask Session`) (`!?@agentId !tellaskSession tellaskSession`, or `!?@self !tellaskSession tellaskSession`)
1108
+ #### TYPE B: Registered Subdialog Tellask (`Tellask Session`) (`!?@agentId !tellaskSession tellaskSession`; `!?@self !tellaskSession ...` is FBR tool-less)
1104
1109
 
1105
1110
  ```mermaid
1106
1111
  sequenceDiagram
@@ -1125,7 +1130,7 @@ sequenceDiagram
1125
1130
  end
1126
1131
  ```
1127
1132
 
1128
- #### TYPE C: Transient Subdialog Tellask (`Fresh Tellask`) (`!?@agentId`, or `!?@self`)
1133
+ #### TYPE C: Transient Subdialog Tellask (`Fresh Tellask`) (`!?@agentId`; `!?@self` is FBR tool-less)
1129
1134
 
1130
1135
  ```mermaid
1131
1136
  sequenceDiagram
@@ -189,6 +189,7 @@ LLM 发出:!?@orchestrator 我应该如何处理数据库迁移?
189
189
 
190
190
  - `!?@self` 是一个显式的"相同角色"调用,指向**当前对话的 agentId**(不是单独队友)。
191
191
  - 这是自调用的**明确**语法,有助于避免因回声/引用先前调用标题而导致的意外 `@teammate`→`@teammate` 自调用。
192
+ - 注意:在 Dominds 中,`!?@self` 会触发扪心自问(FBR)机制,并以更严格的“无工具”策略驱动;详见 [`fbr.zh.md`](./fbr.zh.md)。
192
193
  - **FBR 本身应该很常见**,但使用 `!tellaskSession` 寻址的变体应该很罕见。对于大多数 FBR 使用,首选 `!?@self`(TYPE C,瞬态)。仅当你明确想要一个可恢复的、长期存在的"初心会话"用于多步骤子问题时,才使用 `!?@self !tellaskSession ...`。
193
194
 
194
195
  **Tellask 会话键模式**:`<tellaskSession>` 使用与 `<mention-id>` 相同的标识符模式:`[a-zA-Z][a-zA-Z0-9_-]*`。解析在空白或标点处停止;任何尾随的标题文本在 tellaskSession 解析时被忽略。
@@ -261,14 +262,17 @@ LLM 再次发出:!?@researcher !tellaskSession market-analysis
261
262
 
262
263
  **扪心自问 (FBR) 自调用语法(默认;最常见)**:`!?@self`
263
264
 
264
- - `!?@self` 指向当前对话的 agentId,并创建一个具有相同角色/配置的**新的临时子对话**。
265
+ - `!?@self` 指向当前对话的 agentId,并创建一条路由到同一 agentId 的**新的临时子对话**。
266
+ - 由 `!?@self` 创建的支线对话属于 FBR,并以更严格的“无工具”策略驱动;详见 [`fbr.zh.md`](./fbr.zh.md)。
265
267
  - 对于大多数扪心自问 会话使用此方式:隔离单个子问题,产生答案,然后返回。
266
268
 
267
269
  **行为**:
268
270
 
269
271
  1. 当前对话**挂起**
270
272
  2. 使用指定的 agentId 创建**新的子对话**
271
- 3. 驱动新的子对话(它是完全成熟的 - 可以进行上位调用、队友 Tellask、工具调用)
273
+ 3. 驱动新的子对话:
274
+ - 一般 TYPE C 子对话是“完整能力”的(可上位调用、队友诉请、按配置使用工具)。
275
+ - `!?@self` 属于 FBR 特例:无工具、诉请受限(见 `fbr.zh.md`)。
272
276
  4. 子对话的响应流回父级
273
277
  5. 父级**恢复**,子对话的响应在上下文中
274
278
 
@@ -276,7 +280,7 @@ LLM 再次发出:!?@researcher !tellaskSession market-analysis
276
280
 
277
281
  - **无注册表查找** - 总是创建新的子对话
278
282
  - **不注册** - 在 Tellask 之间不持久化
279
- - 子对话本身是完全 capable 的(可以进行上位调用、队友 Tellask、工具调用)
283
+ - 子对话本身一般是“完整能力”的;但 `!?@self` FBR 是特例:无工具且诉请受限(见 `fbr.zh.md`)。
280
284
  - 与 TYPE B 的唯一区别:无注册表查找/恢复能力
281
285
  - 用于一次性的、独立的任务
282
286
 
@@ -40,6 +40,7 @@ Related docs:
40
40
 
41
41
  - Establish immediate trust that Tellask/return/persistence are real.
42
42
  - Run a real `!?@self` FBR loop at dialog creation.
43
+ - Build muscle memory for the timing contract: initiate FBR, wait for feedback, then synthesize/decide.
43
44
  - Make distillation itself part of the “felt” experience (dedupe/reconcile/extract-the-best).
44
45
  - Keep the procedure safe, small, and deterministic (default command: `uname -a`).
45
46
  - Persist and display the interaction so it is credible from multiple angles (backend record + frontend transcript).
@@ -109,9 +110,15 @@ Optional parallel drafts:
109
110
  - If `fbr_effort` is `0`, skip FBR.
110
111
  - If `fbr_effort` is greater than `100`, the runtime errors out and stops priming (invalid config).
111
112
 
113
+ Phase boundary (critical):
114
+
115
+ - `!?@self` is the **initiation action**, not completed decision-making.
116
+ - Mainline must enter a wait phase until feedback from that FBR run returns.
117
+ - If `fbr_effort = N`, mainline must wait for all N drafts before distillation; do not finalize from partial drafts.
118
+
112
119
  ### 4) Distill into an “Agent Priming” note
113
120
 
114
- The main agent then writes a short, user-visible **Agent Priming** note via a **normal generation** in the mainline
121
+ After confirming feedback from that FBR run has been collected, the main agent writes a short, user-visible **Agent Priming** note via a **normal generation** in the mainline
115
122
  dialog. It should be explicitly distilled (dedupe/reconcile/extract-the-best) rather than repeating each draft.
116
123
 
117
124
  Implementation constraint (matches runtime behavior):
@@ -120,6 +127,8 @@ Implementation constraint (matches runtime behavior):
120
127
  - The runtime may use a non-persisted **internal prompt** to anchor “this generation is distillation”.
121
128
  - The runtime may also include the shell snapshot and FBR drafts as “evidence” inside that internal prompt (for this
122
129
  drive only, not persisted), so distillation does not depend on any queue timing/concurrency details.
130
+ - During the Agent Priming lifecycle (from prelude start until the priming note is produced), runtime must suppress
131
+ diligence-push injections; restore normal diligence behavior only after priming completes.
123
132
 
124
133
  Implementation note (internal prompt):
125
134
 
@@ -29,6 +29,7 @@ Dominds 的诉请(Tellask,`!?@...`)与扪心自问(FBR,`!?@self`)并
29
29
 
30
30
  - 在对话一开始就建立“诉请/回传/持久化都是真的”的信任。
31
31
  - 在对话一开始就跑通一次 `!?@self` 的 FBR 回路。
32
+ - 把“发起 FBR 后先等待回贴,再做综合决策”的时序固化为肌肉记忆。
32
33
  - 把多份 FBR 草稿做一次**综合提炼**,把“取精华、去糟粕”的动作也变成体感的一部分。
33
34
  - 过程足够小、可控、低风险(默认只执行 `uname -a`)。
34
35
  - 记录从多角度都高度拟真:后端存档 + 前端可见的对话转录。
@@ -95,15 +96,22 @@ Dominds 的诉请(Tellask,`!?@...`)与扪心自问(FBR,`!?@self`)并
95
96
  - 若 `fbr_effort` 为 `0`,则跳过 FBR。
96
97
  - 若 `fbr_effort` 大于 `100`,运行时会报错并终止启动流程(配置错误)。
97
98
 
99
+ 阶段边界(关键):
100
+
101
+ - `!?@self` 只是**发起动作**,不是“已完成决策”。
102
+ - 主线对话必须先进入等待态,直到该次 FBR 的回贴返回。
103
+ - 若 `fbr_effort = N`,主线必须等待全部 N 条回贴后再进入综合提炼;不得基于部分草稿提前定稿。
104
+
98
105
  ### 4)综合提炼成“智能体启动(Priming)”笔记
99
106
 
100
- 主线智能体以一次**正常生成**在主线对话里追加一条短笔记(Agent Priming),让关键信息显性化、可检索,并体现“综合提炼”(去重/消冲突/抽取最有用的要点)。
107
+ 在确认该次 FBR 回贴已收齐后,主线智能体以一次**正常生成**在主线对话里追加一条短笔记(Agent Priming),让关键信息显性化、可检索,并体现“综合提炼”(去重/消冲突/抽取最有用的要点)。
101
108
 
102
109
  实现约束(与运行时一致):
103
110
 
104
111
  - “综合提炼”阶段**不应**通过拼装/拼接一段新的 system prompt 或引入一条独立的 system-prompt 组装路径。
105
112
  - 运行时可以使用一条**internal prompt** 来锚定“本次生成就是综合提炼”。internal prompt 必须不落盘、不展示。
106
113
  - FBR 草稿与 shell 回传等“证据材料”可以通过 internal prompt 一并提供给模型(仅用于本次 drive 的上下文,不写入对话历史),从而避免依赖“支线回复注入队列”的时序与并发细节。
114
+ - Agent Priming 生命周期(从序幕开始到 priming 笔记产出完成)内,运行时必须禁止注入 diligence-push(鞭策)消息;待 priming 结束后再恢复常规机制。
107
115
 
108
116
  实现补充(internal prompt):
109
117