@gramatr/mcp 0.7.10 → 0.7.14
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/__mocks__/bun-sqlite.d.ts +35 -0
- package/dist/__mocks__/bun-sqlite.d.ts.map +1 -0
- package/dist/__mocks__/bun-sqlite.js +89 -0
- package/dist/__mocks__/bun-sqlite.js.map +1 -0
- package/dist/bin/build-mcpb.d.ts +2 -5
- package/dist/bin/build-mcpb.d.ts.map +1 -1
- package/dist/bin/build-mcpb.js +20 -43
- package/dist/bin/build-mcpb.js.map +1 -1
- package/dist/bin/gramatr-mcp.d.ts +10 -2
- package/dist/bin/gramatr-mcp.d.ts.map +1 -1
- package/dist/bin/gramatr-mcp.js +73 -15
- package/dist/bin/gramatr-mcp.js.map +1 -1
- package/dist/bin/login.d.ts.map +1 -1
- package/dist/bin/login.js +5 -0
- package/dist/bin/login.js.map +1 -1
- package/dist/bin/setup.d.ts +13 -10
- package/dist/bin/setup.d.ts.map +1 -1
- package/dist/bin/setup.js +88 -42
- package/dist/bin/setup.js.map +1 -1
- package/dist/cache/lru-cache.js +1 -1
- package/dist/config-runtime.d.ts +13 -0
- package/dist/config-runtime.d.ts.map +1 -1
- package/dist/config-runtime.js +24 -0
- package/dist/config-runtime.js.map +1 -1
- package/dist/gramatr +0 -0
- package/dist/hooks/input-validator.d.ts.map +1 -1
- package/dist/hooks/input-validator.js +27 -9
- package/dist/hooks/input-validator.js.map +1 -1
- package/dist/hooks/lib/client-runtime.d.ts +7 -0
- package/dist/hooks/lib/client-runtime.d.ts.map +1 -0
- package/dist/hooks/lib/client-runtime.js +22 -0
- package/dist/hooks/lib/client-runtime.js.map +1 -0
- package/dist/hooks/lib/hook-state.d.ts +7 -2
- package/dist/hooks/lib/hook-state.d.ts.map +1 -1
- package/dist/hooks/lib/hook-state.js +56 -35
- package/dist/hooks/lib/hook-state.js.map +1 -1
- package/dist/hooks/lib/intelligence.d.ts.map +1 -1
- package/dist/hooks/lib/intelligence.js +281 -427
- package/dist/hooks/lib/intelligence.js.map +1 -1
- package/dist/hooks/lib/routing.d.ts +6 -1
- package/dist/hooks/lib/routing.d.ts.map +1 -1
- package/dist/hooks/lib/routing.js +35 -11
- package/dist/hooks/lib/routing.js.map +1 -1
- package/dist/hooks/lib/session.d.ts.map +1 -1
- package/dist/hooks/lib/session.js +3 -4
- package/dist/hooks/lib/session.js.map +1 -1
- package/dist/hooks/lib/tool-envelope.d.ts +9 -0
- package/dist/hooks/lib/tool-envelope.d.ts.map +1 -0
- package/dist/hooks/lib/tool-envelope.js +24 -0
- package/dist/hooks/lib/tool-envelope.js.map +1 -0
- package/dist/hooks/lib/types.d.ts +7 -0
- package/dist/hooks/lib/types.d.ts.map +1 -1
- package/dist/hooks/lib/version.d.ts.map +1 -1
- package/dist/hooks/lib/version.js +3 -0
- package/dist/hooks/lib/version.js.map +1 -1
- package/dist/hooks/rating-capture.d.ts.map +1 -1
- package/dist/hooks/rating-capture.js +7 -2
- package/dist/hooks/rating-capture.js.map +1 -1
- package/dist/hooks/session-end.d.ts.map +1 -1
- package/dist/hooks/session-end.js +8 -6
- package/dist/hooks/session-end.js.map +1 -1
- package/dist/hooks/session-start.d.ts.map +1 -1
- package/dist/hooks/session-start.js +39 -13
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/hooks/stop.d.ts.map +1 -1
- package/dist/hooks/stop.js +18 -6
- package/dist/hooks/stop.js.map +1 -1
- package/dist/hooks/user-prompt-submit.d.ts.map +1 -1
- package/dist/hooks/user-prompt-submit.js +24 -11
- package/dist/hooks/user-prompt-submit.js.map +1 -1
- package/dist/intelligence/packet2-fetcher.d.ts +2 -2
- package/dist/intelligence/packet2-fetcher.d.ts.map +1 -1
- package/dist/intelligence/packet2-fetcher.js +24 -5
- package/dist/intelligence/packet2-fetcher.js.map +1 -1
- package/dist/intelligence/session-manager.d.ts.map +1 -1
- package/dist/intelligence/session-manager.js +25 -1
- package/dist/intelligence/session-manager.js.map +1 -1
- package/dist/proxy/tool-proxy.d.ts.map +1 -1
- package/dist/proxy/tool-proxy.js +57 -11
- package/dist/proxy/tool-proxy.js.map +1 -1
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +8 -9
- package/dist/server/server.js.map +1 -1
- package/dist/setup/instructions.d.ts +2 -2
- package/dist/setup/instructions.d.ts.map +1 -1
- package/dist/setup/instructions.js +35 -11
- package/dist/setup/instructions.js.map +1 -1
- package/dist/setup/integrations.d.ts +1 -1
- package/dist/setup/integrations.d.ts.map +1 -1
- package/dist/setup/integrations.js +7 -4
- package/dist/setup/integrations.js.map +1 -1
- package/dist/setup/targets.d.ts +1 -1
- package/dist/setup/targets.d.ts.map +1 -1
- package/dist/setup/targets.js +2 -3
- package/dist/setup/targets.js.map +1 -1
- package/dist/setup/web-connector.d.ts.map +1 -1
- package/dist/setup/web-connector.js +3 -1
- package/dist/setup/web-connector.js.map +1 -1
- package/package.json +10 -7
|
@@ -1,43 +1,104 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
function toAgentHint(agent) {
|
|
2
|
+
if (!agent || typeof agent !== 'object')
|
|
3
|
+
return null;
|
|
4
|
+
const a = agent;
|
|
5
|
+
const displayName = typeof a.display_name === 'string'
|
|
6
|
+
? a.display_name
|
|
7
|
+
: typeof a.displayName === 'string'
|
|
8
|
+
? a.displayName
|
|
9
|
+
: null;
|
|
10
|
+
const model = typeof a.model === 'string'
|
|
11
|
+
? a.model
|
|
12
|
+
: typeof a.model_preference === 'string'
|
|
13
|
+
? a.model_preference
|
|
14
|
+
: null;
|
|
15
|
+
return {
|
|
16
|
+
name: typeof a.name === 'string' ? a.name : null,
|
|
17
|
+
display_name: displayName,
|
|
18
|
+
model,
|
|
19
|
+
reason: typeof a.reason === 'string' ? a.reason : null,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function hasAgentIdentity(hint) {
|
|
23
|
+
return !!hint && !!(hint.name || hint.display_name || hint.model || hint.reason);
|
|
24
|
+
}
|
|
25
|
+
function toRecommendationMeta(value) {
|
|
26
|
+
if (!value || typeof value !== 'object')
|
|
27
|
+
return null;
|
|
28
|
+
const r = value;
|
|
29
|
+
return {
|
|
30
|
+
type: typeof r.type === 'string' ? r.type : null,
|
|
31
|
+
source: typeof r.source === 'string' ? r.source : null,
|
|
32
|
+
confidence: typeof r.confidence === 'number' ? r.confidence : null,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function renderContractBlock(payload) {
|
|
36
|
+
return ['```json', JSON.stringify(payload, null, 2), '```'].join('\n');
|
|
37
|
+
}
|
|
38
|
+
function cloneContractPayload(payload) {
|
|
39
|
+
return JSON.parse(JSON.stringify(payload));
|
|
40
|
+
}
|
|
41
|
+
function isRecord(value) {
|
|
42
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
43
|
+
}
|
|
44
|
+
function normalizeHardGates(value) {
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
return value.filter((gate) => typeof gate === 'string' && gate.trim().length > 0);
|
|
47
|
+
}
|
|
48
|
+
if (isRecord(value)) {
|
|
49
|
+
return Object.values(value)
|
|
50
|
+
.filter((gate) => typeof gate === 'string' && gate.trim().length > 0);
|
|
36
51
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
function deriveCanonicalPacket2State(payload) {
|
|
55
|
+
const packet1 = isRecord(payload.packet_1) ? payload.packet_1 : {};
|
|
56
|
+
const manifest = isRecord(packet1.manifest) ? packet1.manifest : {};
|
|
57
|
+
const packet2 = isRecord(payload.packet_2) ? payload.packet_2 : {};
|
|
58
|
+
const unifiedPacket = isRecord(payload.unified_packet) ? payload.unified_packet : {};
|
|
59
|
+
const unifiedManifest = isRecord(unifiedPacket.manifest) ? unifiedPacket.manifest : {};
|
|
60
|
+
const unifiedEnrichment = isRecord(unifiedPacket.enrichment) ? unifiedPacket.enrichment : {};
|
|
61
|
+
const status = manifest.packet_2_status
|
|
62
|
+
|| packet2.status
|
|
63
|
+
|| unifiedManifest.enrichment_status
|
|
64
|
+
|| payload.packet_2_status
|
|
65
|
+
|| 'not_applicable';
|
|
66
|
+
const required = Boolean((typeof manifest.packet_2_required === 'boolean' ? manifest.packet_2_required : undefined)
|
|
67
|
+
?? (typeof packet2.required === 'boolean' ? packet2.required : undefined)
|
|
68
|
+
?? (typeof unifiedManifest.enrichment_required === 'boolean' ? unifiedManifest.enrichment_required : undefined)
|
|
69
|
+
?? (typeof unifiedEnrichment.required === 'boolean' ? unifiedEnrichment.required : undefined)
|
|
70
|
+
?? (typeof payload.packet_2_required === 'boolean' ? payload.packet_2_required : undefined)
|
|
71
|
+
?? (status === 'required'));
|
|
72
|
+
const enrichmentId = manifest.enrichment_id
|
|
73
|
+
|| packet2.enrichment_id
|
|
74
|
+
|| unifiedManifest.enrichment_id
|
|
75
|
+
|| unifiedEnrichment.enrichment_id
|
|
76
|
+
|| payload.enrichment_id
|
|
77
|
+
|| null;
|
|
78
|
+
return { status, required, enrichmentId };
|
|
79
|
+
}
|
|
80
|
+
export function formatFailureWarning(failure) {
|
|
81
|
+
const titleMap = {
|
|
82
|
+
auth: 'AUTHENTICATION FAILURE',
|
|
83
|
+
timeout: 'TIMEOUT',
|
|
84
|
+
server_down: 'SERVER UNREACHABLE',
|
|
85
|
+
server_error: 'SERVER ERROR',
|
|
86
|
+
parse_error: 'PARSE ERROR',
|
|
87
|
+
unknown: 'UNKNOWN ERROR',
|
|
88
|
+
};
|
|
89
|
+
return renderContractBlock({
|
|
90
|
+
schema: 'gmtr.intelligence.error.v1',
|
|
91
|
+
error: {
|
|
92
|
+
reason: failure.reason,
|
|
93
|
+
title: titleMap[failure.reason],
|
|
94
|
+
detail: failure.detail,
|
|
95
|
+
},
|
|
96
|
+
required_actions: [
|
|
97
|
+
'Tell the user intelligence pre-classification failed.',
|
|
98
|
+
'Do not pretend intelligence packet delivery succeeded.',
|
|
99
|
+
'Continue with degraded flow only after surfacing the failure.',
|
|
100
|
+
],
|
|
101
|
+
});
|
|
41
102
|
}
|
|
42
103
|
export function mergeEnrichmentIntoRoute(route, enrichment) {
|
|
43
104
|
const packet2 = enrichment?.packet_2 || enrichment;
|
|
@@ -63,400 +124,193 @@ function normalizeClassifierHeadScores(value) {
|
|
|
63
124
|
return [];
|
|
64
125
|
return Array.isArray(value) ? value : [value];
|
|
65
126
|
}
|
|
127
|
+
function normalizeMatchedSkillNames(packet1, classification) {
|
|
128
|
+
const fromClassification = Array.isArray(classification.matched_skills)
|
|
129
|
+
? classification.matched_skills.filter((skill) => typeof skill === 'string')
|
|
130
|
+
: [];
|
|
131
|
+
if (fromClassification.length > 0)
|
|
132
|
+
return fromClassification;
|
|
133
|
+
const matched = packet1.skills?.routing?.matched_skills || [];
|
|
134
|
+
return matched
|
|
135
|
+
.map((skill) => skill.name || skill.id)
|
|
136
|
+
.filter((name) => typeof name === 'string');
|
|
137
|
+
}
|
|
138
|
+
function normalizeRoutingSignals(value) {
|
|
139
|
+
if (!value || typeof value !== 'object')
|
|
140
|
+
return null;
|
|
141
|
+
const raw = value;
|
|
142
|
+
const { bert_entity_scope, bert_entity_category, bert_entity_type_suggestion, classifier_entity_scope, classifier_entity_category, classifier_entity_type_suggestion, ...rest } = raw;
|
|
143
|
+
return {
|
|
144
|
+
...rest,
|
|
145
|
+
classifier_entity_scope: classifier_entity_scope ?? bert_entity_scope ?? null,
|
|
146
|
+
classifier_entity_category: classifier_entity_category ?? bert_entity_category ?? null,
|
|
147
|
+
classifier_entity_type_suggestion: classifier_entity_type_suggestion ?? bert_entity_type_suggestion ?? null,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function normalizeClassifierSignals(classifierHeads, routingSignals) {
|
|
151
|
+
const normalizedHeads = classifierHeads
|
|
152
|
+
? Object.fromEntries(Object.entries(classifierHeads).map(([head, value]) => [
|
|
153
|
+
head,
|
|
154
|
+
normalizeClassifierHeadScores(value),
|
|
155
|
+
]))
|
|
156
|
+
: null;
|
|
157
|
+
const entityClassification = {
|
|
158
|
+
scope: routingSignals?.classifier_entity_scope ?? null,
|
|
159
|
+
category: routingSignals?.classifier_entity_category ?? null,
|
|
160
|
+
type_suggestion: routingSignals?.classifier_entity_type_suggestion ?? null,
|
|
161
|
+
};
|
|
162
|
+
if (!normalizedHeads && !entityClassification.scope && !entityClassification.category && !entityClassification.type_suggestion) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
heads: normalizedHeads,
|
|
167
|
+
entity_classification: entityClassification,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function buildRequiredActions(packet2Required, enrichmentId, hardGates = []) {
|
|
171
|
+
const actions = [];
|
|
172
|
+
if (packet2Required && enrichmentId) {
|
|
173
|
+
actions.push(`Call gramatr_get_packet_two with enrichment_id="${enrichmentId}" before proceeding.`);
|
|
174
|
+
}
|
|
175
|
+
for (const gate of hardGates) {
|
|
176
|
+
actions.push(`Mandatory gate: ${gate}`);
|
|
177
|
+
}
|
|
178
|
+
return actions;
|
|
179
|
+
}
|
|
180
|
+
function normalizeFullContractPayload(data) {
|
|
181
|
+
const payload = cloneContractPayload(data);
|
|
182
|
+
const packet1 = (payload.packet_1 || {});
|
|
183
|
+
const manifest = (packet1.manifest || {});
|
|
184
|
+
const unifiedPacket = (payload.unified_packet || null);
|
|
185
|
+
const packet2 = (payload.packet_2 || {});
|
|
186
|
+
const packet2State = deriveCanonicalPacket2State(payload);
|
|
187
|
+
const packet1RoutingSignals = normalizeRoutingSignals(packet1.routing_signals);
|
|
188
|
+
if (packet1RoutingSignals) {
|
|
189
|
+
packet1.routing_signals = packet1RoutingSignals;
|
|
190
|
+
}
|
|
191
|
+
const packet1ClassifierHeads = packet1.classifier_heads;
|
|
192
|
+
const packet1ClassifierSignals = normalizeClassifierSignals(packet1ClassifierHeads, packet1RoutingSignals);
|
|
193
|
+
if (packet1ClassifierSignals) {
|
|
194
|
+
packet1.classifier_signals = packet1ClassifierSignals;
|
|
195
|
+
}
|
|
196
|
+
if (unifiedPacket) {
|
|
197
|
+
const unifiedRoutingSignals = normalizeRoutingSignals(unifiedPacket.routing_signals);
|
|
198
|
+
if (unifiedRoutingSignals) {
|
|
199
|
+
unifiedPacket.routing_signals = unifiedRoutingSignals;
|
|
200
|
+
}
|
|
201
|
+
const unifiedClassifierSignals = normalizeClassifierSignals(packet1ClassifierHeads, unifiedRoutingSignals);
|
|
202
|
+
if (unifiedClassifierSignals) {
|
|
203
|
+
unifiedPacket.classifier_signals = unifiedClassifierSignals;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (Object.keys(packet2).length > 0) {
|
|
207
|
+
packet2.fetch_tool = packet2.fetch_tool || 'gramatr_get_packet_two';
|
|
208
|
+
packet2.required = packet2State.required;
|
|
209
|
+
packet2.enrichment_id = packet2.enrichment_id ?? packet2State.enrichmentId;
|
|
210
|
+
}
|
|
211
|
+
manifest.packet_2_status = manifest.packet_2_status || packet2State.status;
|
|
212
|
+
manifest.packet_2_required = packet2State.required;
|
|
213
|
+
manifest.enrichment_id = manifest.enrichment_id ?? packet2State.enrichmentId;
|
|
214
|
+
const hardGates = normalizeHardGates((isRecord(packet1.behavioral_rules) ? packet1.behavioral_rules.hard_gates : undefined)
|
|
215
|
+
?? (unifiedPacket && isRecord(unifiedPacket.behavioral_rules) ? unifiedPacket.behavioral_rules.hard_gates : undefined));
|
|
216
|
+
payload.required_actions = buildRequiredActions(packet2State.required, packet2State.enrichmentId, hardGates);
|
|
217
|
+
payload.contract_enforcement = {
|
|
218
|
+
required_actions: payload.required_actions,
|
|
219
|
+
hard_gates: hardGates,
|
|
220
|
+
packet_2_required: packet2State.required,
|
|
221
|
+
};
|
|
222
|
+
return payload;
|
|
223
|
+
}
|
|
66
224
|
export function formatIntelligence(data, enrichment) {
|
|
225
|
+
if (data.schema === 'gmtr.intelligence.unified.v1' || data.contract_shape === 'full' || data.unified_packet) {
|
|
226
|
+
return renderContractBlock(normalizeFullContractPayload(data));
|
|
227
|
+
}
|
|
67
228
|
const packet1 = data.packet_1 || {};
|
|
68
229
|
const manifest = packet1.manifest;
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
const enrichmentId = manifest?.enrichment_id ?? data.enrichment_id;
|
|
230
|
+
const packet2State = deriveCanonicalPacket2State(data);
|
|
231
|
+
const packet2Status = packet2State.status;
|
|
232
|
+
const enrichmentId = packet2State.enrichmentId;
|
|
73
233
|
const c = packet1.classification || data.classification || {};
|
|
74
|
-
const ts = packet1.token_savings || data.token_savings || {};
|
|
75
234
|
const es = packet1.execution_summary || data.execution_summary || {};
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
lines.push('');
|
|
81
|
-
lines.push('ACTIVE PROJECT STATE:');
|
|
82
|
-
if (ps.active_prd_title) {
|
|
83
|
-
lines.push(` PRD: ${ps.active_prd_title}${ps.active_prd_id ? ` (${ps.active_prd_id})` : ''}`);
|
|
84
|
-
}
|
|
85
|
-
if (ps.current_phase) {
|
|
86
|
-
lines.push(` Phase: ${ps.current_phase}`);
|
|
87
|
-
}
|
|
88
|
-
if (ps.isc_summary && ps.isc_summary.total && ps.isc_summary.total > 0) {
|
|
89
|
-
const s = ps.isc_summary;
|
|
90
|
-
lines.push(` ISC: ${s.passing || 0}/${s.total} passing, ${s.failing || 0} failing, ${s.pending || 0} pending`);
|
|
91
|
-
}
|
|
92
|
-
if (ps.session_history_summary) {
|
|
93
|
-
lines.push(` Last session: "${ps.session_history_summary}"`);
|
|
94
|
-
}
|
|
95
|
-
if (ps.current_phase && ps.current_phase !== 'OBSERVE') {
|
|
96
|
-
lines.push(` ⚠️ RESUME from ${ps.current_phase} phase — do NOT restart OBSERVE`);
|
|
97
|
-
}
|
|
98
|
-
lines.push('');
|
|
99
|
-
}
|
|
100
|
-
const meta = [];
|
|
101
|
-
if (c.effort_level)
|
|
102
|
-
meta.push(`Effort: ${c.effort_level}`);
|
|
103
|
-
if (c.intent_type)
|
|
104
|
-
meta.push(`Intent: ${c.intent_type}`);
|
|
105
|
-
if (c.confidence)
|
|
106
|
-
meta.push(`Confidence: ${Math.round(c.confidence * 100)}%`);
|
|
107
|
-
if (c.memory_scope)
|
|
108
|
-
meta.push(`Scope: ${c.memory_scope}`);
|
|
109
|
-
if (meta.length)
|
|
110
|
-
lines.push(meta.join(' | '));
|
|
111
|
-
if (c.matched_skills?.length) {
|
|
112
|
-
lines.push(`Matched skills: ${c.matched_skills.join(', ')}`);
|
|
113
|
-
}
|
|
114
|
-
const re = c.reverse_engineering;
|
|
115
|
-
if (re) {
|
|
116
|
-
if (re.explicit_wants?.length) {
|
|
117
|
-
lines.push('What user explicitly wants:');
|
|
118
|
-
for (const w of re.explicit_wants)
|
|
119
|
-
lines.push(` - ${w}`);
|
|
120
|
-
}
|
|
121
|
-
if (re.implicit_wants?.length) {
|
|
122
|
-
lines.push('What is implied but not stated:');
|
|
123
|
-
for (const w of re.implicit_wants)
|
|
124
|
-
lines.push(` - ${w}`);
|
|
125
|
-
}
|
|
126
|
-
if (re.explicit_dont_wants?.length) {
|
|
127
|
-
lines.push('What user explicitly does NOT want:');
|
|
128
|
-
for (const w of re.explicit_dont_wants)
|
|
129
|
-
lines.push(` - ${w}`);
|
|
130
|
-
}
|
|
131
|
-
if (re.implicit_dont_wants?.length) {
|
|
132
|
-
lines.push('What user would clearly NOT want:');
|
|
133
|
-
for (const w of re.implicit_dont_wants)
|
|
134
|
-
lines.push(` - ${w}`);
|
|
135
|
-
}
|
|
136
|
-
if (re.gotchas?.length) {
|
|
137
|
-
lines.push('Gotchas and edge cases:');
|
|
138
|
-
for (const g of re.gotchas)
|
|
139
|
-
lines.push(` - ${g}`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (c.suggested_capabilities?.length) {
|
|
143
|
-
lines.push(`Suggested capabilities: ${c.suggested_capabilities.join(', ')}`);
|
|
144
|
-
}
|
|
145
|
-
if (c.isc_scaffold?.length) {
|
|
146
|
-
lines.push('ISC Scaffold (preliminary Ideal State Criteria):');
|
|
147
|
-
for (let i = 0; i < c.isc_scaffold.length; i++) {
|
|
148
|
-
lines.push(` ${i + 1}. ${c.isc_scaffold[i]}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (c.constraints_extracted?.length) {
|
|
152
|
-
lines.push(`Constraints: ${c.constraints_extracted.join('; ')}`);
|
|
153
|
-
}
|
|
154
|
-
const audit = packet1.capability_audit || data.capability_audit;
|
|
155
|
-
if (audit?.formatted_summary) {
|
|
156
|
-
lines.push('');
|
|
157
|
-
lines.push(audit.formatted_summary);
|
|
158
|
-
}
|
|
159
|
-
const qg = packet1.quality_gate_config || data.quality_gate_config;
|
|
160
|
-
if (qg?.rules?.length) {
|
|
161
|
-
lines.push('');
|
|
162
|
-
lines.push(`ISC Quality Gate: min ${qg.min_criteria || 4} criteria, ${qg.anti_required ? 'anti-criteria required' : 'anti-criteria optional'}, ${qg.word_range?.min || 8}-${qg.word_range?.max || 12} words each`);
|
|
163
|
-
const effortGated = qg.rules.filter((r) => r.min_effort);
|
|
164
|
-
if (effortGated.length) {
|
|
165
|
-
lines.push(` Effort-gated rules: ${effortGated.map((r) => `${r.id} (${r.min_effort}+)`).join(', ')}`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
const preload = packet1.context_pre_load_plan || data.context_pre_load_plan;
|
|
169
|
-
if (preload?.entity_types?.length) {
|
|
170
|
-
lines.push(`Context pre-load: ${preload.entity_types.join(', ')}`);
|
|
171
|
-
}
|
|
172
|
-
const memoryPlan = packet1.memory_plan || data.memory_plan;
|
|
173
|
-
if (memoryPlan?.strategy) {
|
|
174
|
-
lines.push(`Memory plan: strategy=${memoryPlan.strategy}${memoryPlan.memory_scope ? ` | scope=${memoryPlan.memory_scope}` : ''}${memoryPlan.domain_class ? ` | domain=${memoryPlan.domain_class}` : ''}${memoryPlan.entity_type_filter ? ` | filter=${memoryPlan.entity_type_filter}` : ''}${typeof memoryPlan.top_k === 'number' ? ` | top_k=${memoryPlan.top_k}` : ''}`);
|
|
175
|
-
}
|
|
176
|
-
const directives = packet1.behavioral_directives || data.behavioral_directives;
|
|
177
|
-
if (directives?.length) {
|
|
178
|
-
lines.push('');
|
|
179
|
-
lines.push('BEHAVIORAL DIRECTIVES (from gramatr steering rules — follow these):');
|
|
180
|
-
for (const d of directives)
|
|
181
|
-
lines.push(` - ${d}`);
|
|
182
|
-
}
|
|
183
|
-
if (packet1Contents?.length || packet2Contents?.length || packet2Status || enrichmentId) {
|
|
184
|
-
lines.push('');
|
|
185
|
-
if (packet1Contents?.length) {
|
|
186
|
-
lines.push(`PACKET 1 CONTENTS: ${packet1Contents.join(', ')}`);
|
|
187
|
-
}
|
|
188
|
-
const packet2Parts = [
|
|
189
|
-
packet2Status ? `status=${packet2Status}` : '',
|
|
190
|
-
packet2Contents?.length ? `contents=${packet2Contents.join(', ')}` : '',
|
|
191
|
-
enrichmentId ? `enrichment_id=${enrichmentId}` : '',
|
|
192
|
-
].filter(Boolean);
|
|
193
|
-
if (packet2Parts.length) {
|
|
194
|
-
lines.push(`PACKET 2: ${packet2Parts.join(' | ')}`);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
const formatSpec = packet1.format_spec || data.format_spec;
|
|
198
|
-
if (formatSpec?.mode || formatSpec?.phases?.length || formatSpec?.response_contract?.length) {
|
|
199
|
-
lines.push('');
|
|
200
|
-
lines.push(`FORMAT SPEC: ${[
|
|
201
|
-
formatSpec.mode ? `mode=${formatSpec.mode}` : '',
|
|
202
|
-
formatSpec.phases?.length ? `phases=${formatSpec.phases.join('→')}` : '',
|
|
203
|
-
formatSpec.response_contract?.length ? `contract=${formatSpec.response_contract.join(', ')}` : '',
|
|
204
|
-
].filter(Boolean).join(' | ')}`);
|
|
205
|
-
}
|
|
206
|
-
const classifierHeads = packet1.classifier_heads || data.classifier_heads;
|
|
207
|
-
if (classifierHeads) {
|
|
208
|
-
const entries = Object.entries(classifierHeads).slice(0, 4);
|
|
209
|
-
if (entries.length) {
|
|
210
|
-
lines.push('');
|
|
211
|
-
lines.push('CLASSIFIER HEADS:');
|
|
212
|
-
for (const [head, rawScores] of entries) {
|
|
213
|
-
const top = normalizeClassifierHeadScores(rawScores)
|
|
214
|
-
.slice(0, 2)
|
|
215
|
-
.map((score) => {
|
|
216
|
-
const numericScore = typeof score.score === 'number'
|
|
217
|
-
? score.score
|
|
218
|
-
: typeof score.confidence === 'number'
|
|
219
|
-
? score.confidence
|
|
220
|
-
: null;
|
|
221
|
-
const pct = typeof numericScore === 'number' ? `${Math.round(numericScore * 100)}%` : '';
|
|
222
|
-
return [score.label, pct].filter(Boolean).join(' ');
|
|
223
|
-
})
|
|
224
|
-
.filter(Boolean)
|
|
225
|
-
.join(', ');
|
|
226
|
-
lines.push(` - ${head}: ${top || 'present'}`);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
const routingSignals = packet1.routing_signals || data.routing_signals;
|
|
231
|
-
if (routingSignals) {
|
|
232
|
-
const parts = [
|
|
233
|
-
routingSignals.complexity ? `complexity=${routingSignals.complexity}` : '',
|
|
234
|
-
routingSignals.crud_operation ? `crud=${routingSignals.crud_operation}` : '',
|
|
235
|
-
routingSignals.conversation_phase ? `phase=${routingSignals.conversation_phase}` : '',
|
|
236
|
-
routingSignals.memory_scope ? `scope=${routingSignals.memory_scope}` : '',
|
|
237
|
-
routingSignals.memory_priority ? `memory=${routingSignals.memory_priority}` : '',
|
|
238
|
-
typeof routingSignals.retrieval_needed === 'boolean' ? `retrieval=${routingSignals.retrieval_needed}` : '',
|
|
239
|
-
typeof routingSignals.is_read_only === 'boolean' ? `read_only=${routingSignals.is_read_only}` : '',
|
|
240
|
-
typeof routingSignals.requires_approval === 'boolean' ? `approval=${routingSignals.requires_approval}` : '',
|
|
241
|
-
typeof routingSignals.escalation_recommended === 'boolean' ? `escalate=${routingSignals.escalation_recommended}` : '',
|
|
242
|
-
].filter(Boolean);
|
|
243
|
-
if (parts.length || routingSignals.safety_flags?.length) {
|
|
244
|
-
lines.push('');
|
|
245
|
-
lines.push(`ROUTING SIGNALS: ${parts.join(' | ')}`);
|
|
246
|
-
if (routingSignals.entity_type_suggestion?.top) {
|
|
247
|
-
lines.push(` Entity suggestion: ${routingSignals.entity_type_suggestion.top}`);
|
|
248
|
-
}
|
|
249
|
-
if (routingSignals.safety_flags?.length) {
|
|
250
|
-
lines.push(` Safety flags: ${routingSignals.safety_flags.join(', ')}`);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
const skillRouting = packet1.skills?.routing || packet1.skill_routing || data.skill_routing;
|
|
255
|
-
if (skillRouting) {
|
|
256
|
-
const matched = (skillRouting.matched_skills || []).map((skill) => skill.name || skill.id).filter(Boolean);
|
|
257
|
-
const stats = [
|
|
258
|
-
typeof skillRouting.use_count === 'number' ? `use=${skillRouting.use_count}` : '',
|
|
259
|
-
typeof skillRouting.decline_count === 'number' ? `decline=${skillRouting.decline_count}` : '',
|
|
260
|
-
typeof skillRouting.na_count === 'number' ? `na=${skillRouting.na_count}` : '',
|
|
261
|
-
typeof skillRouting.pattern_boost_applied === 'boolean' ? `pattern_boost=${skillRouting.pattern_boost_applied}` : '',
|
|
262
|
-
].filter(Boolean);
|
|
263
|
-
if (matched.length || stats.length) {
|
|
264
|
-
lines.push('');
|
|
265
|
-
if (matched.length)
|
|
266
|
-
lines.push(`SKILL ROUTING: ${matched.join(', ')}`);
|
|
267
|
-
if (stats.length)
|
|
268
|
-
lines.push(` Stats: ${stats.join(' | ')}`);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
const activeSkill = packet1.skills?.active || packet1.active_skill || data.active_skill;
|
|
272
|
-
if (activeSkill?.directives?.length) {
|
|
273
|
-
lines.push('');
|
|
274
|
-
lines.push(`ACTIVE SKILL: ${activeSkill.title || activeSkill.name} (phase: ${activeSkill.phase || 'ALL'})`);
|
|
275
|
-
for (const d of activeSkill.directives)
|
|
276
|
-
lines.push(` - ${d}`);
|
|
277
|
-
}
|
|
278
|
-
const rules = packet1.behavioral_rules || data.behavioral_rules;
|
|
279
|
-
const effort = c.effort_level || 'standard';
|
|
280
|
-
const routingMemoryPlan = packet1.memory_plan || data.memory_plan;
|
|
281
|
-
const memoryScope = c.memory_scope || routingSignals?.memory_scope || null;
|
|
282
|
-
if (rules) {
|
|
283
|
-
lines.push('');
|
|
284
|
-
lines.push(`ALGORITHM: ${(rules.algorithm_phases || []).join(' → ')}`);
|
|
285
|
-
if (rules.hard_gates) {
|
|
286
|
-
lines.push('');
|
|
287
|
-
lines.push('HARD GATES:');
|
|
288
|
-
for (const value of Object.values(rules.hard_gates)) {
|
|
289
|
-
lines.push(` - ${value}`);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
if (rules.verification_rules?.length) {
|
|
293
|
-
lines.push('');
|
|
294
|
-
lines.push('VERIFICATION RULES:');
|
|
295
|
-
for (const r of rules.verification_rules)
|
|
296
|
-
lines.push(` - ${r}`);
|
|
297
|
-
}
|
|
298
|
-
if (rules.code_rules?.length) {
|
|
299
|
-
lines.push('');
|
|
300
|
-
lines.push('CODE RULES:');
|
|
301
|
-
for (const r of rules.code_rules)
|
|
302
|
-
lines.push(` - ${r}`);
|
|
303
|
-
}
|
|
304
|
-
if (rules.safety_rules?.length) {
|
|
305
|
-
lines.push('');
|
|
306
|
-
lines.push('SAFETY RULES:');
|
|
307
|
-
for (const r of rules.safety_rules)
|
|
308
|
-
lines.push(` - ${r}`);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
if (routingMemoryPlan?.semantic_search_enabled || memoryScope) {
|
|
312
|
-
lines.push('');
|
|
313
|
-
lines.push('═══ MANDATORY: QUERY GRAMATR MEMORY BEFORE ANY WORK ═══');
|
|
314
|
-
lines.push(`${memoryScope ? `Memory scope: ${memoryScope} | ` : ''}Use search_results from Packet 1 first. Only call search_semantic for follow-up queries beyond the returned packet.`);
|
|
315
|
-
lines.push('Do NOT answer from stale local markdown alone. gramatr has the live knowledge graph.');
|
|
316
|
-
}
|
|
317
|
-
lines.push('');
|
|
318
|
-
lines.push('═══ MANDATORY: CREATE ISC VIA TaskCreate BEFORE ANY WORK ═══');
|
|
319
|
-
lines.push('You MUST call the TaskCreate tool for each criterion below. This creates visible tracked tasks.');
|
|
320
|
-
lines.push('NEVER write criteria as manual text/tables. ALWAYS use TaskCreate + TaskList tools.');
|
|
321
|
-
lines.push('ALWAYS prefix task subjects with "ISC-C{N}: " for criteria or "ISC-A{N}: " for anti-criteria.');
|
|
322
|
-
lines.push('The ISC prefix is REQUIRED — it signals to the user that gramatr intelligence is driving the criteria.');
|
|
323
|
-
lines.push('This is a HARD GATE — do NOT proceed to any work until TaskCreate calls are complete.');
|
|
324
|
-
lines.push('');
|
|
325
|
-
lines.push('When presenting gramatr intelligence (ISC scaffolds, search results, agent recommendations, summaries), prefix with **grā:** in bold. This distinguishes server-pre-computed content from your own reasoning. Example: "**grā:** ISC scaffold suggests 6 criteria for this migration task."');
|
|
326
|
-
if (effort === 'instant') {
|
|
327
|
-
lines.push('');
|
|
328
|
-
lines.push('FORMAT (instant effort — minimal): State, do, confirm.');
|
|
329
|
-
}
|
|
330
|
-
else if (effort === 'fast') {
|
|
331
|
-
lines.push('');
|
|
332
|
-
lines.push('FORMAT (fast effort — compressed):');
|
|
333
|
-
lines.push(' 1. "Understanding: [wants] | Avoiding: [don\'t wants]"');
|
|
334
|
-
if (c.isc_scaffold?.length) {
|
|
335
|
-
lines.push(' 2. MANDATORY — call TaskCreate for each:');
|
|
336
|
-
for (let i = 0; i < c.isc_scaffold.length; i++) {
|
|
337
|
-
lines.push(` [INVOKE TaskCreate: subject="ISC-C${i + 1}: ${c.isc_scaffold[i]}", description="Binary testable: PASS or FAIL."]`);
|
|
338
|
-
}
|
|
339
|
-
lines.push(' 3. [INVOKE TaskList to display criteria to user]');
|
|
340
|
-
lines.push(' 4. Do the work');
|
|
341
|
-
lines.push(' 5. [INVOKE TaskList], then [INVOKE TaskUpdate] each with PASS/FAIL + evidence');
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
lines.push(' 2. [INVOKE TaskCreate for at least 4 criteria you identify]');
|
|
345
|
-
lines.push(' 3. [INVOKE TaskList to display criteria to user]');
|
|
346
|
-
lines.push(' 4. Do the work');
|
|
347
|
-
lines.push(' 5. [INVOKE TaskList], then [INVOKE TaskUpdate] each with PASS/FAIL + evidence');
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
else {
|
|
351
|
-
lines.push('');
|
|
352
|
-
lines.push(`FORMAT (${effort} effort — full phases)`);
|
|
353
|
-
const agents = packet1.agents?.suggested || packet1.suggested_agents || data.packet_2?.agents?.suggested || data.packet_2?.suggested_agents || data.suggested_agents;
|
|
354
|
-
if (agents?.length) {
|
|
355
|
-
lines.push('');
|
|
356
|
-
lines.push('Suggested agents:');
|
|
357
|
-
for (const a of agents) {
|
|
358
|
-
lines.push(` - ${a.display_name || a.name || 'agent'} (${a.model || 'default'}) — ${a.reason || ''}`);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
const mem = packet1.memory_context || data.memory_context;
|
|
363
|
-
if (mem?.results?.length) {
|
|
364
|
-
lines.push('');
|
|
365
|
-
lines.push(`RELEVANT MEMORY (${mem.total_count} matches from gramatr knowledge graph):`);
|
|
366
|
-
for (const r of mem.results.slice(0, 5)) {
|
|
367
|
-
const sim = r.similarity ? ` (${Math.round(r.similarity * 100)}% match)` : '';
|
|
368
|
-
lines.push(` - [${r.entity_type || 'unknown'}] ${r.entity_name || 'unnamed'}${sim}: ${((r.summary || r.content) || '').substring(0, 150)}`);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
235
|
+
const routingSignals = normalizeRoutingSignals(packet1.routing_signals || data.routing_signals);
|
|
236
|
+
const classifierHeads = (packet1.classifier_heads || data.classifier_heads);
|
|
237
|
+
const classifierSignals = normalizeClassifierSignals(classifierHeads, routingSignals);
|
|
238
|
+
const memory = packet1.memory_context || data.memory_context;
|
|
371
239
|
const searchResults = packet1.search_results || data.search_results;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
const degraded = es.degraded_components?.filter((component) => component.startsWith('classification.')) || [];
|
|
448
|
-
if (degraded.length > 0) {
|
|
449
|
-
lines.push('');
|
|
450
|
-
lines.push('CLASSIFIER DIAGNOSTICS:');
|
|
451
|
-
for (const component of degraded) {
|
|
452
|
-
lines.push(` - ${component.replace('classification.', '').replace(/_/g, ' ')} degraded`);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
if (!enrichment && packet2Status === 'required' && enrichmentId) {
|
|
456
|
-
lines.push('');
|
|
457
|
-
lines.push(`Packet 2 (reverse engineering + ISC scaffold) is required but still generating. Call gramatr_get_enrichment with enrichment_id="${enrichmentId}" before proceeding.`);
|
|
458
|
-
}
|
|
459
|
-
return lines.join('\n');
|
|
240
|
+
const agentRecommendation = packet1.agents?.recommendation || packet1.agent_recommendation || data.agent_recommendation || null;
|
|
241
|
+
const suggestedAgents = packet1.agents?.suggested || packet1.suggested_agents || data.suggested_agents || [];
|
|
242
|
+
const selectedAgent = suggestedAgents[0] || null;
|
|
243
|
+
const recommendationHint = toAgentHint(agentRecommendation);
|
|
244
|
+
const selectedHint = toAgentHint(selectedAgent);
|
|
245
|
+
const recommendationMeta = toRecommendationMeta(agentRecommendation);
|
|
246
|
+
const matchedSkillNames = normalizeMatchedSkillNames(packet1, c);
|
|
247
|
+
const activeSkill = packet1.skills?.active?.name || packet1.active_skill?.name || null;
|
|
248
|
+
const skillStats = packet1.skills?.routing
|
|
249
|
+
? {
|
|
250
|
+
use_count: packet1.skills.routing.use_count ?? null,
|
|
251
|
+
decline_count: packet1.skills.routing.decline_count ?? null,
|
|
252
|
+
na_count: packet1.skills.routing.na_count ?? null,
|
|
253
|
+
}
|
|
254
|
+
: null;
|
|
255
|
+
const envelope = {
|
|
256
|
+
schema: 'gmtr.intelligence.envelope.v1',
|
|
257
|
+
source: 'gramatr',
|
|
258
|
+
consumer_instructions: {
|
|
259
|
+
protocol: 'Process packet_1 first. Treat packet_1 as deterministic contract input.',
|
|
260
|
+
packet_1: [
|
|
261
|
+
'Use classification + routing_signals to decide immediate response mode.',
|
|
262
|
+
'Use memory_context/search_results directly; do not re-summarize with LLM in packet one.',
|
|
263
|
+
'Execute required_actions exactly when present.',
|
|
264
|
+
],
|
|
265
|
+
packet_2: [
|
|
266
|
+
'If packet_2.required is true, call fetch_tool with enrichment_id before deep reasoning.',
|
|
267
|
+
'Merge packet_2 reasoning into your plan, then continue implementation.',
|
|
268
|
+
],
|
|
269
|
+
contract_enforcement: [
|
|
270
|
+
'Execute required_actions as mandatory contract obligations.',
|
|
271
|
+
'Treat behavioral_rules.hard_gates as non-optional constraints.',
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
packet_1: {
|
|
275
|
+
manifest: {
|
|
276
|
+
packet_2_status: packet2Status,
|
|
277
|
+
packet_2_required: packet2State.required,
|
|
278
|
+
enrichment_id: enrichmentId,
|
|
279
|
+
},
|
|
280
|
+
classification: {
|
|
281
|
+
effort_level: c.effort_level || null,
|
|
282
|
+
intent_type: c.intent_type || null,
|
|
283
|
+
confidence: c.confidence ?? null,
|
|
284
|
+
memory_scope: c.memory_scope || routingSignals?.memory_scope || null,
|
|
285
|
+
matched_skills: matchedSkillNames,
|
|
286
|
+
constraints_extracted: c.constraints_extracted || [],
|
|
287
|
+
},
|
|
288
|
+
routing_signals: routingSignals || null,
|
|
289
|
+
classifier_signals: classifierSignals,
|
|
290
|
+
memory_context: memory || null,
|
|
291
|
+
search_results: searchResults || null,
|
|
292
|
+
skills: {
|
|
293
|
+
active: activeSkill,
|
|
294
|
+
matched: matchedSkillNames,
|
|
295
|
+
stats: skillStats,
|
|
296
|
+
},
|
|
297
|
+
agents: {
|
|
298
|
+
recommendation: hasAgentIdentity(recommendationHint) ? recommendationHint : null,
|
|
299
|
+
recommendation_meta: recommendationMeta,
|
|
300
|
+
selected: selectedHint,
|
|
301
|
+
suggested: selectedHint ? [selectedHint] : [],
|
|
302
|
+
suggested_count: suggestedAgents.length,
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
packet_2: {
|
|
306
|
+
status: packet2Status,
|
|
307
|
+
required: packet2State.required,
|
|
308
|
+
enrichment_id: enrichmentId,
|
|
309
|
+
fetch_tool: 'gramatr_get_packet_two',
|
|
310
|
+
},
|
|
311
|
+
required_actions: buildRequiredActions(packet2State.required, enrichmentId, normalizeHardGates(packet1.behavioral_rules?.hard_gates || data.behavioral_rules?.hard_gates)),
|
|
312
|
+
};
|
|
313
|
+
return renderContractBlock(envelope);
|
|
460
314
|
}
|
|
461
315
|
export function emitStatus(data, elapsed, lastFailure) {
|
|
462
316
|
if (!data) {
|