clementine-agent 1.18.209 → 1.18.211
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/agent-definitions.js +10 -10
- package/dist/agent/approval-signals.d.ts +2 -2
- package/dist/agent/approval-signals.js +1 -1
- package/dist/agent/assistant.js +34 -3
- package/dist/agent/bg-planner.d.ts +3 -4
- package/dist/agent/bg-planner.js +4 -5
- package/dist/agent/claim-verification.d.ts +1 -1
- package/dist/agent/claim-verification.js +1 -1
- package/dist/agent/clarification-gate.d.ts +116 -0
- package/dist/agent/clarification-gate.js +402 -0
- package/dist/agent/clementine-turn-context.d.ts +1 -1
- package/dist/agent/clementine-turn-context.js +8 -3
- package/dist/agent/complex-task-detector.d.ts +7 -12
- package/dist/agent/complex-task-detector.js +70 -26
- package/dist/agent/execution-policy.d.ts +23 -0
- package/dist/agent/execution-policy.js +36 -0
- package/dist/agent/intent-classifier.d.ts +1 -1
- package/dist/agent/precondition-guard.d.ts +61 -0
- package/dist/agent/precondition-guard.js +88 -0
- package/dist/agent/project-resolver.d.ts +3 -3
- package/dist/agent/project-resolver.js +7 -7
- package/dist/agent/role-scaffolds.d.ts +1 -1
- package/dist/agent/role-scaffolds.js +1 -1
- package/dist/agent/run-agent-context.js +4 -5
- package/dist/agent/run-agent-cron.d.ts +2 -3
- package/dist/agent/run-agent-cron.js +7 -3
- package/dist/agent/run-agent-heartbeat.js +6 -2
- package/dist/agent/run-agent-mcp.d.ts +1 -2
- package/dist/agent/run-agent-mcp.js +29 -5
- package/dist/agent/run-agent-team-task.js +6 -3
- package/dist/agent/run-agent.d.ts +8 -0
- package/dist/agent/run-agent.js +30 -2
- package/dist/agent/schedule-registry.d.ts +2 -2
- package/dist/agent/skill-suppressions.d.ts +1 -1
- package/dist/agent/skill-suppressions.js +1 -1
- package/dist/agent/turn-policy.js +3 -3
- package/dist/channels/discord-agent-bot.js +2 -12
- package/dist/channels/discord-utils.d.ts +2 -0
- package/dist/channels/discord-utils.js +32 -0
- package/dist/channels/discord.js +2 -12
- package/dist/cli/dashboard.js +7 -6
- package/dist/config.js +1 -1
- package/dist/gateway/failure-monitor.js +9 -2
- package/dist/gateway/heartbeat-scheduler.js +1 -1
- package/dist/gateway/router.d.ts +1 -0
- package/dist/gateway/router.js +130 -30
- package/dist/integrations/composio/client.d.ts +6 -0
- package/dist/integrations/composio/client.js +117 -10
- package/dist/memory/store.js +2 -2
- package/dist/tools/admin-tools.js +2 -2
- package/dist/tools/project-tools.d.ts +1 -1
- package/dist/tools/project-tools.js +68 -17
- package/dist/tools/schedule-tools.js +1 -1
- package/dist/vault-migrations/0002-add-agentic-communication.js +1 -1
- package/package.json +1 -1
|
@@ -141,15 +141,15 @@ function buildHiredAgentDescription(p) {
|
|
|
141
141
|
'Spawn this subagent when the user names them, asks a question in their domain, or asks Clementine to "have <name> do X".',
|
|
142
142
|
].filter(Boolean).join(' ');
|
|
143
143
|
}
|
|
144
|
-
/** Map a hired-agent profile to an AgentDefinition.
|
|
145
|
-
* Used when Clementine wants to delegate to Ross/Sasha/Nora etc. */
|
|
144
|
+
/** Map a hired-agent profile to an AgentDefinition. */
|
|
146
145
|
function profileToAgentDefinition(p) {
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
|
|
146
|
+
// Hired-agent definitions are leaf subagents by default. The Claude
|
|
147
|
+
// Agent SDK does not support recursive subagent spawning via `Agent`
|
|
148
|
+
// inside subagent tool lists; if Clementine grows nested orchestration,
|
|
149
|
+
// it should be explicit and depth-limited rather than accidental.
|
|
150
|
+
const baseline = ['Read', 'Grep', 'Glob', 'WebSearch', 'WebFetch', 'TodoWrite'];
|
|
151
151
|
const tools = p.team?.allowedTools?.length
|
|
152
|
-
? Array.from(new Set(
|
|
152
|
+
? Array.from(new Set(p.team.allowedTools.filter(tool => tool !== 'Agent')))
|
|
153
153
|
: baseline;
|
|
154
154
|
return {
|
|
155
155
|
description: buildHiredAgentDescription(p),
|
|
@@ -198,10 +198,10 @@ export function buildAgentMap(opts = {}) {
|
|
|
198
198
|
// 1.18.198 — NO `tools` allowlist. Researcher inherits every tool the
|
|
199
199
|
// parent has access to (Bash, Read, MCP wildcards, etc.). The earlier
|
|
200
200
|
// hardcoded ['Read', 'Grep', 'Glob', 'WebSearch', 'WebFetch'] blocked
|
|
201
|
-
// researcher from using the parent's MCP servers
|
|
202
|
-
// "Parallel SEO enrichment for 13 domains"
|
|
201
|
+
// researcher from using the parent's MCP servers. A delegated
|
|
202
|
+
// "Parallel SEO enrichment for 13 domains" subagent couldn't call
|
|
203
203
|
// `mcp__dataforseo__*` because it wasn't in the allowlist. Result: the
|
|
204
|
-
// subagent said "I can't do that" and
|
|
204
|
+
// subagent said "I can't do that" and the parent fell back to running 25
|
|
205
205
|
// sequential MCP calls in his own turn, defeating the fan-out.
|
|
206
206
|
//
|
|
207
207
|
// Read-only behavior is enforced in RESEARCHER_PROMPT (behavior class:
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* ## Owner approval signals (recent)
|
|
14
14
|
* APPROVED (do more like this):
|
|
15
15
|
* - cron/insight-check: "Apply lean mode to reduce prompt size"
|
|
16
|
-
* - agent/
|
|
16
|
+
* - agent/marketing-agent: "Add explicit citation requirement to system prompt"
|
|
17
17
|
*
|
|
18
18
|
* DENIED (avoid these patterns):
|
|
19
19
|
* - workflow/email-gen: "Replace template with LLM generation" ← user note: "too generic; loses voice"
|
|
@@ -31,7 +31,7 @@ export interface ApprovalSignal {
|
|
|
31
31
|
experimentId: string;
|
|
32
32
|
/** The area the proposal targeted (cron, agent, skill, soul, etc.). */
|
|
33
33
|
area: string;
|
|
34
|
-
/** The specific target (e.g., "insight-check", "
|
|
34
|
+
/** The specific target (e.g., "insight-check", "marketing-agent"). */
|
|
35
35
|
target: string;
|
|
36
36
|
/** The proposal's one-sentence hypothesis (truncated to 200 chars). */
|
|
37
37
|
hypothesis: string;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* ## Owner approval signals (recent)
|
|
14
14
|
* APPROVED (do more like this):
|
|
15
15
|
* - cron/insight-check: "Apply lean mode to reduce prompt size"
|
|
16
|
-
* - agent/
|
|
16
|
+
* - agent/marketing-agent: "Add explicit citation requirement to system prompt"
|
|
17
17
|
*
|
|
18
18
|
* DENIED (avoid these patterns):
|
|
19
19
|
* - workflow/email-gen: "Replace template with LLM generation" ← user note: "too generic; loses voice"
|
package/dist/agent/assistant.js
CHANGED
|
@@ -262,6 +262,9 @@ const TOOLS_SERVER = `${ASSISTANT_NAME.toLowerCase()}-tools`;
|
|
|
262
262
|
function mcpTool(name) {
|
|
263
263
|
return `mcp__${TOOLS_SERVER}__${name}`;
|
|
264
264
|
}
|
|
265
|
+
function mcpServerWildcard(serverName) {
|
|
266
|
+
return `mcp__${serverName}__*`;
|
|
267
|
+
}
|
|
265
268
|
const CLEMENTINE_CORE_TOOL_NAMES = [
|
|
266
269
|
'working_memory',
|
|
267
270
|
'user_model',
|
|
@@ -1748,6 +1751,31 @@ You have a cost budget per message — not a hard turn limit. Work until the tas
|
|
|
1748
1751
|
fullSurface: false,
|
|
1749
1752
|
};
|
|
1750
1753
|
}
|
|
1754
|
+
const profileComposioAllowList = profile?.allowedComposioToolkits;
|
|
1755
|
+
if (!toolsDisabledForCall
|
|
1756
|
+
&& !isPlanStep
|
|
1757
|
+
&& !toolRoute.fullSurface
|
|
1758
|
+
&& Array.isArray(toolRoute.composioToolkits)
|
|
1759
|
+
&& !Array.isArray(profileComposioAllowList)) {
|
|
1760
|
+
try {
|
|
1761
|
+
const { listConnectedToolkits, matchConnectedToolkitsInText } = await import('../integrations/composio/client.js');
|
|
1762
|
+
const composioRoutingText = [
|
|
1763
|
+
directScopeText,
|
|
1764
|
+
allowContextToolRoute ? contextRoutingText : '',
|
|
1765
|
+
].filter(Boolean).join('\n');
|
|
1766
|
+
const mentioned = matchConnectedToolkitsInText(composioRoutingText, await listConnectedToolkits());
|
|
1767
|
+
if (mentioned.length > 0) {
|
|
1768
|
+
toolRoute = {
|
|
1769
|
+
...toolRoute,
|
|
1770
|
+
composioToolkits: [...new Set([...toolRoute.composioToolkits, ...mentioned])],
|
|
1771
|
+
reason: 'matched',
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
catch (err) {
|
|
1776
|
+
logger.debug({ err }, 'Connected Composio toolkit text match failed (non-fatal)');
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1751
1779
|
let allowedTools = [];
|
|
1752
1780
|
const addAllowed = (...tools) => {
|
|
1753
1781
|
for (const tool of tools) {
|
|
@@ -1944,9 +1972,8 @@ You have a cost budget per message — not a hard turn limit. Work until the tas
|
|
|
1944
1972
|
if (!toolsDisabledForCall && !isPlanStep) {
|
|
1945
1973
|
try {
|
|
1946
1974
|
const { buildComposioMcpServers } = await import('../integrations/composio/mcp-bridge.js');
|
|
1947
|
-
const
|
|
1948
|
-
|
|
1949
|
-
? profileAllowList
|
|
1975
|
+
const allowList = Array.isArray(profileComposioAllowList)
|
|
1976
|
+
? profileComposioAllowList
|
|
1950
1977
|
: toolRoute.composioToolkits;
|
|
1951
1978
|
composioMcpServers = await buildComposioMcpServers(allowList);
|
|
1952
1979
|
}
|
|
@@ -1956,6 +1983,10 @@ You have a cost budget per message — not a hard turn limit. Work until the tas
|
|
|
1956
1983
|
}
|
|
1957
1984
|
}
|
|
1958
1985
|
const composioConnectedSlugs = Object.keys(composioMcpServers);
|
|
1986
|
+
if (!toolsDisabledForCall) {
|
|
1987
|
+
for (const slug of composioConnectedSlugs)
|
|
1988
|
+
addAllowed(mcpServerWildcard(slug));
|
|
1989
|
+
}
|
|
1959
1990
|
const { stable, volatile: volatilePromptPart } = this.buildSystemPrompt({
|
|
1960
1991
|
isHeartbeat, cronTier: isPlanStep ? null : cronTier, retrievalContext, profile, sessionKey, model: resolvedModel, verboseLevel, intentClassification,
|
|
1961
1992
|
contextTier: turnPolicy?.retrievalTier ?? (retrievalContext ? 'full' : 'core'),
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Why this exists (1.18.190)
|
|
6
6
|
* ──────────────────────────
|
|
7
|
-
* Before this, a complex multi-step user ask ("find the
|
|
7
|
+
* Before this, a complex multi-step user ask ("find the catalog project,
|
|
8
8
|
* build me an HTML report, deploy it to Netlify, verify the URL") got
|
|
9
9
|
* handed to a single monolithic bg-task worker. The worker had its own
|
|
10
10
|
* 200K context but still autocompact-thrashed because:
|
|
@@ -36,15 +36,14 @@
|
|
|
36
36
|
* a multi-domain ask into proper steps is not mechanical.
|
|
37
37
|
*
|
|
38
38
|
* If you're tempted to "save tokens" by flipping this to Haiku, read
|
|
39
|
-
*
|
|
40
|
-
* (~/.claude/plans/look-at-the-last-vivid-rossum.md). The whole point
|
|
39
|
+
* a recent root-cause plan first. The whole point
|
|
41
40
|
* of this ship is to NOT cut corners on the decomposition layer.
|
|
42
41
|
*/
|
|
43
42
|
import type { ProjectMeta } from './assistant.js';
|
|
44
43
|
export interface PlanStep {
|
|
45
44
|
/** 0-indexed position. */
|
|
46
45
|
index: number;
|
|
47
|
-
/** Short imperative title (e.g., "Find the
|
|
46
|
+
/** Short imperative title (e.g., "Find the catalog project"). */
|
|
48
47
|
title: string;
|
|
49
48
|
/** What this step does, in 1-2 sentences. The chained worker sees this. */
|
|
50
49
|
scope: string;
|
package/dist/agent/bg-planner.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Why this exists (1.18.190)
|
|
6
6
|
* ──────────────────────────
|
|
7
|
-
* Before this, a complex multi-step user ask ("find the
|
|
7
|
+
* Before this, a complex multi-step user ask ("find the catalog project,
|
|
8
8
|
* build me an HTML report, deploy it to Netlify, verify the URL") got
|
|
9
9
|
* handed to a single monolithic bg-task worker. The worker had its own
|
|
10
10
|
* 200K context but still autocompact-thrashed because:
|
|
@@ -36,8 +36,7 @@
|
|
|
36
36
|
* a multi-domain ask into proper steps is not mechanical.
|
|
37
37
|
*
|
|
38
38
|
* If you're tempted to "save tokens" by flipping this to Haiku, read
|
|
39
|
-
*
|
|
40
|
-
* (~/.claude/plans/look-at-the-last-vivid-rossum.md). The whole point
|
|
39
|
+
* a recent root-cause plan first. The whole point
|
|
41
40
|
* of this ship is to NOT cut corners on the decomposition layer.
|
|
42
41
|
*/
|
|
43
42
|
import fs from 'node:fs';
|
|
@@ -202,7 +201,7 @@ function buildPlannerSystemPrompt() {
|
|
|
202
201
|
'{',
|
|
203
202
|
' "steps": [',
|
|
204
203
|
' {',
|
|
205
|
-
' "title": "<short imperative title, e.g. \'Find the
|
|
204
|
+
' "title": "<short imperative title, e.g. \'Find the catalog project\'>",',
|
|
206
205
|
' "scope": "<1-2 sentences describing exactly what this step does>",',
|
|
207
206
|
' "expectedTools": ["tool_name_1", "tool_name_2"],',
|
|
208
207
|
' "deliverable": "<file path | URL | description of the artifact>"',
|
|
@@ -273,7 +272,7 @@ async function runPlannerLlm(userPrompt, systemPrompt, model) {
|
|
|
273
272
|
// Raw `systemPrompt: string` tells the SDK to use API-key auth, which
|
|
274
273
|
// 99% of installs don't have configured — they're logged into Claude
|
|
275
274
|
// Code, not the Anthropic API. This was the "Not logged in · Please
|
|
276
|
-
// run /login" failure
|
|
275
|
+
// run /login" provider-auth failure.
|
|
277
276
|
//
|
|
278
277
|
// The preset injects Claude Code's default system prompt; our planning
|
|
279
278
|
// instructions go in `append` and dominate behavior for the single
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Why this exists (1.18.187)
|
|
6
6
|
* ──────────────────────────
|
|
7
7
|
* On 2026-05-11 a bg task was diagnosed where Clementine said "The
|
|
8
|
-
* site is live again at https://X.netlify.app — all 100
|
|
8
|
+
* site is live again at https://X.netlify.app — all 100 product records with
|
|
9
9
|
* search/filter/sort intact" — but the live URL returned HTTP 404,
|
|
10
10
|
* and the run had zero tool calls matching a deploy. She had
|
|
11
11
|
* confabulated success from a recall summary of a PRIOR task.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Why this exists (1.18.187)
|
|
6
6
|
* ──────────────────────────
|
|
7
7
|
* On 2026-05-11 a bg task was diagnosed where Clementine said "The
|
|
8
|
-
* site is live again at https://X.netlify.app — all 100
|
|
8
|
+
* site is live again at https://X.netlify.app — all 100 product records with
|
|
9
9
|
* search/filter/sort intact" — but the live URL returned HTTP 404,
|
|
10
10
|
* and the run had zero tool calls matching a deploy. She had
|
|
11
11
|
* confabulated success from a recall summary of a PRIOR task.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { RunSummary, SideEffectCall } from './run-summary.js';
|
|
2
|
+
export type PendingAgentDecisionKind = 'blocked_external_action';
|
|
3
|
+
export type BlockedActionCategory = 'deployment_target_missing';
|
|
4
|
+
export interface PendingAgentDecision {
|
|
5
|
+
id: string;
|
|
6
|
+
kind: PendingAgentDecisionKind;
|
|
7
|
+
createdAt: number;
|
|
8
|
+
expiresAt: number;
|
|
9
|
+
runIds: string[];
|
|
10
|
+
originalRequest: string;
|
|
11
|
+
question: string;
|
|
12
|
+
context: {
|
|
13
|
+
category: BlockedActionCategory;
|
|
14
|
+
classifierId: string;
|
|
15
|
+
provider: string;
|
|
16
|
+
providerLabel: string;
|
|
17
|
+
blockerSummary: string;
|
|
18
|
+
failedCommand: string;
|
|
19
|
+
error: string;
|
|
20
|
+
targetNoun: string;
|
|
21
|
+
targetPlaceholder: string;
|
|
22
|
+
createInstructions: string[];
|
|
23
|
+
existingInstructions: string[];
|
|
24
|
+
projectPath?: string;
|
|
25
|
+
agentId?: string;
|
|
26
|
+
completedSideEffects?: string[];
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export type AgentDecisionReply = {
|
|
30
|
+
kind: 'answer';
|
|
31
|
+
action: 'create_new_target';
|
|
32
|
+
} | {
|
|
33
|
+
kind: 'answer';
|
|
34
|
+
action: 'use_existing_target';
|
|
35
|
+
target: string;
|
|
36
|
+
} | {
|
|
37
|
+
kind: 'cancel';
|
|
38
|
+
} | {
|
|
39
|
+
kind: 'unclear';
|
|
40
|
+
message: string;
|
|
41
|
+
};
|
|
42
|
+
export interface BlockedActionClassifier {
|
|
43
|
+
id: string;
|
|
44
|
+
category: BlockedActionCategory;
|
|
45
|
+
provider: string;
|
|
46
|
+
providerLabel: string;
|
|
47
|
+
targetNoun: string;
|
|
48
|
+
targetPlaceholder: string;
|
|
49
|
+
defaultCommand: string;
|
|
50
|
+
defaultError: string;
|
|
51
|
+
blockerSummary: string;
|
|
52
|
+
matches(call: SideEffectCall): boolean;
|
|
53
|
+
createInstructions: string[];
|
|
54
|
+
existingInstructions: string[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Extension point for install-specific tool/provider blockers. Core owns the
|
|
58
|
+
* state machine; providers own only small classifiers and resume instructions.
|
|
59
|
+
*/
|
|
60
|
+
export declare function registerBlockedActionClassifier(classifier: BlockedActionClassifier): () => void;
|
|
61
|
+
export interface PreconditionEnv {
|
|
62
|
+
/** Working directory the agent will use for this tool call. */
|
|
63
|
+
cwd: string;
|
|
64
|
+
/** Active project path if the router resolved one. */
|
|
65
|
+
activeProjectPath?: string;
|
|
66
|
+
/** filesystem.existsSync injection point for testability. */
|
|
67
|
+
existsSync?: (path: string) => boolean;
|
|
68
|
+
}
|
|
69
|
+
export interface PreconditionMatch {
|
|
70
|
+
/** The command or tool action that would have run (for owner display). */
|
|
71
|
+
attemptedCommand: string;
|
|
72
|
+
/** The reason the precondition failed (for owner display). */
|
|
73
|
+
reason: string;
|
|
74
|
+
/** Optional project path inferred from the input (e.g. `cd /path && netlify deploy`). */
|
|
75
|
+
projectPath?: string;
|
|
76
|
+
}
|
|
77
|
+
export interface PreconditionClassifier {
|
|
78
|
+
id: string;
|
|
79
|
+
category: BlockedActionCategory;
|
|
80
|
+
provider: string;
|
|
81
|
+
providerLabel: string;
|
|
82
|
+
targetNoun: string;
|
|
83
|
+
targetPlaceholder: string;
|
|
84
|
+
blockerSummary: string;
|
|
85
|
+
/** Tool names this classifier inspects. e.g. ['Bash'] or
|
|
86
|
+
* ['mcp__clementine-tools__project_deploy']. Wildcard `'*'` not supported —
|
|
87
|
+
* classifiers should be narrow on purpose. */
|
|
88
|
+
toolNames: readonly string[];
|
|
89
|
+
/** Returns a PreconditionMatch when the call should be blocked, or null
|
|
90
|
+
* to let it proceed. Errors thrown here are caught and treated as a pass
|
|
91
|
+
* (fail-open) — the post-hoc classifier still catches the failure. */
|
|
92
|
+
matchesPreconditions(input: Record<string, unknown>, env: PreconditionEnv): PreconditionMatch | null;
|
|
93
|
+
createInstructions: string[];
|
|
94
|
+
existingInstructions: string[];
|
|
95
|
+
}
|
|
96
|
+
/** Extension point for pre-call classifiers. Mirrors registerBlockedActionClassifier. */
|
|
97
|
+
export declare function registerPreconditionClassifier(classifier: PreconditionClassifier): () => void;
|
|
98
|
+
export declare function buildBlockedActionDecisionFromRunSummary(summary: RunSummary, originalRequest: string, nowMs?: number): PendingAgentDecision | null;
|
|
99
|
+
export declare function parseAgentDecisionReply(decision: PendingAgentDecision, message: string): AgentDecisionReply;
|
|
100
|
+
export declare function buildAgentDecisionContinuationPrompt(decision: PendingAgentDecision, reply: Extract<AgentDecisionReply, {
|
|
101
|
+
kind: 'answer';
|
|
102
|
+
}>): string;
|
|
103
|
+
export declare const buildRepairDecisionFromRunSummary: typeof buildBlockedActionDecisionFromRunSummary;
|
|
104
|
+
/**
|
|
105
|
+
* Run all registered precondition classifiers against an attempted tool
|
|
106
|
+
* call. Returns the first PendingAgentDecision that matches, or null if
|
|
107
|
+
* the call should proceed. Errors inside individual classifiers are
|
|
108
|
+
* swallowed (fail-open) — the post-hoc classifier remains as the safety
|
|
109
|
+
* net for any case the pre-call rule mishandles.
|
|
110
|
+
*/
|
|
111
|
+
export declare function evaluatePreconditionsForToolCall(toolName: string, input: Record<string, unknown>, env: PreconditionEnv, opts?: {
|
|
112
|
+
originalRequest?: string;
|
|
113
|
+
runId?: string;
|
|
114
|
+
nowMs?: number;
|
|
115
|
+
}): PendingAgentDecision | null;
|
|
116
|
+
//# sourceMappingURL=clarification-gate.d.ts.map
|