@aiwg/cli 2026.10.0 → 2026.10.3

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.
Files changed (168) hide show
  1. package/agentic/code/providers/capability-matrix.yaml +270 -0
  2. package/agentic/code/providers/model-capabilities.v1.json +3091 -24
  3. package/bin/aiwg.mjs +86 -21
  4. package/dist/src/a2a/codecs.js +9 -0
  5. package/dist/src/artifacts/corpus-tools/vision-extract.js +105 -15
  6. package/dist/src/artifacts/repair.js +9 -4
  7. package/dist/src/channel/manager.mjs +59 -10
  8. package/dist/src/cli/child-process-result.js +40 -0
  9. package/dist/src/cli/env.js +38 -16
  10. package/dist/src/cli/flag-parsing.js +236 -0
  11. package/dist/src/cli/handlers/decision.js +297 -2
  12. package/dist/src/cli/handlers/diagnose.js +9 -2
  13. package/dist/src/cli/handlers/feedback.js +14 -5
  14. package/dist/src/cli/handlers/init.js +245 -30
  15. package/dist/src/cli/handlers/mc.js +23 -0
  16. package/dist/src/cli/handlers/models.js +69 -6
  17. package/dist/src/cli/handlers/ralph.js +3 -0
  18. package/dist/src/cli/handlers/refresh.js +16 -0
  19. package/dist/src/cli/handlers/regenerate.js +14 -0
  20. package/dist/src/cli/handlers/runtime-info.js +24 -9
  21. package/dist/src/cli/handlers/script-runner.js +16 -6
  22. package/dist/src/cli/handlers/session.js +396 -62
  23. package/dist/src/cli/handlers/sessions.js +146 -40
  24. package/dist/src/cli/handlers/setup-manifest.js +439 -39
  25. package/dist/src/cli/handlers/setup.js +139 -39
  26. package/dist/src/cli/handlers/subcommands.js +3 -1
  27. package/dist/src/cli/handlers/team.js +18 -8
  28. package/dist/src/cli/handlers/use.js +13 -0
  29. package/dist/src/cli/handlers/utilities.js +106 -23
  30. package/dist/src/cli/prompt-utils.js +72 -0
  31. package/dist/src/cli/provider-resolution.js +11 -0
  32. package/dist/src/config/aiwg-config.js +268 -4
  33. package/dist/src/config/cli.js +146 -19
  34. package/dist/src/config/dispatch-thresholds-runtime.mjs +38 -0
  35. package/dist/src/config/project-artifacts-health.mjs +14 -3
  36. package/dist/src/config/user-config.js +36 -10
  37. package/dist/src/decision/adapters/jev.js +80 -28
  38. package/dist/src/decision/ask.js +352 -0
  39. package/dist/src/decision/driver.js +4 -0
  40. package/dist/src/decision/entry.js +38 -6
  41. package/dist/src/decision/heldout/collector.js +10 -1
  42. package/dist/src/decision/index.js +3 -0
  43. package/dist/src/decision/interop.js +60 -8
  44. package/dist/src/decision/jev-credentials.js +121 -0
  45. package/dist/src/decision/ledger.js +839 -0
  46. package/dist/src/decision/validate.js +6 -3
  47. package/dist/src/effects/dispatch-verifier.js +252 -0
  48. package/dist/src/effects/index.js +1 -0
  49. package/dist/src/features/installer.js +2 -2
  50. package/dist/src/flow/graph-metadata.js +5 -0
  51. package/dist/src/gates/providers/loader.js +3 -1
  52. package/dist/src/installation/manager-command.mjs +1 -1
  53. package/dist/src/installation/manager.mjs +17 -2
  54. package/dist/src/lint/runner.js +2 -2
  55. package/dist/src/mcp/adapters/codex-runtime.js +360 -56
  56. package/dist/src/mcp/cli.mjs +587 -77
  57. package/dist/src/mcp/config-file.mjs +279 -0
  58. package/dist/src/mcp/config-layers.mjs +348 -0
  59. package/dist/src/mcp/credentials.mjs +484 -0
  60. package/dist/src/mcp/grok-build-config.mjs +16 -26
  61. package/dist/src/mcp/helpers.mjs +106 -2
  62. package/dist/src/mcp/omp-config.mjs +50 -29
  63. package/dist/src/mcp/profiles.js +97 -23
  64. package/dist/src/mcp/profiles.mjs +99 -27
  65. package/dist/src/mcp/registry.js +264 -57
  66. package/dist/src/mcp/registry.mjs +198 -45
  67. package/dist/src/mcp/server.mjs +403 -20
  68. package/dist/src/mcp/toml-string.mjs +9 -0
  69. package/dist/src/mcp/toml-strip-mcp.mjs +135 -0
  70. package/dist/src/mcp/tool-filters.mjs +357 -0
  71. package/dist/src/mcp/tools/agentic-sandbox.mjs +3 -1
  72. package/dist/src/mcp/tools/decision.mjs +58 -0
  73. package/dist/src/mcp/tools/orchestration.mjs +38 -0
  74. package/dist/src/mcp/tools/subsystems.mjs +39 -8
  75. package/dist/src/mcp/tools/worker-invoke.mjs +1539 -0
  76. package/dist/src/mcp/tools/worker-shell-control.mjs +258 -0
  77. package/dist/src/mcp/tools/worker-stdin-runtime.mjs +79 -0
  78. package/dist/src/memory/project-registry.js +2 -2
  79. package/dist/src/mission-protocol/codecs.js +639 -1
  80. package/dist/src/mission-protocol/types.js +110 -0
  81. package/dist/src/mission-protocol/worker-status.js +2 -0
  82. package/dist/src/models/config-loader.js +70 -13
  83. package/dist/src/models/grok-build-models.js +93 -41
  84. package/dist/src/models/model-capabilities.v1.json +3091 -24
  85. package/dist/src/models/model-discovery.js +862 -63
  86. package/dist/src/models/provider-policy.js +625 -11
  87. package/dist/src/models/qualification-digest.mjs +17 -0
  88. package/dist/src/models/resolver.js +259 -0
  89. package/dist/src/models/worker-direct-readiness.js +529 -0
  90. package/dist/src/models/worker-dispatch-offer.js +169 -0
  91. package/dist/src/models/worker-health-readiness.js +131 -0
  92. package/dist/src/models/worker-installation.mjs +879 -0
  93. package/dist/src/models/wrapper-route.js +18 -0
  94. package/dist/src/ops/registry.js +9 -14
  95. package/dist/src/plugins/standalone-packager.js +4 -3
  96. package/dist/src/process/bounded-child-process.mjs +387 -0
  97. package/dist/src/process/cli-command.mjs +75 -0
  98. package/dist/src/providers/capability-matrix.js +8 -0
  99. package/dist/src/providers/capability-matrix.yaml +270 -0
  100. package/dist/src/providers/grok-build-headless.js +43 -21
  101. package/dist/src/providers/provider-definitions.js +9 -1
  102. package/dist/src/providers/provider-definitions.mjs +9 -2
  103. package/dist/src/serve/executor-registry.js +16 -24
  104. package/dist/src/serve/fleet-mission-conductor.js +9 -0
  105. package/dist/src/serve/mission-conductor.js +9 -0
  106. package/dist/src/serve/shared-host-scheduler.js +2 -0
  107. package/dist/src/serve/worker-invocation.js +538 -0
  108. package/dist/src/serve/worker-stdin-frame.mjs +107 -0
  109. package/dist/src/sessions/adapter-registry.js +45 -0
  110. package/dist/src/sessions/adapters/generic.js +37 -3
  111. package/dist/src/sessions/adapters/grokbot-locator.js +111 -0
  112. package/dist/src/sessions/adapters/grokbot.js +423 -24
  113. package/dist/src/sessions/adapters/muse-workspace-scan.js +108 -0
  114. package/dist/src/sessions/adapters/muse.js +68 -29
  115. package/dist/src/sessions/adapters/pi.js +1 -0
  116. package/dist/src/sessions/batch-contracts.js +13 -1
  117. package/dist/src/sessions/batch-import.js +23 -42
  118. package/dist/src/sessions/candidates.js +47 -11
  119. package/dist/src/sessions/contracts.js +35 -0
  120. package/dist/src/sessions/coverage-preflight.js +134 -0
  121. package/dist/src/sessions/discovery.js +3 -0
  122. package/dist/src/sessions/grok-build-cli.js +67 -5
  123. package/dist/src/sessions/importer.js +24 -8
  124. package/dist/src/sessions/index.js +2 -0
  125. package/dist/src/sessions/repository.js +54 -13
  126. package/dist/src/sessions/workspace-discovery.js +99 -37
  127. package/dist/src/skills/adapters/clawhub.js +10 -8
  128. package/dist/src/skills/adapters/openclaw.js +10 -7
  129. package/dist/src/smiths/context-pipeline/parallelism-section.js +192 -3
  130. package/dist/src/smiths/context-pipeline/workspace-context.js +116 -9
  131. package/dist/src/smiths/hook-bridge/codex-translator.js +6 -5
  132. package/dist/src/smiths/mcpsmith/example.js +1 -1
  133. package/dist/src/smiths/toolsmith/runtime-discovery.mjs +10 -14
  134. package/dist/src/storage/backends/logseq.js +68 -7
  135. package/dist/src/storage/fortemi-qualification-receipt.js +2 -2
  136. package/dist/src/testing/generators/test-code-generator.js +57 -30
  137. package/dist/src/uhp/client.js +11 -1
  138. package/dist/src/uhp/mission.js +5 -0
  139. package/dist/src/update/checker.mjs +5 -5
  140. package/dist/src/update/notifier.mjs +54 -2
  141. package/dist/src/writing/fidelity.js +18 -1
  142. package/package.json +18 -1
  143. package/schemas/mission-v1.schema.json +2429 -0
  144. package/schemas/models/model-catalog.v1.schema.json +301 -0
  145. package/schemas/models/model-config-compatibility.v1.schema.json +281 -0
  146. package/schemas/models/model-policy.v1.schema.json +14 -0
  147. package/schemas/models/provider-model-capabilities.v1.schema.json +1066 -0
  148. package/tools/_resolve-impl.mjs +39 -0
  149. package/tools/agents/deploy-agents.mjs +15 -2
  150. package/tools/agents/providers/base.mjs +63 -43
  151. package/tools/agents/providers/grokbot.mjs +11 -12
  152. package/tools/agents/providers/hermes.mjs +6 -3
  153. package/tools/agents/providers/omp.mjs +5 -2
  154. package/tools/agents/providers/openclaw-translator.mjs +19 -5
  155. package/tools/providers/deepseek-harness-transport.mjs +358 -0
  156. package/tools/providers/omp-transport.mjs +192 -0
  157. package/tools/ralph-external/lib/claude-adapter.mjs +389 -0
  158. package/tools/ralph-external/lib/codex-adapter.mjs +432 -0
  159. package/tools/ralph-external/lib/deepseek-harness-adapter.mjs +397 -0
  160. package/tools/ralph-external/lib/factory-adapter.mjs +503 -0
  161. package/tools/ralph-external/lib/muse-adapter.mjs +364 -0
  162. package/tools/ralph-external/lib/omp-adapter.mjs +315 -0
  163. package/tools/ralph-external/lib/opencode-adapter.mjs +575 -0
  164. package/tools/ralph-external/lib/openhuman-adapter.mjs +75 -0
  165. package/tools/ralph-external/lib/pi-adapter.mjs +333 -0
  166. package/tools/ralph-external/lib/provider-adapter.mjs +690 -0
  167. package/tools/ralph-external/lib/worker-health.mjs +439 -0
  168. package/vscode-extension/schemas/aiwg.config.v1.json +1953 -0
