oh-my-opencode 4.18.2 → 4.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.ja.md +2 -2
  2. package/README.ko.md +2 -2
  3. package/README.md +4 -4
  4. package/README.ru.md +2 -2
  5. package/README.zh-cn.md +2 -2
  6. package/dist/agents/atlas/agent.d.ts +6 -5
  7. package/dist/agents/sisyphus/index.d.ts +5 -0
  8. package/dist/agents/sisyphus/kimi-k3.d.ts +19 -0
  9. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  10. package/dist/agents/sisyphus-junior/agent.d.ts +8 -4
  11. package/dist/agents/sisyphus-junior/index.d.ts +2 -0
  12. package/dist/agents/sisyphus-junior/kimi-k3.d.ts +12 -0
  13. package/dist/agents/types.d.ts +2 -2
  14. package/dist/cli/index.js +648 -136
  15. package/dist/cli-node/index.js +648 -136
  16. package/dist/config/index.d.ts +1 -1
  17. package/dist/config/schema/browser-automation.d.ts +1 -0
  18. package/dist/config/schema/commands.d.ts +1 -3
  19. package/dist/config/schema/default-mode.d.ts +1 -1
  20. package/dist/config/schema/goal.d.ts +7 -0
  21. package/dist/config/schema/hooks.d.ts +1 -1
  22. package/dist/config/schema/oh-my-opencode-config.d.ts +6 -10
  23. package/dist/config/schema/ralph-loop.d.ts +1 -1
  24. package/dist/config/schema.d.ts +1 -1
  25. package/dist/create-hooks.d.ts +1 -1
  26. package/dist/features/builtin-commands/templates/goal.d.ts +1 -0
  27. package/dist/features/builtin-commands/templates/stop-continuation.d.ts +1 -1
  28. package/dist/features/builtin-commands/types.d.ts +1 -1
  29. package/dist/hooks/auto-slash-command/executor.d.ts +1 -0
  30. package/dist/hooks/goal/command-arguments.d.ts +13 -0
  31. package/dist/hooks/goal/controller.d.ts +26 -0
  32. package/dist/hooks/goal/index.d.ts +23 -0
  33. package/dist/hooks/goal/prompt.d.ts +3 -0
  34. package/dist/hooks/goal/store.d.ts +8 -0
  35. package/dist/hooks/goal/tools.d.ts +10 -0
  36. package/dist/hooks/goal/types.d.ts +93 -0
  37. package/dist/hooks/goal/validation.d.ts +4 -0
  38. package/dist/hooks/index.d.ts +1 -0
  39. package/dist/hooks/keyword-detector/hook.d.ts +1 -2
  40. package/dist/hooks/ralph-loop/types.d.ts +1 -1
  41. package/dist/index.js +3515 -4365
  42. package/dist/oh-my-opencode.schema.json +23 -19
  43. package/dist/plugin/chat-message/loop-commands.d.ts +1 -1
  44. package/dist/plugin/chat-message/types.d.ts +23 -10
  45. package/dist/plugin/hooks/create-core-hooks.d.ts +1 -1
  46. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -2
  47. package/dist/plugin/hooks/create-transform-hooks.d.ts +0 -2
  48. package/dist/plugin/stop-continuation.d.ts +2 -2
  49. package/dist/shared/system-directive.d.ts +0 -1
  50. package/dist/skills/ulw-plan/SKILL.md +11 -7
  51. package/dist/skills/ulw-plan/references/full-workflow.md +117 -6
  52. package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  53. package/dist/skills/ulw-research/SKILL.md +3 -3
  54. package/dist/tools/delegate-task/types.d.ts +0 -1
  55. package/dist/tui.js +73 -25
  56. package/package.json +14 -14
  57. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  58. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +352 -17
  59. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  60. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  61. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +7 -6
  62. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +97 -30
  63. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  64. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +1 -1
  65. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  66. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  67. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  68. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  69. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  70. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  71. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +1 -0
  72. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  73. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  74. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  75. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  76. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  77. package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +8 -0
  78. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +147 -60
  79. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  80. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  81. package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +3 -71
  82. package/packages/omo-codex/plugin/components/start-work-continuation/src/plan-checklist.ts +171 -0
  83. package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +198 -23
  84. package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +4 -3
  85. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +6 -5
  86. package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/plan-scaffold.md +15 -0
  87. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  88. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  89. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  90. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  91. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -10
  92. package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +3 -3
  93. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  94. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  95. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +11 -7
  96. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +117 -6
  97. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  98. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  99. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  106. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  107. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  108. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  109. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  110. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  111. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  112. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  113. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  114. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  115. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  116. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  117. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  118. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  119. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  120. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  121. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  122. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  123. package/packages/omo-codex/plugin/package-lock.json +13 -13
  124. package/packages/omo-codex/plugin/package.json +1 -1
  125. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +32 -28
  126. package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +17 -45
  127. package/packages/omo-codex/plugin/scripts/migrate-codex-config/toml-section-editor.mjs +455 -0
  128. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +3 -18
  129. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +11 -7
  130. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +117 -6
  131. package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  132. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +2 -2
  133. package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +2 -2
  134. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +6 -6
  135. package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +3 -3
  136. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +62 -0
  137. package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +271 -14
  138. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +3 -18
  139. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +0 -5
  140. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +293 -0
  141. package/packages/omo-codex/scripts/install-config.test.mjs +10 -10
  142. package/packages/omo-codex/scripts/install-dist/install-local.mjs +353 -18
  143. package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +39 -2
  144. package/packages/shared-skills/skills/ulw-plan/SKILL.md +11 -7
  145. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +117 -6
  146. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  147. package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -3
  148. package/dist/features/builtin-commands/templates/ralph-loop.d.ts +0 -3
  149. package/dist/skills/ultraresearch/SKILL.md +0 -10
  150. package/packages/shared-skills/skills/lcx-contribute-bug-fix/SKILL.md +0 -273
  151. package/packages/shared-skills/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -12
  152. package/packages/shared-skills/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -107
  153. package/packages/shared-skills/skills/lcx-doctor/SKILL.md +0 -128
  154. package/packages/shared-skills/skills/lcx-doctor/agents/openai.yaml +0 -11
  155. package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +0 -268
  156. package/packages/shared-skills/skills/lcx-report-bug/agents/openai.yaml +0 -11
  157. package/packages/shared-skills/skills/ultraresearch/SKILL.md +0 -10
  158. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/SKILL.md +0 -0
  159. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -0
  160. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -0
  161. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/SKILL.md +0 -0
  162. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/agents/openai.yaml +0 -0
  163. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/SKILL.md +0 -0
  164. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/agents/openai.yaml +0 -0
