@aiwg/cli 2026.9.2 → 2026.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/agentic/code/providers/antigravity/provider-contract.v1.json +121 -0
  2. package/agentic/code/providers/capability-matrix.yaml +87 -1
  3. package/agentic/code/providers/model-capabilities.v1.json +31 -0
  4. package/agentic/code/providers/model-catalog.v1.json +29 -0
  5. package/agentic/code/providers/omp/README.md +58 -0
  6. package/agentic/code/providers/omp/aiwg-bridge.ts +52 -0
  7. package/dist/src/agents/agent-deployer.js +18 -0
  8. package/dist/src/agents/agent-packager.js +25 -0
  9. package/dist/src/artifacts/backends/sqlite-backend.js +18 -10
  10. package/dist/src/artifacts/query-engine.js +30 -0
  11. package/dist/src/cli/agent-spawn.js +13 -2
  12. package/dist/src/cli/handlers/help.js +3 -1
  13. package/dist/src/cli/handlers/init.js +2 -0
  14. package/dist/src/cli/handlers/models.js +1 -1
  15. package/dist/src/cli/handlers/runtime-info.js +8 -1
  16. package/dist/src/cli/handlers/session.js +5 -4
  17. package/dist/src/cli/handlers/sessions.js +26 -9
  18. package/dist/src/cli/handlers/setup.js +9 -2
  19. package/dist/src/cli/handlers/steward.js +13 -2
  20. package/dist/src/cli/handlers/subcommands.js +11 -0
  21. package/dist/src/cli/handlers/team.js +68 -7
  22. package/dist/src/cli/handlers/use.js +121 -9
  23. package/dist/src/cli/scope-resolver.js +7 -0
  24. package/dist/src/config/aiwg-config.js +1 -0
  25. package/dist/src/dataset/fortemi-live-qualification.d.ts +53 -0
  26. package/dist/src/dataset/fortemi-live-qualification.js +297 -0
  27. package/dist/src/dataset/index.d.ts +1 -0
  28. package/dist/src/dataset/index.js +1 -0
  29. package/dist/src/mcp/cli.mjs +30 -1
  30. package/dist/src/mcp/omp-config.mjs +128 -0
  31. package/dist/src/mcp/registry.js +45 -5
  32. package/dist/src/mcp/registry.mjs +29 -6
  33. package/dist/src/models/model-capabilities.v1.json +31 -0
  34. package/dist/src/models/model-catalog.v1.json +29 -0
  35. package/dist/src/models/model-discovery.js +46 -5
  36. package/dist/src/models/provider-policy.js +5 -3
  37. package/dist/src/plugin/skill-command-translator.js +2 -0
  38. package/dist/src/providers/capability-matrix.yaml +87 -1
  39. package/dist/src/providers/omp-agent.mjs +40 -0
  40. package/dist/src/providers/omp-diagnostics.mjs +15 -0
  41. package/dist/src/providers/omp-paths.mjs +38 -0
  42. package/dist/src/providers/provider-definitions.js +83 -0
  43. package/dist/src/providers/provider-definitions.mjs +25 -1
  44. package/dist/src/providers/provider-inventory.js +2 -0
  45. package/dist/src/sessions/adapters/omp.js +203 -0
  46. package/dist/src/sessions/batch-import.js +7 -0
  47. package/dist/src/sessions/contracts.js +1 -1
  48. package/dist/src/sessions/importer.js +4 -3
  49. package/dist/src/sessions/index.js +1 -0
  50. package/dist/src/sessions/readers.js +4 -3
  51. package/dist/src/sessions/workspace-discovery.js +12 -2
  52. package/dist/src/skills/deployer.js +21 -1
  53. package/dist/src/smiths/agentsmith/generator.js +1 -0
  54. package/dist/src/smiths/context-pipeline/parallelism-section.js +2 -0
  55. package/dist/src/smiths/context-pipeline/provider-policy.js +2 -2
  56. package/dist/src/smiths/context-pipeline/workspace-context.js +2 -2
  57. package/dist/src/storage/backends/fortemi.js +142 -17
  58. package/dist/src/storage/fortemi-qualification-receipt.js +206 -0
  59. package/dist/src/storage/fortemi-qualification.js +67 -6
  60. package/dist/src/storage/index.js +1 -0
  61. package/package.json +2 -1
  62. package/schemas/dataset/fortemi-live-qualification-receipt.v1.schema.json +132 -0
  63. package/tools/agents/deploy-agents.mjs +6 -3
  64. package/tools/agents/providers/antigravity.mjs +147 -0
  65. package/tools/agents/providers/omp.d.mts +4 -0
  66. package/tools/agents/providers/omp.mjs +256 -0
  67. package/tools/providers/antigravity-transport.mjs +124 -0
@@ -12,6 +12,7 @@ const ArtifactPathsSchema = z.object({
12
12
  });
