@aiwg/cli 0.0.0-bootstrap.0 → 2026.7.18
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/LICENSE +21 -0
- package/README.md +22 -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 +1486 -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 +886 -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 +65 -9
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curator (PROF-S) tooling — discovery-provenance / source-tracking subsystem (#1499).
|
|
3
|
+
*
|
|
4
|
+
* - curator-status: per-curator yield (inducted REFs, avg GRADE, return-to score),
|
|
5
|
+
* revisit-cadence staleness (shared computeStaleness), and the curator-orphan
|
|
6
|
+
* check (discovery.curator-id set but the PROF-S is missing that REF).
|
|
7
|
+
* - curator-init: scaffold a PROF-S source profile from a handle.
|
|
8
|
+
*
|
|
9
|
+
* The discovery block + PROF-S frontmatter are already parsed by the #1497
|
|
10
|
+
* parser (extractDiscovery / loadProfiles incl. `sources`); the read views
|
|
11
|
+
* by-source / by-curator shipped in #1492. This is the write/compute side.
|
|
12
|
+
*
|
|
13
|
+
* @source historical: documentation/SOURCE-TRACKING.md, profiles/sources/TEMPLATE-source-profile.md
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from 'fs';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { loadProfiles, loadCorpus } from '../corpus-views/ref-parser.js';
|
|
18
|
+
import { computeStaleness } from '../corpus-views/corpus-config.js';
|
|
19
|
+
import { readAnalysisGrade } from './radar-shared.js';
|
|
20
|
+
/** GRADE letter → numeric for averaging (A=4 … D=1; signs interpolate). */
|
|
21
|
+
const GRADE_VALUE = { A: 4, 'A-': 3.7, B: 3, 'B-': 2.7, C: 2, 'C-': 1.7, D: 1 };
|
|
22
|
+
function gradeNum(g) {
|
|
23
|
+
return GRADE_VALUE[g.toUpperCase()] ?? GRADE_VALUE[(g[0] ?? '').toUpperCase()] ?? null;
|
|
24
|
+
}
|
|
25
|
+
function fmStr(v) {
|
|
26
|
+
if (typeof v === 'string')
|
|
27
|
+
return v.trim() || null;
|
|
28
|
+
if (typeof v === 'number')
|
|
29
|
+
return String(v);
|
|
30
|
+
if (v instanceof Date)
|
|
31
|
+
return v.toISOString().slice(0, 10);
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
/** Per-curator (PROF-S) yield rows, ranked by return-to score (highest first). */
|
|
35
|
+
export function curatorRows(corpusRoot, opts = {}) {
|
|
36
|
+
const today = new Date(`${opts.today ?? new Date().toISOString().slice(0, 10)}T00:00:00Z`);
|
|
37
|
+
const rows = loadProfiles(corpusRoot)
|
|
38
|
+
.filter((p) => p.type === 'source')
|
|
39
|
+
.map((p) => {
|
|
40
|
+
const grades = p.corpusRefs.map((r) => gradeNum(readAnalysisGrade(corpusRoot, r))).filter((x) => x !== null);
|
|
41
|
+
const avgGrade = grades.length ? grades.reduce((a, b) => a + b, 0) / grades.length : 0;
|
|
42
|
+
const cadence = fmStr(p.frontmatter['revisit-cadence']);
|
|
43
|
+
const last = fmStr(p.frontmatter['last-harvested']);
|
|
44
|
+
const s = computeStaleness(cadence, last, today);
|
|
45
|
+
return {
|
|
46
|
+
profId: p.profId,
|
|
47
|
+
name: p.name ?? '',
|
|
48
|
+
handle: fmStr(p.frontmatter.handle) ?? '',
|
|
49
|
+
platform: fmStr(p.frontmatter.platform) ?? '',
|
|
50
|
+
signalQuality: fmStr(p.frontmatter['signal-quality']) ?? '—',
|
|
51
|
+
revisitCadence: cadence ?? '—',
|
|
52
|
+
lastHarvested: last ?? '',
|
|
53
|
+
inductedCount: p.corpusRefs.length,
|
|
54
|
+
avgGrade: Math.round(avgGrade * 100) / 100,
|
|
55
|
+
returnToScore: Math.round(p.corpusRefs.length * avgGrade * 100) / 100,
|
|
56
|
+
overdueDays: s.overdueDays,
|
|
57
|
+
isStale: s.isStale,
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
return rows.sort((a, b) => b.returnToScore - a.returnToScore || (a.profId < b.profId ? -1 : a.profId > b.profId ? 1 : 0));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Curator orphans: a citation sidecar with `discovery.curator-id` set, but the
|
|
64
|
+
* named PROF-S is absent or is missing that REF in its `corpus-refs`. The check
|
|
65
|
+
* fires ONLY when curator-id is set (SOURCE-TRACKING §0/§3) — a missing or
|
|
66
|
+
* null/`direct` discovery block is never an orphan.
|
|
67
|
+
*/
|
|
68
|
+
export function curatorOrphans(corpusRoot) {
|
|
69
|
+
const { records } = loadCorpus(corpusRoot);
|
|
70
|
+
const curatorRefs = new Map(loadProfiles(corpusRoot)
|
|
71
|
+
.filter((p) => p.type === 'source')
|
|
72
|
+
.map((p) => [p.profId, new Set(p.corpusRefs)]));
|
|
73
|
+
const orphans = [];
|
|
74
|
+
for (const r of records) {
|
|
75
|
+
const cid = r.discovery?.curatorId;
|
|
76
|
+
if (!cid)
|
|
77
|
+
continue;
|
|
78
|
+
if (!curatorRefs.has(cid))
|
|
79
|
+
orphans.push({ refId: r.refId, curatorId: cid, reason: 'no PROF-S profile' });
|
|
80
|
+
else if (!curatorRefs.get(cid).has(r.refId))
|
|
81
|
+
orphans.push({ refId: r.refId, curatorId: cid, reason: 'REF missing from curator corpus-refs' });
|
|
82
|
+
}
|
|
83
|
+
return orphans;
|
|
84
|
+
}
|
|
85
|
+
/** Render the curator yield ranking + an orphan section. */
|
|
86
|
+
export function renderCuratorStatus(rows, orphans) {
|
|
87
|
+
const lines = [
|
|
88
|
+
'# Curators (PROF-S) — yield & freshness',
|
|
89
|
+
'',
|
|
90
|
+
`${rows.length} curators · ${orphans.length} discovery orphans`,
|
|
91
|
+
'',
|
|
92
|
+
'| Curator | Handle | Signal | Cadence | Last Harvested | Inducted | Avg GRADE | Return-to | Overdue |',
|
|
93
|
+
'|---|---|---|---|---|---:|---:|---:|---:|',
|
|
94
|
+
];
|
|
95
|
+
for (const r of rows) {
|
|
96
|
+
lines.push(`| ${r.profId} | ${r.handle || '—'} | ${r.signalQuality} | ${r.revisitCadence} | ${r.lastHarvested || '—'} | ${r.inductedCount} | ${r.avgGrade || '—'} | ${r.returnToScore || '—'} | ${r.overdueDays ?? '—'} |`);
|
|
97
|
+
}
|
|
98
|
+
lines.push('', '## Discovery orphans', '');
|
|
99
|
+
if (orphans.length) {
|
|
100
|
+
lines.push('`discovery.curator-id` set but the curator is missing the REF (SOURCE-TRACKING §3):', '', '| REF | Curator | Issue |', '|---|---|---|');
|
|
101
|
+
for (const o of orphans)
|
|
102
|
+
lines.push(`| ${o.refId} | ${o.curatorId} | ${o.reason} |`);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
lines.push('None — every `discovery.curator-id` resolves to a PROF-S that lists the REF.');
|
|
106
|
+
}
|
|
107
|
+
return lines.join('\n') + '\n';
|
|
108
|
+
}
|
|
109
|
+
/** Curator slug from a handle: lowercased, leading punctuation stripped, `_`→`-`. */
|
|
110
|
+
export function curatorSlug(handle) {
|
|
111
|
+
return handle
|
|
112
|
+
.trim()
|
|
113
|
+
.replace(/^[@/]+/, '')
|
|
114
|
+
.toLowerCase()
|
|
115
|
+
.replace(/_/g, '-')
|
|
116
|
+
.replace(/[^a-z0-9-]+/g, '-')
|
|
117
|
+
.replace(/-+/g, '-')
|
|
118
|
+
.replace(/^-+|-+$/g, '');
|
|
119
|
+
}
|
|
120
|
+
/** Scaffold a PROF-S source/curator profile from a handle. */
|
|
121
|
+
export function scaffoldCurator(corpusRoot, handle, opts = {}) {
|
|
122
|
+
const slug = curatorSlug(handle);
|
|
123
|
+
const today = opts.today || new Date().toISOString().slice(0, 10);
|
|
124
|
+
const platform = opts.platform || 'x';
|
|
125
|
+
const cadence = opts.cadence || 'weekly';
|
|
126
|
+
const name = opts.name || handle;
|
|
127
|
+
const outRel = path.join('documentation', 'profiles', 'sources', `PROF-S-${slug}.md`);
|
|
128
|
+
const content = [
|
|
129
|
+
'---',
|
|
130
|
+
`prof-id: PROF-S-${slug}`,
|
|
131
|
+
`name: "${name}"`,
|
|
132
|
+
'type: source',
|
|
133
|
+
`platform: ${platform}`,
|
|
134
|
+
`handle: "${handle}"`,
|
|
135
|
+
'url: ""',
|
|
136
|
+
'operator: ""',
|
|
137
|
+
'corpus-refs: []',
|
|
138
|
+
'surfaces: []',
|
|
139
|
+
'focus-areas: []',
|
|
140
|
+
'signal-quality: "—"',
|
|
141
|
+
'grade-trajectory: unknown',
|
|
142
|
+
`revisit-cadence: ${cadence}`,
|
|
143
|
+
`last-harvested: ${today}`,
|
|
144
|
+
'last-harvested-by: curator-init-scaffold',
|
|
145
|
+
'candidate-yield: 0',
|
|
146
|
+
'---',
|
|
147
|
+
'',
|
|
148
|
+
`# ${name} — Source / Curator Profile`,
|
|
149
|
+
'',
|
|
150
|
+
'**Type**: Source / Curator',
|
|
151
|
+
`**Profile ID**: \`PROF-S-${slug}\``,
|
|
152
|
+
`**Platform**: ${platform} · **Handle**: ${handle}`,
|
|
153
|
+
`**Revisit cadence**: ${cadence}`,
|
|
154
|
+
`**Last harvested**: ${today}`,
|
|
155
|
+
'',
|
|
156
|
+
'---',
|
|
157
|
+
'',
|
|
158
|
+
'## 1. Curator Summary',
|
|
159
|
+
'',
|
|
160
|
+
'Initial scaffold — describe what this account posts and why it is worth tracking on first harvest.',
|
|
161
|
+
'',
|
|
162
|
+
'## 2. Sources Surfaced',
|
|
163
|
+
'',
|
|
164
|
+
'### Inducted (in corpus)',
|
|
165
|
+
'| REF | Title | Surfaced | GRADE |',
|
|
166
|
+
'|---|---|---|---|',
|
|
167
|
+
'',
|
|
168
|
+
'### Candidate Sources Surfaced (not yet inducted)',
|
|
169
|
+
'| Candidate | Surfaced | Harvest batch | Working file |',
|
|
170
|
+
'|---|---|---|---|',
|
|
171
|
+
'',
|
|
172
|
+
'## 3. Notes',
|
|
173
|
+
'',
|
|
174
|
+
`- Scaffolded by \`aiwg corpus curator-init\` on ${today}. Populate yield + signal-quality on first harvest.`,
|
|
175
|
+
'',
|
|
176
|
+
].join('\n');
|
|
177
|
+
const outAbs = path.join(corpusRoot, outRel);
|
|
178
|
+
if (!opts.write)
|
|
179
|
+
return { slug, status: 'dry-run', message: `DRY-RUN PROF-S-${slug}: ${name}`, outPath: outRel, content };
|
|
180
|
+
if (fs.existsSync(outAbs))
|
|
181
|
+
return { slug, status: 'skip', message: `SKIP PROF-S-${slug} (exists)`, outPath: outRel };
|
|
182
|
+
fs.mkdirSync(path.dirname(outAbs), { recursive: true });
|
|
183
|
+
fs.writeFileSync(outAbs, content, 'utf-8');
|
|
184
|
+
return { slug, status: 'wrote', message: `WROTE PROF-S-${slug}: ${name}`, outPath: outRel, content };
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=curator.js.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* discovery-log — record the source-tracking `discovery:` block on a citation
|
|
3
|
+
* sidecar (#1499). Adds or replaces the block in the sidecar frontmatter,
|
|
4
|
+
* preserving the rest of the file. Dry-run unless `write`.
|
|
5
|
+
*
|
|
6
|
+
* The `discovery` block is OPTIONAL by design (SOURCE-TRACKING §0): `date` +
|
|
7
|
+
* `surface` are the only meaningful required fields; `curator-id` is set only
|
|
8
|
+
* when the source came through a named, repeatable curator.
|
|
9
|
+
*
|
|
10
|
+
* @source historical: documentation/SOURCE-TRACKING.md §1
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
const SURFACE_VOCAB = ['x-account', 'x-search', 'x-bookmarks', 'x-foryou', 'x-following', 'rss', 'newsletter', 'web', 'referral', 'direct'];
|
|
15
|
+
/** Render the `discovery:` YAML block (2-space indented under the key). */
|
|
16
|
+
export function renderDiscoveryBlock(f, today) {
|
|
17
|
+
const lines = ['discovery:', ` date: ${f.date || today}`, ` surface: ${f.surface}`];
|
|
18
|
+
if (f.via)
|
|
19
|
+
lines.push(` via: "${f.via}"`);
|
|
20
|
+
lines.push(` curator-id: ${f.curatorId || 'null'}`);
|
|
21
|
+
if (f.harvestBatch)
|
|
22
|
+
lines.push(` harvest-batch: ${f.harvestBatch}`);
|
|
23
|
+
if (f.harvestedBy)
|
|
24
|
+
lines.push(` harvested-by: ${f.harvestedBy}`);
|
|
25
|
+
return lines.join('\n');
|
|
26
|
+
}
|
|
27
|
+
/** Drop an existing top-level `discovery:` block (key + its indented lines) from frontmatter lines. */
|
|
28
|
+
function stripDiscovery(fmLines) {
|
|
29
|
+
const out = [];
|
|
30
|
+
let skipping = false;
|
|
31
|
+
for (const line of fmLines) {
|
|
32
|
+
if (skipping) {
|
|
33
|
+
if (/^\s/.test(line) || line.trim() === '')
|
|
34
|
+
continue; // still inside the block's indented body
|
|
35
|
+
skipping = false;
|
|
36
|
+
}
|
|
37
|
+
if (/^discovery:\s*$/.test(line)) {
|
|
38
|
+
skipping = true;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
out.push(line);
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
/** Add or replace the discovery block in REF-XXX-citations.md frontmatter. */
|
|
46
|
+
export function logDiscovery(corpusRoot, refId, opts) {
|
|
47
|
+
const today = opts.date || new Date().toISOString().slice(0, 10);
|
|
48
|
+
const block = renderDiscoveryBlock(opts, today);
|
|
49
|
+
if (!SURFACE_VOCAB.includes(opts.surface)) {
|
|
50
|
+
throw new Error(`discovery-log: unknown surface '${opts.surface}' (one of: ${SURFACE_VOCAB.join(', ')})`);
|
|
51
|
+
}
|
|
52
|
+
const sidecar = path.join(corpusRoot, 'documentation', 'citations', `${refId}-citations.md`);
|
|
53
|
+
if (!fs.existsSync(sidecar)) {
|
|
54
|
+
return { refId, status: 'skip', message: `SKIP ${refId}: no citation sidecar found`, block };
|
|
55
|
+
}
|
|
56
|
+
const text = fs.readFileSync(sidecar, 'utf-8');
|
|
57
|
+
const m = text.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
58
|
+
if (!m) {
|
|
59
|
+
return { refId, status: 'skip', message: `SKIP ${refId}: citation sidecar has no YAML frontmatter`, block };
|
|
60
|
+
}
|
|
61
|
+
const fmLines = stripDiscovery(m[1].split('\n'));
|
|
62
|
+
const newFm = [...fmLines, block].join('\n');
|
|
63
|
+
const content = `---\n${newFm}\n---\n${m[2]}`;
|
|
64
|
+
if (!opts.write) {
|
|
65
|
+
return { refId, status: 'dry-run', message: `DRY-RUN ${refId}: would set discovery (surface=${opts.surface}${opts.curatorId ? `, curator=${opts.curatorId}` : ''})`, block, content };
|
|
66
|
+
}
|
|
67
|
+
fs.writeFileSync(sidecar, content, 'utf-8');
|
|
68
|
+
return { refId, status: 'wrote', message: `WROTE discovery block to ${refId}-citations.md`, block, content };
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=discovery-log.js.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* funder-network — bipartite funder↔paper analytics (#1500).
|
|
3
|
+
*
|
|
4
|
+
* Port of profiles/funder_network.py: per-funder paper/A-grade/mean-grade rollup,
|
|
5
|
+
* mean CD-index + novelty-bias (reusing the #1501 CD-index), and co-funding
|
|
6
|
+
* clusters. Funder linkage comes from the #1497 parser (`funders[]` on each REF).
|
|
7
|
+
* FUNDER_ALIASES are NOT ported — the optional acknowledgement scan reads a
|
|
8
|
+
* corpus-local `documentation/profiles/funder-aliases.yaml` (absent → no aliasing).
|
|
9
|
+
*
|
|
10
|
+
* @source historical: profiles/funder_network.py
|
|
11
|
+
* Reference: Wang et al. 2017 (novelty bias); Funk & Owen-Smith 2017 (novelty).
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'fs';
|
|
14
|
+
import * as path from 'path';
|
|
15
|
+
import { load as loadYaml } from 'js-yaml';
|
|
16
|
+
import { loadCorpus } from '../corpus-views/ref-parser.js';
|
|
17
|
+
import { buildCitationGraph, cdIndex } from './corpus-graph.js';
|
|
18
|
+
import { readAnalysisGrade } from './radar-shared.js';
|
|
19
|
+
/** Wang et al. 2017 corpus-mean novelty baseline (override via funder-aliases.yaml `novelty-baseline`). */
|
|
20
|
+
const DEFAULT_NOVELTY_BASELINE = 0.41;
|
|
21
|
+
const GRADE_W = { A: 4, B: 3, C: 2, D: 1 };
|
|
22
|
+
function gradeNum(g) {
|
|
23
|
+
return GRADE_W[(g[0] ?? '').toUpperCase()] ?? null;
|
|
24
|
+
}
|
|
25
|
+
/** Load corpus-local funder aliases (raw lowercase name → PROF-F/PROF-O id) + novelty baseline. */
|
|
26
|
+
export function loadFunderAliases(corpusRoot) {
|
|
27
|
+
const file = path.join(corpusRoot, 'documentation', 'profiles', 'funder-aliases.yaml');
|
|
28
|
+
const aliases = new Map();
|
|
29
|
+
let baseline = DEFAULT_NOVELTY_BASELINE;
|
|
30
|
+
try {
|
|
31
|
+
const raw = loadYaml(fs.readFileSync(file, 'utf-8'));
|
|
32
|
+
if (raw && typeof raw === 'object') {
|
|
33
|
+
const o = raw;
|
|
34
|
+
if (typeof o['novelty-baseline'] === 'number')
|
|
35
|
+
baseline = o['novelty-baseline'];
|
|
36
|
+
const a = o.aliases;
|
|
37
|
+
if (a && typeof a === 'object')
|
|
38
|
+
for (const [k, v] of Object.entries(a))
|
|
39
|
+
aliases.set(k.toLowerCase(), String(v));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
/* absent → no aliasing */
|
|
44
|
+
}
|
|
45
|
+
return { aliases, baseline };
|
|
46
|
+
}
|
|
47
|
+
function buildFunderCtx(corpusRoot, scanAcks) {
|
|
48
|
+
const { records } = loadCorpus(corpusRoot);
|
|
49
|
+
const byId = new Map(records.map((r) => [r.refId, r]));
|
|
50
|
+
const cite = buildCitationGraph(records);
|
|
51
|
+
const cdByRef = new Map(records.map((r) => [r.refId, cdIndex(r.refId, cite)]));
|
|
52
|
+
const { aliases, baseline } = loadFunderAliases(corpusRoot);
|
|
53
|
+
const funderPapers = new Map();
|
|
54
|
+
const add = (fid, ref) => (funderPapers.get(fid) ?? funderPapers.set(fid, []).get(fid)).push(ref);
|
|
55
|
+
for (const r of records)
|
|
56
|
+
for (const f of r.funders)
|
|
57
|
+
if (f.id)
|
|
58
|
+
add(f.id, r.refId);
|
|
59
|
+
// Optional acknowledgement scan (externalized aliases only).
|
|
60
|
+
if (scanAcks && aliases.size) {
|
|
61
|
+
for (const r of records) {
|
|
62
|
+
if (r.funders.length)
|
|
63
|
+
continue; // sidecar funders take precedence
|
|
64
|
+
const text = fs.existsSync(r.path) ? fs.readFileSync(r.path, 'utf-8').toLowerCase() : '';
|
|
65
|
+
const ackIdx = Math.max(text.indexOf('## acknowledgement'), text.indexOf('**acknowledgement'));
|
|
66
|
+
if (ackIdx < 0)
|
|
67
|
+
continue;
|
|
68
|
+
const ack = text.slice(ackIdx, ackIdx + 2000);
|
|
69
|
+
for (const [alias, fid] of aliases)
|
|
70
|
+
if (ack.includes(alias))
|
|
71
|
+
add(fid, r.refId);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return { funderPapers, byId, cdByRef, baseline };
|
|
75
|
+
}
|
|
76
|
+
/** Per-funder analytics, ranked by paper count. */
|
|
77
|
+
export function funderRows(corpusRoot, opts = {}) {
|
|
78
|
+
const { funderPapers, byId, cdByRef, baseline } = buildFunderCtx(corpusRoot, !!opts.scanAcks);
|
|
79
|
+
const rows = [];
|
|
80
|
+
for (const [funderId, papersRaw] of funderPapers) {
|
|
81
|
+
const papers = [...new Set(papersRaw)].sort();
|
|
82
|
+
const grades = papers.map((r) => readAnalysisGrade(corpusRoot, r));
|
|
83
|
+
const gradeNums = grades.map(gradeNum).filter((x) => x != null);
|
|
84
|
+
const cds = papers.map((r) => cdByRef.get(r) ?? null).filter((x) => x != null);
|
|
85
|
+
const topicCount = new Map();
|
|
86
|
+
const years = [];
|
|
87
|
+
for (const r of papers) {
|
|
88
|
+
for (const t of byId.get(r)?.topics ?? [])
|
|
89
|
+
topicCount.set(t, (topicCount.get(t) ?? 0) + 1);
|
|
90
|
+
const y = byId.get(r)?.year;
|
|
91
|
+
if (y != null)
|
|
92
|
+
years.push(y);
|
|
93
|
+
}
|
|
94
|
+
const meanCd = cds.length ? Math.round((cds.reduce((a, b) => a + b, 0) / cds.length) * 1e4) / 1e4 : null;
|
|
95
|
+
const noveltyBias = meanCd == null ? null : meanCd < baseline - 0.1 ? 'below-baseline' : meanCd > baseline + 0.1 ? 'above-baseline' : 'baseline';
|
|
96
|
+
rows.push({
|
|
97
|
+
funderId,
|
|
98
|
+
paperCount: papers.length,
|
|
99
|
+
aGradeCount: grades.filter((g) => g.toUpperCase().startsWith('A')).length,
|
|
100
|
+
meanGrade: gradeNums.length ? Math.round((gradeNums.reduce((a, b) => a + b, 0) / gradeNums.length) * 100) / 100 : null,
|
|
101
|
+
meanCdIndex: meanCd,
|
|
102
|
+
noveltyBias,
|
|
103
|
+
topTopics: [...topicCount.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([t]) => t),
|
|
104
|
+
yearRange: years.length ? [Math.min(...years), Math.max(...years)] : null,
|
|
105
|
+
papers,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return rows.sort((a, b) => b.paperCount - a.paperCount || (a.funderId < b.funderId ? -1 : 1));
|
|
109
|
+
}
|
|
110
|
+
/** Papers with ≥2 funders (co-funding), ranked by funder count. */
|
|
111
|
+
export function cofundingClusters(corpusRoot) {
|
|
112
|
+
const { records } = loadCorpus(corpusRoot);
|
|
113
|
+
const clusters = [];
|
|
114
|
+
for (const r of records) {
|
|
115
|
+
const funders = [...new Set(r.funders.map((f) => f.id).filter(Boolean))];
|
|
116
|
+
if (funders.length >= 2)
|
|
117
|
+
clusters.push({ paper: r.refId, funders, count: funders.length });
|
|
118
|
+
}
|
|
119
|
+
return clusters.sort((a, b) => b.count - a.count || (a.paper < b.paper ? -1 : 1));
|
|
120
|
+
}
|
|
121
|
+
/** Render the funder-network markdown index. */
|
|
122
|
+
export function renderFunderNetwork(rows, clusters) {
|
|
123
|
+
const lines = [
|
|
124
|
+
'# Funder Network',
|
|
125
|
+
'',
|
|
126
|
+
`**Funders tracked**: ${rows.length} · **Co-funded papers**: ${clusters.length}`,
|
|
127
|
+
'',
|
|
128
|
+
'| Funder | Papers | A-Grade | Mean Grade | Mean CD | Novelty Bias | Top Topics |',
|
|
129
|
+
'|---|---:|---:|---:|---:|---|---|',
|
|
130
|
+
];
|
|
131
|
+
for (const r of rows) {
|
|
132
|
+
lines.push(`| ${r.funderId} | ${r.paperCount} | ${r.aGradeCount} | ${r.meanGrade ?? '—'} | ${r.meanCdIndex ?? '—'} | ${r.noveltyBias ?? '—'} | ${r.topTopics.slice(0, 3).join(', ') || '—'} |`);
|
|
133
|
+
}
|
|
134
|
+
if (clusters.length) {
|
|
135
|
+
lines.push('', '## Co-Funded Papers', '', '| Paper | Funders | Count |', '|---|---|---:|');
|
|
136
|
+
for (const c of clusters.slice(0, 20))
|
|
137
|
+
lines.push(`| ${c.paper} | ${c.funders.join(', ')} | ${c.count} |`);
|
|
138
|
+
}
|
|
139
|
+
return lines.join('\n') + '\n';
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=funder-network.js.map
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Induction quality: frontmatter backfill + per-type induction depth audit (#1504).
|
|
3
|
+
*
|
|
4
|
+
* TS-native port of section9 `backfill_frontmatter.py` + `audit_inductions.py`.
|
|
5
|
+
* The audit is **source-type-aware** (#1509): required-section checks come from
|
|
6
|
+
* the source-type registry, so a blog isn't flagged for missing "Benchmark
|
|
7
|
+
* Results" and a repo is checked for "Architecture"/"Maintenance Signals". This
|
|
8
|
+
* is the audit consumer that demonstrates the #1509 registry end-to-end.
|
|
9
|
+
*
|
|
10
|
+
* Reconciles with `research-quality-audit` (GRADE evidence quality) and
|
|
11
|
+
* `best-practices-audit` (corpus-wide best practices): this is the structural +
|
|
12
|
+
* depth + per-type-section induction check, not a GRADE assessment.
|
|
13
|
+
*
|
|
14
|
+
* @source historical: corpus/audit_inductions.py, corpus/backfill_frontmatter.py
|
|
15
|
+
* @tests @test/unit/artifacts/induction-audit.test.ts
|
|
16
|
+
*/
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
import { createHash } from 'crypto';
|
|
20
|
+
import { parseFrontmatter } from '../corpus-views/ref-parser.js';
|
|
21
|
+
import { classifyFirst, VENUE_PATTERNS } from '../corpus-views/taxonomies.js';
|
|
22
|
+
import { loadSourceTypeRegistry, normalizeSourceType, getSourceType, } from './source-types.js';
|
|
23
|
+
const REFS_DIR = ['documentation', 'references'];
|
|
24
|
+
const CITES_DIR = ['documentation', 'citations'];
|
|
25
|
+
const PDFS_DIR = ['pdfs', 'full'];
|
|
26
|
+
const LEGACY_EXCLUDED_TYPES = new Set(['redirect', 'gap-note', 'chapter']);
|
|
27
|
+
function asStr(v) {
|
|
28
|
+
return v == null ? '' : String(v);
|
|
29
|
+
}
|
|
30
|
+
// ── Depth bands (port of audit_inductions depth logic) ───────────────────────
|
|
31
|
+
function depthBand(lines) {
|
|
32
|
+
if (lines < 80)
|
|
33
|
+
return 'STUB';
|
|
34
|
+
if (lines < 150)
|
|
35
|
+
return 'compact';
|
|
36
|
+
if (lines < 250)
|
|
37
|
+
return 'good';
|
|
38
|
+
if (lines < 400)
|
|
39
|
+
return 'full';
|
|
40
|
+
return 'deep';
|
|
41
|
+
}
|
|
42
|
+
function refFiles(root) {
|
|
43
|
+
const dir = path.join(root, ...REFS_DIR);
|
|
44
|
+
if (!fs.existsSync(dir))
|
|
45
|
+
return [];
|
|
46
|
+
return fs.readdirSync(dir).filter((f) => /^REF-\d{3,4}[a-z]?(-.*)?\.md$/.test(f)).sort();
|
|
47
|
+
}
|
|
48
|
+
function refIdOf(filename) {
|
|
49
|
+
const m = filename.match(/^(REF-\d{3,4}[a-z]?)/);
|
|
50
|
+
return m ? m[1] : null;
|
|
51
|
+
}
|
|
52
|
+
function findAnalysis(root, refId) {
|
|
53
|
+
const dir = path.join(root, ...REFS_DIR);
|
|
54
|
+
if (!fs.existsSync(dir))
|
|
55
|
+
return null;
|
|
56
|
+
const m = fs.readdirSync(dir).find((f) => f === `${refId}.md` || f.startsWith(`${refId}-`));
|
|
57
|
+
return m ? path.join(dir, m) : null;
|
|
58
|
+
}
|
|
59
|
+
function hasPdf(root, refId) {
|
|
60
|
+
const dir = path.join(root, ...PDFS_DIR);
|
|
61
|
+
if (!fs.existsSync(dir))
|
|
62
|
+
return false;
|
|
63
|
+
return fs.readdirSync(dir).some((f) => f === `${refId}.pdf` || f.startsWith(`${refId}-`));
|
|
64
|
+
}
|
|
65
|
+
/** Audit one ref. Required sections come from its source type's registry entry. */
|
|
66
|
+
function auditRef(root, refId, reg) {
|
|
67
|
+
const r = {
|
|
68
|
+
ref: refId, analysisExists: false, analysisLines: 0, sidecarExists: false,
|
|
69
|
+
pdfExists: false, pdfExcluded: false, sourceType: 'other', depthBand: '',
|
|
70
|
+
missingSections: [], issues: [],
|
|
71
|
+
};
|
|
72
|
+
const analysis = findAnalysis(root, refId);
|
|
73
|
+
if (analysis) {
|
|
74
|
+
r.analysisExists = true;
|
|
75
|
+
const text = fs.readFileSync(analysis, 'utf-8');
|
|
76
|
+
const low = text.toLowerCase();
|
|
77
|
+
r.analysisLines = text.split('\n').length;
|
|
78
|
+
r.depthBand = depthBand(r.analysisLines);
|
|
79
|
+
if (r.depthBand === 'STUB')
|
|
80
|
+
r.issues.push('below-80-line-stub-threshold');
|
|
81
|
+
const fm = parseFrontmatter(text);
|
|
82
|
+
const venue = classifyFirst(text.slice(0, 3500).toLowerCase(), VENUE_PATTERNS);
|
|
83
|
+
r.sourceType = normalizeSourceType({ type: asStr(fm.type), sourceType: asStr(fm.source_type), venue }, reg);
|
|
84
|
+
// Required sections by source type (the #1509 consumer). `meta` docs
|
|
85
|
+
// (redirects/stubs) are exempt; unknown types fall back to a base set.
|
|
86
|
+
if (r.sourceType !== 'meta') {
|
|
87
|
+
const required = getSourceType(r.sourceType, reg)?.requiredSections ?? ['Citation', 'Summary'];
|
|
88
|
+
for (const sec of required) {
|
|
89
|
+
if (!low.includes(sec.toLowerCase()))
|
|
90
|
+
r.missingSections.push(sec);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// PDF-exclusion conventions (audit-exclude-missing-pdf flag or legacy type).
|
|
94
|
+
const flag = asStr(fm['audit-exclude-missing-pdf']).toLowerCase();
|
|
95
|
+
if (['true', 'yes', '1'].includes(flag))
|
|
96
|
+
r.pdfExcluded = true;
|
|
97
|
+
if (LEGACY_EXCLUDED_TYPES.has(asStr(fm.type).toLowerCase()))
|
|
98
|
+
r.pdfExcluded = true;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
r.issues.push('MISSING-ANALYSIS-DOC');
|
|
102
|
+
}
|
|
103
|
+
r.sidecarExists = fs.existsSync(path.join(root, ...CITES_DIR, `${refId}-citations.md`));
|
|
104
|
+
if (!r.sidecarExists)
|
|
105
|
+
r.issues.push('MISSING-SIDECAR');
|
|
106
|
+
r.pdfExists = hasPdf(root, refId);
|
|
107
|
+
if (r.pdfExists && r.pdfExcluded)
|
|
108
|
+
r.issues.push('PDF-PRESENT-BUT-MARKED-EXCLUDED');
|
|
109
|
+
else if (!r.pdfExists && !r.pdfExcluded)
|
|
110
|
+
r.issues.push('MISSING-PDF');
|
|
111
|
+
// missingSections is an informational per-type completeness signal, not a hard
|
|
112
|
+
// issue — the registry's required set is the type's full template, which real
|
|
113
|
+
// inductions don't always fill. Structural problems + stub depth are the issues.
|
|
114
|
+
return r;
|
|
115
|
+
}
|
|
116
|
+
export function auditInductions(root, opts = {}) {
|
|
117
|
+
const reg = loadSourceTypeRegistry(root);
|
|
118
|
+
let ids;
|
|
119
|
+
if (opts.refs?.length) {
|
|
120
|
+
ids = opts.refs;
|
|
121
|
+
}
|
|
122
|
+
else if (opts.start != null && opts.end != null) {
|
|
123
|
+
ids = [];
|
|
124
|
+
for (let n = opts.start; n <= opts.end; n++)
|
|
125
|
+
ids.push(`REF-${n}`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
ids = refFiles(root).map(refIdOf).filter((x) => !!x);
|
|
129
|
+
ids = [...new Set(ids)];
|
|
130
|
+
}
|
|
131
|
+
return ids.map((id) => auditRef(root, id, reg));
|
|
132
|
+
}
|
|
133
|
+
export function renderAudit(results) {
|
|
134
|
+
const out = [];
|
|
135
|
+
const present = results.filter((r) => r.analysisExists);
|
|
136
|
+
const bands = {};
|
|
137
|
+
for (const r of present)
|
|
138
|
+
bands[r.depthBand] = (bands[r.depthBand] ?? 0) + 1;
|
|
139
|
+
out.push(`Induction audit — ${results.length} refs`);
|
|
140
|
+
out.push(`Analysis present: ${present.length}/${results.length}`);
|
|
141
|
+
out.push(`Sidecars present: ${results.filter((r) => r.sidecarExists).length}/${results.length}`);
|
|
142
|
+
out.push(`Depth bands: ${['STUB', 'compact', 'good', 'full', 'deep'].map((b) => `${b}=${bands[b] ?? 0}`).join(' ')}`);
|
|
143
|
+
// Per-type required-section completeness (informational — consumes the #1509 registry).
|
|
144
|
+
const incompleteByType = {};
|
|
145
|
+
for (const r of present)
|
|
146
|
+
if (r.missingSections.length)
|
|
147
|
+
incompleteByType[r.sourceType] = (incompleteByType[r.sourceType] ?? 0) + 1;
|
|
148
|
+
if (Object.keys(incompleteByType).length) {
|
|
149
|
+
out.push(`Per-type incomplete required sections: ${Object.entries(incompleteByType).map(([t, n]) => `${t}=${n}`).join(' ')}`);
|
|
150
|
+
}
|
|
151
|
+
out.push('');
|
|
152
|
+
out.push(`${'REF'.padEnd(10)} ${'type'.padEnd(14)} ${'lines'.padEnd(6)} ${'band'.padEnd(8)} ${'miss-sec'.padEnd(8)} issues`);
|
|
153
|
+
for (const r of results) {
|
|
154
|
+
if (!r.issues.length && r.depthBand !== 'STUB' && r.missingSections.length === 0)
|
|
155
|
+
continue;
|
|
156
|
+
out.push(`${r.ref.padEnd(10)} ${r.sourceType.padEnd(14)} ${String(r.analysisLines).padEnd(6)} ${r.depthBand.padEnd(8)} ${String(r.missingSections.length).padEnd(8)} ${r.issues.join(', ')}`);
|
|
157
|
+
}
|
|
158
|
+
const clean = results.filter((r) => !r.issues.length).length;
|
|
159
|
+
out.push('');
|
|
160
|
+
out.push(`${clean}/${results.length} refs free of structural issues; section-completeness shown above (informational).`);
|
|
161
|
+
return out.join('\n') + '\n';
|
|
162
|
+
}
|
|
163
|
+
function extractTitle(refId, text) {
|
|
164
|
+
const m1 = text.match(new RegExp(`^#\\s+${refId}[:\\s]+(.+?)\\s*$`, 'm'));
|
|
165
|
+
if (m1)
|
|
166
|
+
return m1[1].trim();
|
|
167
|
+
const m2 = text.match(/^#\s+(.+?)\s*$/m);
|
|
168
|
+
if (m2)
|
|
169
|
+
return m2[1].replace(new RegExp(`^${refId}[:\\s]+`), '').trim();
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
function extractYear(text) {
|
|
173
|
+
const cite = text.match(/^##\s+(?:1\.\s*)?Citation\s*\n+([\s\S]*?)(?:\n##|$)/m);
|
|
174
|
+
const space = (cite ? cite[1] : text).slice(0, 3000);
|
|
175
|
+
const paren = space.match(/\((19|20)\d{2}\)/);
|
|
176
|
+
if (paren)
|
|
177
|
+
return paren[0].replace(/[()]/g, '');
|
|
178
|
+
const bare = space.match(/\b(19|20)\d{2}\b/);
|
|
179
|
+
return bare ? bare[0] : null;
|
|
180
|
+
}
|
|
181
|
+
function pdfHash(root, refId) {
|
|
182
|
+
const dir = path.join(root, ...PDFS_DIR);
|
|
183
|
+
if (!fs.existsSync(dir))
|
|
184
|
+
return null;
|
|
185
|
+
const m = fs.readdirSync(dir).find((f) => f === `${refId}.pdf` || f.startsWith(`${refId}-`));
|
|
186
|
+
if (!m)
|
|
187
|
+
return null;
|
|
188
|
+
return createHash('sha256').update(fs.readFileSync(path.join(dir, m))).digest('hex');
|
|
189
|
+
}
|
|
190
|
+
/** Additive frontmatter backfill: skips docs that already have frontmatter. */
|
|
191
|
+
export function backfillFrontmatter(root, opts = {}) {
|
|
192
|
+
const dir = path.join(root, ...REFS_DIR);
|
|
193
|
+
const res = { changed: [], skippedExisting: 0, holdouts: [] };
|
|
194
|
+
if (!fs.existsSync(dir))
|
|
195
|
+
return res;
|
|
196
|
+
const date = opts.date ?? 'backfilled';
|
|
197
|
+
for (const f of fs.readdirSync(dir).filter((x) => /^REF-.*\.md$/.test(x)).sort()) {
|
|
198
|
+
const refId = refIdOf(f);
|
|
199
|
+
if (!refId)
|
|
200
|
+
continue;
|
|
201
|
+
const full = path.join(dir, f);
|
|
202
|
+
const text = fs.readFileSync(full, 'utf-8');
|
|
203
|
+
if (text.startsWith('---\n')) {
|
|
204
|
+
res.skippedExisting++;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const title = extractTitle(refId, text);
|
|
208
|
+
const year = extractYear(text);
|
|
209
|
+
if (!title || !year) {
|
|
210
|
+
const missing = [!title && 'title', !year && 'year'].filter(Boolean).join(',');
|
|
211
|
+
res.holdouts.push({ ref: refId, missing });
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const digest = pdfHash(root, refId);
|
|
215
|
+
const fm = ['---', `ref_id: ${refId}`, `title: ${JSON.stringify(title)}`, `year: ${year}`];
|
|
216
|
+
if (digest)
|
|
217
|
+
fm.push(`pdf_hash: ${JSON.stringify(digest)}`);
|
|
218
|
+
fm.push(`frontmatter-backfilled: ${date}`, '---', '');
|
|
219
|
+
if (opts.write)
|
|
220
|
+
fs.writeFileSync(full, fm.join('\n') + text);
|
|
221
|
+
res.changed.push(refId);
|
|
222
|
+
}
|
|
223
|
+
return res;
|
|
224
|
+
}
|
|
225
|
+
export function renderBackfill(r, write) {
|
|
226
|
+
const out = [];
|
|
227
|
+
out.push(`frontmatter-backfill (${write ? 'WRITE' : 'dry-run'})`);
|
|
228
|
+
out.push(`changed: ${r.changed.length} skipped (already had frontmatter): ${r.skippedExisting} holdouts: ${r.holdouts.length}`);
|
|
229
|
+
for (const h of r.holdouts.slice(0, 20))
|
|
230
|
+
out.push(` ! ${h.ref}: missing ${h.missing}`);
|
|
231
|
+
return out.join('\n') + '\n';
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=induction-audit.js.map
|