@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,717 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ralph External Process Launcher
|
|
3
|
+
*
|
|
4
|
+
* Spawns the external Ralph supervisor as a detached background process
|
|
5
|
+
* that survives terminal closure and can be managed across sessions.
|
|
6
|
+
*
|
|
7
|
+
* @implements @.aiwg/working/issue-ralph-external-completion.md
|
|
8
|
+
* @issue #275
|
|
9
|
+
* @security docs/ralph-external-security.md
|
|
10
|
+
*
|
|
11
|
+
* SECURITY WARNING
|
|
12
|
+
* ================
|
|
13
|
+
* This module launches Claude Code sessions with --dangerously-skip-permissions.
|
|
14
|
+
* Spawned sessions can read/write ANY file and execute ANY command without
|
|
15
|
+
* user confirmation. Sessions run as detached daemons for extended periods
|
|
16
|
+
* without human oversight.
|
|
17
|
+
*
|
|
18
|
+
* BEFORE USING:
|
|
19
|
+
* - Read docs/ralph-external-security.md
|
|
20
|
+
* - Understand all security implications
|
|
21
|
+
* - Set appropriate limits (budget, iterations, timeout)
|
|
22
|
+
* - Ensure clean git state for rollback capability
|
|
23
|
+
* - Have monitoring and abort procedures ready
|
|
24
|
+
*/
|
|
25
|
+
import { spawn } from 'child_process';
|
|
26
|
+
import { join } from 'path';
|
|
27
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, rmSync, readdirSync, copyFileSync, statSync, openSync, readSync, closeSync, } from 'fs';
|
|
28
|
+
import { getProviderConfig } from '../agent-spawn.js';
|
|
29
|
+
import { AiwgError, EXIT_CODES } from '../errors.js';
|
|
30
|
+
import { projectAiwgPath } from '../../config/project-artifacts.js';
|
|
31
|
+
/**
|
|
32
|
+
* Get the path to the external Ralph orchestrator
|
|
33
|
+
*/
|
|
34
|
+
export function getOrchestratorPath(frameworkRoot) {
|
|
35
|
+
return join(frameworkRoot, 'tools', 'ralph-external', 'index.mjs');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get the registry directory path
|
|
39
|
+
*/
|
|
40
|
+
export function getRegistryDir(projectRoot) {
|
|
41
|
+
return projectAiwgPath(projectRoot, 'ralph-external');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the registry file path
|
|
45
|
+
*/
|
|
46
|
+
export function getRegistryPath(projectRoot) {
|
|
47
|
+
return join(getRegistryDir(projectRoot), 'registry.json');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Generate a unique loop ID
|
|
51
|
+
*/
|
|
52
|
+
export function generateLoopId(objective) {
|
|
53
|
+
const slug = objective
|
|
54
|
+
.toLowerCase()
|
|
55
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
56
|
+
.replace(/^-+|-+$/g, '')
|
|
57
|
+
.slice(0, 30);
|
|
58
|
+
const shortId = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
|
|
59
|
+
return `ralph-${slug}-${shortId}`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Build command-line arguments for the external Ralph process
|
|
63
|
+
*/
|
|
64
|
+
export function buildArgs(options) {
|
|
65
|
+
const args = [options.objective];
|
|
66
|
+
args.push('--completion', options.completionCriteria);
|
|
67
|
+
if (options.maxIterations) {
|
|
68
|
+
args.push('--max-iterations', String(options.maxIterations));
|
|
69
|
+
}
|
|
70
|
+
if (options.model) {
|
|
71
|
+
args.push('--model', options.model);
|
|
72
|
+
}
|
|
73
|
+
if (options.budget) {
|
|
74
|
+
args.push('--budget', String(options.budget));
|
|
75
|
+
}
|
|
76
|
+
if (options.maxTotalTokens) {
|
|
77
|
+
args.push('--max-total-tokens', String(options.maxTotalTokens));
|
|
78
|
+
}
|
|
79
|
+
if (options.maxOutputTokens) {
|
|
80
|
+
args.push('--max-output-tokens', String(options.maxOutputTokens));
|
|
81
|
+
}
|
|
82
|
+
if (options.maxToolCalls) {
|
|
83
|
+
args.push('--max-tool-calls', String(options.maxToolCalls));
|
|
84
|
+
}
|
|
85
|
+
if (options.maxTotalCost) {
|
|
86
|
+
args.push('--max-total-cost', String(options.maxTotalCost));
|
|
87
|
+
}
|
|
88
|
+
if (options.maxWallClockMinutes) {
|
|
89
|
+
args.push('--max-wall-clock-minutes', String(options.maxWallClockMinutes));
|
|
90
|
+
}
|
|
91
|
+
if (options.explorationQuota) {
|
|
92
|
+
args.push('--exploration-quota', String(options.explorationQuota));
|
|
93
|
+
}
|
|
94
|
+
if (options.budgetStopPolicy) {
|
|
95
|
+
args.push('--budget-stop-policy', options.budgetStopPolicy);
|
|
96
|
+
}
|
|
97
|
+
if (options.timeout) {
|
|
98
|
+
args.push('--timeout', String(options.timeout));
|
|
99
|
+
}
|
|
100
|
+
if (options.mcpConfig) {
|
|
101
|
+
args.push('--mcp-config', options.mcpConfig);
|
|
102
|
+
}
|
|
103
|
+
if (options.giteaIssue) {
|
|
104
|
+
args.push('--gitea-issue');
|
|
105
|
+
}
|
|
106
|
+
if (options.memory !== undefined) {
|
|
107
|
+
args.push('--memory', String(options.memory));
|
|
108
|
+
}
|
|
109
|
+
if (options.crossTask === false) {
|
|
110
|
+
args.push('--no-cross-task');
|
|
111
|
+
}
|
|
112
|
+
if (options.enableAnalytics === false) {
|
|
113
|
+
args.push('--no-analytics');
|
|
114
|
+
}
|
|
115
|
+
if (options.enableBestOutput === false) {
|
|
116
|
+
args.push('--no-best-output');
|
|
117
|
+
}
|
|
118
|
+
if (options.enableEarlyStopping === false) {
|
|
119
|
+
args.push('--no-early-stopping');
|
|
120
|
+
}
|
|
121
|
+
if (options.provider && options.provider !== 'claude') {
|
|
122
|
+
args.push('--provider', options.provider);
|
|
123
|
+
}
|
|
124
|
+
if (options.dangerous) {
|
|
125
|
+
args.push('--dangerous');
|
|
126
|
+
}
|
|
127
|
+
if (options.params) {
|
|
128
|
+
args.push('--params', options.params);
|
|
129
|
+
}
|
|
130
|
+
if (options.verbose) {
|
|
131
|
+
args.push('--verbose');
|
|
132
|
+
}
|
|
133
|
+
if (options.logFile) {
|
|
134
|
+
args.push('--log-file', options.logFile);
|
|
135
|
+
}
|
|
136
|
+
return args;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Enforce `parallelism.max_parallel_ralph_loops` from `.aiwg/aiwg.config`.
|
|
140
|
+
* Hard-fails (throws AiwgError) when the count of running + live Ralph loops
|
|
141
|
+
* already meets or exceeds the cap. Non-fatal when no config or config read
|
|
142
|
+
* fails — caller proceeds with launch.
|
|
143
|
+
*
|
|
144
|
+
* Extracted so the cap-check logic is unit-testable independently of the
|
|
145
|
+
* detached-process spawn machinery.
|
|
146
|
+
*
|
|
147
|
+
* @implements #1361
|
|
148
|
+
*/
|
|
149
|
+
export async function assertRalphParallelismCap(projectRoot) {
|
|
150
|
+
let cfg;
|
|
151
|
+
let resolveParallelism;
|
|
152
|
+
try {
|
|
153
|
+
const mod = await import('../../config/aiwg-config.js');
|
|
154
|
+
resolveParallelism = mod.resolveParallelism;
|
|
155
|
+
cfg = await mod.readAiwgConfig(projectRoot);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return; // Config unreadable — non-fatal, let launch proceed
|
|
159
|
+
}
|
|
160
|
+
if (!cfg)
|
|
161
|
+
return;
|
|
162
|
+
const resolved = resolveParallelism(cfg.parallelism, cfg.providers[0]);
|
|
163
|
+
const launcherRegistry = loadLauncherRegistry(projectRoot);
|
|
164
|
+
const activeCount = Object.values(launcherRegistry.loops).filter((l) => l.status === 'running' && isProcessAlive(l.pid)).length;
|
|
165
|
+
if (activeCount >= resolved.max_parallel_ralph_loops) {
|
|
166
|
+
throw new AiwgError({
|
|
167
|
+
code: 'ERR_RALPH_PARALLELISM_CAP',
|
|
168
|
+
message: `Project parallelism cap reached: ${activeCount}/${resolved.max_parallel_ralph_loops} Ralph loops already running.`,
|
|
169
|
+
hint: `Wait for an existing loop to finish ('aiwg ralph-status'), or bump the cap ('aiwg config set --project parallelism.max_parallel_ralph_loops N').`,
|
|
170
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Launch the external Ralph process as a detached daemon
|
|
176
|
+
*/
|
|
177
|
+
export async function launchExternalRalph(frameworkRoot, projectRoot, options) {
|
|
178
|
+
const orchestratorPath = getOrchestratorPath(frameworkRoot);
|
|
179
|
+
if (!existsSync(orchestratorPath)) {
|
|
180
|
+
throw new AiwgError({
|
|
181
|
+
code: 'ERR_RALPH_ORCHESTRATOR_MISSING',
|
|
182
|
+
message: `External Ralph orchestrator not found at: ${orchestratorPath}`,
|
|
183
|
+
hint: 'Run `aiwg use ralph` to deploy the orchestrator, or `npm run build` in the dev repo',
|
|
184
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const registryDir = getRegistryDir(projectRoot);
|
|
188
|
+
mkdirSync(registryDir, { recursive: true });
|
|
189
|
+
// #1361: Enforce project-level max_parallel_ralph_loops cap. Hard fail
|
|
190
|
+
// (not queue) — Ralph loops are long-running, silent queueing would be
|
|
191
|
+
// surprising. Tell the operator what's running and how to lift the cap.
|
|
192
|
+
await assertRalphParallelismCap(projectRoot);
|
|
193
|
+
const loopId = options.loopId || generateLoopId(options.objective);
|
|
194
|
+
const loopDir = join(registryDir, 'loops', loopId);
|
|
195
|
+
mkdirSync(loopDir, { recursive: true });
|
|
196
|
+
// Create output file for the detached process
|
|
197
|
+
const outputFile = join(loopDir, 'daemon-output.log');
|
|
198
|
+
const sessionStdoutFile = join(loopDir, 'outputs', '001-stdout.log');
|
|
199
|
+
const sessionStderrFile = join(loopDir, 'outputs', '001-stderr.log');
|
|
200
|
+
const promptFile = join(loopDir, 'prompts', '001-prompt.md');
|
|
201
|
+
// Build arguments
|
|
202
|
+
const args = buildArgs(options);
|
|
203
|
+
// Create output file descriptors
|
|
204
|
+
const { openSync, closeSync } = await import('fs');
|
|
205
|
+
const outFd = openSync(outputFile, 'w');
|
|
206
|
+
// Spawn detached process
|
|
207
|
+
const child = spawn('node', [orchestratorPath, ...args], {
|
|
208
|
+
detached: true,
|
|
209
|
+
stdio: ['ignore', outFd, outFd],
|
|
210
|
+
cwd: projectRoot,
|
|
211
|
+
env: {
|
|
212
|
+
...process.env,
|
|
213
|
+
RALPH_LOOP_ID: loopId,
|
|
214
|
+
RALPH_DETACHED: 'true',
|
|
215
|
+
...(options.provider ? { RALPH_PROVIDER: options.provider } : {}),
|
|
216
|
+
...(options.dangerous ? {
|
|
217
|
+
RALPH_DANGEROUS: 'true',
|
|
218
|
+
RALPH_DANGEROUS_FLAG: getProviderConfig(options.provider ?? 'claude').dangerousFlag ?? '',
|
|
219
|
+
} : {}),
|
|
220
|
+
...(options.params ? { RALPH_EXTRA_PARAMS: options.params } : {}),
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
// Detach from parent - let it run independently
|
|
224
|
+
child.unref();
|
|
225
|
+
closeSync(outFd);
|
|
226
|
+
const pid = child.pid;
|
|
227
|
+
if (!pid) {
|
|
228
|
+
throw new AiwgError({
|
|
229
|
+
code: 'ERR_RALPH_SPAWN_FAILED',
|
|
230
|
+
message: 'Failed to start external Ralph process — no PID returned by spawn',
|
|
231
|
+
hint: 'Check system resources (ulimit -u) and that `node` is on PATH',
|
|
232
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
// Record the loop in our launcher registry (backup to the external-multi-loop-state-manager)
|
|
236
|
+
const launcherRegistry = loadLauncherRegistry(projectRoot);
|
|
237
|
+
launcherRegistry.loops[loopId] = {
|
|
238
|
+
loopId,
|
|
239
|
+
pid,
|
|
240
|
+
objective: options.objective,
|
|
241
|
+
completionCriteria: options.completionCriteria,
|
|
242
|
+
status: 'running',
|
|
243
|
+
startedAt: new Date().toISOString(),
|
|
244
|
+
lastUpdate: new Date().toISOString(),
|
|
245
|
+
iteration: 0,
|
|
246
|
+
maxIterations: options.maxIterations || 5,
|
|
247
|
+
outputFile,
|
|
248
|
+
sessionStdoutFile,
|
|
249
|
+
sessionStderrFile,
|
|
250
|
+
promptFile,
|
|
251
|
+
provider: options.provider,
|
|
252
|
+
};
|
|
253
|
+
saveLauncherRegistry(projectRoot, launcherRegistry);
|
|
254
|
+
return {
|
|
255
|
+
success: true,
|
|
256
|
+
loopId,
|
|
257
|
+
pid,
|
|
258
|
+
message: `agent loop started (${loopId}). Check status: aiwg ralph-status`,
|
|
259
|
+
registryPath: getRegistryPath(projectRoot),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Load the launcher registry
|
|
264
|
+
*/
|
|
265
|
+
export function loadLauncherRegistry(projectRoot) {
|
|
266
|
+
const registryPath = join(getRegistryDir(projectRoot), 'launcher-registry.json');
|
|
267
|
+
if (!existsSync(registryPath)) {
|
|
268
|
+
return {
|
|
269
|
+
version: '1.0.0',
|
|
270
|
+
loops: {},
|
|
271
|
+
updatedAt: new Date().toISOString(),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
try {
|
|
275
|
+
return JSON.parse(readFileSync(registryPath, 'utf8'));
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return {
|
|
279
|
+
version: '1.0.0',
|
|
280
|
+
loops: {},
|
|
281
|
+
updatedAt: new Date().toISOString(),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Save the launcher registry
|
|
287
|
+
*/
|
|
288
|
+
export function saveLauncherRegistry(projectRoot, registry) {
|
|
289
|
+
const registryDir = getRegistryDir(projectRoot);
|
|
290
|
+
mkdirSync(registryDir, { recursive: true });
|
|
291
|
+
const registryPath = join(registryDir, 'launcher-registry.json');
|
|
292
|
+
registry.updatedAt = new Date().toISOString();
|
|
293
|
+
writeFileSync(registryPath, JSON.stringify(registry, null, 2));
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Check if a process is still running
|
|
297
|
+
*/
|
|
298
|
+
export function isProcessAlive(pid) {
|
|
299
|
+
try {
|
|
300
|
+
process.kill(pid, 0);
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Get status of all agent loops.
|
|
309
|
+
* Detects stale entries (>24h without heartbeat) and auto-cleans completed entries.
|
|
310
|
+
*/
|
|
311
|
+
export function getLoopStatuses(projectRoot, options = {}) {
|
|
312
|
+
const registry = loadLauncherRegistry(projectRoot);
|
|
313
|
+
const statuses = [];
|
|
314
|
+
const staleThresholdMs = 24 * 60 * 60 * 1000; // 24 hours
|
|
315
|
+
let registryDirty = false;
|
|
316
|
+
for (const [loopId, entry] of Object.entries(registry.loops)) {
|
|
317
|
+
// Update status based on process liveness
|
|
318
|
+
if (entry.status === 'running' && !isProcessAlive(entry.pid)) {
|
|
319
|
+
// Process died - mark as failed unless we can determine it completed
|
|
320
|
+
const stateFile = join(getRegistryDir(projectRoot), 'loops', loopId, 'session-state.json');
|
|
321
|
+
if (existsSync(stateFile)) {
|
|
322
|
+
try {
|
|
323
|
+
const state = JSON.parse(readFileSync(stateFile, 'utf8'));
|
|
324
|
+
entry.status = state.status || 'failed';
|
|
325
|
+
entry.iteration = state.currentIteration || entry.iteration;
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
entry.status = 'failed';
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
entry.status = 'failed';
|
|
333
|
+
}
|
|
334
|
+
registryDirty = true;
|
|
335
|
+
}
|
|
336
|
+
// Detect stale entries (>24h since last update)
|
|
337
|
+
const lastUpdateAge = Date.now() - new Date(entry.lastUpdate).getTime();
|
|
338
|
+
if (lastUpdateAge > staleThresholdMs && entry.status === 'running') {
|
|
339
|
+
entry.stale = true;
|
|
340
|
+
}
|
|
341
|
+
// Auto-clean completed entries if requested
|
|
342
|
+
if (options.autoCleanCompleted && (entry.status === 'completed')) {
|
|
343
|
+
cleanupCompletedLoop(projectRoot, loopId);
|
|
344
|
+
registryDirty = true;
|
|
345
|
+
continue; // Don't include in statuses
|
|
346
|
+
}
|
|
347
|
+
statuses.push(entry);
|
|
348
|
+
}
|
|
349
|
+
if (registryDirty) {
|
|
350
|
+
saveLauncherRegistry(projectRoot, registry);
|
|
351
|
+
}
|
|
352
|
+
return statuses;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Abort a running agent loop by killing its process
|
|
356
|
+
*/
|
|
357
|
+
export function abortLoop(projectRoot, loopId) {
|
|
358
|
+
const registry = loadLauncherRegistry(projectRoot);
|
|
359
|
+
// If no loopId specified, find the most recent running loop
|
|
360
|
+
if (!loopId) {
|
|
361
|
+
const runningLoops = Object.values(registry.loops)
|
|
362
|
+
.filter((l) => l.status === 'running' && isProcessAlive(l.pid))
|
|
363
|
+
.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
|
|
364
|
+
if (runningLoops.length === 0) {
|
|
365
|
+
return { success: false, message: 'No running agent loops found' };
|
|
366
|
+
}
|
|
367
|
+
loopId = runningLoops[0].loopId;
|
|
368
|
+
}
|
|
369
|
+
const entry = registry.loops[loopId];
|
|
370
|
+
if (!entry) {
|
|
371
|
+
return { success: false, message: `Loop not found: ${loopId}` };
|
|
372
|
+
}
|
|
373
|
+
if (!isProcessAlive(entry.pid)) {
|
|
374
|
+
entry.status = 'aborted';
|
|
375
|
+
saveLauncherRegistry(projectRoot, registry);
|
|
376
|
+
return { success: true, message: `Loop ${loopId} was already stopped` };
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
process.kill(entry.pid, 'SIGTERM');
|
|
380
|
+
entry.status = 'aborted';
|
|
381
|
+
entry.lastUpdate = new Date().toISOString();
|
|
382
|
+
saveLauncherRegistry(projectRoot, registry);
|
|
383
|
+
return { success: true, message: `Aborted loop ${loopId} (PID: ${entry.pid})` };
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
return {
|
|
387
|
+
success: false,
|
|
388
|
+
message: `Failed to kill process ${entry.pid}: ${error instanceof Error ? error.message : String(error)}`,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Resume an interrupted agent loop
|
|
394
|
+
*/
|
|
395
|
+
export async function resumeLoop(frameworkRoot, projectRoot, loopId, overrides) {
|
|
396
|
+
const orchestratorPath = getOrchestratorPath(frameworkRoot);
|
|
397
|
+
if (!existsSync(orchestratorPath)) {
|
|
398
|
+
throw new AiwgError({
|
|
399
|
+
code: 'ERR_RALPH_ORCHESTRATOR_MISSING',
|
|
400
|
+
message: `External Ralph orchestrator not found at: ${orchestratorPath}`,
|
|
401
|
+
hint: 'Run `aiwg use ralph` to deploy the orchestrator',
|
|
402
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
// Build resume arguments
|
|
406
|
+
const args = ['--resume'];
|
|
407
|
+
if (overrides?.maxIterations) {
|
|
408
|
+
args.push('--max-iterations', String(overrides.maxIterations));
|
|
409
|
+
}
|
|
410
|
+
const registryDir = getRegistryDir(projectRoot);
|
|
411
|
+
mkdirSync(registryDir, { recursive: true });
|
|
412
|
+
// Find loop to resume
|
|
413
|
+
const registry = loadLauncherRegistry(projectRoot);
|
|
414
|
+
let targetLoopId = loopId;
|
|
415
|
+
if (!targetLoopId) {
|
|
416
|
+
// Find most recent non-running loop
|
|
417
|
+
const resumable = Object.values(registry.loops)
|
|
418
|
+
.filter((l) => l.status !== 'running' || !isProcessAlive(l.pid))
|
|
419
|
+
.sort((a, b) => new Date(b.lastUpdate).getTime() - new Date(a.lastUpdate).getTime());
|
|
420
|
+
if (resumable.length === 0) {
|
|
421
|
+
throw new AiwgError({
|
|
422
|
+
code: 'ERR_RALPH_NO_RESUMABLE',
|
|
423
|
+
message: 'No loops available to resume',
|
|
424
|
+
hint: 'Start a new loop with: aiwg ralph "<objective>"',
|
|
425
|
+
exitCode: EXIT_CODES.USAGE,
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
targetLoopId = resumable[0].loopId;
|
|
429
|
+
}
|
|
430
|
+
const entry = registry.loops[targetLoopId];
|
|
431
|
+
if (!entry) {
|
|
432
|
+
throw new AiwgError({
|
|
433
|
+
code: 'ERR_RALPH_LOOP_NOT_FOUND',
|
|
434
|
+
message: `Loop not found: ${targetLoopId}`,
|
|
435
|
+
hint: 'List available loops with: aiwg ralph-status',
|
|
436
|
+
exitCode: EXIT_CODES.USAGE,
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
const loopDir = join(registryDir, 'loops', targetLoopId);
|
|
440
|
+
const outputFile = join(loopDir, 'daemon-output.log');
|
|
441
|
+
// Create output file descriptor
|
|
442
|
+
const { openSync, closeSync } = await import('fs');
|
|
443
|
+
const outFd = openSync(outputFile, 'a'); // Append mode for resume
|
|
444
|
+
// Spawn detached process
|
|
445
|
+
const child = spawn('node', [orchestratorPath, ...args], {
|
|
446
|
+
detached: true,
|
|
447
|
+
stdio: ['ignore', outFd, outFd],
|
|
448
|
+
cwd: projectRoot,
|
|
449
|
+
env: {
|
|
450
|
+
...process.env,
|
|
451
|
+
RALPH_LOOP_ID: targetLoopId,
|
|
452
|
+
RALPH_DETACHED: 'true',
|
|
453
|
+
},
|
|
454
|
+
});
|
|
455
|
+
child.unref();
|
|
456
|
+
closeSync(outFd);
|
|
457
|
+
const pid = child.pid;
|
|
458
|
+
if (!pid) {
|
|
459
|
+
throw new AiwgError({
|
|
460
|
+
code: 'ERR_RALPH_SPAWN_FAILED',
|
|
461
|
+
message: 'Failed to start external Ralph process — no PID returned by spawn',
|
|
462
|
+
hint: 'Check system resources (ulimit -u) and that `node` is on PATH',
|
|
463
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
// Update registry
|
|
467
|
+
entry.pid = pid;
|
|
468
|
+
entry.status = 'running';
|
|
469
|
+
entry.lastUpdate = new Date().toISOString();
|
|
470
|
+
if (overrides?.maxIterations) {
|
|
471
|
+
entry.maxIterations = overrides.maxIterations;
|
|
472
|
+
}
|
|
473
|
+
saveLauncherRegistry(projectRoot, registry);
|
|
474
|
+
return {
|
|
475
|
+
success: true,
|
|
476
|
+
loopId: targetLoopId,
|
|
477
|
+
pid,
|
|
478
|
+
message: `Resumed agent loop (${targetLoopId}). Check status: aiwg ralph-status`,
|
|
479
|
+
registryPath: getRegistryPath(projectRoot),
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Clean up a completed loop: remove from launcher-registry and delete working state.
|
|
484
|
+
* Preserves completion reports by moving them to the ralph-external root before deletion.
|
|
485
|
+
*
|
|
486
|
+
* @param projectRoot - Project root directory
|
|
487
|
+
* @param loopId - Loop ID to clean up
|
|
488
|
+
* @param options - Cleanup options
|
|
489
|
+
* @returns Object with success status and details
|
|
490
|
+
*/
|
|
491
|
+
export function cleanupCompletedLoop(projectRoot, loopId, options = {}) {
|
|
492
|
+
const registryDir = getRegistryDir(projectRoot);
|
|
493
|
+
const loopDir = join(registryDir, 'loops', loopId);
|
|
494
|
+
const preserved = [];
|
|
495
|
+
// Preserve completion reports before deleting the loop directory
|
|
496
|
+
if (existsSync(loopDir)) {
|
|
497
|
+
try {
|
|
498
|
+
const files = readdirSync(loopDir);
|
|
499
|
+
for (const file of files) {
|
|
500
|
+
if (file.startsWith('completion-') && file.endsWith('.md')) {
|
|
501
|
+
const dest = join(registryDir, file);
|
|
502
|
+
copyFileSync(join(loopDir, file), dest);
|
|
503
|
+
preserved.push(dest);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
catch {
|
|
508
|
+
// Non-fatal: proceed with cleanup even if report preservation fails
|
|
509
|
+
}
|
|
510
|
+
if (options.archive) {
|
|
511
|
+
// Move to archive instead of deleting
|
|
512
|
+
const archiveDir = join(registryDir, 'archive', loopId);
|
|
513
|
+
mkdirSync(join(registryDir, 'archive'), { recursive: true });
|
|
514
|
+
try {
|
|
515
|
+
const { renameSync } = require('fs');
|
|
516
|
+
renameSync(loopDir, archiveDir);
|
|
517
|
+
}
|
|
518
|
+
catch {
|
|
519
|
+
// If rename fails (cross-device), fall through to deletion
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
// Delete working state
|
|
524
|
+
try {
|
|
525
|
+
rmSync(loopDir, { recursive: true, force: true });
|
|
526
|
+
}
|
|
527
|
+
catch {
|
|
528
|
+
// Non-fatal
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
// Remove entry from launcher registry
|
|
533
|
+
const registry = loadLauncherRegistry(projectRoot);
|
|
534
|
+
if (registry.loops[loopId]) {
|
|
535
|
+
delete registry.loops[loopId];
|
|
536
|
+
saveLauncherRegistry(projectRoot, registry);
|
|
537
|
+
}
|
|
538
|
+
return {
|
|
539
|
+
success: true,
|
|
540
|
+
message: `Cleaned up loop ${loopId}`,
|
|
541
|
+
preserved,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Clean up internal Ralph state after successful completion.
|
|
546
|
+
* Deletes current-loop.json, heartbeats, and iteration working state.
|
|
547
|
+
* Preserves completion report files.
|
|
548
|
+
*
|
|
549
|
+
* @param projectRoot - Project root directory
|
|
550
|
+
* @returns Object with success status and what was cleaned
|
|
551
|
+
*/
|
|
552
|
+
export function cleanupInternalRalph(projectRoot) {
|
|
553
|
+
const ralphDir = projectAiwgPath(projectRoot, 'ralph');
|
|
554
|
+
const cleaned = [];
|
|
555
|
+
const preserved = [];
|
|
556
|
+
if (!existsSync(ralphDir)) {
|
|
557
|
+
return { success: true, cleaned: [], preserved: [] };
|
|
558
|
+
}
|
|
559
|
+
// Check if current-loop.json exists and is completed
|
|
560
|
+
const currentLoopPath = join(ralphDir, 'current-loop.json');
|
|
561
|
+
if (existsSync(currentLoopPath)) {
|
|
562
|
+
try {
|
|
563
|
+
const state = JSON.parse(readFileSync(currentLoopPath, 'utf8'));
|
|
564
|
+
if (state.status === 'completed' || state.status === 'success') {
|
|
565
|
+
rmSync(currentLoopPath, { force: true });
|
|
566
|
+
cleaned.push('current-loop.json');
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
catch {
|
|
570
|
+
// If we can't parse it, leave it alone
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
// Clean up heartbeats directory
|
|
574
|
+
const heartbeatsDir = join(ralphDir, 'heartbeats');
|
|
575
|
+
if (existsSync(heartbeatsDir)) {
|
|
576
|
+
try {
|
|
577
|
+
rmSync(heartbeatsDir, { recursive: true, force: true });
|
|
578
|
+
cleaned.push('heartbeats/');
|
|
579
|
+
}
|
|
580
|
+
catch {
|
|
581
|
+
// Non-fatal
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
// Clean up iterations working state (but preserve completion reports)
|
|
585
|
+
const iterationsDir = join(ralphDir, 'iterations');
|
|
586
|
+
if (existsSync(iterationsDir)) {
|
|
587
|
+
try {
|
|
588
|
+
rmSync(iterationsDir, { recursive: true, force: true });
|
|
589
|
+
cleaned.push('iterations/');
|
|
590
|
+
}
|
|
591
|
+
catch {
|
|
592
|
+
// Non-fatal
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
// Log preserved completion reports
|
|
596
|
+
try {
|
|
597
|
+
const files = readdirSync(ralphDir);
|
|
598
|
+
for (const file of files) {
|
|
599
|
+
if (file.startsWith('completion-') && file.endsWith('.md')) {
|
|
600
|
+
preserved.push(file);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
catch {
|
|
605
|
+
// Non-fatal
|
|
606
|
+
}
|
|
607
|
+
return { success: true, cleaned, preserved };
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Clean up completed/failed loops from registry
|
|
611
|
+
*/
|
|
612
|
+
export function cleanupRegistry(projectRoot, keepDays = 7) {
|
|
613
|
+
const registry = loadLauncherRegistry(projectRoot);
|
|
614
|
+
const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1000;
|
|
615
|
+
let cleaned = 0;
|
|
616
|
+
for (const [loopId, entry] of Object.entries(registry.loops)) {
|
|
617
|
+
if (entry.status !== 'running') {
|
|
618
|
+
const lastUpdate = new Date(entry.lastUpdate).getTime();
|
|
619
|
+
if (lastUpdate < cutoff) {
|
|
620
|
+
delete registry.loops[loopId];
|
|
621
|
+
cleaned++;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (cleaned > 0) {
|
|
626
|
+
saveLauncherRegistry(projectRoot, registry);
|
|
627
|
+
}
|
|
628
|
+
return cleaned;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Attach to a running agent loop's output stream.
|
|
632
|
+
*
|
|
633
|
+
* Tails the loop's daemon-output.log to stdout in real-time.
|
|
634
|
+
* Ctrl+C detaches (the background loop keeps running).
|
|
635
|
+
* Returns a Promise that resolves when the user detaches or the loop exits.
|
|
636
|
+
*/
|
|
637
|
+
export function attachToLoopOutput(projectRoot, loopId) {
|
|
638
|
+
const registry = loadLauncherRegistry(projectRoot);
|
|
639
|
+
const entries = Object.values(registry.loops);
|
|
640
|
+
let entry;
|
|
641
|
+
if (loopId) {
|
|
642
|
+
entry = registry.loops[loopId];
|
|
643
|
+
if (!entry) {
|
|
644
|
+
return Promise.reject(new Error(`Loop not found: ${loopId}`));
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
// Use most recently started running loop
|
|
649
|
+
const running = entries
|
|
650
|
+
.filter((e) => e.status === 'running' && isProcessAlive(e.pid))
|
|
651
|
+
.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
|
|
652
|
+
if (running.length === 0) {
|
|
653
|
+
return Promise.reject(new Error('No running loops to attach to. Use --loop-id to specify a loop.'));
|
|
654
|
+
}
|
|
655
|
+
entry = running[0];
|
|
656
|
+
}
|
|
657
|
+
const outputFile = entry.outputFile;
|
|
658
|
+
const attachedLoopId = entry.loopId;
|
|
659
|
+
return new Promise((resolve) => {
|
|
660
|
+
let offset = 0;
|
|
661
|
+
// Print any existing content
|
|
662
|
+
try {
|
|
663
|
+
const stats = statSync(outputFile);
|
|
664
|
+
if (stats.size > 0) {
|
|
665
|
+
const fd = openSync(outputFile, 'r');
|
|
666
|
+
const buf = Buffer.alloc(stats.size);
|
|
667
|
+
readSync(fd, buf, 0, stats.size, 0);
|
|
668
|
+
closeSync(fd);
|
|
669
|
+
process.stdout.write(buf);
|
|
670
|
+
offset = stats.size;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
catch {
|
|
674
|
+
// Log file may not exist yet — will appear shortly
|
|
675
|
+
}
|
|
676
|
+
// Poll for new content every 250 ms. .unref() so the interval cannot
|
|
677
|
+
// outlive the resolve() path and hold the event loop alive.
|
|
678
|
+
const interval = setInterval(() => {
|
|
679
|
+
try {
|
|
680
|
+
const stats = statSync(outputFile);
|
|
681
|
+
if (stats.size > offset) {
|
|
682
|
+
const newBytes = stats.size - offset;
|
|
683
|
+
const fd = openSync(outputFile, 'r');
|
|
684
|
+
const buf = Buffer.alloc(newBytes);
|
|
685
|
+
readSync(fd, buf, 0, newBytes, offset);
|
|
686
|
+
closeSync(fd);
|
|
687
|
+
process.stdout.write(buf);
|
|
688
|
+
offset = stats.size;
|
|
689
|
+
}
|
|
690
|
+
// Stop polling if the process has exited
|
|
691
|
+
if (!isProcessAlive(registry.loops[attachedLoopId]?.pid ?? 0)) {
|
|
692
|
+
clearInterval(interval);
|
|
693
|
+
process.removeListener('SIGINT', onSigint);
|
|
694
|
+
process.stdout.write('\n[ralph-attach] Loop process has exited.\n');
|
|
695
|
+
resolve();
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
catch {
|
|
699
|
+
// File may be temporarily unavailable during rotation — ignore
|
|
700
|
+
}
|
|
701
|
+
}, 250);
|
|
702
|
+
interval.unref?.();
|
|
703
|
+
// Ctrl+C detaches without stopping the loop. Registered with named handler
|
|
704
|
+
// + process.once so we can remove it cleanly on process-exit path and so
|
|
705
|
+
// it does not accumulate across re-attach cycles within a single CLI run.
|
|
706
|
+
const onSigint = () => {
|
|
707
|
+
clearInterval(interval);
|
|
708
|
+
process.stdout.write('\n\nDetached from loop output. Loop continues in background.\n');
|
|
709
|
+
process.stdout.write(` Status: aiwg ralph-status\n`);
|
|
710
|
+
process.stdout.write(` Re-attach: aiwg ralph-attach --loop-id ${attachedLoopId}\n`);
|
|
711
|
+
process.stdout.write(` Abort: aiwg ralph-abort --loop-id ${attachedLoopId}\n`);
|
|
712
|
+
resolve();
|
|
713
|
+
};
|
|
714
|
+
process.once('SIGINT', onSigint);
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
//# sourceMappingURL=ralph-launcher.js.map
|