@gajae-code/coding-agent 0.12.21 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/CHANGELOG.md +67 -2
  2. package/dist/types/cli/args.d.ts +5 -2
  3. package/dist/types/cli/root-flags.d.ts +246 -0
  4. package/dist/types/cli.d.ts +11 -19
  5. package/dist/types/commands/daemon.d.ts +0 -30
  6. package/dist/types/commands/launch.d.ts +11 -19
  7. package/dist/types/commands/quick-lane.d.ts +32 -0
  8. package/dist/types/commands/sdk.d.ts +21 -15
  9. package/dist/types/config/file-lock-gc.d.ts +2 -0
  10. package/dist/types/config/model-equivalence.d.ts +20 -0
  11. package/dist/types/config/model-profile-activation.d.ts +62 -17
  12. package/dist/types/config/model-profiles.d.ts +10 -0
  13. package/dist/types/config/model-registry.d.ts +68 -1
  14. package/dist/types/config/model-resolver.d.ts +15 -4
  15. package/dist/types/config/models-config-schema.d.ts +7 -2
  16. package/dist/types/config/provider-selection-policy.d.ts +62 -0
  17. package/dist/types/config/settings-schema.d.ts +36 -78
  18. package/dist/types/config/settings.d.ts +2 -0
  19. package/dist/types/edit/renderer.d.ts +5 -2
  20. package/dist/types/edit/streaming.d.ts +13 -0
  21. package/dist/types/extensibility/custom-tools/types.d.ts +2 -0
  22. package/dist/types/extensibility/extensions/compact-handler.d.ts +2 -1
  23. package/dist/types/extensibility/extensions/types.d.ts +3 -0
  24. package/dist/types/gjc-runtime/gc-runtime.d.ts +19 -5
  25. package/dist/types/internal-urls/local-protocol.d.ts +1 -0
  26. package/dist/types/modes/components/model-selector.d.ts +0 -2
  27. package/dist/types/modes/components/provider-order-context.d.ts +45 -0
  28. package/dist/types/modes/components/provider-order-editor.d.ts +24 -0
  29. package/dist/types/modes/components/settings-defs.d.ts +5 -1
  30. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  31. package/dist/types/quick-lane/classify.d.ts +40 -0
  32. package/dist/types/runtime/stt-settings-setup.d.ts +18 -0
  33. package/dist/types/sdk/broker/broker.d.ts +56 -2
  34. package/dist/types/sdk/broker/operation-receipt-ledger.d.ts +25 -0
  35. package/dist/types/sdk/broker/session-index.d.ts +83 -2
  36. package/dist/types/sdk/broker/state-version.d.ts +1 -1
  37. package/dist/types/sdk/bus/notification-service.d.ts +6 -0
  38. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +8 -1
  39. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +4 -1
  40. package/dist/types/sdk/bus/telegram-daemon.d.ts +26 -0
  41. package/dist/types/sdk/cli/rows.d.ts +98 -0
  42. package/dist/types/sdk/cli/session-cli.d.ts +35 -3
  43. package/dist/types/sdk/elevation/allowlist.d.ts +20 -0
  44. package/dist/types/sdk/elevation/audit.d.ts +93 -0
  45. package/dist/types/sdk/elevation/capability.d.ts +3 -0
  46. package/dist/types/sdk/elevation/digest.d.ts +72 -0
  47. package/dist/types/sdk/elevation/dispatch-receipt.d.ts +85 -0
  48. package/dist/types/sdk/elevation/grant-ledger.d.ts +163 -0
  49. package/dist/types/sdk/elevation/owner.d.ts +48 -0
  50. package/dist/types/sdk/guides/cache.d.ts +98 -0
  51. package/dist/types/sdk/guides/catalog.d.ts +156 -0
  52. package/dist/types/sdk/guides/cli.d.ts +39 -0
  53. package/dist/types/sdk/guides/manifest.d.ts +66 -0
  54. package/dist/types/sdk/guides/verify.d.ts +66 -0
  55. package/dist/types/sdk/host/control/dispatch.d.ts +8 -0
  56. package/dist/types/sdk/host/control/index.d.ts +1 -1
  57. package/dist/types/sdk/host/control/operations.d.ts +3 -2
  58. package/dist/types/sdk/host/query/cursor.d.ts +10 -0
  59. package/dist/types/sdk/host/query/handlers.d.ts +21 -0
  60. package/dist/types/sdk/host/session-runtime.d.ts +9 -0
  61. package/dist/types/sdk/mcp/server.d.ts +2 -2
  62. package/dist/types/sdk/prompt-status.d.ts +11 -0
  63. package/dist/types/sdk/session.d.ts +4 -0
  64. package/dist/types/sdk/transport/index.d.ts +1 -0
  65. package/dist/types/sdk/transport/relay.d.ts +1 -0
  66. package/dist/types/sdk/transport/serve-cli.d.ts +20 -1
  67. package/dist/types/session/agent-session.d.ts +32 -18
  68. package/dist/types/session/blob-store.d.ts +13 -7
  69. package/dist/types/session/fallback-chain-controller.d.ts +15 -0
  70. package/dist/types/session/internal/managed-session-storage.d.ts +25 -1
  71. package/dist/types/session/internal/session-memory-sidecar.d.ts +5 -5
  72. package/dist/types/session/session-manager.d.ts +139 -10
  73. package/dist/types/session/session-storage.d.ts +48 -0
  74. package/dist/types/setup/provider-onboarding.d.ts +7 -1
  75. package/dist/types/slash-commands/builtin-registry.d.ts +14 -0
  76. package/dist/types/stt/setup.d.ts +2 -0
  77. package/dist/types/task/executor.d.ts +10 -2
  78. package/dist/types/tools/browser/runtime-diagnostics.d.ts +65 -0
  79. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  80. package/dist/types/tools/browser/tab-supervisor.d.ts +2 -0
  81. package/dist/types/tools/browser/tab-worker.d.ts +2 -0
  82. package/dist/types/tools/browser.d.ts +2 -0
  83. package/dist/types/tools/image-gen.d.ts +14 -18
  84. package/dist/types/tools/index.d.ts +2 -0
  85. package/dist/types/tools/resource-gc.d.ts +2 -0
  86. package/dist/types/utils/pasted-image-path.d.ts +6 -0
  87. package/package.json +9 -9
  88. package/scripts/generate-sdk-operation-inventory.ts +8 -0
  89. package/scripts/run-test-manifest.ts +61 -21
  90. package/scripts/verify-gjc-sdk-canonicalization.ts +9 -4
  91. package/src/cli/args.ts +62 -9
  92. package/src/cli/completion-cli.ts +1 -0
  93. package/src/cli/fast-help.ts +1 -0
  94. package/src/cli/root-flags.ts +100 -0
  95. package/src/cli/setup-cli.ts +6 -2
  96. package/src/cli.ts +42 -65
  97. package/src/commands/acp.ts +1 -1
  98. package/src/commands/daemon.ts +2 -31
  99. package/src/commands/gc.ts +1 -1
  100. package/src/commands/launch.ts +8 -129
  101. package/src/commands/quick-lane.ts +51 -0
  102. package/src/commands/sdk.ts +200 -26
  103. package/src/commands/setup.ts +4 -2
  104. package/src/config/file-lock-gc.ts +4 -1
  105. package/src/config/model-equivalence.ts +76 -7
  106. package/src/config/model-profile-activation.ts +1115 -265
  107. package/src/config/model-profiles.ts +134 -2
  108. package/src/config/model-registry.ts +352 -50
  109. package/src/config/model-resolver.ts +289 -38
  110. package/src/config/models-config-schema.ts +11 -4
  111. package/src/config/provider-selection-policy.ts +146 -0
  112. package/src/config/settings-schema.ts +50 -77
  113. package/src/config/settings.ts +40 -0
  114. package/src/coordinator-mcp/server.ts +32 -2
  115. package/src/edit/renderer.ts +175 -223
  116. package/src/edit/streaming.ts +108 -1
  117. package/src/export/html/index.ts +57 -7
  118. package/src/extensibility/custom-tools/types.ts +2 -0
  119. package/src/extensibility/extensions/compact-handler.ts +3 -2
  120. package/src/extensibility/extensions/runner.ts +6 -0
  121. package/src/extensibility/extensions/types.ts +3 -0
  122. package/src/gjc-runtime/gc-runtime.ts +379 -20
  123. package/src/gjc-runtime/launch-worktree.ts +5 -1
  124. package/src/gjc-runtime/team-runtime.ts +59 -2
  125. package/src/gjc-runtime/tmux-owner-isolation.ts +19 -0
  126. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +16 -1
  127. package/src/internal-urls/docs-index.generated.ts +17 -13
  128. package/src/internal-urls/local-protocol.ts +1 -0
  129. package/src/main.ts +40 -3
  130. package/src/memories/index.ts +4 -2
  131. package/src/modes/acp/acp-agent.ts +235 -91
  132. package/src/modes/components/model-selector.ts +206 -42
  133. package/src/modes/components/provider-order-context.ts +197 -0
  134. package/src/modes/components/provider-order-editor.ts +441 -0
  135. package/src/modes/components/settings-defs.ts +21 -1
  136. package/src/modes/components/settings-selector.ts +45 -2
  137. package/src/modes/components/tool-execution.ts +47 -15
  138. package/src/modes/controllers/command-controller.ts +6 -3
  139. package/src/modes/controllers/extension-ui-controller.ts +2 -0
  140. package/src/modes/controllers/input-controller.ts +73 -2
  141. package/src/modes/controllers/selector-controller.ts +260 -153
  142. package/src/modes/prompt-suggestion-controller.ts +1 -1
  143. package/src/modes/runtime-init.ts +1 -0
  144. package/src/modes/utils/ui-helpers.ts +18 -0
  145. package/src/prompts/tools/browser.md +1 -0
  146. package/src/quick-lane/classify.ts +257 -0
  147. package/src/rlm/index.ts +1 -1
  148. package/src/runtime/stt-settings-setup.ts +57 -0
  149. package/src/sdk/acp/adapter.ts +2 -1
  150. package/src/sdk/broker/broker.ts +780 -12
  151. package/src/sdk/broker/lifecycle.ts +70 -29
  152. package/src/sdk/broker/operation-receipt-ledger.ts +144 -0
  153. package/src/sdk/broker/session-index.ts +463 -48
  154. package/src/sdk/broker/state-version.ts +13 -9
  155. package/src/sdk/broker/transport.ts +14 -1
  156. package/src/sdk/bus/index.ts +34 -13
  157. package/src/sdk/bus/kind-aware-reconciliation.ts +21 -2
  158. package/src/sdk/bus/notification-service.ts +47 -1
  159. package/src/sdk/bus/prompt-reconciliation.ts +22 -3
  160. package/src/sdk/bus/telegram-daemon-contract.ts +4 -1
  161. package/src/sdk/bus/telegram-daemon.ts +54 -3
  162. package/src/sdk/cli/rows.ts +247 -0
  163. package/src/sdk/cli/session-cli.ts +930 -79
  164. package/src/sdk/elevation/allowlist.ts +54 -0
  165. package/src/sdk/elevation/audit.ts +208 -0
  166. package/src/sdk/elevation/capability.ts +41 -0
  167. package/src/sdk/elevation/digest.ts +129 -0
  168. package/src/sdk/elevation/dispatch-receipt.ts +184 -0
  169. package/src/sdk/elevation/grant-ledger.ts +1142 -0
  170. package/src/sdk/elevation/owner.ts +109 -0
  171. package/src/sdk/guides/cache.ts +363 -0
  172. package/src/sdk/guides/catalog.ts +554 -0
  173. package/src/sdk/guides/cli.ts +235 -0
  174. package/src/sdk/guides/manifest.ts +152 -0
  175. package/src/sdk/guides/verify.ts +178 -0
  176. package/src/sdk/host/control/dispatch.ts +49 -1
  177. package/src/sdk/host/control/index.ts +1 -0
  178. package/src/sdk/host/control/operations.ts +8 -1
  179. package/src/sdk/host/query/cursor.ts +47 -3
  180. package/src/sdk/host/query/handlers.ts +155 -2
  181. package/src/sdk/host/sdk-surface-parity.test.ts +1 -0
  182. package/src/sdk/host/session-runtime.test.ts +391 -1
  183. package/src/sdk/host/session-runtime.ts +308 -73
  184. package/src/sdk/host/surface-policy.ts +3 -0
  185. package/src/sdk/host/websocket-transport.ts +7 -1
  186. package/src/sdk/mcp/server.ts +88 -15
  187. package/src/sdk/prompt-status.ts +8 -0
  188. package/src/sdk/protocol/operation-inventory.generated.json +62 -0
  189. package/src/sdk/protocol/operation-registry.ts +3 -2
  190. package/src/sdk/session.ts +87 -39
  191. package/src/sdk/transport/index.ts +1 -0
  192. package/src/sdk/transport/relay.ts +3 -0
  193. package/src/sdk/transport/serve-cli.ts +111 -24
  194. package/src/secrets/obfuscator.ts +92 -12
  195. package/src/session/agent-session.ts +322 -93
  196. package/src/session/blob-store.ts +60 -8
  197. package/src/session/fallback-chain-controller.ts +35 -0
  198. package/src/session/internal/managed-session-scope.ts +25 -3
  199. package/src/session/internal/managed-session-storage.ts +574 -73
  200. package/src/session/internal/session-memory-sidecar.ts +19 -29
  201. package/src/session/session-manager.ts +2166 -743
  202. package/src/session/session-storage.ts +715 -48
  203. package/src/setup/provider-onboarding.ts +19 -3
  204. package/src/setup/provider-presets.json +3 -1
  205. package/src/slash-commands/builtin-registry.ts +85 -3
  206. package/src/stt/downloader.ts +2 -3
  207. package/src/stt/setup.ts +29 -4
  208. package/src/task/executor.ts +22 -18
  209. package/src/task/index.ts +24 -1
  210. package/src/tools/archive-reader.ts +11 -2
  211. package/src/tools/browser/runtime-diagnostics.ts +249 -0
  212. package/src/tools/browser/tab-protocol.ts +4 -0
  213. package/src/tools/browser/tab-supervisor.ts +5 -0
  214. package/src/tools/browser/tab-worker.ts +36 -1
  215. package/src/tools/browser.ts +7 -0
  216. package/src/tools/image-gen.ts +110 -166
  217. package/src/tools/index.ts +2 -0
  218. package/src/tools/read.ts +1 -1
  219. package/src/tools/resource-gc.ts +6 -1
  220. package/src/tools/tool-catalog.generated.ts +5 -1
  221. package/src/utils/pasted-image-path.ts +93 -0
  222. package/src/web/search/index.ts +3 -3
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Deterministic quick-lane classifier (issue #3984).
3
+ *
4
+ * The deep-interview and ralplan skills describe a task-routing surface in
5
+ * prose: small, clearly scoped, low-risk work should take a quick lane
6
+ * (minimal orchestration) while vague, ambiguous, risky, or wide-breadth work
7
+ * keeps the existing deep path. That gate existed only as prompt guidance, so
8
+ * it was not auditable or testable. This module encodes the same signals as
9
+ * deterministic, pure code so eligibility and exclusions are explicit and
10
+ * regression-covered.
11
+ *
12
+ * The classifier is intentionally conservative and fail-closed:
13
+ * - Any exclusion signal forces the `deep` lane, even when the task also names
14
+ * concrete files or symbols. Safety is never overridden by a concrete anchor.
15
+ * - The `deep` lane preserves the existing deep/interview behavior untouched;
16
+ * this module only *classifies*, it never routes or mutates.
17
+ * - A task with neither a concrete anchor nor an exclusion defaults to `deep`
18
+ * because boundness cannot be confirmed.
19
+ */
20
+
21
+ export type QuickLane = "quick" | "deep";
22
+
23
+ export interface QuickLaneDecision {
24
+ /** The routed lane: `quick` (bounded, direct execution) or `deep` (planning/interview path). */
25
+ lane: QuickLane;
26
+ /** Concrete anchors that made the task eligible for the quick lane (empty when `deep`). */
27
+ reasons: string[];
28
+ /** Exclusions that forced the deep lane (empty when `quick`). */
29
+ exclusions: string[];
30
+ }
31
+
32
+ /** Build a standalone-word regex so keywords do not match inside joined identifiers or file names. */
33
+ function standalone(word: string): RegExp {
34
+ return new RegExp(`(?<![A-Za-z0-9_-])${word}(?![A-Za-z0-9_-])`, "i");
35
+ }
36
+
37
+ /** Source/config file extensions treated as concrete file-path anchors. */
38
+ const FILE_EXT =
39
+ "(?:ts|tsx|js|jsx|mjs|cjs|py|rs|go|rb|md|markdown|json|jsonl|yml|yaml|toml|xml|sql|sh|bash|css|scss|html|vue|svelte|java|kt|scala|c|cpp|h|hpp|csv|txt|env|tf)";
40
+
41
+ /** Regex matching one concrete file-path anchor (also used to count distinct paths). */
42
+ const FILE_PATH_PATTERN = new RegExp(
43
+ `(?:(?:[A-Za-z0-9_@.+~\\-]+/)*[A-Za-z0-9_.@+\\-]+|(?:[A-Za-z0-9_@.+~\\-]+/)*\\.[A-Za-z0-9_-]+|(?:[A-Za-z0-9_@.+~\\-]+/)*)\\.${FILE_EXT}(?![A-Za-z0-9])`,
44
+ "i",
45
+ );
46
+
47
+ /** Global variant of FILE_PATH_PATTERN for counting distinct file-path anchors. */
48
+ const FILE_PATH_PATTERN_GLOBAL = new RegExp(FILE_PATH_PATTERN.source, "gi");
49
+
50
+ /** Concrete anchors that establish quick-lane eligibility. */
51
+ const QUICK_SIGNALS: ReadonlyArray<{ id: string; label: string; pattern: RegExp }> = [
52
+ {
53
+ id: "file-path",
54
+ label: "explicit file path",
55
+ pattern: FILE_PATH_PATTERN,
56
+ },
57
+ {
58
+ id: "issue-number",
59
+ label: "issue/PR number",
60
+ // Hex-color-shaped tokens (#rgb/#rgba/#rrggbb/#rrggbbaa) must not read as
61
+ // issue/PR numbers: exclude 3-digit rgb short forms, any token containing
62
+ // a hex letter (a-f), and 6/8-digit color forms. Pure 4+ digit numbers
63
+ // like #4146 remain issue/PR references.
64
+ pattern: /#(?!\d{3}\b|[0-9a-fA-F]*[a-fA-F][0-9a-fA-F]*\b)\d+/,
65
+ },
66
+ {
67
+ id: "named-symbol",
68
+ label: "named symbol (camelCase / snake_case)",
69
+ // lowerCamelCase and snake_case identifiers are unambiguous code anchors
70
+ // and rarely appear in ordinary prose. PascalCase is deliberately
71
+ // excluded to avoid false positives on proper nouns ("Google").
72
+ pattern:
73
+ /\b[a-z]{2,}[a-zA-Z0-9]*[A-Z][a-zA-Z0-9]*\b|\b[a-z][a-z0-9]*(?:_[a-z0-9]+)+\b|\b[A-Z][A-Z]+\b|\b[A-Z][a-z]+[A-Z][a-zA-Z0-9]*\b/,
74
+ },
75
+ {
76
+ id: "named-symbol-pascal",
77
+ label: "named symbol (PascalCase)",
78
+ // Two or more capitalized segments ("UserService" = User+Service) are
79
+ // unambiguous code anchors; single-segment proper nouns ("Google") and
80
+ // lowercase-leading names ("iPhone") must not match.
81
+ pattern: /\b[A-Z][a-z]+(?:[A-Z][a-z]*)+\b/,
82
+ },
83
+ {
84
+ id: "explicit-test",
85
+ label: "explicit test/validation request",
86
+ pattern:
87
+ /\b(?:bun test|unit test|integration test|regression(?: test)?|e2e(?: test)?|add (?:a )?(?:test|validation)|write (?:a )?(?:test|test case)|tests? for)\b/i,
88
+ },
89
+ {
90
+ id: "test-runner",
91
+ label: "test runner",
92
+ pattern:
93
+ /\b(?:run (?:pytest|vitest|jest|mocha|rspec|go test|cargo test|bun test|npm test|pnpm test|yarn test|deno test))\b/i,
94
+ },
95
+ {
96
+ id: "numbered-steps",
97
+ label: "numbered steps",
98
+ pattern: /(?:^|\n)\s*\d+[.)]\s+/m,
99
+ },
100
+ {
101
+ id: "acceptance-criteria",
102
+ label: "acceptance criteria / expected behavior",
103
+ pattern:
104
+ /\b(?:acceptance criteria|expected behavior|should (?:be|work|return|pass|fail|not|throw)|must (?:be|work|return|pass|not|throw)|when .*expect)\b/i,
105
+ },
106
+ {
107
+ id: "error-reference",
108
+ label: "error/failure reference",
109
+ pattern: /\b(?:error|exception|throws?|stack trace|fails? when|does not (?:work|load|start|run)|broken)\b/i,
110
+ },
111
+ {
112
+ id: "code-block",
113
+ label: "inline code or code fence",
114
+ pattern: /`[^`\n]+`|\n```/,
115
+ },
116
+ {
117
+ id: "explicit-override",
118
+ label: "explicit quick-lane override (force: / !)",
119
+ // The gate prose says "prefix `force:` or `!`" — only a prefix at the
120
+ // very start of the trimmed request counts, never mid-text.
121
+ pattern: /^(?:force:|!)\s*/,
122
+ },
123
+ ];
124
+
125
+ /** Safety/risk exclusions that always force the deep lane. */
126
+ const RISK_KEYWORDS = [
127
+ "auth",
128
+ "authentication",
129
+ "authorization",
130
+ "login",
131
+ "logout",
132
+ "security",
133
+ "secure",
134
+ "vulnerability",
135
+ "migrate",
136
+ "migration",
137
+ "destructive",
138
+ "compliance",
139
+ "pii",
140
+ "payment",
141
+ "ledger",
142
+ "legal",
143
+ "credential",
144
+ "secret",
145
+ "password",
146
+ "passphrase",
147
+ "passwd",
148
+ "privilege",
149
+ "firewall",
150
+ "encryption",
151
+ "decrypt",
152
+ "rollback",
153
+ "audit",
154
+ "breaking change",
155
+ "public api",
156
+ "api contract",
157
+ ];
158
+
159
+ /** Explicit ambiguity / brainstorming exclusions that force the deep lane. */
160
+ const AMBIGUITY_KEYWORDS = [
161
+ "i don't know",
162
+ "i do not know",
163
+ "not sure",
164
+ "unsure",
165
+ "vague",
166
+ "explore",
167
+ "brainstorm",
168
+ "open-ended",
169
+ "what should",
170
+ "what would",
171
+ "how should",
172
+ "kind of",
173
+ "something like",
174
+ "a thing",
175
+ "maybe",
176
+ ];
177
+
178
+ /** Wide-breadth exclusions indicating multi-file / cross-contract scope. */
179
+ const BREADTH_KEYWORDS = [
180
+ "all files",
181
+ "all modules",
182
+ "across modules",
183
+ "across every",
184
+ "everywhere",
185
+ "across the board",
186
+ "multiple modules",
187
+ "many files",
188
+ "entire",
189
+ "whole codebase",
190
+ "entire app",
191
+ "whole app",
192
+ "cross-cutting",
193
+ "cross-contract",
194
+ "the whole",
195
+ "redesign",
196
+ "redesigning",
197
+ "rewrite",
198
+ "rewriting",
199
+ "from scratch",
200
+ ];
201
+
202
+ const EXCLUSION_KEYWORDS: ReadonlyArray<{ id: string; label: string; words: readonly string[] }> = [
203
+ { id: "risk", label: "risk/safety-sensitive scope", words: RISK_KEYWORDS },
204
+ { id: "ambiguity", label: "ambiguous or exploratory scope", words: AMBIGUITY_KEYWORDS },
205
+ { id: "breadth", label: "multi-file / cross-contract breadth", words: BREADTH_KEYWORDS },
206
+ ];
207
+
208
+ function matchesAny(text: string, words: readonly string[]): boolean {
209
+ return words.some(word => standalone(word).test(text));
210
+ }
211
+
212
+ /**
213
+ * Classify a task request into the quick lane (bounded, direct execution) or
214
+ * the deep path (existing planning/interview orchestration).
215
+ *
216
+ * Order of operations (fail-closed):
217
+ * 1. Exclusions are authoritative — any risk/ambiguity/breadth signal (including
218
+ * two or more distinct file-path anchors) forces `deep`, even when concrete
219
+ * anchors are present.
220
+ * 2. Otherwise, any concrete anchor yields `quick`.
221
+ * 3. Otherwise, `deep` (boundness could not be confirmed).
222
+ */
223
+ export function classifyQuickLane(input: string): QuickLaneDecision {
224
+ const text = input.trim();
225
+ if (!text) {
226
+ return { lane: "deep", reasons: [], exclusions: ["empty request"] };
227
+ }
228
+
229
+ const exclusions: string[] = [];
230
+ for (const group of EXCLUSION_KEYWORDS) {
231
+ if (matchesAny(text, group.words)) {
232
+ exclusions.push(`${group.label} (matched keyword group "${group.id}")`);
233
+ }
234
+ }
235
+ const distinctFilePaths = new Set(Array.from(text.matchAll(FILE_PATH_PATTERN_GLOBAL), match => match[0]));
236
+ if (distinctFilePaths.size >= 2) {
237
+ exclusions.push("multi-file / cross-contract breadth (matched 2 or more distinct file paths)");
238
+ }
239
+ if (exclusions.length > 0) {
240
+ return { lane: "deep", reasons: [], exclusions };
241
+ }
242
+
243
+ const reasons: string[] = [];
244
+ for (const signal of QUICK_SIGNALS) {
245
+ if (signal.pattern.test(text)) {
246
+ reasons.push(signal.label);
247
+ }
248
+ }
249
+ if (reasons.length === 0) {
250
+ return {
251
+ lane: "deep",
252
+ reasons: [],
253
+ exclusions: ["no concrete anchor — boundedness cannot be confirmed"],
254
+ };
255
+ }
256
+ return { lane: "quick", reasons, exclusions: [] };
257
+ }
package/src/rlm/index.ts CHANGED
@@ -262,6 +262,7 @@ export async function runRlmCommand(argv: string[]): Promise<void> {
262
262
  const cwd = getProjectDir();
263
263
  ensureRlmGjcSessionId();
264
264
  const { dataPath, resumeSessionId, minSuccessfulRuns, rest } = extractRlmFlags(argv);
265
+ const parsed = parseArgs(rest, "local");
265
266
  const dataContext = await loadRlmDataContext(cwd, dataPath);
266
267
 
267
268
  const sessionId = resumeSessionId ?? generateRlmSessionId();
@@ -297,7 +298,6 @@ export async function runRlmCommand(argv: string[]): Promise<void> {
297
298
  },
298
299
  });
