jfl 0.4.4 → 0.5.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/dist/commands/context-hub.d.ts.map +1 -1
- package/dist/commands/context-hub.js +818 -39
- package/dist/commands/context-hub.js.map +1 -1
- package/dist/commands/eval.d.ts +1 -1
- package/dist/commands/eval.d.ts.map +1 -1
- package/dist/commands/eval.js +192 -1
- package/dist/commands/eval.js.map +1 -1
- package/dist/commands/findings.d.ts +6 -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/hud.d.ts.map +1 -1
- package/dist/commands/hud.js +47 -9
- package/dist/commands/hud.js.map +1 -1
- package/dist/commands/ide.d.ts +27 -0
- package/dist/commands/ide.d.ts.map +1 -0
- package/dist/commands/ide.js +546 -0
- package/dist/commands/ide.js.map +1 -0
- package/dist/commands/onboard.d.ts.map +1 -1
- package/dist/commands/onboard.js +212 -2
- package/dist/commands/onboard.js.map +1 -1
- package/dist/commands/openclaw.d.ts +3 -0
- package/dist/commands/openclaw.d.ts.map +1 -1
- package/dist/commands/openclaw.js +76 -2
- package/dist/commands/openclaw.js.map +1 -1
- package/dist/commands/peter.d.ts +1 -0
- package/dist/commands/peter.d.ts.map +1 -1
- package/dist/commands/peter.js +935 -15
- package/dist/commands/peter.js.map +1 -1
- 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.map +1 -1
- package/dist/commands/pi.js +18 -3
- package/dist/commands/pi.js.map +1 -1
- package/dist/commands/scope.d.ts.map +1 -1
- package/dist/commands/scope.js +90 -1
- package/dist/commands/scope.js.map +1 -1
- package/dist/commands/services.d.ts.map +1 -1
- package/dist/commands/services.js +18 -0
- package/dist/commands/services.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +22 -4
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/viz.d.ts.map +1 -1
- package/dist/commands/viz.js +417 -0
- package/dist/commands/viz.js.map +1 -1
- package/dist/dashboard-static/assets/index-B6b867Pv.js +121 -0
- package/dist/dashboard-static/assets/index-Y4BrqxV-.css +1 -0
- package/dist/dashboard-static/index.html +2 -2
- package/dist/index.js +225 -61
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-config.d.ts +52 -0
- package/dist/lib/agent-config.d.ts.map +1 -0
- package/dist/lib/agent-config.js +231 -0
- package/dist/lib/agent-config.js.map +1 -0
- package/dist/lib/agent-generator.d.ts +10 -0
- package/dist/lib/agent-generator.d.ts.map +1 -1
- package/dist/lib/agent-generator.js +64 -10
- package/dist/lib/agent-generator.js.map +1 -1
- 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 +627 -0
- package/dist/lib/agent-session.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 +315 -0
- package/dist/lib/eval-snapshot.js.map +1 -0
- package/dist/lib/eval-store.d.ts +5 -0
- package/dist/lib/eval-store.d.ts.map +1 -1
- package/dist/lib/eval-store.js +33 -3
- package/dist/lib/eval-store.js.map +1 -1
- 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 +8 -0
- package/dist/lib/flow-engine.d.ts.map +1 -1
- package/dist/lib/flow-engine.js +84 -2
- package/dist/lib/flow-engine.js.map +1 -1
- package/dist/lib/hub-client.d.ts +1 -0
- package/dist/lib/hub-client.d.ts.map +1 -1
- package/dist/lib/hub-client.js +33 -6
- package/dist/lib/hub-client.js.map +1 -1
- 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/memory-db.js +4 -4
- package/dist/lib/memory-db.js.map +1 -1
- package/dist/lib/memory-indexer.d.ts.map +1 -1
- package/dist/lib/memory-indexer.js +3 -0
- package/dist/lib/memory-indexer.js.map +1 -1
- package/dist/lib/memory-search.d.ts +148 -4
- package/dist/lib/memory-search.d.ts.map +1 -1
- package/dist/lib/memory-search.js +496 -58
- package/dist/lib/memory-search.js.map +1 -1
- package/dist/lib/meta-orchestrator.d.ts +104 -0
- package/dist/lib/meta-orchestrator.d.ts.map +1 -0
- package/dist/lib/meta-orchestrator.js +373 -0
- package/dist/lib/meta-orchestrator.js.map +1 -0
- package/dist/lib/peer-agent-generator.d.ts.map +1 -1
- package/dist/lib/peer-agent-generator.js +43 -19
- package/dist/lib/peer-agent-generator.js.map +1 -1
- package/dist/lib/policy-head.d.ts +25 -0
- package/dist/lib/policy-head.d.ts.map +1 -0
- package/dist/lib/policy-head.js +136 -0
- package/dist/lib/policy-head.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/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/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/stratus-client.d.ts +1 -0
- package/dist/lib/stratus-client.d.ts.map +1 -1
- package/dist/lib/stratus-client.js +24 -2
- package/dist/lib/stratus-client.js.map +1 -1
- 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 +1042 -0
- package/dist/lib/telemetry-agent-v2.js.map +1 -0
- package/dist/lib/telemetry-agent.d.ts.map +1 -1
- package/dist/lib/telemetry-agent.js +27 -6
- package/dist/lib/telemetry-agent.js.map +1 -1
- package/dist/lib/telemetry-digest.d.ts.map +1 -1
- package/dist/lib/telemetry-digest.js +27 -5
- package/dist/lib/telemetry-digest.js.map +1 -1
- package/dist/lib/telemetry.d.ts.map +1 -1
- package/dist/lib/telemetry.js +29 -4
- package/dist/lib/telemetry.js.map +1 -1
- 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/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/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 +463 -0
- package/dist/lib/workspace/data-pipeline.js.map +1 -0
- package/dist/lib/workspace/engine.d.ts +64 -0
- package/dist/lib/workspace/engine.d.ts.map +1 -0
- package/dist/lib/workspace/engine.js +397 -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/surface-registry.d.ts +49 -0
- package/dist/lib/workspace/surface-registry.d.ts.map +1 -0
- package/dist/lib/workspace/surface-registry.js +217 -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 +16 -0
- package/dist/lib/workspace/surfaces/index.d.ts.map +1 -0
- package/dist/lib/workspace/surfaces/index.js +16 -0
- package/dist/lib/workspace/surfaces/index.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/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 +27 -0
- package/dist/lib/workspace/tmux-adapter.d.ts.map +1 -0
- package/dist/lib/workspace/tmux-adapter.js +106 -0
- package/dist/lib/workspace/tmux-adapter.js.map +1 -0
- package/dist/mcp/context-hub-mcp.js +7 -24
- package/dist/mcp/context-hub-mcp.js.map +1 -1
- package/dist/types/flows.d.ts +2 -0
- package/dist/types/flows.d.ts.map +1 -1
- 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/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/telemetry-digest.d.ts +2 -0
- package/dist/types/telemetry-digest.d.ts.map +1 -1
- package/dist/utils/ensure-project.d.ts +1 -0
- package/dist/utils/ensure-project.d.ts.map +1 -1
- package/dist/utils/ensure-project.js +19 -7
- package/dist/utils/ensure-project.js.map +1 -1
- package/dist/utils/jfl-config.d.ts +1 -0
- package/dist/utils/jfl-config.d.ts.map +1 -1
- package/dist/utils/jfl-config.js +19 -1
- package/dist/utils/jfl-config.js.map +1 -1
- package/dist/utils/jfl-paths.d.ts +5 -0
- package/dist/utils/jfl-paths.d.ts.map +1 -1
- package/dist/utils/jfl-paths.js +25 -3
- package/dist/utils/jfl-paths.js.map +1 -1
- package/package.json +3 -2
- package/packages/pi/AGENTS.md +112 -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 +427 -0
- package/packages/pi/extensions/bookmarks.ts +85 -0
- package/packages/pi/extensions/context.ts +151 -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 +60 -0
- package/packages/pi/extensions/footer.ts +239 -0
- package/packages/pi/extensions/hud-tool.ts +145 -0
- package/packages/pi/extensions/index.ts +392 -0
- package/packages/pi/extensions/journal.ts +224 -0
- package/packages/pi/extensions/map-bridge.ts +178 -0
- package/packages/pi/extensions/memory-tool.ts +68 -0
- package/packages/pi/extensions/notifications.ts +73 -0
- package/packages/pi/extensions/peter-parker.ts +202 -0
- package/packages/pi/extensions/policy-head-tool.ts +276 -0
- package/packages/pi/extensions/portfolio-bridge.ts +90 -0
- package/packages/pi/extensions/session.ts +90 -0
- package/packages/pi/extensions/shortcuts.ts +259 -0
- package/packages/pi/extensions/stratus-bridge.ts +115 -0
- package/packages/pi/extensions/synopsis-tool.ts +83 -0
- package/packages/pi/extensions/tool-renderers.ts +352 -0
- package/packages/pi/extensions/training-buffer-tool.ts +368 -0
- package/packages/pi/extensions/types.ts +163 -0
- package/packages/pi/package-lock.json +346 -0
- package/packages/pi/package.json +44 -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 +1782 -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/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/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/collect-tuples.sh +124 -0
- package/scripts/destroy-fleet.sh +37 -0
- package/scripts/jfl-ide.sh +48 -0
- package/scripts/session/session-cleanup.sh +4 -11
- package/scripts/session/session-init.sh +6 -0
- package/scripts/session/session-sync.sh +25 -0
- package/scripts/setup-branch-protection.sh +106 -0
- package/scripts/spawn-fleet.sh +144 -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/template/.github/workflows/jfl-eval.yml +6 -1
- package/template/.github/workflows/jfl-review.yml +4 -0
- package/template/scripts/session/session-end.sh +69 -6
- package/template/scripts/session/session-init.sh +55 -30
- package/template/scripts/session/session-lock.sh +464 -0
- package/template/templates/service-agent/workflows/jfl-eval.yml +19 -0
- package/dist/dashboard-static/assets/index-B6kRK9Rq.js +0 -116
- package/dist/dashboard-static/assets/index-BpdKJPLu.css +0 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Peter Parker Extension — Full Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Replaces the WebSocket bridge with a proper Pi extension orchestrator.
|
|
5
|
+
* Subscribes to MAP events, queries Stratus predictor for optimal action,
|
|
6
|
+
* spawns Pi RPC subprocesses, and runs the review loop (max 5 iterations).
|
|
7
|
+
*
|
|
8
|
+
* @purpose Full Peter Parker orchestrator — review loop with Stratus dispatch via Pi RPC
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { spawn } from "child_process"
|
|
12
|
+
import { existsSync, readFileSync } from "fs"
|
|
13
|
+
import { join } from "path"
|
|
14
|
+
import type { PiContext, JflConfig } from "./types.js"
|
|
15
|
+
import { emitCustomEvent, hubUrl, authToken } from "./map-bridge.js"
|
|
16
|
+
|
|
17
|
+
interface ReviewTask {
|
|
18
|
+
id: string
|
|
19
|
+
prompt: string
|
|
20
|
+
source: string
|
|
21
|
+
priority?: number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface PeterIteration {
|
|
25
|
+
taskId: string
|
|
26
|
+
iteration: number
|
|
27
|
+
agentPid?: number
|
|
28
|
+
startTime: Date
|
|
29
|
+
prediction?: { delta: number; recommendation: string }
|
|
30
|
+
result?: "success" | "failed" | "max_iterations"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const MAX_ITERATIONS = 5
|
|
34
|
+
let projectRoot = ""
|
|
35
|
+
let maxIterations = MAX_ITERATIONS
|
|
36
|
+
let activeIterations = new Map<string, PeterIteration>()
|
|
37
|
+
|
|
38
|
+
async function getPredictor(root: string) {
|
|
39
|
+
try {
|
|
40
|
+
// @ts-ignore — resolved from jfl package at runtime
|
|
41
|
+
const { Predictor } = await import("../../src/lib/predictor.js")
|
|
42
|
+
return new Predictor(root)
|
|
43
|
+
} catch {
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function spawnPiAgent(
|
|
49
|
+
ctx: PiContext,
|
|
50
|
+
task: ReviewTask,
|
|
51
|
+
extensionPath: string
|
|
52
|
+
): Promise<{ exitCode: number | null }> {
|
|
53
|
+
return new Promise((resolve) => {
|
|
54
|
+
const args = [
|
|
55
|
+
"--mode", "rpc",
|
|
56
|
+
"--extension", extensionPath,
|
|
57
|
+
"--task", task.prompt,
|
|
58
|
+
"--yolo",
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
ctx.log(`PP: spawning agent for task ${task.id}`, "debug")
|
|
62
|
+
|
|
63
|
+
const proc = spawn("pi", args, {
|
|
64
|
+
cwd: projectRoot,
|
|
65
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
66
|
+
env: {
|
|
67
|
+
...process.env,
|
|
68
|
+
JFL_SESSION_ID: ctx.session.id,
|
|
69
|
+
JFL_TASK_ID: task.id,
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
proc.stdout?.on("data", (d: Buffer) => ctx.log(`PP agent: ${d.toString().trim()}`, "debug"))
|
|
74
|
+
proc.stderr?.on("data", (d: Buffer) => ctx.log(`PP agent err: ${d.toString().trim()}`, "debug"))
|
|
75
|
+
|
|
76
|
+
proc.on("close", (code) => resolve({ exitCode: code }))
|
|
77
|
+
proc.on("error", () => resolve({ exitCode: -1 }))
|
|
78
|
+
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
proc.kill()
|
|
81
|
+
resolve({ exitCode: -1 })
|
|
82
|
+
}, 5 * 60 * 1000)
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function runReviewLoop(ctx: PiContext, task: ReviewTask): Promise<void> {
|
|
87
|
+
const current = activeIterations.get(task.id)
|
|
88
|
+
const iteration = current ? current.iteration + 1 : 1
|
|
89
|
+
|
|
90
|
+
if (iteration > maxIterations) {
|
|
91
|
+
ctx.log(`PP: max iterations (${maxIterations}) reached for task ${task.id}`, "warn")
|
|
92
|
+
await emitCustomEvent(ctx, "peter:max-iterations", { taskId: task.id, iterations: iteration - 1 })
|
|
93
|
+
activeIterations.delete(task.id)
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const iterRecord: PeterIteration = {
|
|
98
|
+
taskId: task.id,
|
|
99
|
+
iteration,
|
|
100
|
+
startTime: new Date(),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const predictor = await getPredictor(projectRoot)
|
|
104
|
+
if (predictor) {
|
|
105
|
+
try {
|
|
106
|
+
const prediction = await predictor.predict({
|
|
107
|
+
proposal: {
|
|
108
|
+
description: task.prompt,
|
|
109
|
+
change_type: "fix",
|
|
110
|
+
scope: "small",
|
|
111
|
+
},
|
|
112
|
+
current_score: 0,
|
|
113
|
+
goal: "resolve review findings",
|
|
114
|
+
recent_trajectory: [],
|
|
115
|
+
})
|
|
116
|
+
iterRecord.prediction = { delta: prediction.predicted_delta, recommendation: prediction.recommendation }
|
|
117
|
+
|
|
118
|
+
if (prediction.recommendation === "abandon") {
|
|
119
|
+
ctx.log(`PP: predictor recommends abandon for task ${task.id}`, "info")
|
|
120
|
+
activeIterations.delete(task.id)
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
} catch {}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
activeIterations.set(task.id, iterRecord)
|
|
127
|
+
await emitCustomEvent(ctx, "peter:dispatched", { taskId: task.id, iteration, prediction: iterRecord.prediction })
|
|
128
|
+
|
|
129
|
+
const extensionPath = join(projectRoot, "node_modules", "@jfl", "pi", "dist", "extensions", "index.js")
|
|
130
|
+
const result = await spawnPiAgent(ctx, task, extensionPath)
|
|
131
|
+
|
|
132
|
+
iterRecord.result = result.exitCode === 0 ? "success" : "failed"
|
|
133
|
+
activeIterations.set(task.id, iterRecord)
|
|
134
|
+
|
|
135
|
+
if (result.exitCode !== 0) {
|
|
136
|
+
ctx.log(`PP: agent failed (iteration ${iteration}), will retry`, "info")
|
|
137
|
+
await runReviewLoop(ctx, task)
|
|
138
|
+
} else {
|
|
139
|
+
await emitCustomEvent(ctx, "peter:completed", { taskId: task.id, iterations: iteration })
|
|
140
|
+
activeIterations.delete(task.id)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export async function setupPeterParker(ctx: PiContext, config: JflConfig): Promise<void> {
|
|
145
|
+
projectRoot = ctx.session.projectRoot
|
|
146
|
+
maxIterations = config.pi?.max_peter_iterations ?? MAX_ITERATIONS
|
|
147
|
+
|
|
148
|
+
ctx.on("map:eval:scored", async (data) => {
|
|
149
|
+
const event = data as { taskId?: string; score?: number; findings?: string[] }
|
|
150
|
+
if (!event.taskId || !event.findings?.length) return
|
|
151
|
+
|
|
152
|
+
const task: ReviewTask = {
|
|
153
|
+
id: event.taskId,
|
|
154
|
+
prompt: `Review findings to address:\n${event.findings.join("\n")}`,
|
|
155
|
+
source: "eval:scored",
|
|
156
|
+
}
|
|
157
|
+
await runReviewLoop(ctx, task)
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
ctx.on("map:review:findings", async (data) => {
|
|
161
|
+
const event = data as { id?: string; findings?: string; priority?: number }
|
|
162
|
+
if (!event.findings) return
|
|
163
|
+
|
|
164
|
+
const task: ReviewTask = {
|
|
165
|
+
id: event.id ?? `review-${Date.now()}`,
|
|
166
|
+
prompt: event.findings,
|
|
167
|
+
source: "review:findings",
|
|
168
|
+
priority: event.priority,
|
|
169
|
+
}
|
|
170
|
+
await runReviewLoop(ctx, task)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
ctx.on("map:task:requested", async (data) => {
|
|
174
|
+
const event = data as { id?: string; prompt?: string }
|
|
175
|
+
if (!event.prompt) return
|
|
176
|
+
|
|
177
|
+
const task: ReviewTask = {
|
|
178
|
+
id: event.id ?? `task-${Date.now()}`,
|
|
179
|
+
prompt: event.prompt,
|
|
180
|
+
source: "task:requested",
|
|
181
|
+
}
|
|
182
|
+
await runReviewLoop(ctx, task)
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
ctx.registerCommand({
|
|
186
|
+
name: "peter",
|
|
187
|
+
description: "Peter Parker orchestrator — run a task through the review loop",
|
|
188
|
+
async handler(args, ctx) {
|
|
189
|
+
if (!args.trim()) {
|
|
190
|
+
ctx.ui.notify("Usage: /peter <task description>", { level: "info" })
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
const task: ReviewTask = {
|
|
194
|
+
id: `peter-${Date.now()}`,
|
|
195
|
+
prompt: args.trim(),
|
|
196
|
+
source: "manual",
|
|
197
|
+
}
|
|
198
|
+
ctx.ui.notify(`Starting Peter Parker loop for: ${args.trim().slice(0, 60)}`, { level: "info" })
|
|
199
|
+
await runReviewLoop(ctx, task)
|
|
200
|
+
},
|
|
201
|
+
})
|
|
202
|
+
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy Head Tool
|
|
3
|
+
*
|
|
4
|
+
* Exposes the RL policy head to the agent as a tool. The agent can score
|
|
5
|
+
* candidate actions before executing them — "should I fix this test or
|
|
6
|
+
* refactor that module?" — and get a predicted reward delta.
|
|
7
|
+
*
|
|
8
|
+
* Also registers /policy command to show policy head stats and rank
|
|
9
|
+
* ad-hoc proposals interactively.
|
|
10
|
+
*
|
|
11
|
+
* @purpose Pi tool for RL policy head — score candidate actions, rank proposals
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { existsSync, readFileSync } from "fs"
|
|
15
|
+
import { join } from "path"
|
|
16
|
+
import type { PiContext, JflConfig } from "./types.js"
|
|
17
|
+
import { emitCustomEvent } from "./map-bridge.js"
|
|
18
|
+
|
|
19
|
+
let projectRoot = ""
|
|
20
|
+
|
|
21
|
+
interface PolicyWeights {
|
|
22
|
+
version: number
|
|
23
|
+
trained_on: number
|
|
24
|
+
direction_accuracy: number
|
|
25
|
+
rank_correlation: number
|
|
26
|
+
target_mean: number
|
|
27
|
+
target_std: number
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getWeightsInfo(): PolicyWeights | null {
|
|
31
|
+
const weightsPath = join(projectRoot, ".jfl", "policy-weights.json")
|
|
32
|
+
if (!existsSync(weightsPath)) return null
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(readFileSync(weightsPath, "utf-8")) as PolicyWeights
|
|
35
|
+
} catch {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function getPolicyHead(): Promise<any> {
|
|
41
|
+
try {
|
|
42
|
+
// @ts-ignore — resolved from jfl package at runtime
|
|
43
|
+
const { PolicyHeadInference } = await import("../../src/lib/policy-head.js")
|
|
44
|
+
return new PolicyHeadInference(projectRoot)
|
|
45
|
+
} catch {
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function getTrainingBuffer(): Promise<any> {
|
|
51
|
+
try {
|
|
52
|
+
// @ts-ignore — resolved from jfl package at runtime
|
|
53
|
+
const { TrainingBuffer } = await import("../../src/lib/training-buffer.js")
|
|
54
|
+
return new TrainingBuffer(projectRoot)
|
|
55
|
+
} catch {
|
|
56
|
+
return null
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function setupPolicyHeadTool(ctx: PiContext, _config: JflConfig): Promise<void> {
|
|
61
|
+
projectRoot = ctx.session.projectRoot
|
|
62
|
+
|
|
63
|
+
ctx.registerTool({
|
|
64
|
+
name: "jfl_policy_score",
|
|
65
|
+
description: "Score a candidate action using the RL policy head. Returns predicted reward delta to help decide which action to take next. Requires trained policy weights (.jfl/policy-weights.json).",
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {
|
|
69
|
+
action_type: {
|
|
70
|
+
type: "string",
|
|
71
|
+
description: "Type of action",
|
|
72
|
+
enum: ["fix", "refactor", "feature", "test", "config", "experiment"],
|
|
73
|
+
},
|
|
74
|
+
description: {
|
|
75
|
+
type: "string",
|
|
76
|
+
description: "What the action does (1-2 sentences)",
|
|
77
|
+
},
|
|
78
|
+
files: {
|
|
79
|
+
type: "string",
|
|
80
|
+
description: "Comma-separated list of files affected",
|
|
81
|
+
},
|
|
82
|
+
scope: {
|
|
83
|
+
type: "string",
|
|
84
|
+
description: "Scope of change",
|
|
85
|
+
enum: ["small", "medium", "large"],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
required: ["action_type", "description"],
|
|
89
|
+
},
|
|
90
|
+
async handler(input) {
|
|
91
|
+
const {
|
|
92
|
+
action_type,
|
|
93
|
+
description,
|
|
94
|
+
files,
|
|
95
|
+
scope,
|
|
96
|
+
} = input as {
|
|
97
|
+
action_type: string
|
|
98
|
+
description: string
|
|
99
|
+
files?: string
|
|
100
|
+
scope?: string
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const policyHead = await getPolicyHead()
|
|
104
|
+
if (!policyHead || !policyHead.isLoaded) {
|
|
105
|
+
return "Policy head not available. No trained weights found at .jfl/policy-weights.json. Run `jfl eval train` to train the policy head from existing training tuples."
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const tb = await getTrainingBuffer()
|
|
109
|
+
const entries: any[] = tb ? tb.read() : []
|
|
110
|
+
const recentDeltas = entries.slice(-10).map((e: any) => e.reward.composite_delta)
|
|
111
|
+
|
|
112
|
+
const state = {
|
|
113
|
+
composite_score: entries.length > 0
|
|
114
|
+
? entries[entries.length - 1].reward.composite_delta + entries[entries.length - 1].state.composite_score
|
|
115
|
+
: 0,
|
|
116
|
+
dimension_scores: {} as Record<string, number>,
|
|
117
|
+
tests_passing: 0,
|
|
118
|
+
tests_total: 0,
|
|
119
|
+
trajectory_length: entries.length,
|
|
120
|
+
recent_deltas: recentDeltas,
|
|
121
|
+
agent: "pi-agent",
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const action = {
|
|
125
|
+
type: action_type as "fix" | "refactor" | "feature" | "test" | "config" | "experiment",
|
|
126
|
+
description,
|
|
127
|
+
files_affected: files ? files.split(",").map(f => f.trim()) : [],
|
|
128
|
+
scope: (scope || "medium") as "small" | "medium" | "large",
|
|
129
|
+
branch: ctx.session.branch,
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
const predicted = await policyHead.predictReward(state, action)
|
|
134
|
+
const stats = policyHead.stats
|
|
135
|
+
|
|
136
|
+
await emitCustomEvent(ctx, "policy:scored", {
|
|
137
|
+
action_type,
|
|
138
|
+
description: description.slice(0, 80),
|
|
139
|
+
predicted_reward: predicted,
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
const lines = [
|
|
143
|
+
`Predicted reward delta: ${predicted >= 0 ? "+" : ""}${predicted.toFixed(4)}`,
|
|
144
|
+
`Recommendation: ${predicted > 0.01 ? "PROCEED — positive expected outcome" : predicted > -0.005 ? "NEUTRAL — marginal expected impact" : "SKIP — negative expected outcome"}`,
|
|
145
|
+
"",
|
|
146
|
+
`Policy head stats:`,
|
|
147
|
+
` Trained on: ${stats?.trained_on ?? "?"} tuples`,
|
|
148
|
+
` Direction accuracy: ${stats?.direction_accuracy ? (stats.direction_accuracy * 100).toFixed(1) + "%" : "?"}`,
|
|
149
|
+
` Rank correlation: ${stats?.rank_correlation?.toFixed(3) ?? "?"}`,
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
return lines.join("\n")
|
|
153
|
+
} catch (err) {
|
|
154
|
+
return `Policy head inference failed: ${err}. Ensure STRATUS_API_KEY is set for embedding generation.`
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
ctx.registerTool({
|
|
160
|
+
name: "jfl_policy_rank",
|
|
161
|
+
description: "Rank multiple candidate actions by predicted reward. Pass 2-5 actions as JSON array. Returns ranked list with predicted deltas.",
|
|
162
|
+
inputSchema: {
|
|
163
|
+
type: "object",
|
|
164
|
+
properties: {
|
|
165
|
+
actions: {
|
|
166
|
+
type: "string",
|
|
167
|
+
description: 'JSON array of actions, each with: {"type": "fix|refactor|feature|test|config|experiment", "description": "what it does", "files": ["file1.ts"], "scope": "small|medium|large"}',
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
required: ["actions"],
|
|
171
|
+
},
|
|
172
|
+
async handler(input) {
|
|
173
|
+
const { actions: actionsStr } = input as { actions: string }
|
|
174
|
+
|
|
175
|
+
const policyHead = await getPolicyHead()
|
|
176
|
+
if (!policyHead || !policyHead.isLoaded) {
|
|
177
|
+
return "Policy head not available. No trained weights at .jfl/policy-weights.json."
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
let candidates: Array<{
|
|
181
|
+
type: string
|
|
182
|
+
description: string
|
|
183
|
+
files?: string[]
|
|
184
|
+
scope?: string
|
|
185
|
+
}>
|
|
186
|
+
try {
|
|
187
|
+
candidates = JSON.parse(actionsStr)
|
|
188
|
+
if (!Array.isArray(candidates) || candidates.length < 2) {
|
|
189
|
+
return "Provide at least 2 actions as a JSON array."
|
|
190
|
+
}
|
|
191
|
+
} catch {
|
|
192
|
+
return "Invalid JSON. Provide a JSON array of action objects."
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const tb = await getTrainingBuffer()
|
|
196
|
+
const entries: any[] = tb ? tb.read() : []
|
|
197
|
+
|
|
198
|
+
const state = {
|
|
199
|
+
composite_score: entries.length > 0
|
|
200
|
+
? entries[entries.length - 1].reward.composite_delta + entries[entries.length - 1].state.composite_score
|
|
201
|
+
: 0,
|
|
202
|
+
dimension_scores: {} as Record<string, number>,
|
|
203
|
+
tests_passing: 0,
|
|
204
|
+
tests_total: 0,
|
|
205
|
+
trajectory_length: entries.length,
|
|
206
|
+
recent_deltas: entries.slice(-10).map((e: any) => e.reward.composite_delta),
|
|
207
|
+
agent: "pi-agent",
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const rlActions = candidates.map(c => ({
|
|
211
|
+
type: (c.type || "feature") as "fix" | "refactor" | "feature" | "test" | "config" | "experiment",
|
|
212
|
+
description: c.description,
|
|
213
|
+
files_affected: c.files || [],
|
|
214
|
+
scope: (c.scope || "medium") as "small" | "medium" | "large",
|
|
215
|
+
branch: ctx.session.branch,
|
|
216
|
+
}))
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
const ranked = await policyHead.rankActions(state, rlActions)
|
|
220
|
+
|
|
221
|
+
await emitCustomEvent(ctx, "policy:ranked", {
|
|
222
|
+
count: ranked.length,
|
|
223
|
+
top: ranked[0]?.action.description.slice(0, 60),
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
const lines = ["Ranked actions (best first):", ""]
|
|
227
|
+
for (const r of ranked) {
|
|
228
|
+
const sign = r.predictedReward >= 0 ? "+" : ""
|
|
229
|
+
lines.push(` #${r.rank} [${sign}${r.predictedReward.toFixed(4)}] ${r.action.type}: ${r.action.description.slice(0, 80)}`)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return lines.join("\n")
|
|
233
|
+
} catch (err) {
|
|
234
|
+
return `Ranking failed: ${err}`
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
ctx.registerCommand({
|
|
240
|
+
name: "policy",
|
|
241
|
+
description: "Show policy head status and training buffer stats",
|
|
242
|
+
async handler(_args, ctx) {
|
|
243
|
+
const weights = getWeightsInfo()
|
|
244
|
+
const tb = await getTrainingBuffer()
|
|
245
|
+
const stats = tb ? tb.stats() : null
|
|
246
|
+
|
|
247
|
+
const lines: string[] = []
|
|
248
|
+
|
|
249
|
+
if (weights) {
|
|
250
|
+
lines.push(
|
|
251
|
+
"Policy Head: LOADED",
|
|
252
|
+
` Trained on: ${weights.trained_on} tuples`,
|
|
253
|
+
` Direction accuracy: ${(weights.direction_accuracy * 100).toFixed(1)}%`,
|
|
254
|
+
` Rank correlation: ${weights.rank_correlation.toFixed(3)}`,
|
|
255
|
+
"",
|
|
256
|
+
)
|
|
257
|
+
} else {
|
|
258
|
+
lines.push("Policy Head: NOT LOADED (no .jfl/policy-weights.json)", "")
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (stats) {
|
|
262
|
+
lines.push(
|
|
263
|
+
`Training Buffer: ${stats.total} tuples`,
|
|
264
|
+
` Avg reward: ${stats.avgReward.toFixed(4)}`,
|
|
265
|
+
` Improvement rate: ${(stats.improvedRate * 100).toFixed(1)}%`,
|
|
266
|
+
` By agent: ${Object.entries(stats.byAgent).map(([k, v]) => `${k}=${v}`).join(", ") || "none"}`,
|
|
267
|
+
` By source: ${Object.entries(stats.bySource).map(([k, v]) => `${k}=${v}`).join(", ") || "none"}`,
|
|
268
|
+
)
|
|
269
|
+
} else {
|
|
270
|
+
lines.push("Training Buffer: empty or unavailable")
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
ctx.ui.notify(lines.join("\n"), { level: "info" })
|
|
274
|
+
},
|
|
275
|
+
})
|
|
276
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portfolio Bridge Extension
|
|
3
|
+
*
|
|
4
|
+
* Handles cross-GTM coordination: phoneHome on session end, journal sync to parent,
|
|
5
|
+
* and eval scores propagated to portfolio hub for cross-GTM RL training.
|
|
6
|
+
*
|
|
7
|
+
* @purpose Portfolio-GTM coordination — phoneHome, journal sync, eval propagation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { existsSync, readFileSync } from "fs"
|
|
11
|
+
import { join } from "path"
|
|
12
|
+
import type { PiContext, JflConfig } from "./types.js"
|
|
13
|
+
import { emitCustomEvent } from "./map-bridge.js"
|
|
14
|
+
|
|
15
|
+
let projectRoot = ""
|
|
16
|
+
let portfolioParent: string | null = null
|
|
17
|
+
|
|
18
|
+
async function phoneHome(ctx: PiContext): Promise<void> {
|
|
19
|
+
if (!portfolioParent || !existsSync(portfolioParent)) return
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
// @ts-ignore — resolved from jfl package at runtime
|
|
23
|
+
const { phoneHomeToPortfolio } = await import("../../src/lib/service-gtm.js")
|
|
24
|
+
await phoneHomeToPortfolio(projectRoot)
|
|
25
|
+
ctx.log("Portfolio phoneHome complete", "debug")
|
|
26
|
+
} catch (err) {
|
|
27
|
+
ctx.log(`Portfolio phoneHome failed: ${err}`, "debug")
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function syncJournalEntry(ctx: PiContext, entry: unknown): Promise<void> {
|
|
32
|
+
if (!portfolioParent || !existsSync(portfolioParent)) return
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// @ts-ignore — resolved from jfl package at runtime
|
|
36
|
+
const { writeSyncToParent } = await import("../../src/lib/service-gtm.js")
|
|
37
|
+
await (writeSyncToParent as (root: string, entry: unknown) => Promise<void>)(projectRoot, entry)
|
|
38
|
+
} catch (err) {
|
|
39
|
+
ctx.log(`Journal sync to parent failed: ${err}`, "debug")
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function propagateEvalToPortfolio(ctx: PiContext, evalData: unknown): Promise<void> {
|
|
44
|
+
if (!portfolioParent) return
|
|
45
|
+
|
|
46
|
+
const portfolioConfigPath = join(portfolioParent, ".jfl", "context-hub.port")
|
|
47
|
+
if (!existsSync(portfolioConfigPath)) return
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const port = readFileSync(portfolioConfigPath, "utf-8").trim()
|
|
51
|
+
const portfolioHub = `http://localhost:${port}`
|
|
52
|
+
const tokenPath = join(portfolioParent, ".jfl", "context-hub.token")
|
|
53
|
+
const token = existsSync(tokenPath) ? readFileSync(tokenPath, "utf-8").trim() : null
|
|
54
|
+
|
|
55
|
+
await fetch(`${portfolioHub}/api/events`, {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: {
|
|
58
|
+
"Content-Type": "application/json",
|
|
59
|
+
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
60
|
+
},
|
|
61
|
+
body: JSON.stringify({
|
|
62
|
+
type: "eval:scored",
|
|
63
|
+
source: projectRoot,
|
|
64
|
+
data: evalData,
|
|
65
|
+
ts: new Date().toISOString(),
|
|
66
|
+
}),
|
|
67
|
+
})
|
|
68
|
+
} catch {}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function setupPortfolioBridge(ctx: PiContext, config: JflConfig): Promise<void> {
|
|
72
|
+
projectRoot = ctx.session.projectRoot
|
|
73
|
+
portfolioParent = config.portfolio_parent ?? null
|
|
74
|
+
|
|
75
|
+
if (!portfolioParent) return
|
|
76
|
+
|
|
77
|
+
ctx.on("map:journal:entry", (data) => syncJournalEntry(ctx, data))
|
|
78
|
+
|
|
79
|
+
ctx.on("map:eval:scored", (data) => propagateEvalToPortfolio(ctx, data))
|
|
80
|
+
|
|
81
|
+
ctx.on("map:portfolio:directive", async (data) => {
|
|
82
|
+
const directive = data as { action?: string; payload?: unknown }
|
|
83
|
+
ctx.log(`Portfolio directive received: ${directive.action}`, "info")
|
|
84
|
+
await emitCustomEvent(ctx, "portfolio:directive:received", directive)
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function onPortfolioShutdown(ctx: PiContext): Promise<void> {
|
|
89
|
+
await phoneHome(ctx)
|
|
90
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JFL Session Extension
|
|
3
|
+
*
|
|
4
|
+
* Handles auto-commit and session cleanup within a Pi session.
|
|
5
|
+
* Does NOT run session-init.sh — that script is a Claude Code pre-hook that
|
|
6
|
+
* launches the AI CLI, which would cause a double-launch inside Pi.
|
|
7
|
+
* Pi IS the AI runtime; we only handle the persistent background tasks here.
|
|
8
|
+
*
|
|
9
|
+
* @purpose Pi session lifecycle — auto-commit daemon + cleanup script delegation
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { execSync, spawn } from "child_process"
|
|
13
|
+
import { existsSync, readFileSync } from "fs"
|
|
14
|
+
import { join } from "path"
|
|
15
|
+
import type { PiContext, JflConfig } from "./types.js"
|
|
16
|
+
|
|
17
|
+
let autoCommitProcess: ReturnType<typeof spawn> | null = null
|
|
18
|
+
|
|
19
|
+
function findScript(root: string, scriptName: string): string | null {
|
|
20
|
+
const candidates = [
|
|
21
|
+
join(root, "scripts", "session", scriptName),
|
|
22
|
+
join(root, "scripts", scriptName),
|
|
23
|
+
]
|
|
24
|
+
for (const candidate of candidates) {
|
|
25
|
+
if (existsSync(candidate)) return candidate
|
|
26
|
+
}
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function setupSession(ctx: PiContext, _config: JflConfig): Promise<void> {
|
|
31
|
+
const root = ctx.session.projectRoot
|
|
32
|
+
|
|
33
|
+
// Start auto-commit daemon — detached so it outlives this call
|
|
34
|
+
const autoCommitScript = findScript(root, "auto-commit.sh")
|
|
35
|
+
if (autoCommitScript) {
|
|
36
|
+
autoCommitProcess = spawn("bash", [autoCommitScript, "start", "120"], {
|
|
37
|
+
cwd: root,
|
|
38
|
+
detached: true,
|
|
39
|
+
stdio: "ignore",
|
|
40
|
+
})
|
|
41
|
+
autoCommitProcess.unref()
|
|
42
|
+
ctx.log("Auto-commit daemon started (120s interval)", "debug")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
ctx.emit("hook:session-start", {
|
|
46
|
+
session: ctx.session.id,
|
|
47
|
+
branch: ctx.session.branch,
|
|
48
|
+
projectRoot: root,
|
|
49
|
+
ts: new Date().toISOString(),
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function onShutdown(ctx: PiContext): Promise<void> {
|
|
54
|
+
const root = ctx.session.projectRoot
|
|
55
|
+
|
|
56
|
+
if (autoCommitProcess) {
|
|
57
|
+
try {
|
|
58
|
+
autoCommitProcess.kill()
|
|
59
|
+
} catch {}
|
|
60
|
+
autoCommitProcess = null
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const cleanupScript = findScript(root, "session-cleanup.sh")
|
|
64
|
+
if (cleanupScript) {
|
|
65
|
+
try {
|
|
66
|
+
execSync(`bash "${cleanupScript}"`, { cwd: root, stdio: "inherit" })
|
|
67
|
+
} catch (err) {
|
|
68
|
+
ctx.log(`session-cleanup.sh failed: ${err}`, "warn")
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ctx.emit("hook:session-end", {
|
|
73
|
+
session: ctx.session.id,
|
|
74
|
+
branch: ctx.session.branch,
|
|
75
|
+
ts: new Date().toISOString(),
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function getCurrentBranch(root: string): string {
|
|
80
|
+
try {
|
|
81
|
+
return execSync("git branch --show-current", { cwd: root }).toString().trim()
|
|
82
|
+
} catch {
|
|
83
|
+
try {
|
|
84
|
+
const saved = readFileSync(join(root, ".jfl", "current-session-branch.txt"), "utf-8").trim()
|
|
85
|
+
return saved
|
|
86
|
+
} catch {
|
|
87
|
+
return "main"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|