@aiwg/cli 2026.8.7 → 2026.8.10

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 (76) hide show
  1. package/README.md +23 -8
  2. package/THIRD_PARTY_NOTICES.md +35 -0
  3. package/agentic/code/providers/capability-matrix.yaml +3 -3
  4. package/bin/aiwg.mjs +125 -0
  5. package/dist/src/artifacts/backends/graphology-backend.js +4 -3
  6. package/dist/src/artifacts/backends/sqlite-backend.js +4 -5
  7. package/dist/src/artifacts/cli.js +2 -2
  8. package/dist/src/artifacts/corpus-tools/cli.js +27 -0
  9. package/dist/src/artifacts/corpus-tools/profile-embed.js +3 -2
  10. package/dist/src/artifacts/corpus-tools/retrieval-lab.js +356 -0
  11. package/dist/src/artifacts/discover-facets.js +2 -2
  12. package/dist/src/artifacts/embedding-index.js +9 -8
  13. package/dist/src/artifacts/graph-backend.js +2 -2
  14. package/dist/src/artifacts/move.js +40 -2
  15. package/dist/src/artifacts/query-engine.js +21 -7
  16. package/dist/src/artifacts/repair.js +47 -0
  17. package/dist/src/artifacts/types.js +3 -3
  18. package/dist/src/cli/command-log.js +2 -2
  19. package/dist/src/cli/handlers/artifacts.js +50 -1
  20. package/dist/src/cli/handlers/cost-report.js +71 -0
  21. package/dist/src/cli/handlers/evidence.js +78 -0
  22. package/dist/src/cli/handlers/help.js +9 -0
  23. package/dist/src/cli/handlers/index.js +8 -3
  24. package/dist/src/cli/handlers/local-executor.js +4 -3
  25. package/dist/src/cli/handlers/refresh.js +20 -8
  26. package/dist/src/cli/handlers/regenerate.js +22 -12
  27. package/dist/src/cli/handlers/serve.js +15 -36
  28. package/dist/src/cli/handlers/sessions.js +5 -4
  29. package/dist/src/cli/handlers/setup-manifest.js +8 -1
  30. package/dist/src/cli/handlers/subcommands.js +30 -0
  31. package/dist/src/cli/handlers/use.js +272 -89
  32. package/dist/src/cli/handlers/utilities.js +149 -0
  33. package/dist/src/cli/handlers/workspace.js +10 -0
  34. package/dist/src/cli/help-generator.js +2 -1
  35. package/dist/src/cli/regenerate-selector.js +94 -0
  36. package/dist/src/cli/router.js +4 -1
  37. package/dist/src/cli/services/deployment-verification.js +596 -0
  38. package/dist/src/cli/skill-usage.js +2 -2
  39. package/dist/src/cli/workflow-orchestrator.js +1 -1
  40. package/dist/src/cli/workspace-signals.js +2 -2
  41. package/dist/src/config/aiwg-config.js +54 -27
  42. package/dist/src/config/cli.js +3 -3
  43. package/dist/src/config/project-artifacts-health.js +2 -0
  44. package/dist/src/config/project-artifacts-health.mjs +123 -0
  45. package/dist/src/config/project-artifacts-runtime.mjs +16 -0
  46. package/dist/src/config/project-artifacts.js +2 -1
  47. package/dist/src/cost/fleet-report.js +329 -0
  48. package/dist/src/evidence/bundle.js +256 -0
  49. package/dist/src/extensions/commands/definitions.js +77 -25
  50. package/dist/src/extensions/deployment-registration.js +6 -4
  51. package/dist/src/extensions/project-local-doctor.js +10 -6
  52. package/dist/src/extensions/project-local-gitignore.js +8 -4
  53. package/dist/src/extensions/project-quickref.js +197 -10
  54. package/dist/src/features/catalog.js +26 -0
  55. package/dist/src/features/cli.js +1 -3
  56. package/dist/src/features/runtime.js +17 -1
  57. package/dist/src/issues/cli.js +91 -7
  58. package/dist/src/mcp/server.mjs +1 -1
  59. package/dist/src/ops/registry.js +2 -2
  60. package/dist/src/policy/authorization.js +2 -2
  61. package/dist/src/providers/capability-matrix.yaml +3 -3
  62. package/dist/src/providers/provider-definitions.js +7 -5
  63. package/dist/src/providers/provider-definitions.mjs +1 -1
  64. package/dist/src/serve/pty-bridge.js +2 -8
  65. package/dist/src/serve/screen-reader.js +3 -6
  66. package/dist/src/smiths/context-pipeline/aiwg-md.js +2 -2
  67. package/dist/src/smiths/context-pipeline/finalization.js +18 -5
  68. package/dist/src/smiths/context-pipeline/generator.js +2 -2
  69. package/dist/src/smiths/context-pipeline/workspace-context.js +16 -17
  70. package/package.json +2 -1
  71. package/tools/agents/deploy-agents.mjs +10 -11
  72. package/tools/agents/providers/base.mjs +47 -5
  73. package/tools/agents/providers/openclaw.mjs +5 -2
  74. package/tools/agents/providers/windsurf.mjs +13 -24
  75. package/tools/plugin/package-plugins.mjs +53 -0
  76. package/tools/skills/deploy-skills-codex.mjs +21 -5