@@ -2,7 +2,8 @@ import { existsSync, linkSync, mkdirSync, readFileSync, realpathSync, renameSync
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { basename, dirname, isAbsolute, join, resolve, } from 'node:path';
4
4
  import { pathToFileURL } from 'node:url';
5
- 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, 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, SESSION_PROVIDER_IDS, SessionContractError, SessionRepository, SessionSourceSchema, StructuralCandidateExtractor, resolveMemoryConsumerManifest, assertSessionProviderId, acquireImportLease, defaultDiscoveryManifestPath, discoverWorkspaceHistories, deriveSessionTimeline, importDiscoveryManifest, previewDiscoveryImport, publicDiscoveryManifest, readDiscoveryManifest, redactSourceLocator, sha256, parseTimelineGap, writeDiscoveryManifest, buildSessionExportPlan, reverifySessionExportPlan, buildSessionAiwgFortemiIndexExport, recoverAiwgFortemiIndexFromFullV1Shard, embedAttachmentsInFullV1Shard, recoverEmbeddedAttachments, SESSION_EXPORT_PLAN_SCHEMA_VERSION, } from '../../sessions/index.js';
5
+ 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 { classifyGrokbotBlobName } from '../../sessions/adapters/grokbot-locator.js';
6
7
  const JSON_CONTRACT_VERSION = '1.0.0';
