@danya-ai/cli 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +33 -3
  2. package/dist/REPL-5VRUWUUA.js +42 -0
  3. package/dist/{acp-XPFY5L23.js → acp-SBV4SUS5.js} +26 -26
  4. package/dist/{agentsValidate-YP7GA4ER.js → agentsValidate-GBCUUJ37.js} +7 -7
  5. package/dist/{ask-F53PCNWW.js → ask-A44NOQXG.js} +25 -25
  6. package/dist/{autoUpdater-PAZTRW74.js → autoUpdater-7XV25FPF.js} +3 -3
  7. package/dist/{chunk-5GADLAR7.js → chunk-2ZWXQRFX.js} +1 -1
  8. package/dist/{chunk-EOZSZNKR.js → chunk-3IXSSL3F.js} +3 -3
  9. package/dist/{chunk-JKRPU66R.js → chunk-5GHO3SUE.js} +4 -4
  10. package/dist/{chunk-5552MSXN.js → chunk-66P52YYI.js} +1 -1
  11. package/dist/{chunk-3LC6LWSN.js → chunk-6Z7EGLJB.js} +1 -1
  12. package/dist/{chunk-QUV2YCUP.js → chunk-AL7YT6CO.js} +1742 -234
  13. package/dist/chunk-AL7YT6CO.js.map +7 -0
  14. package/dist/{chunk-NFMXSWNI.js → chunk-CEARH7HF.js} +3 -3
  15. package/dist/{chunk-CDS5HL6U.js → chunk-CSAIELUO.js} +2 -2
  16. package/dist/chunk-DKOCP6VD.js.map +7 -0
  17. package/dist/{chunk-LO3O7WT2.js → chunk-EPA5LFNP.js} +2 -2
  18. package/dist/{chunk-2ON4OVWS.js → chunk-F4DQYOST.js} +2 -2
  19. package/dist/{chunk-4FOB6KC5.js → chunk-FCXTZVJG.js} +3 -3
  20. package/dist/{chunk-UOERQDSJ.js → chunk-HGMX7LUU.js} +1 -1
  21. package/dist/{chunk-DQ3YBGNC.js → chunk-HPXXYGE5.js} +3 -3
  22. package/dist/{chunk-WTLJM7O2.js → chunk-KMJTUDQT.js} +3 -3
  23. package/dist/{chunk-5XPLGRCI.js → chunk-LWSO4XGK.js} +11 -11
  24. package/dist/{chunk-KS5K2JLY.js → chunk-NWCMSPVL.js} +1 -1
  25. package/dist/{chunk-UYR5Q3GS.js → chunk-NYT5K544.js} +1 -1
  26. package/dist/{chunk-UYR5Q3GS.js.map → chunk-NYT5K544.js.map} +1 -1
  27. package/dist/{chunk-DH6PY5WA.js → chunk-OPC7BAW5.js} +1 -1
  28. package/dist/{chunk-RIE2FUKS.js → chunk-PFTCTG5X.js} +2 -2
  29. package/dist/{chunk-7NTVKI6U.js → chunk-PKOEWHPC.js} +1 -1
  30. package/dist/{chunk-L4IPQYSY.js → chunk-S7FJMZJQ.js} +3 -3
  31. package/dist/{chunk-QOWU527O.js → chunk-U5SAUK33.js} +4 -4
  32. package/dist/{chunk-JIBQDOXO.js → chunk-VUWBPLA2.js} +1 -1
  33. package/dist/{chunk-DVRQKRHN.js → chunk-W5HDZPFZ.js} +2 -2
  34. package/dist/{chunk-ZS6GNOVF.js → chunk-XQVGT6FI.js} +2 -2
  35. package/dist/{chunk-TLCZFEI3.js → chunk-YMT4ZP5L.js} +3 -3
  36. package/dist/{chunk-DYHI3HU4.js → chunk-ZVXACFY4.js} +1 -1
  37. package/dist/{cli-74WUWFKO.js → cli-7F5UP7H3.js} +78 -78
  38. package/dist/commands-2B3NLK4I.js +46 -0
  39. package/dist/{config-KBJLBJ4F.js → config-NUGWMTAD.js} +4 -4
  40. package/dist/{context-SUQRQHNG.js → context-IU336CQN.js} +5 -5
  41. package/dist/{customCommands-4H5TDSCI.js → customCommands-H26PZL7C.js} +4 -4
  42. package/dist/{env-EBAMYGTP.js → env-XZ365TBZ.js} +2 -2
  43. package/dist/index.js +3 -3
  44. package/dist/{kodeAgentSessionLoad-OEYEYLKG.js → kodeAgentSessionLoad-3SQDQPTS.js} +4 -4
  45. package/dist/{kodeAgentSessionResume-53WMZDR6.js → kodeAgentSessionResume-URRDKPNQ.js} +4 -4
  46. package/dist/{kodeAgentStreamJsonSession-QQV52SDB.js → kodeAgentStreamJsonSession-DATEVTTG.js} +1 -1
  47. package/dist/{kodeHooks-LXHKYCVC.js → kodeHooks-QQUC3N42.js} +4 -4
  48. package/dist/{llm-5DSL623J.js → llm-XBH33BXT.js} +28 -28
  49. package/dist/{llm-5DSL623J.js.map → llm-XBH33BXT.js.map} +2 -2
  50. package/dist/{llmLazy-EMO4BVVB.js → llmLazy-HBMPPNDL.js} +1 -1
  51. package/dist/{loader-DSVKWJVQ.js → loader-2RC2FXT3.js} +4 -4
  52. package/dist/{mcp-3CCDCYYX.js → mcp-FBNQXOUB.js} +7 -7
  53. package/dist/{mentionProcessor-HRUF4ANP.js → mentionProcessor-S2QYN2CS.js} +5 -5
  54. package/dist/{messages-KZTRKY2I.js → messages-GOTZDIQV.js} +1 -1
  55. package/dist/{model-PHL6VTAG.js → model-B5TCGITV.js} +5 -5
  56. package/dist/{openai-M3RAQFGM.js → openai-HHXFBOUM.js} +5 -5
  57. package/dist/{outputStyles-6VVYMSWK.js → outputStyles-SER6OXBX.js} +4 -4
  58. package/dist/{pluginRuntime-TCH3K4F6.js → pluginRuntime-TJ55FZXH.js} +6 -6
  59. package/dist/{pluginValidation-X4A5NSMU.js → pluginValidation-JIVFSJJI.js} +6 -6
  60. package/dist/prompts-EL2VO3DH.js +50 -0
  61. package/dist/query-CMWS2UNL.js +50 -0
  62. package/dist/{ripgrep-TVXVT4WE.js → ripgrep-LJA652X4.js} +3 -3
  63. package/dist/{skillMarketplace-AXUCUS3B.js → skillMarketplace-MDN37RZ4.js} +3 -3
  64. package/dist/{state-SDEP3HY3.js → state-4L5XK2VN.js} +2 -2
  65. package/dist/{theme-SPQRPQ7O.js → theme-NNMEGAUR.js} +5 -5
  66. package/dist/{toolPermissionSettings-H6TWVANG.js → toolPermissionSettings-PAIDFMPX.js} +6 -6
  67. package/dist/tools-AZR4CVVE.js +47 -0
  68. package/dist/{userInput-QU3SH2SR.js → userInput-KMFH77N4.js} +27 -27
  69. package/package.json +1 -1
  70. package/dist/REPL-JPCWUTDB.js +0 -42
  71. package/dist/chunk-HJCCXED7.js.map +0 -7
  72. package/dist/chunk-QUV2YCUP.js.map +0 -7
  73. package/dist/commands-2ZN5PXG5.js +0 -46
  74. package/dist/prompts-IVLP5KLQ.js +0 -50
  75. package/dist/query-JIRCNAY5.js +0 -50
  76. package/dist/tools-G2P3XRE7.js +0 -47
  77. /package/dist/{REPL-JPCWUTDB.js.map → REPL-5VRUWUUA.js.map} +0 -0
  78. /package/dist/{acp-XPFY5L23.js.map → acp-SBV4SUS5.js.map} +0 -0
  79. /package/dist/{agentsValidate-YP7GA4ER.js.map → agentsValidate-GBCUUJ37.js.map} +0 -0
  80. /package/dist/{ask-F53PCNWW.js.map → ask-A44NOQXG.js.map} +0 -0
  81. /package/dist/{autoUpdater-PAZTRW74.js.map → autoUpdater-7XV25FPF.js.map} +0 -0
  82. /package/dist/{chunk-5GADLAR7.js.map → chunk-2ZWXQRFX.js.map} +0 -0
  83. /package/dist/{chunk-EOZSZNKR.js.map → chunk-3IXSSL3F.js.map} +0 -0
  84. /package/dist/{chunk-JKRPU66R.js.map → chunk-5GHO3SUE.js.map} +0 -0
  85. /package/dist/{chunk-5552MSXN.js.map → chunk-66P52YYI.js.map} +0 -0
  86. /package/dist/{chunk-3LC6LWSN.js.map → chunk-6Z7EGLJB.js.map} +0 -0
  87. /package/dist/{chunk-NFMXSWNI.js.map → chunk-CEARH7HF.js.map} +0 -0
  88. /package/dist/{chunk-CDS5HL6U.js.map → chunk-CSAIELUO.js.map} +0 -0
  89. /package/dist/{chunk-HJCCXED7.js → chunk-DKOCP6VD.js} +0 -0
  90. /package/dist/{chunk-LO3O7WT2.js.map → chunk-EPA5LFNP.js.map} +0 -0
  91. /package/dist/{chunk-2ON4OVWS.js.map → chunk-F4DQYOST.js.map} +0 -0
  92. /package/dist/{chunk-4FOB6KC5.js.map → chunk-FCXTZVJG.js.map} +0 -0
  93. /package/dist/{chunk-UOERQDSJ.js.map → chunk-HGMX7LUU.js.map} +0 -0
  94. /package/dist/{chunk-DQ3YBGNC.js.map → chunk-HPXXYGE5.js.map} +0 -0
  95. /package/dist/{chunk-WTLJM7O2.js.map → chunk-KMJTUDQT.js.map} +0 -0
  96. /package/dist/{chunk-5XPLGRCI.js.map → chunk-LWSO4XGK.js.map} +0 -0
  97. /package/dist/{chunk-KS5K2JLY.js.map → chunk-NWCMSPVL.js.map} +0 -0
  98. /package/dist/{chunk-DH6PY5WA.js.map → chunk-OPC7BAW5.js.map} +0 -0
  99. /package/dist/{chunk-RIE2FUKS.js.map → chunk-PFTCTG5X.js.map} +0 -0
  100. /package/dist/{chunk-7NTVKI6U.js.map → chunk-PKOEWHPC.js.map} +0 -0
  101. /package/dist/{chunk-L4IPQYSY.js.map → chunk-S7FJMZJQ.js.map} +0 -0
  102. /package/dist/{chunk-QOWU527O.js.map → chunk-U5SAUK33.js.map} +0 -0
  103. /package/dist/{chunk-JIBQDOXO.js.map → chunk-VUWBPLA2.js.map} +0 -0
  104. /package/dist/{chunk-DVRQKRHN.js.map → chunk-W5HDZPFZ.js.map} +0 -0
  105. /package/dist/{chunk-ZS6GNOVF.js.map → chunk-XQVGT6FI.js.map} +0 -0
  106. /package/dist/{chunk-TLCZFEI3.js.map → chunk-YMT4ZP5L.js.map} +0 -0
  107. /package/dist/{chunk-DYHI3HU4.js.map → chunk-ZVXACFY4.js.map} +0 -0
  108. /package/dist/{cli-74WUWFKO.js.map → cli-7F5UP7H3.js.map} +0 -0
  109. /package/dist/{commands-2ZN5PXG5.js.map → commands-2B3NLK4I.js.map} +0 -0
  110. /package/dist/{config-KBJLBJ4F.js.map → config-NUGWMTAD.js.map} +0 -0
  111. /package/dist/{context-SUQRQHNG.js.map → context-IU336CQN.js.map} +0 -0
  112. /package/dist/{customCommands-4H5TDSCI.js.map → customCommands-H26PZL7C.js.map} +0 -0
  113. /package/dist/{env-EBAMYGTP.js.map → env-XZ365TBZ.js.map} +0 -0
  114. /package/dist/{kodeAgentSessionLoad-OEYEYLKG.js.map → kodeAgentSessionLoad-3SQDQPTS.js.map} +0 -0
  115. /package/dist/{kodeAgentSessionResume-53WMZDR6.js.map → kodeAgentSessionResume-URRDKPNQ.js.map} +0 -0
  116. /package/dist/{kodeAgentStreamJsonSession-QQV52SDB.js.map → kodeAgentStreamJsonSession-DATEVTTG.js.map} +0 -0
  117. /package/dist/{kodeHooks-LXHKYCVC.js.map → kodeHooks-QQUC3N42.js.map} +0 -0
  118. /package/dist/{llmLazy-EMO4BVVB.js.map → llmLazy-HBMPPNDL.js.map} +0 -0
  119. /package/dist/{loader-DSVKWJVQ.js.map → loader-2RC2FXT3.js.map} +0 -0
  120. /package/dist/{mcp-3CCDCYYX.js.map → mcp-FBNQXOUB.js.map} +0 -0
  121. /package/dist/{mentionProcessor-HRUF4ANP.js.map → mentionProcessor-S2QYN2CS.js.map} +0 -0
  122. /package/dist/{messages-KZTRKY2I.js.map → messages-GOTZDIQV.js.map} +0 -0
  123. /package/dist/{model-PHL6VTAG.js.map → model-B5TCGITV.js.map} +0 -0
  124. /package/dist/{openai-M3RAQFGM.js.map → openai-HHXFBOUM.js.map} +0 -0
  125. /package/dist/{outputStyles-6VVYMSWK.js.map → outputStyles-SER6OXBX.js.map} +0 -0
  126. /package/dist/{pluginRuntime-TCH3K4F6.js.map → pluginRuntime-TJ55FZXH.js.map} +0 -0
  127. /package/dist/{pluginValidation-X4A5NSMU.js.map → pluginValidation-JIVFSJJI.js.map} +0 -0
  128. /package/dist/{prompts-IVLP5KLQ.js.map → prompts-EL2VO3DH.js.map} +0 -0
  129. /package/dist/{query-JIRCNAY5.js.map → query-CMWS2UNL.js.map} +0 -0
  130. /package/dist/{ripgrep-TVXVT4WE.js.map → ripgrep-LJA652X4.js.map} +0 -0
  131. /package/dist/{skillMarketplace-AXUCUS3B.js.map → skillMarketplace-MDN37RZ4.js.map} +0 -0
  132. /package/dist/{state-SDEP3HY3.js.map → state-4L5XK2VN.js.map} +0 -0
  133. /package/dist/{theme-SPQRPQ7O.js.map → theme-NNMEGAUR.js.map} +0 -0
  134. /package/dist/{toolPermissionSettings-H6TWVANG.js.map → toolPermissionSettings-PAIDFMPX.js.map} +0 -0
  135. /package/dist/{tools-G2P3XRE7.js.map → tools-AZR4CVVE.js.map} +0 -0
  136. /package/dist/{userInput-QU3SH2SR.js.map → userInput-KMFH77N4.js.map} +0 -0
@@ -2,7 +2,7 @@ import { createRequire as __kodeCreateRequire } from "node:module";
2
2
  const require = __kodeCreateRequire(import.meta.url);
3
3
  import {
4
4
  listDanyaAgentSessions
5
- } from "./chunk-DYHI3HU4.js";
5
+ } from "./chunk-ZVXACFY4.js";
6
6
  import {
7
7
  DEFAULT_TIMEOUT_MS,
8
8
  FallbackToolUseRejectedMessage,
@@ -16,11 +16,11 @@ import {
16
16
  listMCPServers,
17
17
  loadMergedSettings,
18
18
  normalizeSandboxRuntimeConfigFromSettings
19
- } from "./chunk-QOWU527O.js";
19
+ } from "./chunk-U5SAUK33.js";
20
20
  import {
21
21
  formatValidationResult,
22
22
  validatePluginOrMarketplacePath
23
- } from "./chunk-WTLJM7O2.js";
23
+ } from "./chunk-KMJTUDQT.js";
24
24
  import {
25
25
  addMarketplace,
26
26
  disableSkillPlugin,
@@ -33,15 +33,15 @@ import {
33
33
  refreshMarketplaceAsync,
34
34
  removeMarketplace,
35
35
  uninstallSkillPlugin
36
- } from "./chunk-3LC6LWSN.js";
36
+ } from "./chunk-6Z7EGLJB.js";
37
37
  import {
38
38
  loadDanyaAgentSessionMessages
39
- } from "./chunk-UOERQDSJ.js";
39
+ } from "./chunk-HGMX7LUU.js";
40
40
  import {
41
41
  appendSessionCustomTitleRecord,
42
42
  appendSessionJsonlFromMessage,
43
43
  appendSessionTagRecord
44
- } from "./chunk-2ON4OVWS.js";
44
+ } from "./chunk-F4DQYOST.js";
45
45
  import {
46
46
  getRequestStatus,
47
47
  setRequestStatus,
@@ -58,7 +58,7 @@ import {
58
58
  runStopHooks,
59
59
  runUserPromptSubmitHooks,
60
60
  updateHookTranscriptForMessages
61
- } from "./chunk-DQ3YBGNC.js";
61
+ } from "./chunk-HPXXYGE5.js";
62
62
  import {
63
63
  getDanyaAgentSessionId,
64
64
  setDanyaAgentSessionId
@@ -71,34 +71,34 @@ import {
71
71
  getOutputStyleSystemPromptAdditions,
72
72
  resolveOutputStyleName,
73
73
  setCurrentOutputStyle
74
- } from "./chunk-CDS5HL6U.js";
74
+ } from "./chunk-CSAIELUO.js";
75
75
  import {
76
76
  fetchCustomModels,
77
77
  getModelFeatures
78
- } from "./chunk-DVRQKRHN.js";
78
+ } from "./chunk-W5HDZPFZ.js";
79
79
  import {
80
80
  queryLLM,
81
81
  queryQuick,
82
82
  verifyApiKey
83
- } from "./chunk-JKRPU66R.js";
83
+ } from "./chunk-5GHO3SUE.js";
84
84
  import {
85
85
  listAllContentFiles,
86
86
  ripGrep
87
- } from "./chunk-5552MSXN.js";
87
+ } from "./chunk-66P52YYI.js";
88
88
  import {
89
89
  getCustomCommandDirectories,
90
90
  hasCustomCommands,
91
91
  loadCustomCommands,
92
92
  reloadCustomCommands
93
- } from "./chunk-LO3O7WT2.js";
93
+ } from "./chunk-EPA5LFNP.js";
94
94
  import {
95
95
  loadToolPermissionContextFromDisk,
96
96
  persistToolPermissionUpdateToDisk
97
- } from "./chunk-L4IPQYSY.js";
97
+ } from "./chunk-S7FJMZJQ.js";
98
98
  import {
99
99
  getSettingsFileCandidates,
100
100
  loadSettingsWithLegacyFallback
101
- } from "./chunk-5GADLAR7.js";
101
+ } from "./chunk-2ZWXQRFX.js";
102
102
  import {
103
103
  applyToolPermissionContextUpdate,
104
104
  createDefaultToolPermissionContext
@@ -111,7 +111,7 @@ import {
111
111
  resetReminderSession,
112
112
  setTodos,
113
113
  systemReminderService
114
- } from "./chunk-ZS6GNOVF.js";
114
+ } from "./chunk-XQVGT6FI.js";
115
115
  import {
116
116
  getSessionState
117
117
  } from "./chunk-XEYEKVFT.js";
@@ -120,7 +120,7 @@ import {
120
120
  getActiveAgents,
121
121
  getAgentByType,
122
122
  getAllAgents
123
- } from "./chunk-RIE2FUKS.js";
123
+ } from "./chunk-PFTCTG5X.js";
124
124
  import {
125
125
  getSessionPlugins
126
126
  } from "./chunk-2VQWLLDU.js";
