@aiwg/cli 2026.9.0 → 2026.9.1

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 (94) hide show
  1. package/agentic/code/providers/capability-matrix.yaml +41 -0
  2. package/bin/aiwg.mjs +15 -3
  3. package/dist/src/api/index.d.ts +3 -0
  4. package/dist/src/api/index.js +3 -0
  5. package/dist/src/channel/manager.mjs +2 -2
  6. package/dist/src/cli/handlers/dataset.js +186 -0
  7. package/dist/src/cli/handlers/help.js +2 -1
  8. package/dist/src/cli/handlers/index.js +5 -1
  9. package/dist/src/cli/handlers/init.js +1 -0
  10. package/dist/src/cli/handlers/output-mode.js +18 -1
  11. package/dist/src/cli/handlers/run.js +11 -3
  12. package/dist/src/cli/handlers/schema.js +221 -0
  13. package/dist/src/cli/handlers/steward.js +11 -1
  14. package/dist/src/cli/handlers/use.js +6 -2
  15. package/dist/src/cli/hooks/builtin/activity-log-hook.js +6 -0
  16. package/dist/src/cli/router.js +1 -1
  17. package/dist/src/cli/scope-resolver.js +22 -0
  18. package/dist/src/dataset/adapter-sdk.d.ts +41 -0
  19. package/dist/src/dataset/adapter-sdk.js +147 -0
  20. package/dist/src/dataset/adapter-types.d.ts +179 -0
  21. package/dist/src/dataset/adapter-types.js +2 -0
  22. package/dist/src/dataset/adapters.d.ts +104 -0
  23. package/dist/src/dataset/adapters.js +518 -0
  24. package/dist/src/dataset/conformance-types.d.ts +84 -0
  25. package/dist/src/dataset/conformance-types.js +3 -0
  26. package/dist/src/dataset/conformance.d.ts +13 -0
  27. package/dist/src/dataset/conformance.js +90 -0
  28. package/dist/src/dataset/contracts.d.ts +17 -0
  29. package/dist/src/dataset/contracts.js +236 -0
  30. package/dist/src/dataset/file-orchestration-repository.d.ts +19 -0
  31. package/dist/src/dataset/file-orchestration-repository.js +68 -0
  32. package/dist/src/dataset/fortemi-execution-bridge.d.ts +33 -0
  33. package/dist/src/dataset/fortemi-execution-bridge.js +35 -0
  34. package/dist/src/dataset/index.d.ts +21 -0
  35. package/dist/src/dataset/index.js +21 -0
  36. package/dist/src/dataset/ledger-types.d.ts +141 -0
  37. package/dist/src/dataset/ledger-types.js +2 -0
  38. package/dist/src/dataset/ledger.d.ts +27 -0
  39. package/dist/src/dataset/ledger.js +100 -0
  40. package/dist/src/dataset/local-execution-backend.d.ts +10 -0
  41. package/dist/src/dataset/local-execution-backend.js +32 -0
  42. package/dist/src/dataset/orchestration-repository.d.ts +29 -0
  43. package/dist/src/dataset/orchestration-repository.js +34 -0
  44. package/dist/src/dataset/orchestration-service.d.ts +56 -0
  45. package/dist/src/dataset/orchestration-service.js +466 -0
  46. package/dist/src/dataset/orchestration-types.d.ts +83 -0
  47. package/dist/src/dataset/orchestration-types.js +2 -0
  48. package/dist/src/dataset/presentation.d.ts +3 -0
  49. package/dist/src/dataset/presentation.js +8 -0
  50. package/dist/src/dataset/projections.d.ts +42 -0
  51. package/dist/src/dataset/projections.js +192 -0
  52. package/dist/src/dataset/schema-governance.d.ts +71 -0
  53. package/dist/src/dataset/schema-governance.js +135 -0
  54. package/dist/src/dataset/standards-types.d.ts +66 -0
  55. package/dist/src/dataset/standards-types.js +10 -0
  56. package/dist/src/dataset/standards.d.ts +13 -0
  57. package/dist/src/dataset/standards.js +291 -0
  58. package/dist/src/dataset/types.d.ts +258 -0
  59. package/dist/src/dataset/types.js +2 -0
  60. package/dist/src/extensions/commands/definitions.js +27 -1
  61. package/dist/src/installation/manager.mjs +5 -1
  62. package/dist/src/output-modes/index.js +4 -0
  63. package/dist/src/output-modes/registry.js +68 -24
  64. package/dist/src/output-modes/runtime.js +10 -8
  65. package/dist/src/plugin/skill-command-translator.js +1 -0
  66. package/dist/src/providers/capability-matrix.yaml +41 -0
  67. package/dist/src/providers/provider-definitions.js +72 -0
  68. package/dist/src/providers/provider-inventory.js +1 -0
  69. package/dist/src/schema/catalog.js +234 -0
  70. package/dist/src/schema/compatibility.js +42 -0
  71. package/dist/src/schema/diagnostics.js +36 -0
  72. package/dist/src/schema/index.js +8 -0
  73. package/dist/src/schema/policy.js +58 -0
  74. package/dist/src/schema/resolver.js +76 -0
  75. package/dist/src/schema/types.js +2 -0
  76. package/dist/src/schema/validator.js +82 -0
  77. package/dist/src/storage/backends/fortemi.js +6 -0
  78. package/dist/src/storage/config.js +18 -4
  79. package/dist/src/storage/fortemi-qualification.js +106 -0
  80. package/dist/src/storage/index.js +1 -0
  81. package/dist/src/storage/types.js +1 -1
  82. package/package.json +3 -1
  83. package/schemas/dataset/conformance-manifest.v1.schema.json +35 -0
  84. package/schemas/dataset/conformance-receipt.v1.schema.json +22 -0
  85. package/schemas/dataset/dataset-contracts.v1.schema.json +117 -0
  86. package/schemas/dataset/dataset-deprecations.v1.schema.json +37 -0
  87. package/schemas/dataset/dataset-schema-governance.v1.schema.json +92 -0
  88. package/schemas/dataset/dataset-standards-exchange.v1.schema.json +59 -0
  89. package/schemas/dataset/profiles/openlineage-1.0.0.schema.json +15 -0
  90. package/schemas/dataset/profiles/prov-json-20130430.schema.json +12 -0
  91. package/schemas/dataset/run-ledger.v1.schema.json +39 -0
  92. package/schemas/dataset/source-adapter.v1.schema.json +112 -0
  93. package/tools/agents/deploy-agents.mjs +9 -3
  94. package/tools/agents/providers/pi.mjs +164 -0
