@aiwg/cli 2026.10.11 → 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.
Files changed (132) hide show
  1. package/agentic/code/providers/model-catalog.v1.json +62 -12
  2. package/dist/src/artifacts/binding-target-identity.js +51 -0
  3. package/dist/src/artifacts/checksum-manifest.js +12 -0
  4. package/dist/src/artifacts/index-builder.js +11 -13
  5. package/dist/src/artifacts/query-engine.js +5 -11
  6. package/dist/src/cli/handlers/doctor-help.js +32 -0
  7. package/dist/src/cli/handlers/gates.js +19 -18
  8. package/dist/src/cli/handlers/models-help.js +7 -1
  9. package/dist/src/cli/handlers/models.js +3 -3
  10. package/dist/src/cli/handlers/script-runner.js +8 -5
  11. package/dist/src/cli/handlers/sessions-intake.js +104 -0
  12. package/dist/src/cli/handlers/sessions-tail.js +172 -0
  13. package/dist/src/cli/handlers/sessions.js +90 -17
  14. package/dist/src/cli/handlers/skill-lint.js +10 -3
  15. package/dist/src/cli/handlers/steward-format.js +100 -0
  16. package/dist/src/cli/handlers/steward-models.js +167 -0
  17. package/dist/src/cli/handlers/steward.js +14 -248
  18. package/dist/src/cli/handlers/use-bundle-counts.js +61 -0
  19. package/dist/src/cli/handlers/use.js +6 -24
  20. package/dist/src/cli/handlers/utilities.js +1 -24
  21. package/dist/src/config/aiwg-config.js +7 -0
  22. package/dist/src/config/authorization-cli.js +89 -0
  23. package/dist/src/config/cli-help.js +1 -0
  24. package/dist/src/config/cli.js +10 -1
  25. package/dist/src/decision/context-pruning.js +3 -2
  26. package/dist/src/decision/ensemble/contract.js +15 -4
  27. package/dist/src/decision/ensemble-study/artifacts.js +5 -0
  28. package/dist/src/decision/ensemble-study/score.js +4 -3
  29. package/dist/src/decision/feature-export.js +3 -9
  30. package/dist/src/decision/heldout/collector.js +2 -2
  31. package/dist/src/decision/issue-triage/runtime.js +3 -9
  32. package/dist/src/decision/qualification/gates.js +2 -1
  33. package/dist/src/decision/qualification/release.js +2 -3
  34. package/dist/src/decision/routing/report.js +2 -0
  35. package/dist/src/decision/sdlc-screening.js +3 -5
  36. package/dist/src/decision/sensitivity/comparative.js +5 -3
  37. package/dist/src/gates/driver.js +6 -77
  38. package/dist/src/gates/evaluate.js +4 -11
  39. package/dist/src/gates/floors.js +4 -4
  40. package/dist/src/gates/index.js +3 -3
  41. package/dist/src/gates/lattice.js +26 -0
  42. package/dist/src/gates/registry.js +2 -1
  43. package/dist/src/gates/report.js +19 -7
  44. package/dist/src/issues/audit-cli.js +120 -0
  45. package/dist/src/issues/audit-contract.js +64 -0
  46. package/dist/src/issues/audit-local.js +82 -0
  47. package/dist/src/issues/audit.js +220 -0
  48. package/dist/src/lint/rule-activation.js +15 -1
  49. package/dist/src/mission-protocol/canonical-codecs.js +270 -0
  50. package/dist/src/mission-protocol/codecs.js +22 -550
  51. package/dist/src/mission-protocol/health-trace-codecs.js +281 -0
  52. package/dist/src/mission-protocol/health-trace-types.js +43 -0
  53. package/dist/src/mission-protocol/types.js +2 -42
  54. package/dist/src/mission-protocol/worker-contract-json.js +10 -0
  55. package/dist/src/mission-protocol/worker-review-gate.js +100 -0
  56. package/dist/src/mission-protocol/worker-review-types.js +2 -0
  57. package/dist/src/models/catalog-policy.js +280 -0
  58. package/dist/src/models/index.js +1 -1
  59. package/dist/src/models/model-catalog.v1.json +62 -12
  60. package/dist/src/models/policy-resources.js +28 -0
  61. package/dist/src/models/provider-policy.js +10 -546
  62. package/dist/src/models/resolver.js +26 -8
  63. package/dist/src/models/router.js +15 -2
  64. package/dist/src/models/tiers.js +13 -0
  65. package/dist/src/models/types.js +0 -6
  66. package/dist/src/models/worker-ceilings.js +59 -0
  67. package/dist/src/models/worker-invocation-policy.js +243 -0
  68. package/dist/src/models/worker-plan.js +16 -20
  69. package/dist/src/models/worker-review-lineage.js +55 -0
  70. package/dist/src/models/worker-selection-policy.js +1 -1
  71. package/dist/src/models/wrapper-route.js +6 -3
  72. package/dist/src/policy/authorization.js +1 -0
  73. package/dist/src/policy/hitl-config.js +63 -0
  74. package/dist/src/policy/hitl-receipt.js +57 -0
  75. package/dist/src/policy/hitl-types.js +4 -0
  76. package/dist/src/policy/hitl-validation.js +39 -0
  77. package/dist/src/policy/hitl.js +117 -0
  78. package/dist/src/rules/activation.d.mts +1 -1
  79. package/dist/src/rules/activation.mjs +0 -2
  80. package/dist/src/rules/gate-coverage.js +51 -0
  81. package/dist/src/rules/gate-references.js +16 -0
  82. package/dist/src/rules/rule-frontmatter.schema.json +7 -1
  83. package/dist/src/serve/worker-command-request.js +21 -4
  84. package/dist/src/serve/worker-invocation-preparation.js +3 -1
  85. package/dist/src/serve/worker-invocation.js +21 -10
  86. package/dist/src/sessions/adapters/deepseek-harness.js +1 -0
  87. package/dist/src/sessions/adapters/grok-build-native.js +269 -0
  88. package/dist/src/sessions/adapters/grok-build.js +57 -15
  89. package/dist/src/sessions/adapters/hermes-state-db.js +252 -0
  90. package/dist/src/sessions/adapters/hermes.js +42 -3
  91. package/dist/src/sessions/adapters/warp.js +1 -1
  92. package/dist/src/sessions/batch-import.js +10 -0
  93. package/dist/src/sessions/contracts.js +1 -1
  94. package/dist/src/sessions/discovery-capability.js +38 -0
  95. package/dist/src/sessions/importer.js +8 -251
  96. package/dist/src/sessions/index.js +4 -0
  97. package/dist/src/sessions/intake-dir.js +71 -0
  98. package/dist/src/sessions/normalization.js +251 -0
  99. package/dist/src/sessions/tail.js +91 -0
  100. package/dist/src/sessions/workspace-discovery.js +83 -7
  101. package/dist/src/skills/agent-skill-sidecar.js +28 -0
  102. package/dist/src/skills/agent-skills.js +4 -23
  103. package/dist/src/skills/claude-surface-projection.js +25 -0
  104. package/dist/src/skills/deployer.js +8 -288
  105. package/dist/src/skills/deployment-policy.js +114 -0
  106. package/dist/src/skills/deployment-projection.js +152 -0
  107. package/dist/src/skills/deployment-types.js +20 -0
  108. package/dist/src/skills/exporter.js +8 -31
  109. package/dist/src/skills/provider-extensions.js +41 -0
  110. package/dist/src/skills/run.js +6 -0
  111. package/dist/src/skills/types.js +0 -8
  112. package/dist/src/skills/validator-resources.js +68 -0
  113. package/dist/src/skills/validator.js +6 -55
  114. package/dist/src/storage/cli-migrate-options.js +125 -0
  115. package/dist/src/storage/cli-migrate.js +111 -0
  116. package/dist/src/storage/cli.js +4 -279
  117. package/dist/src/storage/migration-adapter.js +79 -0
  118. package/dist/src/storage/migration-copy.js +108 -0
  119. package/dist/src/storage/migration-protocol.js +14 -197
  120. package/dist/src/storage/migration-records.js +186 -0
  121. package/dist/src/storage/migration-types.js +12 -0
  122. package/dist/src/tracker/forge-http.js +2 -1
  123. package/dist/src/tracker/issue-pages.js +110 -0
  124. package/package.json +1 -1
  125. package/schemas/mission-v1.schema.json +335 -0
  126. package/schemas/models/model-catalog.v1.schema.json +19 -1
  127. package/schemas/models/model-config-compatibility.v1.schema.json +3 -2
  128. package/schemas/models/model-policy.v1.schema.json +1 -1
  129. package/tools/agents/providers/provider-paths-staging.mjs +35 -0
  130. package/tools/agents/providers/rule-binding-targets.mjs +146 -0
  131. package/tools/agents/providers/rule-delivery.mjs +7 -126
  132. package/vscode-extension/schemas/aiwg.config.v1.json +177 -0
