@gajae-code/coding-agent 0.4.1 → 0.4.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 (94) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/types/async/job-manager.d.ts +25 -0
  3. package/dist/types/commands/ultragoal.d.ts +1 -0
  4. package/dist/types/commit/model-selection.d.ts +1 -1
  5. package/dist/types/config/model-registry.d.ts +3 -1
  6. package/dist/types/config/model-resolver.d.ts +1 -19
  7. package/dist/types/config/models-config-schema.d.ts +12 -0
  8. package/dist/types/config/settings-schema.d.ts +26 -4
  9. package/dist/types/gjc-runtime/goal-mode-request.d.ts +8 -1
  10. package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
  11. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +29 -0
  12. package/dist/types/harness-control-plane/finalize.d.ts +8 -0
  13. package/dist/types/harness-control-plane/receipts.d.ts +16 -1
  14. package/dist/types/harness-control-plane/types.d.ts +16 -3
  15. package/dist/types/modes/acp/acp-event-mapper.d.ts +2 -0
  16. package/dist/types/modes/components/custom-editor.d.ts +7 -0
  17. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +18 -0
  18. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +84 -0
  19. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +14 -7
  20. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +37 -0
  21. package/dist/types/modes/shared/agent-wire/protocol.d.ts +13 -34
  22. package/dist/types/reminders/star-reminder.d.ts +115 -0
  23. package/dist/types/session/agent-session.d.ts +30 -1
  24. package/dist/types/session/session-manager.d.ts +1 -1
  25. package/dist/types/tools/bash.d.ts +2 -0
  26. package/dist/types/tools/browser/actions.d.ts +54 -0
  27. package/dist/types/tools/browser.d.ts +80 -0
  28. package/dist/types/tools/image-gen.d.ts +1 -0
  29. package/dist/types/tools/index.d.ts +3 -1
  30. package/dist/types/tools/job.d.ts +1 -1
  31. package/examples/extensions/README.md +20 -41
  32. package/package.json +7 -7
  33. package/src/async/job-manager.ts +120 -1
  34. package/src/cli/grep-cli.ts +1 -1
  35. package/src/commands/harness.ts +42 -3
  36. package/src/commands/ultragoal.ts +8 -1
  37. package/src/commit/agentic/index.ts +2 -2
  38. package/src/commit/model-selection.ts +7 -22
  39. package/src/commit/pipeline.ts +2 -2
  40. package/src/config/model-registry.ts +17 -9
  41. package/src/config/model-resolver.ts +14 -84
  42. package/src/config/models-config-schema.ts +2 -0
  43. package/src/config/settings-schema.ts +27 -4
  44. package/src/defaults/gjc/skills/team/SKILL.md +10 -1
  45. package/src/defaults/gjc/skills/ultragoal/SKILL.md +3 -2
  46. package/src/gjc-runtime/goal-mode-request.ts +21 -1
  47. package/src/gjc-runtime/launch-tmux.ts +25 -2
  48. package/src/gjc-runtime/team-runtime.ts +78 -3
  49. package/src/gjc-runtime/ultragoal-guard.ts +18 -2
  50. package/src/gjc-runtime/ultragoal-runtime.ts +240 -30
  51. package/src/harness-control-plane/finalize.ts +84 -0
  52. package/src/harness-control-plane/owner.ts +16 -3
  53. package/src/harness-control-plane/receipts.ts +39 -1
  54. package/src/harness-control-plane/rpc-adapter.ts +7 -1
  55. package/src/harness-control-plane/types.ts +33 -12
  56. package/src/internal-urls/docs-index.generated.ts +3 -3
  57. package/src/memories/index.ts +1 -1
  58. package/src/modes/acp/acp-agent.ts +17 -9
  59. package/src/modes/acp/acp-event-mapper.ts +33 -1
  60. package/src/modes/components/custom-editor.ts +19 -3
  61. package/src/modes/controllers/input-controller.ts +27 -7
  62. package/src/modes/controllers/selector-controller.ts +7 -1
  63. package/src/modes/interactive-mode.ts +29 -1
  64. package/src/modes/rpc/rpc-client.ts +16 -3
  65. package/src/modes/rpc/rpc-mode.ts +5 -2
  66. package/src/modes/shared/agent-wire/command-contract.ts +18 -0
  67. package/src/modes/shared/agent-wire/event-contract.ts +147 -0
  68. package/src/modes/shared/agent-wire/event-envelope.ts +35 -16
  69. package/src/modes/shared/agent-wire/event-observation.ts +397 -0
  70. package/src/modes/shared/agent-wire/protocol.ts +24 -81
  71. package/src/modes/utils/context-usage.ts +2 -2
  72. package/src/prompts/agents/explore.md +1 -1
  73. package/src/prompts/agents/plan.md +1 -1
  74. package/src/prompts/agents/reviewer.md +1 -1
  75. package/src/prompts/tools/browser.md +3 -2
  76. package/src/reminders/star-reminder.ts +422 -0
  77. package/src/runtime-mcp/manager.ts +15 -2
  78. package/src/sdk.ts +3 -1
  79. package/src/session/agent-session.ts +139 -17
  80. package/src/session/session-manager.ts +1 -1
  81. package/src/task/agents.ts +1 -1
  82. package/src/tools/bash.ts +6 -1
  83. package/src/tools/browser/actions.ts +189 -0
  84. package/src/tools/browser.ts +91 -1
  85. package/src/tools/image-gen.ts +42 -15
  86. package/src/tools/index.ts +7 -1
  87. package/src/tools/inspect-image.ts +10 -8
  88. package/src/tools/job.ts +12 -2
  89. package/src/tools/monitor.ts +98 -17
  90. package/src/utils/commit-message-generator.ts +6 -13
  91. package/src/utils/title-generator.ts +1 -1
  92. package/dist/types/harness-control-plane/frame-mapper.d.ts +0 -29
  93. package/src/harness-control-plane/frame-mapper.ts +0 -286
  94. package/src/priority.json +0 -37