@@ -29,6 +29,9 @@ import { buildWrapperRouteEnvelope } from '../../models/wrapper-route.js';
29
29
  import { loadProviderModelCatalog, } from '../../models/provider-policy.js';
30
30
  import { CapabilityResolutionError, resolveRoutableCapability, } from '../../artifacts/capability-resolver.js';
31
31
  const BASELINE_PROVIDER = 'claude-code';
32
+ function isModelPolicyProvider(provider) {
33
+ return Object.hasOwn(loadProviderModelCatalog().providers, provider);
34
+ }
32
35
  // ── Feature name normalization ────────────────────────────────────────────────
33
36
  /**
34
37
  * Accept both hyphenated (agent-teams) and underscored (agent_teams) feature
@@ -192,7 +195,7 @@ async function handleSteward(args, ctx) {
192
195
  aiwg steward permissions migrate --apply Back up and atomically normalize config
193
196
 
194
197
  Providers:
195
- claude-code, codex, copilot, cursor, factory, opencode, warp, windsurf, hermes, openclaw
198
+ claude-code, codex, copilot, cursor, factory, opencode, pi, warp, windsurf, hermes, openclaw
196
199
 
197
200
  Features:
198
201
  cron, agent_teams, tasks, mcp, behaviors, mission_control, daemon
@@ -455,6 +458,13 @@ async function handleSteward(args, ctx) {
455
458
  hint: 'Pass --provider with a supported provider id.',
456
459
  exitCode: EXIT_CODES.USAGE,
457
460
  });
461
+ if (!isModelPolicyProvider(provider))
462
+ throw new AiwgError({
463
+ code: 'ERR_USAGE_UNSUPPORTED_PROVIDER',
464
+ message: `Model wrapper routing is not implemented for provider: ${provider}`,
465
+ hint: 'Use `aiwg steward capabilities --provider pi` for current Pi capability routing; model routing is tracked separately.',
466
+ exitCode: EXIT_CODES.USAGE,
467
+ });
458
468
  const capabilityType = flagValue('--capability-type');
459
469
  const capability = flagValue('--capability');
460
470
  const assignment = flagValue('--assignment');
@@ -2922,7 +2922,7 @@ export class UseHandler {
2922
2922
  catch {
2923
2923
  // Profile selection is optional — don't fail deployment
2924
2924
  }
2925
- if (framework === 'aiwg-utils' && !remainingArgs.includes('--dry-run')) {
2925
+ if (framework === 'aiwg-utils' && provider !== 'pi' && !remainingArgs.includes('--dry-run')) {
2926
2926
  const wrapperValidation = await validateDeployedModelWrappers({
2927
2927
  provider: normalizeProviderDefinitionId(provider) ?? provider,
2928
2928
  target,
@@ -3025,6 +3025,7 @@ export class UseHandler {
3025
3025
  ? withProviderOverride(deployFilteredArgs, provider)
3026
3026
  : deployFilteredArgs;
3027
3027
  const bulkKernelOnly = framework === 'all'
3028
+ && provider !== 'pi'
3028
3029
  && !remainingArgs.includes('--copy-all')
3029
3030
  && !remainingArgs.includes('--copy-standard-skills');
3030
3031
  if (bulkKernelOnly)
@@ -3230,7 +3231,10 @@ export class UseHandler {
3230
3231
  }
3231
3232
  await ensureProviderGeneratedDirsIgnored(target, provider, { dryRun, verbose });
3232
3233
  const paths = getProviderPaths(provider);
3233
- if (!dryRun && !skipUtils && !bulkKernelOnly) {
3234
+ // Pi model selection/headless routing is delivered by #2151. Until that
3235
+ // adapter exists, do not require model-wrapper artifacts that Pi cannot
3236
+ // load; resource deployment remains independently valid.
3237
+ if (!dryRun && !skipUtils && !bulkKernelOnly && provider !== 'pi') {
3234
3238
  const wrapperValidation = await validateDeployedModelWrappers({
3235
3239
  provider,
3236
3240
  target,
@@ -74,6 +74,12 @@ export const activityLogPostCommandHook = {
74
74
  commands: Object.keys(COMMAND_OPERATION_MAP),
75
75
  },
76
76
  async execute(ctx) {
77
+ // A dry-run is a strict no-write contract. The command handler may preview
78
+ // mutations, but the post-command hook must not create activity.log as a
79
+ // side effect of that preview.
80
+ if (ctx.args.includes('--dry-run')) {
81
+ return { action: 'continue' };
82
+ }
77
83
  // Skip on env-var opt-out
78
84
  if (isActivityLogSkipped()) {
79
85
  return { action: 'continue' };
@@ -316,7 +316,7 @@ async function logCommandInvocation(input) {
316
316
  * @returns Handler context
317
317
  */