@@ -0,0 +1,172 @@
1
+ // Resolve catalog identities and authorized native paths for the sessions tail verb.
2
+ import { existsSync } from 'node:fs';
3
+ import { dirname, isAbsolute, resolve } from 'node:path';
4
+ import { readAiwgConfig } from '../../config/aiwg-config.js';
5
+ import { createSessionAdapterRegistry } from '../../sessions/adapter-registry.js';
6
+ import { assertSessionProviderId, SessionContractError } from '../../sessions/contracts.js';
7
+ import { redactSessionValue } from '../../sessions/policy.js';
8
+ import { resolveImportLimits } from '../../sessions/import-limits.js';
9
+ import { acquireImportLease } from '../../sessions/import-lease.js';
10
+ import { SessionRepository } from '../../sessions/repository.js';
11
+ import { assertTailSupported, tailSession } from '../../sessions/tail.js';
12
+ import { defaultDiscoveryManifestPath, readDiscoveryManifest } from '../../sessions/workspace-discovery.js';
13
+ export async function executeSessionsTail(ctx, args, helpers) {
14
+ const json = args.flags.has('--json');
15
+ let repository;
16
+ let lease;
17
+ const controller = new AbortController();
18
+ const stop = () => controller.abort();
19
+ const signal = ctx.signal ? AbortSignal.any([ctx.signal, controller.signal]) : controller.signal;
20
+ process.on('SIGINT', stop);
21
+ try {
22
+ const latest = args.flags.has('--latest');
23
+ const reference = args.positionals[0];
24
+ const providerInput = args.values.get('--provider');
25
+ if (args.positionals.length > 1 || (latest ? !providerInput || !!reference : !reference)) {
26
+ throw new SessionContractError('INVALID_ARGUMENT', 'tail requires <session-id> or --provider <p> --latest');
27
+ }
28
+ if (args.flags.has('--import') && (ctx.dryRun || args.flags.has('--dry-run'))) {
29
+ throw new SessionContractError('INVALID_ARGUMENT', 'tail --import cannot be combined with --dry-run');
30
+ }
31
+ const provider = providerInput ? assertSessionProviderId(providerInput) : undefined;
32
+ if (provider)
33
+ assertTailSupported(createSessionAdapterRegistry().get(provider));
34
+ let database = helpers.databasePath(ctx, args);
35
+ repository = new SessionRepository(database, { readonly: true });
36
+ const workspace = args.values.has('--workspace') || latest
37
+ ? helpers.readAuthorizationContext(ctx, args, 'tail', repository).workspaceId : undefined;
38
+ let matches = latest
39
+ ? repository.listSessions({ provider, workspaceId: workspace, limit: 1 }).items
40
+ : repository.findSessionsByReference(reference, workspace);
41
+ if (provider)
42
+ matches = matches.filter(session => session.provider === provider);
43
+ // Account-scoped providers live in the referenced host catalog (#3232).
44
+ const references = repository.listHostSessionReferences().filter(item => !provider || item.provider === provider);
45
+ const hosts = new Set(references.map(item => item.hostCatalog));
46
+ const candidates = matches.map(session => ({ session, database }));
47
+ for (const hostPath of hosts) {
48
+ if (!existsSync(hostPath))
49
+ continue;
50
+ const host = new SessionRepository(hostPath, { readonly: true });
51
+ try {
52
+ const allowed = new Set(references.filter(item => item.hostCatalog === hostPath)
53
+ .map(item => item.sessionId));
54
+ const sessions = latest
55
+ ? references.filter(item => item.hostCatalog === hostPath)
56
+ .flatMap(item => host.getSession(item.sessionId) ?? [])
57
+ : host.findSessionsByReference(reference);
58
+ candidates.push(...sessions.filter(session => allowed.has(session.sessionId))
59
+ .map(session => ({ session, database: hostPath })));
60
+ }
61
+ finally {
62
+ host.close();
63
+ }
64
+ }
65
+ const selected = latest
66
+ ? candidates.sort((a, b) => (b.session.updatedAt ?? '').localeCompare(a.session.updatedAt ?? '')
67
+ || b.session.sessionId.localeCompare(a.session.sessionId)).slice(0, 1)
68
+ : candidates;
69
+ if (selected.length !== 1) {
70
+ throw new SessionContractError('INVALID_ARGUMENT', selected.length
71
+ ? 'session reference is ambiguous; select --workspace or an internal session ID'
72
+ : 'session not found in the selected catalog and workspace');
73
+ }
74
+ const session = selected[0].session;
75
+ if (selected[0].database !== database) {
76
+ repository.close();
77
+ database = selected[0].database;
78
+ repository = new SessionRepository(database, { readonly: true });
79
+ }
80
+ const source = repository.getSource(session.sourceId);
81
+ if (!source)
82
+ throw new SessionContractError('SOURCE_NOT_AUTHORIZED', 'catalog source is unavailable');
83
+ const config = await readAiwgConfig(isAbsolute(session.workspaceId) ? session.workspaceId : ctx.cwd);
84
+ const limits = resolveImportLimits(config?.sessions?.import, {
85
+ maxRecordBytes: args.values.get('--max-record-bytes'),
86
+ maxSourceBytes: args.values.get('--max-source-bytes'),
87
+ });
88
+ const adapter = createSessionAdapterRegistry(limits).get(session.provider);
89
+ assertTailSupported(adapter);
90
+ const selectedSource = await resolveTailSource(ctx, args, session, source.locatorClass, config?.sessions?.discovery_manifests ?? [], resolve(dirname(helpers.databasePath(ctx, args)), 'discovery-manifest.json'));
91
+ const importing = args.flags.has('--import');
92
+ if (importing) {
93
+ repository.close();
94
+ repository = undefined;
95
+ lease = await acquireImportLease(database, `sessions-tail-${process.pid}`);
96
+ repository = new SessionRepository(database);
97
+ }
98
+ const checkpoint = repository.getCheckpoint(source.sourceId, adapter.adapterVersion);
99
+ await tailSession({
100
+ source, selectedSource, adapter, repository, sessionId: session.sessionId,
101
+ workspaceId: session.workspaceId, policyVersion: checkpoint?.policyVersion ?? '1.0.0',
102
+ limits, signal, follow: args.flags.has('--follow'), import: importing,
103
+ onEvent: event => {
104
+ if (json)
105
+ console.log(JSON.stringify({ contractVersion: '1.0.0', command: 'sessions.tail',
106
+ status: 'ok', data: { event }, error: null }));
107
+ else
108
+ console.log(`${event.occurredAt ?? '-'} ${session.provider} ${event.kind}: ${event.searchableText}`);
109
+ },
110
+ onPoll: flushStdout,
111
+ });
112
+ await flushStdout();
113
+ return { exitCode: 0 };
114
+ }
115
+ catch (error) {
116
+ if (signal.aborted)
117
+ return { exitCode: 0 };
118
+ const cliError = error instanceof Error && 'code' in error && 'exitCode' in error
119
+ ? error : undefined;
120
+ const code = error instanceof SessionContractError ? error.code
121
+ : cliError ? cliError.code
122
+ : 'code' in Object(error) && error.code === 'IMPORT_LOCKED'
123
+ ? 'IMPORT_LOCKED' : 'CATALOG_UNAVAILABLE';
124
+ const message = redactSessionValue(error instanceof Error ? error.message : 'session tail failed').value;
125
+ if (json) {
126
+ console.log(JSON.stringify({ contractVersion: '1.0.0', command: 'sessions.tail', status: 'error',
127
+ data: null, error: { code, message } }));
128
+ await flushStdout();
129
+ }
130
+ else
131
+ console.error(`${code}: ${message}`);
132
+ return { exitCode: cliError?.exitCode ?? (code === 'UNSUPPORTED_PROVIDER' ? 3 : code === 'INVALID_ARGUMENT' ? 2
133
+ : code === 'IMPORT_LOCKED' ? 7 : code === 'CATALOG_UNAVAILABLE' ? 6 : 5), message };
134
+ }
135
+ finally {
136
+ process.removeListener('SIGINT', stop);
137
+ repository?.close();
138
+ await lease?.release();
139
+ }
140
+ }
141
+ async function resolveTailSource(ctx, args, session, locatorClass, configured, catalogManifest) {
142
+ const workspace = isAbsolute(session.workspaceId) ? session.workspaceId : ctx.cwd;
143
+ // Existing explicit input option also supports older direct imports, whose
144
+ // catalog intentionally never retained the unredacted native pathname.
145
+ const input = args.values.get('--input');
146
+ if (input) {
147
+ const locator = resolve(ctx.cwd, input);
148
+ return { provider: session.provider, sourceId: session.sourceId, nativeSessionId: session.nativeSessionId, locatorClass, locator,
149
+ authorizedScope: { workspaceId: session.workspaceId, allowedRoots: [dirname(locator)] } };
150
+ }
151
+ const paths = args.values.has('--manifest') ? [resolve(ctx.cwd, args.values.get('--manifest'))] : [
152
+ defaultDiscoveryManifestPath(workspace), defaultDiscoveryManifestPath(ctx.cwd), catalogManifest,
153
+ ...configured.map(path => resolve(workspace, path)),
154
+ ];
155
+ for (const path of new Set(paths)) {
156
+ if (!existsSync(path))
157
+ continue;
158
+ const manifest = await readDiscoveryManifest(path);
159
+ const source = manifest.sources.find(item => item.sourceId === session.sourceId
160
+ && item.provider === session.provider && item.locatorClass === locatorClass && item.status !== 'excluded');
161
+ if (source)
162
+ return { provider: session.provider, sourceId: session.sourceId, nativeSessionId: session.nativeSessionId, locatorClass,
163
+ locator: source.locator, authorizedScope: {
164
+ workspaceId: session.workspaceId, allowedRoots: [source.authorizedRoot],
165
+ } };
166
+ }
167
+ throw new SessionContractError('SOURCE_NOT_AUTHORIZED', 'native source location is unavailable; pass its saved --manifest or explicitly authorize --input <native-source>');
168
+ }
169
+ function flushStdout() {
170
+ return new Promise((resolve, reject) => process.stdout.write('', error => error ? reject(error) : resolve()));
171
+ }
172
+ //# sourceMappingURL=sessions-tail.js.map
@@ -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, countUniqueSessionsAcrossCatalogs, defaultDiscoveryManifestPath, defaultHostCatalogPath, HOST_CATALOG_WORKSPACE_ID, indexIdentitiesBySessionId, manifestNeedsHostCatalog, mergeCrossCatalogRows, mergeSessionLists, resolveHostReferences, summarizeSessionAnalyticsFacts, 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) => providerDisposition(adapter.provider));
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
  }
