@aiwg/cli 2026.9.0 → 2026.9.2

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 (107) hide show
  1. package/agentic/code/providers/capability-matrix.yaml +41 -0
  2. package/agentic/code/providers/model-capabilities.v1.json +11 -0
  3. package/agentic/code/providers/model-catalog.v1.json +8 -0
  4. package/agentic/code/providers/pi/aiwg-bridge.ts +26 -0
  5. package/bin/aiwg.mjs +15 -3
  6. package/dist/src/api/index.d.ts +3 -0
  7. package/dist/src/api/index.js +3 -0
  8. package/dist/src/auth/credential-store.js +6 -0
  9. package/dist/src/channel/manager.mjs +2 -2
  10. package/dist/src/cli/handlers/dataset.js +186 -0
  11. package/dist/src/cli/handlers/help.js +2 -1
  12. package/dist/src/cli/handlers/index.js +5 -1
  13. package/dist/src/cli/handlers/init.js +1 -0
  14. package/dist/src/cli/handlers/output-mode.js +18 -1
  15. package/dist/src/cli/handlers/run.js +11 -3
  16. package/dist/src/cli/handlers/schema.js +221 -0
  17. package/dist/src/cli/handlers/sessions.js +30 -12
  18. package/dist/src/cli/handlers/steward.js +11 -1
  19. package/dist/src/cli/handlers/use.js +6 -2
  20. package/dist/src/cli/hooks/builtin/activity-log-hook.js +6 -0
  21. package/dist/src/cli/router.js +1 -1
  22. package/dist/src/cli/scope-resolver.js +22 -0
  23. package/dist/src/dataset/adapter-sdk.d.ts +41 -0
  24. package/dist/src/dataset/adapter-sdk.js +147 -0
  25. package/dist/src/dataset/adapter-types.d.ts +179 -0
  26. package/dist/src/dataset/adapter-types.js +2 -0
  27. package/dist/src/dataset/adapters.d.ts +104 -0
  28. package/dist/src/dataset/adapters.js +518 -0
  29. package/dist/src/dataset/conformance-types.d.ts +84 -0
  30. package/dist/src/dataset/conformance-types.js +3 -0
  31. package/dist/src/dataset/conformance.d.ts +13 -0
  32. package/dist/src/dataset/conformance.js +90 -0
  33. package/dist/src/dataset/contracts.d.ts +17 -0
  34. package/dist/src/dataset/contracts.js +236 -0
  35. package/dist/src/dataset/file-orchestration-repository.d.ts +19 -0
  36. package/dist/src/dataset/file-orchestration-repository.js +68 -0
  37. package/dist/src/dataset/fortemi-execution-bridge.d.ts +33 -0
  38. package/dist/src/dataset/fortemi-execution-bridge.js +35 -0
  39. package/dist/src/dataset/index.d.ts +21 -0
  40. package/dist/src/dataset/index.js +21 -0
  41. package/dist/src/dataset/ledger-types.d.ts +141 -0
  42. package/dist/src/dataset/ledger-types.js +2 -0
  43. package/dist/src/dataset/ledger.d.ts +27 -0
  44. package/dist/src/dataset/ledger.js +100 -0
  45. package/dist/src/dataset/local-execution-backend.d.ts +10 -0
  46. package/dist/src/dataset/local-execution-backend.js +32 -0
  47. package/dist/src/dataset/orchestration-repository.d.ts +29 -0
  48. package/dist/src/dataset/orchestration-repository.js +34 -0
  49. package/dist/src/dataset/orchestration-service.d.ts +56 -0
  50. package/dist/src/dataset/orchestration-service.js +466 -0
  51. package/dist/src/dataset/orchestration-types.d.ts +83 -0
  52. package/dist/src/dataset/orchestration-types.js +2 -0
  53. package/dist/src/dataset/presentation.d.ts +3 -0
  54. package/dist/src/dataset/presentation.js +8 -0
  55. package/dist/src/dataset/projections.d.ts +42 -0
  56. package/dist/src/dataset/projections.js +192 -0
  57. package/dist/src/dataset/schema-governance.d.ts +71 -0
  58. package/dist/src/dataset/schema-governance.js +135 -0
  59. package/dist/src/dataset/standards-types.d.ts +66 -0
  60. package/dist/src/dataset/standards-types.js +10 -0
  61. package/dist/src/dataset/standards.d.ts +13 -0
  62. package/dist/src/dataset/standards.js +291 -0
  63. package/dist/src/dataset/types.d.ts +258 -0
  64. package/dist/src/dataset/types.js +2 -0
  65. package/dist/src/extensions/commands/definitions.js +27 -1
  66. package/dist/src/installation/manager.mjs +5 -1
  67. package/dist/src/models/model-capabilities.v1.json +11 -0
  68. package/dist/src/models/model-catalog.v1.json +8 -0
  69. package/dist/src/models/model-discovery.js +32 -0
  70. package/dist/src/models/provider-policy.js +3 -2
  71. package/dist/src/output-modes/index.js +4 -0
  72. package/dist/src/output-modes/registry.js +68 -24
  73. package/dist/src/output-modes/runtime.js +10 -8
  74. package/dist/src/plugin/skill-command-translator.js +1 -0
  75. package/dist/src/providers/capability-matrix.yaml +41 -0
  76. package/dist/src/providers/provider-definitions.js +72 -0
  77. package/dist/src/providers/provider-inventory.js +1 -0
  78. package/dist/src/schema/catalog.js +234 -0
  79. package/dist/src/schema/compatibility.js +42 -0
  80. package/dist/src/schema/diagnostics.js +36 -0
  81. package/dist/src/schema/index.js +8 -0
  82. package/dist/src/schema/policy.js +58 -0
  83. package/dist/src/schema/resolver.js +76 -0
  84. package/dist/src/schema/types.js +2 -0
  85. package/dist/src/schema/validator.js +82 -0
  86. package/dist/src/sessions/adapters/pi.js +141 -0
  87. package/dist/src/sessions/contracts.js +1 -1
  88. package/dist/src/sessions/index.js +1 -0
  89. package/dist/src/sessions/workspace-discovery.js +10 -0
  90. package/dist/src/storage/backends/fortemi.js +6 -0
  91. package/dist/src/storage/config.js +18 -4
  92. package/dist/src/storage/fortemi-qualification.js +106 -0
  93. package/dist/src/storage/index.js +1 -0
  94. package/dist/src/storage/types.js +1 -1
  95. package/package.json +3 -1
  96. package/schemas/dataset/conformance-manifest.v1.schema.json +35 -0
  97. package/schemas/dataset/conformance-receipt.v1.schema.json +22 -0
  98. package/schemas/dataset/dataset-contracts.v1.schema.json +117 -0
  99. package/schemas/dataset/dataset-deprecations.v1.schema.json +37 -0
  100. package/schemas/dataset/dataset-schema-governance.v1.schema.json +92 -0
  101. package/schemas/dataset/dataset-standards-exchange.v1.schema.json +59 -0
  102. package/schemas/dataset/profiles/openlineage-1.0.0.schema.json +15 -0
  103. package/schemas/dataset/profiles/prov-json-20130430.schema.json +12 -0
  104. package/schemas/dataset/run-ledger.v1.schema.json +39 -0
  105. package/schemas/dataset/source-adapter.v1.schema.json +112 -0
  106. package/tools/agents/deploy-agents.mjs +9 -3
  107. package/tools/agents/providers/pi.mjs +176 -0
