@gajae-code/coding-agent 0.16.3 → 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.
- package/CHANGELOG.md +113 -0
- package/dist/types/capability/types.d.ts +4 -0
- package/dist/types/cli/args.d.ts +2 -2
- package/dist/types/cli/customize-doctor.d.ts +22 -0
- package/dist/types/cli/root-flags.d.ts +4 -2
- package/dist/types/cli.d.ts +1 -1
- package/dist/types/commands/launch.d.ts +1 -1
- package/dist/types/config/autorouting-tier-map.d.ts +3 -0
- package/dist/types/config/file-lock.d.ts +31 -3
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/model-resolver.d.ts +9 -0
- package/dist/types/config/settings-schema.d.ts +29 -1
- package/dist/types/coordinator-mcp/question-state.d.ts +7 -0
- package/dist/types/coordinator-mcp/server.d.ts +7 -0
- package/dist/types/discovery/claude-plugins.d.ts +3 -1
- package/dist/types/discovery/helpers.d.ts +35 -0
- package/dist/types/exec/bash-executor.d.ts +17 -1
- package/dist/types/exec/bash-shell-guardian.d.ts +15 -0
- package/dist/types/exec/bash-shell-runtime-entry.d.ts +2 -0
- package/dist/types/exec/bash-shell-signals.d.ts +2 -0
- package/dist/types/exec/bash-shell-supervisor-entry.d.ts +1 -0
- package/dist/types/exec/bash-shell-supervisor.d.ts +10 -0
- package/dist/types/exec/bash-shell-worker-entry.d.ts +2 -0
- package/dist/types/exec/bash-shell-worker-protocol.d.ts +63 -0
- package/dist/types/exec/bash-shell-worker.d.ts +1 -0
- package/dist/types/exec/isolated-shell.d.ts +19 -0
- package/dist/types/extensibility/extensions/function-hooks-internal.d.ts +9 -0
- package/dist/types/extensibility/extensions/function-hooks.d.ts +169 -0
- package/dist/types/extensibility/extensions/index.d.ts +1 -0
- package/dist/types/extensibility/extensions/runner.d.ts +46 -6
- package/dist/types/extensibility/extensions/types.d.ts +16 -0
- package/dist/types/extensibility/extensions/wrapper.d.ts +3 -1
- package/dist/types/extensibility/gjc-plugins/constrained-hooks.d.ts +35 -2
- package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +16 -0
- package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -0
- package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
- package/dist/types/extensibility/hooks/types.d.ts +4 -0
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +5 -2
- package/dist/types/extensibility/shared-events.d.ts +1 -1
- package/dist/types/extensibility/skill-management.d.ts +9 -4
- package/dist/types/extensibility/skills.d.ts +2 -0
- package/dist/types/gjc-runtime/empty-delete-gc.d.ts +4 -1
- package/dist/types/gjc-runtime/linux-proc.d.ts +2 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +14 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +41 -3
- package/dist/types/gjc-runtime/ultragoal-succession.d.ts +251 -0
- package/dist/types/modes/components/assistant-message.d.ts +1 -2
- package/dist/types/modes/components/bash-execution.d.ts +1 -0
- package/dist/types/modes/components/execution-shared.d.ts +1 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -1
- package/dist/types/modes/components/status-line/command.d.ts +35 -0
- package/dist/types/modes/components/status-line/index.d.ts +1 -0
- package/dist/types/modes/components/status-line/types.d.ts +5 -0
- package/dist/types/modes/components/tool-status-header.d.ts +14 -0
- package/dist/types/modes/controllers/event-controller.d.ts +6 -0
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/types.d.ts +7 -0
- package/dist/types/runtime-mcp/client.d.ts +9 -1
- package/dist/types/runtime-mcp/manager.d.ts +7 -1
- package/dist/types/runtime-mcp/pool.d.ts +22 -3
- package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
- package/dist/types/runtime-mcp/types.d.ts +22 -0
- package/dist/types/sdk/broker/ensure.d.ts +32 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +0 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +6 -0
- package/dist/types/sdk/broker/startup-failure.d.ts +4 -1
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +12 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +17 -2
- package/dist/types/sdk/bus/conversation-store.d.ts +11 -0
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +8 -8
- package/dist/types/sdk/bus/slack-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/slack-live-provider.d.ts +6 -0
- package/dist/types/sdk/bus/slack-provider.d.ts +12 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +8 -0
- package/dist/types/sdk/client/client.d.ts +6 -0
- package/dist/types/sdk/host/host.d.ts +3 -1
- package/dist/types/sdk/host/session-runtime.d.ts +26 -1
- package/dist/types/sdk/lifecycle/service.d.ts +1 -0
- package/dist/types/sdk/router/session-router.d.ts +10 -2
- package/dist/types/sdk/session-api-key.d.ts +26 -0
- package/dist/types/sdk/session.d.ts +5 -1
- package/dist/types/sdk/transport/serve-cli.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +11 -0
- package/dist/types/session/fallback-chain-controller.d.ts +15 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +7 -0
- package/dist/types/session/messages.d.ts +1 -0
- package/dist/types/session/session-manager.d.ts +3 -1
- package/dist/types/setup/paseo/announce.d.ts +112 -0
- package/dist/types/setup/paseo/setup-deps.d.ts +2 -1
- package/dist/types/skill-state/canonical-skills.d.ts +4 -0
- package/dist/types/system-prompt.d.ts +10 -0
- package/dist/types/task/executor.d.ts +5 -1
- package/dist/types/tools/bash.d.ts +1 -0
- package/dist/types/tools/fetch.d.ts +7 -0
- package/dist/types/tools/github-cache.d.ts +2 -1
- package/dist/types/tools/index.d.ts +10 -0
- package/dist/types/tools/path-utils.d.ts +2 -0
- package/dist/types/tools/search.d.ts +6 -0
- package/package.json +9 -7
- package/scripts/capture-status-line-custom-editor-showcase.ts +151 -0
- package/scripts/generate-sdk-operation-inventory.ts +11 -0
- package/scripts/verify-status-line-custom-editor-showcase.ts +309 -0
- package/src/capability/index.ts +14 -2
- package/src/capability/types.ts +4 -0
- package/src/cli/args.ts +20 -9
- package/src/cli/customize-doctor.ts +155 -12
- package/src/cli/root-flags.ts +5 -3
- package/src/cli.ts +22 -0
- package/src/commands/sdk.ts +74 -31
- package/src/config/autorouting-tier-map.ts +1 -0
- package/src/config/file-lock-gc.ts +40 -2
- package/src/config/file-lock.ts +379 -31
- package/src/config/model-preset-registry.ts +120 -19
- package/src/config/model-profiles.ts +40 -0
- package/src/config/model-registry.ts +73 -23
- package/src/config/model-resolver.ts +48 -0
- package/src/config/settings-schema.ts +33 -1
- package/src/config/settings.ts +1 -0
- package/src/coordinator-mcp/question-state.ts +33 -2
- package/src/coordinator-mcp/server.ts +477 -101
- package/src/crash/sanitize.ts +1 -1
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +11 -11
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +13 -2
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +22 -0
- package/src/discovery/builtin.ts +52 -55
- package/src/discovery/claude-plugins.ts +12 -4
- package/src/discovery/helpers.ts +307 -34
- package/src/exec/bash-executor.ts +330 -50
- package/src/exec/bash-shell-guardian.ts +388 -0
- package/src/exec/bash-shell-runtime-entry.ts +5 -0
- package/src/exec/bash-shell-signals.ts +29 -0
- package/src/exec/bash-shell-supervisor-entry.ts +3 -0
- package/src/exec/bash-shell-supervisor.ts +359 -0
- package/src/exec/bash-shell-worker-entry.ts +5 -0
- package/src/exec/bash-shell-worker-protocol.ts +36 -0
- package/src/exec/bash-shell-worker.ts +116 -0
- package/src/exec/isolated-shell.ts +393 -0
- package/src/extensibility/extensions/function-hooks-internal.ts +73 -0
- package/src/extensibility/extensions/function-hooks.ts +959 -0
- package/src/extensibility/extensions/index.ts +22 -0
- package/src/extensibility/extensions/loader.ts +53 -2
- package/src/extensibility/extensions/runner.ts +895 -264
- package/src/extensibility/extensions/types.ts +42 -0
- package/src/extensibility/extensions/wrapper.ts +56 -15
- package/src/extensibility/gjc-plugins/compiler.ts +228 -60
- package/src/extensibility/gjc-plugins/constrained-hooks.ts +321 -23
- package/src/extensibility/gjc-plugins/installer.ts +13 -12
- package/src/extensibility/gjc-plugins/mcp-policy.ts +81 -52
- package/src/extensibility/gjc-plugins/paths.ts +13 -0
- package/src/extensibility/gjc-plugins/registry.ts +113 -1
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +758 -16
- package/src/extensibility/gjc-plugins/runtime-quarantine.ts +20 -2
- package/src/extensibility/gjc-plugins/schema.ts +121 -4
- package/src/extensibility/gjc-plugins/types.ts +25 -0
- package/src/extensibility/hooks/loader.ts +133 -16
- package/src/extensibility/hooks/types.ts +28 -0
- package/src/extensibility/runtime-skill-discovery.ts +149 -190
- package/src/extensibility/shared-events.ts +1 -1
- package/src/extensibility/skill-management.ts +200 -52
- package/src/extensibility/skills.ts +73 -25
- package/src/gjc-runtime/empty-delete-gc.ts +94 -4
- package/src/gjc-runtime/gc-runtime.ts +29 -0
- package/src/gjc-runtime/linux-proc.ts +14 -0
- package/src/gjc-runtime/repository-binding.ts +1 -1
- package/src/gjc-runtime/session-state-lock.ts +143 -10
- package/src/gjc-runtime/session-state-sidecar.ts +27 -11
- package/src/gjc-runtime/state-writer.ts +30 -29
- package/src/gjc-runtime/ultragoal-runtime.ts +189 -47
- package/src/gjc-runtime/ultragoal-succession.ts +1667 -0
- package/src/gjc-runtime/workflow-manifest.generated.json +52 -1
- package/src/gjc-runtime/workflow-manifest.ts +16 -0
- package/src/harness-control-plane/session-lease.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +12 -12
- package/src/lsp/config.ts +10 -3
- package/src/lsp/index.ts +1 -1
- package/src/lsp/path-trust.ts +69 -14
- package/src/main.ts +78 -35
- package/src/modes/DESIGN.md +54 -0
- package/src/modes/acp/acp-agent.ts +16 -3
- package/src/modes/components/assistant-message.ts +22 -9
- package/src/modes/components/bash-execution.ts +4 -1
- package/src/modes/components/execution-shared.ts +4 -1
- package/src/modes/components/model-selector.ts +166 -33
- package/src/modes/components/session-observer-overlay.ts +1 -1
- package/src/modes/components/settings-selector.ts +1075 -235
- package/src/modes/components/status-line/command.ts +190 -0
- package/src/modes/components/status-line/index.ts +1 -0
- package/src/modes/components/status-line/segments.ts +32 -5
- package/src/modes/components/status-line/types.ts +5 -0
- package/src/modes/components/tool-status-header.ts +396 -22
- package/src/modes/controllers/command-controller.ts +3 -0
- package/src/modes/controllers/event-controller.ts +151 -7
- package/src/modes/controllers/extension-ui-controller.ts +1 -0
- package/src/modes/controllers/input-controller.ts +6 -3
- package/src/modes/controllers/selector-controller.ts +21 -0
- package/src/modes/interactive-mode.ts +53 -6
- package/src/modes/print-mode.ts +5 -1
- package/src/modes/prompt-action-autocomplete.ts +54 -27
- package/src/modes/runtime-init.ts +2 -0
- package/src/modes/types.ts +17 -3
- package/src/modes/utils/ui-helpers.ts +2 -0
- package/src/prompts/system/system-prompt.md +8 -0
- package/src/prompts/tools/search.md +2 -0
- package/src/prompts/tools/subagent.md +1 -0
- package/src/runtime-mcp/client.ts +60 -17
- package/src/runtime-mcp/manager.ts +189 -14
- package/src/runtime-mcp/pool.test.ts +218 -0
- package/src/runtime-mcp/pool.ts +224 -23
- package/src/runtime-mcp/transports/stdio.ts +158 -24
- package/src/runtime-mcp/types.ts +24 -0
- package/src/sdk/broker/broker.ts +124 -32
- package/src/sdk/broker/ensure.ts +248 -41
- package/src/sdk/broker/lifecycle-ledger.ts +7 -17
- package/src/sdk/broker/lifecycle.ts +56 -6
- package/src/sdk/broker/startup-failure.ts +15 -6
- package/src/sdk/bus/chat-daemon-control.ts +3 -1
- package/src/sdk/bus/chat-daemon-runtime.ts +72 -6
- package/src/sdk/bus/chat-effect-journal.ts +132 -7
- package/src/sdk/bus/conversation-store.ts +29 -0
- package/src/sdk/bus/lifecycle-commands.ts +17 -11
- package/src/sdk/bus/slack-conversation.ts +1 -0
- package/src/sdk/bus/slack-daemon.ts +478 -49
- package/src/sdk/bus/slack-live-provider.ts +12 -0
- package/src/sdk/bus/slack-provider.ts +5 -0
- package/src/sdk/bus/telegram-daemon.ts +16 -2
- package/src/sdk/bus/topic-registry.ts +19 -0
- package/src/sdk/cli/master-cli.ts +1 -1
- package/src/sdk/cli/session-cli.ts +11 -8
- package/src/sdk/client/client.ts +66 -17
- package/src/sdk/host/host.ts +29 -9
- package/src/sdk/host/query/revision-store.ts +19 -13
- package/src/sdk/host/reverse-leases.ts +7 -4
- package/src/sdk/host/session-runtime.test.ts +52 -10
- package/src/sdk/host/session-runtime.ts +383 -44
- package/src/sdk/lifecycle/service.ts +4 -0
- package/src/sdk/protocol/operation-inventory.generated.json +77 -0
- package/src/sdk/router/session-router.ts +89 -38
- package/src/sdk/session-api-key.ts +94 -0
- package/src/sdk/session.ts +228 -55
- package/src/sdk/transport/relay.ts +35 -13
- package/src/sdk/transport/serve-cli.ts +3 -3
- package/src/session/agent-session.ts +240 -90
- package/src/session/contribution-prep.ts +214 -21
- package/src/session/fallback-chain-controller.ts +38 -0
- package/src/session/internal/managed-session-storage.ts +19 -5
- package/src/session/messages.ts +5 -0
- package/src/session/session-manager.ts +29 -5
- package/src/session-import/redact.ts +5 -1
- package/src/setup/paseo/announce.ts +456 -0
- package/src/setup/paseo/setup-deps.ts +15 -3
- package/src/skill-state/canonical-skills.ts +12 -0
- package/src/skills/skills.test.ts +41 -21
- package/src/slash-commands/builtin-registry.ts +1 -0
- package/src/system-prompt.ts +29 -3
- package/src/task/executor.ts +7 -1
- package/src/task/index.ts +21 -4
- package/src/tools/bash.ts +63 -19
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +29 -1
- package/src/tools/gh.ts +26 -3
- package/src/tools/github-cache.ts +68 -16
- package/src/tools/index.ts +10 -0
- package/src/tools/job.ts +21 -4
- package/src/tools/monitor.ts +8 -2
- package/src/tools/path-utils.ts +7 -0
- package/src/tools/read.ts +14 -2
- package/src/tools/render-utils.ts +1 -3
- package/src/tools/resource-gc.ts +28 -8
- package/src/tools/search.ts +116 -58
- package/src/tools/skill-discovery.ts +5 -0
- package/src/tools/skill.ts +37 -2
- package/src/tools/subagent.ts +6 -3
- package/src/tools/tool-catalog.generated.ts +10 -3
- package/src/tools/ultragoal-ask-guard.ts +2 -2
- package/src/web/insane/bridge.ts +113 -23
- package/src/web/search/providers/perplexity.ts +102 -41
package/src/crash/sanitize.ts
CHANGED
|
@@ -40,7 +40,7 @@ const INVISIBLE_PATTERN = new RegExp(INVISIBLE_CLASS, "g");
|
|
|
40
40
|
// residual scanner that silently alternates verdicts is worse than none.
|
|
41
41
|
const CONTROL_PROBE = new RegExp(CONTROL_CLASS);
|
|
42
42
|
const INVISIBLE_PROBE = new RegExp(INVISIBLE_CLASS);
|
|
43
|
-
const URL_PATTERN =
|
|
43
|
+
const URL_PATTERN = /(?<![A-Za-z0-9+.-])[a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^\s<>"'`)\]]+/g;
|
|
44
44
|
/** Anything still matching these after sanitization means the scanner is not certain. */
|
|
45
45
|
const RESIDUAL_PATTERNS: readonly RegExp[] = [
|
|
46
46
|
/\bsk-[A-Za-z0-9_-]{8,}/,
|
|
@@ -73,6 +73,7 @@ const FALLBACK_MODELS: GrokCliModelConfig[] = [
|
|
|
73
73
|
cost: COST_43,
|
|
74
74
|
contextWindow: 1_000_000,
|
|
75
75
|
maxTokens: 30_000,
|
|
76
|
+
maxReasoningEffort: Effort.High,
|
|
76
77
|
},
|
|
77
78
|
{
|
|
78
79
|
// Official metadata and pricing: https://docs.x.ai/developers/models/grok-4.6
|
|
@@ -158,23 +159,22 @@ function matchesModelFamily(name: string, modelId: string): boolean {
|
|
|
158
159
|
return name.startsWith(`${modelId}-`) && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(suffix);
|
|
159
160
|
}
|
|
160
161
|
|
|
162
|
+
const REASONING_EFFORT_CAPS = [
|
|
163
|
+
{ prefix: 'grok-3-mini', max: Effort.High },
|
|
164
|
+
{ prefix: 'grok-4.3', max: Effort.High },
|
|
165
|
+
{ prefix: 'grok-4.5', max: Effort.High },
|
|
166
|
+
{ prefix: 'grok-4.6', max: Effort.XHigh },
|
|
167
|
+
{ prefix: 'grok-4.20-multi-agent', max: Effort.XHigh },
|
|
168
|
+
] as const;
|
|
169
|
+
|
|
161
170
|
export function getMaxReasoningEffort(modelId: string): Effort | undefined {
|
|
162
171
|
const name = getCanonicalModelName(modelId);
|
|
163
|
-
return
|
|
164
|
-
?.maxReasoningEffort;
|
|
172
|
+
return REASONING_EFFORT_CAPS.find(({ prefix }) => matchesModelFamily(name, prefix))?.max;
|
|
165
173
|
}
|
|
166
174
|
|
|
167
|
-
const EFFORT_CAPABLE_PREFIXES = [
|
|
168
|
-
'grok-3-mini',
|
|
169
|
-
'grok-4.20-multi-agent',
|
|
170
|
-
'grok-4.3',
|
|
171
|
-
'grok-4.5',
|
|
172
|
-
'grok-4.6',
|
|
173
|
-
];
|
|
174
|
-
|
|
175
175
|
export function supportsReasoningEffort(modelId: string): boolean {
|
|
176
176
|
const name = getCanonicalModelName(modelId);
|
|
177
|
-
if (!
|
|
177
|
+
if (!REASONING_EFFORT_CAPS.some(({ prefix }) => matchesModelFamily(name, prefix))) {
|
|
178
178
|
return false;
|
|
179
179
|
}
|
|
180
180
|
const model = resolveModels().find((entry) => getCanonicalModelName(entry.id) === name);
|
|
@@ -7,7 +7,12 @@ import { Effort } from '@gajae-code/ai/model-thinking';
|
|
|
7
7
|
import type { OAuthCredentials, OAuthLoginCallbacks } from '@gajae-code/ai/utils/oauth/types';
|
|
8
8
|
import { loginXai, refreshXaiToken, XAI_OAUTH_SCOPE } from '@gajae-code/ai/utils/oauth/xai';
|
|
9
9
|
import type { ExtensionAPI, ProviderConfig } from '@gajae-code/coding-agent';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
type GrokCliModelConfig,
|
|
12
|
+
getMaxReasoningEffort,
|
|
13
|
+
resolveModels,
|
|
14
|
+
supportsReasoningEffort,
|
|
15
|
+
} from '../models/catalog.js';
|
|
11
16
|
import { sanitizePayload } from '../payload/sanitize.js';
|
|
12
17
|
import { getBaseUrl, isGrokBuildBaseUrlOverrideIgnored } from '../shared/base-url.js';
|
|
13
18
|
import { streamGrokCli } from './stream.js';
|
|
@@ -38,7 +43,7 @@ export default function registerGrokCli(api: ExtensionAPI) {
|
|
|
38
43
|
thinking: m.reasoning
|
|
39
44
|
? {
|
|
40
45
|
minLevel: Effort.Low,
|
|
41
|
-
maxLevel: m.
|
|
46
|
+
maxLevel: getMaxReasoningEffort(m.id) ?? Effort.XHigh,
|
|
42
47
|
mode: 'effort',
|
|
43
48
|
}
|
|
44
49
|
: undefined,
|
|
@@ -46,6 +51,12 @@ export default function registerGrokCli(api: ExtensionAPI) {
|
|
|
46
51
|
cost: m.cost,
|
|
47
52
|
contextWindow: m.contextWindow,
|
|
48
53
|
maxTokens: m.maxTokens,
|
|
54
|
+
// cli-chat-proxy is not a generic audited OpenAI origin. Carry only the
|
|
55
|
+
// catalog's model-scoped evidence into core reasoning request gating.
|
|
56
|
+
compat:
|
|
57
|
+
m.reasoning && supportsReasoningEffort(m.id)
|
|
58
|
+
? { supportsReasoningEffort: true }
|
|
59
|
+
: undefined,
|
|
49
60
|
})),
|
|
50
61
|
oauth: {
|
|
51
62
|
name: 'Grok Build',
|
|
@@ -442,6 +442,28 @@ Receipts are freshness-scoped:
|
|
|
442
442
|
- Appending required goals or changing final required-goal state stales final aggregate receipts. Final aggregate completion requires a fresh final aggregate receipt proving no incomplete, blocked, or `review_blocked` required goals remain.
|
|
443
443
|
- Deferred per-goal receipts (validation-batch members) are incomplete until a matching fresh batch-close receipt exists on the batch's `finalGoalId`; a story-scope query for a deferred member stays blocked until that close, and mutating a member after close stales the batch-close and final aggregate receipts.
|
|
444
444
|
|
|
445
|
+
## Cross-repository succession
|
|
446
|
+
|
|
447
|
+
When an approved run was planned in one repository but the implementation belongs in another, the repository-binding guard correctly refuses to execute the plan from the second repository. Never edit `repositoryBinding` and never copy the runtime directory: both defeat the boundary and launder verification provenance. Use the explicit successor path instead.
|
|
448
|
+
|
|
449
|
+
```
|
|
450
|
+
gjc ultragoal succession offer --target-repo <path> --goal-id G002 --goal-id G003 --authorize "<who approved what, for which source, target and goals>" --authorized-by <identity> --json
|
|
451
|
+
gjc ultragoal succession adopt --offer <offer path inside the source worktree> --json
|
|
452
|
+
gjc ultragoal succession status --json
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
`offer` runs in the source repository. It records an offer document plus a durable outgoing ownership fence, and writes nothing to `brief.md`, `goals.json` or `ledger.jsonl`. From that moment the source run refuses to schedule or checkpoint the fenced goals; goals outside the selection stay fully schedulable. Ownership therefore leaves the source at the offer, not when the target happens to adopt, so no interval exists in which both runs may resume the same goal. There is deliberately no `revoke` verb: any read-then-delete of the fence races a concurrent adoption and could revive the source while the target is starting, so an unadopted offer keeps its goals fenced.
|
|
456
|
+
|
|
457
|
+
Because unselected goals stay schedulable, ordinary source progress moves whole-file digests. Adoption therefore compares a **snapshot of the offered work** — the brief plus each selected goal's record and unresolved obligations — instead of whole-file equality, so unrelated progress cannot permanently strand the handed-off work. Whole-file digests are still recorded as provenance and any drift is written into the adoption record.
|
|
458
|
+
|
|
459
|
+
`adopt` runs in the target repository and starts a genuinely fresh run: new pending goals, fresh timestamps, the target repository's own binding, and no inherited receipts, quality gates, validation batches, steering or activated objective. The source brief and every selected objective are carried verbatim, together with the unresolved obligations recorded against those goals — requirements are carried forward in full, never summarized down. Dependency groups travel as explicit obligations with source-to-target id mapping: the source's batch metadata and receipts are not inherited, but the requirement to validate those goals together is.
|
|
460
|
+
|
|
461
|
+
Selection and authorization must be explicit. Only unfinished goals (`pending`, `failed`, `blocked`, `review_blocked`) may be handed off; the source run must be quiescent with no `active` goal; there is no implicit or wildcard selection; and a selection that takes only part of a validation batch, or splits a review blocker from the goal it still blocks, is rejected rather than silently dropping that obligation. Adoption fails closed on changed offered work, an altered or unfenced offer, an offer path that escapes the source worktree, a target the offer does not name, a linked worktree that is not the exact named target, an occupied target session, and any duplicate or simultaneous adoption anywhere in the target repository. A retry reconciles the exact recorded operation or fails closed — a matching operation id is never authority to overwrite target work it did not write, and a published plan that has disappeared is never reconstructed.
|
|
462
|
+
|
|
463
|
+
Until publication completes, the target refuses to execute: a visible `goals.json` is not admission evidence, the adoption record is. `start`/`complete-goals` and `checkpoint` reject while an adoption remains pending.
|
|
464
|
+
|
|
465
|
+
Integrity digests are evidence, not authorization: a matching digest set with no fence, no bounded authorization, or the wrong target is still rejected. Historical source statuses, receipts, reviews and approvals travel as provenance only and never satisfy a target gate.
|
|
466
|
+
|
|
445
467
|
## Handoff back to planning
|
|
446
468
|
|
|
447
469
|
When the aggregate ultragoal is complete OR the user requests return to planning/clarification, mark ultragoal ready for handoff so the skill tool's chain guard permits the backward transition:
|
package/src/discovery/builtin.ts
CHANGED
|
@@ -28,8 +28,11 @@ import {
|
|
|
28
28
|
createSourceMeta,
|
|
29
29
|
discoverExtensionModulePaths,
|
|
30
30
|
expandEnvVarsDeep,
|
|
31
|
+
getAncestorDirs,
|
|
31
32
|
getExtensionNameFromPath,
|
|
33
|
+
getUserSkillScanDirs,
|
|
32
34
|
loadFilesFromDir,
|
|
35
|
+
readContainedFile,
|
|
33
36
|
SOURCE_PATHS,
|
|
34
37
|
scanSkillsFromDir,
|
|
35
38
|
} from "./helpers";
|
|
@@ -41,10 +44,6 @@ const PRIORITY = 100;
|
|
|
41
44
|
|
|
42
45
|
const PATHS = SOURCE_PATHS.native;
|
|
43
46
|
|
|
44
|
-
function getUserAgentDirs(): string[] {
|
|
45
|
-
return [PATHS.userAgent];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
47
|
/**
|
|
49
48
|
* GJC's user-scope config directory.
|
|
50
49
|
*
|
|
@@ -92,26 +91,12 @@ async function getConfigDirs(ctx: LoadContext): Promise<Array<{ dir: string; lev
|
|
|
92
91
|
return result;
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
function getAncestorDirs(cwd: string, stopAt?: string | null): Array<{ dir: string; depth: number }> {
|
|
96
|
-
const ancestors: Array<{ dir: string; depth: number }> = [];
|
|
97
|
-
let current = cwd;
|
|
98
|
-
let depth = 0;
|
|
99
|
-
while (true) {
|
|
100
|
-
ancestors.push({ dir: current, depth });
|
|
101
|
-
if (stopAt && current === stopAt) break;
|
|
102
|
-
const parent = path.dirname(current);
|
|
103
|
-
if (parent === current) break;
|
|
104
|
-
current = parent;
|
|
105
|
-
depth++;
|
|
106
|
-
}
|
|
107
|
-
return ancestors;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
94
|
async function findNearestProjectConfigDir(
|
|
111
95
|
cwd: string,
|
|
112
96
|
repoRoot?: string | null,
|
|
97
|
+
home?: string,
|
|
113
98
|
): Promise<{ dir: string; depth: number } | null> {
|
|
114
|
-
for (const ancestor of getAncestorDirs(cwd, repoRoot)) {
|
|
99
|
+
for (const ancestor of getAncestorDirs(cwd, repoRoot ?? home, home)) {
|
|
115
100
|
for (const projectConfigDir of getProjectConfigDirs()) {
|
|
116
101
|
const configDir = await ifNonEmptyDir(ancestor.dir, projectConfigDir);
|
|
117
102
|
if (configDir) return { dir: configDir, depth: ancestor.depth };
|
|
@@ -280,20 +265,21 @@ registerProvider<MCPServer>(mcpCapability.id, {
|
|
|
280
265
|
async function loadSystemPrompt(ctx: LoadContext): Promise<LoadResult<SystemPrompt>> {
|
|
281
266
|
const items: SystemPrompt[] = [];
|
|
282
267
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
268
|
+
// User scope is the agent directory — the directory `gjc config path` prints
|
|
269
|
+
// and the only user-scope seam. A profile is a separate scope; the default
|
|
270
|
+
// profile's home-relative SYSTEM.md is not read under one.
|
|
271
|
+
const userPath = path.join(resolveUserAgentDir(ctx), "SYSTEM.md");
|
|
272
|
+
const userContent = await readContainedFile(resolveUserAgentDir(ctx), userPath);
|
|
273
|
+
if (userContent) {
|
|
274
|
+
items.push({
|
|
275
|
+
path: userPath,
|
|
276
|
+
content: userContent,
|
|
277
|
+
level: "user",
|
|
278
|
+
_source: createSourceMeta(PROVIDER_ID, userPath, "user"),
|
|
279
|
+
});
|
|
294
280
|
}
|
|
295
281
|
|
|
296
|
-
const nearestProjectConfigDir = await findNearestProjectConfigDir(ctx.cwd, ctx.repoRoot);
|
|
282
|
+
const nearestProjectConfigDir = await findNearestProjectConfigDir(ctx.cwd, ctx.repoRoot, ctx.home);
|
|
297
283
|
if (nearestProjectConfigDir) {
|
|
298
284
|
const projectPath = path.join(nearestProjectConfigDir.dir, "SYSTEM.md");
|
|
299
285
|
const projectContent = await readFile(projectPath);
|
|
@@ -321,7 +307,7 @@ registerProvider<SystemPrompt>(systemPromptCapability.id, {
|
|
|
321
307
|
// Skills
|
|
322
308
|
async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
323
309
|
// Walk up from cwd finding .gjc/skills/ in ancestors (closest first)
|
|
324
|
-
const ancestors = getAncestorDirs(ctx.cwd, ctx.repoRoot ?? ctx.home);
|
|
310
|
+
const ancestors = getAncestorDirs(ctx.cwd, ctx.repoRoot ?? ctx.home, ctx.home);
|
|
325
311
|
const projectScans = ancestors.flatMap(({ dir }) =>
|
|
326
312
|
getProjectConfigDirs().map(projectConfigDir =>
|
|
327
313
|
scanSkillsFromDir(ctx, {
|
|
@@ -333,15 +319,18 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
333
319
|
),
|
|
334
320
|
);
|
|
335
321
|
|
|
336
|
-
// User-level scan from the
|
|
337
|
-
|
|
322
|
+
// User-level scan from the selected agent-directory profile plus documented
|
|
323
|
+
// default-profile legacy scan roots.
|
|
324
|
+
const userAgentDir = resolveUserAgentDir(ctx);
|
|
325
|
+
const userScans = getUserSkillScanDirs(ctx.home, userAgentDir, ctx.profileAuthority).map(dir =>
|
|
338
326
|
scanSkillsFromDir(ctx, {
|
|
339
|
-
dir
|
|
327
|
+
dir,
|
|
328
|
+
authorityRoot: path.resolve(dir) === path.resolve(userAgentDir, "skills") ? userAgentDir : undefined,
|
|
340
329
|
providerId: PROVIDER_ID,
|
|
341
330
|
level: "user",
|
|
342
331
|
requireDescription: true,
|
|
343
332
|
}),
|
|
344
|
-
|
|
333
|
+
);
|
|
345
334
|
|
|
346
335
|
const results = await Promise.all([...projectScans, ...userScans]);
|
|
347
336
|
|
|
@@ -395,28 +384,36 @@ registerProvider<SlashCommand>(slashCommandCapability.id, {
|
|
|
395
384
|
async function loadRules(ctx: LoadContext): Promise<LoadResult<Rule>> {
|
|
396
385
|
const items: Rule[] = [];
|
|
397
386
|
const warnings: string[] = [];
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
387
|
+
const configDirs = await getConfigDirs(ctx);
|
|
388
|
+
const projectConfigDirs = configDirs.filter(({ level }) => level === "project");
|
|
389
|
+
const userConfigDirs = configDirs.filter(({ level }) => level === "user");
|
|
390
|
+
|
|
391
|
+
const loadRulesFromDirs = async (dirs: Array<{ dir: string; level: "user" | "project" }>) => {
|
|
392
|
+
for (const { dir, level } of dirs) {
|
|
393
|
+
const rulesDir = path.join(dir, "rules");
|
|
394
|
+
const result = await loadFilesFromDir<Rule>(ctx, rulesDir, PROVIDER_ID, level, {
|
|
395
|
+
extensions: ["md", "mdc"],
|
|
396
|
+
transform: (name, content, path, source) =>
|
|
397
|
+
buildRuleFromMarkdown(name, content, path, source, { stripNamePattern: /\.(md|mdc)$/ }),
|
|
398
|
+
});
|
|
399
|
+
items.push(...result.items);
|
|
400
|
+
if (result.warnings) warnings.push(...result.warnings);
|
|
401
|
+
}
|
|
402
|
+
};
|
|
409
403
|
|
|
410
404
|
// Top-level RULES.md is a sticky always-apply rule. The context-file
|
|
411
405
|
// discovery contract treats it as the file "re-injected near the current
|
|
412
406
|
// turn so they keep hold across long conversations".
|
|
413
|
-
// User scope:
|
|
407
|
+
// User scope: <agentDir>/RULES.md (a profile is a separate user scope;
|
|
408
|
+
// the default profile's home-relative copy is not read)
|
|
414
409
|
// Project scope: nearest .gjc/RULES.md walking up from cwd to repoRoot
|
|
410
|
+
await loadRulesFromDirs([...projectConfigDirs, ...userConfigDirs]);
|
|
411
|
+
|
|
415
412
|
const userRulesFile = path.join(resolveUserAgentDir(ctx), "RULES.md");
|
|
416
413
|
const userRule = await loadStickyRulesFile(userRulesFile, "user");
|
|
417
414
|
if (userRule) items.push(userRule);
|
|
418
415
|
|
|
419
|
-
const nearestProjectConfigDir = await findNearestProjectConfigDir(ctx.cwd, ctx.repoRoot);
|
|
416
|
+
const nearestProjectConfigDir = await findNearestProjectConfigDir(ctx.cwd, ctx.repoRoot, ctx.home);
|
|
420
417
|
if (nearestProjectConfigDir) {
|
|
421
418
|
const projectRulesFile = path.join(nearestProjectConfigDir.dir, "RULES.md");
|
|
422
419
|
const projectRule = await loadStickyRulesFile(projectRulesFile, "project");
|
|
@@ -431,7 +428,7 @@ async function loadRules(ctx: LoadContext): Promise<LoadResult<Rule>> {
|
|
|
431
428
|
* Returns null when the file is absent or empty so callers can short-circuit.
|
|
432
429
|
*/
|
|
433
430
|
async function loadStickyRulesFile(filePath: string, level: "user" | "project"): Promise<Rule | null> {
|
|
434
|
-
const content = await
|
|
431
|
+
const content = await readContainedFile(path.dirname(filePath), filePath);
|
|
435
432
|
if (!content) return null;
|
|
436
433
|
const source = createSourceMeta(PROVIDER_ID, filePath, level);
|
|
437
434
|
const rule = buildRuleFromMarkdown("RULES.md", content, filePath, source, { ruleName: "RULES" });
|
|
@@ -719,7 +716,7 @@ async function loadHooks(ctx: LoadContext): Promise<LoadResult<Hook>> {
|
|
|
719
716
|
const { typeDir, hookType, level } = typeDirRequests[i];
|
|
720
717
|
const typeEntries = typeEntriesResults[i];
|
|
721
718
|
|
|
722
|
-
for (const entry of typeEntries) {
|
|
719
|
+
for (const entry of [...typeEntries].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))) {
|
|
723
720
|
if (entry.name.startsWith(".")) continue;
|
|
724
721
|
if (!entry.isFile()) continue;
|
|
725
722
|
|
|
@@ -929,8 +926,8 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
929
926
|
const items: ContextFile[] = [];
|
|
930
927
|
const warnings: string[] = [];
|
|
931
928
|
|
|
932
|
-
const userPath = path.join(ctx
|
|
933
|
-
const userContent = await
|
|
929
|
+
const userPath = path.join(resolveUserAgentDir(ctx), "AGENTS.md");
|
|
930
|
+
const userContent = await readContainedFile(resolveUserAgentDir(ctx), userPath);
|
|
934
931
|
if (userContent) {
|
|
935
932
|
items.push({
|
|
936
933
|
path: userPath,
|
|
@@ -940,7 +937,7 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
940
937
|
});
|
|
941
938
|
}
|
|
942
939
|
|
|
943
|
-
const nearestProjectConfigDir = await findNearestProjectConfigDir(ctx.cwd, ctx.repoRoot);
|
|
940
|
+
const nearestProjectConfigDir = await findNearestProjectConfigDir(ctx.cwd, ctx.repoRoot, ctx.home);
|
|
944
941
|
if (nearestProjectConfigDir) {
|
|
945
942
|
const projectPath = path.join(nearestProjectConfigDir.dir, "AGENTS.md");
|
|
946
943
|
const projectContent = await readFile(projectPath);
|
|
@@ -17,6 +17,7 @@ import { rootContainsGjcManifest } from "../extensibility/gjc-plugins";
|
|
|
17
17
|
import {
|
|
18
18
|
type ClaudePluginRoot,
|
|
19
19
|
createSourceMeta,
|
|
20
|
+
invalidateClaudePluginRoots,
|
|
20
21
|
listClaudePluginRoots,
|
|
21
22
|
loadFilesFromDir,
|
|
22
23
|
scanSkillsFromDir,
|
|
@@ -95,12 +96,15 @@ async function resolvePluginDir(
|
|
|
95
96
|
async function listNonGjcPluginRoots(
|
|
96
97
|
home: string,
|
|
97
98
|
cwd: string,
|
|
99
|
+
allowedLevels: ReadonlySet<"user" | "project"> = new Set(["user", "project"]),
|
|
98
100
|
): Promise<{ roots: ClaudePluginRoot[]; warnings: string[] }> {
|
|
101
|
+
await invalidateClaudePluginRoots(home, cwd);
|
|
99
102
|
const { roots, warnings } = await listClaudePluginRoots(home, cwd);
|
|
100
103
|
const filteredRoots: ClaudePluginRoot[] = [];
|
|
101
|
-
const filteredWarnings = [...warnings];
|
|
104
|
+
const filteredWarnings = allowedLevels.size === 2 ? [...warnings] : [];
|
|
102
105
|
|
|
103
106
|
for (const root of roots) {
|
|
107
|
+
if (!allowedLevels.has(root.scope)) continue;
|
|
104
108
|
if (await rootContainsGjcManifest(root.path)) {
|
|
105
109
|
filteredWarnings.push(`[claude-plugins] Skipping gajae-code plugin root (binding-only): ${root.path}`);
|
|
106
110
|
continue;
|
|
@@ -115,11 +119,14 @@ async function listNonGjcPluginRoots(
|
|
|
115
119
|
// Skills
|
|
116
120
|
// =============================================================================
|
|
117
121
|
|
|
118
|
-
async function
|
|
122
|
+
export async function loadMarketplaceSkills(
|
|
123
|
+
ctx: LoadContext,
|
|
124
|
+
allowedLevels: ReadonlySet<"user" | "project"> = new Set(["user", "project"]),
|
|
125
|
+
): Promise<LoadResult<Skill>> {
|
|
119
126
|
const items: Skill[] = [];
|
|
120
127
|
const warnings: string[] = [];
|
|
121
128
|
|
|
122
|
-
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(ctx.home, ctx.cwd);
|
|
129
|
+
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(ctx.home, ctx.cwd, allowedLevels);
|
|
123
130
|
warnings.push(...rootWarnings);
|
|
124
131
|
|
|
125
132
|
const results = await Promise.all(
|
|
@@ -129,6 +136,7 @@ async function loadSkills(ctx: LoadContext): Promise<LoadResult<Skill>> {
|
|
|
129
136
|
dir: skillsDir,
|
|
130
137
|
providerId: PROVIDER_ID,
|
|
131
138
|
level: root.scope,
|
|
139
|
+
requireDescription: true,
|
|
132
140
|
});
|
|
133
141
|
return { root, result, warning };
|
|
134
142
|
}),
|
|
@@ -371,7 +379,7 @@ registerProvider<Skill>(skillCapability.id, {
|
|
|
371
379
|
displayName: DISPLAY_NAME,
|
|
372
380
|
description: "Load skills from GJC marketplace plugins",
|
|
373
381
|
priority: PRIORITY,
|
|
374
|
-
load:
|
|
382
|
+
load: loadMarketplaceSkills,
|
|
375
383
|
});
|
|
376
384
|
|
|
377
385
|
registerProvider<SlashCommand>(slashCommandCapability.id, {
|