@@ -882,9 +882,16 @@ function findTomlSection(config, header) {
882
882
  const lines = config.match(/[^\n]*\n?|$/g) ?? [];
883
883
  let offset = 0;
884
884
  let start = -1;
885
+ let multilineQuote = null;
885
886
  for (const line of lines) {
886
887
  if (line.length === 0)
887
888
  break;
889
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
890
+ multilineQuote = multilineScan.nextQuote;
891
+ if (multilineScan.wasInside) {
892
+ offset += line.length;
893
+ continue;
894
+ }
888
895
  const trimmed = line.trim();
889
896
  if (start === -1) {
890
897
  if (tomlTableHeaderMatches(trimmed, headerLine, targetHeaderPath))
@@ -899,8 +906,37 @@ function findTomlSection(config, header) {
899
906
  return { start, end: config.length, text: config.slice(start) };
900
907
  }
901
908
  function replaceOrInsertSetting(config, section, key, value) {
902
- const linePattern = new RegExp(`^[ \\t]*${escapeRegExp(key)}[ \\t]*=.*$`, "m");
903
- const replacement = linePattern.test(section.text) ? section.text.replace(linePattern, `${key} = ${value}`) : insertSetting(section.text, key, value);
909
+ const targetPath = parseTomlDottedKey(key);
910
+ if (!targetPath)
911
+ return config;
912
+ const lines = section.text.match(/[^\n]*\n?|$/g) ?? [];
913
+ let offset = 0;
914
+ let multilineQuote = null;
915
+ for (const line of lines) {
916
+ if (line.length === 0)
917
+ break;
918
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
919
+ multilineQuote = multilineScan.nextQuote;
920
+ if (multilineScan.wasInside) {
921
+ offset += line.length;
922
+ continue;
923
+ }
924
+ const assignmentIndex = findUnquotedAssignment(line);
925
+ if (assignmentIndex < 0) {
926
+ offset += line.length;
927
+ continue;
928
+ }
929
+ const settingPath = parseTomlDottedKey(line.slice(0, assignmentIndex).trim());
930
+ if (!settingPath || !tomlPathMatches(settingPath, targetPath)) {
931
+ offset += line.length;
932
+ continue;
933
+ }
934
+ const replacement2 = replaceTomlAssignmentValue(line, assignmentIndex, value);
935
+ const assignmentEnd = multilineScan.nextQuote ? findTomlMultilineValueEnd(section.text, offset + line.length, multilineScan.nextQuote) : offset + line.length;
936
+ const sectionReplacement = section.text.slice(0, offset) + replacement2 + section.text.slice(assignmentEnd);
937
+ return config.slice(0, section.start) + sectionReplacement + config.slice(section.end);
938
+ }
939
+ const replacement = insertSetting(section.text, key, value);
904
940
  return config.slice(0, section.start) + replacement + config.slice(section.end);
905
941
  }
906
942
  function removeSetting(config, section, key) {
@@ -920,6 +956,50 @@ function replaceOrInsertRootSetting(config, key, value) {
920
956
  return replacement;
921
957
  return `${replacement.trimEnd()}
922
958
 
959
+ ${suffix.trimStart()}`;
960
+ }
961
+ function replaceOrInsertRootDottedSetting(config, keyPath, value) {
962
+ const targetPath = parseTomlDottedKey(keyPath);
963
+ if (!targetPath)
964
+ return config;
965
+ const lines = config.match(/[^\n]*\n?|$/g) ?? [];
966
+ let offset = 0;
967
+ let multilineQuote = null;
968
+ for (const line of lines) {
969
+ if (line.length === 0)
970
+ break;
971
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
972
+ multilineQuote = multilineScan.nextQuote;
973
+ if (multilineScan.wasInside) {
974
+ offset += line.length;
975
+ continue;
976
+ }
977
+ if (isTomlTableHeaderLine(line))
978
+ break;
979
+ const assignmentIndex = findUnquotedAssignment(line);
980
+ if (assignmentIndex < 0) {
981
+ offset += line.length;
982
+ continue;
983
+ }
984
+ const settingPath = parseTomlDottedKey(line.slice(0, assignmentIndex).trim());
985
+ if (!settingPath || !tomlPathMatches(settingPath, targetPath)) {
986
+ offset += line.length;
987
+ continue;
988
+ }
989
+ const replacement2 = replaceTomlAssignmentValue(line, assignmentIndex, value);
990
+ const assignmentEnd = multilineScan.nextQuote ? findTomlMultilineValueEnd(config, offset + line.length, multilineScan.nextQuote) : offset + line.length;
991
+ return config.slice(0, offset) + replacement2 + config.slice(assignmentEnd);
992
+ }
993
+ const sectionStart = findFirstTableStart(config);
994
+ const root = config.slice(0, sectionStart).trimEnd();
995
+ const suffix = config.slice(sectionStart);
996
+ const replacement = `${root}${root.length > 0 ? `
997
+ ` : ""}${keyPath} = ${value}
998
+ `;
999
+ if (suffix.length === 0)
1000
+ return replacement;
1001
+ return `${replacement.trimEnd()}
1002
+
923
1003
  ${suffix.trimStart()}`;
924
1004
  }
925
1005
  function appendBlock(config, block) {
@@ -932,9 +1012,16 @@ function appendBlock(config, block) {
932
1012
  function findFirstTableStart(config) {
933
1013
  const lines = config.match(/[^\n]*\n?|$/g) ?? [];
934
1014
  let offset = 0;
1015
+ let multilineQuote = null;
935
1016
  for (const line of lines) {
936
1017
  if (line.length === 0)
937
1018
  break;
1019
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
1020
+ multilineQuote = multilineScan.nextQuote;
1021
+ if (multilineScan.wasInside) {
1022
+ offset += line.length;
1023
+ continue;
1024
+ }
938
1025
  if (isTomlTableHeaderLine(line))
939
1026
  return offset;
940
1027
  offset += line.length;
@@ -972,6 +1059,131 @@ function isTomlTableHeaderLine(line) {
972
1059
  const normalizedLine = stripUnquotedInlineComment(line).trim();
973
1060
  return normalizedLine.startsWith("[") && normalizedLine.endsWith("]");
974
1061
  }
1062
+ function scanTomlMultilineLine(line, currentQuote) {
1063
+ if (currentQuote) {
1064
+ return {
1065
+ wasInside: true,
1066
+ nextQuote: findTomlMultilineDelimiter(line, currentQuote, 0) === -1 ? currentQuote : null
1067
+ };
1068
+ }
1069
+ let quote = null;
1070
+ let index = 0;
1071
+ while (index < line.length) {
1072
+ const char = line[index];
1073
+ if (quote === '"') {
1074
+ if (char === "\\") {
1075
+ index += 2;
1076
+ continue;
1077
+ }
1078
+ if (char === '"')
1079
+ quote = null;
1080
+ index += 1;
1081
+ continue;
1082
+ }
1083
+ if (quote === "'") {
1084
+ if (char === "'")
1085
+ quote = null;
1086
+ index += 1;
1087
+ continue;
1088
+ }
1089
+ if (char === "#")
1090
+ break;
1091
+ const delimiter2 = line.startsWith('"""', index) ? '"""' : line.startsWith("'''", index) ? "'''" : null;
1092
+ if (delimiter2) {
1093
+ const closingIndex = findTomlMultilineDelimiter(line, delimiter2, index + delimiter2.length);
1094
+ return { wasInside: false, nextQuote: closingIndex === -1 ? delimiter2 : null };
1095
+ }
1096
+ if (char === '"' || char === "'")
1097
+ quote = char;
1098
+ index += 1;
1099
+ }
1100
+ return { wasInside: false, nextQuote: null };
1101
+ }
1102
+ function findTomlMultilineDelimiter(line, delimiter2, startIndex) {
1103
+ let index = line.indexOf(delimiter2, startIndex);
1104
+ while (index !== -1) {
1105
+ if (delimiter2 === "'''" || countPrecedingBackslashes(line, index) % 2 === 0)
1106
+ return index;
1107
+ index = line.indexOf(delimiter2, index + 1);
1108
+ }
1109
+ return -1;
1110
+ }
1111
+ function countPrecedingBackslashes(line, index) {
1112
+ let count = 0;
1113
+ let cursor = index - 1;
1114
+ while (cursor >= 0 && line[cursor] === "\\") {
1115
+ count += 1;
1116
+ cursor -= 1;
1117
+ }
1118
+ return count;
1119
+ }
1120
+ function findUnquotedAssignment(line) {
1121
+ return findUnquotedCharacter(line, "=", 0);
1122
+ }
1123
+ function findUnquotedComment(line, startIndex) {
1124
+ return findUnquotedCharacter(line, "#", startIndex);
1125
+ }
1126
+ function findUnquotedCharacter(line, target, startIndex) {
1127
+ let quote = null;
1128
+ let index = startIndex;
1129
+ while (index < line.length) {
1130
+ const char = line[index];
1131
+ if (quote === '"') {
1132
+ if (char === "\\") {
1133
+ index += 2;
1134
+ continue;
1135
+ }
1136
+ if (char === '"')
1137
+ quote = null;
1138
+ index += 1;
1139
+ continue;
1140
+ }
1141
+ if (quote === "'") {
1142
+ if (char === "'")
1143
+ quote = null;
1144
+ index += 1;
1145
+ continue;
1146
+ }
1147
+ if (char === '"' || char === "'") {
1148
+ quote = char;
1149
+ index += 1;
1150
+ continue;
1151
+ }
1152
+ if (char === target)
1153
+ return index;
1154
+ if (char === "#")
1155
+ return -1;
1156
+ index += 1;
1157
+ }
1158
+ return -1;
1159
+ }
1160
+ function tomlPathMatches(candidate, target) {
1161
+ return candidate.length === target.length && candidate.every((part, index) => part === target[index]);
1162
+ }
1163
+ function replaceTomlAssignmentValue(line, assignmentIndex, value) {
1164
+ const newline = line.endsWith(`
1165
+ `) ? `
1166
+ ` : "";
1167
+ const lineBody = newline ? line.slice(0, -1) : line;
1168
+ const commentIndex = findUnquotedComment(lineBody, assignmentIndex + 1);
1169
+ const comment = commentIndex === -1 ? "" : ` ${lineBody.slice(commentIndex).trimStart()}`;
1170
+ return `${lineBody.slice(0, assignmentIndex + 1)} ${value}${comment}${newline}`;
1171
+ }
1172
+ function findTomlMultilineValueEnd(text, startOffset, quote) {
1173
+ const lines = text.slice(startOffset).match(/[^\n]*\n?|$/g) ?? [];
1174
+ let offset = startOffset;
1175
+ let currentQuote = quote;
1176
+ for (const line of lines) {
1177
+ if (line.length === 0)
1178
+ break;
1179
+ const scan = scanTomlMultilineLine(line, currentQuote);
1180
+ currentQuote = scan.nextQuote;
1181
+ offset += line.length;
1182
+ if (currentQuote === null)
1183
+ return offset;
1184
+ }
1185
+ return text.length;
1186
+ }
975
1187
  function stripUnquotedInlineComment(line) {
976
1188
  let quote = null;
977
1189
  let index = 0;
@@ -1232,6 +1444,10 @@ var MANAGED_REASONING_DEFAULT_UPGRADES = new Map([
1232
1444
  {
1233
1445
  previous: { model: "gpt-5.5", effort: "xhigh" },
1234
1446
  current: { model: "gpt-5.6-sol", effort: "ultra" }
1447
+ },
1448
+ {
1449
+ previous: { model: "gpt-5.6-sol", effort: "ultra" },
1450
+ current: { model: "gpt-5.6-terra", effort: "high" }
1235
1451
  }
1236
1452
  ]
1237
1453
  ],
@@ -2195,13 +2411,137 @@ function delay(milliseconds) {
2195
2411
  return new Promise((resolveDelay) => setTimeout(resolveDelay, milliseconds));
2196
2412
  }
2197
2413
 
2414
+ // ../src/install/toml-setting-reader.ts
2415
+ function hasTomlSetting(config, keyPath) {
2416
+ const targetPath = parseTomlDottedKey(keyPath);
2417
+ if (!targetPath)
2418
+ return false;
2419
+ return hasTomlAssignment(config, (tablePath, settingPath) => {
2420
+ const fullPath = [...tablePath, ...settingPath];
2421
+ return fullPath.length === targetPath.length && fullPath.every((part, index) => part === targetPath[index]);
2422
+ });
2423
+ }
2424
+ function hasTomlRootDottedKeyPrefix(config, rootKey) {
2425
+ return hasTomlAssignment(config, (tablePath, settingPath) => tablePath.length === 0 && settingPath.length > 1 && settingPath[0] === rootKey);
2426
+ }
2427
+ function hasTomlAssignment(config, predicate) {
2428
+ let tablePath = [];
2429
+ let multilineQuote = null;
2430
+ for (const line of config.split(`
2431
+ `)) {
2432
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
2433
+ multilineQuote = multilineScan.nextQuote;
2434
+ if (multilineScan.wasInside)
2435
+ continue;
2436
+ const normalizedLine = stripUnquotedInlineComment2(line).trim();
2437
+ if (normalizedLine.length === 0)
2438
+ continue;
2439
+ const headerPath = parseTomlTableHeader2(normalizedLine);
2440
+ if (headerPath) {
2441
+ tablePath = headerPath;
2442
+ continue;
2443
+ }
2444
+ if (isTomlTableHeaderLine2(normalizedLine)) {
2445
+ tablePath = null;
2446
+ continue;
2447
+ }
2448
+ if (!tablePath)
2449
+ continue;
2450
+ const assignmentIndex = findUnquotedAssignment2(normalizedLine);
2451
+ if (assignmentIndex < 0)
2452
+ continue;
2453
+ const settingPath = parseTomlDottedKey(normalizedLine.slice(0, assignmentIndex).trim());
2454
+ if (!settingPath)
2455
+ continue;
2456
+ if (predicate(tablePath, settingPath))
2457
+ return true;
2458
+ }
2459
+ return false;
2460
+ }
2461
+ function parseTomlTableHeader2(line) {
2462
+ if (!line.startsWith("[") || !line.endsWith("]") || line.startsWith("[["))
2463
+ return null;
2464
+ return parseTomlDottedKey(line.slice(1, -1).trim());
2465
+ }
2466
+ function isTomlTableHeaderLine2(line) {
2467
+ return line.startsWith("[") && line.endsWith("]");
2468
+ }
2469
+ function stripUnquotedInlineComment2(line) {
2470
+ let quote = null;
2471
+ let index = 0;
2472
+ while (index < line.length) {
2473
+ const char = line[index];
2474
+ if (quote === '"') {
2475
+ if (char === "\\") {
2476
+ index += 2;
2477
+ continue;
2478
+ }
2479
+ if (char === '"')
2480
+ quote = null;
2481
+ index += 1;
2482
+ continue;
2483
+ }
2484
+ if (quote === "'") {
2485
+ if (char === "'")
2486
+ quote = null;
2487
+ index += 1;
2488
+ continue;
2489
+ }
2490
+ if (char === '"' || char === "'") {
2491
+ quote = char;
2492
+ index += 1;
2493
+ continue;
2494
+ }
2495
+ if (char === "#")
2496
+ return line.slice(0, index);
2497
+ index += 1;
2498
+ }
2499
+ return line;
2500
+ }
2501
+ function findUnquotedAssignment2(line) {
2502
+ let quote = null;
2503
+ let index = 0;
2504
+ while (index < line.length) {
2505
+ const char = line[index];
2506
+ if (quote === '"') {
2507
+ if (char === "\\") {
2508
+ index += 2;
2509
+ continue;
2510
+ }
2511
+ if (char === '"')
2512
+ quote = null;
2513
+ index += 1;
2514
+ continue;
2515
+ }
2516
+ if (quote === "'") {
2517
+ if (char === "'")
2518
+ quote = null;
2519
+ index += 1;
2520
+ continue;
2521
+ }
2522
+ if (char === '"' || char === "'") {
2523
+ quote = char;
2524
+ index += 1;
2525
+ continue;
2526
+ }
2527
+ if (char === "=")
2528
+ return index;
2529
+ index += 1;
2530
+ }
2531
+ return -1;
2532
+ }
2533
+
2198
2534
  // ../src/install/codex-config-features.ts
2199
2535
  function ensureFeatureEnabled(config, featureName) {
2200
2536
  const section = findTomlSection(config, "features");
2201
- if (!section)
2537
+ if (!section) {
2538
+ if (hasTomlRootDottedKeyPrefix(config, "features")) {
2539
+ return replaceOrInsertRootDottedSetting(config, `features.${featureName}`, "true");
2540
+ }
2202
2541
  return appendBlock(config, `[features]
2203
2542
  ${featureName} = true
2204
2543
  `);
2544
+ }
2205
2545
  return replaceOrInsertSetting(config, section, featureName, "true");
2206
2546
  }
2207
2547
 
@@ -2269,7 +2609,7 @@ function ensureAutonomousPermissions(config) {
2269
2609
  next = replaceOrInsertRootSetting(next, "sandbox_mode", JSON.stringify("danger-full-access"));
2270
2610
  next = replaceOrInsertRootSetting(next, "network_access", JSON.stringify("enabled"));
2271
2611
  for (const featureName of AUTONOMOUS_FEATURES) {
2272
- next = ensureFeatureEnabled2(next, featureName);
2612
+ next = ensureFeatureEnabled(next, featureName);
2273
2613
  }
2274
2614
  next = removeWindowsSandboxSetting(next);
2275
2615
  next = ensureNoticeEnabled(next, "hide_full_access_warning");
@@ -2287,14 +2627,6 @@ function ensureNoticeEnabled(config, key) {
2287
2627
  return appendNoticeBlock(config, key);
2288
2628
  return replaceOrInsertSetting(config, section, key, "true");
2289
2629
  }
2290
- function ensureFeatureEnabled2(config, key) {
2291
- const section = findTomlSection(config, "features");
2292
- if (section === null)
2293
- return appendBlock(config, `[features]
2294
- ${key} = true
2295
- `);
2296
- return replaceOrInsertSetting(config, section, key, "true");
2297
- }
2298
2630
  function appendNoticeBlock(config, key) {
2299
2631
  return appendBlock(config, `[notice]
2300
2632
  ${key} = true
@@ -2366,7 +2698,7 @@ function readStringArraySetting(sectionText, key) {
2366
2698
  const assignmentIndex = line.indexOf("=");
2367
2699
  if (assignmentIndex === -1)
2368
2700
  return null;
2369
- return parseTomlStringArray(stripUnquotedInlineComment2(line.slice(assignmentIndex + 1)).trim());
2701
+ return parseTomlStringArray(stripUnquotedInlineComment3(line.slice(assignmentIndex + 1)).trim());
2370
2702
  }
2371
2703
  return null;
2372
2704
  }
@@ -2410,7 +2742,7 @@ function parseTomlString(input, startIndex) {
2410
2742
  }
2411
2743
  return null;
2412
2744
  }
2413
- function stripUnquotedInlineComment2(line) {
2745
+ function stripUnquotedInlineComment3(line) {
2414
2746
  let quote = null;
2415
2747
  let index = 0;
2416
2748
  while (index < line.length) {
@@ -2624,24 +2956,27 @@ import { readFileSync } from "node:fs";
2624
2956
  import { dirname as dirname7, isAbsolute as isAbsolute5, join as join17 } from "node:path";
2625
2957
  var CODEX_AGENTS_HEADER = "agents";
2626
2958
  var CODEX_MULTI_AGENT_V2_HEADER = "features.multi_agent_v2";
2959
+ var CODEX_MULTI_AGENT_V2_THREAD_LIMIT_KEY = `${CODEX_MULTI_AGENT_V2_HEADER}.max_concurrent_threads_per_session`;
2627
2960
  var CODEX_SUBAGENT_THREAD_LIMIT = 1000;
2961
+ var CODEX_MULTI_AGENT_V2_THREAD_LIMIT = 16;
2628
2962
  function ensureCodexMultiAgentV2Config(config, options = {}) {
2629
2963
  const featureFlag = removeFeatureFlagSetting(config, "multi_agent_v2");
2630
2964
  const v2Preferred = options.multiAgentVersion === "v2";
2631
2965
  const modelKnown = options.multiAgentVersion != null || readRootModel(featureFlag.config) !== null;
2632
2966
  const agentsConfig = v2Preferred ? removeAgentsMaxThreads(featureFlag.config) : modelKnown ? ensureAgentsMaxThreads(featureFlag.config) : raiseExistingAgentsMaxThreads(featureFlag.config);
2633
- const maxThreadsValue = CODEX_SUBAGENT_THREAD_LIMIT.toString();
2634
2967
  const preserveDisable = featureFlag.value === false && !v2Preferred;
2635
2968
  const featureConfig = preserveDisable ? setMultiAgentV2Disable(agentsConfig) : v2Preferred ? removeMultiAgentV2Disable(agentsConfig) : agentsConfig;
2969
+ if (hasTomlSetting(featureConfig, CODEX_MULTI_AGENT_V2_THREAD_LIMIT_KEY))
2970
+ return featureConfig;
2636
2971
  const section = findTomlSection(featureConfig, CODEX_MULTI_AGENT_V2_HEADER);
2637
2972
  if (!section) {
2638
2973
  const enabledSetting = preserveDisable ? `enabled = false
2639
2974
  ` : "";
2640
2975
  return appendBlock(featureConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
2641
- ${enabledSetting}max_concurrent_threads_per_session = ${maxThreadsValue}
2976
+ ${enabledSetting}max_concurrent_threads_per_session = ${CODEX_MULTI_AGENT_V2_THREAD_LIMIT}
2642
2977
  `);
2643
2978
  }
2644
- return replaceOrInsertSetting(featureConfig, section, "max_concurrent_threads_per_session", maxThreadsValue);
2979
+ return replaceOrInsertSetting(featureConfig, section, "max_concurrent_threads_per_session", CODEX_MULTI_AGENT_V2_THREAD_LIMIT.toString());
2645
2980
  }
2646
2981
  function resolveCodexMultiAgentVersion(config, configPath) {
2647
2982
  const model = readRootModel(config);
@@ -8,7 +8,7 @@
8
8
  "command": "node \"${PLUGIN_ROOT}/components/bootstrap/dist/cli.js\" hook session-start",
9
9
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1\"",
10
10
  "timeout": 30,
11
- "statusMessage": "(OmO 4.18.2) Checking Bootstrap Provisioning"
11
+ "statusMessage": "(OmO 4.19.0) Checking Bootstrap Provisioning"
12
12
  }
13
13
  ]
14
14
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/codex-bootstrap",
3
- "version": "4.18.2",
3
+ "version": "4.19.0",
4
4
  "description": "Codex SessionStart bootstrap component that provisions LazyCodex runtime dependencies from a detached worker.",
5
5
  "type": "module",
6
6
  "private": true,
@@ -1,6 +1,6 @@
1
- # packages/omo-codex/plugin/components/codegraph/ CodeGraph MCP Wrapper + Bootstrap Hooks
1
+ # packages/omo-codex/plugin/components/codegraph/ (CodeGraph MCP Wrapper + Bootstrap Hooks)
2
2
 
3
- **Generated:** 2026-07-03
3
+ **Generated:** 2026-07-17 (7d664b96b)
4
4
 
5
5
  ## OVERVIEW
6
6
 
@@ -12,13 +12,13 @@ Codex wiring (all repo-relative to `packages/omo-codex/plugin/`):
12
12
  - **PostToolUse hook:** `hooks/post-tool-use-checking-codegraph-init-guidance.json`, matcher `^(codegraph[._].*|mcp__codegraph__.*)$` → `dist/cli.js hook post-tool-use`.
13
13
  - Both hooks registered in `.codex-plugin/plugin.json`; Windows variants dispatch via `components/bootstrap/scripts/node-dispatch.ps1`.
14
14
 
15
- Serve pipeline (`src/serve.ts`): OMO SOT config gate (`[codex].codegraph.enabled=false` → unavailable stub) → resolve binary (`OMO_CODEGRAPH_BIN` env → bundled → provisioned `~/.omo/codegraph/bin` → PATH) → Node support gate (major 2024; >=25 crashes CodeGraph mid-indexing; `CODEGRAPH_ALLOW_UNSAFE_NODE=1` overrides) → auto-provision into `~/.omo/codegraph` unless `codegraph.auto_provision=false` → bridge JSON-RPC to `codegraph serve --mcp`. Project cwd resolved from `OMO_CODEGRAPH_PROJECT_CWD` → `OMO_CODEGRAPH_SESSION_START_CWD` → `PWD` → wrapper cwd. When the binary is missing/disabled, `mcp-unavailable.ts` still answers `initialize`/`tools/*` with the skip reason so Codex startup never fails.
15
+ Serve pipeline (`src/serve.ts`): OMO SOT config gate (`[codex].codegraph.enabled=false` → unavailable stub) → resolve binary (`OMO_CODEGRAPH_BIN` env → bundled → provisioned `~/.omo/codegraph/bin` → PATH) → Node support gate (major 20-24; >=25 crashes CodeGraph mid-indexing; `CODEGRAPH_ALLOW_UNSAFE_NODE=1` overrides) → auto-provision into `~/.omo/codegraph` unless `codegraph.auto_provision=false` → bridge JSON-RPC to `codegraph serve --mcp`. Project cwd resolved from `OMO_CODEGRAPH_PROJECT_CWD` → `OMO_CODEGRAPH_SESSION_START_CWD` → `PWD` → wrapper cwd. When the binary is missing/disabled, `mcp-unavailable.ts` still answers `initialize`/`tools/*` with the skip reason so Codex startup never fails.
16
16
 
17
17
  Hook pipeline (`src/hook.ts` + `src/session-start-worker.ts`): `hook session-start` probes `status --json` (2s timeout); uninitialized project → spawns a detached `hook session-start-worker` (prepare workspace + gitignore → `status --json` → `init` or `sync`, 60s per command) and emits a SessionStart `additionalContext` notice. Worker outcomes append to `~/.omo/codegraph/session-start.jsonl`. `hook post-tool-use` emits init guidance when a codegraph tool result indicates an uninitialized project. `cli.js` with no hook subcommand falls through to serve.
18
18
 
19
19
  ## includeCode CONTRACT (commit 4cf383c5b)
20
20
 
21
- `src/mcp-bridge.ts` rewrites the upstream `codegraph_node` contract in-flight: `tools/list` responses get a clarified description + `includeCode` schema description, and `tools/call` results replace "Structural outline only" text. Contract: `includeCode=true` returns leaf-symbol source only; container symbols (classes, interfaces, structs, enums, modules, namespaces) return structural outlines with member lists BY DESIGN for container source, request a specific member symbol or file mode with `symbolsOnly=false` plus `offset`/`limit`. Pinned by `test/serve-mcp-bridge.test.ts`.
21
+ `src/mcp-bridge.ts` rewrites the upstream `codegraph_node` contract in-flight: `tools/list` responses get a clarified description + `includeCode` schema description, and `tools/call` results replace "Structural outline only" text. Contract: `includeCode=true` returns leaf-symbol source only; container symbols (classes, interfaces, structs, enums, modules, namespaces) return structural outlines with member lists BY DESIGN: for container source, request a specific member symbol or file mode with `symbolsOnly=false` plus `offset`/`limit`. Pinned by `test/serve-mcp-bridge.test.ts`.
22
22
 
23
23
  ## KEY FILES
24
24
 
@@ -28,7 +28,7 @@ Hook pipeline (`src/hook.ts` + `src/session-start-worker.ts`): `hook session-sta
28
28
  | `src/cli.ts` | Hook CLI router: `hook session-start` / `hook post-tool-use` / `hook session-start-worker` / serve fallback |
29
29
  | `src/hook.ts` | SessionStart probe + detached worker spawn, PostToolUse guidance emission |
30
30
  | `src/session-start-worker.ts` | Background bootstrap: provision → workspace prep → `init`/`sync`, jsonl outcome log |
31
- | `src/mcp-bridge.ts` | Stdio JSON-RPC forwarder; per-request framed/line response-mode tracking; codegraph_node contract rewrites |
31
+ | `src/mcp-bridge.ts` | Stdio JSON-RPC forwarder; per-request framed/line response-mode tracking; codegraph_node contract rewrites; awaits stdio writes and SIGKILLs the child on response-forwarding failure |
32
32
  | `src/mcp-unavailable.ts` | Reason-bearing stub MCP server for disabled/missing binary |
33
33
  | `src/serve-invocation.ts` | win32 invocation shim: `.cmd`/`.bat` via `cmd.exe /d /s /c`, `.js`/`.mjs`/`.cjs` via `process.execPath` (mirrored by `resolveCodegraphCommandInvocation` in session-start-worker) |
34
34
  | `src/hook-types.ts` | Shared hook/worker option + outcome types |
@@ -37,7 +37,7 @@ Hook pipeline (`src/hook.ts` + `src/session-start-worker.ts`): `hook session-sta
37
37
 
38
38
  | Task | Location |
39
39
  |------|----------|
40
- | Resolution order, provisioning, Node gate, env, gitignore/workspace prep | `packages/utils/src/codegraph/` (`resolve.ts`, `provision.ts`, `node-support.ts`, `env.ts`, `workspace.ts`, `guidance.ts`) bundled at build time |
40
+ | Resolution order, provisioning, Node gate, env, gitignore/workspace prep | `packages/utils/src/codegraph/` (`resolve.ts`, `provision.ts`, `node-support.ts`, `env.ts`, `workspace.ts`, `guidance.ts`), bundled at build time |
41
41
  | `[codex].codegraph` config keys (`enabled`, `auto_provision`, `trustedCodegraphInstallDir`) | `packages/omo-codex/plugin/shared/src/config-loader.ts` |
42
42
  | JSON-RPC framing primitives | `packages/mcp-stdio-core/src/` |
43
43
  | Build / test / typecheck | `bun run build` (bun build → `dist/serve.js` + `dist/cli.js`, target node ESM), `bun test ./test`, `tsc --noEmit` |
@@ -49,3 +49,4 @@ Hook pipeline (`src/hook.ts` + `src/session-start-worker.ts`): `hook session-sta
49
49
  - `CODEGRAPH_VERSION` is duplicated in `serve.ts` and `session-start-worker.ts` and must match the `@colbymchenry/codegraph` optionalDependency version.
50
50
  - `trustedCodegraphInstallDir` overrides the `~/.omo/codegraph` install dir and is forwarded to children as `CODEGRAPH_INSTALL_DIR`.
51
51
  - `resolution.source === "env"` is never auto-provisioned over: a user-set `OMO_CODEGRAPH_BIN` pointing at a missing file skips the MCP instead of silently substituting a download.
52
+ - `runBridgedCodegraphProcess` awaits every stdio write and races `childExit` against response forwarding; a forwarding error (e.g. parent stdout `EPIPE`) rejects the serve promise, destroys the child pipes, and `SIGKILL`s the codegraph child if still alive so a held-open child is never orphaned. Pinned by `test/serve-mcp-bridge-lifecycle.test.ts` and the held-open case in `test/serve-mcp-bridge.test.ts`.