@evomap/evolver-adapter-public 2.0.0-beta.19 → 2.0.0-beta.22
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/antiAbuseTelemetry.js +2 -1
- package/dist/auth/credentialStore.d.ts +5 -2
- package/dist/auth/credentialStore.js +133 -45
- package/dist/auth/legacyShim.d.ts +2 -2
- package/dist/auth/legacyShim.js +2 -2
- package/dist/auth/windowsPowerShell.d.ts +3 -0
- package/dist/auth/windowsPowerShell.js +91 -0
- package/dist/hubCapability.d.ts +14 -1
- package/dist/hubCapability.js +274 -33
- package/dist/hubFetch.d.ts +3 -3
- package/dist/hubFetch.js +55 -13
- package/dist/hubReuse.d.ts +2 -1
- package/dist/hubReuse.js +34 -19
- package/dist/learningPacketSink.d.ts +9 -1
- package/dist/learningPacketSink.js +51 -10
- package/package.json +2 -2
package/dist/hubReuse.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// - payload cache: assetId → phase-3 payload (content-addressed, long/permanent, bounded LRU). A cached
|
|
14
14
|
// payload → ZERO fetch. Both clocks are injected so TTL/eviction is deterministic and testable.
|
|
15
15
|
import { createHash } from 'node:crypto';
|
|
16
|
-
import { hub, algo, wire } from '@evomap/evolver-core';
|
|
16
|
+
import { hub, algo, signals as signalNs, wire } from '@evomap/evolver-core';
|
|
17
17
|
const { scoreSearchResults, decideReuse, DEFAULT_MIN_REUSE_SCORE, } = hub;
|
|
18
18
|
const GENE_WIRE_KEYS = new Set([
|
|
19
19
|
'type',
|
|
@@ -32,10 +32,17 @@ const GENE_WIRE_KEYS = new Set([
|
|
|
32
32
|
'routing_hint',
|
|
33
33
|
'tool_policy',
|
|
34
34
|
'generation_meta',
|
|
35
|
+
// K_auto projection-key coordinates + runtime authorship (v2-delta; ride-along until gep-sdk 1.13).
|
|
36
|
+
'model_name',
|
|
37
|
+
'claims',
|
|
38
|
+
'scope',
|
|
39
|
+
'runtime_profile',
|
|
40
|
+
'verifier_profile',
|
|
35
41
|
'asset_id',
|
|
36
42
|
]);
|
|
37
43
|
const HUB_DELIVERY_METADATA_KEYS = new Set([
|
|
38
44
|
'status',
|
|
45
|
+
'trust_state',
|
|
39
46
|
'success_streak',
|
|
40
47
|
'reputation_score',
|
|
41
48
|
'gdi_score',
|
|
@@ -55,8 +62,15 @@ const HUB_DELIVERY_METADATA_KEYS = new Set([
|
|
|
55
62
|
'semanticSimilarity',
|
|
56
63
|
'_search_score',
|
|
57
64
|
'search_score',
|
|
65
|
+
'_match_score',
|
|
66
|
+
'match_score',
|
|
67
|
+
'_retrieval_rank',
|
|
68
|
+
'retrieval_rank',
|
|
58
69
|
'payload_backfill_reason',
|
|
70
|
+
'original_asset_id',
|
|
59
71
|
'asset_type',
|
|
72
|
+
'local_id',
|
|
73
|
+
'source',
|
|
60
74
|
'bundle_id',
|
|
61
75
|
'callable',
|
|
62
76
|
'payload_ready',
|
|
@@ -131,7 +145,7 @@ export function buildSemanticQuery(signals) {
|
|
|
131
145
|
export function signalFingerprint(signals) {
|
|
132
146
|
return [...signals].map((s) => String(s).trim()).filter(Boolean).sort().join('|');
|
|
133
147
|
}
|
|
134
|
-
export const TASK_DOMAIN_SIGNAL_PREFIX =
|
|
148
|
+
export const TASK_DOMAIN_SIGNAL_PREFIX = signalNs.TASK_DOMAIN_SIGNAL_PREFIX;
|
|
135
149
|
/**
|
|
136
150
|
* evolver domain slug → hub domain taxonomy (evomap-hub domainDetectionService VALID_DOMAINS).
|
|
137
151
|
* Only mapped slugs may ride the wire: the hub validates against its own taxonomy and silently
|
|
@@ -153,19 +167,10 @@ const HUB_DOMAIN_BY_SLUG = {
|
|
|
153
167
|
* fall back to unscoped recall (today's behaviour).
|
|
154
168
|
*/
|
|
155
169
|
export function hubDomainFromSignals(signals) {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
continue;
|
|
161
|
-
const slug = signal.slice(TASK_DOMAIN_SIGNAL_PREFIX.length).trim();
|
|
162
|
-
if (slug)
|
|
163
|
-
slugs.add(slug);
|
|
164
|
-
}
|
|
165
|
-
if (slugs.size !== 1)
|
|
166
|
-
return null;
|
|
167
|
-
const [slug] = slugs;
|
|
168
|
-
return HUB_DOMAIN_BY_SLUG[slug] ?? null;
|
|
170
|
+
const resolution = signalNs.resolveTaskDomainSignals(signals);
|
|
171
|
+
return resolution.status === 'resolved'
|
|
172
|
+
? HUB_DOMAIN_BY_SLUG[resolution.slug] ?? null
|
|
173
|
+
: null;
|
|
169
174
|
}
|
|
170
175
|
/**
|
|
171
176
|
* The two-layer reuse cache. Bounded + TTL'd, per-process. A search-cache hit means phase 1 makes ZERO hub
|
|
@@ -255,10 +260,15 @@ function stripHubPayloadMetadata(rec) {
|
|
|
255
260
|
}
|
|
256
261
|
return out;
|
|
257
262
|
}
|
|
258
|
-
|
|
263
|
+
// Shared content projection for by-id verification and sync quarantine classification.
|
|
264
|
+
export function stripHubDeliveryMetadataForIntegrity(rec) {
|
|
259
265
|
const out = { ...rec };
|
|
260
|
-
for (const key of HUB_DELIVERY_METADATA_KEYS)
|
|
266
|
+
for (const key of HUB_DELIVERY_METADATA_KEYS) {
|
|
267
|
+
// Hub ranking streak is metadata for Genes, while Capsule.success_streak is canonical content.
|
|
268
|
+
if (key === 'success_streak' && out['type'] === 'Capsule')
|
|
269
|
+
continue;
|
|
261
270
|
delete out[key];
|
|
271
|
+
}
|
|
262
272
|
// Hub ranking confidence is metadata for Genes, while Capsule.confidence is canonical content.
|
|
263
273
|
if (out['type'] === 'Gene')
|
|
264
274
|
delete out['confidence'];
|
|
@@ -299,6 +309,10 @@ export function toGeneCandidate(rec) {
|
|
|
299
309
|
const signalsMatch = strArr(r['signals_match'] ?? r['signalsMatch']) ?? [];
|
|
300
310
|
const reuseCount = num(r['reuse_count'] ?? r['reuseCount']) ?? 0;
|
|
301
311
|
const generationSource = algo.geneGenerationSource(r, geneId);
|
|
312
|
+
// Project onto the wire allowlist first, then re-run strict K_auto on the same bytes selection
|
|
313
|
+
// will see. Soft-preference must not stamp membership from hub delivery metadata that strip drops.
|
|
314
|
+
const hubAsset = stripHubPayloadMetadata(rec);
|
|
315
|
+
const kautoMember = algo.decideKauto(hubAsset).inKauto;
|
|
302
316
|
return {
|
|
303
317
|
geneId,
|
|
304
318
|
assetId,
|
|
@@ -310,7 +324,8 @@ export function toGeneCandidate(rec) {
|
|
|
310
324
|
...(typeof r['category'] === 'string' ? { category: r['category'] } : {}),
|
|
311
325
|
...(typeof r['summary'] === 'string' ? { summary: r['summary'] } : {}),
|
|
312
326
|
...(generationSource ? { generationSource } : {}),
|
|
313
|
-
|
|
327
|
+
...(kautoMember ? { kautoMember: true } : {}),
|
|
328
|
+
hubAsset,
|
|
314
329
|
};
|
|
315
330
|
}
|
|
316
331
|
/**
|
|
@@ -332,7 +347,7 @@ export async function searchHubMetadata(cap, cache, signals, opts = {}) {
|
|
|
332
347
|
// Domain fence: derived from the turn's own task_domain:* signals (never from prose), mapped to
|
|
333
348
|
// the hub taxonomy. Scopes the structured signal leg only — the semantic leg already carries its
|
|
334
349
|
// own allowlisted free-text and stays domain-agnostic as the discovery fallback.
|
|
335
|
-
const hubDomain = hubDomainFromSignals(
|
|
350
|
+
const hubDomain = hubDomainFromSignals(signals);
|
|
336
351
|
const signalSearchLimit = opts.searchLimit ? opts.searchLimit : undefined;
|
|
337
352
|
const limitKey = signalSearchLimit === undefined ? 'all' : String(signalSearchLimit);
|
|
338
353
|
const domainKey = hubDomain === null ? '' : `:domain:${hubDomain}`;
|
|
@@ -9,7 +9,15 @@ export interface HubLearningPacketSinkOptions {
|
|
|
9
9
|
/** Optional node identity recorded on the packet (hub nodeId column). */
|
|
10
10
|
nodeId?: () => string | undefined;
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Deterministic content hash over the draft body (hub contentHash column, dedup aid).
|
|
14
|
+
*
|
|
15
|
+
* Bare 64-hex, NOT `sha256:`-prefixed: the hub column is VarChar(64), so a prefixed
|
|
16
|
+
* digest is 71 chars and every upload failed with a Prisma "value too long" 500. The
|
|
17
|
+
* hub schema now rejects over-64 at validation, which would make it a 400 instead —
|
|
18
|
+
* either way the algorithm is fixed at sha256 by this contract, so the prefix carried
|
|
19
|
+
* no information.
|
|
20
|
+
*/
|
|
13
21
|
export declare function learningPacketContentHash(draft: trace.LearningPacketDraft): string;
|
|
14
22
|
/**
|
|
15
23
|
* Auth headers for the strict learning-packets routes (requireAuth reads Authorization only).
|
|
@@ -19,16 +19,47 @@ function failureCategoryFor(failureKind) {
|
|
|
19
19
|
return 'tool_error';
|
|
20
20
|
return 'other';
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Map the runtime's outcome onto the hub OUTCOME_STATUSES enum, tiered by whether an
|
|
24
|
+
* external verifier actually adjudicated the run.
|
|
25
|
+
*
|
|
26
|
+
* A verified run gets a definite verdict (`succeeded` / `failed`). An unverified one
|
|
27
|
+
* gets `partially_succeeded` -- deliberately NOT `succeeded`, and no longer omitted:
|
|
28
|
+
*
|
|
29
|
+
* - Omitting it (the previous behaviour) threw the run away. The packet reached the
|
|
30
|
+
* hub with no outcome at all, which is indistinguishable from a run nobody looked
|
|
31
|
+
* at, so a consumer could not tell "we don't know" from "not recorded".
|
|
32
|
+
* - Calling it `succeeded` would be worse: the runtime only knows the turn loop
|
|
33
|
+
* ended without crashing, which is not evidence the task was done correctly.
|
|
34
|
+
* Training on that teaches format imitation.
|
|
35
|
+
*
|
|
36
|
+
* `partially_succeeded` says exactly what is true -- it ran to completion and nobody
|
|
37
|
+
* checked the result -- and pairs with `verifier` being absent, so a consumer filters
|
|
38
|
+
* on the verifier rather than having to infer trust from the status. Darwin's training
|
|
39
|
+
* path takes only rows with a real verifier; see docs/rsi-stage1-plan.md.
|
|
40
|
+
* @param status Runtime-side outcome.
|
|
41
|
+
* @param verified True when an external verifier ran (evaluation.placeholder === false).
|
|
42
|
+
* @returns A hub OUTCOME_STATUSES value.
|
|
43
|
+
*/
|
|
44
|
+
function outcomeStatusFor(status, verified) {
|
|
25
45
|
if (status === 'failed')
|
|
26
46
|
return 'failed';
|
|
27
|
-
|
|
47
|
+
if (status === 'success' && verified)
|
|
48
|
+
return 'succeeded';
|
|
49
|
+
// Ran to completion, unadjudicated -- or the runtime itself is unsure.
|
|
50
|
+
return 'partially_succeeded';
|
|
28
51
|
}
|
|
29
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Deterministic content hash over the draft body (hub contentHash column, dedup aid).
|
|
54
|
+
*
|
|
55
|
+
* Bare 64-hex, NOT `sha256:`-prefixed: the hub column is VarChar(64), so a prefixed
|
|
56
|
+
* digest is 71 chars and every upload failed with a Prisma "value too long" 500. The
|
|
57
|
+
* hub schema now rejects over-64 at validation, which would make it a 400 instead —
|
|
58
|
+
* either way the algorithm is fixed at sha256 by this contract, so the prefix carried
|
|
59
|
+
* no information.
|
|
60
|
+
*/
|
|
30
61
|
export function learningPacketContentHash(draft) {
|
|
31
|
-
return
|
|
62
|
+
return createHash('sha256').update(JSON.stringify(draft)).digest('hex');
|
|
32
63
|
}
|
|
33
64
|
/**
|
|
34
65
|
* Auth headers for the strict learning-packets routes (requireAuth reads Authorization only).
|
|
@@ -47,7 +78,7 @@ export async function learningOpsAuthHeaders(auth, method, path) {
|
|
|
47
78
|
export function learningPacketWireBody(draft, nodeId) {
|
|
48
79
|
const truncated = draft.trajectory.length > HUB_TRACE_EVENTS_MAX;
|
|
49
80
|
const events = draft.trajectory.slice(0, HUB_TRACE_EVENTS_MAX);
|
|
50
|
-
const outcomeStatus = outcomeStatusFor(draft.evaluation.outcomeStatus);
|
|
81
|
+
const outcomeStatus = outcomeStatusFor(draft.evaluation.outcomeStatus, draft.evaluation.placeholder === false);
|
|
51
82
|
const failureCategory = failureCategoryFor(draft.evaluation.failureCategory);
|
|
52
83
|
return {
|
|
53
84
|
schemaVersion: draft.schemaVersion,
|
|
@@ -60,7 +91,7 @@ export function learningPacketWireBody(draft, nodeId) {
|
|
|
60
91
|
idempotencyKey: `${draft.source.repo}:${draft.source.run}`,
|
|
61
92
|
contentHash: learningPacketContentHash(draft),
|
|
62
93
|
...(nodeId ? { nodeId } : {}),
|
|
63
|
-
|
|
94
|
+
outcomeStatus,
|
|
64
95
|
// evaluation fill-in (slice 6): a non-placeholder evaluation carries the runtime's external verifier
|
|
65
96
|
// ('automated_test' is in the hub VERIFIERS enum); passed/score details ride inside payload.evaluation.
|
|
66
97
|
...(draft.evaluation.verifier !== null ? { verifier: draft.evaluation.verifier } : {}),
|
|
@@ -116,10 +147,20 @@ export class HubLearningPacketSink {
|
|
|
116
147
|
redirect: 'manual',
|
|
117
148
|
body: JSON.stringify(learningPacketWireBody(draft, this.opts.nodeId?.())),
|
|
118
149
|
});
|
|
119
|
-
|
|
150
|
+
// Hub route returns 201 Created. The public website BFF/proxy in front of
|
|
151
|
+
// /api/learning-packets has been observed to surface the same body as 200.
|
|
152
|
+
// Accept both when a packet id is present so a successful write is never
|
|
153
|
+
// reported as hub 200 rejection (which previously made every live upload
|
|
154
|
+
// look failed while the row was already stored).
|
|
155
|
+
if (res.status === 201 || res.status === 200) {
|
|
120
156
|
const body = await res.json().catch(() => null);
|
|
121
157
|
const packet = body && typeof body === 'object' ? body.packet : undefined;
|
|
122
|
-
|
|
158
|
+
if (typeof packet?.id === 'string') {
|
|
159
|
+
return { accepted: true, reason: packet.id };
|
|
160
|
+
}
|
|
161
|
+
if (res.status === 201)
|
|
162
|
+
return { accepted: true };
|
|
163
|
+
// Bare 200 without a packet body is not a create success we can claim.
|
|
123
164
|
}
|
|
124
165
|
if (res.status === 409)
|
|
125
166
|
return { accepted: true, reason: 'duplicate_source' };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evomap/evolver-adapter-public",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.22",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@evomap/atp-sdk": "^0.1.0",
|
|
20
|
-
"@evomap/evolver-core": "2.0.0-beta.
|
|
20
|
+
"@evomap/evolver-core": "2.0.0-beta.22",
|
|
21
21
|
"undici": "^6.27.0"
|
|
22
22
|
},
|
|
23
23
|
"optionalDependencies": {
|