package/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.4.3] - 2026-06-10
6
+
7
+ ### Added
8
+
9
+ - Added a `busyPromptMode` setting (`steer` | `queue`, default `steer`) so a prompt submitted while the agent is busy can either steer the active turn or be queued to run after it completes, keeping steering and queued-next-turn semantics distinct. Ctrl+Enter still always queues as a follow-up (#434).
10
+ ### Fixed
11
+
12
+ - Fixed a persistent `monitor` notification flood where a cancelled or evicted monitor kept delivering queued `task-notification` follow-ups (surviving process death, log deletion, and `job cancel` returning not-found). Monitors now purge their queued notifications on cancel/terminal/eviction, retain a short tombstone so post-eviction `job cancel` still purges, coalesce rapid duplicate output to the latest state, and close a cancel/trailing-flush race.
13
+ - Fixed `ultragoal` execution leaking across concurrent independent GJC sessions. The runtime `goal-mode-request.json` is now stamped with the producing session's `GJC_SESSION_ID`, and the consumer only activates a request that belongs to the current session (another session's request is left intact instead of being consumed/deleted). Legacy unscoped requests remain consumable for single-session compatibility ([#457](https://github.com/Yeachan-Heo/gajae-code/issues/457)).
14
+
15
+ ## [0.4.2] - 2026-06-09
16
+
17
+ ### Changed
18
+
19
+ - Added conservative `timeout-minutes` values to all CI workflow jobs to prevent indefinite hangs.
20
+
21
+ ### Fixed
22
+
23
+ - Improved the grep limit-reached message to show the current limit value and suggest using `--limit` for more results.
24
+ - Passed the active model's `maxTokens` (reserved completion budget) into the auto-compaction threshold and context-usage reserve so prompt packing reserves output for large-window models, keeping the safe input budget below the total context window (e.g. ~272K for a 400K/128K model) instead of filling the whole window ([#442](https://github.com/Yeachan-Heo/gajae-code/issues/442)).
25
+ - Fixed a `gjc harness` recovery deadlock where a session created by `start` without `--detach` (persisted as `started` with no owner lease/endpoint) could never get a live owner: `recover` refused to spawn one because no prior endpoint existed, while `start` reported `session-already-exists`. `recover` now bootstraps a fresh owner for a never-started session (no lease, no endpoint, no owner-run evidence) without writing a misleading `vanish` receipt, reported via `bootstrappedOwner: true`. Bootstrap is independent of the vanish classifier's `ownerRequired` verdict (nothing has vanished), so a session started in a non-git workspace (git delta `unknown`) is recovered too, while a deleted worktree is still refused (#421).
26
+
5
27
  ## [0.4.1] - 2026-06-07
6
28
 
7
29
  ### Changed
@@ -95,6 +95,25 @@ export interface AsyncJobDeliveryState {
95
95
  nextRetryAt?: number;
96
96
  pendingJobIds: string[];
97
97
  }
98
+ export interface AsyncJobLifecycleCleanup {
99
+ onCancel?: (job: AsyncJob) => void;
100
+ onTerminal?: (job: AsyncJob) => void;
101
+ onEvict?: (job: AsyncJob) => void;
102
+ /**
103
+ * Idempotent residual cleanup invoked by a post-eviction tombstone purge
104
+ * (e.g. a late `job cancel` after the job left the registry). Kept distinct
105
+ * from the at-most-once lifecycle phases so a tombstone purge never has to
106
+ * re-invoke a phase hook. Must be safe to call repeatedly.
107
+ */
108
+ onTombstonePurge?: (job: AsyncJob) => void;
109
+ }
110
+ export interface MonitorTombstone {
111
+ jobId: string;
112
+ ownerId?: string;
113
+ status: AsyncJob["status"];
114
+ expiresAt: number;
115
+ purge: () => unknown;
116
+ }
98
117
  export interface AsyncJobRegisterOptions {
99
118
  id?: string;
100
119
  /** Registry id of the agent that owns this job; used to scope cancelAll. */
@@ -102,6 +121,7 @@ export interface AsyncJobRegisterOptions {
102
121
  /** Structured metadata for tool-specific control surfaces. */
103
122
  metadata?: AsyncJobMetadata;
104
123
  onProgress?: (text: string, details?: Record<string, unknown>) => void | Promise<void>;
124
+ lifecycle?: AsyncJobLifecycleCleanup;
105
125
  }
106
126
  /**
107
127
  * Filter applied to job query/cancel APIs. With `ownerId`, results are
@@ -157,6 +177,11 @@ export declare class AsyncJobManager {
157
177
  * so cross-agent cancellation is rejected at the manager level.
158
178
  */
159
179
  cancel(id: string, filter?: AsyncJobFilter): boolean;
180
+ getMonitorTombstone(jobId: string, filter?: AsyncJobFilter): MonitorTombstone | undefined;
181
+ purgeMonitorTombstone(jobId: string, filter?: AsyncJobFilter): {
182
+ found: boolean;
183
+ status?: AsyncJob["status"];
184
+ };
160
185
  /** Register or replace the canonical record for a subagent. */
161
186
  registerSubagentRecord(record: SubagentRecord): void;
162
187
  getSubagentRecord(subagentId: string, filter?: AsyncJobFilter): SubagentRecord | undefined;
@@ -3,5 +3,6 @@ export default class Ultragoal extends Command {
3
3
  static description: string;
4
4
  static strict: boolean;
5
5
  static examples: string[];
6
+ static delegateHelp: boolean;
6
7
  run(): Promise<void>;
7
8
  }
@@ -11,5 +11,5 @@ type CommitModelRegistry = ModelLookupRegistry & {
11
11
  getApiKey: (model: Model<Api>) => Promise<string | undefined>;
12
12
  };
13
13
  export declare function resolvePrimaryModel(override: string | undefined, settings: Settings, modelRegistry: CommitModelRegistry): Promise<ResolvedCommitModel>;
14
- export declare function resolveSmolModel(settings: Settings, modelRegistry: CommitModelRegistry, fallbackModel: Model<Api>, fallbackApiKey: string): Promise<ResolvedCommitModel>;
14
+ export declare function resolveSecondaryCommitModel(settings: Settings, modelRegistry: CommitModelRegistry, fallbackModel: Model<Api>, fallbackApiKey: string): Promise<ResolvedCommitModel>;
15
15
  export {};
@@ -9,7 +9,7 @@ import { type Settings } from "./settings";
9
9
  export type { CanonicalModelIndex, CanonicalModelRecord, CanonicalModelVariant, ModelEquivalenceConfig };
10
10
  export declare const kNoAuth = "N/A";
11
11
  export declare function isAuthenticated(apiKey: string | undefined | null): apiKey is string;
12
- export type ModelRole = "default" | "smol" | "slow" | "vision" | "plan" | "designer" | "commit" | "task";
12
+ export type ModelRole = "default";
13
13
  export interface ModelRoleInfo {
14
14
  tag?: string;
15
15
  name: string;
@@ -110,6 +110,7 @@ export declare const ModelsConfigFile: ConfigFile<{
110
110
  levels?: ("high" | "low" | "max" | "medium" | "minimal" | "xhigh")[] | undefined;
111
111
  } | undefined;
112
112
  input?: ("image" | "text")[] | undefined;
113
+ output?: ("image" | "text")[] | undefined;
113
114
  cost?: {
114
115
  input: number;
115
116
  output: number;
@@ -180,6 +181,7 @@ export declare const ModelsConfigFile: ConfigFile<{
180
181
  levels?: ("high" | "low" | "max" | "medium" | "minimal" | "xhigh")[] | undefined;
181
182
  } | undefined;
182
183
  input?: ("image" | "text")[] | undefined;
184
+ output?: ("image" | "text")[] | undefined;
183
185
  cost?: {
184
186
  input?: number | undefined;
185
187
  output?: number | undefined;
@@ -58,7 +58,7 @@ export declare function parseModelPattern(pattern: string, availableModels: Mode
58
58
  modelRegistry?: CanonicalModelRegistry;
59
59
  }): ParsedModelResult;
60
60
  /**
61
- * Expand a role alias like "pi/smol" to the configured model string.
61
+ * Expand a role alias like "pi/default" to the configured model string.
62
62
  */
63
63
  export declare function expandRoleAlias(value: string, settings?: Settings): string;
64
64
  export declare function resolveConfiguredModelPatterns(value: string | string[] | undefined, settings?: Settings): string[];
@@ -212,22 +212,4 @@ export declare function restoreModelFromSession(savedProvider: string, savedMode
212
212
  model: Model<Api> | undefined;
213
213
  fallbackMessage: string | undefined;
214
214
  }>;
215
- /**
216
- * Find a smol/fast model using the priority chain.
217
- * Tries exact matches first, then fuzzy matches.
218
- *
219
- * @param modelRegistry The model registry to search
220
- * @param savedModel Optional saved model string from settings (provider/modelId)
221
- * @returns The best available smol model, or undefined if none found
222
- */
223
- export declare function findSmolModel(modelRegistry: ModelLookupRegistry, savedModel?: string): Promise<Model<Api> | undefined>;
224
- /**
225
- * Find a slow/comprehensive model using the priority chain.
226
- * Prioritizes reasoning and OpenAI code backend models for thorough analysis.
227
- *
228
- * @param modelRegistry The model registry to search
229
- * @param savedModel Optional saved model string from settings (provider/modelId)
230
- * @returns The best available slow model, or undefined if none found
231
- */
232
- export declare function findSlowModel(modelRegistry: ModelLookupRegistry, savedModel?: string): Promise<Model<Api> | undefined>;
233
215
  export {};
@@ -137,6 +137,10 @@ export declare const ModelOverrideSchema: z.ZodObject<{
137
137
  image: "image";
138
138
  text: "text";
139
139
  }>>>;
140
+ output: z.ZodOptional<z.ZodArray<z.ZodEnum<{
141
+ image: "image";
142
+ text: "text";
143
+ }>>>;
140
144
  cost: z.ZodOptional<z.ZodObject<{
141
145
  input: z.ZodOptional<z.ZodNumber>;
142
146
  output: z.ZodOptional<z.ZodNumber>;
@@ -393,6 +397,10 @@ export declare const ModelsConfigSchema: z.ZodObject<{
393
397
  image: "image";
394
398
  text: "text";
395
399
  }>>>;
400
+ output: z.ZodOptional<z.ZodArray<z.ZodEnum<{
401
+ image: "image";
402
+ text: "text";
403
+ }>>>;
396
404
  cost: z.ZodOptional<z.ZodObject<{
397
405
  input: z.ZodNumber;
398
406
  output: z.ZodNumber;
@@ -522,6 +530,10 @@ export declare const ModelsConfigSchema: z.ZodObject<{
522
530
  image: "image";
523
531
  text: "text";
524
532
  }>>>;
533
+ output: z.ZodOptional<z.ZodArray<z.ZodEnum<{
534
+ image: "image";
535
+ text: "text";
536
+ }>>>;
525
537
  cost: z.ZodOptional<z.ZodObject<{
526
538
  input: z.ZodOptional<z.ZodNumber>;
527
539
  output: z.ZodOptional<z.ZodNumber>;
@@ -1,6 +1,5 @@
1
1
  import { type SkillDiscoverySettings } from "./skill-settings-defaults";
2
2
  /** Unified settings schema - single source of truth for all settings.
3
- * Unified settings schema - single source of truth for all settings.
4
3
  *
5
4
  * Each setting is defined once here with:
6
5
  * - Type and default value
@@ -1069,6 +1068,16 @@ export declare const SETTINGS_SCHEMA: {
1069
1068
  readonly description: "When steering messages interrupt tool execution";
1070
1069
  };
1071
1070
  };
1071
+ readonly busyPromptMode: {
1072
+ readonly type: "enum";
1073
+ readonly values: readonly ["steer", "queue"];
1074
+ readonly default: "steer";
1075
+ readonly ui: {
1076
+ readonly tab: "interaction";
1077
+ readonly label: "Busy Prompt Mode";
1078
+ readonly description: "What a submitted prompt does while the agent is busy: steer (interrupt the active turn) or queue (run after the active turn completes)";
1079
+ };
1080
+ };
1072
1081
  readonly doubleEscapeAction: {
1073
1082
  readonly type: "enum";
1074
1083
  readonly values: readonly ["branch", "tree", "none"];
@@ -1144,6 +1153,15 @@ export declare const SETTINGS_SCHEMA: {
1144
1153
  readonly description: "If false, skip update check";
1145
1154
  };
1146
1155
  };
1156
+ readonly "starReminder.enabled": {
1157
+ readonly type: "boolean";
1158
+ readonly default: true;
1159
+ readonly ui: {
1160
+ readonly tab: "interaction";
1161
+ readonly label: "GitHub Star Reminder";
1162
+ readonly description: "Show the interactive GitHub star reminder when gh is authenticated";
1163
+ };
1164
+ };
1147
1165
  readonly collapseChangelog: {
1148
1166
  readonly type: "boolean";
1149
1167
  readonly default: false;
@@ -1260,11 +1278,11 @@ export declare const SETTINGS_SCHEMA: {
1260
1278
  };
1261
1279
  readonly "contextPromotion.enabled": {
1262
1280
  readonly type: "boolean";
1263
- readonly default: true;
1281
+ readonly default: false;
1264
1282
  readonly ui: {
1265
1283
  readonly tab: "context";
1266
1284
  readonly label: "Auto-Promote Context";
1267
- readonly description: "Promote to a larger-context model on context overflow instead of compacting";
1285
+ readonly description: "Promote to a larger-context model on context overflow instead of compacting (off by default; opt in to enable)";
1268
1286
  };
1269
1287
  };
1270
1288
  readonly "compaction.enabled": {
@@ -3008,7 +3026,7 @@ export declare const SETTINGS_SCHEMA: {
3008
3026
  };
3009
3027
  readonly "providers.image": {
3010
3028
  readonly type: "enum";
3011
- readonly values: readonly ["auto", "openai", "gemini", "openrouter"];
3029
+ readonly values: readonly ["auto", "openai", "gemini", "openrouter", "antigravity"];
3012
3030
  readonly default: "auto";
3013
3031
  readonly ui: {
3014
3032
  readonly tab: "providers";
@@ -3030,6 +3048,10 @@ export declare const SETTINGS_SCHEMA: {
3030
3048
  readonly value: "openrouter";
3031
3049
  readonly label: "OpenRouter";
3032
3050
  readonly description: "Requires OPENROUTER_API_KEY";
3051
+ }, {
3052
+ readonly value: "antigravity";
3053
+ readonly label: "Antigravity";
3054
+ readonly description: "Requires login with google-antigravity";
3033
3055
  }];
3034
3056
  };
3035
3057
  };
@@ -11,6 +11,12 @@ export interface PendingGoalModeRequest {
11
11
  objective: string;
12
12
  createdAt: string;
13
13
  goalsPath?: string;
14
+ /**
15
+ * Session id that produced this request (from GJC_SESSION_ID). When present,
16
+ * only the originating session may consume it, so concurrent sessions sharing
17
+ * the same `.gjc` project state never auto-run each other's ultragoal.
18
+ */
19
+ sessionId?: string;
14
20
  }
15
21
  export type CurrentSessionGoalModeWriteResult = {
16
22
  status: "unavailable";
@@ -32,12 +38,13 @@ export declare function writePendingGoalModeRequest(input: {
32
38
  cwd: string;
33
39
  objective: string;
34
40
  goalsPath?: string;
41
+ sessionId?: string | null;
35
42
  }): Promise<PendingGoalModeRequest>;
36
43
  export declare function writeCurrentSessionGoalModeState(input: {
37
44
  sessionFile?: string | null;
38
45
  objective: string;
39
46
  }): Promise<CurrentSessionGoalModeWriteResult>;
40
- export declare function consumePendingGoalModeRequest(cwd: string): Promise<PendingGoalModeRequest | null>;
47
+ export declare function consumePendingGoalModeRequest(cwd: string, currentSessionId?: string | null): Promise<PendingGoalModeRequest | null>;
41
48
  export declare function buildGjcRuntimeSessionEnv(input: {
42
49
  sessionFile?: string | null;
43
50
  sessionId?: string | null;
@@ -22,6 +22,7 @@ export interface TmuxLaunchContext {
22
22
  currentBranch?: string | null;
23
23
  existingBranchSessionName?: string | null;
24
24
  project?: string | null;
25
+ diagnosticWriter?: (message: string) => void;
25
26
  }
26
27
  export interface TmuxSpawnResult {
27
28
  exitCode: number | null;
@@ -99,6 +99,17 @@ export declare function createUltragoalPlan(input: {
99
99
  brief: string;
100
100
  gjcGoalMode?: UltragoalGjcGoalMode;
101
101
  }): Promise<UltragoalPlan>;
102
+ export interface UltragoalRunCompletionState {
103
+ requiredGoals: UltragoalGoal[];
104
+ incompleteGoals: UltragoalGoal[];
105
+ nextGoal?: UltragoalGoal;
106
+ allComplete: boolean;
107
+ hasBlockers: boolean;
108
+ needsFinalAggregateReceipt: boolean;
109
+ }
110
+ export declare function getUltragoalRunCompletionState(plan: UltragoalPlan, options?: {
111
+ retryFailed?: boolean;
112
+ }): UltragoalRunCompletionState;
102
113
  export declare function startNextUltragoalGoal(input: {
103
114
  cwd: string;
104
115
  retryFailed?: boolean;
@@ -115,6 +126,24 @@ export declare function checkpointUltragoalGoal(input: {
115
126
  gjcGoalJson?: string;
116
127
  qualityGateJson?: string;
117
128
  }): Promise<UltragoalPlan>;
129
+ export interface UltragoalCheckpointContinuation {
130
+ plan: UltragoalPlan;
131
+ checkpointedGoal: UltragoalGoal;
132
+ nextGoal?: UltragoalGoal;
133
+ startedNext: boolean;
134
+ allComplete: boolean;
135
+ incompleteGoals: UltragoalGoal[];
136
+ }
137
+ export declare function checkpointAndContinueUltragoalGoal(input: {
138
+ cwd: string;
139
+ goalId: string;
140
+ status: UltragoalGoalStatus;
141
+ evidence: string;
142
+ gjcGoalJson?: string;
143
+ qualityGateJson?: string;
144
+ advanceNext?: boolean;
145
+ retryFailed?: boolean;
146
+ }): Promise<UltragoalCheckpointContinuation>;
118
147
  export declare function addUltragoalSubgoal(input: {
119
148
  cwd: string;
120
149
  title: string;
@@ -1,3 +1,4 @@
1
+ import { type ReviewVerdict } from "./types";
1
2
  export interface ValidationCommandSpec {
2
3
  name: string;
3
4
  command: string;
@@ -25,6 +26,12 @@ export interface FinalizeOptions {
25
26
  requireTests?: boolean;
26
27
  requireCommit?: boolean;
27
28
  requirePr?: boolean;
29
+ /** Review-only sessions produce a terminal verdict instead of implementation validation. */
30
+ reviewOnly?: boolean;
31
+ /** Operator/loop-supplied terminal review verdict (closed vocabulary). */
32
+ verdict?: string | null;
33
+ /** Bounded PR/issue reference for the review target (e.g. "PR-414"). Never resolved from the live repo. */
34
+ prTarget?: string | null;
28
35
  validationCommands?: ValidationCommandSpec[];
29
36
  checks: FinalizeChecks;
30
37
  clock?: () => number;
@@ -39,6 +46,7 @@ export interface FinalizeResult {
39
46
  }[];
40
47
  commitHash: string | null;
41
48
  prUrl: string | null;
49
+ verdict?: ReviewVerdict | null;
42
50
  issueArtifact: string | null;
43
51
  blockers: string[];
44
52
  }
@@ -1,4 +1,4 @@
1
- import type { GitDelta, ReceiptFamily, RecoveryClassification } from "./types";
1
+ import { type GitDelta, type ReceiptFamily, type RecoveryClassification, type ReviewVerdict } from "./types";
2
2
  export interface ReceiptSubject {
3
3
  workspace: string;
4
4
  branch: string | null;
@@ -84,5 +84,20 @@ export interface CompletionEvidence {
84
84
  finalizedAt: string;
85
85
  blockers: string[];
86
86
  }
87
+ export interface ReviewVerdictEvidence {
88
+ verdict: ReviewVerdict;
89
+ prTarget: string | null;
90
+ finalizedAt: string;
91
+ /** Bounded summary code/reference for the verdict; never raw assistant text. */
92
+ summaryRef: string | null;
93
+ }
94
+ export interface ReviewFailureEvidence {
95
+ /** Machine-actionable reason the review produced no terminal verdict. */
96
+ reason: string;
97
+ prTarget: string | null;
98
+ failedAt: string;
99
+ /** Routing hint for the operator/fallback path. */
100
+ fallback: string;
101
+ }
87
102
  /** Classifications that MUST have a valid `vanish` receipt before the action proceeds. */
88
103
  export declare function requiresVanishBeforeAction(classification: RecoveryClassification): boolean;
@@ -7,8 +7,15 @@
7
7
  *
8
8
  * v1 implements the gajae-code adapter only. omx/codex/remote/auth are deferred seams.
9
9
  */
10
+ import type { AgentWireObservedSignal } from "../modes/shared/agent-wire/event-contract";
10
11
  /** Harnesses the control plane can operate. v1 implements `gajae-code` only. */
11
12
  export type Harness = "gajae-code" | "codex" | "omx";
13
+ /** Operating mode of a session. `implement` builds/changes code; `review` produces a read-only verdict. */
14
+ export type SessionMode = "implement" | "review";
15
+ /** Closed vocabulary of terminal review verdicts a review-only session may emit. */
16
+ export type ReviewVerdict = "APPROVE_MERGE_READY" | "REQUEST_CHANGES" | "OWNER_CONFIRMATION_REQUIRED";
17
+ export declare const REVIEW_VERDICTS: readonly ReviewVerdict[];
18
+ export declare function isReviewVerdict(value: unknown): value is ReviewVerdict;
12
19
  /** Lifecycle states of an operated session. */
13
20
  export type HarnessLifecycle = "new" | "started" | "submitted" | "observing" | "recovering" | "validating" | "finalizing" | "completed" | "blocked" | "retired";
14
21
  /** Event severities emitted by the owner. */
@@ -20,7 +27,7 @@ export type RiskKind = "normal" | "prompt-not-accepted" | "deleted-worktree" | "
20
27
  /** Deterministic recovery classifications. */
21
28
  export type RecoveryClassification = "continue" | "send-enter" | "reinject-prompt" | "restart-clean" | "restart-preserve-delta" | "fallback-codex-exec" | "human-check";
22
29
  /** Receipt families persisted under the session storage dir. */
23
- export type ReceiptFamily = "vanish" | "prompt-acceptance" | "validation" | "completion";
30
+ export type ReceiptFamily = "vanish" | "prompt-acceptance" | "validation" | "completion" | "review-verdict" | "review-failure";
24
31
  /** The CLI verbs / primitives exposed by `gjc harness <verb>`. */
25
32
  export type HarnessVerb = "start" | "submit" | "observe" | "classify" | "recover" | "validate" | "finalize" | "retire" | "events" | "monitor" | "operate";
26
33
  /** Submission transports. */
@@ -54,6 +61,8 @@ export interface PrimitiveResponse<E = Record<string, unknown>> {
54
61
  export interface SessionHandle {
55
62
  sessionId: string;
56
63
  harness: Harness;
64
+ /** Operating mode; absent on legacy records means `implement`. */
65
+ mode?: SessionMode;
57
66
  repo: string | null;
58
67
  workspace: string;
59
68
  branch: string | null;
@@ -100,8 +109,12 @@ export interface SessionState {
100
109
  createdAt: string;
101
110
  updatedAt: string;
102
111
  }
103
- /** Bounded observed-signal vocabulary surfaced by `observe` (the owner only ever emits these). */
104
- export type ObservedSignal = "SessionStart" | "prompt-accepted" | "tool-call" | "test-running" | "commit-created" | "completed" | "error" | "streaming" | "idle";
112
+ /**
113
+ * Bounded observed-signal vocabulary surfaced by `observe` (the owner only ever
114
+ * emits these). Aliased to the canonical agent-wire signal vocabulary so there
115
+ * is a single source of truth shared with the observation core.
116
+ */
117
+ export type ObservedSignal = AgentWireObservedSignal;
105
118
  export declare const OBSERVED_SIGNALS: readonly ObservedSignal[];
106
119
  /** Bounded observation surfaced by `observe` — never a raw pane/transcript dump. */
107
120
  export interface Observation {
@@ -1,5 +1,6 @@
1
1
  import type { SessionNotification, SessionUpdate, ToolKind } from "@agentclientprotocol/sdk";
2
2
  import type { AgentSessionEvent } from "../../session/agent-session";
3
+ import type { AgentWireEventPayload } from "../shared/agent-wire/event-contract";
3
4
  interface MessageProgress {
4
5
  textEmitted: boolean;
5
6
  thoughtEmitted: boolean;
@@ -17,6 +18,7 @@ interface AcpEventMapperOptions {
17
18
  cwd?: string;
18
19
  }
19
20
  export declare function mapToolKind(toolName: string): ToolKind;
21
+ export declare function mapAgentWireEventPayloadToAcpSessionUpdates(payload: AgentWireEventPayload, sessionId: string, options?: AcpEventMapperOptions): SessionNotification[];
20
22
  export declare function mapAgentSessionEventToAcpSessionUpdates(event: AgentSessionEvent, sessionId: string, options?: AcpEventMapperOptions): SessionNotification[];
21
23
  export declare function buildToolCallStartUpdate(input: {
22
24
  toolCallId: string;
@@ -8,6 +8,13 @@ type PastePendingClearReason = "timeout" | "queue-limit";
8
8
  export declare class CustomEditor extends Editor {
9
9
  #private;
10
10
  onEscape?: () => void;
11
+ /**
12
+ * Optional high-priority interrupt consumer. Invoked when the interrupt key
13
+ * is pressed, before `onEscape`. Returning `true` consumes the keystroke.
14
+ * Used so a transient UI (e.g. the btw panel) stays dismissable even while
15
+ * another controller has temporarily installed its own `onEscape` handler.
16
+ */
17
+ onInterruptPriority?: () => boolean;
11
18
  shouldBypassAutocompleteOnEscape?: () => boolean;
12
19
  onClear?: () => void;
13
20
  onExit?: () => void;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Canonical command-surface boundary for the agent-wire adapters.
3
+ *
4
+ * RPC and Bridge SHARE the JSONL `RpcCommand` grammar and dispatch it through
5
+ * the single `dispatchRpcCommand` entry in `command-dispatch.ts`. This module
6
+ * re-exports that command surface so the shared contract has one documented home.
7
+ *
8
+ * ACP does NOT use `RpcCommand`. It keeps its richer `@agentclientprotocol/sdk`
9
+ * command surface (fork/resume/elicitation/session-mode/session-model) and only
10
+ * shares the lower session/event layer (`AgentWireEventPayload`). ACP must never
11
+ * import `dispatchRpcCommand`.
12
+ *
13
+ * Event semantics are intentionally elsewhere: `event-contract.ts` owns the event
14
+ * types + registry and `event-observation.ts` owns the single semantic mapping.
15
+ */
16
+ export type { RpcCommand, RpcResponse } from "../../rpc/rpc-types";
17
+ export { dispatchRpcCommand, type RpcCommandDispatchContext } from "./command-dispatch";
18
+ export { isRpcCommandType, RPC_COMMAND_TYPES, type RpcCommandType } from "./scopes";
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Canonical agent-wire contract: the single transport-neutral source of truth
3
+ * for AgentSession events and bounded owner observations.
4
+ *
5
+ * Two distinct consumer-facing shapes, deliberately NOT collapsed into one:
6
+ * - `AgentWireEventPayload`: rich, full `AgentSessionEvent` for renderers
7
+ * (ACP SDK notifications, RPC/Bridge event frames).
8
+ * - `AgentWireOwnerObservation`: bounded/redacted owner evidence for control
9
+ * planes (Harness). Never carries assistant text, message deltas, raw tool
10
+ * args, raw command output, raw tool results, answers, or oversize strings.
11
+ *
12
+ * The exhaustive `AGENT_SESSION_EVENT_TYPE_REGISTRY` lives here so that adding
13
+ * an `AgentSessionEvent` variant fails typecheck until it is registered, and so
14
+ * conformance tests can assert fixture coverage equals the registry exactly.
15
+ */
16
+ import type { AgentSessionEvent } from "../../../session/agent-session";
17
+ /** Wire protocol version. Bump on breaking envelope/semantic changes. */
18
+ export declare const AGENT_WIRE_PROTOCOL_VERSION: 2;
19
+ export type AgentWireProtocolVersion = typeof AGENT_WIRE_PROTOCOL_VERSION;
20
+ /** The discriminant of every `AgentSessionEvent` the agent can emit. */
21
+ export type AgentWireEventType = AgentSessionEvent["type"];
22
+ /** Every agent-session event type, derived from the exhaustive registry. */
23
+ export declare const AGENT_WIRE_EVENT_TYPES: readonly AgentWireEventType[];
24
+ /**
25
+ * Rich event payload. Carries the full `AgentSessionEvent` so renderers (ACP,
26
+ * RPC, Bridge) can present message content, tool args/results, todo state, etc.
27
+ */
28
+ export interface AgentWireEventPayload {
29
+ event_type: AgentWireEventType;
30
+ event: AgentSessionEvent;
31
+ }
32
+ /**
33
+ * Bounded observed-signal vocabulary surfaced to owner control planes. Mirrors
34
+ * the Harness `ObservedSignal` set; the Harness type aliases this in a later
35
+ * step so there is a single source of truth.
36
+ */
37
+ export type AgentWireObservedSignal = "SessionStart" | "prompt-accepted" | "tool-call" | "test-running" | "commit-created" | "completed" | "error" | "streaming" | "idle";
38
+ export type AgentWireSeverity = "info" | "warn" | "critical";
39
+ /**
40
+ * Bounded, redacted owner observation. Evidence may include ids, names,
41
+ * categories, statuses, cursors, timestamps, short codes, and bounded short
42
+ * messages ONLY. It must never carry assistant text, message deltas, raw tool
43
+ * args, raw command output, raw tool result content, answers, or oversize
44
+ * strings.
45
+ */
46
+ export interface AgentWireOwnerObservation {
47
+ /** Set when this observation derives from an `AgentSessionEvent`. */
48
+ eventType?: AgentWireEventType;
49
+ /** Set when this observation derives from a non-event wire frame. */
50
+ frameType?: string;
51
+ /** Owner event kind (e.g. `rpc_tool_started`). */
52
+ kind: string;
53
+ /** Bounded observed signal, or null when the frame carries no signal. */
54
+ signal: AgentWireObservedSignal | null;
55
+ /** Bounded evidence — ids/names/statuses/cursors/timestamps/short codes only. */
56
+ evidence: Record<string, unknown>;
57
+ /** Severity for the emitted event. */
58
+ severity: AgentWireSeverity;
59
+ /** Never-drop observations: must be enqueued in order, never coalesced away. */
60
+ semantic: boolean;
61
+ /** Coalescing key for high-frequency non-semantic frames; null otherwise. */
62
+ coalesceKey: string | null;
63
+ }
64
+ /** Top-level frame categories carried over any agent-wire transport. */
65
+ export type AgentWireFrameType = "ready" | "event" | "response" | "ui_request" | "permission_request" | "host_tool_call" | "host_uri_request" | "reset" | "workflow_gate" | "error";
66
+ /**
67
+ * Universal frame envelope. Every frame on every transport carries these
68
+ * fields so clients can order (`seq`), resume (`seq` cursor), and correlate
69
+ * request/response pairs (`correlation_id`).
70
+ */
71
+ export interface AgentWireFrameEnvelope<TType extends AgentWireFrameType = AgentWireFrameType, TPayload = unknown> {
72
+ protocol_version: AgentWireProtocolVersion;
73
+ session_id: string;
74
+ /** Monotonic per-session sequence number, starting at 1. */
75
+ seq: number;
76
+ /** Unique id for this frame. */
77
+ frame_id: string;
78
+ /** Ties a request frame to its response frame, when applicable. */
79
+ correlation_id?: string;
80
+ type: TType;
81
+ payload: TPayload;
82
+ }
83
+ /** An `AgentSessionEvent` serialized into a versioned wire frame. */
84
+ export type AgentWireEventFrame = AgentWireFrameEnvelope<"event", AgentWireEventPayload>;
@@ -1,16 +1,16 @@
1
1
  import type { AgentSessionEvent } from "../../../session/agent-session";
2
- import { type AgentSessionEventType, type BridgeEventFrame, type BridgeFrameEnvelope, type BridgeFrameType } from "./protocol";
2
+ import { type AgentWireEventFrame, type AgentWireEventPayload, type AgentWireEventType, type AgentWireFrameEnvelope, type AgentWireFrameType } from "./event-contract";
3
3
  /**
4
4
  * Resolve the stable wire event-type for an `AgentSessionEvent`.
5
5
  *
6
6
  * Exhaustive over the union; adding a variant without a case is a type error.
7
7
  */
8
- export declare function agentSessionEventType(event: AgentSessionEvent): AgentSessionEventType;
8
+ export declare function agentSessionEventType(event: AgentSessionEvent): AgentWireEventType;
9
9
  /**
10
10
  * Per-session monotonic frame builder. One instance per active session; `seq`
11
11
  * starts at 1 and increments per frame so clients can order and resume.
12
12
  */
13
- export declare class BridgeFrameSequencer {
13
+ export declare class AgentWireFrameSequencer {
14
14
  #private;
15
15
  constructor(sessionId: string);
16
16
  /** The session id stamped onto every frame this sequencer produces. */
@@ -18,14 +18,21 @@ export declare class BridgeFrameSequencer {
18
18
  /** The seq assigned to the most recently produced frame (0 before any). */
19
19
  get lastSeq(): number;
20
20
  /** Build the next envelope of the given type with a fresh seq + frame id. */
21
- next<TType extends BridgeFrameType, TPayload>(type: TType, payload: TPayload, correlationId?: string): BridgeFrameEnvelope<TType, TPayload>;
21
+ next<TType extends AgentWireFrameType, TPayload>(type: TType, payload: TPayload, correlationId?: string): AgentWireFrameEnvelope<TType, TPayload>;
22
22
  }
23
- /** Serialize a single `AgentSessionEvent` into an `event` wire frame. */
24
- export declare function toBridgeEventFrame(event: AgentSessionEvent, sequencer: BridgeFrameSequencer): BridgeEventFrame;
23
+ /** Back-compat alias for {@link AgentWireFrameSequencer}. */
24
+ export declare const BridgeFrameSequencer: typeof AgentWireFrameSequencer;
25
+ export type BridgeFrameSequencer = AgentWireFrameSequencer;
26
+ /** Serialize a single `AgentSessionEvent` into a canonical `event` wire frame. */
27
+ export declare function toAgentWireEventFrame(event: AgentSessionEvent, sequencer: AgentWireFrameSequencer): AgentWireEventFrame;
28
+ /** Build the rich event payload (renderer-facing) for an `AgentSessionEvent`. */
29
+ export declare function toAgentWireEventPayload(event: AgentSessionEvent): AgentWireEventPayload;
30
+ /** Back-compat alias for {@link toAgentWireEventFrame}. */
31
+ export declare const toBridgeEventFrame: typeof toAgentWireEventFrame;
25
32
  /**
26
33
  * Serialize a `workflow_gate` event into a sequenced wire frame (#321). The
27
34
  * gate_id is stamped as the correlation id so the answer (posted to the
28
35
  * ui-responses endpoint) can be matched, and the monotonic `seq` gives replay
29
36
  * while `frame_id` + gate_id give idempotency.
30
37
  */
31
- export declare function toBridgeWorkflowGateFrame(gate: import("../../rpc/rpc-types").RpcWorkflowGate, sequencer: BridgeFrameSequencer): import("./protocol").BridgeWorkflowGateFrame;
38
+ export declare function toBridgeWorkflowGateFrame(gate: import("../../rpc/rpc-types").RpcWorkflowGate, sequencer: AgentWireFrameSequencer): import("./protocol").BridgeWorkflowGateFrame;