299
300
 
300
- const parsed = parseArgs(rest);
301
301
  parsed.sessionDir = paths.agentSessionDir;
302
302
  if (resumeSessionId) {
303
303
  parsed.continue = true;
@@ -0,0 +1,57 @@
1
+ export interface SttDependencySetupProgress {
2
+ stage: string;
3
+ percent?: number;
4
+ }
5
+
6
+ export interface SttDependencySetupOptions {
7
+ modelName?: string;
8
+ onProgress?: (progress: SttDependencySetupProgress) => void;
9
+ }
10
+
11
+ export type EnsureSttDependencies = (options?: SttDependencySetupOptions) => Promise<void>;
12
+
13
+ export interface ConfigureSttFromSettingsOptions {
14
+ modelName?: string;
15
+ ensureDependencies?: EnsureSttDependencies;
16
+ setEnabled(enabled: false): void;
17
+ flush(): Promise<void>;
18
+ showStatus(message: string): void;
19
+ showError(message: string): void;
20
+ }
21
+
22
+ let ensureDependenciesPromise: Promise<EnsureSttDependencies> | undefined;
23
+
24
+ async function loadEnsureSttDependencies(): Promise<EnsureSttDependencies> {
25
+ ensureDependenciesPromise ??= import("../stt/downloader").then(module => module.ensureSTTDependencies);
26
+ return ensureDependenciesPromise;
27
+ }
28
+
29
+ export async function configureSttFromSettings(options: ConfigureSttFromSettingsOptions): Promise<boolean> {
30
+ options.showStatus("Checking speech-to-text dependencies...");
31
+ try {
32
+ const ensureDependencies = options.ensureDependencies ?? (await loadEnsureSttDependencies());
33
+ await ensureDependencies({
34
+ modelName: options.modelName,
35
+ onProgress: progress => {
36
+ options.showStatus(progress.stage + (progress.percent === undefined ? "" : ` (${progress.percent}%)`));
37
+ },
38
+ });
39
+ options.showStatus("Speech-to-text is ready. Use /hotkeys or Ctrl+P → Toggle speech-to-text.");
40
+ return true;
41
+ } catch (error) {
42
+ const cause = error instanceof Error ? error.message : String(error);
43
+ let rollbackFailure: string | undefined;
44
+ try {
45
+ options.setEnabled(false);
46
+ await options.flush();
47
+ } catch (rollbackError) {
48
+ rollbackFailure = rollbackError instanceof Error ? rollbackError.message : String(rollbackError);
49
+ }
50
+ options.showError(
51
+ rollbackFailure
52
+ ? `Speech-to-text setup failed: ${cause}. Disabling STT also failed: ${rollbackFailure}`
53
+ : `Speech-to-text setup failed: ${cause}. STT was disabled; fix the dependency and enable it again.`,
54
+ );
55
+ return false;
56
+ }
57
+ }
@@ -229,10 +229,11 @@ export class AcpSdkAdapter {
229
229
  // request that named no readiness budget is queued for the default one, so it
230
230
  // needs the same extension rather than the client's generic request deadline.
231
231
  const timeoutMs = lifecycleRequestTimeoutMs(operation, input);
232
- return await this.#client.global(operation, input, {
232
+ const response = await this.#client.global(operation, input, {
233
233
  idempotencyKey,
234
234
  ...(timeoutMs === undefined ? {} : { timeoutMs }),
235
235
  });
236
+ return response;
236
237
  }
237
238
 
238
239
  async sdkControl(params: { operation: string; input?: JsonObject }): Promise<unknown> {