package/README.md CHANGED
@@ -21,11 +21,23 @@ agents, CI, and web-backed installations.
21
21
 
22
22
  ```text
23
23
  Install or repair AIWG for this project by following
24
- https://raw.githubusercontent.com/jmagly/aiwg/main/setup.aiwg.yaml
24
+ https://aiwg.io/setup.aiwg.yaml
25
25
  Explain the plan before changing anything, preserve my existing work, and ask
26
26
  me only for choices you cannot safely determine.
27
27
  ```
28
28
 
29
+ The equivalent manual path is three steps:
30
+
31
+ ```bash
32
+ npm install --global aiwg
33
+ cd /path/to/your/project
34
+ aiwg use all --provider <provider>
35
+ ```
36
+
37
+ The final command deploys, refreshes indices and project context, verifies the
38
+ provider wiring, and reports one result. Standalone index, regenerate, status,
39
+ and doctor commands remain advanced maintenance and recovery tools.
40
+
29
41
  [![npm version](https://img.shields.io/npm/v/%40aiwg%2Fcli/latest?label=%40aiwg%2Fcli&color=CB3837&logo=npm&style=flat-square)](https://www.npmjs.com/package/@aiwg/cli)
30
42
  [![npm downloads](https://img.shields.io/npm/dm/%40aiwg%2Fcli?color=CB3837&logo=npm&style=flat-square)](https://www.npmjs.com/package/@aiwg/cli)
31
43
  [![full distribution](https://img.shields.io/npm/v/aiwg/latest?label=aiwg&color=CB3837&logo=npm&style=flat-square)](https://www.npmjs.com/package/aiwg)
@@ -221,7 +233,7 @@ offline operation is required.
221
233
 
222
234
  For a first installation, an uncertain environment, or a machine with an old
223
235
  or broken AIWG setup, use the full `aiwg` package and the
224
- [agentic installer manifest](https://raw.githubusercontent.com/jmagly/aiwg/main/setup.aiwg.yaml).
236
+ [agentic installer manifest](https://aiwg.io/setup.aiwg.yaml).
225
237
  The flow detects development checkouts and preserves development mode unless
226
238
  the user explicitly approves switching to the published package.
227
239
 
@@ -263,7 +275,7 @@ rather than merely printed.
263
275
  Agents do not need to memorize the remaining command surface. AIWG discovery
264
276
  finds the relevant skill, and the skill supplies the right CLI step. Operators
265
277
  who need the complete syntax and examples can use the
266
- [AIWG CLI reference](https://github.com/jmagly/aiwg/blob/main/docs/agents/cli-reference.md).
278
+ [AIWG CLI reference](https://github.com/jmagly/aiwg/blob/main/docs/cli/reference.md).
267
279
 
268
280
  ## How It Works
269
281
 
@@ -454,7 +466,7 @@ This README therefore documents the operating model, package boundary, trust
454
466
  model, and troubleshooting path instead of duplicating every command and flag.
455
467
  The complete operator reference is maintained at:
456
468
 
457
- **[AIWG CLI Reference — every command and example](https://github.com/jmagly/aiwg/blob/main/docs/agents/cli-reference.md)**
469
+ **[AIWG CLI Reference — every command and example](https://github.com/jmagly/aiwg/blob/main/docs/cli/reference.md)**
458
470
 
459
471
  Keeping the command catalog in one canonical location prevents package
460
472
  documentation from drifting as the runtime grows.
@@ -508,7 +520,7 @@ security guidance.
508
520
  Do not routinely call `aiwg help` and place the full output in the model
509
521
  context. If a skill exists, use it. If a maintainer or operator needs an
510
522
  unfamiliar command, link to the canonical
511
- [CLI reference](https://github.com/jmagly/aiwg/blob/main/docs/agents/cli-reference.md) or retrieve only
523
+ [CLI reference](https://github.com/jmagly/aiwg/blob/main/docs/cli/reference.md) or retrieve only
512
524
  the relevant section.
513
525
 
514
526
  ## Using AIWG from a Web-Connected Chat
@@ -1064,7 +1076,7 @@ Package invariants include:
1064
1076
 
1065
1077
  ## Documentation
1066
1078
 
1067
- - [Complete AIWG CLI reference](https://github.com/jmagly/aiwg/blob/main/docs/agents/cli-reference.md)
1079
+ - [Complete AIWG CLI reference](https://github.com/jmagly/aiwg/blob/main/docs/cli/reference.md)
1068
1080
  - [AIWG documentation](https://docs.aiwg.io/)
1069
1081
  - [AIWG project README](https://github.com/jmagly/aiwg#readme)
1070
1082
  - [Web-backed resources guide](https://github.com/jmagly/aiwg/blob/main/docs/install/web-backed-resources.md)
@@ -1086,7 +1098,10 @@ opening a public issue.
1086
1098
 
1087
1099
  ## License
1088
1100
 
1089
- MIT. See the
1101
+ AIWG-authored code is MIT licensed. See the
1090
1102
  [AIWG license](https://github.com/jmagly/aiwg/blob/main/LICENSE).
1091
1103
 
1092
- The package includes its own copy of `LICENSE` in every published tarball.
1104
+ Runtime dependencies retain their own licenses. Every published tarball
1105
+ includes `LICENSE` and `THIRD_PARTY_NOTICES.md`; the latter identifies the
1106
+ reviewed Fortemi and Bytecask AGPL boundary, corresponding source links, and
1107
+ commands for inspecting the versions npm resolved.
@@ -0,0 +1,35 @@
1
+ # Third-party notices
2
+
3
+ AIWG-authored source is distributed under the MIT license in [`LICENSE`](LICENSE). AIWG also declares runtime dependencies that retain their own licenses. This notice does not replace those licenses or change their terms.
4
+
5
+ ## Fortemi Core
6
+
7
+ - Package: `@fortemi/core@2026.7.15`
8
+ - License declared by the package: `AGPL-3.0-only`
9
+ - Source: <https://github.com/Fortemi/fortemi-react/tree/5cab4ea2d3d4bb985ea0d38f8bcb1ea790b32cf7/packages/core>
10
+ - Source tag: <https://github.com/Fortemi/fortemi-react/tree/v2026.7.15/packages/core>
11
+ - Registry integrity: `sha512-49GThHQHzLFD2BbjgXB7AUznRrwtWo8MsH6IcFMhSmCKj/h+Q5j18EBpkwPHJfC5E7crp+rVzy/GcrT/PF1SXA==`
12
+
13
+ AIWG uses the `@fortemi/core/aiwg-index` and `@fortemi/core/aiwg-index-shard` entry points and selected validation/archive exports from the package root. These modules execute in the AIWG Node.js process.
14
+
15
+ ## Bytecask Core
16
+
17
+ - Reviewed package: `@bytecask/core@2026.7.5`
18
+ - License declared by the package: `AGPL-3.0-only`
19
+ - Source: <https://github.com/jmagly/bytecask/tree/bef7ba9590e74f8bfcd724e65928f2f84a5667d4/packages/core>
20
+ - Source tag: <https://github.com/jmagly/bytecask/tree/v2026.7.5/packages/core>
21
+ - Registry integrity: `sha512-CsLJqmw8lNuBxRLGdRzoDdZ4/2iQlluueaiiYOR+l39NOdoG5cfDel/g71QDopRpVEHJOw7hQ3QngmWmi5IjBw==`
22
+
23
+ Fortemi declares Bytecask as a runtime dependency. The reviewed AIWG lockfile resolves version `2026.7.5`; downstream npm resolution can select a later compatible version. Inspect the installed version with:
24
+
25
+ ```bash
26
+ npm ls @fortemi/core @bytecask/core
27
+ ```
28
+
29
+ Each installed dependency package includes its own `LICENSE` and `package.json`. To inspect the exact source reference for a different resolved version, run `npm view @fortemi/core@<version> repository license` or `npm view @bytecask/core@<version> repository license`.
30
+
31
+ ## Distribution boundary
32
+
33
+ The `aiwg` and `@aiwg/cli` npm archives do not copy Fortemi or Bytecask object code into their own tarballs. npm resolves those packages separately during installation. AIWG does, however, intentionally import Fortemi in-process at runtime, so separate archive delivery is not by itself a legal conclusion about whether execution forms a combined work.
34
+
35
+ The reviewed architecture and unresolved legal questions are recorded in [`docs/contributing/fortemi-agpl-runtime-boundary.md`](docs/contributing/fortemi-agpl-runtime-boundary.md). Operators who modify an AGPL-covered package or expose a modified version for remote network interaction should review the GNU AGPL requirements and obtain qualified legal advice for their distribution and deployment model.
@@ -323,9 +323,9 @@ providers:
323
323
  aggregated_output: true
324
324
 
325
325
  windsurf:
326
- display_name: Windsurf
327
- status: experimental
328
- # Windsurf is an IDE extension requiring VS Code host — daemon not supported
326
+ display_name: Devin Desktop
327
+ status: stable
328
+ # Devin Desktop uses the Windsurf compatibility surface and requires a VS Code host — daemon not supported
329
329
  daemon_tier: unsupported
330
330
  daemon_pty_adapter: false
331
331
  artifact_paths:
package/bin/aiwg.mjs CHANGED
@@ -67,9 +67,134 @@ function maybeHandleFastVersion(args) {
67
67
  return true;
68
68
  }
69
69
 
70
+ const FAST_HELP_TEXT = `
71
+ ◆ AIWG
72
+ ────────────────────────────────────────────────────────
73
+
74
+ Usage: aiwg <command> [options]
75
+
76
+ FRAMEWORK
77
+ use <framework> Deploy framework (sdlc, marketing, media-curator, research, forensics, security-engineering, ops, validation, knowledge-base, all)
78
+ use cockpit Install the opt-in @aiwg/cockpit package outside the base aiwg footprint
79
+ list List installed frameworks and addons
80
+ remove <id> Remove a framework or addon
81
+
82
+ PROJECT
83
+ new <name> Create new project with SDLC templates
84
+ init Create the baseline .aiwg/aiwg.config file
85
+ setup project CLI helper used by agents for repo/tracker/delivery/signing policy
86
+ quickref generate --project Generate the canonical project quickref skill (--dry-run previews deterministic output)
87
+ quickref deploy --project Deploy the project quickref to configured provider kernel surfaces
88
+
89
+ WORKSPACE
90
+ status Show workspace health and installed frameworks
91
+ migrate-workspace Migrate legacy .aiwg/ to framework-scoped structure
92
+ rollback-workspace Rollback workspace migration from backup
93
+
94
+ MCP SERVER
95
+ mcp serve Start AIWG MCP server (stdio transport)
96
+ mcp install [target] Generate MCP client config (claude, copilot, factory, cursor)
97
+ mcp info Show MCP server capabilities
98
+
99
+ TOOLSMITH
100
+ runtime-info Show runtime environment summary
101
+ runtime-info --discover Full tool discovery and catalog generation
102
+ runtime-info --check <tool> Check specific tool availability
103
+
104
+ CATALOG
105
+ catalog list List all models in catalog
106
+ catalog info <id> Show detailed model information
107
+ catalog search <q> Search models by query
108
+
109
+ DISCOVERY
110
+ discover "<phrase>" Find skills/agents/commands/rules by capability
111
+ show <type> <name> Stream the body of an indexed artifact
112
+ versions <list|resolve|show> Browse and resolve signed AIWG web resource releases
113
+ auth <login|status|logout> Authenticate for paid AIWG web resources
114
+ index <subcommand> Manage the artifact index (build/query/discover/deps/stats)
115
+ artifacts move --to <path> Move/rename the project AIWG artifact root and reindex
116
+
117
+ DISPATCH
118
+ run skill <name> Execute a script-bearing skill
119
+ run <script-name> Run a user-defined script from .aiwg/aiwg.config
120
+
121
+ FEATURES
122
+ features Show optional feature install status
123
+ cockpit [--status] Launch the opt-in AIWG Cockpit control plane
124
+
125
+ VALIDATION
126
+ validate-metadata [path] Validate AIWG component metadata (defaults to agentic/code)
127
+ context-firewall [scan] Audit provider context, trust, drift, poisoning signals, and budget
128
+ context-firewall baseline Plan or explicitly write the reviewed context baseline
129
+
130
+ METRICS
131
+ cost-report --fleet Observe OpenRouter per-bot MTD spend and correlate local activity
132
+
133
+ EVIDENCE
134
+ evidence export --output <dir> Package portable activity, report, source, eval, and provenance evidence
135
+ evidence verify <bundle> Verify every member hash and the bundle checkpoint
136
+
137
+ SCAFFOLDING
138
+ new-bundle <name> Create project-local bundle (--type extension|addon|framework|plugin|provider, --starter skill|rule|agent|minimal, --dry-run)
139
+ new-extension <name> Alias for new-bundle --type extension
140
+ new-addon <name> Alias for new-bundle --type addon
141
+ new-framework <name> Alias for new-bundle --type framework
142
+ new-plugin <name> Alias for new-bundle --type plugin
143
+ new-provider <name> Alias for new-bundle --type provider
144
+ add-agent <name> Add agent to existing bundle
145
+ add-command <name> Add command to existing bundle
146
+ add-skill <name> Add skill to existing bundle
147
+ scaffold-addon <name> [legacy] Use new-addon instead
148
+ scaffold-framework <name> [legacy] Use new-framework instead
149
+
150
+ PROMOTE
151
+ promote <name> Graduate project-local bundle to upstream (--to upstream|corpus, --dry-run, --cleanup)
152
+
153
+ RALPH LOOP
154
+ ralph "<task>" Execute iterative task loop (--completion, --max-iterations)
155
+ ralph-status Check current loop status
156
+ ralph-abort Abort running loop
157
+ ralph-resume Resume interrupted loop
158
+
159
+ MAINTENANCE
160
+ doctor Check installation health
161
+ version Show version and channel info
162
+ refresh Update AIWG and redeploy frameworks (formerly: sync)
163
+ update Update the active installation and re-deploy installed frameworks (alias: upgrade)
164
+ help Show this help message
165
+
166
+ CHANNEL
167
+ --use-dev [path] Customize AIWG live from a local clone or fork
168
+ --use-main Switch to edge channel (bleeding edge)
169
+ --use-stable Switch back to stable npm package
170
+ ────────────────────────────────────────────────────────
171
+
172
+ Providers: claude (default), copilot, factory, codex, cursor, opencode, warp, windsurf
173
+
174
+ Examples:
175
+ aiwg use sdlc Install SDLC framework
176
+ aiwg use sdlc --global Install user assets + lightweight project wiring
177
+ aiwg use cockpit Install opt-in Cockpit package
178
+ aiwg cockpit Launch Cockpit after install
179
+ aiwg discover "deploy" Find skills by capability
180
+ aiwg show skill intake-wizard Stream a skill body
181
+ aiwg doctor Check installation health
182
+ aiwg refresh Pull latest + redeploy frameworks
183
+ `;
184
+
185
+ function maybeHandleFastHelp(args) {
186
+ if (args.length !== 1) return false;
187
+ if (!['help', '--help', '-help', '-h'].includes(args[0])) return false;
188
+ process.stdout.write(`${FAST_HELP_TEXT}\n`);
189
+ return true;
190
+ }
191
+
70
192
  if (maybeHandleFastVersion(process.argv.slice(2))) {
71
193
  process.exit(0);
72
194
  }
195
+ if (maybeHandleFastHelp(process.argv.slice(2))) {
196
+ process.exit(0);
197
+ }
73
198
 
74
199
  // Preflight: verify dist/ is built before any of the dynamic imports below
75
200
  // try to resolve files that don't exist. Without this, a missing/incomplete
@@ -5,13 +5,14 @@
5
5
  * Provides typed/attributed edges, BFS/DFS traversal, community detection,
6
6
  * and shortest-path algorithms.
7
7
  *
8
- * Install: npm install graphology graphology-types graphology-operators graphology-traversal
8
+ * Enable with: aiwg features install graph
9
9
  *
10
10
  * @implements #728
11
11
  * @source @src/artifacts/graph-backend.ts
12
12
  * @tests @test/unit/artifacts/graphology-backend.test.ts
13
13
  */
14
14
  import { normalizeEdges } from '../types.js';
15
+ import { loadFeaturePackage } from '../../features/runtime.js';
15
16
  /**
16
17
  * Graphology-backed graph with rich traversal and operator ecosystem.
17
18
  *
@@ -31,13 +32,13 @@ export class GraphologyBackend {
31
32
  */
32
33
  static async create() {
33
34
  try {
34
- const graphology = await import('graphology');
35
+ const graphology = await loadFeaturePackage('graphology');
35
36
  const Graph = graphology.default ?? graphology;
36
37
  const graph = new Graph({ type: 'directed', multi: true });
37
38
  return new GraphologyBackend(graph);
38
39
  }
39
40
  catch {
40
- throw new Error('graphology backend requires: npm install graphology graphology-types graphology-operators graphology-traversal');
41
+ throw new Error('graphology backend is unavailable; run `aiwg features install graph`');
41
42
  }
42
43
  }
43
44
  // --- Mutation ---
@@ -6,13 +6,14 @@
6
6
  * (INTERSECT/EXCEPT/UNION), recursive CTE traversal, and cross-graph
7
7
  * federation via ATTACH DATABASE.
8
8
  *
9
- * Install: npm install better-sqlite3 @types/better-sqlite3
9
+ * Enable with: aiwg features install sqlite
10
10
  *
11
11
  * @implements #729
12
12
  * @source @src/artifacts/graph-backend.ts
13
13
  * @tests @test/unit/artifacts/sqlite-backend.test.ts
14
14
  */
15
15
  import { normalizeEdges } from '../types.js';
16
+ import { requireFeaturePackage } from '../../features/runtime.js';
16
17
  /**
17
18
  * SQLite-backed graph with persistent storage and native SQL operations.
18
19
  *
@@ -29,13 +30,11 @@ export class SqliteGraphBackend {
29
30
  */
30
31
  constructor(dbPath = ':memory:') {
31
32
  try {
32
- // Dynamic require so missing package gives a clear error
33
- // eslint-disable-next-line @typescript-eslint/no-require-imports
34
- const Database = require('better-sqlite3');
33
+ const Database = requireFeaturePackage('better-sqlite3');
35
34
  this.db = new Database(dbPath);
36
35
  }
37
36
  catch {
38
- throw new Error('sqlite backend requires: npm install better-sqlite3 @types/better-sqlite3');
37
+ throw new Error('sqlite backend is unavailable; run `aiwg features install sqlite`');
39
38
  }
40
39
  this.db.pragma('journal_mode = WAL');
41
40
  this.initSchema();
@@ -697,7 +697,7 @@ async function requireEmbeddingIndex(cwd, graph) {
697
697
  if (!deps.available) {
698
698
  console.error(`Error: semantic search needs optional dependencies: ${deps.missing.join(', ')}`);
699
699
  console.error('Install them to enable semantic features:');
700
- console.error(' npm install @xenova/transformers hnswlib-node');
700
+ console.error(' aiwg features install embeddings');
701
701
  return null;
702
702
  }
703
703
  const dir = resolveIndexDir(cwd, graph);
@@ -845,7 +845,7 @@ async function handleEmbed(args) {
845
845
  const deps = await checkEmbeddingDeps();
846
846
  if (!deps.available) {
847
847
  console.error(`Error: embedding needs optional dependencies: ${deps.missing.join(', ')}`);
848
- console.error(' npm install @xenova/transformers hnswlib-node');
848
+ console.error(' aiwg features install embeddings');
849
849
  process.exit(1);
850
850
  }
851
851
  const index = loadGraphIndexFile(cwd, 'metadata.json', graph);
@@ -72,6 +72,7 @@ Usage:
72
72
  aiwg corpus frontmatter-backfill [--write] [--out PATH]
73
73
  aiwg corpus profile-edges [--out PATH]
74
74
  aiwg corpus profile-similar --entity PROF-P-x [--top K] | --predict-collabs [--threshold T] [--out PATH]
75
+ aiwg corpus retrieval-lab --queries PATH --concepts PATH [--expected-scheme-hash SHA256] [--limit K] [--latency-ceiling MS] [--json] [--out PATH]
75
76
  aiwg corpus vision-extract --slug SLUG [--images DIR] [--out DIR] [--start N] [--end N] [--provider codex|command] [--command TMPL] [--model M] [--retries N] [--title T] [--force] [--rasterize PDF] [--dpi N]
76
77
 
77
78
  radar-init scaffolds radar sidecars (dry-run unless --write; skips existing).
@@ -98,6 +99,7 @@ snapshot computes one-shot corpus snapshot metrics and renders full markdown, te
98
99
  frontmatter-backfill adds minimal ref_id/title/year/pdf_hash frontmatter to legacy analysis docs lacking it (dry-run unless --write; additive, skips docs that already have frontmatter).
99
100
  profile-edges builds the profile→REF edge graph (first-class adjacency; reconciled against the citation graph so only edges to existing REFs are kept).
100
101
  profile-similar embeds person profiles (text-embedding; opt-in @xenova/transformers) → nearest researchers (--entity) or collaboration link-prediction (--predict-collabs).
102
+ retrieval-lab benchmarks current research-query and direct lexical baselines against vector, BM25, typed graph PPR, and RRF without changing production query behavior.
101
103
  vision-extract transcribes scanned page PNGs → per-page + combined Markdown via a provider-neutral vision adapter (codex | command template), resumable with retry/validation; --rasterize PDF first renders pages via pdftoppm.
102
104
  `;
103
105
  function radarInit(root, args) {
@@ -385,6 +387,31 @@ export async function corpusMain(args, cwd = process.cwd()) {
385
387
  const top = flagValue(rest, '--top') ? parseInt(flagValue(rest, '--top'), 10) : 10;
386
388
  return emit(renderSimilar(entity, profileSimilar(emb, entity, top)), flagValue(rest, '--out'), root);
387
389
  }
390
+ case 'retrieval-lab': {
391
+ const queries = flagValue(rest, '--queries');
392
+ const concepts = flagValue(rest, '--concepts');
393
+ if (!queries || !concepts)
394
+ throw new Error('retrieval-lab requires --queries <jsonl> and --concepts <json>');
395
+ const expectedSchemeHash = flagValue(rest, '--expected-scheme-hash');
396
+ if (expectedSchemeHash && !/^[0-9a-f]{64}$/i.test(expectedSchemeHash))
397
+ throw new Error('retrieval-lab --expected-scheme-hash must be a SHA-256 hex digest');
398
+ const limit = flagValue(rest, '--limit');
399
+ const latencyCeiling = flagValue(rest, '--latency-ceiling');
400
+ if (limit && (!Number.isInteger(Number(limit)) || Number(limit) < 1))
401
+ throw new Error('retrieval-lab --limit must be a positive integer');
402
+ if (latencyCeiling && (!Number.isFinite(Number(latencyCeiling)) || Number(latencyCeiling) <= 0))
403
+ throw new Error('retrieval-lab --latency-ceiling must be a positive number');
404
+ const { runRetrievalLab, renderRetrievalLab } = await import('./retrieval-lab.js');
405
+ const report = await runRetrievalLab({
406
+ root,
407
+ queriesPath: path.resolve(root, queries),
408
+ conceptsPath: path.resolve(root, concepts),
409
+ expectedSchemeHash,
410
+ ...(limit ? { limit: Number(limit) } : {}),
411
+ ...(latencyCeiling ? { latencyCeilingMs: Number(latencyCeiling) } : {}),
412
+ });
413
+ return emit(hasFlag(rest, '--json') ? `${JSON.stringify(report, null, 2)}\n` : renderRetrievalLab(report), flagValue(rest, '--out'), root);
414
+ }
388
415
  default:
389
416
  process.stderr.write(`Unknown corpus subcommand: ${sub}\n\n${HELP}`);
390
417
  throw new Error(`unknown corpus subcommand: ${sub}`);
@@ -17,6 +17,7 @@
17
17
  */
18
18
  import { loadProfiles, loadCorpus } from '../corpus-views/ref-parser.js';
19
19
  import { checkEmbeddingDeps, DEFAULT_EMBEDDING_MODEL } from '../embedding-index.js';
20
+ import { loadFeaturePackage } from '../../features/runtime.js';
20
21
  function cosine(a, b) {
21
22
  let dot = 0;
22
23
  // Vectors are L2-normalized at embed time (normalize: true), so dot == cosine.
@@ -31,7 +32,7 @@ function cosine(a, b) {
31
32
  export async function buildProfileEmbeddings(corpusRoot, model = DEFAULT_EMBEDDING_MODEL) {
32
33
  const deps = await checkEmbeddingDeps();
33
34
  if (!deps.available) {
34
- throw new Error(`profile embeddings need optional deps: ${deps.missing.join(', ')} (npm install @xenova/transformers)`);
35
+ throw new Error(`profile embeddings need optional deps: ${deps.missing.join(', ')}; run \`aiwg features install embeddings\``);
35
36
  }
36
37
  const titleByRef = new Map();
37
38
  for (const r of loadCorpus(corpusRoot).records)
@@ -52,7 +53,7 @@ export async function buildProfileEmbeddings(corpusRoot, model = DEFAULT_EMBEDDI
52
53
  texts.push(text);
53
54
  refs.push(new Set(p.corpusRefs));
54
55
  }
55
- const transformersMod = await (new Function('m', 'return import(m)'))('@xenova/transformers');
56
+ const transformersMod = await loadFeaturePackage('@xenova/transformers');
56
57
  const embed = await transformersMod.pipeline('feature-extraction', model);
57
58
  const vectors = [];
58
59
  for (const t of texts) {