@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.
- 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 +90 -17
- 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 +6 -24
- 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/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/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-catalog.v1.json +62 -12
- package/dist/src/models/policy-resources.js +28 -0
- package/dist/src/models/provider-policy.js +10 -546
- 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 +1 -0
- 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/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/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 +10 -0
- package/dist/src/sessions/contracts.js +1 -1
- package/dist/src/sessions/discovery-capability.js +38 -0
- package/dist/src/sessions/importer.js +8 -251
- package/dist/src/sessions/index.js +4 -0
- package/dist/src/sessions/intake-dir.js +71 -0
- package/dist/src/sessions/normalization.js +251 -0
- package/dist/src/sessions/tail.js +91 -0
- package/dist/src/sessions/workspace-discovery.js +83 -7
- 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 +1 -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/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) =>
|
|
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
|
-
|
|
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: '
|
|
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:
|
|
1649
|
-
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.',
|
|
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
|
-
|
|
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
|