@gajae-code/coding-agent 0.16.4 → 0.16.6

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 (198) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/types/capability/types.d.ts +4 -0
  3. package/dist/types/cli/customize-doctor.d.ts +22 -0
  4. package/dist/types/config/file-lock.d.ts +31 -3
  5. package/dist/types/coordinator-mcp/question-state.d.ts +7 -0
  6. package/dist/types/coordinator-mcp/server.d.ts +7 -0
  7. package/dist/types/discovery/helpers.d.ts +33 -0
  8. package/dist/types/exec/bash-executor.d.ts +17 -1
  9. package/dist/types/exec/bash-shell-guardian.d.ts +15 -0
  10. package/dist/types/exec/bash-shell-runtime-entry.d.ts +2 -0
  11. package/dist/types/exec/bash-shell-signals.d.ts +2 -0
  12. package/dist/types/exec/bash-shell-supervisor-entry.d.ts +1 -0
  13. package/dist/types/exec/bash-shell-supervisor.d.ts +10 -0
  14. package/dist/types/exec/bash-shell-worker-entry.d.ts +2 -0
  15. package/dist/types/exec/bash-shell-worker-protocol.d.ts +63 -0
  16. package/dist/types/exec/bash-shell-worker.d.ts +1 -0
  17. package/dist/types/exec/isolated-shell.d.ts +19 -0
  18. package/dist/types/extensibility/extensions/function-hooks-internal.d.ts +9 -0
  19. package/dist/types/extensibility/extensions/function-hooks.d.ts +169 -0
  20. package/dist/types/extensibility/extensions/index.d.ts +1 -0
  21. package/dist/types/extensibility/extensions/runner.d.ts +46 -6
  22. package/dist/types/extensibility/extensions/types.d.ts +16 -0
  23. package/dist/types/extensibility/extensions/wrapper.d.ts +3 -1
  24. package/dist/types/extensibility/gjc-plugins/constrained-hooks.d.ts +35 -2
  25. package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
  26. package/dist/types/extensibility/hooks/types.d.ts +4 -0
  27. package/dist/types/extensibility/runtime-skill-discovery.d.ts +4 -1
  28. package/dist/types/extensibility/skill-management.d.ts +9 -4
  29. package/dist/types/extensibility/skills.d.ts +2 -0
  30. package/dist/types/gjc-runtime/empty-delete-gc.d.ts +4 -1
  31. package/dist/types/gjc-runtime/linux-proc.d.ts +2 -0
  32. package/dist/types/gjc-runtime/session-state-lock.d.ts +12 -0
  33. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +41 -3
  34. package/dist/types/gjc-runtime/ultragoal-succession.d.ts +251 -0
  35. package/dist/types/modes/components/bash-execution.d.ts +1 -0
  36. package/dist/types/modes/components/execution-shared.d.ts +1 -0
  37. package/dist/types/modes/interactive-mode.d.ts +2 -0
  38. package/dist/types/modes/types.d.ts +6 -0
  39. package/dist/types/sdk/broker/ensure.d.ts +32 -0
  40. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +0 -1
  41. package/dist/types/sdk/broker/lifecycle.d.ts +6 -0
  42. package/dist/types/sdk/broker/startup-failure.d.ts +4 -1
  43. package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -0
  44. package/dist/types/sdk/bus/chat-effect-journal.d.ts +17 -2
  45. package/dist/types/sdk/bus/conversation-store.d.ts +11 -0
  46. package/dist/types/sdk/bus/lifecycle-commands.d.ts +8 -8
  47. package/dist/types/sdk/bus/slack-daemon.d.ts +1 -1
  48. package/dist/types/sdk/bus/topic-registry.d.ts +8 -0
  49. package/dist/types/sdk/client/client.d.ts +6 -0
  50. package/dist/types/sdk/host/host.d.ts +3 -1
  51. package/dist/types/sdk/host/session-runtime.d.ts +4 -2
  52. package/dist/types/sdk/lifecycle/service.d.ts +1 -0
  53. package/dist/types/sdk/router/session-router.d.ts +10 -2
  54. package/dist/types/sdk/session.d.ts +5 -1
  55. package/dist/types/session/agent-session.d.ts +2 -0
  56. package/dist/types/session/fallback-chain-controller.d.ts +15 -0
  57. package/dist/types/session/internal/managed-session-storage.d.ts +7 -0
  58. package/dist/types/session/messages.d.ts +1 -0
  59. package/dist/types/session/session-manager.d.ts +3 -1
  60. package/dist/types/setup/paseo/announce.d.ts +4 -3
  61. package/dist/types/skill-state/canonical-skills.d.ts +4 -0
  62. package/dist/types/system-prompt.d.ts +8 -0
  63. package/dist/types/task/executor.d.ts +3 -0
  64. package/dist/types/tools/bash.d.ts +1 -0
  65. package/dist/types/tools/github-cache.d.ts +2 -1
  66. package/dist/types/tools/index.d.ts +2 -0
  67. package/package.json +9 -7
  68. package/scripts/generate-sdk-operation-inventory.ts +2 -0
  69. package/src/capability/index.ts +14 -2
  70. package/src/capability/types.ts +4 -0
  71. package/src/cli/customize-doctor.ts +155 -12
  72. package/src/cli.ts +22 -0
  73. package/src/commands/sdk.ts +74 -31
  74. package/src/config/file-lock-gc.ts +40 -2
  75. package/src/config/file-lock.ts +198 -14
  76. package/src/config/model-preset-registry.ts +115 -16
  77. package/src/config/model-registry.ts +16 -12
  78. package/src/coordinator-mcp/question-state.ts +33 -2
  79. package/src/coordinator-mcp/server.ts +477 -101
  80. package/src/crash/sanitize.ts +1 -1
  81. package/src/defaults/gjc/skills/ultragoal/SKILL.md +22 -0
  82. package/src/discovery/builtin.ts +50 -62
  83. package/src/discovery/helpers.ts +297 -32
  84. package/src/exec/bash-executor.ts +330 -50
  85. package/src/exec/bash-shell-guardian.ts +388 -0
  86. package/src/exec/bash-shell-runtime-entry.ts +5 -0
  87. package/src/exec/bash-shell-signals.ts +29 -0
  88. package/src/exec/bash-shell-supervisor-entry.ts +3 -0
  89. package/src/exec/bash-shell-supervisor.ts +359 -0
  90. package/src/exec/bash-shell-worker-entry.ts +5 -0
  91. package/src/exec/bash-shell-worker-protocol.ts +36 -0
  92. package/src/exec/bash-shell-worker.ts +116 -0
  93. package/src/exec/isolated-shell.ts +393 -0
  94. package/src/extensibility/extensions/function-hooks-internal.ts +73 -0
  95. package/src/extensibility/extensions/function-hooks.ts +959 -0
  96. package/src/extensibility/extensions/index.ts +22 -0
  97. package/src/extensibility/extensions/loader.ts +53 -2
  98. package/src/extensibility/extensions/runner.ts +895 -264
  99. package/src/extensibility/extensions/types.ts +42 -0
  100. package/src/extensibility/extensions/wrapper.ts +56 -15
  101. package/src/extensibility/gjc-plugins/compiler.ts +20 -2
  102. package/src/extensibility/gjc-plugins/constrained-hooks.ts +321 -23
  103. package/src/extensibility/gjc-plugins/registry.ts +113 -1
  104. package/src/extensibility/gjc-plugins/runtime-quarantine.ts +20 -2
  105. package/src/extensibility/gjc-plugins/schema.ts +121 -4
  106. package/src/extensibility/gjc-plugins/types.ts +25 -0
  107. package/src/extensibility/hooks/loader.ts +133 -16
  108. package/src/extensibility/hooks/types.ts +28 -0
  109. package/src/extensibility/runtime-skill-discovery.ts +80 -47
  110. package/src/extensibility/skill-management.ts +200 -52
  111. package/src/extensibility/skills.ts +29 -9
  112. package/src/gjc-runtime/empty-delete-gc.ts +94 -4
  113. package/src/gjc-runtime/gc-runtime.ts +29 -0
  114. package/src/gjc-runtime/linux-proc.ts +14 -0
  115. package/src/gjc-runtime/session-state-lock.ts +51 -8
  116. package/src/gjc-runtime/session-state-sidecar.ts +27 -11
  117. package/src/gjc-runtime/state-writer.ts +30 -29
  118. package/src/gjc-runtime/ultragoal-runtime.ts +189 -47
  119. package/src/gjc-runtime/ultragoal-succession.ts +1667 -0
  120. package/src/gjc-runtime/workflow-manifest.generated.json +52 -1
  121. package/src/gjc-runtime/workflow-manifest.ts +16 -0
  122. package/src/harness-control-plane/session-lease.ts +2 -2
  123. package/src/internal-urls/docs-index.generated.ts +6 -6
  124. package/src/lsp/config.ts +10 -3
  125. package/src/lsp/index.ts +1 -1
  126. package/src/lsp/path-trust.ts +69 -14
  127. package/src/main.ts +6 -1
  128. package/src/modes/acp/acp-agent.ts +16 -3
  129. package/src/modes/components/bash-execution.ts +4 -1
  130. package/src/modes/components/execution-shared.ts +4 -1
  131. package/src/modes/components/session-observer-overlay.ts +1 -1
  132. package/src/modes/components/tool-status-header.ts +3 -1
  133. package/src/modes/controllers/command-controller.ts +1 -0
  134. package/src/modes/controllers/event-controller.ts +3 -2
  135. package/src/modes/controllers/extension-ui-controller.ts +1 -0
  136. package/src/modes/controllers/input-controller.ts +6 -3
  137. package/src/modes/interactive-mode.ts +6 -5
  138. package/src/modes/print-mode.ts +5 -1
  139. package/src/modes/prompt-action-autocomplete.ts +54 -27
  140. package/src/modes/runtime-init.ts +2 -0
  141. package/src/modes/types.ts +16 -3
  142. package/src/modes/utils/ui-helpers.ts +1 -0
  143. package/src/prompts/tools/subagent.md +1 -0
  144. package/src/runtime-mcp/manager.ts +20 -2
  145. package/src/runtime-mcp/pool.test.ts +20 -11
  146. package/src/sdk/broker/broker.ts +119 -28
  147. package/src/sdk/broker/ensure.ts +248 -41
  148. package/src/sdk/broker/lifecycle-ledger.ts +7 -17
  149. package/src/sdk/broker/lifecycle.ts +56 -6
  150. package/src/sdk/broker/startup-failure.ts +15 -6
  151. package/src/sdk/bus/chat-daemon-control.ts +3 -1
  152. package/src/sdk/bus/chat-daemon-runtime.ts +35 -5
  153. package/src/sdk/bus/chat-effect-journal.ts +132 -7
  154. package/src/sdk/bus/conversation-store.ts +29 -0
  155. package/src/sdk/bus/lifecycle-commands.ts +17 -11
  156. package/src/sdk/bus/slack-conversation.ts +1 -0
  157. package/src/sdk/bus/slack-daemon.ts +387 -48
  158. package/src/sdk/bus/telegram-daemon.ts +16 -2
  159. package/src/sdk/bus/topic-registry.ts +19 -0
  160. package/src/sdk/cli/master-cli.ts +1 -1
  161. package/src/sdk/cli/session-cli.ts +2 -2
  162. package/src/sdk/client/client.ts +66 -17
  163. package/src/sdk/host/host.ts +29 -9
  164. package/src/sdk/host/query/revision-store.ts +19 -13
  165. package/src/sdk/host/reverse-leases.ts +7 -4
  166. package/src/sdk/host/session-runtime.test.ts +50 -8
  167. package/src/sdk/host/session-runtime.ts +158 -51
  168. package/src/sdk/lifecycle/service.ts +4 -0
  169. package/src/sdk/protocol/operation-inventory.generated.json +11 -0
  170. package/src/sdk/router/session-router.ts +89 -38
  171. package/src/sdk/session.ts +155 -26
  172. package/src/sdk/transport/relay.ts +35 -13
  173. package/src/session/agent-session.ts +117 -52
  174. package/src/session/fallback-chain-controller.ts +38 -0
  175. package/src/session/internal/managed-session-storage.ts +19 -5
  176. package/src/session/messages.ts +5 -0
  177. package/src/session/session-manager.ts +29 -5
  178. package/src/session-import/redact.ts +5 -1
  179. package/src/setup/paseo/announce.ts +49 -43
  180. package/src/setup/paseo/setup-deps.ts +1 -1
  181. package/src/skill-state/canonical-skills.ts +12 -0
  182. package/src/skills/skills.test.ts +41 -21
  183. package/src/system-prompt.ts +25 -3
  184. package/src/task/executor.ts +5 -0
  185. package/src/task/index.ts +4 -0
  186. package/src/tools/bash.ts +28 -11
  187. package/src/tools/gh.ts +26 -3
  188. package/src/tools/github-cache.ts +68 -16
  189. package/src/tools/index.ts +2 -0
  190. package/src/tools/job.ts +13 -2
  191. package/src/tools/read.ts +14 -2
  192. package/src/tools/render-utils.ts +1 -3
  193. package/src/tools/resource-gc.ts +28 -8
  194. package/src/tools/skill-discovery.ts +5 -0
  195. package/src/tools/skill.ts +15 -0
  196. package/src/tools/subagent.ts +3 -2
  197. package/src/tools/tool-catalog.generated.ts +2 -2
  198. package/src/tools/ultragoal-ask-guard.ts +2 -2