@@ -154,22 +154,22 @@ import {
154
154
  processUserInput,
155
155
  reorderMessages,
156
156
  stripSystemMessages
157
- } from "./chunk-7NTVKI6U.js";
157
+ } from "./chunk-PKOEWHPC.js";
158
158
  import {
159
159
  ModelManager,
160
160
  getModelManager,
161
161
  isDefaultSlowAndCapableModel
162
- } from "./chunk-EOZSZNKR.js";
162
+ } from "./chunk-3IXSSL3F.js";
163
163
  import {
164
164
  getCodeStyle,
165
165
  getContext,
166
166
  getGitState,
167
167
  getIsGit,
168
168
  getProjectDocs
169
- } from "./chunk-4FOB6KC5.js";
169
+ } from "./chunk-FCXTZVJG.js";
170
170
  import {
171
171
  getTheme
172
- } from "./chunk-KS5K2JLY.js";
172
+ } from "./chunk-NWCMSPVL.js";
173
173
  import {
174
174
  DEFAULT_GLOBAL_CONFIG,
175
175
  enableConfigs,
@@ -182,7 +182,7 @@ import {
182
182
  saveGlobalConfig,
183
183
  setAllPointersToModel,
184
184
  setModelPointer
185
- } from "./chunk-NFMXSWNI.js";
185
+ } from "./chunk-CEARH7HF.js";
186
186
  import {
187
187
  AbortError
188
188
  } from "./chunk-HIIHGKXP.js";
