@gajae-code/coding-agent 0.11.8 → 0.11.10

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 (101) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/dist/types/cli.d.ts +1 -0
  3. package/dist/types/config/model-profiles.d.ts +2 -3
  4. package/dist/types/config/model-registry.d.ts +2 -0
  5. package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +12 -5
  6. package/dist/types/gjc-runtime/deep-interview-draft.d.ts +8 -0
  7. package/dist/types/gjc-runtime/deep-interview-payload.d.ts +41 -0
  8. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +32 -17
  9. package/dist/types/gjc-runtime/deep-interview-repair.d.ts +17 -0
  10. package/dist/types/gjc-runtime/deep-interview-state.d.ts +135 -4
  11. package/dist/types/gjc-runtime/state-writer.d.ts +45 -0
  12. package/dist/types/gjc-runtime/workflow-manifest.d.ts +5 -3
  13. package/dist/types/modes/components/welcome.d.ts +2 -0
  14. package/dist/types/modes/controllers/selector-controller.d.ts +16 -8
  15. package/dist/types/runtime-mcp/redaction.d.ts +2 -0
  16. package/dist/types/sdk/bus/chat-daemon-control.d.ts +3 -1
  17. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  18. package/dist/types/sdk/bus/index.d.ts +8 -1
  19. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
  20. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +14 -7
  21. package/dist/types/sdk/bus/telegram-daemon.d.ts +74 -5
  22. package/dist/types/sdk/session.d.ts +7 -0
  23. package/dist/types/session/agent-session.d.ts +2 -0
  24. package/dist/types/session/internal/managed-session-scope.d.ts +13 -3
  25. package/dist/types/session/internal/managed-session-storage.d.ts +8 -3
  26. package/dist/types/session/session-manager.d.ts +5 -1
  27. package/dist/types/session/session-storage.d.ts +13 -0
  28. package/dist/types/skill-state/active-state.d.ts +4 -0
  29. package/dist/types/task/provider-retry-status.d.ts +13 -0
  30. package/dist/types/task/types.d.ts +3 -0
  31. package/dist/types/tools/index.d.ts +3 -1
  32. package/package.json +8 -8
  33. package/scripts/generate-sdk-operation-inventory.ts +1 -0
  34. package/src/cli/mcp-cli.ts +4 -21
  35. package/src/cli/notify-cli.ts +1 -0
  36. package/src/cli.ts +32 -0
  37. package/src/commands/deep-interview.ts +9 -4
  38. package/src/commit/agentic/index.ts +3 -3
  39. package/src/commit/map-reduce/index.ts +2 -2
  40. package/src/config/model-profiles.ts +9 -10
  41. package/src/config/model-registry.ts +4 -2
  42. package/src/defaults/gjc/skills/deep-interview/SKILL.md +78 -163
  43. package/src/eval/js/tool-bridge.ts +1 -1
  44. package/src/gjc-runtime/deep-interview-ambiguity.ts +68 -47
  45. package/src/gjc-runtime/deep-interview-draft.ts +843 -0
  46. package/src/gjc-runtime/deep-interview-payload.ts +262 -0
  47. package/src/gjc-runtime/deep-interview-recorder.ts +310 -227
  48. package/src/gjc-runtime/deep-interview-repair.ts +1674 -0
  49. package/src/gjc-runtime/deep-interview-runtime.ts +264 -103
  50. package/src/gjc-runtime/deep-interview-state.ts +916 -4
  51. package/src/gjc-runtime/ralplan-runtime.ts +3 -1
  52. package/src/gjc-runtime/state-writer.ts +166 -2
  53. package/src/gjc-runtime/workflow-manifest.generated.json +386 -1
  54. package/src/gjc-runtime/workflow-manifest.ts +191 -5
  55. package/src/hooks/skill-state.ts +23 -1
  56. package/src/internal-urls/docs-index.generated.ts +6 -5
  57. package/src/modes/components/welcome.ts +10 -2
  58. package/src/modes/controllers/selector-controller.ts +38 -8
  59. package/src/modes/interactive-mode.ts +29 -9
  60. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  61. package/src/prompts/agents/architect.md +8 -1
  62. package/src/prompts/agents/critic.md +8 -1
  63. package/src/prompts/agents/planner.md +8 -1
  64. package/src/prompts/system/system-prompt.md +1 -0
  65. package/src/runtime-mcp/json-rpc.ts +7 -4
  66. package/src/runtime-mcp/redaction.ts +30 -0
  67. package/src/sdk/broker/identity.ts +22 -12
  68. package/src/sdk/broker/session-index.ts +11 -1
  69. package/src/sdk/bus/chat-daemon-control.ts +5 -3
  70. package/src/sdk/bus/daemon-paths.ts +2 -0
  71. package/src/sdk/bus/index.ts +60 -5
  72. package/src/sdk/bus/notification-service.ts +19 -5
  73. package/src/sdk/bus/operator-runtime.ts +31 -5
  74. package/src/sdk/bus/telegram-cli.ts +6 -13
  75. package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
  76. package/src/sdk/bus/telegram-daemon-contract.ts +15 -7
  77. package/src/sdk/bus/telegram-daemon-control.ts +14 -5
  78. package/src/sdk/bus/telegram-daemon.ts +685 -120
  79. package/src/sdk/protocol/operation-inventory.generated.json +11 -0
  80. package/src/sdk/session.ts +12 -0
  81. package/src/session/agent-session.ts +140 -10
  82. package/src/session/internal/managed-session-scope.ts +339 -228
  83. package/src/session/internal/managed-session-storage.ts +17 -4
  84. package/src/session/session-manager.ts +96 -33
  85. package/src/session/session-storage.ts +23 -0
  86. package/src/skill-state/active-state.ts +10 -0
  87. package/src/skill-state/workflow-mutation-guard.ts +41 -7
  88. package/src/task/executor.ts +154 -44
  89. package/src/task/provider-retry-status.ts +88 -0
  90. package/src/task/render.ts +45 -26
  91. package/src/task/types.ts +3 -0
  92. package/src/tools/ask.ts +1 -0
  93. package/src/tools/bash-allowed-prefixes.ts +45 -1
  94. package/src/tools/index.ts +3 -1
  95. package/src/tools/subagent-render.ts +74 -16
  96. package/src/tools/subagent.ts +2 -0
  97. package/vendor/insane-search/MANIFEST.json +4 -1
  98. package/vendor/insane-search/engine/bias_check.py +5 -0
  99. package/vendor/insane-search/engine/fetch_chain.py +67 -1
  100. package/vendor/insane-search/engine/transport.py +13 -2
  101. package/vendor/insane-search/engine/validators.py +4 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.11.10] - 2026-07-25