@@ -2,6 +2,7 @@
2
2
  * Extension system for lifecycle events and custom tools.
3
3
  */
4
4
  export type { SlashCommandInfo, SlashCommandLocation, SlashCommandSource } from "../slash-commands";
5
+ export { attenuateFunctionHookGrant, cloneFunctionHookData, compatibilityFunctionHookGrant, createFunctionHookCapabilities, DEFAULT_EXTENSION_FUNCTION_HOOK_GRANT, FUNCTION_HOOK_CAPABILITIES, functionHookDenyAllowed, functionHookEventIdentityMatches, functionHookGrantHash, functionHookGrantOperations, functionHookPayloadHash, functionHookTransformAllowed, intersectFunctionHookGrants, isPlainFunctionHookData, isSafeFunctionHookValue, isValidFunctionHookEventValue, normalizeFunctionHookGrant, redactFunctionHookValue, sanitizeFunctionHookReason, validateFunctionHookTarget, } from "./function-hooks";
5
6
  export { discoverAndLoadExtensions, ExtensionRuntimeNotInitializedError, loadExtensionFromFactory, loadExtensions, } from "./loader";
6
7
  export * from "./ouroboros-ooo-bridge";
7
8
  export * from "./prefix-command-bridge";
@@ -8,11 +8,14 @@ import type { ModelRegistry } from "../../config/model-registry";
8
8
  import type { Settings } from "../../config/settings";
