@wrongstack/cli 0.297.0 → 0.298.1
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/{acp-A5OSIU2P.js → acp-S4LZQB66.js} +91 -23
- package/dist/{auth-CJWQJVRH.js → auth-NLLGEYQR.js} +3 -3
- package/dist/boot/governance-evidence-candidate.d.ts +3 -0
- package/dist/boot/governance-shadow-bridge.d.ts +19 -0
- package/dist/boot/governance-trace-context.d.ts +64 -0
- package/dist/boot/tui-session-resume.d.ts +10 -1
- package/dist/chimera-reviewer-policy.d.ts +89 -1
- package/dist/chimera-subagent-ladder.d.ts +72 -0
- package/dist/{chunk-AZESNNIC.js → chunk-4HH3YGG4.js} +3 -3
- package/dist/{chunk-QUNHS6O3.js → chunk-4U3DMA2Y.js} +2 -2
- package/dist/{chunk-IHBYBYGA.js → chunk-A6Q5KGLV.js} +51 -18
- package/dist/{chunk-ABXK4VVY.js → chunk-ARWGQUB3.js} +2 -1
- package/dist/{chunk-7JABKXET.js → chunk-C5GH4YBL.js} +1018 -175
- package/dist/{chunk-TADVX644.js → chunk-GO3TJICK.js} +11 -2
- package/dist/{chunk-JBTFWWKV.js → chunk-I2BM6FK6.js} +9 -4
- package/dist/{chunk-AXVZMEWG.js → chunk-I5MEUFDI.js} +2 -2
- package/dist/{chunk-XWEGWYDU.js → chunk-PEKUKUCH.js} +4 -71
- package/dist/chunk-U3SS4NRH.js +10 -0
- package/dist/{chunk-QZKWRNIP.js → chunk-V3XH6XBJ.js} +12 -9
- package/dist/{cli-main-GOY5YGVL.js → cli-main-7QLL2PY6.js} +957 -271
- package/dist/cli-main-helpers.d.ts +42 -2
- package/dist/{execution-A4PGK4XV.js → execution-HJ643JGZ.js} +834 -676
- package/dist/execution-chimera-cascade.d.ts +7 -1
- package/dist/execution-chimera-review.d.ts +35 -0
- package/dist/fleet/host-types.d.ts +6 -1
- package/dist/fleet-statusline.d.ts +1 -0
- package/dist/governance-V2Z42RBE.js +65 -0
- package/dist/governance-hq-telemetry.d.ts +17 -0
- package/dist/{hq-GBPGXIR5.js → hq-WO6CLUSI.js} +2 -2
- package/dist/hq-server/auth.d.ts +33 -2
- package/dist/hq-server/login-attempt-store.d.ts +73 -0
- package/dist/hq-server/routes/auth-handlers.d.ts +73 -5
- package/dist/hq-server/routes.d.ts +5 -5
- package/dist/hq-server/types.d.ts +36 -2
- package/dist/hq-server/utils.d.ts +51 -6
- package/dist/{hq-server-YQUUMTPU.js → hq-server-6TSAORAC.js} +2 -2
- package/dist/hq-server.d.ts +10 -0
- package/dist/index.js +52 -24
- package/dist/live-settings-input.d.ts +4 -3
- package/dist/plugin-management.d.ts +3 -8
- package/dist/{plugin-usage-OU6X6LM3.js → plugin-usage-VTL7ZTVC.js} +2 -2
- package/dist/{plugins-4LJ5IUBI.js → plugins-ETY6W3DC.js} +3 -3
- package/dist/settings-menu.d.ts +1 -1
- package/dist/slash-commands/fallback.d.ts +2 -0
- package/dist/slash-commands/goal-refiner.d.ts +1 -1
- package/dist/subcommands/handlers/acp-connection-gate.d.ts +20 -0
- package/dist/subcommands/handlers/governance.d.ts +8 -0
- package/dist/{update-YC4TYW2Y.js → update-MV6TUACD.js} +3 -3
- package/dist/utils/win32-cmd.d.ts +9 -6
- package/dist/{version-help-DROHZRW6.js → version-help-ASKQYXDJ.js} +2 -2
- package/dist/{webui-server-XKFUOKMJ.js → webui-server-PCLSXX6L.js} +10 -3
- package/dist/wiring/brain-and-orchestration.d.ts +2 -0
- package/dist/wiring/provider-runtime-setup.d.ts +2 -2
- package/package.json +24 -23
- package/dist/acp-A5OSIU2P.js.map +0 -7
- package/dist/acp-registry-cache.d.ts.map +0 -1
- package/dist/acp-server-agent.d.ts.map +0 -1
- package/dist/arg-parser.d.ts.map +0 -1
- package/dist/audit-2ZSFGNIF.js.map +0 -7
- package/dist/auth-CJWQJVRH.js.map +0 -7
- package/dist/auth-menu/add-provider.d.ts.map +0 -1
- package/dist/auth-menu/anthropic-oauth.d.ts.map +0 -1
- package/dist/auth-menu/auth-menu-audit.d.ts.map +0 -1
- package/dist/auth-menu/direct.d.ts.map +0 -1
- package/dist/auth-menu/github-copilot-oauth.d.ts.map +0 -1
- package/dist/auth-menu/helpers.d.ts.map +0 -1
- package/dist/auth-menu/index.d.ts.map +0 -1
- package/dist/auth-menu/local-presets.d.ts.map +0 -1
- package/dist/auth-menu/local.d.ts.map +0 -1
- package/dist/auth-menu/loopback-server.d.ts.map +0 -1
- package/dist/auth-menu/oauth-menu.d.ts.map +0 -1
- package/dist/auth-menu/openai-codex-oauth.d.ts.map +0 -1
- package/dist/auth-menu/panel-service.d.ts.map +0 -1
- package/dist/auth-menu/provider-menu.d.ts.map +0 -1
- package/dist/auth-menu/shared.d.ts.map +0 -1
- package/dist/auth-menu/top-menu.d.ts.map +0 -1
- package/dist/auth-menu/types.d.ts.map +0 -1
- package/dist/auth-menu.d.ts.map +0 -1
- package/dist/bench-7ZDWSNEF.js.map +0 -7
- package/dist/boot/auto-discover-providers.d.ts.map +0 -1
- package/dist/boot/brain-decision-log.d.ts.map +0 -1
- package/dist/boot/config-backup-recovery.d.ts.map +0 -1
- package/dist/boot/container-wiring.d.ts.map +0 -1
- package/dist/boot/dispatch-singleshot.d.ts.map +0 -1
- package/dist/boot/dispatch-tui.d.ts.map +0 -1
- package/dist/boot/dispatch-webui.d.ts.map +0 -1
- package/dist/boot/event-wiring.d.ts.map +0 -1
- package/dist/boot/execution-mode.d.ts.map +0 -1
- package/dist/boot/launch-banner.d.ts.map +0 -1
- package/dist/boot/launch-menu.d.ts.map +0 -1
- package/dist/boot/short-circuit-desktop.d.ts.map +0 -1
- package/dist/boot/short-circuit-flags.d.ts.map +0 -1
- package/dist/boot/short-circuit-hq.d.ts.map +0 -1
- package/dist/boot/simpleui-full-auto.d.ts.map +0 -1
- package/dist/boot/system-prompt-builder.d.ts.map +0 -1
- package/dist/boot/system-prompt.d.ts.map +0 -1
- package/dist/boot/tool-registry.d.ts.map +0 -1
- package/dist/boot/tui-coordinator-callbacks.d.ts.map +0 -1
- package/dist/boot/tui-coordinator-setup.d.ts.map +0 -1
- package/dist/boot/tui-debug-stream.d.ts.map +0 -1
- package/dist/boot/tui-goal-wiring.d.ts.map +0 -1
- package/dist/boot/tui-live-sessions.d.ts.map +0 -1
- package/dist/boot/tui-project-picker-callback.d.ts.map +0 -1
- package/dist/boot/tui-project-spawn.d.ts.map +0 -1
- package/dist/boot/tui-project-switch.d.ts.map +0 -1
- package/dist/boot/tui-runtime-state.d.ts.map +0 -1
- package/dist/boot/tui-sdd-callback.d.ts.map +0 -1
- package/dist/boot/tui-session-resume.d.ts.map +0 -1
- package/dist/boot/tui-settings-adapter.d.ts.map +0 -1
- package/dist/boot-config.d.ts.map +0 -1
- package/dist/boot.d.ts.map +0 -1
- package/dist/brain-menu/panel-service.d.ts.map +0 -1
- package/dist/chimera-review-task.d.ts.map +0 -1
- package/dist/chimera-reviewer-policy.d.ts.map +0 -1
- package/dist/chronicle-QQEQFSSE.js.map +0 -7
- package/dist/chunk-5N34EWJR.js.map +0 -7
- package/dist/chunk-66T43Q4Y.js.map +0 -7
- package/dist/chunk-7JABKXET.js.map +0 -7
- package/dist/chunk-7OCVIDC7.js.map +0 -7
- package/dist/chunk-ABXK4VVY.js.map +0 -7
- package/dist/chunk-AXVZMEWG.js.map +0 -7
- package/dist/chunk-AZESNNIC.js.map +0 -7
- package/dist/chunk-BGFM3PD7.js.map +0 -7
- package/dist/chunk-DPJZQCVP.js.map +0 -7
- package/dist/chunk-F4PEGAJZ.js.map +0 -7
- package/dist/chunk-IHBYBYGA.js.map +0 -7
- package/dist/chunk-JBSQ7ONN.js.map +0 -7
- package/dist/chunk-JBTFWWKV.js.map +0 -7
- package/dist/chunk-JUHRI6OV.js.map +0 -7
- package/dist/chunk-JW75HY4F.js.map +0 -7
- package/dist/chunk-OP47B3IX.js.map +0 -7
- package/dist/chunk-PJHET45A.js.map +0 -7
- package/dist/chunk-Q5GTM25S.js.map +0 -7
- package/dist/chunk-QD544J2B.js.map +0 -7
- package/dist/chunk-QUNHS6O3.js.map +0 -7
- package/dist/chunk-QZKWRNIP.js.map +0 -7
- package/dist/chunk-TADVX644.js.map +0 -7
- package/dist/chunk-TGDHN4LM.js.map +0 -7
- package/dist/chunk-TYO2OVAD.js.map +0 -7
- package/dist/chunk-VCYZ3WZV.js.map +0 -7
- package/dist/chunk-VJUEZZYB.js +0 -29
- package/dist/chunk-VJUEZZYB.js.map +0 -7
- package/dist/chunk-WHOIR577.js.map +0 -7
- package/dist/chunk-XJXDOF63.js.map +0 -7
- package/dist/chunk-XTIXVJXP.js.map +0 -7
- package/dist/chunk-XWEGWYDU.js.map +0 -7
- package/dist/chunk-YWUPHRGB.js.map +0 -7
- package/dist/cli-bundled-prompts.d.ts.map +0 -1
- package/dist/cli-bundled-skills.d.ts.map +0 -1
- package/dist/cli-context.d.ts.map +0 -1
- package/dist/cli-entry-main.d.ts.map +0 -1
- package/dist/cli-entry-point.d.ts.map +0 -1
- package/dist/cli-eternal-flag.d.ts.map +0 -1
- package/dist/cli-main-GOY5YGVL.js.map +0 -7
- package/dist/cli-main-helpers.d.ts.map +0 -1
- package/dist/cli-main.d.ts.map +0 -1
- package/dist/cli-update-notice.d.ts.map +0 -1
- package/dist/config-doctor.d.ts.map +0 -1
- package/dist/config-history.d.ts.map +0 -1
- package/dist/context-limit.d.ts.map +0 -1
- package/dist/context-overflow-diagnostic.d.ts.map +0 -1
- package/dist/diag-doctor-OQ3AA63O.js.map +0 -7
- package/dist/diff-renderer.d.ts.map +0 -1
- package/dist/execute-deps.d.ts.map +0 -1
- package/dist/execution-A4PGK4XV.js.map +0 -7
- package/dist/execution-chimera-ask.d.ts +0 -10
- package/dist/execution-chimera-ask.d.ts.map +0 -1
- package/dist/execution-chimera-cascade.d.ts.map +0 -1
- package/dist/execution-cleanup.d.ts.map +0 -1
- package/dist/execution-kanban-dispatch.d.ts.map +0 -1
- package/dist/execution-repl-fleet-callbacks.d.ts.map +0 -1
- package/dist/execution-storage-observability.d.ts.map +0 -1
- package/dist/execution-tui-next-step-callbacks.d.ts.map +0 -1
- package/dist/execution.d.ts.map +0 -1
- package/dist/export-TPORYVRZ.js.map +0 -7
- package/dist/fleet/host-acp-runner-cache.d.ts.map +0 -1
- package/dist/fleet/host-acp.d.ts.map +0 -1
- package/dist/fleet/host-concurrency.d.ts.map +0 -1
- package/dist/fleet/host-context.d.ts.map +0 -1
- package/dist/fleet/host-director-builder.d.ts.map +0 -1
- package/dist/fleet/host-director-event-bridges.d.ts.map +0 -1
- package/dist/fleet/host-director-services.d.ts.map +0 -1
- package/dist/fleet/host-event-bridge.d.ts.map +0 -1
- package/dist/fleet/host-helpers.d.ts.map +0 -1
- package/dist/fleet/host-learning-tracker.d.ts.map +0 -1
- package/dist/fleet/host-learning.d.ts.map +0 -1
- package/dist/fleet/host-lifecycle-events.d.ts.map +0 -1
- package/dist/fleet/host-paths.d.ts.map +0 -1
- package/dist/fleet/host-provider.d.ts.map +0 -1
- package/dist/fleet/host-session-writer.d.ts.map +0 -1
- package/dist/fleet/host-shadow-pass.d.ts.map +0 -1
- package/dist/fleet/host-spawn-types.d.ts.map +0 -1
- package/dist/fleet/host-status.d.ts.map +0 -1
- package/dist/fleet/host-subagent-factory.d.ts.map +0 -1
- package/dist/fleet/host-supervisor.d.ts.map +0 -1
- package/dist/fleet/host-task-result-report.d.ts.map +0 -1
- package/dist/fleet/host-types.d.ts.map +0 -1
- package/dist/fleet/host.d.ts.map +0 -1
- package/dist/fleet/routing.d.ts.map +0 -1
- package/dist/fleet/status-broadcast.d.ts.map +0 -1
- package/dist/fleet/supervisor-registry.d.ts.map +0 -1
- package/dist/fleet-statusline.d.ts.map +0 -1
- package/dist/goal-host.d.ts.map +0 -1
- package/dist/hooks-wiring.d.ts.map +0 -1
- package/dist/hq-GBPGXIR5.js.map +0 -7
- package/dist/hq-command-controller.d.ts.map +0 -1
- package/dist/hq-publisher.d.ts.map +0 -1
- package/dist/hq-recovery-html.d.ts.map +0 -1
- package/dist/hq-server/audit-actor.d.ts.map +0 -1
- package/dist/hq-server/auth-state.d.ts.map +0 -1
- package/dist/hq-server/auth.d.ts.map +0 -1
- package/dist/hq-server/preflight.d.ts.map +0 -1
- package/dist/hq-server/project-root.d.ts.map +0 -1
- package/dist/hq-server/routes/auth-handlers.d.ts.map +0 -1
- package/dist/hq-server/routes/session-handlers.d.ts.map +0 -1
- package/dist/hq-server/routes/system-handlers.d.ts.map +0 -1
- package/dist/hq-server/routes.d.ts.map +0 -1
- package/dist/hq-server/snapshot.d.ts.map +0 -1
- package/dist/hq-server/startup.d.ts.map +0 -1
- package/dist/hq-server/trust-boundary.d.ts.map +0 -1
- package/dist/hq-server/types.d.ts.map +0 -1
- package/dist/hq-server/utils.d.ts.map +0 -1
- package/dist/hq-server/ws.d.ts.map +0 -1
- package/dist/hq-server-YQUUMTPU.js.map +0 -7
- package/dist/hq-server.d.ts.map +0 -1
- package/dist/hq-static-serve.d.ts.map +0 -1
- package/dist/hq-ttl-U2FAYFAT.js.map +0 -7
- package/dist/hq-tunnel-RFKGC4HI.js.map +0 -7
- package/dist/hq-tunnel.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -7
- package/dist/init-E2NDDOHI.js.map +0 -7
- package/dist/input-reader.d.ts.map +0 -1
- package/dist/kanban-dispatch-route.d.ts.map +0 -1
- package/dist/kanban-hq-sync.d.ts.map +0 -1
- package/dist/kanban-run-mirror-EKVNGXWW.js.map +0 -7
- package/dist/launch-hints.d.ts.map +0 -1
- package/dist/live-settings-input.d.ts.map +0 -1
- package/dist/mailbox-bridge-bootstrap.d.ts.map +0 -1
- package/dist/mailbox-serve-DBOOOOWZ.js.map +0 -7
- package/dist/mcp-CYLPUEHC.js.map +0 -7
- package/dist/mcp-serve.d.ts.map +0 -1
- package/dist/modeldiag-HENYJ4N7.js.map +0 -7
- package/dist/multi-agent.d.ts.map +0 -1
- package/dist/next-task-predictor.d.ts.map +0 -1
- package/dist/permission-prompt.d.ts.map +0 -1
- package/dist/permissions-FNYLZIL4.js.map +0 -7
- package/dist/picker-key-state.d.ts.map +0 -1
- package/dist/picker-model-picker.d.ts.map +0 -1
- package/dist/picker-ui.d.ts.map +0 -1
- package/dist/picker.d.ts.map +0 -1
- package/dist/plugin-api-factory.d.ts.map +0 -1
- package/dist/plugin-management.d.ts.map +0 -1
- package/dist/plugin-usage-OU6X6LM3.js.map +0 -7
- package/dist/plugins-4LJ5IUBI.js.map +0 -7
- package/dist/pre-launch/launch-prompts.d.ts.map +0 -1
- package/dist/pre-launch/project-check.d.ts.map +0 -1
- package/dist/pre-launch.d.ts.map +0 -1
- package/dist/preflight.d.ts.map +0 -1
- package/dist/profile-config-path.d.ts.map +0 -1
- package/dist/project-BLQ3ALVL.js.map +0 -7
- package/dist/project-manifest-GE25PW4S.js.map +0 -7
- package/dist/project-picker-BOCWHBXP.js.map +0 -7
- package/dist/project-picker.d.ts.map +0 -1
- package/dist/projects-XE76NFNZ.js.map +0 -7
- package/dist/provider-config-utils.d.ts.map +0 -1
- package/dist/provider-helpers.d.ts.map +0 -1
- package/dist/provider-id.d.ts.map +0 -1
- package/dist/providers-models-GDELBHZK.js.map +0 -7
- package/dist/quick-VIO2BEHS.js.map +0 -7
- package/dist/renderer.d.ts.map +0 -1
- package/dist/repl-auto-proceed.d.ts.map +0 -1
- package/dist/repl-client-registration.d.ts.map +0 -1
- package/dist/repl-input.d.ts.map +0 -1
- package/dist/repl-options.d.ts.map +0 -1
- package/dist/repl-rendering.d.ts.map +0 -1
- package/dist/repl-suggestions.d.ts.map +0 -1
- package/dist/repl.d.ts.map +0 -1
- package/dist/replay-KCTXNMZQ.js.map +0 -7
- package/dist/rewind-EJMVFVLS.js.map +0 -7
- package/dist/sdd-runtime-AIJCJGWC.js.map +0 -7
- package/dist/services/autonomy-mode.d.ts.map +0 -1
- package/dist/services/commit-message.d.ts.map +0 -1
- package/dist/services/dispatch-classifier.d.ts.map +0 -1
- package/dist/services/mcp-management.d.ts.map +0 -1
- package/dist/services/project-facts.d.ts.map +0 -1
- package/dist/services/project-manifest.d.ts.map +0 -1
- package/dist/services/sdd/project-context.d.ts.map +0 -1
- package/dist/services/sdd/spec-detection.d.ts.map +0 -1
- package/dist/services/sdd/state.d.ts.map +0 -1
- package/dist/services/sdd/task-manager.d.ts.map +0 -1
- package/dist/services/sdd-runtime.d.ts.map +0 -1
- package/dist/services/statusline-config.d.ts.map +0 -1
- package/dist/services/suggestion-store.d.ts.map +0 -1
- package/dist/session-event-wiring.d.ts.map +0 -1
- package/dist/session-stats.d.ts.map +0 -1
- package/dist/sessions-config-NLCMK3BY.js.map +0 -7
- package/dist/settings-menu.d.ts.map +0 -1
- package/dist/shutdown-cleanup.d.ts.map +0 -1
- package/dist/simpleui-dist-JIFGUJO7.js.map +0 -7
- package/dist/simpleui-dist.d.ts.map +0 -1
- package/dist/slash-commands/acp.d.ts.map +0 -1
- package/dist/slash-commands/agent-improve.d.ts.map +0 -1
- package/dist/slash-commands/agents.d.ts.map +0 -1
- package/dist/slash-commands/audit.d.ts.map +0 -1
- package/dist/slash-commands/auth.d.ts.map +0 -1
- package/dist/slash-commands/autonomy.d.ts.map +0 -1
- package/dist/slash-commands/brain.d.ts.map +0 -1
- package/dist/slash-commands/btw.d.ts.map +0 -1
- package/dist/slash-commands/clear.d.ts.map +0 -1
- package/dist/slash-commands/codebase-reindex.d.ts.map +0 -1
- package/dist/slash-commands/collab.d.ts.map +0 -1
- package/dist/slash-commands/command-context.d.ts.map +0 -1
- package/dist/slash-commands/commit-llm.d.ts.map +0 -1
- package/dist/slash-commands/compact.d.ts.map +0 -1
- package/dist/slash-commands/context.d.ts.map +0 -1
- package/dist/slash-commands/coordinator.d.ts.map +0 -1
- package/dist/slash-commands/delegate.d.ts.map +0 -1
- package/dist/slash-commands/design.d.ts.map +0 -1
- package/dist/slash-commands/dev.d.ts.map +0 -1
- package/dist/slash-commands/diag-stats.d.ts.map +0 -1
- package/dist/slash-commands/dispatch-llm.d.ts.map +0 -1
- package/dist/slash-commands/doctor.d.ts.map +0 -1
- package/dist/slash-commands/enhance.d.ts.map +0 -1
- package/dist/slash-commands/ensemble.d.ts.map +0 -1
- package/dist/slash-commands/f-keys.d.ts.map +0 -1
- package/dist/slash-commands/fallback.d.ts.map +0 -1
- package/dist/slash-commands/fix-classifier.d.ts.map +0 -1
- package/dist/slash-commands/fix.d.ts.map +0 -1
- package/dist/slash-commands/fleet.d.ts.map +0 -1
- package/dist/slash-commands/git.d.ts.map +0 -1
- package/dist/slash-commands/gitid.d.ts.map +0 -1
- package/dist/slash-commands/goal-refiner.d.ts.map +0 -1
- package/dist/slash-commands/goal.d.ts.map +0 -1
- package/dist/slash-commands/health.d.ts.map +0 -1
- package/dist/slash-commands/help.d.ts.map +0 -1
- package/dist/slash-commands/helpers.d.ts.map +0 -1
- package/dist/slash-commands/hq.d.ts.map +0 -1
- package/dist/slash-commands/index.d.ts.map +0 -1
- package/dist/slash-commands/init.d.ts.map +0 -1
- package/dist/slash-commands/interrupt.d.ts.map +0 -1
- package/dist/slash-commands/kanban-agent-helpers.d.ts.map +0 -1
- package/dist/slash-commands/kanban-format.d.ts.map +0 -1
- package/dist/slash-commands/kanban-help.d.ts.map +0 -1
- package/dist/slash-commands/kanban.d.ts.map +0 -1
- package/dist/slash-commands/mailbox-demo.d.ts.map +0 -1
- package/dist/slash-commands/mailbox-serve.d.ts.map +0 -1
- package/dist/slash-commands/mailbox.d.ts.map +0 -1
- package/dist/slash-commands/mcp-utils.d.ts.map +0 -1
- package/dist/slash-commands/mcp.d.ts.map +0 -1
- package/dist/slash-commands/memory-compact.d.ts.map +0 -1
- package/dist/slash-commands/memory-flags.d.ts.map +0 -1
- package/dist/slash-commands/memory-formatters.d.ts.map +0 -1
- package/dist/slash-commands/memory.d.ts.map +0 -1
- package/dist/slash-commands/metrics.d.ts.map +0 -1
- package/dist/slash-commands/mode.d.ts.map +0 -1
- package/dist/slash-commands/modelcaps.d.ts.map +0 -1
- package/dist/slash-commands/models.d.ts.map +0 -1
- package/dist/slash-commands/mouse.d.ts.map +0 -1
- package/dist/slash-commands/next.d.ts.map +0 -1
- package/dist/slash-commands/plan.d.ts.map +0 -1
- package/dist/slash-commands/plugin.d.ts.map +0 -1
- package/dist/slash-commands/profile.d.ts.map +0 -1
- package/dist/slash-commands/project-utils.d.ts.map +0 -1
- package/dist/slash-commands/project.d.ts.map +0 -1
- package/dist/slash-commands/provider-status.d.ts.map +0 -1
- package/dist/slash-commands/prune.d.ts.map +0 -1
- package/dist/slash-commands/refiner.d.ts.map +0 -1
- package/dist/slash-commands/review.d.ts.map +0 -1
- package/dist/slash-commands/sdd/rendering.d.ts.map +0 -1
- package/dist/slash-commands/sdd-command-helpers.d.ts.map +0 -1
- package/dist/slash-commands/sdd-format.d.ts.map +0 -1
- package/dist/slash-commands/sdd.d.ts.map +0 -1
- package/dist/slash-commands/security.d.ts.map +0 -1
- package/dist/slash-commands/session.d.ts.map +0 -1
- package/dist/slash-commands/setmodel.d.ts.map +0 -1
- package/dist/slash-commands/settings.d.ts.map +0 -1
- package/dist/slash-commands/shadow.d.ts.map +0 -1
- package/dist/slash-commands/slash-deep-help.d.ts.map +0 -1
- package/dist/slash-commands/spawn-agents.d.ts.map +0 -1
- package/dist/slash-commands/statusline.d.ts.map +0 -1
- package/dist/slash-commands/suggest.d.ts.map +0 -1
- package/dist/slash-commands/suggestion-store.d.ts.map +0 -1
- package/dist/slash-commands/supervisor.d.ts.map +0 -1
- package/dist/slash-commands/surfaces.d.ts.map +0 -1
- package/dist/slash-commands/tasks.d.ts.map +0 -1
- package/dist/slash-commands/techstack.d.ts.map +0 -1
- package/dist/slash-commands/telegram-pairing.d.ts.map +0 -1
- package/dist/slash-commands/telegram-settings.d.ts.map +0 -1
- package/dist/slash-commands/telegram-setup.d.ts.map +0 -1
- package/dist/slash-commands/todos.d.ts.map +0 -1
- package/dist/slash-commands/tool.d.ts.map +0 -1
- package/dist/slash-commands/tools.d.ts.map +0 -1
- package/dist/slash-commands/tuneup.d.ts.map +0 -1
- package/dist/slash-commands/working-dir.d.ts.map +0 -1
- package/dist/slash-commands/worktree.d.ts.map +0 -1
- package/dist/slash-commands/yolo.d.ts.map +0 -1
- package/dist/spinner.d.ts.map +0 -1
- package/dist/subcommands/contracts.d.ts.map +0 -1
- package/dist/subcommands/handlers/acp.d.ts.map +0 -1
- package/dist/subcommands/handlers/audit.d.ts.map +0 -1
- package/dist/subcommands/handlers/auth-local-help.d.ts.map +0 -1
- package/dist/subcommands/handlers/auth.d.ts.map +0 -1
- package/dist/subcommands/handlers/bench-run-help.d.ts.map +0 -1
- package/dist/subcommands/handlers/bench.d.ts.map +0 -1
- package/dist/subcommands/handlers/chronicle.d.ts.map +0 -1
- package/dist/subcommands/handlers/config-history.d.ts.map +0 -1
- package/dist/subcommands/handlers/diag-doctor.d.ts.map +0 -1
- package/dist/subcommands/handlers/export.d.ts.map +0 -1
- package/dist/subcommands/handlers/helpers.d.ts.map +0 -1
- package/dist/subcommands/handlers/hq.d.ts.map +0 -1
- package/dist/subcommands/handlers/init.d.ts.map +0 -1
- package/dist/subcommands/handlers/mailbox-serve.d.ts.map +0 -1
- package/dist/subcommands/handlers/mcp.d.ts.map +0 -1
- package/dist/subcommands/handlers/model-smoke-test.d.ts.map +0 -1
- package/dist/subcommands/handlers/modeldiag-profiles.d.ts.map +0 -1
- package/dist/subcommands/handlers/modeldiag.d.ts.map +0 -1
- package/dist/subcommands/handlers/models-add-help.d.ts.map +0 -1
- package/dist/subcommands/handlers/per-subcommand-deep-help-table.d.ts.map +0 -1
- package/dist/subcommands/handlers/per-subcommand-help-data.d.ts.map +0 -1
- package/dist/subcommands/handlers/per-subcommand-help-table.d.ts.map +0 -1
- package/dist/subcommands/handlers/per-subcommand-help-types.d.ts.map +0 -1
- package/dist/subcommands/handlers/per-subcommand-help.d.ts.map +0 -1
- package/dist/subcommands/handlers/permissions.d.ts.map +0 -1
- package/dist/subcommands/handlers/plugin-usage.d.ts.map +0 -1
- package/dist/subcommands/handlers/project.d.ts.map +0 -1
- package/dist/subcommands/handlers/projects.d.ts.map +0 -1
- package/dist/subcommands/handlers/providers-models.d.ts.map +0 -1
- package/dist/subcommands/handlers/quick.d.ts.map +0 -1
- package/dist/subcommands/handlers/replay.d.ts.map +0 -1
- package/dist/subcommands/handlers/rewind.d.ts.map +0 -1
- package/dist/subcommands/handlers/sessions-config.d.ts.map +0 -1
- package/dist/subcommands/handlers/sessions-fleet.d.ts.map +0 -1
- package/dist/subcommands/handlers/tools-skills.d.ts.map +0 -1
- package/dist/subcommands/handlers/update.d.ts.map +0 -1
- package/dist/subcommands/handlers/version-help.d.ts.map +0 -1
- package/dist/subcommands/index.d.ts.map +0 -1
- package/dist/theme.d.ts.map +0 -1
- package/dist/tools-skills-UNKLOB7M.js.map +0 -7
- package/dist/tui-thinking-word.d.ts.map +0 -1
- package/dist/tuneup.d.ts.map +0 -1
- package/dist/update-YC4TYW2Y.js.map +0 -7
- package/dist/update-check-UMYTOH7Z.js.map +0 -7
- package/dist/update-check.d.ts.map +0 -1
- package/dist/utils/delay-format.d.ts.map +0 -1
- package/dist/utils/hq-ttl.d.ts.map +0 -1
- package/dist/utils/win32-cmd.d.ts.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/version-help-DROHZRW6.js.map +0 -7
- package/dist/version.d.ts.map +0 -1
- package/dist/webui-server/client-registration.d.ts.map +0 -1
- package/dist/webui-server/connection-handler.d.ts.map +0 -1
- package/dist/webui-server/context-breakdown.d.ts.map +0 -1
- package/dist/webui-server/contracts.d.ts.map +0 -1
- package/dist/webui-server/cost-helpers.d.ts.map +0 -1
- package/dist/webui-server/kanban-host-adapter.d.ts.map +0 -1
- package/dist/webui-server/kanban-run-mirror.d.ts.map +0 -1
- package/dist/webui-server/kanban-supervisor.d.ts.map +0 -1
- package/dist/webui-server/lifecycle.d.ts.map +0 -1
- package/dist/webui-server/listen-helpers.d.ts.map +0 -1
- package/dist/webui-server/logger-shim.d.ts.map +0 -1
- package/dist/webui-server/node-pty-loader.d.ts.map +0 -1
- package/dist/webui-server/prefs-seeding.d.ts.map +0 -1
- package/dist/webui-server/privileged-actions.d.ts.map +0 -1
- package/dist/webui-server/provider-config.d.ts.map +0 -1
- package/dist/webui-server/session-start-payload.d.ts.map +0 -1
- package/dist/webui-server/setup-events.d.ts.map +0 -1
- package/dist/webui-server/static-serve.d.ts.map +0 -1
- package/dist/webui-server/stream-coalescer.d.ts.map +0 -1
- package/dist/webui-server/terminal-log-view.d.ts.map +0 -1
- package/dist/webui-server-XKFUOKMJ.js.map +0 -7
- package/dist/webui-server-options.d.ts.map +0 -1
- package/dist/webui-server.d.ts.map +0 -1
- package/dist/wiring/brain-and-orchestration.d.ts.map +0 -1
- package/dist/wiring/codebase-index.d.ts.map +0 -1
- package/dist/wiring/command-host-adapters.d.ts.map +0 -1
- package/dist/wiring/command-host-state.d.ts.map +0 -1
- package/dist/wiring/controllers.d.ts.map +0 -1
- package/dist/wiring/dep-watcher-bridge.d.ts.map +0 -1
- package/dist/wiring/dep-watcher.d.ts.map +0 -1
- package/dist/wiring/design-studio.d.ts.map +0 -1
- package/dist/wiring/director-setup.d.ts.map +0 -1
- package/dist/wiring/eternal-command-handlers.d.ts.map +0 -1
- package/dist/wiring/fleet-command-handlers.d.ts.map +0 -1
- package/dist/wiring/hq-telemetry.d.ts.map +0 -1
- package/dist/wiring/lifecycle-plugins.d.ts.map +0 -1
- package/dist/wiring/mailbox-bridge-bootstrap.d.ts.map +0 -1
- package/dist/wiring/management-tools.d.ts.map +0 -1
- package/dist/wiring/metrics.d.ts.map +0 -1
- package/dist/wiring/pipeline.d.ts.map +0 -1
- package/dist/wiring/plugins.d.ts.map +0 -1
- package/dist/wiring/provider-runtime-setup.d.ts.map +0 -1
- package/dist/wiring/provider-runtime.d.ts.map +0 -1
- package/dist/wiring/provider-status.d.ts.map +0 -1
- package/dist/wiring/provider-utility-tools.d.ts.map +0 -1
- package/dist/wiring/provider.d.ts.map +0 -1
- package/dist/wiring/replay.d.ts.map +0 -1
- package/dist/wiring/runtime-controller-deps.d.ts.map +0 -1
- package/dist/wiring/runtime-dispatch-state.d.ts.map +0 -1
- package/dist/wiring/runtime-lifecycle-deps.d.ts.map +0 -1
- package/dist/wiring/runtime-picker-deps.d.ts.map +0 -1
- package/dist/wiring/sage.d.ts.map +0 -1
- package/dist/wiring/sdd-handlers.d.ts.map +0 -1
- package/dist/wiring/security-command.d.ts.map +0 -1
- package/dist/wiring/session-command-handlers.d.ts.map +0 -1
- package/dist/wiring/session-registry.d.ts.map +0 -1
- package/dist/wiring/session.d.ts.map +0 -1
- package/dist/wiring/slash-commands.d.ts.map +0 -1
- package/dist/wiring/to-execute-deps.d.ts.map +0 -1
- package/dist/wiring/tools.d.ts.map +0 -1
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
resolvePersistPath,
|
|
8
8
|
setAutoSuggestions,
|
|
9
9
|
setSuggestions
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-V3XH6XBJ.js";
|
|
11
11
|
import {
|
|
12
12
|
startCliHqConnection
|
|
13
13
|
} from "./chunk-JW75HY4F.js";
|
|
@@ -40,17 +40,10 @@ import {
|
|
|
40
40
|
import "./chunk-7OCVIDC7.js";
|
|
41
41
|
|
|
42
42
|
// src/execution.ts
|
|
43
|
-
import
|
|
44
|
-
import
|
|
45
|
-
import { setQueuedMessagesSnapshot as setQueuedMessagesSnapshot2 } from "@wrongstack/core/agent";
|
|
46
|
-
import { isMailboxLeader } from "@wrongstack/core/coordination";
|
|
47
|
-
import {
|
|
48
|
-
CHIMERA_REVIEW_PROMPT
|
|
49
|
-
} from "@wrongstack/core/plugin";
|
|
43
|
+
import * as path11 from "node:path";
|
|
44
|
+
import { effectiveFallbackChain as effectiveFallbackChain2, setQueuedMessagesSnapshot as setQueuedMessagesSnapshot2 } from "@wrongstack/core/agent";
|
|
50
45
|
import { attachTodosCheckpoint as attachTodosCheckpoint2 } from "@wrongstack/core/storage";
|
|
51
|
-
import {
|
|
52
|
-
normalizeTokenSavingTier as normalizeTokenSavingTier2
|
|
53
|
-
} from "@wrongstack/core/types";
|
|
46
|
+
import { normalizeTokenSavingTier as normalizeTokenSavingTier2 } from "@wrongstack/core/types";
|
|
54
47
|
import { mergeCustomModelDefs } from "@wrongstack/core/utils";
|
|
55
48
|
import { capabilitiesFor } from "@wrongstack/providers";
|
|
56
49
|
import { createToolVisionAdapters } from "@wrongstack/runtime/vision";
|
|
@@ -194,7 +187,7 @@ async function runWebUIDispatch(ctx) {
|
|
|
194
187
|
const isSimpleUi = flags["simpleui"] === true;
|
|
195
188
|
agent.disableInteractiveConfirmation();
|
|
196
189
|
renderer.setSilent(true);
|
|
197
|
-
const { runWebUI } = await import("./webui-server-
|
|
190
|
+
const { runWebUI } = await import("./webui-server-PCLSXX6L.js");
|
|
198
191
|
const flagValue = (names) => {
|
|
199
192
|
for (const name of names) {
|
|
200
193
|
if (!Object.hasOwn(flags, name)) continue;
|
|
@@ -1096,6 +1089,12 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1096
1089
|
let identityClaimed = false;
|
|
1097
1090
|
let writerSwapped = false;
|
|
1098
1091
|
let openedWriter;
|
|
1092
|
+
let oldWriter;
|
|
1093
|
+
let oldMessages;
|
|
1094
|
+
let previousDetachFn;
|
|
1095
|
+
let oldTodos = [];
|
|
1096
|
+
let oldPlanPath;
|
|
1097
|
+
let oldTaskPath;
|
|
1099
1098
|
try {
|
|
1100
1099
|
if (state.activateSessionIdentity) {
|
|
1101
1100
|
await state.activateSessionIdentity(canonicalSessionId);
|
|
@@ -1118,8 +1117,8 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1118
1117
|
agent.ctx.traceId,
|
|
1119
1118
|
resumed.writer.id
|
|
1120
1119
|
).catch(() => null);
|
|
1121
|
-
|
|
1122
|
-
|
|
1120
|
+
oldWriter = agent.ctx.session;
|
|
1121
|
+
oldMessages = [...agent.ctx.messages];
|
|
1123
1122
|
agent.ctx.session = resumed.writer;
|
|
1124
1123
|
try {
|
|
1125
1124
|
agent.ctx.state.replaceMessages(resumed.data.messages);
|
|
@@ -1139,7 +1138,11 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1139
1138
|
})
|
|
1140
1139
|
);
|
|
1141
1140
|
});
|
|
1142
|
-
|
|
1141
|
+
previousDetachFn = state.detachActiveTodosCheckpoint;
|
|
1142
|
+
oldTodos = agent.ctx.state.todos ? [...agent.ctx.state.todos] : [];
|
|
1143
|
+
oldPlanPath = agent.ctx.state.meta?.["plan.path"];
|
|
1144
|
+
oldTaskPath = agent.ctx.state.meta?.["task.path"];
|
|
1145
|
+
await Promise.resolve(previousDetachFn?.()).catch(() => void 0);
|
|
1143
1146
|
agent.ctx.state.setMeta(
|
|
1144
1147
|
"plan.path",
|
|
1145
1148
|
sessionScopedPath2(sessionsDir, resumed.writer.id, ".plan.json")
|
|
@@ -1181,9 +1184,10 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1181
1184
|
} else if (targetModel !== agent.ctx.model) {
|
|
1182
1185
|
agent.ctx.model = targetModel;
|
|
1183
1186
|
}
|
|
1187
|
+
let oldWriterFinalize;
|
|
1184
1188
|
if (oldWriter && oldWriter !== resumed.writer) {
|
|
1185
1189
|
const endedUsage = tokenCounter.total();
|
|
1186
|
-
void (async () => {
|
|
1190
|
+
oldWriterFinalize = void (async () => {
|
|
1187
1191
|
let appendOk = false;
|
|
1188
1192
|
try {
|
|
1189
1193
|
await oldWriter.append({
|
|
@@ -1220,13 +1224,19 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1220
1224
|
}
|
|
1221
1225
|
tokenCounter.reset();
|
|
1222
1226
|
tokenCounter.account(resumed.data.usage, targetModel, targetProviderId);
|
|
1223
|
-
|
|
1227
|
+
const reqTokens = tokenCounter.currentRequestTokens?.();
|
|
1228
|
+
const tokens = (typeof reqTokens === "number" ? reqTokens : 0) + (typeof reqTokens?.input === "number" ? reqTokens.input : 0) + (typeof reqTokens?.cacheRead === "number" ? reqTokens.cacheRead : 0) + (typeof reqTokens?.cacheWrite === "number" ? reqTokens.cacheWrite : 0);
|
|
1229
|
+
const maxContext = agent.ctx.provider?.capabilities?.maxContext ?? 0;
|
|
1230
|
+
const result = {
|
|
1224
1231
|
entries,
|
|
1225
1232
|
nextId: entries.length + 1,
|
|
1226
|
-
sessionId: resumed.writer.id
|
|
1233
|
+
sessionId: resumed.writer.id,
|
|
1234
|
+
contextSnapshot: { tokens, maxContext }
|
|
1227
1235
|
};
|
|
1236
|
+
void oldWriterFinalize;
|
|
1237
|
+
return result;
|
|
1228
1238
|
} catch (err) {
|
|
1229
|
-
if (identityClaimed &&
|
|
1239
|
+
if (identityClaimed && previousSessionId) {
|
|
1230
1240
|
await state.activateSessionIdentity?.(previousSessionId).catch((rollbackErr) => {
|
|
1231
1241
|
console.error(
|
|
1232
1242
|
JSON.stringify({
|
|
@@ -1241,6 +1251,24 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1241
1251
|
}
|
|
1242
1252
|
if (!writerSwapped) {
|
|
1243
1253
|
await openedWriter?.close().catch(() => void 0);
|
|
1254
|
+
} else {
|
|
1255
|
+
try {
|
|
1256
|
+
if (oldWriter !== void 0) agent.ctx.session = oldWriter;
|
|
1257
|
+
if (oldMessages !== void 0) agent.ctx.state.replaceMessages(oldMessages);
|
|
1258
|
+
if (previousDetachFn !== void 0) state.detachActiveTodosCheckpoint = previousDetachFn;
|
|
1259
|
+
agent.ctx.state.replaceTodos([...oldTodos]);
|
|
1260
|
+
if (oldPlanPath !== void 0) agent.ctx.state.setMeta("plan.path", oldPlanPath);
|
|
1261
|
+
if (oldTaskPath !== void 0) agent.ctx.state.setMeta("task.path", oldTaskPath);
|
|
1262
|
+
} catch (rollbackErr) {
|
|
1263
|
+
console.error(
|
|
1264
|
+
JSON.stringify({
|
|
1265
|
+
level: "error",
|
|
1266
|
+
event: "execution.resume_post_swap_rollback_failed",
|
|
1267
|
+
message: rollbackErr instanceof Error ? rollbackErr.message : String(rollbackErr),
|
|
1268
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1269
|
+
})
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1244
1272
|
}
|
|
1245
1273
|
console.error(
|
|
1246
1274
|
JSON.stringify({
|
|
@@ -1261,6 +1289,12 @@ import { decryptConfigSecrets, encryptConfigSecrets, noOpVault } from "@wrongsta
|
|
|
1261
1289
|
import { normalizeTokenSavingTier, resolveFleetChatVerbosity } from "@wrongstack/core/types";
|
|
1262
1290
|
import { atomicWrite } from "@wrongstack/core/utils";
|
|
1263
1291
|
import { getProcessRegistry } from "@wrongstack/tools";
|
|
1292
|
+
function coerceAgentSwarmMode(v) {
|
|
1293
|
+
if (v === true || v === void 0) return "bottom";
|
|
1294
|
+
if (v === false) return "off";
|
|
1295
|
+
if (typeof v === "string" && (v === "bottom" || v === "sidebar" || v === "off")) return v;
|
|
1296
|
+
return "bottom";
|
|
1297
|
+
}
|
|
1264
1298
|
var ANIMATION_STYLES = ["rainbow", "wave", "pulse", "dots", "breathe", "cycle"];
|
|
1265
1299
|
function normalizeAnimationStyle(raw) {
|
|
1266
1300
|
return typeof raw === "string" && ANIMATION_STYLES.includes(raw) ? raw : "rainbow";
|
|
@@ -1313,7 +1347,7 @@ function createSettingsAdapter(ctx) {
|
|
|
1313
1347
|
autoProceedMaxIterations: cfg.autonomy?.autoProceedMaxIterations ?? 50,
|
|
1314
1348
|
debugStream: cfg.debugStream ?? false,
|
|
1315
1349
|
shellBangWarningDontShowAgain: autonomy?.shellBangWarningDontShowAgain === true,
|
|
1316
|
-
statuslineMode: autonomy?.statuslineMode === "no-color" ? "no-color" : autonomy?.statuslineMode === "
|
|
1350
|
+
statuslineMode: autonomy?.statuslineMode === "no-color" ? "no-color" : autonomy?.statuslineMode === "detailed" ? "detailed" : "minimum",
|
|
1317
1351
|
thinkingWord: normalizeTuiThinkingWord(autonomy?.thinkingWord),
|
|
1318
1352
|
animationStyle: normalizeAnimationStyle(autonomy?.animationStyle),
|
|
1319
1353
|
configScope: cfg.configScope ?? "global",
|
|
@@ -1330,7 +1364,7 @@ function createSettingsAdapter(ctx) {
|
|
|
1330
1364
|
breakerEnabled: cfg.circuitBreaker?.enabled === true,
|
|
1331
1365
|
breakerAutoKillResetMs: cfg.circuitBreaker?.autoKillResetMs ?? 6e4,
|
|
1332
1366
|
showModelReasoning: autonomy?.showModelReasoning ?? true,
|
|
1333
|
-
showAgentSwarmPanel: autonomy?.showAgentSwarmPanel
|
|
1367
|
+
showAgentSwarmPanel: coerceAgentSwarmMode(autonomy?.showAgentSwarmPanel),
|
|
1334
1368
|
showSageMemoryInject: autonomy?.showSageMemoryInject ?? false,
|
|
1335
1369
|
readSymbols: autonomy?.readAdvancedMode ?? false,
|
|
1336
1370
|
sageMemoryInjectThreshold: cfg.Sage?.inject ? cfg.Sage.inject?.relationFloor : void 0
|
|
@@ -1389,8 +1423,7 @@ function createSettingsAdapter(ctx) {
|
|
|
1389
1423
|
autonomy.showAgentSwarmPanel = s.showAgentSwarmPanel;
|
|
1390
1424
|
if (s.showSageMemoryInject !== void 0)
|
|
1391
1425
|
autonomy.showSageMemoryInject = s.showSageMemoryInject;
|
|
1392
|
-
if (s.readSymbols !== void 0)
|
|
1393
|
-
autonomy.readAdvancedMode = s.readSymbols;
|
|
1426
|
+
if (s.readSymbols !== void 0) autonomy.readAdvancedMode = s.readSymbols;
|
|
1394
1427
|
if (s.autonomyNextPrompt !== void 0) autonomy.autonomyNextPrompt = s.autonomyNextPrompt;
|
|
1395
1428
|
if (s.autoProceedMaxIterations !== void 0)
|
|
1396
1429
|
autonomy.autoProceedMaxIterations = s.autoProceedMaxIterations;
|
|
@@ -1723,151 +1756,8 @@ function createBrainPanelHost(deps) {
|
|
|
1723
1756
|
};
|
|
1724
1757
|
}
|
|
1725
1758
|
|
|
1726
|
-
// src/chimera-review-task.ts
|
|
1727
|
-
import { parseReviewSeverity } from "@wrongstack/core/plugin";
|
|
1728
|
-
function truncateAtCodePointBoundary(text, maxCodeUnits) {
|
|
1729
|
-
if (text.length <= maxCodeUnits) return text;
|
|
1730
|
-
let result = "";
|
|
1731
|
-
for (const ch of text) {
|
|
1732
|
-
if (result.length + ch.length > maxCodeUnits) break;
|
|
1733
|
-
result += ch;
|
|
1734
|
-
}
|
|
1735
|
-
return result;
|
|
1736
|
-
}
|
|
1737
|
-
function isChimeraAllClearReview(text) {
|
|
1738
|
-
const severities = parseReviewSeverity(text);
|
|
1739
|
-
if (severities.critical > 0 || severities.high > 0 || severities.medium > 0) {
|
|
1740
|
-
return false;
|
|
1741
|
-
}
|
|
1742
|
-
const normalized = text.trim().toLowerCase();
|
|
1743
|
-
return normalized.startsWith("## \u{1F982} chimera review \u2014 all clear") || normalized.includes("chimera review: all clear");
|
|
1744
|
-
}
|
|
1745
|
-
function buildChimeraReviewTaskDescription(p) {
|
|
1746
|
-
const lines = [];
|
|
1747
|
-
lines.push(`Review the following ${p.files.length} file(s) changed in this session at ${p.cwd}.`);
|
|
1748
|
-
lines.push("");
|
|
1749
|
-
for (const f of p.files) {
|
|
1750
|
-
lines.push(`## [${f.status.toUpperCase()}] ${f.path}`);
|
|
1751
|
-
if (f.diff) {
|
|
1752
|
-
lines.push("");
|
|
1753
|
-
lines.push("```diff");
|
|
1754
|
-
lines.push(f.diff);
|
|
1755
|
-
lines.push("```");
|
|
1756
|
-
} else if (f.status === "added") {
|
|
1757
|
-
lines.push("");
|
|
1758
|
-
lines.push("(New file \u2014 full content provided)");
|
|
1759
|
-
}
|
|
1760
|
-
lines.push("");
|
|
1761
|
-
}
|
|
1762
|
-
if (p.allChangedFiles && p.allChangedFiles.length > p.files.length) {
|
|
1763
|
-
const reviewedPaths = new Set(p.files.map((f) => f.path));
|
|
1764
|
-
const siblings = p.allChangedFiles.filter((s) => !reviewedPaths.has(s.path)).map((s) => ` ${s.path} (${s.status})`);
|
|
1765
|
-
if (siblings.length > 0) {
|
|
1766
|
-
lines.push("---");
|
|
1767
|
-
lines.push("");
|
|
1768
|
-
lines.push(
|
|
1769
|
-
`**Also changed this session (${siblings.length} files \u2014 for context, NOT in your review scope):**`
|
|
1770
|
-
);
|
|
1771
|
-
lines.push(siblings.slice(0, 30).join("\n"));
|
|
1772
|
-
lines.push("");
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
if (p.recentCommits && p.recentCommits.length > 0) {
|
|
1776
|
-
lines.push("---");
|
|
1777
|
-
lines.push("");
|
|
1778
|
-
lines.push("**Recent commits (newest first):**");
|
|
1779
|
-
for (const c of p.recentCommits) lines.push(` ${c}`);
|
|
1780
|
-
lines.push("");
|
|
1781
|
-
}
|
|
1782
|
-
if (p.activeTodos && p.activeTodos.length > 0) {
|
|
1783
|
-
lines.push("---");
|
|
1784
|
-
lines.push("");
|
|
1785
|
-
lines.push(`**Active task items (${p.activeTodos.length}):**`);
|
|
1786
|
-
for (const t of p.activeTodos) {
|
|
1787
|
-
lines.push(` [${t.status}] ${t.content}`);
|
|
1788
|
-
}
|
|
1789
|
-
lines.push("");
|
|
1790
|
-
}
|
|
1791
|
-
if (p.kanbanCard) {
|
|
1792
|
-
lines.push("---");
|
|
1793
|
-
lines.push("");
|
|
1794
|
-
lines.push(`**Kanban card: ${p.kanbanCard.title}**`);
|
|
1795
|
-
if (p.kanbanCard.description) {
|
|
1796
|
-
lines.push(` ${p.kanbanCard.description.slice(0, 500)}`);
|
|
1797
|
-
}
|
|
1798
|
-
if (p.kanbanCard.successCriteria && p.kanbanCard.successCriteria.length > 0) {
|
|
1799
|
-
lines.push(" **Success criteria:**");
|
|
1800
|
-
for (const sc of p.kanbanCard.successCriteria) lines.push(` - ${sc}`);
|
|
1801
|
-
}
|
|
1802
|
-
lines.push("");
|
|
1803
|
-
}
|
|
1804
|
-
if (p.fileProvenance && p.fileProvenance.length > 0) {
|
|
1805
|
-
lines.push("---");
|
|
1806
|
-
lines.push("");
|
|
1807
|
-
lines.push("**File provenance (Chronicle):**");
|
|
1808
|
-
for (const fp of p.fileProvenance) {
|
|
1809
|
-
const parts = [];
|
|
1810
|
-
if (fp.agentId) parts.push(`agent: ${fp.agentId}`);
|
|
1811
|
-
if (fp.taskId) parts.push(`task: ${fp.taskId}`);
|
|
1812
|
-
if (fp.eventType) parts.push(fp.eventType);
|
|
1813
|
-
if (fp.observedAt) parts.push(fp.observedAt);
|
|
1814
|
-
lines.push(` ${fp.path} \u2014 ${parts.join(", ")}`);
|
|
1815
|
-
}
|
|
1816
|
-
lines.push("");
|
|
1817
|
-
}
|
|
1818
|
-
lines.push("---");
|
|
1819
|
-
lines.push("");
|
|
1820
|
-
lines.push("Read each file using the read tool. For modified files, focus on the");
|
|
1821
|
-
lines.push("diff above \u2014 do not re-review unchanged pre-existing code.");
|
|
1822
|
-
lines.push("Check for bugs, type issues, security problems, and produce a");
|
|
1823
|
-
lines.push("structured review report.");
|
|
1824
|
-
return lines.join("\n");
|
|
1825
|
-
}
|
|
1826
|
-
function buildChimeraCascadeTaskDescription(agentKind, p) {
|
|
1827
|
-
const fileList = p.bundle.files.map((f) => `- ${f.path}`).join("\n");
|
|
1828
|
-
const reportSlice = truncateAtCodePointBoundary(p.reviewText, 12e3);
|
|
1829
|
-
const severityLine = `Critical: ${p.severities.critical}, High: ${p.severities.high}, Medium: ${p.severities.medium}`;
|
|
1830
|
-
if (agentKind === "security-scanner") {
|
|
1831
|
-
return [
|
|
1832
|
-
`You are a security cascade agent. A Chimera code review flagged security-relevant findings.`,
|
|
1833
|
-
``,
|
|
1834
|
-
`Repository: ${p.bundle.cwd}`,
|
|
1835
|
-
`Severity summary: ${severityLine}`,
|
|
1836
|
-
``,
|
|
1837
|
-
`--- Review report ---`,
|
|
1838
|
-
reportSlice,
|
|
1839
|
-
``,
|
|
1840
|
-
`--- Changed files ---`,
|
|
1841
|
-
fileList,
|
|
1842
|
-
``,
|
|
1843
|
-
`Investigate the security findings above. Read the flagged files, confirm or refute`,
|
|
1844
|
-
`each finding, and **apply fixes** for confirmed vulnerabilities using the edit tool.`,
|
|
1845
|
-
`Use severity (Critical/High/Medium), file:line citations, and remediation steps.`,
|
|
1846
|
-
`After fixing, run the project's typecheck and linter to verify. If a finding is a`,
|
|
1847
|
-
`false positive, say so and do not modify the file.`
|
|
1848
|
-
].join("\n");
|
|
1849
|
-
}
|
|
1850
|
-
return [
|
|
1851
|
-
`You are a bug-hunter cascade agent. A Chimera code review flagged correctness defects.`,
|
|
1852
|
-
``,
|
|
1853
|
-
`Repository: ${p.bundle.cwd}`,
|
|
1854
|
-
`Severity summary: ${severityLine}`,
|
|
1855
|
-
``,
|
|
1856
|
-
`--- Review report ---`,
|
|
1857
|
-
reportSlice,
|
|
1858
|
-
``,
|
|
1859
|
-
`--- Changed files ---`,
|
|
1860
|
-
fileList,
|
|
1861
|
-
``,
|
|
1862
|
-
`Hunt for the bugs flagged above. Read the affected files, trace each finding to its`,
|
|
1863
|
-
`root cause, and **apply minimal fixes** for confirmed bugs using the edit tool.`,
|
|
1864
|
-
`Use severity (Critical/High/Medium), file:line citations. After fixing, run the`,
|
|
1865
|
-
`project's typecheck and linter to verify. If a finding is a false positive, say so`,
|
|
1866
|
-
`and do not modify the file.`
|
|
1867
|
-
].join("\n");
|
|
1868
|
-
}
|
|
1869
|
-
|
|
1870
1759
|
// src/chimera-reviewer-policy.ts
|
|
1760
|
+
import { parseModelRef } from "@wrongstack/core/agent";
|
|
1871
1761
|
import {
|
|
1872
1762
|
buildReviewerModelPool,
|
|
1873
1763
|
selectRoundRobinReviewerAssignment
|
|
@@ -1905,6 +1795,75 @@ function assignReviewerModelsRoundRobin(provider, model, fallbackModels) {
|
|
|
1905
1795
|
fallbackModels: assignment.fallbackModels
|
|
1906
1796
|
};
|
|
1907
1797
|
}
|
|
1798
|
+
var MAX_REVIEWER_ATTEMPTS = 4;
|
|
1799
|
+
var REVIEWER_ATTEMPT_TIMEOUT_MS = 9e5;
|
|
1800
|
+
var REVIEWER_LADDER_BUDGET_MS = 12e5;
|
|
1801
|
+
var REVIEWER_MIN_ATTEMPT_MS = 12e4;
|
|
1802
|
+
function buildReviewerAttemptLadder(input) {
|
|
1803
|
+
const assignedChain = [...input.assigned.fallbackModels ?? []];
|
|
1804
|
+
const profileChain = [...input.profileChain ?? []];
|
|
1805
|
+
const rungs = [];
|
|
1806
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1807
|
+
const key = (provider, model) => `${provider.trim()}/${model.trim()}`;
|
|
1808
|
+
const push = (provider, model, fallbackModels, tier) => {
|
|
1809
|
+
const p = provider.trim();
|
|
1810
|
+
const m = model.trim();
|
|
1811
|
+
if (!p || !m) return;
|
|
1812
|
+
if (seen.has(key(p, m))) return;
|
|
1813
|
+
seen.add(key(p, m));
|
|
1814
|
+
rungs.push({ provider: p, model: m, fallbackModels, tier });
|
|
1815
|
+
};
|
|
1816
|
+
push(input.assigned.provider, input.assigned.model, [...assignedChain], "primary");
|
|
1817
|
+
for (const [chain, tier] of [
|
|
1818
|
+
[assignedChain, "fallback"],
|
|
1819
|
+
[profileChain, "fallback"]
|
|
1820
|
+
]) {
|
|
1821
|
+
for (let i = 0; i < chain.length; i++) {
|
|
1822
|
+
const parsed = parseModelRef(chain[i]);
|
|
1823
|
+
push(parsed.provider ?? "", parsed.model, chain.slice(i + 1), tier);
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
const sessionKey = key(input.session.provider, input.session.model);
|
|
1827
|
+
push(input.session.provider, input.session.model, [], "session");
|
|
1828
|
+
const cap = Math.max(1, Math.floor(input.maxAttempts ?? MAX_REVIEWER_ATTEMPTS));
|
|
1829
|
+
if (rungs.length <= cap) return rungs;
|
|
1830
|
+
const trimmed = rungs.slice(0, cap);
|
|
1831
|
+
if (!trimmed.some((r) => key(r.provider, r.model) === sessionKey)) {
|
|
1832
|
+
const sessionRung = rungs.find((r) => key(r.provider, r.model) === sessionKey);
|
|
1833
|
+
if (sessionRung) trimmed[trimmed.length - 1] = sessionRung;
|
|
1834
|
+
}
|
|
1835
|
+
return trimmed;
|
|
1836
|
+
}
|
|
1837
|
+
var MAX_MUTATING_ATTEMPTS = 2;
|
|
1838
|
+
function buildMutatingAgentLadder(input) {
|
|
1839
|
+
const cap = Math.max(1, Math.floor(input.maxAttempts ?? MAX_MUTATING_ATTEMPTS));
|
|
1840
|
+
const inherit = {
|
|
1841
|
+
provider: "",
|
|
1842
|
+
model: "",
|
|
1843
|
+
fallbackModels: [],
|
|
1844
|
+
tier: "inherit"
|
|
1845
|
+
};
|
|
1846
|
+
if (cap === 1) return [inherit];
|
|
1847
|
+
return [
|
|
1848
|
+
inherit,
|
|
1849
|
+
...buildReviewerAttemptLadder({
|
|
1850
|
+
assigned: { provider: "", model: "" },
|
|
1851
|
+
profileChain: input.profileChain,
|
|
1852
|
+
session: input.session,
|
|
1853
|
+
maxAttempts: cap - 1
|
|
1854
|
+
})
|
|
1855
|
+
];
|
|
1856
|
+
}
|
|
1857
|
+
function shouldAdvanceReviewerLadder(status, error) {
|
|
1858
|
+
if (status === "success") return false;
|
|
1859
|
+
if (status === "stopped") return false;
|
|
1860
|
+
if (error?.kind === "aborted_by_parent") return false;
|
|
1861
|
+
return true;
|
|
1862
|
+
}
|
|
1863
|
+
function reviewerAttemptTimeoutMs(remainingMs, attemptTimeoutMs = REVIEWER_ATTEMPT_TIMEOUT_MS, minAttemptMs = REVIEWER_MIN_ATTEMPT_MS) {
|
|
1864
|
+
if (remainingMs < minAttemptMs) return 0;
|
|
1865
|
+
return Math.min(attemptTimeoutMs, Math.floor(remainingMs));
|
|
1866
|
+
}
|
|
1908
1867
|
var CHIMERA_REVIEW_READ_ONLY_TOOLS = Object.freeze([
|
|
1909
1868
|
"read",
|
|
1910
1869
|
"grep",
|
|
@@ -2040,7 +1999,7 @@ import { WIDE_SUBAGENT_CAPABILITIES } from "@wrongstack/core/security";
|
|
|
2040
1999
|
// src/kanban-dispatch-route.ts
|
|
2041
2000
|
import {
|
|
2042
2001
|
fallbackProfileChain,
|
|
2043
|
-
parseModelRef
|
|
2002
|
+
parseModelRef as parseModelRef2
|
|
2044
2003
|
} from "@wrongstack/core/agent";
|
|
2045
2004
|
function resolveKanbanDispatchRoute(config, spawnOpts) {
|
|
2046
2005
|
let provider = spawnOpts?.provider;
|
|
@@ -2048,7 +2007,7 @@ function resolveKanbanDispatchRoute(config, spawnOpts) {
|
|
|
2048
2007
|
let fallbackModels = spawnOpts?.fallbackModels;
|
|
2049
2008
|
if (spawnOpts?.fallbackProfile) {
|
|
2050
2009
|
const chain = fallbackProfileChain(config, spawnOpts.fallbackProfile);
|
|
2051
|
-
const primary = chain[0] ?
|
|
2010
|
+
const primary = chain[0] ? parseModelRef2(chain[0]) : void 0;
|
|
2052
2011
|
if (primary?.model) {
|
|
2053
2012
|
provider = primary.provider ?? config.provider;
|
|
2054
2013
|
model = primary.model;
|
|
@@ -2233,6 +2192,7 @@ var FleetStatusLine = class {
|
|
|
2233
2192
|
rows = 0;
|
|
2234
2193
|
repaintTimer = null;
|
|
2235
2194
|
tickTimer = null;
|
|
2195
|
+
deactivateTimer = null;
|
|
2236
2196
|
resizeCleanup = null;
|
|
2237
2197
|
lastPaint = 0;
|
|
2238
2198
|
onResize = () => {
|
|
@@ -2308,7 +2268,9 @@ var FleetStatusLine = class {
|
|
|
2308
2268
|
s.endedAt = this.now();
|
|
2309
2269
|
this.schedulePaint();
|
|
2310
2270
|
if (![...this.states.values()].some((a) => a.status === "running")) {
|
|
2311
|
-
|
|
2271
|
+
if (this.deactivateTimer) clearTimeout(this.deactivateTimer);
|
|
2272
|
+
this.deactivateTimer = setTimeout(() => {
|
|
2273
|
+
this.deactivateTimer = null;
|
|
2312
2274
|
if (![...this.states.values()].some((a) => a.status === "running")) {
|
|
2313
2275
|
this.deactivate();
|
|
2314
2276
|
}
|
|
@@ -2352,6 +2314,10 @@ var FleetStatusLine = class {
|
|
|
2352
2314
|
clearTimeout(this.repaintTimer);
|
|
2353
2315
|
this.repaintTimer = null;
|
|
2354
2316
|
}
|
|
2317
|
+
if (this.deactivateTimer) {
|
|
2318
|
+
clearTimeout(this.deactivateTimer);
|
|
2319
|
+
this.deactivateTimer = null;
|
|
2320
|
+
}
|
|
2355
2321
|
this.resizeCleanup?.();
|
|
2356
2322
|
this.resizeCleanup = null;
|
|
2357
2323
|
if (this.isTty()) {
|
|
@@ -2389,216 +2355,341 @@ var FleetStatusLine = class {
|
|
|
2389
2355
|
}
|
|
2390
2356
|
};
|
|
2391
2357
|
|
|
2392
|
-
// src/execution-chimera-ask.ts
|
|
2393
|
-
import { createHash } from "node:crypto";
|
|
2394
|
-
async function waitForChimeraAskApproval(opts) {
|
|
2395
|
-
const rawPoll = opts.meta["chimeraPollIntervalMs"] ?? 2e3;
|
|
2396
|
-
const pollIntervalMs = Number.isFinite(rawPoll) ? Math.max(0, rawPoll) : 2e3;
|
|
2397
|
-
const abortSignal = opts.meta["chimeraAbortSignal"];
|
|
2398
|
-
const askStartTime = Date.now();
|
|
2399
|
-
let leaderApproved = false;
|
|
2400
|
-
let repliesFound = false;
|
|
2401
|
-
let nonLeaderReplyCount = 0;
|
|
2402
|
-
let pollDone = false;
|
|
2403
|
-
const pollNext = () => {
|
|
2404
|
-
if (pollDone) return Promise.resolve();
|
|
2405
|
-
const elapsed = Date.now() - askStartTime;
|
|
2406
|
-
const remaining = opts.askTimeoutMs - elapsed;
|
|
2407
|
-
if (remaining <= 0 || abortSignal?.aborted) {
|
|
2408
|
-
pollDone = true;
|
|
2409
|
-
return Promise.resolve();
|
|
2410
|
-
}
|
|
2411
|
-
return new Promise((r) => setTimeout(r, Math.min(pollIntervalMs, remaining))).then(
|
|
2412
|
-
() => pollForReply()
|
|
2413
|
-
);
|
|
2414
|
-
};
|
|
2415
|
-
const pollForReply = async () => {
|
|
2416
|
-
if (pollDone) return;
|
|
2417
|
-
const replies = await opts.mailbox.query({ replyTo: opts.messageId, limit: 5 });
|
|
2418
|
-
if (replies.length > 0) {
|
|
2419
|
-
repliesFound = true;
|
|
2420
|
-
const firstReply = replies[0];
|
|
2421
|
-
if (!firstReply) return pollNext();
|
|
2422
|
-
const replyFromBase = (firstReply.from ?? "").split("@")[0];
|
|
2423
|
-
if (replyFromBase !== "leader" || firstReply.audience === "leaders") {
|
|
2424
|
-
nonLeaderReplyCount++;
|
|
2425
|
-
if (nonLeaderReplyCount >= 5) {
|
|
2426
|
-
console.warn(
|
|
2427
|
-
JSON.stringify({
|
|
2428
|
-
level: "warn",
|
|
2429
|
-
event: "execution.chimera_ask_non_leader_threshold",
|
|
2430
|
-
message: `${nonLeaderReplyCount} non-leader replies seen on chimera ask \u2014 stopping poll`,
|
|
2431
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2432
|
-
})
|
|
2433
|
-
);
|
|
2434
|
-
pollDone = true;
|
|
2435
|
-
return;
|
|
2436
|
-
}
|
|
2437
|
-
console.warn(
|
|
2438
|
-
JSON.stringify({
|
|
2439
|
-
level: nonLeaderReplyCount <= 1 ? "warn" : "debug",
|
|
2440
|
-
event: "execution.chimera_ask_non_leader_reply",
|
|
2441
|
-
message: `Ignoring non-leader reply #${nonLeaderReplyCount} from ${firstReply.from}`,
|
|
2442
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2443
|
-
})
|
|
2444
|
-
);
|
|
2445
|
-
return pollNext();
|
|
2446
|
-
}
|
|
2447
|
-
await opts.mailbox.ack({
|
|
2448
|
-
messageId: firstReply.id,
|
|
2449
|
-
readerId: "chimera-review",
|
|
2450
|
-
read: true,
|
|
2451
|
-
completed: true
|
|
2452
|
-
}).catch((_ackErr) => {
|
|
2453
|
-
console.warn(
|
|
2454
|
-
JSON.stringify({
|
|
2455
|
-
level: "warn",
|
|
2456
|
-
event: "execution.chimera_ask_ack_failed",
|
|
2457
|
-
message: _ackErr instanceof Error ? _ackErr.message : String(_ackErr),
|
|
2458
|
-
replyMessageId: firstReply.id,
|
|
2459
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2460
|
-
})
|
|
2461
|
-
);
|
|
2462
|
-
});
|
|
2463
|
-
const body = firstReply.body.toLowerCase();
|
|
2464
|
-
if (body.trim().length === 0) {
|
|
2465
|
-
pollDone = true;
|
|
2466
|
-
return;
|
|
2467
|
-
}
|
|
2468
|
-
leaderApproved = /^\s*(?:y(?:es)?|sure|ok(?:ay)?|go ahead|proceed|approve|fix it|please do|do it|yep|yeah)\b/.test(
|
|
2469
|
-
body
|
|
2470
|
-
) || /^\s*👍/.test(body);
|
|
2471
|
-
if (leaderApproved) {
|
|
2472
|
-
pollDone = true;
|
|
2473
|
-
return;
|
|
2474
|
-
}
|
|
2475
|
-
if (/^\s*(no|don'?t|stop|skip|ignore|cancel|reject|decline)\b/.test(body)) {
|
|
2476
|
-
pollDone = true;
|
|
2477
|
-
return;
|
|
2478
|
-
}
|
|
2479
|
-
leaderApproved = /\b(?:y(?:es)?|sure|approve|proceed|go ahead)\b/i.test(body);
|
|
2480
|
-
if (leaderApproved) {
|
|
2481
|
-
pollDone = true;
|
|
2482
|
-
return;
|
|
2483
|
-
}
|
|
2484
|
-
const hash = createHash("sha256").update(body).digest("hex").slice(0, 12);
|
|
2485
|
-
console.warn(
|
|
2486
|
-
JSON.stringify({
|
|
2487
|
-
level: "debug",
|
|
2488
|
-
event: "execution.chimera_ask_reply_unmatched",
|
|
2489
|
-
replyBodyHash: hash,
|
|
2490
|
-
replyBodyLength: body.length,
|
|
2491
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2492
|
-
})
|
|
2493
|
-
);
|
|
2494
|
-
}
|
|
2495
|
-
return pollNext();
|
|
2496
|
-
};
|
|
2497
|
-
await pollForReply();
|
|
2498
|
-
if (!leaderApproved) {
|
|
2499
|
-
await recordChimeraAskFallback(opts.session, opts.askTimeoutMs, repliesFound);
|
|
2500
|
-
}
|
|
2501
|
-
return leaderApproved;
|
|
2502
|
-
}
|
|
2503
|
-
async function recordChimeraAskFallback(session, askTimeoutMs, repliesFound) {
|
|
2504
|
-
console.warn(
|
|
2505
|
-
JSON.stringify({
|
|
2506
|
-
level: "warn",
|
|
2507
|
-
event: repliesFound ? "execution.chimera_ask_rejected" : "execution.chimera_ask_timeout",
|
|
2508
|
-
message: repliesFound ? "Leader replied to ask but did not approve" : "Ask timeout expired, falling back to off mode (no auto-fix)",
|
|
2509
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2510
|
-
})
|
|
2511
|
-
);
|
|
2512
|
-
await session.append({
|
|
2513
|
-
type: "llm_response",
|
|
2514
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2515
|
-
content: [
|
|
2516
|
-
{
|
|
2517
|
-
type: "text",
|
|
2518
|
-
text: `\u{1F982} Chimera auto-fix request sent to leader \u2014 no approval received within ${askTimeoutMs / 1e3}s timeout. Falling back to manual review mode. Set autoFix via \`/chimera autoFix auto\` to auto-approve future reviews.`
|
|
2519
|
-
}
|
|
2520
|
-
],
|
|
2521
|
-
stopReason: "end_turn",
|
|
2522
|
-
usage: { input: 0, output: 0 }
|
|
2523
|
-
}).catch((_appendErr) => {
|
|
2524
|
-
console.warn(
|
|
2525
|
-
JSON.stringify({
|
|
2526
|
-
level: "warn",
|
|
2527
|
-
event: "execution.chimera_timeout_append_failed",
|
|
2528
|
-
message: _appendErr instanceof Error ? _appendErr.message : String(_appendErr),
|
|
2529
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2530
|
-
})
|
|
2531
|
-
);
|
|
2532
|
-
});
|
|
2533
|
-
}
|
|
2534
|
-
|
|
2535
2358
|
// src/execution-chimera-cascade.ts
|
|
2536
|
-
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
2537
2359
|
import * as fsp from "node:fs/promises";
|
|
2538
2360
|
import * as path8 from "node:path";
|
|
2539
2361
|
import { emitReviewIfChanged } from "@wrongstack/core/plugin";
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2362
|
+
|
|
2363
|
+
// src/chimera-review-task.ts
|
|
2364
|
+
import { parseReviewSeverity } from "@wrongstack/core/plugin";
|
|
2365
|
+
function truncateAtCodePointBoundary(text, maxCodeUnits) {
|
|
2366
|
+
if (text.length <= maxCodeUnits) return text;
|
|
2367
|
+
let result = "";
|
|
2368
|
+
for (const ch of text) {
|
|
2369
|
+
if (result.length + ch.length > maxCodeUnits) break;
|
|
2370
|
+
result += ch;
|
|
2371
|
+
}
|
|
2372
|
+
return result;
|
|
2373
|
+
}
|
|
2374
|
+
function isChimeraAllClearReview(text) {
|
|
2375
|
+
const severities = parseReviewSeverity(text);
|
|
2376
|
+
if (severities.critical > 0 || severities.high > 0 || severities.medium > 0) {
|
|
2377
|
+
return false;
|
|
2378
|
+
}
|
|
2379
|
+
const normalized = text.trim().toLowerCase();
|
|
2380
|
+
return normalized.startsWith("## \u{1F982} chimera review \u2014 all clear") || normalized.includes("chimera review: all clear");
|
|
2381
|
+
}
|
|
2382
|
+
function buildChimeraReviewTaskDescription(p) {
|
|
2383
|
+
const lines = [];
|
|
2384
|
+
lines.push(`Review the following ${p.files.length} file(s) changed in this session at ${p.cwd}.`);
|
|
2385
|
+
lines.push("");
|
|
2386
|
+
for (const f of p.files) {
|
|
2387
|
+
lines.push(`## [${f.status.toUpperCase()}] ${f.path}`);
|
|
2388
|
+
if (f.diff) {
|
|
2389
|
+
lines.push("");
|
|
2390
|
+
lines.push("```diff");
|
|
2391
|
+
lines.push(f.diff);
|
|
2392
|
+
lines.push("```");
|
|
2393
|
+
} else if (f.status === "added") {
|
|
2394
|
+
lines.push("");
|
|
2395
|
+
lines.push("(New file \u2014 full content provided)");
|
|
2396
|
+
}
|
|
2397
|
+
lines.push("");
|
|
2398
|
+
}
|
|
2399
|
+
if (p.allChangedFiles && p.allChangedFiles.length > p.files.length) {
|
|
2400
|
+
const reviewedPaths = new Set(p.files.map((f) => f.path));
|
|
2401
|
+
const siblings = p.allChangedFiles.filter((s) => !reviewedPaths.has(s.path)).map((s) => ` ${s.path} (${s.status})`);
|
|
2402
|
+
if (siblings.length > 0) {
|
|
2403
|
+
lines.push("---");
|
|
2404
|
+
lines.push("");
|
|
2405
|
+
lines.push(
|
|
2406
|
+
`**Also changed this session (${siblings.length} files \u2014 for context, NOT in your review scope):**`
|
|
2407
|
+
);
|
|
2408
|
+
lines.push(siblings.slice(0, 30).join("\n"));
|
|
2409
|
+
lines.push("");
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
if (p.recentCommits && p.recentCommits.length > 0) {
|
|
2413
|
+
lines.push("---");
|
|
2414
|
+
lines.push("");
|
|
2415
|
+
lines.push("**Recent commits (newest first):**");
|
|
2416
|
+
for (const c of p.recentCommits) lines.push(` ${c}`);
|
|
2417
|
+
lines.push("");
|
|
2418
|
+
}
|
|
2419
|
+
if (p.activeTodos && p.activeTodos.length > 0) {
|
|
2420
|
+
lines.push("---");
|
|
2421
|
+
lines.push("");
|
|
2422
|
+
lines.push(`**Active task items (${p.activeTodos.length}):**`);
|
|
2423
|
+
for (const t of p.activeTodos) {
|
|
2424
|
+
lines.push(` [${t.status}] ${t.content}`);
|
|
2425
|
+
}
|
|
2426
|
+
lines.push("");
|
|
2427
|
+
}
|
|
2428
|
+
if (p.kanbanCard) {
|
|
2429
|
+
lines.push("---");
|
|
2430
|
+
lines.push("");
|
|
2431
|
+
lines.push(`**Kanban card: ${p.kanbanCard.title}**`);
|
|
2432
|
+
if (p.kanbanCard.description) {
|
|
2433
|
+
lines.push(` ${p.kanbanCard.description.slice(0, 500)}`);
|
|
2434
|
+
}
|
|
2435
|
+
if (p.kanbanCard.successCriteria && p.kanbanCard.successCriteria.length > 0) {
|
|
2436
|
+
lines.push(" **Success criteria:**");
|
|
2437
|
+
for (const sc of p.kanbanCard.successCriteria) lines.push(` - ${sc}`);
|
|
2438
|
+
}
|
|
2439
|
+
lines.push("");
|
|
2440
|
+
}
|
|
2441
|
+
if (p.fileProvenance && p.fileProvenance.length > 0) {
|
|
2442
|
+
lines.push("---");
|
|
2443
|
+
lines.push("");
|
|
2444
|
+
lines.push("**File provenance (Chronicle):**");
|
|
2445
|
+
for (const fp of p.fileProvenance) {
|
|
2446
|
+
const parts = [];
|
|
2447
|
+
if (fp.agentId) parts.push(`agent: ${fp.agentId}`);
|
|
2448
|
+
if (fp.taskId) parts.push(`task: ${fp.taskId}`);
|
|
2449
|
+
if (fp.eventType) parts.push(fp.eventType);
|
|
2450
|
+
if (fp.observedAt) parts.push(fp.observedAt);
|
|
2451
|
+
lines.push(` ${fp.path} \u2014 ${parts.join(", ")}`);
|
|
2452
|
+
}
|
|
2453
|
+
lines.push("");
|
|
2454
|
+
}
|
|
2455
|
+
lines.push("---");
|
|
2456
|
+
lines.push("");
|
|
2457
|
+
lines.push("Read each file using the read tool. For modified files, focus on the");
|
|
2458
|
+
lines.push("diff above \u2014 do not re-review unchanged pre-existing code.");
|
|
2459
|
+
lines.push("Check for bugs, type issues, security problems, and produce a");
|
|
2460
|
+
lines.push("structured review report.");
|
|
2461
|
+
return lines.join("\n");
|
|
2462
|
+
}
|
|
2463
|
+
function buildChimeraCascadeTaskDescription(agentKind, p) {
|
|
2464
|
+
const fileList = p.bundle.files.map((f) => `- ${f.path}`).join("\n");
|
|
2465
|
+
const reportSlice = truncateAtCodePointBoundary(p.reviewText, 12e3);
|
|
2466
|
+
const severityLine = `Critical: ${p.severities.critical}, High: ${p.severities.high}, Medium: ${p.severities.medium}`;
|
|
2467
|
+
if (agentKind === "security-scanner") {
|
|
2468
|
+
return [
|
|
2469
|
+
`You are a security cascade agent. A Chimera code review flagged security-relevant findings.`,
|
|
2470
|
+
``,
|
|
2471
|
+
`Repository: ${p.bundle.cwd}`,
|
|
2472
|
+
`Severity summary: ${severityLine}`,
|
|
2473
|
+
``,
|
|
2474
|
+
`--- Review report ---`,
|
|
2475
|
+
reportSlice,
|
|
2476
|
+
``,
|
|
2477
|
+
`--- Changed files ---`,
|
|
2478
|
+
fileList,
|
|
2479
|
+
``,
|
|
2480
|
+
`Investigate the security findings above. Read the flagged files, confirm or refute`,
|
|
2481
|
+
`each finding, and **apply fixes** for confirmed vulnerabilities using the edit tool.`,
|
|
2482
|
+
`Use severity (Critical/High/Medium), file:line citations, and remediation steps.`,
|
|
2483
|
+
`After fixing, run the project's typecheck and linter to verify. If a finding is a`,
|
|
2484
|
+
`false positive, say so and do not modify the file.`
|
|
2485
|
+
].join("\n");
|
|
2486
|
+
}
|
|
2487
|
+
return [
|
|
2488
|
+
`You are a bug-hunter cascade agent. A Chimera code review flagged correctness defects.`,
|
|
2489
|
+
``,
|
|
2490
|
+
`Repository: ${p.bundle.cwd}`,
|
|
2491
|
+
`Severity summary: ${severityLine}`,
|
|
2492
|
+
``,
|
|
2493
|
+
`--- Review report ---`,
|
|
2494
|
+
reportSlice,
|
|
2495
|
+
``,
|
|
2496
|
+
`--- Changed files ---`,
|
|
2497
|
+
fileList,
|
|
2498
|
+
``,
|
|
2499
|
+
`Hunt for the bugs flagged above. Read the affected files, trace each finding to its`,
|
|
2500
|
+
`root cause, and **apply minimal fixes** for confirmed bugs using the edit tool.`,
|
|
2501
|
+
`Use severity (Critical/High/Medium), file:line citations. After fixing, run the`,
|
|
2502
|
+
`project's typecheck and linter to verify. If a finding is a false positive, say so`,
|
|
2503
|
+
`and do not modify the file.`
|
|
2504
|
+
].join("\n");
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
// src/chimera-subagent-ladder.ts
|
|
2508
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
2509
|
+
function attemptLabel(attempt) {
|
|
2510
|
+
return attempt.tier === "inherit" ? "inherited model" : `${attempt.provider}/${attempt.model}`;
|
|
2511
|
+
}
|
|
2512
|
+
async function runSubagentModelLadder(opts) {
|
|
2513
|
+
const {
|
|
2514
|
+
director: dir,
|
|
2515
|
+
ladder,
|
|
2516
|
+
buildConfig,
|
|
2517
|
+
buildTask,
|
|
2518
|
+
attemptTimeoutMs = REVIEWER_ATTEMPT_TIMEOUT_MS,
|
|
2519
|
+
budgetMs = REVIEWER_LADDER_BUDGET_MS,
|
|
2520
|
+
keepWinnerAlive = false,
|
|
2521
|
+
onAttemptFailed,
|
|
2522
|
+
onRecovered,
|
|
2523
|
+
now = Date.now
|
|
2524
|
+
} = opts;
|
|
2525
|
+
const startedAt = now();
|
|
2526
|
+
const failures = [];
|
|
2527
|
+
const outcome = { attemptsUsed: 0, failures };
|
|
2528
|
+
for (let rung = 0; rung < ladder.length; rung++) {
|
|
2529
|
+
const attempt = ladder[rung];
|
|
2530
|
+
const timeoutMs = reviewerAttemptTimeoutMs(
|
|
2531
|
+
budgetMs - (now() - startedAt),
|
|
2532
|
+
attemptTimeoutMs,
|
|
2533
|
+
REVIEWER_MIN_ATTEMPT_MS
|
|
2534
|
+
);
|
|
2535
|
+
if (timeoutMs === 0) {
|
|
2536
|
+
outcome.lastError = new Error(
|
|
2537
|
+
`ladder budget exhausted after ${outcome.attemptsUsed} attempt(s)`
|
|
2538
|
+
);
|
|
2539
|
+
break;
|
|
2540
|
+
}
|
|
2541
|
+
outcome.attemptsUsed++;
|
|
2542
|
+
let subagentId;
|
|
2543
|
+
let attemptResult;
|
|
2544
|
+
let attemptError;
|
|
2545
|
+
try {
|
|
2546
|
+
subagentId = await dir.spawn(buildConfig(attempt, timeoutMs));
|
|
2547
|
+
const taskId = randomUUID2();
|
|
2548
|
+
await dir.assign({
|
|
2549
|
+
id: taskId,
|
|
2550
|
+
description: buildTask(attempt, failures),
|
|
2551
|
+
subagentId
|
|
2552
|
+
});
|
|
2553
|
+
attemptResult = (await dir.awaitTasks([taskId]))[0];
|
|
2554
|
+
} catch (err) {
|
|
2555
|
+
attemptError = err;
|
|
2556
|
+
}
|
|
2557
|
+
if (!attemptError && attemptResult?.status === "success") {
|
|
2558
|
+
outcome.result = attemptResult;
|
|
2559
|
+
outcome.wonAt = rung + 1;
|
|
2560
|
+
outcome.lastError = void 0;
|
|
2561
|
+
if (keepWinnerAlive) {
|
|
2562
|
+
outcome.subagentId = subagentId;
|
|
2563
|
+
} else if (subagentId) {
|
|
2564
|
+
await terminateQuietly(dir, subagentId);
|
|
2565
|
+
}
|
|
2566
|
+
if (rung > 0) await onRecovered?.(attempt, failures);
|
|
2567
|
+
return outcome;
|
|
2568
|
+
}
|
|
2569
|
+
if (subagentId) await terminateQuietly(dir, subagentId);
|
|
2570
|
+
outcome.result = attemptResult;
|
|
2571
|
+
outcome.lastError = attemptError;
|
|
2572
|
+
const failure = {
|
|
2573
|
+
model: attemptLabel(attempt),
|
|
2574
|
+
tier: attempt.tier,
|
|
2575
|
+
attempt: rung + 1,
|
|
2576
|
+
reason: attemptError ? errorText(attemptError) : `${attemptResult?.status ?? "unknown"}: ${attemptResult?.error?.message ?? "no result"}`,
|
|
2577
|
+
threw: attemptError !== void 0,
|
|
2578
|
+
toolCalls: attemptResult?.toolCalls ?? 0
|
|
2579
|
+
};
|
|
2580
|
+
failures.push(failure);
|
|
2581
|
+
const canAdvance = attemptError ? true : shouldAdvanceReviewerLadder(attemptResult?.status, attemptResult?.error);
|
|
2582
|
+
const next = canAdvance ? ladder[rung + 1] : void 0;
|
|
2583
|
+
await onAttemptFailed?.(failure, next);
|
|
2584
|
+
if (!next) break;
|
|
2585
|
+
}
|
|
2586
|
+
return outcome;
|
|
2587
|
+
}
|
|
2588
|
+
function buildRetryPreamble(failures) {
|
|
2589
|
+
if (failures.length === 0) return "";
|
|
2590
|
+
const mayHaveWritten = failures.some((f) => f.threw || f.toolCalls > 0);
|
|
2591
|
+
const history = failures.map((f) => `${f.model} (${f.reason})`).join("; ");
|
|
2592
|
+
return [
|
|
2593
|
+
`\u26A0 RETRY \u2014 ${failures.length} previous attempt(s) failed: ${history}.`,
|
|
2594
|
+
mayHaveWritten ? "Those attempts may have already applied part of this work, so the working tree can be in a half-finished state. Re-read every file before you change it and treat any fix that is already present as done \u2014 do not apply it twice." : "They made no tool calls, so the working tree is untouched.",
|
|
2595
|
+
""
|
|
2596
|
+
].join("\n");
|
|
2597
|
+
}
|
|
2598
|
+
function errorText(err) {
|
|
2599
|
+
return err instanceof Error ? err.message : String(err);
|
|
2600
|
+
}
|
|
2601
|
+
async function terminateQuietly(dir, subagentId) {
|
|
2602
|
+
try {
|
|
2603
|
+
await dir.terminate(subagentId);
|
|
2604
|
+
} catch {
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
// src/execution-chimera-cascade.ts
|
|
2609
|
+
var CASCADE_ATTEMPT_TIMEOUT_MS = 6e5;
|
|
2610
|
+
var CASCADE_LADDER_BUDGET_MS = 9e5;
|
|
2611
|
+
var INHERIT_ONLY_LADDER = [
|
|
2612
|
+
{ provider: "", model: "", fallbackModels: [], tier: "inherit" }
|
|
2613
|
+
];
|
|
2614
|
+
function installChimeraCascadeHandler({
|
|
2615
|
+
events,
|
|
2616
|
+
director,
|
|
2617
|
+
session,
|
|
2618
|
+
getPendingWork,
|
|
2619
|
+
setPendingWork,
|
|
2620
|
+
buildLadder
|
|
2621
|
+
}) {
|
|
2622
|
+
events.onPattern("chimera.cascade_needed", (_event, payload) => {
|
|
2623
|
+
const p = payload;
|
|
2624
|
+
const dir = director;
|
|
2625
|
+
if (!dir) return;
|
|
2626
|
+
if (p.agents.length === 0) return;
|
|
2627
|
+
const previousWork = getPendingWork();
|
|
2628
|
+
const pendingWork = (async () => {
|
|
2629
|
+
try {
|
|
2630
|
+
await previousWork;
|
|
2631
|
+
} catch {
|
|
2632
|
+
}
|
|
2633
|
+
for (const agentKind of p.agents) {
|
|
2634
|
+
try {
|
|
2635
|
+
const taskDesc = buildChimeraCascadeTaskDescription(agentKind, p);
|
|
2636
|
+
const role = agentKind === "security-scanner" ? "security-scanner" : "bug-hunter";
|
|
2637
|
+
const ladder = buildLadder?.() ?? INHERIT_ONLY_LADDER;
|
|
2638
|
+
const outcome = await runSubagentModelLadder({
|
|
2639
|
+
director: dir,
|
|
2640
|
+
ladder,
|
|
2641
|
+
attemptTimeoutMs: CASCADE_ATTEMPT_TIMEOUT_MS,
|
|
2642
|
+
budgetMs: CASCADE_LADDER_BUDGET_MS,
|
|
2643
|
+
buildConfig: (attempt, timeoutMs) => ({
|
|
2644
|
+
name: `chimera-cascade-${agentKind}`,
|
|
2645
|
+
role,
|
|
2646
|
+
maxIterations: 40,
|
|
2647
|
+
maxToolCalls: 200,
|
|
2648
|
+
timeoutMs,
|
|
2649
|
+
// Rung 0 stays unpinned so the role model matrix still decides;
|
|
2650
|
+
// later rungs pin a model precisely because it just failed.
|
|
2651
|
+
...attempt.tier === "inherit" ? {} : {
|
|
2652
|
+
provider: attempt.provider,
|
|
2653
|
+
model: attempt.model,
|
|
2654
|
+
fallbackModels: attempt.fallbackModels
|
|
2655
|
+
}
|
|
2656
|
+
}),
|
|
2657
|
+
// Cascade agents write files, so a successor must be told the tree
|
|
2658
|
+
// may already hold the dead attempt's partial edits.
|
|
2659
|
+
buildTask: (_attempt, failures) => `${buildRetryPreamble(failures)}${taskDesc}`,
|
|
2660
|
+
onAttemptFailed: async (failure, next) => {
|
|
2661
|
+
if (!next) return;
|
|
2590
2662
|
await session.append({
|
|
2591
2663
|
type: "error",
|
|
2592
2664
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2593
|
-
message: `\u{1F982} Chimera cascade (${agentKind}) ${
|
|
2665
|
+
message: `\u{1F982} Chimera cascade (${agentKind}) on ${failure.model} failed (${failure.reason}) \u2014 retrying on ${attemptLabel(next)} (${next.tier}).`,
|
|
2594
2666
|
phase: "agent"
|
|
2595
2667
|
});
|
|
2596
2668
|
}
|
|
2597
|
-
}
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2669
|
+
});
|
|
2670
|
+
const result = outcome.result;
|
|
2671
|
+
if (result?.status === "success") {
|
|
2672
|
+
const resultText = typeof result.result === "string" ? result.result : JSON.stringify(result.result);
|
|
2673
|
+
await session.append({
|
|
2674
|
+
type: "llm_response",
|
|
2675
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2676
|
+
content: [
|
|
2677
|
+
{
|
|
2678
|
+
type: "text",
|
|
2679
|
+
text: `\u{1F982} Chimera cascade (${agentKind}) \u2014 ${resultText}`
|
|
2680
|
+
}
|
|
2681
|
+
],
|
|
2682
|
+
stopReason: "end_turn",
|
|
2683
|
+
usage: { input: 0, output: 0 }
|
|
2684
|
+
});
|
|
2685
|
+
} else {
|
|
2686
|
+
const detail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
|
|
2687
|
+
await session.append({
|
|
2688
|
+
type: "error",
|
|
2689
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2690
|
+
message: `\u{1F982} Chimera cascade (${agentKind}) ${result?.status ?? "unknown"}: ${detail} \u2014 exhausted ${outcome.attemptsUsed} of ${ladder.length} model(s)`,
|
|
2691
|
+
phase: "agent"
|
|
2692
|
+
});
|
|
2602
2693
|
}
|
|
2603
2694
|
} catch (err) {
|
|
2604
2695
|
await session.append({
|
|
@@ -2693,6 +2784,357 @@ async function maybeReReviewCascade({
|
|
|
2693
2784
|
}
|
|
2694
2785
|
}
|
|
2695
2786
|
|
|
2787
|
+
// src/execution-chimera-review.ts
|
|
2788
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
2789
|
+
import path9 from "node:path";
|
|
2790
|
+
import { effectiveFallbackChain } from "@wrongstack/core/agent";
|
|
2791
|
+
import {
|
|
2792
|
+
CHIMERA_REVIEW_PROMPT,
|
|
2793
|
+
integrateFindings,
|
|
2794
|
+
maybeCompactReviewStores,
|
|
2795
|
+
parseChimeraReviewReport,
|
|
2796
|
+
persistReviewReport,
|
|
2797
|
+
recordCompletedReview
|
|
2798
|
+
} from "@wrongstack/core/plugin";
|
|
2799
|
+
function normalizeFileKeyForCitation(raw, cwd) {
|
|
2800
|
+
const forward = raw.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
2801
|
+
const isAbsolute = forward.startsWith("/") || /^[a-zA-Z]:\//.test(forward);
|
|
2802
|
+
const relative = isAbsolute ? path9.relative(cwd, forward).replace(/\\/g, "/").replace(/^\.\//, "") : forward;
|
|
2803
|
+
return process.platform === "win32" ? relative.toLowerCase() : relative;
|
|
2804
|
+
}
|
|
2805
|
+
function installChimeraReviewHandler({
|
|
2806
|
+
events,
|
|
2807
|
+
director,
|
|
2808
|
+
session,
|
|
2809
|
+
mailbox,
|
|
2810
|
+
agent,
|
|
2811
|
+
config,
|
|
2812
|
+
projectDir,
|
|
2813
|
+
persistReview = persistChimeraReview,
|
|
2814
|
+
setPendingWork
|
|
2815
|
+
}) {
|
|
2816
|
+
events.onPattern("chimera.review_needed", (_event, payload) => {
|
|
2817
|
+
const p = payload;
|
|
2818
|
+
const reviewSessionId = agent.ctx.activeRunSessionId ?? agent.ctx.session?.id ?? session.id;
|
|
2819
|
+
const dir = director;
|
|
2820
|
+
if (!dir) {
|
|
2821
|
+
return;
|
|
2822
|
+
}
|
|
2823
|
+
if (p.files.length === 0) return;
|
|
2824
|
+
const appendChimeraNotice = async (message) => {
|
|
2825
|
+
try {
|
|
2826
|
+
await session.append({
|
|
2827
|
+
type: "error",
|
|
2828
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2829
|
+
message,
|
|
2830
|
+
phase: "agent"
|
|
2831
|
+
});
|
|
2832
|
+
} catch (err) {
|
|
2833
|
+
console.warn(
|
|
2834
|
+
JSON.stringify({
|
|
2835
|
+
level: "warn",
|
|
2836
|
+
event: "execution.chimera_notice_append_failed",
|
|
2837
|
+
message: err instanceof Error ? err.message : String(err),
|
|
2838
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2839
|
+
})
|
|
2840
|
+
);
|
|
2841
|
+
}
|
|
2842
|
+
};
|
|
2843
|
+
const persistAndEmitCompletion = async (completion) => {
|
|
2844
|
+
try {
|
|
2845
|
+
await persistReview(completion, projectDir);
|
|
2846
|
+
events.emitCustom("chimera.review_persisted", {
|
|
2847
|
+
reportId: completion.reportId,
|
|
2848
|
+
sessionId: completion.sessionId,
|
|
2849
|
+
cwd: completion.cwd
|
|
2850
|
+
});
|
|
2851
|
+
} catch (error) {
|
|
2852
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2853
|
+
events.emitCustom("chimera.review_persistence_failed", {
|
|
2854
|
+
reportId: completion.reportId,
|
|
2855
|
+
sessionId: completion.sessionId,
|
|
2856
|
+
cwd: completion.cwd,
|
|
2857
|
+
error: message
|
|
2858
|
+
});
|
|
2859
|
+
await appendChimeraNotice(
|
|
2860
|
+
`\u{1F982} Chimera report persistence failed: ${message}. The review remains in the session transcript and mailbox.`
|
|
2861
|
+
);
|
|
2862
|
+
} finally {
|
|
2863
|
+
recordCompletedReview(events, completion);
|
|
2864
|
+
events.emitCustom("chimera.review_complete", completion);
|
|
2865
|
+
}
|
|
2866
|
+
};
|
|
2867
|
+
setPendingWork(
|
|
2868
|
+
(async () => {
|
|
2869
|
+
let subagentId;
|
|
2870
|
+
try {
|
|
2871
|
+
const taskDesc = buildChimeraReviewTaskDescription(p);
|
|
2872
|
+
const tProvider = config.provider?.trim() || void 0;
|
|
2873
|
+
const tModel = config.model?.trim() || void 0;
|
|
2874
|
+
const rawProvider = p.reviewFallbackModels ? p.config.provider?.trim() || void 0 : tProvider;
|
|
2875
|
+
const rawModel = p.reviewFallbackModels ? p.config.model?.trim() || void 0 : tModel;
|
|
2876
|
+
const baseProvider = rawProvider || tProvider || config.provider;
|
|
2877
|
+
const baseModel = rawModel || tModel || config.model;
|
|
2878
|
+
const baseFallbacks = p.reviewFallbackModels ? [...p.reviewFallbackModels] : resolveReviewerFallbackModels(void 0);
|
|
2879
|
+
const assigned = assignReviewerModelsRoundRobin(baseProvider, baseModel, baseFallbacks);
|
|
2880
|
+
const ladder = buildReviewerAttemptLadder({
|
|
2881
|
+
assigned,
|
|
2882
|
+
profileChain: effectiveFallbackChain(config),
|
|
2883
|
+
session: { provider: config.provider, model: config.model }
|
|
2884
|
+
});
|
|
2885
|
+
const ladderRefs = ladder.map(attemptLabel);
|
|
2886
|
+
const outcome = await runSubagentModelLadder({
|
|
2887
|
+
director: dir,
|
|
2888
|
+
ladder,
|
|
2889
|
+
budgetMs: REVIEWER_LADDER_BUDGET_MS,
|
|
2890
|
+
keepWinnerAlive: false,
|
|
2891
|
+
buildConfig: (attempt, timeoutMs) => applyChimeraReviewerReadOnlyPolicy({
|
|
2892
|
+
name: "chimera-review",
|
|
2893
|
+
role: "reviewer",
|
|
2894
|
+
systemPromptOverride: CHIMERA_REVIEW_PROMPT,
|
|
2895
|
+
maxIterations: 50,
|
|
2896
|
+
maxToolCalls: 250,
|
|
2897
|
+
timeoutMs,
|
|
2898
|
+
provider: attempt.provider,
|
|
2899
|
+
model: attempt.model,
|
|
2900
|
+
fallbackModels: attempt.fallbackModels
|
|
2901
|
+
}),
|
|
2902
|
+
// The reviewer is read-only, so a retry re-runs the task verbatim.
|
|
2903
|
+
buildTask: () => taskDesc,
|
|
2904
|
+
onAttemptFailed: async (failure, next) => {
|
|
2905
|
+
console.warn(
|
|
2906
|
+
JSON.stringify({
|
|
2907
|
+
level: "warn",
|
|
2908
|
+
event: "execution.chimera_reviewer_attempt_failed",
|
|
2909
|
+
message: failure.reason,
|
|
2910
|
+
model: failure.model,
|
|
2911
|
+
tier: failure.tier,
|
|
2912
|
+
attempt: failure.attempt,
|
|
2913
|
+
of: ladder.length,
|
|
2914
|
+
nextModel: next ? attemptLabel(next) : void 0,
|
|
2915
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2916
|
+
})
|
|
2917
|
+
);
|
|
2918
|
+
if (!next) return;
|
|
2919
|
+
events.emitCustom("chimera.reviewer_model_fallback", {
|
|
2920
|
+
from: failure.model,
|
|
2921
|
+
to: attemptLabel(next),
|
|
2922
|
+
tier: next.tier,
|
|
2923
|
+
attempt: failure.attempt,
|
|
2924
|
+
of: ladder.length,
|
|
2925
|
+
reason: failure.reason
|
|
2926
|
+
});
|
|
2927
|
+
await appendChimeraNotice(
|
|
2928
|
+
`\u{1F982} Chimera review on ${failure.model} failed (${failure.reason}) \u2014 retrying the same review on ${attemptLabel(next)} (${next.tier}).`
|
|
2929
|
+
);
|
|
2930
|
+
},
|
|
2931
|
+
onRecovered: async (attempt, failures) => {
|
|
2932
|
+
await appendChimeraNotice(
|
|
2933
|
+
`\u{1F982} Chimera review recovered on ${attemptLabel(attempt)} (${attempt.tier}) after ${failures.length} failed attempt(s).`
|
|
2934
|
+
);
|
|
2935
|
+
}
|
|
2936
|
+
});
|
|
2937
|
+
subagentId = outcome.subagentId;
|
|
2938
|
+
const result = outcome.result;
|
|
2939
|
+
if (result?.status !== "success") {
|
|
2940
|
+
const exhaustedDetail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
|
|
2941
|
+
try {
|
|
2942
|
+
await session.append({
|
|
2943
|
+
type: "error",
|
|
2944
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2945
|
+
message: `\u{1F982} Chimera review subagent ${result?.status ?? "unknown"}: ${exhaustedDetail} \u2014 exhausted ${outcome.attemptsUsed} of ${ladder.length} model(s): ${ladderRefs.join(" \u2192 ")}`,
|
|
2946
|
+
phase: "agent"
|
|
2947
|
+
});
|
|
2948
|
+
} catch (err) {
|
|
2949
|
+
console.error(
|
|
2950
|
+
JSON.stringify({
|
|
2951
|
+
level: "error",
|
|
2952
|
+
event: "execution.chimera_append_failed",
|
|
2953
|
+
message: err instanceof Error ? err.message : String(err),
|
|
2954
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2955
|
+
})
|
|
2956
|
+
);
|
|
2957
|
+
}
|
|
2958
|
+
await persistAndEmitCompletion({
|
|
2959
|
+
bundle: p,
|
|
2960
|
+
reviewText: "",
|
|
2961
|
+
status: result?.status ?? "unknown",
|
|
2962
|
+
cwd: p.cwd,
|
|
2963
|
+
sessionId: reviewSessionId,
|
|
2964
|
+
reportId: randomUUID3()
|
|
2965
|
+
});
|
|
2966
|
+
return;
|
|
2967
|
+
}
|
|
2968
|
+
const reviewText = typeof result.result === "string" ? result.result.trim() : JSON.stringify(result.result);
|
|
2969
|
+
const reportId = randomUUID3();
|
|
2970
|
+
await persistAndEmitCompletion({
|
|
2971
|
+
bundle: p,
|
|
2972
|
+
reviewText,
|
|
2973
|
+
status: "success",
|
|
2974
|
+
cwd: p.cwd,
|
|
2975
|
+
sessionId: reviewSessionId,
|
|
2976
|
+
reportId
|
|
2977
|
+
});
|
|
2978
|
+
if (reviewText) {
|
|
2979
|
+
const reviewHasFindings = !isChimeraAllClearReview(reviewText);
|
|
2980
|
+
const parsedReview = parseChimeraReviewReport(reviewText);
|
|
2981
|
+
const citedFindings = parsedReview.findings.filter((finding) => finding.location);
|
|
2982
|
+
const citedPaths = new Set(
|
|
2983
|
+
p.files.map((file) => normalizeFileKeyForCitation(file.path, p.cwd))
|
|
2984
|
+
);
|
|
2985
|
+
const changedBasenameIndex = /* @__PURE__ */ new Map();
|
|
2986
|
+
for (const file of p.files) {
|
|
2987
|
+
const normalized = normalizeFileKeyForCitation(file.path, p.cwd);
|
|
2988
|
+
const basename5 = path9.basename(file.path).toLowerCase();
|
|
2989
|
+
const bucket = changedBasenameIndex.get(basename5);
|
|
2990
|
+
if (bucket) bucket.push(normalized);
|
|
2991
|
+
else changedBasenameIndex.set(basename5, [normalized]);
|
|
2992
|
+
}
|
|
2993
|
+
const droppedCitations = citedFindings.filter((finding) => {
|
|
2994
|
+
const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
|
|
2995
|
+
if (citedPaths.has(citedKey)) return false;
|
|
2996
|
+
const basename5 = path9.basename(finding.location.file).toLowerCase();
|
|
2997
|
+
const bucket = changedBasenameIndex.get(basename5);
|
|
2998
|
+
return !(bucket && bucket.length === 1);
|
|
2999
|
+
});
|
|
3000
|
+
const effectiveHasFindings = reviewHasFindings && (parsedReview.findings.length === 0 || parsedReview.findings.length > droppedCitations.length);
|
|
3001
|
+
const hallucinationNote = droppedCitations.length > 0 ? `
|
|
3002
|
+
|
|
3003
|
+
\u26A0\uFE0F Citation validation: ${droppedCitations.length} finding(s) cite files outside the changed-file set and should be verified before acting.` : "";
|
|
3004
|
+
const subject = `\u{1F982} Chimera report ready \u2014 ${p.files.length} file(s) checked`;
|
|
3005
|
+
let reviewMailMessageId;
|
|
3006
|
+
try {
|
|
3007
|
+
const directive = effectiveHasFindings ? "Chimera found potential issues. This report is informational: no leader turn, fix agent, or cascade was started. Open the report and explicitly ask the leader to act if you want changes." : "Chimera completed with no actionable findings. No follow-up was started.";
|
|
3008
|
+
const reviewBody = reviewText.length > 7500 ? truncateAtCodePointBoundary(reviewText, 7500) + "\n\n\u2026(truncated, full report is in the Chimera report store)" : reviewText;
|
|
3009
|
+
const body = `${directive}${hallucinationNote}
|
|
3010
|
+
|
|
3011
|
+
${reviewBody}`;
|
|
3012
|
+
const mailMsg = await mailbox.send({
|
|
3013
|
+
from: "chimera-review",
|
|
3014
|
+
to: "leader",
|
|
3015
|
+
type: "result",
|
|
3016
|
+
audience: "leaders",
|
|
3017
|
+
subject,
|
|
3018
|
+
body,
|
|
3019
|
+
priority: "normal"
|
|
3020
|
+
});
|
|
3021
|
+
if (!mailMsg?.id) throw new Error("mailbox.send returned no message id");
|
|
3022
|
+
reviewMailMessageId = mailMsg.id;
|
|
3023
|
+
events.emitCustom("chimera.mailbox_delivered", {
|
|
3024
|
+
subject,
|
|
3025
|
+
autoFixMode: "off",
|
|
3026
|
+
fileCount: p.files.length,
|
|
3027
|
+
reviewLength: reviewText.length,
|
|
3028
|
+
messageId: reviewMailMessageId
|
|
3029
|
+
});
|
|
3030
|
+
if (!effectiveHasFindings) {
|
|
3031
|
+
try {
|
|
3032
|
+
await mailbox.ack({
|
|
3033
|
+
messageId: reviewMailMessageId,
|
|
3034
|
+
readerId: "chimera",
|
|
3035
|
+
completed: true,
|
|
3036
|
+
outcome: "Review completed with no actionable findings."
|
|
3037
|
+
});
|
|
3038
|
+
} catch (ackError) {
|
|
3039
|
+
console.warn(
|
|
3040
|
+
JSON.stringify({
|
|
3041
|
+
level: "warn",
|
|
3042
|
+
event: "execution.chimera_mailbox_completion_failed",
|
|
3043
|
+
message: ackError instanceof Error ? ackError.message : String(ackError),
|
|
3044
|
+
messageId: reviewMailMessageId,
|
|
3045
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3046
|
+
})
|
|
3047
|
+
);
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
} catch (mailErr) {
|
|
3051
|
+
const errMsg = mailErr instanceof Error ? mailErr.message : String(mailErr);
|
|
3052
|
+
console.error(
|
|
3053
|
+
JSON.stringify({
|
|
3054
|
+
level: "error",
|
|
3055
|
+
event: "execution.chimera_mailbox_failed",
|
|
3056
|
+
message: errMsg,
|
|
3057
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3058
|
+
})
|
|
3059
|
+
);
|
|
3060
|
+
events.emitCustom("chimera.mailbox_failed", {
|
|
3061
|
+
subject,
|
|
3062
|
+
autoFixMode: "off",
|
|
3063
|
+
fileCount: p.files.length,
|
|
3064
|
+
reviewLength: reviewText.length,
|
|
3065
|
+
error: errMsg
|
|
3066
|
+
});
|
|
3067
|
+
await session.append({
|
|
3068
|
+
type: "error",
|
|
3069
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3070
|
+
message: `\u{1F982} Chimera report ${reportId} is ready, but mailbox delivery failed: ${errMsg}. No follow-up was started.`,
|
|
3071
|
+
phase: "agent"
|
|
3072
|
+
});
|
|
3073
|
+
}
|
|
3074
|
+
const findingCount = Math.max(
|
|
3075
|
+
0,
|
|
3076
|
+
parsedReview.findings.length - droppedCitations.length
|
|
3077
|
+
);
|
|
3078
|
+
const message = effectiveHasFindings ? `\u{1F982} Chimera report ready \u2014 ${findingCount || "unparsed"} potential finding(s) across ${p.files.length} file(s). No follow-up started; open the mailbox and explicitly ask the leader to act if wanted.` : `\u{1F982} Chimera report ready \u2014 ${p.files.length} file(s) checked, no actionable findings. No follow-up started.`;
|
|
3079
|
+
events.emitCustom("chimera.report_available", {
|
|
3080
|
+
reportId,
|
|
3081
|
+
sessionId: reviewSessionId,
|
|
3082
|
+
message,
|
|
3083
|
+
fileCount: p.files.length,
|
|
3084
|
+
findingCount,
|
|
3085
|
+
hasActionableFindings: effectiveHasFindings,
|
|
3086
|
+
...reviewMailMessageId ? { messageId: reviewMailMessageId } : {}
|
|
3087
|
+
});
|
|
3088
|
+
}
|
|
3089
|
+
} catch (err) {
|
|
3090
|
+
try {
|
|
3091
|
+
await session.append({
|
|
3092
|
+
type: "error",
|
|
3093
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3094
|
+
message: `\u{1F982} Chimera review failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
3095
|
+
phase: "agent"
|
|
3096
|
+
});
|
|
3097
|
+
} catch (appendErr) {
|
|
3098
|
+
console.error(
|
|
3099
|
+
JSON.stringify({
|
|
3100
|
+
level: "error",
|
|
3101
|
+
event: "execution.chimera_review_append_failed",
|
|
3102
|
+
message: appendErr instanceof Error ? appendErr.message : String(appendErr),
|
|
3103
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3104
|
+
})
|
|
3105
|
+
);
|
|
3106
|
+
}
|
|
3107
|
+
} finally {
|
|
3108
|
+
if (subagentId) {
|
|
3109
|
+
try {
|
|
3110
|
+
await dir.terminate(subagentId);
|
|
3111
|
+
} catch {
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
})()
|
|
3116
|
+
);
|
|
3117
|
+
});
|
|
3118
|
+
}
|
|
3119
|
+
async function persistChimeraReview(payload, projectDir) {
|
|
3120
|
+
const reportId = payload.reportId;
|
|
3121
|
+
if (!reportId) throw new Error("Chimera completion is missing reportId");
|
|
3122
|
+
await persistReviewReport(payload, reportId, projectDir);
|
|
3123
|
+
await integrateFindings(payload, projectDir, reportId);
|
|
3124
|
+
try {
|
|
3125
|
+
await maybeCompactReviewStores(projectDir);
|
|
3126
|
+
} catch (error) {
|
|
3127
|
+
console.error(
|
|
3128
|
+
JSON.stringify({
|
|
3129
|
+
level: "warn",
|
|
3130
|
+
event: "execution.chimera_store_maintenance_failed",
|
|
3131
|
+
message: error instanceof Error ? error.message : String(error),
|
|
3132
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3133
|
+
})
|
|
3134
|
+
);
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
|
|
2696
3138
|
// src/execution-storage-observability.ts
|
|
2697
3139
|
function installStorageObservability(events, rootTraceId) {
|
|
2698
3140
|
const isStorageNamespace = (event) => event === "storage.read" || event === "storage.write" || event === "storage.error" || event.startsWith("storage.");
|
|
@@ -3061,7 +3503,7 @@ function printBanner(renderer, projectName) {
|
|
|
3061
3503
|
|
|
3062
3504
|
// src/repl-client-registration.ts
|
|
3063
3505
|
import * as crypto from "node:crypto";
|
|
3064
|
-
import * as
|
|
3506
|
+
import * as path10 from "node:path";
|
|
3065
3507
|
import {
|
|
3066
3508
|
getSharedProjectMailbox,
|
|
3067
3509
|
resolveProjectDir
|
|
@@ -3074,7 +3516,7 @@ function registerReplClient(opts) {
|
|
|
3074
3516
|
const hqConnection = startCliHqConnection({
|
|
3075
3517
|
clientKind: "repl",
|
|
3076
3518
|
projectRoot: replProjectRoot,
|
|
3077
|
-
projectName:
|
|
3519
|
+
projectName: path10.basename(replProjectRoot),
|
|
3078
3520
|
appConfig: opts.appConfig,
|
|
3079
3521
|
capabilities: ["telemetry.publish", "mailbox.summary"]
|
|
3080
3522
|
});
|
|
@@ -3083,14 +3525,16 @@ function registerReplClient(opts) {
|
|
|
3083
3525
|
void 0,
|
|
3084
3526
|
() => hqConnection.getPublisher()
|
|
3085
3527
|
);
|
|
3528
|
+
let closed = false;
|
|
3086
3529
|
let clientHeartbeat;
|
|
3087
3530
|
clientMailbox.registerClient({
|
|
3088
3531
|
clientId,
|
|
3089
3532
|
sessionId: opts.getSessionId?.() ?? replProjectRoot,
|
|
3090
|
-
name: `REPL [${
|
|
3533
|
+
name: `REPL [${path10.basename(replProjectRoot)}]`,
|
|
3091
3534
|
source: "repl",
|
|
3092
3535
|
pid: process.pid
|
|
3093
3536
|
}).then(() => {
|
|
3537
|
+
if (closed) return;
|
|
3094
3538
|
clientHeartbeat = setInterval(() => {
|
|
3095
3539
|
clientMailbox.clientHeartbeat({ clientId, sessionId: opts.getSessionId?.() ?? replProjectRoot }).catch(() => {
|
|
3096
3540
|
});
|
|
@@ -3100,6 +3544,7 @@ function registerReplClient(opts) {
|
|
|
3100
3544
|
return {
|
|
3101
3545
|
clientId,
|
|
3102
3546
|
close() {
|
|
3547
|
+
closed = true;
|
|
3103
3548
|
if (clientHeartbeat) clearInterval(clientHeartbeat);
|
|
3104
3549
|
clientMailbox.deregisterClient(clientId).catch(() => void 0);
|
|
3105
3550
|
hqConnection.stop();
|
|
@@ -3993,313 +4438,26 @@ async function execute(deps) {
|
|
|
3993
4438
|
const bootUpdateInfo = initialUpdateInfo;
|
|
3994
4439
|
const offStorageObservability = installStorageObservability(events, context.traceId);
|
|
3995
4440
|
let pendingChimeraWork;
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4441
|
+
installChimeraReviewHandler({
|
|
4442
|
+
events,
|
|
4443
|
+
director,
|
|
4444
|
+
session,
|
|
4445
|
+
mailbox,
|
|
4446
|
+
agent,
|
|
4447
|
+
config,
|
|
4448
|
+
projectDir: wpaths.projectDir,
|
|
4449
|
+
setPendingWork: (work) => {
|
|
4450
|
+
pendingChimeraWork = work;
|
|
4001
4451
|
}
|
|
4002
|
-
if (p.files.length === 0) return;
|
|
4003
|
-
pendingChimeraWork = (async () => {
|
|
4004
|
-
let subagentId;
|
|
4005
|
-
try {
|
|
4006
|
-
const taskDesc = buildChimeraReviewTaskDescription(p);
|
|
4007
|
-
const tProvider = config.provider?.trim() || void 0;
|
|
4008
|
-
const tModel = config.model?.trim() || void 0;
|
|
4009
|
-
const rawProvider = p.reviewFallbackModels ? p.config.provider?.trim() || void 0 : tProvider;
|
|
4010
|
-
const rawModel = p.reviewFallbackModels ? p.config.model?.trim() || void 0 : tModel;
|
|
4011
|
-
const baseProvider = rawProvider || tProvider || config.provider;
|
|
4012
|
-
const baseModel = rawModel || tModel || config.model;
|
|
4013
|
-
const baseFallbacks = p.reviewFallbackModels ? [...p.reviewFallbackModels] : resolveReviewerFallbackModels(void 0);
|
|
4014
|
-
const assigned = assignReviewerModelsRoundRobin(baseProvider, baseModel, baseFallbacks);
|
|
4015
|
-
const cfg = applyChimeraReviewerReadOnlyPolicy({
|
|
4016
|
-
name: "chimera-review",
|
|
4017
|
-
role: "reviewer",
|
|
4018
|
-
systemPromptOverride: CHIMERA_REVIEW_PROMPT,
|
|
4019
|
-
maxIterations: 50,
|
|
4020
|
-
maxToolCalls: 250,
|
|
4021
|
-
timeoutMs: 9e5,
|
|
4022
|
-
provider: assigned.provider,
|
|
4023
|
-
model: assigned.model,
|
|
4024
|
-
fallbackModels: assigned.fallbackModels
|
|
4025
|
-
});
|
|
4026
|
-
subagentId = await dir.spawn(cfg);
|
|
4027
|
-
const taskId = randomUUID4();
|
|
4028
|
-
await dir.assign({
|
|
4029
|
-
id: taskId,
|
|
4030
|
-
description: taskDesc,
|
|
4031
|
-
subagentId
|
|
4032
|
-
});
|
|
4033
|
-
const results = await dir.awaitTasks([taskId]);
|
|
4034
|
-
const result = results[0];
|
|
4035
|
-
if (result?.status !== "success") {
|
|
4036
|
-
try {
|
|
4037
|
-
await session.append({
|
|
4038
|
-
type: "error",
|
|
4039
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4040
|
-
message: `\u{1F982} Chimera review subagent ${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`,
|
|
4041
|
-
phase: "agent"
|
|
4042
|
-
});
|
|
4043
|
-
} catch (err) {
|
|
4044
|
-
console.error(
|
|
4045
|
-
JSON.stringify({
|
|
4046
|
-
level: "error",
|
|
4047
|
-
event: "execution.chimera_append_failed",
|
|
4048
|
-
message: err instanceof Error ? err.message : String(err),
|
|
4049
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4050
|
-
})
|
|
4051
|
-
);
|
|
4052
|
-
}
|
|
4053
|
-
events.emitCustom("chimera.review_complete", {
|
|
4054
|
-
bundle: p,
|
|
4055
|
-
reviewText: "",
|
|
4056
|
-
status: result?.status ?? "unknown",
|
|
4057
|
-
cwd: p.cwd,
|
|
4058
|
-
sessionId: session.id
|
|
4059
|
-
});
|
|
4060
|
-
return;
|
|
4061
|
-
}
|
|
4062
|
-
const reviewText = typeof result.result === "string" ? result.result.trim() : JSON.stringify(result.result);
|
|
4063
|
-
events.emitCustom("chimera.review_complete", {
|
|
4064
|
-
bundle: p,
|
|
4065
|
-
reviewText,
|
|
4066
|
-
status: "success",
|
|
4067
|
-
cwd: p.cwd,
|
|
4068
|
-
sessionId: session.id
|
|
4069
|
-
});
|
|
4070
|
-
if (reviewText) {
|
|
4071
|
-
await session.append({
|
|
4072
|
-
type: "llm_response",
|
|
4073
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4074
|
-
content: [{ type: "text", text: reviewText }],
|
|
4075
|
-
stopReason: "end_turn",
|
|
4076
|
-
usage: { input: 0, output: 0 }
|
|
4077
|
-
});
|
|
4078
|
-
const autoFix = agent.ctx.meta["chimeraAutoFix"] ?? p.config.autoFix ?? "off";
|
|
4079
|
-
const reviewHasFindings = !isChimeraAllClearReview(reviewText);
|
|
4080
|
-
const isAskMode = autoFix === "ask" && reviewHasFindings;
|
|
4081
|
-
const mailboxType = isAskMode ? "ask" : "result";
|
|
4082
|
-
const subject = isAskMode ? `\u{1F982} Chimera review \u2014 ${p.files.length} file(s) changed. Shall I fix the findings?` : `\u{1F982} Chimera review \u2014 ${p.files.length} file(s) changed`;
|
|
4083
|
-
let leaderApproved = false;
|
|
4084
|
-
let spawnedFix = false;
|
|
4085
|
-
let askMailMsgId;
|
|
4086
|
-
let leaderOnline = false;
|
|
4087
|
-
if (isAskMode) {
|
|
4088
|
-
try {
|
|
4089
|
-
const onlineAgents = await mailbox.getOnlineAgents();
|
|
4090
|
-
leaderOnline = onlineAgents.some(
|
|
4091
|
-
(a) => a.online && isMailboxLeader(a.agentId, a.role)
|
|
4092
|
-
);
|
|
4093
|
-
} catch (leaderCheckErr) {
|
|
4094
|
-
console.warn(
|
|
4095
|
-
JSON.stringify({
|
|
4096
|
-
level: "warn",
|
|
4097
|
-
event: "execution.chimera_leader_check_failed",
|
|
4098
|
-
message: leaderCheckErr instanceof Error ? leaderCheckErr.message : String(leaderCheckErr),
|
|
4099
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4100
|
-
})
|
|
4101
|
-
);
|
|
4102
|
-
}
|
|
4103
|
-
if (!leaderOnline) {
|
|
4104
|
-
console.warn(
|
|
4105
|
-
JSON.stringify({
|
|
4106
|
-
level: "warn",
|
|
4107
|
-
event: "execution.chimera_mailbox_leader_offline",
|
|
4108
|
-
message: `Leader not online \u2014 mailbox ${mailboxType} from chimera-review to leader will be delivered when leader reconnects`,
|
|
4109
|
-
fileCount: p.files.length,
|
|
4110
|
-
autoFix,
|
|
4111
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4112
|
-
})
|
|
4113
|
-
);
|
|
4114
|
-
}
|
|
4115
|
-
} else {
|
|
4116
|
-
leaderOnline = true;
|
|
4117
|
-
console.debug(
|
|
4118
|
-
JSON.stringify({
|
|
4119
|
-
level: "debug",
|
|
4120
|
-
event: "execution.chimera_auto_no_presence_check",
|
|
4121
|
-
message: "Result mode: leader presence not checked \u2014 mailbox message delivered regardless",
|
|
4122
|
-
fileCount: p.files.length,
|
|
4123
|
-
autoFix,
|
|
4124
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4125
|
-
})
|
|
4126
|
-
);
|
|
4127
|
-
}
|
|
4128
|
-
try {
|
|
4129
|
-
const askTimeoutRaw = agent.ctx.meta["chimeraAskTimeoutMs"] ?? 3e4;
|
|
4130
|
-
const ASK_TIMEOUT_MS = Number.isFinite(askTimeoutRaw) ? Math.max(0, askTimeoutRaw) : 3e4;
|
|
4131
|
-
const directive = isAskMode ? `LEADER ACTION REQUIRED: The Chimera review below found issues. Reply with "yes" to auto-fix, or "no" to skip (${ASK_TIMEOUT_MS / 1e3}s timeout).` : reviewHasFindings ? "LEADER ACTION REQUIRED: The Chimera review below found issues. Read the report and fix any Critical or High findings automatically using the edit tool. Verify with typecheck and linter." : "Chimera review completed with no findings. Read the report summary below; no fix action is requested.";
|
|
4132
|
-
const reviewBody = reviewText.length > 7500 ? truncateAtCodePointBoundary(reviewText, 7500) + "\n\n\u2026(truncated, full report in session transcript)" : reviewText;
|
|
4133
|
-
const body = `${directive}
|
|
4134
|
-
|
|
4135
|
-
${reviewBody}`;
|
|
4136
|
-
const mailMsg = await mailbox.send({
|
|
4137
|
-
from: "chimera-review",
|
|
4138
|
-
to: "leader",
|
|
4139
|
-
type: mailboxType,
|
|
4140
|
-
audience: "leaders",
|
|
4141
|
-
subject,
|
|
4142
|
-
body,
|
|
4143
|
-
priority: "normal"
|
|
4144
|
-
});
|
|
4145
|
-
if (!mailMsg?.id) throw new Error("mailbox.send returned no message id");
|
|
4146
|
-
askMailMsgId = mailMsg.id;
|
|
4147
|
-
if (isAskMode) {
|
|
4148
|
-
leaderApproved = await waitForChimeraAskApproval({
|
|
4149
|
-
mailbox,
|
|
4150
|
-
messageId: askMailMsgId,
|
|
4151
|
-
meta: agent.ctx.meta,
|
|
4152
|
-
session: agent.ctx.session ?? session,
|
|
4153
|
-
askTimeoutMs: ASK_TIMEOUT_MS
|
|
4154
|
-
});
|
|
4155
|
-
}
|
|
4156
|
-
} catch (mailErr) {
|
|
4157
|
-
const errMsg = mailErr instanceof Error ? mailErr.message : String(mailErr);
|
|
4158
|
-
console.error(
|
|
4159
|
-
JSON.stringify({
|
|
4160
|
-
level: "error",
|
|
4161
|
-
event: "execution.chimera_mailbox_failed",
|
|
4162
|
-
message: errMsg,
|
|
4163
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4164
|
-
})
|
|
4165
|
-
);
|
|
4166
|
-
await session.append({
|
|
4167
|
-
type: "error",
|
|
4168
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4169
|
-
message: `\u{1F982} Chimera auto-fix skipped \u2014 mailbox unreachable: ${errMsg}. Falling back to manual review mode.`,
|
|
4170
|
-
phase: "agent"
|
|
4171
|
-
});
|
|
4172
|
-
}
|
|
4173
|
-
events.emitCustom("chimera.mailbox_delivered", {
|
|
4174
|
-
subject,
|
|
4175
|
-
autoFixMode: autoFix,
|
|
4176
|
-
fileCount: p.files.length,
|
|
4177
|
-
reviewLength: reviewText.length
|
|
4178
|
-
});
|
|
4179
|
-
if (!leaderOnline) {
|
|
4180
|
-
try {
|
|
4181
|
-
await mailbox.send({
|
|
4182
|
-
from: "chimera-review",
|
|
4183
|
-
to: "leader",
|
|
4184
|
-
type: "note",
|
|
4185
|
-
audience: "leaders",
|
|
4186
|
-
subject: `\u23F0 Chimera review pending \u2014 ${p.files.length} file(s) checked`,
|
|
4187
|
-
body: `The leader was offline when a chimera review completed. A full review result with "LEADER ACTION REQUIRED" directive is waiting in this mailbox from chimera-review. Open it, read the findings, and fix any Critical or High issues.`,
|
|
4188
|
-
priority: "high"
|
|
4189
|
-
});
|
|
4190
|
-
} catch (wakeErr) {
|
|
4191
|
-
console.warn(
|
|
4192
|
-
JSON.stringify({
|
|
4193
|
-
level: "warn",
|
|
4194
|
-
event: "execution.chimera_wakeup_companion_failed",
|
|
4195
|
-
message: wakeErr instanceof Error ? wakeErr.message : String(wakeErr),
|
|
4196
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4197
|
-
})
|
|
4198
|
-
);
|
|
4199
|
-
}
|
|
4200
|
-
}
|
|
4201
|
-
const shouldSpawnFix = !spawnedFix && reviewHasFindings && (autoFix === "auto" || isAskMode && leaderApproved) && reviewText.length > 0;
|
|
4202
|
-
if (shouldSpawnFix) {
|
|
4203
|
-
spawnedFix = true;
|
|
4204
|
-
const fixTaskDesc = [
|
|
4205
|
-
`You are a fix agent. Apply the fixes requested in this review report.`,
|
|
4206
|
-
``,
|
|
4207
|
-
`Repository: ${p.cwd}`,
|
|
4208
|
-
``,
|
|
4209
|
-
`--- Review report ---`,
|
|
4210
|
-
truncateAtCodePointBoundary(reviewText, 12e3),
|
|
4211
|
-
``,
|
|
4212
|
-
`--- Changed files ---`,
|
|
4213
|
-
p.files.map((f) => `- ${f.path}`).join("\n"),
|
|
4214
|
-
``,
|
|
4215
|
-
`Read each file, understand the issue, apply fixes using the edit tool.`,
|
|
4216
|
-
`After fixing, run the project's typecheck and linter to verify.`,
|
|
4217
|
-
`Do NOT remove or reorder existing code unless the bug requires it.`
|
|
4218
|
-
].join("\n");
|
|
4219
|
-
try {
|
|
4220
|
-
const fixCfg = {
|
|
4221
|
-
name: "chimera-fix",
|
|
4222
|
-
role: "fixer",
|
|
4223
|
-
maxIterations: 60,
|
|
4224
|
-
maxToolCalls: 350,
|
|
4225
|
-
timeoutMs: 12e5
|
|
4226
|
-
};
|
|
4227
|
-
const fixSubagentId = await dir.spawn(fixCfg);
|
|
4228
|
-
try {
|
|
4229
|
-
const fixTaskId = randomUUID4();
|
|
4230
|
-
await dir.assign({
|
|
4231
|
-
id: fixTaskId,
|
|
4232
|
-
description: fixTaskDesc,
|
|
4233
|
-
subagentId: fixSubagentId
|
|
4234
|
-
});
|
|
4235
|
-
const fixResults = await dir.awaitTasks([fixTaskId]);
|
|
4236
|
-
const fixResult = fixResults[0];
|
|
4237
|
-
if (fixResult?.status === "success") {
|
|
4238
|
-
await session.append({
|
|
4239
|
-
type: "llm_response",
|
|
4240
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4241
|
-
content: [
|
|
4242
|
-
{ type: "text", text: `Chimera fix subagent completed: ${fixResult.result}` }
|
|
4243
|
-
],
|
|
4244
|
-
stopReason: "end_turn",
|
|
4245
|
-
usage: { input: 0, output: 0 }
|
|
4246
|
-
});
|
|
4247
|
-
} else {
|
|
4248
|
-
await session.append({
|
|
4249
|
-
type: "error",
|
|
4250
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4251
|
-
message: `Chimera fix subagent ${fixResult?.status ?? "unknown"}: ${fixResult?.error?.message ?? "no result"}`,
|
|
4252
|
-
phase: "agent"
|
|
4253
|
-
});
|
|
4254
|
-
}
|
|
4255
|
-
} finally {
|
|
4256
|
-
try {
|
|
4257
|
-
await dir.terminate(fixSubagentId);
|
|
4258
|
-
} catch {
|
|
4259
|
-
}
|
|
4260
|
-
}
|
|
4261
|
-
} catch (fixErr) {
|
|
4262
|
-
await session.append({
|
|
4263
|
-
type: "error",
|
|
4264
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4265
|
-
message: `\u{1F982} Chimera auto-fix failed: ${fixErr instanceof Error ? fixErr.message : String(fixErr)}`,
|
|
4266
|
-
phase: "agent"
|
|
4267
|
-
});
|
|
4268
|
-
}
|
|
4269
|
-
}
|
|
4270
|
-
}
|
|
4271
|
-
} catch (err) {
|
|
4272
|
-
try {
|
|
4273
|
-
await session.append({
|
|
4274
|
-
type: "error",
|
|
4275
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4276
|
-
message: `\u{1F982} Chimera review failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
4277
|
-
phase: "agent"
|
|
4278
|
-
});
|
|
4279
|
-
} catch (appendErr) {
|
|
4280
|
-
console.error(
|
|
4281
|
-
JSON.stringify({
|
|
4282
|
-
level: "error",
|
|
4283
|
-
event: "execution.chimera_review_append_failed",
|
|
4284
|
-
message: appendErr instanceof Error ? appendErr.message : String(appendErr),
|
|
4285
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4286
|
-
})
|
|
4287
|
-
);
|
|
4288
|
-
}
|
|
4289
|
-
} finally {
|
|
4290
|
-
if (subagentId) {
|
|
4291
|
-
try {
|
|
4292
|
-
await dir.terminate(subagentId);
|
|
4293
|
-
} catch {
|
|
4294
|
-
}
|
|
4295
|
-
}
|
|
4296
|
-
}
|
|
4297
|
-
})();
|
|
4298
4452
|
});
|
|
4299
4453
|
installChimeraCascadeHandler({
|
|
4300
4454
|
events,
|
|
4301
4455
|
director,
|
|
4302
4456
|
session,
|
|
4457
|
+
buildLadder: () => buildMutatingAgentLadder({
|
|
4458
|
+
profileChain: effectiveFallbackChain2(config),
|
|
4459
|
+
session: { provider: config.provider, model: config.model }
|
|
4460
|
+
}),
|
|
4303
4461
|
getPendingWork: () => pendingChimeraWork,
|
|
4304
4462
|
setPendingWork: (work) => {
|
|
4305
4463
|
pendingChimeraWork = work;
|
|
@@ -4651,7 +4809,7 @@ ${reviewBody}`;
|
|
|
4651
4809
|
attachments,
|
|
4652
4810
|
effectiveMaxContext,
|
|
4653
4811
|
getEffectiveMaxContext,
|
|
4654
|
-
projectName:
|
|
4812
|
+
projectName: path11.basename(projectRoot) || void 0,
|
|
4655
4813
|
projectRoot,
|
|
4656
4814
|
appConfig: config,
|
|
4657
4815
|
getSessionId: () => agent.ctx.session?.id ?? session.id,
|
|
@@ -4709,4 +4867,4 @@ export {
|
|
|
4709
4867
|
execute,
|
|
4710
4868
|
resolveReviewerFallbackModels
|
|
4711
4869
|
};
|
|
4712
|
-
//# sourceMappingURL=execution-
|
|
4870
|
+
//# sourceMappingURL=execution-HJ643JGZ.js.map
|