@@ -191,7 +191,7 @@ import {
191
191
  getCurrentRequest,
192
192
  logUserFriendly,
193
193
  markPhase
194
- } from "./chunk-JIBQDOXO.js";
194
+ } from "./chunk-VUWBPLA2.js";
195
195
  import {
196
196
  ASCII_LOGO,
197
197
  BunShell,
@@ -236,11 +236,11 @@ import {
236
236
  renderBashNotification,
237
237
  setActivePlanConversationKey,
238
238
  setCwd
239
- } from "./chunk-DH6PY5WA.js";
239
+ } from "./chunk-OPC7BAW5.js";
240
240
  import {
241
241
  MACRO,
242
242
  init_macros
243
- } from "./chunk-UYR5Q3GS.js";
243
+ } from "./chunk-NYT5K544.js";
244
244
  import {
245
245
  formatTotalCost,
246
246
  getTotalAPIDuration,
@@ -251,15 +251,15 @@ import {
251
251
  import {
252
252
  __esm,
253
253
  __export,
254
- __require
254
+ __toCommonJS
255
255
  } from "./chunk-M3TKNAUR.js";
256
256
 
257
257
  // src/engine/detect.ts
258
- import { existsSync as existsSync15 } from "fs";
259
- import { join as join13 } from "path";
258
+ import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync9 } from "fs";
259
+ import { join as join6 } from "path";
260
260
  import { globSync } from "glob";
261
- function detectEngine(projectPath) {
262
- if (existsSync15(join13(projectPath, "ProjectSettings")) && existsSync15(join13(projectPath, "Assets"))) {
261
+ function detectEngine(projectPath, depth = 0) {
262
+ if (existsSync8(join6(projectPath, "ProjectSettings")) && existsSync8(join6(projectPath, "Assets"))) {
263
263
  return "unity";
264
264
  }
265
265
  try {
@@ -269,39 +269,42 @@ function detectEngine(projectPath) {
269
269
  }
270
270
  } catch {
271
271
  }
272
- if (existsSync15(join13(projectPath, "project.godot"))) {
272
+ if (existsSync8(join6(projectPath, "project.godot"))) {
273
273
  return "godot";
274
274
  }
275
- const parentCandidates = ["client", "server", "game-client", "game-server"];
276
- for (const candidate of parentCandidates) {
277
- const subPath = join13(projectPath, candidate);
278
- if (existsSync15(subPath)) {
279
- const subEngine = detectEngine(subPath);
280
- if (subEngine) return subEngine;
275
+ if (depth < 1) {
276
+ const subCandidates = ["client", "server", "game-client", "game-server"];
277
+ for (const candidate of subCandidates) {
278
+ const subPath = join6(projectPath, candidate);
279
+ if (existsSync8(subPath)) {
280
+ const subEngine = detectEngine(subPath, depth + 1);
281
+ if (subEngine) return subEngine;
282
+ }
281
283
  }
282
284
  }
283
285
  return null;
284
286
  }
285
- function detectServerLanguage(projectPath) {
286
- if (existsSync15(join13(projectPath, "go.mod"))) {
287
+ function detectServerLanguage(projectPath, depth = 0) {
288
+ if (existsSync8(join6(projectPath, "go.mod"))) {
287
289
  return "go";
288
290
  }
289
- if (existsSync15(join13(projectPath, "Makefile"))) {
291
+ if (existsSync8(join6(projectPath, "Makefile"))) {
290
292
  try {
291
- const { readFileSync: readFileSync11 } = __require("fs");
292
- const makefile = readFileSync11(join13(projectPath, "Makefile"), "utf-8");
293
+ const makefile = readFileSync6(join6(projectPath, "Makefile"), "utf-8");
293
294
  if (makefile.includes("go build") || makefile.includes("go test")) {
294
295
  return "go";
295
296
  }
296
297
  } catch {
297
298
  }
298
299
  }
299
- if (existsSync15(join13(projectPath, "CMakeLists.txt"))) {
300
+ if (existsSync8(join6(projectPath, "CMakeLists.txt"))) {
300
301
  return "cpp";
301
302
  }
302
- const serverDir = join13(projectPath, "server");
303
- if (existsSync15(serverDir) && projectPath !== serverDir) {
304
- return detectServerLanguage(serverDir);
303
+ if (depth < 1) {
304
+ const serverDir = join6(projectPath, "server");
305
+ if (existsSync8(serverDir)) {
306
+ return detectServerLanguage(serverDir, depth + 1);
307
+ }
305
308
  }
306
309
  return null;
307
310
  }
@@ -316,7 +319,6 @@ function detectLanguages(engine, serverLanguage) {
316
319
  break;
317
320
  case "godot":
318
321
  languages.push("GDScript");
319
- languages.push("C#");
320
322
  break;
321
323
  }
322
324
  switch (serverLanguage) {
@@ -340,20 +342,405 @@ function detectProject(projectPath) {
340
342
  const languages = detectLanguages(engine, serverLanguage);
341
343
  return { engine, serverLanguage, languages };
342
344
  }
345
+ function inferRole(name2, engine, serverLanguage) {
346
+ const lower = name2.toLowerCase();
347
+ if (lower.includes("client") || lower.includes("game-client")) return "client";
348
+ if (lower.includes("server") || lower.includes("game-server")) return "server";
349
+ if (lower.includes("shared") || lower.includes("common")) return "shared";
350
+ if (engine) return "client";
351
+ if (serverLanguage) return "server";
352
+ return "unknown";
353
+ }
354
+ function detectWorkspace(rootPath) {
355
+ const subProjects = [];
356
+ try {
357
+ const entries = readdirSync2(rootPath);
358
+ for (const entry of entries) {
359
+ if (entry.startsWith(".") || entry === "node_modules" || entry === "dist" || entry === "Docs" || entry === "Tools") continue;
360
+ const subPath = join6(rootPath, entry);
361
+ try {
362
+ if (!statSync9(subPath).isDirectory()) continue;
363
+ } catch {
364
+ continue;
365
+ }
366
+ const engine = detectEngine(subPath);
367
+ const serverLanguage = detectServerLanguage(subPath);
368
+ if (engine || serverLanguage) {
369
+ subProjects.push({
370
+ name: entry,
371
+ path: subPath,
372
+ engine,
373
+ serverLanguage,
374
+ role: inferRole(entry, engine, serverLanguage)
375
+ });
376
+ }
377
+ }
378
+ } catch {
379
+ }
380
+ if (subProjects.length >= 2) {
381
+ return { type: "workspace", rootPath, subProjects };
382
+ }
383
+ return { type: "single-project", rootPath, subProjects: [] };
384
+ }
343
385
  var init_detect = __esm({
344
386
  "src/engine/detect.ts"() {
345
387
  }
346
388
  });
347
389
 
390
+ // src/templates/bundles/common.ts
391
+ var common_exports = {};
392
+ __export(common_exports, {
393
+ CMD_AUTO_BUGFIX: () => CMD_AUTO_BUGFIX,
394
+ CMD_AUTO_WORK: () => CMD_AUTO_WORK,
395
+ CMD_FIX_HARNESS: () => CMD_FIX_HARNESS,
396
+ CMD_PARALLEL_EXECUTE: () => CMD_PARALLEL_EXECUTE,
397
+ CMD_PLAN: () => CMD_PLAN,
398
+ CMD_REVIEW: () => CMD_REVIEW,
399
+ CMD_VERIFY: () => CMD_VERIFY,
400
+ HOOK_CONSTITUTION_GUARD: () => HOOK_CONSTITUTION_GUARD,
401
+ HOOK_HARNESS_EVOLUTION: () => HOOK_HARNESS_EVOLUTION,
402
+ HOOK_POST_COMMIT: () => HOOK_POST_COMMIT,
403
+ HOOK_PRE_COMMIT: () => HOOK_PRE_COMMIT,
404
+ HOOK_PUSH_GATE: () => HOOK_PUSH_GATE,
405
+ MEMORY_INDEX: () => MEMORY_INDEX,
406
+ RULE_ARCHITECTURE_BOUNDARIES: () => RULE_ARCHITECTURE_BOUNDARIES,
407
+ RULE_KNOWN_PITFALLS: () => RULE_KNOWN_PITFALLS
408
+ });
409
+ var CMD_AUTO_WORK, CMD_AUTO_BUGFIX, CMD_REVIEW, CMD_FIX_HARNESS, CMD_PLAN, CMD_VERIFY, CMD_PARALLEL_EXECUTE, RULE_KNOWN_PITFALLS, RULE_ARCHITECTURE_BOUNDARIES, MEMORY_INDEX, HOOK_CONSTITUTION_GUARD, HOOK_PRE_COMMIT, HOOK_POST_COMMIT, HOOK_PUSH_GATE, HOOK_HARNESS_EVOLUTION;
410
+ var init_common = __esm({
411
+ "src/templates/bundles/common.ts"() {
412
+ CMD_AUTO_WORK = `# /auto-work <requirement>
413
+
414
+ Full-auto development pipeline. Walks through the entire cycle without manual intervention.
415
+
416
+ ## Stages
417
+
418
+ ### Stage 0: Classify
419
+ Determine requirement type: bug | feature | refactor
420
+
421
+ ### Stage 1: Plan
422
+ - List all files to modify with 1-line intent per file
423
+ - If >3 tasks and parallelizable \u2192 switch to parallel mode
424
+
425
+ ### Stage 2: Code
426
+ - Modify files per plan
427
+ - After each file \u2192 compile check immediately (fail-fast)
428
+ - After all: run /verify
429
+ - Verify fail \u2192 fix (max 3 rounds), else abort
430
+
431
+ ### Stage 3: Review
432
+ - Run /review (100-point scoring)
433
+ - CRITICAL \u2192 fail; <80 \u2192 fail
434
+ - Quality ratchet: score must not drop
435
+ - Pass \u2192 write push-approved marker
436
+
437
+ ### Stage 4: Commit
438
+ - git add + git commit
439
+ - Pre-commit hook runs lint + test
440
+ - Fail \u2192 fix and retry (max 2 times)
441
+
442
+ ### Stage 5: Knowledge Deposit
443
+ - Feature \u2192 Docs/Version/<version>/<feature>/summary.md
444
+ - Bug \u2192 Docs/Bugs/<version>/<bug-name>.md
445
+ - New module \u2192 Docs/Engine/Business/<module>/
446
+
447
+ ### Stage 6: Harness Self-Evolution
448
+ - Check for errors fixed in Stages 2-3
449
+ - If found \u2192 update .danya/rules/ to prevent recurrence
450
+
451
+ ## Termination Conditions
452
+ - Verify fail after 3 rounds (Stage 2)
453
+ - Review score <80 after 3 rounds (Stage 3)
454
+ - Commit fail after 2 attempts (Stage 4)
455
+
456
+ ## Important
457
+ - Do NOT push. Push is manual after human review.
458
+ - Do NOT skip stages. Each stage must complete before next.
459
+ `;
460
+ CMD_AUTO_BUGFIX = `# /auto-bugfix <bug-description>
461
+
462
+ Autonomous bug-fix pipeline. Must reproduce before fixing.
463
+
464
+ ## Flow
465
+
466
+ ### Step 1: Reproduce
467
+ - Analyze bug description
468
+ - Find reproduction steps
469
+ - Verify the bug exists (compile, run test, check logs)
470
+ - If NOT reproducible \u2192 report and STOP
471
+
472
+ ### Step 2: Root Cause Analysis
473
+ - Trace from symptom to root cause
474
+ - Do NOT guess. Read code, check logs, add debug output if needed.
475
+
476
+ ### Step 3: Fix (max 5 rounds)
477
+ - Modify code to fix root cause
478
+ - Run /verify after each fix attempt
479
+ - If verify fails \u2192 analyze why and try again
480
+ - If 5 rounds exhausted \u2192 report failure
481
+
482
+ ### Step 4: Review + Commit
483
+ - Run /review (must pass \u226580, no CRITICAL)
484
+ - git commit with descriptive message
485
+
486
+ ### Step 5: Knowledge Deposit
487
+ - Write to Docs/Bugs/<version>/<bug-name>.md
488
+ - Include: reproduction steps, root cause, fix, lessons learned
489
+
490
+ ### Step 6: Harness Evolution
491
+ - If this bug type isn't in known-pitfalls.md \u2192 add it
492
+ `;
493
+ CMD_REVIEW = `# /review
494
+
495
+ Score-based code review. Quantitative, not subjective.
496
+
497
+ ## Pre-check
498
+ Run /verify first. If verify fails, fix before reviewing.
499
+
500
+ ## Scoring System
501
+ - Initial score: 100
502
+ - CRITICAL: -30 each (any CRITICAL = automatic FAIL)
503
+ - HIGH: -10 each
504
+ - MEDIUM: -3 each
505
+ - Pass threshold: \u226580 AND no CRITICAL
506
+
507
+ ## Check Categories
508
+
509
+ ### 1. Architecture Compliance (mechanical + AI)
510
+ - Forbidden file edits (constitution)?
511
+ - Cross-layer imports?
512
+ - Package boundary violations?
513
+
514
+ ### 2. Coding Standards (mechanical + AI)
515
+ - Engine-specific style violations?
516
+ - Error handling patterns?
517
+ - Naming conventions?
518
+
519
+ ### 3. Logic Review (AI only)
520
+ - Intent clarity
521
+ - Error propagation
522
+ - Concurrency safety
523
+ - Edge cases
524
+ - Dead code
525
+
526
+ ### 4. Harness Completeness
527
+ - Were errors fixed during development?
528
+ - Did rules get updated to match?
529
+
530
+ ## Quality Ratchet
531
+ Score must not drop compared to previous review. If it drops, the fix introduced regressions.
532
+
533
+ ## Output
534
+ On PASS: write .danya/push-approved marker (one-time use).
535
+ On FAIL: list all issues with severity, do NOT write marker.
536
+ `;
537
+ CMD_FIX_HARNESS = `# /fix-harness [error-description]
538
+
539
+ Update harness rules after discovering an error pattern.
540
+
541
+ ## Process
542
+
543
+ 1. Analyze the error that occurred
544
+ 2. Route to the correct rule file:
545
+ - Forbidden zone violation \u2192 constitution.md
546
+ - Coding principle violation \u2192 golden-principles.md
547
+ - Known pitfall re-occurrence \u2192 known-pitfalls.md
548
+ - Architecture boundary violation \u2192 architecture-boundaries.md
549
+ - Style issue \u2192 engine-style rule file
550
+ 3. Add a concise rule:
551
+ - \u274C What went wrong (with example)
552
+ - \u2705 Correct approach (with example)
553
+ 4. If mechanically checkable \u2192 add to /verify checks
554
+ 5. Check total rule file lines < 550 (if exceeded, consolidate)
555
+
556
+ ## Important
557
+ - Only add NEW patterns not already captured
558
+ - Keep rules minimal: one error = one rule
559
+ - Include correct-usage example, not just prohibition
560
+ `;
561
+ CMD_PLAN = `# /plan <requirement>
562
+
563
+ Analyze requirement and create a development plan.
564
+
565
+ ## Output Format
566
+
567
+ ### 1. Requirement Analysis
568
+ - What needs to change and why
569
+ - Scope assessment
570
+
571
+ ### 2. File Checklist
572
+ For each file to modify:
573
+ - File path
574
+ - 1-line description of changes
575
+ - Risk level (low/medium/high)
576
+
577
+ ### 3. Execution Order
578
+ - Dependencies between changes
579
+ - Which files can be modified in parallel
580
+ - Which must be sequential
581
+
582
+ ### 4. Verification Strategy
583
+ - How to verify each change works
584
+ - Integration test approach
585
+
586
+ ## Rules
587
+ - Read existing code before planning changes
588
+ - Check architecture boundaries before proposing cross-layer changes
589
+ - Flag any forbidden zone files that would need regeneration
590
+ `;
591
+ CMD_VERIFY = `# /verify [level]
592
+
593
+ Mechanical verification checks. Levels: quick | build | full
594
+
595
+ ## quick (default)
596
+ - Lint check
597
+ - Syntax check (engine-specific)
598
+
599
+ ## build
600
+ - Everything in quick
601
+ - Full compilation/build
602
+
603
+ ## full
604
+ - Everything in build
605
+ - Run tests
606
+ - Architecture boundary check
607
+
608
+ ## Important
609
+ - Run this BEFORE /review
610
+ - If verify fails, fix issues before reviewing
611
+ - Exit with clear pass/fail and error details
612
+ `;
613
+ CMD_PARALLEL_EXECUTE = `# /parallel-execute <mode> <description>
614
+
615
+ Wave-based parallel task execution.
616
+
617
+ ## Modes
618
+ - prepare: Decompose task into sub-tasks with dependency declarations
619
+ - execute: Run prepared tasks in parallel waves
620
+
621
+ ## Prepare Mode
622
+ Create task files in .danya/exec-plans/active/:
623
+ - task-01.md, task-02.md, etc.
624
+ - Each has YAML frontmatter with \`depends: []\` field
625
+ - Tasks with no dependencies \u2192 Wave 1
626
+ - Tasks depending on Wave 1 \u2192 Wave 2, etc.
627
+
628
+ ## Execute Mode
629
+ - Parse dependency DAG \u2192 compute waves
630
+ - Wave 1: run all independent tasks in parallel (separate worktrees)
631
+ - Collect results, merge successful tasks
632
+ - Wave 2: run next batch
633
+ - Continue until all waves complete
634
+ - Run /verify full on integrated code
635
+
636
+ ## Rules
637
+ - Each task must be atomic (can succeed/fail independently)
638
+ - Failed task \u2192 rollback its worktree, don't affect others
639
+ - Cyclic dependencies \u2192 error, re-decompose
640
+ `;
641
+ RULE_KNOWN_PITFALLS = `# Known Pitfalls
642
+
643
+ Real errors encountered during development. Each entry prevents the same mistake.
644
+
645
+ _This file grows through harness self-evolution. Start empty, fill as errors occur._
646
+ `;
647
+ RULE_ARCHITECTURE_BOUNDARIES = `# Architecture Boundaries
648
+
649
+ Dependency direction rules. Higher layers can import lower layers, not vice versa.
650
+
651
+ ## General Principle
652
+ - One-way dependencies: lower layers must NOT reference higher layers
653
+ - Cross-module communication through events/interfaces, not direct references
654
+
655
+ _Customize with your project's actual layer structure._
656
+ `;
657
+ MEMORY_INDEX = `# Project Memory
658
+
659
+ Persistent domain knowledge. Updated as the agent learns about this project.
660
+
661
+ _Memory files are auto-loaded each session and survive context compression._
662
+ `;
663
+ HOOK_CONSTITUTION_GUARD = `#!/bin/bash
664
+ # Gate 0: GUARD \u2014 forbidden zone check. Exit 2 = block.
665
+ INPUT=$(cat)
666
+ FILE_PATH=$(echo "$INPUT" | sed -n 's/.*"file_path"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
667
+ [ -z "$FILE_PATH" ] && exit 0
668
+ FILE_PATH=$(echo "$FILE_PATH" | sed 's/\\\\\\\\/\\//g')
669
+ RULES=".danya/guard-rules.json"
670
+ [ ! -f "$RULES" ] && exit 0
671
+ while IFS= read -r p; do
672
+ p=$(echo "$p" | tr -d '"' | tr -d ' ')
673
+ [ -z "$p" ] && continue
674
+ if echo "$FILE_PATH" | grep -qE "$p" 2>/dev/null; then
675
+ echo "{\\"systemMessage\\":\\"\u274C GUARD: $FILE_PATH is in forbidden zone ($p). Edit the source data and regenerate instead.\\"}"
676
+ exit 2
677
+ fi
678
+ done < <(grep '"pattern"' "$RULES" | sed 's/.*"pattern"\\s*:\\s*"//;s/".*//')
679
+ exit 0
680
+ `;
681
+ HOOK_PRE_COMMIT = `#!/bin/bash
682
+ # Gate 3: COMMIT \u2014 pre-commit lint + test. Exit 2 = block.
683
+ INPUT=$(cat)
684
+ CMD=$(echo "$INPUT" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
685
+ echo "$CMD" | grep -qE 'git\\s+commit' || exit 0
686
+ if [ -f "Makefile" ]; then
687
+ make lint > /tmp/danya-lint.log 2>&1 || { echo "\u274C Lint failed" >&2; tail -10 /tmp/danya-lint.log >&2; exit 2; }
688
+ make test > /tmp/danya-test.log 2>&1 || { echo "\u274C Tests failed" >&2; tail -10 /tmp/danya-test.log >&2; exit 2; }
689
+ fi
690
+ exit 0
691
+ `;
692
+ HOOK_POST_COMMIT = `#!/bin/bash
693
+ # Gate 4: Post-commit review reminder. Always exit 0.
694
+ echo '{"systemMessage":"\u2705 Commit done. Run /review before push (score \u226580, no CRITICAL)."}'
695
+ exit 0
696
+ `;
697
+ HOOK_PUSH_GATE = `#!/bin/bash
698
+ # Gate 5: PUSH \u2014 check push-approved marker. Exit 2 = block.
699
+ INPUT=$(cat)
700
+ CMD=$(echo "$INPUT" | sed -n 's/.*"command"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
701
+ echo "$CMD" | grep -qE 'git[[:space:]]+push' || exit 0
702
+ MARKER=".danya/push-approved"
703
+ [ ! -f "$MARKER" ] && { echo "\u274C PUSH BLOCKED: run /review first" >&2; exit 2; }
704
+ rm -f "$MARKER"
705
+ exit 0
706
+ `;
707
+ HOOK_HARNESS_EVOLUTION = `#!/bin/bash
708
+ # PostToolUse: detect error-then-fix pattern for harness self-evolution.
709
+ # Reads tool result, checks if a previous error was just fixed.
710
+ # If so, injects a system message prompting the agent to update rules.
711
+ INPUT=$(cat)
712
+ TOOL_NAME=$(echo "$INPUT" | sed -n 's/.*"tool_name"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
713
+ EXIT_CODE=$(echo "$INPUT" | sed -n 's/.*"exit_code"[[:space:]]*:[[:space:]]*\\([0-9]*\\).*/\\1/p' 2>/dev/null)
714
+
715
+ # Track error state using project-scoped file (stable across hook invocations)
716
+ STATE_FILE=".danya/.error-state"
717
+
718
+ case "$TOOL_NAME" in
719
+ Bash)
720
+ if [ "$EXIT_CODE" != "0" ] && [ -n "$EXIT_CODE" ]; then
721
+ # Error occurred \u2014 record it
722
+ echo "error" > "$STATE_FILE" 2>/dev/null
723
+ elif [ -f "$STATE_FILE" ] && [ "$(cat "$STATE_FILE" 2>/dev/null)" = "error" ]; then
724
+ # Previous error, now success \u2014 fix confirmed
725
+ rm -f "$STATE_FILE"
726
+ echo '{"systemMessage":"Error was fixed. Consider running /fix-harness to update rules and prevent this error pattern in the future."}'
727
+ fi
728
+ ;;
729
+ esac
730
+ exit 0
731
+ `;
732
+ }
733
+ });
734
+
348
735
  // src/constants/prompts.ts
349
736
  init_env();
350
737
  init_state();
351
738
  init_product();
352
739
 
353
740
  // src/tools/system/BashTool/BashTool.tsx
354
- import { statSync as statSync12 } from "fs";
741
+ import { statSync as statSync15 } from "fs";
355
742
  import { EOL as EOL3 } from "os";
356
- import { isAbsolute as isAbsolute10, relative as relative13, resolve as resolve10 } from "path";
743
+ import { isAbsolute as isAbsolute10, relative as relative15, resolve as resolve10 } from "path";
357
744
  import * as React108 from "react";
358
745
  import { z as z16 } from "zod";
359
746
  init_product();
@@ -527,7 +914,7 @@ var getCommandSubcommandPrefix = memoize(
527
914
  var getCommandPrefix = memoize(
528
915
  async (command4, abortSignal) => {
529
916
  const { systemPrompt, userPrompt } = buildBashCommandPrefixDetectionPrompt(command4);
530
- const { API_ERROR_MESSAGE_PREFIX: API_ERROR_MESSAGE_PREFIX2, queryQuick: queryQuick2 } = await import("./llm-5DSL623J.js");
917
+ const { API_ERROR_MESSAGE_PREFIX: API_ERROR_MESSAGE_PREFIX2, queryQuick: queryQuick2 } = await import("./llm-XBH33BXT.js");
531
918
  const response = await queryQuick2({
532
919
  systemPrompt,
533
920
  userPrompt,
@@ -1623,11 +2010,11 @@ function isSensitiveFilePath(inputPath) {
1623
2010
  if (p.startsWith("\\\\") || p.startsWith("//")) return true;
1624
2011
  const absolutePath = resolveLikeCliPath(p);
1625
2012
  const parts = toPosixPath(absolutePath).split(POSIX_SEP);
1626
- const basename6 = parts[parts.length - 1] ?? "";
2013
+ const basename9 = parts[parts.length - 1] ?? "";
1627
2014
  for (const part of parts) {
1628
2015
  if (SENSITIVE_DIR_NAMES.has(toLower(part))) return true;
1629
2016
  }
1630
- if (basename6 && SENSITIVE_FILE_NAMES.has(toLower(basename6))) return true;
2017
+ if (basename9 && SENSITIVE_FILE_NAMES.has(toLower(basename9))) return true;
1631
2018
  return false;
1632
2019
  }
1633
2020
  function getSettingsPathsForWriteProtection(options) {
@@ -1708,13 +2095,13 @@ function isPathInWorkingDirectories(inputPath, context) {
1708
2095
  toPosixPath(resolvedCandidate)
1709
2096
  );
1710
2097
  const rootPosix = normalizeMacPrivatePrefix(toPosixPath(resolvedRoot));
1711
- const relative14 = posixRelative(
2098
+ const relative16 = posixRelative(
1712
2099
  toLower(rootPosix),
1713
2100
  toLower(candidatePosix)
1714
2101
  );
1715
- if (relative14 === "") return true;
1716
- if (hasParentTraversalSegment(relative14)) return false;
1717
- if (POSIX.isAbsolute(relative14)) return false;
2102
+ if (relative16 === "") return true;
2103
+ if (hasParentTraversalSegment(relative16)) return false;
2104
+ if (POSIX.isAbsolute(relative16)) return false;
1718
2105
  return true;
1719
2106
  });
1720
2107
  });
@@ -1817,9 +2204,9 @@ function matchPermissionRuleForPath(args) {
1817
2204
  }
1818
2205
  for (const [root, patternsMap] of grouped.entries()) {
1819
2206
  const baseRoot = root ?? getCwd();
1820
- const relative14 = posixRelative(baseRoot, targetPosix);
1821
- if (relative14.startsWith(`..${POSIX_SEP}`)) continue;
1822
- if (!relative14) continue;
2207
+ const relative16 = posixRelative(baseRoot, targetPosix);
2208
+ if (relative16.startsWith(`..${POSIX_SEP}`)) continue;
2209
+ if (!relative16) continue;
1823
2210
  const matchAll = patternsMap.get("/**")?.ruleString ?? patternsMap.get("**")?.ruleString ?? null;
1824
2211
  if (matchAll) return matchAll;
1825
2212
  const patterns = Array.from(patternsMap.keys()).map((pattern) => {
@@ -1833,7 +2220,7 @@ function matchPermissionRuleForPath(args) {
1833
2220
  return candidate;
1834
2221
  });
1835
2222
  const matcher = buildIgnoreMatcher(patterns);
1836
- const result = matcher.test(relative14);
2223
+ const result = matcher.test(relative16);
1837
2224
  if (!result.ignored || !result.rule) continue;
1838
2225
  let matched = result.rule.pattern;
1839
2226
  const matchedWithGlob = `${matched}/**`;
@@ -4596,7 +4983,7 @@ function formatParseError(error) {
4596
4983
  return error instanceof Error ? error.message : String(error);
4597
4984
  }
4598
4985
  async function defaultGateQuery(args) {
4599
- const { API_ERROR_MESSAGE_PREFIX: API_ERROR_MESSAGE_PREFIX2, queryLLM: queryLLM2 } = await import("./llm-5DSL623J.js");
4986
+ const { API_ERROR_MESSAGE_PREFIX: API_ERROR_MESSAGE_PREFIX2, queryLLM: queryLLM2 } = await import("./llm-XBH33BXT.js");
4600
4987
  const messages = [
4601
4988
  {
4602
4989
  type: "user",
@@ -10539,8 +10926,8 @@ var help_default = help;
10539
10926
  import * as React28 from "react";
10540
10927
  import { OrderedList } from "@inkjs/ui";
10541
10928
  import { Box as Box21, Text as Text24 } from "ink";
10542
- import { existsSync as existsSync8 } from "fs";
10543
- import { join as join6 } from "path";
10929
+ import { existsSync as existsSync13 } from "fs";
10930
+ import { join as join11 } from "path";
10544
10931
  import { homedir as homedir6 } from "os";
10545
10932
 
10546
10933
  // src/constants/releaseNotes.ts
@@ -10554,6 +10941,871 @@ var RELEASE_NOTES = {
10554
10941
  import { gt } from "semver";
10555
10942
  init_macros();
10556
10943
  init_product();
10944
+
10945
+ // src/ui/screens/autoInitHarness.ts
10946
+ import { existsSync as existsSync12 } from "fs";
10947
+ import { join as join10 } from "path";
10948
+
10949
+ // src/commands/initProject.ts
10950
+ init_detect();
10951
+ import { writeFileSync as writeFileSync6, existsSync as existsSync11 } from "fs";
10952
+ import { join as join9, basename as basename4 } from "path";
10953
+
10954
+ // src/templates/templateEngine.ts
10955
+ function renderTemplate(content, ctx) {
10956
+ return content.replace(/\{\{PROJECT_NAME\}\}/g, ctx.projectName).replace(/\{\{ENGINE\}\}/g, ctx.engine ?? "unknown").replace(/\{\{SERVER_LANG\}\}/g, ctx.serverLanguage ?? "none").replace(/\{\{CONFIG_GEN_PATH\}\}/g, ctx.configGenPath).replace(/\{\{FRAMEWORK_PATH\}\}/g, ctx.frameworkPath).replace(/\{\{PROTO_PATH\}\}/g, ctx.protoPath).replace(/\{\{ORM_PATH\}\}/g, ctx.ormPath).replace(/\{\{INSTRUCTIONS_FILE\}\}/g, ctx.instructionsFile);
10957
+ }
10958
+ function buildTemplateContext(projectName, engine, serverLanguage, instructionsFile) {
10959
+ let configGenPath = "Config/Gen/";
10960
+ let frameworkPath = "Scripts/Framework/";
10961
+ let protoPath = "Proto/";
10962
+ let ormPath = "orm/";
10963
+ if (engine === "unity") {
10964
+ configGenPath = "Assets/Scripts/Gameplay/Config/Gen/";
10965
+ frameworkPath = "Assets/Scripts/Framework/";
10966
+ protoPath = "Assets/Scripts/Proto/";
10967
+ } else if (engine === "unreal") {
10968
+ configGenPath = "Source/Generated/";
10969
+ frameworkPath = "Source/Core/";
10970
+ protoPath = "Source/Proto/";
10971
+ } else if (engine === "godot") {
10972
+ configGenPath = "scripts/generated/";
10973
+ frameworkPath = "scripts/core/";
10974
+ protoPath = "proto/";
10975
+ }
10976
+ if (serverLanguage === "go" && !engine) {
10977
+ configGenPath = "common/config/cfg_*.go";
10978
+ ormPath = "orm/(golang|redis|mongo)/";
10979
+ protoPath = "resources/proto/";
10980
+ }
10981
+ return { projectName, engine, serverLanguage, configGenPath, frameworkPath, protoPath, ormPath, instructionsFile };
10982
+ }
10983
+
10984
+ // src/templates/bundleInstaller.ts
10985
+ import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync4, existsSync as existsSync9 } from "fs";
10986
+ import { join as join7, dirname as dirname6 } from "path";
10987
+ function installBundle(targetDir, bundleContent, ctx, options = {}) {
10988
+ const installed = [];
10989
+ for (const [relativePath, content] of Object.entries(bundleContent)) {
10990
+ const isTemplate = relativePath.endsWith(".tmpl");
10991
+ const finalRelPath = isTemplate ? relativePath.replace(/\.tmpl$/, "") : relativePath;
10992
+ const finalPath = join7(targetDir, finalRelPath);
10993
+ const dir = dirname6(finalPath);
10994
+ if (!existsSync9(finalPath) || options.force) {
10995
+ mkdirSync5(dir, { recursive: true });
10996
+ const rendered = isTemplate ? renderTemplate(content, ctx) : content;
10997
+ writeFileSync4(finalPath, rendered, { encoding: "utf-8", mode: relativePath.includes("hooks/") ? 493 : 420 });
10998
+ installed.push(finalRelPath);
10999
+ }
11000
+ }
11001
+ return installed;
11002
+ }
11003
+
11004
+ // src/templates/bundles/unity.ts
11005
+ init_common();
11006
+ var UNITY_RULES_CONSTITUTION = `# Forbidden Zone Constitution
11007
+
11008
+ ## Auto-Generated Code (DO NOT edit manually)
11009
+ - \`{{CONFIG_GEN_PATH}}\` \u2014 Generated config. Edit Excel/data source \u2192 run ConfigGenerate.
11010
+ - \`*_pb.cs\` \u2014 Protobuf generated. Edit .proto \u2192 regenerate.
11011
+
11012
+ ## Framework Layer (requires approval)
11013
+ - \`{{FRAMEWORK_PATH}}\` \u2014 Core framework code. Modifying without understanding impacts all systems.
11014
+
11015
+ ## Art & Resource Directories
11016
+ - \`ArtResources/\`, \`PackResources/\` \u2014 Managed by art pipeline, not code.
11017
+ - \`.unity\` scene files \u2014 Binary, merge-unfriendly. Coordinate with team.
11018
+
11019
+ ## Third-Party Plugins
11020
+ - \`Assets/Plugins/\`, \`Assets/3rd/\` \u2014 No modification unless marked with [CUSTOM_MOD].
11021
+ `;
11022
+ var UNITY_RULES_GOLDEN_PRINCIPLES = `# Golden Principles \u2014 Unity/C#
11023
+
11024
+ Non-negotiable coding rules for this project.
11025
+
11026
+ ## Logging
11027
+ - \u274C \`Debug.Log\`, \`Debug.LogWarning\`, \`Debug.LogError\`
11028
+ - \u2705 Use project logger (MLog or equivalent)
11029
+
11030
+ ## Async
11031
+ - \u274C \`System.Threading.Tasks.Task\`, \`async/await\` with Task
11032
+ - \u2705 \`UniTask\` for all async operations
11033
+
11034
+ ## Object Lifecycle
11035
+ - \u274C \`Destroy()\` on pooled objects
11036
+ - \u2705 \`ObjectPoolUtility.Return()\` or equivalent pool API
11037
+
11038
+ ## Events
11039
+ - Subscribe in \`OnEnable()\` / initialization
11040
+ - Unsubscribe in \`OnDisable()\` / cleanup
11041
+ - \u274C Unmatched Subscribe without Unsubscribe \u2192 memory leak
11042
+
11043
+ ## Architecture
11044
+ - One-way dependencies: Framework \u2190 Gameplay \u2190 Renderer \u2190 Tools
11045
+ - \u274C Lower layer referencing higher layer
11046
+ - \u2705 Cross-module communication through EventManager/interfaces
11047
+
11048
+ ## Null Safety
11049
+ - Always null-check GetComponent<T>() results
11050
+ - Use TryGetComponent<T>() where possible
11051
+ - Never assume Find() returns non-null
11052
+ `;
11053
+ var UNITY_RULES_STYLE = `# Unity C# Style Guide
11054
+
11055
+ ## Naming
11056
+ - Classes/Structs: PascalCase
11057
+ - Methods: PascalCase
11058
+ - Private fields: _camelCase with underscore prefix
11059
+ - Public properties: PascalCase
11060
+ - Constants: UPPER_SNAKE_CASE
11061
+ - Enums: PascalCase (members too)
11062
+
11063
+ ## File Organization
11064
+ - One primary class per file
11065
+ - File name matches class name
11066
+ - Namespace matches directory structure
11067
+
11068
+ ## MonoBehaviour
11069
+ - Lifecycle order: Awake \u2192 OnEnable \u2192 Start \u2192 Update \u2192 OnDisable \u2192 OnDestroy
11070
+ - Heavy init in Awake, subscriptions in OnEnable
11071
+ - Never call Destroy() in Awake or OnEnable
11072
+ `;
11073
+ var UNITY_MEMORY_ARCHITECTURE = `---
11074
+ name: architecture-layers
11075
+ description: Unity project layer structure and dependencies
11076
+ type: project
11077
+ ---
11078
+
11079
+ ## Layer Structure
11080
+
11081
+ | Layer | Responsibility | Can Reference |
11082
+ |-------|---------------|---------------|
11083
+ | Framework | Core systems, managers, utilities | Nothing above |
11084
+ | Gameplay | Game logic, features, handlers | Framework |
11085
+ | Renderer | Visual, UI, effects | Framework, Gameplay |
11086
+ | Tools | Editor tools, debug utilities | All layers |
11087
+
11088
+ _Update this with your project's actual architecture as you learn it._
11089
+ `;
11090
+ var UNITY_HOOK_SYNTAX = `#!/bin/bash
11091
+ # Gate 1: SYNTAX \u2014 post-edit C# syntax check.
11092
+ INPUT=$(cat)
11093
+ FILE_PATH=$(echo "$INPUT" | sed -n 's/.*"file_path"[[:space:]]*:[[:space:]]*"\\([^"]*\\)".*/\\1/p' 2>/dev/null)
11094
+ [ -z "$FILE_PATH" ] && exit 0
11095
+ echo "$FILE_PATH" | grep -qE '\\.cs$' || exit 0
11096
+ # If dotnet-csharp-syntax-check is available, use it
11097
+ if command -v dotnet-csharp-syntax-check &>/dev/null; then
11098
+ dotnet-csharp-syntax-check "$FILE_PATH" 2>&1 || true
11099
+ fi
11100
+ exit 0
11101
+ `;
11102
+ function getUnityBundle() {
11103
+ return {
11104
+ "rules/constitution.md.tmpl": UNITY_RULES_CONSTITUTION,
11105
+ "rules/golden-principles.md": UNITY_RULES_GOLDEN_PRINCIPLES,
11106
+ "rules/unity-csharp.md": UNITY_RULES_STYLE,
11107
+ "rules/known-pitfalls.md": RULE_KNOWN_PITFALLS,
11108
+ "rules/architecture-boundaries.md": RULE_ARCHITECTURE_BOUNDARIES,
11109
+ "commands/auto-work.md": CMD_AUTO_WORK,
11110
+ "commands/auto-bugfix.md": CMD_AUTO_BUGFIX,
11111
+ "commands/review.md": CMD_REVIEW,
11112
+ "commands/fix-harness.md": CMD_FIX_HARNESS,
11113
+ "commands/plan.md": CMD_PLAN,
11114
+ "commands/verify.md": CMD_VERIFY,
11115
+ "commands/parallel-execute.md": CMD_PARALLEL_EXECUTE,
11116
+ "memory/MEMORY.md": MEMORY_INDEX,
11117
+ "memory/architecture-layers.md": UNITY_MEMORY_ARCHITECTURE,
11118
+ "hooks/constitution-guard.sh": HOOK_CONSTITUTION_GUARD,
11119
+ "hooks/syntax-check.sh": UNITY_HOOK_SYNTAX,
11120
+ "hooks/pre-commit.sh": HOOK_PRE_COMMIT,
11121
+ "hooks/post-commit.sh": HOOK_POST_COMMIT,
11122
+ "hooks/push-gate.sh": HOOK_PUSH_GATE,
11123
+ "hooks/harness-evolution.sh": HOOK_HARNESS_EVOLUTION
11124
+ };
11125
+ }
11126
+
11127
+ // src/templates/bundles/goServer.ts
11128
+ init_common();
11129
+ var GO_RULES_CONSTITUTION = `# Forbidden Zone Constitution
11130
+
11131
+ ## Auto-Generated Code (DO NOT edit manually)
11132
+ - \`{{ORM_PATH}}\` \u2014 ORM generated from XML. Edit XML \u2192 run ORM generator.
11133
+ - \`{{CONFIG_GEN_PATH}}\` \u2014 Config generated from game data. Edit data source \u2192 regenerate.
11134
+ - \`*_service.go\`, \`*_client.go\` \u2014 Protobuf RPC wrappers. Edit .proto \u2192 protoc.
11135
+
11136
+ ## Git Submodules (edit in upstream repo)
11137
+ - \`base/\` \u2014 Shared base library. Edit in the base repo, then update submodule.
11138
+ - \`{{PROTO_PATH}}\` \u2014 Proto definitions. Edit in proto repo.
11139
+
11140
+ ## Important
11141
+ When you see these files, tell the user HOW to regenerate instead of editing directly.
11142
+ `;
11143
+ var GO_RULES_GOLDEN_PRINCIPLES = `# Golden Principles \u2014 Go Server
11144
+
11145
+ Non-negotiable coding rules.
11146
+
11147
+ ## Error Handling
11148
+ - \u274C \`_ = err\` (errcheck enforced)
11149
+ - \u274C \`fmt.Errorf("...")\` without %w
11150
+ - \u2705 \`fmt.Errorf("context: %w", err)\` \u2014 always wrap errors
11151
+
11152
+ ## RPC Handlers
11153
+ - \u274C Log error + return error (double reporting)
11154
+ - \u2705 RPC handler: catch error \u2192 return RpcError, no log
11155
+ - \u2705 Internal logic: log.Errorf + return err
11156
+
11157
+ ## Goroutines
11158
+ - \u274C Bare \`go func() { ... }()\`
11159
+ - \u2705 \`safego.Go(func() { ... })\` \u2014 panic recovery built-in
11160
+
11161
+ ## Atomics
11162
+ - \u274C \`sync/atomic\`
11163
+ - \u2705 \`go.uber.org/atomic\`
11164
+
11165
+ ## UUID
11166
+ - \u274C \`pborman/uuid\`
11167
+ - \u2705 \`google/uuid\`
11168
+
11169
+ ## Database Operations
11170
+ - \u274C Direct DB access from game logic
11171
+ - \u2705 All DB operations through db_server RPC
11172
+
11173
+ ## ECS (if applicable)
11174
+ - Components: data only, no logic
11175
+ - Systems: logic only, operate on components
11176
+ - \u274C Logic in components, data mutation outside systems
11177
+
11178
+ ## Workflow
11179
+ - Plan first for multi-file changes
11180
+ - Use TaskCreate for progress tracking
11181
+ - Use subagent for 5+ file searches
11182
+ `;
11183
+ var GO_RULES_STYLE = `# Go Style Guide
11184
+
11185
+ ## File Naming
11186
+ - snake_case for all .go files
11187
+ - _test.go suffix for tests
11188
+ - Group by feature, not by type
11189
+
11190
+ ## Error Handling
11191
+ - Check errors immediately after function call
11192
+ - Wrap with context: fmt.Errorf("operation: %w", err)
11193
+ - Don't ignore errors silently
11194
+
11195
+ ## Logging
11196
+ - log.Debugf \u2014 development only, verbose
11197
+ - log.Infof \u2014 normal operations
11198
+ - log.Warnf \u2014 recoverable issues
11199
+ - log.Errorf \u2014 errors that need attention
11200
+ - \u274C fmt.Println, fmt.Printf for logging
11201
+
11202
+ ## Testing
11203
+ - Table-driven tests preferred
11204
+ - go test ./... must pass before commit
11205
+ `;
11206
+ var GO_MEMORY_ARCHITECTURE = `---
11207
+ name: cluster-architecture
11208
+ description: Go microservices cluster structure
11209
+ type: project
11210
+ ---
11211
+
11212
+ ## Service Architecture
11213
+
11214
+ _Update this with your project's actual services as you learn them._
11215
+
11216
+ | Service | Role |
11217
+ |---------|------|
11218
+ | gate_server | Client connection, protocol decode |
11219
+ | logic_server | Game logic, state management |
11220
+ | scene_server | Scene/combat, ECS-based |
11221
+ | db_server | Database operations (all DB access goes here) |
11222
+
11223
+ ## Startup Order
11224
+ Services have dependency order. Check project docs or startup scripts.
11225
+
11226
+ ## RPC Call Chain
11227
+ Typical request flow: client \u2192 gate \u2192 logic \u2192 scene \u2192 db
11228
+ `;
11229
+ var GO_HOOK_VERIFY = `#!/bin/bash
11230
+ # Leveled verification for Go server.
11231
+ LEVEL=\${1:-quick}
11232
+ case "$LEVEL" in
11233
+ quick)
11234
+ go vet ./... 2>&1 || exit 1
11235
+ ;;
11236
+ build)
11237
+ go vet ./... 2>&1 || exit 1
11238
+ go build ./... 2>&1 || exit 1
11239
+ ;;
11240
+ full)
11241
+ go vet ./... 2>&1 || exit 1
11242
+ go build ./... 2>&1 || exit 1
11243
+ go test ./... 2>&1 || exit 1
11244
+ ;;
11245
+ esac
11246
+ exit 0
11247
+ `;
11248
+ function getGoServerBundle() {
11249
+ return {
11250
+ "rules/constitution.md.tmpl": GO_RULES_CONSTITUTION,
11251
+ "rules/golden-principles.md": GO_RULES_GOLDEN_PRINCIPLES,
11252
+ "rules/go-style.md": GO_RULES_STYLE,
11253
+ "rules/known-pitfalls.md": RULE_KNOWN_PITFALLS,
11254
+ "rules/architecture-boundaries.md": RULE_ARCHITECTURE_BOUNDARIES,
11255
+ "commands/auto-work.md": CMD_AUTO_WORK,
11256
+ "commands/auto-bugfix.md": CMD_AUTO_BUGFIX,
11257
+ "commands/review.md": CMD_REVIEW,
11258
+ "commands/fix-harness.md": CMD_FIX_HARNESS,
11259
+ "commands/plan.md": CMD_PLAN,
11260
+ "commands/verify.md": CMD_VERIFY,
11261
+ "commands/parallel-execute.md": CMD_PARALLEL_EXECUTE,
11262
+ "memory/MEMORY.md": MEMORY_INDEX,
11263
+ "memory/cluster-architecture.md": GO_MEMORY_ARCHITECTURE,
11264
+ "hooks/constitution-guard.sh": HOOK_CONSTITUTION_GUARD,
11265
+ "hooks/verify-server.sh": GO_HOOK_VERIFY,
11266
+ "hooks/pre-commit.sh": HOOK_PRE_COMMIT,
11267
+ "hooks/post-commit.sh": HOOK_POST_COMMIT,
11268
+ "hooks/push-gate.sh": HOOK_PUSH_GATE,
11269
+ "hooks/harness-evolution.sh": HOOK_HARNESS_EVOLUTION
11270
+ };
11271
+ }
11272
+
11273
+ // src/templates/bundles/unreal.ts
11274
+ init_common();
11275
+ var UE_RULES_CONSTITUTION = `# Forbidden Zone Constitution
11276
+
11277
+ ## Auto-Generated Code
11278
+ - \`{{CONFIG_GEN_PATH}}\` \u2014 Generated code. Do not edit manually.
11279
+ - \`Intermediate/\` \u2014 Build intermediates. Never commit or edit.
11280
+ - \`*.generated.h\` \u2014 UHT generated headers.
11281
+
11282
+ ## Engine Source
11283
+ - \`Engine/\` \u2014 Unreal Engine source. Modify only in engine fork.
11284
+ `;
11285
+ var UE_RULES_GOLDEN_PRINCIPLES = `# Golden Principles \u2014 Unreal C++
11286
+
11287
+ ## Memory Management
11288
+ - \u274C Raw \`new\` for UObjects
11289
+ - \u2705 \`NewObject<T>()\`, \`CreateDefaultSubobject<T>()\`
11290
+ - All UObject* references must have UPROPERTY()
11291
+
11292
+ ## Logging
11293
+ - \u274C printf, cout, std::cerr
11294
+ - \u2705 UE_LOG(LogCategory, Verbosity, TEXT("..."))
11295
+
11296
+ ## Threading
11297
+ - \u274C std::thread
11298
+ - \u2705 FRunnable, AsyncTask, FGraphEvent
11299
+
11300
+ ## Naming Conventions
11301
+ - F = Struct (FVector, FTransform)
11302
+ - U = UObject-derived (UActorComponent)
11303
+ - A = AActor-derived (ACharacter)
11304
+ - E = Enum (EMovementMode)
11305
+ - I = Interface (IInteractable)
11306
+ - b prefix for booleans (bIsActive)
11307
+
11308
+ ## Garbage Collection
11309
+ - Pointers in containers must be UPROPERTY() or AddToRoot()
11310
+ - Use TWeakObjectPtr for non-owning references
11311
+ - Never cache raw pointers to UObjects across frames
11312
+ `;
11313
+ var UE_RULES_STYLE = `# Unreal C++ Style Guide
11314
+
11315
+ ## Headers
11316
+ - #pragma once (not include guards)
11317
+ - Engine headers before project headers
11318
+ - Minimal includes in headers, forward-declare where possible
11319
+
11320
+ ## Code Organization
11321
+ - .h in Public/, .cpp in Private/
11322
+ - One class per file pair
11323
+ - Module boundaries respected
11324
+ `;
11325
+ function getUnrealBundle() {
11326
+ return {
11327
+ "rules/constitution.md.tmpl": UE_RULES_CONSTITUTION,
11328
+ "rules/golden-principles.md": UE_RULES_GOLDEN_PRINCIPLES,
11329
+ "rules/unreal-cpp.md": UE_RULES_STYLE,
11330
+ "rules/known-pitfalls.md": RULE_KNOWN_PITFALLS,
11331
+ "rules/architecture-boundaries.md": RULE_ARCHITECTURE_BOUNDARIES,
11332
+ "commands/auto-work.md": CMD_AUTO_WORK,
11333
+ "commands/auto-bugfix.md": CMD_AUTO_BUGFIX,
11334
+ "commands/review.md": CMD_REVIEW,
11335
+ "commands/fix-harness.md": CMD_FIX_HARNESS,
11336
+ "commands/plan.md": CMD_PLAN,
11337
+ "commands/verify.md": CMD_VERIFY,
11338
+ "commands/parallel-execute.md": CMD_PARALLEL_EXECUTE,
11339
+ "memory/MEMORY.md": MEMORY_INDEX,
11340
+ "hooks/constitution-guard.sh": HOOK_CONSTITUTION_GUARD,
11341
+ "hooks/pre-commit.sh": HOOK_PRE_COMMIT,
11342
+ "hooks/post-commit.sh": HOOK_POST_COMMIT,
11343
+ "hooks/push-gate.sh": HOOK_PUSH_GATE,
11344
+ "hooks/harness-evolution.sh": HOOK_HARNESS_EVOLUTION
11345
+ };
11346
+ }
11347
+
11348
+ // src/templates/bundles/godot.ts
11349
+ init_common();
11350
+ var GODOT_RULES_CONSTITUTION = `# Forbidden Zone Constitution
11351
+
11352
+ ## Auto-Generated Code
11353
+ - \`{{CONFIG_GEN_PATH}}\` \u2014 Generated scripts. Edit source data \u2192 regenerate.
11354
+ - \`.import/\` \u2014 Godot import cache. Never edit or commit.
11355
+
11356
+ ## Addons
11357
+ - \`addons/\` \u2014 Third-party plugins. Do not modify unless forked.
11358
+ `;
11359
+ var GODOT_RULES_GOLDEN_PRINCIPLES = `# Golden Principles \u2014 Godot/GDScript
11360
+
11361
+ ## Type Hints
11362
+ - \u2705 All function parameters and return types must have type hints
11363
+ - \u274C Untyped \`func process(delta)\`
11364
+ - \u2705 \`func _process(delta: float) -> void\`
11365
+
11366
+ ## Signals
11367
+ - Connect in \`_ready()\`
11368
+ - Disconnect in \`_exit_tree()\`
11369
+ - \u274C Unmatched connect without disconnect
11370
+
11371
+ ## Physics
11372
+ - \u274C Movement in \`_process()\`
11373
+ - \u2705 Movement in \`_physics_process()\`
11374
+
11375
+ ## Node References
11376
+ - \u274C Hardcoded paths: \`get_node("../Player/Sprite")\`
11377
+ - \u2705 @onready var + @export for configurable references
11378
+
11379
+ ## Resource Loading
11380
+ - \u274C \`load()\` at runtime for large resources
11381
+ - \u2705 \`preload()\` for small, always-needed resources
11382
+ - \u2705 \`ResourceLoader.load_threaded_request()\` for large resources
11383
+ `;
11384
+ var GODOT_RULES_STYLE = `# GDScript Style Guide
11385
+
11386
+ ## Naming
11387
+ - Classes: PascalCase
11388
+ - Functions/variables: snake_case
11389
+ - Constants: UPPER_SNAKE_CASE
11390
+ - Signals: snake_case (past tense: health_changed, item_picked_up)
11391
+ - Private: underscore prefix (_internal_method)
11392
+
11393
+ ## File Organization
11394
+ - One script per node/scene where possible
11395
+ - Autoloads for global systems
11396
+ - Class name matches file name
11397
+ `;
11398
+ function getGodotBundle() {
11399
+ return {
11400
+ "rules/constitution.md.tmpl": GODOT_RULES_CONSTITUTION,
11401
+ "rules/golden-principles.md": GODOT_RULES_GOLDEN_PRINCIPLES,
11402
+ "rules/godot-gdscript.md": GODOT_RULES_STYLE,
11403
+ "rules/known-pitfalls.md": RULE_KNOWN_PITFALLS,
11404
+ "rules/architecture-boundaries.md": RULE_ARCHITECTURE_BOUNDARIES,
11405
+ "commands/auto-work.md": CMD_AUTO_WORK,
11406
+ "commands/auto-bugfix.md": CMD_AUTO_BUGFIX,
11407
+ "commands/review.md": CMD_REVIEW,
11408
+ "commands/fix-harness.md": CMD_FIX_HARNESS,
11409
+ "commands/plan.md": CMD_PLAN,
11410
+ "commands/verify.md": CMD_VERIFY,
11411
+ "commands/parallel-execute.md": CMD_PARALLEL_EXECUTE,
11412
+ "memory/MEMORY.md": MEMORY_INDEX,
11413
+ "hooks/constitution-guard.sh": HOOK_CONSTITUTION_GUARD,
11414
+ "hooks/pre-commit.sh": HOOK_PRE_COMMIT,
11415
+ "hooks/post-commit.sh": HOOK_POST_COMMIT,
11416
+ "hooks/push-gate.sh": HOOK_PUSH_GATE,
11417
+ "hooks/harness-evolution.sh": HOOK_HARNESS_EVOLUTION
11418
+ };
11419
+ }
11420
+
11421
+ // src/templates/bundles/workspace.ts
11422
+ init_common();
11423
+ var WORKSPACE_MEMORY_CROSS_PROJECT = `---
11424
+ name: cross-project-protocol
11425
+ description: Cross-project protocol and data sync rules
11426
+ type: project
11427
+ ---
11428
+
11429
+ ## Cross-Project Sync Points
11430
+
11431
+ _Update as you discover sync boundaries between sub-projects._
11432
+
11433
+ ### Protobuf
11434
+ - Proto definitions are shared between client and server
11435
+ - Edit .proto \u2192 regenerate both sides
11436
+ - Check field number compatibility when adding fields
11437
+
11438
+ ### Config Tables
11439
+ - Config data flows: Data Source \u2192 Generator \u2192 Client code + Server code
11440
+ - Both sides must regenerate when schema changes
11441
+
11442
+ ### Version Compatibility
11443
+ - Client and server versions must match on protocol level
11444
+ - Breaking changes require coordinated release
11445
+ `;
11446
+ var WORKSPACE_MEMORY_PITFALLS = `---
11447
+ name: cross-project-pitfalls
11448
+ description: Common mistakes when working across sub-projects
11449
+ type: project
11450
+ ---
11451
+
11452
+ ## Cross-Project Pitfalls
11453
+
11454
+ _This file grows through harness self-evolution._
11455
+
11456
+ ### Proto Field Number Conflicts
11457
+ - \u274C Reusing deleted field numbers
11458
+ - \u2705 Reserve deleted field numbers, always use new ones
11459
+
11460
+ ### Config Schema Drift
11461
+ - \u274C Changing config format on one side only
11462
+ - \u2705 Update generator, regenerate both client and server
11463
+ `;
11464
+ function getWorkspaceBundle() {
11465
+ return {
11466
+ "commands/fix-harness.md": CMD_FIX_HARNESS,
11467
+ "commands/plan.md": CMD_PLAN,
11468
+ "memory/MEMORY.md": MEMORY_INDEX,
11469
+ "memory/cross-project-protocol.md": WORKSPACE_MEMORY_CROSS_PROJECT,
11470
+ "memory/cross-project-pitfalls.md": WORKSPACE_MEMORY_PITFALLS
11471
+ };
11472
+ }
11473
+
11474
+ // src/templates/index.ts
11475
+ function getBundleForEngine(engine, serverLanguage) {
11476
+ if (engine === "unity") return getUnityBundle();
11477
+ if (engine === "unreal") return getUnrealBundle();
11478
+ if (engine === "godot") return getGodotBundle();
11479
+ if (serverLanguage === "go") return getGoServerBundle();
11480
+ const common = (init_common(), __toCommonJS(common_exports));
11481
+ return {
11482
+ "rules/known-pitfalls.md": common.RULE_KNOWN_PITFALLS,
11483
+ "rules/architecture-boundaries.md": common.RULE_ARCHITECTURE_BOUNDARIES,
11484
+ "commands/auto-work.md": common.CMD_AUTO_WORK,
11485
+ "commands/auto-bugfix.md": common.CMD_AUTO_BUGFIX,
11486
+ "commands/review.md": common.CMD_REVIEW,
11487
+ "commands/fix-harness.md": common.CMD_FIX_HARNESS,
11488
+ "commands/plan.md": common.CMD_PLAN,
11489
+ "commands/verify.md": common.CMD_VERIFY,
11490
+ "commands/parallel-execute.md": common.CMD_PARALLEL_EXECUTE,
11491
+ "memory/MEMORY.md": common.MEMORY_INDEX,
11492
+ "hooks/constitution-guard.sh": common.HOOK_CONSTITUTION_GUARD,
11493
+ "hooks/pre-commit.sh": common.HOOK_PRE_COMMIT,
11494
+ "hooks/post-commit.sh": common.HOOK_POST_COMMIT,
11495
+ "hooks/push-gate.sh": common.HOOK_PUSH_GATE,
11496
+ "hooks/harness-evolution.sh": common.HOOK_HARNESS_EVOLUTION
11497
+ };
11498
+ }
11499
+
11500
+ // src/services/harness/consolidate.ts
11501
+ import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, statSync as statSync11 } from "fs";
11502
+ import { join as join8 } from "path";
11503
+ var CONSOLIDATION_DIRS = ["rules", "commands", "memory", "skills", "hooks"];
11504
+ var LEGACY_DIRS = [".claude", ".codex"];
11505
+ function consolidateLegacyIntoDanya(projectDir) {
11506
+ const danyaDir = join8(projectDir, ".danya");
11507
+ const result = { merged: [], skipped: [], sources: [] };
11508
+ for (const legacyName of LEGACY_DIRS) {
11509
+ const legacyDir = join8(projectDir, legacyName);
11510
+ if (!existsSync10(legacyDir)) continue;
11511
+ result.sources.push(legacyName);
11512
+ for (const subDir of CONSOLIDATION_DIRS) {
11513
+ const legacySub = join8(legacyDir, subDir);
11514
+ if (!existsSync10(legacySub)) continue;
11515
+ const danyaSub = join8(danyaDir, subDir);
11516
+ mkdirSync6(danyaSub, { recursive: true });
11517
+ copyMissing(legacySub, danyaSub, subDir, result);
11518
+ }
11519
+ mergeSettings(legacyDir, danyaDir, result);
11520
+ }
11521
+ return result;
11522
+ }
11523
+ function copyMissing(legacyDir, danyaDir, prefix, result) {
11524
+ let entries;
11525
+ try {
11526
+ entries = readdirSync4(legacyDir);
11527
+ } catch {
11528
+ return;
11529
+ }
11530
+ for (const entry of entries) {
11531
+ const legacyPath = join8(legacyDir, entry);
11532
+ const danyaPath = join8(danyaDir, entry);
11533
+ try {
11534
+ if (statSync11(legacyPath).isDirectory()) {
11535
+ mkdirSync6(danyaPath, { recursive: true });
11536
+ copyMissing(legacyPath, danyaPath, `${prefix}/${entry}`, result);
11537
+ continue;
11538
+ }
11539
+ } catch {
11540
+ continue;
11541
+ }
11542
+ const relPath = `${prefix}/${entry}`;
11543
+ if (existsSync10(danyaPath)) {
11544
+ result.skipped.push(relPath);
11545
+ } else {
11546
+ try {
11547
+ const content = readFileSync8(legacyPath);
11548
+ writeFileSync5(danyaPath, content, {
11549
+ mode: prefix === "hooks" ? 493 : 420
11550
+ });
11551
+ result.merged.push(relPath);
11552
+ } catch {
11553
+ }
11554
+ }
11555
+ }
11556
+ }
11557
+ function mergeSettings(legacyDir, danyaDir, result) {
11558
+ const legacySettings = join8(legacyDir, "settings.json");
11559
+ const danyaSettings = join8(danyaDir, "settings.json");
11560
+ if (!existsSync10(legacySettings)) return;
11561
+ let legacyConfig;
11562
+ let danyaConfig;
11563
+ try {
11564
+ legacyConfig = JSON.parse(readFileSync8(legacySettings, "utf-8"));
11565
+ } catch {
11566
+ return;
11567
+ }
11568
+ try {
11569
+ danyaConfig = existsSync10(danyaSettings) ? JSON.parse(readFileSync8(danyaSettings, "utf-8")) : {};
11570
+ } catch {
11571
+ danyaConfig = {};
11572
+ }
11573
+ if (legacyConfig.hooks) {
11574
+ if (!danyaConfig.hooks) danyaConfig.hooks = {};
11575
+ for (const [event, handlers] of Object.entries(legacyConfig.hooks)) {
11576
+ if (!danyaConfig.hooks[event]) {
11577
+ danyaConfig.hooks[event] = handlers;
11578
+ result.merged.push(`settings.json:hooks.${event}`);
11579
+ }
11580
+ }
11581
+ writeFileSync5(danyaSettings, JSON.stringify(danyaConfig, null, 2), "utf-8");
11582
+ }
11583
+ }
11584
+
11585
+ // src/commands/initProject.ts
11586
+ async function initDanyaProject(cwd2, force = false) {
11587
+ const danyaDir = join9(cwd2, ".danya");
11588
+ if (existsSync11(danyaDir) && !force) {
11589
+ return "\u26A0\uFE0F .danya/ already exists. Skipping initialization. Use --force to overwrite.";
11590
+ }
11591
+ const workspace = detectWorkspace(cwd2);
11592
+ const instructionsFile = isClaudeModel() ? "CLAUDE.md" : "AGENTS.md";
11593
+ if (workspace.type === "workspace") {
11594
+ return initWorkspace(cwd2, workspace.subProjects, instructionsFile, force);
11595
+ }
11596
+ return initSingleProject(cwd2, instructionsFile, force);
11597
+ }
11598
+ function initSingleProject(cwd2, instructionsFile, force) {
11599
+ const danyaDir = join9(cwd2, ".danya");
11600
+ const detection = detectProject(cwd2);
11601
+ const projectName = basename4(cwd2);
11602
+ const bundle = getBundleForEngine(detection.engine, detection.serverLanguage);
11603
+ const ctx = buildTemplateContext(projectName, detection.engine, detection.serverLanguage, instructionsFile);
11604
+ const installed = installBundle(danyaDir, bundle, ctx, { force });
11605
+ const guardRules = generateGuardRules(detection.engine, detection.serverLanguage);
11606
+ writeFileSync6(join9(danyaDir, "guard-rules.json"), JSON.stringify(guardRules, null, 2), "utf-8");
11607
+ writeFileSync6(join9(danyaDir, "gate-chain.json"), JSON.stringify({
11608
+ gates: {
11609
+ guard: { enabled: true },
11610
+ syntax: { enabled: true },
11611
+ verify: { enabled: true, default_level: "build" },
11612
+ commit: { enabled: true },
11613
+ review: { enabled: true },
11614
+ push: { enabled: true, require_review: true }
11615
+ }
11616
+ }, null, 2), "utf-8");
11617
+ writeFileSync6(join9(danyaDir, "settings.json"), JSON.stringify(generateSettings(), null, 2), "utf-8");
11618
+ const consolidation = consolidateLegacyIntoDanya(cwd2);
11619
+ writeInstructionsFile(cwd2, instructionsFile, detection.engine, detection.serverLanguage);
11620
+ const legacyMsg = consolidation.sources.length > 0 ? [` Legacy integrated: ${consolidation.sources.join(", ")} \u2192 .danya/ (${consolidation.merged.length} merged, ${consolidation.skipped.length} skipped)`] : [];
11621
+ return [
11622
+ "\u2705 Danya project initialized! (single-project mode)",
11623
+ "",
11624
+ `Detected: engine=${detection.engine ?? "none"}, server=${detection.serverLanguage ?? "none"}`,
11625
+ `Guard rules: ${guardRules.length} forbidden zone patterns`,
11626
+ `Harness files: ${installed.length} files installed`,
11627
+ "",
11628
+ "Created:",
11629
+ ` .danya/rules/ \u2014 ${countFiles(installed, "rules/")} constraint files`,
11630
+ ` .danya/commands/ \u2014 ${countFiles(installed, "commands/")} workflow commands`,
11631
+ ` .danya/memory/ \u2014 ${countFiles(installed, "memory/")} knowledge files`,
11632
+ ` .danya/hooks/ \u2014 ${countFiles(installed, "hooks/")} hook scripts`,
11633
+ " .danya/gate-chain.json \u2014 Gate chain configuration",
11634
+ " .danya/guard-rules.json \u2014 Forbidden zone patterns",
11635
+ " .danya/settings.json \u2014 Hook registration",
11636
+ ...legacyMsg,
11637
+ "",
11638
+ "Gate chain: Edit \u2192 Guard \u2192 Syntax \u2192 Verify \u2192 Commit \u2192 Review \u2192 Push",
11639
+ "",
11640
+ "Available commands:",
11641
+ " /auto-work <req> \u2014 Full-auto pipeline (plan\u2192code\u2192verify\u2192review\u2192commit\u2192sediment\u2192evolve)",
11642
+ " /auto-bugfix <bug> \u2014 Bug reproduction + auto-fix (max 5 rounds)",
11643
+ " /review \u2014 100-point scoring code review",
11644
+ " /fix-harness \u2014 Update rules after error pattern",
11645
+ " /plan <req> \u2014 Analysis and planning",
11646
+ " /verify [level] \u2014 Mechanical verification (quick|build|full)",
11647
+ "",
11648
+ "Next steps:",
11649
+ ` 1. Customize ${instructionsFile} with your project-specific rules`,
11650
+ " 2. Review .danya/rules/ and adjust to your project",
11651
+ " 3. Start developing: danya"
11652
+ ].join("\n");
11653
+ }
11654
+ function initWorkspace(rootPath, subProjects, instructionsFile, force) {
11655
+ const rootDanyaDir = join9(rootPath, ".danya");
11656
+ const rootName = basename4(rootPath);
11657
+ const wsBundle = getWorkspaceBundle();
11658
+ const wsCtx = buildTemplateContext(rootName, null, null, instructionsFile);
11659
+ const wsInstalled = installBundle(rootDanyaDir, wsBundle, wsCtx, { force });
11660
+ writeFileSync6(join9(rootDanyaDir, "guard-rules.json"), "[]", "utf-8");
11661
+ writeFileSync6(join9(rootDanyaDir, "gate-chain.json"), JSON.stringify({
11662
+ gates: { guard: { enabled: true }, review: { enabled: true }, push: { enabled: true } }
11663
+ }, null, 2), "utf-8");
11664
+ const subResults = [];
11665
+ for (const sub of subProjects) {
11666
+ const subDanyaDir = join9(sub.path, ".danya");
11667
+ const bundle = getBundleForEngine(sub.engine, sub.serverLanguage);
11668
+ const ctx = buildTemplateContext(sub.name, sub.engine, sub.serverLanguage, instructionsFile);
11669
+ const installed = installBundle(subDanyaDir, bundle, ctx, { force });
11670
+ const guardRules = generateGuardRules(sub.engine, sub.serverLanguage);
11671
+ writeFileSync6(join9(subDanyaDir, "guard-rules.json"), JSON.stringify(guardRules, null, 2), "utf-8");
11672
+ writeFileSync6(join9(subDanyaDir, "gate-chain.json"), JSON.stringify({
11673
+ gates: { guard: { enabled: true }, syntax: { enabled: true }, verify: { enabled: true }, commit: { enabled: true }, review: { enabled: true }, push: { enabled: true, require_review: true } }
11674
+ }, null, 2), "utf-8");
11675
+ writeFileSync6(join9(subDanyaDir, "settings.json"), JSON.stringify(generateSettings(), null, 2), "utf-8");
11676
+ consolidateLegacyIntoDanya(sub.path);
11677
+ writeInstructionsFile(sub.path, instructionsFile, sub.engine, sub.serverLanguage);
11678
+ subResults.push(` ${sub.name}/ (${sub.role}): engine=${sub.engine ?? "none"}, server=${sub.serverLanguage ?? "none"}, ${installed.length} files`);
11679
+ }
11680
+ consolidateLegacyIntoDanya(rootPath);
11681
+ writeInstructionsFile(rootPath, instructionsFile, null, null);
11682
+ return [
11683
+ "\u2705 Danya workspace initialized! (multi-project mode)",
11684
+ "",
11685
+ "Workspace structure:",
11686
+ ` ${rootName}/.danya/ \u2014 Cross-project (${wsInstalled.length} files)`,
11687
+ ...subResults,
11688
+ "",
11689
+ "Three-layer isolation:",
11690
+ " Layer 1: Workspace \u2014 cross-project rules, memory, commands",
11691
+ " Layer 2: Sub-projects \u2014 engine-specific rules, hooks, commands",
11692
+ " Layer 3: Session \u2014 git worktree isolation for parallel tasks",
11693
+ "",
11694
+ "Gate chain per sub-project: Edit \u2192 Guard \u2192 Syntax \u2192 Verify \u2192 Commit \u2192 Review \u2192 Push"
11695
+ ].join("\n");
11696
+ }
11697
+ function generateSettings() {
11698
+ return {
11699
+ hooks: {
11700
+ PreToolUse: [
11701
+ { matcher: "Edit|Write", hooks: [{ type: "command", command: "bash .danya/hooks/constitution-guard.sh", timeout: 5e3 }] },
11702
+ { matcher: "Bash", commandPattern: "git\\s+commit", hooks: [{ type: "command", command: "bash .danya/hooks/pre-commit.sh", timeout: 3e5 }] },
11703
+ { matcher: "Bash", commandPattern: "git\\s+push", hooks: [{ type: "command", command: "bash .danya/hooks/push-gate.sh", timeout: 5e3 }] }
11704
+ ],
11705
+ PostToolUse: [
11706
+ { matcher: "Bash", hooks: [{ type: "command", command: "bash .danya/hooks/harness-evolution.sh", timeout: 5e3 }] },
11707
+ { matcher: "Bash", commandPattern: "git\\s+commit", hooks: [{ type: "command", command: "bash .danya/hooks/post-commit.sh", timeout: 5e3 }] }
11708
+ ]
11709
+ }
11710
+ };
11711
+ }
11712
+ function writeInstructionsFile(dir, instructionsFile, engine, serverLanguage) {
11713
+ const path5 = join9(dir, instructionsFile);
11714
+ const altFile = instructionsFile === "CLAUDE.md" ? "AGENTS.md" : "CLAUDE.md";
11715
+ if (existsSync11(path5) || existsSync11(join9(dir, altFile))) return;
11716
+ writeFileSync6(path5, generateInstructionsTemplate(engine, serverLanguage), "utf-8");
11717
+ }
11718
+ function generateInstructionsTemplate(engine, serverLanguage) {
11719
+ const lines = ["# Project Instructions", ""];
11720
+ lines.push("## Build & Test");
11721
+ if (engine === "unity") {
11722
+ lines.push("- Build: Unity Editor \u2192 File > Build Settings");
11723
+ lines.push("- Test: Window > General > Test Runner");
11724
+ } else if (engine === "unreal") {
11725
+ lines.push("- Build: UnrealBuildTool or IDE build");
11726
+ lines.push("- Test: Automation tab in Session Frontend");
11727
+ } else if (engine === "godot") {
11728
+ lines.push("- Build: godot --export-release <preset>");
11729
+ lines.push("- Test: GUT or custom test framework");
11730
+ }
11731
+ if (serverLanguage === "go") {
11732
+ lines.push("- Server build: make build");
11733
+ lines.push("- Server test: make test");
11734
+ lines.push("- Server lint: make lint");
11735
+ }
11736
+ if (!engine && !serverLanguage) {
11737
+ lines.push("- Build: <your build command>");
11738
+ lines.push("- Test: <your test command>");
11739
+ }
11740
+ lines.push("");
11741
+ lines.push("## Harness");
11742
+ lines.push("This project uses Danya harness. See .danya/ for:");
11743
+ lines.push("- rules/ \u2014 Coding constraints (auto-loaded every session)");
11744
+ lines.push("- commands/ \u2014 Workflow commands (/auto-work, /review, /fix-harness, etc.)");
11745
+ lines.push("- memory/ \u2014 Persistent domain knowledge");
11746
+ lines.push("- hooks/ \u2014 Mechanical enforcement scripts");
11747
+ lines.push("");
11748
+ lines.push("## Forbidden Zones");
11749
+ lines.push("See .danya/guard-rules.json. Hook enforced \u2014 Agent cannot bypass.");
11750
+ lines.push("");
11751
+ return lines.join("\n");
11752
+ }
11753
+ function generateGuardRules(engine, serverLanguage) {
11754
+ const rules = [];
11755
+ if (engine === "unity") {
11756
+ rules.push(
11757
+ { pattern: "Config/Gen/", description: "Auto-generated config", fix_hint: "Edit Excel \u2192 run ConfigGenerate" },
11758
+ { pattern: "Scripts/Framework/", description: "Core framework", fix_hint: "Needs programmer approval" }
11759
+ );
11760
+ }
11761
+ if (engine === "unreal") {
11762
+ rules.push(
11763
+ { pattern: "Generated/", description: "UE generated code", fix_hint: "Regenerate via UBT" },
11764
+ { pattern: "Intermediate/", description: "Build intermediates", fix_hint: "Do not edit" }
11765
+ );
11766
+ }
11767
+ if (engine === "godot") {
11768
+ rules.push(
11769
+ { pattern: "\\.import/", description: "Godot import cache", fix_hint: "Do not edit" }
11770
+ );
11771
+ }
11772
+ if (serverLanguage === "go") {
11773
+ rules.push(
11774
+ { pattern: "orm/(golang|redis|mongo)/", description: "ORM generated code", fix_hint: "Edit XML \u2192 make orm" },
11775
+ { pattern: "cfg_.*\\.go$", description: "Config generated code", fix_hint: "Edit data source \u2192 regenerate" },
11776
+ { pattern: ".*_pb\\.go$", description: "Protobuf generated", fix_hint: "Edit .proto \u2192 protoc" }
11777
+ );
11778
+ }
11779
+ return rules;
11780
+ }
11781
+ function countFiles(installed, prefix) {
11782
+ return installed.filter((f) => f.startsWith(prefix)).length;
11783
+ }
11784
+ function isClaudeModel() {
11785
+ try {
11786
+ const modelManager = getModelManager();
11787
+ const modelName = modelManager.getCurrentModel();
11788
+ return Boolean(modelName && modelName.startsWith("claude"));
11789
+ } catch {
11790
+ return false;
11791
+ }
11792
+ }
11793
+
11794
+ // src/ui/screens/autoInitHarness.ts
11795
+ var hasRun = false;
11796
+ function autoInitHarness(cwd2) {
11797
+ if (hasRun) return;
11798
+ hasRun = true;
11799
+ const danyaDir = join10(cwd2, ".danya");
11800
+ if (existsSync12(danyaDir)) return;
11801
+ try {
11802
+ initDanyaProject(cwd2, false).catch(() => {
11803
+ });
11804
+ } catch {
11805
+ }
11806
+ }
11807
+
11808
+ // src/ui/components/ProjectOnboarding.tsx
10557
11809
  function markProjectOnboardingComplete() {
10558
11810
  const projectConfig = getCurrentProjectConfig();
10559
11811
  if (!projectConfig.hasCompletedProjectOnboarding) {
@@ -10590,9 +11842,14 @@ function ProjectOnboarding({
10590
11842
  if (!showOnboarding && !hasReleaseNotes) {
10591
11843
  return null;
10592
11844
  }
10593
- const workspaceHasProjectGuide = existsSync8(join6(workspaceDir, PROJECT_FILE));
11845
+ const workspaceHasProjectGuide = existsSync13(join11(workspaceDir, PROJECT_FILE));
10594
11846
  const isWorkspaceDirEmpty = isDirEmpty(workspaceDir);
10595
11847
  const shouldRecommendProjectGuide = !workspaceHasProjectGuide && !isWorkspaceDirEmpty;
11848
+ React28.useEffect(() => {
11849
+ if (!isWorkspaceDirEmpty) {
11850
+ autoInitHarness(workspaceDir);
11851
+ }
11852
+ }, [workspaceDir, isWorkspaceDirEmpty]);
10596
11853
  const theme = getTheme();
10597
11854
  return /* @__PURE__ */ React28.createElement(Box21, { flexDirection: "column", gap: 1, padding: 1, paddingBottom: 0 }, showOnboarding && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(Text24, { color: theme.secondaryText }, "Tips for getting started:"), /* @__PURE__ */ React28.createElement(OrderedList, null, (() => {
10598
11855
  const items = [];
@@ -10626,31 +11883,44 @@ function ProjectOnboarding({
10626
11883
 
10627
11884
  // src/commands/init.ts
10628
11885
  init_product();
11886
+ init_state();
10629
11887
  var command2 = {
10630
11888
  type: "prompt",
10631
11889
  name: "init",
10632
- description: `Initialize a new ${PROJECT_FILE} file with codebase documentation`,
11890
+ description: `Initialize Danya harness + ${PROJECT_FILE} for this project`,
10633
11891
  isEnabled: true,
10634
11892
  isHidden: false,
10635
- progressMessage: "analyzing your codebase",
11893
+ progressMessage: "initializing harness and analyzing codebase",
10636
11894
  userFacingName() {
10637
11895
  return "init";
10638
11896
  },
10639
11897
  async getPromptForCommand(_args) {
10640
11898
  markProjectOnboardingComplete();
11899
+ let harnessResult = "";
11900
+ try {
11901
+ const force = _args.includes("--force");
11902
+ harnessResult = await initDanyaProject(getCwd(), force);
11903
+ } catch (e) {
11904
+ harnessResult = `\u26A0\uFE0F Harness init failed: ${e.message}`;
11905
+ }
10641
11906
  return [
10642
11907
  {
10643
11908
  role: "user",
10644
11909
  content: [
10645
11910
  {
10646
11911
  type: "text",
10647
- text: `Please analyze this codebase and create a ${PROJECT_FILE} file containing:
11912
+ text: `${harnessResult}
11913
+
11914
+ ---
11915
+
11916
+ Now please analyze this codebase and create a ${PROJECT_FILE} file containing:
10648
11917
  1. Build/lint/test commands - especially for running a single test
10649
11918
  2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
10650
11919
 
10651
11920
  The file you create will be given to agentic coding agents (such as yourself) that operate in this repository. Make it about 20 lines long.
10652
11921
  If there's already a ${PROJECT_FILE}, improve it.
10653
- If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md), make sure to include them.`
11922
+ If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md), make sure to include them.
11923
+ Also review the .danya/rules/ files and customize them based on what you learn about this codebase.`
10654
11924
  }
10655
11925
  ]
10656
11926
  }
@@ -10740,8 +12010,8 @@ function getReplStaticPrefixLength(orderedMessages, allMessages, unresolvedToolU
10740
12010
 
10741
12011
  // src/commands/messages-debug.ts
10742
12012
  init_log();
10743
- import { existsSync as existsSync9, readdirSync as readdirSync2, readFileSync as readFileSync6, statSync as statSync9 } from "fs";
10744
- import { join as join7 } from "path";
12013
+ import { existsSync as existsSync14, readdirSync as readdirSync5, readFileSync as readFileSync9, statSync as statSync12 } from "fs";
12014
+ import { join as join12 } from "path";
10745
12015
  function isDebugMode() {
10746
12016
  return process.argv.includes("--debug") || process.argv.includes("--debug-verbose");
10747
12017
  }
@@ -10772,15 +12042,15 @@ function getProgressText(message) {
10772
12042
  }
10773
12043
  function getLatestMessagesLogFile() {
10774
12044
  const dir = CACHE_PATHS.messages();
10775
- if (!existsSync9(dir)) return null;
10776
- const files = readdirSync2(dir).filter((f) => f.endsWith(".json"));
12045
+ if (!existsSync14(dir)) return null;
12046
+ const files = readdirSync5(dir).filter((f) => f.endsWith(".json"));
10777
12047
  if (files.length === 0) return null;
10778
12048
  let best = null;
10779
12049
  for (const file of files) {
10780
- const fullPath = join7(dir, file);
12050
+ const fullPath = join12(dir, file);
10781
12051
  let mtimeMs = 0;
10782
12052
  try {
10783
- mtimeMs = statSync9(fullPath).mtimeMs;
12053
+ mtimeMs = statSync12(fullPath).mtimeMs;
10784
12054
  } catch {
10785
12055
  continue;
10786
12056
  }
@@ -10891,9 +12161,9 @@ var command3 = {
10891
12161
  );
10892
12162
  const { toolUseIDs, duplicates, byID } = summarizeToolUses(normalized);
10893
12163
  const latestLog = getLatestMessagesLogFile();
10894
- const latestLogContent = latestLog && existsSync9(latestLog.path) ? (() => {
12164
+ const latestLogContent = latestLog && existsSync14(latestLog.path) ? (() => {
10895
12165
  try {
10896
- return JSON.parse(readFileSync6(latestLog.path, "utf8"));
12166
+ return JSON.parse(readFileSync9(latestLog.path, "utf8"));
10897
12167
  } catch {
10898
12168
  return null;
10899
12169
  }
@@ -11172,7 +12442,7 @@ async function createAndStoreApiKey(accessToken) {
11172
12442
  }
11173
12443
  saveGlobalConfig(config2);
11174
12444
  try {
11175
- const { resetAnthropicClient } = await import("./llm-5DSL623J.js");
12445
+ const { resetAnthropicClient } = await import("./llm-XBH33BXT.js");
11176
12446
  resetAnthropicClient();
11177
12447
  } catch {
11178
12448
  }
@@ -15523,7 +16793,7 @@ async function refreshPluginRuntimeFromInstalls() {
15523
16793
  const existingRoots = getSessionPlugins().map((p) => p.rootDir);
15524
16794
  const dirs = Array.from(/* @__PURE__ */ new Set([...existingRoots, ...installedRoots]));
15525
16795
  if (dirs.length === 0) return [];
15526
- const { configureSessionPlugins } = await import("./pluginRuntime-TCH3K4F6.js");
16796
+ const { configureSessionPlugins } = await import("./pluginRuntime-TJ55FZXH.js");
15527
16797
  const { errors } = await configureSessionPlugins({ pluginDirs: dirs });
15528
16798
  return errors;
15529
16799
  }
@@ -16192,7 +17462,7 @@ async function call(onDone, context) {
16192
17462
  ModelConfig,
16193
17463
  {
16194
17464
  onClose: () => {
16195
- import("./model-PHL6VTAG.js").then(({ reloadModelManager: reloadModelManager2 }) => {
17465
+ import("./model-B5TCGITV.js").then(({ reloadModelManager: reloadModelManager2 }) => {
16196
17466
  reloadModelManager2();
16197
17467
  triggerModelConfigChange();
16198
17468
  onDone();
@@ -16880,6 +18150,69 @@ var parallel_execute_default = {
16880
18150
  }
16881
18151
  };
16882
18152
 
18153
+ // src/commands/fix-harness.ts
18154
+ var fixHarnessCommand = {
18155
+ name: "fix-harness",
18156
+ description: "Update harness rules after an error pattern is found",
18157
+ isEnabled: true,
18158
+ isHidden: false,
18159
+ type: "prompt",
18160
+ progressMessage: "Analyzing error and updating harness rules...",
18161
+ argumentHint: "[error-description]",
18162
+ userFacingName() {
18163
+ return "fix-harness";
18164
+ },
18165
+ async getPromptForCommand(args) {
18166
+ return [
18167
+ {
18168
+ role: "user",
18169
+ content: [
18170
+ {
18171
+ type: "text",
18172
+ text: buildFixHarnessPrompt(args)
18173
+ }
18174
+ ]
18175
+ }
18176
+ ];
18177
+ }
18178
+ };
18179
+ function buildFixHarnessPrompt(errorDescription) {
18180
+ return `You are performing harness self-evolution. An error pattern was discovered during development.
18181
+
18182
+ Error description: ${errorDescription || "(Analyze recent errors in this session)"}
18183
+
18184
+ ## Process
18185
+
18186
+ 1. **Identify the error pattern**: What went wrong? What type of error is it?
18187
+
18188
+ 2. **Route to correct rule file**:
18189
+ - Forbidden zone violation \u2192 .danya/rules/constitution.md
18190
+ - Coding principle violation \u2192 .danya/rules/golden-principles.md
18191
+ - Known pitfall re-occurrence \u2192 .danya/rules/known-pitfalls.md
18192
+ - Architecture boundary violation \u2192 .danya/rules/architecture-boundaries.md
18193
+ - Style issue \u2192 engine-specific style rule file
18194
+
18195
+ 3. **Add a concise rule**:
18196
+ - \u274C What went wrong (with example)
18197
+ - \u2705 Correct approach (with example)
18198
+
18199
+ 4. **Check constraints**:
18200
+ - Is this error pattern already captured in rules? If yes, skip.
18201
+ - Total rule file lines must stay under 550. If exceeded, consolidate.
18202
+ - If mechanically checkable, note it for /verify checks.
18203
+
18204
+ 5. **Write the update**: Edit the appropriate rule file.
18205
+
18206
+ 6. **Report**: State which file was updated and what rule was added.
18207
+
18208
+ ## Important
18209
+ - Only add NEW patterns not already captured
18210
+ - Keep rules minimal: one error = one rule
18211
+ - Include correct-usage example, not just prohibition
18212
+ - Do NOT modify code files \u2014 only update .danya/rules/`;
18213
+ }
18214
+ var fix_harness_default = fixHarnessCommand;
18215
+
16883
18216
  // src/commands/rename.ts
16884
18217
  var rename = {
16885
18218
  type: "local",
@@ -18523,7 +19856,7 @@ import * as React89 from "react";
18523
19856
  // src/ui/components/permissions/file-edit-permission-request/FileEditPermissionRequest.tsx
18524
19857
  import chalk7 from "chalk";
18525
19858
  import { Box as Box55, Text as Text60, useInput as useInput19 } from "ink";
18526
- import { basename as basename2, dirname as dirname6, extname as extname7 } from "path";
19859
+ import { basename as basename5, dirname as dirname7, extname as extname8 } from "path";
18527
19860
  import React74, { useCallback as useCallback8, useMemo as useMemo13 } from "react";
18528
19861
 
18529
19862
  // src/ui/hooks/usePermissionRequestLogging.ts
@@ -18603,11 +19936,11 @@ function PermissionRequestTitle({
18603
19936
 
18604
19937
  // src/ui/components/permissions/file-edit-permission-request/FileEditToolDiff.tsx
18605
19938
  import * as React73 from "react";
18606
- import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
19939
+ import { existsSync as existsSync15, readFileSync as readFileSync10 } from "fs";
18607
19940
  import { useMemo as useMemo12 } from "react";
18608
19941
  import { Box as Box54, Text as Text59 } from "ink";
18609
19942
  init_state();
18610
- import { relative as relative11 } from "path";
19943
+ import { relative as relative13 } from "path";
18611
19944
  function FileEditToolDiff({
18612
19945
  file_path,
18613
19946
  new_string,
@@ -18617,7 +19950,7 @@ function FileEditToolDiff({
18617
19950
  width
18618
19951
  }) {
18619
19952
  const file = useMemo12(
18620
- () => existsSync10(file_path) ? readFileSync7(file_path, "utf8") : "",
19953
+ () => existsSync15(file_path) ? readFileSync10(file_path, "utf8") : "",
18621
19954
  [file_path]
18622
19955
  );
18623
19956
  const patch = useMemo12(
@@ -18637,7 +19970,7 @@ function FileEditToolDiff({
18637
19970
  flexDirection: "column",
18638
19971
  paddingX: 1
18639
19972
  },
18640
- /* @__PURE__ */ React73.createElement(Box54, { paddingBottom: 1 }, /* @__PURE__ */ React73.createElement(Text59, { bold: true }, verbose ? file_path : relative11(getCwd(), file_path))),
19973
+ /* @__PURE__ */ React73.createElement(Box54, { paddingBottom: 1 }, /* @__PURE__ */ React73.createElement(Text59, { bold: true }, verbose ? file_path : relative13(getCwd(), file_path))),
18641
19974
  intersperse(
18642
19975
  patch.map((_) => /* @__PURE__ */ React73.createElement(
18643
19976
  StructuredDiff,
@@ -18694,8 +20027,8 @@ function getPermissionModeCycleShortcut() {
18694
20027
 
18695
20028
  // src/ui/components/permissions/file-edit-permission-request/FileEditPermissionRequest.tsx
18696
20029
  function getOptions(args) {
18697
- const dirPath = dirname6(args.path);
18698
- const dirName = basename2(dirPath) || "this directory";
20030
+ const dirPath = dirname7(args.path);
20031
+ const dirName = basename5(dirPath) || "this directory";
18699
20032
  const options = [
18700
20033
  {
18701
20034
  label: "Yes",
@@ -18726,7 +20059,7 @@ function FileEditPermissionRequest({
18726
20059
  const modeCycleShortcut = useMemo13(() => getPermissionModeCycleShortcut(), []);
18727
20060
  const hasSessionSuggestion = (toolUseConfirm.suggestions?.length ?? 0) > 0;
18728
20061
  const isInWorkingDir = isPathInWorkingDirectories(
18729
- dirname6(file_path),
20062
+ dirname7(file_path),
18730
20063
  toolPermissionContext
18731
20064
  );
18732
20065
  const unaryEvent = useMemo13(
@@ -18836,7 +20169,7 @@ function FileEditPermissionRequest({
18836
20169
  width: columns - 12
18837
20170
  }
18838
20171
  ),
18839
- /* @__PURE__ */ React74.createElement(Box55, { flexDirection: "column" }, /* @__PURE__ */ React74.createElement(Text60, null, "Do you want to make this edit to", " ", /* @__PURE__ */ React74.createElement(Text60, { bold: true }, basename2(file_path)), "?"), /* @__PURE__ */ React74.createElement(
20172
+ /* @__PURE__ */ React74.createElement(Box55, { flexDirection: "column" }, /* @__PURE__ */ React74.createElement(Text60, null, "Do you want to make this edit to", " ", /* @__PURE__ */ React74.createElement(Text60, { bold: true }, basename5(file_path)), "?"), /* @__PURE__ */ React74.createElement(
18840
20173
  Select,
18841
20174
  {
18842
20175
  options: getOptions({
@@ -18851,7 +20184,7 @@ function FileEditPermissionRequest({
18851
20184
  );
18852
20185
  }
18853
20186
  async function extractLanguageName(file_path) {
18854
- const ext = extname7(file_path);
20187
+ const ext = extname8(file_path);
18855
20188
  if (!ext) {
18856
20189
  return "unknown";
18857
20190
  }
@@ -19217,31 +20550,31 @@ function useNotifyAfterTimeout(message, timeout = DEFAULT_INTERACTION_THRESHOLD_
19217
20550
  // src/ui/components/permissions/file-write-permission-request/FileWritePermissionRequest.tsx
19218
20551
  import { Box as Box59, Text as Text64, useInput as useInput20 } from "ink";
19219
20552
  import React78, { useCallback as useCallback9, useMemo as useMemo17 } from "react";
19220
- import { basename as basename3, dirname as dirname7, extname as extname9 } from "path";
20553
+ import { basename as basename6, dirname as dirname8, extname as extname10 } from "path";
19221
20554
  init_env();
19222
- import { existsSync as existsSync12 } from "fs";
20555
+ import { existsSync as existsSync17 } from "fs";
19223
20556
  import chalk10 from "chalk";
19224
20557
 
19225
20558
  // src/ui/components/permissions/file-write-permission-request/FileWriteToolDiff.tsx
19226
20559
  import * as React77 from "react";
19227
- import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
20560
+ import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
19228
20561
  import { useMemo as useMemo16 } from "react";
19229
20562
  import { Box as Box58, Text as Text63 } from "ink";
19230
20563
  init_state();
19231
- import { extname as extname8, relative as relative12 } from "path";
20564
+ import { extname as extname9, relative as relative14 } from "path";
19232
20565
  function FileWriteToolDiff({
19233
20566
  file_path,
19234
20567
  content,
19235
20568
  verbose,
19236
20569
  width
19237
20570
  }) {
19238
- const fileExists = useMemo16(() => existsSync11(file_path), [file_path]);
20571
+ const fileExists = useMemo16(() => existsSync16(file_path), [file_path]);
19239
20572
  const oldContent = useMemo16(() => {
19240
20573
  if (!fileExists) {
19241
20574
  return "";
19242
20575
  }
19243
20576
  const enc = detectFileEncoding(file_path);
19244
- return readFileSync8(file_path, enc);
20577
+ return readFileSync11(file_path, enc);
19245
20578
  }, [file_path, fileExists]);
19246
20579
  const hunks = useMemo16(() => {
19247
20580
  if (!fileExists) {
@@ -19262,7 +20595,7 @@ function FileWriteToolDiff({
19262
20595
  flexDirection: "column",
19263
20596
  paddingX: 1
19264
20597
  },
19265
- /* @__PURE__ */ React77.createElement(Box58, { paddingBottom: 1 }, /* @__PURE__ */ React77.createElement(Text63, { bold: true }, verbose ? file_path : relative12(getCwd(), file_path))),
20598
+ /* @__PURE__ */ React77.createElement(Box58, { paddingBottom: 1 }, /* @__PURE__ */ React77.createElement(Text63, { bold: true }, verbose ? file_path : relative14(getCwd(), file_path))),
19266
20599
  hunks ? intersperse(
19267
20600
  hunks.map((_) => /* @__PURE__ */ React77.createElement(
19268
20601
  StructuredDiff,
@@ -19278,7 +20611,7 @@ function FileWriteToolDiff({
19278
20611
  HighlightedCode,
19279
20612
  {
19280
20613
  code: content || "(No content)",
19281
- language: extname8(file_path).slice(1)
20614
+ language: extname9(file_path).slice(1)
19282
20615
  }
19283
20616
  )
19284
20617
  );
@@ -19295,18 +20628,18 @@ function FileWritePermissionRequest({
19295
20628
  const modeCycleShortcut = useMemo17(() => getPermissionModeCycleShortcut(), []);
19296
20629
  const hasSessionSuggestion = (toolUseConfirm.suggestions?.length ?? 0) > 0;
19297
20630
  const isInWorkingDir = isPathInWorkingDirectories(
19298
- dirname7(file_path),
20631
+ dirname8(file_path),
19299
20632
  toolPermissionContext
19300
20633
  );
19301
20634
  const sessionLabel = useMemo17(() => {
19302
- const dirPath = dirname7(file_path);
19303
- const dirName = basename3(dirPath) || "this directory";
20635
+ const dirPath = dirname8(file_path);
20636
+ const dirName = basename6(dirPath) || "this directory";
19304
20637
  const shortcutHint = chalk10.bold.hex(getTheme().warning)(
19305
20638
  `(${modeCycleShortcut.displayText})`
19306
20639
  );
19307
20640
  return isInWorkingDir ? `Yes, allow all edits during this session ${shortcutHint}` : `Yes, allow all edits in ${chalk10.bold(`${dirName}/`)} during this session ${shortcutHint}`;
19308
20641
  }, [file_path, isInWorkingDir, modeCycleShortcut.displayText]);
19309
- const fileExists = useMemo17(() => existsSync12(file_path), [file_path]);
20642
+ const fileExists = useMemo17(() => existsSync17(file_path), [file_path]);
19310
20643
  const unaryEvent = useMemo17(
19311
20644
  () => ({
19312
20645
  completion_type: "write_file_single",
@@ -19414,7 +20747,7 @@ function FileWritePermissionRequest({
19414
20747
  width: columns - 12
19415
20748
  }
19416
20749
  )),
19417
- /* @__PURE__ */ React78.createElement(Box59, { flexDirection: "column" }, /* @__PURE__ */ React78.createElement(Text64, null, "Do you want to ", fileExists ? "make this edit to" : "create", " ", /* @__PURE__ */ React78.createElement(Text64, { bold: true }, basename3(file_path)), "?"), /* @__PURE__ */ React78.createElement(
20750
+ /* @__PURE__ */ React78.createElement(Box59, { flexDirection: "column" }, /* @__PURE__ */ React78.createElement(Text64, null, "Do you want to ", fileExists ? "make this edit to" : "create", " ", /* @__PURE__ */ React78.createElement(Text64, { bold: true }, basename6(file_path)), "?"), /* @__PURE__ */ React78.createElement(
19418
20751
  Select,
19419
20752
  {
19420
20753
  options: [
@@ -19439,7 +20772,7 @@ function FileWritePermissionRequest({
19439
20772
  );
19440
20773
  }
19441
20774
  async function extractLanguageName2(file_path) {
19442
- const ext = extname9(file_path);
20775
+ const ext = extname10(file_path);
19443
20776
  if (!ext) {
19444
20777
  return "unknown";
19445
20778
  }
@@ -19453,8 +20786,8 @@ import React79, { useCallback as useCallback10, useMemo as useMemo18 } from "rea
19453
20786
  init_env();
19454
20787
  import chalk11 from "chalk";
19455
20788
  init_state();
19456
- import { basename as basename4, dirname as dirname8 } from "path";
19457
- import { statSync as statSync10 } from "fs";
20789
+ import { basename as basename7, dirname as dirname9 } from "path";
20790
+ import { statSync as statSync13 } from "fs";
19458
20791
  function pathArgNameForToolUse(toolUseConfirm) {
19459
20792
  switch (toolUseConfirm.tool) {
19460
20793
  case FileWriteTool:
@@ -19483,11 +20816,11 @@ function isMultiFile(toolUseConfirm) {
19483
20816
  }
19484
20817
  function pathToPermissionDirectory2(path5) {
19485
20818
  try {
19486
- const stats = statSync10(path5);
20819
+ const stats = statSync13(path5);
19487
20820
  if (stats.isDirectory()) return path5;
19488
20821
  } catch {
19489
20822
  }
19490
- return dirname8(path5);
20823
+ return dirname9(path5);
19491
20824
  }
19492
20825
  function pathFromToolUse(toolUseConfirm) {
19493
20826
  const pathArgName = pathArgNameForToolUse(toolUseConfirm);
@@ -19530,7 +20863,7 @@ function FilesystemPermissionRequest({
19530
20863
  function getDontAskAgainOptions(toolUseConfirm, path5, modeCycleShortcut, isInWorkingDir, hasSessionSuggestion) {
19531
20864
  if (!hasSessionSuggestion) return [];
19532
20865
  const permissionDirPath = pathToPermissionDirectory2(path5);
19533
- const permissionDirName = basename4(permissionDirPath) || "this directory";
20866
+ const permissionDirName = basename7(permissionDirPath) || "this directory";
19534
20867
  if (toolUseConfirm.tool.isReadOnly(toolUseConfirm.input)) {
19535
20868
  const label2 = isInWorkingDir ? "Yes, during this session" : `Yes, allow reading from ${chalk11.bold(`${permissionDirName}/`)} during this session`;
19536
20869
  return [{ label: label2, value: "yes-session" }];
@@ -20565,9 +21898,9 @@ init_planMode();
20565
21898
 
20566
21899
  // src/utils/system/externalEditor.ts
20567
21900
  import { spawn, spawnSync } from "child_process";
20568
- import { mkdtempSync, readFileSync as readFileSync9, rmSync, writeFileSync as writeFileSync4 } from "fs";
21901
+ import { mkdtempSync, readFileSync as readFileSync12, rmSync, writeFileSync as writeFileSync7 } from "fs";
20569
21902
  import { tmpdir } from "os";
20570
- import { join as join8 } from "path";
21903
+ import { join as join13 } from "path";
20571
21904
  var isWindows = process.platform === "win32";
20572
21905
  function isCommandAvailable(command4) {
20573
21906
  const checker = isWindows ? "where" : "which";
@@ -20643,9 +21976,9 @@ async function launchExternalEditor(initialText) {
20643
21976
  )
20644
21977
  };
20645
21978
  }
20646
- const dir = mkdtempSync(join8(tmpdir(), "kode-edit-"));
20647
- const filePath = join8(dir, "message.txt");
20648
- writeFileSync4(filePath, initialText, "utf-8");
21979
+ const dir = mkdtempSync(join13(tmpdir(), "kode-edit-"));
21980
+ const filePath = join13(dir, "message.txt");
21981
+ writeFileSync7(filePath, initialText, "utf-8");
20649
21982
  const wasRaw = Boolean(process.stdin.isTTY && process.stdin.isRaw);
20650
21983
  if (process.stdin.isTTY) {
20651
21984
  process.stdin.pause();
@@ -20687,7 +22020,7 @@ async function launchExternalEditor(initialText) {
20687
22020
  }
20688
22021
  restoreStdinState(wasRaw);
20689
22022
  try {
20690
- const edited = normalizeNewlines(readFileSync9(filePath, "utf-8"));
22023
+ const edited = normalizeNewlines(readFileSync12(filePath, "utf-8"));
20691
22024
  rmSync(dir, { recursive: true, force: true });
20692
22025
  return { text: edited, editorLabel: editorCommand.displayName };
20693
22026
  } catch (error) {
@@ -20752,7 +22085,7 @@ async function launchExternalEditorForFilePath(filePath) {
20752
22085
  }
20753
22086
 
20754
22087
  // src/ui/components/permissions/plan-mode-permission-request/ExitPlanModePermissionRequest.tsx
20755
- import { writeFileSync as writeFileSync5 } from "fs";
22088
+ import { writeFileSync as writeFileSync8 } from "fs";
20756
22089
  function getExitPlanModeOptions(args) {
20757
22090
  const options = [];
20758
22091
  options.push(
@@ -20838,7 +22171,7 @@ function ExitPlanModePermissionRequest({
20838
22171
  if (!planExists) {
20839
22172
  const initial = planText === planPlaceholder() ? "# Plan\n" : planText;
20840
22173
  try {
20841
- writeFileSync5(planFilePath, initial, "utf-8");
22174
+ writeFileSync8(planFilePath, initial, "utf-8");
20842
22175
  } catch {
20843
22176
  const edited = await launchExternalEditor(initial);
20844
22177
  if (edited.text !== null) {
@@ -21708,8 +23041,8 @@ function getCompletionContext(args) {
21708
23041
  }
21709
23042
 
21710
23043
  // src/utils/completion/fileSuggestions.ts
21711
- import { existsSync as existsSync13, readdirSync as readdirSync3, statSync as statSync11 } from "fs";
21712
- import { basename as basename5, dirname as dirname9, join as join9, resolve as resolve9 } from "path";
23044
+ import { existsSync as existsSync18, readdirSync as readdirSync6, statSync as statSync14 } from "fs";
23045
+ import { basename as basename8, dirname as dirname10, join as join14, resolve as resolve9 } from "path";
21713
23046
  function generateFileSuggestions(args) {
21714
23047
  const { prefix, cwd: cwd2 } = args;
21715
23048
  try {
@@ -21725,35 +23058,35 @@ function generateFileSuggestions(args) {
21725
23058
  searchPath = resolve9(cwd2, userPath);
21726
23059
  }
21727
23060
  const endsWithSlash = userPath.endsWith("/");
21728
- const searchStat = existsSync13(searchPath) ? statSync11(searchPath) : null;
23061
+ const searchStat = existsSync18(searchPath) ? statSync14(searchPath) : null;
21729
23062
  let searchDir;
21730
23063
  let nameFilter;
21731
23064
  if (endsWithSlash || searchStat?.isDirectory()) {
21732
23065
  searchDir = searchPath;
21733
23066
  nameFilter = "";
21734
23067
  } else {
21735
- searchDir = dirname9(searchPath);
21736
- nameFilter = basename5(searchPath);
23068
+ searchDir = dirname10(searchPath);
23069
+ nameFilter = basename8(searchPath);
21737
23070
  }
21738
- if (!existsSync13(searchDir)) return [];
23071
+ if (!existsSync18(searchDir)) return [];
21739
23072
  const showHidden = nameFilter.startsWith(".") || userPath.includes("/.");
21740
- const entries = readdirSync3(searchDir).filter((entry) => {
23073
+ const entries = readdirSync6(searchDir).filter((entry) => {
21741
23074
  if (!showHidden && entry.startsWith(".")) return false;
21742
23075
  if (nameFilter && !entry.toLowerCase().startsWith(nameFilter.toLowerCase()))
21743
23076
  return false;
21744
23077
  return true;
21745
23078
  }).sort((a, b) => {
21746
- const aPath = join9(searchDir, a);
21747
- const bPath = join9(searchDir, b);
21748
- const aIsDir = statSync11(aPath).isDirectory();
21749
- const bIsDir = statSync11(bPath).isDirectory();
23079
+ const aPath = join14(searchDir, a);
23080
+ const bPath = join14(searchDir, b);
23081
+ const aIsDir = statSync14(aPath).isDirectory();
23082
+ const bIsDir = statSync14(bPath).isDirectory();
21750
23083
  if (aIsDir && !bIsDir) return -1;
21751
23084
  if (!aIsDir && bIsDir) return 1;
21752
23085
  return a.toLowerCase().localeCompare(b.toLowerCase());
21753
23086
  }).slice(0, 25);
21754
23087
  return entries.map((entry) => {
21755
- const entryPath = join9(searchDir, entry);
21756
- const isDir = statSync11(entryPath).isDirectory();
23088
+ const entryPath = join14(searchDir, entry);
23089
+ const isDir = statSync14(entryPath).isDirectory();
21757
23090
  const icon = isDir ? "\u{1F4C1}" : "\u{1F4C4}";
21758
23091
  let value;
21759
23092
  if (userPath.includes("/")) {
@@ -23086,19 +24419,19 @@ function useUnifiedCompletion({
23086
24419
  if (systemCommands.length > 0 || isLoadingCommands) return;
23087
24420
  setIsLoadingCommands(true);
23088
24421
  try {
23089
- const { readdirSync: readdirSync4, statSync: statSync13 } = await import("fs");
24422
+ const { readdirSync: readdirSync7, statSync: statSync16 } = await import("fs");
23090
24423
  const pathDirs = (process.env.PATH || "").split(":").filter(Boolean);
23091
24424
  const commandSet = /* @__PURE__ */ new Set();
23092
24425
  const essentialCommands = getEssentialCommands();
23093
24426
  essentialCommands.forEach((cmd) => commandSet.add(cmd));
23094
24427
  for (const dir of pathDirs) {
23095
24428
  try {
23096
- if (readdirSync4 && statSync13) {
23097
- const entries = readdirSync4(dir);
24429
+ if (readdirSync7 && statSync16) {
24430
+ const entries = readdirSync7(dir);
23098
24431
  for (const entry of entries) {
23099
24432
  try {
23100
24433
  const fullPath = `${dir}/${entry}`;
23101
- const stats = statSync13(fullPath);
24434
+ const stats = statSync16(fullPath);
23102
24435
  if (stats.isFile() && (stats.mode & 73) !== 0) {
23103
24436
  commandSet.add(entry);
23104
24437
  }
@@ -23632,17 +24965,17 @@ function TokenWarning({ tokenUsage }) {
23632
24965
 
23633
24966
  // src/utils/commands/hashCommand.ts
23634
24967
  init_log();
23635
- import { join as join10 } from "path";
23636
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
24968
+ import { join as join15 } from "path";
24969
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "fs";
23637
24970
  function handleHashCommand(interpreted) {
23638
24971
  try {
23639
24972
  const cwd2 = process.cwd();
23640
- const agentsPath = join10(cwd2, "AGENTS.md");
23641
- const legacyPath = join10(cwd2, "CLAUDE.md");
24973
+ const agentsPath = join15(cwd2, "AGENTS.md");
24974
+ const legacyPath = join15(cwd2, "CLAUDE.md");
23642
24975
  const filesToUpdate = [];
23643
24976
  filesToUpdate.push({ path: agentsPath, name: "AGENTS.md" });
23644
24977
  try {
23645
- readFileSync10(legacyPath, "utf-8");
24978
+ readFileSync13(legacyPath, "utf-8");
23646
24979
  filesToUpdate.push({ path: legacyPath, name: "CLAUDE.md" });
23647
24980
  } catch {
23648
24981
  }
@@ -23657,12 +24990,12 @@ _Added on ${now.toLocaleString()} ${timezone}_`;
23657
24990
  try {
23658
24991
  let existingContent = "";
23659
24992
  try {
23660
- existingContent = readFileSync10(file.path, "utf-8").trim();
24993
+ existingContent = readFileSync13(file.path, "utf-8").trim();
23661
24994
  } catch {
23662
24995
  }
23663
24996
  const separator = existingContent ? "\n\n" : "";
23664
24997
  const newContent = `${existingContent}${separator}${interpreted}${timestamp}`;
23665
- writeFileSync6(file.path, newContent, "utf-8");
24998
+ writeFileSync9(file.path, newContent, "utf-8");
23666
24999
  updatedFiles.push(file.name);
23667
25000
  } catch (error) {
23668
25001
  logError(error);
@@ -23862,7 +25195,7 @@ function useStatusLine() {
23862
25195
  // src/ui/components/PromptInput.tsx
23863
25196
  async function interpretHashCommand(input) {
23864
25197
  try {
23865
- const { queryQuick: queryQuick2 } = await import("./llm-5DSL623J.js");
25198
+ const { queryQuick: queryQuick2 } = await import("./llm-XBH33BXT.js");
23866
25199
  const systemPrompt = [
23867
25200
  "You're helping the user structure notes that will be added to their KODING.md file.",
23868
25201
  "Format the user's input into a well-structured note that will be useful for later reference.",
@@ -24175,7 +25508,7 @@ function PromptInput({
24175
25508
  if (messages2.length) {
24176
25509
  if (mode === "bash") {
24177
25510
  onQuery(messages2, newAbortController).then(async () => {
24178
- const { getCwd: getCwd2 } = await import("./state-SDEP3HY3.js");
25511
+ const { getCwd: getCwd2 } = await import("./state-4L5XK2VN.js");
24179
25512
  setCurrentPwd(getCwd2());
24180
25513
  });
24181
25514
  } else {
@@ -24894,35 +26227,121 @@ async function selectAndReadFiles() {
24894
26227
 
24895
26228
  // src/utils/session/autoCompactCore.ts
24896
26229
  init_log();
24897
- async function getMainConversationContextLimit() {
24898
- try {
24899
- const modelManager = getModelManager();
24900
- const resolution = modelManager.resolveModelWithInfo("main");
24901
- const modelProfile = resolution.success ? resolution.profile : null;
24902
- if (modelProfile?.contextLength) {
24903
- return modelProfile.contextLength;
26230
+
26231
+ // src/services/compact/compact.ts
26232
+ var DEFAULT_COMPACTION_CONFIG = {
26233
+ triggerThresholdPercent: 90,
26234
+ targetPercent: 60,
26235
+ preserveRecentMessages: 4,
26236
+ enabled: true
26237
+ };
26238
+ function groupMessages(messages, preserveCount) {
26239
+ const groups = [];
26240
+ const preserveStartIdx = Math.max(0, messages.length - preserveCount);
26241
+ let currentGroup = null;
26242
+ for (let i = 0; i < messages.length; i++) {
26243
+ const msg = messages[i];
26244
+ const isPreserved = i >= preserveStartIdx;
26245
+ if (isPreserved) {
26246
+ if (currentGroup) {
26247
+ groups.push(currentGroup);
26248
+ currentGroup = null;
26249
+ }
26250
+ groups.push({
26251
+ type: "preserved",
26252
+ messages: [msg],
26253
+ totalTokens: msg.tokens
26254
+ });
26255
+ continue;
26256
+ }
26257
+ if (msg.type === "tool_result") {
26258
+ if (currentGroup?.type === "tool_use") {
26259
+ currentGroup.messages.push(msg);
26260
+ currentGroup.totalTokens += msg.tokens;
26261
+ } else {
26262
+ if (currentGroup) groups.push(currentGroup);
26263
+ currentGroup = {
26264
+ type: "tool_use",
26265
+ messages: [msg],
26266
+ totalTokens: msg.tokens
26267
+ };
26268
+ }
26269
+ } else if (msg.type === "system") {
26270
+ if (currentGroup) groups.push(currentGroup);
26271
+ groups.push({
26272
+ type: "system",
26273
+ messages: [msg],
26274
+ totalTokens: msg.tokens
26275
+ });
26276
+ currentGroup = null;
26277
+ } else {
26278
+ if (currentGroup?.type === "conversation") {
26279
+ currentGroup.messages.push(msg);
26280
+ currentGroup.totalTokens += msg.tokens;
26281
+ } else {
26282
+ if (currentGroup) groups.push(currentGroup);
26283
+ currentGroup = {
26284
+ type: msg.type === "assistant" ? "tool_use" : "conversation",
26285
+ messages: [msg],
26286
+ totalTokens: msg.tokens
26287
+ };
26288
+ }
26289
+ }
26290
+ }
26291
+ if (currentGroup) groups.push(currentGroup);
26292
+ return groups;
26293
+ }
26294
+ function calculateCompactionTarget(currentTokens, contextWindowSize, config2 = DEFAULT_COMPACTION_CONFIG) {
26295
+ const targetTokens = Math.floor(contextWindowSize * (config2.targetPercent / 100));
26296
+ return Math.max(0, currentTokens - targetTokens);
26297
+ }
26298
+ function selectGroupsForCompaction(groups, tokensToFree) {
26299
+ const toCompact = [];
26300
+ const toKeep = [];
26301
+ let freed = 0;
26302
+ for (const group of groups) {
26303
+ if (group.type === "preserved") {
26304
+ toKeep.push(group);
26305
+ continue;
26306
+ }
26307
+ if (freed < tokensToFree) {
26308
+ toCompact.push(group);
26309
+ freed += group.totalTokens;
26310
+ } else {
26311
+ toKeep.push(group);
24904
26312
  }
24905
- return 2e5;
24906
- } catch (error) {
24907
- return 2e5;
24908
26313
  }
26314
+ return { toCompact, toKeep };
26315
+ }
26316
+ function buildCompactionPrompt(groups) {
26317
+ const lines = [];
26318
+ for (const group of groups) {
26319
+ for (const msg of group.messages) {
26320
+ const prefix = msg.type === "user" ? "User" : msg.type === "assistant" ? "Assistant" : "System";
26321
+ const content = msg.content.length > 2e3 ? msg.content.slice(0, 2e3) + "... (truncated)" : msg.content;
26322
+ lines.push(`[${prefix}]: ${content}`);
26323
+ }
26324
+ }
26325
+ return lines.join("\n\n");
24909
26326
  }
24910
- var COMPRESSION_PROMPT2 = `Please provide a comprehensive summary of our conversation structured as follows:
26327
+
26328
+ // src/utils/session/autoCompactCore.ts
26329
+ var COMPRESSION_PROMPT2 = `Please provide a comprehensive summary of the following conversation history, structured as follows:
24911
26330
 
24912
26331
  ## Technical Context
24913
26332
  Development environment, tools, frameworks, and configurations in use. Programming languages, libraries, and technical constraints. File structure, directory organization, and project architecture.
24914
26333
 
24915
- ## Project Overview
26334
+ ## Project Overview
24916
26335
  Main project goals, features, and scope. Key components, modules, and their relationships. Data models, APIs, and integration patterns.
24917
26336
 
24918
26337
  ## Code Changes
24919
- Files created, modified, or analyzed during our conversation. Specific code implementations, functions, and algorithms added. Configuration changes and structural modifications.
26338
+ Files created, modified, or analyzed during the conversation. Specific code implementations, functions, and algorithms added. Configuration changes and structural modifications.
24920
26339
 
24921
26340
  ## Debugging & Issues
24922
26341
  Problems encountered and their root causes. Solutions implemented and their effectiveness. Error messages, logs, and diagnostic information.
24923
26342
 
24924
26343
  ## Current Status
24925
- What we just completed successfully. Current state of the codebase and any ongoing work. Test results, validation steps, and verification performed.
26344
+ What was most recently completed. Current state of the codebase and any ongoing work. Test results, validation steps, and verification performed.
24926
26345
 
24927
26346
  ## Pending Tasks
24928
26347
  Immediate next steps and priorities. Planned features, improvements, and refactoring. Known issues, technical debt, and areas needing attention.
@@ -24934,14 +26353,22 @@ Coding style, formatting, and organizational preferences. Communication patterns
24934
26353
  Important technical decisions made and their rationale. Alternative approaches considered and why they were rejected. Trade-offs accepted and their implications.
24935
26354
 
24936
26355
  Focus on information essential for continuing the conversation effectively, including specific details about code, files, errors, and plans.`;
24937
- async function calculateThresholds(tokenCount) {
24938
- const contextLimit = await getMainConversationContextLimit();
24939
- return calculateAutoCompactThresholds(tokenCount, contextLimit);
26356
+ async function getMainConversationContextLimit() {
26357
+ try {
26358
+ const modelManager = getModelManager();
26359
+ const resolution = modelManager.resolveModelWithInfo("main");
26360
+ const modelProfile = resolution.success ? resolution.profile : null;
26361
+ if (modelProfile?.contextLength) return modelProfile.contextLength;
26362
+ return 2e5;
26363
+ } catch {
26364
+ return 2e5;
26365
+ }
24940
26366
  }
24941
26367
  async function shouldAutoCompact(messages) {
24942
26368
  if (messages.length < 3) return false;
24943
26369
  const tokenCount = countTokens(messages);
24944
- const { isAboveAutoCompactThreshold } = await calculateThresholds(tokenCount);
26370
+ const contextLimit = await getMainConversationContextLimit();
26371
+ const { isAboveAutoCompactThreshold } = calculateAutoCompactThresholds(tokenCount, contextLimit);
24945
26372
  return isAboveAutoCompactThreshold;
24946
26373
  }
24947
26374
  async function checkAutoCompact(messages, toolUseContext) {
@@ -24950,10 +26377,7 @@ async function checkAutoCompact(messages, toolUseContext) {
24950
26377
  }
24951
26378
  try {
24952
26379
  const compactedMessages = await executeAutoCompact(messages, toolUseContext);
24953
- return {
24954
- messages: compactedMessages,
24955
- wasCompacted: true
24956
- };
26380
+ return { messages: compactedMessages, wasCompacted: true };
24957
26381
  } catch (error) {
24958
26382
  logError(error);
24959
26383
  debug.warn("AUTO_COMPACT_FAILED", {
@@ -24963,30 +26387,53 @@ async function checkAutoCompact(messages, toolUseContext) {
24963
26387
  }
24964
26388
  }
24965
26389
  async function executeAutoCompact(messages, toolUseContext) {
24966
- const summaryRequest = createUserMessage(COMPRESSION_PROMPT2);
24967
26390
  const tokenCount = countTokens(messages);
24968
- const modelManager = getModelManager();
24969
- const compactResolution = modelManager.resolveModelWithInfo("compact");
24970
- const mainResolution = modelManager.resolveModelWithInfo("main");
24971
- let compressionModelPointer = "compact";
24972
- let compressionNotice = null;
24973
- if (!compactResolution.success || !compactResolution.profile) {
24974
- compressionModelPointer = "main";
24975
- compressionNotice = compactResolution.error || "Compression model pointer 'compact' is not configured.";
24976
- } else {
24977
- const compactBudget = Math.floor(
24978
- compactResolution.profile.contextLength * 0.9
24979
- );
24980
- if (compactBudget > 0 && tokenCount > compactBudget) {
24981
- compressionModelPointer = "main";
24982
- compressionNotice = `Compression model '${compactResolution.profile.name}' does not fit current context (~${Math.round(tokenCount / 1e3)}k tokens).`;
24983
- }
26391
+ const contextLimit = await getMainConversationContextLimit();
26392
+ const compactableMessages = messagesToCompactable(messages);
26393
+ const groups = groupMessages(compactableMessages, DEFAULT_COMPACTION_CONFIG.preserveRecentMessages);
26394
+ const tokensToFree = calculateCompactionTarget(tokenCount, contextLimit);
26395
+ const { toCompact, toKeep } = selectGroupsForCompaction(groups, tokensToFree);
26396
+ if (toCompact.length === 0) {
26397
+ return executeFullCompact(messages, toolUseContext, tokenCount);
24984
26398
  }
24985
- if (compressionModelPointer === "main" && (!mainResolution.success || !mainResolution.profile)) {
24986
- throw new Error(
24987
- mainResolution.error || "Compression fallback failed: model pointer 'main' is not configured."
24988
- );
26399
+ const conversationToSummarize = buildCompactionPrompt(toCompact);
26400
+ const { modelPointer, notice } = resolveCompressionModel(tokenCount);
26401
+ const summaryPrompt = `${COMPRESSION_PROMPT2}
26402
+
26403
+ ---
26404
+
26405
+ Conversation to summarize:
26406
+
26407
+ ${conversationToSummarize}`;
26408
+ const summaryRequest = createUserMessage(summaryPrompt);
26409
+ const summaryResponse = await queryLLM(
26410
+ normalizeMessagesForAPI([summaryRequest]),
26411
+ [
26412
+ "You are a helpful AI assistant tasked with creating comprehensive conversation summaries that preserve all essential context for continuing development work."
26413
+ ],
26414
+ 0,
26415
+ [],
26416
+ toolUseContext.abortController.signal,
26417
+ {
26418
+ safeMode: false,
26419
+ model: modelPointer,
26420
+ prependCLISysprompt: true
26421
+ }
26422
+ );
26423
+ const noticeText = notice ? `Context selectively compressed (${toCompact.length} groups summarized, ${toKeep.length} preserved). ${notice}` : `Context selectively compressed (${toCompact.length} groups summarized, ${toKeep.length} preserved).`;
26424
+ const result = await finalizeSummary(summaryResponse, noticeText);
26425
+ for (const group of toKeep) {
26426
+ for (const msg of group.messages) {
26427
+ if (msg.original) {
26428
+ result.push(msg.original);
26429
+ }
26430
+ }
24989
26431
  }
26432
+ return result;
26433
+ }
26434
+ async function executeFullCompact(messages, toolUseContext, tokenCount) {
26435
+ const { modelPointer, notice } = resolveCompressionModel(tokenCount);
26436
+ const summaryRequest = createUserMessage(COMPRESSION_PROMPT2);
24990
26437
  const summaryResponse = await queryLLM(
24991
26438
  normalizeMessagesForAPI([...messages, summaryRequest]),
24992
26439
  [
@@ -24997,16 +26444,17 @@ async function executeAutoCompact(messages, toolUseContext) {
24997
26444
  toolUseContext.abortController.signal,
24998
26445
  {
24999
26446
  safeMode: false,
25000
- model: compressionModelPointer,
26447
+ model: modelPointer,
25001
26448
  prependCLISysprompt: true
25002
26449
  }
25003
26450
  );
25004
- const content = summaryResponse.message.content;
25005
- const summary = typeof content === "string" ? content : content.length > 0 && content[0]?.type === "text" ? content[0].text : null;
26451
+ const noticeText = notice ? `Context fully compressed due to token limit. ${notice}` : `Context fully compressed due to token limit.`;
26452
+ return finalizeSummary(summaryResponse, noticeText);
26453
+ }
26454
+ async function finalizeSummary(summaryResponse, noticeText) {
26455
+ const summary = extractSummaryText(summaryResponse);
25006
26456
  if (!summary) {
25007
- throw new Error(
25008
- "Failed to generate conversation summary - response did not contain valid text content"
25009
- );
26457
+ throw new Error("Failed to generate conversation summary");
25010
26458
  }
25011
26459
  summaryResponse.message.usage = {
25012
26460
  input_tokens: 0,
@@ -25015,19 +26463,14 @@ async function executeAutoCompact(messages, toolUseContext) {
25015
26463
  cache_read_input_tokens: 0
25016
26464
  };
25017
26465
  const recoveredFiles = await selectAndReadFiles();
25018
- const compactedMessages = [
25019
- createUserMessage(
25020
- compressionNotice ? `Context automatically compressed due to token limit. ${compressionNotice} Using '${compressionModelPointer}' for compression.` : `Context automatically compressed due to token limit. Using '${compressionModelPointer}' for compression.`
25021
- ),
26466
+ const result = [
26467
+ createUserMessage(noticeText),
25022
26468
  summaryResponse
25023
26469
  ];
25024
- if (recoveredFiles.length > 0) {
25025
- for (const file of recoveredFiles) {
25026
- const contentWithLines = addLineNumbers({
25027
- content: file.content,
25028
- startLine: 1
25029
- });
25030
- const recoveryMessage = createUserMessage(
26470
+ for (const file of recoveredFiles) {
26471
+ const contentWithLines = addLineNumbers({ content: file.content, startLine: 1 });
26472
+ result.push(
26473
+ createUserMessage(
25031
26474
  `**Recovered File: ${file.path}**
25032
26475
 
25033
26476
  \`\`\`
@@ -25035,15 +26478,62 @@ ${contentWithLines}
25035
26478
  \`\`\`
25036
26479
 
25037
26480
  *Automatically recovered (${file.tokens} tokens)${file.truncated ? " [truncated]" : ""}*`
25038
- );
25039
- compactedMessages.push(recoveryMessage);
25040
- }
26481
+ )
26482
+ );
25041
26483
  }
25042
26484
  getMessagesSetter()([]);
25043
26485
  getContext.cache.clear?.();
25044
26486
  getCodeStyle.cache.clear?.();
25045
26487
  resetFileFreshnessSession();
25046
- return compactedMessages;
26488
+ return result;
26489
+ }
26490
+ function resolveCompressionModel(tokenCount) {
26491
+ const modelManager = getModelManager();
26492
+ const compactResolution = modelManager.resolveModelWithInfo("compact");
26493
+ const mainResolution = modelManager.resolveModelWithInfo("main");
26494
+ let modelPointer = "compact";
26495
+ let notice = null;
26496
+ if (!compactResolution.success || !compactResolution.profile) {
26497
+ modelPointer = "main";
26498
+ notice = compactResolution.error || "Compression model 'compact' not configured.";
26499
+ } else {
26500
+ const compactBudget = Math.floor(compactResolution.profile.contextLength * 0.9);
26501
+ if (compactBudget > 0 && tokenCount > compactBudget) {
26502
+ modelPointer = "main";
26503
+ notice = `Compression model '${compactResolution.profile.name}' can't fit context (~${Math.round(tokenCount / 1e3)}k tokens).`;
26504
+ }
26505
+ }
26506
+ if (modelPointer === "main" && (!mainResolution.success || !mainResolution.profile)) {
26507
+ throw new Error(mainResolution.error || "Compression fallback failed: 'main' not configured.");
26508
+ }
26509
+ return { modelPointer, notice };
26510
+ }
26511
+ function extractSummaryText(response) {
26512
+ const content = response.message.content;
26513
+ if (typeof content === "string") return content;
26514
+ if (Array.isArray(content)) {
26515
+ for (const block of content) {
26516
+ if (block?.type === "text" && block.text) return block.text;
26517
+ }
26518
+ }
26519
+ return null;
26520
+ }
26521
+ function messagesToCompactable(messages) {
26522
+ return messages.map((msg) => {
26523
+ let content = "";
26524
+ let type2 = "user";
26525
+ if (msg.type === "user") {
26526
+ type2 = "user";
26527
+ const rawContent = msg.message?.content;
26528
+ content = typeof rawContent === "string" ? rawContent : Array.isArray(rawContent) ? rawContent.map((c) => c.text || "").join("\n") : "";
26529
+ } else if (msg.type === "assistant") {
26530
+ type2 = "assistant";
26531
+ const rawContent = msg.message?.content;
26532
+ content = typeof rawContent === "string" ? rawContent : Array.isArray(rawContent) ? rawContent.map((c) => c.text || "").join("\n") : "";
26533
+ }
26534
+ const tokens = Math.ceil(content.length * 0.25);
26535
+ return { type: type2, content, tokens, original: msg };
26536
+ });
25047
26537
  }
25048
26538
 
25049
26539
  // src/app/query.ts
@@ -26911,7 +28401,7 @@ import React102, { useCallback as useCallback17, useEffect as useEffect26, useMe
26911
28401
  import { Box as Box76, Text as Text80, useInput as useInput30 } from "ink";
26912
28402
  import figures8 from "figures";
26913
28403
  import chalk15 from "chalk";
26914
- import { join as join12 } from "path";
28404
+ import { join as join17 } from "path";
26915
28405
  import { spawn as spawn2 } from "child_process";
26916
28406
 
26917
28407
  // src/commands/agents/tooling.ts
@@ -26953,13 +28443,13 @@ async function getAvailableTools() {
26953
28443
  // src/commands/agents/storage.ts
26954
28444
  init_state();
26955
28445
  import {
26956
- existsSync as existsSync14,
26957
- mkdirSync as mkdirSync5,
28446
+ existsSync as existsSync19,
28447
+ mkdirSync as mkdirSync8,
26958
28448
  renameSync as renameSync2,
26959
28449
  unlinkSync as unlinkSync2,
26960
- writeFileSync as writeFileSync7
28450
+ writeFileSync as writeFileSync10
26961
28451
  } from "fs";
26962
- import { join as join11 } from "path";
28452
+ import { join as join16 } from "path";
26963
28453
  import { homedir as homedir7 } from "os";
26964
28454
  init_log();
26965
28455
 
@@ -26967,7 +28457,7 @@ init_log();
26967
28457
  import { randomUUID as randomUUID5 } from "crypto";
26968
28458
  init_log();
26969
28459
  async function generateAgentWithClaude(prompt) {
26970
- const { queryModel } = await import("./llm-5DSL623J.js");
28460
+ const { queryModel } = await import("./llm-XBH33BXT.js");
26971
28461
  const systemPrompt = `You are an expert at creating AI agent configurations. Based on the user's description, generate a specialized agent configuration.
26972
28462
 
26973
28463
  Return your response as a JSON object with exactly these fields:
@@ -27151,26 +28641,26 @@ var LEGACY_FOLDER = ".kode";
27151
28641
  var AGENTS_DIR = "agents";
27152
28642
  function getAgentDirectory(location) {
27153
28643
  if (location === "user") {
27154
- return join11(homedir7(), PRIMARY_FOLDER, AGENTS_DIR);
28644
+ return join16(homedir7(), PRIMARY_FOLDER, AGENTS_DIR);
27155
28645
  }
27156
- return join11(getCwd(), PRIMARY_FOLDER, AGENTS_DIR);
28646
+ return join16(getCwd(), PRIMARY_FOLDER, AGENTS_DIR);
27157
28647
  }
27158
28648
  function getLegacyAgentDirectory(location) {
27159
28649
  if (location === "user") {
27160
- return join11(homedir7(), LEGACY_FOLDER, AGENTS_DIR);
28650
+ return join16(homedir7(), LEGACY_FOLDER, AGENTS_DIR);
27161
28651
  }
27162
- return join11(getCwd(), LEGACY_FOLDER, AGENTS_DIR);
28652
+ return join16(getCwd(), LEGACY_FOLDER, AGENTS_DIR);
27163
28653
  }
27164
28654
  function getPrimaryAgentFilePath(location, agentType) {
27165
- return join11(getAgentDirectory(location), `${agentType}.md`);
28655
+ return join16(getAgentDirectory(location), `${agentType}.md`);
27166
28656
  }
27167
28657
  function getLegacyAgentFilePath(location, agentType) {
27168
- return join11(getLegacyAgentDirectory(location), `${agentType}.md`);
28658
+ return join16(getLegacyAgentDirectory(location), `${agentType}.md`);
27169
28659
  }
27170
28660
  function ensureDirectoryExists(location) {
27171
28661
  const dir = getAgentDirectory(location);
27172
- if (!existsSync14(dir)) {
27173
- mkdirSync5(dir, { recursive: true });
28662
+ if (!existsSync19(dir)) {
28663
+ mkdirSync8(dir, { recursive: true });
27174
28664
  }
27175
28665
  return dir;
27176
28666
  }
@@ -27178,7 +28668,7 @@ async function saveAgent(location, agentType, description2, tools, systemPrompt,
27178
28668
  ensureDirectoryExists(location);
27179
28669
  const filePath = getPrimaryAgentFilePath(location, agentType);
27180
28670
  const legacyPath = getLegacyAgentFilePath(location, agentType);
27181
- if (throwIfExists && (existsSync14(filePath) || existsSync14(legacyPath))) {
28671
+ if (throwIfExists && (existsSync19(filePath) || existsSync19(legacyPath))) {
27182
28672
  throw new Error(`Agent file already exists: ${filePath}`);
27183
28673
  }
27184
28674
  const tempFile = `${filePath}.tmp.${Date.now()}.${Math.random().toString(36).substr(2, 9)}`;
@@ -27192,8 +28682,8 @@ async function saveAgent(location, agentType, description2, tools, systemPrompt,
27192
28682
  color
27193
28683
  );
27194
28684
  try {
27195
- writeFileSync7(tempFile, content, { encoding: "utf-8", flag: "wx" });
27196
- if (throwIfExists && (existsSync14(filePath) || existsSync14(legacyPath))) {
28685
+ writeFileSync10(tempFile, content, { encoding: "utf-8", flag: "wx" });
28686
+ if (throwIfExists && (existsSync19(filePath) || existsSync19(legacyPath))) {
27197
28687
  try {
27198
28688
  unlinkSync2(tempFile);
27199
28689
  } catch {
@@ -27203,7 +28693,7 @@ async function saveAgent(location, agentType, description2, tools, systemPrompt,
27203
28693
  renameSync2(tempFile, filePath);
27204
28694
  } catch (error) {
27205
28695
  try {
27206
- if (existsSync14(tempFile)) {
28696
+ if (existsSync19(tempFile)) {
27207
28697
  unlinkSync2(tempFile);
27208
28698
  }
27209
28699
  } catch (cleanupError) {
@@ -27231,9 +28721,9 @@ async function updateAgent(agent, description2, tools, systemPrompt, color, mode
27231
28721
  const location = agent.location;
27232
28722
  const primaryPath = getPrimaryAgentFilePath(location, agent.agentType);
27233
28723
  const legacyPath = getLegacyAgentFilePath(location, agent.agentType);
27234
- const filePath = existsSync14(primaryPath) ? primaryPath : existsSync14(legacyPath) ? legacyPath : primaryPath;
28724
+ const filePath = existsSync19(primaryPath) ? primaryPath : existsSync19(legacyPath) ? legacyPath : primaryPath;
27235
28725
  ensureDirectoryExists(location);
27236
- writeFileSync7(filePath, content, { encoding: "utf-8", flag: "w" });
28726
+ writeFileSync10(filePath, content, { encoding: "utf-8", flag: "w" });
27237
28727
  }
27238
28728
  async function deleteAgent(agent) {
27239
28729
  if (agent.location === "built-in" || agent.location === "plugin") {
@@ -27242,10 +28732,10 @@ async function deleteAgent(agent) {
27242
28732
  const location = agent.location;
27243
28733
  const primaryPath = getPrimaryAgentFilePath(location, agent.agentType);
27244
28734
  const legacyPath = getLegacyAgentFilePath(location, agent.agentType);
27245
- if (existsSync14(primaryPath)) {
28735
+ if (existsSync19(primaryPath)) {
27246
28736
  unlinkSync2(primaryPath);
27247
28737
  }
27248
- if (existsSync14(legacyPath)) {
28738
+ if (existsSync19(legacyPath)) {
27249
28739
  unlinkSync2(legacyPath);
27250
28740
  }
27251
28741
  }
@@ -28261,8 +29751,8 @@ function ViewAgent(props) {
28261
29751
  if (props.agent.source === "plugin") return `Plugin: ${props.agent.baseDir ?? "Unknown"}`;
28262
29752
  const baseDir = props.agent.baseDir;
28263
29753
  const file = `${props.agent.filename ?? props.agent.agentType}.md`;
28264
- if (props.agent.source === "projectSettings") return join12(".claude", "agents", file);
28265
- if (baseDir) return join12(baseDir, file);
29754
+ if (props.agent.source === "projectSettings") return join17(".claude", "agents", file);
29755
+ if (baseDir) return join17(baseDir, file);
28266
29756
  return props.agent.source;
28267
29757
  })();
28268
29758
  const toolsSummary = () => {
@@ -28610,6 +30100,7 @@ var COMMANDS = memoize3(() => [
28610
30100
  auto_work_default,
28611
30101
  auto_bugfix_default,
28612
30102
  parallel_execute_default,
30103
+ fix_harness_default,
28613
30104
  todos_default,
28614
30105
  ...isAnthropicAuthEnabled() ? [logout_default, login_default()] : [],
28615
30106
  ...INTERNAL_ONLY_COMMANDS
@@ -30229,8 +31720,8 @@ var BashTool = {
30229
31720
  const targetDir = parts[1].replace(/^['"]|['"]$/g, "");
30230
31721
  const fullTargetDir = isAbsolute10(targetDir) ? targetDir : resolve10(getCwd(), targetDir);
30231
31722
  if (!isInDirectory(
30232
- relative13(getOriginalCwd(), fullTargetDir),
30233
- relative13(getCwd(), getOriginalCwd())
31723
+ relative15(getOriginalCwd(), fullTargetDir),
31724
+ relative15(getCwd(), getOriginalCwd())
30234
31725
  )) {
30235
31726
  return {
30236
31727
  result: false,
@@ -30636,7 +32127,7 @@ ${footerParts.join(" ")}`;
30636
32127
  for (const filePath of filePaths) {
30637
32128
  const fullFilePath = isAbsolute10(filePath) ? filePath : resolve10(getCwd(), filePath);
30638
32129
  try {
30639
- readFileTimestamps[fullFilePath] = statSync12(fullFilePath).mtimeMs;
32130
+ readFileTimestamps[fullFilePath] = statSync15(fullFilePath).mtimeMs;
30640
32131
  } catch (e) {
30641
32132
  logError(e);
30642
32133
  }
@@ -31051,8 +32542,25 @@ Game project changes must pass through verification layers before being committe
31051
32542
  ## Harness Self-Evolution
31052
32543
  When your changes cause an error and you fix it:
31053
32544
  1. Analyze the root cause
31054
- 2. Determine which rule file should be updated to prevent the same class of error
31055
- 3. Add a rule with the shortest possible statement + a correct-usage example`;
32545
+ 2. Determine which rule file should be updated (.danya/rules/) to prevent the same class of error
32546
+ 3. Route to the correct file:
32547
+ - Forbidden zone violation \u2192 constitution.md
32548
+ - Coding principle violation \u2192 golden-principles.md
32549
+ - Known pitfall \u2192 known-pitfalls.md
32550
+ - Architecture boundary \u2192 architecture-boundaries.md
32551
+ 4. Add a rule: \u274C what went wrong + \u2705 correct approach
32552
+ 5. Keep total lines per rule file under 550
32553
+ The system will prompt you when it detects an error-then-fix pattern. Cooperate by writing the rule update.
32554
+ You can also manually run /fix-harness at any time.
32555
+
32556
+ ## Subagent Dispatch
32557
+ Use subagents to avoid polluting the main context with large search/analysis results:
32558
+ - Searching 5+ files \u2192 dispatch to subagent, get back a file list
32559
+ - Analyzing large compilation output \u2192 dispatch to subagent, get back a summary
32560
+ - Exploring unfamiliar codebase area \u2192 dispatch to subagent, get back structure overview
32561
+ - Checking all event subscriptions/references \u2192 dispatch to subagent, get back unmatched pairs
32562
+ Rule of thumb: if the task needs 5+ tool calls and you only need the final result, use a subagent.
32563
+ Do NOT use subagents for: single file edits, single command execution, reading 2-3 files.`;
31056
32564
  }
31057
32565
  function getExecutingWithCareSection() {
31058
32566
  return `# Executing Actions with Care