@10et/cli 1.0.0
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 +79 -0
- package/clawdbot-plugin/clawdbot.plugin.json +20 -0
- package/clawdbot-plugin/index.js +555 -0
- package/clawdbot-plugin/index.ts +582 -0
- package/clawdbot-skill/README.md +328 -0
- package/clawdbot-skill/SKILL.md +59 -0
- package/clawdbot-skill/index.ts +683 -0
- package/clawdbot-skill/package.json +28 -0
- package/clawdbot-skill/skill.json +19 -0
- package/dist/commands/agent.d.ts +7 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +170 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/agents.d.ts +5 -0
- package/dist/commands/agents.d.ts.map +1 -0
- package/dist/commands/agents.js +400 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/ci-setup.d.ts +5 -0
- package/dist/commands/ci-setup.d.ts.map +1 -0
- package/dist/commands/ci-setup.js +82 -0
- package/dist/commands/ci-setup.js.map +1 -0
- package/dist/commands/clawdbot.d.ts +11 -0
- package/dist/commands/clawdbot.d.ts.map +1 -0
- package/dist/commands/clawdbot.js +215 -0
- package/dist/commands/clawdbot.js.map +1 -0
- package/dist/commands/context-hub.d.ts +22 -0
- package/dist/commands/context-hub.d.ts.map +1 -0
- package/dist/commands/context-hub.js +3505 -0
- package/dist/commands/context-hub.js.map +1 -0
- package/dist/commands/deploy.d.ts +5 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +371 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/digest.d.ts +12 -0
- package/dist/commands/digest.d.ts.map +1 -0
- package/dist/commands/digest.js +128 -0
- package/dist/commands/digest.js.map +1 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +265 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/eval.d.ts +46 -0
- package/dist/commands/eval.d.ts.map +1 -0
- package/dist/commands/eval.js +427 -0
- package/dist/commands/eval.js.map +1 -0
- package/dist/commands/feedback.d.ts +2 -0
- package/dist/commands/feedback.d.ts.map +1 -0
- package/dist/commands/feedback.js +179 -0
- package/dist/commands/feedback.js.map +1 -0
- package/dist/commands/findings.d.ts +13 -0
- package/dist/commands/findings.d.ts.map +1 -0
- package/dist/commands/findings.js +203 -0
- package/dist/commands/findings.js.map +1 -0
- package/dist/commands/flows.d.ts +10 -0
- package/dist/commands/flows.d.ts.map +1 -0
- package/dist/commands/flows.js +423 -0
- package/dist/commands/flows.js.map +1 -0
- package/dist/commands/gtm-process-update.d.ts +10 -0
- package/dist/commands/gtm-process-update.d.ts.map +1 -0
- package/dist/commands/gtm-process-update.js +101 -0
- package/dist/commands/gtm-process-update.js.map +1 -0
- package/dist/commands/hooks.d.ts +13 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +304 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/hud.d.ts +4 -0
- package/dist/commands/hud.d.ts.map +1 -0
- package/dist/commands/hud.js +300 -0
- package/dist/commands/hud.js.map +1 -0
- package/dist/commands/ide.d.ts +28 -0
- package/dist/commands/ide.d.ts.map +1 -0
- package/dist/commands/ide.js +628 -0
- package/dist/commands/ide.js.map +1 -0
- package/dist/commands/improve.d.ts +11 -0
- package/dist/commands/improve.d.ts.map +1 -0
- package/dist/commands/improve.js +77 -0
- package/dist/commands/improve.js.map +1 -0
- package/dist/commands/init-from-service.d.ts +15 -0
- package/dist/commands/init-from-service.d.ts.map +1 -0
- package/dist/commands/init-from-service.js +540 -0
- package/dist/commands/init-from-service.js.map +1 -0
- package/dist/commands/init.d.ts +15 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +940 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/kanban.d.ts +34 -0
- package/dist/commands/kanban.d.ts.map +1 -0
- package/dist/commands/kanban.js +225 -0
- package/dist/commands/kanban.js.map +1 -0
- package/dist/commands/linear.d.ts +41 -0
- package/dist/commands/linear.d.ts.map +1 -0
- package/dist/commands/linear.js +740 -0
- package/dist/commands/linear.js.map +1 -0
- package/dist/commands/login.d.ts +12 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +780 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/memory.d.ts +38 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +229 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/migrate-services.d.ts +8 -0
- package/dist/commands/migrate-services.d.ts.map +1 -0
- package/dist/commands/migrate-services.js +182 -0
- package/dist/commands/migrate-services.js.map +1 -0
- package/dist/commands/migrate-tenet.d.ts +25 -0
- package/dist/commands/migrate-tenet.d.ts.map +1 -0
- package/dist/commands/migrate-tenet.js +252 -0
- package/dist/commands/migrate-tenet.js.map +1 -0
- package/dist/commands/onboard.d.ts +24 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +873 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/openclaw.d.ts +59 -0
- package/dist/commands/openclaw.d.ts.map +1 -0
- package/dist/commands/openclaw.js +775 -0
- package/dist/commands/openclaw.js.map +1 -0
- package/dist/commands/orchestrate.d.ts +14 -0
- package/dist/commands/orchestrate.d.ts.map +1 -0
- package/dist/commands/orchestrate.js +270 -0
- package/dist/commands/orchestrate.js.map +1 -0
- package/dist/commands/organize.d.ts +16 -0
- package/dist/commands/organize.d.ts.map +1 -0
- package/dist/commands/organize.js +334 -0
- package/dist/commands/organize.js.map +1 -0
- package/dist/commands/peter.d.ts +21 -0
- package/dist/commands/peter.d.ts.map +1 -0
- package/dist/commands/peter.js +2778 -0
- package/dist/commands/peter.js.map +1 -0
- package/dist/commands/pi-fleet.d.ts +18 -0
- package/dist/commands/pi-fleet.d.ts.map +1 -0
- package/dist/commands/pi-fleet.js +382 -0
- package/dist/commands/pi-fleet.js.map +1 -0
- package/dist/commands/pi.d.ts +25 -0
- package/dist/commands/pi.d.ts.map +1 -0
- package/dist/commands/pi.js +218 -0
- package/dist/commands/pi.js.map +1 -0
- package/dist/commands/pivot.d.ts +28 -0
- package/dist/commands/pivot.d.ts.map +1 -0
- package/dist/commands/pivot.js +216 -0
- package/dist/commands/pivot.js.map +1 -0
- package/dist/commands/portfolio.d.ts +11 -0
- package/dist/commands/portfolio.d.ts.map +1 -0
- package/dist/commands/portfolio.js +239 -0
- package/dist/commands/portfolio.js.map +1 -0
- package/dist/commands/predict.d.ts +25 -0
- package/dist/commands/predict.d.ts.map +1 -0
- package/dist/commands/predict.js +234 -0
- package/dist/commands/predict.js.map +1 -0
- package/dist/commands/profile.d.ts +46 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +498 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/ralph.d.ts +11 -0
- package/dist/commands/ralph.d.ts.map +1 -0
- package/dist/commands/ralph.js +102 -0
- package/dist/commands/ralph.js.map +1 -0
- package/dist/commands/repair.d.ts +7 -0
- package/dist/commands/repair.d.ts.map +1 -0
- package/dist/commands/repair.js +356 -0
- package/dist/commands/repair.js.map +1 -0
- package/dist/commands/scope.d.ts +8 -0
- package/dist/commands/scope.d.ts.map +1 -0
- package/dist/commands/scope.js +503 -0
- package/dist/commands/scope.js.map +1 -0
- package/dist/commands/service-agent.d.ts +16 -0
- package/dist/commands/service-agent.d.ts.map +1 -0
- package/dist/commands/service-agent.js +375 -0
- package/dist/commands/service-agent.js.map +1 -0
- package/dist/commands/service-manager.d.ts +12 -0
- package/dist/commands/service-manager.d.ts.map +1 -0
- package/dist/commands/service-manager.js +969 -0
- package/dist/commands/service-manager.js.map +1 -0
- package/dist/commands/service-validate.d.ts +12 -0
- package/dist/commands/service-validate.d.ts.map +1 -0
- package/dist/commands/service-validate.js +619 -0
- package/dist/commands/service-validate.js.map +1 -0
- package/dist/commands/services-create.d.ts +15 -0
- package/dist/commands/services-create.d.ts.map +1 -0
- package/dist/commands/services-create.js +1800 -0
- package/dist/commands/services-create.js.map +1 -0
- package/dist/commands/services-scan.d.ts +13 -0
- package/dist/commands/services-scan.d.ts.map +1 -0
- package/dist/commands/services-scan.js +251 -0
- package/dist/commands/services-scan.js.map +1 -0
- package/dist/commands/services-sync-agents.d.ts +23 -0
- package/dist/commands/services-sync-agents.d.ts.map +1 -0
- package/dist/commands/services-sync-agents.js +207 -0
- package/dist/commands/services-sync-agents.js.map +1 -0
- package/dist/commands/services.d.ts +19 -0
- package/dist/commands/services.d.ts.map +1 -0
- package/dist/commands/services.js +906 -0
- package/dist/commands/services.js.map +1 -0
- package/dist/commands/session.d.ts +7 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +597 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/setup.d.ts +12 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +727 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/skills.d.ts +31 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +314 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/start.d.ts +25 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +251 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +163 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/synopsis.d.ts +54 -0
- package/dist/commands/synopsis.d.ts.map +1 -0
- package/dist/commands/synopsis.js +277 -0
- package/dist/commands/synopsis.js.map +1 -0
- package/dist/commands/telemetry-monitor.d.ts +11 -0
- package/dist/commands/telemetry-monitor.d.ts.map +1 -0
- package/dist/commands/telemetry-monitor.js +224 -0
- package/dist/commands/telemetry-monitor.js.map +1 -0
- package/dist/commands/telemetry-test.d.ts +11 -0
- package/dist/commands/telemetry-test.d.ts.map +1 -0
- package/dist/commands/telemetry-test.js +67 -0
- package/dist/commands/telemetry-test.js.map +1 -0
- package/dist/commands/tenet-agents.d.ts +13 -0
- package/dist/commands/tenet-agents.d.ts.map +1 -0
- package/dist/commands/tenet-agents.js +191 -0
- package/dist/commands/tenet-agents.js.map +1 -0
- package/dist/commands/tenet-setup.d.ts +20 -0
- package/dist/commands/tenet-setup.d.ts.map +1 -0
- package/dist/commands/tenet-setup.js +135 -0
- package/dist/commands/tenet-setup.js.map +1 -0
- package/dist/commands/train.d.ts +51 -0
- package/dist/commands/train.d.ts.map +1 -0
- package/dist/commands/train.js +692 -0
- package/dist/commands/train.js.map +1 -0
- package/dist/commands/update.d.ts +12 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +559 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate-settings.d.ts +37 -0
- package/dist/commands/validate-settings.d.ts.map +1 -0
- package/dist/commands/validate-settings.js +197 -0
- package/dist/commands/validate-settings.js.map +1 -0
- package/dist/commands/verify.d.ts +14 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +304 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/viz.d.ts +40 -0
- package/dist/commands/viz.d.ts.map +1 -0
- package/dist/commands/viz.js +877 -0
- package/dist/commands/viz.js.map +1 -0
- package/dist/commands/voice.d.ts +409 -0
- package/dist/commands/voice.d.ts.map +1 -0
- package/dist/commands/voice.js +4765 -0
- package/dist/commands/voice.js.map +1 -0
- package/dist/commands/whoami.d.ts +2 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +24 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/dashboard/index.d.ts +11 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +70 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard-static/assets/index-BVrmW-ZI.js +154 -0
- package/dist/dashboard-static/assets/index-DtruPD44.css +1 -0
- package/dist/dashboard-static/index.html +16 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1707 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/advanced-setup.d.ts +78 -0
- package/dist/lib/advanced-setup.d.ts.map +1 -0
- package/dist/lib/advanced-setup.js +433 -0
- package/dist/lib/advanced-setup.js.map +1 -0
- package/dist/lib/agent-config.d.ts +86 -0
- package/dist/lib/agent-config.d.ts.map +1 -0
- package/dist/lib/agent-config.js +281 -0
- package/dist/lib/agent-config.js.map +1 -0
- package/dist/lib/agent-generator.d.ts +36 -0
- package/dist/lib/agent-generator.d.ts.map +1 -0
- package/dist/lib/agent-generator.js +400 -0
- package/dist/lib/agent-generator.js.map +1 -0
- package/dist/lib/agent-guards.d.ts +67 -0
- package/dist/lib/agent-guards.d.ts.map +1 -0
- package/dist/lib/agent-guards.js +229 -0
- package/dist/lib/agent-guards.js.map +1 -0
- package/dist/lib/agent-manifest.d.ts +35 -0
- package/dist/lib/agent-manifest.d.ts.map +1 -0
- package/dist/lib/agent-manifest.js +75 -0
- package/dist/lib/agent-manifest.js.map +1 -0
- package/dist/lib/agent-runtime-api.d.ts +32 -0
- package/dist/lib/agent-runtime-api.d.ts.map +1 -0
- package/dist/lib/agent-runtime-api.js +270 -0
- package/dist/lib/agent-runtime-api.js.map +1 -0
- package/dist/lib/agent-session.d.ts +104 -0
- package/dist/lib/agent-session.d.ts.map +1 -0
- package/dist/lib/agent-session.js +954 -0
- package/dist/lib/agent-session.js.map +1 -0
- package/dist/lib/build-supervisor.d.ts +44 -0
- package/dist/lib/build-supervisor.d.ts.map +1 -0
- package/dist/lib/build-supervisor.js +79 -0
- package/dist/lib/build-supervisor.js.map +1 -0
- package/dist/lib/connectors/index.d.ts +19 -0
- package/dist/lib/connectors/index.d.ts.map +1 -0
- package/dist/lib/connectors/index.js +23 -0
- package/dist/lib/connectors/index.js.map +1 -0
- package/dist/lib/counterfactual-engine.d.ts +136 -0
- package/dist/lib/counterfactual-engine.d.ts.map +1 -0
- package/dist/lib/counterfactual-engine.js +417 -0
- package/dist/lib/counterfactual-engine.js.map +1 -0
- package/dist/lib/counterfactual-training-bridge.d.ts +114 -0
- package/dist/lib/counterfactual-training-bridge.d.ts.map +1 -0
- package/dist/lib/counterfactual-training-bridge.js +322 -0
- package/dist/lib/counterfactual-training-bridge.js.map +1 -0
- package/dist/lib/discovery-agent.d.ts +48 -0
- package/dist/lib/discovery-agent.d.ts.map +1 -0
- package/dist/lib/discovery-agent.js +111 -0
- package/dist/lib/discovery-agent.js.map +1 -0
- package/dist/lib/domain/engine.d.ts +11 -0
- package/dist/lib/domain/engine.d.ts.map +1 -0
- package/dist/lib/domain/engine.js +23 -0
- package/dist/lib/domain/engine.js.map +1 -0
- package/dist/lib/domain/index.d.ts +3 -0
- package/dist/lib/domain/index.d.ts.map +1 -0
- package/dist/lib/domain/index.js +3 -0
- package/dist/lib/domain/index.js.map +1 -0
- package/dist/lib/domain/template-loader.d.ts +9 -0
- package/dist/lib/domain/template-loader.d.ts.map +1 -0
- package/dist/lib/domain/template-loader.js +29 -0
- package/dist/lib/domain/template-loader.js.map +1 -0
- package/dist/lib/domain/types.d.ts +29 -0
- package/dist/lib/domain/types.d.ts.map +1 -0
- package/dist/lib/domain/types.js +2 -0
- package/dist/lib/domain/types.js.map +1 -0
- package/dist/lib/dynamics-model.d.ts +107 -0
- package/dist/lib/dynamics-model.d.ts.map +1 -0
- package/dist/lib/dynamics-model.js +363 -0
- package/dist/lib/dynamics-model.js.map +1 -0
- package/dist/lib/eval-snapshot.d.ts +47 -0
- package/dist/lib/eval-snapshot.d.ts.map +1 -0
- package/dist/lib/eval-snapshot.js +326 -0
- package/dist/lib/eval-snapshot.js.map +1 -0
- package/dist/lib/eval-store.d.ts +20 -0
- package/dist/lib/eval-store.d.ts.map +1 -0
- package/dist/lib/eval-store.js +209 -0
- package/dist/lib/eval-store.js.map +1 -0
- package/dist/lib/findings-engine.d.ts +51 -0
- package/dist/lib/findings-engine.d.ts.map +1 -0
- package/dist/lib/findings-engine.js +338 -0
- package/dist/lib/findings-engine.js.map +1 -0
- package/dist/lib/flow-engine.d.ts +57 -0
- package/dist/lib/flow-engine.d.ts.map +1 -0
- package/dist/lib/flow-engine.js +717 -0
- package/dist/lib/flow-engine.js.map +1 -0
- package/dist/lib/gtm-generator.d.ts +29 -0
- package/dist/lib/gtm-generator.d.ts.map +1 -0
- package/dist/lib/gtm-generator.js +250 -0
- package/dist/lib/gtm-generator.js.map +1 -0
- package/dist/lib/hook-transformer.d.ts +11 -0
- package/dist/lib/hook-transformer.d.ts.map +1 -0
- package/dist/lib/hook-transformer.js +74 -0
- package/dist/lib/hook-transformer.js.map +1 -0
- package/dist/lib/hub-client.d.ts +81 -0
- package/dist/lib/hub-client.d.ts.map +1 -0
- package/dist/lib/hub-client.js +73 -0
- package/dist/lib/hub-client.js.map +1 -0
- package/dist/lib/hub-health.d.ts +40 -0
- package/dist/lib/hub-health.d.ts.map +1 -0
- package/dist/lib/hub-health.js +101 -0
- package/dist/lib/hub-health.js.map +1 -0
- package/dist/lib/ide-panes.d.ts +58 -0
- package/dist/lib/ide-panes.d.ts.map +1 -0
- package/dist/lib/ide-panes.js +508 -0
- package/dist/lib/ide-panes.js.map +1 -0
- package/dist/lib/invariant-monitor.d.ts +54 -0
- package/dist/lib/invariant-monitor.d.ts.map +1 -0
- package/dist/lib/invariant-monitor.js +487 -0
- package/dist/lib/invariant-monitor.js.map +1 -0
- package/dist/lib/journal-analyzer.d.ts +71 -0
- package/dist/lib/journal-analyzer.d.ts.map +1 -0
- package/dist/lib/journal-analyzer.js +306 -0
- package/dist/lib/journal-analyzer.js.map +1 -0
- package/dist/lib/kanban-github.d.ts +81 -0
- package/dist/lib/kanban-github.d.ts.map +1 -0
- package/dist/lib/kanban-github.js +318 -0
- package/dist/lib/kanban-github.js.map +1 -0
- package/dist/lib/kanban.d.ts +131 -0
- package/dist/lib/kanban.d.ts.map +1 -0
- package/dist/lib/kanban.js +340 -0
- package/dist/lib/kanban.js.map +1 -0
- package/dist/lib/kuva.d.ts +45 -0
- package/dist/lib/kuva.d.ts.map +1 -0
- package/dist/lib/kuva.js +131 -0
- package/dist/lib/kuva.js.map +1 -0
- package/dist/lib/linear-client.d.ts +73 -0
- package/dist/lib/linear-client.d.ts.map +1 -0
- package/dist/lib/linear-client.js +112 -0
- package/dist/lib/linear-client.js.map +1 -0
- package/dist/lib/linear-id-map.d.ts +20 -0
- package/dist/lib/linear-id-map.d.ts.map +1 -0
- package/dist/lib/linear-id-map.js +59 -0
- package/dist/lib/linear-id-map.js.map +1 -0
- package/dist/lib/linear-kanban.d.ts +66 -0
- package/dist/lib/linear-kanban.d.ts.map +1 -0
- package/dist/lib/linear-kanban.js +175 -0
- package/dist/lib/linear-kanban.js.map +1 -0
- package/dist/lib/linear-webhook.d.ts +50 -0
- package/dist/lib/linear-webhook.d.ts.map +1 -0
- package/dist/lib/linear-webhook.js +92 -0
- package/dist/lib/linear-webhook.js.map +1 -0
- package/dist/lib/map-event-bus.d.ts +50 -0
- package/dist/lib/map-event-bus.d.ts.map +1 -0
- package/dist/lib/map-event-bus.js +366 -0
- package/dist/lib/map-event-bus.js.map +1 -0
- package/dist/lib/memory-db.d.ts +136 -0
- package/dist/lib/memory-db.d.ts.map +1 -0
- package/dist/lib/memory-db.js +429 -0
- package/dist/lib/memory-db.js.map +1 -0
- package/dist/lib/memory-indexer.d.ts +61 -0
- package/dist/lib/memory-indexer.d.ts.map +1 -0
- package/dist/lib/memory-indexer.js +418 -0
- package/dist/lib/memory-indexer.js.map +1 -0
- package/dist/lib/memory-search.d.ts +185 -0
- package/dist/lib/memory-search.d.ts.map +1 -0
- package/dist/lib/memory-search.js +678 -0
- package/dist/lib/memory-search.js.map +1 -0
- package/dist/lib/meta-orchestrator.d.ts +141 -0
- package/dist/lib/meta-orchestrator.d.ts.map +1 -0
- package/dist/lib/meta-orchestrator.js +552 -0
- package/dist/lib/meta-orchestrator.js.map +1 -0
- package/dist/lib/model-pricing.d.ts +11 -0
- package/dist/lib/model-pricing.d.ts.map +1 -0
- package/dist/lib/model-pricing.js +27 -0
- package/dist/lib/model-pricing.js.map +1 -0
- package/dist/lib/onboarding.d.ts +40 -0
- package/dist/lib/onboarding.d.ts.map +1 -0
- package/dist/lib/onboarding.js +213 -0
- package/dist/lib/onboarding.js.map +1 -0
- package/dist/lib/openclaw-registry.d.ts +48 -0
- package/dist/lib/openclaw-registry.d.ts.map +1 -0
- package/dist/lib/openclaw-registry.js +181 -0
- package/dist/lib/openclaw-registry.js.map +1 -0
- package/dist/lib/openclaw-sdk.d.ts +115 -0
- package/dist/lib/openclaw-sdk.d.ts.map +1 -0
- package/dist/lib/openclaw-sdk.js +220 -0
- package/dist/lib/openclaw-sdk.js.map +1 -0
- package/dist/lib/peer-agent-generator.d.ts +44 -0
- package/dist/lib/peer-agent-generator.d.ts.map +1 -0
- package/dist/lib/peer-agent-generator.js +310 -0
- package/dist/lib/peer-agent-generator.js.map +1 -0
- package/dist/lib/peter-parker-bridge.d.ts +70 -0
- package/dist/lib/peter-parker-bridge.d.ts.map +1 -0
- package/dist/lib/peter-parker-bridge.js +345 -0
- package/dist/lib/peter-parker-bridge.js.map +1 -0
- package/dist/lib/peter-parker-config.d.ts +13 -0
- package/dist/lib/peter-parker-config.d.ts.map +1 -0
- package/dist/lib/peter-parker-config.js +86 -0
- package/dist/lib/peter-parker-config.js.map +1 -0
- package/dist/lib/physical-world-model.d.ts +50 -0
- package/dist/lib/physical-world-model.d.ts.map +1 -0
- package/dist/lib/physical-world-model.js +251 -0
- package/dist/lib/physical-world-model.js.map +1 -0
- package/dist/lib/pi-sky/bridge.d.ts +55 -0
- package/dist/lib/pi-sky/bridge.d.ts.map +1 -0
- package/dist/lib/pi-sky/bridge.js +264 -0
- package/dist/lib/pi-sky/bridge.js.map +1 -0
- package/dist/lib/pi-sky/cost-monitor.d.ts +21 -0
- package/dist/lib/pi-sky/cost-monitor.d.ts.map +1 -0
- package/dist/lib/pi-sky/cost-monitor.js +126 -0
- package/dist/lib/pi-sky/cost-monitor.js.map +1 -0
- package/dist/lib/pi-sky/eval-sweep.d.ts +27 -0
- package/dist/lib/pi-sky/eval-sweep.d.ts.map +1 -0
- package/dist/lib/pi-sky/eval-sweep.js +141 -0
- package/dist/lib/pi-sky/eval-sweep.js.map +1 -0
- package/dist/lib/pi-sky/event-router.d.ts +32 -0
- package/dist/lib/pi-sky/event-router.d.ts.map +1 -0
- package/dist/lib/pi-sky/event-router.js +176 -0
- package/dist/lib/pi-sky/event-router.js.map +1 -0
- package/dist/lib/pi-sky/experiment.d.ts +9 -0
- package/dist/lib/pi-sky/experiment.d.ts.map +1 -0
- package/dist/lib/pi-sky/experiment.js +83 -0
- package/dist/lib/pi-sky/experiment.js.map +1 -0
- package/dist/lib/pi-sky/index.d.ts +16 -0
- package/dist/lib/pi-sky/index.d.ts.map +1 -0
- package/dist/lib/pi-sky/index.js +16 -0
- package/dist/lib/pi-sky/index.js.map +1 -0
- package/dist/lib/pi-sky/stratus-gate.d.ts +28 -0
- package/dist/lib/pi-sky/stratus-gate.d.ts.map +1 -0
- package/dist/lib/pi-sky/stratus-gate.js +61 -0
- package/dist/lib/pi-sky/stratus-gate.js.map +1 -0
- package/dist/lib/pi-sky/swarm.d.ts +28 -0
- package/dist/lib/pi-sky/swarm.d.ts.map +1 -0
- package/dist/lib/pi-sky/swarm.js +208 -0
- package/dist/lib/pi-sky/swarm.js.map +1 -0
- package/dist/lib/pi-sky/types.d.ts +139 -0
- package/dist/lib/pi-sky/types.d.ts.map +1 -0
- package/dist/lib/pi-sky/types.js +2 -0
- package/dist/lib/pi-sky/types.js.map +1 -0
- package/dist/lib/pi-sky/voice-bridge.d.ts +20 -0
- package/dist/lib/pi-sky/voice-bridge.d.ts.map +1 -0
- package/dist/lib/pi-sky/voice-bridge.js +91 -0
- package/dist/lib/pi-sky/voice-bridge.js.map +1 -0
- package/dist/lib/planning-loop.d.ts +157 -0
- package/dist/lib/planning-loop.d.ts.map +1 -0
- package/dist/lib/planning-loop.js +537 -0
- package/dist/lib/planning-loop.js.map +1 -0
- package/dist/lib/policy-head.d.ts +53 -0
- package/dist/lib/policy-head.d.ts.map +1 -0
- package/dist/lib/policy-head.js +400 -0
- package/dist/lib/policy-head.js.map +1 -0
- package/dist/lib/predictor.d.ts +109 -0
- package/dist/lib/predictor.d.ts.map +1 -0
- package/dist/lib/predictor.js +433 -0
- package/dist/lib/predictor.js.map +1 -0
- package/dist/lib/replay-buffer.d.ts +93 -0
- package/dist/lib/replay-buffer.d.ts.map +1 -0
- package/dist/lib/replay-buffer.js +302 -0
- package/dist/lib/replay-buffer.js.map +1 -0
- package/dist/lib/resource-optimizer-middleware.d.ts +39 -0
- package/dist/lib/resource-optimizer-middleware.d.ts.map +1 -0
- package/dist/lib/resource-optimizer-middleware.js +228 -0
- package/dist/lib/resource-optimizer-middleware.js.map +1 -0
- package/dist/lib/resource-optimizer.d.ts +71 -0
- package/dist/lib/resource-optimizer.d.ts.map +1 -0
- package/dist/lib/resource-optimizer.js +228 -0
- package/dist/lib/resource-optimizer.js.map +1 -0
- package/dist/lib/rewards/index.d.ts +14 -0
- package/dist/lib/rewards/index.d.ts.map +1 -0
- package/dist/lib/rewards/index.js +15 -0
- package/dist/lib/rewards/index.js.map +1 -0
- package/dist/lib/rl-manager.d.ts +74 -0
- package/dist/lib/rl-manager.d.ts.map +1 -0
- package/dist/lib/rl-manager.js +245 -0
- package/dist/lib/rl-manager.js.map +1 -0
- package/dist/lib/sentinel-rl.d.ts +97 -0
- package/dist/lib/sentinel-rl.d.ts.map +1 -0
- package/dist/lib/sentinel-rl.js +430 -0
- package/dist/lib/sentinel-rl.js.map +1 -0
- package/dist/lib/service-analyzer.d.ts +76 -0
- package/dist/lib/service-analyzer.d.ts.map +1 -0
- package/dist/lib/service-analyzer.js +704 -0
- package/dist/lib/service-analyzer.js.map +1 -0
- package/dist/lib/service-dependencies.d.ts +44 -0
- package/dist/lib/service-dependencies.d.ts.map +1 -0
- package/dist/lib/service-dependencies.js +314 -0
- package/dist/lib/service-dependencies.js.map +1 -0
- package/dist/lib/service-detector.d.ts +61 -0
- package/dist/lib/service-detector.d.ts.map +1 -0
- package/dist/lib/service-detector.js +541 -0
- package/dist/lib/service-detector.js.map +1 -0
- package/dist/lib/service-gtm.d.ts +208 -0
- package/dist/lib/service-gtm.d.ts.map +1 -0
- package/dist/lib/service-gtm.js +1006 -0
- package/dist/lib/service-gtm.js.map +1 -0
- package/dist/lib/service-mcp-base.d.ts +103 -0
- package/dist/lib/service-mcp-base.d.ts.map +1 -0
- package/dist/lib/service-mcp-base.js +263 -0
- package/dist/lib/service-mcp-base.js.map +1 -0
- package/dist/lib/service-questionnaire.d.ts +11 -0
- package/dist/lib/service-questionnaire.d.ts.map +1 -0
- package/dist/lib/service-questionnaire.js +89 -0
- package/dist/lib/service-questionnaire.js.map +1 -0
- package/dist/lib/service-utils.d.ts +103 -0
- package/dist/lib/service-utils.d.ts.map +1 -0
- package/dist/lib/service-utils.js +385 -0
- package/dist/lib/service-utils.js.map +1 -0
- package/dist/lib/session-lock.d.ts +61 -0
- package/dist/lib/session-lock.d.ts.map +1 -0
- package/dist/lib/session-lock.js +438 -0
- package/dist/lib/session-lock.js.map +1 -0
- package/dist/lib/setup/agent-generator.d.ts +25 -0
- package/dist/lib/setup/agent-generator.d.ts.map +1 -0
- package/dist/lib/setup/agent-generator.js +444 -0
- package/dist/lib/setup/agent-generator.js.map +1 -0
- package/dist/lib/setup/context-analyzer.d.ts +16 -0
- package/dist/lib/setup/context-analyzer.d.ts.map +1 -0
- package/dist/lib/setup/context-analyzer.js +112 -0
- package/dist/lib/setup/context-analyzer.js.map +1 -0
- package/dist/lib/setup/doc-auditor.d.ts +54 -0
- package/dist/lib/setup/doc-auditor.d.ts.map +1 -0
- package/dist/lib/setup/doc-auditor.js +629 -0
- package/dist/lib/setup/doc-auditor.js.map +1 -0
- package/dist/lib/setup/domain-generator.d.ts +7 -0
- package/dist/lib/setup/domain-generator.d.ts.map +1 -0
- package/dist/lib/setup/domain-generator.js +58 -0
- package/dist/lib/setup/domain-generator.js.map +1 -0
- package/dist/lib/setup/flow-generator.d.ts +10 -0
- package/dist/lib/setup/flow-generator.d.ts.map +1 -0
- package/dist/lib/setup/flow-generator.js +113 -0
- package/dist/lib/setup/flow-generator.js.map +1 -0
- package/dist/lib/setup/invariant-bridge.d.ts +91 -0
- package/dist/lib/setup/invariant-bridge.d.ts.map +1 -0
- package/dist/lib/setup/invariant-bridge.js +384 -0
- package/dist/lib/setup/invariant-bridge.js.map +1 -0
- package/dist/lib/setup/smart-eval-generator.d.ts +38 -0
- package/dist/lib/setup/smart-eval-generator.d.ts.map +1 -0
- package/dist/lib/setup/smart-eval-generator.js +378 -0
- package/dist/lib/setup/smart-eval-generator.js.map +1 -0
- package/dist/lib/setup/smart-recommender.d.ts +63 -0
- package/dist/lib/setup/smart-recommender.d.ts.map +1 -0
- package/dist/lib/setup/smart-recommender.js +329 -0
- package/dist/lib/setup/smart-recommender.js.map +1 -0
- package/dist/lib/setup/spec-generator.d.ts +99 -0
- package/dist/lib/setup/spec-generator.d.ts.map +1 -0
- package/dist/lib/setup/spec-generator.js +784 -0
- package/dist/lib/setup/spec-generator.js.map +1 -0
- package/dist/lib/setup/starter-intelligence.d.ts +25 -0
- package/dist/lib/setup/starter-intelligence.d.ts.map +1 -0
- package/dist/lib/setup/starter-intelligence.js +309 -0
- package/dist/lib/setup/starter-intelligence.js.map +1 -0
- package/dist/lib/setup/violation-agent-generator.d.ts +32 -0
- package/dist/lib/setup/violation-agent-generator.d.ts.map +1 -0
- package/dist/lib/setup/violation-agent-generator.js +255 -0
- package/dist/lib/setup/violation-agent-generator.js.map +1 -0
- package/dist/lib/skill-generator.d.ts +21 -0
- package/dist/lib/skill-generator.d.ts.map +1 -0
- package/dist/lib/skill-generator.js +253 -0
- package/dist/lib/skill-generator.js.map +1 -0
- package/dist/lib/state-capture.d.ts +36 -0
- package/dist/lib/state-capture.d.ts.map +1 -0
- package/dist/lib/state-capture.js +541 -0
- package/dist/lib/state-capture.js.map +1 -0
- package/dist/lib/stealth-onboarding.d.ts +40 -0
- package/dist/lib/stealth-onboarding.d.ts.map +1 -0
- package/dist/lib/stealth-onboarding.js +213 -0
- package/dist/lib/stealth-onboarding.js.map +1 -0
- package/dist/lib/storage/cloud.d.ts +27 -0
- package/dist/lib/storage/cloud.d.ts.map +1 -0
- package/dist/lib/storage/cloud.js +75 -0
- package/dist/lib/storage/cloud.js.map +1 -0
- package/dist/lib/storage/index.d.ts +15 -0
- package/dist/lib/storage/index.d.ts.map +1 -0
- package/dist/lib/storage/index.js +15 -0
- package/dist/lib/storage/index.js.map +1 -0
- package/dist/lib/storage/interface.d.ts +56 -0
- package/dist/lib/storage/interface.d.ts.map +1 -0
- package/dist/lib/storage/interface.js +2 -0
- package/dist/lib/storage/interface.js.map +1 -0
- package/dist/lib/storage/local.d.ts +26 -0
- package/dist/lib/storage/local.d.ts.map +1 -0
- package/dist/lib/storage/local.js +164 -0
- package/dist/lib/storage/local.js.map +1 -0
- package/dist/lib/stratus-client.d.ts +178 -0
- package/dist/lib/stratus-client.d.ts.map +1 -0
- package/dist/lib/stratus-client.js +739 -0
- package/dist/lib/stratus-client.js.map +1 -0
- package/dist/lib/stratus-rollout-test.d.ts +10 -0
- package/dist/lib/stratus-rollout-test.d.ts.map +1 -0
- package/dist/lib/stratus-rollout-test.js +412 -0
- package/dist/lib/stratus-rollout-test.js.map +1 -0
- package/dist/lib/surface-agent.d.ts +78 -0
- package/dist/lib/surface-agent.d.ts.map +1 -0
- package/dist/lib/surface-agent.js +105 -0
- package/dist/lib/surface-agent.js.map +1 -0
- package/dist/lib/surface-coordination-example.d.ts +30 -0
- package/dist/lib/surface-coordination-example.d.ts.map +1 -0
- package/dist/lib/surface-coordination-example.js +164 -0
- package/dist/lib/surface-coordination-example.js.map +1 -0
- package/dist/lib/telemetry/physical-world-collector.d.ts +15 -0
- package/dist/lib/telemetry/physical-world-collector.d.ts.map +1 -0
- package/dist/lib/telemetry/physical-world-collector.js +177 -0
- package/dist/lib/telemetry/physical-world-collector.js.map +1 -0
- package/dist/lib/telemetry/training-bridge.d.ts +51 -0
- package/dist/lib/telemetry/training-bridge.d.ts.map +1 -0
- package/dist/lib/telemetry/training-bridge.js +185 -0
- package/dist/lib/telemetry/training-bridge.js.map +1 -0
- package/dist/lib/telemetry-agent-v2.d.ts +128 -0
- package/dist/lib/telemetry-agent-v2.d.ts.map +1 -0
- package/dist/lib/telemetry-agent-v2.js +1043 -0
- package/dist/lib/telemetry-agent-v2.js.map +1 -0
- package/dist/lib/telemetry-agent.d.ts +57 -0
- package/dist/lib/telemetry-agent.d.ts.map +1 -0
- package/dist/lib/telemetry-agent.js +289 -0
- package/dist/lib/telemetry-agent.js.map +1 -0
- package/dist/lib/telemetry-digest.d.ts +10 -0
- package/dist/lib/telemetry-digest.d.ts.map +1 -0
- package/dist/lib/telemetry-digest.js +381 -0
- package/dist/lib/telemetry-digest.js.map +1 -0
- package/dist/lib/telemetry.d.ts +37 -0
- package/dist/lib/telemetry.d.ts.map +1 -0
- package/dist/lib/telemetry.js +376 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/dist/lib/tenet-board-agent.d.ts +52 -0
- package/dist/lib/tenet-board-agent.d.ts.map +1 -0
- package/dist/lib/tenet-board-agent.js +226 -0
- package/dist/lib/tenet-board-agent.js.map +1 -0
- package/dist/lib/tenet-ide-agent.d.ts +40 -0
- package/dist/lib/tenet-ide-agent.d.ts.map +1 -0
- package/dist/lib/tenet-ide-agent.js +199 -0
- package/dist/lib/tenet-ide-agent.js.map +1 -0
- package/dist/lib/text-preprocessing.d.ts +83 -0
- package/dist/lib/text-preprocessing.d.ts.map +1 -0
- package/dist/lib/text-preprocessing.js +261 -0
- package/dist/lib/text-preprocessing.js.map +1 -0
- package/dist/lib/tool-schemas.d.ts +35 -0
- package/dist/lib/tool-schemas.d.ts.map +1 -0
- package/dist/lib/tool-schemas.js +246 -0
- package/dist/lib/tool-schemas.js.map +1 -0
- package/dist/lib/training-buffer.d.ts +86 -0
- package/dist/lib/training-buffer.d.ts.map +1 -0
- package/dist/lib/training-buffer.js +139 -0
- package/dist/lib/training-buffer.js.map +1 -0
- package/dist/lib/training-tuples.d.ts +33 -0
- package/dist/lib/training-tuples.d.ts.map +1 -0
- package/dist/lib/training-tuples.js +273 -0
- package/dist/lib/training-tuples.js.map +1 -0
- package/dist/lib/trajectory-loader.d.ts +82 -0
- package/dist/lib/trajectory-loader.d.ts.map +1 -0
- package/dist/lib/trajectory-loader.js +406 -0
- package/dist/lib/trajectory-loader.js.map +1 -0
- package/dist/lib/tuple-miner.d.ts +30 -0
- package/dist/lib/tuple-miner.d.ts.map +1 -0
- package/dist/lib/tuple-miner.js +427 -0
- package/dist/lib/tuple-miner.js.map +1 -0
- package/dist/lib/vm-backend.d.ts +72 -0
- package/dist/lib/vm-backend.d.ts.map +1 -0
- package/dist/lib/vm-backend.js +175 -0
- package/dist/lib/vm-backend.js.map +1 -0
- package/dist/lib/workspace/backend.d.ts +53 -0
- package/dist/lib/workspace/backend.d.ts.map +1 -0
- package/dist/lib/workspace/backend.js +37 -0
- package/dist/lib/workspace/backend.js.map +1 -0
- package/dist/lib/workspace/cmux-adapter.d.ts +46 -0
- package/dist/lib/workspace/cmux-adapter.d.ts.map +1 -0
- package/dist/lib/workspace/cmux-adapter.js +261 -0
- package/dist/lib/workspace/cmux-adapter.js.map +1 -0
- package/dist/lib/workspace/data-pipeline.d.ts +35 -0
- package/dist/lib/workspace/data-pipeline.d.ts.map +1 -0
- package/dist/lib/workspace/data-pipeline.js +494 -0
- package/dist/lib/workspace/data-pipeline.js.map +1 -0
- package/dist/lib/workspace/engine.d.ts +65 -0
- package/dist/lib/workspace/engine.d.ts.map +1 -0
- package/dist/lib/workspace/engine.js +407 -0
- package/dist/lib/workspace/engine.js.map +1 -0
- package/dist/lib/workspace/notifications.d.ts +14 -0
- package/dist/lib/workspace/notifications.d.ts.map +1 -0
- package/dist/lib/workspace/notifications.js +41 -0
- package/dist/lib/workspace/notifications.js.map +1 -0
- package/dist/lib/workspace/sidebar-runner.d.ts +13 -0
- package/dist/lib/workspace/sidebar-runner.d.ts.map +1 -0
- package/dist/lib/workspace/sidebar-runner.js +419 -0
- package/dist/lib/workspace/sidebar-runner.js.map +1 -0
- package/dist/lib/workspace/surface-registry.d.ts +49 -0
- package/dist/lib/workspace/surface-registry.d.ts.map +1 -0
- package/dist/lib/workspace/surface-registry.js +225 -0
- package/dist/lib/workspace/surface-registry.js.map +1 -0
- package/dist/lib/workspace/surface-type.d.ts +153 -0
- package/dist/lib/workspace/surface-type.d.ts.map +1 -0
- package/dist/lib/workspace/surface-type.js +9 -0
- package/dist/lib/workspace/surface-type.js.map +1 -0
- package/dist/lib/workspace/surfaces/agent-overview.d.ts +16 -0
- package/dist/lib/workspace/surfaces/agent-overview.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/agent-overview.js +116 -0
- package/dist/lib/workspace/surfaces/agent-overview.js.map +1 -0
- package/dist/lib/workspace/surfaces/agent.d.ts +16 -0
- package/dist/lib/workspace/surfaces/agent.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/agent.js +112 -0
- package/dist/lib/workspace/surfaces/agent.js.map +1 -0
- package/dist/lib/workspace/surfaces/claude.d.ts +15 -0
- package/dist/lib/workspace/surfaces/claude.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/claude.js +23 -0
- package/dist/lib/workspace/surfaces/claude.js.map +1 -0
- package/dist/lib/workspace/surfaces/dashboard.d.ts +21 -0
- package/dist/lib/workspace/surfaces/dashboard.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/dashboard.js +32 -0
- package/dist/lib/workspace/surfaces/dashboard.js.map +1 -0
- package/dist/lib/workspace/surfaces/eval.d.ts +15 -0
- package/dist/lib/workspace/surfaces/eval.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/eval.js +42 -0
- package/dist/lib/workspace/surfaces/eval.js.map +1 -0
- package/dist/lib/workspace/surfaces/event-stream.d.ts +16 -0
- package/dist/lib/workspace/surfaces/event-stream.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/event-stream.js +40 -0
- package/dist/lib/workspace/surfaces/event-stream.js.map +1 -0
- package/dist/lib/workspace/surfaces/flow.d.ts +16 -0
- package/dist/lib/workspace/surfaces/flow.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/flow.js +49 -0
- package/dist/lib/workspace/surfaces/flow.js.map +1 -0
- package/dist/lib/workspace/surfaces/index.d.ts +19 -0
- package/dist/lib/workspace/surfaces/index.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/index.js +19 -0
- package/dist/lib/workspace/surfaces/index.js.map +1 -0
- package/dist/lib/workspace/surfaces/kanban.d.ts +15 -0
- package/dist/lib/workspace/surfaces/kanban.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/kanban.js +43 -0
- package/dist/lib/workspace/surfaces/kanban.js.map +1 -0
- package/dist/lib/workspace/surfaces/physical-world.d.ts +15 -0
- package/dist/lib/workspace/surfaces/physical-world.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/physical-world.js +37 -0
- package/dist/lib/workspace/surfaces/physical-world.js.map +1 -0
- package/dist/lib/workspace/surfaces/portfolio.d.ts +16 -0
- package/dist/lib/workspace/surfaces/portfolio.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/portfolio.js +102 -0
- package/dist/lib/workspace/surfaces/portfolio.js.map +1 -0
- package/dist/lib/workspace/surfaces/service.d.ts +16 -0
- package/dist/lib/workspace/surfaces/service.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/service.js +45 -0
- package/dist/lib/workspace/surfaces/service.js.map +1 -0
- package/dist/lib/workspace/surfaces/shell.d.ts +15 -0
- package/dist/lib/workspace/surfaces/shell.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/shell.js +19 -0
- package/dist/lib/workspace/surfaces/shell.js.map +1 -0
- package/dist/lib/workspace/surfaces/sidebar.d.ts +22 -0
- package/dist/lib/workspace/surfaces/sidebar.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/sidebar.js +94 -0
- package/dist/lib/workspace/surfaces/sidebar.js.map +1 -0
- package/dist/lib/workspace/surfaces/telemetry.d.ts +16 -0
- package/dist/lib/workspace/surfaces/telemetry.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/telemetry.js +48 -0
- package/dist/lib/workspace/surfaces/telemetry.js.map +1 -0
- package/dist/lib/workspace/surfaces/topology.d.ts +15 -0
- package/dist/lib/workspace/surfaces/topology.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/topology.js +19 -0
- package/dist/lib/workspace/surfaces/topology.js.map +1 -0
- package/dist/lib/workspace/surfaces/training.d.ts +16 -0
- package/dist/lib/workspace/surfaces/training.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/training.js +22 -0
- package/dist/lib/workspace/surfaces/training.js.map +1 -0
- package/dist/lib/workspace/tmux-adapter.d.ts +30 -0
- package/dist/lib/workspace/tmux-adapter.d.ts.map +1 -0
- package/dist/lib/workspace/tmux-adapter.js +137 -0
- package/dist/lib/workspace/tmux-adapter.js.map +1 -0
- package/dist/lib/workspace/tmux-sidebar.d.ts +14 -0
- package/dist/lib/workspace/tmux-sidebar.d.ts.map +1 -0
- package/dist/lib/workspace/tmux-sidebar.js +230 -0
- package/dist/lib/workspace/tmux-sidebar.js.map +1 -0
- package/dist/lib/world-model-store.d.ts +172 -0
- package/dist/lib/world-model-store.d.ts.map +1 -0
- package/dist/lib/world-model-store.js +487 -0
- package/dist/lib/world-model-store.js.map +1 -0
- package/dist/mcp/context-hub-mcp.d.ts +11 -0
- package/dist/mcp/context-hub-mcp.d.ts.map +1 -0
- package/dist/mcp/context-hub-mcp.js +797 -0
- package/dist/mcp/context-hub-mcp.js.map +1 -0
- package/dist/mcp/service-mcp-server.d.ts +12 -0
- package/dist/mcp/service-mcp-server.d.ts.map +1 -0
- package/dist/mcp/service-mcp-server.js +434 -0
- package/dist/mcp/service-mcp-server.js.map +1 -0
- package/dist/mcp/service-peer-mcp.d.ts +36 -0
- package/dist/mcp/service-peer-mcp.d.ts.map +1 -0
- package/dist/mcp/service-peer-mcp.js +220 -0
- package/dist/mcp/service-peer-mcp.js.map +1 -0
- package/dist/mcp/service-registry-mcp.d.ts +13 -0
- package/dist/mcp/service-registry-mcp.d.ts.map +1 -0
- package/dist/mcp/service-registry-mcp.js +330 -0
- package/dist/mcp/service-registry-mcp.js.map +1 -0
- package/dist/telegram/voice.d.ts +146 -0
- package/dist/telegram/voice.d.ts.map +1 -0
- package/dist/telegram/voice.js +351 -0
- package/dist/telegram/voice.js.map +1 -0
- package/dist/types/eval.d.ts +18 -0
- package/dist/types/eval.d.ts.map +1 -0
- package/dist/types/eval.js +5 -0
- package/dist/types/eval.js.map +1 -0
- package/dist/types/flows.d.ts +72 -0
- package/dist/types/flows.d.ts.map +1 -0
- package/dist/types/flows.js +10 -0
- package/dist/types/flows.js.map +1 -0
- package/dist/types/ide.d.ts +49 -0
- package/dist/types/ide.d.ts.map +1 -0
- package/dist/types/ide.js +5 -0
- package/dist/types/ide.js.map +1 -0
- package/dist/types/journal.d.ts +133 -0
- package/dist/types/journal.d.ts.map +1 -0
- package/dist/types/journal.js +59 -0
- package/dist/types/journal.js.map +1 -0
- package/dist/types/map.d.ts +42 -0
- package/dist/types/map.d.ts.map +1 -0
- package/dist/types/map.js +39 -0
- package/dist/types/map.js.map +1 -0
- package/dist/types/physical-world-model.d.ts +65 -0
- package/dist/types/physical-world-model.d.ts.map +1 -0
- package/dist/types/physical-world-model.js +43 -0
- package/dist/types/physical-world-model.js.map +1 -0
- package/dist/types/platform-digest.d.ts +228 -0
- package/dist/types/platform-digest.d.ts.map +1 -0
- package/dist/types/platform-digest.js +5 -0
- package/dist/types/platform-digest.js.map +1 -0
- package/dist/types/skills.d.ts +44 -0
- package/dist/types/skills.d.ts.map +1 -0
- package/dist/types/skills.js +5 -0
- package/dist/types/skills.js.map +1 -0
- package/dist/types/telemetry-digest.d.ts +75 -0
- package/dist/types/telemetry-digest.d.ts.map +1 -0
- package/dist/types/telemetry-digest.js +5 -0
- package/dist/types/telemetry-digest.js.map +1 -0
- package/dist/types/telemetry.d.ts +107 -0
- package/dist/types/telemetry.d.ts.map +1 -0
- package/dist/types/telemetry.js +5 -0
- package/dist/types/telemetry.js.map +1 -0
- package/dist/types/world-model.d.ts +478 -0
- package/dist/types/world-model.d.ts.map +1 -0
- package/dist/types/world-model.js +87 -0
- package/dist/types/world-model.js.map +1 -0
- package/dist/ui/banner.d.ts +18 -0
- package/dist/ui/banner.d.ts.map +1 -0
- package/dist/ui/banner.js +323 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/ui/context-hub-logs.d.ts +10 -0
- package/dist/ui/context-hub-logs.d.ts.map +1 -0
- package/dist/ui/context-hub-logs.js +175 -0
- package/dist/ui/context-hub-logs.js.map +1 -0
- package/dist/ui/event-dashboard.d.ts +12 -0
- package/dist/ui/event-dashboard.d.ts.map +1 -0
- package/dist/ui/event-dashboard.js +342 -0
- package/dist/ui/event-dashboard.js.map +1 -0
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +8 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/prompts.d.ts +52 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +72 -0
- package/dist/ui/prompts.js.map +1 -0
- package/dist/ui/service-dashboard.d.ts +11 -0
- package/dist/ui/service-dashboard.d.ts.map +1 -0
- package/dist/ui/service-dashboard.js +357 -0
- package/dist/ui/service-dashboard.js.map +1 -0
- package/dist/ui/services-manager.d.ts +11 -0
- package/dist/ui/services-manager.d.ts.map +1 -0
- package/dist/ui/services-manager.js +507 -0
- package/dist/ui/services-manager.js.map +1 -0
- package/dist/ui/theme.d.ts +82 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +142 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/utils/auth-guard.d.ts +66 -0
- package/dist/utils/auth-guard.d.ts.map +1 -0
- package/dist/utils/auth-guard.js +347 -0
- package/dist/utils/auth-guard.js.map +1 -0
- package/dist/utils/auth-status.d.ts +21 -0
- package/dist/utils/auth-status.d.ts.map +1 -0
- package/dist/utils/auth-status.js +53 -0
- package/dist/utils/auth-status.js.map +1 -0
- package/dist/utils/claude-md-generator.d.ts +10 -0
- package/dist/utils/claude-md-generator.d.ts.map +1 -0
- package/dist/utils/claude-md-generator.js +215 -0
- package/dist/utils/claude-md-generator.js.map +1 -0
- package/dist/utils/context-hub-port.d.ts +33 -0
- package/dist/utils/context-hub-port.d.ts.map +1 -0
- package/dist/utils/context-hub-port.js +118 -0
- package/dist/utils/context-hub-port.js.map +1 -0
- package/dist/utils/ensure-context-hub.d.ts +20 -0
- package/dist/utils/ensure-context-hub.d.ts.map +1 -0
- package/dist/utils/ensure-context-hub.js +66 -0
- package/dist/utils/ensure-context-hub.js.map +1 -0
- package/dist/utils/ensure-project.d.ts +12 -0
- package/dist/utils/ensure-project.d.ts.map +1 -0
- package/dist/utils/ensure-project.js +81 -0
- package/dist/utils/ensure-project.js.map +1 -0
- package/dist/utils/git.d.ts +73 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +222 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/github-auth.d.ts +54 -0
- package/dist/utils/github-auth.d.ts.map +1 -0
- package/dist/utils/github-auth.js +376 -0
- package/dist/utils/github-auth.js.map +1 -0
- package/dist/utils/github-repo.d.ts +30 -0
- package/dist/utils/github-repo.d.ts.map +1 -0
- package/dist/utils/github-repo.js +219 -0
- package/dist/utils/github-repo.js.map +1 -0
- package/dist/utils/jfl-config.d.ts +30 -0
- package/dist/utils/jfl-config.d.ts.map +1 -0
- package/dist/utils/jfl-config.js +153 -0
- package/dist/utils/jfl-config.js.map +1 -0
- package/dist/utils/jfl-migration.d.ts +29 -0
- package/dist/utils/jfl-migration.d.ts.map +1 -0
- package/dist/utils/jfl-migration.js +142 -0
- package/dist/utils/jfl-migration.js.map +1 -0
- package/dist/utils/jfl-paths.d.ts +71 -0
- package/dist/utils/jfl-paths.d.ts.map +1 -0
- package/dist/utils/jfl-paths.js +157 -0
- package/dist/utils/jfl-paths.js.map +1 -0
- package/dist/utils/platform-auth.d.ts +81 -0
- package/dist/utils/platform-auth.d.ts.map +1 -0
- package/dist/utils/platform-auth.js +192 -0
- package/dist/utils/platform-auth.js.map +1 -0
- package/dist/utils/project-config.d.ts +43 -0
- package/dist/utils/project-config.d.ts.map +1 -0
- package/dist/utils/project-config.js +97 -0
- package/dist/utils/project-config.js.map +1 -0
- package/dist/utils/provenance.d.ts +65 -0
- package/dist/utils/provenance.d.ts.map +1 -0
- package/dist/utils/provenance.js +213 -0
- package/dist/utils/provenance.js.map +1 -0
- package/dist/utils/settings-validator.d.ts +74 -0
- package/dist/utils/settings-validator.d.ts.map +1 -0
- package/dist/utils/settings-validator.js +241 -0
- package/dist/utils/settings-validator.js.map +1 -0
- package/dist/utils/skill-registry.d.ts +49 -0
- package/dist/utils/skill-registry.d.ts.map +1 -0
- package/dist/utils/skill-registry.js +192 -0
- package/dist/utils/skill-registry.js.map +1 -0
- package/dist/utils/tenet-env.d.ts +34 -0
- package/dist/utils/tenet-env.d.ts.map +1 -0
- package/dist/utils/tenet-env.js +42 -0
- package/dist/utils/tenet-env.js.map +1 -0
- package/dist/utils/wallet.d.ts +62 -0
- package/dist/utils/wallet.d.ts.map +1 -0
- package/dist/utils/wallet.js +253 -0
- package/dist/utils/wallet.js.map +1 -0
- package/dist/utils/x402-client.d.ts +86 -0
- package/dist/utils/x402-client.d.ts.map +1 -0
- package/dist/utils/x402-client.js +266 -0
- package/dist/utils/x402-client.js.map +1 -0
- package/package.json +105 -0
- package/packages/pi/AGENTS.md +112 -0
- package/packages/pi/assets/boot.mp3 +0 -0
- package/packages/pi/dist/agent-grid.d.ts +24 -0
- package/packages/pi/dist/agent-grid.d.ts.map +1 -0
- package/packages/pi/dist/agent-grid.js +162 -0
- package/packages/pi/dist/agent-grid.js.map +1 -0
- package/packages/pi/dist/agent-names.d.ts +43 -0
- package/packages/pi/dist/agent-names.d.ts.map +1 -0
- package/packages/pi/dist/agent-names.js +156 -0
- package/packages/pi/dist/agent-names.js.map +1 -0
- package/packages/pi/dist/autoresearch.d.ts +15 -0
- package/packages/pi/dist/autoresearch.d.ts.map +1 -0
- package/packages/pi/dist/autoresearch.js +372 -0
- package/packages/pi/dist/autoresearch.js.map +1 -0
- package/packages/pi/dist/bookmarks.d.ts +15 -0
- package/packages/pi/dist/bookmarks.d.ts.map +1 -0
- package/packages/pi/dist/bookmarks.js +77 -0
- package/packages/pi/dist/bookmarks.js.map +1 -0
- package/packages/pi/dist/context.d.ts +17 -0
- package/packages/pi/dist/context.d.ts.map +1 -0
- package/packages/pi/dist/context.js +152 -0
- package/packages/pi/dist/context.js.map +1 -0
- package/packages/pi/dist/crm-tool.d.ts +12 -0
- package/packages/pi/dist/crm-tool.d.ts.map +1 -0
- package/packages/pi/dist/crm-tool.js +58 -0
- package/packages/pi/dist/crm-tool.js.map +1 -0
- package/packages/pi/dist/eval-tool.d.ts +11 -0
- package/packages/pi/dist/eval-tool.d.ts.map +1 -0
- package/packages/pi/dist/eval-tool.js +188 -0
- package/packages/pi/dist/eval-tool.js.map +1 -0
- package/packages/pi/dist/eval.d.ts +12 -0
- package/packages/pi/dist/eval.d.ts.map +1 -0
- package/packages/pi/dist/eval.js +43 -0
- package/packages/pi/dist/eval.js.map +1 -0
- package/packages/pi/dist/footer.d.ts +20 -0
- package/packages/pi/dist/footer.d.ts.map +1 -0
- package/packages/pi/dist/footer.js +222 -0
- package/packages/pi/dist/footer.js.map +1 -0
- package/packages/pi/dist/header.d.ts +17 -0
- package/packages/pi/dist/header.d.ts.map +1 -0
- package/packages/pi/dist/header.js +156 -0
- package/packages/pi/dist/header.js.map +1 -0
- package/packages/pi/dist/hub-resolver.d.ts +11 -0
- package/packages/pi/dist/hub-resolver.d.ts.map +1 -0
- package/packages/pi/dist/hub-resolver.js +58 -0
- package/packages/pi/dist/hub-resolver.js.map +1 -0
- package/packages/pi/dist/hub-tools.d.ts +14 -0
- package/packages/pi/dist/hub-tools.d.ts.map +1 -0
- package/packages/pi/dist/hub-tools.js +266 -0
- package/packages/pi/dist/hub-tools.js.map +1 -0
- package/packages/pi/dist/hud-tool.d.ts +17 -0
- package/packages/pi/dist/hud-tool.d.ts.map +1 -0
- package/packages/pi/dist/hud-tool.js +297 -0
- package/packages/pi/dist/hud-tool.js.map +1 -0
- package/packages/pi/dist/index.d.ts +12 -0
- package/packages/pi/dist/index.d.ts.map +1 -0
- package/packages/pi/dist/index.js +556 -0
- package/packages/pi/dist/index.js.map +1 -0
- package/packages/pi/dist/jfl-resolve.d.ts +29 -0
- package/packages/pi/dist/jfl-resolve.d.ts.map +1 -0
- package/packages/pi/dist/jfl-resolve.js +89 -0
- package/packages/pi/dist/jfl-resolve.js.map +1 -0
- package/packages/pi/dist/journal.d.ts +23 -0
- package/packages/pi/dist/journal.d.ts.map +1 -0
- package/packages/pi/dist/journal.js +250 -0
- package/packages/pi/dist/journal.js.map +1 -0
- package/packages/pi/dist/map-bridge.d.ts +20 -0
- package/packages/pi/dist/map-bridge.d.ts.map +1 -0
- package/packages/pi/dist/map-bridge.js +181 -0
- package/packages/pi/dist/map-bridge.js.map +1 -0
- package/packages/pi/dist/memory-tool.d.ts +11 -0
- package/packages/pi/dist/memory-tool.d.ts.map +1 -0
- package/packages/pi/dist/memory-tool.js +162 -0
- package/packages/pi/dist/memory-tool.js.map +1 -0
- package/packages/pi/dist/notifications.d.ts +15 -0
- package/packages/pi/dist/notifications.d.ts.map +1 -0
- package/packages/pi/dist/notifications.js +65 -0
- package/packages/pi/dist/notifications.js.map +1 -0
- package/packages/pi/dist/onboarding-v1.d.ts +15 -0
- package/packages/pi/dist/onboarding-v1.d.ts.map +1 -0
- package/packages/pi/dist/onboarding-v1.js +417 -0
- package/packages/pi/dist/onboarding-v1.js.map +1 -0
- package/packages/pi/dist/onboarding-v2.d.ts +18 -0
- package/packages/pi/dist/onboarding-v2.d.ts.map +1 -0
- package/packages/pi/dist/onboarding-v2.js +402 -0
- package/packages/pi/dist/onboarding-v2.js.map +1 -0
- package/packages/pi/dist/onboarding-v3.d.ts +13 -0
- package/packages/pi/dist/onboarding-v3.d.ts.map +1 -0
- package/packages/pi/dist/onboarding-v3.js +581 -0
- package/packages/pi/dist/onboarding-v3.js.map +1 -0
- package/packages/pi/dist/peter-parker.d.ts +12 -0
- package/packages/pi/dist/peter-parker.d.ts.map +1 -0
- package/packages/pi/dist/peter-parker.js +162 -0
- package/packages/pi/dist/peter-parker.js.map +1 -0
- package/packages/pi/dist/pivot-tool.d.ts +11 -0
- package/packages/pi/dist/pivot-tool.d.ts.map +1 -0
- package/packages/pi/dist/pivot-tool.js +56 -0
- package/packages/pi/dist/pivot-tool.js.map +1 -0
- package/packages/pi/dist/policy-head-tool.d.ts +15 -0
- package/packages/pi/dist/policy-head-tool.d.ts.map +1 -0
- package/packages/pi/dist/policy-head-tool.js +220 -0
- package/packages/pi/dist/policy-head-tool.js.map +1 -0
- package/packages/pi/dist/portfolio-bridge.d.ts +12 -0
- package/packages/pi/dist/portfolio-bridge.d.ts.map +1 -0
- package/packages/pi/dist/portfolio-bridge.js +81 -0
- package/packages/pi/dist/portfolio-bridge.js.map +1 -0
- package/packages/pi/dist/service-skills.d.ts +15 -0
- package/packages/pi/dist/service-skills.d.ts.map +1 -0
- package/packages/pi/dist/service-skills.js +198 -0
- package/packages/pi/dist/service-skills.js.map +1 -0
- package/packages/pi/dist/session.d.ts +28 -0
- package/packages/pi/dist/session.d.ts.map +1 -0
- package/packages/pi/dist/session.js +649 -0
- package/packages/pi/dist/session.js.map +1 -0
- package/packages/pi/dist/shortcuts.d.ts +11 -0
- package/packages/pi/dist/shortcuts.d.ts.map +1 -0
- package/packages/pi/dist/shortcuts.js +231 -0
- package/packages/pi/dist/shortcuts.js.map +1 -0
- package/packages/pi/dist/startup-briefing.d.ts +13 -0
- package/packages/pi/dist/startup-briefing.d.ts.map +1 -0
- package/packages/pi/dist/startup-briefing.js +432 -0
- package/packages/pi/dist/startup-briefing.js.map +1 -0
- package/packages/pi/dist/stratus-bridge.d.ts +14 -0
- package/packages/pi/dist/stratus-bridge.d.ts.map +1 -0
- package/packages/pi/dist/stratus-bridge.js +104 -0
- package/packages/pi/dist/stratus-bridge.js.map +1 -0
- package/packages/pi/dist/subway-mesh.d.ts +88 -0
- package/packages/pi/dist/subway-mesh.d.ts.map +1 -0
- package/packages/pi/dist/subway-mesh.js +813 -0
- package/packages/pi/dist/subway-mesh.js.map +1 -0
- package/packages/pi/dist/synopsis-tool.d.ts +12 -0
- package/packages/pi/dist/synopsis-tool.d.ts.map +1 -0
- package/packages/pi/dist/synopsis-tool.js +84 -0
- package/packages/pi/dist/synopsis-tool.js.map +1 -0
- package/packages/pi/dist/tool-renderers.d.ts +55 -0
- package/packages/pi/dist/tool-renderers.d.ts.map +1 -0
- package/packages/pi/dist/tool-renderers.js +349 -0
- package/packages/pi/dist/tool-renderers.js.map +1 -0
- package/packages/pi/dist/training-buffer-tool.d.ts +16 -0
- package/packages/pi/dist/training-buffer-tool.d.ts.map +1 -0
- package/packages/pi/dist/training-buffer-tool.js +319 -0
- package/packages/pi/dist/training-buffer-tool.js.map +1 -0
- package/packages/pi/dist/types.d.ts +195 -0
- package/packages/pi/dist/types.d.ts.map +1 -0
- package/packages/pi/dist/types.js +11 -0
- package/packages/pi/dist/types.js.map +1 -0
- package/packages/pi/extensions/agent-grid.ts +191 -0
- package/packages/pi/extensions/agent-names.ts +178 -0
- package/packages/pi/extensions/autoresearch.ts +428 -0
- package/packages/pi/extensions/bookmarks.ts +85 -0
- package/packages/pi/extensions/context.ts +158 -0
- package/packages/pi/extensions/crm-tool.ts +61 -0
- package/packages/pi/extensions/eval-tool.ts +224 -0
- package/packages/pi/extensions/eval.ts +61 -0
- package/packages/pi/extensions/footer.ts +239 -0
- package/packages/pi/extensions/header.ts +171 -0
- package/packages/pi/extensions/hub-resolver.ts +63 -0
- package/packages/pi/extensions/hub-tools.ts +267 -0
- package/packages/pi/extensions/hud-tool.ts +294 -0
- package/packages/pi/extensions/index.ts +601 -0
- package/packages/pi/extensions/jfl-resolve.ts +98 -0
- package/packages/pi/extensions/journal.ts +309 -0
- package/packages/pi/extensions/map-bridge.ts +209 -0
- package/packages/pi/extensions/memory-tool.ts +170 -0
- package/packages/pi/extensions/notifications.ts +73 -0
- package/packages/pi/extensions/onboarding-v1.ts +455 -0
- package/packages/pi/extensions/onboarding-v2.ts +374 -0
- package/packages/pi/extensions/onboarding-v3.ts +686 -0
- package/packages/pi/extensions/peter-parker.ts +203 -0
- package/packages/pi/extensions/pivot-tool.ts +59 -0
- package/packages/pi/extensions/policy-head-tool.ts +277 -0
- package/packages/pi/extensions/portfolio-bridge.ts +89 -0
- package/packages/pi/extensions/service-skills.ts +219 -0
- package/packages/pi/extensions/session.ts +684 -0
- package/packages/pi/extensions/shortcuts.ts +259 -0
- package/packages/pi/extensions/startup-briefing.ts +482 -0
- package/packages/pi/extensions/stratus-bridge.ts +116 -0
- package/packages/pi/extensions/subway-mesh.ts +893 -0
- package/packages/pi/extensions/synopsis-tool.ts +88 -0
- package/packages/pi/extensions/tool-renderers.ts +366 -0
- package/packages/pi/extensions/training-buffer-tool.ts +376 -0
- package/packages/pi/extensions/types.ts +169 -0
- package/packages/pi/package-lock.json +346 -0
- package/packages/pi/package.json +42 -0
- package/packages/pi/skills/agent-browser/SKILL.md +116 -0
- package/packages/pi/skills/brand-architect/SKILL.md +240 -0
- package/packages/pi/skills/brand-architect/config.yaml +137 -0
- package/packages/pi/skills/campaign-hud/config.yaml +112 -0
- package/packages/pi/skills/content-creator/SKILL.md +294 -0
- package/packages/pi/skills/context/SKILL.md +65 -0
- package/packages/pi/skills/debug/MULTI_AGENT.md +360 -0
- package/packages/pi/skills/debug/SKILL.md +554 -0
- package/packages/pi/skills/end/SKILL.md +1790 -0
- package/packages/pi/skills/eval/SKILL.md +75 -0
- package/packages/pi/skills/fly-deploy/SKILL.md +676 -0
- package/packages/pi/skills/founder-video/SKILL.md +467 -0
- package/packages/pi/skills/hud/SKILL.md +160 -0
- package/packages/pi/skills/orchestrate/SKILL.md +74 -0
- package/packages/pi/skills/pi-agents/SKILL.md +78 -0
- package/packages/pi/skills/pivot/SKILL.md +91 -0
- package/packages/pi/skills/react-best-practices/AGENTS.md +2249 -0
- package/packages/pi/skills/react-best-practices/README.md +123 -0
- package/packages/pi/skills/react-best-practices/SKILL.md +125 -0
- package/packages/pi/skills/react-best-practices/metadata.json +15 -0
- package/packages/pi/skills/react-best-practices/rules/_sections.md +46 -0
- package/packages/pi/skills/react-best-practices/rules/_template.md +28 -0
- package/packages/pi/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/packages/pi/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/packages/pi/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/packages/pi/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/packages/pi/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/packages/pi/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/packages/pi/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/packages/pi/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/packages/pi/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/packages/pi/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/packages/pi/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/packages/pi/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/packages/pi/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/packages/pi/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/packages/pi/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/packages/pi/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/packages/pi/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/packages/pi/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/packages/pi/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/packages/pi/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/packages/pi/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/packages/pi/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/packages/pi/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/packages/pi/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/packages/pi/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/packages/pi/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/packages/pi/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/packages/pi/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/packages/pi/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/packages/pi/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/packages/pi/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/packages/pi/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/packages/pi/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/packages/pi/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/packages/pi/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/packages/pi/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/packages/pi/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/packages/pi/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/packages/pi/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/packages/pi/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/packages/pi/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/packages/pi/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/packages/pi/skills/react-best-practices/rules/server-cache-react.md +26 -0
- package/packages/pi/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
- package/packages/pi/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/packages/pi/skills/remotion-best-practices/SKILL.md +43 -0
- package/packages/pi/skills/remotion-best-practices/rules/3d.md +86 -0
- package/packages/pi/skills/remotion-best-practices/rules/animations.md +29 -0
- package/packages/pi/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
- package/packages/pi/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
- package/packages/pi/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/packages/pi/skills/remotion-best-practices/rules/assets.md +78 -0
- package/packages/pi/skills/remotion-best-practices/rules/audio.md +172 -0
- package/packages/pi/skills/remotion-best-practices/rules/calculate-metadata.md +104 -0
- package/packages/pi/skills/remotion-best-practices/rules/can-decode.md +75 -0
- package/packages/pi/skills/remotion-best-practices/rules/charts.md +58 -0
- package/packages/pi/skills/remotion-best-practices/rules/compositions.md +146 -0
- package/packages/pi/skills/remotion-best-practices/rules/display-captions.md +126 -0
- package/packages/pi/skills/remotion-best-practices/rules/extract-frames.md +229 -0
- package/packages/pi/skills/remotion-best-practices/rules/fonts.md +152 -0
- package/packages/pi/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
- package/packages/pi/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
- package/packages/pi/skills/remotion-best-practices/rules/get-video-duration.md +58 -0
- package/packages/pi/skills/remotion-best-practices/rules/gifs.md +138 -0
- package/packages/pi/skills/remotion-best-practices/rules/images.md +130 -0
- package/packages/pi/skills/remotion-best-practices/rules/import-srt-captions.md +67 -0
- package/packages/pi/skills/remotion-best-practices/rules/lottie.md +68 -0
- package/packages/pi/skills/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
- package/packages/pi/skills/remotion-best-practices/rules/measuring-text.md +143 -0
- package/packages/pi/skills/remotion-best-practices/rules/sequencing.md +106 -0
- package/packages/pi/skills/remotion-best-practices/rules/tailwind.md +11 -0
- package/packages/pi/skills/remotion-best-practices/rules/text-animations.md +20 -0
- package/packages/pi/skills/remotion-best-practices/rules/timing.md +179 -0
- package/packages/pi/skills/remotion-best-practices/rules/transcribe-captions.md +19 -0
- package/packages/pi/skills/remotion-best-practices/rules/transitions.md +122 -0
- package/packages/pi/skills/remotion-best-practices/rules/trimming.md +53 -0
- package/packages/pi/skills/remotion-best-practices/rules/videos.md +171 -0
- package/packages/pi/skills/search/SKILL.md +220 -0
- package/packages/pi/skills/spec/SKILL.md +377 -0
- package/packages/pi/skills/startup/SKILL.md +315 -0
- package/packages/pi/skills/subway-browser/SKILL.md +292 -0
- package/packages/pi/skills/viz/SKILL.md +204 -0
- package/packages/pi/skills/web-architect/SKILL.md +309 -0
- package/packages/pi/skills/x-algorithm/SKILL.md +305 -0
- package/packages/pi/teams/dev-team.yaml +63 -0
- package/packages/pi/teams/gtm-team.yaml +79 -0
- package/packages/pi/themes/jfl.theme.json +76 -0
- package/packages/pi/tsconfig.json +21 -0
- package/scripts/__pycache__/train-policy-head.cpython-314.pyc +0 -0
- package/scripts/collect-tuples.sh +124 -0
- package/scripts/commit-gtm.sh +56 -0
- package/scripts/commit-product.sh +68 -0
- package/scripts/context-query.sh +45 -0
- package/scripts/destroy-fleet.sh +37 -0
- package/scripts/generate-changesets.sh +113 -0
- package/scripts/jfl-ide.sh +48 -0
- package/scripts/migrate-to-branch-sessions.sh +201 -0
- package/scripts/postinstall.js +146 -0
- package/scripts/pp-branch-pr.sh +133 -0
- package/scripts/pp-branch-pr.sh.bak +115 -0
- package/scripts/session/auto-commit.sh +297 -0
- package/scripts/session/fix-tracked-logs.sh +97 -0
- package/scripts/session/jfl-doctor.sh +707 -0
- package/scripts/session/session-cleanup.sh +292 -0
- package/scripts/session/session-end.sh +198 -0
- package/scripts/session/session-init.sh +356 -0
- package/scripts/session/session-init.sh.backup +292 -0
- package/scripts/session/session-sync.sh +192 -0
- package/scripts/session/test-context-preservation.sh +160 -0
- package/scripts/session/test-critical-infrastructure.sh +293 -0
- package/scripts/session/test-experience-level.sh +336 -0
- package/scripts/session/test-session-cleanup.sh +268 -0
- package/scripts/session/test-session-sync.sh +320 -0
- package/scripts/setup-branch-protection.sh +106 -0
- package/scripts/spawn-fleet.sh +144 -0
- package/scripts/telemetry-dashboard.sh +44 -0
- package/scripts/test-map-eventbus.sh +357 -0
- package/scripts/test-onboarding.sh +121 -0
- package/scripts/test-planning-loop-e2e.ts +181 -0
- package/scripts/test-server-inference.ts +49 -0
- package/scripts/test-state-sensitivity.ts +32 -0
- package/scripts/train/requirements.txt +5 -0
- package/scripts/train/train-policy-head.py +477 -0
- package/scripts/train/v2/__pycache__/dataset.cpython-314.pyc +0 -0
- package/scripts/train/v2/__pycache__/eval.cpython-314.pyc +0 -0
- package/scripts/train/v2/__pycache__/generate_data.cpython-314.pyc +0 -0
- package/scripts/train/v2/__pycache__/infer.cpython-314.pyc +0 -0
- package/scripts/train/v2/__pycache__/model.cpython-314.pyc +0 -0
- package/scripts/train/v2/__pycache__/precompute.cpython-314.pyc +0 -0
- package/scripts/train/v2/__pycache__/train.cpython-314.pyc +0 -0
- package/scripts/train/v2/__pycache__/transform_buffer.cpython-314.pyc +0 -0
- package/scripts/train/v2/__pycache__/validate_data.cpython-314.pyc +0 -0
- package/scripts/train/v2/benchmark.py +661 -0
- package/scripts/train/v2/dataset.py +81 -0
- package/scripts/train/v2/domain.json +66 -0
- package/scripts/train/v2/eval.py +196 -0
- package/scripts/train/v2/generate_balanced.py +439 -0
- package/scripts/train/v2/generate_data.py +219 -0
- package/scripts/train/v2/generate_hard_negatives.py +219 -0
- package/scripts/train/v2/infer.py +301 -0
- package/scripts/train/v2/infer_server.py +224 -0
- package/scripts/train/v2/model.py +112 -0
- package/scripts/train/v2/online_train.py +576 -0
- package/scripts/train/v2/precompute.py +150 -0
- package/scripts/train/v2/train.py +302 -0
- package/scripts/train/v2/transform_buffer.py +227 -0
- package/scripts/train/v2/validate_data.py +115 -0
- package/scripts/train-policy-head.py +434 -0
- package/scripts/vm-swarm/README.md +301 -0
- package/scripts/vm-swarm/collect-tuples.sh +331 -0
- package/scripts/vm-swarm/create-base-template.sh +339 -0
- package/scripts/vm-swarm/kill-fleet.sh +204 -0
- package/scripts/vm-swarm/monitor-fleet.sh +346 -0
- package/scripts/vm-swarm/spawn-fleet.sh +304 -0
- package/scripts/voice-start.sh +156 -0
- package/scripts/voice-stop.sh +33 -0
- package/scripts/where-am-i.sh +78 -0
- package/templates/QUICKSTART_SKILL_TO_PRODUCT.md +242 -0
- package/templates/brand/BRAND_BRIEF.md +124 -0
- package/templates/brand/BRAND_DECISIONS.md +168 -0
- package/templates/brand/BRAND_GUIDELINES.md +251 -0
- package/templates/brand/VOICE_AND_TONE.md +146 -0
- package/templates/brand/global.css +240 -0
- package/templates/collaboration/CONTRIBUTOR.md +74 -0
- package/templates/collaboration/CRM.md +97 -0
- package/templates/collaboration/TASKS.md +83 -0
- package/templates/dating/FUNNEL.md +29 -0
- package/templates/dating/REWARDS.md +24 -0
- package/templates/dating/SIGNALS.md +18 -0
- package/templates/dating/anti_patterns.md +23 -0
- package/templates/dating/connectors/index.md +16 -0
- package/templates/dating/modes.md +21 -0
- package/templates/dating/psychology.md +18 -0
- package/templates/default/README.md +19 -0
- package/templates/service-agent/.claude/settings.json +32 -0
- package/templates/service-agent/CLAUDE.md +334 -0
- package/templates/service-agent/knowledge/ARCHITECTURE.md +115 -0
- package/templates/service-agent/knowledge/DEPLOYMENT.md +199 -0
- package/templates/service-agent/knowledge/RUNBOOK.md +412 -0
- package/templates/service-agent/knowledge/SERVICE_SPEC.md +77 -0
- package/templates/service-mcp-template.js +325 -0
- package/templates/strategic/NARRATIVE.md +114 -0
- package/templates/strategic/ROADMAP.md +128 -0
- package/templates/strategic/THESIS.md +108 -0
- package/templates/strategic/VISION.md +74 -0
|
@@ -0,0 +1,2778 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Peter Parker Command
|
|
3
|
+
*
|
|
4
|
+
* Orchestrator that wraps ralph-tui with model routing and event bridging.
|
|
5
|
+
* Spidey-sense for which model to use per agent role.
|
|
6
|
+
* Includes proactive experiment selection — PP picks its own next task.
|
|
7
|
+
*
|
|
8
|
+
* @purpose CLI command for Peter Parker orchestrator — setup, run, status, experiment
|
|
9
|
+
*/
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
import { execSync, spawn, spawnSync } from "child_process";
|
|
12
|
+
import * as fs from "fs";
|
|
13
|
+
import * as path from "path";
|
|
14
|
+
import { writePeterParkerConfig, readCurrentProfile } from "../lib/peter-parker-config.js";
|
|
15
|
+
import { PeterParkerBridge } from "../lib/peter-parker-bridge.js";
|
|
16
|
+
import { getProjectHubUrl } from "../utils/context-hub-port.js";
|
|
17
|
+
import { TrajectoryLoader } from "../lib/trajectory-loader.js";
|
|
18
|
+
import { readEvals } from "../lib/eval-store.js";
|
|
19
|
+
import { TrainingBuffer } from "../lib/training-buffer.js";
|
|
20
|
+
import { PolicyHeadInference } from "../lib/policy-head.js";
|
|
21
|
+
import { PiRpcBridge, CostMonitor, EventRouter } from "../lib/pi-sky/index.js";
|
|
22
|
+
import { createPlanningLoop } from "../lib/planning-loop.js";
|
|
23
|
+
import { signedAgentCommit } from "../utils/provenance.js";
|
|
24
|
+
import { tenetEnvBool } from "../utils/tenet-env.js";
|
|
25
|
+
function hasRalphTui() {
|
|
26
|
+
try {
|
|
27
|
+
execSync("which ralph-tui", { stdio: "ignore" });
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function hasPi() {
|
|
35
|
+
try {
|
|
36
|
+
execSync("which pi", { stdio: "ignore" });
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function getAuthToken(projectRoot) {
|
|
44
|
+
const tokenPath = path.join(projectRoot, ".jfl", "context-hub.token");
|
|
45
|
+
if (fs.existsSync(tokenPath)) {
|
|
46
|
+
return fs.readFileSync(tokenPath, "utf-8").trim();
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
async function setup(projectRoot, profile) {
|
|
51
|
+
const configPath = writePeterParkerConfig(projectRoot, profile);
|
|
52
|
+
console.log(chalk.green(`\n Peter Parker config generated`));
|
|
53
|
+
console.log(chalk.gray(` Profile: ${profile}`));
|
|
54
|
+
console.log(chalk.gray(` Config: ${path.relative(projectRoot, configPath)}`));
|
|
55
|
+
console.log(chalk.gray(`\n Agents: scout, planner, builder (default), reviewer, tester`));
|
|
56
|
+
console.log(chalk.gray(` Each has a fallback agent at next tier up\n`));
|
|
57
|
+
}
|
|
58
|
+
async function run(projectRoot, task) {
|
|
59
|
+
if (!hasRalphTui()) {
|
|
60
|
+
console.log(chalk.yellow("\n ralph-tui is not installed"));
|
|
61
|
+
console.log(chalk.gray(" Install: bun install -g ralph-tui\n"));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const configPath = path.join(projectRoot, ".ralph-tui", "config.toml");
|
|
65
|
+
if (!fs.existsSync(configPath)) {
|
|
66
|
+
console.log(chalk.yellow("\n No Peter Parker config found"));
|
|
67
|
+
console.log(chalk.gray(" Run: jfl peter setup\n"));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const args = ["run", "--listen"];
|
|
71
|
+
let prdPath = null;
|
|
72
|
+
if (task) {
|
|
73
|
+
const ralphDir = path.join(projectRoot, ".ralph-tui");
|
|
74
|
+
if (!fs.existsSync(ralphDir)) {
|
|
75
|
+
fs.mkdirSync(ralphDir, { recursive: true });
|
|
76
|
+
}
|
|
77
|
+
prdPath = path.join(ralphDir, "peter-task.json");
|
|
78
|
+
const titleLine = task.split("\n")[0].slice(0, 80);
|
|
79
|
+
const prd = {
|
|
80
|
+
name: "Peter Parker Task",
|
|
81
|
+
branchName: `ralph/peter-task-${Date.now()}`,
|
|
82
|
+
description: task,
|
|
83
|
+
userStories: [{
|
|
84
|
+
id: "US-001",
|
|
85
|
+
title: titleLine,
|
|
86
|
+
description: task,
|
|
87
|
+
acceptanceCriteria: ["Task completed as described"],
|
|
88
|
+
priority: 1,
|
|
89
|
+
passes: false,
|
|
90
|
+
notes: "",
|
|
91
|
+
dependsOn: [],
|
|
92
|
+
}],
|
|
93
|
+
metadata: { updatedAt: new Date().toISOString() },
|
|
94
|
+
};
|
|
95
|
+
fs.writeFileSync(prdPath, JSON.stringify(prd, null, 2));
|
|
96
|
+
args.push("--prd", prdPath, "--headless");
|
|
97
|
+
}
|
|
98
|
+
console.log(chalk.cyan("\n Starting Peter Parker orchestrator..."));
|
|
99
|
+
console.log(chalk.gray(` ralph-tui ${args.join(" ")}\n`));
|
|
100
|
+
const token = getAuthToken(projectRoot);
|
|
101
|
+
const hubUrl = getProjectHubUrl(projectRoot);
|
|
102
|
+
let bridge = null;
|
|
103
|
+
if (token) {
|
|
104
|
+
bridge = new PeterParkerBridge({
|
|
105
|
+
contextHubUrl: hubUrl,
|
|
106
|
+
authToken: token,
|
|
107
|
+
onEvent: (event) => {
|
|
108
|
+
console.log(chalk.gray(` [MAP] ${event.type}`));
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const env = { ...process.env };
|
|
113
|
+
delete env.CLAUDECODE;
|
|
114
|
+
delete env.CLAUDE_CODE;
|
|
115
|
+
const child = spawn("ralph-tui", args, {
|
|
116
|
+
cwd: projectRoot,
|
|
117
|
+
stdio: "inherit",
|
|
118
|
+
env,
|
|
119
|
+
});
|
|
120
|
+
if (bridge) {
|
|
121
|
+
setTimeout(() => bridge.start(), 1000);
|
|
122
|
+
}
|
|
123
|
+
function cleanup() {
|
|
124
|
+
if (prdPath && fs.existsSync(prdPath)) {
|
|
125
|
+
try {
|
|
126
|
+
fs.unlinkSync(prdPath);
|
|
127
|
+
}
|
|
128
|
+
catch { }
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
child.on("error", (error) => {
|
|
132
|
+
cleanup();
|
|
133
|
+
console.error(chalk.red(`Failed to start ralph-tui: ${error.message}`));
|
|
134
|
+
});
|
|
135
|
+
child.on("exit", (code) => {
|
|
136
|
+
cleanup();
|
|
137
|
+
if (bridge)
|
|
138
|
+
bridge.stop();
|
|
139
|
+
process.exit(code || 0);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
async function status(projectRoot) {
|
|
143
|
+
console.log(chalk.bold("\n Peter Parker Status\n"));
|
|
144
|
+
const profile = readCurrentProfile(projectRoot);
|
|
145
|
+
if (profile) {
|
|
146
|
+
console.log(chalk.gray(" Config profile: ") + chalk.cyan(profile));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.log(chalk.yellow(" No config found. Run: jfl peter setup"));
|
|
150
|
+
}
|
|
151
|
+
const token = getAuthToken(projectRoot);
|
|
152
|
+
const hubUrl = getProjectHubUrl(projectRoot);
|
|
153
|
+
if (token) {
|
|
154
|
+
try {
|
|
155
|
+
const params = new URLSearchParams({ pattern: "peter:*", limit: "5" });
|
|
156
|
+
const response = await fetch(`${hubUrl}/api/events?${params}`, {
|
|
157
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
158
|
+
signal: AbortSignal.timeout(2000),
|
|
159
|
+
});
|
|
160
|
+
if (response.ok) {
|
|
161
|
+
const data = await response.json();
|
|
162
|
+
console.log(chalk.gray(` Recent events: ${data.count}`));
|
|
163
|
+
for (const event of data.events) {
|
|
164
|
+
const time = new Date(event.ts).toISOString().replace("T", " ").slice(11, 19);
|
|
165
|
+
console.log(chalk.gray(` [${time}] ${event.type}`));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
console.log(chalk.gray(" Event bus: not reachable"));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
console.log(chalk.gray(" Event bus: no auth token"));
|
|
175
|
+
}
|
|
176
|
+
console.log();
|
|
177
|
+
}
|
|
178
|
+
function gitExec(args, cwd) {
|
|
179
|
+
const result = spawnSync("git", args, { cwd, encoding: "utf-8", stdio: "pipe" });
|
|
180
|
+
return { ok: result.status === 0, output: (result.stdout || "").trim() };
|
|
181
|
+
}
|
|
182
|
+
function ghExec(args, cwd) {
|
|
183
|
+
const result = spawnSync("gh", args, { cwd, encoding: "utf-8", stdio: "pipe" });
|
|
184
|
+
return { ok: result.status === 0, output: (result.stdout || "").trim() };
|
|
185
|
+
}
|
|
186
|
+
async function postHubEvent(projectRoot, eventType, data) {
|
|
187
|
+
const token = getAuthToken(projectRoot);
|
|
188
|
+
const hubUrl = getProjectHubUrl(projectRoot);
|
|
189
|
+
if (!token)
|
|
190
|
+
return;
|
|
191
|
+
try {
|
|
192
|
+
await fetch(`${hubUrl}/api/events`, {
|
|
193
|
+
method: "POST",
|
|
194
|
+
headers: {
|
|
195
|
+
"Content-Type": "application/json",
|
|
196
|
+
Authorization: `Bearer ${token}`,
|
|
197
|
+
},
|
|
198
|
+
body: JSON.stringify({
|
|
199
|
+
type: eventType,
|
|
200
|
+
source: "peter-parker",
|
|
201
|
+
data,
|
|
202
|
+
}),
|
|
203
|
+
signal: AbortSignal.timeout(5000),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
console.log(chalk.gray(" PP: Warning - could not post event to hub"));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async function initPiRuntime(projectRoot, options) {
|
|
211
|
+
const state = {
|
|
212
|
+
bridge: null,
|
|
213
|
+
costMonitor: null,
|
|
214
|
+
eventRouter: null,
|
|
215
|
+
};
|
|
216
|
+
// Check if Pi should be used
|
|
217
|
+
const shouldUsePi = options.usePi === true || (options.usePi !== false && hasPi());
|
|
218
|
+
if (!shouldUsePi) {
|
|
219
|
+
return state;
|
|
220
|
+
}
|
|
221
|
+
console.log(chalk.cyan(" Initializing Pi runtime..."));
|
|
222
|
+
// Create Pi RPC bridge
|
|
223
|
+
state.bridge = new PiRpcBridge({
|
|
224
|
+
cwd: projectRoot,
|
|
225
|
+
yolo: true,
|
|
226
|
+
noSession: true,
|
|
227
|
+
});
|
|
228
|
+
// Initialize cost monitor if budget is set
|
|
229
|
+
if (options.budget) {
|
|
230
|
+
const costConfig = {
|
|
231
|
+
maxCost: options.budget,
|
|
232
|
+
downgradeModel: { provider: "anthropic", modelId: "claude-haiku-4-5-20251001" },
|
|
233
|
+
downgradeThinkingLevel: "low",
|
|
234
|
+
upgradeModel: { provider: "anthropic", modelId: "claude-sonnet-4-20250514" },
|
|
235
|
+
upgradeThinkingLevel: "medium",
|
|
236
|
+
criticalKeywords: ["security", "auth", "payment", "migration", "deploy", "production"],
|
|
237
|
+
};
|
|
238
|
+
state.costMonitor = new CostMonitor(costConfig);
|
|
239
|
+
state.costMonitor.on("downgrade", (data) => {
|
|
240
|
+
console.log(chalk.yellow(` CostMonitor: Downgrading ${data.agent} to ${data.model} (budget: $${data.totalCost.toFixed(2)}/$${data.budget.toFixed(2)})`));
|
|
241
|
+
});
|
|
242
|
+
state.costMonitor.on("upgrade", (data) => {
|
|
243
|
+
console.log(chalk.cyan(` CostMonitor: Upgrading ${data.agent} to ${data.model} (critical path: ${data.reason})`));
|
|
244
|
+
});
|
|
245
|
+
state.costMonitor.on("cost_update", (data) => {
|
|
246
|
+
if (data.remaining < data.totalCost * 0.2) {
|
|
247
|
+
console.log(chalk.yellow(` CostMonitor: Budget low — $${data.remaining.toFixed(2)} remaining`));
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
// Initialize event router for Context Hub SSE
|
|
252
|
+
const hubUrl = getProjectHubUrl(projectRoot);
|
|
253
|
+
state.eventRouter = new EventRouter({
|
|
254
|
+
hubUrl,
|
|
255
|
+
routes: [
|
|
256
|
+
{
|
|
257
|
+
pattern: "eval:scored",
|
|
258
|
+
action: "steer",
|
|
259
|
+
messageTemplate: "SYSTEM EVENT: Eval regression detected. Agent={{data.agent}}, delta={{data.delta}}. Investigate what caused this before continuing.",
|
|
260
|
+
condition: (e) => Number(e.data?.delta ?? 0) < -0.01,
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
pattern: "scope:impact",
|
|
264
|
+
action: "follow_up",
|
|
265
|
+
messageTemplate: "SYSTEM EVENT: Scope impact from {{data.agent}} on {{data.pattern}}. Consider if this affects your current work.",
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
});
|
|
269
|
+
state.eventRouter.on("route", (data) => {
|
|
270
|
+
console.log(chalk.gray(` EventRouter: ${data.event.type} → ${data.route.action}`));
|
|
271
|
+
});
|
|
272
|
+
state.eventRouter.on("error", (err) => {
|
|
273
|
+
// Silent — hub may not be running
|
|
274
|
+
});
|
|
275
|
+
return state;
|
|
276
|
+
}
|
|
277
|
+
async function runTaskWithPi(bridge, task, costMonitor, timeout = 300000) {
|
|
278
|
+
if (!bridge.started) {
|
|
279
|
+
await bridge.start();
|
|
280
|
+
}
|
|
281
|
+
// TOCTOU guard: re-verify hub before starting agent (TLA+ invariant: HubRequiredForScheduling)
|
|
282
|
+
// TLC found: agent can be scheduled when hub is up, then hub crashes before start
|
|
283
|
+
try {
|
|
284
|
+
const { guardHubAvailable } = await import("../lib/hub-health.js");
|
|
285
|
+
const projectRoot = process.cwd();
|
|
286
|
+
const guard = await guardHubAvailable(projectRoot, "peter-parker");
|
|
287
|
+
if (!guard.proceed) {
|
|
288
|
+
console.log(chalk.yellow(`\n ⚠ Hub health check failed: ${guard.reason}`));
|
|
289
|
+
console.log(chalk.gray(` Proceeding without hub (results won't be tracked).\n`));
|
|
290
|
+
// Don't block — hub is optional for execution, just warn
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
// Hub health check not available — proceed
|
|
295
|
+
}
|
|
296
|
+
// Check critical path for model upgrade if cost monitor is active
|
|
297
|
+
if (costMonitor) {
|
|
298
|
+
await costMonitor.checkCriticalPath("experiment", task);
|
|
299
|
+
}
|
|
300
|
+
// Create a promise that resolves when agent is done
|
|
301
|
+
const agentDone = new Promise((resolve) => {
|
|
302
|
+
bridge.once("agent_end", () => resolve());
|
|
303
|
+
});
|
|
304
|
+
// Send prompt
|
|
305
|
+
await bridge.prompt(task);
|
|
306
|
+
// Wait for completion with timeout
|
|
307
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
308
|
+
setTimeout(() => reject(new Error("Pi task timeout")), timeout);
|
|
309
|
+
});
|
|
310
|
+
try {
|
|
311
|
+
await Promise.race([agentDone, timeoutPromise]);
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
await bridge.abort().catch(() => { });
|
|
315
|
+
}
|
|
316
|
+
// Update cost tracking
|
|
317
|
+
if (costMonitor) {
|
|
318
|
+
await costMonitor.checkCost("experiment");
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
async function shutdownPiRuntime(state) {
|
|
322
|
+
state.eventRouter?.stop();
|
|
323
|
+
if (state.bridge && !state.bridge.exited) {
|
|
324
|
+
await state.bridge.shutdown().catch(() => { });
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Run an agent task using claude CLI directly (~50MB vs ~500MB for Pi).
|
|
329
|
+
* Karpathy pattern: all context in the prompt, agent reads/edits/exits.
|
|
330
|
+
* Use JFL_AGENT_USE_PI=1 to force Pi runtime for debugging.
|
|
331
|
+
*/
|
|
332
|
+
async function runAgentWithPi(projectRoot, task) {
|
|
333
|
+
const ppGuardrails = [
|
|
334
|
+
"",
|
|
335
|
+
"RULES:",
|
|
336
|
+
"- Make minimal, focused changes. Don't refactor unrelated code.",
|
|
337
|
+
"- Run the build (npm run build) and check for type errors before finishing.",
|
|
338
|
+
"- If tests exist for the area you're changing, run them.",
|
|
339
|
+
"- Do NOT create new test files unless the task specifically asks for tests.",
|
|
340
|
+
"- Do NOT modify files outside the scope of the task.",
|
|
341
|
+
"- When done, stop immediately. Do not ask for confirmation.",
|
|
342
|
+
].join("\n");
|
|
343
|
+
const fullTask = task + ppGuardrails;
|
|
344
|
+
// API-based runtime: zero memory churn. No process spawning.
|
|
345
|
+
// Falls back to claude CLI spawn only if ANTHROPIC_API_KEY is missing.
|
|
346
|
+
if ((process.env.ANTHROPIC_API_KEY || process.env.OPENROUTER_API_KEY) && !tenetEnvBool('AGENT_USE_SPAWN')) {
|
|
347
|
+
console.log(chalk.cyan(" PP: Using API runtime (zero memory churn)"));
|
|
348
|
+
try {
|
|
349
|
+
const { runAgentViaAPI } = await import("../lib/agent-runtime-api.js");
|
|
350
|
+
await runAgentViaAPI({ task: fullTask, cwd: projectRoot, timeoutMs: 300_000 });
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
catch (err) {
|
|
354
|
+
console.error(chalk.yellow(` PP: API runtime failed: ${err.message} — falling back to spawn`));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
// Legacy spawn fallback — each call creates a ~300MB process.
|
|
358
|
+
// macOS compresses dead pages, unreclaimable without reboot.
|
|
359
|
+
// Set ANTHROPIC_API_KEY to use API runtime instead.
|
|
360
|
+
const forceSpawnPi = tenetEnvBool('AGENT_USE_PI');
|
|
361
|
+
if (forceSpawnPi) {
|
|
362
|
+
console.log(chalk.cyan(" PP: Using pi agent (heavy — TENET_AGENT_USE_PI=1)"));
|
|
363
|
+
await new Promise((resolve) => {
|
|
364
|
+
const env = { ...process.env };
|
|
365
|
+
delete env.CLAUDECODE;
|
|
366
|
+
delete env.CLAUDE_CODE;
|
|
367
|
+
env.JFL_AGENT_MODE = "1";
|
|
368
|
+
env.JFL_PP_SPAWNED = "1";
|
|
369
|
+
const child = spawn("pi", [
|
|
370
|
+
"--print", fullTask,
|
|
371
|
+
"--no-session",
|
|
372
|
+
"--no-skills",
|
|
373
|
+
"--no-prompt-templates",
|
|
374
|
+
"--no-themes",
|
|
375
|
+
], {
|
|
376
|
+
cwd: projectRoot,
|
|
377
|
+
stdio: "inherit",
|
|
378
|
+
env,
|
|
379
|
+
});
|
|
380
|
+
child.on("error", (error) => {
|
|
381
|
+
console.error(chalk.red(` PP: Failed to start pi: ${error.message}`));
|
|
382
|
+
resolve();
|
|
383
|
+
});
|
|
384
|
+
child.on("exit", () => {
|
|
385
|
+
resolve();
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
console.log(chalk.yellow(" PP: Using claude CLI spawn (⚠ memory churn — set ANTHROPIC_API_KEY for API runtime)"));
|
|
391
|
+
await new Promise((resolve) => {
|
|
392
|
+
const env = { ...process.env };
|
|
393
|
+
delete env.CLAUDECODE;
|
|
394
|
+
delete env.CLAUDE_CODE;
|
|
395
|
+
const child = spawn("claude", [
|
|
396
|
+
"--dangerously-skip-permissions",
|
|
397
|
+
"-p", fullTask,
|
|
398
|
+
"--output-format", "text",
|
|
399
|
+
], {
|
|
400
|
+
cwd: projectRoot,
|
|
401
|
+
stdio: "inherit",
|
|
402
|
+
env,
|
|
403
|
+
});
|
|
404
|
+
child.on("error", (error) => {
|
|
405
|
+
console.error(chalk.red(` PP: Failed to start claude: ${error.message}`));
|
|
406
|
+
resolve();
|
|
407
|
+
});
|
|
408
|
+
child.on("exit", () => {
|
|
409
|
+
resolve();
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Run an agent task using ralph-tui (legacy fallback).
|
|
416
|
+
* Has session lock issues — prefer pi.
|
|
417
|
+
*/
|
|
418
|
+
async function runAgentWithRalphTui(projectRoot, task) {
|
|
419
|
+
const configPath = path.join(projectRoot, ".ralph-tui", "config.toml");
|
|
420
|
+
if (!fs.existsSync(configPath)) {
|
|
421
|
+
console.log(chalk.yellow("\n No Peter Parker config found"));
|
|
422
|
+
console.log(chalk.gray(" Run: jfl peter setup\n"));
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
// Clear stale locks — dead PIDs shouldn't block autonomous operation
|
|
426
|
+
const lockPath = path.join(projectRoot, ".ralph-tui", "ralph.lock");
|
|
427
|
+
if (fs.existsSync(lockPath)) {
|
|
428
|
+
try {
|
|
429
|
+
const lock = JSON.parse(fs.readFileSync(lockPath, "utf-8"));
|
|
430
|
+
try {
|
|
431
|
+
process.kill(lock.pid, 0); // Check if PID is alive
|
|
432
|
+
}
|
|
433
|
+
catch {
|
|
434
|
+
// PID is dead — remove stale lock
|
|
435
|
+
fs.unlinkSync(lockPath);
|
|
436
|
+
console.log(chalk.gray(" PP: Cleared stale ralph-tui lock"));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
catch {
|
|
440
|
+
fs.unlinkSync(lockPath);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
console.log(chalk.cyan(" PP: Using ralph-tui agent (legacy)"));
|
|
444
|
+
await new Promise((resolve) => {
|
|
445
|
+
const ralphDir = path.join(projectRoot, ".ralph-tui");
|
|
446
|
+
if (!fs.existsSync(ralphDir)) {
|
|
447
|
+
fs.mkdirSync(ralphDir, { recursive: true });
|
|
448
|
+
}
|
|
449
|
+
const prdPath = path.join(ralphDir, "peter-task.json");
|
|
450
|
+
const titleLine = task.split("\n")[0].slice(0, 80);
|
|
451
|
+
const prd = {
|
|
452
|
+
name: "Peter Parker Task",
|
|
453
|
+
branchName: `ralph/peter-task-${Date.now()}`,
|
|
454
|
+
description: task,
|
|
455
|
+
userStories: [{
|
|
456
|
+
id: "US-001",
|
|
457
|
+
title: titleLine,
|
|
458
|
+
description: task,
|
|
459
|
+
acceptanceCriteria: ["Task completed as described"],
|
|
460
|
+
priority: 1,
|
|
461
|
+
passes: false,
|
|
462
|
+
notes: "",
|
|
463
|
+
dependsOn: [],
|
|
464
|
+
}],
|
|
465
|
+
metadata: { updatedAt: new Date().toISOString() },
|
|
466
|
+
};
|
|
467
|
+
fs.writeFileSync(prdPath, JSON.stringify(prd, null, 2));
|
|
468
|
+
const args = ["run", "--listen", "--prd", prdPath, "--headless"];
|
|
469
|
+
const token = getAuthToken(projectRoot);
|
|
470
|
+
let bridge = null;
|
|
471
|
+
if (token) {
|
|
472
|
+
bridge = new PeterParkerBridge({
|
|
473
|
+
contextHubUrl: getProjectHubUrl(projectRoot),
|
|
474
|
+
authToken: token,
|
|
475
|
+
onEvent: (event) => {
|
|
476
|
+
console.log(chalk.gray(` [MAP] ${event.type}`));
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
const env = { ...process.env };
|
|
481
|
+
delete env.CLAUDECODE;
|
|
482
|
+
delete env.CLAUDE_CODE;
|
|
483
|
+
const child = spawn("ralph-tui", args, {
|
|
484
|
+
cwd: projectRoot,
|
|
485
|
+
stdio: "inherit",
|
|
486
|
+
env,
|
|
487
|
+
});
|
|
488
|
+
if (bridge) {
|
|
489
|
+
setTimeout(() => bridge.start(), 1000);
|
|
490
|
+
}
|
|
491
|
+
function cleanup() {
|
|
492
|
+
if (prdPath && fs.existsSync(prdPath)) {
|
|
493
|
+
try {
|
|
494
|
+
fs.unlinkSync(prdPath);
|
|
495
|
+
}
|
|
496
|
+
catch { }
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
child.on("error", (error) => {
|
|
500
|
+
cleanup();
|
|
501
|
+
console.error(chalk.red(` PP: Failed to start ralph-tui: ${error.message}`));
|
|
502
|
+
resolve();
|
|
503
|
+
});
|
|
504
|
+
child.on("exit", () => {
|
|
505
|
+
cleanup();
|
|
506
|
+
if (bridge)
|
|
507
|
+
bridge.stop();
|
|
508
|
+
resolve();
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
async function runWithPR(projectRoot, task) {
|
|
513
|
+
if (!task) {
|
|
514
|
+
console.log(chalk.yellow("\n --task is required for pr mode"));
|
|
515
|
+
console.log(chalk.gray(" Usage: jfl peter pr --task \"fix the login bug\"\n"));
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
if (!hasPi() && !hasRalphTui()) {
|
|
519
|
+
console.log(chalk.yellow("\n Neither pi nor ralph-tui is installed"));
|
|
520
|
+
console.log(chalk.gray(" Install pi: npm i -g @mariozechner/pi-coding-agent"));
|
|
521
|
+
console.log(chalk.gray(" Or ralph-tui: bun install -g ralph-tui\n"));
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
const baseBranch = "main";
|
|
525
|
+
const branchName = `pp/fix-${Date.now()}`;
|
|
526
|
+
console.log(chalk.cyan(`\n PP: Creating branch ${branchName}`));
|
|
527
|
+
gitExec(["fetch", "origin", baseBranch], projectRoot);
|
|
528
|
+
let checkout = gitExec(["checkout", "-b", branchName, `origin/${baseBranch}`], projectRoot);
|
|
529
|
+
if (!checkout.ok) {
|
|
530
|
+
checkout = gitExec(["checkout", "-b", branchName, baseBranch], projectRoot);
|
|
531
|
+
}
|
|
532
|
+
if (!checkout.ok) {
|
|
533
|
+
console.log(chalk.red(` PP: Failed to create branch ${branchName}`));
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
console.log(chalk.cyan(` PP: Running agent on task: ${task}`));
|
|
537
|
+
// Use pi (preferred) or fall back to ralph-tui
|
|
538
|
+
if (hasPi()) {
|
|
539
|
+
await runAgentWithPi(projectRoot, task);
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
await runAgentWithRalphTui(projectRoot, task);
|
|
543
|
+
}
|
|
544
|
+
const diffCheck = gitExec(["diff", "--quiet", "HEAD"], projectRoot);
|
|
545
|
+
const untrackedResult = spawnSync("git", ["ls-files", "--others", "--exclude-standard"], {
|
|
546
|
+
cwd: projectRoot,
|
|
547
|
+
encoding: "utf-8",
|
|
548
|
+
stdio: "pipe",
|
|
549
|
+
});
|
|
550
|
+
const untracked = (untrackedResult.stdout || "").trim();
|
|
551
|
+
if (diffCheck.ok && !untracked) {
|
|
552
|
+
console.log(chalk.yellow("\n PP: No changes made, cleaning up"));
|
|
553
|
+
gitExec(["checkout", baseBranch], projectRoot);
|
|
554
|
+
gitExec(["branch", "-D", branchName], projectRoot);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
console.log(chalk.cyan(" PP: Changes detected, committing..."));
|
|
558
|
+
const commitMsg = `fix(pp): ${task}`;
|
|
559
|
+
const commitHash = signedAgentCommit(projectRoot, commitMsg, {
|
|
560
|
+
agentId: "peter-parker",
|
|
561
|
+
sessionId: branchName,
|
|
562
|
+
});
|
|
563
|
+
if (!commitHash) {
|
|
564
|
+
console.log(chalk.red(" PP: Commit failed"));
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
console.log(chalk.cyan(" PP: Pushing branch..."));
|
|
568
|
+
const pushResult = gitExec(["push", "-u", "origin", branchName], projectRoot);
|
|
569
|
+
if (!pushResult.ok) {
|
|
570
|
+
console.log(chalk.red(" PP: Push failed"));
|
|
571
|
+
console.log(chalk.gray(` ${pushResult.output}`));
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
console.log(chalk.cyan(" PP: Creating PR..."));
|
|
575
|
+
const prTitle = `PP: ${task.slice(0, 60)}`;
|
|
576
|
+
// Extract issue number from task text (e.g. "GitHub #20: ..." or "Closes #20")
|
|
577
|
+
const issueMatch = task.match(/GitHub #(\d+)/i) || task.match(/(?:Closes|Fixes|Resolves) #(\d+)/i);
|
|
578
|
+
const linkedIssue = issueMatch ? issueMatch[1] : null;
|
|
579
|
+
const prBody = [
|
|
580
|
+
"## Auto-generated by Peter Parker",
|
|
581
|
+
"",
|
|
582
|
+
`**Task:** ${task}`,
|
|
583
|
+
`**Branch:** \`${branchName}\``,
|
|
584
|
+
"",
|
|
585
|
+
...(linkedIssue ? [`Closes #${linkedIssue}`, ""] : []),
|
|
586
|
+
"### Eval Suite",
|
|
587
|
+
"This PR will be evaluated by the CI eval suite.",
|
|
588
|
+
"Auto-merge will trigger if eval score improves over baseline.",
|
|
589
|
+
"",
|
|
590
|
+
"---",
|
|
591
|
+
"*Generated by JFL self-driving loop*",
|
|
592
|
+
].join("\n");
|
|
593
|
+
let prResult = ghExec([
|
|
594
|
+
"pr", "create",
|
|
595
|
+
"--title", prTitle,
|
|
596
|
+
"--body", prBody,
|
|
597
|
+
"--base", baseBranch,
|
|
598
|
+
"--head", branchName,
|
|
599
|
+
"--label", "pp-generated",
|
|
600
|
+
], projectRoot);
|
|
601
|
+
if (!prResult.ok) {
|
|
602
|
+
prResult = ghExec([
|
|
603
|
+
"pr", "create",
|
|
604
|
+
"--title", prTitle,
|
|
605
|
+
"--body", prBody,
|
|
606
|
+
"--base", baseBranch,
|
|
607
|
+
"--head", branchName,
|
|
608
|
+
], projectRoot);
|
|
609
|
+
}
|
|
610
|
+
if (!prResult.ok) {
|
|
611
|
+
console.log(chalk.red(" PP: Failed to create PR"));
|
|
612
|
+
console.log(chalk.gray(` ${prResult.output}`));
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
const prUrl = prResult.output;
|
|
616
|
+
console.log(chalk.green(`\n PP: PR created at ${prUrl}`));
|
|
617
|
+
await postHubEvent(projectRoot, "pr:created", {
|
|
618
|
+
task,
|
|
619
|
+
pr_url: prUrl,
|
|
620
|
+
branch: branchName,
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
gitExec(["checkout", baseBranch], projectRoot);
|
|
624
|
+
console.log(chalk.green(" PP: Done\n"));
|
|
625
|
+
}
|
|
626
|
+
// ============================================================================
|
|
627
|
+
// Pickup — self-driving loop: poll backlog → pick → branch → execute → PR
|
|
628
|
+
// ============================================================================
|
|
629
|
+
function slugify(text) {
|
|
630
|
+
return text
|
|
631
|
+
.toLowerCase()
|
|
632
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
633
|
+
.replace(/^-+|-+$/g, "")
|
|
634
|
+
.slice(0, 40);
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Extract cross-repo close reference from issue body metadata.
|
|
638
|
+
* Looks for patterns like "402goose/JFL-GTM#25" in the jfl metadata block,
|
|
639
|
+
* or falls back to same-repo #N.
|
|
640
|
+
*/
|
|
641
|
+
function extractCloseRef(card) {
|
|
642
|
+
// Check for explicit cross-repo ref in metadata block
|
|
643
|
+
const metaMatch = card.description.match(/<!--\s*jfl:([\s\S]*?)-->/);
|
|
644
|
+
if (metaMatch) {
|
|
645
|
+
const meta = metaMatch[1];
|
|
646
|
+
const crossRepoMatch = meta.match(/close_ref:\s*(.+)/);
|
|
647
|
+
if (crossRepoMatch)
|
|
648
|
+
return crossRepoMatch[1].trim();
|
|
649
|
+
}
|
|
650
|
+
// Default: same-repo reference
|
|
651
|
+
return `#${card.number}`;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Append an entry to the pickup queue for audit/tracking.
|
|
655
|
+
*/
|
|
656
|
+
function appendPickupQueue(projectRoot, entry) {
|
|
657
|
+
const queuePath = path.join(projectRoot, ".jfl", "pickup-queue.jsonl");
|
|
658
|
+
const dir = path.dirname(queuePath);
|
|
659
|
+
if (!fs.existsSync(dir))
|
|
660
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
661
|
+
fs.appendFileSync(queuePath, JSON.stringify(entry) + "\n");
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Poll jfl/backlog for source:linear issues, pick the highest priority,
|
|
665
|
+
* move to in_progress, create branch, execute, create PR, close on merge.
|
|
666
|
+
*/
|
|
667
|
+
async function runPickup(projectRoot) {
|
|
668
|
+
console.log(chalk.bold("\n Peter Parker — Backlog Pickup\n"));
|
|
669
|
+
console.log(chalk.gray(" Polling jfl/backlog for source:linear issues...\n"));
|
|
670
|
+
if (!hasPi() && !hasRalphTui()) {
|
|
671
|
+
console.log(chalk.yellow(" Neither pi nor ralph-tui is installed"));
|
|
672
|
+
console.log(chalk.gray(" Install pi: npm i -g @mariozechner/pi-coding-agent"));
|
|
673
|
+
console.log(chalk.gray(" Or ralph-tui: bun install -g ralph-tui\n"));
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const { GitHubKanban } = await import("../lib/kanban-github.js");
|
|
677
|
+
let kb;
|
|
678
|
+
try {
|
|
679
|
+
kb = new GitHubKanban(projectRoot);
|
|
680
|
+
}
|
|
681
|
+
catch (err) {
|
|
682
|
+
console.log(chalk.red(` PP: ${err.message}`));
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
// Fetch backlog cards with source:linear
|
|
686
|
+
let cards;
|
|
687
|
+
try {
|
|
688
|
+
cards = await kb.getCards({ column: "backlog", source: "linear" });
|
|
689
|
+
}
|
|
690
|
+
catch (err) {
|
|
691
|
+
console.log(chalk.red(` PP: Failed to fetch backlog: ${err.message}`));
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
if (cards.length === 0) {
|
|
695
|
+
console.log(chalk.yellow(" No source:linear issues in jfl/backlog. Nothing to pick up.\n"));
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
// Already sorted by priority desc from getCards
|
|
699
|
+
const card = cards[0];
|
|
700
|
+
console.log(chalk.cyan(` Picked: #${card.number} — ${card.title}`));
|
|
701
|
+
console.log(chalk.gray(` Priority: ${card.priority} Source: ${card.source}`));
|
|
702
|
+
if (card.labels.length > 0) {
|
|
703
|
+
console.log(chalk.gray(` Labels: ${card.labels.join(", ")}`));
|
|
704
|
+
}
|
|
705
|
+
console.log();
|
|
706
|
+
// Move to in_progress
|
|
707
|
+
try {
|
|
708
|
+
kb.pick(card.number, "peter-parker");
|
|
709
|
+
console.log(chalk.gray(` 📋 Issue #${card.number} → in_progress (assigned: peter-parker)`));
|
|
710
|
+
}
|
|
711
|
+
catch (err) {
|
|
712
|
+
console.log(chalk.yellow(` PP: Could not move issue: ${err.message}`));
|
|
713
|
+
// Continue anyway — don't block on label move failure
|
|
714
|
+
}
|
|
715
|
+
// Build task prompt from issue title + description
|
|
716
|
+
const taskLines = [`GitHub #${card.number}: ${card.title}`];
|
|
717
|
+
if (card.description) {
|
|
718
|
+
// Strip the jfl metadata block from the description for the prompt
|
|
719
|
+
const cleanDesc = card.description.replace(/<!--\s*jfl:[\s\S]*?-->/g, "").trim();
|
|
720
|
+
if (cleanDesc)
|
|
721
|
+
taskLines.push("", cleanDesc);
|
|
722
|
+
}
|
|
723
|
+
const task = taskLines.join("\n");
|
|
724
|
+
// Create branch
|
|
725
|
+
const baseBranch = "main";
|
|
726
|
+
const slug = slugify(card.title);
|
|
727
|
+
const branchName = `pp/issue-${card.number}-${slug}`;
|
|
728
|
+
console.log(chalk.cyan(`\n PP: Creating branch ${branchName}`));
|
|
729
|
+
gitExec(["fetch", "origin", baseBranch], projectRoot);
|
|
730
|
+
let checkout = gitExec(["checkout", "-b", branchName, `origin/${baseBranch}`], projectRoot);
|
|
731
|
+
if (!checkout.ok) {
|
|
732
|
+
checkout = gitExec(["checkout", "-b", branchName, baseBranch], projectRoot);
|
|
733
|
+
}
|
|
734
|
+
if (!checkout.ok) {
|
|
735
|
+
console.log(chalk.red(` PP: Failed to create branch ${branchName}`));
|
|
736
|
+
// Revert kanban move
|
|
737
|
+
try {
|
|
738
|
+
kb.move(card.number, "backlog");
|
|
739
|
+
}
|
|
740
|
+
catch { }
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
// Track pickup
|
|
744
|
+
appendPickupQueue(projectRoot, {
|
|
745
|
+
ts: new Date().toISOString(),
|
|
746
|
+
issue: card.number,
|
|
747
|
+
title: card.title,
|
|
748
|
+
branch: branchName,
|
|
749
|
+
source: card.source,
|
|
750
|
+
priority: card.priority,
|
|
751
|
+
status: "in_progress",
|
|
752
|
+
});
|
|
753
|
+
// Run the agent
|
|
754
|
+
console.log(chalk.cyan(` PP: Running agent on task...\n`));
|
|
755
|
+
if (hasPi()) {
|
|
756
|
+
await runAgentWithPi(projectRoot, task);
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
759
|
+
await runAgentWithRalphTui(projectRoot, task);
|
|
760
|
+
}
|
|
761
|
+
// Check for changes
|
|
762
|
+
const diffCheck = gitExec(["diff", "--quiet", "HEAD"], projectRoot);
|
|
763
|
+
const untrackedResult = spawnSync("git", ["ls-files", "--others", "--exclude-standard"], {
|
|
764
|
+
cwd: projectRoot,
|
|
765
|
+
encoding: "utf-8",
|
|
766
|
+
stdio: "pipe",
|
|
767
|
+
});
|
|
768
|
+
const untracked = (untrackedResult.stdout || "").trim();
|
|
769
|
+
if (diffCheck.ok && !untracked) {
|
|
770
|
+
console.log(chalk.yellow("\n PP: No changes made, reverting to backlog"));
|
|
771
|
+
gitExec(["checkout", baseBranch], projectRoot);
|
|
772
|
+
gitExec(["branch", "-D", branchName], projectRoot);
|
|
773
|
+
try {
|
|
774
|
+
kb.move(card.number, "backlog");
|
|
775
|
+
}
|
|
776
|
+
catch { }
|
|
777
|
+
appendPickupQueue(projectRoot, {
|
|
778
|
+
ts: new Date().toISOString(),
|
|
779
|
+
issue: card.number,
|
|
780
|
+
branch: branchName,
|
|
781
|
+
status: "no_changes",
|
|
782
|
+
});
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
// Commit
|
|
786
|
+
console.log(chalk.cyan(" PP: Changes detected, committing..."));
|
|
787
|
+
const commitMsg = `fix(pp): #${card.number} ${card.title}`;
|
|
788
|
+
const commitHash = signedAgentCommit(projectRoot, commitMsg, {
|
|
789
|
+
agentId: "peter-parker",
|
|
790
|
+
sessionId: branchName,
|
|
791
|
+
});
|
|
792
|
+
if (!commitHash) {
|
|
793
|
+
console.log(chalk.red(" PP: Commit failed"));
|
|
794
|
+
gitExec(["checkout", baseBranch], projectRoot);
|
|
795
|
+
try {
|
|
796
|
+
kb.move(card.number, "backlog");
|
|
797
|
+
}
|
|
798
|
+
catch { }
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
// Push
|
|
802
|
+
console.log(chalk.cyan(" PP: Pushing branch..."));
|
|
803
|
+
const pushResult = gitExec(["push", "-u", "origin", branchName], projectRoot);
|
|
804
|
+
if (!pushResult.ok) {
|
|
805
|
+
console.log(chalk.red(" PP: Push failed"));
|
|
806
|
+
console.log(chalk.gray(` ${pushResult.output}`));
|
|
807
|
+
gitExec(["checkout", baseBranch], projectRoot);
|
|
808
|
+
try {
|
|
809
|
+
kb.move(card.number, "backlog");
|
|
810
|
+
}
|
|
811
|
+
catch { }
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
// Create PR
|
|
815
|
+
console.log(chalk.cyan(" PP: Creating PR..."));
|
|
816
|
+
const closeRef = extractCloseRef(card);
|
|
817
|
+
const prTitle = `PP: #${card.number} ${card.title.slice(0, 60)}`;
|
|
818
|
+
const prBody = [
|
|
819
|
+
"## Auto-generated by Peter Parker (Backlog Pickup)",
|
|
820
|
+
"",
|
|
821
|
+
`**Issue:** #${card.number} — ${card.title}`,
|
|
822
|
+
`**Branch:** \`${branchName}\``,
|
|
823
|
+
`**Source:** ${card.source}`,
|
|
824
|
+
"",
|
|
825
|
+
`Closes ${closeRef}`,
|
|
826
|
+
"",
|
|
827
|
+
"### Eval Suite",
|
|
828
|
+
"This PR will be evaluated by the CI eval suite.",
|
|
829
|
+
"Auto-merge will trigger if eval score improves over baseline.",
|
|
830
|
+
"",
|
|
831
|
+
"---",
|
|
832
|
+
"*Generated by JFL self-driving loop (pickup)*",
|
|
833
|
+
].join("\n");
|
|
834
|
+
let prResult = ghExec([
|
|
835
|
+
"pr", "create",
|
|
836
|
+
"--title", prTitle,
|
|
837
|
+
"--body", prBody,
|
|
838
|
+
"--base", baseBranch,
|
|
839
|
+
"--head", branchName,
|
|
840
|
+
"--label", "pp-generated",
|
|
841
|
+
], projectRoot);
|
|
842
|
+
if (!prResult.ok) {
|
|
843
|
+
prResult = ghExec([
|
|
844
|
+
"pr", "create",
|
|
845
|
+
"--title", prTitle,
|
|
846
|
+
"--body", prBody,
|
|
847
|
+
"--base", baseBranch,
|
|
848
|
+
"--head", branchName,
|
|
849
|
+
], projectRoot);
|
|
850
|
+
}
|
|
851
|
+
if (!prResult.ok) {
|
|
852
|
+
console.log(chalk.red(" PP: Failed to create PR"));
|
|
853
|
+
console.log(chalk.gray(` ${prResult.output}`));
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
const prUrl = prResult.output;
|
|
857
|
+
console.log(chalk.green(`\n PP: PR created at ${prUrl}`));
|
|
858
|
+
// Move to eval column
|
|
859
|
+
try {
|
|
860
|
+
kb.move(card.number, "eval");
|
|
861
|
+
}
|
|
862
|
+
catch { }
|
|
863
|
+
// Track completion
|
|
864
|
+
appendPickupQueue(projectRoot, {
|
|
865
|
+
ts: new Date().toISOString(),
|
|
866
|
+
issue: card.number,
|
|
867
|
+
branch: branchName,
|
|
868
|
+
pr_url: prUrl,
|
|
869
|
+
status: "pr_created",
|
|
870
|
+
});
|
|
871
|
+
await postHubEvent(projectRoot, "peter:pickup-complete", {
|
|
872
|
+
issue: card.number,
|
|
873
|
+
title: card.title,
|
|
874
|
+
branch: branchName,
|
|
875
|
+
pr_url: prUrl,
|
|
876
|
+
source: card.source,
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
// Write journal entry
|
|
880
|
+
writeJournalEntry(projectRoot, {
|
|
881
|
+
v: 1,
|
|
882
|
+
ts: new Date().toISOString(),
|
|
883
|
+
session: branchName,
|
|
884
|
+
type: "feature",
|
|
885
|
+
status: "complete",
|
|
886
|
+
title: `Pickup: #${card.number} ${card.title}`,
|
|
887
|
+
summary: `Auto-picked source:linear issue from backlog and executed. Branch: ${branchName}`,
|
|
888
|
+
detail: `Issue: #${card.number} — ${card.title}\nSource: ${card.source}\nPriority: ${card.priority}`,
|
|
889
|
+
agent_id: "peter-parker",
|
|
890
|
+
});
|
|
891
|
+
gitExec(["checkout", baseBranch], projectRoot);
|
|
892
|
+
console.log(chalk.green(" PP: Pickup complete.\n"));
|
|
893
|
+
}
|
|
894
|
+
function buildRLState(evals, trajectoryLength, recentDeltas) {
|
|
895
|
+
const latest = evals.sort((a, b) => b.ts.localeCompare(a.ts))[0];
|
|
896
|
+
return {
|
|
897
|
+
composite_score: latest?.composite ?? 0,
|
|
898
|
+
dimension_scores: latest?.metrics ?? {},
|
|
899
|
+
tests_passing: latest?.metrics?.tests_passed ?? 0,
|
|
900
|
+
tests_total: latest?.metrics?.tests_total ?? 1,
|
|
901
|
+
trajectory_length: trajectoryLength,
|
|
902
|
+
recent_deltas: recentDeltas,
|
|
903
|
+
agent: "peter-parker",
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
function proposalToRLAction(p) {
|
|
907
|
+
return {
|
|
908
|
+
type: "experiment",
|
|
909
|
+
description: p.task,
|
|
910
|
+
files_affected: [],
|
|
911
|
+
scope: "medium",
|
|
912
|
+
branch: "",
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
async function rerankWithPolicyHead(projectRoot, proposals, evals, recentDeltas) {
|
|
916
|
+
const ph = new PolicyHeadInference(projectRoot);
|
|
917
|
+
if (!ph.isLoaded || proposals.length < 2)
|
|
918
|
+
return proposals;
|
|
919
|
+
const state = buildRLState(evals, 0, recentDeltas);
|
|
920
|
+
const actions = proposals.map(proposalToRLAction);
|
|
921
|
+
try {
|
|
922
|
+
const ranked = await ph.rankActions(state, actions);
|
|
923
|
+
const reordered = ranked.map(r => proposals[actions.indexOf(r.action)]);
|
|
924
|
+
const stats = ph.stats;
|
|
925
|
+
console.log(chalk.magenta(` Policy head re-ranked ${proposals.length} proposals (trained on ${stats.trained_on} tuples, rank_corr=${stats.rank_correlation.toFixed(3)})`));
|
|
926
|
+
for (let i = 0; i < ranked.length; i++) {
|
|
927
|
+
const r = ranked[i];
|
|
928
|
+
const p = reordered[i];
|
|
929
|
+
console.log(chalk.gray(` #${i + 1} [pred=${r.predictedReward.toFixed(4)}] ${p.task.slice(0, 60)}`));
|
|
930
|
+
}
|
|
931
|
+
console.log();
|
|
932
|
+
return reordered;
|
|
933
|
+
}
|
|
934
|
+
catch (err) {
|
|
935
|
+
console.log(chalk.yellow(` Policy head ranking failed: ${err.message}`));
|
|
936
|
+
return proposals;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Use the planning loop (PH → WM rollouts → select) to choose the best action.
|
|
941
|
+
* Falls back to rerankWithPolicyHead if planning loop fails.
|
|
942
|
+
*/
|
|
943
|
+
async function planWithRollouts(projectRoot, agentId, goal, proposals, evals, recentDeltas, verbose = false) {
|
|
944
|
+
try {
|
|
945
|
+
const planner = createPlanningLoop(projectRoot, {
|
|
946
|
+
topK: Math.min(5, proposals.length),
|
|
947
|
+
verbose,
|
|
948
|
+
maxPlanningTimeMs: 10000, // 10s for experiment selection
|
|
949
|
+
});
|
|
950
|
+
if (!planner.isReady) {
|
|
951
|
+
if (verbose)
|
|
952
|
+
console.log(chalk.gray(" Planning loop: PolicyHead not loaded, using rerank fallback"));
|
|
953
|
+
const reranked = await rerankWithPolicyHead(projectRoot, proposals, evals, recentDeltas);
|
|
954
|
+
return { proposals: reranked, planningResult: null };
|
|
955
|
+
}
|
|
956
|
+
console.log(chalk.magenta(" Planning loop: PH → WM rollouts → select"));
|
|
957
|
+
const result = await planner.plan(agentId, goal);
|
|
958
|
+
if (result.selectedAction) {
|
|
959
|
+
console.log(chalk.magenta(` Planning completed in ${result.planningTimeMs}ms, ${result.rolloutsPerformed} rollouts`));
|
|
960
|
+
// Map planning results back to proposals by scoring alignment
|
|
961
|
+
const scoredProposals = proposals.map(p => {
|
|
962
|
+
// Find best matching evaluated action
|
|
963
|
+
const bestMatch = result.allActions
|
|
964
|
+
.filter(a => !a.filtered)
|
|
965
|
+
.sort((a, b) => {
|
|
966
|
+
// Score by how well the action type matches the proposal
|
|
967
|
+
const aMatch = proposalMatchesAction(p, a) ? 1 : 0;
|
|
968
|
+
const bMatch = proposalMatchesAction(p, b) ? 1 : 0;
|
|
969
|
+
if (aMatch !== bMatch)
|
|
970
|
+
return bMatch - aMatch;
|
|
971
|
+
return b.combinedScore - a.combinedScore;
|
|
972
|
+
})[0];
|
|
973
|
+
return {
|
|
974
|
+
proposal: p,
|
|
975
|
+
score: bestMatch?.combinedScore ?? 0,
|
|
976
|
+
prediction: bestMatch?.prediction,
|
|
977
|
+
};
|
|
978
|
+
});
|
|
979
|
+
scoredProposals.sort((a, b) => b.score - a.score);
|
|
980
|
+
// Log the ranked results
|
|
981
|
+
for (let i = 0; i < scoredProposals.length; i++) {
|
|
982
|
+
const s = scoredProposals[i];
|
|
983
|
+
const predDelta = s.prediction?.outcome?.immediate?.evalScoreChange;
|
|
984
|
+
const conf = s.prediction?.confidence;
|
|
985
|
+
console.log(chalk.gray(` #${i + 1} [score=${s.score.toFixed(3)}` +
|
|
986
|
+
(predDelta !== undefined ? ` pred_delta=${predDelta > 0 ? "+" : ""}${predDelta.toFixed(4)}` : "") +
|
|
987
|
+
(conf !== undefined ? ` conf=${conf.toFixed(2)}` : "") +
|
|
988
|
+
`] ${s.proposal.task.slice(0, 60)}`));
|
|
989
|
+
}
|
|
990
|
+
console.log();
|
|
991
|
+
return {
|
|
992
|
+
proposals: scoredProposals.map(s => s.proposal),
|
|
993
|
+
planningResult: result,
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
else {
|
|
997
|
+
console.log(chalk.yellow(` Planning loop: no valid action selected (${result.noSelectionReason})`));
|
|
998
|
+
const reranked = await rerankWithPolicyHead(projectRoot, proposals, evals, recentDeltas);
|
|
999
|
+
return { proposals: reranked, planningResult: result };
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
catch (err) {
|
|
1003
|
+
console.log(chalk.yellow(` Planning loop failed: ${err.message}`));
|
|
1004
|
+
const reranked = await rerankWithPolicyHead(projectRoot, proposals, evals, recentDeltas);
|
|
1005
|
+
return { proposals: reranked, planningResult: null };
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
/** Check if a proposal's task description matches an evaluated action type */
|
|
1009
|
+
function proposalMatchesAction(proposal, action) {
|
|
1010
|
+
const task = proposal.task.toLowerCase();
|
|
1011
|
+
const actionType = action.action.actionType;
|
|
1012
|
+
const matches = {
|
|
1013
|
+
"fix": ["fix", "bug", "error", "crash", "broken"],
|
|
1014
|
+
"refactor": ["refactor", "clean", "simplify", "extract", "dedup"],
|
|
1015
|
+
"feature": ["add", "implement", "create", "build", "new"],
|
|
1016
|
+
"test": ["test", "coverage", "spec", "assert"],
|
|
1017
|
+
"config": ["config", "setting", "env", "deploy"],
|
|
1018
|
+
"experiment": ["experiment", "try", "investigate", "explore"],
|
|
1019
|
+
"eval": ["eval", "score", "metric", "measure"],
|
|
1020
|
+
"research": ["research", "read", "analyze", "understand"],
|
|
1021
|
+
};
|
|
1022
|
+
const keywords = matches[actionType] || [];
|
|
1023
|
+
return keywords.some(kw => task.includes(kw));
|
|
1024
|
+
}
|
|
1025
|
+
function writeJournalEntry(projectRoot, entry) {
|
|
1026
|
+
const journalDir = path.join(projectRoot, ".jfl", "journal");
|
|
1027
|
+
if (!fs.existsSync(journalDir)) {
|
|
1028
|
+
fs.mkdirSync(journalDir, { recursive: true });
|
|
1029
|
+
}
|
|
1030
|
+
const journalFile = path.join(journalDir, "peter-experiment.jsonl");
|
|
1031
|
+
fs.appendFileSync(journalFile, JSON.stringify(entry) + "\n");
|
|
1032
|
+
}
|
|
1033
|
+
function buildEvalSummary(evals, limit = 10) {
|
|
1034
|
+
if (evals.length === 0)
|
|
1035
|
+
return "No eval entries found.";
|
|
1036
|
+
const recent = evals
|
|
1037
|
+
.sort((a, b) => b.ts.localeCompare(a.ts))
|
|
1038
|
+
.slice(0, limit);
|
|
1039
|
+
const lines = [];
|
|
1040
|
+
for (const e of recent) {
|
|
1041
|
+
const metricsStr = Object.entries(e.metrics)
|
|
1042
|
+
.map(([k, v]) => `${k}=${typeof v === "number" ? v.toFixed(4) : v}`)
|
|
1043
|
+
.join(", ");
|
|
1044
|
+
lines.push(`[${e.ts}] agent=${e.agent} composite=${e.composite?.toFixed(4) ?? "N/A"} ${metricsStr}`);
|
|
1045
|
+
}
|
|
1046
|
+
return lines.join("\n");
|
|
1047
|
+
}
|
|
1048
|
+
function findLowestDimension(evals) {
|
|
1049
|
+
if (evals.length === 0)
|
|
1050
|
+
return null;
|
|
1051
|
+
const latest = evals
|
|
1052
|
+
.sort((a, b) => b.ts.localeCompare(a.ts))[0];
|
|
1053
|
+
if (!latest.metrics || Object.keys(latest.metrics).length === 0)
|
|
1054
|
+
return null;
|
|
1055
|
+
let lowestDim = "";
|
|
1056
|
+
let lowestScore = Infinity;
|
|
1057
|
+
for (const [dim, score] of Object.entries(latest.metrics)) {
|
|
1058
|
+
if (typeof score === "number" && score < lowestScore) {
|
|
1059
|
+
lowestScore = score;
|
|
1060
|
+
lowestDim = dim;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
if (!lowestDim)
|
|
1064
|
+
return null;
|
|
1065
|
+
return { dimension: lowestDim, score: lowestScore };
|
|
1066
|
+
}
|
|
1067
|
+
function findRegressedDimensions(evals) {
|
|
1068
|
+
if (evals.length < 2)
|
|
1069
|
+
return [];
|
|
1070
|
+
const sorted = evals.sort((a, b) => b.ts.localeCompare(a.ts));
|
|
1071
|
+
const latest = sorted[0];
|
|
1072
|
+
const previous = sorted[1];
|
|
1073
|
+
if (!latest?.metrics || !previous?.metrics)
|
|
1074
|
+
return [];
|
|
1075
|
+
const regressed = [];
|
|
1076
|
+
for (const [dim, score] of Object.entries(latest.metrics)) {
|
|
1077
|
+
const prevScore = previous.metrics[dim];
|
|
1078
|
+
if (typeof score === "number" && typeof prevScore === "number" && score < prevScore) {
|
|
1079
|
+
regressed.push({ dimension: dim, delta: score - prevScore });
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
return regressed.sort((a, b) => a.delta - b.delta);
|
|
1083
|
+
}
|
|
1084
|
+
async function runExperiment(projectRoot) {
|
|
1085
|
+
console.log(chalk.bold("\n Peter Parker - Proactive Experiment Selection\n"));
|
|
1086
|
+
const loader = new TrajectoryLoader(projectRoot);
|
|
1087
|
+
const evals = readEvals(projectRoot);
|
|
1088
|
+
if (evals.length === 0) {
|
|
1089
|
+
console.log(chalk.yellow(" No eval history yet -- run `jfl peter pr` first to build a baseline.\n"));
|
|
1090
|
+
return;
|
|
1091
|
+
}
|
|
1092
|
+
const trajectoryEntries = loader.load({ maxAge: "30d", limit: 50 });
|
|
1093
|
+
const experimentEntries = loader.load({ type: "experiment", maxAge: "30d", limit: 20 });
|
|
1094
|
+
const pastTitles = experimentEntries.map(e => e.title);
|
|
1095
|
+
console.log(chalk.gray(` Loaded ${evals.length} eval entries, ${trajectoryEntries.length} trajectory entries`));
|
|
1096
|
+
let proposal = null;
|
|
1097
|
+
const stratusKey = process.env.STRATUS_API_KEY;
|
|
1098
|
+
const stratusUrl = process.env.STRATUS_API_URL || "https://api.stratus.run";
|
|
1099
|
+
if (stratusKey) {
|
|
1100
|
+
console.log(chalk.gray(" Using Stratus to rank experiment proposals...\n"));
|
|
1101
|
+
try {
|
|
1102
|
+
const { StratusClient } = await import("../lib/stratus-client.js");
|
|
1103
|
+
const stratus = new StratusClient({
|
|
1104
|
+
baseUrl: stratusUrl,
|
|
1105
|
+
apiKey: stratusKey,
|
|
1106
|
+
model: "stratus-x1ac-base-claude-sonnet-4-6",
|
|
1107
|
+
timeout: 60000,
|
|
1108
|
+
});
|
|
1109
|
+
const evalSummary = buildEvalSummary(evals, 15);
|
|
1110
|
+
const trajectoryContext = loader.renderForContext(loader.deduplicate(experimentEntries.slice(0, 10)));
|
|
1111
|
+
const prompt = `Given the following experiment trajectory and eval history, suggest the top 3 improvements that would most increase the composite eval score.
|
|
1112
|
+
|
|
1113
|
+
Recent eval entries:
|
|
1114
|
+
${evalSummary}
|
|
1115
|
+
|
|
1116
|
+
Recent experiment outcomes:
|
|
1117
|
+
${trajectoryContext}
|
|
1118
|
+
|
|
1119
|
+
What has been tried (avoid repeats):
|
|
1120
|
+
${pastTitles.length > 0 ? pastTitles.map(t => `- ${t}`).join("\n") : "Nothing yet"}
|
|
1121
|
+
|
|
1122
|
+
For each suggestion, provide a JSON array with objects having these fields:
|
|
1123
|
+
- task: one-line description of what to implement
|
|
1124
|
+
- predicted_delta: estimated score improvement (0.0 to 1.0)
|
|
1125
|
+
- reasoning: why this would help
|
|
1126
|
+
- risk: what could go wrong
|
|
1127
|
+
|
|
1128
|
+
Respond with ONLY a JSON array, no other text.`;
|
|
1129
|
+
const response = await stratus.reason(prompt, {
|
|
1130
|
+
temperature: 0.7,
|
|
1131
|
+
maxTokens: 1500,
|
|
1132
|
+
featureContext: "experiment-selection",
|
|
1133
|
+
});
|
|
1134
|
+
const content = response.choices[0]?.message?.content || "";
|
|
1135
|
+
const jsonMatch = content.match(/\[[\s\S]*\]/);
|
|
1136
|
+
if (jsonMatch) {
|
|
1137
|
+
let proposals = JSON.parse(jsonMatch[0]);
|
|
1138
|
+
if (proposals.length > 0) {
|
|
1139
|
+
proposals.sort((a, b) => b.predicted_delta - a.predicted_delta);
|
|
1140
|
+
const recentDeltas = experimentEntries
|
|
1141
|
+
.slice(0, 5)
|
|
1142
|
+
.map(e => e.score_delta ?? 0)
|
|
1143
|
+
.filter((d) => typeof d === "number");
|
|
1144
|
+
// Use planning loop (PH → WM rollouts) when available, fallback to rerank
|
|
1145
|
+
const planResult = await planWithRollouts(projectRoot, "peter-parker", "Select highest-impact experiment for eval score improvement", proposals, evals, recentDeltas);
|
|
1146
|
+
proposals = planResult.proposals;
|
|
1147
|
+
console.log(chalk.bold(" Top 3 Proposals:\n"));
|
|
1148
|
+
for (let i = 0; i < Math.min(3, proposals.length); i++) {
|
|
1149
|
+
const p = proposals[i];
|
|
1150
|
+
const rank = i + 1;
|
|
1151
|
+
console.log(chalk.cyan(` ${rank}. ${p.task}`));
|
|
1152
|
+
console.log(chalk.gray(` Delta: +${p.predicted_delta.toFixed(4)} | Risk: ${p.risk}`));
|
|
1153
|
+
console.log(chalk.gray(` Reasoning: ${p.reasoning}\n`));
|
|
1154
|
+
}
|
|
1155
|
+
proposal = proposals[0];
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
if (!proposal) {
|
|
1159
|
+
console.log(chalk.yellow(" Stratus returned no parseable proposals, falling back to heuristic"));
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
catch (err) {
|
|
1163
|
+
console.log(chalk.yellow(` Stratus call failed: ${err.message}`));
|
|
1164
|
+
console.log(chalk.gray(" Falling back to heuristic approach\n"));
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
if (!proposal) {
|
|
1168
|
+
console.log(chalk.gray(" Using heuristic: targeting lowest-scoring eval dimension\n"));
|
|
1169
|
+
const regressed = findRegressedDimensions(evals);
|
|
1170
|
+
const lowest = findLowestDimension(evals);
|
|
1171
|
+
if (regressed.length > 0) {
|
|
1172
|
+
const worst = regressed[0];
|
|
1173
|
+
proposal = {
|
|
1174
|
+
task: `Improve ${worst.dimension} score which regressed by ${worst.delta.toFixed(4)} in the latest eval. Analyze recent changes that may have caused the regression and fix them.`,
|
|
1175
|
+
predicted_delta: Math.abs(worst.delta),
|
|
1176
|
+
reasoning: `${worst.dimension} regressed by ${worst.delta.toFixed(4)} -- recovering this regression is the highest-value action`,
|
|
1177
|
+
risk: "Fix may not fully recover the regression if root cause is structural",
|
|
1178
|
+
};
|
|
1179
|
+
console.log(chalk.cyan(` Target: ${worst.dimension} (regressed by ${worst.delta.toFixed(4)})`));
|
|
1180
|
+
}
|
|
1181
|
+
else if (lowest) {
|
|
1182
|
+
proposal = {
|
|
1183
|
+
task: `Improve ${lowest.dimension} score (currently ${lowest.score.toFixed(4)}) which is the lowest-performing eval dimension. Focus changes on improving this specific metric.`,
|
|
1184
|
+
predicted_delta: Math.max(0.01, (1 - lowest.score) * 0.1),
|
|
1185
|
+
reasoning: `${lowest.dimension} at ${lowest.score.toFixed(4)} is the weakest dimension -- improving it has the most room for composite score gains`,
|
|
1186
|
+
risk: "Improvements to one dimension may trade off against others",
|
|
1187
|
+
};
|
|
1188
|
+
console.log(chalk.cyan(` Target: ${lowest.dimension} (score: ${lowest.score.toFixed(4)})`));
|
|
1189
|
+
}
|
|
1190
|
+
else {
|
|
1191
|
+
console.log(chalk.yellow(" Could not determine a target dimension from eval history.\n"));
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
console.log(chalk.bold(`\n Selected experiment:`));
|
|
1196
|
+
console.log(chalk.white(` Task: ${proposal.task}`));
|
|
1197
|
+
console.log(chalk.gray(` Predicted delta: +${proposal.predicted_delta.toFixed(4)}`));
|
|
1198
|
+
console.log(chalk.gray(` Risk: ${proposal.risk}\n`));
|
|
1199
|
+
writeJournalEntry(projectRoot, {
|
|
1200
|
+
v: 1,
|
|
1201
|
+
ts: new Date().toISOString(),
|
|
1202
|
+
session: "peter-experiment",
|
|
1203
|
+
type: "experiment",
|
|
1204
|
+
status: "incomplete",
|
|
1205
|
+
title: `Experiment: ${proposal.task.slice(0, 80)}`,
|
|
1206
|
+
summary: `Proactive experiment selected. Predicted delta: +${proposal.predicted_delta.toFixed(4)}. ${proposal.reasoning}`,
|
|
1207
|
+
detail: `Task: ${proposal.task}\nRisk: ${proposal.risk}`,
|
|
1208
|
+
hypothesis: `Implementing "${proposal.task}" will improve composite score by ~${proposal.predicted_delta.toFixed(4)}`,
|
|
1209
|
+
agent_id: "peter-parker",
|
|
1210
|
+
});
|
|
1211
|
+
await postHubEvent(projectRoot, "peter:task-selected", {
|
|
1212
|
+
task: proposal.task,
|
|
1213
|
+
predicted_delta: proposal.predicted_delta,
|
|
1214
|
+
source: "experiment",
|
|
1215
|
+
reasoning: proposal.reasoning,
|
|
1216
|
+
});
|
|
1217
|
+
// Create GitHub Issue for the experiment
|
|
1218
|
+
try {
|
|
1219
|
+
const { GitHubKanban } = await import("../lib/kanban-github.js");
|
|
1220
|
+
const kb = new GitHubKanban(projectRoot);
|
|
1221
|
+
const issueNum = kb.create({
|
|
1222
|
+
title: proposal.task.slice(0, 120),
|
|
1223
|
+
description: `Predicted delta: +${proposal.predicted_delta.toFixed(4)}. ${proposal.reasoning}\n\nAuthored-by: peter-parker (jfl-cli)`,
|
|
1224
|
+
source: "agent",
|
|
1225
|
+
priority: Math.round(proposal.predicted_delta * 10),
|
|
1226
|
+
agent: "peter-parker",
|
|
1227
|
+
labels: ["agent"],
|
|
1228
|
+
});
|
|
1229
|
+
if (issueNum) {
|
|
1230
|
+
kb.pick(issueNum, "peter-parker");
|
|
1231
|
+
console.log(chalk.gray(` 📋 Issue #${issueNum} → in_progress`));
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
catch { }
|
|
1235
|
+
console.log(chalk.cyan(" Dispatching to Peter Parker PR workflow...\n"));
|
|
1236
|
+
await runWithPR(projectRoot, proposal.task);
|
|
1237
|
+
}
|
|
1238
|
+
async function runAutoresearch(projectRoot, options) {
|
|
1239
|
+
const { rounds, budget, usePi } = options;
|
|
1240
|
+
console.log(chalk.bold(`\n Peter Parker - Autoresearch Mode (${rounds} rounds)\n`));
|
|
1241
|
+
console.log(chalk.gray(" Pattern: branch → change → eval → keep|revert → repeat"));
|
|
1242
|
+
console.log(chalk.gray(" Only the winning experiment gets a PR."));
|
|
1243
|
+
if (budget) {
|
|
1244
|
+
console.log(chalk.gray(` Budget: $${budget.toFixed(2)}`));
|
|
1245
|
+
}
|
|
1246
|
+
if (usePi || (usePi !== false && hasPi())) {
|
|
1247
|
+
console.log(chalk.cyan(" Runtime: Pi (RPC)"));
|
|
1248
|
+
}
|
|
1249
|
+
else {
|
|
1250
|
+
console.log(chalk.gray(" Runtime: claude CLI"));
|
|
1251
|
+
}
|
|
1252
|
+
console.log();
|
|
1253
|
+
// Initialize Pi runtime if available
|
|
1254
|
+
const piState = await initPiRuntime(projectRoot, { budget, usePi });
|
|
1255
|
+
const usePiRuntime = piState.bridge !== null;
|
|
1256
|
+
// Start event router to listen for eval regressions
|
|
1257
|
+
if (piState.eventRouter && piState.bridge) {
|
|
1258
|
+
piState.eventRouter.registerBridge("experiment", piState.bridge);
|
|
1259
|
+
try {
|
|
1260
|
+
await piState.eventRouter.startSse();
|
|
1261
|
+
}
|
|
1262
|
+
catch {
|
|
1263
|
+
// Fall back to polling if SSE not available
|
|
1264
|
+
await piState.eventRouter.startPolling(5000);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
// Register bridge with cost monitor
|
|
1268
|
+
if (piState.costMonitor && piState.bridge) {
|
|
1269
|
+
piState.costMonitor.registerBridge("experiment", piState.bridge);
|
|
1270
|
+
}
|
|
1271
|
+
// Only require ralph-tui if not using Pi
|
|
1272
|
+
if (!usePiRuntime && !hasRalphTui()) {
|
|
1273
|
+
console.log(chalk.yellow(" ralph-tui is not installed (and Pi not available)"));
|
|
1274
|
+
console.log(chalk.gray(" Install: bun install -g ralph-tui\n"));
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
if (!usePiRuntime) {
|
|
1278
|
+
const configPath = path.join(projectRoot, ".ralph-tui", "config.toml");
|
|
1279
|
+
if (!fs.existsSync(configPath)) {
|
|
1280
|
+
console.log(chalk.yellow(" No Peter Parker config found"));
|
|
1281
|
+
console.log(chalk.gray(" Run: jfl peter setup\n"));
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
const loader = new TrajectoryLoader(projectRoot);
|
|
1286
|
+
const evals = readEvals(projectRoot);
|
|
1287
|
+
if (evals.length === 0) {
|
|
1288
|
+
console.log(chalk.yellow(" No eval history. Run `jfl peter pr` first.\n"));
|
|
1289
|
+
return;
|
|
1290
|
+
}
|
|
1291
|
+
const baseBranch = "main";
|
|
1292
|
+
const latestEval = evals.sort((a, b) => b.ts.localeCompare(a.ts))[0];
|
|
1293
|
+
const baselinePassRate = latestEval?.composite ?? 0;
|
|
1294
|
+
const baselineTotal = latestEval?.metrics?.tests_total ?? 0;
|
|
1295
|
+
const baselineScore = baselinePassRate + (baselineTotal > 0 ? baselineTotal * 0.001 : 0);
|
|
1296
|
+
console.log(chalk.gray(` Baseline composite: ${baselineScore.toFixed(4)} (${baselineTotal} tests)`));
|
|
1297
|
+
const results = [];
|
|
1298
|
+
let bestResult = null;
|
|
1299
|
+
for (let round = 1; round <= rounds; round++) {
|
|
1300
|
+
console.log(chalk.bold(`\n ── Round ${round}/${rounds} ${"─".repeat(40)}\n`));
|
|
1301
|
+
const experimentEntries = loader.load({ type: "experiment", maxAge: "30d", limit: 20 });
|
|
1302
|
+
const pastTitles = [
|
|
1303
|
+
...experimentEntries.map(e => e.title),
|
|
1304
|
+
...results.map(r => r.task),
|
|
1305
|
+
];
|
|
1306
|
+
let proposal = null;
|
|
1307
|
+
const stratusKey = process.env.STRATUS_API_KEY;
|
|
1308
|
+
if (stratusKey) {
|
|
1309
|
+
try {
|
|
1310
|
+
const { StratusClient } = await import("../lib/stratus-client.js");
|
|
1311
|
+
const stratus = new StratusClient({
|
|
1312
|
+
baseUrl: process.env.STRATUS_API_URL || "https://api.stratus.run",
|
|
1313
|
+
apiKey: stratusKey,
|
|
1314
|
+
model: "stratus-x1ac-base-claude-sonnet-4-6",
|
|
1315
|
+
timeout: 60000,
|
|
1316
|
+
});
|
|
1317
|
+
const evalSummary = buildEvalSummary(evals.concat(results.map(r => ({
|
|
1318
|
+
v: 1, ts: new Date().toISOString(), agent: "autoresearch",
|
|
1319
|
+
run_id: `autoresearch-r${r.round}`,
|
|
1320
|
+
metrics: { composite: r.score }, composite: r.score,
|
|
1321
|
+
model_version: `round-${r.round}`,
|
|
1322
|
+
}))), 15);
|
|
1323
|
+
const policyHead = new PolicyHeadInference(projectRoot);
|
|
1324
|
+
const useMultiProposal = policyHead.isLoaded;
|
|
1325
|
+
// v2 policy head: get recommended action type before generating proposals
|
|
1326
|
+
let actionGuidance = "";
|
|
1327
|
+
if (policyHead.isLoaded && policyHead.version >= 2) {
|
|
1328
|
+
try {
|
|
1329
|
+
const rlState = buildRLState(evals, round, results.slice(-5).map(r => r.delta));
|
|
1330
|
+
const selection = await policyHead.selectAction(rlState, "Improve codebase quality");
|
|
1331
|
+
actionGuidance = `\nPolicy head recommends action type: "${selection.action}" (confidence: ${(selection.confidence * 100).toFixed(0)}%).`;
|
|
1332
|
+
if (selection.alternatives.length > 0) {
|
|
1333
|
+
actionGuidance += ` Alternatives: ${selection.alternatives.map(a => `${a.action}(${(a.confidence * 100).toFixed(0)}%)`).join(", ")}.`;
|
|
1334
|
+
}
|
|
1335
|
+
actionGuidance += `\nFavor proposals that align with the "${selection.action}" action type.`;
|
|
1336
|
+
console.log(chalk.magenta(` Policy head v2 recommends: ${selection.action} (${(selection.confidence * 100).toFixed(0)}%)`));
|
|
1337
|
+
}
|
|
1338
|
+
catch {
|
|
1339
|
+
// v2 not available, continue without guidance
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
const prompt = useMultiProposal
|
|
1343
|
+
? `Autoresearch round ${round}/${rounds}. Suggest 3 specific improvements ranked by expected impact.
|
|
1344
|
+
${actionGuidance}
|
|
1345
|
+
Eval history:
|
|
1346
|
+
${evalSummary}
|
|
1347
|
+
|
|
1348
|
+
Already tried (avoid these):
|
|
1349
|
+
${pastTitles.map(t => `- ${t}`).join("\n") || "Nothing yet"}
|
|
1350
|
+
|
|
1351
|
+
Previous rounds this session:
|
|
1352
|
+
${results.map(r => `- Round ${r.round}: "${r.task}" → delta=${r.delta > 0 ? "+" : ""}${r.delta.toFixed(4)}`).join("\n") || "None yet"}
|
|
1353
|
+
|
|
1354
|
+
Respond with ONLY a JSON array of 3 objects: [{"task": "...", "predicted_delta": 0.0-1.0, "reasoning": "...", "risk": "..."}, ...]`
|
|
1355
|
+
: `Autoresearch round ${round}/${rounds}. Suggest ONE specific improvement.
|
|
1356
|
+
${actionGuidance}
|
|
1357
|
+
Eval history:
|
|
1358
|
+
${evalSummary}
|
|
1359
|
+
|
|
1360
|
+
Already tried (avoid these):
|
|
1361
|
+
${pastTitles.map(t => `- ${t}`).join("\n") || "Nothing yet"}
|
|
1362
|
+
|
|
1363
|
+
Previous rounds this session:
|
|
1364
|
+
${results.map(r => `- Round ${r.round}: "${r.task}" → delta=${r.delta > 0 ? "+" : ""}${r.delta.toFixed(4)}`).join("\n") || "None yet"}
|
|
1365
|
+
|
|
1366
|
+
Suggest the SINGLE highest-value change. JSON format:
|
|
1367
|
+
{"task": "...", "predicted_delta": 0.0-1.0, "reasoning": "...", "risk": "..."}`;
|
|
1368
|
+
const response = await stratus.reason(prompt, {
|
|
1369
|
+
temperature: 0.8 + (round * 0.05),
|
|
1370
|
+
maxTokens: useMultiProposal ? 1500 : 500,
|
|
1371
|
+
featureContext: "autoresearch",
|
|
1372
|
+
});
|
|
1373
|
+
const content = response.choices[0]?.message?.content || "";
|
|
1374
|
+
if (useMultiProposal) {
|
|
1375
|
+
const jsonMatch = content.match(/\[[\s\S]*\]/);
|
|
1376
|
+
if (jsonMatch) {
|
|
1377
|
+
let proposals = JSON.parse(jsonMatch[0]);
|
|
1378
|
+
const recentDeltas = results.slice(-5).map(r => r.delta);
|
|
1379
|
+
// Use planning loop (PH → WM rollouts) when available
|
|
1380
|
+
const planResult = await planWithRollouts(projectRoot, "peter-parker", `Autoresearch round ${round}: improve eval score`, proposals, evals, recentDeltas);
|
|
1381
|
+
proposals = planResult.proposals;
|
|
1382
|
+
if (proposals.length > 0)
|
|
1383
|
+
proposal = proposals[0];
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
if (!proposal) {
|
|
1387
|
+
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
1388
|
+
if (jsonMatch) {
|
|
1389
|
+
proposal = JSON.parse(jsonMatch[0]);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
catch (err) {
|
|
1394
|
+
console.log(chalk.yellow(` Stratus failed: ${err.message}`));
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
if (!proposal) {
|
|
1398
|
+
const regressed = findRegressedDimensions(evals);
|
|
1399
|
+
const lowest = findLowestDimension(evals);
|
|
1400
|
+
if (regressed.length > 0) {
|
|
1401
|
+
const worst = regressed[0];
|
|
1402
|
+
proposal = {
|
|
1403
|
+
task: `Improve ${worst.dimension} score (regressed by ${worst.delta.toFixed(4)})`,
|
|
1404
|
+
predicted_delta: Math.abs(worst.delta),
|
|
1405
|
+
reasoning: `Recovering ${worst.dimension} regression`,
|
|
1406
|
+
risk: "May not fully recover",
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
else if (lowest) {
|
|
1410
|
+
proposal = {
|
|
1411
|
+
task: `Improve ${lowest.dimension} score (currently ${lowest.score.toFixed(4)})`,
|
|
1412
|
+
predicted_delta: Math.max(0.01, (1 - lowest.score) * 0.1),
|
|
1413
|
+
reasoning: `${lowest.dimension} is weakest dimension`,
|
|
1414
|
+
risk: "May trade off against others",
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
else {
|
|
1418
|
+
console.log(chalk.yellow(" No target found, skipping round"));
|
|
1419
|
+
continue;
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
console.log(chalk.cyan(` Task: ${proposal.task}`));
|
|
1423
|
+
console.log(chalk.gray(` Predicted: +${proposal.predicted_delta.toFixed(4)}\n`));
|
|
1424
|
+
const branchName = `pp/autoresearch-r${round}-${Date.now()}`;
|
|
1425
|
+
gitExec(["stash", "--include-untracked"], projectRoot);
|
|
1426
|
+
gitExec(["fetch", "origin", baseBranch], projectRoot);
|
|
1427
|
+
let checkout = gitExec(["checkout", "-b", branchName, `origin/${baseBranch}`], projectRoot);
|
|
1428
|
+
if (!checkout.ok) {
|
|
1429
|
+
checkout = gitExec(["checkout", "-b", branchName, baseBranch], projectRoot);
|
|
1430
|
+
}
|
|
1431
|
+
if (!checkout.ok) {
|
|
1432
|
+
console.log(chalk.red(` Failed to create branch ${branchName}`));
|
|
1433
|
+
continue;
|
|
1434
|
+
}
|
|
1435
|
+
// Run the task using Pi runtime or claude CLI
|
|
1436
|
+
if (usePiRuntime && piState.bridge) {
|
|
1437
|
+
try {
|
|
1438
|
+
await runTaskWithPi(piState.bridge, proposal.task, piState.costMonitor, 300000);
|
|
1439
|
+
}
|
|
1440
|
+
catch (err) {
|
|
1441
|
+
console.log(chalk.yellow(` Pi task failed: ${err.message}`));
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
else {
|
|
1445
|
+
// Fall back to claude CLI
|
|
1446
|
+
await new Promise((resolve) => {
|
|
1447
|
+
const ralphDir = path.join(projectRoot, ".ralph-tui");
|
|
1448
|
+
if (!fs.existsSync(ralphDir))
|
|
1449
|
+
fs.mkdirSync(ralphDir, { recursive: true });
|
|
1450
|
+
const prdPath = path.join(ralphDir, "autoresearch-task.json");
|
|
1451
|
+
const prd = {
|
|
1452
|
+
name: "Autoresearch Task",
|
|
1453
|
+
branchName: `ralph/autoresearch-${Date.now()}`,
|
|
1454
|
+
description: proposal.task,
|
|
1455
|
+
userStories: [{
|
|
1456
|
+
id: "US-001",
|
|
1457
|
+
title: proposal.task.slice(0, 80),
|
|
1458
|
+
description: proposal.task,
|
|
1459
|
+
acceptanceCriteria: ["Task completed"],
|
|
1460
|
+
priority: 1, passes: false, notes: "", dependsOn: [],
|
|
1461
|
+
}],
|
|
1462
|
+
metadata: { updatedAt: new Date().toISOString() },
|
|
1463
|
+
};
|
|
1464
|
+
fs.writeFileSync(prdPath, JSON.stringify(prd, null, 2));
|
|
1465
|
+
const env = { ...process.env };
|
|
1466
|
+
delete env.CLAUDECODE;
|
|
1467
|
+
delete env.CLAUDE_CODE;
|
|
1468
|
+
const child = spawn("claude", [
|
|
1469
|
+
"--dangerously-skip-permissions",
|
|
1470
|
+
"-p", proposal.task,
|
|
1471
|
+
"--output-format", "text",
|
|
1472
|
+
], {
|
|
1473
|
+
cwd: projectRoot, stdio: "inherit", env,
|
|
1474
|
+
});
|
|
1475
|
+
child.on("error", () => { try {
|
|
1476
|
+
fs.unlinkSync(prdPath);
|
|
1477
|
+
}
|
|
1478
|
+
catch { } resolve(); });
|
|
1479
|
+
child.on("exit", () => { try {
|
|
1480
|
+
fs.unlinkSync(prdPath);
|
|
1481
|
+
}
|
|
1482
|
+
catch { } resolve(); });
|
|
1483
|
+
});
|
|
1484
|
+
}
|
|
1485
|
+
const diffCheck = gitExec(["diff", "--quiet", "HEAD"], projectRoot);
|
|
1486
|
+
const untrackedResult = spawnSync("git", ["ls-files", "--others", "--exclude-standard"], {
|
|
1487
|
+
cwd: projectRoot, encoding: "utf-8", stdio: "pipe",
|
|
1488
|
+
});
|
|
1489
|
+
const hasChanges = !diffCheck.ok || (untrackedResult.stdout || "").trim().length > 0;
|
|
1490
|
+
if (!hasChanges) {
|
|
1491
|
+
console.log(chalk.yellow(` Round ${round}: No changes, skipping eval`));
|
|
1492
|
+
gitExec(["checkout", baseBranch], projectRoot);
|
|
1493
|
+
gitExec(["branch", "-D", branchName], projectRoot);
|
|
1494
|
+
continue;
|
|
1495
|
+
}
|
|
1496
|
+
signedAgentCommit(projectRoot, `autoresearch: round ${round} - ${proposal.task}`, {
|
|
1497
|
+
agentId: "peter-parker",
|
|
1498
|
+
sessionId: `autoresearch-r${round}`,
|
|
1499
|
+
});
|
|
1500
|
+
console.log(chalk.gray(" Running local eval..."));
|
|
1501
|
+
const testResult = spawnSync("npx", ["jest", "--json", "--silent"], {
|
|
1502
|
+
cwd: projectRoot, encoding: "utf-8", stdio: "pipe", timeout: 120000,
|
|
1503
|
+
});
|
|
1504
|
+
let passing = 0, total = 1;
|
|
1505
|
+
try {
|
|
1506
|
+
const json = JSON.parse(testResult.stdout || "{}");
|
|
1507
|
+
passing = json.numPassedTests || 0;
|
|
1508
|
+
total = json.numTotalTests || 1;
|
|
1509
|
+
}
|
|
1510
|
+
catch { }
|
|
1511
|
+
const passRate = total > 0 ? passing / total : 0;
|
|
1512
|
+
const testsAdded = total - baselineTotal;
|
|
1513
|
+
const score = passRate + (testsAdded > 0 ? testsAdded * 0.001 : 0);
|
|
1514
|
+
const delta = score - baselineScore;
|
|
1515
|
+
const result = {
|
|
1516
|
+
round,
|
|
1517
|
+
task: proposal.task,
|
|
1518
|
+
score,
|
|
1519
|
+
delta,
|
|
1520
|
+
testsPassing: passing,
|
|
1521
|
+
testsTotal: total,
|
|
1522
|
+
branch: branchName,
|
|
1523
|
+
};
|
|
1524
|
+
results.push(result);
|
|
1525
|
+
const emoji = delta > 0 ? "+" : delta < 0 ? "" : "=";
|
|
1526
|
+
console.log(chalk.bold(` Round ${round} result: ${score.toFixed(4)} (${emoji}${delta.toFixed(4)})`));
|
|
1527
|
+
console.log(chalk.gray(` Tests: ${passing}/${total}${testsAdded > 0 ? chalk.green(` (+${testsAdded} new)`) : ""}`));
|
|
1528
|
+
if (!bestResult || result.delta > bestResult.delta) {
|
|
1529
|
+
bestResult = result;
|
|
1530
|
+
console.log(chalk.green(` New best! (round ${round})`));
|
|
1531
|
+
}
|
|
1532
|
+
writeJournalEntry(projectRoot, {
|
|
1533
|
+
v: 1,
|
|
1534
|
+
ts: new Date().toISOString(),
|
|
1535
|
+
session: "autoresearch",
|
|
1536
|
+
type: "experiment",
|
|
1537
|
+
status: (delta > 0 || testsAdded > 0) ? "complete" : "incomplete",
|
|
1538
|
+
title: `Autoresearch R${round}: ${proposal.task.slice(0, 60)}`,
|
|
1539
|
+
summary: `Score: ${score.toFixed(4)}, delta: ${delta > 0 ? "+" : ""}${delta.toFixed(4)}`,
|
|
1540
|
+
detail: `Task: ${proposal.task}\nResult: ${passing}/${total} tests passing`,
|
|
1541
|
+
hypothesis: `"${proposal.task}" improves composite by ~${proposal.predicted_delta.toFixed(4)}`,
|
|
1542
|
+
outcome: delta > 0 ? "confirmed" : delta < 0 ? "rejected" : "inconclusive",
|
|
1543
|
+
score_delta: delta,
|
|
1544
|
+
agent_id: "peter-parker",
|
|
1545
|
+
});
|
|
1546
|
+
const tb = new TrainingBuffer(projectRoot);
|
|
1547
|
+
tb.append({
|
|
1548
|
+
agent: "peter-parker",
|
|
1549
|
+
state: {
|
|
1550
|
+
composite_score: baselineScore,
|
|
1551
|
+
dimension_scores: evals.sort((a, b) => b.ts.localeCompare(a.ts))[0]?.metrics ?? {},
|
|
1552
|
+
tests_passing: evals.sort((a, b) => b.ts.localeCompare(a.ts))[0]?.metrics?.tests_passed ?? 0,
|
|
1553
|
+
tests_total: evals.sort((a, b) => b.ts.localeCompare(a.ts))[0]?.metrics?.tests_total ?? 1,
|
|
1554
|
+
trajectory_length: results.length,
|
|
1555
|
+
recent_deltas: results.slice(-5).map(r => r.delta),
|
|
1556
|
+
agent: "peter-parker",
|
|
1557
|
+
},
|
|
1558
|
+
action: {
|
|
1559
|
+
type: "experiment",
|
|
1560
|
+
description: proposal.task,
|
|
1561
|
+
files_affected: [],
|
|
1562
|
+
scope: "medium",
|
|
1563
|
+
branch: branchName,
|
|
1564
|
+
},
|
|
1565
|
+
reward: {
|
|
1566
|
+
composite_delta: delta,
|
|
1567
|
+
dimension_deltas: {},
|
|
1568
|
+
tests_added: testsAdded,
|
|
1569
|
+
quality_score: passRate,
|
|
1570
|
+
improved: delta > 0 || testsAdded > 0,
|
|
1571
|
+
prediction_error: Math.abs(proposal.predicted_delta - delta),
|
|
1572
|
+
},
|
|
1573
|
+
metadata: {
|
|
1574
|
+
branch: branchName,
|
|
1575
|
+
autoresearch_round: round,
|
|
1576
|
+
source: "autoresearch",
|
|
1577
|
+
},
|
|
1578
|
+
});
|
|
1579
|
+
// Update GitHub Issue — move done or revert to backlog
|
|
1580
|
+
try {
|
|
1581
|
+
const { GitHubKanban } = await import("../lib/kanban-github.js");
|
|
1582
|
+
const kb = new GitHubKanban(projectRoot);
|
|
1583
|
+
const cards = await kb.getCards({ column: "in_progress" });
|
|
1584
|
+
const ppCards = cards.filter(c => c.agent === "peter-parker");
|
|
1585
|
+
if (ppCards.length > 0) {
|
|
1586
|
+
const card = ppCards[ppCards.length - 1];
|
|
1587
|
+
if (delta > 0 || testsAdded > 0) {
|
|
1588
|
+
kb.move(card.number, "done");
|
|
1589
|
+
console.log(chalk.gray(` 📋 Issue ${card.id} → done (${score.toFixed(4)})`));
|
|
1590
|
+
}
|
|
1591
|
+
else {
|
|
1592
|
+
kb.move(card.number, "backlog");
|
|
1593
|
+
console.log(chalk.gray(` 📋 Issue ${card.id} → backlog (no improvement)`));
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
catch { }
|
|
1598
|
+
gitExec(["checkout", baseBranch], projectRoot);
|
|
1599
|
+
}
|
|
1600
|
+
console.log(chalk.bold(`\n ── Autoresearch Complete ${"─".repeat(35)}\n`));
|
|
1601
|
+
console.log(chalk.gray(` Rounds: ${rounds}`));
|
|
1602
|
+
console.log(chalk.gray(` Results:`));
|
|
1603
|
+
for (const r of results) {
|
|
1604
|
+
const emoji = r.delta > 0 ? chalk.green("+") : r.delta < 0 ? chalk.red("-") : chalk.gray("=");
|
|
1605
|
+
const best = bestResult && r.round === bestResult.round ? chalk.yellow(" ★") : "";
|
|
1606
|
+
console.log(chalk.gray(` R${r.round}: ${r.score.toFixed(4)} (${emoji}${Math.abs(r.delta).toFixed(4)}) ${r.task.slice(0, 50)}${best}`));
|
|
1607
|
+
}
|
|
1608
|
+
if (bestResult && bestResult.delta > 0) {
|
|
1609
|
+
console.log(chalk.green(`\n Winner: Round ${bestResult.round} (${bestResult.delta > 0 ? "+" : ""}${bestResult.delta.toFixed(4)})`));
|
|
1610
|
+
console.log(chalk.cyan(" Creating PR for winning experiment...\n"));
|
|
1611
|
+
gitExec(["checkout", bestResult.branch], projectRoot);
|
|
1612
|
+
const pushResult = gitExec(["push", "-u", "origin", bestResult.branch], projectRoot);
|
|
1613
|
+
if (pushResult.ok) {
|
|
1614
|
+
const prTitle = `PP autoresearch: ${bestResult.task.slice(0, 50)} (+${bestResult.delta.toFixed(4)})`;
|
|
1615
|
+
const prBody = [
|
|
1616
|
+
"## Autoresearch Winner",
|
|
1617
|
+
"",
|
|
1618
|
+
`**Task:** ${bestResult.task}`,
|
|
1619
|
+
`**Score:** ${bestResult.score.toFixed(4)} (delta: +${bestResult.delta.toFixed(4)})`,
|
|
1620
|
+
`**Tests:** ${bestResult.testsPassing}/${bestResult.testsTotal}`,
|
|
1621
|
+
`**Round:** ${bestResult.round}/${rounds}`,
|
|
1622
|
+
"",
|
|
1623
|
+
"### All Rounds",
|
|
1624
|
+
...results.map(r => `- R${r.round}: ${r.score.toFixed(4)} (${r.delta > 0 ? "+" : ""}${r.delta.toFixed(4)}) ${r.task.slice(0, 60)}${r.round === bestResult.round ? " **← winner**" : ""}`),
|
|
1625
|
+
"",
|
|
1626
|
+
"---",
|
|
1627
|
+
"*Generated by JFL autoresearch loop*",
|
|
1628
|
+
].join("\n");
|
|
1629
|
+
let prResult = ghExec([
|
|
1630
|
+
"pr", "create", "--title", prTitle, "--body", prBody,
|
|
1631
|
+
"--base", baseBranch, "--head", bestResult.branch, "--label", "pp-generated",
|
|
1632
|
+
], projectRoot);
|
|
1633
|
+
if (!prResult.ok) {
|
|
1634
|
+
prResult = ghExec([
|
|
1635
|
+
"pr", "create", "--title", prTitle, "--body", prBody,
|
|
1636
|
+
"--base", baseBranch, "--head", bestResult.branch,
|
|
1637
|
+
], projectRoot);
|
|
1638
|
+
}
|
|
1639
|
+
if (prResult.ok) {
|
|
1640
|
+
console.log(chalk.green(` PR created: ${prResult.output}`));
|
|
1641
|
+
await postHubEvent(projectRoot, "autoresearch:complete", {
|
|
1642
|
+
rounds,
|
|
1643
|
+
winner_round: bestResult.round,
|
|
1644
|
+
winner_task: bestResult.task,
|
|
1645
|
+
winner_delta: bestResult.delta,
|
|
1646
|
+
pr_url: prResult.output,
|
|
1647
|
+
all_results: results.map(r => ({
|
|
1648
|
+
round: r.round, task: r.task, score: r.score, delta: r.delta,
|
|
1649
|
+
})),
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
else {
|
|
1653
|
+
console.log(chalk.red(` Failed to create PR: ${prResult.output}`));
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
else {
|
|
1657
|
+
console.log(chalk.red(` Failed to push: ${pushResult.output}`));
|
|
1658
|
+
}
|
|
1659
|
+
gitExec(["checkout", baseBranch], projectRoot);
|
|
1660
|
+
}
|
|
1661
|
+
else {
|
|
1662
|
+
console.log(chalk.yellow("\n No improvement found across all rounds."));
|
|
1663
|
+
console.log(chalk.gray(" All experiment branches preserved for review.\n"));
|
|
1664
|
+
}
|
|
1665
|
+
for (const r of results) {
|
|
1666
|
+
if (!bestResult || r.round !== bestResult.round) {
|
|
1667
|
+
gitExec(["branch", "-D", r.branch], projectRoot);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
gitExec(["stash", "pop"], projectRoot);
|
|
1671
|
+
// Shutdown Pi runtime
|
|
1672
|
+
if (piState.bridge || piState.eventRouter) {
|
|
1673
|
+
console.log(chalk.gray(" Shutting down Pi runtime..."));
|
|
1674
|
+
await shutdownPiRuntime(piState);
|
|
1675
|
+
if (piState.costMonitor) {
|
|
1676
|
+
console.log(chalk.gray(` Total cost: $${piState.costMonitor.totalCost.toFixed(4)}`));
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
console.log();
|
|
1680
|
+
}
|
|
1681
|
+
// ============================================================================
|
|
1682
|
+
// Scoped Agent Commands
|
|
1683
|
+
// ============================================================================
|
|
1684
|
+
async function agentCreate(projectRoot) {
|
|
1685
|
+
const { writeAgentConfig, generateAgentToml } = await import("../lib/agent-config.js");
|
|
1686
|
+
const readline = await import("readline");
|
|
1687
|
+
const rl = readline.createInterface({
|
|
1688
|
+
input: process.stdin,
|
|
1689
|
+
output: process.stdout,
|
|
1690
|
+
});
|
|
1691
|
+
const ask = (q) => new Promise(resolve => rl.question(q, resolve));
|
|
1692
|
+
console.log(chalk.bold("\n Create Scoped Agent\n"));
|
|
1693
|
+
const name = await ask(" Agent name (e.g., search-quality): ");
|
|
1694
|
+
const scope = await ask(" Scope (e.g., search, tests, quality): ");
|
|
1695
|
+
const metric = await ask(" Metric (e.g., ndcg@10, test_pass_rate): ");
|
|
1696
|
+
const direction = await ask(" Direction (maximize/minimize) [maximize]: ") || "maximize";
|
|
1697
|
+
const timeBudget = await ask(" Time budget seconds [300]: ") || "300";
|
|
1698
|
+
const evalScript = await ask(" Eval script path [eval/eval.ts]: ") || "eval/eval.ts";
|
|
1699
|
+
const evalData = await ask(" Eval data path [eval/fixtures/data.jsonl]: ") || "eval/fixtures/data.jsonl";
|
|
1700
|
+
const filesInScope = await ask(" Files in scope (glob, comma-sep) [src/**]: ") || "src/**";
|
|
1701
|
+
rl.close();
|
|
1702
|
+
const configPath = writeAgentConfig(projectRoot, {
|
|
1703
|
+
name,
|
|
1704
|
+
scope,
|
|
1705
|
+
metric,
|
|
1706
|
+
direction: direction,
|
|
1707
|
+
time_budget_seconds: parseInt(timeBudget, 10),
|
|
1708
|
+
eval: {
|
|
1709
|
+
script: evalScript,
|
|
1710
|
+
data: evalData,
|
|
1711
|
+
},
|
|
1712
|
+
constraints: {
|
|
1713
|
+
files_in_scope: filesInScope.split(",").map(s => s.trim()),
|
|
1714
|
+
files_readonly: ["eval/**"],
|
|
1715
|
+
max_file_changes: 10,
|
|
1716
|
+
},
|
|
1717
|
+
policy: {
|
|
1718
|
+
embedding_model: "stratus-x1ac-base-claude-sonnet-4-6",
|
|
1719
|
+
exploration_rate: 0.2,
|
|
1720
|
+
decay_per_round: 0.01,
|
|
1721
|
+
min_exploration: 0.05,
|
|
1722
|
+
},
|
|
1723
|
+
});
|
|
1724
|
+
console.log(chalk.green(`\n Agent config created: ${configPath}\n`));
|
|
1725
|
+
}
|
|
1726
|
+
async function agentList(projectRoot) {
|
|
1727
|
+
const { listAgentConfigs, loadAgentConfig } = await import("../lib/agent-config.js");
|
|
1728
|
+
const agents = listAgentConfigs(projectRoot);
|
|
1729
|
+
if (agents.length === 0) {
|
|
1730
|
+
console.log(chalk.yellow("\n No agents configured."));
|
|
1731
|
+
console.log(chalk.gray(" Run: jfl peter agent create\n"));
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
console.log(chalk.bold("\n Configured Agents\n"));
|
|
1735
|
+
for (const name of agents) {
|
|
1736
|
+
try {
|
|
1737
|
+
const config = loadAgentConfig(projectRoot, name);
|
|
1738
|
+
console.log(chalk.cyan(` ${name}`));
|
|
1739
|
+
console.log(chalk.gray(` Scope: ${config.scope}`));
|
|
1740
|
+
console.log(chalk.gray(` Metric: ${config.metric} (${config.direction})`));
|
|
1741
|
+
console.log(chalk.gray(` Time budget: ${config.time_budget_seconds}s`));
|
|
1742
|
+
console.log(chalk.gray(` Files: ${config.constraints.files_in_scope.join(", ")}`));
|
|
1743
|
+
console.log();
|
|
1744
|
+
}
|
|
1745
|
+
catch (err) {
|
|
1746
|
+
console.log(chalk.red(` ${name}: Error loading config - ${err.message}`));
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
async function agentRun(projectRoot, agentName, roundsOverride) {
|
|
1751
|
+
const { loadAgentConfig, validateAgentConfig } = await import("../lib/agent-config.js");
|
|
1752
|
+
const { startSession, runBaseline, runRound, endSession, saveSessionState, writeExperimentHistory } = await import("../lib/agent-session.js");
|
|
1753
|
+
const { ReplayBuffer } = await import("../lib/replay-buffer.js");
|
|
1754
|
+
const { StratusClient } = await import("../lib/stratus-client.js");
|
|
1755
|
+
// Load and validate config
|
|
1756
|
+
let config;
|
|
1757
|
+
try {
|
|
1758
|
+
config = loadAgentConfig(projectRoot, agentName);
|
|
1759
|
+
}
|
|
1760
|
+
catch (err) {
|
|
1761
|
+
console.log(chalk.red(`\n Agent not found: ${agentName}`));
|
|
1762
|
+
console.log(chalk.gray(" Run: jfl peter agent list\n"));
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
const validation = validateAgentConfig(config, projectRoot);
|
|
1766
|
+
if (!validation.valid) {
|
|
1767
|
+
console.log(chalk.red(`\n Invalid agent config:`));
|
|
1768
|
+
for (const err of validation.errors) {
|
|
1769
|
+
console.log(chalk.red(` - ${err}`));
|
|
1770
|
+
}
|
|
1771
|
+
console.log();
|
|
1772
|
+
return;
|
|
1773
|
+
}
|
|
1774
|
+
// Pre-flight guards — verify environment before starting session
|
|
1775
|
+
const { runGuards } = await import("../lib/agent-guards.js");
|
|
1776
|
+
const guardSummary = await runGuards(projectRoot, agentName, config);
|
|
1777
|
+
// Log guard results
|
|
1778
|
+
for (const result of guardSummary.results) {
|
|
1779
|
+
if (result.passed) {
|
|
1780
|
+
console.log(chalk.green(` ✓ Guard: ${result.name}`));
|
|
1781
|
+
}
|
|
1782
|
+
else if (result.critical) {
|
|
1783
|
+
console.log(chalk.red(` ✗ Guard: ${result.name} — ${result.reason}`));
|
|
1784
|
+
}
|
|
1785
|
+
else {
|
|
1786
|
+
console.log(chalk.yellow(` ⚠ Guard: ${result.name} — ${result.reason}`));
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
if (!guardSummary.proceed) {
|
|
1790
|
+
console.log(chalk.red(`\n Blocked by ${guardSummary.blockers.length} critical guard(s). Fix the issues above and retry.\n`));
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
if (guardSummary.warnings.length > 0) {
|
|
1794
|
+
console.log(chalk.yellow(`\n ${guardSummary.warnings.length} warning(s) — proceeding anyway.\n`));
|
|
1795
|
+
}
|
|
1796
|
+
else {
|
|
1797
|
+
console.log();
|
|
1798
|
+
}
|
|
1799
|
+
// Use config.rounds as default (Karpathy: ~50 experiments per session)
|
|
1800
|
+
// Allow override via CLI for debugging/testing
|
|
1801
|
+
const rounds = roundsOverride ?? config.rounds ?? 50;
|
|
1802
|
+
// Get scope_files for display
|
|
1803
|
+
const rawScopeFiles = config.constraints.scope_files || config.constraints.files_in_scope || [];
|
|
1804
|
+
const displayScopeFiles = Array.isArray(rawScopeFiles) ? rawScopeFiles : [String(rawScopeFiles)];
|
|
1805
|
+
const scopeFilesDisplay = displayScopeFiles.slice(0, 3).join(", ") + (displayScopeFiles.length > 3 ? "..." : "");
|
|
1806
|
+
console.log(chalk.bold(`\n Running Scoped Agent: ${agentName} (${rounds} rounds)\n`));
|
|
1807
|
+
console.log(chalk.gray(` Metric: ${config.metric} (${config.direction})`));
|
|
1808
|
+
console.log(chalk.gray(` Time budget: ${config.time_budget_seconds}s per round`));
|
|
1809
|
+
console.log(chalk.gray(` Focus files: ${scopeFilesDisplay}`));
|
|
1810
|
+
console.log(chalk.gray(` Pattern: branch → change → eval → keep|revert → repeat\n`));
|
|
1811
|
+
// Start session
|
|
1812
|
+
const session = startSession(config, projectRoot);
|
|
1813
|
+
saveSessionState(session);
|
|
1814
|
+
console.log(chalk.cyan(` Session: ${session.id}`));
|
|
1815
|
+
console.log(chalk.cyan(` Branch: ${session.branch}`));
|
|
1816
|
+
console.log(chalk.gray(` Eval snapshot: ${session.evalSnapshot.hash.slice(0, 8)}\n`));
|
|
1817
|
+
// Run baseline
|
|
1818
|
+
console.log(chalk.gray(" Running baseline eval..."));
|
|
1819
|
+
let baseline;
|
|
1820
|
+
try {
|
|
1821
|
+
baseline = await runBaseline(session);
|
|
1822
|
+
}
|
|
1823
|
+
catch (err) {
|
|
1824
|
+
console.log(chalk.red(` Baseline eval failed: ${err.message}`));
|
|
1825
|
+
return;
|
|
1826
|
+
}
|
|
1827
|
+
console.log(chalk.green(` Baseline: ${baseline.toFixed(4)}\n`));
|
|
1828
|
+
const replayBuffer = new ReplayBuffer(projectRoot);
|
|
1829
|
+
const transitions = [];
|
|
1830
|
+
// Stratus for task generation
|
|
1831
|
+
const stratus = process.env.STRATUS_API_KEY
|
|
1832
|
+
? new StratusClient({ apiKey: process.env.STRATUS_API_KEY })
|
|
1833
|
+
: null;
|
|
1834
|
+
// Get scope_files from config (Karpathy pattern: focused file list)
|
|
1835
|
+
const rawScope = config.constraints.scope_files || config.constraints.files_in_scope || [];
|
|
1836
|
+
const scopeFiles = Array.isArray(rawScope) ? rawScope : [String(rawScope)];
|
|
1837
|
+
const scopeFilesStr = scopeFiles.slice(0, 5).join(", ");
|
|
1838
|
+
// ── Build rich context for agent (autoresearch pattern: read before write) ──
|
|
1839
|
+
// 1. Read scope files from worktree so agent knows what code it's modifying
|
|
1840
|
+
let codeContext = "";
|
|
1841
|
+
for (const scopeFile of scopeFiles.slice(0, 4)) {
|
|
1842
|
+
const filePath = path.join(session.worktreePath, scopeFile);
|
|
1843
|
+
if (fs.existsSync(filePath)) {
|
|
1844
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
1845
|
+
const lines = content.split("\n").slice(0, 150); // First 150 lines
|
|
1846
|
+
codeContext += `\n--- ${scopeFile} (first ${lines.length} lines) ---\n${lines.join("\n")}\n`;
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
// 2. Parse eval diagnostics from baseline run (which queries fail, what scores broke down)
|
|
1850
|
+
let evalDiagnostics = "";
|
|
1851
|
+
const rawEvalOutput = session.lastEvalOutput || "";
|
|
1852
|
+
if (rawEvalOutput) {
|
|
1853
|
+
try {
|
|
1854
|
+
const evalJson = JSON.parse(rawEvalOutput);
|
|
1855
|
+
// Extract failing queries/tests/dimensions for the agent to focus on
|
|
1856
|
+
if (evalJson.failed_queries) {
|
|
1857
|
+
evalDiagnostics = `\n\nFAILING QUERIES (fix these to improve the metric):\n${evalJson.failed_queries.map((q) => ` ✗ ${q}`).join("\n")}`;
|
|
1858
|
+
}
|
|
1859
|
+
if (evalJson.per_query) {
|
|
1860
|
+
const failing = evalJson.per_query.filter((q) => q.hits < q.expected);
|
|
1861
|
+
if (failing.length > 0) {
|
|
1862
|
+
evalDiagnostics += `\n\nDETAILED FAILURES:\n${failing.slice(0, 5).map((q) => ` Query: "${q.query}" — got ${q.hits}/${q.expected} hits. Found IDs: [${(q.found || []).join(",")}]`).join("\n")}`;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
// Generic: show any dimension breakdowns (easy/medium/hard, per-category scores)
|
|
1866
|
+
const dimKeys = Object.keys(evalJson).filter(k => k.endsWith("_recall") || k.endsWith("_score") || k.endsWith("_pct") || k.endsWith("_count"));
|
|
1867
|
+
if (dimKeys.length > 0) {
|
|
1868
|
+
evalDiagnostics += `\n\nMETRIC BREAKDOWN:\n${dimKeys.map(k => ` ${k}: ${evalJson[k]}`).join("\n")}`;
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
catch {
|
|
1872
|
+
// Not JSON — include raw stderr/stdout hints
|
|
1873
|
+
const lines = rawEvalOutput.split("\n").filter((l) => l.includes("✗") || l.includes("fail") || l.includes("error") || l.includes("FAIL"));
|
|
1874
|
+
if (lines.length > 0) {
|
|
1875
|
+
evalDiagnostics = `\n\nEVAL DIAGNOSTICS:\n${lines.slice(0, 10).join("\n")}`;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
for (let round = 1; round <= rounds; round++) {
|
|
1880
|
+
console.log(chalk.bold(`\n ── Round ${round}/${rounds} ${"─".repeat(40)}\n`));
|
|
1881
|
+
// Generate task — use TOML [task] description if present, otherwise default RL task
|
|
1882
|
+
let task;
|
|
1883
|
+
if (config.task?.description) {
|
|
1884
|
+
// Build agent — use spec task, prepend action-oriented instruction
|
|
1885
|
+
task = `BUILD TASK — Create the files described below. Write code immediately. Do NOT spend turns exploring — the eval diagnostics tell you exactly what's missing.
|
|
1886
|
+
|
|
1887
|
+
FAILED CHECKS (from eval):
|
|
1888
|
+
${evalDiagnostics || 'Run eval to see what is missing.'}
|
|
1889
|
+
|
|
1890
|
+
YOUR TASK:
|
|
1891
|
+
${config.task.description}
|
|
1892
|
+
|
|
1893
|
+
IMPORTANT: Use write_file to create complete files. Every failed check above is something you need to fix. Start writing code NOW.`;
|
|
1894
|
+
}
|
|
1895
|
+
else {
|
|
1896
|
+
task = `Improve ${config.metric} by modifying: ${scopeFilesStr}. Read the code context and eval diagnostics below. Make ONE small, focused change to the actual source files.${evalDiagnostics}`;
|
|
1897
|
+
}
|
|
1898
|
+
// Build history context from replay buffer + current session transitions
|
|
1899
|
+
const pastTuples = replayBuffer.getForAgent(config.name).slice(-20); // Last 20 tuples
|
|
1900
|
+
const keptExperiments = [];
|
|
1901
|
+
const rejectedExperiments = [];
|
|
1902
|
+
// From replay buffer (past sessions)
|
|
1903
|
+
for (const t of pastTuples) {
|
|
1904
|
+
const action = t.action?.description || "unknown";
|
|
1905
|
+
const reward = t.reward ?? 0;
|
|
1906
|
+
if (reward > 0) {
|
|
1907
|
+
keptExperiments.push(`"${action.slice(0, 50)}" (+${reward.toFixed(4)})`);
|
|
1908
|
+
}
|
|
1909
|
+
else {
|
|
1910
|
+
rejectedExperiments.push(`"${action.slice(0, 50)}"`);
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
// From current session transitions
|
|
1914
|
+
for (const t of transitions) {
|
|
1915
|
+
const action = t.action?.description || "unknown";
|
|
1916
|
+
const reward = t.reward ?? 0;
|
|
1917
|
+
if (reward > 0) {
|
|
1918
|
+
keptExperiments.push(`"${action.slice(0, 50)}" (+${reward.toFixed(4)})`);
|
|
1919
|
+
}
|
|
1920
|
+
else {
|
|
1921
|
+
rejectedExperiments.push(`"${action.slice(0, 50)}"`);
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
let historyContext = "";
|
|
1925
|
+
if (keptExperiments.length > 0 || rejectedExperiments.length > 0) {
|
|
1926
|
+
historyContext = `
|
|
1927
|
+
|
|
1928
|
+
Experiment history for ${config.name}:
|
|
1929
|
+
KEPT (these worked — build on them): ${keptExperiments.slice(-5).join(", ") || "none yet"}
|
|
1930
|
+
REJECTED (do NOT repeat these): ${rejectedExperiments.slice(-5).join(", ") || "none yet"}
|
|
1931
|
+
|
|
1932
|
+
CRITICAL: Do NOT repeat rejected experiments. Try something NEW and DIFFERENT.`;
|
|
1933
|
+
}
|
|
1934
|
+
// Read product context (Layer 2) if available
|
|
1935
|
+
let productContext = "";
|
|
1936
|
+
const productContextPath = path.join(projectRoot, ".jfl", "product-context.md");
|
|
1937
|
+
if (fs.existsSync(productContextPath)) {
|
|
1938
|
+
const pc = fs.readFileSync(productContextPath, "utf-8");
|
|
1939
|
+
// Extract agent-specific guidance if present
|
|
1940
|
+
const agentSection = pc.match(new RegExp(`${config.name}[:\\s].*?(?=\\n[A-Z#]|$)`, "s"));
|
|
1941
|
+
productContext = agentSection
|
|
1942
|
+
? `\n\nProduct context for this agent:\n${agentSection[0].slice(0, 500)}`
|
|
1943
|
+
: `\n\nProduct context (summary):\n${pc.slice(0, 500)}`;
|
|
1944
|
+
}
|
|
1945
|
+
if (stratus) {
|
|
1946
|
+
try {
|
|
1947
|
+
// Enhanced prompt with full context: eval failures + code + history
|
|
1948
|
+
const prompt = `Suggest ONE specific code change to improve the ${config.metric} metric (${config.direction}).
|
|
1949
|
+
|
|
1950
|
+
FOCUS FILES (modify only these): ${scopeFilesStr}
|
|
1951
|
+
CURRENT METRIC: ${session.baselineMetric.toFixed(4)}
|
|
1952
|
+
ROUND: ${round}/${rounds}
|
|
1953
|
+
${evalDiagnostics}
|
|
1954
|
+
${historyContext}${productContext}
|
|
1955
|
+
|
|
1956
|
+
CODE CONTEXT (first 150 lines of each scope file):
|
|
1957
|
+
${codeContext.slice(0, 3000)}
|
|
1958
|
+
|
|
1959
|
+
Based on the failing queries/tests and the actual code, suggest ONE concrete change. Be specific about which function to modify and how. Return just the task description (2-3 sentences).`;
|
|
1960
|
+
const response = await stratus.reason(prompt, { maxTokens: 300, temperature: 0.5 + round * 0.05 });
|
|
1961
|
+
task = response.choices[0]?.message?.content || task;
|
|
1962
|
+
}
|
|
1963
|
+
catch {
|
|
1964
|
+
// Stratus failed — use the eval-diagnostics-enriched default task (still much better than before)
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
const hypothesis = `Implementing this will improve ${config.metric}`;
|
|
1968
|
+
console.log(chalk.cyan(` Task: ${task.slice(0, 80)}...`));
|
|
1969
|
+
// Pass transitions to runRound so it can build experiment history (Karpathy pattern)
|
|
1970
|
+
const { result, transition } = await runRound(session, round, task, hypothesis, transitions);
|
|
1971
|
+
transitions.push(transition);
|
|
1972
|
+
// Write to replay buffer
|
|
1973
|
+
replayBuffer.write({
|
|
1974
|
+
agent: config.name,
|
|
1975
|
+
session_id: session.id,
|
|
1976
|
+
state_hash: transition.state_hash,
|
|
1977
|
+
state: transition.state,
|
|
1978
|
+
action_diff: transition.action_diff,
|
|
1979
|
+
action: transition.action,
|
|
1980
|
+
hypothesis,
|
|
1981
|
+
reward: result.delta,
|
|
1982
|
+
timestamp: new Date().toISOString(),
|
|
1983
|
+
});
|
|
1984
|
+
const emoji = result.kept ? chalk.green("✓") : chalk.red("✗");
|
|
1985
|
+
const deltaStr = result.delta > 0 ? `+${result.delta.toFixed(4)}` : result.delta.toFixed(4);
|
|
1986
|
+
console.log(` ${emoji} Result: ${result.metricAfter.toFixed(4)} (${deltaStr}) ${result.kept ? "KEPT" : "REVERTED"}`);
|
|
1987
|
+
// Build supervisor: detect patterns, inject hints for next round
|
|
1988
|
+
if (config.scope === "build") {
|
|
1989
|
+
try {
|
|
1990
|
+
const { checkRound, logLearning } = await import("../lib/build-supervisor.js");
|
|
1991
|
+
// Build round history from transitions
|
|
1992
|
+
let runningScore = session.baselineMetric;
|
|
1993
|
+
const roundHistory = transitions.map((t, i) => {
|
|
1994
|
+
const scoreBefore = runningScore;
|
|
1995
|
+
const delta = t.reward ?? 0;
|
|
1996
|
+
const kept = delta > 0;
|
|
1997
|
+
if (kept)
|
|
1998
|
+
runningScore += delta;
|
|
1999
|
+
return {
|
|
2000
|
+
agent: config.name,
|
|
2001
|
+
round: i + 1,
|
|
2002
|
+
scoreBefore,
|
|
2003
|
+
scoreAfter: kept ? scoreBefore + delta : scoreBefore,
|
|
2004
|
+
delta,
|
|
2005
|
+
kept,
|
|
2006
|
+
filesCreated: [], // TODO: parse from transition
|
|
2007
|
+
failedChecks: session.lastEvalOutput ?
|
|
2008
|
+
JSON.parse(session.lastEvalOutput)?.failed_checks || [] : [],
|
|
2009
|
+
};
|
|
2010
|
+
});
|
|
2011
|
+
const hint = checkRound(roundHistory);
|
|
2012
|
+
if (hint) {
|
|
2013
|
+
console.log(chalk.yellow(` 🔍 Supervisor: ${hint.slice(0, 120)}...`));
|
|
2014
|
+
// Inject into EXPERIMENTS.md for next round
|
|
2015
|
+
const { appendFileSync: appendFs } = await import("fs");
|
|
2016
|
+
const expPath = path.join(session.worktreePath, "EXPERIMENTS.md");
|
|
2017
|
+
appendFs(expPath, `\n\n## Supervisor Hint (after round ${round})\n${hint}\n`);
|
|
2018
|
+
// Log the learning (supervisor's teacup memory)
|
|
2019
|
+
logLearning(projectRoot, {
|
|
2020
|
+
ts: new Date().toISOString(),
|
|
2021
|
+
agent: config.name,
|
|
2022
|
+
pattern: hint.split(":")[0] || "unknown",
|
|
2023
|
+
resolution: "hint injected, awaiting next round",
|
|
2024
|
+
failedChecks: roundHistory[roundHistory.length - 1]?.failedChecks || [],
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
catch { /* supervisor not built yet — graceful degradation */ }
|
|
2029
|
+
}
|
|
2030
|
+
// Build journal: one line per round to .jfl/build-journal.jsonl
|
|
2031
|
+
if (config.scope === "build") {
|
|
2032
|
+
try {
|
|
2033
|
+
const { appendFileSync } = await import("fs");
|
|
2034
|
+
const journalPath = path.join(projectRoot, ".jfl", "build-journal.jsonl");
|
|
2035
|
+
appendFileSync(journalPath, JSON.stringify({
|
|
2036
|
+
type: "build:round",
|
|
2037
|
+
agent: config.name,
|
|
2038
|
+
round,
|
|
2039
|
+
score: result.metricAfter,
|
|
2040
|
+
delta: result.delta,
|
|
2041
|
+
kept: result.kept,
|
|
2042
|
+
ts: new Date().toISOString(),
|
|
2043
|
+
}) + "\n");
|
|
2044
|
+
}
|
|
2045
|
+
catch { /* journal write failed — not critical */ }
|
|
2046
|
+
}
|
|
2047
|
+
// Early termination for build agents at 1.0
|
|
2048
|
+
if (config.scope === "build" && result.metricAfter >= 1.0) {
|
|
2049
|
+
console.log(chalk.green(` ✅ Score hit 1.0 — stopping early`));
|
|
2050
|
+
break;
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
// End session
|
|
2054
|
+
const summary = await endSession(session, transitions);
|
|
2055
|
+
// Post eval:scored to hub event bus — triggers auto-merge, flag-regression, training flows
|
|
2056
|
+
await postHubEvent(projectRoot, "eval:scored", {
|
|
2057
|
+
agent: agentName,
|
|
2058
|
+
metric: config.metric,
|
|
2059
|
+
baseline: (summary.baseline).toFixed(4),
|
|
2060
|
+
composite: (summary.finalMetric).toFixed(4),
|
|
2061
|
+
delta: summary.totalDelta.toFixed(4),
|
|
2062
|
+
improved: String(summary.improvedRounds > 0),
|
|
2063
|
+
rounds: summary.rounds,
|
|
2064
|
+
kept: summary.improvedRounds,
|
|
2065
|
+
branch: session.branch,
|
|
2066
|
+
pr_number: summary.prUrl ? summary.prUrl.split("/").pop() : "",
|
|
2067
|
+
});
|
|
2068
|
+
console.log(chalk.bold(`\n ── Session Complete ${"─".repeat(35)}\n`));
|
|
2069
|
+
console.log(chalk.gray(` Rounds: ${summary.rounds}`));
|
|
2070
|
+
console.log(chalk.gray(` Improved: ${summary.improvedRounds}`));
|
|
2071
|
+
console.log(chalk.gray(` Total delta: ${summary.totalDelta > 0 ? "+" : ""}${summary.totalDelta.toFixed(4)}`));
|
|
2072
|
+
console.log(chalk.gray(` Best delta: +${summary.bestDelta.toFixed(4)}`));
|
|
2073
|
+
if (summary.branchUrl) {
|
|
2074
|
+
console.log(chalk.green(`\n Branch pushed for review: ${summary.branchUrl}`));
|
|
2075
|
+
}
|
|
2076
|
+
if (summary.prUrl) {
|
|
2077
|
+
console.log(chalk.green(` PR: ${summary.prUrl}`));
|
|
2078
|
+
}
|
|
2079
|
+
console.log();
|
|
2080
|
+
}
|
|
2081
|
+
// ============================================================================
|
|
2082
|
+
// Telemetry Agent V2 Commands
|
|
2083
|
+
// ============================================================================
|
|
2084
|
+
async function runTelemetryAgent(projectRoot) {
|
|
2085
|
+
const { TelemetryAgentV2 } = await import("../lib/telemetry-agent-v2.js");
|
|
2086
|
+
console.log(chalk.bold("\n Telemetry Agent V2 - Platform Digest Analysis\n"));
|
|
2087
|
+
const agent = new TelemetryAgentV2({
|
|
2088
|
+
projectRoot,
|
|
2089
|
+
emitEvent: (type, data) => {
|
|
2090
|
+
console.log(chalk.gray(` [EVENT] ${type}`));
|
|
2091
|
+
},
|
|
2092
|
+
});
|
|
2093
|
+
console.log(chalk.gray(" Fetching platform digest..."));
|
|
2094
|
+
const result = await agent.run();
|
|
2095
|
+
if (!result.digest24h) {
|
|
2096
|
+
console.log(chalk.yellow("\n Could not fetch platform digest."));
|
|
2097
|
+
console.log(chalk.gray(" Check JFL_PLATFORM_URL and network connectivity.\n"));
|
|
2098
|
+
return;
|
|
2099
|
+
}
|
|
2100
|
+
console.log(chalk.green(`\n Digest fetched for ${result.digest24h.periodHours}h period\n`));
|
|
2101
|
+
// Show metrics
|
|
2102
|
+
if (result.metrics) {
|
|
2103
|
+
console.log(chalk.bold(" Current Metrics:"));
|
|
2104
|
+
console.log(chalk.gray(` Command Success Rate: ${(result.metrics.command_success_rate * 100).toFixed(1)}%`));
|
|
2105
|
+
console.log(chalk.gray(` Command P90 Latency: ${result.metrics.command_p90_latency_ms}ms`));
|
|
2106
|
+
console.log(chalk.gray(` Session Crash Rate: ${(result.metrics.session_crash_rate * 100).toFixed(2)}%`));
|
|
2107
|
+
console.log(chalk.gray(` Hub Crash Rate: ${(result.metrics.hub_crash_rate * 100).toFixed(2)}%`));
|
|
2108
|
+
console.log(chalk.gray(` Flow Completion Rate: ${(result.metrics.flow_completion_rate * 100).toFixed(1)}%`));
|
|
2109
|
+
console.log(chalk.gray(` Cost Per Session: $${result.metrics.cost_per_session_usd.toFixed(4)}`));
|
|
2110
|
+
console.log(chalk.gray(` Active Installs: ${result.metrics.active_installs}`));
|
|
2111
|
+
console.log(chalk.gray(` Error Clusters: ${result.metrics.error_cluster_count}`));
|
|
2112
|
+
console.log();
|
|
2113
|
+
}
|
|
2114
|
+
// Show alerts
|
|
2115
|
+
if (result.alerts.length > 0) {
|
|
2116
|
+
console.log(chalk.bold(chalk.red(" Alerts:")));
|
|
2117
|
+
for (const alert of result.alerts) {
|
|
2118
|
+
console.log(chalk.red(` ⚠ ${alert.name}: ${alert.percentChange.toFixed(1)}% decline`));
|
|
2119
|
+
console.log(chalk.gray(` ${alert.previous.toFixed(4)} → ${alert.current.toFixed(4)}`));
|
|
2120
|
+
}
|
|
2121
|
+
console.log();
|
|
2122
|
+
}
|
|
2123
|
+
// Show wins
|
|
2124
|
+
if (result.wins.length > 0) {
|
|
2125
|
+
console.log(chalk.bold(chalk.green(" Wins:")));
|
|
2126
|
+
for (const win of result.wins) {
|
|
2127
|
+
console.log(chalk.green(` ✓ ${win.name}: ${win.percentChange.toFixed(1)}% improvement`));
|
|
2128
|
+
console.log(chalk.gray(` ${win.previous.toFixed(4)} → ${win.current.toFixed(4)}`));
|
|
2129
|
+
}
|
|
2130
|
+
console.log();
|
|
2131
|
+
}
|
|
2132
|
+
// Show proposed agents
|
|
2133
|
+
if (result.proposedAgents.length > 0) {
|
|
2134
|
+
console.log(chalk.bold(" Proposed Agents:"));
|
|
2135
|
+
for (const agent of result.proposedAgents) {
|
|
2136
|
+
const priority = agent.priority === "high" ? chalk.red(agent.priority) :
|
|
2137
|
+
agent.priority === "medium" ? chalk.yellow(agent.priority) :
|
|
2138
|
+
chalk.gray(agent.priority);
|
|
2139
|
+
console.log(chalk.cyan(` ${agent.name} [${priority}]`));
|
|
2140
|
+
console.log(chalk.gray(` ${agent.reason}`));
|
|
2141
|
+
}
|
|
2142
|
+
console.log(chalk.gray(`\n Agent configs written to .jfl/agents/proposed/\n`));
|
|
2143
|
+
}
|
|
2144
|
+
// Show status
|
|
2145
|
+
const status = agent.getStatus();
|
|
2146
|
+
console.log(chalk.gray(` Run #${status.runCount}`));
|
|
2147
|
+
console.log(chalk.gray(` Training tuples generated: ${status.totalTrainingTuples}`));
|
|
2148
|
+
console.log();
|
|
2149
|
+
}
|
|
2150
|
+
async function runSentinelReview(projectRoot) {
|
|
2151
|
+
const { SentinelRL } = await import("../lib/sentinel-rl.js");
|
|
2152
|
+
console.log(chalk.bold("\n Sentinel - Nightly System Review\n"));
|
|
2153
|
+
const sentinel = new SentinelRL({
|
|
2154
|
+
projectRoot,
|
|
2155
|
+
emitEvent: (type, data) => {
|
|
2156
|
+
console.log(chalk.gray(` [EVENT] ${type}`));
|
|
2157
|
+
},
|
|
2158
|
+
});
|
|
2159
|
+
console.log(chalk.gray(" Collecting inputs..."));
|
|
2160
|
+
const { scores, recommendations, inputs } = await sentinel.run();
|
|
2161
|
+
// Show scores
|
|
2162
|
+
console.log(chalk.bold("\n System Scores:"));
|
|
2163
|
+
console.log(chalk.gray(` Product Health: ${(scores.productHealth * 100).toFixed(0)}% ${scoreEmoji(scores.productHealth)}`));
|
|
2164
|
+
console.log(chalk.gray(` Development Velocity: ${(scores.developmentVelocity * 100).toFixed(0)}% ${scoreEmoji(scores.developmentVelocity)}`));
|
|
2165
|
+
console.log(chalk.gray(` Agent Effectiveness: ${(scores.agentEffectiveness * 100).toFixed(0)}% ${scoreEmoji(scores.agentEffectiveness)}`));
|
|
2166
|
+
console.log(chalk.gray(` Data Quality: ${(scores.dataQuality * 100).toFixed(0)}% ${scoreEmoji(scores.dataQuality)}`));
|
|
2167
|
+
console.log(chalk.bold(` Composite: ${(scores.composite * 100).toFixed(0)}% ${scoreEmoji(scores.composite)}`));
|
|
2168
|
+
console.log();
|
|
2169
|
+
// Show recommendations
|
|
2170
|
+
if (recommendations.length > 0) {
|
|
2171
|
+
console.log(chalk.bold(" Recommendations:"));
|
|
2172
|
+
for (const rec of recommendations) {
|
|
2173
|
+
const priority = rec.priority === "high" ? chalk.red(`[${rec.priority}]`) :
|
|
2174
|
+
rec.priority === "medium" ? chalk.yellow(`[${rec.priority}]`) :
|
|
2175
|
+
chalk.gray(`[${rec.priority}]`);
|
|
2176
|
+
console.log(` ${priority} ${rec.description}`);
|
|
2177
|
+
console.log(chalk.gray(` ${rec.reason}`));
|
|
2178
|
+
}
|
|
2179
|
+
console.log();
|
|
2180
|
+
}
|
|
2181
|
+
else {
|
|
2182
|
+
console.log(chalk.green(" No recommendations at this time.\n"));
|
|
2183
|
+
}
|
|
2184
|
+
// Show data summary
|
|
2185
|
+
console.log(chalk.gray(` Journal entries analyzed: ${inputs.journalEntries.length}`));
|
|
2186
|
+
console.log(chalk.gray(` Eval entries analyzed: ${inputs.evalHistory.length}`));
|
|
2187
|
+
console.log(chalk.gray(` PR reviews analyzed: ${inputs.prReviews.length}`));
|
|
2188
|
+
console.log(chalk.gray(` Training tuples: ${inputs.trainingStats.total}`));
|
|
2189
|
+
console.log(chalk.gray(` Replay entries: ${inputs.replayStats.totalEntries}`));
|
|
2190
|
+
console.log(chalk.gray(`\n Report written to .jfl/SENTINEL-REPORT.md\n`));
|
|
2191
|
+
}
|
|
2192
|
+
function scoreEmoji(score) {
|
|
2193
|
+
if (score >= 0.8)
|
|
2194
|
+
return chalk.green("●");
|
|
2195
|
+
if (score >= 0.5)
|
|
2196
|
+
return chalk.yellow("●");
|
|
2197
|
+
return chalk.red("●");
|
|
2198
|
+
}
|
|
2199
|
+
async function showMetrics(projectRoot) {
|
|
2200
|
+
const { TelemetryAgentV2 } = await import("../lib/telemetry-agent-v2.js");
|
|
2201
|
+
console.log(chalk.bold("\n Current Platform Metrics\n"));
|
|
2202
|
+
const agent = new TelemetryAgentV2({ projectRoot });
|
|
2203
|
+
const metrics = await agent.getMetrics();
|
|
2204
|
+
if (!metrics) {
|
|
2205
|
+
console.log(chalk.yellow(" Could not fetch metrics from platform."));
|
|
2206
|
+
console.log(chalk.gray(" Check JFL_PLATFORM_URL and network connectivity.\n"));
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
const format = (value, isPercent = false) => {
|
|
2210
|
+
if (isPercent)
|
|
2211
|
+
return `${(value * 100).toFixed(1)}%`;
|
|
2212
|
+
return value.toFixed(4);
|
|
2213
|
+
};
|
|
2214
|
+
console.log(chalk.cyan(" Health Metrics:"));
|
|
2215
|
+
console.log(chalk.gray(` Command Success Rate: ${format(metrics.command_success_rate, true)}`));
|
|
2216
|
+
console.log(chalk.gray(` Session Crash Rate: ${format(metrics.session_crash_rate, true)}`));
|
|
2217
|
+
console.log(chalk.gray(` Hub Crash Rate: ${format(metrics.hub_crash_rate, true)}`));
|
|
2218
|
+
console.log(chalk.gray(` Flow Completion Rate: ${format(metrics.flow_completion_rate, true)}`));
|
|
2219
|
+
console.log();
|
|
2220
|
+
console.log(chalk.cyan(" Performance Metrics:"));
|
|
2221
|
+
console.log(chalk.gray(` Command P90 Latency: ${metrics.command_p90_latency_ms}ms`));
|
|
2222
|
+
console.log(chalk.gray(` MCP Avg Latency: ${metrics.mcp_avg_latency_ms.toFixed(1)}ms`));
|
|
2223
|
+
console.log();
|
|
2224
|
+
console.log(chalk.cyan(" Usage Metrics:"));
|
|
2225
|
+
console.log(chalk.gray(` Active Installs: ${metrics.active_installs}`));
|
|
2226
|
+
console.log(chalk.gray(` Error Clusters: ${metrics.error_cluster_count}`));
|
|
2227
|
+
console.log(chalk.gray(` Hook Hit Rate: ${format(metrics.hook_hit_rate, true)}`));
|
|
2228
|
+
console.log();
|
|
2229
|
+
console.log(chalk.cyan(" Cost Metrics:"));
|
|
2230
|
+
console.log(chalk.gray(` Cost Per Session: $${metrics.cost_per_session_usd.toFixed(4)}`));
|
|
2231
|
+
console.log();
|
|
2232
|
+
}
|
|
2233
|
+
async function runDailyLoop(projectRoot) {
|
|
2234
|
+
const { MetaOrchestrator } = await import("../lib/meta-orchestrator.js");
|
|
2235
|
+
const { loadAllAgentConfigs } = await import("../lib/agent-config.js");
|
|
2236
|
+
// Prevent concurrent runs with lockfile
|
|
2237
|
+
const lockPath = path.join(projectRoot, ".jfl", "daily.lock");
|
|
2238
|
+
if (fs.existsSync(lockPath)) {
|
|
2239
|
+
const lockContent = fs.readFileSync(lockPath, "utf-8").trim();
|
|
2240
|
+
const lockTime = parseInt(lockContent, 10);
|
|
2241
|
+
const lockAge = Date.now() - lockTime;
|
|
2242
|
+
const MAX_LOCK_AGE = 2 * 60 * 60 * 1000; // 2 hours stale lock threshold
|
|
2243
|
+
if (lockAge < MAX_LOCK_AGE) {
|
|
2244
|
+
console.log(chalk.red(`\n Daily loop already running (locked ${Math.floor(lockAge / 60000)}m ago). Exiting.\n`));
|
|
2245
|
+
return;
|
|
2246
|
+
}
|
|
2247
|
+
console.log(chalk.yellow(`\n Stale lock found (${Math.floor(lockAge / 60000)}m old), breaking it.\n`));
|
|
2248
|
+
}
|
|
2249
|
+
fs.writeFileSync(lockPath, String(Date.now()));
|
|
2250
|
+
const releaseLock = () => { try {
|
|
2251
|
+
fs.unlinkSync(lockPath);
|
|
2252
|
+
}
|
|
2253
|
+
catch { } };
|
|
2254
|
+
process.on("exit", releaseLock);
|
|
2255
|
+
process.on("SIGTERM", () => { releaseLock(); process.exit(143); });
|
|
2256
|
+
process.on("SIGINT", () => { releaseLock(); process.exit(130); });
|
|
2257
|
+
console.log(chalk.bold("\n Peter Parker - Daily RL Agent Loop\n"));
|
|
2258
|
+
const orchestrator = new MetaOrchestrator(projectRoot);
|
|
2259
|
+
const agents = orchestrator.getAgents();
|
|
2260
|
+
if (agents.length === 0) {
|
|
2261
|
+
console.log(chalk.yellow(" No RL agents configured."));
|
|
2262
|
+
console.log(chalk.gray(" Run: jfl onboard <service-path> to discover metrics"));
|
|
2263
|
+
console.log(chalk.gray(" Or: jfl peter agent create\n"));
|
|
2264
|
+
return;
|
|
2265
|
+
}
|
|
2266
|
+
console.log(chalk.gray(` Found ${agents.length} RL agent(s):\n`));
|
|
2267
|
+
for (const agent of agents) {
|
|
2268
|
+
console.log(chalk.gray(` • ${agent.name} (${agent.metric}, ${agent.direction})`));
|
|
2269
|
+
}
|
|
2270
|
+
console.log();
|
|
2271
|
+
// Read training buffer to check for stale agents
|
|
2272
|
+
const tb = new TrainingBuffer(projectRoot);
|
|
2273
|
+
const entries = tb.read();
|
|
2274
|
+
const now = Date.now();
|
|
2275
|
+
const staleThreshold = 24 * 60 * 60 * 1000; // 24 hours
|
|
2276
|
+
const staleAgents = [];
|
|
2277
|
+
const activeAgents = [];
|
|
2278
|
+
for (const agent of agents) {
|
|
2279
|
+
const agentEntries = entries.filter(e => e.agent === agent.name);
|
|
2280
|
+
const latestEntry = agentEntries.sort((a, b) => b.ts.localeCompare(a.ts))[0];
|
|
2281
|
+
if (!latestEntry) {
|
|
2282
|
+
staleAgents.push(agent.name);
|
|
2283
|
+
console.log(chalk.yellow(` ⚠ ${agent.name}: No training data (never run)`));
|
|
2284
|
+
}
|
|
2285
|
+
else {
|
|
2286
|
+
const lastRun = new Date(latestEntry.ts).getTime();
|
|
2287
|
+
if (now - lastRun > staleThreshold) {
|
|
2288
|
+
staleAgents.push(agent.name);
|
|
2289
|
+
const hoursAgo = Math.floor((now - lastRun) / (60 * 60 * 1000));
|
|
2290
|
+
console.log(chalk.yellow(` ⚠ ${agent.name}: Stale (${hoursAgo}h since last training)`));
|
|
2291
|
+
}
|
|
2292
|
+
else {
|
|
2293
|
+
activeAgents.push(agent.name);
|
|
2294
|
+
console.log(chalk.green(` ✓ ${agent.name}: Recent training data`));
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
console.log();
|
|
2299
|
+
// ── Pre-flight: Mine tuples + Synthesize product context ──
|
|
2300
|
+
console.log(chalk.cyan(" Pre-flight: Mining tuples from journals...\n"));
|
|
2301
|
+
try {
|
|
2302
|
+
const { mineAll } = await import("../lib/tuple-miner.js");
|
|
2303
|
+
const { tuples: minedTuples, stats: mineStats } = mineAll({ all: true });
|
|
2304
|
+
if (minedTuples.length > 0) {
|
|
2305
|
+
const existing = new Set(entries.map(e => e.id));
|
|
2306
|
+
let newCount = 0;
|
|
2307
|
+
for (const tuple of minedTuples) {
|
|
2308
|
+
const id = `tb_${Buffer.from(JSON.stringify(tuple.state) + JSON.stringify(tuple.action)).toString("base64").slice(0, 12)}`;
|
|
2309
|
+
if (!existing.has(id)) {
|
|
2310
|
+
tb.append({ ...tuple, id, v: "1", ts: new Date().toISOString() });
|
|
2311
|
+
newCount++;
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
console.log(chalk.gray(` Mined ${mineStats.totalMined} tuples, ${newCount} new → buffer total: ${entries.length + newCount}`));
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
catch (err) {
|
|
2318
|
+
console.log(chalk.yellow(` Tuple mining failed: ${err.message}`));
|
|
2319
|
+
}
|
|
2320
|
+
console.log(chalk.cyan("\n Pre-flight: Synthesizing product context...\n"));
|
|
2321
|
+
try {
|
|
2322
|
+
await runSynthesis(projectRoot);
|
|
2323
|
+
}
|
|
2324
|
+
catch (err) {
|
|
2325
|
+
console.log(chalk.yellow(` Synthesis failed: ${err.message}`));
|
|
2326
|
+
}
|
|
2327
|
+
// ── Layer 3: Strategic reasoning ──
|
|
2328
|
+
console.log(chalk.cyan("\n Layer 3: Strategic reasoning...\n"));
|
|
2329
|
+
let strategicRunList = [];
|
|
2330
|
+
try {
|
|
2331
|
+
const { StratusClient } = await import("../lib/stratus-client.js");
|
|
2332
|
+
const stratus = new StratusClient();
|
|
2333
|
+
const productContextPath = path.join(projectRoot, ".jfl", "product-context.md");
|
|
2334
|
+
const productCtx = fs.existsSync(productContextPath) ? fs.readFileSync(productContextPath, "utf-8").slice(0, 2000) : "No product context yet.";
|
|
2335
|
+
// Get recent results per agent
|
|
2336
|
+
const agentSummaries = agents.map(a => {
|
|
2337
|
+
const agentEntries = entries.filter(e => e.agent === a.name).slice(-5);
|
|
2338
|
+
const improved = agentEntries.filter(e => e.reward?.improved).length;
|
|
2339
|
+
return `${a.name} (${a.metric}, ${a.direction}): ${agentEntries.length} recent tuples, ${improved} improved`;
|
|
2340
|
+
}).join("\n");
|
|
2341
|
+
const strategicPrompt = `You are Peter Parker, a strategic agent orchestrator. Based on the product context and agent performance, decide:
|
|
2342
|
+
1. Which agents should run tonight (and why)
|
|
2343
|
+
2. Which agents to skip (and why)
|
|
2344
|
+
3. Any priority shifts or new metric suggestions
|
|
2345
|
+
|
|
2346
|
+
Product context:
|
|
2347
|
+
${productCtx}
|
|
2348
|
+
|
|
2349
|
+
Agent performance:
|
|
2350
|
+
${agentSummaries}
|
|
2351
|
+
|
|
2352
|
+
Stale agents (haven't run in 24h): ${staleAgents.join(", ") || "none"}
|
|
2353
|
+
|
|
2354
|
+
Be concise. Output a JSON object: { "run": ["agent1", "agent2"], "skip": ["agent3"], "reasoning": "brief explanation", "suggestions": "any new metrics or priority changes" }`;
|
|
2355
|
+
const response = await stratus.reason(strategicPrompt, { maxTokens: 500, temperature: 0.3 });
|
|
2356
|
+
const strategicText = response?.choices?.[0]?.message?.content || "";
|
|
2357
|
+
console.log(chalk.gray(` Strategic reasoning:\n ${strategicText.slice(0, 500)}`));
|
|
2358
|
+
// Try to parse JSON from response
|
|
2359
|
+
try {
|
|
2360
|
+
const jsonMatch = strategicText.match(/\{[\s\S]*\}/);
|
|
2361
|
+
if (jsonMatch) {
|
|
2362
|
+
const strategic = JSON.parse(jsonMatch[0]);
|
|
2363
|
+
if (Array.isArray(strategic.run)) {
|
|
2364
|
+
strategicRunList = strategic.run;
|
|
2365
|
+
}
|
|
2366
|
+
if (strategic.reasoning) {
|
|
2367
|
+
console.log(chalk.cyan(`\n Reasoning: ${strategic.reasoning}`));
|
|
2368
|
+
}
|
|
2369
|
+
if (strategic.suggestions) {
|
|
2370
|
+
console.log(chalk.gray(` Suggestions: ${strategic.suggestions}`));
|
|
2371
|
+
}
|
|
2372
|
+
// Write strategic decision to journal
|
|
2373
|
+
const journalPath = path.join(projectRoot, ".jfl", "journal");
|
|
2374
|
+
if (fs.existsSync(journalPath)) {
|
|
2375
|
+
const entry = {
|
|
2376
|
+
v: 2, ts: new Date().toISOString(), session: "peter-parker",
|
|
2377
|
+
type: "decision", status: "complete",
|
|
2378
|
+
title: "Layer 3: Strategic reasoning",
|
|
2379
|
+
summary: strategic.reasoning || strategicText.slice(0, 200),
|
|
2380
|
+
detail: strategicText,
|
|
2381
|
+
};
|
|
2382
|
+
const files = fs.readdirSync(journalPath).filter(f => f.endsWith(".jsonl")).sort();
|
|
2383
|
+
const latestJournal = files[files.length - 1];
|
|
2384
|
+
if (latestJournal) {
|
|
2385
|
+
fs.appendFileSync(path.join(journalPath, latestJournal), "\n" + JSON.stringify(entry));
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
catch { /* non-JSON response, that's fine */ }
|
|
2391
|
+
}
|
|
2392
|
+
catch (err) {
|
|
2393
|
+
console.log(chalk.yellow(` Strategic reasoning failed: ${err.message}`));
|
|
2394
|
+
}
|
|
2395
|
+
console.log();
|
|
2396
|
+
// Check for scope:impact events that should trigger downstream agents
|
|
2397
|
+
const impactTriggered = orchestrator.getImpactTriggeredAgents();
|
|
2398
|
+
if (impactTriggered.length > 0) {
|
|
2399
|
+
console.log(chalk.cyan(" Scope impact events detected:"));
|
|
2400
|
+
for (const { agent, impactPattern } of impactTriggered) {
|
|
2401
|
+
console.log(chalk.gray(` • ${agent.name} should react to: ${impactPattern}`));
|
|
2402
|
+
}
|
|
2403
|
+
console.log();
|
|
2404
|
+
}
|
|
2405
|
+
// TOCTOU guard: verify hub before starting agents (TLA+ invariant: HubRequiredForScheduling)
|
|
2406
|
+
try {
|
|
2407
|
+
const { guardHubAvailable } = await import("../lib/hub-health.js");
|
|
2408
|
+
const hubGuard = await guardHubAvailable(projectRoot, "daily-loop");
|
|
2409
|
+
if (hubGuard.proceed) {
|
|
2410
|
+
console.log(chalk.green(` Hub health: ✓ (${hubGuard.status.responseMs}ms)`));
|
|
2411
|
+
}
|
|
2412
|
+
else {
|
|
2413
|
+
console.log(chalk.yellow(` Hub health: ✗ (${hubGuard.status.error})`));
|
|
2414
|
+
console.log(chalk.gray(" Agents will run without hub tracking. Results may not be recorded."));
|
|
2415
|
+
}
|
|
2416
|
+
console.log();
|
|
2417
|
+
}
|
|
2418
|
+
catch {
|
|
2419
|
+
// Hub check unavailable — proceed
|
|
2420
|
+
}
|
|
2421
|
+
// Schedule next agent using meta-orchestrator
|
|
2422
|
+
const decision = orchestrator.scheduleNext();
|
|
2423
|
+
if (!decision) {
|
|
2424
|
+
console.log(chalk.yellow(" No agent available to schedule."));
|
|
2425
|
+
return;
|
|
2426
|
+
}
|
|
2427
|
+
console.log(chalk.bold(` Scheduled: ${decision.agent.name}`));
|
|
2428
|
+
console.log(chalk.gray(` Reason: ${decision.reason}`));
|
|
2429
|
+
if (decision.impactPattern) {
|
|
2430
|
+
console.log(chalk.gray(` Triggered by: ${decision.impactPattern}`));
|
|
2431
|
+
}
|
|
2432
|
+
if (decision.emaReward !== undefined) {
|
|
2433
|
+
console.log(chalk.gray(` EMA Reward: ${decision.emaReward.toFixed(4)}`));
|
|
2434
|
+
}
|
|
2435
|
+
console.log();
|
|
2436
|
+
// Run autoresearch for stale agents — filtered by strategic reasoning
|
|
2437
|
+
// Cap rounds for nightly: 5 rounds per agent keeps total runtime under 1 hour
|
|
2438
|
+
const NIGHTLY_ROUNDS_CAP = 5;
|
|
2439
|
+
// Only run stale agents that strategic reasoning approved (if available)
|
|
2440
|
+
const filteredStaleAgents = strategicRunList.length > 0
|
|
2441
|
+
? staleAgents.filter(a => strategicRunList.includes(a))
|
|
2442
|
+
: staleAgents;
|
|
2443
|
+
if (filteredStaleAgents.length > 0) {
|
|
2444
|
+
console.log(chalk.cyan(` Running autoresearch for ${filteredStaleAgents.length} stale agent(s) (${NIGHTLY_ROUNDS_CAP} rounds each)...\n`));
|
|
2445
|
+
if (staleAgents.length !== filteredStaleAgents.length) {
|
|
2446
|
+
const skipped = staleAgents.filter(a => !filteredStaleAgents.includes(a));
|
|
2447
|
+
console.log(chalk.gray(` Skipped by strategic reasoning: ${skipped.join(", ")}\n`));
|
|
2448
|
+
}
|
|
2449
|
+
for (const agentName of filteredStaleAgents) {
|
|
2450
|
+
console.log(chalk.bold(`\n ── ${agentName} ${"─".repeat(45)}\n`));
|
|
2451
|
+
try {
|
|
2452
|
+
await agentRun(projectRoot, agentName, NIGHTLY_ROUNDS_CAP);
|
|
2453
|
+
}
|
|
2454
|
+
catch (err) {
|
|
2455
|
+
console.log(chalk.red(` Agent ${agentName} failed: ${err.message}`));
|
|
2456
|
+
console.log(chalk.gray(" Continuing to next agent...\n"));
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
// Post summary event
|
|
2461
|
+
await postHubEvent(projectRoot, "peter:daily-complete", {
|
|
2462
|
+
total_agents: agents.length,
|
|
2463
|
+
stale_agents: staleAgents,
|
|
2464
|
+
active_agents: activeAgents,
|
|
2465
|
+
impact_triggered: impactTriggered.map(t => t.agent.name),
|
|
2466
|
+
scheduled: decision.agent.name,
|
|
2467
|
+
reason: decision.reason,
|
|
2468
|
+
});
|
|
2469
|
+
releaseLock();
|
|
2470
|
+
console.log(chalk.green("\n Daily loop complete.\n"));
|
|
2471
|
+
}
|
|
2472
|
+
async function agentSwarm(projectRoot, rounds) {
|
|
2473
|
+
const { MetaOrchestrator } = await import("../lib/meta-orchestrator.js");
|
|
2474
|
+
const orchestrator = new MetaOrchestrator(projectRoot);
|
|
2475
|
+
const agents = orchestrator.getAgents();
|
|
2476
|
+
if (agents.length === 0) {
|
|
2477
|
+
console.log(chalk.yellow("\n No agents configured."));
|
|
2478
|
+
console.log(chalk.gray(" Run: jfl peter agent create\n"));
|
|
2479
|
+
return;
|
|
2480
|
+
}
|
|
2481
|
+
console.log(chalk.bold(`\n Agent Swarm: ${agents.length} agents, ${rounds} rounds total\n`));
|
|
2482
|
+
for (const agent of agents) {
|
|
2483
|
+
console.log(chalk.gray(` - ${agent.name} (${agent.metric})`));
|
|
2484
|
+
}
|
|
2485
|
+
console.log();
|
|
2486
|
+
const result = await orchestrator.runSwarm(rounds, (agent, round, reward, reason) => {
|
|
2487
|
+
const emoji = reward > 0 ? chalk.green("+") : reward < 0 ? chalk.red("-") : chalk.gray("=");
|
|
2488
|
+
console.log(chalk.gray(` [${round}/${rounds}] ${agent} → ${emoji}${Math.abs(reward).toFixed(4)} (${reason})`));
|
|
2489
|
+
});
|
|
2490
|
+
console.log(chalk.bold(`\n ── Swarm Complete ${"─".repeat(38)}\n`));
|
|
2491
|
+
const stats = orchestrator.getStats();
|
|
2492
|
+
console.log(chalk.gray(` Total rounds: ${stats.totalRounds}`));
|
|
2493
|
+
console.log(chalk.gray(` Avg EMA reward: ${stats.avgEmaReward.toFixed(4)}`));
|
|
2494
|
+
console.log(chalk.gray(` Overall win rate: ${(stats.overallWinRate * 100).toFixed(1)}%`));
|
|
2495
|
+
if (stats.bestAgent) {
|
|
2496
|
+
console.log(chalk.green(` Best agent: ${stats.bestAgent.name} (EMA: ${stats.bestAgent.emaReward.toFixed(4)})`));
|
|
2497
|
+
}
|
|
2498
|
+
console.log(chalk.bold("\n Per-Agent Results:\n"));
|
|
2499
|
+
for (const [name, data] of Object.entries(result.perAgent)) {
|
|
2500
|
+
console.log(chalk.cyan(` ${name}: ${data.rounds} rounds, total delta: ${data.totalReward > 0 ? "+" : ""}${data.totalReward.toFixed(4)}`));
|
|
2501
|
+
}
|
|
2502
|
+
console.log();
|
|
2503
|
+
}
|
|
2504
|
+
// ============================================================================
|
|
2505
|
+
// Synthesis — distill journals + events into product context for agents
|
|
2506
|
+
// ============================================================================
|
|
2507
|
+
async function runSynthesis(projectRoot) {
|
|
2508
|
+
console.log(chalk.bold("\n Peter Parker - Product Context Synthesis\n"));
|
|
2509
|
+
const { StratusClient } = await import("../lib/stratus-client.js");
|
|
2510
|
+
const stratus = process.env.STRATUS_API_KEY
|
|
2511
|
+
? new StratusClient({ apiKey: process.env.STRATUS_API_KEY })
|
|
2512
|
+
: null;
|
|
2513
|
+
if (!stratus) {
|
|
2514
|
+
console.log(chalk.red(" STRATUS_API_KEY required for synthesis"));
|
|
2515
|
+
return;
|
|
2516
|
+
}
|
|
2517
|
+
// 1. Read recent journals (last 7 days)
|
|
2518
|
+
const journalDir = path.join(projectRoot, ".jfl", "journal");
|
|
2519
|
+
let journalEntries = [];
|
|
2520
|
+
if (fs.existsSync(journalDir)) {
|
|
2521
|
+
const files = fs.readdirSync(journalDir).filter(f => f.endsWith(".jsonl"));
|
|
2522
|
+
for (const file of files.slice(-10)) { // Last 10 journal files
|
|
2523
|
+
const content = fs.readFileSync(path.join(journalDir, file), "utf-8").trim();
|
|
2524
|
+
if (content)
|
|
2525
|
+
journalEntries.push(...content.split("\n").slice(-20)); // Last 20 entries per file
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
console.log(chalk.gray(` Read ${journalEntries.length} journal entries`));
|
|
2529
|
+
// 2. Read recent events
|
|
2530
|
+
const eventsPath = path.join(projectRoot, ".jfl", "service-events.jsonl");
|
|
2531
|
+
let events = [];
|
|
2532
|
+
if (fs.existsSync(eventsPath)) {
|
|
2533
|
+
events = fs.readFileSync(eventsPath, "utf-8").trim().split("\n").slice(-30); // Last 30 events
|
|
2534
|
+
}
|
|
2535
|
+
console.log(chalk.gray(` Read ${events.length} events`));
|
|
2536
|
+
// 3. Read agent results from training buffer
|
|
2537
|
+
const bufferPath = path.join(projectRoot, ".jfl", "training-buffer.jsonl");
|
|
2538
|
+
let tuples = [];
|
|
2539
|
+
if (fs.existsSync(bufferPath)) {
|
|
2540
|
+
tuples = fs.readFileSync(bufferPath, "utf-8").trim().split("\n").slice(-20);
|
|
2541
|
+
}
|
|
2542
|
+
console.log(chalk.gray(` Read ${tuples.length} training tuples`));
|
|
2543
|
+
// 4. Read current agent configs
|
|
2544
|
+
const { listAgentConfigs, loadAgentConfig } = await import("../lib/agent-config.js");
|
|
2545
|
+
const agentNames = listAgentConfigs(projectRoot);
|
|
2546
|
+
const configs = agentNames.map(name => { try {
|
|
2547
|
+
return loadAgentConfig(projectRoot, name);
|
|
2548
|
+
}
|
|
2549
|
+
catch {
|
|
2550
|
+
return null;
|
|
2551
|
+
} }).filter(Boolean);
|
|
2552
|
+
const agentSummary = configs.map((c) => `${c.name}: ${c.metric} (${c.direction}), target: ${c.target_repo || "self"}`).join("\n");
|
|
2553
|
+
// 5. Send to Stratus for synthesis
|
|
2554
|
+
console.log(chalk.gray("\n Synthesizing with Stratus...\n"));
|
|
2555
|
+
const prompt = `You are Peter Parker, the orchestrator for a software product portfolio.
|
|
2556
|
+
|
|
2557
|
+
Your job: read the recent activity (journals, events, experiment results) and produce a PRODUCT CONTEXT document that tells scoped RL agents what the product is, what's been happening, and what to focus on.
|
|
2558
|
+
|
|
2559
|
+
## Current Agents
|
|
2560
|
+
${agentSummary}
|
|
2561
|
+
|
|
2562
|
+
## Recent Journal Entries (last 7 days)
|
|
2563
|
+
${journalEntries.slice(-15).map(e => e.slice(0, 200)).join("\n")}
|
|
2564
|
+
|
|
2565
|
+
## Recent Events
|
|
2566
|
+
${events.slice(-15).join("\n")}
|
|
2567
|
+
|
|
2568
|
+
## Recent Experiment Results
|
|
2569
|
+
${tuples.slice(-10).join("\n")}
|
|
2570
|
+
|
|
2571
|
+
---
|
|
2572
|
+
|
|
2573
|
+
Produce a concise product-context.md with these sections:
|
|
2574
|
+
1. **Product State** — what is this product, what's working, what's broken
|
|
2575
|
+
2. **Recent Activity** — what the team has been building/fixing (distilled from journals)
|
|
2576
|
+
3. **Agent Guidance** — for each active agent, specific guidance based on recent context (e.g. "cli-speed: startup is already fast, focus on subcommand latency")
|
|
2577
|
+
4. **Priority Shifts** — any metrics that should be deprioritized or new metrics to consider
|
|
2578
|
+
5. **Open Questions** — things that need human input
|
|
2579
|
+
|
|
2580
|
+
Be concise. This document is consumed by agents, not humans. Skip fluff.`;
|
|
2581
|
+
try {
|
|
2582
|
+
const response = await stratus.reason(prompt, { maxTokens: 1500, temperature: 0.3 });
|
|
2583
|
+
const synthesis = response.choices[0]?.message?.content || "";
|
|
2584
|
+
if (synthesis) {
|
|
2585
|
+
const outputPath = path.join(projectRoot, ".jfl", "product-context.md");
|
|
2586
|
+
fs.writeFileSync(outputPath, `# Product Context\n\n_Synthesized by Peter Parker at ${new Date().toISOString()}_\n\n${synthesis}\n`);
|
|
2587
|
+
console.log(chalk.green(` ✓ Product context written to .jfl/product-context.md`));
|
|
2588
|
+
console.log(chalk.gray(` (${synthesis.length} chars)\n`));
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
catch (err) {
|
|
2592
|
+
console.log(chalk.red(` Synthesis failed: ${err.message}`));
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
// ============================================================================
|
|
2596
|
+
// Review — check autoresearch branches, audit with Stratus, prepare PRs
|
|
2597
|
+
// ============================================================================
|
|
2598
|
+
async function runReview(projectRoot) {
|
|
2599
|
+
console.log(chalk.bold("\n Peter Parker - Autoresearch Review\n"));
|
|
2600
|
+
const { spawnSync } = await import("child_process");
|
|
2601
|
+
// Find session branches on remote
|
|
2602
|
+
const result = spawnSync("git", ["branch", "-r", "--list", "origin/session/*"], { cwd: projectRoot, encoding: "utf-8" });
|
|
2603
|
+
const branches = (result.stdout || "").trim().split("\n").map(b => b.trim()).filter(Boolean);
|
|
2604
|
+
if (branches.length === 0) {
|
|
2605
|
+
console.log(chalk.yellow(" No autoresearch branches found.\n"));
|
|
2606
|
+
return;
|
|
2607
|
+
}
|
|
2608
|
+
console.log(chalk.gray(` Found ${branches.length} session branch(es):\n`));
|
|
2609
|
+
for (const branch of branches) {
|
|
2610
|
+
const shortBranch = branch.replace("origin/", "");
|
|
2611
|
+
// Get diff stats
|
|
2612
|
+
const diffStat = spawnSync("git", ["diff", "--stat", `origin/main...${branch}`], { cwd: projectRoot, encoding: "utf-8" });
|
|
2613
|
+
const logResult = spawnSync("git", ["log", "--oneline", `origin/main..${branch}`], { cwd: projectRoot, encoding: "utf-8" });
|
|
2614
|
+
const commits = (logResult.stdout || "").trim().split("\n").filter(Boolean);
|
|
2615
|
+
console.log(chalk.cyan(` ${shortBranch}`));
|
|
2616
|
+
console.log(chalk.gray(` ${commits.length} commits`));
|
|
2617
|
+
if (diffStat.stdout) {
|
|
2618
|
+
const lastLine = diffStat.stdout.trim().split("\n").pop() || "";
|
|
2619
|
+
console.log(chalk.gray(` ${lastLine.trim()}`));
|
|
2620
|
+
}
|
|
2621
|
+
console.log();
|
|
2622
|
+
}
|
|
2623
|
+
console.log(chalk.gray(" To create PRs from these branches:"));
|
|
2624
|
+
console.log(chalk.gray(" gh pr create --base main --head <branch> --title '...'\n"));
|
|
2625
|
+
}
|
|
2626
|
+
export async function peterCommand(action, options = {}) {
|
|
2627
|
+
const projectRoot = process.cwd();
|
|
2628
|
+
// Handle "agent" subcommand
|
|
2629
|
+
if (action === "agent") {
|
|
2630
|
+
const subAction = options.name || options.task; // name is the subcommand, task might be agent name
|
|
2631
|
+
if (subAction === "create") {
|
|
2632
|
+
await agentCreate(projectRoot);
|
|
2633
|
+
return;
|
|
2634
|
+
}
|
|
2635
|
+
else if (subAction === "list") {
|
|
2636
|
+
await agentList(projectRoot);
|
|
2637
|
+
return;
|
|
2638
|
+
}
|
|
2639
|
+
else if (subAction === "run") {
|
|
2640
|
+
// jfl peter agent run <name> --rounds N
|
|
2641
|
+
// The agent name would be in a different position
|
|
2642
|
+
console.log(chalk.yellow("\n Usage: jfl peter agent run <name> --rounds N\n"));
|
|
2643
|
+
return;
|
|
2644
|
+
}
|
|
2645
|
+
else if (subAction === "swarm") {
|
|
2646
|
+
const rounds = parseInt(options.rounds || "20", 10);
|
|
2647
|
+
await agentSwarm(projectRoot, rounds);
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2650
|
+
else if (subAction) {
|
|
2651
|
+
// Assume it's an agent name for "run"
|
|
2652
|
+
// Use CLI override if provided, otherwise use config.rounds (default 50)
|
|
2653
|
+
const roundsOverride = options.rounds ? parseInt(options.rounds, 10) : undefined;
|
|
2654
|
+
await agentRun(projectRoot, subAction, roundsOverride);
|
|
2655
|
+
return;
|
|
2656
|
+
}
|
|
2657
|
+
// Show agent help
|
|
2658
|
+
console.log(chalk.bold("\n Peter Parker - Scoped Agent Commands\n"));
|
|
2659
|
+
console.log(chalk.gray(" Commands:"));
|
|
2660
|
+
console.log(" jfl peter agent create Interactive agent creation");
|
|
2661
|
+
console.log(" jfl peter agent list List configured agents");
|
|
2662
|
+
console.log(" jfl peter agent run <name> [--rounds N] Run a specific agent");
|
|
2663
|
+
console.log(" jfl peter agent swarm [--rounds N] Run all agents with meta-orchestrator");
|
|
2664
|
+
console.log();
|
|
2665
|
+
return;
|
|
2666
|
+
}
|
|
2667
|
+
switch (action) {
|
|
2668
|
+
case "setup": {
|
|
2669
|
+
let profile = "balanced";
|
|
2670
|
+
if (options.cost)
|
|
2671
|
+
profile = "cost-optimized";
|
|
2672
|
+
if (options.quality)
|
|
2673
|
+
profile = "quality-first";
|
|
2674
|
+
if (options.balanced)
|
|
2675
|
+
profile = "balanced";
|
|
2676
|
+
await setup(projectRoot, profile);
|
|
2677
|
+
break;
|
|
2678
|
+
}
|
|
2679
|
+
case "run": {
|
|
2680
|
+
await run(projectRoot, options.task);
|
|
2681
|
+
break;
|
|
2682
|
+
}
|
|
2683
|
+
case "status": {
|
|
2684
|
+
await status(projectRoot);
|
|
2685
|
+
break;
|
|
2686
|
+
}
|
|
2687
|
+
case "pr": {
|
|
2688
|
+
await runWithPR(projectRoot, options.task);
|
|
2689
|
+
break;
|
|
2690
|
+
}
|
|
2691
|
+
case "dashboard": {
|
|
2692
|
+
const { startEventDashboard } = await import("../ui/event-dashboard.js");
|
|
2693
|
+
await startEventDashboard();
|
|
2694
|
+
break;
|
|
2695
|
+
}
|
|
2696
|
+
case "experiment": {
|
|
2697
|
+
if (options.mode === "autoresearch") {
|
|
2698
|
+
const rounds = parseInt(options.rounds || "5", 10);
|
|
2699
|
+
const budget = options.budget ? parseFloat(options.budget) : undefined;
|
|
2700
|
+
await runAutoresearch(projectRoot, { rounds, budget, usePi: options.pi });
|
|
2701
|
+
}
|
|
2702
|
+
else {
|
|
2703
|
+
await runExperiment(projectRoot);
|
|
2704
|
+
}
|
|
2705
|
+
break;
|
|
2706
|
+
}
|
|
2707
|
+
case "autoresearch": {
|
|
2708
|
+
const rounds = parseInt(options.rounds || "5", 10);
|
|
2709
|
+
const budget = options.budget ? parseFloat(options.budget) : undefined;
|
|
2710
|
+
await runAutoresearch(projectRoot, { rounds, budget, usePi: options.pi });
|
|
2711
|
+
break;
|
|
2712
|
+
}
|
|
2713
|
+
case "telemetry": {
|
|
2714
|
+
await runTelemetryAgent(projectRoot);
|
|
2715
|
+
break;
|
|
2716
|
+
}
|
|
2717
|
+
case "sentinel": {
|
|
2718
|
+
await runSentinelReview(projectRoot);
|
|
2719
|
+
break;
|
|
2720
|
+
}
|
|
2721
|
+
case "metrics": {
|
|
2722
|
+
await showMetrics(projectRoot);
|
|
2723
|
+
break;
|
|
2724
|
+
}
|
|
2725
|
+
case "daily": {
|
|
2726
|
+
await runDailyLoop(projectRoot);
|
|
2727
|
+
break;
|
|
2728
|
+
}
|
|
2729
|
+
case "nightly": {
|
|
2730
|
+
// Alias for daily
|
|
2731
|
+
await runDailyLoop(projectRoot);
|
|
2732
|
+
break;
|
|
2733
|
+
}
|
|
2734
|
+
case "synthesize": {
|
|
2735
|
+
await runSynthesis(projectRoot);
|
|
2736
|
+
break;
|
|
2737
|
+
}
|
|
2738
|
+
case "review": {
|
|
2739
|
+
await runReview(projectRoot);
|
|
2740
|
+
break;
|
|
2741
|
+
}
|
|
2742
|
+
case "pickup": {
|
|
2743
|
+
await runPickup(projectRoot);
|
|
2744
|
+
break;
|
|
2745
|
+
}
|
|
2746
|
+
default: {
|
|
2747
|
+
console.log(chalk.bold("\n Peter Parker - Model-Routed Agent Orchestrator\n"));
|
|
2748
|
+
console.log(chalk.gray(" Commands:"));
|
|
2749
|
+
console.log(" jfl peter setup [--cost|--balanced|--quality] Generate agent config");
|
|
2750
|
+
console.log(" jfl peter run [--task <task>] Run orchestrator");
|
|
2751
|
+
console.log(" jfl peter pr --task <task> Run + branch + PR");
|
|
2752
|
+
console.log(" jfl peter pickup Poll backlog, pick source:linear issue, execute, PR");
|
|
2753
|
+
console.log(" jfl peter experiment Proactive: pick + execute next experiment");
|
|
2754
|
+
console.log(" jfl peter autoresearch [--rounds N] [--budget $] [--pi]");
|
|
2755
|
+
console.log(" Autoresearch mode with Pi runtime");
|
|
2756
|
+
console.log(" jfl peter status Show status + recent events");
|
|
2757
|
+
console.log(" jfl peter dashboard Live event stream dashboard");
|
|
2758
|
+
console.log();
|
|
2759
|
+
console.log(chalk.bold(" Pi-sky Runtime Options:\n"));
|
|
2760
|
+
console.log(" --budget <amount> Cost budget in USD (auto-downgrades model when exceeded)");
|
|
2761
|
+
console.log(" --pi Force Pi runtime (default: auto-detect)");
|
|
2762
|
+
console.log();
|
|
2763
|
+
console.log(chalk.bold(" Telemetry & RL:\n"));
|
|
2764
|
+
console.log(" jfl peter telemetry Run telemetry agent (platform digest)");
|
|
2765
|
+
console.log(" jfl peter sentinel Run Sentinel nightly review");
|
|
2766
|
+
console.log(" jfl peter metrics Show current platform metrics");
|
|
2767
|
+
console.log(" jfl peter daily Daily RL loop (check stale agents, schedule next)");
|
|
2768
|
+
console.log();
|
|
2769
|
+
console.log(chalk.bold(" Scoped Agents:\n"));
|
|
2770
|
+
console.log(" jfl peter agent create Interactive agent creation");
|
|
2771
|
+
console.log(" jfl peter agent list List configured agents");
|
|
2772
|
+
console.log(" jfl peter agent run <name> [--rounds N] Run a specific scoped agent");
|
|
2773
|
+
console.log(" jfl peter agent swarm [--rounds N] Run all agents with orchestrator");
|
|
2774
|
+
console.log();
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
//# sourceMappingURL=peter.js.map
|