@aiwg/cli 2026.10.10 → 2026.10.12
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/agentic/code/providers/model-capabilities.v1.json +78 -14
- package/agentic/code/providers/model-catalog.v1.json +62 -12
- package/dist/src/artifacts/binding-target-identity.js +51 -0
- package/dist/src/artifacts/checksum-manifest.js +12 -0
- package/dist/src/artifacts/index-builder.js +11 -13
- package/dist/src/artifacts/query-engine.js +5 -11
- package/dist/src/cli/handlers/doctor-help.js +32 -0
- package/dist/src/cli/handlers/gates.js +19 -18
- package/dist/src/cli/handlers/models-help.js +7 -1
- package/dist/src/cli/handlers/models.js +3 -3
- package/dist/src/cli/handlers/script-runner.js +8 -5
- package/dist/src/cli/handlers/sessions-intake.js +104 -0
- package/dist/src/cli/handlers/sessions-tail.js +172 -0
- package/dist/src/cli/handlers/sessions.js +287 -31
- package/dist/src/cli/handlers/skill-lint.js +10 -3
- package/dist/src/cli/handlers/steward-format.js +100 -0
- package/dist/src/cli/handlers/steward-models.js +167 -0
- package/dist/src/cli/handlers/steward.js +14 -248
- package/dist/src/cli/handlers/use-bundle-counts.js +61 -0
- package/dist/src/cli/handlers/use.js +18 -28
- package/dist/src/cli/handlers/utilities.js +1 -24
- package/dist/src/config/aiwg-config.js +7 -0
- package/dist/src/config/authorization-cli.js +89 -0
- package/dist/src/config/cli-help.js +1 -0
- package/dist/src/config/cli.js +10 -1
- package/dist/src/config/worker-context.js +337 -0
- package/dist/src/decision/context-pruning.js +3 -2
- package/dist/src/decision/ensemble/contract.js +15 -4
- package/dist/src/decision/ensemble-study/artifacts.js +5 -0
- package/dist/src/decision/ensemble-study/score.js +4 -3
- package/dist/src/decision/feature-export.js +3 -9
- package/dist/src/decision/heldout/collector.js +2 -2
- package/dist/src/decision/issue-triage/runtime.js +3 -9
- package/dist/src/decision/qualification/gates.js +2 -1
- package/dist/src/decision/qualification/release.js +2 -3
- package/dist/src/decision/routing/report.js +2 -0
- package/dist/src/decision/sdlc-screening.js +3 -5
- package/dist/src/decision/sensitivity/comparative.js +5 -3
- package/dist/src/gates/driver.js +6 -77
- package/dist/src/gates/evaluate.js +4 -11
- package/dist/src/gates/floors.js +4 -4
- package/dist/src/gates/index.js +3 -3
- package/dist/src/gates/lattice.js +26 -0
- package/dist/src/gates/registry.js +2 -1
- package/dist/src/gates/report.js +19 -7
- package/dist/src/issues/audit-cli.js +120 -0
- package/dist/src/issues/audit-contract.js +64 -0
- package/dist/src/issues/audit-local.js +82 -0
- package/dist/src/issues/audit.js +220 -0
- package/dist/src/lint/rule-activation.js +15 -1
- package/dist/src/mcp/tools/worker-invoke.mjs +108 -10
- package/dist/src/mission-protocol/canonical-codecs.js +270 -0
- package/dist/src/mission-protocol/codecs.js +22 -550
- package/dist/src/mission-protocol/health-trace-codecs.js +281 -0
- package/dist/src/mission-protocol/health-trace-types.js +43 -0
- package/dist/src/mission-protocol/types.js +2 -42
- package/dist/src/mission-protocol/worker-contract-json.js +10 -0
- package/dist/src/mission-protocol/worker-review-gate.js +100 -0
- package/dist/src/mission-protocol/worker-review-types.js +2 -0
- package/dist/src/models/catalog-policy.js +280 -0
- package/dist/src/models/index.js +1 -1
- package/dist/src/models/model-capabilities.v1.json +78 -14
- package/dist/src/models/model-catalog.v1.json +62 -12
- package/dist/src/models/policy-resources.js +28 -0
- package/dist/src/models/provider-policy.js +10 -539
- package/dist/src/models/resolver.js +26 -8
- package/dist/src/models/router.js +15 -2
- package/dist/src/models/tiers.js +13 -0
- package/dist/src/models/types.js +0 -6
- package/dist/src/models/worker-ceilings.js +59 -0
- package/dist/src/models/worker-invocation-policy.js +243 -0
- package/dist/src/models/worker-plan.js +16 -20
- package/dist/src/models/worker-review-lineage.js +55 -0
- package/dist/src/models/worker-selection-policy.js +1 -1
- package/dist/src/models/wrapper-route.js +6 -3
- package/dist/src/policy/authorization.js +30 -1
- package/dist/src/policy/hitl-config.js +63 -0
- package/dist/src/policy/hitl-receipt.js +57 -0
- package/dist/src/policy/hitl-types.js +4 -0
- package/dist/src/policy/hitl-validation.js +39 -0
- package/dist/src/policy/hitl.js +117 -0
- package/dist/src/process/aiwg-probe-command.d.mts +15 -0
- package/dist/src/process/aiwg-probe-command.mjs +37 -0
- package/dist/src/rules/activation.d.mts +1 -1
- package/dist/src/rules/activation.mjs +0 -2
- package/dist/src/rules/gate-coverage.js +51 -0
- package/dist/src/rules/gate-references.js +16 -0
- package/dist/src/rules/rule-frontmatter.schema.json +7 -1
- package/dist/src/serve/worker-command-request.js +21 -4
- package/dist/src/serve/worker-invocation-preparation.js +3 -1
- package/dist/src/serve/worker-invocation.js +21 -10
- package/dist/src/sessions/adapters/deepseek-harness.js +1 -0
- package/dist/src/sessions/adapters/grok-build-native.js +269 -0
- package/dist/src/sessions/adapters/grok-build.js +57 -15
- package/dist/src/sessions/adapters/grokbot.js +7 -0
- package/dist/src/sessions/adapters/hermes-state-db.js +252 -0
- package/dist/src/sessions/adapters/hermes.js +42 -3
- package/dist/src/sessions/adapters/warp.js +1 -1
- package/dist/src/sessions/batch-import.js +44 -6
- package/dist/src/sessions/contracts.js +20 -1
- package/dist/src/sessions/coverage-preflight.js +7 -1
- package/dist/src/sessions/discovery-capability.js +38 -0
- package/dist/src/sessions/fortemi-export-mapping.js +33 -3
- package/dist/src/sessions/host-catalog.js +157 -0
- package/dist/src/sessions/image-blobs.js +141 -0
- package/dist/src/sessions/importer.js +9 -232
- package/dist/src/sessions/index.js +6 -0
- package/dist/src/sessions/intake-dir.js +71 -0
- package/dist/src/sessions/normalization.js +251 -0
- package/dist/src/sessions/refresh.js +25 -2
- package/dist/src/sessions/repository.js +164 -22
- package/dist/src/sessions/tail.js +91 -0
- package/dist/src/sessions/workspace-discovery.js +88 -9
- package/dist/src/skills/agent-skill-sidecar.js +28 -0
- package/dist/src/skills/agent-skills.js +4 -23
- package/dist/src/skills/claude-surface-projection.js +25 -0
- package/dist/src/skills/deployer.js +8 -288
- package/dist/src/skills/deployment-policy.js +114 -0
- package/dist/src/skills/deployment-projection.js +152 -0
- package/dist/src/skills/deployment-types.js +20 -0
- package/dist/src/skills/exporter.js +8 -31
- package/dist/src/skills/provider-extensions.js +41 -0
- package/dist/src/skills/run.js +6 -0
- package/dist/src/skills/types.js +0 -8
- package/dist/src/skills/validator-resources.js +68 -0
- package/dist/src/skills/validator.js +6 -55
- package/dist/src/storage/cli-migrate-options.js +125 -0
- package/dist/src/storage/cli-migrate.js +111 -0
- package/dist/src/storage/cli.js +4 -279
- package/dist/src/storage/migration-adapter.js +79 -0
- package/dist/src/storage/migration-copy.js +108 -0
- package/dist/src/storage/migration-protocol.js +14 -197
- package/dist/src/storage/migration-records.js +186 -0
- package/dist/src/storage/migration-types.js +12 -0
- package/dist/src/tracker/forge-http.js +2 -1
- package/dist/src/tracker/issue-pages.js +110 -0
- package/package.json +7 -1
- package/schemas/mission-v1.schema.json +335 -0
- package/schemas/models/model-catalog.v1.schema.json +19 -1
- package/schemas/models/model-config-compatibility.v1.schema.json +3 -2
- package/schemas/models/model-policy.v1.schema.json +1 -1
- package/tools/agents/providers/provider-paths-staging.mjs +35 -0
- package/tools/agents/providers/rule-binding-targets.mjs +146 -0
- package/tools/agents/providers/rule-delivery.mjs +7 -126
- package/tools/ralph-external/lib/muse-adapter.mjs +10 -0
- package/tools/ralph-external/lib/worker-context.mjs +237 -0
- package/tools/ralph-external/lib/worker-invocation-ancestry.mjs +132 -0
- package/tools/ralph-external/lib/worker-invocation-processes.mjs +123 -0
- package/tools/ralph-external/lib/worker-isolation-status.mjs +48 -0
- package/tools/ralph-external/lib/worker-isolation.mjs +17 -29
- package/tools/ralph-external/lib/worker-launch-cli.mjs +3 -1
- package/tools/ralph-external/lib/worker-overflow.mjs +48 -13
- package/tools/ralph-external/lib/worker-retry-evidence.mjs +103 -0
- package/tools/ralph-external/lib/worker-termination.mjs +82 -0
- package/tools/ralph-external/session-launcher.mjs +51 -96
- package/vscode-extension/schemas/aiwg.config.v1.json +177 -0
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { SESSION_CONTRACT_VERSION,
|
|
1
|
+
import { SESSION_CONTRACT_VERSION, assertSupportedSchemaMajor, sha256, SessionContractError, schemaIssueDetail, assertSessionResourceLimit, } from './contracts.js';
|
|
2
2
|
import { assertImportByteLimit, DEFAULT_IMPORT_BYTE_LIMITS, resolveImportLimits } from './import-limits.js';
|
|
3
|
-
import { redactSessionValue,
|
|
3
|
+
import { redactSessionValue, sanitizeNativeExtensions } from './policy.js';
|
|
4
4
|
import { fingerprintSourcePrefix } from './readers.js';
|
|
5
|
-
import {
|
|
6
|
-
import { classifySessionEventOrigin, deriveSessionIntent, } from './origin.js';
|
|
5
|
+
import { normalizeSessionBatch, sourceGenerationDigest } from './normalization.js';
|
|
7
6
|
export const DEFAULT_IMPORT_LIMITS = {
|
|
8
7
|
maxRecords: 1_000_000,
|
|
9
8
|
...DEFAULT_IMPORT_BYTE_LIMITS,
|
|
@@ -99,7 +98,7 @@ export class IncrementalSessionImporter {
|
|
|
99
98
|
batchStart, checkpoint.recordsRead,
|
|
100
99
|
...batchDigests,
|
|
101
100
|
].join('\0'));
|
|
102
|
-
const normalized =
|
|
101
|
+
const normalized = normalizeSessionBatch(request, batch, batchDigests, runId, sourceObservedAt);
|
|
103
102
|
const run = {
|
|
104
103
|
contractVersion: SESSION_CONTRACT_VERSION,
|
|
105
104
|
importRunId: runId,
|
|
@@ -123,6 +122,7 @@ export class IncrementalSessionImporter {
|
|
|
123
122
|
source: sanitizedSource, run,
|
|
124
123
|
sessions: normalized.sessions, events: normalized.events,
|
|
125
124
|
batchRunId: request.batchRunId,
|
|
125
|
+
imageBlobs: normalized.imageBlobs,
|
|
126
126
|
}, { ...checkpoint }, request.publish ?? request.source.consistency !== 'complete');
|
|
127
127
|
const memory = process.memoryUsage();
|
|
128
128
|
peakHeap = Math.max(peakHeap, memory.heapUsed);
|
|
@@ -176,7 +176,10 @@ export class IncrementalSessionImporter {
|
|
|
176
176
|
}
|
|
177
177
|
else {
|
|
178
178
|
checkpoint.bytesRead += bytes;
|
|
179
|
-
|
|
179
|
+
// Older Pi adapters exposed bare byte counts without a byte: tag;
|
|
180
|
+
// those checkpoints historically counted records instead.
|
|
181
|
+
checkpoint.cursor = request.adapter.provider === 'pi' ? String(checkpoint.recordsRead)
|
|
182
|
+
: record.sourceCursor ?? String(checkpoint.recordsRead);
|
|
180
183
|
}
|
|
181
184
|
if (batch.length >= limits.batchSize)
|
|
182
185
|
flush();
|
|
@@ -230,232 +233,6 @@ function recordIdentity(record) {
|
|
|
230
233
|
const serialized = JSON.stringify(record);
|
|
231
234
|
return { bytes: Buffer.byteLength(serialized), digest: sha256(serialized) };
|
|
232
235
|
}
|
|
233
|
-
function normalizeBatch(request, records, digests, importRunId, sourceObservedAt) {
|
|
234
|
-
const sessions = new Map();
|
|
235
|
-
const events = records.map((record, index) => {
|
|
236
|
-
const sessionId = stableSessionId(request.source.provider, request.source.sourceId, record.nativeSessionId);
|
|
237
|
-
const native = sanitizeNativeExtensions(record.extensions ?? {});
|
|
238
|
-
const lineage = request.source.provider === 'codex' && native.value.lineage
|
|
239
|
-
? { lineage: native.value.lineage } : {};
|
|
240
|
-
const digest = digests[index];
|
|
241
|
-
const origin = classifySessionEventOrigin(request.source.provider, record);
|
|
242
|
-
const lifecycle = sessionLifecycle(request, record, sourceObservedAt);
|
|
243
|
-
const lifecycleEvidence = sessionLifecycleEvidence(request, record, sourceObservedAt);
|
|
244
|
-
const extensions = {
|
|
245
|
-
[`native.${request.source.provider}`]: record.extensions ?? {},
|
|
246
|
-
};
|
|
247
|
-
const event = sanitizeSessionEvent(SessionEventSchema.parse({
|
|
248
|
-
contractVersion: SESSION_CONTRACT_VERSION,
|
|
249
|
-
eventId: stableEventId(request.source.provider, request.source.sourceId, record, digest),
|
|
250
|
-
sessionId, sourceId: request.source.sourceId, importRunId,
|
|
251
|
-
nativeId: record.nativeEventId ?? null, sequence: record.sequence,
|
|
252
|
-
kind: record.kind, role: record.role ?? null, occurredAt: record.occurredAt ?? null,
|
|
253
|
-
activityBoundary: record.activityBoundary ?? null,
|
|
254
|
-
activityBoundaryBasis: record.activityBoundaryBasis ?? null,
|
|
255
|
-
activityBoundaryConfidence: record.activityBoundaryConfidence ?? null,
|
|
256
|
-
origin: origin.origin,
|
|
257
|
-
originRule: origin.rule,
|
|
258
|
-
originClassifierVersion: origin.classifierVersion,
|
|
259
|
-
participant: record.participant ?? null,
|
|
260
|
-
toolName: record.toolName ?? null,
|
|
261
|
-
toolCallId: record.toolCallId ?? null,
|
|
262
|
-
model: record.model ?? null,
|
|
263
|
-
entities: record.entities ?? [],
|
|
264
|
-
extractionState: record.extractionState ?? null,
|
|
265
|
-
searchableText: record.text, digest, rawReference: record.rawReference,
|
|
266
|
-
adapterVersion: request.adapter.adapterVersion,
|
|
267
|
-
consistency: request.source.consistency,
|
|
268
|
-
sensitivity: { classification: 'none', classes: [] },
|
|
269
|
-
opaque: !isKnownEventKind(record.kind),
|
|
270
|
-
extensions,
|
|
271
|
-
}));
|
|
272
|
-
if (!sessions.has(sessionId)) {
|
|
273
|
-
sessions.set(sessionId, SessionSchema.parse({
|
|
274
|
-
contractVersion: SESSION_CONTRACT_VERSION,
|
|
275
|
-
sessionId, sourceId: request.source.sourceId, provider: request.source.provider,
|
|
276
|
-
nativeSessionId: record.nativeSessionId, workspaceId: request.workspaceId,
|
|
277
|
-
startedAt: record.occurredAt ?? null, updatedAt: record.occurredAt ?? null,
|
|
278
|
-
consistency: request.source.consistency,
|
|
279
|
-
lifecycle,
|
|
280
|
-
sourceDigest: sha256(`${sourceGenerationDigest(request)}\0${record.nativeSessionId}`),
|
|
281
|
-
extensions: {
|
|
282
|
-
[`native.${request.source.provider}`]: {
|
|
283
|
-
...lineage,
|
|
284
|
-
lifecycleEvidence,
|
|
285
|
-
},
|
|
286
|
-
},
|
|
287
|
-
}));
|
|
288
|
-
}
|
|
289
|
-
else {
|
|
290
|
-
const session = sessions.get(sessionId);
|
|
291
|
-
session.startedAt = earlierTimestamp(session.startedAt, record.occurredAt ?? null);
|
|
292
|
-
session.updatedAt = laterTimestamp(session.updatedAt, record.occurredAt ?? null);
|
|
293
|
-
session.consistency = strongerConsistency(session.consistency, request.source.consistency);
|
|
294
|
-
const nativeKey = `native.${request.source.provider}`;
|
|
295
|
-
const nativeEnvelope = session.extensions[nativeKey];
|
|
296
|
-
const nativeRecord = nativeEnvelope && typeof nativeEnvelope === 'object' && !Array.isArray(nativeEnvelope)
|
|
297
|
-
? nativeEnvelope
|
|
298
|
-
: {};
|
|
299
|
-
const selected = selectLifecycleTransition(session.lifecycle, nativeRecord.lifecycleEvidence, lifecycle, lifecycleEvidence);
|
|
300
|
-
session.lifecycle = selected.lifecycle;
|
|
301
|
-
session.extensions[nativeKey] = {
|
|
302
|
-
...nativeRecord,
|
|
303
|
-
...lineage,
|
|
304
|
-
lifecycleEvidence: selected.evidence,
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
return event;
|
|
308
|
-
});
|
|
309
|
-
for (const session of sessions.values()) {
|
|
310
|
-
session.intent = deriveSessionIntent(events.filter((event) => event.sessionId === session.sessionId));
|
|
311
|
-
}
|
|
312
|
-
return { sessions: redactSessionValue([...sessions.values()]).value, events };
|
|
313
|
-
}
|
|
314
|
-
const KNOWN_EVENT_KINDS = new Set(['message', 'tool-call', 'tool-result', 'artifact', 'attachment', 'summary']);
|
|
315
|
-
function isKnownEventKind(kind) {
|
|
316
|
-
const normalized = kind.toLowerCase();
|
|
317
|
-
return KNOWN_EVENT_KINDS.has(normalized)
|
|
318
|
-
|| /^(?:tool-call|tool-result)(?:[._-]|$)/.test(normalized)
|
|
319
|
-
|| /^(?:sandbox|permission|approval|hitl|human|lifecycle)(?:[._-]|$)/.test(normalized);
|
|
320
|
-
}
|
|
321
|
-
function earlierTimestamp(left, right) {
|
|
322
|
-
if (!left)
|
|
323
|
-
return right;
|
|
324
|
-
if (!right)
|
|
325
|
-
return left;
|
|
326
|
-
return Date.parse(left) <= Date.parse(right) ? left : right;
|
|
327
|
-
}
|
|
328
|
-
function laterTimestamp(left, right) {
|
|
329
|
-
if (!left)
|
|
330
|
-
return right;
|
|
331
|
-
if (!right)
|
|
332
|
-
return left;
|
|
333
|
-
return Date.parse(left) >= Date.parse(right) ? left : right;
|
|
334
|
-
}
|
|
335
|
-
function strongerConsistency(left, right) {
|
|
336
|
-
const rank = {
|
|
337
|
-
provisional: 0,
|
|
338
|
-
'consistent-snapshot': 1,
|
|
339
|
-
complete: 2,
|
|
340
|
-
};
|
|
341
|
-
return rank[left] >= rank[right] ? left : right;
|
|
342
|
-
}
|
|
343
|
-
function sessionLifecycle(request, record, sourceObservedAt) {
|
|
344
|
-
const explicit = nativeLifecycle(record.extensions);
|
|
345
|
-
if (explicit)
|
|
346
|
-
return explicit;
|
|
347
|
-
if (request.source.consistency === 'complete')
|
|
348
|
-
return 'complete';
|
|
349
|
-
const observedAt = record.occurredAt ?? sourceObservedAt;
|
|
350
|
-
if (observedAt && isStaleHistoricalTimestamp(observedAt, inactivityThresholdMs(request)))
|
|
351
|
-
return 'inactive';
|
|
352
|
-
return 'active';
|
|
353
|
-
}
|
|
354
|
-
function sessionLifecycleEvidence(request, record, sourceObservedAt) {
|
|
355
|
-
const observedAt = record.occurredAt ?? sourceObservedAt;
|
|
356
|
-
const explicit = nativeLifecycle(record.extensions);
|
|
357
|
-
if (explicit) {
|
|
358
|
-
return {
|
|
359
|
-
basis: 'provider-explicit-event',
|
|
360
|
-
state: explicit,
|
|
361
|
-
observedAt: observedAt ?? request.source.authorizedAt,
|
|
362
|
-
confidence: 'high',
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
if (request.source.consistency === 'complete') {
|
|
366
|
-
return {
|
|
367
|
-
basis: 'complete-source',
|
|
368
|
-
state: 'complete',
|
|
369
|
-
observedAt: observedAt ?? request.source.authorizedAt,
|
|
370
|
-
confidence: 'high',
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
const thresholdMs = inactivityThresholdMs(request);
|
|
374
|
-
if (observedAt && isStaleHistoricalTimestamp(observedAt, thresholdMs)) {
|
|
375
|
-
return {
|
|
376
|
-
basis: 'inactivity-threshold',
|
|
377
|
-
state: 'inactive',
|
|
378
|
-
observedAt,
|
|
379
|
-
confidence: 'medium',
|
|
380
|
-
thresholdMs,
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
return {
|
|
384
|
-
basis: 'open-provisional-source',
|
|
385
|
-
state: 'active',
|
|
386
|
-
observedAt: observedAt ?? request.source.authorizedAt,
|
|
387
|
-
confidence: 'provisional',
|
|
388
|
-
thresholdMs,
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
function nativeLifecycle(extensions) {
|
|
392
|
-
const raw = typeof extensions?.lifecycle === 'string' ? extensions.lifecycle : undefined;
|
|
393
|
-
if (!raw)
|
|
394
|
-
return null;
|
|
395
|
-
const normalized = {
|
|
396
|
-
active: 'active',
|
|
397
|
-
inactive: 'inactive',
|
|
398
|
-
paused: 'paused',
|
|
399
|
-
complete: 'complete',
|
|
400
|
-
completed: 'complete',
|
|
401
|
-
archived: 'archived',
|
|
402
|
-
deleted: 'tombstoned',
|
|
403
|
-
cancelled: 'interrupted',
|
|
404
|
-
canceled: 'interrupted',
|
|
405
|
-
failed: 'interrupted',
|
|
406
|
-
interrupted: 'interrupted',
|
|
407
|
-
unknown: 'unknown',
|
|
408
|
-
'unknown-at-import': 'unknown',
|
|
409
|
-
'completed-at-import': 'complete',
|
|
410
|
-
};
|
|
411
|
-
return normalized[raw] ?? null;
|
|
412
|
-
}
|
|
413
|
-
function selectLifecycleTransition(leftLifecycle, left, rightLifecycle, right) {
|
|
414
|
-
const leftEvidence = asLifecycleEvidence(left);
|
|
415
|
-
if (leftLifecycle === 'tombstoned') {
|
|
416
|
-
return { lifecycle: leftLifecycle, evidence: leftEvidence ?? right };
|
|
417
|
-
}
|
|
418
|
-
if (!leftEvidence)
|
|
419
|
-
return { lifecycle: rightLifecycle, evidence: right };
|
|
420
|
-
const rank = {
|
|
421
|
-
'open-provisional-source': 1,
|
|
422
|
-
'inactivity-threshold': 1,
|
|
423
|
-
'complete-source': 2,
|
|
424
|
-
'provider-explicit-event': 3,
|
|
425
|
-
};
|
|
426
|
-
const leftRank = rank[String(leftEvidence.basis)] ?? 0;
|
|
427
|
-
const rightRank = rank[String(right.basis)] ?? 0;
|
|
428
|
-
const rightIsNewer = evidenceTimestamp(right) > evidenceTimestamp(leftEvidence);
|
|
429
|
-
return rightRank > leftRank || (rightRank === leftRank && rightIsNewer)
|
|
430
|
-
? { lifecycle: rightLifecycle, evidence: right }
|
|
431
|
-
: { lifecycle: leftLifecycle, evidence: leftEvidence };
|
|
432
|
-
}
|
|
433
|
-
function asLifecycleEvidence(value) {
|
|
434
|
-
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
435
|
-
? value
|
|
436
|
-
: null;
|
|
437
|
-
}
|
|
438
|
-
function evidenceTimestamp(value) {
|
|
439
|
-
const parsed = Date.parse(String(value.observedAt ?? ''));
|
|
440
|
-
return Number.isFinite(parsed) ? parsed : Number.NEGATIVE_INFINITY;
|
|
441
|
-
}
|
|
442
|
-
function inactivityThresholdMs(request) {
|
|
443
|
-
return request.inactivityThresholdMs ?? DEFAULT_INACTIVITY_THRESHOLD_MS;
|
|
444
|
-
}
|
|
445
|
-
function isStaleHistoricalTimestamp(value, thresholdMs) {
|
|
446
|
-
const timestamp = Date.parse(value);
|
|
447
|
-
return Number.isFinite(timestamp)
|
|
448
|
-
&& Date.now() - timestamp > thresholdMs;
|
|
449
|
-
}
|
|
450
|
-
function sourceGenerationDigest(request) {
|
|
451
|
-
return sha256([
|
|
452
|
-
request.source.sourceId,
|
|
453
|
-
request.source.provider,
|
|
454
|
-
request.selectedSource.locatorClass,
|
|
455
|
-
request.source.sourceSchemaVersion,
|
|
456
|
-
request.adapter.adapterVersion,
|
|
457
|
-
].join('\0'));
|
|
458
|
-
}
|
|
459
236
|
async function sourceContinuity(request, previous) {
|
|
460
237
|
if (request.selectedSource.authorizedScope.allowedRoots.length === 0
|
|
461
238
|
|| /^[a-z][a-z0-9+.-]*:\/\//i.test(request.selectedSource.locator)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './contracts.js';
|
|
2
|
+
export * from './image-blobs.js';
|
|
2
3
|
export * from './fixtures.js';
|
|
3
4
|
export * from './policy.js';
|
|
4
5
|
export * from './discovery.js';
|
|
@@ -19,6 +20,8 @@ export * from './importer.js';
|
|
|
19
20
|
export * from './import-lease.js';
|
|
20
21
|
export * from './batch-contracts.js';
|
|
21
22
|
export * from './batch-import.js';
|
|
23
|
+
export * from './intake-dir.js';
|
|
24
|
+
export * from './host-catalog.js';
|
|
22
25
|
export * from './workspace-discovery.js';
|
|
23
26
|
export * from './timeline.js';
|
|
24
27
|
export * from './origin.js';
|
|
@@ -30,11 +33,13 @@ export * from './adapters/copilot.js';
|
|
|
30
33
|
export * from './adapters/cursor.js';
|
|
31
34
|
export * from './adapters/factory.js';
|
|
32
35
|
export * from './adapters/hermes.js';
|
|
36
|
+
export * from './adapters/hermes-state-db.js';
|
|
33
37
|
export * from './adapters/opencode.js';
|
|
34
38
|
export * from './adapters/openclaw.js';
|
|
35
39
|
export * from './adapters/openhuman.js';
|
|
36
40
|
export * from './adapters/grokbot.js';
|
|
37
41
|
export * from './adapters/grok-build.js';
|
|
42
|
+
export * from './adapters/grok-build-native.js';
|
|
38
43
|
export * from './grok-build-cli.js';
|
|
39
44
|
export * from './adapters/pi.js';
|
|
40
45
|
export * from './adapters/deepseek-harness.js';
|
|
@@ -44,4 +49,5 @@ export * from './adapters/muse.js';
|
|
|
44
49
|
export * from './adapters/omp.js';
|
|
45
50
|
export * from './adapter-registry.js';
|
|
46
51
|
export * from './coverage-preflight.js';
|
|
52
|
+
export * from './discovery-capability.js';
|
|
47
53
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Intake-directory batch import for `sessions import --from-dir` (#3168).
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { SessionContractError } from './contracts.js';
|
|
4
|
+
export const INTAKE_DIR_SCHEMA_VERSION = '1.0.0';
|
|
5
|
+
/** Recognised intake files are provider export payloads, never control files. */
|
|
6
|
+
export function isRecognisedIntakeFile(provider, filename) {
|
|
7
|
+
if (filename.startsWith('.')) {
|
|
8
|
+
return { recognised: false, reason: `skipped dotfile ${JSON.stringify(filename)}` };
|
|
9
|
+
}
|
|
10
|
+
if (provider === 'claude') {
|
|
11
|
+
if (filename.endsWith('.json') || filename.endsWith('.jsonl'))
|
|
12
|
+
return { recognised: true };
|
|
13
|
+
return {
|
|
14
|
+
recognised: false,
|
|
15
|
+
reason: 'unrecognised extension for provider claude:'
|
|
16
|
+
+ ` expected .json (web/account export) or .jsonl (transcript/hook), got ${JSON.stringify(filename)}`,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (filename.endsWith('.json') || filename.endsWith('.jsonl'))
|
|
20
|
+
return { recognised: true };
|
|
21
|
+
return {
|
|
22
|
+
recognised: false,
|
|
23
|
+
reason: `unrecognised extension for provider ${provider}:`
|
|
24
|
+
+ ` expected .json or .jsonl, got ${JSON.stringify(filename)}`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Stable per-file source identity: an optional prefix plus the file basename. */
|
|
28
|
+
export function intakeSourceId(prefix, filename) {
|
|
29
|
+
const base = filename.replace(/[^A-Za-z0-9._-]+/g, '_');
|
|
30
|
+
return prefix ? `${prefix}/${base}` : base;
|
|
31
|
+
}
|
|
32
|
+
/** Sorted basenames of regular files directly inside the intake directory. */
|
|
33
|
+
export async function listIntakeDirFiles(dir) {
|
|
34
|
+
let entries;
|
|
35
|
+
try {
|
|
36
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
throw new SessionContractError('INVALID_ARGUMENT', `intake directory is not readable: ${dir}`);
|
|
40
|
+
}
|
|
41
|
+
return entries
|
|
42
|
+
.filter((entry) => entry.isFile())
|
|
43
|
+
.map((entry) => entry.name)
|
|
44
|
+
.sort();
|
|
45
|
+
}
|
|
46
|
+
/** Content-free roll-up over one receipt per intake file. */
|
|
47
|
+
export function summarizeIntakeReceipts(files) {
|
|
48
|
+
const summary = {
|
|
49
|
+
total: files.length,
|
|
50
|
+
imported: 0,
|
|
51
|
+
alreadyImported: 0,
|
|
52
|
+
skipped: 0,
|
|
53
|
+
rejected: 0,
|
|
54
|
+
sessionsInserted: 0,
|
|
55
|
+
eventsInserted: 0,
|
|
56
|
+
};
|
|
57
|
+
for (const file of files) {
|
|
58
|
+
if (file.status === 'imported')
|
|
59
|
+
summary.imported += 1;
|
|
60
|
+
else if (file.status === 'already-imported')
|
|
61
|
+
summary.alreadyImported += 1;
|
|
62
|
+
else if (file.status === 'skipped')
|
|
63
|
+
summary.skipped += 1;
|
|
64
|
+
else
|
|
65
|
+
summary.rejected += 1;
|
|
66
|
+
summary.sessionsInserted += file.sessionsInserted;
|
|
67
|
+
summary.eventsInserted += file.eventsInserted;
|
|
68
|
+
}
|
|
69
|
+
return summary;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=intake-dir.js.map
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// Shared event normalization, image extraction, redaction, and lifecycle derivation.
|
|
2
|
+
import { SESSION_CONTRACT_VERSION, SessionEventSchema, SessionSchema, sha256, stableEventId, stableSessionId, } from './contracts.js';
|
|
3
|
+
import { redactSessionValue, sanitizeSessionEvent, sanitizeNativeExtensions } from './policy.js';
|
|
4
|
+
import { extractEventImages } from './image-blobs.js';
|
|
5
|
+
import { DEFAULT_INACTIVITY_THRESHOLD_MS } from './lifecycle.js';
|
|
6
|
+
import { classifySessionEventOrigin, deriveSessionIntent } from './origin.js';
|
|
7
|
+
export function normalizeSessionBatch(request, records, digests, importRunId, sourceObservedAt) {
|
|
8
|
+
const sessions = new Map();
|
|
9
|
+
// Extract inline images before sanitization: provider image blocks in
|
|
10
|
+
// extensions are redacted to markers below, so bytes must be lifted out
|
|
11
|
+
// first while the raw record is still intact (#3265).
|
|
12
|
+
const imageBlobs = new Map();
|
|
13
|
+
const events = records.map((record, index) => {
|
|
14
|
+
const sessionId = stableSessionId(request.source.provider, request.source.sourceId, record.nativeSessionId);
|
|
15
|
+
const native = sanitizeNativeExtensions(record.extensions ?? {});
|
|
16
|
+
const lineage = request.source.provider === 'codex' && native.value.lineage
|
|
17
|
+
? { lineage: native.value.lineage } : {};
|
|
18
|
+
const images = extractEventImages({
|
|
19
|
+
searchableText: record.text,
|
|
20
|
+
extensions: record.extensions,
|
|
21
|
+
rawReference: record.rawReference,
|
|
22
|
+
});
|
|
23
|
+
for (const image of images.images) {
|
|
24
|
+
if (!imageBlobs.has(image.digest))
|
|
25
|
+
imageBlobs.set(image.digest, image);
|
|
26
|
+
}
|
|
27
|
+
const digest = digests[index];
|
|
28
|
+
const origin = classifySessionEventOrigin(request.source.provider, record);
|
|
29
|
+
const lifecycle = sessionLifecycle(request, record, sourceObservedAt);
|
|
30
|
+
const lifecycleEvidence = sessionLifecycleEvidence(request, record, sourceObservedAt);
|
|
31
|
+
const extensions = {
|
|
32
|
+
[`native.${request.source.provider}`]: images.extensions,
|
|
33
|
+
};
|
|
34
|
+
const event = sanitizeSessionEvent(SessionEventSchema.parse({
|
|
35
|
+
contractVersion: SESSION_CONTRACT_VERSION,
|
|
36
|
+
eventId: stableEventId(request.source.provider, request.source.sourceId, record, digest),
|
|
37
|
+
sessionId, sourceId: request.source.sourceId, importRunId,
|
|
38
|
+
nativeId: record.nativeEventId ?? null, sequence: record.sequence,
|
|
39
|
+
kind: record.kind, role: record.role ?? null, occurredAt: record.occurredAt ?? null,
|
|
40
|
+
activityBoundary: record.activityBoundary ?? null,
|
|
41
|
+
activityBoundaryBasis: record.activityBoundaryBasis ?? null,
|
|
42
|
+
activityBoundaryConfidence: record.activityBoundaryConfidence ?? null,
|
|
43
|
+
origin: origin.origin,
|
|
44
|
+
originRule: origin.rule,
|
|
45
|
+
originClassifierVersion: origin.classifierVersion,
|
|
46
|
+
participant: record.participant ?? null,
|
|
47
|
+
toolName: record.toolName ?? null,
|
|
48
|
+
toolCallId: record.toolCallId ?? null,
|
|
49
|
+
model: record.model ?? null,
|
|
50
|
+
entities: record.entities ?? [],
|
|
51
|
+
extractionState: record.extractionState ?? null,
|
|
52
|
+
searchableText: images.searchableText, imageRefs: images.imageRefs,
|
|
53
|
+
digest, rawReference: record.rawReference,
|
|
54
|
+
adapterVersion: request.adapter.adapterVersion,
|
|
55
|
+
consistency: request.source.consistency,
|
|
56
|
+
sensitivity: { classification: 'none', classes: [] },
|
|
57
|
+
opaque: !isKnownEventKind(record.kind),
|
|
58
|
+
extensions,
|
|
59
|
+
}));
|
|
60
|
+
if (!sessions.has(sessionId)) {
|
|
61
|
+
sessions.set(sessionId, SessionSchema.parse({
|
|
62
|
+
contractVersion: SESSION_CONTRACT_VERSION,
|
|
63
|
+
sessionId, sourceId: request.source.sourceId, provider: request.source.provider,
|
|
64
|
+
nativeSessionId: record.nativeSessionId, workspaceId: request.workspaceId,
|
|
65
|
+
startedAt: record.occurredAt ?? null, updatedAt: record.occurredAt ?? null,
|
|
66
|
+
consistency: request.source.consistency,
|
|
67
|
+
lifecycle,
|
|
68
|
+
sourceDigest: sha256(`${sourceGenerationDigest(request)}\0${record.nativeSessionId}`),
|
|
69
|
+
extensions: {
|
|
70
|
+
[`native.${request.source.provider}`]: {
|
|
71
|
+
...lineage,
|
|
72
|
+
lifecycleEvidence,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
const session = sessions.get(sessionId);
|
|
79
|
+
session.startedAt = earlierTimestamp(session.startedAt, record.occurredAt ?? null);
|
|
80
|
+
session.updatedAt = laterTimestamp(session.updatedAt, record.occurredAt ?? null);
|
|
81
|
+
session.consistency = strongerConsistency(session.consistency, request.source.consistency);
|
|
82
|
+
const nativeKey = `native.${request.source.provider}`;
|
|
83
|
+
const nativeEnvelope = session.extensions[nativeKey];
|
|
84
|
+
const nativeRecord = nativeEnvelope && typeof nativeEnvelope === 'object' && !Array.isArray(nativeEnvelope)
|
|
85
|
+
? nativeEnvelope
|
|
86
|
+
: {};
|
|
87
|
+
const selected = selectLifecycleTransition(session.lifecycle, nativeRecord.lifecycleEvidence, lifecycle, lifecycleEvidence);
|
|
88
|
+
session.lifecycle = selected.lifecycle;
|
|
89
|
+
session.extensions[nativeKey] = {
|
|
90
|
+
...nativeRecord,
|
|
91
|
+
...lineage,
|
|
92
|
+
lifecycleEvidence: selected.evidence,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return event;
|
|
96
|
+
});
|
|
97
|
+
for (const session of sessions.values()) {
|
|
98
|
+
session.intent = deriveSessionIntent(events.filter((event) => event.sessionId === session.sessionId));
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
sessions: redactSessionValue([...sessions.values()]).value,
|
|
102
|
+
events,
|
|
103
|
+
imageBlobs: [...imageBlobs.values()],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const KNOWN_EVENT_KINDS = new Set(['message', 'tool-call', 'tool-result', 'artifact', 'attachment', 'summary']);
|
|
107
|
+
function isKnownEventKind(kind) {
|
|
108
|
+
const normalized = kind.toLowerCase();
|
|
109
|
+
return KNOWN_EVENT_KINDS.has(normalized)
|
|
110
|
+
|| /^(?:tool-call|tool-result)(?:[._-]|$)/.test(normalized)
|
|
111
|
+
|| /^(?:sandbox|permission|approval|hitl|human|lifecycle)(?:[._-]|$)/.test(normalized);
|
|
112
|
+
}
|
|
113
|
+
function earlierTimestamp(left, right) {
|
|
114
|
+
if (!left)
|
|
115
|
+
return right;
|
|
116
|
+
if (!right)
|
|
117
|
+
return left;
|
|
118
|
+
return Date.parse(left) <= Date.parse(right) ? left : right;
|
|
119
|
+
}
|
|
120
|
+
function laterTimestamp(left, right) {
|
|
121
|
+
if (!left)
|
|
122
|
+
return right;
|
|
123
|
+
if (!right)
|
|
124
|
+
return left;
|
|
125
|
+
return Date.parse(left) >= Date.parse(right) ? left : right;
|
|
126
|
+
}
|
|
127
|
+
function strongerConsistency(left, right) {
|
|
128
|
+
const rank = {
|
|
129
|
+
provisional: 0,
|
|
130
|
+
'consistent-snapshot': 1,
|
|
131
|
+
complete: 2,
|
|
132
|
+
};
|
|
133
|
+
return rank[left] >= rank[right] ? left : right;
|
|
134
|
+
}
|
|
135
|
+
function sessionLifecycle(request, record, sourceObservedAt) {
|
|
136
|
+
const explicit = nativeLifecycle(record.extensions);
|
|
137
|
+
if (explicit)
|
|
138
|
+
return explicit;
|
|
139
|
+
if (request.source.consistency === 'complete')
|
|
140
|
+
return 'complete';
|
|
141
|
+
const observedAt = record.occurredAt ?? sourceObservedAt;
|
|
142
|
+
if (observedAt && isStaleHistoricalTimestamp(observedAt, inactivityThresholdMs(request)))
|
|
143
|
+
return 'inactive';
|
|
144
|
+
return 'active';
|
|
145
|
+
}
|
|
146
|
+
function sessionLifecycleEvidence(request, record, sourceObservedAt) {
|
|
147
|
+
const observedAt = record.occurredAt ?? sourceObservedAt;
|
|
148
|
+
const explicit = nativeLifecycle(record.extensions);
|
|
149
|
+
if (explicit) {
|
|
150
|
+
return {
|
|
151
|
+
basis: 'provider-explicit-event',
|
|
152
|
+
state: explicit,
|
|
153
|
+
observedAt: observedAt ?? request.source.authorizedAt,
|
|
154
|
+
confidence: 'high',
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (request.source.consistency === 'complete') {
|
|
158
|
+
return {
|
|
159
|
+
basis: 'complete-source',
|
|
160
|
+
state: 'complete',
|
|
161
|
+
observedAt: observedAt ?? request.source.authorizedAt,
|
|
162
|
+
confidence: 'high',
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const thresholdMs = inactivityThresholdMs(request);
|
|
166
|
+
if (observedAt && isStaleHistoricalTimestamp(observedAt, thresholdMs)) {
|
|
167
|
+
return {
|
|
168
|
+
basis: 'inactivity-threshold',
|
|
169
|
+
state: 'inactive',
|
|
170
|
+
observedAt,
|
|
171
|
+
confidence: 'medium',
|
|
172
|
+
thresholdMs,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
basis: 'open-provisional-source',
|
|
177
|
+
state: 'active',
|
|
178
|
+
observedAt: observedAt ?? request.source.authorizedAt,
|
|
179
|
+
confidence: 'provisional',
|
|
180
|
+
thresholdMs,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function nativeLifecycle(extensions) {
|
|
184
|
+
const raw = typeof extensions?.lifecycle === 'string' ? extensions.lifecycle : undefined;
|
|
185
|
+
if (!raw)
|
|
186
|
+
return null;
|
|
187
|
+
const normalized = {
|
|
188
|
+
active: 'active',
|
|
189
|
+
inactive: 'inactive',
|
|
190
|
+
paused: 'paused',
|
|
191
|
+
complete: 'complete',
|
|
192
|
+
completed: 'complete',
|
|
193
|
+
archived: 'archived',
|
|
194
|
+
deleted: 'tombstoned',
|
|
195
|
+
cancelled: 'interrupted',
|
|
196
|
+
canceled: 'interrupted',
|
|
197
|
+
failed: 'interrupted',
|
|
198
|
+
interrupted: 'interrupted',
|
|
199
|
+
unknown: 'unknown',
|
|
200
|
+
'unknown-at-import': 'unknown',
|
|
201
|
+
'completed-at-import': 'complete',
|
|
202
|
+
};
|
|
203
|
+
return normalized[raw] ?? null;
|
|
204
|
+
}
|
|
205
|
+
function selectLifecycleTransition(leftLifecycle, left, rightLifecycle, right) {
|
|
206
|
+
const leftEvidence = asLifecycleEvidence(left);
|
|
207
|
+
if (leftLifecycle === 'tombstoned') {
|
|
208
|
+
return { lifecycle: leftLifecycle, evidence: leftEvidence ?? right };
|
|
209
|
+
}
|
|
210
|
+
if (!leftEvidence)
|
|
211
|
+
return { lifecycle: rightLifecycle, evidence: right };
|
|
212
|
+
const rank = {
|
|
213
|
+
'open-provisional-source': 1,
|
|
214
|
+
'inactivity-threshold': 1,
|
|
215
|
+
'complete-source': 2,
|
|
216
|
+
'provider-explicit-event': 3,
|
|
217
|
+
};
|
|
218
|
+
const leftRank = rank[String(leftEvidence.basis)] ?? 0;
|
|
219
|
+
const rightRank = rank[String(right.basis)] ?? 0;
|
|
220
|
+
const rightIsNewer = evidenceTimestamp(right) > evidenceTimestamp(leftEvidence);
|
|
221
|
+
return rightRank > leftRank || (rightRank === leftRank && rightIsNewer)
|
|
222
|
+
? { lifecycle: rightLifecycle, evidence: right }
|
|
223
|
+
: { lifecycle: leftLifecycle, evidence: leftEvidence };
|
|
224
|
+
}
|
|
225
|
+
function asLifecycleEvidence(value) {
|
|
226
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
227
|
+
? value
|
|
228
|
+
: null;
|
|
229
|
+
}
|
|
230
|
+
function evidenceTimestamp(value) {
|
|
231
|
+
const parsed = Date.parse(String(value.observedAt ?? ''));
|
|
232
|
+
return Number.isFinite(parsed) ? parsed : Number.NEGATIVE_INFINITY;
|
|
233
|
+
}
|
|
234
|
+
function inactivityThresholdMs(request) {
|
|
235
|
+
return request.inactivityThresholdMs ?? DEFAULT_INACTIVITY_THRESHOLD_MS;
|
|
236
|
+
}
|
|
237
|
+
function isStaleHistoricalTimestamp(value, thresholdMs) {
|
|
238
|
+
const timestamp = Date.parse(value);
|
|
239
|
+
return Number.isFinite(timestamp)
|
|
240
|
+
&& Date.now() - timestamp > thresholdMs;
|
|
241
|
+
}
|
|
242
|
+
export function sourceGenerationDigest(request) {
|
|
243
|
+
return sha256([
|
|
244
|
+
request.source.sourceId,
|
|
245
|
+
request.source.provider,
|
|
246
|
+
request.selectedSource.locatorClass,
|
|
247
|
+
request.source.sourceSchemaVersion,
|
|
248
|
+
request.adapter.adapterVersion,
|
|
249
|
+
].join('\0'));
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=normalization.js.map
|