@aiwg/cli 0.0.0-bootstrap.0 → 2026.7.17
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.
- package/README.md +21 -1
- package/bin/aiwg.mjs +349 -0
- package/dist/src/a2a/agent-card.js +145 -0
- package/dist/src/a2a/client.js +411 -0
- package/dist/src/a2a/hitl-cli.js +171 -0
- package/dist/src/a2a/hitl-driver.js +370 -0
- package/dist/src/a2a/hitl.js +181 -0
- package/dist/src/a2a/http.js +193 -0
- package/dist/src/a2a/jcs.js +128 -0
- package/dist/src/a2a/jws.js +187 -0
- package/dist/src/a2a/types.js +24 -0
- package/dist/src/a2a/webhook.js +240 -0
- package/dist/src/activity-log/cli.js +348 -0
- package/dist/src/activity-log/parser.js +81 -0
- package/dist/src/activity-log/types.js +50 -0
- package/dist/src/agents/agent-deployer.js +367 -0
- package/dist/src/agents/agent-packager.js +271 -0
- package/dist/src/agents/agent-validator.js +271 -0
- package/dist/src/agents/grounding/knowledge-base.js +161 -0
- package/dist/src/agents/grounding/types.js +12 -0
- package/dist/src/agents/index.js +10 -0
- package/dist/src/agents/packaged-agent-inventory.js +75 -0
- package/dist/src/agents/types.js +7 -0
- package/dist/src/api/index.d.ts +10 -0
- package/dist/src/api/index.js +10 -0
- package/dist/src/artifacts/address-parser.js +73 -0
- package/dist/src/artifacts/audit/cli.js +183 -0
- package/dist/src/artifacts/audit/drift.js +122 -0
- package/dist/src/artifacts/audit/types.js +12 -0
- package/dist/src/artifacts/backends/graphology-backend.js +160 -0
- package/dist/src/artifacts/backends/json-backend.js +129 -0
- package/dist/src/artifacts/backends/sqlite-backend.js +199 -0
- package/dist/src/artifacts/browser-export.js +622 -0
- package/dist/src/artifacts/capability-resolver.js +94 -0
- package/dist/src/artifacts/checksum-manifest.js +91 -0
- package/dist/src/artifacts/citation-parser.js +162 -0
- package/dist/src/artifacts/cli.js +1462 -0
- package/dist/src/artifacts/corpus-tools/citation-densify.js +311 -0
- package/dist/src/artifacts/corpus-tools/cli.js +393 -0
- package/dist/src/artifacts/corpus-tools/corpus-graph.js +225 -0
- package/dist/src/artifacts/corpus-tools/curator.js +186 -0
- package/dist/src/artifacts/corpus-tools/discovery-log.js +70 -0
- package/dist/src/artifacts/corpus-tools/funder-network.js +141 -0
- package/dist/src/artifacts/corpus-tools/induction-audit.js +233 -0
- package/dist/src/artifacts/corpus-tools/integrity-scan.js +202 -0
- package/dist/src/artifacts/corpus-tools/profile-communities.js +166 -0
- package/dist/src/artifacts/corpus-tools/profile-edges.js +72 -0
- package/dist/src/artifacts/corpus-tools/profile-embed.js +113 -0
- package/dist/src/artifacts/corpus-tools/profile-generate-fm.js +167 -0
- package/dist/src/artifacts/corpus-tools/profile-generate.js +181 -0
- package/dist/src/artifacts/corpus-tools/profile-metrics.js +98 -0
- package/dist/src/artifacts/corpus-tools/profile-status.js +86 -0
- package/dist/src/artifacts/corpus-tools/profile-temporal.js +139 -0
- package/dist/src/artifacts/corpus-tools/radar-init.js +93 -0
- package/dist/src/artifacts/corpus-tools/radar-report.js +118 -0
- package/dist/src/artifacts/corpus-tools/radar-shared.js +189 -0
- package/dist/src/artifacts/corpus-tools/radar-status.js +68 -0
- package/dist/src/artifacts/corpus-tools/sidecar-lint.js +233 -0
- package/dist/src/artifacts/corpus-tools/sidecar-repair.js +277 -0
- package/dist/src/artifacts/corpus-tools/snapshot.js +591 -0
- package/dist/src/artifacts/corpus-tools/source-types.js +164 -0
- package/dist/src/artifacts/corpus-tools/vision-extract.js +243 -0
- package/dist/src/artifacts/corpus-views/build.js +126 -0
- package/dist/src/artifacts/corpus-views/corpus-config.js +124 -0
- package/dist/src/artifacts/corpus-views/ref-parser.js +437 -0
- package/dist/src/artifacts/corpus-views/renderers.js +353 -0
- package/dist/src/artifacts/corpus-views/taxonomies.js +131 -0
- package/dist/src/artifacts/dep-graph.js +173 -0
- package/dist/src/artifacts/discover-facets.js +375 -0
- package/dist/src/artifacts/embedding-index.js +354 -0
- package/dist/src/artifacts/enrichment/cli.js +240 -0
- package/dist/src/artifacts/enrichment/prompt.js +47 -0
- package/dist/src/artifacts/enrichment/store.js +90 -0
- package/dist/src/artifacts/enrichment/types.js +12 -0
- package/dist/src/artifacts/fortemi-core-query-adapter.js +475 -0
- package/dist/src/artifacts/fortemi-core-sync.js +251 -0
- package/dist/src/artifacts/fortemi-shard-export.js +44 -0
- package/dist/src/artifacts/fulltext.js +108 -0
- package/dist/src/artifacts/graph-backend.js +51 -0
- package/dist/src/artifacts/graph-query.js +247 -0
- package/dist/src/artifacts/hybrid-query.js +225 -0
- package/dist/src/artifacts/index-builder.js +1089 -0
- package/dist/src/artifacts/index-reader.js +112 -0
- package/dist/src/artifacts/index-status.js +193 -0
- package/dist/src/artifacts/legacy-index-migration.js +169 -0
- package/dist/src/artifacts/move.js +154 -0
- package/dist/src/artifacts/operational-state.js +239 -0
- package/dist/src/artifacts/prebuilt-build-lock.js +49 -0
- package/dist/src/artifacts/query-engine.js +1955 -0
- package/dist/src/artifacts/source-graph.js +529 -0
- package/dist/src/artifacts/stats.js +169 -0
- package/dist/src/artifacts/types.js +606 -0
- package/dist/src/artifacts/views/cli.js +293 -0
- package/dist/src/artifacts/views/definition.js +170 -0
- package/dist/src/artifacts/views/store.js +149 -0
- package/dist/src/artifacts/views/types.js +8 -0
- package/dist/src/artifacts/watcher.js +255 -0
- package/dist/src/catalog/builtin-models.json +636 -0
- package/dist/src/catalog/cli.js +228 -0
- package/dist/src/catalog/cli.mjs +289 -0
- package/dist/src/catalog/index.js +15 -0
- package/dist/src/catalog/loader.js +217 -0
- package/dist/src/catalog/loader.mjs +251 -0
- package/dist/src/catalog/sources.json +41 -0
- package/dist/src/catalog/types.js +8 -0
- package/dist/src/channel/manager.mjs +504 -0
- package/dist/src/cli/agent-spawn.js +178 -0
- package/dist/src/cli/cli-extension-loader.js +245 -0
- package/dist/src/cli/command-log.js +275 -0
- package/dist/src/cli/config-loader.js +232 -0
- package/dist/src/cli/env.js +82 -0
- package/dist/src/cli/errors.js +150 -0
- package/dist/src/cli/find-package-root.js +40 -0
- package/dist/src/cli/git-hooks.js +250 -0
- package/dist/src/cli/handlers/agentcard.js +206 -0
- package/dist/src/cli/handlers/artifacts.js +76 -0
- package/dist/src/cli/handlers/best-practices-audit.js +280 -0
- package/dist/src/cli/handlers/cockpit.js +137 -0
- package/dist/src/cli/handlers/command-log.js +37 -0
- package/dist/src/cli/handlers/daemon.js +59 -0
- package/dist/src/cli/handlers/diagnose.js +300 -0
- package/dist/src/cli/handlers/execution-mode.js +105 -0
- package/dist/src/cli/handlers/feedback.js +341 -0
- package/dist/src/cli/handlers/help.js +147 -0
- package/dist/src/cli/handlers/index.js +302 -0
- package/dist/src/cli/handlers/init.js +179 -0
- package/dist/src/cli/handlers/install.js +129 -0
- package/dist/src/cli/handlers/issues.js +46 -0
- package/dist/src/cli/handlers/lint.js +42 -0
- package/dist/src/cli/handlers/local-executor.js +315 -0
- package/dist/src/cli/handlers/marketplace.js +168 -0
- package/dist/src/cli/handlers/mc.js +1010 -0
- package/dist/src/cli/handlers/models.js +352 -0
- package/dist/src/cli/handlers/packages.js +155 -0
- package/dist/src/cli/handlers/ralph-launcher.js +717 -0
- package/dist/src/cli/handlers/ralph.js +575 -0
- package/dist/src/cli/handlers/refresh.js +432 -0
- package/dist/src/cli/handlers/regenerate.js +336 -0
- package/dist/src/cli/handlers/repo-access.js +109 -0
- package/dist/src/cli/handlers/run.js +165 -0
- package/dist/src/cli/handlers/runtime-info.js +301 -0
- package/dist/src/cli/handlers/sandbox.js +197 -0
- package/dist/src/cli/handlers/scaffolding.js +149 -0
- package/dist/src/cli/handlers/script-runner.js +121 -0
- package/dist/src/cli/handlers/sdlc-accelerate.js +148 -0
- package/dist/src/cli/handlers/serve.js +1835 -0
- package/dist/src/cli/handlers/session.js +348 -0
- package/dist/src/cli/handlers/setup.js +440 -0
- package/dist/src/cli/handlers/skill-lint.js +367 -0
- package/dist/src/cli/handlers/skill-usage.js +74 -0
- package/dist/src/cli/handlers/steward.js +567 -0
- package/dist/src/cli/handlers/subcommands.js +1702 -0
- package/dist/src/cli/handlers/team.js +337 -0
- package/dist/src/cli/handlers/types.js +11 -0
- package/dist/src/cli/handlers/use.js +2772 -0
- package/dist/src/cli/handlers/utilities.js +703 -0
- package/dist/src/cli/handlers/version.js +134 -0
- package/dist/src/cli/handlers/workspace-context.js +93 -0
- package/dist/src/cli/handlers/workspace.js +126 -0
- package/dist/src/cli/help-generator.js +178 -0
- package/dist/src/cli/hooks/builtin/activity-log-hook.js +126 -0
- package/dist/src/cli/hooks/executor.js +96 -0
- package/dist/src/cli/hooks/index.js +15 -0
- package/dist/src/cli/hooks/registry.js +143 -0
- package/dist/src/cli/hooks/types.js +13 -0
- package/dist/src/cli/log.js +492 -0
- package/dist/src/cli/project-isolation/detect.js +70 -0
- package/dist/src/cli/project-isolation/index.js +7 -0
- package/dist/src/cli/project-isolation/signals.js +17 -0
- package/dist/src/cli/project-isolation/warning.js +102 -0
- package/dist/src/cli/prompt-utils.js +155 -0
- package/dist/src/cli/provider-deployment-plan.js +126 -0
- package/dist/src/cli/provider-resolution.js +119 -0
- package/dist/src/cli/router.js +305 -0
- package/dist/src/cli/scope-resolver.js +392 -0
- package/dist/src/cli/skill-usage.js +616 -0
- package/dist/src/cli/ui.js +224 -0
- package/dist/src/cli/watch-service.js +203 -0
- package/dist/src/cli/workflow-orchestrator.js +478 -0
- package/dist/src/cli/workspace-signals.js +321 -0
- package/dist/src/community/footer.js +14 -0
- package/dist/src/community/links.js +123 -0
- package/dist/src/community/milestones.js +46 -0
- package/dist/src/community/nudge-policy.js +93 -0
- package/dist/src/config/aiwg-config.js +883 -0
- package/dist/src/config/cli.js +703 -0
- package/dist/src/config/gitignore.js +156 -0
- package/dist/src/config/project-artifacts.js +76 -0
- package/dist/src/config/user-config.js +428 -0
- package/dist/src/config/user-registry.js +127 -0
- package/dist/src/config/workspace.js +276 -0
- package/dist/src/contributors/detect.js +39 -0
- package/dist/src/contributors/discover.js +172 -0
- package/dist/src/contributors/heuristic.js +186 -0
- package/dist/src/contributors/index.js +11 -0
- package/dist/src/contributors/types.js +13 -0
- package/dist/src/contributors/validation.js +116 -0
- package/dist/src/data/community.schema.json +43 -0
- package/dist/src/data/community.yaml +16 -0
- package/dist/src/extensions/capability-index.js +270 -0
- package/dist/src/extensions/claude-hooks-installer.js +268 -0
- package/dist/src/extensions/commands/definitions.js +3485 -0
- package/dist/src/extensions/deployment-registration.js +463 -0
- package/dist/src/extensions/index.js +22 -0
- package/dist/src/extensions/loader.js +132 -0
- package/dist/src/extensions/managed-marker.js +100 -0
- package/dist/src/extensions/manifest.js +196 -0
- package/dist/src/extensions/project-local-activity.js +114 -0
- package/dist/src/extensions/project-local-discovery.js +261 -0
- package/dist/src/extensions/project-local-doctor.js +281 -0
- package/dist/src/extensions/project-local-gitignore.js +176 -0
- package/dist/src/extensions/project-local-paths.js +121 -0
- package/dist/src/extensions/project-local-promote.js +218 -0
- package/dist/src/extensions/project-local-remove.js +373 -0
- package/dist/src/extensions/project-local-scaffold.js +252 -0
- package/dist/src/extensions/project-quickref.js +291 -0
- package/dist/src/extensions/registry.js +368 -0
- package/dist/src/extensions/shadow-resolver.js +271 -0
- package/dist/src/extensions/types.js +86 -0
- package/dist/src/extensions/upstream-registry.js +195 -0
- package/dist/src/extensions/validation.js +631 -0
- package/dist/src/features/catalog.js +88 -0
- package/dist/src/features/cli.js +197 -0
- package/dist/src/features/installer.js +57 -0
- package/dist/src/features/paths.js +14 -0
- package/dist/src/features/runtime.js +21 -0
- package/dist/src/features/status.js +134 -0
- package/dist/src/hooks/laziness-detection.js +532 -0
- package/dist/src/intake/git-history-analyzer.js +486 -0
- package/dist/src/intake/index.js +9 -0
- package/dist/src/issues/cli.js +327 -0
- package/dist/src/issues/index.js +5 -0
- package/dist/src/issues/live.js +154 -0
- package/dist/src/issues/local.js +666 -0
- package/dist/src/issues/sync.js +143 -0
- package/dist/src/issues/types.js +2 -0
- package/dist/src/issues/workflows.js +164 -0
- package/dist/src/kb/cli.js +173 -0
- package/dist/src/lint/cli.js +171 -0
- package/dist/src/lint/loader.js +225 -0
- package/dist/src/lint/reporters.js +141 -0
- package/dist/src/lint/runner.js +364 -0
- package/dist/src/lint/types.js +10 -0
- package/dist/src/marketplace/cache.js +110 -0
- package/dist/src/marketplace/identifier.js +63 -0
- package/dist/src/marketplace/registry.js +36 -0
- package/dist/src/marketplace/sources/clawhub.js +53 -0
- package/dist/src/marketplace/sources/git.js +45 -0
- package/dist/src/marketplace/types.js +9 -0
- package/dist/src/mcp/adapters/codex-runtime.js +224 -0
- package/dist/src/mcp/cli.mjs +1197 -0
- package/dist/src/mcp/elicitation.mjs +149 -0
- package/dist/src/mcp/helpers.mjs +287 -0
- package/dist/src/mcp/index.mjs +11 -0
- package/dist/src/mcp/profiles.js +263 -0
- package/dist/src/mcp/profiles.mjs +360 -0
- package/dist/src/mcp/registry.js +376 -0
- package/dist/src/mcp/registry.mjs +387 -0
- package/dist/src/mcp/server.mjs +633 -0
- package/dist/src/mcp/test-simple.mjs +271 -0
- package/dist/src/mcp/tools/command-run.mjs +101 -0
- package/dist/src/mcp/tools/discovery.mjs +291 -0
- package/dist/src/mcp/tools/interaction.mjs +87 -0
- package/dist/src/mcp/tools/orchestration.mjs +320 -0
- package/dist/src/mcp/tools/subsystems.mjs +640 -0
- package/dist/src/memory/cli.js +166 -0
- package/dist/src/memory/project-registry.js +282 -0
- package/dist/src/metrics/artifact-metrics.js +184 -0
- package/dist/src/metrics/context-budget.js +174 -0
- package/dist/src/metrics/token-counter.js +133 -0
- package/dist/src/models/config-loader.js +228 -0
- package/dist/src/models/index.js +22 -0
- package/dist/src/models/model-capabilities.v1.json +120 -0
- package/dist/src/models/model-catalog.v1.json +96 -0
- package/dist/src/models/model-discovery.js +521 -0
- package/dist/src/models/provider-models.js +73 -0
- package/dist/src/models/provider-policy.js +273 -0
- package/dist/src/models/resolver.js +245 -0
- package/dist/src/models/router.js +70 -0
- package/dist/src/models/types.js +8 -0
- package/dist/src/models/wrapper-deployment.js +178 -0
- package/dist/src/models/wrapper-route.js +54 -0
- package/dist/src/ops/cli.js +268 -0
- package/dist/src/ops/registry.js +623 -0
- package/dist/src/packages/adapters/clawhub.js +113 -0
- package/dist/src/packages/adapters/git.js +153 -0
- package/dist/src/packages/adapters/gitea.js +93 -0
- package/dist/src/packages/adapters/github.js +69 -0
- package/dist/src/packages/adapters/local-cache.js +89 -0
- package/dist/src/packages/package-registry.js +143 -0
- package/dist/src/packages/registry.js +238 -0
- package/dist/src/packages/types.js +11 -0
- package/dist/src/plugin/cross-framework-ops.js +475 -0
- package/dist/src/plugin/framework-config-loader.js +235 -0
- package/dist/src/plugin/framework-detector.js +186 -0
- package/dist/src/plugin/framework-isolator.js +341 -0
- package/dist/src/plugin/framework-migration.js +371 -0
- package/dist/src/plugin/metadata-validator.js +906 -0
- package/dist/src/plugin/plugin-installer.js +436 -0
- package/dist/src/plugin/plugin-status.js +369 -0
- package/dist/src/plugin/plugin-uninstaller.js +473 -0
- package/dist/src/plugin/registry-validator.js +344 -0
- package/dist/src/plugin/skill-command-translator.js +415 -0
- package/dist/src/plugin/workspace-creator.js +189 -0
- package/dist/src/plugin/workspace-migrator.js +821 -0
- package/dist/src/policy/authorization.js +390 -0
- package/dist/src/policy/repo-access.js +215 -0
- package/dist/src/provenance/cli.js +16 -0
- package/dist/src/providers/capability-matrix.js +300 -0
- package/dist/src/providers/capability-matrix.yaml +514 -0
- package/dist/src/providers/provider-definitions.js +977 -0
- package/dist/src/providers/provider-definitions.mjs +159 -0
- package/dist/src/providers/provider-inventory.js +169 -0
- package/dist/src/quality/feedback-ab.js +174 -0
- package/dist/src/quality/feedback-collector.js +176 -0
- package/dist/src/quality/feedback-tracker.js +123 -0
- package/dist/src/quality/patterns/adr.json +24 -0
- package/dist/src/quality/patterns/sad.json +24 -0
- package/dist/src/quality/patterns/test-plan.json +24 -0
- package/dist/src/quality/patterns/use-case.json +24 -0
- package/dist/src/quality/scoring.js +157 -0
- package/dist/src/reflections/cli.js +15 -0
- package/dist/src/release/plan.js +139 -0
- package/dist/src/research/cache/manager.js +227 -0
- package/dist/src/research/clients/arxiv.js +156 -0
- package/dist/src/research/clients/base.js +197 -0
- package/dist/src/research/clients/crossref.js +112 -0
- package/dist/src/research/clients/semantic-scholar.js +126 -0
- package/dist/src/research/clients/unpaywall.js +87 -0
- package/dist/src/research/index.js +14 -0
- package/dist/src/research/query-cli.js +336 -0
- package/dist/src/research/services/acquisition.js +313 -0
- package/dist/src/research/services/archival.js +225 -0
- package/dist/src/research/services/citation.js +279 -0
- package/dist/src/research/services/discovery.js +243 -0
- package/dist/src/research/services/documentation.js +269 -0
- package/dist/src/research/services/index.js +14 -0
- package/dist/src/research/services/provenance.js +279 -0
- package/dist/src/research/services/quality.js +370 -0
- package/dist/src/research/services/types.js +7 -0
- package/dist/src/research/storage-cli.js +20 -0
- package/dist/src/research/types.js +47 -0
- package/dist/src/resources/index.d.ts +2 -0
- package/dist/src/resources/index.js +2 -0
- package/dist/src/resources/web-release.d.ts +89 -0
- package/dist/src/resources/web-release.js +882 -0
- package/dist/src/rlm/cache/cli.js +162 -0
- package/dist/src/rlm/cache/hash.js +35 -0
- package/dist/src/rlm/cache/store.js +170 -0
- package/dist/src/rlm/cache/types.js +8 -0
- package/dist/src/rlm/cli.js +650 -0
- package/dist/src/serve/a2a-terminal-observer.js +120 -0
- package/dist/src/serve/agent-router.js +205 -0
- package/dist/src/serve/dispatch-router.js +171 -0
- package/dist/src/serve/executor-registry.js +715 -0
- package/dist/src/serve/mission-conductor.js +177 -0
- package/dist/src/serve/orchestrator-adapter.js +113 -0
- package/dist/src/serve/orchestrator-override.js +94 -0
- package/dist/src/serve/orchestrator-pty.js +133 -0
- package/dist/src/serve/pty-bridge.js +799 -0
- package/dist/src/serve/sandbox-registry.js +832 -0
- package/dist/src/serve/screen-reader.js +228 -0
- package/dist/src/serve/stack-adapters.js +68 -0
- package/dist/src/serve/telemetry.js +143 -0
- package/dist/src/skills/adapters/clawhub.js +250 -0
- package/dist/src/skills/adapters/local.js +335 -0
- package/dist/src/skills/adapters/openclaw.js +316 -0
- package/dist/src/skills/cli.js +334 -0
- package/dist/src/skills/registry.js +117 -0
- package/dist/src/skills/run.js +259 -0
- package/dist/src/skills/runtime.js +94 -0
- package/dist/src/skills/types.js +10 -0
- package/dist/src/smiths/agentsmith/demo.js +116 -0
- package/dist/src/smiths/agentsmith/examples.js +300 -0
- package/dist/src/smiths/agentsmith/generator.js +503 -0
- package/dist/src/smiths/agentsmith/index.js +11 -0
- package/dist/src/smiths/agentsmith/types.js +8 -0
- package/dist/src/smiths/commandsmith/example.js +220 -0
- package/dist/src/smiths/commandsmith/generator.js +288 -0
- package/dist/src/smiths/commandsmith/index.js +41 -0
- package/dist/src/smiths/commandsmith/templates.js +296 -0
- package/dist/src/smiths/commandsmith/types.js +7 -0
- package/dist/src/smiths/context-pipeline/aiwg-md.js +104 -0
- package/dist/src/smiths/context-pipeline/allowlist.js +195 -0
- package/dist/src/smiths/context-pipeline/claude-hook.js +127 -0
- package/dist/src/smiths/context-pipeline/discovery.js +187 -0
- package/dist/src/smiths/context-pipeline/external-links-section.js +49 -0
- package/dist/src/smiths/context-pipeline/finalization.js +147 -0
- package/dist/src/smiths/context-pipeline/generator.js +477 -0
- package/dist/src/smiths/context-pipeline/index.js +30 -0
- package/dist/src/smiths/context-pipeline/legacy-inject.js +103 -0
- package/dist/src/smiths/context-pipeline/managed-hook.js +95 -0
- package/dist/src/smiths/context-pipeline/overflow.js +212 -0
- package/dist/src/smiths/context-pipeline/parallelism-section.js +94 -0
- package/dist/src/smiths/context-pipeline/provider-policy.js +64 -0
- package/dist/src/smiths/context-pipeline/sanitizer.js +93 -0
- package/dist/src/smiths/context-pipeline/types.js +23 -0
- package/dist/src/smiths/context-pipeline/workspace-context.js +988 -0
- package/dist/src/smiths/hook-bridge/codex-translator.js +129 -0
- package/dist/src/smiths/hook-bridge/copilot-translator.js +64 -0
- package/dist/src/smiths/hook-bridge/factory-translator.js +43 -0
- package/dist/src/smiths/hook-bridge/hermes-translator.js +88 -0
- package/dist/src/smiths/hook-bridge/index.js +79 -0
- package/dist/src/smiths/hook-bridge/loader.js +116 -0
- package/dist/src/smiths/hook-bridge/shim.js +89 -0
- package/dist/src/smiths/hook-bridge/types.js +31 -0
- package/dist/src/smiths/index.js +39 -0
- package/dist/src/smiths/mcpsmith/analyzers/cli-analyzer.js +390 -0
- package/dist/src/smiths/mcpsmith/example.js +119 -0
- package/dist/src/smiths/mcpsmith/generator.js +236 -0
- package/dist/src/smiths/mcpsmith/index.js +17 -0
- package/dist/src/smiths/mcpsmith/types.js +10 -0
- package/dist/src/smiths/platform-paths.js +101 -0
- package/dist/src/smiths/skillsmith/codex-sidecar.js +85 -0
- package/dist/src/smiths/skillsmith/collision-detector.js +249 -0
- package/dist/src/smiths/skillsmith/demo.js +83 -0
- package/dist/src/smiths/skillsmith/examples.js +161 -0
- package/dist/src/smiths/skillsmith/generator.js +316 -0
- package/dist/src/smiths/skillsmith/index.js +12 -0
- package/dist/src/smiths/skillsmith/namespace-adapter.js +180 -0
- package/dist/src/smiths/skillsmith/platform-resolver.js +157 -0
- package/dist/src/smiths/skillsmith/types.js +9 -0
- package/dist/src/smiths/toolsmith/index.js +10 -0
- package/dist/src/smiths/toolsmith/runtime-discovery.mjs +710 -0
- package/dist/src/smiths/toolsmith/types.js +8 -0
- package/dist/src/storage/backends/fortemi.js +227 -0
- package/dist/src/storage/backends/fs.js +134 -0
- package/dist/src/storage/backends/logseq.js +309 -0
- package/dist/src/storage/backends/obsidian.js +233 -0
- package/dist/src/storage/cli.js +468 -0
- package/dist/src/storage/config.js +272 -0
- package/dist/src/storage/index.js +108 -0
- package/dist/src/storage/subsystem-cli.js +201 -0
- package/dist/src/storage/types.js +33 -0
- package/dist/src/testing/corpus/corpus-builder.js +383 -0
- package/dist/src/testing/corpus/ground-truth-manager.js +460 -0
- package/dist/src/testing/corpus/index.js +10 -0
- package/dist/src/testing/fixtures/index.js +9 -0
- package/dist/src/testing/fixtures/test-data-factory.js +472 -0
- package/dist/src/testing/generators/index.js +11 -0
- package/dist/src/testing/generators/test-case-generator.js +393 -0
- package/dist/src/testing/generators/test-code-generator.js +384 -0
- package/dist/src/testing/generators/use-case-parser.js +325 -0
- package/dist/src/testing/index.js +11 -0
- package/dist/src/tracker/capability-protocol.js +118 -0
- package/dist/src/update/checker.mjs +396 -0
- package/dist/src/update/notifier.mjs +235 -0
- package/dist/src/writing/content-diversifier.js +804 -0
- package/dist/src/writing/example-generator.js +959 -0
- package/dist/src/writing/example-templates.js +99 -0
- package/dist/src/writing/pattern-library.js +486 -0
- package/dist/src/writing/patterns/banned-phrases.json +4413 -0
- package/dist/src/writing/patterns/formulaic-structures.json +1300 -0
- package/dist/src/writing/patterns/generic-adjectives.json +1510 -0
- package/dist/src/writing/patterns/hedging-language.json +2096 -0
- package/dist/src/writing/patterns/transition-words.json +1285 -0
- package/dist/src/writing/patterns/weak-verbs.json +1112 -0
- package/dist/src/writing/prompt-optimizer.js +660 -0
- package/dist/src/writing/prompt-templates.js +583 -0
- package/dist/src/writing/scoring-config-loader.js +168 -0
- package/dist/src/writing/validation-engine.js +595 -0
- package/dist/src/writing/validation-rules.js +380 -0
- package/dist/src/writing/voice-analyzer.js +439 -0
- package/dist/src/writing/voice-calibration.js +661 -0
- package/dist/src/writing/voice-profiles.json +588 -0
- package/package.json +64 -9
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Embedding Index
|
|
3
|
+
*
|
|
4
|
+
* Optional ANN (approximate nearest neighbor) layer on top of the artifact
|
|
5
|
+
* index. Embeds node summaries/titles, or opt-in chunked source bodies, into
|
|
6
|
+
* dense vectors using a small local model and stores them in an HNSW index for
|
|
7
|
+
* fast similarity queries.
|
|
8
|
+
*
|
|
9
|
+
* Install: npm install @xenova/transformers hnswlib-node
|
|
10
|
+
*
|
|
11
|
+
* @implements #730
|
|
12
|
+
* @source @src/artifacts/types.ts
|
|
13
|
+
* @tests @test/unit/artifacts/embedding-index.test.ts
|
|
14
|
+
*/
|
|
15
|
+
import fs from 'fs';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
/**
|
|
18
|
+
* Default embedding model (all-MiniLM-L6-v2: ~22MB, 384 dims, ~5ms/embedding on CPU)
|
|
19
|
+
*/
|
|
20
|
+
export const DEFAULT_EMBEDDING_MODEL = 'Xenova/all-MiniLM-L6-v2';
|
|
21
|
+
export const DEFAULT_EMBEDDING_DIMS = 384;
|
|
22
|
+
const DEFAULT_MAX_EMBEDDING_BODY_BYTES = 256 * 1024;
|
|
23
|
+
const DEFAULT_BODY_CHUNK_CHARS = 1400;
|
|
24
|
+
const DEFAULT_BODY_CHUNK_OVERLAP_CHARS = 200;
|
|
25
|
+
const DEFAULT_MAX_BODY_CHUNKS = 48;
|
|
26
|
+
const BINARY_SOURCE_EXTENSIONS = new Set([
|
|
27
|
+
'.7z', '.a', '.avi', '.bin', '.bmp', '.bz2', '.class', '.dll', '.doc',
|
|
28
|
+
'.docx', '.dylib', '.exe', '.gif', '.gz', '.ico', '.jar', '.jpeg', '.jpg',
|
|
29
|
+
'.mov', '.mp3', '.mp4', '.o', '.odt', '.pdf', '.png', '.ppt', '.pptx',
|
|
30
|
+
'.so', '.tar', '.tgz', '.war', '.webp', '.xls', '.xlsx', '.zip',
|
|
31
|
+
]);
|
|
32
|
+
function stripFrontmatter(text) {
|
|
33
|
+
if (!text.startsWith('---'))
|
|
34
|
+
return text;
|
|
35
|
+
const match = text.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);
|
|
36
|
+
return match ? text.slice(match[0].length) : text;
|
|
37
|
+
}
|
|
38
|
+
function looksBinary(buffer) {
|
|
39
|
+
if (buffer.includes(0))
|
|
40
|
+
return true;
|
|
41
|
+
const sample = buffer.subarray(0, Math.min(buffer.length, 4096)).toString('utf-8');
|
|
42
|
+
if (sample.length === 0)
|
|
43
|
+
return false;
|
|
44
|
+
const replacementCount = (sample.match(/\uFFFD/g) ?? []).length;
|
|
45
|
+
return replacementCount / sample.length > 0.01;
|
|
46
|
+
}
|
|
47
|
+
function metadataTextForEntry(entry) {
|
|
48
|
+
return [
|
|
49
|
+
`title: ${entry.title}`,
|
|
50
|
+
entry.name ? `name: ${entry.name}` : '',
|
|
51
|
+
`type: ${entry.type}`,
|
|
52
|
+
entry.kind ? `kind: ${entry.kind}` : '',
|
|
53
|
+
entry.sourceType ? `source type: ${entry.sourceType}` : '',
|
|
54
|
+
entry.capability ? `capability: ${entry.capability}` : '',
|
|
55
|
+
entry.summary ? `summary: ${entry.summary}` : '',
|
|
56
|
+
entry.tags.length > 0 ? `tags: ${entry.tags.join(', ')}` : '',
|
|
57
|
+
entry.triggers?.length ? `triggers: ${entry.triggers.join('; ')}` : '',
|
|
58
|
+
entry.searchTerms?.length ? `search terms: ${entry.searchTerms.join('; ')}` : '',
|
|
59
|
+
].filter(Boolean).join('\n');
|
|
60
|
+
}
|
|
61
|
+
function chunkText(text, chunkChars, overlapChars, maxChunks) {
|
|
62
|
+
const normalized = text.replace(/\s+/g, ' ').trim();
|
|
63
|
+
if (!normalized)
|
|
64
|
+
return [];
|
|
65
|
+
const size = Math.max(200, chunkChars);
|
|
66
|
+
const overlap = Math.max(0, Math.min(overlapChars, size - 1));
|
|
67
|
+
const chunks = [];
|
|
68
|
+
let start = 0;
|
|
69
|
+
while (start < normalized.length && chunks.length < maxChunks) {
|
|
70
|
+
let end = Math.min(start + size, normalized.length);
|
|
71
|
+
if (end < normalized.length) {
|
|
72
|
+
const boundary = normalized.lastIndexOf(' ', end);
|
|
73
|
+
if (boundary > start + Math.floor(size * 0.6))
|
|
74
|
+
end = boundary;
|
|
75
|
+
}
|
|
76
|
+
chunks.push(normalized.slice(start, end).trim());
|
|
77
|
+
if (end >= normalized.length)
|
|
78
|
+
break;
|
|
79
|
+
start = Math.max(end - overlap, start + 1);
|
|
80
|
+
}
|
|
81
|
+
return chunks.filter(Boolean);
|
|
82
|
+
}
|
|
83
|
+
function sourceBodyForEntry(cwd, entry, maxBytes) {
|
|
84
|
+
const sourcePath = path.isAbsolute(entry.path) ? entry.path : path.join(cwd, entry.path);
|
|
85
|
+
try {
|
|
86
|
+
const stat = fs.statSync(sourcePath);
|
|
87
|
+
if (!stat.isFile() || stat.size > maxBytes)
|
|
88
|
+
return '';
|
|
89
|
+
if (BINARY_SOURCE_EXTENSIONS.has(path.extname(sourcePath).toLowerCase()))
|
|
90
|
+
return '';
|
|
91
|
+
const buffer = fs.readFileSync(sourcePath);
|
|
92
|
+
if (looksBinary(buffer))
|
|
93
|
+
return '';
|
|
94
|
+
return stripFrontmatter(buffer.toString('utf-8')).trim();
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return '';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export function embeddingTextForEntry(entry, options = {}) {
|
|
101
|
+
return embeddingTextsForEntry(entry, options).join('\n\n');
|
|
102
|
+
}
|
|
103
|
+
export function embeddingTextsForEntry(entry, options = {}) {
|
|
104
|
+
const metadataText = metadataTextForEntry(entry);
|
|
105
|
+
if (options.granularity !== 'body')
|
|
106
|
+
return [metadataText];
|
|
107
|
+
const bodyText = options.cwd
|
|
108
|
+
? sourceBodyForEntry(options.cwd, entry, options.maxSourceBodyBytes ?? DEFAULT_MAX_EMBEDDING_BODY_BYTES)
|
|
109
|
+
: '';
|
|
110
|
+
if (!bodyText)
|
|
111
|
+
return [metadataText];
|
|
112
|
+
const chunks = chunkText(bodyText, options.bodyChunkChars ?? DEFAULT_BODY_CHUNK_CHARS, options.bodyChunkOverlapChars ?? DEFAULT_BODY_CHUNK_OVERLAP_CHARS, options.maxBodyChunks ?? DEFAULT_MAX_BODY_CHUNKS);
|
|
113
|
+
return chunks.length > 0 ? chunks.map(chunk => [metadataText, chunk].join('\n\n')) : [metadataText];
|
|
114
|
+
}
|
|
115
|
+
function normalizeVector(vector) {
|
|
116
|
+
const norm = Math.sqrt(vector.reduce((sum, value) => sum + value * value, 0));
|
|
117
|
+
if (norm === 0)
|
|
118
|
+
return vector;
|
|
119
|
+
return vector.map(value => value / norm);
|
|
120
|
+
}
|
|
121
|
+
async function embedEntryVector(embed, entry, options) {
|
|
122
|
+
const texts = embeddingTextsForEntry(entry, options);
|
|
123
|
+
const vectors = [];
|
|
124
|
+
for (const text of texts) {
|
|
125
|
+
const result = await embed(text, { pooling: 'mean', normalize: true });
|
|
126
|
+
vectors.push(Array.from(result.data));
|
|
127
|
+
}
|
|
128
|
+
if (vectors.length === 1)
|
|
129
|
+
return vectors[0];
|
|
130
|
+
const mean = new Array(vectors[0].length).fill(0);
|
|
131
|
+
for (const vector of vectors) {
|
|
132
|
+
for (let i = 0; i < vector.length; i++) {
|
|
133
|
+
mean[i] += vector[i];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return normalizeVector(mean.map(value => value / vectors.length));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Check if embedding dependencies are available.
|
|
140
|
+
*/
|
|
141
|
+
export async function checkEmbeddingDeps() {
|
|
142
|
+
const missing = [];
|
|
143
|
+
try {
|
|
144
|
+
await (new Function('m', 'return import(m)'))('@xenova/transformers');
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
missing.push('@xenova/transformers');
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
await (new Function('m', 'return import(m)'))('hnswlib-node');
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
missing.push('hnswlib-node');
|
|
154
|
+
}
|
|
155
|
+
return { available: missing.length === 0, missing };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Build an embedding index from artifact metadata entries.
|
|
159
|
+
*
|
|
160
|
+
* Embeds each entry into a dense vector and stores it in an HNSW index for
|
|
161
|
+
* fast approximate nearest-neighbor queries. Body granularity reads the source
|
|
162
|
+
* file, strips frontmatter, embeds bounded overlapping chunks, and stores the
|
|
163
|
+
* normalized mean vector for the node.
|
|
164
|
+
*
|
|
165
|
+
* @param entries - Map of node ID → MetadataEntry
|
|
166
|
+
* @param outputDir - Directory to write embeddings/ subfolder
|
|
167
|
+
* @param model - Transformer model identifier
|
|
168
|
+
* @returns Number of entries embedded
|
|
169
|
+
*/
|
|
170
|
+
export async function buildEmbeddingIndex(entries, outputDir, model = DEFAULT_EMBEDDING_MODEL, options = {}) {
|
|
171
|
+
const transformersMod = await (new Function('m', 'return import(m)'))('@xenova/transformers');
|
|
172
|
+
const { pipeline } = transformersMod;
|
|
173
|
+
const hnswlib = await (new Function('m', 'return import(m)'))('hnswlib-node');
|
|
174
|
+
const HierarchicalNSW = hnswlib.HierarchicalNSW ?? hnswlib.default?.HierarchicalNSW;
|
|
175
|
+
if (!HierarchicalNSW) {
|
|
176
|
+
throw new Error('hnswlib-node: HierarchicalNSW not found in module exports');
|
|
177
|
+
}
|
|
178
|
+
const embed = await pipeline('feature-extraction', model);
|
|
179
|
+
const ids = Object.keys(entries);
|
|
180
|
+
if (ids.length === 0)
|
|
181
|
+
return 0;
|
|
182
|
+
// Determine dimensions from a test embedding
|
|
183
|
+
const testResult = await embed('test', { pooling: 'mean', normalize: true });
|
|
184
|
+
const dims = testResult.data.length;
|
|
185
|
+
const index = new HierarchicalNSW('cosine', dims);
|
|
186
|
+
index.initIndex(Math.max(ids.length, 1));
|
|
187
|
+
const checksums = {};
|
|
188
|
+
for (let i = 0; i < ids.length; i++) {
|
|
189
|
+
const entry = entries[ids[i]];
|
|
190
|
+
const vector = await embedEntryVector(embed, entry, options);
|
|
191
|
+
index.addPoint(vector, i);
|
|
192
|
+
checksums[ids[i]] = entry.checksum;
|
|
193
|
+
}
|
|
194
|
+
// Write index and manifest
|
|
195
|
+
const embeddingsDir = path.join(outputDir, 'embeddings');
|
|
196
|
+
fs.mkdirSync(embeddingsDir, { recursive: true });
|
|
197
|
+
index.writeIndex(path.join(embeddingsDir, 'vectors.hnsw'));
|
|
198
|
+
const manifest = {
|
|
199
|
+
model,
|
|
200
|
+
dims,
|
|
201
|
+
nodeIds: ids,
|
|
202
|
+
builtAt: new Date().toISOString(),
|
|
203
|
+
checksums,
|
|
204
|
+
granularity: options.granularity === 'body' ? 'body' : 'title-summary',
|
|
205
|
+
};
|
|
206
|
+
fs.writeFileSync(path.join(embeddingsDir, 'manifest.json'), JSON.stringify(manifest, null, 2), 'utf-8');
|
|
207
|
+
return ids.length;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Load an embedding manifest from an index directory.
|
|
211
|
+
*/
|
|
212
|
+
export function loadEmbeddingManifest(indexDir) {
|
|
213
|
+
const manifestPath = path.join(indexDir, 'embeddings', 'manifest.json');
|
|
214
|
+
if (!fs.existsSync(manifestPath))
|
|
215
|
+
return null;
|
|
216
|
+
try {
|
|
217
|
+
return JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Query the embedding index for semantically similar artifacts.
|
|
225
|
+
*
|
|
226
|
+
* @param query - Natural language query string
|
|
227
|
+
* @param indexDir - Directory containing the embeddings/ subfolder
|
|
228
|
+
* @param topK - Number of results to return
|
|
229
|
+
* @returns Ranked list of semantic results
|
|
230
|
+
*/
|
|
231
|
+
export async function semanticQuery(query, indexDir, topK = 10) {
|
|
232
|
+
const manifest = loadEmbeddingManifest(indexDir);
|
|
233
|
+
if (!manifest) {
|
|
234
|
+
throw new Error(`No embedding index found at ${indexDir}/embeddings/`);
|
|
235
|
+
}
|
|
236
|
+
const transformersMod = await (new Function('m', 'return import(m)'))('@xenova/transformers');
|
|
237
|
+
const { pipeline } = transformersMod;
|
|
238
|
+
const hnswlib = await (new Function('m', 'return import(m)'))('hnswlib-node');
|
|
239
|
+
const HierarchicalNSW = hnswlib.HierarchicalNSW ?? hnswlib.default?.HierarchicalNSW;
|
|
240
|
+
if (!HierarchicalNSW) {
|
|
241
|
+
throw new Error('hnswlib-node: HierarchicalNSW not found in module exports');
|
|
242
|
+
}
|
|
243
|
+
const embed = await pipeline('feature-extraction', manifest.model);
|
|
244
|
+
const result = await embed(query, { pooling: 'mean', normalize: true });
|
|
245
|
+
const index = new HierarchicalNSW('cosine', manifest.dims);
|
|
246
|
+
// readIndexSync, not the async readIndex — the async form returns a promise
|
|
247
|
+
// that, if not awaited, leaves the index empty (getCurrentCount() === 0).
|
|
248
|
+
index.readIndexSync(path.join(indexDir, 'embeddings', 'vectors.hnsw'));
|
|
249
|
+
// setEfSearch controls recall quality — higher = better but slower
|
|
250
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
251
|
+
const idx = index;
|
|
252
|
+
if (typeof idx.setEfSearch === 'function') {
|
|
253
|
+
idx.setEfSearch(Math.max(topK * 2, 50));
|
|
254
|
+
}
|
|
255
|
+
const effectiveK = Math.min(topK, manifest.nodeIds.length);
|
|
256
|
+
const { neighbors, distances } = index.searchKnn(Array.from(result.data), effectiveK);
|
|
257
|
+
return neighbors.map((pos, i) => ({
|
|
258
|
+
nodeId: manifest.nodeIds[pos],
|
|
259
|
+
// HNSW cosine distance is 1 - cosine_similarity
|
|
260
|
+
score: 1 - (distances[i] ?? 0),
|
|
261
|
+
}));
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Get semantic neighbors of a specific node.
|
|
265
|
+
*
|
|
266
|
+
* @param nodeId - Node to find neighbors for
|
|
267
|
+
* @param entries - Metadata entries to get the node's text
|
|
268
|
+
* @param indexDir - Directory containing the embeddings/ subfolder
|
|
269
|
+
* @param topK - Number of results
|
|
270
|
+
*/
|
|
271
|
+
export async function semanticNeighbors(nodeId, entries, indexDir, topK = 10) {
|
|
272
|
+
const entry = entries[nodeId];
|
|
273
|
+
if (!entry) {
|
|
274
|
+
throw new Error(`Node '${nodeId}' not found in metadata`);
|
|
275
|
+
}
|
|
276
|
+
const queryText = `${entry.title} ${entry.summary}`.trim();
|
|
277
|
+
// Get topK + 1 since the node itself will likely be the top result
|
|
278
|
+
const results = await semanticQuery(queryText, indexDir, topK + 1);
|
|
279
|
+
// Filter out the query node itself
|
|
280
|
+
return results.filter(r => r.nodeId !== nodeId).slice(0, topK);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Determine which entries need re-embedding based on checksum changes.
|
|
284
|
+
*
|
|
285
|
+
* @param entries - Current metadata entries
|
|
286
|
+
* @param manifest - Existing embedding manifest
|
|
287
|
+
* @returns Object with entries that changed and entries that are new
|
|
288
|
+
*/
|
|
289
|
+
export function detectEmbeddingChanges(entries, manifest) {
|
|
290
|
+
const changed = [];
|
|
291
|
+
const added = [];
|
|
292
|
+
const removed = [];
|
|
293
|
+
const manifestIds = new Set(manifest.nodeIds);
|
|
294
|
+
const entryIds = new Set(Object.keys(entries));
|
|
295
|
+
for (const id of entryIds) {
|
|
296
|
+
if (!manifestIds.has(id)) {
|
|
297
|
+
added.push(id);
|
|
298
|
+
}
|
|
299
|
+
else if (entries[id].checksum !== manifest.checksums[id]) {
|
|
300
|
+
changed.push(id);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
for (const id of manifestIds) {
|
|
304
|
+
if (!entryIds.has(id)) {
|
|
305
|
+
removed.push(id);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return { changed, added, removed };
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Near-duplicate report (#1493). Reads the prebuilt embedding index and, using
|
|
312
|
+
* each stored vector (no re-embedding), finds node pairs whose cosine
|
|
313
|
+
* similarity is at or above `threshold`. Pairs are de-duplicated (unordered)
|
|
314
|
+
* and returned most-similar-first.
|
|
315
|
+
*
|
|
316
|
+
* Requires a built embedding index (`aiwg index embed`). Throws if absent.
|
|
317
|
+
*/
|
|
318
|
+
export async function dedupReport(indexDir, threshold = 0.92, topK = 5) {
|
|
319
|
+
const manifest = loadEmbeddingManifest(indexDir);
|
|
320
|
+
if (!manifest) {
|
|
321
|
+
throw new Error(`No embedding index found at ${indexDir}/embeddings/`);
|
|
322
|
+
}
|
|
323
|
+
const hnswlib = await (new Function('m', 'return import(m)'))('hnswlib-node');
|
|
324
|
+
const HierarchicalNSW = hnswlib.HierarchicalNSW ?? hnswlib.default?.HierarchicalNSW;
|
|
325
|
+
if (!HierarchicalNSW) {
|
|
326
|
+
throw new Error('hnswlib-node: HierarchicalNSW not found in module exports');
|
|
327
|
+
}
|
|
328
|
+
const index = new HierarchicalNSW('cosine', manifest.dims);
|
|
329
|
+
index.readIndexSync(path.join(indexDir, 'embeddings', 'vectors.hnsw'));
|
|
330
|
+
const idx = index;
|
|
331
|
+
const k = Math.min(topK + 1, manifest.nodeIds.length);
|
|
332
|
+
if (typeof idx.setEf === 'function')
|
|
333
|
+
idx.setEf(Math.max(k * 2, 50));
|
|
334
|
+
const seen = new Map();
|
|
335
|
+
for (let i = 0; i < manifest.nodeIds.length; i++) {
|
|
336
|
+
const vec = idx.getPoint(i);
|
|
337
|
+
const { neighbors, distances } = index.searchKnn(vec, k);
|
|
338
|
+
for (let n = 0; n < neighbors.length; n++) {
|
|
339
|
+
const j = neighbors[n];
|
|
340
|
+
if (j === i)
|
|
341
|
+
continue;
|
|
342
|
+
const score = 1 - (distances[n] ?? 0);
|
|
343
|
+
if (score < threshold)
|
|
344
|
+
continue;
|
|
345
|
+
const [a, b] = [manifest.nodeIds[i], manifest.nodeIds[j]].sort();
|
|
346
|
+
const key = `${a}|${b}`;
|
|
347
|
+
const prev = seen.get(key);
|
|
348
|
+
if (!prev || score > prev.score)
|
|
349
|
+
seen.set(key, { a, b, score });
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return [...seen.values()].sort((x, y) => y.score - x.score);
|
|
353
|
+
}
|
|
354
|
+
//# sourceMappingURL=embedding-index.js.map
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aiwg index enrich` subcommand router.
|
|
3
|
+
*
|
|
4
|
+
* Subcommands / flags:
|
|
5
|
+
* --using-rlm — emit enrichment plan(s) for an agent to dispatch
|
|
6
|
+
* --filter <expr> — restrict to artifacts matching expr
|
|
7
|
+
* --force — re-enrich even when enriched_hash matches
|
|
8
|
+
* --dry-run — count and estimate cost only
|
|
9
|
+
* --reset — drop all enrichment data
|
|
10
|
+
* --list — list current enrichment entries
|
|
11
|
+
* --apply --id <id> --result <path> — write a result back from agent dispatch
|
|
12
|
+
*
|
|
13
|
+
* Like `views build`, this CLI does NOT directly invoke RLM. It emits
|
|
14
|
+
* EnrichmentPlan records the agent acts on (dispatching /rlm-batch),
|
|
15
|
+
* then the agent writes results back via `--apply`.
|
|
16
|
+
*
|
|
17
|
+
* @implements #1204
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
20
|
+
import { join, resolve } from 'node:path';
|
|
21
|
+
import { computeHash } from '../../rlm/cache/hash.js';
|
|
22
|
+
import { ENRICHMENT_PROMPT, validateEnrichmentOutput } from './prompt.js';
|
|
23
|
+
import { computeContentHash, get as getEnrichment, has as hasEnrichment, list as listEnrichments, put as putEnrichment, reset as resetEnrichments, resolveSemanticRoot, } from './store.js';
|
|
24
|
+
export async function main(args) {
|
|
25
|
+
if (args.includes('--reset')) {
|
|
26
|
+
handleReset();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (args.includes('--list')) {
|
|
30
|
+
handleList(args);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (args.includes('--apply')) {
|
|
34
|
+
handleApply(args);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (args.includes('--using-rlm')) {
|
|
38
|
+
handleUsingRlm(args);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
printUsage();
|
|
42
|
+
if (args.length > 0) {
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function asJson(args) {
|
|
47
|
+
return args.includes('--json');
|
|
48
|
+
}
|
|
49
|
+
function flagValue(args, flag) {
|
|
50
|
+
const i = args.indexOf(flag);
|
|
51
|
+
return i !== -1 && args[i + 1] ? args[i + 1] : undefined;
|
|
52
|
+
}
|
|
53
|
+
function handleReset() {
|
|
54
|
+
const root = resolveSemanticRoot();
|
|
55
|
+
const r = resetEnrichments(root);
|
|
56
|
+
console.log(`Reset enrichment: removed ${r.removed} sidecar entries from ${root}`);
|
|
57
|
+
}
|
|
58
|
+
function handleList(args) {
|
|
59
|
+
const root = resolveSemanticRoot();
|
|
60
|
+
const summaries = listEnrichments(root, /* currentHashes */ {});
|
|
61
|
+
if (asJson(args)) {
|
|
62
|
+
console.log(JSON.stringify(summaries, null, 2));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (summaries.length === 0) {
|
|
66
|
+
console.log('No enrichment entries.');
|
|
67
|
+
console.log(`Semantic root: ${root}`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.log(`artifact symbols citations age stale`);
|
|
71
|
+
console.log(`───────────────────────────────────────────── ─────── ───────── ──── ─────`);
|
|
72
|
+
for (const s of summaries) {
|
|
73
|
+
const id = s.artifactId.length > 45 ? `…${s.artifactId.slice(-44)}` : s.artifactId.padEnd(45);
|
|
74
|
+
console.log(`${id} ${String(s.symbolCount).padStart(7)} ${String(s.citationCount).padStart(9)} ${String(s.ageDays).padStart(3)}d ${s.isStale ? 'YES' : ''}`);
|
|
75
|
+
}
|
|
76
|
+
console.log(`\n${summaries.length} entries at ${root}`);
|
|
77
|
+
}
|
|
78
|
+
function handleApply(args) {
|
|
79
|
+
const id = flagValue(args, '--id');
|
|
80
|
+
const result = flagValue(args, '--result');
|
|
81
|
+
if (!id || !result) {
|
|
82
|
+
console.error('Usage: aiwg index enrich --apply --id <id> --result <path-to-json>');
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (!existsSync(result)) {
|
|
87
|
+
console.error(`No file: ${result}`);
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
let parsed;
|
|
92
|
+
try {
|
|
93
|
+
parsed = JSON.parse(readFileSync(result, 'utf-8'));
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
console.error(`Failed to parse JSON: ${err.message}`);
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const issues = validateEnrichmentOutput(parsed);
|
|
101
|
+
if (issues.length > 0) {
|
|
102
|
+
console.error('Enrichment result validation failed:');
|
|
103
|
+
for (const i of issues)
|
|
104
|
+
console.error(` - ${i}`);
|
|
105
|
+
process.exitCode = 1;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// Read the artifact to compute its current hash
|
|
109
|
+
const absId = resolve(id);
|
|
110
|
+
if (!existsSync(absId)) {
|
|
111
|
+
console.error(`Artifact not found at ${absId} — cannot compute content hash`);
|
|
112
|
+
process.exitCode = 1;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const contentHash = computeContentHash(readFileSync(absId));
|
|
116
|
+
const r = parsed;
|
|
117
|
+
const fields = {
|
|
118
|
+
summary: r['summary'],
|
|
119
|
+
declaredSymbols: r['declared_symbols'],
|
|
120
|
+
citations: r['citations'],
|
|
121
|
+
inferredTags: r['inferred_tags'],
|
|
122
|
+
openQuestions: r['open_questions'],
|
|
123
|
+
enrichedAt: new Date().toISOString(),
|
|
124
|
+
enrichedBy: flagValue(args, '--by') ?? 'rlm-batch',
|
|
125
|
+
enrichedHash: contentHash,
|
|
126
|
+
};
|
|
127
|
+
const root = resolveSemanticRoot();
|
|
128
|
+
const file = putEnrichment(root, id, fields);
|
|
129
|
+
console.log(`Enrichment applied: ${id}`);
|
|
130
|
+
console.log(` Written: ${file}`);
|
|
131
|
+
}
|
|
132
|
+
function handleUsingRlm(args) {
|
|
133
|
+
const filter = flagValue(args, '--filter');
|
|
134
|
+
const force = args.includes('--force');
|
|
135
|
+
const dryRun = args.includes('--dry-run');
|
|
136
|
+
const json = asJson(args);
|
|
137
|
+
const root = resolveSemanticRoot();
|
|
138
|
+
// Discover artifacts to enrich. We delegate target selection to the user
|
|
139
|
+
// via --files (one path per line, or comma-separated). This keeps the CLI
|
|
140
|
+
// free of an opinionated index walker; agents typically pass the file list
|
|
141
|
+
// they want enriched.
|
|
142
|
+
const filesArg = flagValue(args, '--files');
|
|
143
|
+
let files;
|
|
144
|
+
if (filesArg) {
|
|
145
|
+
if (existsSync(filesArg)) {
|
|
146
|
+
files = readFileSync(filesArg, 'utf-8')
|
|
147
|
+
.split(/\r?\n/)
|
|
148
|
+
.map((s) => s.trim())
|
|
149
|
+
.filter((s) => s.length > 0);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
files = filesArg.split(',').map((s) => s.trim()).filter((s) => s.length > 0);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
console.error('Usage: aiwg index enrich --using-rlm --files <path-to-list|csv> [--filter <expr>] [--force] [--dry-run]');
|
|
157
|
+
console.error(' aiwg index enrich --using-rlm --files src/foo.ts,src/bar.ts');
|
|
158
|
+
console.error('');
|
|
159
|
+
console.error('Tip: pipe `aiwg index query --json | jq -r .results[].path` into --files <path>.');
|
|
160
|
+
process.exitCode = 1;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (filter) {
|
|
164
|
+
const re = new RegExp(filter);
|
|
165
|
+
files = files.filter((f) => re.test(f));
|
|
166
|
+
}
|
|
167
|
+
// Filter by enrichment freshness unless --force
|
|
168
|
+
const plans = [];
|
|
169
|
+
let skipped = 0;
|
|
170
|
+
for (const f of files) {
|
|
171
|
+
if (!existsSync(f)) {
|
|
172
|
+
console.error(`[skip] missing: ${f}`);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const contentHash = computeContentHash(readFileSync(f));
|
|
176
|
+
if (!force && hasEnrichment(root, f)) {
|
|
177
|
+
try {
|
|
178
|
+
const existing = getEnrichment(root, f);
|
|
179
|
+
if (existing.enrichedHash === contentHash) {
|
|
180
|
+
skipped++;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch { /* fall through to enrich */ }
|
|
185
|
+
}
|
|
186
|
+
const cacheKey = computeHash({
|
|
187
|
+
inputs: [{ artifactId: f, contentHash }],
|
|
188
|
+
query: ENRICHMENT_PROMPT,
|
|
189
|
+
subPrompt: ENRICHMENT_PROMPT,
|
|
190
|
+
model: 'claude-sonnet-4-6',
|
|
191
|
+
aggregateStrategy: 'json-merge',
|
|
192
|
+
});
|
|
193
|
+
plans.push({
|
|
194
|
+
artifactId: f,
|
|
195
|
+
contentHash,
|
|
196
|
+
prompt: ENRICHMENT_PROMPT,
|
|
197
|
+
outputPath: join(root, `${f.replace(/\//g, '__')}.json`),
|
|
198
|
+
cacheKey,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
if (json) {
|
|
202
|
+
console.log(JSON.stringify({ plans, skipped, totalFiles: files.length }, null, 2));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (plans.length === 0) {
|
|
206
|
+
console.log(`No artifacts need enrichment (${skipped} already fresh, ${files.length} total).`);
|
|
207
|
+
if (!force)
|
|
208
|
+
console.log('Use --force to re-enrich regardless of hash.');
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
console.log(`Enrichment plan: ${plans.length} artifact(s) to enrich, ${skipped} fresh, ${files.length} total.`);
|
|
212
|
+
if (dryRun) {
|
|
213
|
+
console.log('--dry-run: plan emitted, no dispatch.');
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
console.log('');
|
|
217
|
+
console.log('NOTE: This command emits dispatch plans. The RLM agent (/rlm-batch) reads each plan,');
|
|
218
|
+
console.log('runs the canonical extraction prompt against the artifact, and applies the result via:');
|
|
219
|
+
console.log(' aiwg index enrich --apply --id <id> --result <path>');
|
|
220
|
+
console.log('');
|
|
221
|
+
for (const p of plans.slice(0, 10)) {
|
|
222
|
+
console.log(` • ${p.artifactId} (cache: ${p.cacheKey.slice(0, 12)}…)`);
|
|
223
|
+
}
|
|
224
|
+
if (plans.length > 10) {
|
|
225
|
+
console.log(` … and ${plans.length - 10} more (use --json for full list)`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function printUsage() {
|
|
229
|
+
console.log('aiwg index enrich [flags]');
|
|
230
|
+
console.log('');
|
|
231
|
+
console.log('Flags:');
|
|
232
|
+
console.log(' --using-rlm --files <path|csv> Emit enrichment dispatch plans');
|
|
233
|
+
console.log(' --filter <regex> Restrict --using-rlm targets by regex');
|
|
234
|
+
console.log(' --force Re-enrich even when enriched_hash matches');
|
|
235
|
+
console.log(' --dry-run Plan without dispatch');
|
|
236
|
+
console.log(' --apply --id <id> --result <p> Write back a single agent result');
|
|
237
|
+
console.log(' --list [--json] List current enrichment entries');
|
|
238
|
+
console.log(' --reset Drop all enrichment data (rollback)');
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical extraction prompt — single source of truth for semantic enrichment.
|
|
3
|
+
*
|
|
4
|
+
* The prompt instructs the dispatched RLM agent to read one artifact and
|
|
5
|
+
* return JSON matching the SemanticFields schema. Cache invalidation depends
|
|
6
|
+
* on this prompt being stable; changing it busts the cache for every
|
|
7
|
+
* previously-enriched artifact.
|
|
8
|
+
*
|
|
9
|
+
* @implements #1204
|
|
10
|
+
* @see .aiwg/architecture/adr-rlm-index-features-impl-plan.md
|
|
11
|
+
*/
|
|
12
|
+
export const ENRICHMENT_PROMPT = `Read the artifact below. Return JSON matching this schema exactly:
|
|
13
|
+
|
|
14
|
+
{
|
|
15
|
+
"summary": "<one paragraph, max 500 chars>",
|
|
16
|
+
"declared_symbols": ["<exported function / type / entity / class names>"],
|
|
17
|
+
"citations": ["<REF-XXX | path/to/file.md | @-mention target>"],
|
|
18
|
+
"inferred_tags": ["<topic keywords from the content>"],
|
|
19
|
+
"open_questions": ["<contradictions or open questions stated in the artifact>"]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Be conservative: empty arrays are fine when nothing applies. Do not fabricate citations or symbols not present in the source. Do not include the artifact's title or path in the summary — write the summary as if the reader already knows what file they are reading.
|
|
23
|
+
|
|
24
|
+
Output ONLY the JSON object, no surrounding prose.`;
|
|
25
|
+
/** Validate raw RLM output against the SemanticFields shape. Returns issues, empty if valid. */
|
|
26
|
+
export function validateEnrichmentOutput(raw) {
|
|
27
|
+
const issues = [];
|
|
28
|
+
if (!raw || typeof raw !== 'object') {
|
|
29
|
+
return ['enrichment output must be a JSON object'];
|
|
30
|
+
}
|
|
31
|
+
const r = raw;
|
|
32
|
+
if (typeof r['summary'] !== 'string')
|
|
33
|
+
issues.push('summary must be a string');
|
|
34
|
+
else if (r['summary'].length > 1000)
|
|
35
|
+
issues.push('summary exceeds 1000 chars');
|
|
36
|
+
for (const arrField of ['declared_symbols', 'citations', 'inferred_tags', 'open_questions']) {
|
|
37
|
+
const v = r[arrField];
|
|
38
|
+
if (!Array.isArray(v)) {
|
|
39
|
+
issues.push(`${arrField} must be a string array`);
|
|
40
|
+
}
|
|
41
|
+
else if (v.some((item) => typeof item !== 'string')) {
|
|
42
|
+
issues.push(`${arrField} must contain only strings`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return issues;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=prompt.js.map
|