@aiwg/cli 2026.9.2 → 2026.9.4

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 (68) hide show
  1. package/README.md +21 -0
  2. package/agentic/code/providers/antigravity/provider-contract.v1.json +121 -0
  3. package/agentic/code/providers/capability-matrix.yaml +87 -1
  4. package/agentic/code/providers/model-capabilities.v1.json +31 -0
  5. package/agentic/code/providers/model-catalog.v1.json +29 -0
  6. package/agentic/code/providers/omp/README.md +58 -0
  7. package/agentic/code/providers/omp/aiwg-bridge.ts +52 -0
  8. package/dist/src/agents/agent-deployer.js +18 -0
  9. package/dist/src/agents/agent-packager.js +25 -0
  10. package/dist/src/artifacts/backends/sqlite-backend.js +18 -10
  11. package/dist/src/artifacts/query-engine.js +30 -0
  12. package/dist/src/cli/agent-spawn.js +13 -2
  13. package/dist/src/cli/handlers/help.js +3 -1
  14. package/dist/src/cli/handlers/init.js +2 -0
  15. package/dist/src/cli/handlers/models.js +1 -1
  16. package/dist/src/cli/handlers/runtime-info.js +8 -1
  17. package/dist/src/cli/handlers/session.js +5 -4
  18. package/dist/src/cli/handlers/sessions.js +26 -9
  19. package/dist/src/cli/handlers/setup.js +9 -2
  20. package/dist/src/cli/handlers/steward.js +13 -2
  21. package/dist/src/cli/handlers/subcommands.js +11 -0
  22. package/dist/src/cli/handlers/team.js +68 -7
  23. package/dist/src/cli/handlers/use.js +158 -9
  24. package/dist/src/cli/scope-resolver.js +7 -0
  25. package/dist/src/config/aiwg-config.js +1 -0
  26. package/dist/src/dataset/fortemi-live-qualification.d.ts +53 -0
  27. package/dist/src/dataset/fortemi-live-qualification.js +297 -0
  28. package/dist/src/dataset/index.d.ts +1 -0
  29. package/dist/src/dataset/index.js +1 -0
  30. package/dist/src/mcp/cli.mjs +30 -1
  31. package/dist/src/mcp/omp-config.mjs +128 -0
  32. package/dist/src/mcp/registry.js +45 -5
  33. package/dist/src/mcp/registry.mjs +29 -6
  34. package/dist/src/models/model-capabilities.v1.json +31 -0
  35. package/dist/src/models/model-catalog.v1.json +29 -0
  36. package/dist/src/models/model-discovery.js +46 -5
  37. package/dist/src/models/provider-policy.js +5 -3
  38. package/dist/src/plugin/skill-command-translator.js +2 -0
  39. package/dist/src/providers/capability-matrix.yaml +87 -1
  40. package/dist/src/providers/omp-agent.mjs +40 -0
  41. package/dist/src/providers/omp-diagnostics.mjs +15 -0
  42. package/dist/src/providers/omp-paths.mjs +38 -0
  43. package/dist/src/providers/provider-definitions.js +83 -0
  44. package/dist/src/providers/provider-definitions.mjs +25 -1
  45. package/dist/src/providers/provider-inventory.js +2 -0
  46. package/dist/src/sessions/adapters/omp.js +203 -0
  47. package/dist/src/sessions/batch-import.js +7 -0
  48. package/dist/src/sessions/contracts.js +1 -1
  49. package/dist/src/sessions/importer.js +4 -3
  50. package/dist/src/sessions/index.js +1 -0
  51. package/dist/src/sessions/readers.js +4 -3
  52. package/dist/src/sessions/workspace-discovery.js +12 -2
  53. package/dist/src/skills/deployer.js +21 -1
  54. package/dist/src/smiths/agentsmith/generator.js +1 -0
  55. package/dist/src/smiths/context-pipeline/parallelism-section.js +2 -0
  56. package/dist/src/smiths/context-pipeline/provider-policy.js +2 -2
  57. package/dist/src/smiths/context-pipeline/workspace-context.js +2 -2
  58. package/dist/src/storage/backends/fortemi.js +142 -17
  59. package/dist/src/storage/fortemi-qualification-receipt.js +206 -0
  60. package/dist/src/storage/fortemi-qualification.js +67 -6
  61. package/dist/src/storage/index.js +1 -0
  62. package/package.json +2 -1
  63. package/schemas/dataset/fortemi-live-qualification-receipt.v1.schema.json +132 -0
  64. package/tools/agents/deploy-agents.mjs +6 -3
  65. package/tools/agents/providers/antigravity.mjs +147 -0
  66. package/tools/agents/providers/omp.d.mts +4 -0
  67. package/tools/agents/providers/omp.mjs +256 -0
  68. package/tools/providers/antigravity-transport.mjs +124 -0