@@ -470,6 +470,47 @@ providers:
470
470
  deploy_target: mixed
471
471
  aggregated_output: true
472
472
 
473
+ pi:
474
+ display_name: Pi Coding Agent
475
+ aliases:
476
+ - pi-coding-agent
477
+ status: experimental
478
+ daemon_tier: unsupported
479
+ daemon_pty_adapter: false
480
+ artifact_paths:
481
+ agents: .agents/skills/
482
+ commands: .pi/prompts/
483
+ skills: .pi/skills/
484
+ skills_cross_agent: .agents/skills/
485
+ rules: AGENTS.md
486
+ behaviors: .pi/extensions/
487
+ native_features:
488
+ cron: false
489
+ agent_teams: false
490
+ tasks: false
491
+ mcp: false
492
+ behaviors: true
493
+ mission_control: false
494
+ daemon: false
495
+ emulation:
496
+ cron: external-trigger
497
+ agent_teams: aiwg-mc
498
+ tasks: aiwg-mc
499
+ mcp: null
500
+ behaviors: null
501
+ mission_control: aiwg-mc
502
+ daemon: null
503
+ hook_wiring:
504
+ at_link_support: false
505
+ fallback: full-inject
506
+ context_file: AGENTS.md
507
+ interaction:
508
+ structured_questions: none
509
+ fallback: markdown
510
+ notes: Pi does not expose a built-in structured question tool.
511
+ deploy_target: project
512
+ aggregated_output: false
513
+
473
514
  # Feature definitions — documents what each feature key means and
