@code-yeongyu/senpi 2026.9.23-2 → 2026.9.23-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 (181) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/bundle/chunks/{app-server-command-UO3ODP6D.js → app-server-command-U5Y46LHO.js} +1 -1
  3. package/dist/bundle/chunks/{chunk-OLJ7LQJY.js → chunk-BBOQ5H4W.js} +1 -1
  4. package/dist/bundle/chunks/{chunk-7EH64T6E.js → chunk-ORCF262V.js} +2 -2
  5. package/dist/bundle/chunks/{chunk-BPHXJ4N2.js → chunk-R6F525XB.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-LMO3WYKH.js → chunk-TH4PERSI.js} +131 -124
  7. package/dist/bundle/chunks/{chunk-IBHBWRC4.js → chunk-TUVSARCZ.js} +2 -2
  8. package/dist/bundle/chunks/{chunk-WJ2BGYFK.js → chunk-XPDV6SIX.js} +1 -1
  9. package/dist/bundle/chunks/{chunk-IDJUNOOR.js → chunk-Y4AJLTFT.js} +2 -2
  10. package/dist/bundle/chunks/{cli-main-LUQZADLN.js → cli-main-65WMMIRT.js} +1 -1
  11. package/dist/bundle/chunks/{interactive-host-runtime-A6PM52FT.js → interactive-host-runtime-DUNYT24Q.js} +1 -1
  12. package/dist/bundle/chunks/{interactive-mode-VR7QYMAE.js → interactive-mode-SCG5PQZ6.js} +1 -1
  13. package/dist/bundle/chunks/{list-tips-VGOIMT6W.js → list-tips-Z62FXPOJ.js} +1 -1
  14. package/dist/bundle/chunks/{multi-session-host-LYOVVA75.js → multi-session-host-QC6BZZNH.js} +1 -1
  15. package/dist/bundle/chunks/{package-manager-cli-OMEJACX6.js → package-manager-cli-23GULCVL.js} +1 -1
  16. package/dist/bundle/chunks/{rpc-mode-AKGJA73P.js → rpc-mode-ZQ4E6FFA.js} +1 -1
  17. package/dist/bundle/chunks/{session-picker-UE5LOM6W.js → session-picker-CO2ZK3EC.js} +1 -1
  18. package/dist/bundle/chunks/session-worker.js +202 -195
  19. package/dist/bundle/cli.js +1 -1
  20. package/dist/bundle/index.js +1 -1
  21. package/dist/bundle/rpc-entry.js +1 -1
  22. package/dist/core/extensions/builtin/anthropic-subscription/executable-model-support.d.ts +19 -0
  23. package/dist/core/extensions/builtin/anthropic-subscription/executable-model-support.d.ts.map +1 -0
  24. package/dist/core/extensions/builtin/anthropic-subscription/executable-model-support.js +76 -0
  25. package/dist/core/extensions/builtin/anthropic-subscription/executable-model-support.js.map +1 -0
  26. package/dist/core/extensions/builtin/anthropic-subscription/executable-path-lookup.d.ts +7 -2
  27. package/dist/core/extensions/builtin/anthropic-subscription/executable-path-lookup.d.ts.map +1 -1
  28. package/dist/core/extensions/builtin/anthropic-subscription/executable-path-lookup.js +28 -3
  29. package/dist/core/extensions/builtin/anthropic-subscription/executable-path-lookup.js.map +1 -1
  30. package/dist/core/extensions/builtin/anthropic-subscription/executable.d.ts +11 -0
  31. package/dist/core/extensions/builtin/anthropic-subscription/executable.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/anthropic-subscription/executable.js +31 -10
  33. package/dist/core/extensions/builtin/anthropic-subscription/executable.js.map +1 -1
  34. package/dist/core/extensions/builtin/anthropic-subscription/guidance.d.ts +2 -1
  35. package/dist/core/extensions/builtin/anthropic-subscription/guidance.d.ts.map +1 -1
  36. package/dist/core/extensions/builtin/anthropic-subscription/guidance.js +18 -2
  37. package/dist/core/extensions/builtin/anthropic-subscription/guidance.js.map +1 -1
  38. package/dist/core/extensions/builtin/anthropic-subscription/stream-guidance.d.ts +2 -1
  39. package/dist/core/extensions/builtin/anthropic-subscription/stream-guidance.d.ts.map +1 -1
  40. package/dist/core/extensions/builtin/anthropic-subscription/stream-guidance.js +2 -2
  41. package/dist/core/extensions/builtin/anthropic-subscription/stream-guidance.js.map +1 -1
  42. package/dist/core/extensions/builtin/anthropic-subscription/stream.d.ts.map +1 -1
  43. package/dist/core/extensions/builtin/anthropic-subscription/stream.js +5 -3
  44. package/dist/core/extensions/builtin/anthropic-subscription/stream.js.map +1 -1
  45. package/dist/core/extensions/builtin/goal/cache-warm-renderer.d.ts +6 -0
  46. package/dist/core/extensions/builtin/goal/cache-warm-renderer.d.ts.map +1 -1
  47. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js +8 -0
  48. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js.map +1 -1
  49. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  50. package/dist/core/extensions/builtin/goal/index.js +4 -2
  51. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  52. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts +3 -1
  53. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  54. package/dist/core/extensions/builtin/goal/monitor-continuation.js +32 -10
  55. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  56. package/dist/core/extensions/builtin/goal/parked-wait.d.ts +16 -0
  57. package/dist/core/extensions/builtin/goal/parked-wait.d.ts.map +1 -0
  58. package/dist/core/extensions/builtin/goal/parked-wait.js +54 -0
  59. package/dist/core/extensions/builtin/goal/parked-wait.js.map +1 -0
  60. package/dist/core/extensions/builtin/mcp/auth/commands-auth-dispatch.d.ts +1 -1
  61. package/dist/core/extensions/builtin/mcp/auth/commands-auth-dispatch.d.ts.map +1 -1
  62. package/dist/core/extensions/builtin/mcp/auth/commands-auth-dispatch.js +8 -2
  63. package/dist/core/extensions/builtin/mcp/auth/commands-auth-dispatch.js.map +1 -1
  64. package/dist/core/extensions/builtin/mcp/auth/commands-auth.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/mcp/auth/commands-auth.js +15 -4
  66. package/dist/core/extensions/builtin/mcp/auth/commands-auth.js.map +1 -1
  67. package/dist/core/extensions/builtin/mcp/commands.d.ts.map +1 -1
  68. package/dist/core/extensions/builtin/mcp/commands.js +2 -0
  69. package/dist/core/extensions/builtin/mcp/commands.js.map +1 -1
  70. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts +5 -5
  71. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
  72. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +16 -11
  73. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  74. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts +5 -5
  75. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts.map +1 -1
  76. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +9 -6
  77. package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js.map +1 -1
  78. package/dist/core/extensions/builtin/prompt-preset/test-decision.d.ts +2 -0
  79. package/dist/core/extensions/builtin/prompt-preset/test-decision.d.ts.map +1 -0
  80. package/dist/core/extensions/builtin/prompt-preset/test-decision.js +5 -0
  81. package/dist/core/extensions/builtin/prompt-preset/test-decision.js.map +1 -0
  82. package/dist/core/extensions/index.d.ts +1 -1
  83. package/dist/core/extensions/index.d.ts.map +1 -1
  84. package/dist/core/extensions/index.js.map +1 -1
  85. package/dist/core/extensions/loader.d.ts.map +1 -1
  86. package/dist/core/extensions/loader.js +6 -1
  87. package/dist/core/extensions/loader.js.map +1 -1
  88. package/dist/core/extensions/runner.d.ts +3 -1
  89. package/dist/core/extensions/runner.d.ts.map +1 -1
  90. package/dist/core/extensions/runner.js +5 -0
  91. package/dist/core/extensions/runner.js.map +1 -1
  92. package/dist/core/extensions/types.d.ts +10 -1
  93. package/dist/core/extensions/types.d.ts.map +1 -1
  94. package/dist/core/extensions/types.js.map +1 -1
  95. package/dist/core/model-config.d.ts +1 -0
  96. package/dist/core/model-config.d.ts.map +1 -1
  97. package/dist/core/model-config.js +26 -20
  98. package/dist/core/model-config.js.map +1 -1
  99. package/dist/core/models-json-migration.d.ts +30 -0
  100. package/dist/core/models-json-migration.d.ts.map +1 -0
  101. package/dist/core/models-json-migration.js +257 -0
  102. package/dist/core/models-json-migration.js.map +1 -0
  103. package/dist/core/output-guard.d.ts +2 -0
  104. package/dist/core/output-guard.d.ts.map +1 -1
  105. package/dist/core/output-guard.js +31 -0
  106. package/dist/core/output-guard.js.map +1 -1
  107. package/dist/core/settings-manager.d.ts +4 -0
  108. package/dist/core/settings-manager.d.ts.map +1 -1
  109. package/dist/core/settings-manager.js +16 -6
  110. package/dist/core/settings-manager.js.map +1 -1
  111. package/dist/core/settings-overrides.d.ts +8 -0
  112. package/dist/core/settings-overrides.d.ts.map +1 -0
  113. package/dist/core/settings-overrides.js +28 -0
  114. package/dist/core/settings-overrides.js.map +1 -0
  115. package/dist/index.d.ts +1 -1
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.js.map +1 -1
  118. package/dist/modes/interactive/components/assistant-message.d.ts +2 -0
  119. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  120. package/dist/modes/interactive/components/assistant-message.js +4 -0
  121. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  122. package/dist/modes/interactive/components/custom-entry.d.ts +10 -1
  123. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  124. package/dist/modes/interactive/components/custom-entry.js +22 -0
  125. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  126. package/dist/modes/interactive/components/exploration-call.d.ts +12 -0
  127. package/dist/modes/interactive/components/exploration-call.d.ts.map +1 -0
  128. package/dist/modes/interactive/components/exploration-call.js +41 -0
  129. package/dist/modes/interactive/components/exploration-call.js.map +1 -0
  130. package/dist/modes/interactive/components/exploration-group.d.ts +19 -0
  131. package/dist/modes/interactive/components/exploration-group.d.ts.map +1 -0
  132. package/dist/modes/interactive/components/exploration-group.js +89 -0
  133. package/dist/modes/interactive/components/exploration-group.js.map +1 -0
  134. package/dist/modes/interactive/components/exploration-transcript-container.d.ts +18 -0
  135. package/dist/modes/interactive/components/exploration-transcript-container.d.ts.map +1 -0
  136. package/dist/modes/interactive/components/exploration-transcript-container.js +67 -0
  137. package/dist/modes/interactive/components/exploration-transcript-container.js.map +1 -0
  138. package/dist/modes/interactive/components/tool-execution.d.ts +7 -1
  139. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  140. package/dist/modes/interactive/components/tool-execution.js +4 -0
  141. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  142. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  143. package/dist/modes/interactive/interactive-mode.js +24 -35
  144. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  145. package/dist/modes/interactive/replay-assistant-tools.d.ts +14 -0
  146. package/dist/modes/interactive/replay-assistant-tools.d.ts.map +1 -0
  147. package/dist/modes/interactive/replay-assistant-tools.js +33 -0
  148. package/dist/modes/interactive/replay-assistant-tools.js.map +1 -0
  149. package/dist/modes/interactive/tool-progress.d.ts +2 -0
  150. package/dist/modes/interactive/tool-progress.d.ts.map +1 -1
  151. package/dist/modes/interactive/tool-progress.js +5 -2
  152. package/dist/modes/interactive/tool-progress.js.map +1 -1
  153. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  154. package/dist/modes/interactive/tui-renderer.js +6 -1
  155. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  156. package/docs/extensions.md +8 -0
  157. package/docs/mcp.md +9 -6
  158. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +16 -0
  159. package/node_modules/@code-yeongyu/senpi-codemode/README.md +10 -8
  160. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  161. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/display-code.ts +145 -0
  162. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-request.ts +7 -12
  163. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +2 -2
  164. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +34 -16
  165. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +1 -4
  166. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  167. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  168. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  169. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  170. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  171. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  172. package/node_modules/@earendil-works/pi-tui/dist/stderr-observer.d.ts +3 -0
  173. package/node_modules/@earendil-works/pi-tui/dist/stderr-observer.d.ts.map +1 -0
  174. package/node_modules/@earendil-works/pi-tui/dist/stderr-observer.js +14 -0
  175. package/node_modules/@earendil-works/pi-tui/dist/stderr-observer.js.map +1 -0
  176. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +4 -1
  177. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  178. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +8 -12
  179. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  180. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  181. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"commands-auth.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/auth/commands-auth.ts"],"names":[],"mappings":"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","sourcesContent":["import type { McpServerConfig } from \"../config-schema.ts\";\nimport type { McpLogger } from \"../log.ts\";\nimport { openCallbackChannel } from \"./callback.ts\";\nimport { resolveServerAuth } from \"./context.ts\";\nimport type { OAuthFlowOptions } from \"./oauth.ts\";\nimport {\n\tbeginAuthorization,\n\tclientCredentialsGrant,\n\tcompleteAuthorization,\n\tfinishAuthorization,\n\tlogout,\n} from \"./oauth.ts\";\nimport { OAuthFlowError } from \"./oauth-errors.ts\";\nimport type { McpOAuthProvider } from \"./oauth-provider.ts\";\n\ntype Notify = (message: string, type?: \"info\" | \"warning\" | \"error\") => void;\n\nexport interface AuthCommandDeps {\n\tserverName: string;\n\tconfig: McpServerConfig;\n\tagentDir?: string;\n\tenv?: Record<string, string | undefined>;\n\tlogger?: McpLogger;\n\thasUI: boolean;\n\tnotify: Notify;\n\t// settings.oauthCallbackUrl override: when set, no local listener is opened.\n\tcallbackUrl?: string;\n\topenBrowser?: (url: URL) => void | Promise<void>;\n\tonReconnect: () => Promise<void>;\n\t// Persists the provider between auth-start and auth-complete so the in-memory\n\t// CSRF state survives across two command invocations in one session.\n\tpending: Map<string, McpOAuthProvider>;\n\t/** Per-service guard: the same server may authenticate in another session. */\n\tinteractiveGuard?: { begin(serverName: string): boolean; end(serverName: string): void };\n\tflow?: OAuthFlowOptions;\n}\n\nconst PASTE_REDIRECT = \"http://127.0.0.1:0/callback\";\nconst activeInteractiveAuthServers = new Set<string>();\n\nfunction ensureOAuth(deps: AuthCommandDeps): void {\n\tif (deps.config.auth === false || deps.config.type !== \"http\" || deps.config.url === undefined) {\n\t\tthrow new OAuthFlowError(\"headless\", `MCP server ${deps.serverName} is not an OAuth HTTP server.`, {\n\t\t\tserverName: deps.serverName,\n\t\t});\n\t}\n}\n\nfunction buildProvider(\n\tdeps: AuthCommandDeps,\n\tredirectUrl: string,\n\tonRedirect?: (url: URL) => void | Promise<void>,\n): McpOAuthProvider {\n\tconst plan = resolveServerAuth({\n\t\tagentDir: deps.agentDir,\n\t\tconfig: { ...deps.config, auth: \"oauth\" },\n\t\tenv: deps.env,\n\t\tlogger: deps.logger,\n\t\tonRedirect,\n\t\tredirectUrl,\n\t\tserverName: deps.serverName,\n\t});\n\tif (plan.provider === undefined) {\n\t\tthrow new OAuthFlowError(\"headless\", `MCP server ${deps.serverName} could not build an OAuth provider.`, {\n\t\t\tserverName: deps.serverName,\n\t\t});\n\t}\n\treturn plan.provider;\n}\n\n// `/mcp auth <server>`: client_credentials M2M, or interactive loopback flow.\n// Non-UI callers fail fast with an actionable headless hint (no browser).\nexport async function runAuth(deps: AuthCommandDeps): Promise<void> {\n\tensureOAuth(deps);\n\tif (deps.config.oauth?.flow === \"client_credentials\") {\n\t\tconst provider = buildProvider(deps, deps.callbackUrl ?? PASTE_REDIRECT);\n\t\tawait clientCredentialsGrant(provider, deps.flow);\n\t\tawait deps.onReconnect();\n\t\tdeps.notify(`MCP server ${deps.serverName} authenticated (client_credentials)`);\n\t\treturn;\n\t}\n\tif (!deps.hasUI) {\n\t\tdeps.notify(\n\t\t\t`MCP server ${deps.serverName} needs interactive OAuth. Run senpi in a terminal, then: /mcp auth-start ${deps.serverName} and /mcp auth-complete ${deps.serverName} <redirect-url>`,\n\t\t\t\"error\",\n\t\t);\n\t\treturn;\n\t}\n\tawait runInteractive(deps);\n}\n\nasync function runInteractive(deps: AuthCommandDeps): Promise<void> {\n\tconst beginInteractiveAuth =\n\t\tdeps.interactiveGuard?.begin(deps.serverName) ?? !activeInteractiveAuthServers.has(deps.serverName);\n\tif (!beginInteractiveAuth) {\n\t\tthrow new OAuthFlowError(\n\t\t\t\"needs_auth\",\n\t\t\t`MCP server ${deps.serverName} authorization is already in progress; complete the existing browser flow or retry after it finishes.`,\n\t\t\t{ serverName: deps.serverName },\n\t\t);\n\t}\n\tif (deps.interactiveGuard === undefined) activeInteractiveAuthServers.add(deps.serverName);\n\tlet provider: McpOAuthProvider | undefined;\n\tlet channel: Awaited<ReturnType<typeof openCallbackChannel>> | undefined;\n\tconst oauth = deps.config.oauth;\n\tlet callbackPort: number | undefined;\n\tif (\n\t\t(deps.callbackUrl === undefined || deps.callbackUrl.length === 0) &&\n\t\toauth?.clientId !== undefined &&\n\t\toauth.clientMetadataUrl === undefined\n\t) {\n\t\tcallbackPort = oauth.callbackPort;\n\t}\n\ttry {\n\t\tchannel = await openCallbackChannel({\n\t\t\toverrideUrl: deps.callbackUrl,\n\t\t\tport: callbackPort,\n\t\t\tserverName: deps.serverName,\n\t\t\tvalidateState: (state) => provider?.consumeState(state) ?? false,\n\t\t});\n\t\tconst loopbackResult = channel.usesLoopback ? channel.waitForCode() : undefined;\n\t\tprovider = buildProvider(deps, channel.redirectUrl, (url) => deps.openBrowser?.(url));\n\t\tconst begin = await beginAuthorization(provider, deps.flow);\n\t\tif (begin.authorizationUrl !== undefined) deps.notify(`Opening browser to authorize ${deps.serverName}...`);\n\t\tif (!channel.usesLoopback) {\n\t\t\tdeps.pending.set(deps.serverName, provider);\n\t\t\tif (begin.authorizationUrl === undefined) {\n\t\t\t\tthrow new OAuthFlowError(\n\t\t\t\t\t\"needs_auth\",\n\t\t\t\t\t`MCP server ${deps.serverName} did not produce an authorization URL.`,\n\t\t\t\t\t{\n\t\t\t\t\t\tserverName: deps.serverName,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\tdeps.notify(\n\t\t\t\t`Complete the browser flow, then run /mcp auth-complete ${deps.serverName} <redirect-url> with the final redirect URL.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst { code } = await (loopbackResult ?? channel.waitForCode());\n\t\tawait finishAuthorization(provider, code, deps.flow);\n\t\tawait deps.onReconnect();\n\t\tdeps.notify(`MCP server ${deps.serverName} authorized`);\n\t} finally {\n\t\tif (deps.interactiveGuard) deps.interactiveGuard.end(deps.serverName);\n\t\telse activeInteractiveAuthServers.delete(deps.serverName);\n\t\tawait channel?.close();\n\t}\n}\n\n// `/mcp auth-start <server>`: print the authorize URL for a browser-less paste.\nexport async function runAuthStart(deps: AuthCommandDeps): Promise<string> {\n\tensureOAuth(deps);\n\tconst provider = buildProvider(deps, deps.callbackUrl ?? PASTE_REDIRECT);\n\tconst begin = await beginAuthorization(provider, deps.flow);\n\tconst url = begin.authorizationUrl;\n\tif (url === undefined) {\n\t\tthrow new OAuthFlowError(\"needs_auth\", `MCP server ${deps.serverName} did not produce an authorization URL.`, {\n\t\t\tserverName: deps.serverName,\n\t\t});\n\t}\n\tdeps.pending.set(deps.serverName, provider);\n\tdeps.notify(\n\t\t`Open this URL, approve, then run /mcp auth-complete ${deps.serverName} <redirect-url>:\\n${url.toString()}`,\n\t);\n\treturn url.toString();\n}\n\n// `/mcp auth-complete <server> <redirect-url>`: finish the paste flow.\nexport async function runAuthComplete(deps: AuthCommandDeps, redirectUrl: string): Promise<void> {\n\tensureOAuth(deps);\n\tconst pending = deps.pending.get(deps.serverName);\n\tconst provider = pending ?? buildProvider(deps, deps.callbackUrl ?? PASTE_REDIRECT);\n\tawait completeAuthorization(provider, redirectUrl, deps.flow);\n\tdeps.pending.delete(deps.serverName);\n\tawait deps.onReconnect();\n\tdeps.notify(`MCP server ${deps.serverName} authorized`);\n}\n\n// `/mcp logout <server>`: clear stored credentials.\nexport async function runLogout(deps: AuthCommandDeps): Promise<void> {\n\tconst provider = buildProvider(deps, PASTE_REDIRECT);\n\tawait logout(provider);\n\tdeps.pending.delete(deps.serverName);\n\tawait deps.onReconnect();\n\tdeps.notify(`MCP server ${deps.serverName} logged out`);\n}\n"]}