9
9
  import type { AttemptRecordStore } from "../../session/attempt-record-store";
10
10
  import { type SessionManager } from "../../session/session-manager";
11
+ import { type FunctionHookAuditRecord, type FunctionHookRegistration } from "./function-hooks";
11
12
  import type { AfterProviderResponseEvent, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderRequestEvent, BeforeProviderRequestEventResult, ContextEvent, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionRuntime, ExtensionShortcut, ExtensionUIContext, InputEvent, InputEventResult, MessageRenderer, RegisteredCommand, RegisteredTool, ResourcesDiscoverEvent, SessionBeforeBranchResult, SessionBeforeCompactResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionCompactingResult, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, UserBashEvent, UserBashEventResult, UserPythonEvent, UserPythonEventResult } from "./types";
12
13
  /** Combined result from all before_agent_start handlers */
13
14
  interface BeforeAgentStartCombinedResult {
14
15
  messages?: NonNullable<BeforeAgentStartEventResult["message"]>[];
15
16
  systemPrompt?: string[];
17
+ prompt?: string;
18
+ images?: ImageContent[];
16
19
  }
17
20
  export type ExtensionErrorListener = (error: ExtensionError) => void;
18
21
  /** Bounded timeout for session_shutdown handlers — generous but never infinite. */
@@ -36,6 +39,24 @@ type RunnerEmitResult<TEvent extends RunnerEmitEvent> = TEvent extends {
36
39
  } ? SessionBeforeTreeResult | undefined : TEvent extends {
37
40
  type: "session.compacting";
38
41
  } ? SessionCompactingResult | undefined : undefined;