13
13
  const ProviderDefinitionSchema = z.object({
14
14
  id: z.enum([
15
+ 'antigravity',
15
16
  'claude',
16
17
  'codex',
17
18
  'copilot',
@@ -22,6 +23,7 @@ const ProviderDefinitionSchema = z.object({
22
23
  'openclaw',
23
24
  'openhuman',
24
25
  'pi',
26
+ 'omp',
25
27
  'warp',
26
28
  'windsurf',
27
29
  'generic',
@@ -123,6 +125,7 @@ const ProviderDefinitionSchema = z.object({
123
125
  }),
124
126
  });
125
127
  export const PROVIDER_IDS = [
128
+ 'antigravity',
126
129
  'claude',
127
130
  'codex',
128
131
  'copilot',
@@ -133,12 +136,24 @@ export const PROVIDER_IDS = [
133
136
  'openclaw',
134
137
  'openhuman',
135
138
  'pi',
139
+ 'omp',
136
140
  'warp',
137
141
  'windsurf',
138
142
  'generic',
139
143
  ];
140
144
  const VERIFIED_ON = '2026-07-21';
141
145
  const CONTEXT_CONTRACTS = {
146
+ antigravity: {
147
+ startupFiles: ['AGENTS.md', 'GEMINI.md'],
148
+ precedence: ['provider/system', 'project AGENTS.md or GEMINI.md', 'nested project context when selected by the CLI'],
149
+ loadMode: 'prose-directive', includeSyntax: null, configRegistration: null,
150
+ bootstrapTargets: ['AGENTS.md'], maxContextBytes: null, recommendedMaxLines: null, nestedContext: true, support: 'supported',
151
+ verification: {
152
+ method: 'official Antigravity CLI documentation and sanitized 1.1.26 help evidence',
153
+ source: 'https://antigravity.google/docs/cli/overview/',
154
+ lastVerified: '2026-09-04',
155
+ },
156
+ },
142
157
  claude: {
143
158
  startupFiles: ['CLAUDE.md', '.claude/CLAUDE.md'], precedence: ['provider/system', 'nested CLAUDE.md', 'root CLAUDE.md'],
144
159
  loadMode: 'native-include', includeSyntax: '@WORKSPACE.md\n@AIWG.md', configRegistration: null,
@@ -193,6 +208,17 @@ const CONTEXT_CONTRACTS = {
193
208
  bootstrapTargets: ['AGENTS.md'], maxContextBytes: null, recommendedMaxLines: null, nestedContext: false, support: 'degraded',
194
209
  verification: { method: 'AIWG mixed-scope adapter contract; host loading remains capability-dependent', source: 'agentic/code/providers/capability-matrix.yaml', lastVerified: VERIFIED_ON },
195
210
  },
211
+ omp: {
212
+ startupFiles: ['.omp/AGENTS.md', 'AGENTS.md'],
213
+ precedence: ['provider/system', 'native nearest nonempty .omp', 'compatibility context ordered by depth; exact paragraph deduplication'],
214
+ loadMode: 'native-include', includeSyntax: '@<relative-path>', configRegistration: null,
215
+ bootstrapTargets: ['.omp/AGENTS.md'], maxContextBytes: null, recommendedMaxLines: null, nestedContext: true, support: 'supported',
216
+ verification: {
217
+ method: 'OMP 18.1.10 source and live context import smoke',
218
+ source: 'https://github.com/can1357/oh-my-pi/blob/5964a0f7649275bcde818f20073193fd032451f2/packages/coding-agent/src/system-prompt.ts#L451',
219
+ lastVerified: '2026-09-04',
220
+ },
221
+ },
196
222
  pi: {
197
223
  startupFiles: ['AGENTS.override.md', 'AGENTS.md', 'CLAUDE.md'],
198
224
  precedence: ['provider/system', 'root-to-cwd context chain', 'AGENTS.override.md supersedes same-directory AGENTS.md and CLAUDE.md'],
@@ -223,6 +249,42 @@ const CONTEXT_CONTRACTS = {
223
249
  },
224
250
  };
225
251
  const BUILT_IN_SEEDS = [
252
+ {
253
+ id: 'antigravity',
254
+ displayName: 'Google Antigravity CLI',
255
+ aliases: ['agy'],
256
+ status: 'experimental',
257
+ builtIn: true,
258
+ surfaces: {
259
+ primary: 'antigravity',
260
+ compatibility: ['agy'],
261
+ precedence: ['AGENTS.md', 'GEMINI.md', '.agents/agents/', '.agents/skills/'],
262
+ related: [],
263
+ },
264
+ detection: { env: [], process: ['agy'], capabilityId: 'antigravity' },
265
+ paths: {
266
+ deployTarget: 'project',
267
+ artifacts: {
268
+ agents: '.agents/agents', commands: null, skills: '.agents/.aiwg/skills', rules: null, behaviors: null,
269
+ },
270
+ kernelSkills: '.agents/skills',
271
+ contextDiscovery: { agents: '.agents/agents', skills: '.agents/skills', rules: null, behaviors: null },
272
+ configFile: 'AGENTS.md',
273
+ contextFiles: { aiwgMd: true, agentsMd: true, claudeMdHook: false, hookFile: null, contextFile: 'AGENTS.md' },
274
+ },
275
+ smithPaths: {
276
+ agents: '.agents/agents', commands: null, skills: '.agents/skills', rules: null,
277
+ fileExtension: '.md', configFile: 'AGENTS.md', aggregated: false,
278
+ },
279
+ skillNamespace: {
280
+ deploymentGroup: 'deep-recursion', pathType: 'project', skillsBaseDir: '.agents/skills', subdirLayout: true,
281
+ },
282
+ adapters: {
283
+ agentFormat: 'antigravity-markdown', hookBridge: null, mcpInjection: 'antigravity',
284
+ contextAggregation: 'agents-md', ruleFormat: null,
285
+ },
286
+ matrixRef: 'antigravity',
287
+ },
226
288
  {
227
289
  id: 'claude',
228
290
  displayName: 'Claude Code',
@@ -669,6 +731,27 @@ const BUILT_IN_SEEDS = [
669
731
  },
670
732
  matrixRef: 'openhuman',
671
733
  },
734
+ {
735
+ id: 'omp',
736
+ aliases: ['oh-my-pi'],
737
+ builtIn: true,
738
+ surfaces: {
739
+ primary: 'omp', compatibility: ['oh-my-pi'],
740
+ precedence: ['.omp/AGENTS.md', 'AGENTS.md', '.agents/skills/', '.omp/skills/', '.omp/prompts/'], related: [],
741
+ },
742
+ detection: { env: [], process: ['omp', '@oh-my-pi/pi-coding-agent'], capabilityId: 'omp' },
743
+ paths: {
744
+ artifacts: { agents: '.omp/agents', commands: '.omp/prompts', skills: '.agents/skills', rules: '.omp/rules', behaviors: '.omp/extensions' },
745
+ kernelSkills: '.agents/skills',
746
+ contextDiscovery: { agents: '.omp/agents', skills: '.agents/skills', rules: '.omp/rules', behaviors: '.omp/extensions' },
747
+ configFile: '.omp/AGENTS.md',
748
+ contextFiles: { aiwgMd: true, agentsMd: false, claudeMdHook: false, hookFile: '.omp/AGENTS.md', contextFile: '.omp/AGENTS.md' },
749
+ },
750
+ smithPaths: { agents: '.omp/agents', commands: '.omp/prompts', skills: '.agents/skills', rules: '.omp/rules', fileExtension: '.md', configFile: '.omp/AGENTS.md', aggregated: false },
751
+ skillNamespace: { deploymentGroup: 'one-level', pathType: 'project', skillsBaseDir: '.omp/skills', subdirLayout: false },
752
+ adapters: { agentFormat: 'omp-markdown', hookBridge: 'omp', mcpInjection: 'omp', contextAggregation: 'agents-md', ruleFormat: 'omp-markdown' },
753
+ matrixRef: 'omp',
754
+ },
672
755
  {
673
756
  id: 'pi',
674
757
  aliases: ['pi-coding-agent'],
@@ -1,7 +1,24 @@
1
+ import { resolveOmpPaths } from './omp-paths.mjs';
1
2
  import { homedir } from 'os';
2
3
  import { resolve } from 'path';
3
4
 
4
5
  const MCP_INJECTION_DEFINITIONS = [
6
+ {
7
+ id: 'antigravity', aliases: ['agy'],
8
+ mcp: { providerId: 'antigravity', includeInSupportedProviders: true, configFormat: 'json',
9
+ serverConfigFormat: 'antigravity', serversKey: 'mcpServers',
10
+ configPath: { scope: 'project', path: '.agents/mcp_config.json' },
11
+ supportsEphemeral: false,
12
+ unsupportedReason: 'Antigravity uses project or user persistent MCP configuration; temporary injection is not qualified.' },
13
+ },
14
+ {
15
+ id: 'omp', aliases: ['oh-my-pi'],
16
+ mcp: { providerId: 'omp', includeInSupportedProviders: true, configFormat: 'json',
17
+ serverConfigFormat: 'standard', serversKey: 'mcpServers',
18
+ configPath: { scope: 'project', path: '.omp/mcp.json' },
19
+ supportsEphemeral: false,
20
+ unsupportedReason: 'OMP uses owned persistent MCP configuration; temporary injection is not supported.' },
21
+ },
5
22
  {
6
23
  id: 'claude',
7
24
  aliases: ['claude-code'],
@@ -147,7 +164,14 @@ export function listMcpInjectProviderIds() {
147
164
  .map((definition) => definition.providerId);
148
165
  }
149
166
 
150
- export function resolveMcpConfigPath(provider, projectDir = '.') {
167
+ export function resolveMcpConfigPath(provider, projectDir = '.', options = {}) {
168
+ if (normalizeRuntimeProviderId(provider) === 'antigravity' && options.scope === 'user') {
169
+ const home = process.env.HOME || process.env.USERPROFILE || homedir();
170
+ return resolve(home, '.gemini/config/mcp_config.json');
171
+ }
172
+ if (normalizeRuntimeProviderId(provider) === 'omp' && options.scope === 'user') {
173
+ return resolve(resolveOmpPaths(options).agentDir, 'mcp.json');
174
+ }
151
175
  const definition = getMcpInjectionDefinition(provider);
152
176
  if (!definition) return '';
153
177
 
@@ -5,6 +5,7 @@ import { readAiwgConfig } from '../config/aiwg-config.js';
5
5
  import { resolveActiveProvider } from '../cli/provider-resolution.js';
6
6
  import { listProviderDefinitions, normalizeProviderDefinitionId, resolveProviderPathValue, } from './provider-definitions.js';
7
7
  const PROVIDER_EXECUTABLES = {
8
+ antigravity: ['agy'],
8
9
  claude: ['claude'],
9
10
  codex: ['codex'],
10
11
  copilot: ['github-copilot-cli', 'copilot'],
@@ -15,6 +16,7 @@ const PROVIDER_EXECUTABLES = {
15
16
  openclaw: ['openclaw'],
16
17
  openhuman: ['openhuman'],
17
18
  pi: ['pi'],
19
+ omp: ['omp'],
18
20
  warp: ['warp'],
19
21
  windsurf: ['windsurf'],
20
22
  };
@@ -0,0 +1,203 @@
1
+ import { opendir } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import { z } from 'zod';
4
+ import { SessionContractError, } from '../contracts.js';
5
+ import { readBoundedJsonLines, streamBoundedJsonLines } from '../readers.js';
6
+ export const OMP_ADAPTER_VERSION = '1.0.0';
7
+ export const OMP_SOURCE_SCHEMA_VERSION = '3.0.0';
8
+ const Title = z.object({ type: z.literal('title'), v: z.literal(1), title: z.string(), source: z.enum(['auto', 'user']).optional(), updatedAt: z.string(), pad: z.string() });
9
+ const Header = z.object({ type: z.literal('session'), version: z.number().int(), id: z.string().min(1),
10
+ timestamp: z.string().datetime({ offset: true }), cwd: z.string(), parentSession: z.string().optional() }).passthrough();
11
+ const Entry = z.object({ type: z.string().min(1), id: z.string().min(1),
12
+ parentId: z.string().nullable(), timestamp: z.string().datetime({ offset: true }) }).passthrough();
13
+ export class OmpSessionAdapter {
14
+ limits;
15
+ maxFiles;
16
+ provider = 'omp';
17
+ sourceSchemaMajor = 3;
18
+ adapterVersion = OMP_ADAPTER_VERSION;
19
+ disposition = 'implemented';
20
+ supportedOperations = ['discover', 'inspect', 'stream'];
21
+ acquisitionModes = ['jsonl'];
22
+ constructor(limits, maxFiles = 10_000) {
23
+ this.limits = limits;
24
+ this.maxFiles = maxFiles;
25
+ }
26
+ async *discover(scope) {
27
+ if (!scope.allowedRoots.length)
28
+ throw new SessionContractError('SOURCE_NOT_AUTHORIZED', 'OMP discovery requires an authorized sessions root');
29
+ let count = 0;
30
+ for (const root of [...scope.allowedRoots].sort()) {
31
+ for await (const locator of jsonlFiles(resolve(root))) {
32
+ if (++count > this.maxFiles)
33
+ throw new SessionContractError('RESOURCE_LIMIT_EXCEEDED', 'OMP discovery file limit exceeded');
34
+ yield { provider: 'omp', locator, locatorClass: 'omp-session-v3-jsonl' };
35
+ }
36
+ }
37
+ }
38
+ async inspect(source) {
39
+ let input;
40
+ try {
41
+ input = await readBoundedJsonLines({ selectedPath: source.locator,
42
+ allowedRoots: source.authorizedScope.allowedRoots }, { consistency: 'provisional', limits: this.limits });
43
+ }
44
+ catch (error) {
45
+ throw normalizeAuthorizationError(error);
46
+ }
47
+ const header = parseHeader(input.records[titleOffset(input.records[0]) ? 1 : 0]?.value);
48
+ if (input.incompleteTail)
49
+ throw new SessionContractError('TRUNCATED_SOURCE', 'OMP session has a truncated JSONL tail');
50
+ return { sourceSchemaVersion: `${header.version}.0.0`, consistency: 'complete', operationalState: 'available' };
51
+ }
52
+ async *stream(source, cursor) {
53
+ let input;
54
+ try {
55
+ input = await streamBoundedJsonLines({ selectedPath: source.locator,
56
+ allowedRoots: source.authorizedScope.allowedRoots }, { consistency: 'provisional', limits: this.limits });
57
+ }
58
+ catch (error) {
59
+ throw normalizeAuthorizationError(error);
60
+ }
61
+ let sessionId = '';
62
+ let header = {};
63
+ let prefix = true;
64
+ const start = cursor?.value.replace(/^byte:/, '') ?? '0';
65
+ if (!/^\d+$/.test(start))
66
+ throw new SessionContractError('SCHEMA_DRIFT', 'invalid OMP cursor');
67
+ let end = 0;
68
+ const ids = new Set();
69
+ for await (const line of input) {
70
+ end = line.byteOffset + line.byteLength;
71
+ if (Number(start) > line.byteOffset && Number(start) < end) {
72
+ throw new SessionContractError('SCHEMA_DRIFT', 'OMP cursor is not a record boundary');
73
+ }
74
+ if (prefix) {
75
+ prefix = false;
76
+ if (titleOffset(line))
77
+ continue;
78
+ }
79
+ if (!sessionId) {
80
+ header = parseHeader(line.value);
81
+ sessionId = String(header.id);
82
+ continue;
83
+ }
84
+ const parsed = Entry.safeParse(line.value);
85
+ if (!parsed.success)
86
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP session entry is malformed');
87
+ const entry = parsed.data;
88
+ if (ids.has(entry.id))
89
+ throw new SessionContractError('DUPLICATE_NATIVE_ID', 'OMP session contains a duplicate entry id');
90
+ ids.add(entry.id);
91
+ if (end <= Number(start))
92
+ continue;
93
+ const message = object(entry.message);
94
+ const role = string(message.role) ?? roleFor(entry.type);
95
+ const sensitive = role === 'toolResult' || ['custom', 'custom_message', 'session_init', 'credential_pin'].includes(entry.type) || !KNOWN.has(entry.type);
96
+ const text = sensitive ? '[redacted provider content]' : entryText(entry, message);
97
+ yield { nativeSessionId: sessionId, nativeEventId: entry.id, sequence: line.sequence,
98
+ kind: kindFor(entry.type, role), role, toolName: sensitive ? string(message.toolName) : undefined,
99
+ toolCallId: sensitive ? string(message.toolCallId) : undefined,
100
+ occurredAt: entry.timestamp, text, model: string(entry.model) ?? string(message.model), sourceCursor: `byte:${end}`,
101
+ sourceBytes: line.byteLength, rawReference: { locatorClass: 'omp-session-v3-jsonl', offset: line.byteOffset },
102
+ activityBoundary: entry.type === 'compaction' ? 'continuation' : undefined,
103
+ activityBoundaryBasis: entry.type === 'compaction' ? 'pi-session:compaction' : undefined,
104
+ activityBoundaryConfidence: entry.type === 'compaction' ? 'high' : undefined,
105
+ extensions: { provenance: { acquisition: 'omp-session-v3', parentId: entry.parentId, parentSession: header.parentSession, previousSessionFiles: header.previousSessionFiles, cwd: header.cwd, additionalDirectories: header.additionalDirectories },
106
+ opaque: !KNOWN.has(entry.type), redacted: sensitive,
107
+ nativeType: entry.type, parentId: entry.parentId, ...metadata(entry, message) } };
108
+ }
109
+ if (!sessionId)
110
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP session header is missing');
111
+ if (Number(start) > end)
112
+ throw new SessionContractError('SCHEMA_DRIFT', 'OMP cursor exceeds source size');
113
+ if (input.incompleteTail)
114
+ throw new SessionContractError('TRUNCATED_SOURCE', 'OMP session has a truncated JSONL tail');
115
+ }
116
+ async mutablePrefixBytes(source) {
117
+ const input = await streamBoundedJsonLines({ selectedPath: source.locator, allowedRoots: source.authorizedScope.allowedRoots }, { consistency: 'provisional', limits: this.limits });
118
+ for await (const line of input)
119
+ return titleOffset(line);
120
+ return 0;
121
+ }
122
+ }
123
+ const KNOWN = new Set(['message', 'thinking_level_change', 'model_change', 'compaction',
124
+ 'branch_summary', 'custom', 'label', 'session_info', 'custom_message', 'model_usage', 'title_change', 'service_tier_change', 'reset_boundary', 'ttsr_injection', 'credential_pin', 'session_init', 'mode_change']);
125
+ function parseHeader(value) {
126
+ const parsed = Header.safeParse(value);
127
+ if (!parsed.success)
128
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP session header is malformed');
129
+ if (parsed.data.version !== 3)
130
+ throw new SessionContractError('UNKNOWN_SCHEMA_MAJOR', `unsupported OMP session version: ${parsed.data.version}`);
131
+ return parsed.data;
132
+ }
133
+ function object(value) { return value && typeof value === 'object' ? value : {}; }
134
+ function string(value) { return typeof value === 'string' && value ? value : undefined; }
135
+ function roleFor(type) { return type === 'compaction' || type === 'branch_summary' ? 'system' : undefined; }
136
+ function kindFor(type, role) { return type === 'message' ? `message.${role ?? 'unknown'}` : `omp.${type}`; }
137
+ function entryText(entry, message) {
138
+ const value = entry.type === 'message' ? message.content : entry.summary ?? entry.title ?? entry.name ?? entry.label ?? '';
139
+ if (typeof value === 'string')
140
+ return value;
141
+ if (Array.isArray(value))
142
+ return value.flatMap(part => typeof part === 'string' ? part : string(object(part).text) ?? []).join('\n');
143
+ return '';
144
+ }
145
+ async function* jsonlFiles(root) {
146
+ let directory;
147
+ try {
148
+ directory = await opendir(root);
149
+ }
150
+ catch {
151
+ return;
152
+ }
153
+ for await (const entry of directory) {
154
+ const path = resolve(root, entry.name);
155
+ if (entry.isDirectory())
156
+ yield* jsonlFiles(path);
157
+ else if (entry.isFile() && entry.name.endsWith('.jsonl'))
158
+ yield path;
159
+ }
160
+ }
161
+ function normalizeAuthorizationError(error) {
162
+ if (error instanceof SessionContractError && (error.code === 'SOURCE_OUTSIDE_ALLOWED_ROOT'
163
+ || error.code === 'SOURCE_SYMLINK' || error.code === 'SOURCE_NOT_REGULAR_FILE')) {
164
+ return new SessionContractError('SOURCE_NOT_AUTHORIZED', 'OMP source is not an authorized regular file');
165
+ }
166
+ return error;
167
+ }
168
+ function titleOffset(line) {
169
+ if (object(line?.value).type !== 'title')
170
+ return 0;
171
+ if (!Title.safeParse(line?.value).success || line?.byteLength !== 256) {
172
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP title slot is malformed');
173
+ }
174
+ return 256;
175
+ }
176
+ function metadata(entry, message) {
177
+ const result = {};
178
+ for (const key of ['fromId', 'firstKeptEntryId', 'providerReplayThroughEntryId', 'tokensBefore', 'tokensAfter', 'method', 'role', 'resolvedModelIsFallback', 'purpose', 'provider', 'api', 'stopReason']) {
179
+ if (['string', 'number', 'boolean'].includes(typeof entry[key]))
180
+ result[key] = entry[key];
181
+ }
182
+ const usage = object(entry.usage ?? message.usage);
183
+ const numbers = Object.fromEntries(Object.entries(usage).filter(([, v]) => typeof v === 'number' && Number.isFinite(v)));
184
+ const cost = Object.fromEntries(Object.entries(object(usage.cost)).filter(([, v]) => typeof v === 'number' && Number.isFinite(v)));
185
+ if (Object.keys(numbers).length || Object.keys(cost).length)
186
+ result.usage = { ...numbers, cost };
187
+ return result;
188
+ }
189
+ /** Read only the bounded native preamble; never infer OMP from version alone. */
190
+ export async function readOmpSessionHeader(source) {
191
+ const input = await streamBoundedJsonLines({ selectedPath: source.locator, allowedRoots: source.authorizedScope.allowedRoots }, { consistency: 'provisional', limits: { maxRecords: 2, maxRecordBytes: 1024 * 1024 } });
192
+ let first = true;
193
+ for await (const line of input) {
194
+ if (first) {
195
+ first = false;
196
+ if (titleOffset(line))
197
+ continue;
198
+ }
199
+ return parseHeader(line.value);
200
+ }
201
+ throw new SessionContractError('MALFORMED_SOURCE', 'OMP header is missing');
202
+ }
203
+ //# sourceMappingURL=omp.js.map
@@ -1,3 +1,4 @@
1
+ import { OmpSessionAdapter, OMP_ADAPTER_VERSION } from './adapters/omp.js';
1
2
  import { stat } from 'node:fs/promises';
2
3
  import { CLAUDE_ADAPTER_VERSION, ClaudeSessionAdapter, } from './adapters/claude.js';
3
4
  import { CODEX_ADAPTER_VERSION, CodexSessionAdapter, } from './adapters/codex.js';
@@ -197,6 +198,8 @@ async function assertManifestSourceUnchanged(source) {
197
198
  }
198
199
  }
199
200
  function adapterFor(provider) {
201
+ if (provider === 'omp')
202
+ return new OmpSessionAdapter();
200
203
  if (provider === 'claude')
201
204
  return new ClaudeSessionAdapter();
202
205
  if (provider === 'codex')
@@ -226,6 +229,8 @@ async function sessionSource(selected, adapter) {
226
229
  });
227
230
  }
228
231
  function adapterVersion(provider) {
232
+ if (provider === 'omp')
233
+ return OMP_ADAPTER_VERSION;
229
234
  if (provider === 'claude')
230
235
  return CLAUDE_ADAPTER_VERSION;
231
236
  if (provider === 'codex')
@@ -237,6 +242,8 @@ function adapterVersion(provider) {
237
242
  return '1.0.0';
238
243
  }
239
244
  function providerProfile(provider, locatorClass) {
245
+ if (provider === 'omp')
246
+ return 'native-title-slot-v3';
240
247
  if (provider === 'claude')
241
248
  return 'documented-local-jsonl';
242
249
  if (provider === 'codex')
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
  export const SESSION_CONTRACT_VERSION = '1.0.0';
4
4
  export const SESSION_PROVIDER_IDS = [
5
5
  'claude', 'codex', 'copilot', 'cursor', 'factory', 'hermes',
6
- 'opencode', 'openclaw', 'openhuman', 'pi', 'warp', 'devin-desktop', 'generic',
6
+ 'opencode', 'openclaw', 'openhuman', 'pi', 'omp', 'warp', 'devin-desktop', 'generic',
7
7
  ];
8
8
  export const SessionProviderIdSchema = z.enum(SESSION_PROVIDER_IDS);
9
9
  export const SESSION_PROVIDER_ALIASES = Object.freeze({
@@ -22,7 +22,7 @@ export class IncrementalSessionImporter {
22
22
  this.repository = repository;
23
23
  }
24
24
  async import(request) {
25
- assertSupportedSchemaMajor(request.source.sourceSchemaVersion);
25
+ assertSupportedSchemaMajor(request.source.sourceSchemaVersion, request.adapter.sourceSchemaMajor ?? 1);
26
26
  if (request.inactivityThresholdMs !== undefined
27
27
  && (!Number.isFinite(request.inactivityThresholdMs) || request.inactivityThresholdMs < 0)) {
28
28
  throw new SessionContractError('INVALID_ARGUMENT', 'session inactivity threshold must be a non-negative duration');
@@ -435,6 +435,7 @@ async function sourceContinuity(request, previous) {
435
435
  selectedPath: request.selectedSource.locator,
436
436
  allowedRoots: request.selectedSource.authorizedScope.allowedRoots,
437
437
  };
438
+ const skipPrefixBytes = await request.adapter.mutablePrefixBytes?.(request.selectedSource) ?? 0;
438
439
  const metadata = await fingerprintSourcePrefix(authorization, 0);
439
440
  if (previous?.sourceSize !== undefined) {
440
441
  if (metadata.size < previous.sourceSize) {
@@ -444,12 +445,12 @@ async function sourceContinuity(request, previous) {
444
445
  && previous.sourceFileIdentity !== metadata.fileIdentity) {
445
446
  throw new SessionContractError('SCHEMA_DRIFT', 'session source file generation was replaced or rotated');
446
447
  }
447
- const priorPrefix = await fingerprintSourcePrefix(authorization, previous.sourceSize);
448
+ const priorPrefix = await fingerprintSourcePrefix(authorization, previous.sourceSize, skipPrefixBytes);
448
449
  if (previous.prefixDigest && priorPrefix.digest !== previous.prefixDigest) {
449
450
  throw new SessionContractError('SCHEMA_DRIFT', 'session source prefix was rewritten before its durable checkpoint');
450
451
  }
451
452
  }
452
- const current = await fingerprintSourcePrefix(authorization, metadata.size);
453
+ const current = await fingerprintSourcePrefix(authorization, metadata.size, skipPrefixBytes);
453
454
  const generation = previous?.sourceGeneration ?? sha256([
454
455
  sourceGenerationDigest(request),
455
456
  metadata.fileIdentity,
@@ -31,4 +31,5 @@ export * from './adapters/openhuman.js';
31
31
  export * from './adapters/pi.js';
32
32
  export * from './adapters/warp.js';
33
33
  export * from './adapters/windsurf.js';
34
+ export * from './adapters/omp.js';
34
35
  //# sourceMappingURL=index.js.map
@@ -132,16 +132,17 @@ export async function fingerprintSourceFile(authorization) {
132
132
  }
133
133
  return { digest: `sha256:${hash.digest('hex')}`, size: allowed.size };
134
134
  }
135
- export async function fingerprintSourcePrefix(authorization, length) {
135
+ export async function fingerprintSourcePrefix(authorization, length, skipPrefixBytes = 0) {
136
136
  const allowed = await authorizeSourceFile(authorization);
137
- if (!Number.isSafeInteger(length) || length < 0 || length > allowed.size) {
137
+ if (!Number.isSafeInteger(length) || length < 0 || length > allowed.size
138
+ || !Number.isSafeInteger(skipPrefixBytes) || skipPrefixBytes < 0 || skipPrefixBytes > allowed.size) {
138
139
  throw new SessionContractError('SCHEMA_DRIFT', 'checkpoint source position is beyond the current source size');
139
140
  }
140
141
  const handle = await open(allowed.canonicalPath, 'r');
141
142
  const hash = createHash('sha256');
142
143
  try {
143
144
  const buffer = Buffer.allocUnsafe(64 * 1024);
144
- let position = 0;
145
+ let position = skipPrefixBytes;
145
146
  while (position < length) {
146
147
  const result = await handle.read(buffer, 0, Math.min(buffer.length, length - position), position);
147
148
  if (result.bytesRead === 0)
@@ -7,6 +7,8 @@ import { ClaudeSessionAdapter } from './adapters/claude.js';
7
7
  import { CodexSessionAdapter } from './adapters/codex.js';
8
8
  import { CursorSessionAdapter } from './adapters/cursor.js';
9
9
  import { FactorySessionAdapter } from './adapters/factory.js';
10
+ import { OmpSessionAdapter, readOmpSessionHeader } from './adapters/omp.js';
11
+ import { resolveOmpPaths } from '../providers/omp-paths.mjs';
10
12
  import { PiSessionAdapter } from './adapters/pi.js';
11
13
  import { SESSION_PROVIDER_IDS, sha256, } from './contracts.js';
12
14
  import { redactSourceLocator } from './discovery.js';
@@ -23,6 +25,9 @@ export async function discoverWorkspaceHistories(options) {
23
25
  const keyWithLeadingDash = workspaceKey(workspacePath, true);
24
26
  const keyWithoutLeadingDash = workspaceKey(workspacePath, false);
25
27
  const discoverable = [
28
+ { provider: 'omp', adapter: new OmpSessionAdapter(), roots: options.ompRoot
29
+ ? [resolve(options.ompRoot)] : options.providerHome
30
+ ? [resolveOmpPaths({ home: resolve(options.providerHome), cwd: workspacePath }).sessionsDir] : [] },
26
31
  {
27
32
  provider: 'claude',
28
33
  adapter: new ClaudeSessionAdapter(),
@@ -70,12 +75,12 @@ export async function discoverWorkspaceHistories(options) {
70
75
  availableRoots.push(await canonicalPath(root));
71
76
  }
72
77
  if (availableRoots.length === 0) {
73
- const codexNeedsAuthorization = entry.provider === 'codex'
78
+ const codexNeedsAuthorization = (entry.provider === 'codex' || entry.provider === 'omp')
74
79
  && entry.roots.length === 0;
75
80
  reports.set(entry.provider, providerReport(entry.provider, codexNeedsAuthorization ? 'export-required' : 'unavailable', codexNeedsAuthorization ? 'manual-export' : 'discoverable', [], codexNeedsAuthorization
76
81
  ? 'SHARED_ROOT_AUTHORIZATION_REQUIRED'
77
82
  : 'PROVIDER_ROOT_UNAVAILABLE', codexNeedsAuthorization
78
- ? 'Pass --codex-root with an explicitly authorized Codex sessions or App Server export root.'
83
+ ? `Pass --${entry.provider}-root with an explicitly authorized sessions root.`
79
84
  : `No authorized ${entry.provider} workspace history root was found.`));
80
85
  continue;
81
86
  }
@@ -89,6 +94,9 @@ export async function discoverWorkspaceHistories(options) {
89
94
  if (entry.provider === 'codex'
90
95
  && !await codexSourceMatchesWorkspace(locator, workspacePath))
91
96
  continue;
97
+ const ompHeader = entry.provider === 'omp' ? await readOmpSessionHeader({ ...descriptor, sourceId: 'discovery', authorizedScope: scope }) : undefined;
98
+ if (ompHeader && resolve(ompHeader.cwd) !== workspacePath)
99
+ continue;
92
100
  const details = await stat(locator);
93
101
  const authorizedRoot = scope.allowedRoots.find((root) => locator === root || locator.startsWith(`${root}/`));
94
102
  if (!authorizedRoot)
@@ -102,6 +110,8 @@ export async function discoverWorkspaceHistories(options) {
102
110
  continue;
103
111
  seen.add(dedupeKey);
104
112
  const source = sourceFromDescriptor(descriptor, locator, authorizedRoot, details, fingerprint.digest);
113
+ if (ompHeader)
114
+ source.sourceId = sha256(['omp-native-source-v1', workspaceId, ompHeader.id].join('\0'));
105
115
  providerSources.push(source);
106
116
  candidates.push(source);
107
117
  }
@@ -289,6 +289,16 @@ function readDeploymentSidecar(targetPath, expectedName, expectedProvider) {
289
289
  return undefined;
290
290
  }
291
291
  }
292
+ /**
293
+ * Codex and Antigravity intentionally consume the same portable project skill
294
+ * surface. A projection written for either provider is managed ownership for
295
+ * the other when the desired payload is otherwise byte-identical.
296
+ */
297
+ function providersShareProjectionSurface(actual, expected) {
298
+ return actual === expected
299
+ || (actual === 'codex' && expected === 'antigravity')
300
+ || (actual === 'antigravity' && expected === 'codex');
301
+ }
292
302
  function buildProjectionPlan(record, options) {
293
303
  const policy = resolvePolicy(options.target, options);
294
304
  const targetPath = path.join(policy.root, record.name);
@@ -339,12 +349,15 @@ function isManagedTarget(targetPath, expectedName, expectedProvider) {
339
349
  try {
340
350
  const targetStat = fs.lstatSync(targetPath);
341
351
  const marker = path.join(targetPath, AGENT_SKILL_MANAGED_MARKER);
352
+ const sidecar = readDeploymentSidecar(targetPath, expectedName);
342
353
  return (targetStat.isDirectory()
343
354
  && !targetStat.isSymbolicLink()
344
355
  && fs.lstatSync(marker).isFile()
345
356
  && !fs.lstatSync(marker).isSymbolicLink()
346
357
  && fs.readFileSync(marker, 'utf8') === MARKER_CONTENT
347
- && readDeploymentSidecar(targetPath, expectedName, expectedProvider) !== undefined);
358
+ && sidecar !== undefined
359
+ && (expectedProvider === undefined
360
+ || providersShareProjectionSurface(sidecar.provider, expectedProvider)));
348
361
  }
349
362
  catch {
350
363
  return false;
@@ -381,6 +394,13 @@ function targetMatches(targetPath, desired, name, provider) {
381
394
  if (actual.size !== desired.length)
382
395
  return false;
383
396
  return desired.every((entry) => {
397
+ if (entry.kind === 'file'
398
+ && entry.relativePath === AGENT_SKILL_DEPLOYMENT_SIDECAR) {
399
+ const sidecar = readDeploymentSidecar(targetPath, name);
400
+ return sidecar !== undefined
401
+ && providersShareProjectionSurface(sidecar.provider, provider)
402
+ && sidecar.sourceDigest === JSON.parse(entry.bytes.toString('utf8')).sourceDigest;
403
+ }
384
404
  const value = actual.get(entry.relativePath);
385
405
  return entry.kind === 'directory'
386
406
  ? value === 'directory'
@@ -423,6 +423,7 @@ export class AgentGenerator {
423
423
  model,
424
424
  modelRole: modelPolicy.role,
425
425
  modelTier: modelPolicy.tier,
426
+ ...(platform === 'omp' && effort ? { thinkingLevel: effort } : {}),
426
427
  tools,
427
428
  category: category,
428
429
  version,
@@ -18,6 +18,8 @@ export const PARALLELISM_BLOCK_START = '<!-- AIWG-PARALLELISM-CAP:START -->';
18
18
  export const PARALLELISM_BLOCK_END = '<!-- AIWG-PARALLELISM-CAP:END -->';
19
19
  function delegationSupport(provider) {
20
20
  switch (provider) {
21
+ case 'antigravity':
22
+ return '**Provider behavior (antigravity)**: AIWG team execution uses aiwg-mc emulation. The conservative cap is four workers; native Antigravity subagent limits and heterogeneous model pinning remain unqualified.';
21
23
  case 'claude':
22
24
  case 'codex':
23
25
  case 'copilot':
@@ -46,8 +46,8 @@ export function shouldEmitAiwgMd(provider) {
46
46
  }
47
47
  /**
48
48
  * Whether to emit AGENTS.md at project root. True for the AGENTS-MD
49
- * provider set (codex, copilot, cursor, windsurf, hermes, warp, factory,
50
- * opencode). False for claude (uses CLAUDE.md hook instead), openclaw,
49
+ * provider set (antigravity, codex, copilot, cursor, windsurf, hermes, warp,
50
+ * factory, opencode). False for claude (uses CLAUDE.md hook instead), openclaw,
51
51
  * and generic.
52
52
  */
53
53
  export function shouldEmitAgentsMd(provider) {
@@ -430,8 +430,8 @@ export function buildProviderBootstrapBlock(provider) {
430
430
  ? [
431
431
  'Load the canonical project context first, then the generated AIWG framework context:',
432
432
  '',
433
- '@WORKSPACE.md',
434
- '@AIWG.md',
433
+ provider === 'omp' ? '@../WORKSPACE.md' : '@WORKSPACE.md',
434
+ provider === 'omp' ? '@../AIWG.md' : '@AIWG.md',
435
435
  ]
436
436
  : contract.loadMode === 'config-registration'
437
437
  ? [