474
515
  # what emulation strategies are available when native support is absent.
475
516
  features:
@@ -76,6 +76,17 @@
76
76
  "verification": "Inspect active profile and run metadata",
77
77
  "sourceUrl": "https://docs.warp.dev/agent-platform/capabilities/agent-profiles-permissions", "verifiedAt": "2026-07-20"
78
78
  },
79
+ "pi": {
80
+ "agent": "native", "skill": "inherited", "globalChild": "native",
81
+ "identifierSyntax": "provider/model identifier accepted by Pi --model",
82
+ "effortValues": ["minimal", "low", "medium", "high", "xhigh"],
83
+ "inheritance": "Omitted model and thinking level inherit the invoking Pi session",
84
+ "invalidPinFallback": "Pi resolves against its configured catalog and exits on invalid explicit selection",
85
+ "configTarget": "Pi headless launch arguments",
86
+ "artifactFormat": "Runtime --model and --thinking flags",
87
+ "verification": "Inspect strict JSONL state and the selected provider/model",
88
+ "sourceUrl": "https://github.com/earendil-works/pi/tree/main/packages/coding-agent#cli-reference", "verifiedAt": "2026-09-04"
89
+ },
79
90
  "windsurf": {
80
91
  "agent": "unsupported", "skill": "unsupported", "globalChild": "inherited",
81
92
  "identifierSyntax": "UI-selected provider model",
@@ -52,6 +52,14 @@
52
52
  },
53
53
  "sourceUrl": "https://opencode.ai/docs/models", "verifiedAt": "2026-07-20"
54
54
  },