@@ -12,6 +12,11 @@
12
12
  * spawn(config.binary, spawnArgs, { stdio: 'inherit' });
13
13
  */
14
14
  export const PROVIDER_CONFIGS = {
15
+ antigravity: {
16
+ binary: 'agy',
17
+ dangerousFlag: '--dangerously-skip-permissions',
18
+ name: 'Google Antigravity CLI',
19
+ },
15
20
  claude: {
16
21
  binary: 'claude',
17
22
  dangerousFlag: '--dangerously-skip-permissions',
@@ -152,9 +157,15 @@ export function splitParams(params) {
152
157
  return result;
153
158
  }
154
159
  // ── Provider helpers ──────────────────────────────────────────
155
- /** Get config for a provider, falling back to claude for unknown values. */
160
+ const SPAWN_PROVIDER_ALIASES = { agy: 'antigravity' };
161
+ /** Get config for a provider. Unknown values fail closed instead of launching another harness. */
156
162
  export function getProviderConfig(provider) {
157
- return PROVIDER_CONFIGS[provider] ?? PROVIDER_CONFIGS['claude'];
163
+ const candidate = provider.trim().toLowerCase();
164
+ const canonical = SPAWN_PROVIDER_ALIASES[candidate] ?? candidate;
165
+ const config = PROVIDER_CONFIGS[canonical];
166
+ if (!config)
167
+ throw new Error(`Unsupported provider '${provider}'`);
168
+ return config;
158
169
  }
159
170
  /** Returns true if the provider has a CLI binary that can be spawned. */
160
171
  export function isSpawnableProvider(provider) {
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import * as ui from '../ui.js';
11
11
  import { maybePrintCommunityFooter } from '../../community/footer.js';
12
+ import { listProviderDefinitions } from '../../providers/provider-definitions.js';
12
13
  /**
13
14
  * Help command handler
14
15
  */
@@ -144,7 +145,8 @@ function displayHelp() {
144
145
  ]);
145
146
  ui.rule();
146
147
  ui.blank();
147
- console.log(` ${ui.dimText('Providers:')} 12 claude (default), codex, copilot, cursor, factory, hermes, opencode, openclaw, openhuman, pi, warp, windsurf (alias: devin)`);
148
+ const providers = listProviderDefinitions().filter(({ id }) => id !== 'generic');
149
+ console.log(` ${ui.dimText('Providers:')} ${providers.length} — ${providers.map(({ id }) => id).join(', ')} (default: claude; aliases: agy → antigravity, devin → windsurf, oh-my-pi → omp)`);
148
150
  ui.blank();
149
151
  console.log(` ${ui.dimText('Examples:')}`);
150
152
  console.log(` aiwg use sdlc ${ui.dimText('Install SDLC framework')}`);
@@ -20,6 +20,7 @@ import { askString as sharedAskString, askYesNo as sharedAskYesNo } from '../pro
20
20
  import { writeNormalizedAiwgMd } from '../../smiths/context-pipeline/finalization.js';
21
21
  import { ensureWorkspaceContext } from '../../smiths/context-pipeline/workspace-context.js';
22
22
  const PROVIDER_LABELS = {
23
+ antigravity: 'Google Antigravity .agents/',
23
24
  claude: 'Claude Code .claude/',
24
25
  copilot: 'GitHub Copilot .github/',
25
26
  cursor: 'Cursor .cursor/',
@@ -30,6 +31,7 @@ const PROVIDER_LABELS = {
30
31
  codex: 'OpenAI Codex ~/.codex/',
31
32
  openclaw: 'OpenClaw ~/.openclaw/',
32
33
  hermes: 'Hermes (MCP) aiwg mcp',
34
+ omp: 'Oh My Pi .omp/ + .agents/skills/',
33
35
  pi: 'Pi Coding Agent .pi/ + .agents/skills/',
34
36
  };
35
37
  // Local aliases for the shared prompt utilities. These preserve existing
@@ -10,7 +10,7 @@ import { load as loadYaml } from 'js-yaml';
10
10
  import { compileModelPolicy, validateCanonicalModelPolicy, validateUserProjectModelConfig, } from '../../models/provider-policy.js';
11
11
  const TIERS = new Set(['economy', 'standard', 'premium', 'max-quality']);
12
12
  const PROVIDERS = new Set([
13
- 'claude', 'codex', 'copilot', 'cursor', 'factory', 'hermes',
13
+ 'antigravity', 'claude', 'codex', 'copilot', 'cursor', 'factory', 'hermes',
14
14
  'opencode', 'openclaw', 'openhuman', 'warp', 'windsurf',
15
15
  ]);
16
16
  function parseArgs(args) {
@@ -88,8 +88,13 @@ async function handleRuntimeInfo(args, cwd = process.cwd()) {
88
88
  if (hasProviders) {
89
89
  const { collectProviderInventory } = await import('../../providers/provider-inventory.js');
90
90
  const inventory = await collectProviderInventory(cwd);
91
+ const selected = args[args.indexOf('--provider') + 1];
92
+ const ompSelected = args.includes('--provider') && ['omp', 'oh-my-pi'].includes(selected);
93
+ const ompRuntime = ompSelected
94
+ ? await (await import('../../providers/omp-diagnostics.mjs')).diagnoseOmpRuntime({ cwd })
95
+ : undefined;
91
96
  if (hasJson) {
92
- console.log(JSON.stringify(inventory, null, 2));
97
+ console.log(JSON.stringify({ ...inventory, ...(ompRuntime ? { ompRuntime } : {}) }, null, 2));
93
98
  }
94
99
  else {
95
100
  console.log('\nProvider Inventory');
@@ -109,6 +114,8 @@ async function handleRuntimeInfo(args, cwd = process.cwd()) {
109
114
  for (const reason of provider.reasons)
110
115
  console.log(` note: ${reason}`);
111
116
  }
117
+ if (ompRuntime)
118
+ console.log(`\nOMP runtime: ${JSON.stringify(ompRuntime, null, 2)}`);
112
119
  }
113
120
  return;
114
121
  }
@@ -26,6 +26,7 @@ import { readAiwgConfig, getDeploymentSummary, VALID_PROVIDERS, } from '../../co
26
26
  import { getProviderConfig, isSpawnableProvider, PROVIDER_CONFIGS, } from '../agent-spawn.js';
27
27
  import { useHandler as useFrameworkHandler } from './use.js';
28
28
  import { debug } from '../log.js';
29
+ import { normalizeProviderDefinitionId } from '../../providers/provider-definitions.js';
29
30
  // ── Provider resolution ──────────────────────────────────────────────────────
30
31
  /**
31
32
  * Resolve which provider to target.
@@ -33,11 +34,11 @@ import { debug } from '../log.js';
33
34
  */
34
35
  async function resolveProvider(explicitProvider, cwd) {
35
36
  if (explicitProvider) {
36
- if (!VALID_PROVIDERS.includes(explicitProvider)) {
37
- console.warn(` WARN Unknown provider '${explicitProvider}' falling back to 'claude'`);
38
- return 'claude';
37
+ const normalized = normalizeProviderDefinitionId(explicitProvider);
38
+ if (!normalized || normalized === 'generic' || !VALID_PROVIDERS.includes(normalized)) {
39
+ throw new Error(`Unsupported provider '${explicitProvider}'`);
39
40
  }
40
- return explicitProvider;
41
+ return normalized;
41
42
  }
42
43
  const config = await readAiwgConfig(cwd);
43
44
  if (config?.providers?.[0]) {
@@ -1,7 +1,7 @@
1
1
  import { existsSync, mkdirSync, realpathSync, statSync, } from 'node:fs';
2
2
  import { dirname, isAbsolute, resolve, } from 'node:path';
3
3
  import { pathToFileURL } from 'node:url';
4
- 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, PI_ADAPTER_VERSION, PiSessionAdapter, 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, } from '../../sessions/index.js';
4
+ 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, PI_ADAPTER_VERSION, PiSessionAdapter, 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, } from '../../sessions/index.js';
5
5
  const JSON_CONTRACT_VERSION = '1.0.0';
6
6
  async function createLineMemoryPromotionDestination(projectRoot, manifestPath) {
7
7
  const modulePath = resolve(dirname(manifestPath), 'commands', 'line-memory.mjs');
@@ -54,6 +54,7 @@ Options:
54
54
  --manifest <path> Override the discovery manifest path
55
55
  --provider-home <path> Override the provider home root (testing/portable homes)
56
56
  --codex-root <path> Explicitly authorize a shared Codex sessions/export root
57
+ --omp-root <path> Explicitly authorize an OMP profile sessions root
57
58
  --confirm, --yes Confirm a persistent discovered batch import
58
59
  --lock-wait-ms <n> Maximum import-lease wait (default 5000)
59
60
  --inactivity-threshold <duration> Historical inactivity threshold (default 24h)
@@ -622,7 +623,7 @@ async function importSource(ctx, args) {
622
623
  if (provider !== 'generic' && provider !== 'claude' && provider !== 'codex'
623
624
  && provider !== 'copilot' && provider !== 'cursor' && provider !== 'factory'
624
625
  && provider !== 'hermes' && provider !== 'opencode' && provider !== 'openclaw'
625
- && provider !== 'openhuman' && provider !== 'pi' && provider !== 'warp' && provider !== 'devin-desktop') {
626
+ && provider !== 'openhuman' && provider !== 'pi' && provider !== 'omp' && provider !== 'warp' && provider !== 'devin-desktop') {
626
627
  throw new CliError('UNSUPPORTED_OPERATION', `session import is not implemented for ${provider}`, EXIT.unsupported);
627
628
  }
628
629
  const sourceId = requiredValue(args, '--source-id');
@@ -639,9 +640,10 @@ async function importSource(ctx, args) {
639
640
  const isOpenClaw = provider === 'openclaw';
640
641
  const isOpenHuman = provider === 'openhuman';
641
642
  const isPi = provider === 'pi';
643
+ const isOmp = provider === 'omp';
642
644
  const isWarp = provider === 'warp';
643
645
  const isDevinDesktop = provider === 'devin-desktop';
644
- const adapter = isClaude
646
+ const adapter = isOmp ? new OmpSessionAdapter() : isClaude
645
647
  ? new ClaudeSessionAdapter()
646
648
  : isCodex
647
649
  ? new CodexSessionAdapter()
@@ -666,7 +668,7 @@ async function importSource(ctx, args) {
666
668
  : isDevinDesktop
667
669
  ? new DevinDesktopSessionAdapter()
668
670
  : new GenericSessionInterchangeAdapter();
669
- const locatorClass = isClaude
671
+ const locatorClass = isOmp ? 'omp-session-v3-jsonl' : isClaude
670
672
  ? (input.endsWith('.hooks.jsonl') ? 'claude-hook-jsonl' : 'claude-transcript-jsonl')
671
673
  : isCodex
672
674
  ? (input.endsWith('.app-server.jsonl') ? 'codex-app-server-jsonl' : 'codex-rollout-jsonl')
@@ -698,7 +700,7 @@ async function importSource(ctx, args) {
698
700
  const probe = await adapter.inspect(selectedSource);
699
701
  const source = SessionSourceSchema.parse({
700
702
  contractVersion: SESSION_CONTRACT_VERSION, sourceId, provider,
701
- providerProfile: isClaude
703
+ providerProfile: isOmp ? 'native-title-slot-v3' : isClaude
702
704
  ? 'documented-local-jsonl'
703
705
  : isCodex
704
706
  ? 'app-server-v2-rollout-fallback'
@@ -722,7 +724,7 @@ async function importSource(ctx, args) {
722
724
  ? 'opt-in-cascade-transcript-hook'
723
725
  : 'manual-interchange',
724
726
  locatorClass, redactedLocator: redactSourceLocator(input),
725
- adapterVersion: isClaude
727
+ adapterVersion: isOmp ? OMP_ADAPTER_VERSION : isClaude
726
728
  ? CLAUDE_ADAPTER_VERSION
727
729
  : isCodex
728
730
  ? CODEX_ADAPTER_VERSION
@@ -749,11 +751,11 @@ async function importSource(ctx, args) {
749
751
  disposition: isWarp
750
752
  ? 'manual-only'
751
753
  : isClaude || isCodex || isCopilot || isCursor || isFactory || isHermes
752
- || isOpenCode || isOpenClaw || isOpenHuman || isDevinDesktop
754
+ || isOpenCode || isOpenClaw || isOpenHuman || isDevinDesktop || isOmp
753
755
  ? 'implemented' : 'manual-only',
754
756
  operationalState: probe.operationalState,
755
757
  consistency: probe.consistency, authorizedAt: new Date().toISOString(),
756
- extensions: isClaude
758
+ extensions: isOmp ? { 'native.omp': {} } : isClaude
757
759
  ? { 'native.claude': {} }
758
760
  : isCodex
759
761
  ? { 'native.codex': {} }
@@ -817,6 +819,8 @@ async function discoverWorkspace(ctx, args) {
817
819
  providerHome: args.values.has('--provider-home')
818
820
  ? resolve(ctx.cwd, args.values.get('--provider-home'))
819
821
  : undefined,
822
+ ompRoot: args.values.has('--omp-root')
823
+ ? resolve(ctx.cwd, args.values.get('--omp-root')) : undefined,
820
824
  codexRoot: args.values.has('--codex-root')
821
825
  ? resolve(ctx.cwd, args.values.get('--codex-root'))
822
826
  : undefined,
@@ -1012,6 +1016,19 @@ function providerDisposition(provider) {
1012
1016
  },
1013
1017
  };
1014
1018
  }
1019
+ if (provider === 'omp') {
1020
+ return {
1021
+ provider, disposition: 'implemented', operationalState: 'available',
1022
+ supportedOperations: ['discover', 'inspect', 'stream'],
1023
+ acquisitionModes: ['jsonl'], reasonCode: null,
1024
+ remediation: 'Authorize the selected OMP profile sessions root or an explicit native JSONL file.',
1025
+ evidence: {
1026
+ adapterVersion: OMP_ADAPTER_VERSION,
1027
+ verifiedAt: '2026-09-04',
1028
+ documentation: 'https://github.com/can1357/oh-my-pi/blob/main/packages/coding-agent/src/session/session-entries.ts',
1029
+ },
1030
+ };
1031
+ }
1015
1032
  if (provider === 'pi') {
1016
1033
  return {
1017
1034
  provider, disposition: 'implemented', operationalState: 'available',
@@ -1121,7 +1138,7 @@ function parseArgs(argv) {
1121
1138
  '--entity', '--sensitivity', '--extraction-state', '--page-size', '--max-documents',
1122
1139
  '--state', '--reviewer', '--reason', '--policy-version', '--min-confidence',
1123
1140
  '--consumer', '--actor-class', '--reason-code', '--dependent-action', '--basis',
1124
- '--manifest', '--provider-home', '--codex-root', '--lock-wait-ms', '--min-coverage', '--gap',
1141
+ '--manifest', '--provider-home', '--codex-root', '--omp-root', '--lock-wait-ms', '--min-coverage', '--gap',
1125
1142
  '--inactivity-threshold',
1126
1143
  '--control-events',
1127
1144
  '--session', '--status', '--actor', '--group-by',
@@ -5,6 +5,7 @@ import { AiwgError, EXIT_CODES } from '../errors.js';
5
5
  import { askChoice, askString, askYesNo, createPromptInterface } from '../prompt-utils.js';
6
6
  import * as ui from '../ui.js';
7
7
  import { projectAiwgPath } from '../../config/project-artifacts.js';
8
+ import { normalizeProviderDefinitionId } from '../../providers/provider-definitions.js';
8
9
  const DELIVERY_MODES = ['pr-required', 'feature-branch', 'direct'];
9
10
  const FORCE_PUSH_POLICIES = ['never', 'own-branch-only', 'allowed'];
10
11
  const ISSUE_PROVIDERS = ['gitea', 'github', 'local'];
@@ -56,7 +57,10 @@ function parseStringList(raw) {
56
57
  }
57
58
  function parseProviders(raw, fallback) {
58
59
  const providers = parseStringList(raw);
59
- return providers && providers.length > 0 ? providers : fallback;
60
+ return providers && providers.length > 0 ? normalizeProviders(providers) : fallback;
61
+ }
62
+ function normalizeProviders(providers) {
63
+ return providers.map(provider => normalizeProviderDefinitionId(provider) ?? provider);
60
64
  }
61
65
  export function parseSetupProjectOptions(ctx) {
62
66
  const args = ctx.args;
@@ -88,7 +92,10 @@ export function parseSetupProjectOptions(ctx) {
88
92
  trackerActorVia: parseEnum(flagValue(args, '--tracker-actor-via'), TRACKER_VIA, '--tracker-actor-via'),
89
93
  customerTrackerActorLogin: flagValue(args, '--customer-tracker-actor-login'),
90
94
  customerTrackerActorVia: parseEnum(flagValue(args, '--customer-tracker-actor-via'), TRACKER_VIA, '--customer-tracker-actor-via'),
91
- providers: parseStringList(flagValue(args, '--providers')),
95
+ providers: (() => {
96
+ const providers = parseStringList(flagValue(args, '--providers'));
97
+ return providers ? normalizeProviders(providers) : undefined;
98
+ })(),
92
99
  };
93
100
  }
94
101
  export function detectGitRemotes(projectDir) {
@@ -82,7 +82,18 @@ function formatProvider(id, provider, matrix, meta) {
82
82
  if (feat?.description)
83
83
  lines.push(` ${feat.description}`);
84
84
  if (isNative) {
85
- if (feat?.native_example)
85
+ if (id === 'omp' && featureId === 'mcp') {
86
+ lines.push(' OMP supplies the native client. AIWG persistent injection/removal is available for project and profile scope; ephemeral injection is unsupported.');
87
+ lines.push(' example: aiwg mcp inject --provider omp --servers local-tools');
88
+ }
89
+ else if (id === 'omp' && featureId === 'behaviors') {
90
+ lines.push(' AIWG bridges selected handlers through an OMP extension; no default policy is installed. Permission-request and pre-compaction enforcement are unsupported.');
91
+ }
92
+ else if (id === 'omp' && (featureId === 'tasks' || featureId === 'agent_teams')) {
93
+ lines.push(' OMP native leaf tasks use AIWG workspace admission limits and verified child results; nested requests share the same scheduler.');
94
+ lines.push(' example: aiwg team run --provider omp --body-file tasks.json');
95
+ }
96
+ else if (feat?.native_example)
86
97
  lines.push(` example: ${feat.native_example}`);
87
98
  }
88
99
  else if (isExternalStrategy(emulation)) {
@@ -195,7 +206,7 @@ async function handleSteward(args, ctx) {
195
206
  aiwg steward permissions migrate --apply Back up and atomically normalize config
196
207
 
197
208
  Providers:
198
- claude-code, codex, copilot, cursor, factory, opencode, pi, warp, windsurf, hermes, openclaw
209
+ antigravity (agy), claude-code, codex, copilot, cursor, factory, opencode, pi, omp, warp, windsurf, hermes, openclaw
199
210
 
200
211
  Features:
201
212
  cron, agent_teams, tasks, mcp, behaviors, mission_control, daemon
@@ -689,6 +689,17 @@ export const removeHandler = {
689
689
  category: "framework",
690
690
  aliases: [],
691
691
  async execute(ctx) {
692
+ // Explicit provider removal is separate from framework removal. The native
693
+ // adapter validates receipt hashes and preserves operator modifications.
694
+ const nativeRemovalProvider = parseRemoveProvider(ctx.args);
695
+ if (firstRemovePositional(ctx.args) === 'omp' && nativeRemovalProvider.provider === 'omp') {
696
+ const { uninstall } = await import('../../../tools/agents/providers/omp.mjs');
697
+ const { getProjectDir } = await import('../../config/aiwg-config.js');
698
+ const dryRun = ctx.args.includes('--dry-run');
699
+ const scope = ctx.args.includes('--user') || isScopeUser(ctx.args) ? 'user' : 'project';
700
+ const count = uninstall(getProjectDir({ cwd: ctx.cwd }, ctx.args), { dryRun, scope });
701
+ return { exitCode: 0, message: `${dryRun ? 'Would remove' : 'Removed'} ${count} unchanged OMP-owned files; operator files preserved.` };
702
+ }
692
703
  // #1156 Phase 1 — `--scope user` / `--user`: revert the user-scope mirror
693
704
  // for the given framework. Independent of any project; reads the per-user
694
705
  // registry at ~/.aiwg/installed.json to find what was deployed, deletes
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Team Command Handler
3
3
  *
4
- * Extends Claude Code's native agent teams feature to all 9 AIWG providers.
4
+ * Routes declared teams across AIWG providers, including bounded native OMP tasks.
5
5
  * Provides a provider-agnostic abstraction for declaring, deploying, and
6
6
  * invoking agent teams. On Claude Code, delegates to native team mechanisms.
7
- * On all other providers, emulates via aiwg mc (Mission Control) orchestration.
7
+ * OMP executes explicit task files; other providers use aiwg mc orchestration.
8
8
  *
9
9
  * Subcommands: run, list, info
10
10
  *
@@ -12,13 +12,15 @@
12
12
  */
13
13
  import * as ui from '../ui.js';
14
14
  import { promises as fs } from 'node:fs';
15
- import { join, basename } from 'node:path';
15
+ import { join, basename, resolve } from 'node:path';
16
+ import { pathToFileURL } from 'node:url';
16
17
  import { projectAiwgPath } from '../../config/project-artifacts.js';
18
+ import { normalizeProviderDefinitionId } from '../../providers/provider-definitions.js';
17
19
  // ── Provider Detection ───────────────────────────────────────
18
20
  function detectProvider(args) {
19
21
  const providerFlag = parseFlag(args, '--provider');
20
22
  if (providerFlag)
21
- return providerFlag;
23
+ return normalizeProviderDefinitionId(providerFlag) ?? providerFlag;
22
24
  // Claude Code sets CLAUDE_CODE_VERSION; API key presence is secondary heuristic
23
25
  const isClaudeCode = process.env.CLAUDE_CODE_VERSION !== undefined ||
24
26
  process.env.ANTHROPIC_API_KEY !== undefined;
@@ -103,7 +105,57 @@ async function listAllTeams(frameworkRoot, cwd) {
103
105
  return teams;
104
106
  }
105
107
  // ── Subcommand: run ──────────────────────────────────────────
108
+ /** Public OMP dispatch delegates to the same bounded native runtime used by conformance. */
109
+ async function teamRunOmp(ctx) {
110
+ const allowed = new Set(['--provider', '--body-file', '--cwd', '--output-root', '--max-parallel', '--model', '--profile']);
111
+ const values = {};
112
+ for (let i = 0; i < ctx.args.length; i++) {
113
+ const flag = ctx.args[i];
114
+ if (flag === '--json')
115
+ continue;
116
+ if (!allowed.has(flag) || !ctx.args[i + 1] || ctx.args[i + 1].startsWith('--')) {
117
+ ui.error('OMP usage: aiwg team run --provider omp --body-file tasks.json [--cwd DIR] [--output-root DIR] [--max-parallel N] [--model provider/model] [--profile NAME]');
118
+ return { exitCode: 1 };
119
+ }
120
+ values[flag] = ctx.args[++i];
121
+ }
122
+ if (!values['--body-file']) {
123
+ ui.error('OMP native team dispatch requires --body-file tasks.json with explicit task ownership and tools.');
124
+ return { exitCode: 1 };
125
+ }
126
+ const maxParallel = values['--max-parallel'] === undefined ? 4 : Number(values['--max-parallel']);
127
+ if (!Number.isInteger(maxParallel) || maxParallel < 1) {
128
+ ui.error('OMP --max-parallel must be a positive integer.');
129
+ return { exitCode: 1 };
130
+ }
131
+ const controller = new AbortController();
132
+ const abort = () => controller.abort();
133
+ process.once('SIGINT', abort);
134
+ process.once('SIGTERM', abort);
135
+ try {
136
+ const payload = JSON.parse(await fs.readFile(resolve(ctx.cwd, values['--body-file']), 'utf8'));
137
+ const { runOmpTeam } = await import(pathToFileURL(join(ctx.frameworkRoot, 'tools/providers/omp-teams.mjs')).href);
138
+ const result = await runOmpTeam({
139
+ tasks: payload.tasks,
140
+ cwd: values['--cwd'] ? resolve(ctx.cwd, values['--cwd']) : ctx.cwd,
141
+ outputDir: values['--output-root'] ? resolve(ctx.cwd, values['--output-root']) : undefined,
142
+ maxParallel, model: values['--model'], profile: values['--profile'], signal: controller.signal,
143
+ });
144
+ console.log(JSON.stringify(result, null, 2));
145
+ return { exitCode: result.results.every((task) => task.status === 'completed') ? 0 : 1 };
146
+ }
147
+ catch (error) {
148
+ ui.error(error instanceof SyntaxError ? 'OMP task body is invalid JSON.' : error instanceof Error ? error.message : 'OMP team dispatch failed.');
149
+ return { exitCode: 1 };
150
+ }
151
+ finally {
152
+ process.removeListener('SIGINT', abort);
153
+ process.removeListener('SIGTERM', abort);
154
+ }
155
+ }
106
156
  async function teamRun(ctx) {
157
+ if (['omp', 'oh-my-pi'].includes(detectProvider(ctx.args)))
158
+ return teamRunOmp(ctx);
107
159
  const positional = getPositionalArgs(ctx.args);
108
160
  const slug = positional[0];
109
161
  if (!slug) {
@@ -186,7 +238,7 @@ async function teamList(ctx) {
186
238
  ui.info('No teams found. Deploy the sdlc-complete framework with: aiwg use sdlc');
187
239
  return { exitCode: 0 };
188
240
  }
189
- const backend = isNativeTeamsProvider(provider)
241
+ const backend = ['omp', 'oh-my-pi'].includes(provider) ? 'native (Oh My Pi)' : isNativeTeamsProvider(provider)
190
242
  ? 'native (Claude Code)'
191
243
  : `aiwg mc emulation (${provider})`;
192
244
  ui.blank();
@@ -277,21 +329,30 @@ function showTeamHelp() {
277
329
  ${ui.bold('Usage:')} aiwg team <subcommand> [options]
278
330
 
279
331
  ${ui.bold('Subcommands:')}
280
- run <name> Execute a team (native on Claude Code, aiwg mc on others)
332
+ run <name> Run a declared team (Claude native guidance or aiwg mc)
333
+ run --provider omp --body-file tasks.json Execute bounded native OMP tasks
281
334
  list List available teams
282
335
  info <name> Show team definition and agent roster
283
336
 
284
337
  ${ui.bold('Options:')}
285
- --provider <p> Override provider: claude|warp|copilot|cursor|windsurf|opencode|factory|codex|openclaw
338
+ --provider <p> Override provider: antigravity|agy|claude|warp|copilot|cursor|windsurf|opencode|factory|codex|openclaw|omp|oh-my-pi
286
339
  --objective "<text>" Set objective passed to mc dispatch agents
340
+ --body-file <file> OMP task JSON with explicit ownership and tools
341
+ --cwd <dir> OMP working directory (defaults to current workspace)
342
+ --output-root <dir> OMP result and control artifact directory
343
+ --max-parallel <n> OMP requested worker cap (workspace ceiling still applies)
344
+ --model <id> OMP coordinator/worker model selector
345
+ --profile <name> OMP native profile
287
346
  --json Machine-readable output
288
347
 
289
348
  ${ui.bold('Provider Routing:')}
290
349
  Claude Code Native agent team dispatch (@agent-name invocation)
350
+ Oh My Pi Bounded native task execution from --body-file
291
351
  All others aiwg mc emulation (Mission Control sequential/parallel dispatch)
292
352
 
293
353
  ${ui.bold('Examples:')}
294
354
  aiwg team run sdlc-review
355
+ aiwg team run --provider omp --body-file tasks.json
295
356
  aiwg team run sdlc-review --provider cursor --objective "Phase gate review"
296
357
  aiwg team run security-review --objective "Pre-release audit"
297
358
  aiwg team list