@gajae-code/coding-agent 0.7.2 → 0.7.4

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 (154) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/bin/gjc.js +4 -0
  3. package/dist/types/cli/mcp-cli.d.ts +25 -0
  4. package/dist/types/cli/plugin-cli.d.ts +2 -0
  5. package/dist/types/cli.d.ts +6 -0
  6. package/dist/types/commands/mcp.d.ts +70 -0
  7. package/dist/types/commands/plugin.d.ts +6 -0
  8. package/dist/types/commands/session.d.ts +6 -0
  9. package/dist/types/config/keybindings.d.ts +2 -2
  10. package/dist/types/config/model-profile-activation.d.ts +8 -1
  11. package/dist/types/deep-interview/plaintext-gate-guard.d.ts +11 -0
  12. package/dist/types/extensibility/gjc-plugins/compiler.d.ts +19 -0
  13. package/dist/types/extensibility/gjc-plugins/constrained-hooks.d.ts +29 -0
  14. package/dist/types/extensibility/gjc-plugins/index.d.ts +9 -0
  15. package/dist/types/extensibility/gjc-plugins/injection.d.ts +9 -0
  16. package/dist/types/extensibility/gjc-plugins/installer.d.ts +13 -0
  17. package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +26 -0
  18. package/dist/types/extensibility/gjc-plugins/observability.d.ts +27 -0
  19. package/dist/types/extensibility/gjc-plugins/prompt-appendix.d.ts +16 -0
  20. package/dist/types/extensibility/gjc-plugins/registry.d.ts +32 -0
  21. package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +64 -0
  22. package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +42 -0
  23. package/dist/types/extensibility/gjc-plugins/types.d.ts +158 -2
  24. package/dist/types/extensibility/gjc-plugins/validation.d.ts +8 -1
  25. package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
  26. package/dist/types/gjc-runtime/psmux-detect.d.ts +78 -0
  27. package/dist/types/gjc-runtime/team-runtime.d.ts +2 -0
  28. package/dist/types/gjc-runtime/tmux-common.d.ts +20 -1
  29. package/dist/types/gjc-runtime/tmux-sessions.d.ts +18 -0
  30. package/dist/types/main.d.ts +2 -0
  31. package/dist/types/modes/components/custom-editor.d.ts +1 -1
  32. package/dist/types/modes/components/model-selector.d.ts +8 -0
  33. package/dist/types/modes/components/status-line/git-utils.d.ts +6 -0
  34. package/dist/types/modes/theme/defaults/index.d.ts +99 -0
  35. package/dist/types/notifications/html-format.d.ts +11 -0
  36. package/dist/types/notifications/index.d.ts +149 -1
  37. package/dist/types/notifications/lifecycle-commands.d.ts +72 -0
  38. package/dist/types/notifications/lifecycle-control-runtime.d.ts +98 -0
  39. package/dist/types/notifications/lifecycle-orchestrator.d.ts +144 -0
  40. package/dist/types/notifications/operator-runtime.d.ts +52 -0
  41. package/dist/types/notifications/rate-limit-pool.d.ts +2 -0
  42. package/dist/types/notifications/recent-activity.d.ts +35 -0
  43. package/dist/types/notifications/telegram-daemon.d.ts +114 -16
  44. package/dist/types/notifications/telegram-reference.d.ts +3 -1
  45. package/dist/types/notifications/topic-registry.d.ts +12 -9
  46. package/dist/types/runtime-mcp/types.d.ts +7 -0
  47. package/dist/types/sdk.d.ts +2 -0
  48. package/dist/types/session/agent-session.d.ts +14 -4
  49. package/dist/types/session/blob-store.d.ts +25 -0
  50. package/dist/types/session/session-manager.d.ts +57 -0
  51. package/dist/types/slash-commands/helpers/fast-status-report.d.ts +6 -0
  52. package/dist/types/system-prompt.d.ts +2 -0
  53. package/dist/types/task/executor.d.ts +9 -1
  54. package/dist/types/tools/composer-bash-policy.d.ts +14 -0
  55. package/dist/types/tools/index.d.ts +3 -1
  56. package/dist/types/utils/changelog.d.ts +1 -0
  57. package/dist/types/web/insane/url-guard.d.ts +6 -3
  58. package/dist/types/web/scrapers/types.d.ts +5 -0
  59. package/dist/types/web/scrapers/utils.d.ts +7 -1
  60. package/package.json +11 -9
  61. package/scripts/g004-tmux-smoke.ts +100 -0
  62. package/scripts/g005-daemon-smoke.ts +181 -0
  63. package/scripts/g011-daemon-path-smoke.ts +153 -0
  64. package/src/cli/mcp-cli.ts +272 -0
  65. package/src/cli/plugin-cli.ts +66 -3
  66. package/src/cli.ts +27 -6
  67. package/src/commands/mcp.ts +117 -0
  68. package/src/commands/plugin.ts +4 -0
  69. package/src/commands/session.ts +18 -0
  70. package/src/config/keybindings.ts +2 -2
  71. package/src/config/model-profile-activation.ts +55 -7
  72. package/src/deep-interview/plaintext-gate-guard.ts +94 -0
  73. package/src/defaults/gjc/extensions/grok-cli-vendor/biome.json +1 -1
  74. package/src/defaults/gjc/skills/deep-interview/SKILL.md +7 -6
  75. package/src/defaults/gjc/skills/team/SKILL.md +5 -3
  76. package/src/defaults/gjc/skills/ultragoal/SKILL.md +41 -13
  77. package/src/export/html/index.ts +2 -2
  78. package/src/extensibility/extensions/runner.ts +1 -0
  79. package/src/extensibility/gjc-plugins/compiler.ts +351 -0
  80. package/src/extensibility/gjc-plugins/constrained-hooks.ts +170 -0
  81. package/src/extensibility/gjc-plugins/index.ts +9 -0
  82. package/src/extensibility/gjc-plugins/injection.ts +109 -0
  83. package/src/extensibility/gjc-plugins/installer.ts +434 -0
  84. package/src/extensibility/gjc-plugins/loader.ts +3 -1
  85. package/src/extensibility/gjc-plugins/mcp-policy.ts +239 -0
  86. package/src/extensibility/gjc-plugins/observability.ts +84 -0
  87. package/src/extensibility/gjc-plugins/paths.ts +1 -1
  88. package/src/extensibility/gjc-plugins/prompt-appendix.ts +109 -0
  89. package/src/extensibility/gjc-plugins/registry.ts +180 -0
  90. package/src/extensibility/gjc-plugins/runtime-adapters.ts +234 -0
  91. package/src/extensibility/gjc-plugins/schema.ts +250 -20
  92. package/src/extensibility/gjc-plugins/session-validation.ts +147 -0
  93. package/src/extensibility/gjc-plugins/types.ts +199 -3
  94. package/src/extensibility/gjc-plugins/validation.ts +80 -0
  95. package/src/extensibility/skills.ts +15 -0
  96. package/src/gjc-runtime/launch-tmux.ts +61 -7
  97. package/src/gjc-runtime/psmux-detect.ts +239 -0
  98. package/src/gjc-runtime/team-runtime.ts +56 -23
  99. package/src/gjc-runtime/tmux-common.ts +30 -3
  100. package/src/gjc-runtime/tmux-sessions.ts +51 -1
  101. package/src/gjc-runtime/ultragoal-guard.ts +25 -8
  102. package/src/gjc-runtime/ultragoal-runtime.ts +75 -15
  103. package/src/hooks/skill-state.ts +57 -0
  104. package/src/internal-urls/docs-index.generated.ts +12 -8
  105. package/src/main.ts +14 -3
  106. package/src/modes/bridge/bridge-mode.ts +11 -0
  107. package/src/modes/components/custom-editor.ts +2 -0
  108. package/src/modes/components/footer.ts +2 -3
  109. package/src/modes/components/hook-editor.ts +1 -1
  110. package/src/modes/components/hook-selector.ts +67 -43
  111. package/src/modes/components/model-selector.ts +56 -11
  112. package/src/modes/components/status-line/git-utils.ts +25 -0
  113. package/src/modes/components/status-line.ts +10 -11
  114. package/src/modes/components/welcome.ts +2 -3
  115. package/src/modes/controllers/extension-ui-controller.ts +0 -27
  116. package/src/modes/controllers/selector-controller.ts +53 -11
  117. package/src/modes/interactive-mode.ts +4 -1
  118. package/src/modes/shared/agent-wire/scopes.ts +1 -1
  119. package/src/modes/theme/defaults/gruvbox-dark.json +99 -0
  120. package/src/modes/theme/defaults/index.ts +2 -0
  121. package/src/modes/utils/hotkeys-markdown.ts +1 -1
  122. package/src/notifications/html-format.ts +38 -0
  123. package/src/notifications/index.ts +242 -12
  124. package/src/notifications/lifecycle-commands.ts +228 -0
  125. package/src/notifications/lifecycle-control-runtime.ts +400 -0
  126. package/src/notifications/lifecycle-orchestrator.ts +358 -0
  127. package/src/notifications/operator-runtime.ts +171 -0
  128. package/src/notifications/rate-limit-pool.ts +19 -0
  129. package/src/notifications/recent-activity.ts +132 -0
  130. package/src/notifications/telegram-daemon.ts +778 -257
  131. package/src/notifications/telegram-reference.ts +25 -7
  132. package/src/notifications/topic-registry.ts +23 -9
  133. package/src/prompts/agents/executor.md +2 -2
  134. package/src/runtime-mcp/transports/stdio.ts +38 -4
  135. package/src/runtime-mcp/types.ts +7 -0
  136. package/src/sdk.ts +157 -10
  137. package/src/session/agent-session.ts +166 -74
  138. package/src/session/blob-store.ts +196 -8
  139. package/src/session/session-manager.ts +678 -7
  140. package/src/slash-commands/builtin-registry.ts +23 -3
  141. package/src/slash-commands/helpers/fast-status-report.ts +13 -3
  142. package/src/slash-commands/helpers/parse.ts +2 -1
  143. package/src/system-prompt.ts +9 -0
  144. package/src/task/executor.ts +31 -7
  145. package/src/task/index.ts +2 -0
  146. package/src/tools/ask.ts +5 -1
  147. package/src/tools/bash.ts +9 -0
  148. package/src/tools/composer-bash-policy.ts +96 -0
  149. package/src/tools/fetch.ts +18 -2
  150. package/src/tools/index.ts +3 -1
  151. package/src/utils/changelog.ts +8 -0
  152. package/src/web/insane/url-guard.ts +18 -14
  153. package/src/web/scrapers/types.ts +143 -45
  154. package/src/web/scrapers/utils.ts +70 -19