6
+ ### Changed
7
+
8
+ - The built-in `claude-opus`, `opus-codex`, and `fable-opus-codex` presets now use `anthropic/claude-opus-5` instead of `anthropic/claude-opus-4-8`, with effort suffixes preserved; `packages/ai/src/models.json` was regenerated so `anthropic/claude-opus-5` resolves; non-opus roles (`anthropic/claude-sonnet-5` executor/planner overrides, codex and fable roles) are unchanged.
9
+
10
+ ## [0.11.9] - 2026-07-24
11
+
12
+ ### Fixed
13
+
14
+ - Restricted role-agent `bash` now accepts literal mid-word tildes, so git revision syntax such as `git diff HEAD~1` no longer has to be quoted. Bash performs tilde expansion only at the start of a word, so word-initial forms (`~`, `~/path`, `~user`) remain blocked.
15
+ - Restricted role-agent `bash` now rejects unquoted tildes at every bash expansion position inside assignment words, including the compound `name+=value` form, so `A=~`, `A+=~`, `foo=~root/bar`, `A=x:~`, `A+=x:~`, and repeated colon segments such as `a=x:~:y:~` fail closed. Tildes bash does not expand — mid-word git revisions (`HEAD~1`), non-assignment words (`--opt=~`, `1abc=~`, `a++=~`, `a+b=~`), and quoted forms — remain allowed (#3117).
16
+ - Read-only role agents (`architect`, `planner`, `critic`) now receive the `irc` coordination tool and a read-only git prefix set (`status`, `log`, `show`, `diff`, `blame`, `rev-parse`, `ls-files`) in restricted bash; mutating git and arbitrary shell stay blocked. `irc` also stays in the initial active tool set for subagents whenever the parent runtime reports IRC availability, instead of costing a discovery round-trip (#3109).
17
+ - The restricted-bash workflow guard now allows `/dev/null` redirects (so `cmd 2>/dev/null` is no longer treated as a repository write during planning phases) while keeping `/dev/stdout`, `/dev/stderr`, and `/dev/fd/<n>` blocked, failing closed on `exec` redirections, and recognizing `>|`, `>&path`, `<>`, path-qualified writers, and every `dd of=` operand. Hook-seeded deep-interview state is now gated on `isNativeDeepInterviewV1` and seeded as a native v1 envelope, so typed operations no longer fail with `DI_STATE_SCHEMA_INVALID` and run the interview manually (#3127).
18
+ - The vendored `insane-search` engine no longer treats a `429` as terminal: rate-limited probe and grid candidates back off (linear escalation honoring `Retry-After`, hard-capped at 30s) and continue through grid diversity and browser fallback. The backoff base from `INSANE_RATE_LIMIT_BACKOFF_S` is validated and clamped, so non-numeric, `NaN`, infinite, negative, or huge values can no longer raise, hang, or defeat a per-attempt deadline, and sleeps stay short enough to honor cancellation (#3131).
19
+ - ACP sessions now apply execution permission decisions to eval calls and to tools invoked from JavaScript or Python eval contexts, while non-ACP session behavior remains unchanged.
20
+ - Interactive prompt cancellation now reaches API-key preflight through `ModelRegistry`, allowing aborted submissions to clear immediately even while a shared credential-usage request continues in the background.
21
+ - Alibaba Token Plan canonical first-event timeouts now surface without session retry/fallback replay and are not internally retried by auto-compaction, preventing repeated provider usage (#3026).
22
+ - Delegated-task and subagent status surfaces now distinguish provider recovery from normal running, identify first-event versus idle-stream stalls, show retry budget and provider-progress age, and aggregate concurrent degradation by provider (#3071).
23
+ - Telegram notification daemon ownership hardening (#3048): Bot API outcomes now share one honest classifier so both the initiating `429` response and cooldown-suppressed calls settle retryably instead of being lost or falsely rejected, including selected acknowledgements; exclusive operator work is registered before its callback can throw; notification health degrades corrupt daemon-state JSON to a warning; root-registration ownership tokens propagate through injected and built-in ensure, rollback, reconciliation, teardown, and abandoned-startup cleanup seams, with token-bearing rows refusing tokenless cleanup while genuinely legacy rows retain root-match behavior; and initial daemon readiness is published only after the matching heartbeat sidecar rename is durable, so no waiter can attach during the proof window.
24
+ - `/new`, `fork()`, handoff, `/resume`, and branch/tree-jump transitions now complete verified managed `local://` legacy-root migration for the successor session identity *before* that identity is published to the agent, the workflow-gate emitter, or extension hooks, so no observer can resolve `local://` against an ungated root across the gate's `await` boundary. Matches cold-start `createAgentSession()` (#2797) and extends `/resume` (#2925). Sending a prompt right after `/new` no longer fails with "local:// legacy migration must complete before path resolution".
25
+
26
+ - Telegram notification topics now fence malformed successful `createForumTopic` responses per session endpoint, preventing repeated ambiguous topic creation while keeping explicit Bot API failures retryable.
27
+ - Windows managed-session resume no longer reports `durability_failed` when Bun rejects `fsync` on the read-only descriptor used to revalidate an existing canonical binding; Windows now uses an owner-writable descriptor for that durability fence while retaining no-follow and pre/post identity/content checks.
28
+ - SDK daemon CLI end-to-end tests now capture spawned child stdout and stderr through temporary files instead of pipes, removing the CI pipe teardown race that replaced the product exit contract with SIGPIPE status 141 (#3024).
29
+ - Interactive launch bootstrap is now suppressed for parser-accepted `--print=`, `--help=`, and `--version=` equals forms, keeping non-interactive output free of the warming-workspace preamble on TTYs.
30
+ - Managed legacy-session artifact migration now accepts up to 50,000 files, processes copy work in bounded batches, and reports capacity exhaustion separately from unsafe artifact topology (#2935).
31
+ - Kimi Code first-event timeouts now surface after the provider's continuous first-event wait instead of replaying the full request from zero.
32
+
33
+ - Rejected subagent schema payloads now retain their complete structured data in canonical output artifacts; inline results remain bounded while `agent://` output stays lossless (#2894).
34
+ - Managed legacy-session artifact migration now validates Windows directory roots from the native tree snapshot, tolerates only lazy metadata on plain Windows directories, and replays both clean and cleanup-pending detaches while retaining fail-closed receipt validation. Canonical binding durability sync uses a writable no-follow handle on Windows NTFS stacks that reject `FlushFileBuffers` on read-only handles (#3015, #2913).
35
+ - A single managed session tombstone that fails to reconcile (e.g. an artifact directory identity mismatch) no longer blocks resume or delete of every other session in the same managed scope; the failure is isolated to that tombstone and logged, unless it belongs to the session currently being opened, which still fails closed.
36
+
5
37
  ## [0.11.8] - 2026-07-23
6
38
  ### Added
7
39
 
@@ -15,6 +47,7 @@
15
47
 
16
48
  - Runtime MCP OAuth credentials are now bound to their authorized server origin and token endpoint, reject redirecting refresh responses, and fail closed when legacy or changed configuration lacks an exact match.
17
49
  - `/share` now keeps full-session HTML in owner-private unpredictable staging until the share handler or `gh gist create` process has fully stopped; cancelling a blocked gist upload terminates and awaits that process before reporting cancellation and removing the export.
50
+ - MCP diagnostics now redact opaque endpoint paths, user information, query values, and fragments without changing outbound requests, and parse-failure logs omit response bodies that could echo request secrets.
18
51
  - Telegram notification daemon self-heals degraded on-disk state: permanently missing scan roots are pruned (so one deleted worktree no longer disables orphan-topic cleanup), and retained exact-unlink transition/placeholder artifacts are reaped on ownership acquire and each scan. `gjc daemon reload` can recover without manual filesystem surgery (#2956).
19
52
  - On macOS, resuming a managed session no longer fails with `identity_mismatch` when the first write-append open changes only file `ctime` (e.g. APFS write-provenance / `com.apple.provenance`). `appendSync` allows a single bounded re-capture + retry when `dev`/`ino`/`size`/`mtime`/SHA-256 remain unchanged, and still rejects real content races and repeated ctime transitions (#2944).
20
53
  - Interactive `/resume` / `AgentSession.switchSession()` now awaits verified managed `local://` legacy-root migration for the newly selected session before post-commit lifecycle proceeds, matching cold-start `createAgentSession()` readiness from #2797 so synchronous `local://` resolution no longer fails with "legacy migration must complete before path resolution" after a mid-session switch (#2925).
@@ -45,6 +78,7 @@
45
78
  - ACP session close now rotates idempotency keys for resumed attachment generations while retaining the same key across terminally uncertain close retries.
46
79
  - ConversationStore now tolerates only unsupported Windows parent-directory durability errors after preserving temporary-file fsync and atomic rename.
47
80
  - Ralplan no longer re-asks for execution approval when the user already explicitly named `ultragoal` or `team` in the current turn; that naming is the consent.
81
+ - Interactive Windows startup now stays keyboard-ready with large session histories and native multiplexers by showing an interactive-only bootstrap before the first TUI start, deferring bounded recent-session discovery until afterward, and reducing psmux frame pressure while preserving the three-second animation and update checks.
48
82
 
49
83
  - Cron guidance now routes silent recurring polling and event-driven PR/CI watchers to `monitor`, because every cron firing starts a normal assistant turn and prompt wording cannot reliably suppress its response.
50
84
  - Ordinary `ask` calls now normalize a provider-emitted `deepInterview: null` placeholder instead of misclassifying it as malformed Round-0 intent recovery data and rejecting it before coercion.
@@ -269,11 +303,11 @@
269
303
 
270
304
  ## [0.10.1] - 2026-07-13
271
305
 
306
+ - Deep-interview bundled guidance now uses the typed native setup, topology, answer-recovery, round-result, selective inspection, and sanity-check commands for normal workflow state changes. Generic `gjc state` remains limited to documented compatibility/recovery handoff paths; ambiguity, receipts, revisions, topology persistence, and diagnosis/repair remain runtime-owned.
272
307
  ### Added
273
308
 
274
309
  - Added an owner-proof idle session reaper and `gjc_coordinator_stop_session` for ephemeral (delegate-created) coordinator sessions. Termination goes exclusively through the canonical SDK broker `session.close` lifecycle (durable process identity verified before close) — never a raw `process.kill` or tmux control. The reaper re-validates ephemeral and no-active-turn state at close time under the same per-session mutation lock as delegate reuse, and purges coordinator metadata only after SDK closure is verified, retaining it when closure cannot be confirmed (#2080).
275
310
 
276
- - Added an owner-proof idle session reaper and `gjc_coordinator_stop_session` for ephemeral (delegate-created) coordinator sessions. Termination goes exclusively through the owner-proof `forceCloseGjcTmuxSession` path (pid, native session id, owner generation, server key, and start time all verified before SIGTERM) — never a raw `process.kill`. The reaper binds each close to the persisted runtime-state file, re-validates ephemeral and no-active-turn at kill time under the same per-session mutation lock as delegate reuse, and purges state only on verified termination (#2080).
277
311
  - SDK clients can now pass an explicit thinking level to `model.set`, atomically applying the effective model and thinking level to the active session and the machine-global default for future sessions, while project policy and resumed session history retain precedence.
278
312
  - Context-usage tokens/% now use provider-reported usage as the single source of truth on every surface. `AgentSession.getContextUsage()` returns a source-tagged snapshot (`source: "provider_anchor" | "heuristic" | "unknown"`), and the status-line `context_pct` segment, inline model percentage, and `/context` totals consume that snapshot instead of recomputing an independent heuristic sum — so footer, status line, `/context`, ACP, and RPC can no longer disagree about the same session state. Heuristic estimation now applies only when no provider anchor exists (session start, aborted/error-only turns), and that fallback now includes the fixed system-prompt/tool/skill context it previously omitted. The pre-prompt compaction estimate honors the latest-compaction boundary (never anchors on stale pre-compaction usage totals), unknown post-compaction usage stays unknown (status line renders `?`; ACP omits the `usage_update` instead of reporting `used: 0`), and `/context` labels its total by provenance with a reconciliation line when the estimated category composition diverges from the provider-reported total.
279
313
  - Post-durable default-model-selection failures now expose a stable SDK error with bounded `restored`, `partial`, or `unknown` rollback state; preflight and validation errors remain unchanged.
@@ -6,6 +6,7 @@
6
6
  import "@gajae-code/utils/postmortem";
7
7
  import { Command, type CommandEntry } from "@gajae-code/utils/cli";
8
8
  export declare const commands: CommandEntry[];
9
+ export declare function interactiveBootstrapText(argv: readonly string[], stdinIsTTY?: boolean, stdoutIsTTY?: boolean): string | undefined;
9
10
  export declare class RootHelpCommand extends Command {
10
11
  static description: string;
11
12
  static hidden: boolean;
@@ -1,7 +1,6 @@
1
- import type { GjcModelAssignmentTargetId } from "./model-registry";
2
1
  import { type ModelSelectorValue } from "./model-selector-value";
3
- import type { ModelsConfig } from "./models-config-schema";
4
- export type ModelProfileRole = GjcModelAssignmentTargetId;
2
+ import type { GJC_MODEL_ASSIGNMENT_TARGET_IDS, ModelsConfig } from "./models-config-schema";
3
+ export type ModelProfileRole = (typeof GJC_MODEL_ASSIGNMENT_TARGET_IDS)[number];
5
4
  export interface ModelProfileDefinition {
6
5
  name: string;
7
6
  requiredProviders: string[];
@@ -387,12 +387,14 @@ export declare class ModelRegistry {
387
387
  */
388
388
  getApiKey(model: Model<Api>, sessionId?: string, options?: {
389
389
  credentialSelector?: AuthCredentialSelector;
390
+ signal?: AbortSignal;
390
391
  }): Promise<string | undefined>;
391
392
  /**
392
393
  * Get API key for a provider (e.g., "openai").
393
394
  */
394
395
  getApiKeyForProvider(provider: string, sessionId?: string, baseUrl?: string, options?: {
395
396
  credentialSelector?: AuthCredentialSelector;
397
+ signal?: AbortSignal;
396
398
  }): Promise<string | undefined>;
397
399
  /**
398
400
  * Check if a model is using OAuth credentials (subscription).
@@ -9,15 +9,13 @@ export interface AmbiguityClampResult {
9
9
  effective: number;
10
10
  clamped: boolean;
11
11
  }
12
- /** Compute the deterministic floor from the inner deep-interview `state` object. */
12
+ /** Compute the deterministic floor from integer units of persisted evidence. */
13
13
  export declare function computeAmbiguityFloor(inner: unknown): AmbiguityFloorBreakdown;
14
14
  /** Clamp an LLM-reported ambiguity to the deterministic floor: `max(reported, floor)`. */
15
15
  export declare function clampReportedAmbiguity(reported: number, floor: number): AmbiguityClampResult;
16
16
  /**
17
- * Mark every established fact recorded in `retractedRound` as disputed. This is the
18
- * mechanical contradiction signal for answer retraction: when the user replaces an
19
- * already-scored answer (A -> B pivot), the facts that answer established can no
20
- * longer be trusted, so they raise the floor until re-confirmed or superseded.
17
+ * Legacy pure utility for migrations and explicit repair flows. The recorder does
18
+ * not dispute facts when an answer is retracted: scored evidence is immutable.
21
19
  * Returns new arrays/objects; never mutates the input.
22
20
  */
23
21
  export declare function disputeFactsFromRetractedRound(facts: readonly unknown[], retractedRound: number): {
@@ -37,3 +35,12 @@ export interface AppliedAmbiguityFloor {
37
35
  * (state CLI write/reconcile, recorder) applies this immediately before persisting.
38
36
  */
39
37
  export declare function applyAmbiguityFloorToEnvelope(value: unknown): AppliedAmbiguityFloor;
38
+ export type DeepInterviewAmbiguityMilestone = "initial" | "progress" | "refined" | "ready";
39
+ export declare function deriveAmbiguityMilestone(effectiveUnits: number, thresholdUnits: number): DeepInterviewAmbiguityMilestone;
40
+ export declare function scoreToUnits(score: number): number;
41
+ export declare function weightedAmbiguityUnits(scores: {
42
+ goal: number;
43
+ constraints: number;
44
+ criteria: number;
45
+ context?: number;
46
+ }, type: "greenfield" | "brownfield"): number;
@@ -0,0 +1,8 @@
1
+ import { type DeepInterviewDraftKind } from "./deep-interview-payload";
2
+ export interface DeepInterviewDraftResult {
3
+ status: number;
4
+ stdout?: string;
5
+ stderr?: string;
6
+ }
7
+ export declare function runDeepInterviewDraftCommand(input: readonly string[], cwd: string): Promise<DeepInterviewDraftResult>;
8
+ export declare function runDeepInterviewDraftInternalConsumeCommand(draftId: string, expectedDraftRevision: number, kind: DeepInterviewDraftKind, cwd: string): Promise<DeepInterviewDraftResult>;
@@ -0,0 +1,41 @@
1
+ import type { DeepInterviewRoundResultV1 } from "./deep-interview-state";
2
+ export declare const DEEP_INTERVIEW_DRAFT_KINDS: readonly ["initialize-context", "confirm-topology", "record-answer", "apply-round-result"];
3
+ export type DeepInterviewDraftKind = (typeof DEEP_INTERVIEW_DRAFT_KINDS)[number];
4
+ export type DeepInterviewDraftPayload = Record<string, unknown>;
5
+ export type DraftScalarType = "string" | "id" | "text" | "score" | "number" | "safe-int" | "boolean" | "enum";
6
+ export interface DraftLeafDescriptor {
7
+ kind: "leaf";
8
+ type: DraftScalarType;
9
+ nullable?: boolean;
10
+ maxBytes?: number;
11
+ values?: readonly string[];
12
+ optional?: boolean;
13
+ dynamicMapValue?: boolean;
14
+ }
15
+ export interface DraftObjectDescriptor {
16
+ kind: "object";
17
+ fields: Record<string, DraftDescriptor>;
18
+ optional?: boolean;
19
+ dynamicMapValue?: boolean;
20
+ dynamicValue?: DraftLeafDescriptor;
21
+ }
22
+ export interface DraftArrayDescriptor {
23
+ kind: "array";
24
+ item: DraftLeafDescriptor | DraftObjectDescriptor;
25
+ maxItems: number;
26
+ optional?: boolean;
27
+ }
28
+ export type DraftDescriptor = DraftLeafDescriptor | DraftObjectDescriptor | DraftArrayDescriptor;
29
+ export declare function deepInterviewDraftSchema(kind: DeepInterviewDraftKind): DraftObjectDescriptor;
30
+ /** Shared strict payload decoders used by compatibility JSON and CLI-owned drafts. */
31
+ export declare function decodeInitializeContextPayload(payload: unknown): Record<string, unknown>;
32
+ export declare function decodeConfirmTopologyPayload(payload: unknown): Record<string, unknown>;
33
+ export declare function decodeRecordAnswerPayload(payload: unknown): {
34
+ question: string;
35
+ answer: {
36
+ selected_options: string[];
37
+ custom_input: string | null;
38
+ };
39
+ };
40
+ export declare function decodeApplyRoundResultPayload(payload: unknown, state: Record<string, unknown>): DeepInterviewRoundResultV1;
41
+ export declare function validateDraftPayload(kind: DeepInterviewDraftKind, payload: unknown, state?: Record<string, unknown>): void;
@@ -1,4 +1,4 @@
1
- import { type DeepInterviewEstablishedFact, type DeepInterviewIntentItem, type DeepInterviewIntentSubstitution, type DeepInterviewRoundRecord, type DeepInterviewStateEnvelope, type DeepInterviewTriggerMetadata } from "./deep-interview-state";
1
+ import { type DeepInterviewEstablishedFact, type DeepInterviewIntentItem, type DeepInterviewIntentSubstitution, type DeepInterviewRoundRecord, type DeepInterviewRoundResultV1, type DeepInterviewStateEnvelope, type DeepInterviewTriggerMetadata } from "./deep-interview-state";
2
2
  export * from "./deep-interview-ambiguity";
3
3
  export * from "./deep-interview-state";
4
4
  /**
@@ -40,6 +40,8 @@ export interface DeepInterviewScoringInput {
40
40
  scores: Record<string, number>;
41
41
  ambiguity: number;
42
42
  triggers?: DeepInterviewTriggerMetadata[];
43
+ /** Complete native round result for typed callers. */
44
+ roundResult?: DeepInterviewRoundResultV1;
43
45
  }
44
46
  export type AppendOrMergeAction = "created" | "noop" | "replaced";
45
47
  export interface AppendOrMergeResult {
@@ -67,11 +69,9 @@ export interface TransitionValidationResult {
67
69
  }
68
70
  export declare function buildAnswerShell(input: DeepInterviewAnswerInput, now?: string): DeepInterviewRoundRecord;
69
71
  /**
70
- * Append-or-merge by `round_key`. Exactly one record per key:
71
- * - no existing record -> append (`created`);
72
- * - identical question_hash + answer_hash -> deterministic no-op (`noop`);
73
- * - same key, different hashes -> deterministic replacement of the prior shell
74
- * (`replaced`); the prior answer for that key is superseded and lifecycle resets.
72
+ * Append-or-merge by `round_key`. An answer is a no-op only when its complete
73
+ * canonical shell identity matches; a scored record is immutable evidence and
74
+ * cannot be replaced by a late answer.
75
75
  */
76
76
  export declare function appendOrMergeRound(rounds: readonly DeepInterviewRoundRecord[], shell: DeepInterviewRoundRecord): AppendOrMergeResult;
77
77
  /**
@@ -94,28 +94,43 @@ export declare function ensureDeepInterviewStateShape(value: unknown): DeepInter
94
94
  export declare function projectCompactState(value: unknown, options?: {
95
95
  lastN?: number;
96
96
  }): DeepInterviewCompactState;
97
+ interface RecorderMutationOptions {
98
+ sessionId?: string;
99
+ expectedRevision?: number;
100
+ }
101
+ export interface DeepInterviewPostCommitWarning {
102
+ code: "DI_POST_COMMIT_AUDIT_FAILED" | "DI_POST_COMMIT_ACTIVITY_FAILED" | "DI_POST_COMMIT_HUD_FAILED";
103
+ message: string;
104
+ }
105
+ export declare function runDeepInterviewPostCommitEffects(options: {
106
+ cwd: string;
107
+ statePath: string;
108
+ sessionId: string;
109
+ envelope: Record<string, unknown>;
110
+ revision: number;
111
+ writer: string;
112
+ auditWarnings?: readonly {
113
+ code: "DI_POST_COMMIT_AUDIT_FAILED";
114
+ message: string;
115
+ }[];
116
+ }): Promise<DeepInterviewPostCommitWarning[]>;
97
117
  /** Refresh the best-effort HUD cache from persisted deep-interview state. */
98
118
  export declare function syncDeepInterviewRecorderHud(cwd: string, statePath: string, sessionId: string | undefined): Promise<void>;
99
119
  /**
100
120
  * Record an `answered` shell for one round (append-or-merge by durable key).
101
121
  *
102
- * Retraction dynamics: replacing an already-`scored` answer is a mechanical
103
- * contradiction signal (the user pivoted). The facts that round established are
104
- * marked disputed, which raises the deterministic ambiguity floor immediately —
105
- * without waiting for the LLM scorer to self-report a trigger.
122
+ * Replacing an already-scored answer is rejected with
123
+ * `DI_ANSWER_LIFECYCLE_CONFLICT`; scored evidence is immutable.
106
124
  */
107
- export declare function appendOrMergeDeepInterviewRound(cwd: string, statePath: string, input: DeepInterviewAnswerInput, options?: {
108
- sessionId?: string;
109
- }): Promise<{
125
+ export declare function appendOrMergeDeepInterviewRound(cwd: string, statePath: string, input: DeepInterviewAnswerInput, options?: RecorderMutationOptions): Promise<{
110
126
  action: AppendOrMergeAction;
111
127
  record: DeepInterviewRoundRecord;
112
- disputedFactIds?: string[];
128
+ warnings: DeepInterviewPostCommitWarning[];
113
129
  }>;
114
130
  /** Merge scoring output into the same round record, transitioning to `scored`. */
115
- export declare function enrichDeepInterviewRoundScoring(cwd: string, statePath: string, input: DeepInterviewScoringInput, options?: {
116
- sessionId?: string;
117
- }): Promise<{
131
+ export declare function enrichDeepInterviewRoundScoring(cwd: string, statePath: string, input: DeepInterviewScoringInput, options?: RecorderMutationOptions): Promise<{
118
132
  record: DeepInterviewRoundRecord;
133
+ warnings: DeepInterviewPostCommitWarning[];
119
134
  }>;
120
135
  /** Compact projection so callers read a slice instead of the full transcript. */
121
136
  export declare function readDeepInterviewStateCompact(statePath: string, options?: {
@@ -0,0 +1,17 @@
1
+ import { type DeepInterviewRoundResultV1 } from "./deep-interview-state";
2
+ export interface DeepInterviewRepairResult {
3
+ status: number;
4
+ stdout?: string;
5
+ stderr?: string;
6
+ }
7
+ export declare const DEEP_INTERVIEW_REPAIR_VERBS: readonly ["initialize-context", "confirm-topology", "record-answer", "apply-round-result", "inspect", "sanity-check"];
8
+ export type DeepInterviewRepairVerb = (typeof DEEP_INTERVIEW_REPAIR_VERBS)[number];
9
+ export declare function isDeepInterviewRepairVerb(value: string): value is DeepInterviewRepairVerb;
10
+ export declare function decodeDeepInterviewAnswerJson(value: unknown): {
11
+ selected_options: string[];
12
+ custom_input: string | null;
13
+ };
14
+ export declare function decodeDeepInterviewRoundResultJson(value: unknown, state: Record<string, unknown>): DeepInterviewRoundResultV1;
15
+ export declare function decodeDeepInterviewSetupJson(value: unknown): Record<string, unknown>;
16
+ export declare function decodeDeepInterviewTopologyJson(value: unknown): Record<string, unknown>;
17
+ export declare function runDeepInterviewRepairCommand(args: readonly string[], cwd: string): Promise<DeepInterviewRepairResult>;
@@ -1,3 +1,4 @@
1
+ import { computeAmbiguityFloor, type DeepInterviewAmbiguityMilestone } from "./deep-interview-ambiguity";
1
2
  /**
2
3
  * Pure, dependency-free foundation for deep-interview state shape.
3
4
  *
@@ -35,10 +36,6 @@ export interface DeepInterviewTriggerMetadata {
35
36
  status: DeepInterviewTriggerStatus;
36
37
  component: string;
37
38
  dimension: string;
38
- priorDimensionScore?: number;
39
- newDimensionScore?: number;
40
- priorAmbiguity?: number;
41
- newAmbiguity?: number;
42
39
  evidence?: string;
43
40
  contradictedFactId?: string;
44
41
  /** Required when status is `disputed` or `unresolved` to exempt the invariant. */
@@ -68,9 +65,11 @@ export interface DeepInterviewRoundRecord {
68
65
  /** Deterministic floor in effect when this round was scored, when it clamped. */
69
66
  ambiguity_floor?: number;
70
67
  triggers?: DeepInterviewTriggerMetadata[];
68
+ round_result_digest?: string;
71
69
  }
72
70
  export interface DeepInterviewStateEnvelope {
73
71
  threshold?: number;
72
+ threshold_units?: number;
74
73
  threshold_source?: string;
75
74
  state?: Record<string, unknown>;
76
75
  [key: string]: unknown;
@@ -197,3 +196,135 @@ export declare function assertDeepInterviewIntentReview(value: unknown, locked:
197
196
  round: unknown;
198
197
  answer_hash: unknown;
199
198
  }[]): asserts value is DeepInterviewIntentReview;
199
+ export type DeepInterviewDimension = "goal" | "constraints" | "criteria" | "context";
200
+ export type DeepInterviewResolution = "auto_research_accepted" | "auto_answer" | "direct" | "refined" | "cited_confirmation";
201
+ export interface DeepInterviewFactOperation {
202
+ op: "add" | "dispute" | "supersede";
203
+ id: string;
204
+ statement?: string;
205
+ component?: string;
206
+ dimension?: DeepInterviewDimension;
207
+ evidence?: string;
208
+ target_id?: string;
209
+ }
210
+ export interface DeepInterviewOntologyEntity {
211
+ id: string;
212
+ name: string;
213
+ type: string;
214
+ fields: string[];
215
+ }
216
+ export interface DeepInterviewOntologyRelationship {
217
+ id: string;
218
+ from_entity_id: string;
219
+ to_entity_id: string;
220
+ type: string;
221
+ }
222
+ export interface DeepInterviewOntologyReasoning {
223
+ statement: string;
224
+ evidence?: string;
225
+ }
226
+ export interface DeepInterviewOntologyInput {
227
+ entities: DeepInterviewOntologyEntity[];
228
+ relationships: DeepInterviewOntologyRelationship[];
229
+ reasoning: DeepInterviewOntologyReasoning[];
230
+ }
231
+ export interface DeepInterviewComponentUpdate {
232
+ component_id: string;
233
+ scores: Record<DeepInterviewDimension, number>;
234
+ }
235
+ /**
236
+ * Optional legacy assertions accepted only when they agree with the native
237
+ * target. The persisted target is always derived from component scores.
238
+ */
239
+ export interface DeepInterviewTargetingInput {
240
+ target_component_id?: string;
241
+ target_dimension?: DeepInterviewDimension;
242
+ weakest_component_id?: string;
243
+ weakest_dimension?: DeepInterviewDimension;
244
+ last_targeted_component_id?: string | null;
245
+ }
246
+ export interface DeepInterviewRoundBookkeeping {
247
+ resolution: DeepInterviewResolution;
248
+ round_ids?: string[];
249
+ counter_deltas?: Record<string, number>;
250
+ }
251
+ /**
252
+ * Closed evidence submitted for one scoring transaction. All convergence values
253
+ * (ambiguity, floor, milestone, ontology counts, rotation, and streak) are
254
+ * native-derived and intentionally cannot be supplied here.
255
+ */
256
+ export interface DeepInterviewRoundResultV1 {
257
+ global_scores: Record<DeepInterviewDimension, number>;
258
+ component_updates?: DeepInterviewComponentUpdate[];
259
+ targeting?: DeepInterviewTargetingInput;
260
+ triggers?: DeepInterviewTriggerMetadata[];
261
+ fact_ops?: DeepInterviewFactOperation[];
262
+ ontology?: DeepInterviewOntologyInput | DeepInterviewOntologyEntity[];
263
+ bookkeeping?: DeepInterviewRoundBookkeeping;
264
+ /** Compatibility adapter for recorder callers; never persisted as the v1 wire shape. */
265
+ component_scores?: Record<string, Record<DeepInterviewDimension, number>>;
266
+ auto_answered?: boolean;
267
+ }
268
+ /**
269
+ * Version 1 native projection returned by `apply-round-result` as
270
+ * `native_projection`. This is the complete renderable convergence surface;
271
+ * callers must not derive or supplement it from candidate scorer input.
272
+ */
273
+ export interface DeepInterviewRoundResultProjection {
274
+ score_units: Partial<Record<DeepInterviewDimension, number>>;
275
+ weighted_ambiguity: number;
276
+ weighted_ambiguity_units: number;
277
+ floor: number;
278
+ floor_units: number;
279
+ floor_cause: ReturnType<typeof computeAmbiguityFloor>;
280
+ effective_ambiguity: number;
281
+ effective_ambiguity_units: number;
282
+ prior_effective_ambiguity: number | null;
283
+ direction: "increased" | "decreased" | "unchanged" | "initial";
284
+ ambiguity_milestone: DeepInterviewAmbiguityMilestone;
285
+ topology: unknown;
286
+ topology_counts: {
287
+ active: number;
288
+ deferred: number;
289
+ total: number;
290
+ };
291
+ ontology: unknown;
292
+ ontology_counts: {
293
+ stable: number;
294
+ changed: number;
295
+ new: number;
296
+ basis: string;
297
+ };
298
+ targeting: {
299
+ target_component_id: string | null;
300
+ target_dimension: DeepInterviewDimension | null;
301
+ last_targeted_component_id: string | null;
302
+ };
303
+ transition: {
304
+ round_key: string;
305
+ lifecycle: "scored";
306
+ auto_answer_streak: number;
307
+ };
308
+ }
309
+ export type DeepInterviewApplyRoundResult = {
310
+ kind: "noop";
311
+ envelope: DeepInterviewStateEnvelope;
312
+ projection?: DeepInterviewRoundResultProjection;
313
+ } | {
314
+ kind: "write";
315
+ envelope: DeepInterviewStateEnvelope;
316
+ projection: DeepInterviewRoundResultProjection;
317
+ };
318
+ /** Strict UTF-8 JSON serialization used by v1 replay digests. */
319
+ export declare function canonicalDeepInterviewJson(value: unknown): string;
320
+ export declare function deepInterviewRoundResultDigest(input: {
321
+ round: number;
322
+ question_id: string;
323
+ round_id?: string | null;
324
+ result: unknown;
325
+ }): string;
326
+ /** Complete persisted answer identity; omitted optional values normalize to null. */
327
+ export declare function deepInterviewAnswerIdentityEqual(a: Pick<DeepInterviewRoundRecord, "round" | "round_key" | "round_id" | "question_id" | "component" | "dimension" | "question_text" | "question_hash" | "selected_options" | "custom_input">, b: Pick<DeepInterviewRoundRecord, "round" | "round_key" | "round_id" | "question_id" | "component" | "dimension" | "question_text" | "question_hash" | "selected_options" | "custom_input">): boolean;
328
+ /** Apply one closed v1 scoring round. The input contains evidence only; all convergence state is derived here. */
329
+ export declare function applyDeepInterviewRoundResultV1(envelopeValue: unknown, roundKey: string, result: DeepInterviewRoundResultV1, now: string): DeepInterviewApplyRoundResult;
330
+ export declare function validateDeepInterviewV1Envelope(value: Record<string, unknown>): void;
@@ -46,6 +46,47 @@ export interface WorkflowEnvelopeIntegrityMismatch {
46
46
  expected: string;
47
47
  actual: string;
48
48
  }
49
+ export type WorkflowReceiptVerification = "legacy" | "native-valid" | "receipt-malformed" | "receipt-missing" | "checksum-mismatch";
50
+ export interface GuardedWorkflowEnvelopeTransformOptions extends StateWriterOptions {
51
+ expectedRevision: number;
52
+ /** Additional native schema validation applied to both current and candidate envelopes. */
53
+ validate?: (value: Record<string, unknown>, legacy: boolean) => void;
54
+ transform: (current: Record<string, unknown>, context: {
55
+ revision: number;
56
+ legacy: boolean;
57
+ }) => {
58
+ kind: "noop";
59
+ } | {
60
+ kind: "write";
61
+ value: Record<string, unknown>;
62
+ } | Promise<{
63
+ kind: "noop";
64
+ } | {
65
+ kind: "write";
66
+ value: Record<string, unknown>;
67
+ }>;
68
+ }
69
+ export interface GuardedWorkflowEnvelopeWarning {
70
+ code: "DI_POST_COMMIT_AUDIT_FAILED";
71
+ message: string;
72
+ }
73
+ export type GuardedWorkflowEnvelopeTransformResult = {
74
+ path: string;
75
+ written: false;
76
+ reason: "noop";
77
+ revision: number;
78
+ warnings: [];
79
+ } | {
80
+ path: string;
81
+ written: true;
82
+ revision: number;
83
+ stamped: Record<string, unknown>;
84
+ warnings: GuardedWorkflowEnvelopeWarning[];
85
+ };
86
+ export declare class GuardedWorkflowEnvelopeError extends Error {
87
+ readonly code: string;
88
+ constructor(code: string);
89
+ }
49
90
  export interface WorkflowTransactionJournal {
50
91
  version: 1;
51
92
  mutation_id: string;
@@ -80,6 +121,7 @@ export interface StateWriterOptions {
80
121
  receipt?: StateWriterReceiptContext;
81
122
  audit?: StateWriterAuditContext;
82
123
  sourceRevision?: number;
124
+ orderingRevision?: number;
83
125
  /**
84
126
  * Cross-process lock tuning for read-modify-write paths that route through
85
127
  * `withWorkflowStateLock` / `updateJsonAtomic`. Omit for the hardened
@@ -141,6 +183,8 @@ export type StrictMutationReadResult = {
141
183
  };
142
184
  export declare function readExistingStateForMutation(filePath: string): Promise<StrictMutationReadResult>;
143
185
  export declare function workflowEnvelopeContentSha256(value: unknown): string;
186
+ export declare function isNativeDeepInterviewV1(value: Record<string, unknown>): boolean;
187
+ export declare function verifyWorkflowEnvelopeReceiptValue(value: unknown, filePath: string): WorkflowReceiptVerification;
144
188
  export declare function stampWorkflowEnvelopeChecksum<T>(value: T, filePath: string, computedAt?: string): T;
145
189
  export declare function detectWorkflowEnvelopeIntegrityMismatch(filePath: string): Promise<WorkflowEnvelopeIntegrityMismatch | undefined>;
146
190
  type ActiveStateCacheInvalidator = (cwd?: string, sessionId?: string) => void;
@@ -148,6 +192,7 @@ export declare function setActiveStateCacheInvalidator(invalidator: ActiveStateC
148
192
  export declare function persistedStateRevision(value: unknown): number;
149
193
  export declare function writeGuardedJsonAtomic(targetPath: string, value: unknown, options: GuardedStateWriterOptions): Promise<GuardedWriteResult>;
150
194
  export declare function writeGuardedWorkflowEnvelopeAtomic(targetPath: string, value: unknown, options: GuardedStateWriterOptions): Promise<GuardedWriteResult>;
195
+ export declare function transformGuardedWorkflowEnvelopeAtomic(targetPath: string, options: GuardedWorkflowEnvelopeTransformOptions): Promise<GuardedWorkflowEnvelopeTransformResult>;
151
196
  export declare function writeJsonAtomic(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
152
197
  export declare function writeWorkflowEnvelopeAtomic(targetPath: string, value: unknown, options?: StateWriterOptions): Promise<string>;
153
198
  export declare function writeTextAtomic(targetPath: string, text: string, options?: StateWriterOptions): Promise<string>;
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * TypeScript is the authoritative source of truth for GJC workflow manifests.
3
- * Any JSON manifest projection is derived from this module and must never be
4
- * hand-edited.
3
+ * Keep the checked-in JSON projection synchronized manually with this module.
5
4
  */
6
5
  import { type CanonicalGjcWorkflowSkill } from "../skill-state/canonical-skills";
7
6
  export interface WorkflowState {
@@ -18,7 +17,9 @@ export interface WorkflowVerb {
18
17
  name: string;
19
18
  planned?: boolean;
20
19
  /** Invocation surface that exposes this verb in the real CLI parser. */
21
- surface?: "state-action" | "command-positional" | "command-flag";
20
+ surface?: "state-action" | "command-positional" | "command-flag" | "draft-action";
21
+ /** Legacy surface retained for callers that have not migrated to normal typed commands. */
22
+ compatibilityOnly?: boolean;
22
23
  }
23
24
  export interface TypedArgSpec {
24
25
  name: string;
@@ -26,6 +27,7 @@ export interface TypedArgSpec {
26
27
  enumValues?: string[];
27
28
  required?: boolean;
28
29
  appliesToVerbs?: string[];
30
+ compatibilityOnly?: boolean;
29
31
  planned?: boolean;
30
32
  }
31
33
  export interface RetentionPolicy {
@@ -45,3 +45,5 @@ export declare class WelcomeComponent implements Component {
45
45
  setLspServers(servers: LspServerInfo[]): void;
46
46
  render(termWidth: number): string[];
47
47
  }
48
+ /** Resolve the intro cadence without making tests mutate global process state. */
49
+ export declare function resolveWelcomeIntroTickMs(platform?: NodeJS.Platform, tmux?: string | undefined): number;
@@ -5,7 +5,7 @@ import type { InteractiveModeContext, OAuthSelectorOptions } from "../../modes/t
5
5
  import { getNotificationConfig, maskToken } from "../../sdk/bus/config";
6
6
  import { proposedTelegramIdentity, reconcileCommittedTelegramConfiguration, removeTelegramConfiguration, saveTelegramInactive } from "../../sdk/bus/notification-orchestration";
7
7
  import { buildNotificationStatusReport, checkNotificationHealth, recoverNotifications, sanitizeDiagnostic, sendNotificationTest } from "../../sdk/bus/notification-service";
8
- import { ensureTelegramDaemonRunningDetailed, resolveTelegramSetupPreflight, unregisterNotificationRoot } from "../../sdk/bus/telegram-daemon";
8
+ import { ensureTelegramDaemonRunningDetailed, readNotificationRootRegistration, resolveTelegramSetupPreflight, unregisterNotificationRoot } from "../../sdk/bus/telegram-daemon";
9
9
  import { runTelegramSetup } from "../../sdk/bus/telegram-setup";
10
10
  import { type CredentialAutoImportStateStore } from "../../setup/credential-auto-import";
11
11
  import { type CommandPaletteAction } from "../components/command-palette";
@@ -28,6 +28,13 @@ export interface NotificationsEditorAdapterContext {
28
28
  sessionManager: Pick<InteractiveModeContext["sessionManager"], "getCwd" | "getSessionId">;
29
29
  notifyConfigChanged?: () => Promise<void> | void;
30
30
  }
31
+ type TelegramDaemonStopResult = {
32
+ ok: boolean;
33
+ message: string;
34
+ before?: {
35
+ health?: string;
36
+ };
37
+ };
31
38
  export interface NotificationsEditorOperationDependencies {
32
39
  getNotificationConfig: typeof getNotificationConfig;
33
40
  maskToken: typeof maskToken;
@@ -43,7 +50,13 @@ export interface NotificationsEditorOperationDependencies {
43
50
  reconcileCommittedTelegramConfiguration: typeof reconcileCommittedTelegramConfiguration;
44
51
  saveTelegramInactive: typeof saveTelegramInactive;
45
52
  removeTelegramConfiguration: typeof removeTelegramConfiguration;
53
+ readNotificationRootRegistration: typeof readNotificationRootRegistration;
46
54
  unregisterNotificationRoot: typeof unregisterNotificationRoot;
55
+ stopTelegramDaemonIfRootRegistryFenceMatches(input: {
56
+ settings: Settings;
57
+ registryFingerprint: string;
58
+ stop: () => Promise<TelegramDaemonStopResult>;
59
+ }): Promise<boolean>;
47
60
  reloadTelegramDaemon(settings: Settings): Promise<{
48
61
  ok: boolean;
49
62
  message: string;
@@ -52,13 +65,7 @@ export interface NotificationsEditorOperationDependencies {
52
65
  ok: boolean;
53
66
  message: string;
54
67
  }>;
55
- stopTelegramDaemon(settings: Settings): Promise<{
56
- ok: boolean;
57
- message: string;
58
- before?: {
59
- health?: string;
60
- };
61
- }>;
68
+ stopTelegramDaemon(settings: Settings): Promise<TelegramDaemonStopResult>;
62
69
  }
63
70
  /**
64
71
  * Concrete service adapter for the direct Notifications settings tab. Secrets remain in this closure's
@@ -128,3 +135,4 @@ export declare class SelectorController {
128
135
  showJobsOverlay(observer: JobsObserver): void;
129
136
  showTasksPane(aggregator: TasksAggregator): void;
130
137
  }
138
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function redactMCPEndpoint(value: string | undefined): string | undefined;
2
+ export declare function redactMCPDiagnosticValue(value: unknown): unknown;