318
318
  async function buildContext(args, rawArgs, options) {
319
- const frameworkRoot = await getFrameworkRoot();
319
+ const frameworkRoot = await getFrameworkRoot({ createIfMissing: !args.includes('--dry-run') });
320
320
  const ctx = {
321
321
  args,
322
322
  rawArgs,
@@ -13,6 +13,16 @@ import { homedir } from 'node:os';
13
13
  import * as path from 'node:path';
14
14
  import { resolveHermesHome, resolveHermesHomePath } from '../providers/hermes-home.js';
15
15
  export const hermesHome = resolveHermesHome;
16
+ function piAgentDir() {
17
+ const configured = process.env.PI_CODING_AGENT_DIR;
18
+ if (!configured)
19
+ return path.join(homedir(), '.pi', 'agent');
20
+ if (configured === '~')
21
+ return homedir();
22
+ if (configured.startsWith('~/'))
23
+ return path.join(homedir(), configured.slice(2));
24
+ return configured;
25
+ }
16
26
  /**
17
27
  * User-scope deploy paths per provider per ADR-4 §2. Each path is absolute
18
28
  * (rooted in os.homedir()) so the orchestrator's existing path-join logic
@@ -47,6 +57,18 @@ export const USER_SCOPE_PATHS = {
47
57
  rules: '',
48
58
  behaviors: '',
49
59
  },
60
+ pi: {
61
+ // Pi's global resource root is configurable. Unlike project deployment,
62
+ // user-scope resources belong under the effective agent directory. Keep
63
+ // skills on this single native path instead of also copying them to
64
+ // ~/.agents/skills, which would create duplicate Pi discovery entries.
65
+ // PI_CODING_AGENT_DIR is configuration only and is not runtime evidence.
66
+ agents: '',
67
+ skills: path.join(piAgentDir(), 'skills'),
68
+ commands: path.join(piAgentDir(), 'prompts'),
69
+ rules: '',
70
+ behaviors: path.join(piAgentDir(), 'extensions'),
71
+ },
50
72
  copilot: {
51
73
  // #1160 — Non-applicable for filesystem user-scope discovery.
52
74
  //
@@ -0,0 +1,41 @@
1
+ import type { AdapterCheckpoint, AdapterConfigurationResult, AdapterDiagnostic, AdapterDiagnosticCode, AdapterLimits, AdapterManifest, AdapterOperation, AdapterQualificationCell, AdapterQualificationReport, AdapterRequest, AdapterSchemaDeclaration, CredentialLocator, DatasetSourceAdapter } from './adapter-types.js';
2
+ export declare const DEFAULT_ADAPTER_LIMITS: AdapterLimits;
3
+ export declare function sha256Digest(value: string | Uint8Array): {
4
+ algorithm: 'sha256';
5
+ value: string;
6
+ };
7
+ export declare function canonicalJson(value: unknown): string;
8
+ export declare function diagnostic(operation: AdapterOperation, code: AdapterDiagnosticCode, message: string, options?: {
9
+ path?: string;
10
+ retryable?: boolean;
11
+ severity?: AdapterDiagnostic['severity'];
12
+ }): AdapterDiagnostic;
13
+ export declare class AdapterFailure extends Error {
14
+ readonly diagnostic: AdapterDiagnostic;
15
+ constructor(diagnostic: AdapterDiagnostic);
16
+ }
17
+ export declare function assertActive(signal: AbortSignal | undefined, operation: AdapterOperation): void;
18
+ export declare function effectiveLimits(manifest: AdapterManifest, requested: AdapterLimits): AdapterLimits;
19
+ export declare function isCredentialLocator(value: unknown): value is CredentialLocator;
20
+ export declare function containsRawSecret(value: unknown, key?: string): boolean;
21
+ export declare function redactAdapterValue(value: unknown, key?: string): unknown;
22
+ export declare function schemaDeclaration(id: string, schema: Record<string, unknown>): AdapterSchemaDeclaration;
23
+ export declare function configureObject<T extends Record<string, unknown>>(operation: AdapterOperation, value: unknown, validate: (candidate: Record<string, unknown>) => candidate is T): AdapterConfigurationResult<T>;
24
+ export declare function validateCheckpoint(checkpoint: AdapterCheckpoint | undefined, manifest: AdapterManifest, sourceIdentity: string): AdapterDiagnostic[];
25
+ export declare class AdapterRegistry {
26
+ #private;
27
+ private readonly trust;
28
+ constructor(trust: {
29
+ allowIds: Set<string>;
30
+ allowUntrusted?: boolean;
31
+ });
32
+ register(adapter: DatasetSourceAdapter): void;
33
+ require(id: string, version: string): DatasetSourceAdapter;
34
+ }
35
+ export declare function qualifyAdapter(adapter: DatasetSourceAdapter, options: {
36
+ fixtureRevision: string;
37
+ qualifiedAt: string;
38
+ cells: AdapterQualificationCell[];
39
+ }): Promise<AdapterQualificationReport>;
40
+ export declare function request<T extends Record<string, unknown>>(requestId: string, config: T, policy: AdapterRequest<T>['policy'], limits?: Partial<AdapterLimits>): AdapterRequest<T>;
41
+ //# sourceMappingURL=adapter-sdk.d.ts.map
@@ -0,0 +1,147 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { DATASET_ADAPTER_CONTRACT_VERSION } from './adapter-types.js';
3
+ export const DEFAULT_ADAPTER_LIMITS = Object.freeze({
4
+ maxRecords: 10_000,
5
+ maxBytes: 16 * 1024 * 1024,
6
+ maxRecordBytes: 1024 * 1024,
7
+ timeoutMs: 30_000,
8
+ maxRedirects: 3,
9
+ maxDepth: 16,
10
+ });
11
+ export function sha256Digest(value) {
12
+ return { algorithm: 'sha256', value: createHash('sha256').update(value).digest('hex') };
13
+ }
14
+ export function canonicalJson(value) {
15
+ if (value === null || typeof value !== 'object')
16
+ return JSON.stringify(value);
17
+ if (Array.isArray(value))
18
+ return `[${value.map(canonicalJson).join(',')}]`;
19
+ return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(',')}}`;
20
+ }
21
+ export function diagnostic(operation, code, message, options = {}) {
22
+ return { code, message, operation, retryable: options.retryable ?? false, severity: options.severity ?? 'error', ...(options.path ? { path: options.path } : {}) };
23
+ }
24
+ export class AdapterFailure extends Error {
25
+ diagnostic;
26
+ constructor(diagnostic) {
27
+ super(diagnostic.message);
28
+ this.diagnostic = diagnostic;
29
+ this.name = 'AdapterFailure';
30
+ }
31
+ }
32
+ export function assertActive(signal, operation) {
33
+ if (signal?.aborted)
34
+ throw new AdapterFailure(diagnostic(operation, 'ADAPTER_CANCELLED', 'The adapter operation was cancelled.'));
35
+ }
36
+ export function effectiveLimits(manifest, requested) {
37
+ const positive = (value, ceiling) => Math.max(1, Math.min(Number.isFinite(value) ? Math.trunc(value) : 1, ceiling));
38
+ return {
39
+ maxRecords: positive(requested.maxRecords, manifest.limits.maxRecords),
40
+ maxBytes: positive(requested.maxBytes, manifest.limits.maxBytes),
41
+ maxRecordBytes: positive(requested.maxRecordBytes, manifest.limits.maxRecordBytes),
42
+ timeoutMs: positive(requested.timeoutMs, manifest.limits.timeoutMs),
43
+ maxRedirects: Math.max(0, Math.min(Math.trunc(requested.maxRedirects), manifest.limits.maxRedirects)),
44
+ maxDepth: positive(requested.maxDepth, manifest.limits.maxDepth),
45
+ };
46
+ }
47
+ export function isCredentialLocator(value) {
48
+ if (!value || typeof value !== 'object' || Array.isArray(value))
49
+ return false;
50
+ const candidate = value;
51
+ return ['opaque', 'environment', 'keychain', 'vault'].includes(String(candidate.kind))
52
+ && typeof candidate.locator === 'string' && candidate.locator.length > 0 && candidate.locator.length <= 512;
53
+ }
54
+ const SECRET_KEY = /(?:secret|password|passwd|token|api[-_]?key|credential)/iu;
55
+ export function containsRawSecret(value, key = '') {
56
+ if (SECRET_KEY.test(key))
57
+ return !isCredentialLocator(value);
58
+ if (Array.isArray(value))
59
+ return value.some(item => containsRawSecret(item));
60
+ if (value && typeof value === 'object')
61
+ return Object.entries(value).some(([childKey, child]) => containsRawSecret(child, childKey));
62
+ return false;
63
+ }
64
+ export function redactAdapterValue(value, key = '') {
65
+ if (SECRET_KEY.test(key))
66
+ return '[credential-locator-redacted]';
67
+ if (Array.isArray(value))
68
+ return value.map(item => redactAdapterValue(item));
69
+ if (value && typeof value === 'object')
70
+ return Object.fromEntries(Object.entries(value).map(([childKey, child]) => [childKey, redactAdapterValue(child, childKey)]));
71
+ return value;
72
+ }
73
+ export function schemaDeclaration(id, schema) {
74
+ const version = '1.0.0';
75
+ return { id, version, digest: sha256Digest(canonicalJson(schema)), dialect: 'https://json-schema.org/draft/2020-12/schema', schema };
76
+ }
77
+ export function configureObject(operation, value, validate) {
78
+ if (!value || typeof value !== 'object' || Array.isArray(value) || containsRawSecret(value)) {
79
+ return { ok: false, diagnostics: [diagnostic(operation, containsRawSecret(value) ? 'ADAPTER_SECRET_REJECTED' : 'ADAPTER_INVALID_CONFIGURATION', containsRawSecret(value) ? 'Secret-like fields must contain an opaque credential locator, never credential material.' : 'Configuration must be an object accepted by the adapter schema.')] };
80
+ }
81
+ const candidate = structuredClone(value);
82
+ if (!validate(candidate))
83
+ return { ok: false, diagnostics: [diagnostic(operation, 'ADAPTER_INVALID_CONFIGURATION', 'Configuration does not satisfy the adapter contract.')] };
84
+ return { ok: true, config: candidate, configDigest: sha256Digest(canonicalJson(redactAdapterValue(candidate))), diagnostics: [] };
85
+ }
86
+ export function validateCheckpoint(checkpoint, manifest, sourceIdentity) {
87
+ if (!checkpoint)
88
+ return [];
89
+ const valid = checkpoint.contractVersion === DATASET_ADAPTER_CONTRACT_VERSION
90
+ && checkpoint.kind === 'AdapterCheckpoint'
91
+ && checkpoint.adapter.id === manifest.id
92
+ && checkpoint.adapter.version === manifest.version
93
+ && checkpoint.sourceIdentity === sourceIdentity
94
+ && /^-?\d+$/u.test(checkpoint.cursor)
95
+ && checkpoint.schema.id === manifest.schemas.checkpoint.id
96
+ && checkpoint.schema.version === manifest.schemas.checkpoint.version
97
+ && checkpoint.schema.digest?.value === manifest.schemas.checkpoint.digest.value;
98
+ return valid ? [] : [diagnostic('read', 'ADAPTER_CHECKPOINT_INCOMPATIBLE', 'Checkpoint identity, adapter version, or schema binding is incompatible; no records were read.')];
99
+ }
100
+ export class AdapterRegistry {
101
+ trust;
102
+ #adapters = new Map();
103
+ constructor(trust) {
104
+ this.trust = trust;
105
+ }
106
+ register(adapter) {
107
+ const manifest = adapter.describe();
108
+ if (!this.trust.allowIds.has(manifest.id))
109
+ throw new Error(`ADAPTER_NOT_ALLOWLISTED: ${manifest.id}`);
110
+ if (manifest.trust.state === 'untrusted' && !this.trust.allowUntrusted)
111
+ throw new Error(`ADAPTER_TRUST_REQUIRED: ${manifest.id}`);
112
+ if (manifest.permissions.credentials !== 'none' && manifest.permissions.credentials !== 'locator-only')
113
+ throw new Error(`ADAPTER_PERMISSION_INVALID: ${manifest.id}`);
114
+ this.#adapters.set(`${manifest.id}@${manifest.version}`, adapter);
115
+ }
116
+ require(id, version) {
117
+ const adapter = this.#adapters.get(`${id}@${version}`);
118
+ if (!adapter)
119
+ throw new Error(`ADAPTER_NOT_REGISTERED: ${id}@${version}`);
120
+ return adapter;
121
+ }
122
+ }
123
+ export async function qualifyAdapter(adapter, options) {
124
+ const manifest = adapter.describe();
125
+ const required = new Set(['configuration-schema', 'preview-purity', 'deterministic-read', 'stable-errors', 'cancellation', 'checkpoints', 'version-upgrade', 'secret-leakage']);
126
+ const passed = new Set(options.cells.filter(cell => cell.passed).map(cell => cell.name));
127
+ const qualified = [...required].every(name => passed.has(name));
128
+ const realSource = options.cells.some(cell => cell.source === 'real-source' && cell.passed);
129
+ return {
130
+ contractVersion: DATASET_ADAPTER_CONTRACT_VERSION,
131
+ kind: 'AdapterQualificationReport',
132
+ adapter: { id: manifest.id, version: manifest.version, packageDigest: manifest.packageDigest },
133
+ schemas: {
134
+ config: binding(manifest.schemas.config), record: binding(manifest.schemas.discoveredRecord), checkpoint: binding(manifest.schemas.checkpoint),
135
+ },
136
+ fixtureRevision: options.fixtureRevision,
137
+ cells: structuredClone(options.cells), qualifiedAt: options.qualifiedAt,
138
+ qualified, stableEligible: qualified && realSource,
139
+ };
140
+ }
141
+ function binding(schema) {
142
+ return { id: schema.id, version: schema.version, digest: schema.digest };
143
+ }
144
+ export function request(requestId, config, policy, limits = {}) {
145
+ return { contractVersion: DATASET_ADAPTER_CONTRACT_VERSION, requestId, config, policy, limits: { ...DEFAULT_ADAPTER_LIMITS, ...limits } };
146
+ }
147
+ //# sourceMappingURL=adapter-sdk.js.map
@@ -0,0 +1,179 @@
1
+ import type { Digest, PrivacyClassification, SchemaBinding } from './types.js';
2
+ export declare const DATASET_ADAPTER_CONTRACT_VERSION: "aiwg.dataset.adapter/v1";
3
+ export type DatasetAdapterContractVersion = typeof DATASET_ADAPTER_CONTRACT_VERSION;
4
+ export type AdapterOperation = 'describe' | 'configure' | 'check' | 'discover' | 'preview' | 'read';
5
+ export type AdapterDiagnosticCode = 'ADAPTER_INVALID_CONFIGURATION' | 'ADAPTER_AUTHORIZATION_UNAVAILABLE' | 'ADAPTER_OFFLINE_PROHIBITED' | 'ADAPTER_SOURCE_UNAVAILABLE' | 'ADAPTER_RESOURCE_LIMIT' | 'ADAPTER_SCHEMA_DRIFT' | 'ADAPTER_CHECKPOINT_INCOMPATIBLE' | 'ADAPTER_CANCELLED' | 'ADAPTER_PATH_ESCAPE' | 'ADAPTER_UNSAFE_SYMLINK' | 'ADAPTER_SPECIAL_FILE' | 'ADAPTER_NETWORK_PROHIBITED' | 'ADAPTER_REDIRECT_PROHIBITED' | 'ADAPTER_SECRET_REJECTED' | 'ADAPTER_INTERNAL_ERROR';
6
+ export interface AdapterDiagnostic {
7
+ code: AdapterDiagnosticCode;
8
+ severity: 'info' | 'warning' | 'error';
9
+ message: string;
10
+ operation: AdapterOperation;
11
+ path?: string;
12
+ retryable: boolean;
13
+ }
14
+ export interface AdapterSchemaDeclaration extends SchemaBinding {
15
+ digest: Digest;
16
+ dialect: 'https://json-schema.org/draft/2020-12/schema';
17
+ schema: Record<string, unknown>;
18
+ }
19
+ export interface AdapterManifest {
20
+ contractVersion: DatasetAdapterContractVersion;
21
+ kind: 'AdapterManifest';
22
+ id: string;
23
+ version: string;
24
+ packageDigest: Digest;
25
+ datasetContractRange: string;
26
+ sourceKinds: string[];
27
+ schemas: {
28
+ config: AdapterSchemaDeclaration;
29
+ discoveredRecord: AdapterSchemaDeclaration;
30
+ checkpoint: AdapterSchemaDeclaration;
31
+ };
32
+ capabilities: Array<'discovery' | 'preview' | 'streaming-read' | 'checkpoint' | 'tombstone'>;
33
+ limits: AdapterLimits;
34
+ maturity: 'experimental' | 'qualified' | 'stable';
35
+ publisher: {
36
+ id: string;
37
+ url?: string;
38
+ };
39
+ trust: {
40
+ state: 'builtin' | 'verified' | 'untrusted';
41
+ signature?: string;
42
+ };
43
+ permissions: {
44
+ locality: 'local' | 'remote';
45
+ network: 'none' | 'https-allowlisted';
46
+ credentials: 'none' | 'locator-only';
47
+ };
48
+ incremental: {
49
+ ordering: string;
50
+ sameCursorTieHandling: string;
51
+ lateArrivals: string;
52
+ tombstones: string;
53
+ checkpointCompatibility: string;
54
+ };
55
+ }
56
+ export interface CredentialLocator {
57
+ kind: 'opaque' | 'environment' | 'keychain' | 'vault';
58
+ locator: string;
59
+ }
60
+ export interface AdapterLimits {
61
+ maxRecords: number;
62
+ maxBytes: number;
63
+ maxRecordBytes: number;
64
+ timeoutMs: number;
65
+ maxRedirects: number;
66
+ maxDepth: number;
67
+ }
68
+ export interface AdapterPolicy {
69
+ offline: boolean;
70
+ allowedRoot?: string;
71
+ allowedHosts?: string[];
72
+ allowPrivateNetwork?: boolean;
73
+ }
74
+ export interface AdapterRequest<TConfig extends Record<string, unknown> = Record<string, unknown>> {
75
+ contractVersion: DatasetAdapterContractVersion;
76
+ requestId: string;
77
+ config: TConfig;
78
+ policy: AdapterPolicy;
79
+ limits: AdapterLimits;
80
+ signal?: AbortSignal;
81
+ }
82
+ export interface AdapterCheckpoint {
83
+ contractVersion: DatasetAdapterContractVersion;
84
+ kind: 'AdapterCheckpoint';
85
+ adapter: {
86
+ id: string;
87
+ version: string;
88
+ };
89
+ sourceIdentity: string;
90
+ cursor: string;
91
+ tieBreaker?: string;
92
+ schema: SchemaBinding;
93
+ createdAt: string;
94
+ }
95
+ export interface AdapterConfigurationResult<TConfig extends Record<string, unknown> = Record<string, unknown>> {
96
+ ok: boolean;
97
+ config?: TConfig;
98
+ configDigest?: Digest;
99
+ diagnostics: AdapterDiagnostic[];
100
+ }
101
+ export interface AdapterDiscovery {
102
+ sourceIdentity: string;
103
+ proposedSchema: Record<string, unknown>;
104
+ schemaBasis: 'declared' | 'observed' | 'inferred';
105
+ estimates: {
106
+ records?: number;
107
+ bytes?: number;
108
+ };
109
+ privacySignals: PrivacyClassification[];
110
+ licenseSignals: string[];
111
+ cursorSupport: boolean;
112
+ checkpointSupport: boolean;
113
+ identityStability: 'stable' | 'source-unstable';
114
+ identityLimitation?: string;
115
+ limitations: string[];
116
+ }
117
+ export interface AdapterResult<T> {
118
+ ok: boolean;
119
+ value?: T;
120
+ diagnostics: AdapterDiagnostic[];
121
+ }
122
+ export interface AdapterRecord {
123
+ logicalId: string;
124
+ ordinal: number;
125
+ value: unknown;
126
+ sourceLocator: string;
127
+ contentDigest: Digest;
128
+ tombstone?: boolean;
129
+ }
130
+ export type AdapterReadEvent = {
131
+ kind: 'record';
132
+ record: AdapterRecord;
133
+ } | {
134
+ kind: 'checkpoint';
135
+ checkpoint: AdapterCheckpoint;
136
+ } | {
137
+ kind: 'diagnostic';
138
+ diagnostic: AdapterDiagnostic;
139
+ };
140
+ export interface DatasetSourceAdapter<TConfig extends Record<string, unknown> = Record<string, unknown>> {
141
+ describe(): AdapterManifest;
142
+ configure(config: unknown): Promise<AdapterConfigurationResult<TConfig>>;
143
+ check(request: AdapterRequest<TConfig>): Promise<AdapterResult<{
144
+ sourceIdentity: string;
145
+ }>>;
146
+ discover(request: AdapterRequest<TConfig>): Promise<AdapterResult<AdapterDiscovery>>;
147
+ preview(request: AdapterRequest<TConfig> & {
148
+ count: number;
149
+ }): Promise<AdapterResult<AdapterRecord[]>>;
150
+ read(request: AdapterRequest<TConfig> & {
151
+ checkpoint?: AdapterCheckpoint;
152
+ }): AsyncIterable<AdapterReadEvent>;
153
+ }
154
+ export interface AdapterQualificationCell {
155
+ name: string;
156
+ source: 'fixture' | 'real-source';
157
+ passed: boolean;
158
+ evidence: string[];
159
+ }
160
+ export interface AdapterQualificationReport {
161
+ contractVersion: DatasetAdapterContractVersion;
162
+ kind: 'AdapterQualificationReport';
163
+ adapter: {
164
+ id: string;
165
+ version: string;
166
+ packageDigest: Digest;
167
+ };
168
+ schemas: {
169
+ config: SchemaBinding;
170
+ record: SchemaBinding;
171
+ checkpoint: SchemaBinding;
172
+ };
173
+ fixtureRevision: string;
174
+ cells: AdapterQualificationCell[];
175
+ qualifiedAt: string;
176
+ qualified: boolean;
177
+ stableEligible: boolean;
178
+ }
179
+ //# sourceMappingURL=adapter-types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export const DATASET_ADAPTER_CONTRACT_VERSION = 'aiwg.dataset.adapter/v1';
2
+ //# sourceMappingURL=adapter-types.js.map
@@ -0,0 +1,104 @@
1
+ import type { AdapterCheckpoint, AdapterConfigurationResult, AdapterDiscovery, AdapterManifest, AdapterReadEvent, AdapterRecord, AdapterRequest, AdapterResult, DatasetSourceAdapter } from './adapter-types.js';
2
+ type FileConfig = {
3
+ path: string;
4
+ encoding?: 'utf8';
5
+ };
6
+ type DirectoryConfig = FileConfig & {
7
+ recursive?: boolean;
8
+ };
9
+ type HttpConfig = {
10
+ url: string;
11
+ headers?: Record<string, string | {
12
+ kind: 'opaque' | 'environment' | 'keychain' | 'vault';
13
+ locator: string;
14
+ }>;
15
+ };
16
+ declare abstract class LocalAdapter<T extends FileConfig> implements DatasetSourceAdapter<T> {
17
+ abstract describe(): AdapterManifest;
18
+ protected abstract valid(value: Record<string, unknown>): value is T;
19
+ protected abstract discoverPath(config: T, request: AdapterRequest<T>): Promise<AdapterDiscovery>;
20
+ protected abstract records(config: T, request: AdapterRequest<T> & {
21
+ checkpoint?: AdapterCheckpoint;
22
+ }): AsyncIterable<AdapterRecord>;
23
+ configure(config: unknown): Promise<AdapterConfigurationResult<T>>;
24
+ check(request: AdapterRequest<T>): Promise<AdapterResult<{
25
+ sourceIdentity: string;
26
+ }>>;
27
+ discover(request: AdapterRequest<T>): Promise<AdapterResult<AdapterDiscovery>>;
28
+ preview(request: AdapterRequest<T> & {
29
+ count: number;
30
+ }): Promise<AdapterResult<AdapterRecord[]>>;
31
+ read(request: AdapterRequest<T> & {
32
+ checkpoint?: AdapterCheckpoint;
33
+ }): AsyncIterable<AdapterReadEvent>;
34
+ }
35
+ export declare class FileAdapter extends LocalAdapter<FileConfig> {
36
+ #private;
37
+ describe(): AdapterManifest;
38
+ protected valid(value: Record<string, unknown>): value is FileConfig;
39
+ protected discoverPath(config: FileConfig, request: AdapterRequest<FileConfig>): Promise<AdapterDiscovery>;
40
+ protected records(config: FileConfig, request: AdapterRequest<FileConfig> & {
41
+ checkpoint?: AdapterCheckpoint;
42
+ }): AsyncIterable<AdapterRecord>;
43
+ }
44
+ declare abstract class LineAdapter<T extends FileConfig> extends LocalAdapter<T> {
45
+ protected lineDiscovery(kind: string, config: T, request: AdapterRequest<T>, schema: Record<string, unknown>): Promise<AdapterDiscovery>;
46
+ protected lines(config: T, request: AdapterRequest<T> & {
47
+ checkpoint?: AdapterCheckpoint;
48
+ }, parse: (line: string, ordinal: number) => unknown): AsyncIterable<AdapterRecord>;
49
+ }
50
+ export declare class JsonlAdapter extends LineAdapter<FileConfig> {
51
+ #private;
52
+ describe(): AdapterManifest;
53
+ protected valid(value: Record<string, unknown>): value is FileConfig;
54
+ protected discoverPath(config: FileConfig, request: AdapterRequest<FileConfig>): Promise<AdapterDiscovery>;
55
+ protected records(config: FileConfig, request: AdapterRequest<FileConfig> & {
56
+ checkpoint?: AdapterCheckpoint;
57
+ }): AsyncIterable<AdapterRecord>;
58
+ }
59
+ export declare class CsvAdapter extends LineAdapter<FileConfig> {
60
+ #private;
61
+ describe(): AdapterManifest;
62
+ protected valid(value: Record<string, unknown>): value is FileConfig;
63
+ protected discoverPath(config: FileConfig, request: AdapterRequest<FileConfig>): Promise<AdapterDiscovery>;
64
+ protected records(config: FileConfig, request: AdapterRequest<FileConfig> & {
65
+ checkpoint?: AdapterCheckpoint;
66
+ }): AsyncIterable<AdapterRecord>;
67
+ }
68
+ export declare class DirectoryAdapter extends LocalAdapter<DirectoryConfig> {
69
+ #private;
70
+ describe(): AdapterManifest;
71
+ protected valid(value: Record<string, unknown>): value is DirectoryConfig;
72
+ protected discoverPath(config: DirectoryConfig, request: AdapterRequest<DirectoryConfig>): Promise<AdapterDiscovery>;
73
+ protected records(config: DirectoryConfig, request: AdapterRequest<DirectoryConfig> & {
74
+ checkpoint?: AdapterCheckpoint;
75
+ }): AsyncIterable<AdapterRecord>;
76
+ }
77
+ type FetchLike = typeof fetch;
78
+ type HostResolver = (hostname: string) => Promise<Array<{
79
+ address: string;
80
+ }>>;
81
+ export declare class HttpAdapter implements DatasetSourceAdapter<HttpConfig> {
82
+ #private;
83
+ private readonly fetchImpl;
84
+ private readonly resolveHost;
85
+ constructor(fetchImpl?: FetchLike, resolveHost?: HostResolver);
86
+ describe(): AdapterManifest;
87
+ configure(config: unknown): Promise<AdapterConfigurationResult<HttpConfig>>;
88
+ check(request: AdapterRequest<HttpConfig>): Promise<AdapterResult<{
89
+ sourceIdentity: string;
90
+ }>>;
91
+ discover(request: AdapterRequest<HttpConfig>): Promise<AdapterResult<AdapterDiscovery>>;
92
+ preview(request: AdapterRequest<HttpConfig> & {
93
+ count: number;
94
+ }): Promise<AdapterResult<AdapterRecord[]>>;
95
+ read(request: AdapterRequest<HttpConfig> & {
96
+ checkpoint?: AdapterCheckpoint;
97
+ }): AsyncIterable<AdapterReadEvent>;
98
+ }
99
+ export declare function createBuiltinAdapterRegistry(): {
100
+ adapters: (FileAdapter | JsonlAdapter | CsvAdapter | DirectoryAdapter | HttpAdapter)[];
101
+ manifests: AdapterManifest[];
102
+ };
103
+ export {};
104
+ //# sourceMappingURL=adapters.d.ts.map