@@ -794,10 +811,7 @@ async function executeCommand(ctx, args) {
794
811
  repository.close();
795
812
  }
796
813
  }
797
- async function importSource(ctx, args) {
798
- const limits = await configuredImportLimits(ctx, args);
799
- const input = resolve(ctx.cwd, requiredPositional(args, 0, 'file'));
800
- const providerInput = args.values.get('--provider') ?? 'generic';
814
+ function assertSupportedImportProvider(providerInput) {
801
815
  const provider = assertSessionProviderId(providerInput);
802
816
  if (provider !== 'generic' && provider !== 'claude' && provider !== 'codex'
803
817
  && provider !== 'copilot' && provider !== 'cursor' && provider !== 'factory'
@@ -805,6 +819,57 @@ async function importSource(ctx, args) {
805
819
  && provider !== 'openhuman' && provider !== 'grokbot' && provider !== 'grok-build' && provider !== 'muse' && provider !== 'pi' && provider !== 'omp' && provider !== 'deepseek-harness' && provider !== 'warp' && provider !== 'devin-desktop') {
806
820
  throw new CliError('UNSUPPORTED_OPERATION', `session import is not implemented for ${provider}`, EXIT.unsupported);
807
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);
808
873
  const sourceId = requiredValue(args, '--source-id');
809
874
  const workspaceId = args.values.has('--workspace')
810
875
  ? normalizeWorkspaceId(ctx.cwd, args.values.get('--workspace'))
@@ -822,6 +887,8 @@ async function importSource(ctx, args) {
822
887
  const isGrokbotNative = isGrokbot
823
888
  && classifyGrokbotBlobName(basename(input))?.kind === 'transcript-replica';
824
889
  const isGrokBuild = provider === 'grok-build';
890
+ const isGrokBuildNative = isGrokBuild
891
+ && basename(input) === 'chat_history.jsonl';
825
892
  const isMuse = provider === 'muse';
826
893
  const isPi = provider === 'pi';
827
894
  const isOmp = provider === 'omp';
@@ -880,7 +947,7 @@ async function importSource(ctx, args) {
880
947
  : isGrokbot
881
948
  ? (isGrokbotNative ? GROKBOT_NATIVE_REPLICA_LOCATOR_CLASS : 'manual-export')
882
949
  : isGrokBuild
883
- ? GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS
950
+ ? (isGrokBuildNative ? GROK_BUILD_NATIVE_LOCATOR_CLASS : GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS)
884
951
  : isMuse
885
952
  ? 'manual-export'
886
953
  : isPi
@@ -919,7 +986,7 @@ async function importSource(ctx, args) {
919
986
  : isGrokbot
920
987
  ? (isGrokbotNative ? 'grokbot-native-transcript-replica-v1' : 'manual-interchange')
921
988
  : isGrokBuild
922
- ? 'documented-cli-markdown-export'
989
+ ? (isGrokBuildNative ? 'grok-build-native-chat-history-v1' : 'documented-cli-markdown-export')
923
990
  : isMuse
924
991
  ? 'muse-export-trajectory-v1'
925
992
  : isWarp
@@ -986,7 +1053,7 @@ async function importSource(ctx, args) {
986
1053
  : isGrokbot
987
1054
  ? { 'native.grokbot': {} }
988
1055
  : isGrokBuild
989
- ? { 'native.grok-build': { acquisition: 'grok-cli-export-markdown' } }
1056
+ ? { 'native.grok-build': { acquisition: isGrokBuildNative ? GROK_BUILD_NATIVE_LOCATOR_CLASS : 'grok-cli-export-markdown' } }
990
1057
  : isMuse
991
1058
  ? { 'native.muse': {} }
992
1059
  : isWarp
@@ -1335,6 +1402,12 @@ async function discoverWorkspace(ctx, args) {
1335
1402
  ? resolve(ctx.cwd, args.values.get('--dsh-root')) : undefined,
1336
1403
  grokbotRoot: args.values.has('--grokbot-root')
1337
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,
1338
1411
  codexRoots: [
1339
1412
  ...(config?.sessions?.codex_roots ?? []).map((root) => resolve(workspace, root)),
1340
1413
  ...args.codexRoots.map((root) => resolve(ctx.cwd, root)),
@@ -1532,10 +1605,10 @@ function providerDisposition(provider) {
1532
1605
  if (provider === 'hermes') {
1533
1606
  return {
1534
1607
  provider, disposition: 'implemented', operationalState: 'available',
1535
- supportedOperations: ['inspect', 'stream'],
1608
+ supportedOperations: ['discover', 'inspect', 'stream'],
1536
1609
  acquisitionModes: ['jsonl', 'api', 'sqlite-snapshot'],
1537
1610
  reasonCode: null,
1538
- remediation: 'Use `hermes sessions export` or an explicitly verified sqlite3.backup() snapshot export.',
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.',
1539
1612
  evidence: {
1540
1613
  adapterVersion: HERMES_ADAPTER_VERSION,
1541
1614
  verifiedAt: '2026-07-27',
@@ -1643,10 +1716,10 @@ function providerDisposition(provider) {
1643
1716
  if (provider === 'grok-build') {
1644
1717
  return {
1645
1718
  provider, disposition: 'implemented', operationalState: 'available',
1646
- supportedOperations: ['inspect', 'stream'],
1647
- acquisitionModes: ['manual-export'],
1648
- reasonCode: 'CLI_EXPORT_REQUIRED',
1649
- 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.',
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.',
1650
1723
  evidence: {
1651
1724
  adapterVersion: GROK_BUILD_ADAPTER_VERSION,
1652
1725
  verifiedAt: '2026-09-21',
@@ -1922,12 +1995,12 @@ function parseArgs(argv) {
1922
1995
  const exclude = [];
1923
1996
  const positionals = [];
1924
1997
  const valueFlags = new Set([
1925
- '--db', '--provider', '--workspace', '--tag', '--limit', '--cursor', '--source-id',
1998
+ '--db', '--provider', '--workspace', '--tag', '--limit', '--cursor', '--source-id', '--from-dir',
1926
1999
  '--date-from', '--date-to', '--participant', '--model', '--role', '--tool',
1927
2000
  '--entity', '--sensitivity', '--extraction-state', '--page-size', '--max-documents',
1928
2001
  '--state', '--reviewer', '--reason', '--policy-version', '--min-confidence',
1929
2002
  '--consumer', '--actor-class', '--reason-code', '--dependent-action', '--basis',
1930
- '--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',
1931
2004
  '--inactivity-threshold', '--expected-providers', '--exclude', '--max-record-bytes', '--max-source-bytes',
1932
2005
  '--control-events',
1933
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
- const result = validateSkillFrontmatter(frontmatter);
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}`);
@@ -0,0 +1,100 @@
1
+ // Formats the steward capability matrix and permission command usage.
2
+ import { isExternalStrategy } from '../../providers/capability-matrix.js';
3
+ export function printFullMatrix(matrix) {
4
+ const { providers, features } = matrix;
5
+ const providerIds = Object.keys(providers);
6
+ const featureIds = Object.keys(features);
7
+ console.log(`\n Provider Capability Matrix (v${matrix.version})`);
8
+ console.log(` ✓ = native ~ = AIWG emulation - = not supported\n`);
9
+ const featureColW = 20;
10
+ const provColW = 14;
11
+ const header = ' ' + 'Feature'.padEnd(featureColW) + providerIds.map(p => p.padEnd(provColW)).join('');
12
+ console.log(header);
13
+ console.log(' ' + '─'.repeat(featureColW + providerIds.length * provColW));
14
+ for (const featureId of featureIds) {
15
+ const feat = features[featureId];
16
+ let row = ' ' + featureId.padEnd(featureColW);
17
+ for (const providerId of providerIds) {
18
+ const provider = providers[providerId];
19
+ const isNative = provider?.native_features?.[featureId] === true;
20
+ const emulation = provider?.emulation?.[featureId] ?? null;
21
+ const mark = isNative ? '✓' : (emulation ? '~' : '-');
22
+ row += mark.padEnd(provColW);
23
+ }
24
+ console.log(row);
25
+ if (feat?.description) {
26
+ console.log(' ' + ' '.repeat(featureColW) + feat.description);
27
+ }
28
+ console.log('');
29
+ }
30
+ }
31
+ // ── Main execution ─────────────────────────────────────────────────────────────
32
+ export function permissionsUsage() {
33
+ return `
34
+ aiwg steward permissions — authorization model audit and normalization
35
+
36
+ Usage:
37
+ aiwg steward permissions audit Find normalized-model errors and legacy grants
38
+ aiwg steward permissions migrate --dry-run Preview legacy permission normalization
39
+ aiwg steward permissions migrate --apply Back up and atomically normalize config
40
+
41
+ Reads .aiwg/aiwg.config authorization block. Migration backs up before writing.
42
+ `;
43
+ }
44
+ const NATIVE_MARK = '✓ native';
45
+ const EMULATED_MARK = '~ emulated';
46
+ const EXTERNAL_MARK = '↗ external';
47
+ const UNSUPPORTED_MARK = '- not supported';
48
+ export function emulationLabel(strategy) {
49
+ if (!strategy)
50
+ return 'none';
51
+ if (strategy === 'native')
52
+ return 'native (no fallback needed)';
53
+ return strategy;
54
+ }
55
+ export function formatProvider(id, provider, matrix, meta) {
56
+ const lines = [];
57
+ lines.push(`\n Provider: ${provider.display_name} (${id})`);
58
+ if (meta) {
59
+ lines.push(` Project-local: yes`);
60
+ lines.push(` Base adapter: ${meta.baseAdapter}`);
61
+ }
62
+ lines.push(` Status: ${provider.status}`);
63
+ lines.push(` Daemon: ${provider.daemon_tier}${provider.daemon_pty_adapter ? ' (+ pty-adapter)' : ''}`);
64
+ lines.push(` ${'─'.repeat(60)}`);
65
+ const featureKeys = Object.keys(matrix.features);
66
+ for (const featureId of featureKeys) {
67
+ const isNative = provider.native_features?.[featureId] === true;
68
+ const emulation = provider.emulation?.[featureId] ?? null;
69
+ const status = isNative
70
+ ? NATIVE_MARK
71
+ : isExternalStrategy(emulation) ? EXTERNAL_MARK : (emulation ? EMULATED_MARK : UNSUPPORTED_MARK);
72
+ const feat = matrix.features[featureId];
73
+ lines.push(`\n ${featureId} — ${status}`);
74
+ if (feat?.description)
75
+ lines.push(` ${feat.description}`);
76
+ if (isNative) {
77
+ if (id === 'omp' && featureId === 'mcp') {
78
+ lines.push(' OMP supplies the native client. AIWG persistent injection/removal is available for project and profile scope; ephemeral injection is unsupported.');
79
+ lines.push(' example: aiwg mcp inject --provider omp --servers local-tools');
80
+ }
81
+ else if (id === 'omp' && featureId === 'behaviors') {
82
+ lines.push(' AIWG bridges selected handlers through an OMP extension; no default policy is installed. Permission-request and pre-compaction enforcement are unsupported.');
83
+ }
84
+ else if (id === 'omp' && (featureId === 'tasks' || featureId === 'agent_teams')) {
85
+ lines.push(' OMP native leaf tasks use AIWG workspace admission limits and verified child results; nested requests share the same scheduler.');
86
+ lines.push(' example: aiwg team run --provider omp --body-file tasks.json');
87
+ }
88
+ else if (feat?.native_example)
89
+ lines.push(` example: ${feat.native_example}`);
90
+ }
91
+ else if (isExternalStrategy(emulation)) {
92
+ lines.push(` trigger: system cron, systemd timer, or CI; AIWG does not own the clock`);
93
+ }
94
+ else if (emulation) {
95
+ lines.push(` fallback: ${emulationLabel(emulation)}`);
96
+ }
97
+ }
98
+ return lines.join('\n');
99
+ }
100
+ //# sourceMappingURL=steward-format.js.map