42
+ type Handler = Extension["handlers"] extends Map<string, Array<infer T>> ? T : never;
43
+ type IndexedHandler = {
44
+ ext: Extension;
45
+ handler: Handler;
46
+ registrationOrder: number;
47
+ };
48
+ export type FunctionHookDispatchResult<TEvent extends ExtensionEvent> = {
49
+ action: "continue";
50
+ event: TEvent;
51
+ transformed?: boolean;
52
+ } | {
53
+ action: "deny";
54
+ reason: string;
55
+ } | {
56
+ action: "return";
57
+ value: unknown;
58
+ };
59
+ export type FunctionHookAuditSink = (record: FunctionHookAuditRecord) => void;
39
60
  export type NewSessionHandler = (options?: {
40
61
  parentSession?: string;
41
62
  setup?: (sessionManager: SessionManager) => Promise<void>;
@@ -97,6 +118,12 @@ export declare class ExtensionRunner {
97
118
  onError(listener: ExtensionErrorListener): () => void;
98
119
  emitError(error: ExtensionError): void;
99
120
  hasHandlers(eventType: string): boolean;
121
+ hasToolResultMediation(toolName: string): boolean;
122
+ /** Return immutable registration metadata in authoritative registration order. */
123
+ getFunctionHookRegistrations(): readonly FunctionHookRegistration[];
124
+ /** Install the optional deterministic audit sink used by hosts and tests. */
125
+ setFunctionHookAuditSink(sink: FunctionHookAuditSink | undefined): void;
126
+ getFunctionHookAudit(): readonly FunctionHookAuditRecord[];
100
127
  setAttemptRecordStore(store: AttemptRecordStore): void;
101
128
  getMessageRenderer(customType: string): MessageRenderer | undefined;
102
129
  getRegisteredCommands(reserved?: Set<string>): RegisteredCommand[];
@@ -112,9 +139,22 @@ export declare class ExtensionRunner {
112
139
  */
113
140
  shutdown(): void;
114
141
  createCommandContext(): ExtensionCommandContext;
142
+ /** Execute capability-scoped middleware stored in Extension.handlers. */
143
+ emitFunctionHooks<TEvent extends ExtensionEvent>(event: TEvent, options?: {
144
+ signal?: AbortSignal;
145
+ correlationId?: string;
146
+ scope?: AttemptScopeRef;
147
+ legacyHandler?: (handler: IndexedHandler, event: TEvent) => Promise<FunctionHookDispatchResult<TEvent>>;
148
+ }): Promise<FunctionHookDispatchResult<TEvent>>;
115
149
  emit<TEvent extends RunnerEmitEvent>(event: TEvent, continueWhile?: () => boolean, scope?: AttemptScopeRef): Promise<RunnerEmitResult<TEvent>>;
116
- emitToolResult(event: ToolResultEvent, scope?: AttemptScopeRef): Promise<ToolResultEventResult | undefined>;
117
- emitToolCall(event: ToolCallEvent, scope?: AttemptScopeRef): Promise<ToolCallEventResult | undefined>;
150
+ emitToolResult(event: ToolResultEvent, scope?: AttemptScopeRef, options?: {
151
+ signal?: AbortSignal;
152
+ correlationId?: string;
153
+ }): Promise<ToolResultEventResult | undefined>;
154
+ emitToolCall(event: ToolCallEvent, scope?: AttemptScopeRef, options?: {
155
+ signal?: AbortSignal;
156
+ correlationId?: string;
157
+ }): Promise<ToolCallEventResult | undefined>;
118
158
  emitUserBash(event: UserBashEvent): Promise<UserBashEventResult | undefined>;
119
159
  emitUserPython(event: UserPythonEvent): Promise<UserPythonEventResult | undefined>;
120
160
  private emitUserEvent;
@@ -134,9 +174,9 @@ export declare class ExtensionRunner {
134
174
  }>;
135
175
  /** Emit input event. Transforms chain, "handled" short-circuits. */
136
176
  emitInput(text: string, images: ImageContent[] | undefined, source: "interactive" | "sdk" | "extension"): Promise<InputEventResult>;
137
- emitContext(messages: AgentMessage[], scope?: AttemptScopeRef): Promise<AgentMessage[]>;
138
- emitBeforeProviderRequest(payload: unknown, scope?: AttemptScopeRef): Promise<BeforeProviderRequestEventResult>;
139
- emitAfterProviderResponse(response: ProviderResponseMetadata, _model?: Model, scope?: AttemptScopeRef): Promise<void>;
140
- emitBeforeAgentStart(prompt: string, images: ImageContent[] | undefined, systemPrompt: string[]): Promise<BeforeAgentStartCombinedResult | undefined>;
177
+ emitContext(messages: AgentMessage[], scope?: AttemptScopeRef, signal?: AbortSignal): Promise<AgentMessage[]>;
178
+ emitBeforeProviderRequest(payload: unknown, scope?: AttemptScopeRef, signal?: AbortSignal): Promise<BeforeProviderRequestEventResult>;
179
+ emitAfterProviderResponse(response: ProviderResponseMetadata, _model?: Model, scope?: AttemptScopeRef, signal?: AbortSignal): Promise<void>;
180
+ emitBeforeAgentStart(prompt: string, images: ImageContent[] | undefined, systemPrompt: string[], signal?: AbortSignal): Promise<BeforeAgentStartCombinedResult | undefined>;
141
181
  }
142
182
  export {};
@@ -27,6 +27,7 @@ import type { ExecOptions, ExecResult } from "../../exec/exec";
27
27
  import type { CustomEditor } from "../../modes/components/custom-editor";
28
28
  import type { WorkflowGateEmitter } from "../../modes/shared/agent-wire/workflow-gate-broker";
29
29
  import type { Theme } from "../../modes/theme/theme";
30
+ import type { AgentSessionEventListener } from "../../session/agent-session";
30
31
  import type { ClientBridge, ClientBridgePermissionOption, ClientBridgePermissionOutcome, ClientBridgePermissionToolCall } from "../../session/client-bridge";
31
32
  import type { CustomMessage } from "../../session/messages";
32
33
  import type { ReadonlySessionManager, SessionManager } from "../../session/session-manager";
@@ -34,6 +35,7 @@ import type { BashToolDetails, BashToolInput, FindToolDetails, FindToolInput, Re
34
35
  import type { EventBus } from "../../utils/event-bus";
35
36
  import type { AgentEndEvent, AutoCompactionEndEvent, AutoCompactionStartEvent, AutoRetryEndEvent, AutoRetryStartEvent, ContextEvent, GoalUpdatedEvent, SessionBeforeBranchEvent, SessionBeforeBranchResult, SessionBeforeCompactEvent, SessionBeforeCompactResult, SessionBeforeSwitchEvent, SessionBeforeSwitchResult, SessionBeforeTreeEvent, SessionBeforeTreeResult, SessionBranchEvent, SessionCompactEvent, SessionCompactingEvent, SessionCompactingResult, SessionEvent, SessionShutdownEvent, SessionStartEvent, SessionSwitchEvent, SessionTreeEvent, AgentStartEvent as SharedAgentStartEvent, TodoReminderEvent, ToolCallEventResult, ToolResultEventResult, TtsrTriggeredEvent, TurnEndEvent, TurnStartEvent } from "../shared-events";
36
37
  import type { SlashCommandInfo } from "../slash-commands";
38
+ import type { FunctionHook, FunctionHookEventType, FunctionHookPayloadFor, FunctionHookRegistrationOptions } from "./function-hooks";
37
39
  export type { AppKeybinding, KeybindingsManager } from "../../config/keybindings";
38
40
  export type { ExecOptions, ExecResult } from "../../exec/exec";
39
41
  export type { AgentToolResult, AgentToolUpdateCallback };
@@ -336,6 +338,8 @@ export interface ExtensionContext {
336
338
  getJobs(): unknown;
337
339
  /** Subscribe to foreground-wait folds (`bash_folded`). Returns an unsubscribe function. */
338
340
  onJobFold?(listener: (event: JobFoldEvent) => void): () => void;
341
+ /** Observe session events synchronously in producer order. Returns an unsubscribe function. */
342
+ onSessionEvent?(listener: AgentSessionEventListener): () => void;
339
343
  /** Typed skill and mode controls exposed to the SDK host. */
340
344
  invokeSkill?(name: string, args?: string, options?: {
341
345
  onPreflightAccepted?: () => void;
@@ -489,6 +493,8 @@ export type { AgentEndEvent, TurnEndEvent, TurnStartEvent } from "../shared-even
489
493
  /** Fired when an agent loop starts. `sdkRunToken` is an internal SDK queue-owner binding. */
490
494
  export interface AgentStartEvent extends SharedAgentStartEvent {
491
495
  sdkRunToken?: string;
496
+ /** Complete set of SDK queue owners consumed together by this run. */
497
+ sdkRunTokens?: string[];
492
498
  }
493
499
  /** Fired when an agent run fails before emitting agent_end. The error is the
494
500
  * sanitized `{ code, message }` diagnostic from the agent runtime — never the raw
@@ -796,6 +802,13 @@ export interface ExtensionAPI {
796
802
  on(event: "tool_result", handler: ExtensionHandler<ToolResultEvent, ToolResultEventResult>): void;
797
803
  on(event: "user_bash", handler: ExtensionHandler<UserBashEvent, UserBashEventResult>): void;
798
804
  on(event: "user_python", handler: ExtensionHandler<UserPythonEvent, UserPythonEventResult>): void;
805
+ /**
806
+ * Register capability-scoped middleware on the authoritative ExtensionRunner.
807
+ * The host supplies grants; an extension cannot self-grant capabilities.
808
+ * Wildcard registrations receive a redacted payload unless the host explicitly
809
+ * grants a tool inspection/transform capability.
810
+ */
811
+ registerFunctionHook<T extends FunctionHookEventType>(event: T, handler: FunctionHook<FunctionHookPayloadFor<T>>, options?: FunctionHookRegistrationOptions): void;
799
812
  /** Register a tool that the LLM can call. */
800
813
  registerTool<TParams extends TSchema = TSchema, TDetails = unknown>(tool: ToolDefinition<TParams, TDetails>): void;
801
814
  /** Register a custom command. */
@@ -1157,6 +1170,8 @@ export interface ExtensionContextActions {
1157
1170
  getJobs?: () => unknown;
1158
1171
  /** Subscribe to foreground-wait folds so the SDK host can publish `bash_folded`. Returns an unsubscribe. */
1159
1172
  onJobFold?: (listener: (event: JobFoldEvent) => void) => () => void;
1173
+ /** Ordered, synchronous AgentSession subscription, independent of async extension hooks. */
1174
+ onSessionEvent?: (listener: AgentSessionEventListener) => () => void;
1160
1175
  setSdkPermissionProvider?: (provider: ((toolCall: ClientBridgePermissionToolCall, options: ClientBridgePermissionOption[], signal?: AbortSignal) => Promise<ClientBridgePermissionOutcome>) | undefined) => void;
1161
1176
  setSdkClientBridge?: (bridge: ClientBridge | undefined) => void;
1162
1177
  sdkControl?: (operation: string, input: Record<string, unknown>) => unknown | Promise<unknown>;
@@ -1214,6 +1229,7 @@ export interface Extension {
1214
1229
  flags: Map<string, ExtensionFlag>;
1215
1230
  shortcuts: Map<KeyId, ExtensionShortcut>;
1216
1231
  }
1232
+ export type { FunctionHook, FunctionHookAuditRecord, FunctionHookCapabilities, FunctionHookCapability, FunctionHookEventType, FunctionHookGrant, FunctionHookGrantInput, FunctionHookNext, FunctionHookOperation, FunctionHookPayloadFor, FunctionHookProvenance, FunctionHookRegistration, FunctionHookRegistrationOptions, FunctionHookResult, } from "./function-hooks";
1217
1233
  /** Result of loading extensions. */
1218
1234
  export interface LoadExtensionsResult {
1219
1235
  extensions: Extension[];
@@ -2,7 +2,7 @@
2
2
  * Tool wrappers for extensions.
3
3
  */
4
4
  import type { AgentTool, AgentToolContext, AgentToolUpdateCallback } from "@gajae-code/agent-core";
5
- import type { Static, TSchema } from "@gajae-code/ai/core";
5
+ import { type Static, type TSchema } from "@gajae-code/ai/core";
6
6
  import type { ExtensionRunner } from "./runner";
7
7
  import type { RegisteredTool } from "./types";
8
8
  /**
@@ -44,6 +44,8 @@ export declare class ExtensionToolWrapper<TParameters extends TSchema = TSchema,
44
44
  label: string;
45
45
  strict: boolean;
46
46
  constructor(tool: AgentTool<TParameters, TDetails>, runner: ExtensionRunner);
47
+ /** Host composition hook: guards must run inside Function Hook preflight. */
48
+ getInnerTool(): AgentTool<TParameters, TDetails>;
47
49
  /**
48
50
  * Forward browser mode changes when available.
49
51
  */
@@ -1,3 +1,4 @@
1
+ import { type FunctionHookGrant } from "../extensions/function-hooks";
1
2
  import { type SessionQuarantine } from "./session-validation";
2
3
  import { type GjcPluginScope } from "./types";
3
4
  /**
@@ -11,10 +12,23 @@ import { type GjcPluginScope } from "./types";
11
12
  */
12
13
  export interface ConstrainedPluginHook {
13
14
  plugin: string;
15
+ scope?: GjcPluginScope;
16
+ extensionId?: string;
14
17
  event: string;
15
18
  target?: string;
16
19
  phase?: "before" | "after";
17
- handler: (...args: any[]) => unknown;
20
+ handler: (...args: never[]) => unknown;
21
+ grant?: FunctionHookGrant;
22
+ provenance?: {
23
+ source: "plugin-bundle";
24
+ scope: GjcPluginScope;
25
+ plugin: string;
26
+ path: string;
27
+ extensionId: string;
28
+ activationGeneration?: number;
29
+ };
30
+ functionHook?: boolean;
31
+ activationGeneration?: number;
18
32
  }
19
33
  export interface ConstrainedHookLoadResult {
20
34
  hooks: ConstrainedPluginHook[];
@@ -23,21 +37,39 @@ export interface ConstrainedHookLoadResult {
23
37
  export interface DeclaredHook {
24
38
  plugin: string;
25
39
  scope: GjcPluginScope;
40
+ extensionId?: string;
26
41
  event: string;
27
42
  target?: string;
28
43
  phase?: "before" | "after";
29
44
  relativePath: string;
30
45
  implementationHash?: string;
46
+ capabilities?: string[];
47
+ networkDestinations?: string[];
48
+ filesystemRoots?: string[];
49
+ capabilityHash?: string;
50
+ pluginRoot?: string;
51
+ functionHook?: boolean;
52
+ activationGeneration?: number;
31
53
  }
32
54
  /** Lazy declaration for one constrained hook. Importing this descriptor is metadata-only. */
33
55
  export declare class ConstrainedPluginHookDescriptor {
34
56
  readonly plugin: string;
35
- readonly scope: GjcPluginScope;
57
+ readonly scope?: GjcPluginScope;
58
+ readonly extensionId?: string;
36
59
  readonly event: string;
37
60
  readonly target?: string;
38
61
  readonly phase?: "before" | "after";
39
62
  readonly relativePath: string;
40
63
  readonly implementationHash?: string;
64
+ readonly capabilities?: string[];
65
+ readonly networkDestinations?: string[];
66
+ readonly filesystemRoots?: string[];
67
+ readonly capabilityHash?: string;
68
+ readonly pluginRoot?: string;
69
+ readonly grant: FunctionHookGrant;
70
+ readonly functionHook: boolean;
71
+ readonly activationGeneration?: number;
72
+ readonly persistedFunctionHook?: unknown;
41
73
  constructor(input: DeclaredHook);
42
74
  load(): Promise<ConstrainedPluginHook>;
43
75
  }
@@ -48,4 +80,5 @@ export declare class ConstrainedPluginHookDescriptor {
48
80
  */
49
81
  export declare function loadConstrainedPluginHooks(input: {
50
82
  cwd: string;
83
+ activationGeneration?: number;
51
84
  }): Promise<ConstrainedHookLoadResult>;
@@ -1,4 +1,5 @@
1
1
  import type { CanonicalGjcWorkflowSkill } from "../../skill-state/active-state";
2
+ import type { FunctionHookCapability } from "../extensions/function-hooks";
2
3
  export declare const GJC_PLUGIN_MANIFEST_FILENAME = "gajae-plugin.json";
3
4
  export declare const GJC_PLUGIN_KIND = "gajae-code-plugin";
4
5
  export declare const GJC_SUBSKILL_PARENT_SKILLS: readonly ["deep-interview", "ralplan", "ultragoal", "autoresearch"];
@@ -35,6 +36,10 @@ export interface GjcPluginHookManifestEntry {
35
36
  phase?: "before" | "after";
36
37
  path: string;
37
38
  sha256?: string;
39
+ /** Requested capability families; the runtime never grants more than declared. */
40
+ capabilities?: FunctionHookCapability[];
41
+ networkDestinations?: string[];
42
+ filesystemRoots?: string[];
38
43
  }
39
44
  export type GjcPluginMcpTransport = "stdio" | "http" | "sse";
40
45
  export interface GjcPluginMcpManifestEntry {
@@ -206,6 +211,11 @@ export interface NormalizedHookSurface {
206
211
  relativePath: string;
207
212
  sha256: string;
208
213
  implementationHash?: string;
214
+ capabilities?: FunctionHookCapability[];
215
+ networkDestinations?: string[];
216
+ filesystemRoots?: string[];
217
+ capabilityHash?: string;
218
+ functionHook?: boolean;
209
219
  }
210
220
  export interface NormalizedMcpSurface {
211
221
  extensionId: string;
@@ -406,6 +416,21 @@ export interface GjcRuntimeFinding {
406
416
  surfaceId: string;
407
417
  code: GjcPluginLoadErrorCode;
408
418
  message: string;
419
+ decision?: "loaded" | "quarantined" | "blocked" | "error";
420
+ event?: string;
421
+ phase?: "before" | "after";
422
+ requestedCapabilities?: readonly FunctionHookCapability[];
423
+ effectiveCapabilities?: readonly FunctionHookCapability[];
424
+ capabilityHash?: string;
425
+ provenance?: {
426
+ source: "builtin" | "user" | "project" | "extension" | "plugin-bundle";
427
+ scope?: "user" | "project" | "native";
428
+ plugin?: string;
429
+ path?: string;
430
+ extensionId?: string;
431
+ };
432
+ audit?: Record<string, unknown>;
433
+ generation?: number;
409
434
  }
410
435
  export interface GjcRuntimeSnapshot {
411
436
  /** Monotonic activation generation this snapshot describes. */
@@ -7,8 +7,11 @@ import type { Theme } from "../../modes/theme/theme";
7
7
  import type { HookMessage } from "../../session/messages";
8
8
  import type { ReadonlySessionManager, SessionManager } from "../../session/session-manager";
9
9
  import type { BashToolDetails, FindToolDetails, ReadToolDetails, SearchToolDetails } from "../../tools";
10
+ import type { FunctionHook, FunctionHookEventType, FunctionHookPayloadFor, FunctionHookRegistrationOptions } from "../extensions/function-hooks";
10
11
  import type { AgentEndEvent, AgentStartEvent, AutoCompactionEndEvent, AutoCompactionStartEvent, AutoRetryEndEvent, AutoRetryStartEvent, ContextEvent, SessionBeforeBranchEvent, SessionBeforeBranchResult, SessionBeforeCompactEvent, SessionBeforeCompactResult, SessionBeforeSwitchEvent, SessionBeforeSwitchResult, SessionBeforeTreeEvent, SessionBeforeTreeResult, SessionBranchEvent, SessionCompactEvent, SessionCompactingEvent, SessionCompactingResult, SessionEvent, SessionShutdownEvent, SessionStartEvent, SessionSwitchEvent, SessionTreeEvent, TodoReminderEvent, ToolCallEventResult, ToolResultEventResult, TtsrTriggeredEvent, TurnEndEvent, TurnStartEvent } from "../shared-events";
11
12
  export type { ExecOptions, ExecResult } from "../../exec/exec";
13
+ /** Capability-scoped Function Hooks share the ExtensionRunner event contract. */
14
+ export type { FunctionHook, FunctionHookAuditRecord, FunctionHookCapabilities, FunctionHookCapability, FunctionHookEventType, FunctionHookGrant, FunctionHookGrantInput, FunctionHookNext, FunctionHookOperation, FunctionHookPayloadFor, FunctionHookProvenance, FunctionHookRegistration, FunctionHookRegistrationOptions, FunctionHookResult, } from "../extensions/function-hooks";
12
15
  /**
13
16
  * UI context for hooks to request interactive UI from the harness.
14
17
  * Interactive and headless callers provide their own implementation.
@@ -340,6 +343,7 @@ export interface HookAPI {
340
343
  on(event: "todo_reminder", handler: HookHandler<TodoReminderEvent>): void;
341
344
  on(event: "tool_call", handler: HookHandler<ToolCallEvent, ToolCallEventResult>): void;
342
345
  on(event: "tool_result", handler: HookHandler<ToolResultEvent, ToolResultEventResult>): void;
346
+ registerFunctionHook<T extends FunctionHookEventType>(event: T, handler: FunctionHook<FunctionHookPayloadFor<T>>, options?: FunctionHookRegistrationOptions): void;
343
347
  /**
344
348
  * Send a custom message to the session. Creates a CustomMessageEntry that
345
349
  * participates in LLM context and can be displayed in the TUI.
@@ -24,6 +24,9 @@ export interface RuntimeSkillDiscoveryResult {
24
24
  export interface DiscoverRuntimeSkillsOptions {
25
25
  cwd: string;
26
26
  home?: string;
27
+ agentDir?: string;
28
+ /** Resolver-owned profile classification; unlike path comparison, this survives HOME refreshes. */
29
+ profileAuthority?: "default" | "custom";
27
30
  query?: string;
28
31
  limit?: number;
29
32
  source?: RuntimeSkillDiscoverySource | "all";
@@ -38,4 +41,4 @@ export interface DiscoverRuntimeSkillsOptions {
38
41
  */
39
42
  export declare function describeDisabledSkillScopes(source: RuntimeSkillDiscoverySource | "all", policy: SkillsSettings | undefined): string | undefined;
40
43
  export declare function discoverRuntimeSkills(options: DiscoverRuntimeSkillsOptions): Promise<RuntimeSkillDiscoveryResult>;
41
- export declare function findRuntimeSkillByName(cwd: string, name: string, policy?: SkillsSettings, home?: string): Promise<Skill | undefined>;
44
+ export declare function findRuntimeSkillByName(cwd: string, name: string, policy?: SkillsSettings, home?: string, agentDir?: string, profileAuthority?: "default" | "custom"): Promise<Skill | undefined>;
@@ -32,6 +32,7 @@ export interface ConventionSkillImportSource {
32
32
  export interface WriteNativeSkillInput {
33
33
  cwd: string;
34
34
  home?: string;
35
+ agentDir?: string;
35
36
  scope: SkillScope;
36
37
  name: string;
37
38
  content: string;
@@ -61,13 +62,14 @@ export declare function getProjectSkillDirs(cwd: string, home: string): Promise<
61
62
  repoRoot: string | null;
62
63
  }>;
63
64
  /** Canonical user skill directories in precedence order (same resolution as runtime discovery). */
64
- export declare function getUserSkillDirs(home: string): string[];
65
+ export declare function getUserSkillDirs(home: string, agentDir?: string, profileAuthority?: "default" | "custom"): string[];
65
66
  /**
66
67
  * The canonical directory a write targets for a scope: the repo root (or `cwd`)
67
- * `.gjc/skills` for project scope, the canonical `<config>/agent/skills` user
68
- * root for user scope (honoring `GJC_CONFIG_DIR` / `PI_CONFIG_DIR`).
68
+ * `.gjc/skills` for project scope, the agent directory's `skills` root for user
69
+ * scope — the same directory every reader scans first (`gjc config path` prints
70
+ * it; `--agent-dir` / `GJC_CODING_AGENT_DIR` / `setAgentDir()` move it).
69
71
  */
70
- export declare function resolveNativeSkillScopeDir(cwd: string, scope: SkillScope, home?: string): Promise<string>;
72
+ export declare function resolveNativeSkillScopeDir(cwd: string, scope: SkillScope, _home?: string, agentDir?: string): Promise<string>;
71
73
  /**
72
74
  * Authoritative discovery of native skills with provenance and enablement
73
75
  * state. Unlike runtime session discovery, this lists every scanned skill —
@@ -77,6 +79,9 @@ export declare function resolveNativeSkillScopeDir(cwd: string, scope: SkillScop
77
79
  export declare function listNativeSkillsForManagement(options: {
78
80
  cwd: string;
79
81
  home?: string;
82
+ agentDir?: string;
83
+ /** Resolver-owned profile classification; unlike path comparison, this survives HOME refreshes. */
84
+ profileAuthority?: "default" | "custom";
80
85
  policy?: SkillManagementPolicy;
81
86
  }): Promise<ManagedSkillRecord[]>;
82
87
  /**
@@ -57,6 +57,8 @@ export interface LoadSkillsOptions extends SkillsSettings {
57
57
  home?: string;
58
58
  /** Explicit user agent directory for native user-scope skill discovery. */
59
59
  agentDir?: string;
60
+ /** Resolver-owned classification for the selected agent directory. */
61
+ profileAuthority?: "default" | "custom";
60
62
  }
61
63
  /**
62
64
  * Load skills from all configured locations.
@@ -13,7 +13,7 @@ export interface EmptyDeleteIdentity {
13
13
  mtimeNs: bigint;
14
14
  parentDev: bigint;
15
15
  parentIno: bigint;
16
- sha256: string;
16
+ sha256?: string;
17
17
  }
18
18
  export interface EmptyDeleteGcRecord {
19
19
  root: string;
@@ -44,11 +44,14 @@ export interface EmptyDeleteGcReport {
44
44
  export interface EmptyDeleteGcOptions {
45
45
  roots: string[];
46
46
  prune: boolean;
47
+ /** Disk artifact GC must not remove unrelated file receipts. */
48
+ artifactRootsOnly?: boolean;
47
49
  }
48
50
  export interface EmptyDeleteGcDependencies {
49
51
  /** Internal seam for deterministic collect-to-prune race tests. */
50
52
  collect?: (root: string) => Promise<EmptyDeleteGcRecord[]>;
51
53
  exactUnlinkDirect?: typeof exactUnlinkDirect;
54
+ rmdir?: (directory: string) => Promise<void>;
52
55
  }
53
56
  export declare function collectEmptyDeleteReceipts(root: string, deps?: {
54
57
  lstat?: (file: string, options: {
@@ -26,6 +26,8 @@ export declare function parseLinuxProcStartTime(stat: string | null | undefined)
26
26
  export declare function parseLinuxProcTtyDevice(stat: string | null | undefined): string | null;
27
27
  /** Parse field 3 (single-letter process state) from a `/proc/<pid>/stat` record. */
28
28
  export declare function parseLinuxProcState(stat: string | null | undefined): string | null;
29
+ /** Parse field 4 (`ppid`) from a `/proc/<pid>/stat` record. */
30
+ export declare function parseLinuxProcParentPid(stat: string | null | undefined): number | null;
29
31
  export declare function probeLinuxProcPidSync(pid: number): LinuxProcPidProbeResult;
30
32
  export declare function probeLinuxProcPid(pid: number): Promise<LinuxProcPidProbeResult>;
31
33
  /**
@@ -170,4 +170,16 @@ export declare function reclaimStaleSessionStateLock(lockFile: string, quarantin
170
170
  * lock file itself and may run for as long as it needs.
171
171
  */
172
172
  export declare function withSessionStateFileLock<T>(stateFile: string, operation: () => Promise<T>): Promise<T>;
173
+ /**
174
+ * Try one admission without joining a live owner's queue or backing off on contention.
175
+ * A stale reclaim may return `acquired: false` after making the next attempt possible.
176
+ * Once admitted, the operation and identity-safe release use the normal lock protocol;
177
+ * their failures propagate rather than being reported as contention.
178
+ */
179
+ export declare function tryWithSessionStateFileLock<T>(stateFile: string, operation: () => Promise<T>): Promise<{
180
+ acquired: true;
181
+ value: T;
182
+ } | {
183
+ acquired: false;
184
+ }>;
173
185
  export {};
@@ -208,7 +208,36 @@ export declare function recordUltragoalNudgeIfBudgetRemaining(input: {
208
208
  reason: string;
209
209
  currentGoalObjective?: string;
210
210
  }): Promise<UltragoalNudgeOutcome>;
211
- export declare function writePlan(cwd: string, plan: UltragoalPlan, sessionId?: string | null): Promise<void>;
211
+ export declare function writePlan(cwd: string, plan: UltragoalPlan, sessionId?: string | null,
212
+ /** Set by callers already inside {@link withUltragoalPlanOwnership} for this plan. */
213
+ options?: {
214
+ lockHeld?: boolean;
215
+ }): Promise<void>;
216
+ /**
217
+ * The single exclusion that decides who owns an Ultragoal run (#5353).
218
+ *
219
+ * Establishing ownership is a read-decide-write sequence, not a write: a start
220
+ * reads the plan, checks the outgoing succession fence, then commits `active`.
221
+ * Checking quiescence at a point in time and writing afterwards is not enough —
222
+ * an offer can observe `pending` in the window between an in-flight start's
223
+ * check and its commit, and both runs then believe they own the goal.
224
+ *
225
+ * Every caller that decides ownership — source admission (`start`/`checkpoint`),
226
+ * succession offer/fence issuance, and successor publication — runs its whole
227
+ * decision inside this lock, keyed on the plan it is deciding about, and
228
+ * re-reads the plan under it. Writers inside pass `lockHeld` because
229
+ * `withFileLock` intentionally serializes same-process callers as well.
230
+ *
231
+ * Lock ordering: this lock is always taken BEFORE any ledger lock. The existing
232
+ * ledger-scoped critical sections (nudge budget, critic verdict, critic gate
233
+ * override) never write the plan, so no cycle exists.
234
+ */
235
+ export declare function withUltragoalPlanOwnership<T>(cwd: string, sessionId: string, fn: () => Promise<T>): Promise<T>;
236
+ /**
237
+ * Resolve the session whose plan ownership is being decided, without changing
238
+ * the resolution behaviour callers already depend on.
239
+ */
240
+ export declare function resolveUltragoalOwnershipSession(cwd: string, sessionId?: string | null): Promise<string>;
212
241
  export declare function nonEmptyString(value: unknown): string | null;
213
242
  export declare function stringArray(value: unknown): string[] | null;
214
243
  export declare function readUltragoalPlan(cwd: string, sessionId?: string | null): Promise<UltragoalPlan | null>;
@@ -324,13 +353,22 @@ export declare function validateUltragoalQualityGateReadOnly(input: {
324
353
  valid: boolean;
325
354
  errors: readonly UltragoalQualityGateDiagnostic[];
326
355
  }>;
327
- export declare function checkpointUltragoalGoal(input: {
356
+ export interface UltragoalCheckpointInput {
328
357
  cwd: string;
329
358
  goalId: string;
330
359
  status: UltragoalGoalStatus;
331
360
  evidence: string;
332
361
  qualityGateJson?: string;
333
- }): Promise<UltragoalPlan>;
362
+ }
363
+ /**
364
+ * Checkpointing shares its plan with a succession offer, but only its *commit*
365
+ * is fenced against one (#5353). Completion validation must observe the same
366
+ * repository basis `quality-gate source-hash` did, and the ownership lock's own
367
+ * on-disk artifact lives under `.gjc/` — a path repositories are not required to
368
+ * ignore — so capturing the basis while holding it would make the runtime digest
369
+ * disagree with the gate the caller was told to produce.
370
+ */
371
+ export declare function checkpointUltragoalGoal(input: UltragoalCheckpointInput): Promise<UltragoalPlan>;
334
372
  export interface UltragoalCheckpointContinuation {
335
373
  plan: UltragoalPlan;
336
374
  checkpointedGoal: UltragoalGoal;