55
+ "pi": {
56
+ "roles": {
57
+ "reasoning": { "id": "configured/reasoning", "status": "unverified", "observed": false },
58
+ "coding": { "id": "configured/coding", "status": "unverified", "observed": false },
59
+ "efficiency": { "id": "configured/efficiency", "status": "unverified", "observed": false }
60
+ },
61
+ "sourceUrl": "https://github.com/earendil-works/pi/tree/main/packages/coding-agent#providers--models", "verifiedAt": "2026-09-04"
62
+ },
55
63
  "warp": {
56
64
  "roles": {
57
65
  "reasoning": { "id": "profile-selected", "status": "unverified", "observed": false },
@@ -0,0 +1,26 @@
1
+ /** AIWG's reviewed Pi bridge. Loaded only after Pi project trust is granted. */
2
+ import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
3
+
4
+ const destructive = /(?:^|[;&|]\s*)(?:sudo\s+)?(?:rm\s+-\S*r\S*\s+|git\s+(?:reset\s+--hard|clean\s+-)|chmod\s+777|chown\s+-R)/i;
5
+ const packageMutation = /(?:^|[;&|]\s*)(?:npm|pnpm|yarn|bun|pipx?|uv|cargo)\s+(?:install|add|update|upgrade)\b/i;
6
+
7
+ export async function evaluateAiwgPiCommand(
8
+ command: string,
9
+ hasUI: boolean,
10
+ confirm?: () => Promise<boolean>,
11
+ ): Promise<{ block: true; reason: string } | undefined> {
12
+ if (!destructive.test(command) && !packageMutation.test(command)) return undefined;
13
+ if (!hasUI) return { block: true, reason: 'AIWG policy blocked a destructive or package-mutating command in headless mode.' };
14
+ return await confirm?.() ? undefined : { block: true, reason: 'Denied by AIWG operator policy.' };
15
+ }
16
+
17
+ export default function aiwgBridge(pi: ExtensionAPI): void {
18
+ pi.on('tool_call', async (event, context) => {
19
+ if (event.toolName !== 'bash') return undefined;
20
+ const command = typeof event.input?.command === 'string' ? event.input.command : '';
21
+ return evaluateAiwgPiCommand(command, context.hasUI, async () => {
22
+ const choice = await context.ui.select('AIWG policy requires explicit approval for this command.', ['Deny', 'Allow once']);
23
+ return choice === 'Allow once';
24
+ });
25
+ });
26
+ }
package/bin/aiwg.mjs CHANGED
@@ -128,6 +128,7 @@ const FAST_HELP_TEXT = `
128
128
  DISPATCH
129
129
  run skill <name> Execute a script-bearing skill
130
130
  run <script-name> Run a user-defined script from .aiwg/aiwg.config
131
+ output-mode <action> Configure composable output language and presentation
131
132
 
132
133
  FEATURES
133
134
  features Show optional feature install status
@@ -183,7 +184,7 @@ const FAST_HELP_TEXT = `
183
184
  --use-stable Switch back to stable npm package
184
185
  ────────────────────────────────────────────────────────
185
186
 
186
- Providers: claude (default), copilot, factory, codex, cursor, opencode, warp, windsurf
187
+ Providers: 12 — claude (default), codex, copilot, cursor, factory, hermes, opencode, openclaw, openhuman, pi, warp, windsurf (alias: devin)
187
188
 
188
189
  Examples:
189
190
  aiwg use sdlc Install SDLC framework
@@ -233,6 +234,12 @@ function maybeWarnUnbuiltDist() {
233
234
  }
234
235
  maybeWarnUnbuiltDist();
235
236
 
237
+ // Propagate the strict no-write contract through helpers that may resolve
238
+ // installation/channel state before the command context exists.
239
+ if (process.argv.slice(2).includes('--dry-run')) {
240
+ process.env['AIWG_CLI_DRY_RUN'] = '1';
241
+ }
242
+
236
243
  // Display a cached notice and schedule its refresh before every eligible CLI
237
244
  // path, including fast help/version, channel recovery, and later preflight
238
245
  // failures. This local-only bootstrap never waits on the registry and failures
@@ -299,7 +306,7 @@ trace('bin:entry');
299
306
  */
300
307
  async function resolveRouterPath() {
301
308
  const { loadConfig } = await import('../dist/src/channel/manager.mjs');
302
- const config = await loadConfig();
309
+ const config = await loadConfig({ createIfMissing: !process.argv.slice(2).includes('--dry-run') });
303
310
  if (config.devMode && config.edgePath && config.edgePath !== packageRoot) {
304
311
  const devRouter = path.join(config.edgePath, 'dist', 'src', 'cli', 'router.js');
305
312
  if (!existsSync(devRouter)) {
@@ -414,7 +421,12 @@ async function main() {
414
421
  process.exit(1);
415
422
  }
416
423
  const { assertCanonicalInstallation } = await import(pathToFileURL(identityPath).href);
417
- assertCanonicalInstallation({ actualRoot: activePackageRoot });
424
+ const readOnlyPreview = args.includes('--dry-run');
425
+ assertCanonicalInstallation({
426
+ actualRoot: activePackageRoot,
427
+ createIfMissing: !readOnlyPreview,
428
+ allowUnrecorded: readOnlyPreview,
429
+ });
418
430
  }
419
431
 
420
432
  // Wire up the logger level from -v/-vv/--quiet/AIWG_LOG_LEVEL before any
@@ -19,5 +19,8 @@ export * from '../marketplace/artifact-attestation.js';
19
19
  export * from '../uhp/index.js';
20
20
  export * from '../mission-protocol/index.js';
21
21
  export * from '../governance/index.js';
22
+ export * from '../output-modes/index.js';
23
+ export * from '../schema/index.js';
24
+ export * from '../dataset/index.js';
22
25
  export { ARTIFACT_TRUST_ROOT_MEDIA_TYPE, ARTIFACT_TRUST_ROOT_SCHEMA_VERSION, ARTIFACT_TRUST_STATE_SCHEMA_VERSION, bootstrapTrustRoot, parseTrustRoot, parseTrustState, readTrustState, validateTrustRoot, validateTrustState, verifyRootTransition, writeTrustState, channelStateKey, canonicalJson, dssePae, publicKeyFingerprint, sha256, type ArtifactTrustRoot, type ArtifactTrustState, type RootBootstrapResult, type RootTransitionResult, type ArtifactTrustPolicySettings, type TrustedChannelState, } from '../security/artifact-trust.js';
23
26
  //# sourceMappingURL=index.d.ts.map
@@ -19,5 +19,8 @@ export * from '../marketplace/artifact-attestation.js';
19
19
  export * from '../uhp/index.js';
20
20
  export * from '../mission-protocol/index.js';
21
21
  export * from '../governance/index.js';
22
+ export * from '../output-modes/index.js';
23
+ export * from '../schema/index.js';
24
+ export * from '../dataset/index.js';
22
25
  export { ARTIFACT_TRUST_ROOT_MEDIA_TYPE, ARTIFACT_TRUST_ROOT_SCHEMA_VERSION, ARTIFACT_TRUST_STATE_SCHEMA_VERSION, bootstrapTrustRoot, parseTrustRoot, parseTrustState, readTrustState, validateTrustRoot, validateTrustState, verifyRootTransition, writeTrustState, channelStateKey, canonicalJson, dssePae, publicKeyFingerprint, sha256, } from '../security/artifact-trust.js';
23
26
  //# sourceMappingURL=index.js.map
@@ -17,6 +17,12 @@ export const defaultCommandRunner = (command, args, stdin = "") => new Promise((
17
17
  child.stdout.on("data", (chunk) => collect(stdout, chunk));
18
18
  child.stderr.on("data", (chunk) => collect(stderr, chunk));
19
19
  child.once("error", reject);
20
+ child.stdin.once("error", (error) => {
21
+ // A short-lived credential helper may close stdin before Node flushes the
22
+ // payload. Its process exit remains the authoritative command result.
23
+ if (error.code !== "EPIPE")
24
+ reject(error);
25
+ });
20
26
  child.once("close", (code) => resolve({
21
27
  stdout: Buffer.concat(stdout).toString("utf8"),
22
28
  stderr: Buffer.concat(stderr).toString("utf8"),
@@ -213,8 +213,8 @@ export async function getChannel() {
213
213
  * Get the framework root path based on current channel
214
214
  * @returns {Promise<string>} Path to framework root
215
215
  */
216
- export async function getFrameworkRoot() {
217
- const config = await loadConfig();
216
+ export async function getFrameworkRoot(options = {}) {
217
+ const config = await loadConfig(options);
218
218
 
219
219
  if (config.channel === 'edge') {
220
220
  // Check if edge installation exists
@@ -0,0 +1,186 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { createBuiltinAdapterRegistry } from "../../dataset/adapters.js";
4
+ import { FileDatasetOrchestrationRepository } from "../../dataset/file-orchestration-repository.js";
5
+ import { LocalDatasetExecutionBackend } from "../../dataset/local-execution-backend.js";
6
+ import { DatasetOrchestrationService } from "../../dataset/orchestration-service.js";
7
+ import { presentDatasetResult } from "../../dataset/presentation.js";
8
+ export const DATASET_ACTIONS = [
9
+ "source",
10
+ "check",
11
+ "preview",
12
+ "plan",
13
+ "ingest",
14
+ "status",
15
+ "show",
16
+ "verify",
17
+ "query",
18
+ "lineage",
19
+ "export",
20
+ "cancel",
21
+ "retry",
22
+ ];
23
+ function option(args, name) {
24
+ const i = args.indexOf(name);
25
+ return i < 0 ? undefined : args[i + 1];
26
+ }
27
+ function positions(args) {
28
+ const values = new Set([
29
+ "--file",
30
+ "--count",
31
+ "--digest",
32
+ "--idempotency-key",
33
+ "--approve",
34
+ "--reconciliation-digest",
35
+ "--reconciliation-threshold",
36
+ ]);
37
+ const out = [];
38
+ for (let i = 0; i < args.length; i++) {
39
+ if (values.has(args[i])) {
40
+ i++;
41
+ continue;
42
+ }
43
+ if (!args[i].startsWith("-"))
44
+ out.push(args[i]);
45
+ }
46
+ return out;
47
+ }
48
+ function input(ctx) {
49
+ const file = option(ctx.args, "--file");
50
+ if (!file)
51
+ throw new Error("DATASET_INPUT_REQUIRED: --file <json> is required");
52
+ return JSON.parse(readFileSync(resolve(ctx.cwd, file), "utf8"));
53
+ }
54
+ function service(ctx) {
55
+ const registry = createBuiltinAdapterRegistry();
56
+ return new DatasetOrchestrationService(new FileDatasetOrchestrationRepository(ctx.cwd), {
57
+ adapter: (id, version) => {
58
+ const adapter = registry.adapters.find((candidate) => {
59
+ const manifest = candidate.describe();
60
+ return manifest.id === id && manifest.version === version;
61
+ });
62
+ if (!adapter)
63
+ throw new Error(`ADAPTER_NOT_REGISTERED: ${id}@${version}`);
64
+ return adapter;
65
+ },
66
+ localBackend: new LocalDatasetExecutionBackend(),
67
+ });
68
+ }
69
+ export async function executeDatasetCommand(ctx, providedService) {
70
+ const [action, ...ids] = positions(ctx.args);
71
+ if (!DATASET_ACTIONS.includes(action))
72
+ return {
73
+ exitCode: 1,
74
+ message: `Unknown dataset action '${action ?? ""}'.`,
75
+ };
76
+ const s = providedService ?? service(ctx);
77
+ let result;
78
+ switch (action) {
79
+ case "source":
80
+ result = await s.source(input(ctx));
81
+ break;
82
+ case "check":
83
+ result = await s.check(ids[0], ctx.args.includes("--offline"));
84
+ break;
85
+ case "preview":
86
+ result = await s.preview(ids[0], Number(option(ctx.args, "--count") ?? 10), ctx.args.includes("--offline"), ctx.signal);
87
+ break;
88
+ case "plan":
89
+ result = await s.plan(input(ctx));
90
+ break;
91
+ case "ingest":
92
+ result = await s.ingest({
93
+ planId: ids[0],
94
+ planDigest: option(ctx.args, "--digest") ?? "",
95
+ idempotencyKey: option(ctx.args, "--idempotency-key") ?? "",
96
+ approvalIds: (option(ctx.args, "--approve") ?? "")
97
+ .split(",")
98
+ .filter(Boolean),
99
+ ...(option(ctx.args, "--reconciliation-digest")
100
+ ? {
101
+ reconciliationApproval: {
102
+ previewDigest: option(ctx.args, "--reconciliation-digest"),
103
+ threshold: Number(option(ctx.args, "--reconciliation-threshold")),
104
+ },
105
+ }
106
+ : {}),
107
+ signal: ctx.signal,
108
+ });
109
+ break;
110
+ case "status":
111
+ result = await s.status(ids[0]);
112
+ break;
113
+ case "show":
114
+ result = await s.show(ids[0]);
115
+ break;
116
+ case "verify":
117
+ result = await s.verify(ids[0]);
118
+ break;
119
+ case "query":
120
+ result = await s.query(ids[0]);
121
+ break;
122
+ case "lineage":
123
+ result = await s.lineage(ids[0]);
124
+ break;
125
+ case "export":
126
+ result = await s.export(ids[0]);
127
+ break;
128
+ case "cancel":
129
+ result = await s.cancel(ids[0]);
130
+ break;
131
+ case "retry":
132
+ result = await s.retry(ids[0], ctx.signal);
133
+ break;
134
+ }
135
+ return {
136
+ exitCode: result.ok ? 0 : 1,
137
+ rawOutput: true,
138
+ message: presentDatasetResult(result, ctx.args.includes("--json")),
139
+ };
140
+ }
141
+ export const datasetHandler = {
142
+ id: "dataset",
143
+ name: "Dataset intelligence",
144
+ description: "Register, preview, plan, ingest, verify, query, and trace datasets",
145
+ category: "index",
146
+ aliases: ["datasets"],
147
+ async help() {
148
+ return {
149
+ exitCode: 0,
150
+ rawOutput: true,
151
+ message: [
152
+ "Usage: aiwg dataset <action> [id] [options]",
153
+ "",
154
+ "Actions: source, check, preview, plan, ingest, status, show, verify, query, lineage, export, cancel, retry",
155
+ "source/plan: --file <json>",
156
+ "preview: <source-id> [--count N] [--offline]",
157
+ "ingest: <plan-id> --digest <sha256> --idempotency-key <key> [--approve id,id]",
158
+ "All actions: --json for the canonical aiwg.dataset-orchestration/v1 envelope.",
159
+ ].join("\n"),
160
+ };
161
+ },
162
+ async execute(ctx) {
163
+ try {
164
+ return await executeDatasetCommand(ctx);
165
+ }
166
+ catch (e) {
167
+ return {
168
+ exitCode: 1,
169
+ rawOutput: true,
170
+ message: JSON.stringify({
171
+ schema: "aiwg.dataset-orchestration/v1",
172
+ ok: false,
173
+ diagnostics: [
174
+ {
175
+ code: "DATASET_CLI_INVALID",
176
+ message: e instanceof Error ? e.message : String(e),
177
+ boundary: "input",
178
+ retryable: false,
179
+ },
180
+ ],
181
+ }, null, 2) + "\n",
182
+ };
183
+ }
184
+ },
185
+ };
186
+ //# sourceMappingURL=dataset.js.map
@@ -90,6 +90,7 @@ function displayHelp() {
90
90
  helpGroup('DISPATCH', [
91
91
  ['run skill <name>', 'Execute a script-bearing skill'],
92
92
  ['run <script-name>', 'Run a user-defined script from .aiwg/aiwg.config'],
93
+ ['output-mode <action>', 'Configure composable output language and presentation'],
93
94
  ]);
94
95
  helpGroup('FEATURES', [
95
96
  ['features', 'Show optional feature install status'],
@@ -143,7 +144,7 @@ function displayHelp() {
143
144
  ]);
144
145
  ui.rule();
145
146
  ui.blank();
146
- console.log(` ${ui.dimText('Providers:')} claude (default), copilot, factory, codex, cursor, opencode, warp, windsurf`);
147
+ console.log(` ${ui.dimText('Providers:')} 12 — claude (default), codex, copilot, cursor, factory, hermes, opencode, openclaw, openhuman, pi, warp, windsurf (alias: devin)`);
147
148
  ui.blank();
148
149
  console.log(` ${ui.dimText('Examples:')}`);
149
150
  console.log(` aiwg use sdlc ${ui.dimText('Install SDLC framework')}`);
@@ -66,12 +66,14 @@ import { artifactVerifyHandler } from './artifact-verify.js';
66
66
  import { outputModeHandler } from './output-mode.js';
67
67
  import { installationHandler } from './installation.js';
68
68
  import { uhpHandler } from './uhp.js';
69
+ import { schemaHandler } from './schema.js';
70
+ import { datasetHandler } from './dataset.js';
69
71
  // Re-export individual handlers
70
72
  export {
71
73
  // Maintenance
72
74
  helpHandler, versionHandler, authHandler, doctorHandler, contextFirewallHandler, updateHandler, refreshHandler, regenerateHandler, workspaceContextHandler,
73
75
  // Framework management
74
- useHandler, listHandler, removeHandler, promoteHandler, installHandler, packagesHandler, marketplaceHandler, initHandler, setupHandler, setupGenerateHandler, setupRunHandler, setupValidateHandler, issueHandler, issueAuditHandler, runHandler, jobHandler, costReportHandler, evidenceHandler, artifactVerifyHandler, outputModeHandler, installationHandler,
76
+ useHandler, listHandler, removeHandler, promoteHandler, installHandler, packagesHandler, marketplaceHandler, initHandler, setupHandler, setupGenerateHandler, setupRunHandler, setupValidateHandler, issueHandler, issueAuditHandler, runHandler, jobHandler, costReportHandler, evidenceHandler, artifactVerifyHandler, outputModeHandler, schemaHandler, datasetHandler, installationHandler,
75
77
  // Project
76
78
  newBundleHandler, quickrefHandler, newProjectHandler, sessionHandler, sessionsHandler,
77
79
  // Workspace
@@ -156,6 +158,8 @@ export const allHandlers = [
156
158
  evidenceHandler,
157
159
  artifactVerifyHandler,
158
160
  outputModeHandler,
161
+ schemaHandler,
162
+ datasetHandler,
159
163
  // Workspace management
160
164
  ...workspaceHandlers,
161
165
  // Subcommand handlers (MCP, catalog, index, skills)
@@ -30,6 +30,7 @@ const PROVIDER_LABELS = {
30
30
  codex: 'OpenAI Codex ~/.codex/',
31
31
  openclaw: 'OpenClaw ~/.openclaw/',
32
32
  hermes: 'Hermes (MCP) aiwg mcp',
33
+ pi: 'Pi Coding Agent .pi/ + .agents/skills/',
33
34
  };
34
35
  // Local aliases for the shared prompt utilities. These preserve existing
35
36
  // call sites (askYesNo/askString) while routing through a single timeout
@@ -53,12 +53,29 @@ async function execute(ctx) {
53
53
  return { exitCode: 1, message: `Unknown output mode '${id}'.` };
54
54
  modes = action === 'enable' ? [...new Set([...modes, id])] : modes.filter(value => value !== id);
55
55
  }
56
- await resolveOutputModes(ctx.cwd, ctx.frameworkRoot, scope === 'session' ? modes : []);
56
+ await resolveOutputModes(ctx.cwd, ctx.frameworkRoot, [], { [scope]: modes });
57
57
  const path = await writeOutputModeState(ctx.cwd, scope, modes);
58
58
  return { exitCode: 0, message: `${action === 'clear' ? 'Cleared' : `${action}d`} ${scope} output modes (${modes.join(', ') || 'unaltered'}) at ${path}` };
59
59
  }
60
60
  export const outputModeHandler = {
61
61
  id: 'output-mode', name: 'Output Modes', description: 'List, inspect, and select composable output modes', category: 'project', aliases: ['output-modes'],
62
+ async help() {
63
+ return {
64
+ exitCode: 0,
65
+ rawOutput: true,
66
+ message: [
67
+ 'Usage:',
68
+ ' aiwg output-mode list',
69
+ ' aiwg output-mode show <id>',
70
+ ' aiwg output-mode enable <id> --scope invocation|session|project',
71
+ ' aiwg output-mode disable <id> --scope session|project',
72
+ ' aiwg output-mode clear --scope session|project',
73
+ ' aiwg output-mode status [--output-mode <id>]...',
74
+ '',
75
+ 'Use repeated --output-mode flags with aiwg run for a one-command stack.',
76
+ ].join('\n'),
77
+ };
78
+ },
62
79
  async execute(ctx) { try {
63
80
  return await execute(ctx);
64
81
  }
@@ -17,11 +17,16 @@ import { readAiwgConfig, getProjectDir } from '../../config/aiwg-config.js';
17
17
  import { handlerResultFromError } from '../errors.js';
18
18
  import * as ui from '../ui.js';
19
19
  import { resolveOutputModes } from '../../output-modes/registry.js';
20
- function extractOutputModes(args) {
20
+ export function extractOutputModes(args) {
21
21
  const cleaned = [];
22
22
  const modes = [];
23
+ let forwarding = false;
23
24
  for (let i = 0; i < args.length; i++) {
24
- if (args[i] === '--output-mode') {
25
+ if (args[i] === '--') {
26
+ forwarding = true;
27
+ cleaned.push(args[i]);
28
+ }
29
+ else if (!forwarding && args[i] === '--output-mode') {
25
30
  const id = args[i + 1];
26
31
  if (!id || id.startsWith('-'))
27
32
  throw new Error('--output-mode requires a mode ID');
@@ -67,7 +72,10 @@ export const runHandler = {
67
72
  }
68
73
  const scriptName = parsed.args[0];
69
74
  const projectDir = getProjectDir(ctx, ctx.args);
70
- let outputModeEnv = {};
75
+ let outputModeEnv = {
76
+ AIWG_OUTPUT_MODES: '',
77
+ AIWG_OUTPUT_MODES_JSON: '[]',
78
+ };
71
79
  try {
72
80
  const resolved = await resolveOutputModes(projectDir, ctx.frameworkRoot, parsed.modes);
73
81
  if (resolved.modes.length > 0) {