7
8
  async function createLineMemoryPromotionDestination(projectRoot, manifestPath) {
8
9
  const modulePath = resolve(dirname(manifestPath), 'commands', 'line-memory.mjs');
@@ -33,10 +34,10 @@ Commands:
33
34
  grok-export <id> --workspace <path> --out <dir> Export one CLI transcript
34
35
  grok-id <file> --format json|streaming-json Read a headless session ID
35
36
  import <file> --source-id <id> Import a supported provider JSONL source
36
- list [--limit N] [--cursor N] List normalized sessions
37
- timeline [--gap 30m] Report chronological activity segments
38
- show <session-id> Show a session with events and tags
39
- search <query> --workspace <id> Search authorized normalized content
37
+ list [--workspace <path-or-id>] [--limit N] [--cursor N] List normalized sessions
38
+ timeline [--workspace <path-or-id>] [--gap 30m] Report chronological activity segments
39
+ show <session-id> [--workspace <path-or-id>] Show a session with events and tags
40
+ search <query> [--workspace <path-or-id>] Search authorized normalized content
40
41
  extract [session-id] --workspace <id> Extract structural candidates
41
42
  export plan --workspace <id> --out <file> <session-id...> Select sessions into a reviewable plan
42
43
  export build --plan <file> --out <dir> Build a Fortemi Knowledge Shard from a plan
@@ -59,20 +60,29 @@ Commands:
59
60
  Options:
60
61
  --json Emit the versioned JSON contract
61
62
  --dry-run Preview a mutation without changing state
62
- --db <path> Override .aiwg/sessions/catalog.sqlite
63
+ --db <path> Select a catalog; relative paths resolve from cwd
64
+ --workspace <path-or-id> Select the workspace within that catalog for reads
65
+ (default: current project, matching cwd, or sole catalog workspace)
66
+ Catalog defaults to <project-or-cwd>/.aiwg/sessions/catalog.sqlite
67
+ Imports for other workspaces stay in the selected catalog;
68
+ use --db to read that catalog from another directory
69
+ --expected-providers <ids> Comma-separated authorized scope, independent of runtime inventory
63
70
  --manifest <path> Override the discovery manifest path
64
71
  --provider-home <path> Override the provider home root (testing/portable homes)
65
72
  --codex-root <path> Explicitly authorize a shared Codex sessions/export root
66
73
  --omp-root <path> Explicitly authorize an OMP profile sessions root
67
74
  --muse-root <path> Explicitly authorize a Muse Code sessions root
68
75
  --dsh-root <path> Explicitly authorize a DeepSeek Harness sessions root
76
+ --grokbot-root <path> Explicitly authorize a Grok Bot sand-client-persistence root
77
+ --grok-bin <path> Absolute Grok Build CLI path for grok-list/grok-search/grok-export
78
+ (default: grok on PATH, then $GROK_HOME/bin/grok)
69
79
  --confirm, --yes Confirm a persistent discovered batch import
70
80
  --lock-wait-ms <n> Maximum import-lease wait (default 5000)
71
81
  --inactivity-threshold <duration> Historical inactivity threshold (default 24h)
72
82
  --min-coverage <0..1> Fail list/report commands below a coverage ratio
73
83
  --provider <id> Filter list or select an import adapter
74
84
  --consumer <id> Select a named memory consumer for promotion
75
- --workspace <id>, --tag <tag>, --limit <n>, --cursor <n>
85
+ --tag <tag>, --limit <n>, --cursor <n>
76
86
  --page-size <n> Extraction scan page size (default 250, maximum 500)
77
87
  --max-documents <n> Explicit extraction safety limit; returns a partial receipt
78
88
  --include-bytes Embed registered-output bytes in session export shards
@@ -87,6 +97,12 @@ Search filters:
87
97
  Query syntax: FTS5 terms, quoted phrases, prefixes, AND/OR/NOT
88
98
  Follow the opaque nextCursor with the same query and filters
89
99
 
100
+ Show identifiers:
101
+ Internal session_ IDs, exact provider-native IDs, or unique prefixes
102
+ Native IDs search the selected catalog unless --workspace is explicit
103
+ Internal session_ IDs retain the default workspace scope
104
+ Ambiguous IDs list candidates; select --workspace or an internal ID from list
105
+
90
106
  Analytics / forensics:
91
107
  --session <id>, --date-from <rfc3339>, --date-to <rfc3339>
92
108
  --actor <id>, --participant <id>, --tool <name>, --status <status>
@@ -151,8 +167,10 @@ export const sessionsHandler = {
151
167
  async function executeCommand(ctx, args) {
152
168
  const command = args.command;
153
169
  if (command === 'sources') {
154
- const reports = [...SESSION_PROVIDER_IDS].sort().map(providerDisposition);
155
- return ok(command, { providers: reports, count: reports.length });
170
+ const registry = createSessionAdapterRegistry();
171
+ const reports = registry.list().map((adapter) => providerDisposition(adapter.provider));
172
+ const preflight = coveragePreflight({ expectedProviders: requestedProviders(args), registry });
173
+ return ok(command, { providers: reports, count: reports.length, preflight });
156
174
  }
157
175
  if (command === 'import')
158
176
  return importSource(ctx, args);
@@ -198,7 +216,10 @@ async function executeCommand(ctx, args) {
198
216
  limit,
199
217
  cursor,
200
218
  });
201
- const coverage = repository.getCoverage(workspaceId);
219
+ const coverage = {
220
+ ...repository.getCoverage(workspaceId),
221
+ catalogScope: catalogScope(ctx, args, repository, workspaceId),
222
+ };
202
223
  const response = {
203
224
  items: result.items,
204
225
  page: {
@@ -230,7 +251,10 @@ async function executeCommand(ctx, args) {
230
251
  const { workspaceId } = readAuthorizationContext(ctx, args, command, repository);
231
252
  const gapMs = timelineGap(args.values.get('--gap'));
232
253
  const items = deriveSessionTimeline(repository.listTimelineInputs(workspaceId), gapMs);
233
- const coverage = repository.getCoverage(workspaceId);
254
+ const coverage = {
255
+ ...repository.getCoverage(workspaceId),
256
+ catalogScope: catalogScope(ctx, args, repository, workspaceId),
257
+ };
234
258
  const response = {
235
259
  schemaVersion: '1.0.0',
236
260
  workspaceId,
@@ -257,14 +281,33 @@ async function executeCommand(ctx, args) {
257
281
  }
258
282
  case 'show': {
259
283
  const id = requiredPositional(args, 0, 'session-id');
260
- const { workspaceId } = readAuthorizationContext(ctx, args, command, repository);
261
- const session = repository.getSession(id, workspaceId);
284
+ const explicit = args.values.has('--workspace');
285
+ const catalogMatches = explicit ? undefined : repository.findSessionsByReference(id);
286
+ // Provider-native IDs and their prefixes may themselves start with
287
+ // session_. Exact internal IDs still take precedence.
288
+ const scoped = explicit || catalogMatches?.some((session) => session.sessionId === id)
289
+ || (id.startsWith('session_')
290
+ && !catalogMatches?.some((session) => session.nativeSessionId.startsWith(id)));
291
+ const workspaceId = scoped
292
+ ? readAuthorizationContext(ctx, args, command, repository).workspaceId
293
+ : projectRootCandidate(ctx.cwd) ?? normalizeWorkspaceId(ctx.cwd, '.');
294
+ const scope = catalogScope(ctx, args, repository, workspaceId);
295
+ // Native IDs identify provider transcripts across this local catalog.
296
+ // Explicit workspace selection and internal IDs retain workspace scope.
297
+ const matches = scoped ? repository.findSessionsByReference(id, workspaceId) : catalogMatches;
298
+ if (matches.length > 1) {
299
+ throw new CliError('SESSION_AMBIGUOUS', `session reference is ambiguous: ${id}; candidates: ${matches.map((session) => `${session.sessionId} (provider=${session.provider}, workspace=${JSON.stringify(session.workspaceId)})`).join(', ')}; select --workspace or use an internal session ID from sessions list`, EXIT.usage, { catalogScope: scope, candidates: matches.map((session) => ({
300
+ sessionId: session.sessionId, provider: session.provider, workspaceId: session.workspaceId,
301
+ })) });
302
+ }
303
+ const session = matches[0];
262
304
  if (!session)
263
- throw new CliError('SESSION_NOT_FOUND', `session not found: ${id}`, EXIT.unavailable);
305
+ throw new CliError('SESSION_NOT_FOUND', `session not found: ${id}${scope.hint ? `; ${scope.hint}` : ''}`, EXIT.unavailable, { catalogScope: scope });
264
306
  return ok(command, {
265
307
  session,
266
- tags: repository.listTags(id, workspaceId),
267
- events: repository.listEvents(id, workspaceId),
308
+ tags: repository.listTags(session.sessionId, session.workspaceId),
309
+ events: repository.listEvents(session.sessionId, session.workspaceId),
310
+ catalogScope: catalogScope(ctx, args, repository, session.workspaceId),
268
311
  });
269
312
  }
270
313
  case 'search': {
@@ -292,6 +335,7 @@ async function executeCommand(ctx, args) {
292
335
  });
293
336
  return ok(command, {
294
337
  items: result.items,
338
+ catalogScope: catalogScope(ctx, args, repository, workspaceId),
295
339
  page: { limit: boundedInteger(args.values.get('--limit'), 50, 1, 500, '--limit'),
296
340
  nextCursor: result.nextCursor },
297
341
  });
@@ -700,6 +744,8 @@ async function importSource(ctx, args) {
700
744
  const isOpenClaw = provider === 'openclaw';
701
745
  const isOpenHuman = provider === 'openhuman';
702
746
  const isGrokbot = provider === 'grokbot';
747
+ const isGrokbotNative = isGrokbot
748
+ && classifyGrokbotBlobName(basename(input))?.kind === 'transcript-replica';
703
749
  const isGrokBuild = provider === 'grok-build';
704
750
  const isMuse = provider === 'muse';
705
751
  const isPi = provider === 'pi';
@@ -757,7 +803,7 @@ async function importSource(ctx, args) {
757
803
  : isOpenHuman
758
804
  ? 'openhuman-enriched-jsonl'
759
805
  : isGrokbot
760
- ? 'manual-export'
806
+ ? (isGrokbotNative ? GROKBOT_NATIVE_REPLICA_LOCATOR_CLASS : 'manual-export')
761
807
  : isGrokBuild
762
808
  ? GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS
763
809
  : isMuse
@@ -774,6 +820,7 @@ async function importSource(ctx, args) {
774
820
  authorizedScope: { workspaceId, allowedRoots: [dirname(input)] },
775
821
  };
776
822
  const probe = await adapter.inspect(selectedSource);
823
+ const workspaceReport = importWorkspaceReport(workspaceId, args.values.has('--workspace'), probe);
777
824
  const source = SessionSourceSchema.parse({
778
825
  contractVersion: SESSION_CONTRACT_VERSION, sourceId, provider,
779
826
  providerProfile: isDsh ? 'native-session-v2-jsonl' : isOmp ? 'native-title-slot-v3' : isClaude
@@ -795,7 +842,7 @@ async function importSource(ctx, args) {
795
842
  : isOpenHuman
796
843
  ? 'schema-1-session-raw-enriched'
797
844
  : isGrokbot
798
- ? 'manual-interchange'
845
+ ? (isGrokbotNative ? 'grokbot-native-transcript-replica-v1' : 'manual-interchange')
799
846
  : isGrokBuild
800
847
  ? 'documented-cli-markdown-export'
801
848
  : isMuse
@@ -836,10 +883,10 @@ async function importSource(ctx, args) {
836
883
  ? DEVIN_DESKTOP_ADAPTER_VERSION
837
884
  : GENERIC_ADAPTER_VERSION,
838
885
  sourceSchemaVersion: probe.sourceSchemaVersion,
839
- disposition: isWarp || isGrokbot || isMuse
886
+ disposition: isWarp || (isGrokbot && !isGrokbotNative) || isMuse
840
887
  ? 'manual-only'
841
888
  : isClaude || isCodex || isCopilot || isCursor || isFactory || isHermes
842
- || isOpenCode || isOpenClaw || isOpenHuman || isGrokBuild || isDevinDesktop || isOmp || isDsh || isPi
889
+ || isOpenCode || isOpenClaw || isOpenHuman || isGrokbotNative || isGrokBuild || isDevinDesktop || isOmp || isDsh || isPi
843
890
  ? 'implemented' : 'manual-only',
844
891
  operationalState: probe.operationalState,
845
892
  consistency: probe.consistency, authorizedAt: new Date().toISOString(),
@@ -877,7 +924,7 @@ async function importSource(ctx, args) {
877
924
  : { 'native.generic': {} },
878
925
  });
879
926
  if (isDryRun(ctx, args)) {
880
- return preview('import', { source, wouldInspect: true, wouldPersist: false });
927
+ return preview('import', { source, ...workspaceReport, wouldInspect: true, wouldPersist: false });
881
928
  }
882
929
  const lease = await acquireImportLease(databasePath(ctx, args), sha256(['single-source-import', sourceId, workspaceId].join('\0')), {
883
930
  waitMs: boundedInteger(args.values.get('--lock-wait-ms'), 5_000, 0, 300_000, '--lock-wait-ms'),
@@ -889,8 +936,11 @@ async function importSource(ctx, args) {
889
936
  source, selectedSource, adapter, workspaceId, policyVersion: '1.0.0',
890
937
  inactivityThresholdMs: inactivityThreshold(args.values.get('--inactivity-threshold')),
891
938
  });
939
+ for (const warning of workspaceReport.warnings)
940
+ console.error(`WARNING ${warning}`);
892
941
  return ok('import', {
893
942
  sourceId,
943
+ ...workspaceReport,
894
944
  receipts,
895
945
  totals: {
896
946
  sessionsInserted: receipts.reduce((sum, item) => sum + item.sessionsInserted, 0),
@@ -906,6 +956,24 @@ async function importSource(ctx, args) {
906
956
  await lease.release();
907
957
  }
908
958
  }
959
+ /**
960
+ * Report which catalog workspace an import uses (#2967). A source-declared
961
+ * workspace is provenance only; it never selects the authorization scope.
962
+ */
963
+ function importWorkspaceReport(workspaceId, fromArgument, probe) {
964
+ const warnings = [];
965
+ const declared = probe.declaredWorkspaceId;
966
+ if (declared !== undefined && declared !== workspaceId) {
967
+ warnings.push(`source declares workspace "${declared}" but sessions are imported into "${workspaceId}"`
968
+ + `${fromArgument ? '' : ' (no --workspace given)'}; pass --workspace to choose the catalog workspace`);
969
+ }
970
+ return {
971
+ workspaceId,
972
+ workspaceSource: fromArgument ? 'argument' : 'default',
973
+ ...(declared === undefined ? {} : { declaredWorkspaceId: declared }),
974
+ warnings,
975
+ };
976
+ }
909
977
  /**
910
978
  * `aiwg sessions export {plan,build,verify,unpack}` (#2564). Sub-verb after
911
979
  * `export`, matching the issue's proposed shape:
@@ -1168,6 +1236,7 @@ async function discoverWorkspace(ctx, args) {
1168
1236
  const workspace = resolve(ctx.cwd, requiredValue(args, '--workspace'));
1169
1237
  const manifest = await discoverWorkspaceHistories({
1170
1238
  workspace,
1239
+ expectedProviders: requestedProviders(args),
1171
1240
  providerHome: args.values.has('--provider-home')
1172
1241
  ? resolve(ctx.cwd, args.values.get('--provider-home'))
1173
1242
  : undefined,
@@ -1177,6 +1246,8 @@ async function discoverWorkspace(ctx, args) {
1177
1246
  ? resolve(ctx.cwd, args.values.get('--muse-root')) : undefined,
1178
1247
  dshRoot: args.values.has('--dsh-root')
1179
1248
  ? resolve(ctx.cwd, args.values.get('--dsh-root')) : undefined,
1249
+ grokbotRoot: args.values.has('--grokbot-root')
1250
+ ? resolve(ctx.cwd, args.values.get('--grokbot-root')) : undefined,
1180
1251
  codexRoot: args.values.has('--codex-root')
1181
1252
  ? resolve(ctx.cwd, args.values.get('--codex-root'))
1182
1253
  : undefined,
@@ -1201,6 +1272,10 @@ async function importDiscovered(ctx, args) {
1201
1272
  if (manifest.workspaceId !== canonicalWorkspace) {
1202
1273
  throw new CliError('MANIFEST_WORKSPACE_MISMATCH', 'discovery manifest does not belong to the explicitly authorized workspace', EXIT.contract);
1203
1274
  }
1275
+ const expected = requestedProviders(args);
1276
+ if (expected && JSON.stringify(expected) !== JSON.stringify(manifest.preflight?.expectedProviders)) {
1277
+ throw new SessionContractError('INVALID_ARGUMENT', 'expected provider scope differs from the saved manifest; rediscover with --expected-providers');
1278
+ }
1204
1279
  const confirmed = args.flags.has('--confirm') || args.flags.has('--yes');
1205
1280
  if (isDryRun(ctx, args) || !confirmed) {
1206
1281
  let existing = null;
@@ -1235,6 +1310,11 @@ async function importDiscovered(ctx, args) {
1235
1310
  manifestId: manifest.manifestId,
1236
1311
  receipt,
1237
1312
  resumable: receipt.run.status !== 'complete',
1313
+ catalog: {
1314
+ database: databasePath(ctx, args),
1315
+ workspaceId: manifest.workspaceId,
1316
+ hint: `Read these sessions from either directory with aiwg sessions list --workspace ${JSON.stringify(manifest.workspaceId)} --db ${JSON.stringify(databasePath(ctx, args))}`,
1317
+ },
1238
1318
  });
1239
1319
  }
1240
1320
  finally {
@@ -1414,14 +1494,16 @@ function providerDisposition(provider) {
1414
1494
  }
1415
1495
  if (provider === 'grokbot') {
1416
1496
  return {
1417
- provider, disposition: 'manual-only', operationalState: 'available',
1418
- supportedOperations: ['inspect', 'stream'],
1419
- acquisitionModes: ['manual-export'],
1420
- reasonCode: 'MANUAL_SOURCE_SELECTION_REQUIRED',
1421
- remediation: 'Select an authorized AIWG session interchange export; Grok Bot auto-discover is unsupported until a native locator exists.',
1497
+ provider, disposition: 'implemented', operationalState: 'available',
1498
+ supportedOperations: ['discover', 'inspect', 'stream'],
1499
+ acquisitionModes: ['manual-export', 'jsonl'],
1500
+ reasonCode: null,
1501
+ remediation: 'Import an explicit AIWG session interchange export, or pass --grokbot-root with an '
1502
+ + 'explicitly authorized $XDG_CONFIG_HOME/Grok Bot/sand-client-persistence root (Linux only) for '
1503
+ + 'evidence-gated native discovery.',
1422
1504
  evidence: {
1423
1505
  adapterVersion: GROKBOT_ADAPTER_VERSION,
1424
- verifiedAt: '2026-09-15',
1506
+ verifiedAt: '2026-10-09',
1425
1507
  documentation: 'docs/providers/grokbot-sessions.md',
1426
1508
  },
1427
1509
  };
@@ -1432,7 +1514,7 @@ function providerDisposition(provider) {
1432
1514
  supportedOperations: ['inspect', 'stream'],
1433
1515
  acquisitionModes: ['manual-export'],
1434
1516
  reasonCode: 'CLI_EXPORT_REQUIRED',
1435
- remediation: 'Run `grok sessions list`, then `grok export <session-id> <session-id>.md` and import the explicitly authorized Markdown file.',
1517
+ remediation: 'Run `grok sessions list`, then `grok export <session-id> <session-id>.md` and import the explicitly authorized Markdown file. `aiwg sessions grok-list` finds `grok` on PATH or in $GROK_HOME/bin; pass --grok-bin <absolute path> otherwise.',
1436
1518
  evidence: {
1437
1519
  adapterVersion: GROK_BUILD_ADAPTER_VERSION,
1438
1520
  verifiedAt: '2026-09-21',
@@ -1550,7 +1632,21 @@ function openRepository(ctx, args) {
1550
1632
  function databasePath(ctx, args) {
1551
1633
  if (args.values.has('--db'))
1552
1634
  return resolve(ctx.cwd, args.values.get('--db'));
1553
- return resolve(projectRootCandidate(ctx.cwd) ?? ctx.cwd, '.aiwg/sessions/catalog.sqlite');
1635
+ return resolve(projectRootCandidate(ctx.cwd) ?? normalizeWorkspaceId(ctx.cwd, '.'), '.aiwg/sessions/catalog.sqlite');
1636
+ }
1637
+ function catalogScope(ctx, args, repository, workspaceId) {
1638
+ const workspaces = repository.listWorkspaceSessionCounts();
1639
+ const otherWorkspaces = workspaces.filter((workspace) => workspace.workspaceId !== workspaceId);
1640
+ const database = databasePath(ctx, args);
1641
+ return {
1642
+ database,
1643
+ workspaceId,
1644
+ total: workspaces.reduce((total, workspace) => total + workspace.count, 0),
1645
+ otherWorkspaces,
1646
+ hint: otherWorkspaces.length
1647
+ ? `Other workspaces in this catalog: ${otherWorkspaces.map((workspace) => `${JSON.stringify(workspace.workspaceId)} (${workspace.count} sessions)`).join(', ')}. Select one with --workspace <path-or-id>; from another directory also pass --db ${JSON.stringify(database)}.`
1648
+ : null,
1649
+ };
1554
1650
  }
1555
1651
  function parseArgs(argv) {
1556
1652
  const flags = new Set();
@@ -1562,8 +1658,8 @@ function parseArgs(argv) {
1562
1658
  '--entity', '--sensitivity', '--extraction-state', '--page-size', '--max-documents',
1563
1659
  '--state', '--reviewer', '--reason', '--policy-version', '--min-confidence',
1564
1660
  '--consumer', '--actor-class', '--reason-code', '--dependent-action', '--basis',
1565
- '--manifest', '--provider-home', '--codex-root', '--omp-root', '--muse-root', '--dsh-root', '--lock-wait-ms', '--min-coverage', '--gap',
1566
- '--inactivity-threshold',
1661
+ '--manifest', '--provider-home', '--codex-root', '--omp-root', '--muse-root', '--dsh-root', '--grokbot-root', '--lock-wait-ms', '--min-coverage', '--gap',
1662
+ '--inactivity-threshold', '--expected-providers',
1567
1663
  '--control-events',
1568
1664
  '--session', '--status', '--actor', '--group-by',
1569
1665
  '--out', '--plan', '--input', '--shard-name', '--max-attachment-bytes', '--format', '--grok-bin',
@@ -1591,6 +1687,10 @@ function parseArgs(argv) {
1591
1687
  }
1592
1688
  return { command, positionals, flags, values };
1593
1689
  }
1690
+ function requestedProviders(args) {
1691
+ const value = args.values.get('--expected-providers');
1692
+ return value === undefined ? undefined : expectedSessionProviders(value.split(','));
1693
+ }
1594
1694
  function requiredPositional(args, index, name) {
1595
1695
  const value = args.positionals[index];
1596
1696
  if (!value)
@@ -1634,6 +1734,16 @@ function readAuthorizationContext(ctx, args, operation, repository) {
1634
1734
  };
1635
1735
  }
1636
1736
  const candidates = repository.listWorkspaceIds();
1737
+ const current = normalizeWorkspaceId(ctx.cwd, '.');
1738
+ if (candidates.includes(current) || candidates.length === 0) {
1739
+ return {
1740
+ actorId: 'local-catalog-owner',
1741
+ workspaceId: current,
1742
+ operation,
1743
+ catalogScope: 'workspace',
1744
+ mode: 'local-owner',
1745
+ };
1746
+ }
1637
1747
  if (candidates.length === 1) {
1638
1748
  return {
1639
1749
  actorId: 'local-catalog-owner',
@@ -1643,15 +1753,9 @@ function readAuthorizationContext(ctx, args, operation, repository) {
1643
1753
  mode: 'local-owner',
1644
1754
  };
1645
1755
  }
1646
- if (candidates.length > 1) {
1647
- throw new CliError('WORKSPACE_AMBIGUOUS', 'current workspace cannot be inferred safely; pass --workspace explicitly', EXIT.usage, {
1648
- candidates,
1649
- example: `aiwg sessions ${operation} --workspace ${JSON.stringify(candidates[0])}`,
1650
- });
1651
- }
1652
- throw new CliError('WORKSPACE_REQUIRED', 'current workspace cannot be inferred; pass --workspace explicitly', EXIT.usage, {
1653
- candidates: [],
1654
- example: `aiwg sessions ${operation} --workspace <path-or-id>`,
1756
+ throw new CliError('WORKSPACE_AMBIGUOUS', 'current workspace cannot be inferred safely; pass --workspace explicitly', EXIT.usage, {
1757
+ candidates,
1758
+ example: `aiwg sessions ${operation} --workspace ${JSON.stringify(candidates[0])}`,
1655
1759
  });
1656
1760
  }
1657
1761
  function projectRootCandidate(start) {
@@ -1885,6 +1989,8 @@ function printHuman(value) {
1885
1989
  ].join(' '));
1886
1990
  }
1887
1991
  console.log(`Coverage: ${data.coverage?.status ?? 'unknown'}`);
1992
+ if (data.coverage?.catalogScope?.hint)
1993
+ console.log(data.coverage.catalogScope.hint);
1888
1994
  return;
1889
1995
  }
1890
1996
  console.log(JSON.stringify(value.data, null, 2));