@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
|
@@ -3,11 +3,13 @@ import { randomUUID } from 'node:crypto';
|
|
|
3
3
|
import { basename, dirname, isAbsolute, join, resolve, } from 'node:path';
|
|
4
4
|
import { pathToFileURL } from 'node:url';
|
|
5
5
|
import { providerScopeWarnings } from '../../sessions/coverage-preflight.js';
|
|
6
|
-
import { CLAUDE_ADAPTER_VERSION, ClaudeSessionAdapter, CODEX_ADAPTER_VERSION, CodexSessionAdapter, COPILOT_ADAPTER_VERSION, CopilotSessionAdapter, CURSOR_ADAPTER_VERSION, CursorSessionAdapter, FACTORY_ADAPTER_VERSION, FactorySessionAdapter, HERMES_ADAPTER_VERSION, HermesSessionAdapter, OPENCODE_ADAPTER_VERSION, OpenCodeSessionAdapter, OPENCLAW_ADAPTER_VERSION, OpenClawSessionAdapter, OPENHUMAN_ADAPTER_VERSION, OpenHumanSessionAdapter, GROKBOT_ADAPTER_VERSION, GROKBOT_NATIVE_REPLICA_LOCATOR_CLASS, GrokbotSessionAdapter, GROK_BUILD_ADAPTER_VERSION, GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS, GrokBuildSessionAdapter, grokBuildList, grokBuildSearch, grokBuildExport, grokHeadlessSessionIdFromFile, MUSE_ADAPTER_VERSION, MuseSessionAdapter, PI_ADAPTER_VERSION, PiSessionAdapter, DEEPSEEK_HARNESS_ADAPTER_VERSION, DeepSeekHarnessSessionAdapter, OmpSessionAdapter, OMP_ADAPTER_VERSION, WARP_ADAPTER_VERSION, WarpSessionAdapter, DEVIN_DESKTOP_ADAPTER_VERSION, DevinDesktopSessionAdapter, CandidateExtractionService, GENERIC_ADAPTER_VERSION, GenericSessionInterchangeAdapter, IncrementalSessionImporter, ImportLeaseContentionError, FilesystemMemoryDestination, FilesystemPromotionDispositionCoordinator, MemoryPromotionGateway, SESSION_CONTRACT_VERSION, SessionContractError, SessionRepository, SessionSourceSchema, StructuralCandidateExtractor, resolveMemoryConsumerManifest, assertSessionProviderId, acquireImportLease, defaultDiscoveryManifestPath, discoverWorkspaceHistories, createSessionAdapterRegistry, coveragePreflight, expectedSessionProviders, deriveSessionTimeline, importDiscoveryManifest, previewDiscoveryImport, publicDiscoveryManifest, readDiscoveryManifest, redactSourceLocator, sha256, parseTimelineGap, writeDiscoveryManifest, buildSessionExportPlan, reverifySessionExportPlan, buildSessionAiwgFortemiIndexExport, recoverAiwgFortemiIndexFromFullV1Shard, embedAttachmentsInFullV1Shard, recoverEmbeddedAttachments, SESSION_EXPORT_PLAN_SCHEMA_VERSION, } from '../../sessions/index.js';
|
|
6
|
+
import { CLAUDE_ADAPTER_VERSION, ClaudeSessionAdapter, CODEX_ADAPTER_VERSION, CodexSessionAdapter, COPILOT_ADAPTER_VERSION, CopilotSessionAdapter, CURSOR_ADAPTER_VERSION, CursorSessionAdapter, FACTORY_ADAPTER_VERSION, FactorySessionAdapter, HERMES_ADAPTER_VERSION, HermesSessionAdapter, OPENCODE_ADAPTER_VERSION, OpenCodeSessionAdapter, OPENCLAW_ADAPTER_VERSION, OpenClawSessionAdapter, OPENHUMAN_ADAPTER_VERSION, OpenHumanSessionAdapter, GROKBOT_ADAPTER_VERSION, GROKBOT_NATIVE_REPLICA_LOCATOR_CLASS, GrokbotSessionAdapter, GROK_BUILD_ADAPTER_VERSION, GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS, GROK_BUILD_NATIVE_LOCATOR_CLASS, GrokBuildSessionAdapter, grokBuildList, grokBuildSearch, grokBuildExport, grokHeadlessSessionIdFromFile, MUSE_ADAPTER_VERSION, MuseSessionAdapter, PI_ADAPTER_VERSION, PiSessionAdapter, DEEPSEEK_HARNESS_ADAPTER_VERSION, DeepSeekHarnessSessionAdapter, OmpSessionAdapter, OMP_ADAPTER_VERSION, WARP_ADAPTER_VERSION, WarpSessionAdapter, DEVIN_DESKTOP_ADAPTER_VERSION, DevinDesktopSessionAdapter, CandidateExtractionService, GENERIC_ADAPTER_VERSION, GenericSessionInterchangeAdapter, IncrementalSessionImporter, ImportLeaseContentionError, FilesystemMemoryDestination, FilesystemPromotionDispositionCoordinator, MemoryPromotionGateway, SESSION_CONTRACT_VERSION, SessionContractError, SessionRepository, SessionSourceSchema, StructuralCandidateExtractor, resolveMemoryConsumerManifest, assertSessionProviderId, acquireImportLease, countUniqueSessionsAcrossCatalogs, defaultDiscoveryManifestPath, defaultHostCatalogPath, HOST_CATALOG_WORKSPACE_ID, indexIdentitiesBySessionId, manifestNeedsHostCatalog, mergeCrossCatalogRows, mergeSessionLists, resolveHostReferences, summarizeSessionAnalyticsFacts, discoverWorkspaceHistories, createSessionAdapterRegistry, providerDiscoveryCapability, coveragePreflight, expectedSessionProviders, deriveSessionTimeline, importDiscoveryManifest, previewDiscoveryImport, publicDiscoveryManifest, readDiscoveryManifest, redactSourceLocator, sha256, parseTimelineGap, writeDiscoveryManifest, buildSessionExportPlan, reverifySessionExportPlan, buildSessionAiwgFortemiIndexExport, recoverAiwgFortemiIndexFromFullV1Shard, embedAttachmentsInFullV1Shard, recoverEmbeddedAttachments, SESSION_EXPORT_PLAN_SCHEMA_VERSION, } from '../../sessions/index.js';
|
|
7
7
|
import { resolveImportExclusions } from '../../sessions/import-exclusions.js';
|
|
8
8
|
import { resolveImportLimits } from '../../sessions/import-limits.js';
|
|
9
9
|
import { classifyGrokbotBlobName } from '../../sessions/adapters/grokbot-locator.js';
|
|
10
10
|
import { readAiwgConfig } from '../../config/aiwg-config.js';
|
|
11
|
+
import { importFromDir } from './sessions-intake.js';
|
|
12
|
+
import { executeSessionsTail } from './sessions-tail.js';
|
|
11
13
|
const JSON_CONTRACT_VERSION = '1.0.0';
|
|
12
14
|
async function createLineMemoryPromotionDestination(projectRoot, manifestPath) {
|
|
13
15
|
const modulePath = resolve(dirname(manifestPath), 'commands', 'line-memory.mjs');
|
|
@@ -38,9 +40,13 @@ Commands:
|
|
|
38
40
|
grok-export <id> --workspace <path> --out <dir> Export one CLI transcript
|
|
39
41
|
grok-id <file> --format json|streaming-json Read a headless session ID
|
|
40
42
|
import <file> --source-id <id> Import a supported provider JSONL source
|
|
43
|
+
import --from-dir <dir> [--source-id <prefix>] Batch-import every recognised export in a directory
|
|
41
44
|
list [--workspace <path-or-id>] [--limit N] [--cursor N] List normalized sessions
|
|
42
45
|
timeline [--workspace <path-or-id>] [--gap 30m] Report chronological activity segments
|
|
43
46
|
show <session-id> [--workspace <path-or-id>] Show a session with events and tags
|
|
47
|
+
tail <session-id> | --provider <p> --latest [--workspace <path-or-id>] [--follow] [--json] [--import]
|
|
48
|
+
Read new native events; --follow polls every 500 ms
|
|
49
|
+
Read-only unless --import; --input <file> authorizes older direct imports
|
|
44
50
|
search <query> [--workspace <path-or-id>] Search authorized normalized content
|
|
45
51
|
extract [session-id] --workspace <id> Extract structural candidates
|
|
46
52
|
export plan --workspace <id> --out <file> <session-id...> Select sessions into a reviewable plan
|
|
@@ -81,6 +87,9 @@ Options:
|
|
|
81
87
|
--muse-root <path> Explicitly authorize a Muse Code sessions root
|
|
82
88
|
--dsh-root <path> Explicitly authorize a DeepSeek Harness sessions root
|
|
83
89
|
--grokbot-root <path> Explicitly authorize a Grok Bot sand-client-persistence root
|
|
90
|
+
--grok-root <path> Explicitly authorize a Grok Build sessions root (native chat_history.jsonl discovery)
|
|
91
|
+
--grok-active-sessions <path> Explicitly authorize active_sessions.json for Grok Build live detection (read-only; requires --grok-root)
|
|
92
|
+
--hermes-root <path> Explicitly authorize a Hermes home for a read-only state.db backup snapshot
|
|
84
93
|
--grok-bin <path> Absolute Grok Build CLI path for grok-list/grok-search/grok-export
|
|
85
94
|
(default: grok on PATH, then $GROK_HOME/bin/grok)
|
|
86
95
|
--confirm, --yes Confirm a persistent discovered batch import
|
|
@@ -92,6 +101,9 @@ Options:
|
|
|
92
101
|
--inactivity-threshold <duration> Historical inactivity threshold (default 24h)
|
|
93
102
|
--min-coverage <0..1> Fail list/report commands below a coverage ratio
|
|
94
103
|
--provider <id> Filter list or select an import adapter
|
|
104
|
+
--from-dir <dir> Batch-import every recognised export file in a directory (import only);
|
|
105
|
+
--source-id becomes an optional per-file source-ID prefix;
|
|
106
|
+
files already imported are skipped by content digest
|
|
95
107
|
--consumer <id> Select a named memory consumer for promotion
|
|
96
108
|
--tag <tag>, --limit <n>, --cursor <n>
|
|
97
109
|
--page-size <n> Extraction scan page size (default 250, maximum 500)
|
|
@@ -156,6 +168,8 @@ export const sessionsHandler = {
|
|
|
156
168
|
const explicitHelp = parsed.flags.has('--help') || parsed.flags.has('-h');
|
|
157
169
|
return printHelp(ctx, explicitHelp ? EXIT.ok : EXIT.usage);
|
|
158
170
|
}
|
|
171
|
+
if (parsed.command === 'tail')
|
|
172
|
+
return executeSessionsTail(ctx, parsed, { databasePath, readAuthorizationContext });
|
|
159
173
|
try {
|
|
160
174
|
const result = await executeCommand(ctx, parsed);
|
|
161
175
|
if (json)
|
|
@@ -179,7 +193,10 @@ async function executeCommand(ctx, args) {
|
|
|
179
193
|
const command = args.command;
|
|
180
194
|
if (command === 'sources') {
|
|
181
195
|
const registry = createSessionAdapterRegistry();
|
|
182
|
-
const reports = registry.list().map((adapter) =>
|
|
196
|
+
const reports = registry.list().map((adapter) => ({
|
|
197
|
+
...providerDisposition(adapter.provider),
|
|
198
|
+
discovery: providerDiscoveryCapability(adapter.provider, adapter.supportedOperations),
|
|
199
|
+
}));
|
|
183
200
|
const preflight = coveragePreflight({ expectedProviders: requestedProviders(args), registry });
|
|
184
201
|
return ok(command, { providers: reports, count: reports.length, preflight });
|
|
185
202
|
}
|
|
@@ -227,18 +244,35 @@ async function executeCommand(ctx, args) {
|
|
|
227
244
|
limit,
|
|
228
245
|
cursor,
|
|
229
246
|
});
|
|
247
|
+
// Account-scoped sessions live once in the host catalog; the
|
|
248
|
+
// workspace holds references (#3232). Read through them on the
|
|
249
|
+
// opening page so the workspace lists its referenced sessions.
|
|
250
|
+
// Cursor pages continue the local snapshot. Totals dedupe legacy
|
|
251
|
+
// copied rows against references, counting each session once.
|
|
252
|
+
const hostView = cursor
|
|
253
|
+
? null
|
|
254
|
+
: readHostReferencedSessions(repository, { provider, tag: args.values.get('--tag') });
|
|
255
|
+
const items = hostView && hostView.sessions.length > 0
|
|
256
|
+
? mergeSessionLists(result.items, hostView.sessions).slice(0, limit)
|
|
257
|
+
: result.items;
|
|
258
|
+
const total = hostView && hostView.references.length > 0
|
|
259
|
+
? countUniqueSessionsAcrossCatalogs([{
|
|
260
|
+
identities: repository.listSessionIdentities(workspaceId),
|
|
261
|
+
references: hostView.resolvedReferences,
|
|
262
|
+
}])
|
|
263
|
+
: result.total;
|
|
230
264
|
const coverage = {
|
|
231
265
|
...repository.getCoverage(workspaceId),
|
|
232
266
|
catalogScope: catalogScope(ctx, args, repository, workspaceId),
|
|
233
267
|
};
|
|
234
268
|
const response = {
|
|
235
|
-
items
|
|
269
|
+
items,
|
|
236
270
|
page: {
|
|
237
271
|
limit,
|
|
238
272
|
cursor: cursor ?? null,
|
|
239
273
|
nextCursor: result.nextCursor,
|
|
240
274
|
snapshotRowid: result.snapshotRowid,
|
|
241
|
-
total
|
|
275
|
+
total,
|
|
242
276
|
},
|
|
243
277
|
coverage,
|
|
244
278
|
};
|
|
@@ -314,10 +348,15 @@ async function executeCommand(ctx, args) {
|
|
|
314
348
|
const session = matches[0];
|
|
315
349
|
if (!session)
|
|
316
350
|
throw new CliError('SESSION_NOT_FOUND', `session not found: ${id}${scope.hint ? `; ${scope.hint}` : ''}`, EXIT.unavailable, { catalogScope: scope });
|
|
351
|
+
// Image references resolve against the blob store: available blobs
|
|
352
|
+
// report their reference, missing ones an explicit unavailable
|
|
353
|
+
// state. Bytes stay out of the response; fetch by digest (#3265).
|
|
354
|
+
const events = repository.listEvents(session.sessionId, session.workspaceId)
|
|
355
|
+
.map((event) => ({ ...event, images: repository.resolveEventImages(event) }));
|
|
317
356
|
return ok(command, {
|
|
318
357
|
session,
|
|
319
358
|
tags: repository.listTags(session.sessionId, session.workspaceId),
|
|
320
|
-
events
|
|
359
|
+
events,
|
|
321
360
|
catalogScope: catalogScope(ctx, args, repository, session.workspaceId),
|
|
322
361
|
});
|
|
323
362
|
}
|
|
@@ -326,7 +365,8 @@ async function executeCommand(ctx, args) {
|
|
|
326
365
|
const { workspaceId } = readAuthorizationContext(ctx, args, command, repository);
|
|
327
366
|
const providerInput = args.values.get('--provider');
|
|
328
367
|
const provider = providerInput ? assertSessionProviderId(providerInput) : undefined;
|
|
329
|
-
const
|
|
368
|
+
const limit = boundedInteger(args.values.get('--limit'), 50, 1, 500, '--limit');
|
|
369
|
+
const searchOptions = {
|
|
330
370
|
query,
|
|
331
371
|
workspaceId,
|
|
332
372
|
providers: provider ? [provider] : undefined,
|
|
@@ -341,13 +381,24 @@ async function executeCommand(ctx, args) {
|
|
|
341
381
|
sensitivity: args.values.get('--sensitivity'),
|
|
342
382
|
extractionState: args.values.get('--extraction-state'),
|
|
343
383
|
controlEvents: controlEventMode(args.values.get('--control-events')),
|
|
344
|
-
limit
|
|
384
|
+
limit,
|
|
345
385
|
cursor: args.values.get('--cursor'),
|
|
346
|
-
}
|
|
386
|
+
};
|
|
387
|
+
const result = repository.search(searchOptions);
|
|
388
|
+
// Read through host references on the opening page so workspace
|
|
389
|
+
// search finds referenced account-scoped sessions. Each session
|
|
390
|
+
// counts once: host hits for sessions already present locally
|
|
391
|
+
// (legacy copied rows) are dropped by provider + native session.
|
|
392
|
+
const hostRead = searchOptions.cursor
|
|
393
|
+
? null
|
|
394
|
+
: searchHostReferencedSessions(repository, searchOptions, provider);
|
|
395
|
+
const items = hostRead && hostRead.hits.length > 0
|
|
396
|
+
? mergeCrossCatalogRows(result.items, hostRead.hits, indexIdentitiesBySessionId(repository.listSessionIdentities(workspaceId)), indexIdentitiesBySessionId(hostRead.hostIdentities), (hit) => [hit.provider, hit.eventId].join(' ')).slice(0, limit)
|
|
397
|
+
: result.items;
|
|
347
398
|
return ok(command, {
|
|
348
|
-
items
|
|
399
|
+
items,
|
|
349
400
|
catalogScope: catalogScope(ctx, args, repository, workspaceId),
|
|
350
|
-
page: { limit
|
|
401
|
+
page: { limit,
|
|
351
402
|
nextCursor: result.nextCursor },
|
|
352
403
|
});
|
|
353
404
|
}
|
|
@@ -355,14 +406,22 @@ async function executeCommand(ctx, args) {
|
|
|
355
406
|
const view = requiredPositional(args, 0, 'analytics view');
|
|
356
407
|
const { workspaceId } = readAuthorizationContext(ctx, args, command, repository);
|
|
357
408
|
const query = analyticsQuery(args, workspaceId);
|
|
409
|
+
// Host references resolve to facts stored under the host catalog;
|
|
410
|
+
// each session counts once by provider + native session id. Without
|
|
411
|
+
// references the single-catalog path below is unchanged.
|
|
412
|
+
const mergedFacts = readWorkspaceAnalyticsFacts(repository, query);
|
|
358
413
|
if (view === 'summary') {
|
|
359
414
|
return ok(command, {
|
|
360
415
|
view,
|
|
361
|
-
summary:
|
|
416
|
+
summary: mergedFacts
|
|
417
|
+
? summarizeSessionAnalyticsFacts(mergedFacts, workspaceId)
|
|
418
|
+
: repository.analyticsSummary(query),
|
|
362
419
|
});
|
|
363
420
|
}
|
|
364
421
|
const categories = analyticsCategories(view);
|
|
365
|
-
const items =
|
|
422
|
+
const items = mergedFacts
|
|
423
|
+
? mergedFacts.filter((fact) => categories.includes(fact.category))
|
|
424
|
+
: repository.listAnalyticsFacts({ ...query, categories });
|
|
366
425
|
return ok(command, {
|
|
367
426
|
analyticsVersion: '1.0.0',
|
|
368
427
|
view,
|
|
@@ -752,10 +811,7 @@ async function executeCommand(ctx, args) {
|
|
|
752
811
|
repository.close();
|
|
753
812
|
}
|
|
754
813
|
}
|
|
755
|
-
|
|
756
|
-
const limits = await configuredImportLimits(ctx, args);
|
|
757
|
-
const input = resolve(ctx.cwd, requiredPositional(args, 0, 'file'));
|
|
758
|
-
const providerInput = args.values.get('--provider') ?? 'generic';
|
|
814
|
+
function assertSupportedImportProvider(providerInput) {
|
|
759
815
|
const provider = assertSessionProviderId(providerInput);
|
|
760
816
|
if (provider !== 'generic' && provider !== 'claude' && provider !== 'codex'
|
|
761
817
|
&& provider !== 'copilot' && provider !== 'cursor' && provider !== 'factory'
|
|
@@ -763,6 +819,57 @@ async function importSource(ctx, args) {
|
|
|
763
819
|
&& provider !== 'openhuman' && provider !== 'grokbot' && provider !== 'grok-build' && provider !== 'muse' && provider !== 'pi' && provider !== 'omp' && provider !== 'deepseek-harness' && provider !== 'warp' && provider !== 'devin-desktop') {
|
|
764
820
|
throw new CliError('UNSUPPORTED_OPERATION', `session import is not implemented for ${provider}`, EXIT.unsupported);
|
|
765
821
|
}
|
|
822
|
+
return provider;
|
|
823
|
+
}
|
|
824
|
+
function adapterVersionFor(provider) {
|
|
825
|
+
switch (provider) {
|
|
826
|
+
case 'claude': return CLAUDE_ADAPTER_VERSION;
|
|
827
|
+
case 'codex': return CODEX_ADAPTER_VERSION;
|
|
828
|
+
case 'copilot': return COPILOT_ADAPTER_VERSION;
|
|
829
|
+
case 'cursor': return CURSOR_ADAPTER_VERSION;
|
|
830
|
+
case 'factory': return FACTORY_ADAPTER_VERSION;
|
|
831
|
+
case 'hermes': return HERMES_ADAPTER_VERSION;
|
|
832
|
+
case 'opencode': return OPENCODE_ADAPTER_VERSION;
|
|
833
|
+
case 'openclaw': return OPENCLAW_ADAPTER_VERSION;
|
|
834
|
+
case 'openhuman': return OPENHUMAN_ADAPTER_VERSION;
|
|
835
|
+
case 'grokbot': return GROKBOT_ADAPTER_VERSION;
|
|
836
|
+
case 'grok-build': return GROK_BUILD_ADAPTER_VERSION;
|
|
837
|
+
case 'muse': return MUSE_ADAPTER_VERSION;
|
|
838
|
+
case 'pi': return PI_ADAPTER_VERSION;
|
|
839
|
+
case 'omp': return OMP_ADAPTER_VERSION;
|
|
840
|
+
case 'deepseek-harness': return DEEPSEEK_HARNESS_ADAPTER_VERSION;
|
|
841
|
+
case 'warp': return WARP_ADAPTER_VERSION;
|
|
842
|
+
case 'devin-desktop': return DEVIN_DESKTOP_ADAPTER_VERSION;
|
|
843
|
+
default: return GENERIC_ADAPTER_VERSION;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* `aiwg sessions import --from-dir <dir>` (#3168). Batch-imports every
|
|
848
|
+
* recognised provider export file in one intake directory: one receipt per
|
|
849
|
+
* file plus a summary. Files already imported are skipped by content digest
|
|
850
|
+
* before any adapter work; unrecognised files are skipped with a reason.
|
|
851
|
+
* Each remaining file imports through the single-file path, so adapter
|
|
852
|
+
* selection, redaction, and idempotency semantics are identical.
|
|
853
|
+
*/
|
|
854
|
+
function importFailureReason(error) {
|
|
855
|
+
if (error instanceof CliError)
|
|
856
|
+
return `${error.code}: ${error.message}`;
|
|
857
|
+
if (error instanceof SessionContractError)
|
|
858
|
+
return `${error.code}: ${error.message}`;
|
|
859
|
+
return `IMPORT_INTERRUPTED: ${error instanceof Error ? error.message : String(error)}`;
|
|
860
|
+
}
|
|
861
|
+
async function importSource(ctx, args) {
|
|
862
|
+
const fromDir = args.values.get('--from-dir');
|
|
863
|
+
if (fromDir !== undefined) {
|
|
864
|
+
return importFromDir(ctx, args, resolve(ctx.cwd, fromDir), {
|
|
865
|
+
assertSupportedImportProvider, normalizeWorkspaceId, isDryRun, preview, ok,
|
|
866
|
+
openRepository, adapterVersionFor, importSource, importFailureReason,
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
const limits = await configuredImportLimits(ctx, args);
|
|
870
|
+
const input = resolve(ctx.cwd, requiredPositional(args, 0, 'file'));
|
|
871
|
+
const providerInput = args.values.get('--provider') ?? 'generic';
|
|
872
|
+
const provider = assertSupportedImportProvider(providerInput);
|
|
766
873
|
const sourceId = requiredValue(args, '--source-id');
|
|
767
874
|
const workspaceId = args.values.has('--workspace')
|
|
768
875
|
? normalizeWorkspaceId(ctx.cwd, args.values.get('--workspace'))
|
|
@@ -780,6 +887,8 @@ async function importSource(ctx, args) {
|
|
|
780
887
|
const isGrokbotNative = isGrokbot
|
|
781
888
|
&& classifyGrokbotBlobName(basename(input))?.kind === 'transcript-replica';
|
|
782
889
|
const isGrokBuild = provider === 'grok-build';
|
|
890
|
+
const isGrokBuildNative = isGrokBuild
|
|
891
|
+
&& basename(input) === 'chat_history.jsonl';
|
|
783
892
|
const isMuse = provider === 'muse';
|
|
784
893
|
const isPi = provider === 'pi';
|
|
785
894
|
const isOmp = provider === 'omp';
|
|
@@ -838,7 +947,7 @@ async function importSource(ctx, args) {
|
|
|
838
947
|
: isGrokbot
|
|
839
948
|
? (isGrokbotNative ? GROKBOT_NATIVE_REPLICA_LOCATOR_CLASS : 'manual-export')
|
|
840
949
|
: isGrokBuild
|
|
841
|
-
? GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS
|
|
950
|
+
? (isGrokBuildNative ? GROK_BUILD_NATIVE_LOCATOR_CLASS : GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS)
|
|
842
951
|
: isMuse
|
|
843
952
|
? 'manual-export'
|
|
844
953
|
: isPi
|
|
@@ -877,7 +986,7 @@ async function importSource(ctx, args) {
|
|
|
877
986
|
: isGrokbot
|
|
878
987
|
? (isGrokbotNative ? 'grokbot-native-transcript-replica-v1' : 'manual-interchange')
|
|
879
988
|
: isGrokBuild
|
|
880
|
-
? 'documented-cli-markdown-export'
|
|
989
|
+
? (isGrokBuildNative ? 'grok-build-native-chat-history-v1' : 'documented-cli-markdown-export')
|
|
881
990
|
: isMuse
|
|
882
991
|
? 'muse-export-trajectory-v1'
|
|
883
992
|
: isWarp
|
|
@@ -944,7 +1053,7 @@ async function importSource(ctx, args) {
|
|
|
944
1053
|
: isGrokbot
|
|
945
1054
|
? { 'native.grokbot': {} }
|
|
946
1055
|
: isGrokBuild
|
|
947
|
-
? { 'native.grok-build': { acquisition: 'grok-cli-export-markdown' } }
|
|
1056
|
+
? { 'native.grok-build': { acquisition: isGrokBuildNative ? GROK_BUILD_NATIVE_LOCATOR_CLASS : 'grok-cli-export-markdown' } }
|
|
948
1057
|
: isMuse
|
|
949
1058
|
? { 'native.muse': {} }
|
|
950
1059
|
: isWarp
|
|
@@ -1075,7 +1184,10 @@ async function exportBuild(ctx, args, repository, command) {
|
|
|
1075
1184
|
...output,
|
|
1076
1185
|
bytesEmbedded: includeBytes && outputBytesByRegistrationId.has(output.registrationId),
|
|
1077
1186
|
}));
|
|
1078
|
-
const index = buildSessionAiwgFortemiIndexExport(plan.workspaceId, sessions, eventsBySessionId, outputs, catalogTagsBySessionId
|
|
1187
|
+
const index = buildSessionAiwgFortemiIndexExport(plan.workspaceId, sessions, eventsBySessionId, outputs, catalogTagsBySessionId,
|
|
1188
|
+
// Resolve image references against the live catalog: available blobs
|
|
1189
|
+
// export as references, missing ones as explicit unavailable (#3265).
|
|
1190
|
+
(event) => repository.resolveEventImages(event));
|
|
1079
1191
|
// aiwgFortemiIndexToKnowledgeShardWithReport targets the declared
|
|
1080
1192
|
// full-v1/2.0.0 archive contract and validates losslessness -- unlike the
|
|
1081
1193
|
// plain aiwgFortemiIndexToKnowledgeShard (core-v1), which silently embeds
|
|
@@ -1290,6 +1402,12 @@ async function discoverWorkspace(ctx, args) {
|
|
|
1290
1402
|
? resolve(ctx.cwd, args.values.get('--dsh-root')) : undefined,
|
|
1291
1403
|
grokbotRoot: args.values.has('--grokbot-root')
|
|
1292
1404
|
? resolve(ctx.cwd, args.values.get('--grokbot-root')) : undefined,
|
|
1405
|
+
grokRoot: args.values.has('--grok-root')
|
|
1406
|
+
? resolve(ctx.cwd, args.values.get('--grok-root')) : undefined,
|
|
1407
|
+
grokActiveSessions: args.values.has('--grok-active-sessions')
|
|
1408
|
+
? resolve(ctx.cwd, args.values.get('--grok-active-sessions')) : undefined,
|
|
1409
|
+
hermesRoot: args.values.has('--hermes-root')
|
|
1410
|
+
? resolve(ctx.cwd, args.values.get('--hermes-root')) : undefined,
|
|
1293
1411
|
codexRoots: [
|
|
1294
1412
|
...(config?.sessions?.codex_roots ?? []).map((root) => resolve(workspace, root)),
|
|
1295
1413
|
...args.codexRoots.map((root) => resolve(ctx.cwd, root)),
|
|
@@ -1355,18 +1473,33 @@ async function importDiscovered(ctx, args) {
|
|
|
1355
1473
|
...(carryPath ? { carryForward: redactSourceLocator(carryPath) } : {}),
|
|
1356
1474
|
});
|
|
1357
1475
|
}
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
|
|
1476
|
+
const waitMs = boundedInteger(args.values.get('--lock-wait-ms'), 5_000, 0, 300_000, '--lock-wait-ms');
|
|
1477
|
+
const lease = await acquireImportLease(databasePath(ctx, args), sha256(['discovered-import', manifest.manifestId, manifest.workspaceId].join('\0')), { waitMs });
|
|
1478
|
+
let hostLease;
|
|
1361
1479
|
try {
|
|
1362
1480
|
const previous = carryPath ? new SessionRepository(carryPath, { readonly: true }) : undefined;
|
|
1363
1481
|
let repository;
|
|
1482
|
+
let hostRepository;
|
|
1364
1483
|
try {
|
|
1365
1484
|
repository = openRepository(ctx, args);
|
|
1485
|
+
// Account-scoped providers (Grok Bot) import once into the host
|
|
1486
|
+
// catalog; the workspace catalog records a reference (#3232). The
|
|
1487
|
+
// host catalog is only opened when the manifest actually holds an
|
|
1488
|
+
// account-scoped source.
|
|
1489
|
+
const hostCatalogPath = defaultHostCatalogPath();
|
|
1490
|
+
if (manifestNeedsHostCatalog(manifest.sources)) {
|
|
1491
|
+
mkdirSync(dirname(hostCatalogPath), { recursive: true, mode: 0o700 });
|
|
1492
|
+
// The workspace lease does not cover the shared host catalog; serialize
|
|
1493
|
+
// host writers the same way the hourly refresh does.
|
|
1494
|
+
hostLease = await acquireImportLease(hostCatalogPath, `host-import-${process.pid}`, { waitMs });
|
|
1495
|
+
hostRepository = new SessionRepository(hostCatalogPath);
|
|
1496
|
+
}
|
|
1366
1497
|
const interruptedRuns = repository.interruptRunningBatchImports();
|
|
1367
1498
|
const receipt = await importDiscoveryManifest({
|
|
1368
1499
|
manifest,
|
|
1369
1500
|
repository,
|
|
1501
|
+
hostRepository,
|
|
1502
|
+
hostCatalogPath,
|
|
1370
1503
|
carryForward: previous,
|
|
1371
1504
|
limits,
|
|
1372
1505
|
exclude,
|
|
@@ -1388,10 +1521,12 @@ async function importDiscovered(ctx, args) {
|
|
|
1388
1521
|
}
|
|
1389
1522
|
finally {
|
|
1390
1523
|
repository?.close();
|
|
1524
|
+
hostRepository?.close();
|
|
1391
1525
|
previous?.close();
|
|
1392
1526
|
}
|
|
1393
1527
|
}
|
|
1394
1528
|
finally {
|
|
1529
|
+
await hostLease?.release();
|
|
1395
1530
|
await lease.release();
|
|
1396
1531
|
}
|
|
1397
1532
|
}
|
|
@@ -1470,10 +1605,10 @@ function providerDisposition(provider) {
|
|
|
1470
1605
|
if (provider === 'hermes') {
|
|
1471
1606
|
return {
|
|
1472
1607
|
provider, disposition: 'implemented', operationalState: 'available',
|
|
1473
|
-
supportedOperations: ['inspect', 'stream'],
|
|
1608
|
+
supportedOperations: ['discover', 'inspect', 'stream'],
|
|
1474
1609
|
acquisitionModes: ['jsonl', 'api', 'sqlite-snapshot'],
|
|
1475
1610
|
reasonCode: null,
|
|
1476
|
-
remediation: '
|
|
1611
|
+
remediation: 'Pass --hermes-root with an explicitly authorized Hermes home for a read-only state.db backup snapshot; or use `hermes sessions export` and import the explicitly authorized JSONL file.',
|
|
1477
1612
|
evidence: {
|
|
1478
1613
|
adapterVersion: HERMES_ADAPTER_VERSION,
|
|
1479
1614
|
verifiedAt: '2026-07-27',
|
|
@@ -1581,10 +1716,10 @@ function providerDisposition(provider) {
|
|
|
1581
1716
|
if (provider === 'grok-build') {
|
|
1582
1717
|
return {
|
|
1583
1718
|
provider, disposition: 'implemented', operationalState: 'available',
|
|
1584
|
-
supportedOperations: ['inspect', 'stream'],
|
|
1585
|
-
acquisitionModes: ['manual-export'],
|
|
1586
|
-
reasonCode:
|
|
1587
|
-
remediation: '
|
|
1719
|
+
supportedOperations: ['discover', 'inspect', 'stream'],
|
|
1720
|
+
acquisitionModes: ['manual-export', 'jsonl'],
|
|
1721
|
+
reasonCode: null,
|
|
1722
|
+
remediation: 'Pass --grok-root with an explicitly authorized sessions root for native chat_history.jsonl discovery, optionally with --grok-active-sessions for live detection; or run `grok export <session-id> <session-id>.md` and import the explicitly authorized Markdown file.',
|
|
1588
1723
|
evidence: {
|
|
1589
1724
|
adapterVersion: GROK_BUILD_ADAPTER_VERSION,
|
|
1590
1725
|
verifiedAt: '2026-09-21',
|
|
@@ -1718,6 +1853,127 @@ function catalogScope(ctx, args, repository, workspaceId) {
|
|
|
1718
1853
|
: null,
|
|
1719
1854
|
};
|
|
1720
1855
|
}
|
|
1856
|
+
/**
|
|
1857
|
+
* Host-catalog read-through for account-scoped sessions (#3232). The
|
|
1858
|
+
* workspace catalog holds references instead of copies; each reference
|
|
1859
|
+
* records its host catalog path. Every referenced catalog opens read-only
|
|
1860
|
+
* and closes before returning. Unreadable catalogs contribute nothing, so
|
|
1861
|
+
* local rows still list when the host catalog is missing.
|
|
1862
|
+
*/
|
|
1863
|
+
function eachReferencedHostCatalog(repository, provider, read) {
|
|
1864
|
+
const references = repository.listHostSessionReferences()
|
|
1865
|
+
.filter((reference) => !provider || reference.provider === provider);
|
|
1866
|
+
if (references.length === 0)
|
|
1867
|
+
return [];
|
|
1868
|
+
const byCatalog = new Map();
|
|
1869
|
+
for (const reference of references) {
|
|
1870
|
+
const group = byCatalog.get(reference.hostCatalog);
|
|
1871
|
+
if (group)
|
|
1872
|
+
group.push(reference);
|
|
1873
|
+
else
|
|
1874
|
+
byCatalog.set(reference.hostCatalog, [reference]);
|
|
1875
|
+
}
|
|
1876
|
+
const reads = [];
|
|
1877
|
+
for (const [catalogPath, group] of byCatalog) {
|
|
1878
|
+
let host;
|
|
1879
|
+
try {
|
|
1880
|
+
host = new SessionRepository(catalogPath, { readonly: true });
|
|
1881
|
+
}
|
|
1882
|
+
catch {
|
|
1883
|
+
continue;
|
|
1884
|
+
}
|
|
1885
|
+
try {
|
|
1886
|
+
reads.push({ references: group, value: read(host, group) });
|
|
1887
|
+
}
|
|
1888
|
+
finally {
|
|
1889
|
+
host.close();
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
return reads;
|
|
1893
|
+
}
|
|
1894
|
+
function readHostReferencedSessions(repository, filters) {
|
|
1895
|
+
const reads = eachReferencedHostCatalog(repository, filters.provider, (host, group) => {
|
|
1896
|
+
const page = host.listSessions({
|
|
1897
|
+
provider: filters.provider,
|
|
1898
|
+
workspaceId: HOST_CATALOG_WORKSPACE_ID,
|
|
1899
|
+
limit: group.length,
|
|
1900
|
+
});
|
|
1901
|
+
const sessions = resolveHostReferences(group, page.items)
|
|
1902
|
+
.filter((session) => !filters.tag || host.listTags(session.sessionId).includes(filters.tag));
|
|
1903
|
+
const resolvedSourceIds = new Set(sessions.map((session) => session.sourceId));
|
|
1904
|
+
return {
|
|
1905
|
+
sessions,
|
|
1906
|
+
resolvedReferences: group.filter((reference) => resolvedSourceIds.has(reference.sourceId)),
|
|
1907
|
+
};
|
|
1908
|
+
});
|
|
1909
|
+
return {
|
|
1910
|
+
references: reads.flatMap((read) => read.references),
|
|
1911
|
+
resolvedReferences: reads.flatMap((read) => read.value.resolvedReferences),
|
|
1912
|
+
sessions: reads.flatMap((read) => read.value.sessions),
|
|
1913
|
+
};
|
|
1914
|
+
}
|
|
1915
|
+
function searchHostReferencedSessions(repository, searchOptions, provider) {
|
|
1916
|
+
const reads = eachReferencedHostCatalog(repository, provider, (host) => {
|
|
1917
|
+
const result = host.search({
|
|
1918
|
+
...searchOptions,
|
|
1919
|
+
workspaceId: HOST_CATALOG_WORKSPACE_ID,
|
|
1920
|
+
cursor: undefined,
|
|
1921
|
+
});
|
|
1922
|
+
return {
|
|
1923
|
+
hits: result.items,
|
|
1924
|
+
hostIdentities: host.listSessionIdentities(HOST_CATALOG_WORKSPACE_ID),
|
|
1925
|
+
};
|
|
1926
|
+
});
|
|
1927
|
+
return {
|
|
1928
|
+
hits: reads.flatMap((read) => read.value.hits),
|
|
1929
|
+
hostIdentities: reads.flatMap((read) => read.value.hostIdentities),
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
function readHostReferencedAnalyticsFacts(repository, query) {
|
|
1933
|
+
// query.sessionId is a workspace-local internal id; host rows carry host
|
|
1934
|
+
// stable ids, so resolve it to a provider + native session key first.
|
|
1935
|
+
let sessionKey = null;
|
|
1936
|
+
if (query.sessionId) {
|
|
1937
|
+
const session = repository.getSession(query.sessionId, query.workspaceId);
|
|
1938
|
+
if (!session)
|
|
1939
|
+
return { facts: [], hostIdentities: [] };
|
|
1940
|
+
sessionKey = `${session.provider} ${session.nativeSessionId}`;
|
|
1941
|
+
}
|
|
1942
|
+
const reads = eachReferencedHostCatalog(repository, query.provider, (host, group) => {
|
|
1943
|
+
const wanted = new Set(group.map((reference) => `${reference.provider} ${reference.nativeSessionId}`));
|
|
1944
|
+
const identities = host.listSessionIdentities(HOST_CATALOG_WORKSPACE_ID);
|
|
1945
|
+
const hostSessionIds = new Set(identities
|
|
1946
|
+
.filter((identity) => wanted.has(`${identity.provider} ${identity.nativeSessionId}`))
|
|
1947
|
+
.map((identity) => identity.sessionId));
|
|
1948
|
+
const { sessionId: _localSessionId, ...hostQuery } = query;
|
|
1949
|
+
const facts = host.listAnalyticsFacts({ ...hostQuery, workspaceId: HOST_CATALOG_WORKSPACE_ID })
|
|
1950
|
+
.filter((fact) => hostSessionIds.has(fact.sessionId)
|
|
1951
|
+
&& (!sessionKey || `${fact.provider} ${hostSessionKey(fact.sessionId, identities)}` === sessionKey));
|
|
1952
|
+
return { facts, identities };
|
|
1953
|
+
});
|
|
1954
|
+
return {
|
|
1955
|
+
facts: reads.flatMap((read) => read.value.facts),
|
|
1956
|
+
hostIdentities: reads.flatMap((read) => read.value.identities),
|
|
1957
|
+
};
|
|
1958
|
+
}
|
|
1959
|
+
function hostSessionKey(sessionId, identities) {
|
|
1960
|
+
return identities.find((identity) => identity.sessionId === sessionId)?.nativeSessionId ?? null;
|
|
1961
|
+
}
|
|
1962
|
+
/**
|
|
1963
|
+
* Workspace analytics facts with host references resolved. Returns null
|
|
1964
|
+
* when the workspace holds no references so callers keep the exact
|
|
1965
|
+
* single-catalog query path (SQL limit/filter semantics unchanged).
|
|
1966
|
+
*/
|
|
1967
|
+
function readWorkspaceAnalyticsFacts(repository, query) {
|
|
1968
|
+
const references = repository.listHostSessionReferences()
|
|
1969
|
+
.filter((reference) => !query.provider || reference.provider === query.provider);
|
|
1970
|
+
if (references.length === 0)
|
|
1971
|
+
return null;
|
|
1972
|
+
const hostRead = readHostReferencedAnalyticsFacts(repository, query);
|
|
1973
|
+
if (hostRead.facts.length === 0)
|
|
1974
|
+
return null;
|
|
1975
|
+
return mergeCrossCatalogRows(repository.listAnalyticsFacts(query), hostRead.facts, indexIdentitiesBySessionId(repository.listSessionIdentities(query.workspaceId)), indexIdentitiesBySessionId(hostRead.hostIdentities), (fact) => `${fact.provider} ${fact.factId}`);
|
|
1976
|
+
}
|
|
1721
1977
|
async function configuredImportLimits(ctx, args, workspace) {
|
|
1722
1978
|
const selectedWorkspace = workspace ?? (args.values.has('--workspace')
|
|
1723
1979
|
? resolve(ctx.cwd, args.values.get('--workspace')) : ctx.cwd);
|
|
@@ -1739,12 +1995,12 @@ function parseArgs(argv) {
|
|
|
1739
1995
|
const exclude = [];
|
|
1740
1996
|
const positionals = [];
|
|
1741
1997
|
const valueFlags = new Set([
|
|
1742
|
-
'--db', '--provider', '--workspace', '--tag', '--limit', '--cursor', '--source-id',
|
|
1998
|
+
'--db', '--provider', '--workspace', '--tag', '--limit', '--cursor', '--source-id', '--from-dir',
|
|
1743
1999
|
'--date-from', '--date-to', '--participant', '--model', '--role', '--tool',
|
|
1744
2000
|
'--entity', '--sensitivity', '--extraction-state', '--page-size', '--max-documents',
|
|
1745
2001
|
'--state', '--reviewer', '--reason', '--policy-version', '--min-confidence',
|
|
1746
2002
|
'--consumer', '--actor-class', '--reason-code', '--dependent-action', '--basis',
|
|
1747
|
-
'--carry-forward', '--manifest', '--provider-home', '--codex-root', '--omp-root', '--muse-root', '--dsh-root', '--grokbot-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
2003
|
+
'--carry-forward', '--manifest', '--provider-home', '--codex-root', '--omp-root', '--muse-root', '--dsh-root', '--grokbot-root', '--grok-root', '--grok-active-sessions', '--hermes-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
1748
2004
|
'--inactivity-threshold', '--expected-providers', '--exclude', '--max-record-bytes', '--max-source-bytes',
|
|
1749
2005
|
'--control-events',
|
|
1750
2006
|
'--session', '--status', '--actor', '--group-by',
|
|
@@ -13,6 +13,8 @@ import * as fs from 'fs/promises';
|
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import { validateSkillFrontmatter } from '../../extensions/validation.js';
|
|
15
15
|
import { validateAgentSkillFile } from '../../skills/validator.js';
|
|
16
|
+
import { CLAUDE_SKILL_FIELDS } from '../../skills/provider-extensions.js';
|
|
17
|
+
import { projectClaudeSkillSurfaces } from '../../skills/claude-surface-projection.js';
|
|
16
18
|
const THRESHOLDS = {
|
|
17
19
|
strict: 80,
|
|
18
20
|
standard: 60,
|
|
@@ -44,7 +46,10 @@ function scoreSchema(frontmatter, diagnostics) {
|
|
|
44
46
|
: `${item.yamlPath}: ${item.message} [${item.code}]`));
|
|
45
47
|
return scoreDimension(false, notes);
|
|
46
48
|
}
|
|
47
|
-
|
|
49
|
+
// Native Claude fields belong to the provider layer, including string effort.
|
|
50
|
+
const portableAndAiwg = Object.fromEntries(Object.entries(frontmatter)
|
|
51
|
+
.filter(([key]) => !CLAUDE_SKILL_FIELDS.includes(key)));
|
|
52
|
+
const result = validateSkillFrontmatter(portableAndAiwg);
|
|
48
53
|
if (result.success)
|
|
49
54
|
return scoreDimension(true);
|
|
50
55
|
const notes = result.errors.issues.map((e) => `${e.path.join('.') || '<root>'}: ${e.message}`);
|
|
@@ -211,6 +216,7 @@ export async function lintSkillFile(filePath, rubric = 'standard', profile = 'co
|
|
|
211
216
|
return {
|
|
212
217
|
file: filePath,
|
|
213
218
|
score,
|
|
219
|
+
projections: projectClaudeSkillSurfaces(body),
|
|
214
220
|
conformance: {
|
|
215
221
|
profile,
|
|
216
222
|
state: validation.state,
|
|
@@ -321,14 +327,15 @@ function parseArgs(args) {
|
|
|
321
327
|
function renderTextReport(report) {
|
|
322
328
|
const { files, threshold, rubric, profile, averageScore, failedCount } = report;
|
|
323
329
|
for (const f of files) {
|
|
324
|
-
if (f.passes && f.conformance.diagnostics.length === 0)
|
|
325
|
-
continue;
|
|
326
330
|
const mark = !f.passes
|
|
327
331
|
? '✗'
|
|
328
332
|
: f.conformance.diagnostics.some((item) => item.severity === 'warning')
|
|
329
333
|
? '⚠'
|
|
330
334
|
: '✓';
|
|
331
335
|
console.log(`${mark} ${f.file} (${f.score}/100, conformance=${f.conformance.state})`);
|
|
336
|
+
for (const p of f.projections) {
|
|
337
|
+
console.log(` ${p.provider}/${p.surface}: ${p.status}${p.shellInterpolation ? ` (shell: ${p.shellInterpolation})` : ''}; ${p.reasons.join(' ')}`);
|
|
338
|
+
}
|
|
332
339
|
for (const item of f.conformance.diagnostics) {
|
|
333
340
|
console.log(` ${item.severity} ${item.code} ${item.yamlPath}: ${item.message}; `
|
|
334
341
|
+ `fix: ${item.remediation}`);
|