package/CHANGELOG.md CHANGED
@@ -2,6 +2,91 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.7.4] - 2026-06-27
6
+
7
+ ### Added
8
+
9
+ - Native Windows `gjc --tmux` is now backed by [psmux](https://github.com/psmux/psmux) when no real tmux is on PATH: a new `psmux-detect` module probes `psmux` / `pmux` / `tmux` on Windows and resolves the multiplexer to use, `tmux-common.ts` re-exports the resolver for downstream callers, and `buildDefaultTmuxLaunchPlan` builds a real PowerShell-encoded `--tmux` plan instead of falling through to the direct-launch diagnostic. The native Windows `gjc session` / `gjc team` ownership-tag and worker-spawn paths therefore work end-to-end on a Windows host with psmux installed (no WSL required).
10
+ - Three new environment knobs back the Windows psmux path: `GJC_PSMUX_COMMAND` (force the multiplexer to be treated as psmux), `GJC_PSMUX_DETECTION` (`off` / `false` to skip probing entirely), and `GJC_PSMUX_FORCE_DETECT` (`1` / `true` to re-probe on every call). `GJC_TMUX_COMMAND` and `GJC_TEAM_TMUX_COMMAND` continue to override the multiplexer selection on every platform.
11
+ - Implemented a GJC plugin bundle architecture: `gjc plugin install <path|package>` resolves and installs declarative GJC plugin bundles into user/project scope with a content-addressed registry (per-file SHA-256 manifest hashes), and `gjc plugin list|doctor|enable|disable|uninstall` manage them; local-path bundles install offline without npm (#1149).
12
+ - Added Telegram-driven session lifecycle control so sessions can be created, closed, and resumed from Telegram, with per-session topic management wired into connect and shutdown (#1148).
13
+ - Added a keyless `insane` web search provider that safely ports upstream [`fivetaku/insane-search`](https://github.com/fivetaku/insane-search) public-route fallbacks (MIT; vendored engine pinned in `packages/coding-agent/vendor/insane-search/`) without TLS impersonation, browser/cookie bypasses, credential storage, or auto-installed dependencies (#1011).
14
+ - Added durable cold-spill eviction for compacted session history: after a compaction, `SessionManager.evictCompactedContent()` moves pre-`firstKeptEntryId` payloads (user/assistant text, thinking, tool-call arguments) out of the hot JSONL and resident heap into durable content-addressed sidecar blobs via `BlobStore.putImmutableSync`, keeping hot retained bytes bounded regardless of pre-compaction history size while preserving graph integrity and the compaction summary (#1166).
15
+ - Added a non-materializing, path-only `buildSessionContext()` that no longer populates `#materializedEntriesCache` and performs zero cold-spill reads on covered compacted branches, plus fidelity read APIs (`getEntryForFidelity`/`getBranchForFidelity`/`getEntriesForExport`) that rehydrate cold-spilled content on demand for HTML export, branch & re-edit, and branched-session creation (#1166).
16
+ - Added `BlobStore.putImmutableSync`/`getCheckedSync` (plus `EphemeralBlobStore`/`MemoryBlobStore` overrides): immutable, crash-safe, hash-verified content-addressed install (exclusive copy fallback + fsync) and checked reads that throw `BlobCorruptError` on corrupt blobs and never return silent wrong data (#1166).
17
+ - Raised the `deep-interview` default maximum round count to 100.
18
+ - New unit tests under `packages/coding-agent/test/gjc-runtime/psmux-detect.test.ts` cover detection verdicts, override precedence, cache behavior, and the `resolveGjcTmuxBinary` Windows / POSIX resolution paths.
19
+
20
+ ### Changed
21
+
22
+ - `gjc team` now adopts any real tmux session as its leader — including one you started yourself outside `gjc --tmux` — by writing and reading back GJC's `@gjc-profile` ownership tag, instead of only accepting `gjc --tmux`-launched sessions. Providers that cannot round-trip tmux user options (e.g. psmux) are still rejected as unmanaged (#1140).
23
+ - `gjc team` now fails with actionable guidance when there is no tmux leader to host workers: running it with no tmux installed reports `tmux_not_installed`, and running it outside any tmux session reports `not_inside_tmux` (with a hint to start one via `gjc --tmux` or your own `tmux`, or use `--dry-run`), instead of surfacing raw tmux stderr (#1143).
24
+ - Improved `ultragoal` artifact-gate guidance in the completion quality gate (#1163).
25
+
26
+ ### Fixed
27
+
28
+ - First-time `gjc` startup now shows only the installed/current version changelog entry instead of dumping the full historical changelog before the actionable UI; full history remains available through `/changelog --full` (#1184).
29
+ - `gjc --tmux` on native Windows no longer silently falls through to a tmux-less launch: when psmux is installed the plan now boots gjc through a PowerShell-encoded inner command, when no tmux-class binary resolves on PATH the diagnostic points at the psmux install URL and `GJC_TMUX_COMMAND` override, and explicit `GJC_TMUX_COMMAND` overrides are honored on every platform.
30
+ - The `gjc team` worker-command string is now formatted for the host shell: on Windows + psmux each env assignment uses the `$env:VAR = 'value';` PowerShell form (with PowerShell-safe single-quote escaping) instead of the POSIX `VAR='value'` form, so worker panes spawned via psmux ConPTY panes inherit the right `GJC_TEAM_*` environment.
31
+ - `createGjcTmuxSession` now chooses the new-session bootstrap command for the host shell: PowerShell `$env:GJC_TMUX_LAUNCHED = '1'; gjc` on Windows, `exec env GJC_TMUX_LAUNCHED=1 gjc` on POSIX, so psmux-managed sessions tag the spawned gjc the same way tmux-managed ones do.
32
+ - `applyGjcTmuxProfile` no longer hard-fails the `gjc --tmux` boot on Windows when psmux drops the UX profile round-trip. When the resolved multiplexer is psmux, only the `mouse` / `set-clipboard` / `mode-style` UX keys are filtered out; the `@gjc-profile` / branch / project / session-identity ownership tags are still emitted because those are required for `gjc session` and `gjc team`.
33
+ - `renameExistingTmuxWindowIfNeeded` no longer short-circuits on `platform === "win32"`: on a Windows host running psmux inside `gjc --tmux`, the leader window now inherits the project:branch title the same way it does on POSIX.
34
+ - Fixed tmux startup fast paths (#1142).
35
+ - Deep Interview (and any scrollable `ask`/hook selector) no longer enables SGR mouse reporting, which was hijacking the mouse wheel and disabling the terminal's native scrollback while a question was on screen. The wheel now scrolls the terminal as usual; long questions still scroll inside the dialog via PgUp/PgDn (#1164).
36
+ - Scrollable Deep Interview question boxes now show explicit `▲ more` / `▼ more` affordances when hidden question text exists, and selector mode also supports Ctrl+u/Ctrl+d as question-scroll aliases for PgUp/PgDn (#1164).
37
+ - Fixed unbounded memory growth in long sessions: the full verbatim transcript was retained in `SessionManager.#fileEntries`/`#byId` forever across compactions (compaction only summarized the LLM-bound context), so long coding sessions could OOM. Compaction now reclaims hot resident content via cold-spill, the `AgentSession.compact()` post-append path no longer bulk-materializes the branch, and assistant tool-call arguments/text are no longer kept verbatim indefinitely (#1166).
38
+ - Lossless branch/export fidelity after compaction: HTML export and branch & re-edit now rehydrate cold-spilled pre-compaction content instead of showing tombstone notices, and branched-session creation preserves cold-spill refs without truncating >500k-char content (#1166).
39
+ - Materialize resident blobs before branch export so exported branches never reference unresolved resident blob refs.
40
+ - Inherit the live fast-mode (`serviceTier`) into task subagents so delegated work uses the parent session's service tier (#1171).
41
+ - Fixed model selection after model-profile preset activation so the activated preset's model is actually used (#1172).
42
+ - Preserve session-only model-profile overrides instead of dropping them on later resolution (#1175).
43
+ - Fixed the `gjc ultragoal checkpoint` goal-snapshot fallback so checkpoints reconcile correctly when a fresh snapshot is unavailable (#1177).
44
+ - Added durable `gjc-session` diagnostics for the routed-session harness scripts (#1189).
45
+ - Telegram: apply verbosity commands (#1139), fix clarify-choice rendering (#1147), create the session topic on connect, and delete session topics on shutdown.
46
+
47
+ ### Documentation
48
+
49
+ - The native Windows psmux section in `docs/environment-variables.md` now reflects that `gjc --tmux` builds a real tmux-backed plan via psmux, lists the new `GJC_PSMUX_*` knobs, and explains the worker-spawn shell-quoting rule. The bundled `team` skill doc points readers at the same environment section instead of the legacy "psmux is not fully supported" warning.
50
+ - Clarified Windows tmux fallback guidance.
51
+ - Credited `fivetaku/insane-search` for the ported public-route search fallbacks.
52
+
53
+ ## [0.7.3] - 2026-06-25
54
+
55
+ ### Added
56
+
57
+ - Added the `gruvbox-dark` built-in theme: the canonical Gruvbox dark palette mapped across every GJC theme token, selectable via `/theme`.
58
+ - Added a standalone MCP registration command: `gjc mcp add|list|remove` writes explicit user-provided MCP server definitions (stdio/http/sse) into GJC config without importing or inheriting other tools' live MCP configs, with env/header/auth values redacted in output (#1095).
59
+
60
+ ### Changed
61
+
62
+ - Refined the interactive composer chrome so the input box, status rail, and welcome banner share one visual language: the composer now uses a rounded border (matching the rounded welcome banner) instead of a sharp rectangle, and the status rail uses the subtle elevated `userMessageBg` surface tone instead of the heavy `statusLineBg` block, so it reads as a quiet layered zone rather than a solid bar. Both resolve through existing semantic theme slots, so every bundled theme tracks automatically.
63
+ - When a Composer harness model is active, the `bash` tool now hard-blocks repository file I/O — pipes, process/heredoc/command substitution, redirection, `tee`, file read/discovery (`cat`/`head`/`tail`/`grep`/`find`/`ls`), file mutation (`cp`/`mv`/`rm`/`touch`/`mkdir`/`chmod`/`ln`), `sed`/`awk`, git file-read subcommands, and script file I/O — unless the command is on a strict allowlist (`bun test`/`run check|test|build`, `cargo test|check|build`, `git status`/`rev-parse`, package version queries), forcing Composer models to use the dedicated find/search/read/edit tools for file discovery and mutation (#1027).
64
+ ### Documentation
65
+
66
+ - Documented the docs-only Aside evaluation boundary as an opt-in search/context retrieval sidecar using explicit user-provided MCP configuration, with browser actions, login flows, payments, internal tools, secrets, and raw browser/session payload logging out of scope by default (#1097).
67
+ - Added a UI design and visual QA contract governing future TUI/dashboard/terminal visual work (#1101).
68
+ - Added a CodeGraph custom-tool integration guide (#1073).
69
+ - Documented the Windows psmux namespace boundary for `gjc --tmux`, `gjc session`, and `gjc team`: cwd/`-c` is now called out as a start directory rather than server isolation, `-L <namespace>` is identified as the psmux namespace primitive, and tmux command overrides are documented as executable names rather than shell command lines (#1118).
70
+ - Clarified the Telegram Threaded Mode fallback documentation (#1122).
71
+
72
+ ### Fixed
73
+
74
+ - Expanded the initial GJC forge welcome box to the live terminal viewport width and pinned the status/composer area to the bottom when the startup layout is shorter than the screen (#1120).
75
+
76
+ - Deep Interview Restate/option gates now recover through the ask selector path instead of waiting on plaintext `Options:` output.
77
+ - Widened the forge splash on wide terminals so it no longer clips (#1110).
78
+ - Parse quoted SSH remote host names in the slash-command host parser (#1104).
79
+ - Tolerate an unreadable git HEAD in the status chrome instead of throwing (#1072).
80
+ - Registered the `plugin` command in the CLI command registry so `gjc plugin …` (install/uninstall/list/marketplace/enable/disable/doctor) resolves instead of silently falling through to the default launch/chat command — the command was implemented and tested but was never registered (#1071).
81
+ - Keybinding/Ctrl+Enter newline-handling sweep across the editor and input controller (#1111).
82
+ - Fixed model-profile default badge precedence in the `/model` selector so the correct default-profile badge wins (#1117).
83
+ - Prevented duplicate Telegram topics being created for transient sessions (#1125).
84
+
85
+ ### Security
86
+
87
+ - User-supplied URL reads now share the public HTTP(S) network guard that was previously insane-fallback-only: the initial target, the redirect chain, and binary-conversion redirects are all revalidated against private-network blocking before any request is opened or followed, closing an SSRF path through the normal read-tool fetch pipeline (#1114).
88
+ - Bridge workflow-gate responses now require the claimed controller token before the unattended control plane may resolve a gate, and the `workflow_gate_response` RPC command was raised from prompt scope to control scope, so prompt-only clients can no longer answer lifecycle workflow gates (#1116).
89
+
5
90
  ## [0.7.2] - 2026-06-24
6
91
  ### Added
7
92
 
@@ -19,6 +104,7 @@
19
104
  - Preserve GJC-managed tmux sessions on attach/disconnect instead of tearing them down, and stop implicitly attaching on launch (#1063).
20
105
  - Corrected the auto-compaction output reserve so post-compaction responses keep adequate headroom (#1021).
21
106
  - Improved active-input shortcut hints and the busy-input queueing hint for clearer in-session guidance (#1022, #1024).
107
+ - Fixed the Ultragoal ask guard blocking the `ask` tool when no GJC session can be resolved. `ultragoalReadPaths` falls back to the legacy/global `.gjc/ultragoal` directory when neither `GJC_SESSION_ID` nor an auto-detectable active session is present, but the follow-up `readUltragoalPlan`/`readUltragoalLedger` reads ignored that resolution and re-ran session detection, throwing `no active GJC session found` and surfacing `durable_state_unreadable` — which blocked `ask` for every agent even with no active Ultragoal run. `ultragoalReadPaths` now returns the resolved session id (or `null`); the ask guard treats a null session as inactive and falls open, and threads the resolved id into the plan/ledger reads so they no longer re-resolve. An inconsistent state (state dir present but `goals.json` missing/empty) still fails closed so the pause guard keeps blocking give-ups.
22
108
 
23
109
  ## [0.7.1] - 2026-06-23
24
110
  ### Fixed
package/bin/gjc.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bun
2
+ import { runCli } from "@gajae-code/coding-agent/cli";
3
+
4
+ await runCli(process.argv.slice(2));
@@ -0,0 +1,25 @@
1
+ import type { MCPServerConfig } from "../runtime-mcp/types";
2
+ export type MCPAction = "add" | "list" | "remove";
3
+ export interface MCPCommandArgs {
4
+ action: MCPAction;
5
+ name?: string;
6
+ commandArgs?: string[];
7
+ flags: {
8
+ project?: boolean;
9
+ force?: boolean;
10
+ json?: boolean;
11
+ type?: "stdio" | "http" | "sse";
12
+ command?: string;
13
+ url?: string;
14
+ arg?: string[];
15
+ env?: string[];
16
+ header?: string[];
17
+ cwd?: string;
18
+ timeout?: number;
19
+ };
20
+ cwd?: string;
21
+ }
22
+ export declare class MCPArgsError extends Error {
23
+ }
24
+ export declare function redactMCPServerConfig(config: MCPServerConfig): MCPServerConfig;
25
+ export declare function runMCPCommand(args: MCPCommandArgs): Promise<void>;
@@ -17,6 +17,8 @@ export interface PluginCommandArgs {
17
17
  disable?: string;
18
18
  set?: string;
19
19
  scope?: "user" | "project";
20
+ user?: boolean;
21
+ project?: boolean;
20
22
  };
21
23
  }
22
24
  /**
@@ -1,3 +1,9 @@
1
1
  #!/usr/bin/env bun
2
+ /**
3
+ * CLI entry point — registers all commands explicitly and delegates to the
4
+ * lightweight CLI runner from pi-utils.
5
+ */
6
+ import { type CommandEntry } from "@gajae-code/utils/cli";
7
+ export declare const commands: CommandEntry[];
2
8
  /** Run the CLI with the given argv (no `process.argv` prefix). */
3
9
  export declare function runCli(argv: string[]): Promise<void>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Direct MCP server registration for standalone GJC.
3
+ */
4
+ import { Command } from "@gajae-code/utils/cli";
5
+ import { type MCPAction } from "../cli/mcp-cli";
6
+ export default class MCP extends Command {
7
+ static description: string;
8
+ static delegateHelp: boolean;
9
+ static examples: string[];
10
+ static args: {
11
+ action: import("@gajae-code/utils/cli").ArgDescriptor & {
12
+ description: string;
13
+ required: false;
14
+ options: MCPAction[];
15
+ };
16
+ name: import("@gajae-code/utils/cli").ArgDescriptor & {
17
+ description: string;
18
+ required: false;
19
+ };
20
+ commandArgs: import("@gajae-code/utils/cli").ArgDescriptor & {
21
+ description: string;
22
+ required: false;
23
+ multiple: true;
24
+ };
25
+ };
26
+ static flags: {
27
+ project: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
28
+ description: string;
29
+ };
30
+ force: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
31
+ description: string;
32
+ default: boolean;
33
+ };
34
+ json: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
35
+ char: string;
36
+ description: string;
37
+ default: boolean;
38
+ };
39
+ type: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
40
+ description: string;
41
+ options: string[];
42
+ };
43
+ command: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
44
+ description: string;
45
+ };
46
+ url: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
47
+ description: string;
48
+ };
49
+ arg: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
50
+ description: string;
51
+ multiple: true;
52
+ };
53
+ env: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
54
+ description: string;
55
+ multiple: true;
56
+ };
57
+ header: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
58
+ description: string;
59
+ multiple: true;
60
+ };
61
+ cwd: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
62
+ description: string;
63
+ };
64
+ timeout: import("@gajae-code/utils/cli").FlagDescriptor<"integer"> & {
65
+ description: string;
66
+ };
67
+ };
68
+ run(): Promise<void>;
69
+ private printHelp;
70
+ }
@@ -47,6 +47,12 @@ export default class Plugin extends Command {
47
47
  description: string;
48
48
  options: string[];
49
49
  };
50
+ user: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
51
+ description: string;
52
+ };
53
+ project: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
54
+ description: string;
55
+ };
50
56
  };
51
57
  run(): Promise<void>;
52
58
  }
@@ -18,6 +18,12 @@ export default class Session extends Command {
18
18
  description: string;
19
19
  default: boolean;
20
20
  };
21
+ "session-id": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
22
+ description: string;
23
+ };
24
+ "state-file": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
25
+ description: string;
26
+ };
21
27
  };
22
28
  static examples: string[];
23
29
  run(): Promise<void>;
@@ -230,8 +230,8 @@ export declare const KEYBINDINGS: {
230
230
  readonly description: "Open external editor";
231
231
  };
232
232
  readonly "app.message.followUp": {
233
- readonly defaultKeys: "ctrl+enter";
234
- readonly description: "Send follow-up message";
233
+ readonly defaultKeys: [];
234
+ readonly description: "Send follow-up message (no default; Ctrl+Enter inserts a newline)";
235
235
  };
236
236
  readonly "app.message.queue": {
237
237
  readonly defaultKeys: "alt+enter";
@@ -1,7 +1,7 @@
1
1
  import type { ThinkingLevel } from "@gajae-code/agent-core";
2
2
  import type { Api, Model } from "@gajae-code/ai";
3
3
  import type { AgentSession } from "../session/agent-session";
4
- import { type ModelRegistry } from "./model-registry";
4
+ import { type GjcModelAssignmentTargetId, type ModelRegistry } from "./model-registry";
5
5
  import type { Settings } from "./settings";
6
6
  type ModelProfileActivationSession = Pick<AgentSession, "model" | "thinkingLevel" | "sessionId"> & {
7
7
  setModelTemporary?: AgentSession["setModelTemporary"];
@@ -40,6 +40,13 @@ export interface PreparedModelProfileActivation {
40
40
  */
41
41
  previousSessionDefaultModel: string | undefined;
42
42
  }
43
+ export interface MaterializeModelProfileAssignmentOptions {
44
+ session: Pick<ModelProfileActivationSession, "model" | "thinkingLevel" | "setActiveModelProfile" | "getActiveModelProfile">;
45
+ settings: Pick<Settings, "clearOverride" | "get" | "override" | "set">;
46
+ role: GjcModelAssignmentTargetId;
47
+ selector: string;
48
+ }
49
+ export declare function materializeActiveModelProfileAssignment(options: MaterializeModelProfileAssignmentOptions): boolean;
43
50
  export declare function formatModelProfileCredentialError(profileName: string, providers: readonly string[]): string;
44
51
  export declare function prepareModelProfileActivation(options: PrepareModelProfileActivationOptions): Promise<PreparedModelProfileActivation>;
45
52
  export declare function applyPreparedModelProfileActivation(prepared: PreparedModelProfileActivation, options?: {
@@ -0,0 +1,11 @@
1
+ export type DeepInterviewPlaintextAskLeakOption = "Yes, crystallize" | "Adjust wording" | "Missing scope";
2
+ export type DeepInterviewPlaintextAskLeakResult = {
3
+ kind: "deep_interview_plaintext_ask_leak";
4
+ matchedOptions: DeepInterviewPlaintextAskLeakOption[];
5
+ signals: {
6
+ optionsHeading: true;
7
+ restateIntent: true;
8
+ deepInterviewContext: boolean;
9
+ };
10
+ };
11
+ export declare function detectDeepInterviewPlaintextAskLeak(text: string): DeepInterviewPlaintextAskLeakResult | null;
@@ -0,0 +1,19 @@
1
+ import { type NormalizedGjcPluginBundle } from "./types";
2
+ /**
3
+ * Stable surface extension-id builders. Kept here so install, runtime, and
4
+ * observability all derive identical ids.
5
+ */
6
+ export declare const surfaceIds: {
7
+ readonly tool: (name: string) => string;
8
+ readonly hook: (event: string, phase: string | undefined, target: string | undefined, name: string) => string;
9
+ readonly mcp: (name: string) => string;
10
+ readonly systemAppendix: (plugin: string, name: string) => string;
11
+ readonly agentAppendix: (agent: string, plugin: string, name: string) => string;
12
+ readonly subskill: (parent: string, phase: string, activationArg: string) => string;
13
+ };
14
+ /**
15
+ * Pure compile step: reads only the manifest, subskill frontmatter, and
16
+ * declared files (as bytes for hashing/existence). It NEVER imports or executes
17
+ * plugin tool/hook code.
18
+ */
19
+ export declare function compileGjcPluginBundle(root: string): Promise<NormalizedGjcPluginBundle>;
@@ -0,0 +1,29 @@
1
+ import { type SessionQuarantine } from "./session-validation";
2
+ /**
3
+ * Constrained plugin-hook loader.
4
+ *
5
+ * Third-party plugin hooks are NOT given the broad first-party HookAPI. They
6
+ * receive a restricted API that can only register a handler for their declared
7
+ * event; every session-mutation / command / shell capability throws
8
+ * security_policy. After the factory runs we verify it registered exactly the
9
+ * declared event (and nothing else), or the hook is quarantined.
10
+ */
11
+ export interface ConstrainedPluginHook {
12
+ plugin: string;
13
+ event: string;
14
+ target?: string;
15
+ phase?: "before" | "after";
16
+ handler: (...args: any[]) => unknown;
17
+ }
18
+ export interface ConstrainedHookLoadResult {
19
+ hooks: ConstrainedPluginHook[];
20
+ quarantine: SessionQuarantine[];
21
+ }
22
+ /**
23
+ * Load all always-on constrained plugin hooks for the effective registry at
24
+ * `cwd`, applying hash-drift + collision quarantine first. Returns empty when
25
+ * no plugins are installed.
26
+ */
27
+ export declare function loadConstrainedPluginHooks(input: {
28
+ cwd: string;
29
+ }): Promise<ConstrainedHookLoadResult>;
@@ -1,8 +1,17 @@
1
1
  export * from "./activation";
2
+ export * from "./compiler";
3
+ export * from "./constrained-hooks";
2
4
  export * from "./injection";
5
+ export * from "./installer";
3
6
  export * from "./loader";
7
+ export * from "./mcp-policy";
8
+ export * from "./observability";
4
9
  export * from "./paths";
10
+ export * from "./prompt-appendix";
11
+ export * from "./registry";
12
+ export * from "./runtime-adapters";
5
13
  export * from "./schema";
14
+ export * from "./session-validation";
6
15
  export * from "./state";
7
16
  export * from "./tools";
8
17
  export * from "./types";
@@ -29,3 +29,12 @@ export declare function buildAgentSubskillInjection(input: {
29
29
  sessionId?: string;
30
30
  agentName: string;
31
31
  }): Promise<string>;
32
+ import type { GjcPluginRegistryEntry } from "./types";
33
+ /**
34
+ * Tier-1 advertisement for a workflow parent skill: bounded, metadata-only list
35
+ * of installed sub-skills bound to `parent`, rendered ONLY in that parent's
36
+ * prompt (never the global public-workflow-surface). No body content.
37
+ */
38
+ export declare function buildSubskillAdvertisement(entries: readonly GjcPluginRegistryEntry[], parent: string, phase?: string): string;
39
+ /** Tier-1 advertisement for a role-agent parent. */
40
+ export declare function buildAgentSubskillAdvertisement(entries: readonly GjcPluginRegistryEntry[], agentName: string): string;
@@ -0,0 +1,13 @@
1
+ import { type GjcPluginRegistryEntry, type GjcPluginScope } from "./types";
2
+ export interface InstallGjcPluginOptions {
3
+ scope: GjcPluginScope;
4
+ cwd: string;
5
+ force?: boolean;
6
+ }
7
+ export interface InstallGjcPluginResult {
8
+ status: "installed" | "updated" | "unchanged";
9
+ entry: GjcPluginRegistryEntry;
10
+ }
11
+ export declare function installGjcPluginBundle(source: string, options: InstallGjcPluginOptions): Promise<InstallGjcPluginResult>;
12
+ /** True only when the source actually resolves to a GJC plugin bundle (root gajae-plugin.json). */
13
+ export declare function isGjcPluginBundleSource(source: string): Promise<boolean>;
@@ -0,0 +1,26 @@
1
+ import { type GjcPluginMcpManifestEntry } from "./types";
2
+ export declare function isDeniedIpv4(host: string): boolean;
3
+ export declare function isDeniedIpv6(host: string): boolean;
4
+ /**
5
+ * Synchronous URL policy (scheme, credentials, host literal ranges). Used for
6
+ * the primary endpoint and any redirect/token/discovery URL.
7
+ */
8
+ export declare function assertUrlAllowed(rawUrl: string, label?: string): URL;
9
+ /** Reject headers with control characters / CRLF injection. */
10
+ export declare function assertHeadersAllowed(headers: Record<string, string> | undefined): void;
11
+ /**
12
+ * Runtime DNS check: resolve the host and ensure no resolved address falls in a
13
+ * denied range (covers DNS rebinding when re-run before each connect).
14
+ */
15
+ export declare function assertDnsResolvesPublic(hostname: string, label?: string): Promise<void>;
16
+ export interface StdioPolicyContext {
17
+ pluginRoot: string;
18
+ }
19
+ /** stdio launcher/path confinement policy. */
20
+ export declare function assertStdioAllowed(entry: GjcPluginMcpManifestEntry, ctx: StdioPolicyContext): void;
21
+ /**
22
+ * Install-time MCP policy (no network required). Validates scheme/host literals
23
+ * and stdio confinement. Runtime connect additionally calls
24
+ * assertDnsResolvesPublic and re-validates redirect/token URLs.
25
+ */
26
+ export declare function assertMcpInstallPolicy(entry: GjcPluginMcpManifestEntry, ctx: StdioPolicyContext): void;
@@ -0,0 +1,27 @@
1
+ import type { GjcPluginRegistryEntry, GjcPluginScope } from "./types";
2
+ /**
3
+ * Observability for GJC plugin bundle surfaces, consumable by the extension
4
+ * dashboard / state manager. Each surface row carries its stable extension id,
5
+ * owning plugin, scope, source kind, enabled/disabled/quarantined status, and a
6
+ * content hash. MCP auth/header values are NEVER included.
7
+ */
8
+ export type PluginSurfaceStatus = "enabled" | "disabled" | "quarantined";
9
+ export interface PluginSurfaceRow {
10
+ extensionId: string;
11
+ kind: "tool" | "hook" | "mcp" | "system-appendix" | "agent-appendix" | "subskill";
12
+ plugin: string;
13
+ scope: GjcPluginScope;
14
+ sourceKind: GjcPluginRegistryEntry["source"]["kind"];
15
+ status: PluginSurfaceStatus;
16
+ hash: string;
17
+ quarantineCode?: string;
18
+ }
19
+ export interface PluginObservabilitySummary {
20
+ plugins: number;
21
+ surfaces: PluginSurfaceRow[];
22
+ }
23
+ /**
24
+ * Build the observability summary for the effective registry at `cwd`, including
25
+ * hash-drift and session-collision quarantine status.
26
+ */
27
+ export declare function summarizeGjcPluginObservability(cwd: string): Promise<PluginObservabilitySummary>;
@@ -0,0 +1,16 @@
1
+ import type { GjcPluginRegistryEntry, GjcSubskillParentAgent } from "./types";
2
+ export interface RenderedPluginAppendices {
3
+ /** Combined system-appendix block text (empty if none). */
4
+ system: string;
5
+ /** Per-agent appendix block text. */
6
+ byAgent: Map<GjcSubskillParentAgent, string>;
7
+ /** Stable digest of all rendered appendix content + identities (for cache/refresh). */
8
+ digest: string;
9
+ }
10
+ /**
11
+ * Build appendix blocks from the active, enabled registry entries in their
12
+ * deterministic order. Per-appendix and total size caps are enforced
13
+ * fail-closed (oversize content is dropped with a marker, never silently
14
+ * truncated into the prompt as authoritative text).
15
+ */
16
+ export declare function renderPluginAppendices(entries: readonly GjcPluginRegistryEntry[]): Promise<RenderedPluginAppendices>;
@@ -0,0 +1,32 @@
1
+ import { type GjcPluginRegistry, type GjcPluginRegistryEntry, type GjcPluginScope } from "./types";
2
+ export declare function registryRootForScope(scope: GjcPluginScope, cwd: string): string;
3
+ export declare function registryPathForScope(scope: GjcPluginScope, cwd: string): string;
4
+ /**
5
+ * Deterministic ordering: scope (user before project) -> normalized name ->
6
+ * resolved plugin root. Collisions are errors elsewhere; order only controls
7
+ * stable hook/appendix sequencing.
8
+ */
9
+ export declare function sortRegistryEntries(entries: GjcPluginRegistryEntry[]): GjcPluginRegistryEntry[];
10
+ export declare function readRegistry(scope: GjcPluginScope, cwd: string): Promise<GjcPluginRegistry>;
11
+ export declare function withRegistryLock<T>(scope: GjcPluginScope, cwd: string, fn: () => Promise<T>): Promise<T>;
12
+ /**
13
+ * Lock-free atomic write (temp+fsync+rename). Only call while already holding
14
+ * the per-scope registry lock via withRegistryLock.
15
+ */
16
+ export declare function writeRegistryUnlocked(registry: GjcPluginRegistry, cwd: string): Promise<void>;
17
+ /**
18
+ * Atomic registry write: write to a temp sibling, fsync, then rename. Guarded
19
+ * by an interprocess lockfile so concurrent installs cannot clobber each other.
20
+ */
21
+ export declare function writeRegistry(registry: GjcPluginRegistry, cwd: string): Promise<void>;
22
+ /**
23
+ * Mutate a scope's registry as a single locked read-modify-write transaction so
24
+ * concurrent installs cannot lose each other's updates. The mutator receives a
25
+ * sorted copy and returns the next entry list.
26
+ */
27
+ export declare function updateRegistry(scope: GjcPluginScope, cwd: string, mutator: (entries: GjcPluginRegistryEntry[]) => GjcPluginRegistryEntry[]): Promise<GjcPluginRegistry>;
28
+ /**
29
+ * Effective registry for a cwd: user + project entries in deterministic order.
30
+ */
31
+ export declare function loadEffectiveGjcPluginRegistry(cwd: string): Promise<GjcPluginRegistryEntry[]>;
32
+ export declare function registryEntryFingerprint(entry: GjcPluginRegistryEntry): string;
@@ -0,0 +1,64 @@
1
+ import type { CustomTool } from "../custom-tools/types";
2
+ import { type SessionQuarantine } from "./session-validation";
3
+ export interface AlwaysOnPluginTools {
4
+ tools: CustomTool[];
5
+ quarantine: SessionQuarantine[];
6
+ }
7
+ /**
8
+ * Load the always-on plugin tool surfaces for the effective registry at `cwd`.
9
+ *
10
+ * Safety properties:
11
+ * - Hash drift quarantines the plugin (runtime_mismatch) before any import.
12
+ * - Session-start collisions vs reserved/built-in names quarantine fail-closed.
13
+ * - Manifest-declared tool names are authoritative: a factory that returns a
14
+ * different/extra/missing name is rejected with runtime_mismatch and skipped.
15
+ * - Reserved tool names are never overwritten.
16
+ *
17
+ * Returns an empty result when no plugins are installed, so callers that always
18
+ * call this in `createAgentSession` incur no behavior change without plugins.
19
+ */
20
+ export declare function loadAlwaysOnPluginTools(input: {
21
+ cwd: string;
22
+ reservedToolNames: string[];
23
+ }): Promise<AlwaysOnPluginTools>;
24
+ /**
25
+ * Render the always-on system-appendix blocks for the effective registry at
26
+ * `cwd`, applying hash-drift + collision quarantine first. Returns "" when no
27
+ * plugins are installed/enabled. Safe to call unconditionally at session start.
28
+ */
29
+ export declare function renderAlwaysOnSystemAppendices(input: {
30
+ cwd: string;
31
+ }): Promise<string>;
32
+ /**
33
+ * Render the agent-appendix block and Tier-1 sub-skill advertisement for a role
34
+ * agent at session/spawn time. Hash-drift + collision quarantine applied first.
35
+ * Returns empty strings when nothing applies.
36
+ */
37
+ export declare function renderAgentPromptAdditions(input: {
38
+ cwd: string;
39
+ agentName: string;
40
+ }): Promise<{
41
+ appendix: string;
42
+ advertisement: string;
43
+ }>;
44
+ /**
45
+ * Render the Tier-1 sub-skill advertisement for a workflow parent skill.
46
+ * Returns "" when nothing applies. Quarantine applied first.
47
+ */
48
+ export declare function renderSkillAdvertisement(input: {
49
+ cwd: string;
50
+ skillName: string;
51
+ phase?: string;
52
+ }): Promise<string>;
53
+ /**
54
+ * Convert active plugin-bundle MCP surfaces into runtime MCPServerConfig entries,
55
+ * applying install + runtime MCP policy (URL scheme/private-range deny, DNS
56
+ * re-resolution for http/sse, stdio root-confinement) before connection. Servers
57
+ * failing policy are quarantined and excluded. Returns {} when none.
58
+ */
59
+ export declare function buildPluginMcpConfigs(input: {
60
+ cwd: string;
61
+ }): Promise<{
62
+ configs: Record<string, any>;
63
+ quarantine: SessionQuarantine[];
64
+ }>;
@@ -0,0 +1,42 @@
1
+ import type { GjcPluginLoadErrorCode, GjcPluginRegistryEntry } from "./types";
2
+ /**
3
+ * Session-start validation: the registry is the collision authority. Capability
4
+ * provider output is supplied as EVIDENCE only; plugin surfaces are never
5
+ * resolved by capability first-wins. Offending surfaces are quarantined
6
+ * fail-closed with a stable error code rather than silently shadowed.
7
+ */
8
+ export interface SessionCapabilityEvidence {
9
+ /** Built-in + provider tool names already present before plugin insertion. */
10
+ toolNames?: Iterable<string>;
11
+ /** Non-plugin MCP server names from providers/built-ins. */
12
+ mcpNames?: Iterable<string>;
13
+ /** Non-plugin hook keys (event:phase:target:name) from providers/built-ins. */
14
+ hookKeys?: Iterable<string>;
15
+ /** Existing appendix extension ids already present. */
16
+ appendixIds?: Iterable<string>;
17
+ }
18
+ export interface SessionQuarantine {
19
+ plugin: string;
20
+ surfaceId: string;
21
+ code: GjcPluginLoadErrorCode;
22
+ message: string;
23
+ }
24
+ export interface SessionValidationResult {
25
+ /** Registry entries (enabled, non-quarantined) whose surfaces may activate. */
26
+ active: GjcPluginRegistryEntry[];
27
+ /** Per-surface quarantine records (fail-closed). */
28
+ quarantine: SessionQuarantine[];
29
+ }
30
+ /**
31
+ * Re-verify that the installed files still match the registry's recorded hashes.
32
+ * Drift (manual edits, partial writes) quarantines the whole plugin with
33
+ * runtime_mismatch.
34
+ */
35
+ export declare function verifyEntryHashes(entry: GjcPluginRegistryEntry): Promise<SessionQuarantine | null>;
36
+ /**
37
+ * Validate the effective installed registry against the current capability
38
+ * universe (evidence) and across plugins. Returns the entries that may activate
39
+ * plus per-surface quarantine records. Disabled entries/surfaces are skipped
40
+ * (not an error).
41
+ */
42
+ export declare function validateSessionBundles(entries: readonly GjcPluginRegistryEntry[], evidence?: SessionCapabilityEvidence, preQuarantined?: readonly SessionQuarantine[]): SessionValidationResult;