@gajae-code/coding-agent 0.18.12 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +467 -0
- package/dist/types/capability/rule.d.ts +7 -2
- package/dist/types/cli/append-system-prompt.d.ts +6 -0
- package/dist/types/cli/args.d.ts +7 -2
- package/dist/types/cli/customize-doctor-precedence.d.ts +16 -0
- package/dist/types/cli/customize-doctor.d.ts +4 -3
- package/dist/types/cli/public-command-errors.d.ts +1 -0
- package/dist/types/cli/root-flags.d.ts +0 -12
- package/dist/types/cli/update-cli.d.ts +7 -2
- package/dist/types/cli-main.d.ts +0 -6
- package/dist/types/commands/launch.d.ts +0 -6
- package/dist/types/commands/migrate.d.ts +1 -1
- package/dist/types/commands/sdk.d.ts +8 -0
- package/dist/types/commit/map-reduce/index.d.ts +4 -4
- package/dist/types/config/autorouting-tier-map.d.ts +23 -1
- package/dist/types/config/config-hot-reload.d.ts +5 -0
- package/dist/types/config/file-lock.d.ts +44 -2
- package/dist/types/config/model-profile-activation.d.ts +19 -5
- package/dist/types/config/model-registry.d.ts +16 -3
- package/dist/types/config/model-resolver.d.ts +5 -4
- package/dist/types/config/settings-schema.d.ts +11 -1
- package/dist/types/coordinator-mcp/server.d.ts +4 -0
- package/dist/types/customization/import.d.ts +2 -0
- package/dist/types/customization/types.d.ts +1 -1
- package/dist/types/dap/session.d.ts +11 -2
- package/dist/types/discovery/helpers.d.ts +7 -2
- package/dist/types/edit/index.d.ts +5 -0
- package/dist/types/edit/modes/patch.d.ts +9 -0
- package/dist/types/eval/py/runtime.d.ts +9 -0
- package/dist/types/export/ttsr.d.ts +19 -0
- package/dist/types/extensibility/extensions/types.d.ts +5 -1
- package/dist/types/extensibility/slash-commands.d.ts +1 -0
- package/dist/types/gjc-runtime/ralplan-current-final.d.ts +54 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +24 -0
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +6 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
- package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
- package/dist/types/hindsight/content.d.ts +5 -6
- package/dist/types/internal-urls/types.d.ts +2 -0
- package/dist/types/lsp/clients/swiftlint-client.d.ts +0 -4
- package/dist/types/main.d.ts +23 -18
- package/dist/types/migrate/action-planner.d.ts +10 -1
- package/dist/types/migrate/adapters/codex.d.ts +1 -1
- package/dist/types/migrate/adapters/index.d.ts +35 -3
- package/dist/types/migrate/hook-module.d.ts +23 -0
- package/dist/types/migrate/report.d.ts +2 -1
- package/dist/types/migrate/types.d.ts +69 -2
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +43 -0
- package/dist/types/modes/prompt-suggestion-controller.d.ts +1 -1
- package/dist/types/modes/utils/host-status.d.ts +15 -11
- package/dist/types/runtime-mcp/project-host-values.d.ts +11 -5
- package/dist/types/sdk/broker/broker-exit.d.ts +1 -1
- package/dist/types/sdk/broker/broker.d.ts +22 -1
- package/dist/types/sdk/broker/ensure.d.ts +5 -2
- package/dist/types/sdk/broker/hop.d.ts +9 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +22 -0
- package/dist/types/sdk/broker/session-index.d.ts +2 -0
- package/dist/types/sdk/broker/transport.d.ts +2 -0
- package/dist/types/sdk/bus/index.d.ts +21 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +7 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +2 -0
- package/dist/types/sdk/bus/threaded-render.d.ts +2 -1
- package/dist/types/sdk/host/control/operations.d.ts +5 -1
- package/dist/types/sdk/host/events.d.ts +4 -0
- package/dist/types/sdk/host/host.d.ts +2 -1
- package/dist/types/sdk/host/prompt-image-upload.d.ts +43 -0
- package/dist/types/sdk/host/session-runtime.d.ts +8 -8
- package/dist/types/sdk/host/surface-policy.d.ts +2 -1
- package/dist/types/sdk/lifecycle/service.d.ts +12 -0
- package/dist/types/sdk/prompt-status.d.ts +11 -4
- package/dist/types/session/agent-session.d.ts +50 -8
- package/dist/types/session/session-manager.d.ts +16 -0
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +13 -1
- package/dist/types/slash-commands/helpers/mcp.d.ts +5 -0
- package/dist/types/ssh/ssh-executor.d.ts +8 -1
- package/dist/types/system-prompt.d.ts +3 -2
- package/dist/types/task/role-body.d.ts +11 -0
- package/dist/types/tools/awaiting-input.d.ts +28 -0
- package/dist/types/tools/bash-allowed-prefixes.d.ts +6 -0
- package/dist/types/tools/bash-skill-urls.d.ts +4 -0
- package/dist/types/tools/bash.d.ts +7 -0
- package/dist/types/tools/descriptors.d.ts +13 -2
- package/dist/types/tools/fetch.d.ts +6 -0
- package/dist/types/tools/irc.d.ts +5 -3
- package/dist/types/tools/tmux-self-injection-guard.d.ts +2 -0
- package/dist/types/tools/ultragoal-ask-guard.d.ts +1 -1
- package/dist/types/tools/write.d.ts +2 -0
- package/dist/types/utils/file-mentions.d.ts +5 -0
- package/dist/types/utils/image-limits.d.ts +7 -0
- package/dist/types/utils/image-loading.d.ts +0 -1
- package/dist/types/utils/open.d.ts +0 -1
- package/dist/types/utils/pasted-image-loading.d.ts +1 -5
- package/dist/types/utils/prompt-suggestion.d.ts +2 -2
- package/dist/types/utils/shell-snapshot.d.ts +2 -0
- package/dist/types/utils/title-generator.d.ts +13 -3
- package/dist/types/web/search/providers/codex.d.ts +6 -7
- package/package.json +9 -8
- package/scripts/acp-conformance-agent.ts +12 -2
- package/scripts/generate-sdk-operation-inventory.ts +16 -0
- package/src/capability/fs.ts +31 -3
- package/src/capability/rule.ts +11 -2
- package/src/cli/append-system-prompt.ts +12 -0
- package/src/cli/args.ts +11 -7
- package/src/cli/customize-doctor-precedence.ts +31 -0
- package/src/cli/customize-doctor.ts +49 -39
- package/src/cli/fast-help.ts +0 -2
- package/src/cli/migrate-cli.ts +14 -3
- package/src/cli/public-command-errors.ts +2 -0
- package/src/cli/root-flags.ts +0 -2
- package/src/cli/update-cli.ts +247 -6
- package/src/commands/harness.ts +25 -15
- package/src/commands/migrate.ts +3 -3
- package/src/commands/sdk.ts +81 -11
- package/src/commit/agentic/agent.ts +6 -6
- package/src/commit/analysis/conventional.ts +14 -5
- package/src/commit/map-reduce/index.ts +7 -7
- package/src/commit/pipeline.ts +12 -12
- package/src/config/autorouting-tier-map.ts +20 -1
- package/src/config/config-file.ts +106 -3
- package/src/config/config-hot-reload.ts +8 -0
- package/src/config/file-lock.ts +1431 -304
- package/src/config/keybindings.ts +154 -7
- package/src/config/model-profile-activation.ts +177 -39
- package/src/config/model-registry.ts +380 -55
- package/src/config/model-resolver.ts +49 -21
- package/src/config/settings-schema.ts +13 -1
- package/src/config/settings.ts +2 -0
- package/src/coordinator-mcp/server.ts +37 -2
- package/src/crash/sanitize.ts +3 -1
- package/src/customization/import.ts +276 -7
- package/src/customization/inventory.ts +24 -8
- package/src/customization/types.ts +1 -0
- package/src/dap/client.ts +3 -2
- package/src/dap/session.ts +161 -36
- package/src/debug/crash-diagnostics.ts +87 -5
- package/src/debug/report-bundle.ts +71 -2
- package/src/discovery/builtin.ts +4 -3
- package/src/discovery/helpers.ts +24 -14
- package/src/edit/index.ts +191 -5
- package/src/edit/modes/patch.ts +27 -0
- package/src/eval/py/runtime.ts +44 -4
- package/src/exec/non-interactive-env.ts +0 -1
- package/src/export/html/index.ts +60 -20
- package/src/export/ttsr.ts +176 -1
- package/src/extensibility/extensions/loader.ts +2 -0
- package/src/extensibility/extensions/ouroboros-ooo-bridge.ts +63 -1
- package/src/extensibility/extensions/types.ts +5 -1
- package/src/extensibility/hooks/loader.ts +10 -2
- package/src/extensibility/plugins/marketplace/manager.ts +36 -10
- package/src/extensibility/slash-commands.ts +5 -0
- package/src/gjc-runtime/gc-runtime.ts +4 -1
- package/src/gjc-runtime/launch-tmux.ts +23 -13
- package/src/gjc-runtime/ralplan-current-final.ts +294 -0
- package/src/gjc-runtime/ralplan-runtime.ts +95 -1
- package/src/gjc-runtime/state-writer.ts +109 -5
- package/src/gjc-runtime/tmux-sessions.ts +93 -13
- package/src/gjc-runtime/ultragoal-change-set.ts +90 -11
- package/src/gjc-runtime/ultragoal-guard.ts +9 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +15 -5
- package/src/harness-control-plane/finalize.ts +11 -0
- package/src/harness-control-plane/receipt-spool.ts +105 -28
- package/src/harness-control-plane/storage.ts +124 -6
- package/src/hindsight/content.ts +116 -16
- package/src/hindsight/mental-models.ts +22 -10
- package/src/hindsight/state.ts +7 -4
- package/src/hooks/native-skill-hook.ts +3 -1
- package/src/internal-urls/artifact-protocol.ts +3 -1
- package/src/internal-urls/docs-index.generated.ts +14 -14
- package/src/internal-urls/local-protocol.ts +28 -3
- package/src/internal-urls/types.ts +2 -0
- package/src/lsp/client.ts +2 -1
- package/src/lsp/clients/biome-client.ts +2 -0
- package/src/lsp/clients/swiftlint-client.ts +2 -0
- package/src/main.ts +330 -92
- package/src/memories/index.ts +25 -2
- package/src/migrate/action-planner.ts +517 -2
- package/src/migrate/adapters/claude-code.ts +141 -3
- package/src/migrate/adapters/codex.ts +57 -5
- package/src/migrate/adapters/index.ts +240 -5
- package/src/migrate/adapters/opencode.ts +4 -0
- package/src/migrate/executor.ts +141 -3
- package/src/migrate/hook-module.ts +193 -0
- package/src/migrate/report.ts +45 -1
- package/src/migrate/types.ts +73 -3
- package/src/modes/acp/acp-agent.ts +10 -1
- package/src/modes/components/agent-dashboard.ts +20 -4
- package/src/modes/components/customization/customization-dashboard.ts +7 -0
- package/src/modes/components/customization/import-wizard.ts +29 -3
- package/src/modes/components/model-selector.ts +157 -103
- package/src/modes/components/welcome.ts +3 -1
- package/src/modes/controllers/command-controller.ts +271 -16
- package/src/modes/controllers/event-controller.ts +1 -1
- package/src/modes/controllers/extension-ui-controller.ts +31 -1
- package/src/modes/controllers/goal-mode-controller.ts +79 -10
- package/src/modes/controllers/input-controller.ts +2 -0
- package/src/modes/controllers/plan-mode-controller.ts +49 -4
- package/src/modes/controllers/runtime-mcp-command-controller.ts +7 -6
- package/src/modes/controllers/selector-controller.ts +14 -1
- package/src/modes/interactive-mode.ts +55 -4
- package/src/modes/prompt-suggestion-controller.ts +1 -1
- package/src/modes/runtime-init.ts +5 -1
- package/src/modes/utils/host-status.ts +21 -10
- package/src/prompts/agent-fragments/browser-aside.md +2 -2
- package/src/prompts/system/irc-incoming.md +3 -1
- package/src/prompts/tools/irc.md +1 -1
- package/src/runtime-mcp/manager.ts +8 -3
- package/src/runtime-mcp/project-host-values.ts +12 -8
- package/src/runtime-mcp/tool-bridge.ts +68 -4
- package/src/runtime-mcp/transports/stdio.ts +2 -1
- package/src/sdk/broker/broker-exit.ts +2 -0
- package/src/sdk/broker/broker.ts +143 -4
- package/src/sdk/broker/ensure.ts +74 -6
- package/src/sdk/broker/hop.ts +13 -1
- package/src/sdk/broker/lifecycle-ledger.ts +3 -0
- package/src/sdk/broker/lifecycle.ts +102 -6
- package/src/sdk/broker/session-index.ts +29 -4
- package/src/sdk/broker/transport.ts +17 -1
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/index.ts +408 -14
- package/src/sdk/bus/session-control.ts +2 -0
- package/src/sdk/bus/slack-daemon.ts +105 -9
- package/src/sdk/bus/telegram-daemon-contract.ts +7 -1
- package/src/sdk/bus/telegram-daemon.ts +10 -2
- package/src/sdk/bus/threaded-render.ts +20 -1
- package/src/sdk/cli/session-cli.ts +2 -0
- package/src/sdk/host/control/dispatch.ts +13 -1
- package/src/sdk/host/control/operations.ts +10 -1
- package/src/sdk/host/events.ts +67 -4
- package/src/sdk/host/host.ts +8 -2
- package/src/sdk/host/prompt-image-upload.ts +438 -0
- package/src/sdk/host/sdk-surface-parity.test.ts +15 -0
- package/src/sdk/host/session-runtime.test.ts +1537 -24
- package/src/sdk/host/session-runtime.ts +332 -36
- package/src/sdk/host/surface-policy.ts +4 -0
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +90 -2
- package/src/sdk/host/websocket-transport.ts +19 -7
- package/src/sdk/lifecycle/service.ts +14 -1
- package/src/sdk/prompt-status.ts +6 -4
- package/src/sdk/protocol/adapter-validation.ts +28 -1
- package/src/sdk/protocol/operation-inventory.generated.json +160 -0
- package/src/sdk/protocol/operation-registry.ts +33 -3
- package/src/sdk/session.ts +123 -36
- package/src/session/agent-session.ts +1614 -329
- package/src/session/history-storage.ts +182 -12
- package/src/session/internal/managed-session-scope.ts +47 -18
- package/src/session/internal/managed-session-storage.ts +71 -1
- package/src/session/session-manager.ts +90 -5
- package/src/session-import/redact.ts +53 -2
- package/src/skill-state/workflow-mutation-guard.ts +1498 -18
- package/src/slash-commands/builtin-registry.ts +6 -3
- package/src/slash-commands/helpers/mcp.ts +11 -3
- package/src/ssh/ssh-executor.ts +9 -2
- package/src/stt/recorder.ts +26 -9
- package/src/system-prompt.ts +61 -16
- package/src/task/executor.ts +12 -8
- package/src/task/role-body.ts +84 -0
- package/src/task/token-log-mode.test.ts +162 -0
- package/src/task/token-log.ts +91 -2
- package/src/tools/archive-reader.ts +650 -37
- package/src/tools/ask.ts +1 -0
- package/src/tools/ast-grep.ts +7 -2
- package/src/tools/auto-generated-guard.ts +12 -3
- package/src/tools/awaiting-input.ts +114 -0
- package/src/tools/bash-allowed-prefixes.ts +61 -1
- package/src/tools/bash-skill-urls.ts +58 -5
- package/src/tools/bash.ts +99 -26
- package/src/tools/browser/tab-worker.ts +39 -13
- package/src/tools/browser.ts +17 -7
- package/src/tools/cron.ts +10 -1
- package/src/tools/debug.ts +9 -2
- package/src/tools/descriptors.test.ts +4 -4
- package/src/tools/descriptors.ts +16 -4
- package/src/tools/eval.ts +15 -0
- package/src/tools/fetch.ts +90 -2
- package/src/tools/gh.ts +27 -12
- package/src/tools/image-gen.ts +20 -6
- package/src/tools/irc.ts +5 -3
- package/src/tools/monitor.ts +9 -1
- package/src/tools/output-meta.ts +51 -3
- package/src/tools/read.ts +9 -2
- package/src/tools/recipe/runner.ts +23 -12
- package/src/tools/render-utils.ts +2 -2
- package/src/tools/search.ts +3 -2
- package/src/tools/ssh.ts +274 -8
- package/src/tools/subagent.ts +10 -4
- package/src/tools/tmux-self-injection-guard.ts +3301 -122
- package/src/tools/tool-catalog.generated.ts +1 -1
- package/src/tools/ultragoal-ask-guard.ts +13 -1
- package/src/tools/write.ts +7 -0
- package/src/tui/tree-list.ts +15 -1
- package/src/utils/commit-message-generator.ts +3 -2
- package/src/utils/external-editor.ts +21 -7
- package/src/utils/file-mentions.ts +46 -6
- package/src/utils/git.ts +38 -7
- package/src/utils/image-limits.ts +8 -0
- package/src/utils/image-loading.ts +1 -1
- package/src/utils/open.ts +73 -4
- package/src/utils/pasted-image-loading.ts +9 -8
- package/src/utils/prompt-suggestion.ts +5 -4
- package/src/utils/shell-snapshot.ts +9 -1
- package/src/utils/title-generator.ts +65 -20
- package/src/web/search/index.ts +2 -1
- package/src/web/search/providers/codex.ts +29 -32
|
@@ -102,21 +102,31 @@ server = Bun.serve({
|
|
|
102
102
|
if (prompt.includes("sleep")) {
|
|
103
103
|
const requested = Number(/\bsleep\s+(\d+)/.exec(prompt)?.[1] ?? 0);
|
|
104
104
|
const delay = Math.min(Math.max(requested, 0), 30_000);
|
|
105
|
+
let closed = false;
|
|
106
|
+
let close = (): void => {};
|
|
105
107
|
const stream = new ReadableStream<Uint8Array>({
|
|
106
108
|
start(controller) {
|
|
107
|
-
|
|
108
|
-
const close = () => {
|
|
109
|
+
close = () => {
|
|
109
110
|
if (closed) return;
|
|
110
111
|
closed = true;
|
|
112
|
+
request.signal.removeEventListener("abort", close);
|
|
111
113
|
controller.close();
|
|
112
114
|
};
|
|
113
115
|
request.signal.addEventListener("abort", close, { once: true });
|
|
116
|
+
// The body parse above may yield long enough for the client to abort before
|
|
117
|
+
// this response stream installs its listener. Signals do not replay abort
|
|
118
|
+
// events to late listeners, so close immediately when that already happened.
|
|
119
|
+
if (request.signal.aborted) close();
|
|
114
120
|
void Bun.sleep(delay).then(() => {
|
|
115
121
|
if (closed) return;
|
|
116
122
|
controller.enqueue(new TextEncoder().encode(textCompletion("slept")));
|
|
117
123
|
close();
|
|
118
124
|
});
|
|
119
125
|
},
|
|
126
|
+
cancel() {
|
|
127
|
+
closed = true;
|
|
128
|
+
request.signal.removeEventListener("abort", close);
|
|
129
|
+
},
|
|
120
130
|
});
|
|
121
131
|
return new Response(stream, { headers: { "content-type": "text/event-stream" } });
|
|
122
132
|
}
|
|
@@ -27,6 +27,10 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
27
27
|
"internal read-only run-resource-ledger view, threaded via terminalAbortSeams so the prompt deadline can find a tool-call boundary; not a user-facing SDK control seam",
|
|
28
28
|
"agent_session:markProfileRoleOverrideManual":
|
|
29
29
|
"internal profile role-layer ownership tracking after explicit user assignments; not a user-facing SDK control seam",
|
|
30
|
+
"agent_session:notifySessionIdentityChanged":
|
|
31
|
+
"internal session-identity listener fan-out for in-process session surfaces; not a user-facing SDK control seam",
|
|
32
|
+
"agent_session:subscribeSessionIdentityChanges":
|
|
33
|
+
"internal session-identity subscription used by in-process adapters to follow session replacement; not a user-facing SDK control seam",
|
|
30
34
|
"slash_command:routing":
|
|
31
35
|
"visual/local-only autorouting settings toggle and smart-routing panel entry, not a user-facing SDK control seam",
|
|
32
36
|
"slash_command:mcp":
|
|
@@ -85,6 +89,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
85
89
|
"internal session-scoped startup-profile recovery marker, not a user-facing SDK control seam",
|
|
86
90
|
"agent_session:getUnavailableModelProfile":
|
|
87
91
|
"internal session-scoped startup-profile recovery status for UI rendering, not a public SDK operation",
|
|
92
|
+
"agent_session:getActivatedModelProfile":
|
|
93
|
+
"internal model-profile activation provenance used to gate role-only materialization, not a user-facing SDK control seam",
|
|
88
94
|
"agent_session:getConfigurationPaths":
|
|
89
95
|
"internal config hot-reload path identity projection, not a user-facing SDK control seam",
|
|
90
96
|
"agent_session:validateConfiguration":
|
|
@@ -121,6 +127,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
121
127
|
"internal tool-selection predicate used to preserve the --no-tools boundary, not a user-facing SDK control seam",
|
|
122
128
|
"agent_session:getEffectiveActiveWorkflowSkillState":
|
|
123
129
|
"internal restored-or-live workflow guard for session rescope, not a user-facing SDK control seam",
|
|
130
|
+
"agent_session:refreshEffectiveActiveWorkflowSkillState":
|
|
131
|
+
"internal durable workflow identity refresh before session safety checks, not an independent public SDK operation",
|
|
124
132
|
"agent_session:replaceOwnedMcpManager":
|
|
125
133
|
"internal cwd-rebinding helper for owned MCP authority after move_session, not a user-facing SDK control seam",
|
|
126
134
|
"agent_session:replaceNamedCustomTools":
|
|
@@ -159,6 +167,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
159
167
|
"test-only parked terminal persistence seam, not a user-facing SDK control seam",
|
|
160
168
|
"agent_session:flushParkedAgentEndForCoordinatorPersistForTests":
|
|
161
169
|
"test-only parked terminal flush seam, not a user-facing SDK control seam",
|
|
170
|
+
"agent_session:waitForAgentEndHandlingForTests":
|
|
171
|
+
"test-only SDK terminal-event handler completion barrier, not a user-facing SDK control seam",
|
|
162
172
|
"agent_session:setCancelAndSubmitAbortOutcomeProviderForTests":
|
|
163
173
|
"test-only cancellation seam, not a user-facing SDK control seam",
|
|
164
174
|
"agent_session:awaitDisposeCompletion": "test-only disposal completion seam, not a user-facing SDK control seam",
|
|
@@ -193,6 +203,12 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
193
203
|
"agent_session:onJobFold": "internal fold-event plumbing feeding the bash_folded event frame, not a control seam",
|
|
194
204
|
|
|
195
205
|
"agent_session:getSelectedMCPToolNames": "internal accessor/plumbing, not a user-facing control seam",
|
|
206
|
+
"agent_session:getActiveMCPToolNames":
|
|
207
|
+
"internal MCP bridge subset used by mode controllers to preserve live selections across tool swaps; not a user-facing SDK control seam",
|
|
208
|
+
"agent_session:hasMCPToolSelectionAuthority":
|
|
209
|
+
"internal MCP-selection authority predicate used by catalog and mode-transition reconciliation; not a user-facing SDK control seam",
|
|
210
|
+
"agent_session:hasCommittedMCPToolSelectionAuthority":
|
|
211
|
+
"internal committed MCP-selection authority predicate used by catalog reconciliation; not a user-facing SDK control seam",
|
|
196
212
|
"agent_session:isToolDiscoveryEnabled": "internal accessor/plumbing, not a user-facing control seam",
|
|
197
213
|
"agent_session:getDiscoverableToolSearchIndex": "internal accessor/plumbing, not a user-facing control seam",
|
|
198
214
|
"agent_session:getSelectedDiscoveredToolNames": "internal accessor/plumbing, not a user-facing control seam",
|
package/src/capability/fs.ts
CHANGED
|
@@ -241,6 +241,28 @@ async function openIsolatedFile(abs: string, options?: ReadFileOptions): Promise
|
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
+
/**
|
|
245
|
+
* A lexical path outside the boundary keeps the historical ancestor read.
|
|
246
|
+
* A path inside the boundary must still be inside after realpath, so a
|
|
247
|
+
* repository symlink cannot be opened as its external target.
|
|
248
|
+
*/
|
|
249
|
+
async function containedReadPath(abs: string, options?: ReadFileOptions): Promise<string | null> {
|
|
250
|
+
const root = options?.containmentRoot;
|
|
251
|
+
if (!root || options?.isolatedHome) return abs;
|
|
252
|
+
const lexical = path.resolve(abs);
|
|
253
|
+
const boundary = path.resolve(root);
|
|
254
|
+
if (!isWithinOrEqual(boundary, lexical)) return lexical;
|
|
255
|
+
try {
|
|
256
|
+
const [boundaryReal, targetReal] = await Promise.all([
|
|
257
|
+
fs.promises.realpath(boundary),
|
|
258
|
+
fs.promises.realpath(lexical),
|
|
259
|
+
]);
|
|
260
|
+
return isWithinOrEqual(boundaryReal, targetReal) ? targetReal : null;
|
|
261
|
+
} catch {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
244
266
|
export async function readFile(filePath: string, options?: ReadFileOptions): Promise<string | null> {
|
|
245
267
|
let abs: string | null;
|
|
246
268
|
try {
|
|
@@ -250,13 +272,19 @@ export async function readFile(filePath: string, options?: ReadFileOptions): Pro
|
|
|
250
272
|
}
|
|
251
273
|
if (abs === null) return null;
|
|
252
274
|
if (!(await isCurrentIsolatedPath(abs, options))) return null;
|
|
253
|
-
|
|
275
|
+
// A contained read must not share the lexical cache with a different boundary.
|
|
276
|
+
const useCache = !options?.bypassCache && !options?.isolatedHome && !options?.containmentRoot;
|
|
254
277
|
if (useCache && contentCache.has(abs)) {
|
|
255
278
|
return contentCache.get(abs) ?? null;
|
|
256
279
|
}
|
|
257
280
|
if (!options?.isolatedHome) {
|
|
281
|
+
const readable = await containedReadPath(abs, options);
|
|
282
|
+
if (readable === null) {
|
|
283
|
+
if (useCache) contentCache.set(abs, null);
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
258
286
|
try {
|
|
259
|
-
const content = await Bun.file(
|
|
287
|
+
const content = await Bun.file(readable).text();
|
|
260
288
|
if (useCache) contentCache.set(abs, content);
|
|
261
289
|
return content;
|
|
262
290
|
} catch {
|
|
@@ -460,7 +488,7 @@ export async function findRepoRoot(
|
|
|
460
488
|
let current = resolvePath(startDir);
|
|
461
489
|
const stop = stopAt ? resolvePath(stopAt) : undefined;
|
|
462
490
|
while (true) {
|
|
463
|
-
const entries = await readDirEntries(current, options);
|
|
491
|
+
const entries = await readDirEntries(current, { ...options, bypassCache: true });
|
|
464
492
|
if (entries.some(e => e.name === ".git")) {
|
|
465
493
|
return current;
|
|
466
494
|
}
|
package/src/capability/rule.ts
CHANGED
|
@@ -18,6 +18,8 @@ export interface RuleFrontmatter {
|
|
|
18
18
|
alwaysApply?: boolean;
|
|
19
19
|
/** New key for TTSR match conditions. */
|
|
20
20
|
condition?: string | string[];
|
|
21
|
+
/** AST-grep pattern(s) for TTSR AST matching (evaluated on completed tool args). */
|
|
22
|
+
astCondition?: string | string[];
|
|
21
23
|
/** New key for TTSR stream scope. */
|
|
22
24
|
scope?: string | string[];
|
|
23
25
|
/** Per-rule TTSR interrupt mode override. */
|
|
@@ -48,6 +50,8 @@ export interface Rule {
|
|
|
48
50
|
description?: string;
|
|
49
51
|
/** Regex condition(s) that can trigger TTSR interruption. */
|
|
50
52
|
condition?: string[];
|
|
53
|
+
/** AST-grep pattern(s) for TTSR AST matching (evaluated on completed tool args). */
|
|
54
|
+
astCondition?: string[];
|
|
51
55
|
/** Optional stream scope tokens (for example: text, thinking, tool:edit(*.ts)). */
|
|
52
56
|
scope?: string[];
|
|
53
57
|
/** Per-rule TTSR interrupt mode override (falls back to global ttsr.interruptMode). */
|
|
@@ -182,17 +186,21 @@ function isLikelyFileGlob(value: string): boolean {
|
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
/**
|
|
185
|
-
* Parse `condition`
|
|
189
|
+
* Parse `condition`, `astCondition`, and `scope` from rule frontmatter.
|
|
186
190
|
*
|
|
187
191
|
* - `condition` accepts string or string[]
|
|
192
|
+
* - `astCondition` accepts string or string[] (ast-grep patterns)
|
|
188
193
|
* - `scope` accepts string or string[]
|
|
189
194
|
* - legacy `ttsr_trigger` / `ttsrTrigger` are accepted as a `condition` fallback
|
|
190
195
|
* - condition tokens that look like file globs become scope shorthands:
|
|
191
196
|
* `*.rs` => `tool:edit(*.rs)`, `tool:write(*.rs)` and a catch-all condition `.*`
|
|
192
197
|
*/
|
|
193
|
-
export function parseRuleConditionAndScope(
|
|
198
|
+
export function parseRuleConditionAndScope(
|
|
199
|
+
frontmatter: RuleFrontmatter,
|
|
200
|
+
): Pick<Rule, "condition" | "astCondition" | "scope"> {
|
|
194
201
|
const rawCondition = frontmatter.condition ?? frontmatter.ttsr_trigger ?? frontmatter.ttsrTrigger;
|
|
195
202
|
const parsedCondition = normalizeRuleField(rawCondition);
|
|
203
|
+
const parsedAstCondition = normalizeRuleField(frontmatter.astCondition);
|
|
196
204
|
const parsedScope = normalizeScopeField(frontmatter.scope);
|
|
197
205
|
|
|
198
206
|
const inferredScope: string[] = [];
|
|
@@ -214,6 +222,7 @@ export function parseRuleConditionAndScope(frontmatter: RuleFrontmatter): Pick<R
|
|
|
214
222
|
const scope = [...(parsedScope ?? []), ...inferredScope];
|
|
215
223
|
return {
|
|
216
224
|
condition: condition.length > 0 ? Array.from(new Set(condition)) : undefined,
|
|
225
|
+
astCondition: parsedAstCondition ? Array.from(new Set(parsedAstCondition)) : undefined,
|
|
217
226
|
scope: scope.length > 0 ? Array.from(new Set(scope)) : undefined,
|
|
218
227
|
};
|
|
219
228
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface AppendSystemPromptCandidate {
|
|
2
|
+
level: "user" | "project";
|
|
3
|
+
path: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** First user file. A repository copy is untrusted project text and is never selected. */
|
|
7
|
+
export function selectAppendSystemPromptFile(candidates: readonly AppendSystemPromptCandidate[]): string | undefined {
|
|
8
|
+
for (const candidate of candidates) {
|
|
9
|
+
if (candidate.level === "user") return candidate.path;
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
package/src/cli/args.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { ThinkingLevel } from "@gajae-code/agent-core";
|
|
6
|
-
import { logger } from "@gajae-code/utils";
|
|
6
|
+
import { $pickenv, logger } from "@gajae-code/utils";
|
|
7
7
|
import { CliParseError } from "@gajae-code/utils/cli";
|
|
8
8
|
import { parseThinkingLevel } from "../thinking";
|
|
9
9
|
import { BUILTIN_TOOLS } from "../tools";
|
|
@@ -46,8 +46,6 @@ export interface Args {
|
|
|
46
46
|
allowHome?: boolean;
|
|
47
47
|
provider?: string;
|
|
48
48
|
model?: string;
|
|
49
|
-
smol?: string;
|
|
50
|
-
slow?: string;
|
|
51
49
|
plan?: string;
|
|
52
50
|
mpreset?: string;
|
|
53
51
|
default?: boolean;
|
|
@@ -228,10 +226,6 @@ export function parseArgs(args: string[], authority: ParseArgsAuthority = "local
|
|
|
228
226
|
result.provider = takeFlagValue(args, i++, "--provider");
|
|
229
227
|
} else if (arg === "--model") {
|
|
230
228
|
result.model = takeFlagValue(args, i++, "--model");
|
|
231
|
-
} else if (arg === "--smol") {
|
|
232
|
-
result.smol = takeFlagValue(args, i++, "--smol");
|
|
233
|
-
} else if (arg === "--slow") {
|
|
234
|
-
result.slow = takeFlagValue(args, i++, "--slow");
|
|
235
229
|
} else if (arg === "--plan") {
|
|
236
230
|
result.plan = takeFlagValue(args, i++, "--plan");
|
|
237
231
|
} else if (arg === "--mpreset") {
|
|
@@ -427,3 +421,13 @@ export function assertLocalLaunchArgs(parsed: Args): void {
|
|
|
427
421
|
if (!launchFlagIsOwnedBy(name, "local")) throw new CliParseError(`Unknown option: ${token}`);
|
|
428
422
|
}
|
|
429
423
|
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Resolve the ephemeral `plan` model-role override that plan mode switches to.
|
|
427
|
+
*
|
|
428
|
+
* Precedence is CLI `--plan` > `GJC_PLAN_MODEL` > legacy `PI_PLAN_MODEL`.
|
|
429
|
+
* `$pickenv` trims values and treats empty/whitespace as unset.
|
|
430
|
+
*/
|
|
431
|
+
export function resolvePlanModelOverride(parsed: Pick<Args, "plan">): string | undefined {
|
|
432
|
+
return parsed.plan ?? $pickenv("GJC_PLAN_MODEL", "PI_PLAN_MODEL");
|
|
433
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface DiscoveryPrecedenceCandidate {
|
|
2
|
+
key: string | undefined;
|
|
3
|
+
provider: string;
|
|
4
|
+
scope: "user" | "project" | "native";
|
|
5
|
+
eligible: boolean;
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface DiscoveryPrecedenceResult {
|
|
10
|
+
shadowed: boolean;
|
|
11
|
+
shadowedBy?: { provider: string; scope: DiscoveryPrecedenceCandidate["scope"] };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Resolve ordered discovery candidates without allowing ineligible or disabled entries to own keys. */
|
|
15
|
+
export function resolveDiscoveryPrecedence(
|
|
16
|
+
candidates: readonly DiscoveryPrecedenceCandidate[],
|
|
17
|
+
): DiscoveryPrecedenceResult[] {
|
|
18
|
+
const winners = new Map<string, { provider: string; scope: DiscoveryPrecedenceCandidate["scope"] }>();
|
|
19
|
+
|
|
20
|
+
return candidates.map(candidate => {
|
|
21
|
+
if (!candidate.eligible || candidate.key === undefined) return { shadowed: false };
|
|
22
|
+
|
|
23
|
+
const winner = winners.get(candidate.key);
|
|
24
|
+
if (winner) return { shadowed: true, shadowedBy: winner };
|
|
25
|
+
|
|
26
|
+
if (candidate.enabled) {
|
|
27
|
+
winners.set(candidate.key, { provider: candidate.provider, scope: candidate.scope });
|
|
28
|
+
}
|
|
29
|
+
return { shadowed: false };
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
isCanonicalGjcWorkflowSkillFilesystemAlias,
|
|
55
55
|
} from "../skill-state/canonical-skills";
|
|
56
56
|
import { expandTilde } from "../tools/path-utils";
|
|
57
|
+
import { resolveDiscoveryPrecedence } from "./customize-doctor-precedence";
|
|
57
58
|
|
|
58
59
|
// =============================================================================
|
|
59
60
|
// Public types (stable JSON contract)
|
|
@@ -67,9 +68,10 @@ export type CustomizeSurfaceKind = "mcp" | "skill" | "hook" | "tool" | "extensio
|
|
|
67
68
|
*
|
|
68
69
|
* - `canonical`: project/global `.gjc` entries and GJC bundled defaults — the
|
|
69
70
|
* primary load path and the persisted authority for sessions.
|
|
70
|
-
* - `convention`: items
|
|
71
|
-
*
|
|
72
|
-
*
|
|
71
|
+
* - `convention`: items exposed by registered non-native discovery providers
|
|
72
|
+
* (claude-plugins, claude/codex hooks, agents, cursor, gemini, opencode,
|
|
73
|
+
* windsurf, cline, github, mcp-json, ssh). The item status identifies whether
|
|
74
|
+
* a discovered item is active, stored-only, or otherwise excluded at runtime.
|
|
73
75
|
* - `import-candidate`: Claude Code / Codex project (+ global) files on
|
|
74
76
|
* surfaces GJC deliberately never loads. Reported for provenance only; never
|
|
75
77
|
* active runtime authority. Candidates for a future import flow (#4291).
|
|
@@ -267,7 +269,7 @@ const SOURCE_CLASS_DESCRIPTIONS: Array<{ sourceClass: CustomizeSourceClass; desc
|
|
|
267
269
|
{
|
|
268
270
|
sourceClass: "convention",
|
|
269
271
|
description:
|
|
270
|
-
"Items
|
|
272
|
+
"Items exposed by registered convention providers (claude-plugins, claude/codex hooks, agents, cursor, gemini, opencode, windsurf, cline, github, mcp-json, ssh); item status identifies runtime eligibility.",
|
|
271
273
|
},
|
|
272
274
|
{
|
|
273
275
|
sourceClass: "import-candidate",
|
|
@@ -394,6 +396,7 @@ async function discoverCapability<T extends { _source: SourceMeta }>(
|
|
|
394
396
|
nameOf: (item: T) => string;
|
|
395
397
|
pathOf: (item: T) => string;
|
|
396
398
|
extensionIdOf?: (item: T) => string | undefined;
|
|
399
|
+
precedenceEligible?: (item: T) => boolean;
|
|
397
400
|
},
|
|
398
401
|
): Promise<DiscoveredSet<T>> {
|
|
399
402
|
const disabledProviders = new Set(activeSettings.get("disabledProviders"));
|
|
@@ -405,41 +408,34 @@ async function discoverCapability<T extends { _source: SourceMeta }>(
|
|
|
405
408
|
includeDisabledProviders: true,
|
|
406
409
|
});
|
|
407
410
|
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
// higher-priority provider must never shadow an enabled
|
|
424
|
-
// lower-priority source (includeDisabledProviders reports it
|
|
425
|
-
// as a listed item without giving it effective precedence).
|
|
426
|
-
winners.set(key, { provider: item._source.provider, scope });
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
entries.push({
|
|
411
|
+
// Resolve provider-order winners only after applying surface eligibility and
|
|
412
|
+
// the configured provider-disabled policy.
|
|
413
|
+
const resolvedPrecedence = resolveDiscoveryPrecedence(
|
|
414
|
+
result.all.map(item => ({
|
|
415
|
+
key: capability.key(item),
|
|
416
|
+
provider: item._source.provider,
|
|
417
|
+
scope: scopeOf(item._source),
|
|
418
|
+
eligible: options.precedenceEligible?.(item) ?? true,
|
|
419
|
+
enabled: !disabledProviders.has(item._source.provider),
|
|
420
|
+
})),
|
|
421
|
+
);
|
|
422
|
+
const entries: DiscoveredEntry<T>[] = result.all.map((item, index) => {
|
|
423
|
+
const precedence = resolvedPrecedence[index];
|
|
424
|
+
if (!precedence) throw new Error("discovery precedence result is missing an item");
|
|
425
|
+
return {
|
|
430
426
|
item,
|
|
431
427
|
name: options.nameOf(item),
|
|
432
428
|
path: options.pathOf(item),
|
|
433
429
|
provider: item._source.provider,
|
|
434
430
|
providerName: item._source.providerName,
|
|
435
|
-
scope,
|
|
431
|
+
scope: scopeOf(item._source),
|
|
436
432
|
priority: capability.providers.find(p => p.id === item._source.provider)?.priority ?? 0,
|
|
437
|
-
shadowed,
|
|
438
|
-
shadowedBy,
|
|
433
|
+
shadowed: precedence.shadowed,
|
|
434
|
+
shadowedBy: precedence.shadowedBy,
|
|
439
435
|
invalidReason: capability.validate?.(item),
|
|
440
436
|
extensionId: options.extensionIdOf?.(item),
|
|
441
|
-
}
|
|
442
|
-
}
|
|
437
|
+
};
|
|
438
|
+
});
|
|
443
439
|
|
|
444
440
|
entries.sort((a, b) => a.name.localeCompare(b.name) || a.provider.localeCompare(b.provider));
|
|
445
441
|
|
|
@@ -954,6 +950,7 @@ async function collectHooks(cwd: string, activeSettings: SettingsInstance): Prom
|
|
|
954
950
|
return collectNotExecutedAtStartup("hook", hookCapability, cwd, activeSettings, {
|
|
955
951
|
nameOf: hook => hook.name,
|
|
956
952
|
pathOf: hook => hook.path,
|
|
953
|
+
precedenceEligible: hook => hook.level !== "project",
|
|
957
954
|
notExecutedDetail:
|
|
958
955
|
"Trusted filesystem hook module discovered for session-start activation. Doctor does not execute the module, so dynamic Function Hook registrations and effective runtime order remain opaque until a session loads it.",
|
|
959
956
|
notExecutedRemediation: [
|
|
@@ -989,6 +986,7 @@ async function collectExtensions(cwd: string, activeSettings: SettingsInstance):
|
|
|
989
986
|
interface NotExecutedOptions<T extends { _source: SourceMeta }> {
|
|
990
987
|
nameOf: (item: T) => string;
|
|
991
988
|
pathOf: (item: T) => string;
|
|
989
|
+
precedenceEligible?: (item: T) => boolean;
|
|
992
990
|
notExecutedDetail: string;
|
|
993
991
|
notExecutedRemediation: string[];
|
|
994
992
|
}
|
|
@@ -1004,6 +1002,7 @@ async function collectNotExecutedAtStartup<T extends { _source: SourceMeta }>(
|
|
|
1004
1002
|
nameOf: options.nameOf,
|
|
1005
1003
|
pathOf: options.pathOf,
|
|
1006
1004
|
extensionIdOf: item => capability.toExtensionId?.(item),
|
|
1005
|
+
precedenceEligible: options.precedenceEligible,
|
|
1007
1006
|
});
|
|
1008
1007
|
const disabledExts = disabledExtensionIds(activeSettings);
|
|
1009
1008
|
const disabledProviders = new Set(activeSettings.get("disabledProviders"));
|
|
@@ -1019,6 +1018,18 @@ async function collectNotExecutedAtStartup<T extends { _source: SourceMeta }>(
|
|
|
1019
1018
|
[`Fix ${entry.path}`],
|
|
1020
1019
|
);
|
|
1021
1020
|
}
|
|
1021
|
+
if (kind === "hook" && entry.scope === "project") {
|
|
1022
|
+
return finalizeItem(
|
|
1023
|
+
base,
|
|
1024
|
+
"stored-only",
|
|
1025
|
+
"storage-only",
|
|
1026
|
+
"Project-scoped hooks are stored for inspection, but ordinary sessions do not load repository hook modules.",
|
|
1027
|
+
[
|
|
1028
|
+
"Import the hook into Global .gjc to load it for future sessions",
|
|
1029
|
+
"or configure an explicit hook path if repository-local activation is intentional",
|
|
1030
|
+
],
|
|
1031
|
+
);
|
|
1032
|
+
}
|
|
1022
1033
|
if (entry.extensionId !== undefined && disabledExts.has(entry.extensionId)) {
|
|
1023
1034
|
return finalizeItem(
|
|
1024
1035
|
base,
|
|
@@ -1360,13 +1371,12 @@ async function collectPluginBundles(cwd: string): Promise<CustomizeDoctorSurface
|
|
|
1360
1371
|
// Foreign conventions (Claude project / Codex project)
|
|
1361
1372
|
//
|
|
1362
1373
|
// Claude Code / Codex project hooks are discovered by the registered
|
|
1363
|
-
// claude-hooks/codex-hooks providers (see discovery/index.ts)
|
|
1364
|
-
//
|
|
1365
|
-
//
|
|
1366
|
-
//
|
|
1367
|
-
//
|
|
1368
|
-
//
|
|
1369
|
-
// marks every such item as `ignored`.
|
|
1374
|
+
// claude-hooks/codex-hooks providers (see discovery/index.ts), but like native
|
|
1375
|
+
// project hooks are stored-only and are not imported by ordinary sessions.
|
|
1376
|
+
// Every OTHER `.claude`/`.codex` surface (MCP, skills, tools, extensions,
|
|
1377
|
+
// commands, prompts, settings) is deliberately not part of the load path: the
|
|
1378
|
+
// doctor reports those files by invoking canonical provider load functions
|
|
1379
|
+
// directly (without registering the providers) and marks them `ignored`.
|
|
1370
1380
|
// =============================================================================
|
|
1371
1381
|
|
|
1372
1382
|
interface ForeignConventionDescriptor {
|
|
@@ -1468,7 +1478,7 @@ function foreignItem(
|
|
|
1468
1478
|
async function collectForeignConventions(cwd: string): Promise<ForeignConventionCollection> {
|
|
1469
1479
|
const ctx: LoadContext = { cwd, home: os.homedir(), repoRoot: await findRepoRoot(cwd) };
|
|
1470
1480
|
const itemsByKind: Map<CustomizeSurfaceKind, CustomizeDoctorItem[]> = new Map();
|
|
1471
|
-
const policyNote = `${FOREIGN_CONVENTIONS.map(d => d.dirName).join(" and ")} project hooks are
|
|
1481
|
+
const policyNote = `${FOREIGN_CONVENTIONS.map(d => d.dirName).join(" and ")} project hooks are shown as stored-only (see the Hooks surface); ordinary sessions do not load repository hook modules. All other ${FOREIGN_CONVENTIONS.map(d => d.providerName).join(" / ")} project config surfaces (MCP servers, skills, tools, extensions, commands, prompts, settings) are not part of the GJC load path and are reported below as import candidates for provenance.`;
|
|
1472
1482
|
|
|
1473
1483
|
for (const desc of FOREIGN_CONVENTIONS) {
|
|
1474
1484
|
const inspection = await desc.inspect(ctx);
|
package/src/cli/fast-help.ts
CHANGED
|
@@ -81,8 +81,6 @@ Environment Variables:
|
|
|
81
81
|
GJC_CODING_AGENT_DIR - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
|
|
82
82
|
GJC_UI_LANGUAGE - Explicit first-use onboarding language (en, ko, zh, or ja); invalid values use English without prompting
|
|
83
83
|
GJC_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
|
|
84
|
-
GJC_SMOL_MODEL - Override smol/fast model (see --smol)
|
|
85
|
-
GJC_SLOW_MODEL - Override slow/reasoning model (see --slow)
|
|
86
84
|
GJC_PLAN_MODEL - Override planning model (see --plan)
|
|
87
85
|
GJC_MODEL_PRESET_REGISTRY_URL - HTTPS latest.json override for the signed preset registry
|
|
88
86
|
GJC_MODEL_PRESET_REGISTRY_DISABLED - Disable registry fetch/use (1/true/yes/on)
|
package/src/cli/migrate-cli.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `gjc migrate` — import MCP servers, skills, and instruction files from other coding agents.
|
|
2
|
+
* `gjc migrate` — import MCP servers, skills, slash commands, and instruction files from other coding agents.
|
|
3
3
|
*/
|
|
4
4
|
import * as os from "node:os";
|
|
5
5
|
import * as path from "node:path";
|
|
@@ -55,8 +55,18 @@ function resolveDestinations(project: boolean, cwd: string): MigrateDestinations
|
|
|
55
55
|
const scope = project ? "project" : "user";
|
|
56
56
|
const agentDir = project ? getProjectAgentDir(cwd) : getAgentDir();
|
|
57
57
|
const skillsDir = path.join(agentDir, "skills");
|
|
58
|
+
const commandsDir = path.join(agentDir, "commands");
|
|
59
|
+
const agentsDir = path.join(agentDir, "agents");
|
|
60
|
+
const hooksDir = path.join(agentDir, "hooks");
|
|
58
61
|
const instructionsPath = path.join(agentDir, "AGENTS.md");
|
|
59
|
-
return {
|
|
62
|
+
return {
|
|
63
|
+
mcpConfigPath: getMCPConfigPath(scope, cwd),
|
|
64
|
+
skillsDir,
|
|
65
|
+
commandsDir,
|
|
66
|
+
agentsDir,
|
|
67
|
+
hooksDir,
|
|
68
|
+
instructionsPath,
|
|
69
|
+
};
|
|
60
70
|
}
|
|
61
71
|
|
|
62
72
|
/** Run the migration and return the report (does not set process.exitCode). */
|
|
@@ -71,12 +81,13 @@ export async function runMigrate(args: MigrateCommandArgs): Promise<MigrateRepor
|
|
|
71
81
|
results.push(await getAdapter(source).collect({ homeDir, cwd, scope: args.project ? "project" : "user" }));
|
|
72
82
|
}
|
|
73
83
|
|
|
74
|
-
const { actions, warnings } = await planMigration({ results, destinations, force: args.force });
|
|
84
|
+
const { actions, warnings, manualActions } = await planMigration({ results, destinations, force: args.force });
|
|
75
85
|
const finalActions = args.dryRun ? actions : await executeActions(actions, { project: args.project });
|
|
76
86
|
|
|
77
87
|
return buildReport({
|
|
78
88
|
actions: finalActions,
|
|
79
89
|
warnings,
|
|
90
|
+
manualActions,
|
|
80
91
|
sources,
|
|
81
92
|
destinations,
|
|
82
93
|
dryRun: args.dryRun,
|
|
@@ -111,6 +111,8 @@ export const PUBLIC_COMMAND_DIAGNOSTICS = {
|
|
|
111
111
|
// of them and never implies that another key would be safe.
|
|
112
112
|
lifecycle_idempotency_conflict:
|
|
113
113
|
"The broker reported an idempotency conflict. Reconcile existing lifecycle state before deciding whether another request is safe.",
|
|
114
|
+
lifecycle_legacy_history_ambiguous:
|
|
115
|
+
"The broker refused admission because legacy lifecycle history cannot prove this target is unrelated. This request was not dispatched; this refusal does not settle earlier effects. Preserve the ledger and original operation, request key, and target. For a prior session.create, use read-only session.lookup with its original key and create target; not_found is not proof of no effect. An empty transcript, stopped host, or fresh key does not resolve this fence. Do not edit the ledger, force deletion, or retry with another key; missing identity or terminal effect evidence requires operator investigation.",
|
|
114
116
|
// Refusals of the request payload itself: the broker's own text names the missing field
|
|
115
117
|
// (a required `sessionPath`, for one), and it is never rendered, so the class is named here.
|
|
116
118
|
lifecycle_input_refused:
|
package/src/cli/root-flags.ts
CHANGED
|
@@ -10,8 +10,6 @@ export type RootThinkingLevel = (typeof ROOT_THINKING_LEVELS)[number];
|
|
|
10
10
|
/** Public launch flags shared by root help, completion, and the launch command. */
|
|
11
11
|
export const ROOT_LAUNCH_FLAGS = {
|
|
12
12
|
model: Flags.string({ description: 'Model to use (fuzzy match: "opus", "gpt-5.2", or "openai/gpt-5.2")' }),
|
|
13
|
-
smol: Flags.string({ description: "Smol/fast model for lightweight tasks (or GJC_SMOL_MODEL env)" }),
|
|
14
|
-
slow: Flags.string({ description: "Slow/reasoning model for thorough analysis (or GJC_SLOW_MODEL env)" }),
|
|
15
13
|
plan: Flags.string({ description: "Plan model for architectural planning (or GJC_PLAN_MODEL env)" }),
|
|
16
14
|
mpreset: Flags.string({ description: "Model profile preset to activate for this session" }),
|
|
17
15
|
default: Flags.boolean({ description: "Persist --mpreset as the default model profile" }),
|