1
+ {"version":3,"file":"commands-auth.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/mcp/auth/commands-auth.ts"],"names":[],"mappings":"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","sourcesContent":["import type { McpServerConfig } from \"../config-schema.ts\";\nimport type { McpLogger } from \"../log.ts\";\nimport { openCallbackChannel } from \"./callback.ts\";\nimport { resolveServerAuth } from \"./context.ts\";\nimport type { OAuthFlowOptions } from \"./oauth.ts\";\nimport {\n\tbeginAuthorization,\n\tclientCredentialsGrant,\n\tcompleteAuthorization,\n\tfinishAuthorization,\n\tlogout,\n} from \"./oauth.ts\";\nimport { OAuthFlowError } from \"./oauth-errors.ts\";\nimport type { McpOAuthProvider } from \"./oauth-provider.ts\";\n\ntype Notify = (message: string, type?: \"info\" | \"warning\" | \"error\") => void;\n\nexport interface AuthCommandDeps {\n\tserverName: string;\n\tconfig: McpServerConfig;\n\tagentDir?: string;\n\tenv?: Record<string, string | undefined>;\n\tlogger?: McpLogger;\n\thasUI: boolean;\n\tnotify: Notify;\n\t// settings.oauthCallbackUrl override: when set, no local listener is opened.\n\tcallbackUrl?: string;\n\topenBrowser?: (url: URL) => void | Promise<void>;\n\tonReconnect: () => Promise<void>;\n\t// Persists the provider between auth-start and auth-complete so the in-memory\n\t// CSRF state survives across two command invocations in one session.\n\tpending: Map<string, McpOAuthProvider>;\n\t/** Per-service guard: the same server may authenticate in another session. */\n\tinteractiveGuard?: { begin(serverName: string): boolean; end(serverName: string): void };\n\tflow?: OAuthFlowOptions;\n}\n\nconst PASTE_REDIRECT = \"http://127.0.0.1:0/callback\";\nconst activeInteractiveAuthServers = new Set<string>();\n\nfunction ensureOAuth(deps: AuthCommandDeps): void {\n\tif (deps.config.auth === false || deps.config.type !== \"http\" || deps.config.url === undefined) {\n\t\tthrow new OAuthFlowError(\"headless\", `MCP server ${deps.serverName} is not an OAuth HTTP server.`, {\n\t\t\tserverName: deps.serverName,\n\t\t});\n\t}\n}\n\nfunction buildProvider(\n\tdeps: AuthCommandDeps,\n\tredirectUrl: string,\n\tonRedirect?: (url: URL) => void | Promise<void>,\n): McpOAuthProvider {\n\tconst plan = resolveServerAuth({\n\t\tagentDir: deps.agentDir,\n\t\tconfig: { ...deps.config, auth: \"oauth\" },\n\t\tenv: deps.env,\n\t\tlogger: deps.logger,\n\t\tonRedirect,\n\t\tredirectUrl,\n\t\tserverName: deps.serverName,\n\t});\n\tif (plan.provider === undefined) {\n\t\tthrow new OAuthFlowError(\"headless\", `MCP server ${deps.serverName} could not build an OAuth provider.`, {\n\t\t\tserverName: deps.serverName,\n\t\t});\n\t}\n\treturn plan.provider;\n}\n\n// `/mcp auth <server>`: client_credentials M2M, or interactive loopback flow.\n// Non-UI callers fail fast with an actionable headless hint (no browser).\nexport async function runAuth(deps: AuthCommandDeps): Promise<void> {\n\tensureOAuth(deps);\n\tif (deps.config.oauth?.flow === \"client_credentials\") {\n\t\tconst provider = buildProvider(deps, deps.callbackUrl ?? PASTE_REDIRECT);\n\t\tawait clientCredentialsGrant(provider, deps.flow);\n\t\tawait deps.onReconnect();\n\t\tdeps.notify(`MCP server ${deps.serverName} authenticated (client_credentials)`);\n\t\treturn;\n\t}\n\tif (!deps.hasUI) {\n\t\tdeps.notify(\n\t\t\t`MCP server ${deps.serverName} needs interactive OAuth. Run senpi in a terminal, then: /mcp auth-start ${deps.serverName} and /mcp auth-complete ${deps.serverName} <redirect-url>`,\n\t\t\t\"error\",\n\t\t);\n\t\treturn;\n\t}\n\tawait runInteractive(deps);\n}\n\nasync function runInteractive(deps: AuthCommandDeps): Promise<void> {\n\tconst beginInteractiveAuth =\n\t\tdeps.interactiveGuard?.begin(deps.serverName) ?? !activeInteractiveAuthServers.has(deps.serverName);\n\tif (!beginInteractiveAuth) {\n\t\tthrow new OAuthFlowError(\n\t\t\t\"needs_auth\",\n\t\t\t`MCP server ${deps.serverName} authorization is already in progress; complete the existing browser flow or retry after it finishes.`,\n\t\t\t{ serverName: deps.serverName },\n\t\t);\n\t}\n\tif (deps.interactiveGuard === undefined) activeInteractiveAuthServers.add(deps.serverName);\n\tlet provider: McpOAuthProvider | undefined;\n\tlet channel: Awaited<ReturnType<typeof openCallbackChannel>> | undefined;\n\tconst oauth = deps.config.oauth;\n\tlet callbackPort: number | undefined;\n\tif (\n\t\t(deps.callbackUrl === undefined || deps.callbackUrl.length === 0) &&\n\t\toauth?.clientId !== undefined &&\n\t\toauth.clientMetadataUrl === undefined\n\t) {\n\t\tcallbackPort = oauth.callbackPort;\n\t}\n\ttry {\n\t\tchannel = await openCallbackChannel({\n\t\t\toverrideUrl: deps.callbackUrl,\n\t\t\tport: callbackPort,\n\t\t\tserverName: deps.serverName,\n\t\t\tvalidateState: (state) => provider?.consumeState(state) ?? false,\n\t\t});\n\t\tconst loopbackResult = channel.usesLoopback ? channel.waitForCode() : undefined;\n\t\tconst usesLoopback = channel.usesLoopback;\n\t\tprovider = buildProvider(deps, channel.redirectUrl, async (url) => {\n\t\t\tconst instruction = usesLoopback\n\t\t\t\t? \"\"\n\t\t\t\t: `\\nThen run /mcp auth-complete ${deps.serverName} <redirect-url> with the final redirect URL.`;\n\t\t\tconst announcement = `Open this URL to authorize ${deps.serverName}:\\n${url.toString()}${instruction}`;\n\t\t\tdeps.notify(announcement);\n\t\t\ttry {\n\t\t\t\tawait deps.openBrowser?.(url);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tdeps.notify(`Browser launch failed: ${message}\\n${announcement}`, \"warning\");\n\t\t\t}\n\t\t});\n\t\tconst begin = await beginAuthorization(provider, deps.flow);\n\t\tif (!channel.usesLoopback) {\n\t\t\tdeps.pending.set(deps.serverName, provider);\n\t\t\tif (begin.authorizationUrl === undefined) {\n\t\t\t\tthrow new OAuthFlowError(\n\t\t\t\t\t\"needs_auth\",\n\t\t\t\t\t`MCP server ${deps.serverName} did not produce an authorization URL.`,\n\t\t\t\t\t{\n\t\t\t\t\t\tserverName: deps.serverName,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tconst { code } = await (loopbackResult ?? channel.waitForCode());\n\t\tawait finishAuthorization(provider, code, deps.flow);\n\t\tawait deps.onReconnect();\n\t\tdeps.notify(`MCP server ${deps.serverName} authorized`);\n\t} finally {\n\t\tif (deps.interactiveGuard) deps.interactiveGuard.end(deps.serverName);\n\t\telse activeInteractiveAuthServers.delete(deps.serverName);\n\t\tawait channel?.close();\n\t}\n}\n\n// `/mcp auth-start <server>`: print the authorize URL for a browser-less paste.\nexport async function runAuthStart(deps: AuthCommandDeps): Promise<string> {\n\tensureOAuth(deps);\n\tconst provider = buildProvider(deps, deps.callbackUrl ?? PASTE_REDIRECT);\n\tconst begin = await beginAuthorization(provider, deps.flow);\n\tconst url = begin.authorizationUrl;\n\tif (url === undefined) {\n\t\tthrow new OAuthFlowError(\"needs_auth\", `MCP server ${deps.serverName} did not produce an authorization URL.`, {\n\t\t\tserverName: deps.serverName,\n\t\t});\n\t}\n\tdeps.pending.set(deps.serverName, provider);\n\tdeps.notify(\n\t\t`Open this URL, approve, then run /mcp auth-complete ${deps.serverName} <redirect-url>:\\n${url.toString()}`,\n\t);\n\treturn url.toString();\n}\n\n// `/mcp auth-complete <server> <redirect-url>`: finish the paste flow.\nexport async function runAuthComplete(deps: AuthCommandDeps, redirectUrl: string): Promise<void> {\n\tensureOAuth(deps);\n\tconst pending = deps.pending.get(deps.serverName);\n\tconst provider = pending ?? buildProvider(deps, deps.callbackUrl ?? PASTE_REDIRECT);\n\tawait completeAuthorization(provider, redirectUrl, deps.flow);\n\tdeps.pending.delete(deps.serverName);\n\tawait deps.onReconnect();\n\tdeps.notify(`MCP server ${deps.serverName} authorized`);\n}\n\n// `/mcp logout <server>`: clear stored credentials.\nexport async function runLogout(deps: AuthCommandDeps): Promise<void> {\n\tconst provider = buildProvider(deps, PASTE_REDIRECT);\n\tawait logout(provider);\n\tdeps.pending.delete(deps.serverName);\n\tawait deps.onReconnect();\n\tdeps.notify(`MCP server ${deps.serverName} logged out`);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/mcp/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,gBAAgB,CAAC;AAwB5E,wBAAgB,mBAAmB,CAClC,EAAE,EAAE,YAAY,EAChB,OAAO,oCAAkB,EACzB,aAAa,GAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,SAA2B,GAC9D,IAAI,CAiBN"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/mcp/commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,gBAAgB,CAAC;AAwB5E,wBAAgB,mBAAmB,CAClC,EAAE,EAAE,YAAY,EAChB,OAAO,oCAAkB,EACzB,aAAa,GAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,SAA2B,GAC9D,IAAI,CAuBN"}
@@ -1,3 +1,4 @@
1
+ import { noticeEntryRenderer } from "../../notice/index.js";
1
2
  import { handleMcpAuthCommand } from "./auth/commands-auth-dispatch.js";
2
3
  import { addGlobalMcpServer, setGlobalMcpServerEnabled } from "./config-edit.js";
3
4
  import { getMcpService } from "./service.js";
@@ -18,6 +19,7 @@ const SUBCOMMANDS = [
18
19
  ];
19
20
  const AUTH_SUBCOMMANDS = new Set(["auth", "auth-start", "auth-complete", "logout"]);
20
21
  export function registerMcpCommands(pi, service = getMcpService(), pendingAttach = () => undefined) {
22
+ pi.registerEntryRenderer("mcp-auth", noticeEntryRenderer((entry) => typeof entry.data === "string" ? { title: "MCP authorization", why: entry.data } : undefined));
21
23
  pi.registerCommand("mcp", {
22
24
  description: "Inspect and manage MCP servers.",
23
25
  getArgumentCompletions: (prefix) => SUBCOMMANDS.filter((item) => item.startsWith(prefix)).map((value) => ({ value, label: value })),
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/mcp/commands.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionAPI, ExtensionCommandContext } from \"../../types.ts\";\nimport { handleMcpAuthCommand } from \"./auth/commands-auth-dispatch.ts\";\nimport { addGlobalMcpServer, setGlobalMcpServerEnabled } from \"./config-edit.ts\";\nimport type { McpServerConfig } from \"./config-schema.ts\";\nimport { getMcpService } from \"./service.ts\";\nimport { MCP_STARTUP_RACE_MS } from \"./startup-race.ts\";\nimport { buildMcpStatusRows, formatMcpStatus } from \"./status.ts\";\n\nconst SUBCOMMANDS = [\n\t\"status\",\n\t\"add\",\n\t\"enable\",\n\t\"disable\",\n\t\"test\",\n\t\"logs\",\n\t\"reconnect\",\n\t\"auth\",\n\t\"auth-start\",\n\t\"auth-complete\",\n\t\"logout\",\n] as const;\n\nconst AUTH_SUBCOMMANDS = new Set([\"auth\", \"auth-start\", \"auth-complete\", \"logout\"]);\n\nexport function registerMcpCommands(\n\tpi: ExtensionAPI,\n\tservice = getMcpService(),\n\tpendingAttach: () => Promise<void> | undefined = () => undefined,\n): void {\n\tpi.registerCommand(\"mcp\", {\n\t\tdescription: \"Inspect and manage MCP servers.\",\n\t\tgetArgumentCompletions: (prefix) =>\n\t\t\tSUBCOMMANDS.filter((item) => item.startsWith(prefix)).map((value) => ({ value, label: value })),\n\t\thandler: async (rawArgs, ctx) => {\n\t\t\ttry {\n\t\t\t\t// Startup attach no longer blocks the first frame, so /mcp can be reached while it is still\n\t\t\t\t// in flight. Every subcommand reports or mutates attached state, so wait for the single\n\t\t\t\t// in-flight attach rather than rendering a half-connected snapshot.\n\t\t\t\tawait pendingAttach();\n\t\t\t\tawait handleMcpCommand(rawArgs, ctx, pi, service);\n\t\t\t} catch (error) {\n\t\t\t\tctx.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t\t\t}\n\t\t},\n\t});\n}\n\nasync function handleMcpCommand(\n\trawArgs: string,\n\tctx: ExtensionCommandContext,\n\tpi: ExtensionAPI,\n\tservice: ReturnType<typeof getMcpService>,\n): Promise<void> {\n\tconst args = splitCommandArgs(rawArgs);\n\tconst subcommand = args[0] ?? \"\";\n\tif (subcommand === \"\") {\n\t\tawait showPanel(ctx, service);\n\t\treturn;\n\t}\n\tif (AUTH_SUBCOMMANDS.has(subcommand)) {\n\t\tawait handleMcpAuthCommand(subcommand, args.slice(1), ctx, pi, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"status\") {\n\t\tawait notifyStatus(ctx, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"add\") {\n\t\tawait addServer(args.slice(1), ctx, pi, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"enable\" || subcommand === \"disable\") {\n\t\tawait setServerEnabled(ctx, pi, service, args[1] ?? \"\", subcommand === \"enable\");\n\t\treturn;\n\t}\n\tif (subcommand === \"test\") {\n\t\tawait testServer(args[1] ?? \"\", ctx, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"logs\") {\n\t\tshowLogs(args[1] ?? \"\", ctx, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"reconnect\") {\n\t\tawait reconnectServer(args[1] ?? \"\", ctx, pi, service);\n\t\treturn;\n\t}\n\tctx.ui.notify(`Unknown /mcp subcommand: ${subcommand}`, \"error\");\n}\n\ntype McpCommandService = ReturnType<typeof getMcpService>;\n\nasync function showPanel(ctx: ExtensionCommandContext, service: McpCommandService): Promise<void> {\n\tconst text = await renderStatus(\"MCP servers\", service);\n\tif (!ctx.hasUI) {\n\t\tctx.ui.notify(text);\n\t\treturn;\n\t}\n\tconst choice = await ctx.ui.select(text, [\"status\", \"logs <server>\", \"test <server>\"]);\n\tif (choice === undefined) ctx.ui.notify(text);\n}\n\nasync function notifyStatus(ctx: ExtensionCommandContext, service: McpCommandService): Promise<void> {\n\tctx.ui.notify(await renderStatus(\"MCP status\", service));\n}\n\nasync function renderStatus(title: string, service: McpCommandService): Promise<string> {\n\tconst rows = await buildMcpStatusRows(service.getServerSnapshots(), (name) => service.getServerExposureStatus(name));\n\treturn formatMcpStatus(title, rows);\n}\n\nasync function addServer(\n\targs: readonly string[],\n\tctx: ExtensionCommandContext,\n\tpi: Pick<ExtensionAPI, \"getActiveTools\" | \"setActiveTools\" | \"registerTool\">,\n\tservice: McpCommandService,\n): Promise<void> {\n\tconst [name, ...endpoint] = args;\n\tif (!name || endpoint.length === 0) {\n\t\tctx.ui.notify(\"Usage: /mcp add <name> <command...|url>\", \"error\");\n\t\treturn;\n\t}\n\tif (!ctx.hasUI) {\n\t\tctx.ui.notify(\"Cannot add MCP server without UI confirmation.\", \"error\");\n\t\treturn;\n\t}\n\tconst server = parseServerConfig(endpoint);\n\tconst confirmed = await ctx.ui.confirm(\"Add MCP server?\", `${name}: ${endpoint.join(\" \")}`);\n\tif (!confirmed) {\n\t\tctx.ui.notify(\"MCP add cancelled\", \"warning\");\n\t\treturn;\n\t}\n\taddGlobalMcpServer(name, server);\n\tawait service.attachSession({ type: \"session_start\", reason: \"reload\" }, ctx, pi);\n\tctx.ui.notify(`Added MCP server ${name}`);\n}\n\nasync function setServerEnabled(\n\tctx: ExtensionCommandContext,\n\tpi: Pick<ExtensionAPI, \"getActiveTools\" | \"setActiveTools\" | \"registerTool\">,\n\tservice: McpCommandService,\n\tname: string,\n\tenabled: boolean,\n): Promise<void> {\n\tif (!ensureKnown(name, ctx, service)) return;\n\tif (!setGlobalMcpServerEnabled(name, enabled)) {\n\t\tctx.ui.notify(`MCP server ${name} is not in the global config file`, \"error\");\n\t\treturn;\n\t}\n\tctx.ui.notify(`MCP server ${name} connecting`);\n\tawait service.attachSession({ type: \"session_start\", reason: \"reload\" }, ctx, pi);\n\tctx.ui.notify(`${enabled ? \"Enabled\" : \"Disabled\"} MCP server ${name}`);\n}\n\nasync function testServer(name: string, ctx: ExtensionCommandContext, service: McpCommandService): Promise<void> {\n\tif (!ensureKnown(name, ctx, service)) return;\n\tconst connection = service.getConnection(name);\n\tif (connection === undefined) return;\n\tconst started = Date.now();\n\ttry {\n\t\tawait connection.connect();\n\t\tconst result = await connection.client.listTools({}, { timeout: 2000 });\n\t\tconst elapsedMs = Date.now() - started;\n\t\tservice.recordCall(name, elapsedMs, false);\n\t\tctx.ui.notify(`MCP test ${name} ok (${elapsedMs}ms): ${result.tools.length} tools`);\n\t} catch (error) {\n\t\tconst elapsedMs = Date.now() - started;\n\t\tservice.recordCall(name, elapsedMs, true);\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tctx.ui.notify(`MCP test ${name} failed (${elapsedMs}ms): ${message}`, \"error\");\n\t}\n}\n\nfunction showLogs(name: string, ctx: ExtensionCommandContext, service: McpCommandService): void {\n\tif (!ensureKnown(name, ctx, service)) return;\n\tconst lines = service.getLogLines(name, 20);\n\tctx.ui.notify(lines.length === 0 ? `MCP logs for ${name}: (empty)` : lines.join(\"\\n\"));\n}\n\nasync function reconnectServer(\n\tname: string,\n\tctx: ExtensionCommandContext,\n\tpi: Pick<ExtensionAPI, \"getActiveTools\" | \"setActiveTools\" | \"registerTool\">,\n\tservice: McpCommandService,\n): Promise<void> {\n\tif (!ensureKnown(name, ctx, service)) return;\n\ttry {\n\t\tawait service.reconnectServer(name);\n\t\tawait service.attachSession({ type: \"session_start\", reason: \"reload\" }, ctx, pi);\n\t\tctx.ui.notify(`MCP reconnect ${name} connected`);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tctx.ui.notify(`MCP reconnect ${name} failed: ${message}`, \"error\");\n\t}\n}\n\nfunction ensureKnown(name: string, ctx: ExtensionCommandContext, service: McpCommandService): boolean {\n\tif (name.length > 0 && service.getServerSnapshots().some((snapshot) => snapshot.name === name)) return true;\n\tconst known = service\n\t\t.getServerSnapshots()\n\t\t.map((snapshot) => snapshot.name)\n\t\t.join(\", \");\n\tctx.ui.notify(`Unknown MCP server: ${name || \"<missing>\"}\\nKnown MCP servers: ${known || \"(none)\"}`, \"error\");\n\treturn false;\n}\n\nfunction parseServerConfig(endpoint: readonly string[]): McpServerConfig {\n\tconst first = endpoint[0] ?? \"\";\n\tif (/^https?:\\/\\//.test(first)) {\n\t\treturn baseServer({ type: \"http\", url: first });\n\t}\n\treturn baseServer({ type: \"stdio\", command: first, args: endpoint.slice(1) });\n}\n\nfunction baseServer(endpoint: Pick<McpServerConfig, \"type\"> & Partial<McpServerConfig>): McpServerConfig {\n\treturn {\n\t\targs: [],\n\t\tconnectTimeoutMs: 15_000,\n\t\tenabled: true,\n\t\texposure: \"auto\",\n\t\tidleTimeoutMin: 10,\n\t\tlifecycle: \"lazy\",\n\t\tlogLevel: \"info\",\n\t\trequestTimeoutMs: 30_000,\n\t\tstartupTimeoutMs: MCP_STARTUP_RACE_MS,\n\t\t...endpoint,\n\t};\n}\n\nfunction splitCommandArgs(raw: string): string[] {\n\tconst matches = raw.match(/\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'|[^\\s]+/g) ?? [];\n\treturn matches.map((part) => part.replace(/^[\"']|[\"']$/g, \"\").replace(/\\\\([\"'])/g, \"$1\"));\n}\n"]}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/mcp/commands.ts"],"names":[],"mappings":"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","sourcesContent":["import { noticeEntryRenderer } from \"../../notice/index.ts\";\nimport type { ExtensionAPI, ExtensionCommandContext } from \"../../types.ts\";\nimport { handleMcpAuthCommand } from \"./auth/commands-auth-dispatch.ts\";\nimport { addGlobalMcpServer, setGlobalMcpServerEnabled } from \"./config-edit.ts\";\nimport type { McpServerConfig } from \"./config-schema.ts\";\nimport { getMcpService } from \"./service.ts\";\nimport { MCP_STARTUP_RACE_MS } from \"./startup-race.ts\";\nimport { buildMcpStatusRows, formatMcpStatus } from \"./status.ts\";\n\nconst SUBCOMMANDS = [\n\t\"status\",\n\t\"add\",\n\t\"enable\",\n\t\"disable\",\n\t\"test\",\n\t\"logs\",\n\t\"reconnect\",\n\t\"auth\",\n\t\"auth-start\",\n\t\"auth-complete\",\n\t\"logout\",\n] as const;\n\nconst AUTH_SUBCOMMANDS = new Set([\"auth\", \"auth-start\", \"auth-complete\", \"logout\"]);\n\nexport function registerMcpCommands(\n\tpi: ExtensionAPI,\n\tservice = getMcpService(),\n\tpendingAttach: () => Promise<void> | undefined = () => undefined,\n): void {\n\tpi.registerEntryRenderer(\n\t\t\"mcp-auth\",\n\t\tnoticeEntryRenderer<string>((entry) =>\n\t\t\ttypeof entry.data === \"string\" ? { title: \"MCP authorization\", why: entry.data } : undefined,\n\t\t),\n\t);\n\tpi.registerCommand(\"mcp\", {\n\t\tdescription: \"Inspect and manage MCP servers.\",\n\t\tgetArgumentCompletions: (prefix) =>\n\t\t\tSUBCOMMANDS.filter((item) => item.startsWith(prefix)).map((value) => ({ value, label: value })),\n\t\thandler: async (rawArgs, ctx) => {\n\t\t\ttry {\n\t\t\t\t// Startup attach no longer blocks the first frame, so /mcp can be reached while it is still\n\t\t\t\t// in flight. Every subcommand reports or mutates attached state, so wait for the single\n\t\t\t\t// in-flight attach rather than rendering a half-connected snapshot.\n\t\t\t\tawait pendingAttach();\n\t\t\t\tawait handleMcpCommand(rawArgs, ctx, pi, service);\n\t\t\t} catch (error) {\n\t\t\t\tctx.ui.notify(error instanceof Error ? error.message : String(error), \"error\");\n\t\t\t}\n\t\t},\n\t});\n}\n\nasync function handleMcpCommand(\n\trawArgs: string,\n\tctx: ExtensionCommandContext,\n\tpi: ExtensionAPI,\n\tservice: ReturnType<typeof getMcpService>,\n): Promise<void> {\n\tconst args = splitCommandArgs(rawArgs);\n\tconst subcommand = args[0] ?? \"\";\n\tif (subcommand === \"\") {\n\t\tawait showPanel(ctx, service);\n\t\treturn;\n\t}\n\tif (AUTH_SUBCOMMANDS.has(subcommand)) {\n\t\tawait handleMcpAuthCommand(subcommand, args.slice(1), ctx, pi, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"status\") {\n\t\tawait notifyStatus(ctx, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"add\") {\n\t\tawait addServer(args.slice(1), ctx, pi, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"enable\" || subcommand === \"disable\") {\n\t\tawait setServerEnabled(ctx, pi, service, args[1] ?? \"\", subcommand === \"enable\");\n\t\treturn;\n\t}\n\tif (subcommand === \"test\") {\n\t\tawait testServer(args[1] ?? \"\", ctx, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"logs\") {\n\t\tshowLogs(args[1] ?? \"\", ctx, service);\n\t\treturn;\n\t}\n\tif (subcommand === \"reconnect\") {\n\t\tawait reconnectServer(args[1] ?? \"\", ctx, pi, service);\n\t\treturn;\n\t}\n\tctx.ui.notify(`Unknown /mcp subcommand: ${subcommand}`, \"error\");\n}\n\ntype McpCommandService = ReturnType<typeof getMcpService>;\n\nasync function showPanel(ctx: ExtensionCommandContext, service: McpCommandService): Promise<void> {\n\tconst text = await renderStatus(\"MCP servers\", service);\n\tif (!ctx.hasUI) {\n\t\tctx.ui.notify(text);\n\t\treturn;\n\t}\n\tconst choice = await ctx.ui.select(text, [\"status\", \"logs <server>\", \"test <server>\"]);\n\tif (choice === undefined) ctx.ui.notify(text);\n}\n\nasync function notifyStatus(ctx: ExtensionCommandContext, service: McpCommandService): Promise<void> {\n\tctx.ui.notify(await renderStatus(\"MCP status\", service));\n}\n\nasync function renderStatus(title: string, service: McpCommandService): Promise<string> {\n\tconst rows = await buildMcpStatusRows(service.getServerSnapshots(), (name) => service.getServerExposureStatus(name));\n\treturn formatMcpStatus(title, rows);\n}\n\nasync function addServer(\n\targs: readonly string[],\n\tctx: ExtensionCommandContext,\n\tpi: Pick<ExtensionAPI, \"getActiveTools\" | \"setActiveTools\" | \"registerTool\">,\n\tservice: McpCommandService,\n): Promise<void> {\n\tconst [name, ...endpoint] = args;\n\tif (!name || endpoint.length === 0) {\n\t\tctx.ui.notify(\"Usage: /mcp add <name> <command...|url>\", \"error\");\n\t\treturn;\n\t}\n\tif (!ctx.hasUI) {\n\t\tctx.ui.notify(\"Cannot add MCP server without UI confirmation.\", \"error\");\n\t\treturn;\n\t}\n\tconst server = parseServerConfig(endpoint);\n\tconst confirmed = await ctx.ui.confirm(\"Add MCP server?\", `${name}: ${endpoint.join(\" \")}`);\n\tif (!confirmed) {\n\t\tctx.ui.notify(\"MCP add cancelled\", \"warning\");\n\t\treturn;\n\t}\n\taddGlobalMcpServer(name, server);\n\tawait service.attachSession({ type: \"session_start\", reason: \"reload\" }, ctx, pi);\n\tctx.ui.notify(`Added MCP server ${name}`);\n}\n\nasync function setServerEnabled(\n\tctx: ExtensionCommandContext,\n\tpi: Pick<ExtensionAPI, \"getActiveTools\" | \"setActiveTools\" | \"registerTool\">,\n\tservice: McpCommandService,\n\tname: string,\n\tenabled: boolean,\n): Promise<void> {\n\tif (!ensureKnown(name, ctx, service)) return;\n\tif (!setGlobalMcpServerEnabled(name, enabled)) {\n\t\tctx.ui.notify(`MCP server ${name} is not in the global config file`, \"error\");\n\t\treturn;\n\t}\n\tctx.ui.notify(`MCP server ${name} connecting`);\n\tawait service.attachSession({ type: \"session_start\", reason: \"reload\" }, ctx, pi);\n\tctx.ui.notify(`${enabled ? \"Enabled\" : \"Disabled\"} MCP server ${name}`);\n}\n\nasync function testServer(name: string, ctx: ExtensionCommandContext, service: McpCommandService): Promise<void> {\n\tif (!ensureKnown(name, ctx, service)) return;\n\tconst connection = service.getConnection(name);\n\tif (connection === undefined) return;\n\tconst started = Date.now();\n\ttry {\n\t\tawait connection.connect();\n\t\tconst result = await connection.client.listTools({}, { timeout: 2000 });\n\t\tconst elapsedMs = Date.now() - started;\n\t\tservice.recordCall(name, elapsedMs, false);\n\t\tctx.ui.notify(`MCP test ${name} ok (${elapsedMs}ms): ${result.tools.length} tools`);\n\t} catch (error) {\n\t\tconst elapsedMs = Date.now() - started;\n\t\tservice.recordCall(name, elapsedMs, true);\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tctx.ui.notify(`MCP test ${name} failed (${elapsedMs}ms): ${message}`, \"error\");\n\t}\n}\n\nfunction showLogs(name: string, ctx: ExtensionCommandContext, service: McpCommandService): void {\n\tif (!ensureKnown(name, ctx, service)) return;\n\tconst lines = service.getLogLines(name, 20);\n\tctx.ui.notify(lines.length === 0 ? `MCP logs for ${name}: (empty)` : lines.join(\"\\n\"));\n}\n\nasync function reconnectServer(\n\tname: string,\n\tctx: ExtensionCommandContext,\n\tpi: Pick<ExtensionAPI, \"getActiveTools\" | \"setActiveTools\" | \"registerTool\">,\n\tservice: McpCommandService,\n): Promise<void> {\n\tif (!ensureKnown(name, ctx, service)) return;\n\ttry {\n\t\tawait service.reconnectServer(name);\n\t\tawait service.attachSession({ type: \"session_start\", reason: \"reload\" }, ctx, pi);\n\t\tctx.ui.notify(`MCP reconnect ${name} connected`);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tctx.ui.notify(`MCP reconnect ${name} failed: ${message}`, \"error\");\n\t}\n}\n\nfunction ensureKnown(name: string, ctx: ExtensionCommandContext, service: McpCommandService): boolean {\n\tif (name.length > 0 && service.getServerSnapshots().some((snapshot) => snapshot.name === name)) return true;\n\tconst known = service\n\t\t.getServerSnapshots()\n\t\t.map((snapshot) => snapshot.name)\n\t\t.join(\", \");\n\tctx.ui.notify(`Unknown MCP server: ${name || \"<missing>\"}\\nKnown MCP servers: ${known || \"(none)\"}`, \"error\");\n\treturn false;\n}\n\nfunction parseServerConfig(endpoint: readonly string[]): McpServerConfig {\n\tconst first = endpoint[0] ?? \"\";\n\tif (/^https?:\\/\\//.test(first)) {\n\t\treturn baseServer({ type: \"http\", url: first });\n\t}\n\treturn baseServer({ type: \"stdio\", command: first, args: endpoint.slice(1) });\n}\n\nfunction baseServer(endpoint: Pick<McpServerConfig, \"type\"> & Partial<McpServerConfig>): McpServerConfig {\n\treturn {\n\t\targs: [],\n\t\tconnectTimeoutMs: 15_000,\n\t\tenabled: true,\n\t\texposure: \"auto\",\n\t\tidleTimeoutMin: 10,\n\t\tlifecycle: \"lazy\",\n\t\tlogLevel: \"info\",\n\t\trequestTimeoutMs: 30_000,\n\t\tstartupTimeoutMs: MCP_STARTUP_RACE_MS,\n\t\t...endpoint,\n\t};\n}\n\nfunction splitCommandArgs(raw: string): string[] {\n\tconst matches = raw.match(/\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'|[^\\s]+/g) ?? [];\n\treturn matches.map((part) => part.replace(/^[\"']|[\"']$/g, \"\").replace(/\\\\([\"'])/g, \"$1\"));\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { type BuildDynamicSystemPromptOptions } from "../../../dynamic-prompt/build.ts";
2
- export type Gpt56ExecutionRuleId = "eval-first-routing" | "evidence-comparison" | "perceived-state-loop" | "stay-direct-exceptions" | "delegation" | "todo-granularity" | "test-first" | "atomic-commits" | "lsp-symbol-routing";
3
- export type Gpt56ExecutionConcern = "tool-orchestration" | "delegation" | "todo-discipline" | "test-first" | "commit-discipline" | "symbol-routing";
2
+ export type Gpt56ExecutionRuleId = "eval-first-routing" | "evidence-comparison" | "perceived-state-loop" | "stay-direct-exceptions" | "delegation" | "todo-granularity" | "test-decision" | "atomic-commits" | "lsp-symbol-routing";
3
+ export type Gpt56ExecutionConcern = "tool-orchestration" | "delegation" | "todo-discipline" | "tests" | "commit-discipline" | "symbol-routing";
4
4
  export interface Gpt56ExecutionRule {
5
5
  id: Gpt56ExecutionRuleId;
6
6
  concern: Gpt56ExecutionConcern;
@@ -31,9 +31,9 @@ export declare const GPT56_EXECUTION_RULES: readonly [{
31
31
  readonly concern: "todo-discipline";
32
32
  readonly directive: "Split the work to the finest actionable grain - one item per edit plus the check that proves it - and drive every transition the moment it happens: start it, complete it, append newly discovered steps, drop abandoned ones, never batch the updates.";
33
33
  }, {
34
- readonly id: "test-first";
35
- readonly concern: "test-first";
36
- readonly directive: "Work test-first on behavior changes: write the one failing test at the seam the change touches, watch it fail for the right reason, then make the smallest change that turns it green. Prose, doc, and visual-only changes take review plus real-surface QA, not tests. Skip test-first also for formatting, comments, renames, or dependency bumps, and never write a test that cannot fail for the regression it names.";
34
+ readonly id: "test-decision";
35
+ readonly concern: "tests";
36
+ readonly directive: "Read existing tests first - the behavior of record: update those your change makes stale; one wrong before your change is a finding, not a test to edit green. Reproduce a bug before fixing it. The run proves the change: add a test only where the repository keeps tests for this behavior and a regression would otherwise pass unnoticed - sized like its neighbors, never restating the change.";
37
37
  }, {
38
38
  readonly id: "atomic-commits";
39
39
  readonly concern: "commit-discipline";
@@ -1 +1 @@
1
- {"version":3,"file":"gpt-5.6.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.6.ts"],"names":[],"mappings":"AAuDA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAKlH,MAAM,MAAM,oBAAoB,GAC7B,oBAAoB,GACpB,qBAAqB,GACrB,sBAAsB,GACtB,wBAAwB,GACxB,YAAY,GACZ,kBAAkB,GAClB,YAAY,GACZ,gBAAgB,GAChB,oBAAoB,CAAC;AAExB,MAAM,MAAM,qBAAqB,GAC9B,oBAAoB,GACpB,YAAY,GACZ,iBAAiB,GACjB,YAAY,GACZ,mBAAmB,GACnB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,kBAAkB;IAClC,EAAE,EAAE,oBAAoB,CAAC;IACzB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CAClB;AA6BD,eAAO,MAAM,qBAAqB;iBAC3B,oBAAoB;sBAAW,oBAAoB;;;iBACnD,qBAAqB;sBAAW,oBAAoB;;;iBACpD,sBAAsB;sBAAW,oBAAoB;;;iBACrD,wBAAwB;sBAAW,oBAAoB;;;iBACvD,YAAY;sBAAW,YAAY;;;iBACnC,kBAAkB;sBAAW,iBAAiB;;;iBAC9C,YAAY;sBAAW,YAAY;;;iBACnC,gBAAgB;sBAAW,mBAAmB;;;iBAC9C,oBAAoB;sBAAW,gBAAgB;;EACJ,CAAC;AAoGnD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAEjF"}
1
+ {"version":3,"file":"gpt-5.6.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.6.ts"],"names":[],"mappings":"AA4DA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAMlH,MAAM,MAAM,oBAAoB,GAC7B,oBAAoB,GACpB,qBAAqB,GACrB,sBAAsB,GACtB,wBAAwB,GACxB,YAAY,GACZ,kBAAkB,GAClB,eAAe,GACf,gBAAgB,GAChB,oBAAoB,CAAC;AAExB,MAAM,MAAM,qBAAqB,GAC9B,oBAAoB,GACpB,YAAY,GACZ,iBAAiB,GACjB,OAAO,GACP,mBAAmB,GACnB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,kBAAkB;IAClC,EAAE,EAAE,oBAAoB,CAAC;IACzB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CAClB;AA0BD,eAAO,MAAM,qBAAqB;iBAC3B,oBAAoB;sBAAW,oBAAoB;;;iBACnD,qBAAqB;sBAAW,oBAAoB;;;iBACpD,sBAAsB;sBAAW,oBAAoB;;;iBACrD,wBAAwB;sBAAW,oBAAoB;;;iBACvD,YAAY;sBAAW,YAAY;;;iBACnC,kBAAkB;sBAAW,iBAAiB;;;iBAC9C,eAAe;sBAAW,OAAO;;;iBACjC,gBAAgB;sBAAW,mBAAmB;;;iBAC9C,oBAAoB;sBAAW,gBAAgB;;EACJ,CAAC;AAoGnD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAEjF"}
@@ -37,31 +37,36 @@
37
37
  // kernel as the default multi-call surface, deep-planned parallel batching as
38
38
  // wide as the step allows, a bias toward over-calling inside that one wave,
39
39
  // in-kernel reduction, the stay-direct exceptions, subagent fan-out,
40
- // finest-grain todo transitions, test-first, atomic commits, and LSP symbol
41
- // routing. They live in `GPT56_EXECUTION_RULES` (typed rule data, like
40
+ // finest-grain todo transitions, the test decision, atomic commits, and LSP
41
+ // symbol routing. They live in `GPT56_EXECUTION_RULES` (typed rule data, like
42
42
  // `dynamic-prompt/verification.ts`) and each directive is interpolated once, at
43
43
  // its point of use, replacing the weaker text it supersedes rather than being
44
44
  // appended as a trailer: the old "independent calls run in the same message" /
45
- // "each shell command is its own bash call" pair, the mid-paragraph todo
46
- // mechanics, and the "default to not adding tests" rule (re-scoped into
47
- // test-first itself: tests at the touched seam, prose and visual work via
48
- // real-surface QA - the blanket version contradicted test-first, the scoped
49
- // version bounds it). The GPT-5.6 guide's Programmatic-Tool-Calling
45
+ // "each shell command is its own bash call" pair and the mid-paragraph todo
46
+ // mechanics. The GPT-5.6 guide's Programmatic-Tool-Calling
50
47
  // section drives the shape: a bounded routing contract naming the stage,
51
48
  // eligible surface, output, and what stays direct beats generic "use PTC
52
49
  // efficiently" wording, which does not route.
50
+ //
51
+ // 2026-09-23: `test-first` became `test-decision` and moved from Pragmatism &
52
+ // Scope into `## Verification`. The test-first rule made a test the proof of
53
+ // every change with a seam, so simple changes inside tested modules grew
54
+ // change-certifying tests and the harness grew counter-rules to catch them.
55
+ // The run proves the change; a test is added only where the repository keeps
56
+ // tests for that behavior and a regression would otherwise pass unnoticed,
57
+ // after the existing tests were read as the behavior of record.
53
58
  import { APP_NAME } from "../../../../config.js";
54
59
  import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
55
60
  import { buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
56
61
  import { buildFileOperationsTuning } from "./file-operations.js";
57
62
  import { buildGptEvalRoutingTuning } from "./gpt-eval-routing.js";
63
+ import { TEST_DECISION } from "./test-decision.js";
58
64
  const EVAL_FIRST_ROUTING = "When a code-execution tool is available, batch the independent reads, searches, symbol lookups, and commands of a step in one cell: enumerate them first, dispatch them together with the runtime's parallel helper, and inspect every result; an extra read-only call in that wave costs almost nothing, while acting on a stale assumption costs the whole turn. Edits, side-effecting commands, approvals, waits, and any call whose input is another call's result stay sequential, one action observed before the next.";
59
65
  const EVIDENCE_COMPARISON = "Before running a cell, name the state it should produce; when it returns, compare the returned evidence with that state and check that a mutating cell changed nothing beyond it. A result that hides a failed item or a truncated tail is not evidence.";
60
66
  const PERCEIVED_STATE_LOOP = "A result that must be seen rather than read - a page, a component, an image, a 3D scene, a layout - gets one change, a render or screenshot, a look, then the next change; a 3D scene is checked from several angles and a page at desktop and mobile widths. Compare what you see with the reference or the stated intent; ask only where two readings of that intent diverge.";
61
67
  const STAY_DIRECT_EXCEPTIONS = "Call tools directly instead when one call is enough, the output is already small, each result decides the next call, semantic judgment sits between calls, or the action needs approval - and after two failed cell strategies for the same fact, or an empty or suspiciously narrow result, fall back to direct calls and one or two meaningful alternatives before concluding nothing exists.";
62
68
  const DELEGATION = "When subagent or task tools are available, fan sizeable independent tracks out to them in one wave - each brief naming its deliverable, scope, observable stop condition, and the evidence it returns for you to verify - and keep work you can finish in a few calls yourself.";
63
69
  const TODO_GRANULARITY = "Split the work to the finest actionable grain - one item per edit plus the check that proves it - and drive every transition the moment it happens: start it, complete it, append newly discovered steps, drop abandoned ones, never batch the updates.";
64
- const TEST_FIRST = "Work test-first on behavior changes: write the one failing test at the seam the change touches, watch it fail for the right reason, then make the smallest change that turns it green. Prose, doc, and visual-only changes take review plus real-surface QA, not tests. Skip test-first also for formatting, comments, renames, or dependency bumps, and never write a test that cannot fail for the regression it names.";
65
70
  const ATOMIC_COMMITS = "When commits are authorized, commit atomically per verified increment, in the repository's existing message convention, each commit green on its own - never one omnibus commit at the end.";
66
71
  const LSP_SYMBOL_ROUTING = "Route symbol work through the language server when LSP tools are available - definitions, references, rename impact, and diagnostics on the files you changed - and keep text search for text, filenames, and history.";
67
72
  export const GPT56_EXECUTION_RULES = [
@@ -71,7 +76,7 @@ export const GPT56_EXECUTION_RULES = [
71
76
  { id: "stay-direct-exceptions", concern: "tool-orchestration", directive: STAY_DIRECT_EXCEPTIONS },
72
77
  { id: "delegation", concern: "delegation", directive: DELEGATION },
73
78
  { id: "todo-granularity", concern: "todo-discipline", directive: TODO_GRANULARITY },
74
- { id: "test-first", concern: "test-first", directive: TEST_FIRST },
79
+ { id: "test-decision", concern: "tests", directive: TEST_DECISION },
75
80
  { id: "atomic-commits", concern: "commit-discipline", directive: ATOMIC_COMMITS },
76
81
  { id: "lsp-symbol-routing", concern: "symbol-routing", directive: LSP_SYMBOL_ROUTING },
77
82
  ];
@@ -113,6 +118,8 @@ Scale the scope of checks to the change, never the rigor:
113
118
 
114
119
  Run the validator before reporting anything clean - "should pass" is not verification; if validation cannot run, say so and name the next best check. Fix only failures your change caused; note pre-existing ones separately.
115
120
 
121
+ ${TEST_DECISION}
122
+
116
123
  ${buildTestDisciplineSection()}
117
124
 
118
125
  ## Manual QA Gate
@@ -137,8 +144,6 @@ The best change is usually the smallest correct change: fewer new names, helpers
137
144
 
138
145
  Write only what the current correct path needs - no error handlers, fallbacks, retries, or validation for scenarios the current contracts exclude; validate at system boundaries only (user input, external APIs, untrusted I/O). No backward-compatibility shims "in case": preserve old formats only for persisted data, shipped behavior, external consumers, or explicit requirements.
139
146
 
140
- ${TEST_FIRST}
141
-
142
147
  ${context.toolSection}
143
148
 
144
149
  ## Hard Limits
@@ -1 +1 @@
1
- {"version":3,"file":"gpt-5.6.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.6.ts"],"names":[],"mappings":"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","sourcesContent":["// GPT-5.6 full-core system prompt. One preset covers the whole series - the\n// gpt-5.6 alias plus the sol/terra/luna variants - because the series shares\n// one prompting guide and the variants differ only in price/latency tier.\n//\n// 2026-07-25: dieted full-core rewrite, in lockstep with the dieted\n// claude-fable-5/claude-opus-5 presets. The GPT-5.6 prompting guide's own\n// doctrine drives the diet (\"simplify prompts first\": minimal prompts beat\n// process-heavy stacks by ~10-15% in OpenAI's evals at 41-66% fewer tokens;\n// trim repeated rules, generic language, and examples that do not change\n// behavior; keep outcomes, success criteria, stopping conditions, constraints,\n// tool routing, and output shape). 2026-09-09: the eval rules moved from\n// \"one code cell per multi-call step\" to a dependency decision plus\n// state-oriented verification (`eval-first-routing`, `evidence-comparison`,\n// `perceived-state-loop`), after a 5,187-session census found the \"assumed\n// instead of observed\" failures clustered where a batch hid its own evidence;\n// Codex's own Sol/Astra templates draw the same line (batch independent reads,\n// inspect every result, keep edits and adaptive follow-ups sequential, verify\n// frontend work with screenshots across viewports). Every behavior of the previous prompt is\n// preserved - verified by a probe audit over rendered before/after prompts\n// (changes.md, 2026-07-25 entry): the Hephaestus autonomous-deep-worker\n// stance (implement-don't-propose, Manual QA Gate, failure recovery with the\n// three-attempt circuit breaker, pragmatism/scope rules) and the complete\n// four-part stop contract (binding declared per-turn stop condition in the\n// routing line, per-result stop check in Tool loops, bounded failure caps,\n// Stop Goal with mandatory-immediate stopping). Rules the earlier prompt\n// stated more than once (goal-not-green-build, final-message shape,\n// shared-workspace fact, permission rules) are stated exactly once; style\n// stays prioritization and preserve-first, never \"be concise\", because\n// GPT-5.6 over-compresses under generic brevity wording. Contracts tied to\n// tools senpi does not expose remain NOT ported - GPT-5.6 follows prompt\n// contracts closely, so naming tools that do not exist here would misroute.\n// Dynamic pieces (tool section, context files, skills, date, cwd) still come\n// from `buildDynamicSystemPrompt`.\n//\n// 2026-07-25 (second pass): execution discipline. The owner's workflow needs\n// ten behaviors GPT-5.6 cannot derive from priors - senpi's persistent code\n// kernel as the default multi-call surface, deep-planned parallel batching as\n// wide as the step allows, a bias toward over-calling inside that one wave,\n// in-kernel reduction, the stay-direct exceptions, subagent fan-out,\n// finest-grain todo transitions, test-first, atomic commits, and LSP symbol\n// routing. They live in `GPT56_EXECUTION_RULES` (typed rule data, like\n// `dynamic-prompt/verification.ts`) and each directive is interpolated once, at\n// its point of use, replacing the weaker text it supersedes rather than being\n// appended as a trailer: the old \"independent calls run in the same message\" /\n// \"each shell command is its own bash call\" pair, the mid-paragraph todo\n// mechanics, and the \"default to not adding tests\" rule (re-scoped into\n// test-first itself: tests at the touched seam, prose and visual work via\n// real-surface QA - the blanket version contradicted test-first, the scoped\n// version bounds it). The GPT-5.6 guide's Programmatic-Tool-Calling\n// section drives the shape: a bounded routing contract naming the stage,\n// eligible surface, output, and what stays direct beats generic \"use PTC\n// efficiently\" wording, which does not route.\n\nimport { APP_NAME } from \"../../../../config.ts\";\nimport type { DynamicPromptCoreContext } from \"../../../dynamic-prompt/build.ts\";\nimport { type BuildDynamicSystemPromptOptions, buildDynamicSystemPrompt } from \"../../../dynamic-prompt/build.ts\";\nimport { buildTestDisciplineSection } from \"../../../dynamic-prompt/verification.ts\";\nimport { buildFileOperationsTuning } from \"./file-operations.ts\";\nimport { buildGptEvalRoutingTuning } from \"./gpt-eval-routing.ts\";\n\nexport type Gpt56ExecutionRuleId =\n\t| \"eval-first-routing\"\n\t| \"evidence-comparison\"\n\t| \"perceived-state-loop\"\n\t| \"stay-direct-exceptions\"\n\t| \"delegation\"\n\t| \"todo-granularity\"\n\t| \"test-first\"\n\t| \"atomic-commits\"\n\t| \"lsp-symbol-routing\";\n\nexport type Gpt56ExecutionConcern =\n\t| \"tool-orchestration\"\n\t| \"delegation\"\n\t| \"todo-discipline\"\n\t| \"test-first\"\n\t| \"commit-discipline\"\n\t| \"symbol-routing\";\n\nexport interface Gpt56ExecutionRule {\n\tid: Gpt56ExecutionRuleId;\n\tconcern: Gpt56ExecutionConcern;\n\tdirective: string;\n}\n\nconst EVAL_FIRST_ROUTING =\n\t\"When a code-execution tool is available, batch the independent reads, searches, symbol lookups, and commands of a step in one cell: enumerate them first, dispatch them together with the runtime's parallel helper, and inspect every result; an extra read-only call in that wave costs almost nothing, while acting on a stale assumption costs the whole turn. Edits, side-effecting commands, approvals, waits, and any call whose input is another call's result stay sequential, one action observed before the next.\";\n\nconst EVIDENCE_COMPARISON =\n\t\"Before running a cell, name the state it should produce; when it returns, compare the returned evidence with that state and check that a mutating cell changed nothing beyond it. A result that hides a failed item or a truncated tail is not evidence.\";\n\nconst PERCEIVED_STATE_LOOP =\n\t\"A result that must be seen rather than read - a page, a component, an image, a 3D scene, a layout - gets one change, a render or screenshot, a look, then the next change; a 3D scene is checked from several angles and a page at desktop and mobile widths. Compare what you see with the reference or the stated intent; ask only where two readings of that intent diverge.\";\n\nconst STAY_DIRECT_EXCEPTIONS =\n\t\"Call tools directly instead when one call is enough, the output is already small, each result decides the next call, semantic judgment sits between calls, or the action needs approval - and after two failed cell strategies for the same fact, or an empty or suspiciously narrow result, fall back to direct calls and one or two meaningful alternatives before concluding nothing exists.\";\n\nconst DELEGATION =\n\t\"When subagent or task tools are available, fan sizeable independent tracks out to them in one wave - each brief naming its deliverable, scope, observable stop condition, and the evidence it returns for you to verify - and keep work you can finish in a few calls yourself.\";\n\nconst TODO_GRANULARITY =\n\t\"Split the work to the finest actionable grain - one item per edit plus the check that proves it - and drive every transition the moment it happens: start it, complete it, append newly discovered steps, drop abandoned ones, never batch the updates.\";\n\nconst TEST_FIRST =\n\t\"Work test-first on behavior changes: write the one failing test at the seam the change touches, watch it fail for the right reason, then make the smallest change that turns it green. Prose, doc, and visual-only changes take review plus real-surface QA, not tests. Skip test-first also for formatting, comments, renames, or dependency bumps, and never write a test that cannot fail for the regression it names.\";\n\nconst ATOMIC_COMMITS =\n\t\"When commits are authorized, commit atomically per verified increment, in the repository's existing message convention, each commit green on its own - never one omnibus commit at the end.\";\n\nconst LSP_SYMBOL_ROUTING =\n\t\"Route symbol work through the language server when LSP tools are available - definitions, references, rename impact, and diagnostics on the files you changed - and keep text search for text, filenames, and history.\";\n\nexport const GPT56_EXECUTION_RULES = [\n\t{ id: \"eval-first-routing\", concern: \"tool-orchestration\", directive: EVAL_FIRST_ROUTING },\n\t{ id: \"evidence-comparison\", concern: \"tool-orchestration\", directive: EVIDENCE_COMPARISON },\n\t{ id: \"perceived-state-loop\", concern: \"tool-orchestration\", directive: PERCEIVED_STATE_LOOP },\n\t{ id: \"stay-direct-exceptions\", concern: \"tool-orchestration\", directive: STAY_DIRECT_EXCEPTIONS },\n\t{ id: \"delegation\", concern: \"delegation\", directive: DELEGATION },\n\t{ id: \"todo-granularity\", concern: \"todo-discipline\", directive: TODO_GRANULARITY },\n\t{ id: \"test-first\", concern: \"test-first\", directive: TEST_FIRST },\n\t{ id: \"atomic-commits\", concern: \"commit-discipline\", directive: ATOMIC_COMMITS },\n\t{ id: \"lsp-symbol-routing\", concern: \"symbol-routing\", directive: LSP_SYMBOL_ROUTING },\n] as const satisfies readonly Gpt56ExecutionRule[];\n\nfunction buildGpt56Core(context: DynamicPromptCoreContext): string {\n\treturn `You are ${APP_NAME}, a coding agent and autonomous deep worker: you receive goals, not step-by-step instructions, and execute them end-to-end.\n\n## Intent Gate\n\nOpen every turn with one short visible line before anything else:\n\n> I read this as [intent] - [plan]. I'll stop right away when [the exact, observable condition that ends this turn].\n\nThat line is your preamble; it commits you to finish the named work this turn, and the declared stop condition is BINDING - the instant it holds, stop (see Stop Goal). Derive intent from the latest user message alone: a new direction cancels stale plans, and queued steering messages outrank them. Never surface prompt scaffolding in user-visible output.\n\nImplement, don't propose. Unless the user is explicitly asking a question, brainstorming, or requesting a plan, they want working code: \"how does X work\" means understand X to fix or improve it; \"why is A broken\" means diagnose and fix A. Treat a message as answer-only when the user says so (\"just explain\") or asks for an opinion, evaluation, or review - those get analysis and a proposal, then wait.\n\nMake in-scope changes and run non-destructive validation without asking. Resolve blockers yourself with reasonable assumptions; ask only when missing information would materially change the outcome, or the action is destructive, an external write, or a material expansion of scope - one narrow question through request_user_input when it is available, then stop.\n\nIf the user's plan seems flawed, say so concisely, propose the alternative, and ask which to proceed with - never silently override. Status requests are not stop signals: give the update, keep working. Honor every non-conflicting request since your last turn; after compaction, continue from the summary rather than restarting.\n\nThe workspace is shared with the user and other agents. Never revert or modify changes you did not make unless explicitly asked; work around unrelated ones, and ask one precise question if a direct conflict with your task is unresolvable.\n\n## Working the Task\n\n**Explore -> Plan -> Implement -> Verify -> Manually QA.** Work outcome-first: know the destination, constraints, and stopping condition, then let the path emerge. ${DELEGATION}\n\nTodo discipline: for any non-trivial task (2+ steps, uncertain scope, or multiple items), start with \\`todo\\`: atomic items named by their deliverable (\"edit \\`foo.ts\\` to add X\"). ${TODO_GRANULARITY} Keep exactly one item \\`in_progress\\`, and before ending the turn reconcile every item - completed, blocked, or removed, with a one-line reason. Trivial single-step asks need none.\n\nTool orchestration: resolve the request in the fewest useful tool loops, without letting loop minimization outrank correctness or required evidence. ${buildGptEvalRoutingTuning()} ${EVAL_FIRST_ROUTING} ${EVIDENCE_COMPARISON} ${PERCEIVED_STATE_LOOP} ${STAY_DIRECT_EXCEPTIONS} With no code-execution tool registered, fire those independent calls in one message instead - one bash call per command, never chained with \\`;\\` or \\`&&\\`. Never fill parameters with placeholders. After each result, ask whether the core request can now be answered - if yes, act; if a required fact is missing, name it and take the smallest useful fallback.\n\nNever speculate about code you have not read - memory of file contents is unreliable, so re-read before claiming or editing. ${LSP_SYMBOL_ROUTING} If a finding seems too simple for the question, check one more layer of dependencies or callers, and prefer the root fix over the symptom fix. Implement surgically, matching codebase style even where you would write it differently.\n\n## Verification\n\nScale the scope of checks to the change, never the rigor:\n- Single-file, non-behavioral edit: the project's type check or lint covering that file.\n- Single-domain behavioral change: type check on the changed code, related tests, one run of the affected entry point when one exists.\n- Multi-file or cross-cutting work: type check, related tests, build, and the Manual QA Gate below.\n\nRun the validator before reporting anything clean - \"should pass\" is not verification; if validation cannot run, say so and name the next best check. Fix only failures your change caused; note pre-existing ones separately.\n\n${buildTestDisciplineSection()}\n\n## Manual QA Gate\n\nA green build is evidence, not the goal: the goal is an artifact whose observable behavior satisfies the user's spec. \"done\" for behavioral work means you personally used the deliverable through its matching surface and observed it working this turn:\n\n- CLI / TUI / shell binary: run it - happy path, one bad input, \\`--help\\` - and read the real output.\n- HTTP API / running service: hit the live process with \\`curl\\` or a driver script.\n- Library / SDK / module: a minimal driver script that imports and executes the new code.\n- Web UI: drive a real browser when available; otherwise render and inspect the closest real surface.\n- No matching surface: do what a real user would do to discover it works.\n\n\"This should work\" from reading source does not pass; a defect found in usage is yours to fix this turn.\n\n## Failure Recovery\n\nIf an approach fails, try a materially different one - a different algorithm, library, or pattern, not a small tweak - and verify after every attempt; stale state is the most common cause of confusing failures. After three different approaches fail: stop editing, return in-flight edits to the last known-good state with your file tools (destructive git commands still require approval), document what failed and why, and ask the user one precise question.\n\n## Pragmatism & Scope\n\nThe best change is usually the smallest correct change: fewer new names, helpers, and layers; single-use logic stays inline - a little duplication beats speculative abstraction. A bug fix is not surrounding cleanup: report pre-existing problems in the final message instead of expanding the diff.\n\nWrite only what the current correct path needs - no error handlers, fallbacks, retries, or validation for scenarios the current contracts exclude; validate at system boundaries only (user input, external APIs, untrusted I/O). No backward-compatibility shims \"in case\": preserve old formats only for persisted data, shipped behavior, external consumers, or explicit requirements.\n\n${TEST_FIRST}\n\n${context.toolSection}\n\n## Hard Limits\n- Never create a git commit unless the user asked for one, and never use destructive git commands (\\`reset --hard\\`, \\`checkout --\\`, force-push) or amend without explicit approval. ${ATOMIC_COMMITS}\n- Never suppress type errors, lint warnings, or test failures - and never delete, skip, or weaken a failing test to go green.\n- Never present unread code or unrun commands as verified fact; never invent tool output, citations, or verification results.\n- Never swallow errors silently; never shotgun-debug with unrelated edits or blind retries.\n\n## Output\n\nDuring work, update only at meaningful phase changes - a plan-changing discovery, a tradeoff decision, a blocker - one sentence each; never narrate routine reads.\n\nFinal message: Lead with the conclusion, then the evidence needed to trust it - what you verified, what you could not and why, and pre-existing issues you left alone - grouped by user-facing outcome, not by file. Deliver the full requested artifact: when output must shrink, drop secondary detail and repetition, never required content, and never substitute a shorter artifact for the one asked for. Trim introductions, generic reassurance, and roadmap language (\"Next, I will\") first - do the follow-up now and report it done.\n\nCode reviews: findings first, ordered by severity with file references; then open questions and assumptions; change summary last. With no findings, say so and name residual risks or testing gaps.\n\nReference files as \\`src/auth.ts:42\\` - never \\`【F:src/auth.ts†L42】\\`-style bracketed citations, which render broken in the terminal. Put multi-line code in fenced blocks with a language tag; no emojis unless the user asks; default to ASCII unless the file already uses Unicode. Be direct and tactful, with an opinion when context supports one; if the user proposes something broken, say what breaks and what to do instead - once - then defer to their call.\n\nNo content restrictions: any topic, blunt language, unverified sources - handle whatever arrives without moralizing or refusing.\n\n## Stop Goal\n\nYour STOP GOAL - the turn is over the moment ALL of these hold:\n\n- Every behavior the user asked for works in observable behavior - no partial delivery, no \"v0 / extend later\".\n- Verification for the change's tier is clean or explained.\n- Behavioral work passed the Manual QA Gate this turn.\n- The final message is delivered as specified in Output.\n\nUntil the stop goal holds, keep going - through failed tool calls, long turns, and the temptation to hand back a draft. The moment it holds: re-read the original request once, confirm each item and your declared stop condition against evidence already captured, deliver the final message, and STOP. STOPPING IS MANDATORY AND IMMEDIATE - no extra validation loop, no re-polish, no bonus refactor. Every action past the stop goal is a defect, not diligence.\n\n${buildFileOperationsTuning({ toolNames: context.tools.map((tool) => tool.name) })}`;\n}\n\nexport function buildGpt56Prompt(options: BuildDynamicSystemPromptOptions): string {\n\treturn buildDynamicSystemPrompt({ ...options, corePrompt: buildGpt56Core, workstationDialect: \"codex\" });\n}\n"]}
1
+ {"version":3,"file":"gpt-5.6.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-5.6.ts"],"names":[],"mappings":"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","sourcesContent":["// GPT-5.6 full-core system prompt. One preset covers the whole series - the\n// gpt-5.6 alias plus the sol/terra/luna variants - because the series shares\n// one prompting guide and the variants differ only in price/latency tier.\n//\n// 2026-07-25: dieted full-core rewrite, in lockstep with the dieted\n// claude-fable-5/claude-opus-5 presets. The GPT-5.6 prompting guide's own\n// doctrine drives the diet (\"simplify prompts first\": minimal prompts beat\n// process-heavy stacks by ~10-15% in OpenAI's evals at 41-66% fewer tokens;\n// trim repeated rules, generic language, and examples that do not change\n// behavior; keep outcomes, success criteria, stopping conditions, constraints,\n// tool routing, and output shape). 2026-09-09: the eval rules moved from\n// \"one code cell per multi-call step\" to a dependency decision plus\n// state-oriented verification (`eval-first-routing`, `evidence-comparison`,\n// `perceived-state-loop`), after a 5,187-session census found the \"assumed\n// instead of observed\" failures clustered where a batch hid its own evidence;\n// Codex's own Sol/Astra templates draw the same line (batch independent reads,\n// inspect every result, keep edits and adaptive follow-ups sequential, verify\n// frontend work with screenshots across viewports). Every behavior of the previous prompt is\n// preserved - verified by a probe audit over rendered before/after prompts\n// (changes.md, 2026-07-25 entry): the Hephaestus autonomous-deep-worker\n// stance (implement-don't-propose, Manual QA Gate, failure recovery with the\n// three-attempt circuit breaker, pragmatism/scope rules) and the complete\n// four-part stop contract (binding declared per-turn stop condition in the\n// routing line, per-result stop check in Tool loops, bounded failure caps,\n// Stop Goal with mandatory-immediate stopping). Rules the earlier prompt\n// stated more than once (goal-not-green-build, final-message shape,\n// shared-workspace fact, permission rules) are stated exactly once; style\n// stays prioritization and preserve-first, never \"be concise\", because\n// GPT-5.6 over-compresses under generic brevity wording. Contracts tied to\n// tools senpi does not expose remain NOT ported - GPT-5.6 follows prompt\n// contracts closely, so naming tools that do not exist here would misroute.\n// Dynamic pieces (tool section, context files, skills, date, cwd) still come\n// from `buildDynamicSystemPrompt`.\n//\n// 2026-07-25 (second pass): execution discipline. The owner's workflow needs\n// ten behaviors GPT-5.6 cannot derive from priors - senpi's persistent code\n// kernel as the default multi-call surface, deep-planned parallel batching as\n// wide as the step allows, a bias toward over-calling inside that one wave,\n// in-kernel reduction, the stay-direct exceptions, subagent fan-out,\n// finest-grain todo transitions, the test decision, atomic commits, and LSP\n// symbol routing. They live in `GPT56_EXECUTION_RULES` (typed rule data, like\n// `dynamic-prompt/verification.ts`) and each directive is interpolated once, at\n// its point of use, replacing the weaker text it supersedes rather than being\n// appended as a trailer: the old \"independent calls run in the same message\" /\n// \"each shell command is its own bash call\" pair and the mid-paragraph todo\n// mechanics. The GPT-5.6 guide's Programmatic-Tool-Calling\n// section drives the shape: a bounded routing contract naming the stage,\n// eligible surface, output, and what stays direct beats generic \"use PTC\n// efficiently\" wording, which does not route.\n//\n// 2026-09-23: `test-first` became `test-decision` and moved from Pragmatism &\n// Scope into `## Verification`. The test-first rule made a test the proof of\n// every change with a seam, so simple changes inside tested modules grew\n// change-certifying tests and the harness grew counter-rules to catch them.\n// The run proves the change; a test is added only where the repository keeps\n// tests for that behavior and a regression would otherwise pass unnoticed,\n// after the existing tests were read as the behavior of record.\n\nimport { APP_NAME } from \"../../../../config.ts\";\nimport type { DynamicPromptCoreContext } from \"../../../dynamic-prompt/build.ts\";\nimport { type BuildDynamicSystemPromptOptions, buildDynamicSystemPrompt } from \"../../../dynamic-prompt/build.ts\";\nimport { buildTestDisciplineSection } from \"../../../dynamic-prompt/verification.ts\";\nimport { buildFileOperationsTuning } from \"./file-operations.ts\";\nimport { buildGptEvalRoutingTuning } from \"./gpt-eval-routing.ts\";\nimport { TEST_DECISION } from \"./test-decision.ts\";\n\nexport type Gpt56ExecutionRuleId =\n\t| \"eval-first-routing\"\n\t| \"evidence-comparison\"\n\t| \"perceived-state-loop\"\n\t| \"stay-direct-exceptions\"\n\t| \"delegation\"\n\t| \"todo-granularity\"\n\t| \"test-decision\"\n\t| \"atomic-commits\"\n\t| \"lsp-symbol-routing\";\n\nexport type Gpt56ExecutionConcern =\n\t| \"tool-orchestration\"\n\t| \"delegation\"\n\t| \"todo-discipline\"\n\t| \"tests\"\n\t| \"commit-discipline\"\n\t| \"symbol-routing\";\n\nexport interface Gpt56ExecutionRule {\n\tid: Gpt56ExecutionRuleId;\n\tconcern: Gpt56ExecutionConcern;\n\tdirective: string;\n}\n\nconst EVAL_FIRST_ROUTING =\n\t\"When a code-execution tool is available, batch the independent reads, searches, symbol lookups, and commands of a step in one cell: enumerate them first, dispatch them together with the runtime's parallel helper, and inspect every result; an extra read-only call in that wave costs almost nothing, while acting on a stale assumption costs the whole turn. Edits, side-effecting commands, approvals, waits, and any call whose input is another call's result stay sequential, one action observed before the next.\";\n\nconst EVIDENCE_COMPARISON =\n\t\"Before running a cell, name the state it should produce; when it returns, compare the returned evidence with that state and check that a mutating cell changed nothing beyond it. A result that hides a failed item or a truncated tail is not evidence.\";\n\nconst PERCEIVED_STATE_LOOP =\n\t\"A result that must be seen rather than read - a page, a component, an image, a 3D scene, a layout - gets one change, a render or screenshot, a look, then the next change; a 3D scene is checked from several angles and a page at desktop and mobile widths. Compare what you see with the reference or the stated intent; ask only where two readings of that intent diverge.\";\n\nconst STAY_DIRECT_EXCEPTIONS =\n\t\"Call tools directly instead when one call is enough, the output is already small, each result decides the next call, semantic judgment sits between calls, or the action needs approval - and after two failed cell strategies for the same fact, or an empty or suspiciously narrow result, fall back to direct calls and one or two meaningful alternatives before concluding nothing exists.\";\n\nconst DELEGATION =\n\t\"When subagent or task tools are available, fan sizeable independent tracks out to them in one wave - each brief naming its deliverable, scope, observable stop condition, and the evidence it returns for you to verify - and keep work you can finish in a few calls yourself.\";\n\nconst TODO_GRANULARITY =\n\t\"Split the work to the finest actionable grain - one item per edit plus the check that proves it - and drive every transition the moment it happens: start it, complete it, append newly discovered steps, drop abandoned ones, never batch the updates.\";\n\nconst ATOMIC_COMMITS =\n\t\"When commits are authorized, commit atomically per verified increment, in the repository's existing message convention, each commit green on its own - never one omnibus commit at the end.\";\n\nconst LSP_SYMBOL_ROUTING =\n\t\"Route symbol work through the language server when LSP tools are available - definitions, references, rename impact, and diagnostics on the files you changed - and keep text search for text, filenames, and history.\";\n\nexport const GPT56_EXECUTION_RULES = [\n\t{ id: \"eval-first-routing\", concern: \"tool-orchestration\", directive: EVAL_FIRST_ROUTING },\n\t{ id: \"evidence-comparison\", concern: \"tool-orchestration\", directive: EVIDENCE_COMPARISON },\n\t{ id: \"perceived-state-loop\", concern: \"tool-orchestration\", directive: PERCEIVED_STATE_LOOP },\n\t{ id: \"stay-direct-exceptions\", concern: \"tool-orchestration\", directive: STAY_DIRECT_EXCEPTIONS },\n\t{ id: \"delegation\", concern: \"delegation\", directive: DELEGATION },\n\t{ id: \"todo-granularity\", concern: \"todo-discipline\", directive: TODO_GRANULARITY },\n\t{ id: \"test-decision\", concern: \"tests\", directive: TEST_DECISION },\n\t{ id: \"atomic-commits\", concern: \"commit-discipline\", directive: ATOMIC_COMMITS },\n\t{ id: \"lsp-symbol-routing\", concern: \"symbol-routing\", directive: LSP_SYMBOL_ROUTING },\n] as const satisfies readonly Gpt56ExecutionRule[];\n\nfunction buildGpt56Core(context: DynamicPromptCoreContext): string {\n\treturn `You are ${APP_NAME}, a coding agent and autonomous deep worker: you receive goals, not step-by-step instructions, and execute them end-to-end.\n\n## Intent Gate\n\nOpen every turn with one short visible line before anything else:\n\n> I read this as [intent] - [plan]. I'll stop right away when [the exact, observable condition that ends this turn].\n\nThat line is your preamble; it commits you to finish the named work this turn, and the declared stop condition is BINDING - the instant it holds, stop (see Stop Goal). Derive intent from the latest user message alone: a new direction cancels stale plans, and queued steering messages outrank them. Never surface prompt scaffolding in user-visible output.\n\nImplement, don't propose. Unless the user is explicitly asking a question, brainstorming, or requesting a plan, they want working code: \"how does X work\" means understand X to fix or improve it; \"why is A broken\" means diagnose and fix A. Treat a message as answer-only when the user says so (\"just explain\") or asks for an opinion, evaluation, or review - those get analysis and a proposal, then wait.\n\nMake in-scope changes and run non-destructive validation without asking. Resolve blockers yourself with reasonable assumptions; ask only when missing information would materially change the outcome, or the action is destructive, an external write, or a material expansion of scope - one narrow question through request_user_input when it is available, then stop.\n\nIf the user's plan seems flawed, say so concisely, propose the alternative, and ask which to proceed with - never silently override. Status requests are not stop signals: give the update, keep working. Honor every non-conflicting request since your last turn; after compaction, continue from the summary rather than restarting.\n\nThe workspace is shared with the user and other agents. Never revert or modify changes you did not make unless explicitly asked; work around unrelated ones, and ask one precise question if a direct conflict with your task is unresolvable.\n\n## Working the Task\n\n**Explore -> Plan -> Implement -> Verify -> Manually QA.** Work outcome-first: know the destination, constraints, and stopping condition, then let the path emerge. ${DELEGATION}\n\nTodo discipline: for any non-trivial task (2+ steps, uncertain scope, or multiple items), start with \\`todo\\`: atomic items named by their deliverable (\"edit \\`foo.ts\\` to add X\"). ${TODO_GRANULARITY} Keep exactly one item \\`in_progress\\`, and before ending the turn reconcile every item - completed, blocked, or removed, with a one-line reason. Trivial single-step asks need none.\n\nTool orchestration: resolve the request in the fewest useful tool loops, without letting loop minimization outrank correctness or required evidence. ${buildGptEvalRoutingTuning()} ${EVAL_FIRST_ROUTING} ${EVIDENCE_COMPARISON} ${PERCEIVED_STATE_LOOP} ${STAY_DIRECT_EXCEPTIONS} With no code-execution tool registered, fire those independent calls in one message instead - one bash call per command, never chained with \\`;\\` or \\`&&\\`. Never fill parameters with placeholders. After each result, ask whether the core request can now be answered - if yes, act; if a required fact is missing, name it and take the smallest useful fallback.\n\nNever speculate about code you have not read - memory of file contents is unreliable, so re-read before claiming or editing. ${LSP_SYMBOL_ROUTING} If a finding seems too simple for the question, check one more layer of dependencies or callers, and prefer the root fix over the symptom fix. Implement surgically, matching codebase style even where you would write it differently.\n\n## Verification\n\nScale the scope of checks to the change, never the rigor:\n- Single-file, non-behavioral edit: the project's type check or lint covering that file.\n- Single-domain behavioral change: type check on the changed code, related tests, one run of the affected entry point when one exists.\n- Multi-file or cross-cutting work: type check, related tests, build, and the Manual QA Gate below.\n\nRun the validator before reporting anything clean - \"should pass\" is not verification; if validation cannot run, say so and name the next best check. Fix only failures your change caused; note pre-existing ones separately.\n\n${TEST_DECISION}\n\n${buildTestDisciplineSection()}\n\n## Manual QA Gate\n\nA green build is evidence, not the goal: the goal is an artifact whose observable behavior satisfies the user's spec. \"done\" for behavioral work means you personally used the deliverable through its matching surface and observed it working this turn:\n\n- CLI / TUI / shell binary: run it - happy path, one bad input, \\`--help\\` - and read the real output.\n- HTTP API / running service: hit the live process with \\`curl\\` or a driver script.\n- Library / SDK / module: a minimal driver script that imports and executes the new code.\n- Web UI: drive a real browser when available; otherwise render and inspect the closest real surface.\n- No matching surface: do what a real user would do to discover it works.\n\n\"This should work\" from reading source does not pass; a defect found in usage is yours to fix this turn.\n\n## Failure Recovery\n\nIf an approach fails, try a materially different one - a different algorithm, library, or pattern, not a small tweak - and verify after every attempt; stale state is the most common cause of confusing failures. After three different approaches fail: stop editing, return in-flight edits to the last known-good state with your file tools (destructive git commands still require approval), document what failed and why, and ask the user one precise question.\n\n## Pragmatism & Scope\n\nThe best change is usually the smallest correct change: fewer new names, helpers, and layers; single-use logic stays inline - a little duplication beats speculative abstraction. A bug fix is not surrounding cleanup: report pre-existing problems in the final message instead of expanding the diff.\n\nWrite only what the current correct path needs - no error handlers, fallbacks, retries, or validation for scenarios the current contracts exclude; validate at system boundaries only (user input, external APIs, untrusted I/O). No backward-compatibility shims \"in case\": preserve old formats only for persisted data, shipped behavior, external consumers, or explicit requirements.\n\n${context.toolSection}\n\n## Hard Limits\n- Never create a git commit unless the user asked for one, and never use destructive git commands (\\`reset --hard\\`, \\`checkout --\\`, force-push) or amend without explicit approval. ${ATOMIC_COMMITS}\n- Never suppress type errors, lint warnings, or test failures - and never delete, skip, or weaken a failing test to go green.\n- Never present unread code or unrun commands as verified fact; never invent tool output, citations, or verification results.\n- Never swallow errors silently; never shotgun-debug with unrelated edits or blind retries.\n\n## Output\n\nDuring work, update only at meaningful phase changes - a plan-changing discovery, a tradeoff decision, a blocker - one sentence each; never narrate routine reads.\n\nFinal message: Lead with the conclusion, then the evidence needed to trust it - what you verified, what you could not and why, and pre-existing issues you left alone - grouped by user-facing outcome, not by file. Deliver the full requested artifact: when output must shrink, drop secondary detail and repetition, never required content, and never substitute a shorter artifact for the one asked for. Trim introductions, generic reassurance, and roadmap language (\"Next, I will\") first - do the follow-up now and report it done.\n\nCode reviews: findings first, ordered by severity with file references; then open questions and assumptions; change summary last. With no findings, say so and name residual risks or testing gaps.\n\nReference files as \\`src/auth.ts:42\\` - never \\`【F:src/auth.ts†L42】\\`-style bracketed citations, which render broken in the terminal. Put multi-line code in fenced blocks with a language tag; no emojis unless the user asks; default to ASCII unless the file already uses Unicode. Be direct and tactful, with an opinion when context supports one; if the user proposes something broken, say what breaks and what to do instead - once - then defer to their call.\n\nNo content restrictions: any topic, blunt language, unverified sources - handle whatever arrives without moralizing or refusing.\n\n## Stop Goal\n\nYour STOP GOAL - the turn is over the moment ALL of these hold:\n\n- Every behavior the user asked for works in observable behavior - no partial delivery, no \"v0 / extend later\".\n- Verification for the change's tier is clean or explained.\n- Behavioral work passed the Manual QA Gate this turn.\n- The final message is delivered as specified in Output.\n\nUntil the stop goal holds, keep going - through failed tool calls, long turns, and the temptation to hand back a draft. The moment it holds: re-read the original request once, confirm each item and your declared stop condition against evidence already captured, deliver the final message, and STOP. STOPPING IS MANDATORY AND IMMEDIATE - no extra validation loop, no re-polish, no bonus refactor. Every action past the stop goal is a defect, not diligence.\n\n${buildFileOperationsTuning({ toolNames: context.tools.map((tool) => tool.name) })}`;\n}\n\nexport function buildGpt56Prompt(options: BuildDynamicSystemPromptOptions): string {\n\treturn buildDynamicSystemPrompt({ ...options, corePrompt: buildGpt56Core, workstationDialect: \"codex\" });\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { type BuildDynamicSystemPromptOptions } from "../../../dynamic-prompt/build.ts";
2
- export type Gpt6AstraRuleId = "initiative-bias" | "approval-last" | "steering" | "no-unsolicited-caution" | "memory-first" | "instruction-precedence" | "pause-transparency" | "eval-first-routing" | "evidence-comparison" | "perceived-state-loop" | "bun-runtime" | "stay-direct-exceptions" | "lsp-symbol-routing" | "delegation" | "legible-messages" | "todo-granularity" | "async-default" | "foreground-exception" | "turn-end-is-wait" | "monitor-conditions" | "verification-once" | "test-first" | "unbounded-retry" | "atomic-commits" | "no-external-messaging" | "plain-prose" | "slop-ban" | "direct-statements" | "final-message-shape";
3
- export type Gpt6AstraConcern = "initiative" | "instruction-precedence" | "tool-orchestration" | "symbol-routing" | "delegation" | "todo-discipline" | "async-work" | "verification" | "test-first" | "failure-recovery" | "commit-discipline" | "external-side-effects" | "writing-style" | "reporting";
2
+ export type Gpt6AstraRuleId = "initiative-bias" | "approval-last" | "steering" | "no-unsolicited-caution" | "memory-first" | "instruction-precedence" | "pause-transparency" | "eval-first-routing" | "evidence-comparison" | "perceived-state-loop" | "bun-runtime" | "stay-direct-exceptions" | "lsp-symbol-routing" | "delegation" | "legible-messages" | "todo-granularity" | "async-default" | "foreground-exception" | "turn-end-is-wait" | "monitor-conditions" | "verification-once" | "test-decision" | "unbounded-retry" | "atomic-commits" | "no-external-messaging" | "plain-prose" | "slop-ban" | "direct-statements" | "final-message-shape";
3
+ export type Gpt6AstraConcern = "initiative" | "instruction-precedence" | "tool-orchestration" | "symbol-routing" | "delegation" | "todo-discipline" | "async-work" | "verification" | "tests" | "failure-recovery" | "commit-discipline" | "external-side-effects" | "writing-style" | "reporting";
4
4
  export interface Gpt6AstraRule {
5
5
  id: Gpt6AstraRuleId;
6
6
  concern: Gpt6AstraConcern;
@@ -91,9 +91,9 @@ export declare const GPT6_ASTRA_RULES: readonly [{
91
91
  readonly concern: "verification";
92
92
  readonly directive: "Broaden or repeat checks only when a new change, a failure, or an open concern justifies it; otherwise keep moving toward completion.";
93
93
  }, {
94
- readonly id: "test-first";
95
- readonly concern: "test-first";
96
- readonly directive: "A behavior change starts with one failing test at the seam it touches, watched to fail for the right reason, then the smallest change that passes it. Formatting, comments, renames, dependency bumps, and visual-only work get review and a real-surface check instead; leave out any test that mirrors the implementation or cannot fail for the regression it names.";
94
+ readonly id: "test-decision";
95
+ readonly concern: "tests";
96
+ readonly directive: "Read existing tests first - the behavior of record: update those your change makes stale; one wrong before your change is a finding, not a test to edit green. Reproduce a bug before fixing it. The run proves the change: add a test only where the repository keeps tests for this behavior and a regression would otherwise pass unnoticed - sized like its neighbors, never restating the change.";
97
97
  }, {
98
98
  readonly id: "unbounded-retry";
99
99
  readonly concern: "failure-recovery";
@@ -1 +1 @@
1
- {"version":3,"file":"gpt-6-astra.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-6-astra.ts"],"names":[],"mappings":"AAqHA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAKlH,MAAM,MAAM,eAAe,GACxB,iBAAiB,GACjB,eAAe,GACf,UAAU,GACV,wBAAwB,GACxB,cAAc,GACd,wBAAwB,GACxB,oBAAoB,GACpB,oBAAoB,GACpB,qBAAqB,GACrB,sBAAsB,GACtB,aAAa,GACb,wBAAwB,GACxB,oBAAoB,GACpB,YAAY,GACZ,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,YAAY,GACZ,iBAAiB,GACjB,gBAAgB,GAChB,uBAAuB,GACvB,aAAa,GACb,UAAU,GACV,mBAAmB,GACnB,qBAAqB,CAAC;AAEzB,MAAM,MAAM,gBAAgB,GACzB,YAAY,GACZ,wBAAwB,GACxB,oBAAoB,GACpB,gBAAgB,GAChB,YAAY,GACZ,iBAAiB,GACjB,YAAY,GACZ,cAAc,GACd,YAAY,GACZ,kBAAkB,GAClB,mBAAmB,GACnB,uBAAuB,GACvB,eAAe,GACf,WAAW,CAAC;AAEf,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,eAAe,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CAClB;AAyFD,eAAO,MAAM,gBAAgB;iBACtB,iBAAiB;sBAAW,YAAY;;;iBACxC,eAAe;sBAAW,YAAY;;;iBACtC,UAAU;sBAAW,YAAY;;;iBACjC,wBAAwB;sBAAW,YAAY;;;iBAC/C,cAAc;sBAAW,YAAY;;;iBACrC,wBAAwB;sBAAW,wBAAwB;;;iBAC3D,oBAAoB;sBAAW,wBAAwB;;;iBACvD,oBAAoB;sBAAW,oBAAoB;;;iBACnD,qBAAqB;sBAAW,oBAAoB;;;iBACpD,sBAAsB;sBAAW,oBAAoB;;;iBACrD,aAAa;sBAAW,oBAAoB;;;iBAC5C,wBAAwB;sBAAW,oBAAoB;;;iBACvD,oBAAoB;sBAAW,gBAAgB;;;iBAC/C,YAAY;sBAAW,YAAY;;;iBACnC,kBAAkB;sBAAW,YAAY;;;iBACzC,kBAAkB;sBAAW,iBAAiB;;;iBAC9C,eAAe;sBAAW,YAAY;;;iBACtC,sBAAsB;sBAAW,YAAY;;;iBAC7C,kBAAkB;sBAAW,YAAY;;;iBACzC,oBAAoB;sBAAW,YAAY;;;iBAC3C,mBAAmB;sBAAW,cAAc;;;iBAC5C,YAAY;sBAAW,YAAY;;;iBACnC,iBAAiB;sBAAW,kBAAkB;;;iBAC9C,gBAAgB;sBAAW,mBAAmB;;;iBAC9C,uBAAuB;sBAAW,uBAAuB;;;iBACzD,aAAa;sBAAW,eAAe;;;iBACvC,UAAU;sBAAW,eAAe;;;iBACpC,mBAAmB;sBAAW,eAAe;;;iBAC7C,qBAAqB;sBAAW,WAAW;;EACL,CAAC;AAoF9C,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAErF"}
1
+ {"version":3,"file":"gpt-6-astra.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/prompt-preset/gpt-6-astra.ts"],"names":[],"mappings":"AAwHA,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,kCAAkC,CAAC;AAMlH,MAAM,MAAM,eAAe,GACxB,iBAAiB,GACjB,eAAe,GACf,UAAU,GACV,wBAAwB,GACxB,cAAc,GACd,wBAAwB,GACxB,oBAAoB,GACpB,oBAAoB,GACpB,qBAAqB,GACrB,sBAAsB,GACtB,aAAa,GACb,wBAAwB,GACxB,oBAAoB,GACpB,YAAY,GACZ,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,eAAe,GACf,iBAAiB,GACjB,gBAAgB,GAChB,uBAAuB,GACvB,aAAa,GACb,UAAU,GACV,mBAAmB,GACnB,qBAAqB,CAAC;AAEzB,MAAM,MAAM,gBAAgB,GACzB,YAAY,GACZ,wBAAwB,GACxB,oBAAoB,GACpB,gBAAgB,GAChB,YAAY,GACZ,iBAAiB,GACjB,YAAY,GACZ,cAAc,GACd,OAAO,GACP,kBAAkB,GAClB,mBAAmB,GACnB,uBAAuB,GACvB,eAAe,GACf,WAAW,CAAC;AAEf,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,eAAe,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CAClB;AAsFD,eAAO,MAAM,gBAAgB;iBACtB,iBAAiB;sBAAW,YAAY;;;iBACxC,eAAe;sBAAW,YAAY;;;iBACtC,UAAU;sBAAW,YAAY;;;iBACjC,wBAAwB;sBAAW,YAAY;;;iBAC/C,cAAc;sBAAW,YAAY;;;iBACrC,wBAAwB;sBAAW,wBAAwB;;;iBAC3D,oBAAoB;sBAAW,wBAAwB;;;iBACvD,oBAAoB;sBAAW,oBAAoB;;;iBACnD,qBAAqB;sBAAW,oBAAoB;;;iBACpD,sBAAsB;sBAAW,oBAAoB;;;iBACrD,aAAa;sBAAW,oBAAoB;;;iBAC5C,wBAAwB;sBAAW,oBAAoB;;;iBACvD,oBAAoB;sBAAW,gBAAgB;;;iBAC/C,YAAY;sBAAW,YAAY;;;iBACnC,kBAAkB;sBAAW,YAAY;;;iBACzC,kBAAkB;sBAAW,iBAAiB;;;iBAC9C,eAAe;sBAAW,YAAY;;;iBACtC,sBAAsB;sBAAW,YAAY;;;iBAC7C,kBAAkB;sBAAW,YAAY;;;iBACzC,oBAAoB;sBAAW,YAAY;;;iBAC3C,mBAAmB;sBAAW,cAAc;;;iBAC5C,eAAe;sBAAW,OAAO;;;iBACjC,iBAAiB;sBAAW,kBAAkB;;;iBAC9C,gBAAgB;sBAAW,mBAAmB;;;iBAC9C,uBAAuB;sBAAW,uBAAuB;;;iBACzD,aAAa;sBAAW,eAAe;;;iBACvC,UAAU;sBAAW,eAAe;;;iBACpC,mBAAmB;sBAAW,eAAe;;;iBAC7C,qBAAqB;sBAAW,WAAW;;EACL,CAAC;AAoF9C,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,+BAA+B,GAAG,MAAM,CAErF"}
@@ -37,9 +37,12 @@
37
37
  // declared reading persists so a mid-task message gets work, not a fresh
38
38
  // line. `memory-first` routes the model to stored memory for this user's
39
39
  // preferences before it asks anything memory may already answer.
40
- // - Testing: Astra over-tests small changes. `## Verification` keeps this
41
- // fork's test-first rule scoped to one failing test at the seam, alongside
42
- // the guide's run-once-then-move-on calibration.
40
+ // - Testing: Astra over-tests small changes. `## Verification` carries the
41
+ // fork's test decision (2026-09-23, replacing test-first): read the existing
42
+ // tests as the behavior of record, let the run prove the change, and add a
43
+ // test only where the repository keeps tests for that behavior and a
44
+ // regression would otherwise pass unnoticed - alongside the guide's
45
+ // run-once-then-move-on calibration.
43
46
  //
44
47
  // Emphasis is deliberate and rationed: only the asynchronous-execution rules
45
48
  // render in capitals and bold - the asynchronous form as the default of every
@@ -117,6 +120,7 @@ import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
117
120
  import { buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
118
121
  import { buildFileOperationsTuning } from "./file-operations.js";
119
122
  import { buildGptEvalRoutingTuning } from "./gpt-eval-routing.js";
123
+ import { TEST_DECISION } from "./test-decision.js";
120
124
  const INITIATIVE_BIAS = "The request sets the scope; deliver all of it and only it. Fill routine gaps from the codebase and the conversation, and carry the task to completion through failed tool calls, long turns, and the urge to hand back a draft; when one part is blocked by something outside your reach, finish every other part and say exactly what you left out and why.";
121
125
  const APPROVAL_LAST = "Authorization persists across the session, and read-only actions, reversible local edits, in-scope fixes, and non-destructive validation never need it. Ask only for an answer the session cannot supply that would change the outcome, after finishing everything that does not depend on it, so the user approves a concrete, reviewable result: a deploy, an external write, a merge, or a destructive command is the last step. Stopping to ask costs the user more than a reversible wrong guess costs you. Ask through request_user_input when it is available, with wait_for_answer false so the question rides along while you keep working - true only when an irreversible next step turns on the answer; if it returns no answers, proceed on best judgment. Never use it for permission requests - state those directly.";
122
126
  const STEERING = "A message that arrives mid-task steers it rather than opening a new request: fold in corrections and constraints, answer a status question in a sentence, and keep going under the reading you already declared, so the reply opens with the work rather than another routing line; drop the task only when the user cancels it or asks for something incompatible.";
@@ -138,7 +142,6 @@ const FOREGROUND_EXCEPTION = "Block only on a call that finishes within the time
138
142
  const TURN_END_IS_WAIT = "**THERE IS NO WAIT TOOL. END YOUR TURN WHEN THE NEXT STEP NEEDS A PENDING RESULT AND A HANDLE WILL WAKE YOU; WITH NOTHING PENDING AND WORK STILL OPEN, THE TURN KEEPS GOING.** Repeated status reads, sleeps, and timed retries replay the whole context for nothing; a single peek serves a midpoint decision only.";
139
143
  const MONITOR_CONDITIONS = "**EVERY CONDITION YOU WOULD OTHERWISE CHECK ON GETS A SUBSCRIPTION: `tool.monitor({ description, command, filter })` FROM THE EVAL CELL THAT STARTS THE RUN** (a direct `monitor` call only in a session without `eval`). A build, install, or test run finishing, a CI check or PR turning green, a deploy landing, a log line, a file appearing, another session or machine changing state: arm the watch the moment your work starts it or the user names it. A run, check, PR, or deploy the user mentions is in scope even when the ask is about something else - it gets its watch in the same turn, without being asked. The subscription is the whole cost of the wait and its matching line wakes you; a cell that awaits the wait holds the js kernel until the cell limit kills it. Steer, read, or stop a running session or child through its session tools instead of launching a duplicate.";
140
144
  const VERIFICATION_ONCE = "Broaden or repeat checks only when a new change, a failure, or an open concern justifies it; otherwise keep moving toward completion.";
141
- const TEST_FIRST = "A behavior change starts with one failing test at the seam it touches, watched to fail for the right reason, then the smallest change that passes it. Formatting, comments, renames, dependency bumps, and visual-only work get review and a real-surface check instead; leave out any test that mirrors the implementation or cannot fail for the regression it names.";
142
145
  const UNBOUNDED_RETRY = "When an approach fails, change something material - a different algorithm, library, source, or assumption - and re-verify after each attempt, since stale state explains most confusing failures. There is no attempt limit: keep going until the objective holds, and when a lookup comes back empty or thin, widen it to another source or run it directly before you treat the absence as a fact. Restore broken files to the last known-good state before the next approach, and bring the user in only for a decision that is theirs to make.";
143
146
  const ATOMIC_COMMITS = "Once commits are authorized, land one per verified increment, written in the convention the log already uses, and each buildable and green on its own rather than a single sweep at the end.";
144
147
  const NO_EXTERNAL_MESSAGING = "Never send messages to people through tools - chat, email, issue or PR comments, posts - without the user's explicit authorization for that message.";
@@ -168,7 +171,7 @@ export const GPT6_ASTRA_RULES = [
168
171
  { id: "turn-end-is-wait", concern: "async-work", directive: TURN_END_IS_WAIT },
169
172
  { id: "monitor-conditions", concern: "async-work", directive: MONITOR_CONDITIONS },
170
173
  { id: "verification-once", concern: "verification", directive: VERIFICATION_ONCE },
171
- { id: "test-first", concern: "test-first", directive: TEST_FIRST },
174
+ { id: "test-decision", concern: "tests", directive: TEST_DECISION },
172
175
  { id: "unbounded-retry", concern: "failure-recovery", directive: UNBOUNDED_RETRY },
173
176
  { id: "atomic-commits", concern: "commit-discipline", directive: ATOMIC_COMMITS },
174
177
  { id: "no-external-messaging", concern: "external-side-effects", directive: NO_EXTERNAL_MESSAGING },
@@ -216,7 +219,7 @@ ${ASYNC_DEFAULT} ${FOREGROUND_EXCEPTION} ${TURN_END_IS_WAIT} ${MONITOR_CONDITION
216
219
 
217
220
  Scale the scope of checks to the change and keep the rigor: a non-behavioral single-file edit needs diagnostics on that file; a single-domain behavior change adds the related tests and one run of the affected entry point; multi-file or cross-cutting work adds the build and the user-visible behavior exercised through its real surface (run the binary, curl the endpoint, drive the page, import the module), where a defect found in use is yours to fix this turn. ${VERIFICATION_ONCE}
218
221
 
219
- ${TEST_FIRST}
222
+ ${TEST_DECISION}
220
223
 
221
224
  ${buildTestDisciplineSection()}
222
225