@cluesmith/codev 3.2.3 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard-dist/assets/index-BZRTEMtH.css +32 -0
- package/dashboard-dist/assets/{index-BZ1x7x1X.js → index-JCbkpAcV.js} +33 -33
- package/dashboard-dist/assets/index-JCbkpAcV.js.map +1 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +173 -0
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/attach.js +2 -2
- package/dist/agent-farm/commands/attach.js.map +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.js +16 -0
- package/dist/agent-farm/commands/cleanup.js.map +1 -1
- package/dist/agent-farm/commands/inbox.d.ts +42 -0
- package/dist/agent-farm/commands/inbox.d.ts.map +1 -0
- package/dist/agent-farm/commands/inbox.js +129 -0
- package/dist/agent-farm/commands/inbox.js.map +1 -0
- package/dist/agent-farm/commands/interrupt.d.ts +20 -0
- package/dist/agent-farm/commands/interrupt.d.ts.map +1 -0
- package/dist/agent-farm/commands/interrupt.js +65 -0
- package/dist/agent-farm/commands/interrupt.js.map +1 -0
- package/dist/agent-farm/commands/reset/constants.d.ts +52 -0
- package/dist/agent-farm/commands/reset/constants.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/constants.js +52 -0
- package/dist/agent-farm/commands/reset/constants.js.map +1 -0
- package/dist/agent-farm/commands/reset/context.d.ts +230 -0
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/context.js +428 -0
- package/dist/agent-farm/commands/reset/context.js.map +1 -0
- package/dist/agent-farm/commands/reset/index.d.ts +192 -0
- package/dist/agent-farm/commands/reset/index.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/index.js +488 -0
- package/dist/agent-farm/commands/reset/index.js.map +1 -0
- package/dist/agent-farm/commands/reset/receipt.d.ts +97 -0
- package/dist/agent-farm/commands/reset/receipt.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/receipt.js +149 -0
- package/dist/agent-farm/commands/reset/receipt.js.map +1 -0
- package/dist/agent-farm/commands/reset/reorient.d.ts +117 -0
- package/dist/agent-farm/commands/reset/reorient.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset/reorient.js +313 -0
- package/dist/agent-farm/commands/reset/reorient.js.map +1 -0
- package/dist/agent-farm/commands/reset.d.ts +19 -0
- package/dist/agent-farm/commands/reset.d.ts.map +1 -0
- package/dist/agent-farm/commands/reset.js +292 -0
- package/dist/agent-farm/commands/reset.js.map +1 -0
- package/dist/agent-farm/commands/send.d.ts +2 -2
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +52 -11
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/setup.d.ts +4 -1
- package/dist/agent-farm/commands/setup.d.ts.map +1 -1
- package/dist/agent-farm/commands/setup.js +8 -4
- package/dist/agent-farm/commands/setup.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts +116 -6
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +345 -74
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +13 -1
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/commands/status.d.ts.map +1 -1
- package/dist/agent-farm/commands/status.js +105 -9
- package/dist/agent-farm/commands/status.js.map +1 -1
- package/dist/agent-farm/commands/tower-sweep-husks.d.ts +6 -0
- package/dist/agent-farm/commands/tower-sweep-husks.d.ts.map +1 -0
- package/dist/agent-farm/commands/tower-sweep-husks.js +77 -0
- package/dist/agent-farm/commands/tower-sweep-husks.js.map +1 -0
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +34 -0
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/commands/whoami.d.ts +65 -0
- package/dist/agent-farm/commands/whoami.d.ts.map +1 -0
- package/dist/agent-farm/commands/whoami.js +196 -0
- package/dist/agent-farm/commands/whoami.js.map +1 -0
- package/dist/agent-farm/db/index.d.ts +1 -1
- package/dist/agent-farm/db/index.d.ts.map +1 -1
- package/dist/agent-farm/db/index.js +80 -1
- package/dist/agent-farm/db/index.js.map +1 -1
- package/dist/agent-farm/db/mailbox.d.ts +222 -0
- package/dist/agent-farm/db/mailbox.d.ts.map +1 -0
- package/dist/agent-farm/db/mailbox.js +304 -0
- package/dist/agent-farm/db/mailbox.js.map +1 -0
- package/dist/agent-farm/db/schema.d.ts +1 -1
- package/dist/agent-farm/db/schema.d.ts.map +1 -1
- package/dist/agent-farm/db/schema.js +35 -0
- package/dist/agent-farm/db/schema.js.map +1 -1
- package/dist/agent-farm/db/types.d.ts +45 -0
- package/dist/agent-farm/db/types.d.ts.map +1 -1
- package/dist/agent-farm/db/types.js.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.d.ts +1 -1
- package/dist/agent-farm/lib/builder-lookup.js +2 -2
- package/dist/agent-farm/lib/builder-lookup.js.map +1 -1
- package/dist/agent-farm/lib/reconnect-backoff.d.ts +54 -0
- package/dist/agent-farm/lib/reconnect-backoff.d.ts.map +1 -0
- package/dist/agent-farm/lib/reconnect-backoff.js +47 -0
- package/dist/agent-farm/lib/reconnect-backoff.js.map +1 -0
- package/dist/agent-farm/lib/tower-client.d.ts +16 -6
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tower-client.js +37 -6
- package/dist/agent-farm/lib/tower-client.js.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts +69 -1
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +218 -27
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/architect-session-holder.d.ts +133 -0
- package/dist/agent-farm/servers/architect-session-holder.d.ts.map +1 -0
- package/dist/agent-farm/servers/architect-session-holder.js +268 -0
- package/dist/agent-farm/servers/architect-session-holder.js.map +1 -0
- package/dist/agent-farm/servers/cron-delivery.d.ts +72 -0
- package/dist/agent-farm/servers/cron-delivery.d.ts.map +1 -0
- package/dist/agent-farm/servers/cron-delivery.js +80 -0
- package/dist/agent-farm/servers/cron-delivery.js.map +1 -0
- package/dist/agent-farm/servers/delayed-send.d.ts +85 -0
- package/dist/agent-farm/servers/delayed-send.d.ts.map +1 -0
- package/dist/agent-farm/servers/delayed-send.js +165 -0
- package/dist/agent-farm/servers/delayed-send.js.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts +67 -0
- package/dist/agent-farm/servers/gate-profiles.d.ts.map +1 -0
- package/dist/agent-farm/servers/gate-profiles.js +113 -0
- package/dist/agent-farm/servers/gate-profiles.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts +370 -0
- package/dist/agent-farm/servers/mailbox-delivery.d.ts.map +1 -0
- package/dist/agent-farm/servers/mailbox-delivery.js +617 -0
- package/dist/agent-farm/servers/mailbox-delivery.js.map +1 -0
- package/dist/agent-farm/servers/mailbox-wiring.d.ts +125 -0
- package/dist/agent-farm/servers/mailbox-wiring.d.ts.map +1 -0
- package/dist/agent-farm/servers/mailbox-wiring.js +425 -0
- package/dist/agent-farm/servers/mailbox-wiring.js.map +1 -0
- package/dist/agent-farm/servers/message-write.d.ts +53 -1
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -1
- package/dist/agent-farm/servers/message-write.js +63 -0
- package/dist/agent-farm/servers/message-write.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +23 -4
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/process-census.d.ts +41 -0
- package/dist/agent-farm/servers/process-census.d.ts.map +1 -0
- package/dist/agent-farm/servers/process-census.js +62 -0
- package/dist/agent-farm/servers/process-census.js.map +1 -0
- package/dist/agent-farm/servers/render-gate.d.ts +141 -0
- package/dist/agent-farm/servers/render-gate.d.ts.map +1 -0
- package/dist/agent-farm/servers/render-gate.js +251 -0
- package/dist/agent-farm/servers/render-gate.js.map +1 -0
- package/dist/agent-farm/servers/session-log-sweep.d.ts +93 -0
- package/dist/agent-farm/servers/session-log-sweep.d.ts.map +1 -0
- package/dist/agent-farm/servers/session-log-sweep.js +165 -0
- package/dist/agent-farm/servers/session-log-sweep.js.map +1 -0
- package/dist/agent-farm/servers/session-submit.d.ts +90 -0
- package/dist/agent-farm/servers/session-submit.d.ts.map +1 -0
- package/dist/agent-farm/servers/session-submit.js +127 -0
- package/dist/agent-farm/servers/session-submit.js.map +1 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.d.ts +87 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.d.ts.map +1 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.js +129 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.js.map +1 -0
- package/dist/agent-farm/servers/tower-cron.d.ts +10 -7
- package/dist/agent-farm/servers/tower-cron.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-cron.js +58 -53
- package/dist/agent-farm/servers/tower-cron.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts +14 -2
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +128 -19
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-messages.d.ts +38 -1
- package/dist/agent-farm/servers/tower-messages.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-messages.js +106 -1
- package/dist/agent-farm/servers/tower-messages.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts +16 -4
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +807 -99
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +241 -15
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +17 -2
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +139 -124
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.js +63 -4
- package/dist/agent-farm/servers/tower-tunnel.js.map +1 -1
- package/dist/agent-farm/servers/tower-types.d.ts +2 -1
- package/dist/agent-farm/servers/tower-types.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts +99 -1
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +242 -6
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-websocket.js +6 -21
- package/dist/agent-farm/servers/tower-websocket.js.map +1 -1
- package/dist/agent-farm/servers/write-queue.d.ts +35 -0
- package/dist/agent-farm/servers/write-queue.d.ts.map +1 -0
- package/dist/agent-farm/servers/write-queue.js +56 -0
- package/dist/agent-farm/servers/write-queue.js.map +1 -0
- package/dist/agent-farm/state.d.ts +6 -1
- package/dist/agent-farm/state.d.ts.map +1 -1
- package/dist/agent-farm/state.js +5 -2
- package/dist/agent-farm/state.js.map +1 -1
- package/dist/agent-farm/types.d.ts +39 -0
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/agent-farm/utils/agent-names.d.ts +2 -2
- package/dist/agent-farm/utils/agent-names.d.ts.map +1 -1
- package/dist/agent-farm/utils/agent-names.js +3 -3
- package/dist/agent-farm/utils/agent-names.js.map +1 -1
- package/dist/agent-farm/utils/architect-name.d.ts +2 -2
- package/dist/agent-farm/utils/architect-name.d.ts.map +1 -1
- package/dist/agent-farm/utils/architect-name.js +3 -3
- package/dist/agent-farm/utils/architect-name.js.map +1 -1
- package/dist/agent-farm/utils/config.d.ts +13 -0
- package/dist/agent-farm/utils/config.d.ts.map +1 -1
- package/dist/agent-farm/utils/config.js +33 -1
- package/dist/agent-farm/utils/config.js.map +1 -1
- package/dist/agent-farm/utils/harness.d.ts +103 -7
- package/dist/agent-farm/utils/harness.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.js +126 -19
- package/dist/agent-farm/utils/harness.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -32
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.d.ts +3 -2
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +7 -6
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/consult/agy-auth-cache.d.ts +97 -0
- package/dist/commands/consult/agy-auth-cache.d.ts.map +1 -0
- package/dist/commands/consult/agy-auth-cache.js +320 -0
- package/dist/commands/consult/agy-auth-cache.js.map +1 -0
- package/dist/commands/consult/cli-options.d.ts +34 -0
- package/dist/commands/consult/cli-options.d.ts.map +1 -0
- package/dist/commands/consult/cli-options.js +67 -0
- package/dist/commands/consult/cli-options.js.map +1 -0
- package/dist/commands/consult/index.d.ts +56 -2
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +330 -27
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/consult/metrics.d.ts +42 -0
- package/dist/commands/consult/metrics.d.ts.map +1 -1
- package/dist/commands/consult/metrics.js +129 -9
- package/dist/commands/consult/metrics.js.map +1 -1
- package/dist/commands/doctor.d.ts +28 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +258 -22
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +3 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +7 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/porch/checks.d.ts +23 -0
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +60 -0
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/config.d.ts +20 -0
- package/dist/commands/porch/config.d.ts.map +1 -1
- package/dist/commands/porch/config.js +20 -0
- package/dist/commands/porch/config.js.map +1 -1
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +32 -36
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/next.d.ts.map +1 -1
- package/dist/commands/porch/next.js +2 -41
- package/dist/commands/porch/next.js.map +1 -1
- package/dist/commands/update.d.ts +4 -4
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +9 -11
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/config.d.ts +70 -3
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +67 -3
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/consult-lanes.d.ts +149 -0
- package/dist/lib/consult-lanes.d.ts.map +1 -0
- package/dist/lib/consult-lanes.js +360 -0
- package/dist/lib/consult-lanes.js.map +1 -0
- package/dist/lib/default-branch.d.ts +1 -1
- package/dist/lib/default-branch.js +1 -1
- package/dist/lib/github.js +1 -1
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/gitignore.d.ts +25 -2
- package/dist/lib/gitignore.d.ts.map +1 -1
- package/dist/lib/gitignore.js +70 -0
- package/dist/lib/gitignore.js.map +1 -1
- package/dist/lib/migration-backup-audit.d.ts +64 -0
- package/dist/lib/migration-backup-audit.d.ts.map +1 -0
- package/dist/lib/migration-backup-audit.js +145 -0
- package/dist/lib/migration-backup-audit.js.map +1 -0
- package/dist/lib/prompt-behavior-metrics.d.ts +67 -0
- package/dist/lib/prompt-behavior-metrics.d.ts.map +1 -0
- package/dist/lib/prompt-behavior-metrics.js +290 -0
- package/dist/lib/prompt-behavior-metrics.js.map +1 -0
- package/dist/lib/protocol-drift-audit.d.ts +118 -0
- package/dist/lib/protocol-drift-audit.d.ts.map +1 -0
- package/dist/lib/protocol-drift-audit.js +217 -0
- package/dist/lib/protocol-drift-audit.js.map +1 -0
- package/dist/lib/scaffold.d.ts +10 -3
- package/dist/lib/scaffold.d.ts.map +1 -1
- package/dist/lib/scaffold.js +29 -26
- package/dist/lib/scaffold.js.map +1 -1
- package/dist/lib/skeleton.d.ts +22 -1
- package/dist/lib/skeleton.d.ts.map +1 -1
- package/dist/lib/skeleton.js +120 -0
- package/dist/lib/skeleton.js.map +1 -1
- package/dist/lib/test-env.d.ts +74 -0
- package/dist/lib/test-env.d.ts.map +1 -0
- package/dist/lib/test-env.js +92 -0
- package/dist/lib/test-env.js.map +1 -0
- package/dist/terminal/pty-manager.d.ts +9 -0
- package/dist/terminal/pty-manager.d.ts.map +1 -1
- package/dist/terminal/pty-manager.js +32 -6
- package/dist/terminal/pty-manager.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +156 -4
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +307 -42
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/ring-buffer.d.ts +39 -6
- package/dist/terminal/ring-buffer.d.ts.map +1 -1
- package/dist/terminal/ring-buffer.js +74 -6
- package/dist/terminal/ring-buffer.js.map +1 -1
- package/dist/terminal/session-manager.d.ts +129 -0
- package/dist/terminal/session-manager.d.ts.map +1 -1
- package/dist/terminal/session-manager.js +337 -44
- package/dist/terminal/session-manager.js.map +1 -1
- package/dist/terminal/session-screen.d.ts +91 -0
- package/dist/terminal/session-screen.d.ts.map +1 -0
- package/dist/terminal/session-screen.js +135 -0
- package/dist/terminal/session-screen.js.map +1 -0
- package/dist/terminal/shellper-client.d.ts +19 -4
- package/dist/terminal/shellper-client.d.ts.map +1 -1
- package/dist/terminal/shellper-client.js +70 -8
- package/dist/terminal/shellper-client.js.map +1 -1
- package/dist/terminal/shellper-main.js +2 -1
- package/dist/terminal/shellper-main.js.map +1 -1
- package/dist/terminal/shellper-process.d.ts +1 -1
- package/dist/terminal/shellper-process.d.ts.map +1 -1
- package/dist/terminal/shellper-process.js +33 -9
- package/dist/terminal/shellper-process.js.map +1 -1
- package/dist/terminal/shellper-protocol.d.ts +40 -2
- package/dist/terminal/shellper-protocol.d.ts.map +1 -1
- package/dist/terminal/shellper-protocol.js +72 -5
- package/dist/terminal/shellper-protocol.js.map +1 -1
- package/dist/terminal/shellper-replay-buffer.d.ts +69 -7
- package/dist/terminal/shellper-replay-buffer.d.ts.map +1 -1
- package/dist/terminal/shellper-replay-buffer.js +167 -31
- package/dist/terminal/shellper-replay-buffer.js.map +1 -1
- package/package.json +11 -9
- package/skeleton/.claude/skills/afx/SKILL.md +27 -1
- package/skeleton/.claude/skills/arch-init/SKILL.md +135 -0
- package/skeleton/.claude/skills/arch-save/SKILL.md +183 -0
- package/skeleton/.claude/skills/codev/SKILL.md +33 -2
- package/skeleton/.claude/skills/runnable-worktrees/SKILL.md +119 -0
- package/skeleton/.codex/skills/afx/SKILL.md +170 -0
- package/skeleton/.codex/skills/arch-init/SKILL.md +135 -0
- package/skeleton/.codex/skills/arch-save/SKILL.md +183 -0
- package/skeleton/.codex/skills/codev/SKILL.md +90 -0
- package/skeleton/.codex/skills/consult/SKILL.md +96 -0
- package/skeleton/.codex/skills/generate-image/SKILL.md +45 -0
- package/skeleton/.codex/skills/porch/SKILL.md +60 -0
- package/skeleton/.codex/skills/runnable-worktrees/SKILL.md +119 -0
- package/skeleton/.codex/skills/update-arch-docs/SKILL.md +132 -0
- package/skeleton/protocols/air/builder-prompt.md +28 -47
- package/skeleton/protocols/air/consult-types/impl-review.md +17 -34
- package/skeleton/protocols/air/consult-types/pr-review.md +14 -37
- package/skeleton/protocols/air/prompts/implement.md +20 -73
- package/skeleton/protocols/air/prompts/pr.md +22 -54
- package/skeleton/protocols/air/protocol.md +40 -71
- package/skeleton/protocols/aspir/builder-prompt.md +29 -66
- package/skeleton/protocols/aspir/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/aspir/consult-types/phase-review.md +17 -44
- package/skeleton/protocols/aspir/consult-types/plan-review.md +14 -38
- package/skeleton/protocols/aspir/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/aspir/consult-types/spec-review.md +13 -33
- package/skeleton/protocols/aspir/prompts/implement.md +27 -196
- package/skeleton/protocols/aspir/prompts/plan.md +21 -85
- package/skeleton/protocols/aspir/prompts/review.md +29 -228
- package/skeleton/protocols/aspir/prompts/specify.md +25 -111
- package/skeleton/protocols/aspir/protocol.json +10 -0
- package/skeleton/protocols/aspir/protocol.md +36 -82
- package/skeleton/protocols/bugfix/builder-prompt.md +23 -45
- package/skeleton/protocols/bugfix/consult-types/impl-review.md +21 -45
- package/skeleton/protocols/bugfix/consult-types/pr-review.md +18 -52
- package/skeleton/protocols/bugfix/prompts/fix.md +16 -61
- package/skeleton/protocols/bugfix/prompts/investigate.md +18 -62
- package/skeleton/protocols/bugfix/prompts/pr.md +22 -57
- package/skeleton/protocols/bugfix/protocol.md +44 -50
- package/skeleton/protocols/experiment/builder-prompt.md +25 -58
- package/skeleton/protocols/experiment/protocol.md +22 -188
- package/skeleton/protocols/experiment/templates/notes.md +11 -71
- package/skeleton/protocols/maintain/builder-prompt.md +24 -45
- package/skeleton/protocols/maintain/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/maintain/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/maintain/prompts/maintain.md +1 -1
- package/skeleton/protocols/maintain/protocol.md +32 -266
- package/skeleton/protocols/maintain/templates/maintenance-run.md +11 -0
- package/skeleton/protocols/pir/builder-prompt.md +30 -64
- package/skeleton/protocols/pir/consult-types/impl-review.md +17 -50
- package/skeleton/protocols/pir/consult-types/pr-review.md +11 -40
- package/skeleton/protocols/pir/prompts/implement.md +1 -2
- package/skeleton/protocols/pir/prompts/plan.md +0 -3
- package/skeleton/protocols/pir/prompts/review.md +1 -1
- package/skeleton/protocols/pir/protocol.md +54 -177
- package/skeleton/protocols/research/builder-prompt.md +27 -58
- package/skeleton/protocols/research/protocol.md +28 -153
- package/skeleton/protocols/spike/builder-prompt.md +30 -48
- package/skeleton/protocols/spike/protocol.md +24 -107
- package/skeleton/protocols/spike/templates/findings.md +9 -39
- package/skeleton/protocols/spir/builder-prompt.md +33 -62
- package/skeleton/protocols/spir/consult-types/impl-review.md +17 -44
- package/skeleton/protocols/spir/consult-types/phase-review.md +17 -44
- package/skeleton/protocols/spir/consult-types/plan-review.md +14 -38
- package/skeleton/protocols/spir/consult-types/pr-review.md +13 -39
- package/skeleton/protocols/spir/consult-types/spec-review.md +13 -33
- package/skeleton/protocols/spir/prompts/implement.md +26 -195
- package/skeleton/protocols/spir/prompts/plan.md +20 -84
- package/skeleton/protocols/spir/prompts/review.md +28 -227
- package/skeleton/protocols/spir/prompts/specify.md +24 -110
- package/skeleton/protocols/spir/protocol.json +10 -0
- package/skeleton/protocols/spir/protocol.md +84 -633
- package/skeleton/protocols/spir/templates/plan.md +28 -147
- package/skeleton/protocols/spir/templates/review.md +21 -80
- package/skeleton/protocols/spir/templates/spec.md +24 -118
- package/skeleton/resources/commands/agent-farm.md +348 -0
- package/skeleton/resources/commands/codev.md +5 -0
- package/skeleton/resources/commands/consult.md +262 -8
- package/skeleton/resources/commands/overview.md +1 -0
- package/skeleton/roles/architect.md +67 -306
- package/skeleton/roles/builder.md +77 -191
- package/skeleton/templates/AGENTS.md +2 -0
- package/skeleton/templates/CLAUDE.md +2 -0
- package/templates/tower.html +39 -2
- package/dashboard-dist/assets/index-BZ1x7x1X.js.map +0 -1
- package/dashboard-dist/assets/index-DB1KBSNE.css +0 -32
- package/dist/agent-farm/servers/send-buffer.d.ts +0 -59
- package/dist/agent-farm/servers/send-buffer.d.ts.map +0 -1
- package/dist/agent-farm/servers/send-buffer.js +0 -103
- package/dist/agent-farm/servers/send-buffer.js.map +0 -1
- package/skeleton/porch/prompts/defend.md +0 -108
- package/skeleton/porch/prompts/diagnose.md +0 -70
- package/skeleton/porch/prompts/evaluate.md +0 -132
- package/skeleton/porch/prompts/fix.md +0 -59
- package/skeleton/porch/prompts/implement.md +0 -88
- package/skeleton/porch/prompts/plan.md +0 -74
- package/skeleton/porch/prompts/pr.md +0 -84
- package/skeleton/porch/prompts/review.md +0 -249
- package/skeleton/porch/prompts/specify.md +0 -53
- package/skeleton/porch/prompts/test.md +0 -63
- package/skeleton/protocols/aspir/templates/plan.md +0 -184
- package/skeleton/protocols/aspir/templates/review.md +0 -120
- package/skeleton/protocols/aspir/templates/spec.md +0 -154
|
@@ -15,11 +15,14 @@ import { query as claudeQuery } from '@anthropic-ai/claude-agent-sdk';
|
|
|
15
15
|
import { Codex } from '@openai/codex-sdk';
|
|
16
16
|
import { readCodevFile, findWorkspaceRoot } from '../../lib/skeleton.js';
|
|
17
17
|
import { resolveDefaultBranch } from '../../lib/default-branch.js';
|
|
18
|
-
import { loadConfig } from '../../lib/config.js';
|
|
18
|
+
import { loadConfig, findConfigSource } from '../../lib/config.js';
|
|
19
|
+
import { resolveLaneModel, resolveReasoningEffort, validateModelId, assertLaneAcceptsModelOverride, } from '../../lib/consult-lanes.js';
|
|
19
20
|
import { getResolver, GitRefResolver } from '../porch/artifacts.js';
|
|
20
21
|
import { MetricsDB } from './metrics.js';
|
|
21
22
|
import { extractUsage, extractReviewText } from './usage-extractor.js';
|
|
22
23
|
import { executeForgeCommandSync } from '../../lib/forge.js';
|
|
24
|
+
import { preflightAgyAuth, recordAgyAuthState } from './agy-auth-cache.js';
|
|
25
|
+
import { assertAgyLaneAllowedUnderTest } from '../../lib/test-env.js';
|
|
23
26
|
const MODEL_CONFIGS = {
|
|
24
27
|
// gemini dispatches to the Antigravity CLI (`agy`) via runAgyConsultation —
|
|
25
28
|
// this entry exists only for model validation and the `pro` alias; its
|
|
@@ -49,6 +52,7 @@ function recordMetrics(ctx, extra) {
|
|
|
49
52
|
db.record({
|
|
50
53
|
timestamp: ctx.timestamp,
|
|
51
54
|
model: ctx.model,
|
|
55
|
+
modelId: extra.modelId,
|
|
52
56
|
reviewType: ctx.reviewType,
|
|
53
57
|
subcommand: ctx.subcommand,
|
|
54
58
|
protocol: ctx.protocol,
|
|
@@ -291,13 +295,147 @@ function commandExists(cmd) {
|
|
|
291
295
|
return false;
|
|
292
296
|
}
|
|
293
297
|
}
|
|
294
|
-
|
|
295
|
-
|
|
298
|
+
/**
|
|
299
|
+
* Shipped default model id for the codex consult lane (#1288).
|
|
300
|
+
*
|
|
301
|
+
* The `-sol` suffix is LOAD-BEARING. Both plain `gpt-5.6` and `gpt-5.6-codex`
|
|
302
|
+
* were live-probed on 2026-07-29 and rejected by Codex with a ChatGPT account
|
|
303
|
+
* ("The '<id>' model is not supported when using Codex with a ChatGPT
|
|
304
|
+
* account."). Do not "simplify" this id — `default-models.test.ts` guards it.
|
|
305
|
+
*/
|
|
306
|
+
export const DEFAULT_CODEX_MODEL = 'gpt-5.6-sol';
|
|
307
|
+
/** Shipped default reasoning effort for the codex consult lane. */
|
|
308
|
+
export const DEFAULT_CODEX_REASONING_EFFORT = 'medium';
|
|
309
|
+
/** Shipped default model id for the claude consult lane (#1288). */
|
|
310
|
+
export const DEFAULT_CLAUDE_MODEL = 'claude-opus-5';
|
|
311
|
+
/**
|
|
312
|
+
* Per-1M-token codex rates, keyed by model id. Verified against
|
|
313
|
+
* https://developers.openai.com/api/docs/pricing on 2026-07-30.
|
|
314
|
+
*
|
|
315
|
+
* Only OpenAI's *standard* tier is modelled; the separate long-context tier
|
|
316
|
+
* (charged above the standard context threshold) is not, so cost is
|
|
317
|
+
* under-reported for unusually large consultations.
|
|
318
|
+
*
|
|
319
|
+
* A model id absent from this table yields `costUsd: null` rather than a cost
|
|
320
|
+
* computed from some other model's rates — a confidently wrong number is worse
|
|
321
|
+
* than none.
|
|
322
|
+
*/
|
|
323
|
+
const CODEX_PRICING = {
|
|
324
|
+
'gpt-5.6-sol': { inputPer1M: 5.00, cachedInputPer1M: 0.50, outputPer1M: 30.00 },
|
|
325
|
+
};
|
|
326
|
+
/**
|
|
327
|
+
* Compute codex consultation cost in USD, or null when the model's published
|
|
328
|
+
* rates are unknown.
|
|
329
|
+
*/
|
|
330
|
+
export function computeCodexCost(model, inputTokens, cachedInputTokens, outputTokens, workspaceRoot) {
|
|
331
|
+
// `consult.pricing.codex` (spec 1286) outranks the shipped table, so a workspace running a model
|
|
332
|
+
// Codev has no rates for can still get real costs instead of nulls. Optional param: main's
|
|
333
|
+
// 4-arg callers and tests are unaffected.
|
|
334
|
+
const configured = workspaceRoot ? loadConfig(workspaceRoot).consult?.pricing?.codex : undefined;
|
|
335
|
+
const pricing = configured ?? CODEX_PRICING[model];
|
|
336
|
+
if (!pricing)
|
|
337
|
+
return null;
|
|
338
|
+
const uncached = inputTokens - cachedInputTokens;
|
|
339
|
+
return (uncached / 1_000_000) * pricing.inputPer1M
|
|
340
|
+
+ (cachedInputTokens / 1_000_000) * pricing.cachedInputPer1M
|
|
341
|
+
+ (outputTokens / 1_000_000) * pricing.outputPer1M;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Resolve which model id an SDK lane runs, and record where it came from.
|
|
345
|
+
*
|
|
346
|
+
* Precedence: `--model-id` > `consult.models.<lane>` > the shipped default constant.
|
|
347
|
+
*
|
|
348
|
+
* The provenance is not decoration: with five config layers, telling a user their
|
|
349
|
+
* `consult.models.codex` is wrong doesn't tell them which of five files to edit.
|
|
350
|
+
*/
|
|
351
|
+
export function resolveLaneModelChoice(workspaceRoot, lane, defaultId, modelIdOverride) {
|
|
352
|
+
if (modelIdOverride !== undefined) {
|
|
353
|
+
validateModelId(modelIdOverride, '--model-id');
|
|
354
|
+
return { id: modelIdOverride, key: '--model-id', source: null, fromFlag: true };
|
|
355
|
+
}
|
|
356
|
+
const { id, key } = resolveLaneModel(loadConfig(workspaceRoot).consult, lane);
|
|
357
|
+
if (id === undefined || key === undefined) {
|
|
358
|
+
return { id: defaultId, key: null, source: null, fromFlag: false };
|
|
359
|
+
}
|
|
360
|
+
return { id, key, source: findConfigSource(workspaceRoot, ['consult', 'models', lane]), fromFlag: false };
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Remove a stale review file before failing a consultation.
|
|
364
|
+
*
|
|
365
|
+
* "No review file" has to mean none *exists*, not merely that this run declined to write one.
|
|
366
|
+
* Porch keys off the file's presence, and consult writes to a deterministic per-iteration path — so
|
|
367
|
+
* a review left by an earlier run of the same iteration would be accepted as though the failed run
|
|
368
|
+
* had succeeded, and the phase would advance on a stale verdict. Found by codex reviewing the agy
|
|
369
|
+
* lane; applied to all three lanes because the exposure is identical wherever a runner throws after
|
|
370
|
+
* a previous run wrote output.
|
|
371
|
+
*/
|
|
372
|
+
function discardStaleOutput(outputPath) {
|
|
373
|
+
if (!outputPath)
|
|
374
|
+
return;
|
|
375
|
+
try {
|
|
376
|
+
if (fs.existsSync(outputPath))
|
|
377
|
+
fs.unlinkSync(outputPath);
|
|
378
|
+
}
|
|
379
|
+
catch (err) {
|
|
380
|
+
// Best-effort — failing to unlink must not mask the underlying error. But it must not be
|
|
381
|
+
// silent either: this is precisely the state where porch could accept a stale review, so it
|
|
382
|
+
// has to be visible rather than undetectable.
|
|
383
|
+
console.error(`\n[warning] could not remove stale review at ${outputPath}: ` +
|
|
384
|
+
`${err instanceof Error ? err.message : String(err)}\n` +
|
|
385
|
+
`Delete it manually — porch may otherwise accept it as this iteration's review.`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Resolve a model for a lane that has **no built-in default** — agy picks its own model when
|
|
390
|
+
* `--model` is absent, so there is nothing to fall back to.
|
|
391
|
+
*
|
|
392
|
+
* `null` means "omit the flag entirely", which is what preserves zero-config parity: an
|
|
393
|
+
* unconfigured gemini lane must produce byte-identical argv to before this spec.
|
|
394
|
+
*/
|
|
395
|
+
export function resolveOptionalLaneModelChoice(workspaceRoot, lane, modelIdOverride) {
|
|
396
|
+
if (modelIdOverride !== undefined) {
|
|
397
|
+
validateModelId(modelIdOverride, '--model-id');
|
|
398
|
+
return { id: modelIdOverride, key: '--model-id', source: null, fromFlag: true };
|
|
399
|
+
}
|
|
400
|
+
const { id, key } = resolveLaneModel(loadConfig(workspaceRoot).consult, lane);
|
|
401
|
+
if (id === undefined || key === undefined)
|
|
402
|
+
return null;
|
|
403
|
+
return { id, key, source: findConfigSource(workspaceRoot, ['consult', 'models', lane]), fromFlag: false };
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Attach model provenance to a provider rejection.
|
|
407
|
+
*
|
|
408
|
+
* Deliberately does NOT substitute a working id or otherwise recover — a bad model id must fail
|
|
409
|
+
* loudly. The provider's own text is preserved verbatim and merely annotated, because paraphrasing
|
|
410
|
+
* a provider error is how you lose the one detail that identifies the real problem.
|
|
411
|
+
*/
|
|
412
|
+
function annotateModelError(err, lane, choice) {
|
|
413
|
+
// A shipped default can't be misconfigured by the user — nothing useful to add.
|
|
414
|
+
if (choice.key === null)
|
|
415
|
+
return err;
|
|
416
|
+
const providerText = err instanceof Error ? err.message : String(err);
|
|
417
|
+
const where = choice.fromFlag
|
|
418
|
+
? 'passed via --model-id'
|
|
419
|
+
: `from \`${choice.key}\`${choice.source ? ` in ${choice.source}` : ''}`;
|
|
420
|
+
const annotated = new Error(`${providerText}\n\n` +
|
|
421
|
+
`The ${lane} lane requested model "${choice.id}" (${where}).\n` +
|
|
422
|
+
`If the provider rejected that id, correct it at the source above. ` +
|
|
423
|
+
`Codev does not fall back to a default model.`);
|
|
424
|
+
if (err instanceof Error && err.stack)
|
|
425
|
+
annotated.stack = err.stack;
|
|
426
|
+
return annotated;
|
|
427
|
+
}
|
|
296
428
|
/**
|
|
297
429
|
* Run Codex consultation via @openai/codex-sdk.
|
|
298
430
|
* Mirrors runClaudeConsultation() — streams events, captures usage, records metrics.
|
|
299
431
|
*/
|
|
300
|
-
export async function runCodexConsultation(queryText, role, workspaceRoot, outputPath, metricsCtx) {
|
|
432
|
+
export async function runCodexConsultation(queryText, role, workspaceRoot, outputPath, metricsCtx, modelChoice, reasoningEffort) {
|
|
433
|
+
// Absent an explicit choice (direct callers), resolve from config so behavior is identical
|
|
434
|
+
// whether the caller threads it through or not.
|
|
435
|
+
const choice = modelChoice ?? resolveLaneModelChoice(workspaceRoot, 'codex', DEFAULT_CODEX_MODEL);
|
|
436
|
+
const effort = reasoningEffort
|
|
437
|
+
?? resolveReasoningEffort(loadConfig(workspaceRoot).consult)
|
|
438
|
+
?? DEFAULT_CODEX_REASONING_EFFORT;
|
|
301
439
|
const chunks = [];
|
|
302
440
|
const startTime = Date.now();
|
|
303
441
|
let usageData = null;
|
|
@@ -313,9 +451,9 @@ export async function runCodexConsultation(queryText, role, workspaceRoot, outpu
|
|
|
313
451
|
},
|
|
314
452
|
});
|
|
315
453
|
const thread = codex.startThread({
|
|
316
|
-
model:
|
|
454
|
+
model: choice.id,
|
|
317
455
|
sandboxMode: 'read-only',
|
|
318
|
-
modelReasoningEffort:
|
|
456
|
+
modelReasoningEffort: effort,
|
|
319
457
|
workingDirectory: workspaceRoot,
|
|
320
458
|
});
|
|
321
459
|
const { events } = await thread.runStreamed(queryText);
|
|
@@ -333,10 +471,7 @@ export async function runCodexConsultation(queryText, role, workspaceRoot, outpu
|
|
|
333
471
|
// output_tokens already includes reasoning_output_tokens (OpenAI Responses-API
|
|
334
472
|
// convention) — do NOT add the latter to cost or reasoning is double-billed.
|
|
335
473
|
const output = event.usage.output_tokens;
|
|
336
|
-
const
|
|
337
|
-
const cost = (uncached / 1_000_000) * CODEX_PRICING.inputPer1M
|
|
338
|
-
+ (cached / 1_000_000) * CODEX_PRICING.cachedInputPer1M
|
|
339
|
-
+ (output / 1_000_000) * CODEX_PRICING.outputPer1M;
|
|
474
|
+
const cost = computeCodexCost(choice.id, input, cached, output, workspaceRoot);
|
|
340
475
|
usageData = { inputTokens: input, cachedInputTokens: cached, outputTokens: output, costUsd: cost };
|
|
341
476
|
}
|
|
342
477
|
if (event.type === 'turn.failed') {
|
|
@@ -364,7 +499,8 @@ export async function runCodexConsultation(queryText, role, workspaceRoot, outpu
|
|
|
364
499
|
errorMessage = (err instanceof Error ? err.message : String(err)).substring(0, 500);
|
|
365
500
|
exitCode = 1;
|
|
366
501
|
}
|
|
367
|
-
|
|
502
|
+
discardStaleOutput(outputPath);
|
|
503
|
+
throw annotateModelError(err, 'codex', choice);
|
|
368
504
|
}
|
|
369
505
|
finally {
|
|
370
506
|
// Clean up temp file
|
|
@@ -374,6 +510,7 @@ export async function runCodexConsultation(queryText, role, workspaceRoot, outpu
|
|
|
374
510
|
if (metricsCtx) {
|
|
375
511
|
const duration = (Date.now() - startTime) / 1000;
|
|
376
512
|
recordMetrics(metricsCtx, {
|
|
513
|
+
modelId: choice.id,
|
|
377
514
|
durationSeconds: duration,
|
|
378
515
|
inputTokens: usageData?.inputTokens ?? null,
|
|
379
516
|
cachedInputTokens: usageData?.cachedInputTokens ?? null,
|
|
@@ -419,7 +556,10 @@ export function buildClaudeConsultEnv(processEnv) {
|
|
|
419
556
|
* Uses the SDK's query() function instead of CLI subprocess.
|
|
420
557
|
* This avoids the CLAUDECODE nesting guard and enables tool use during reviews.
|
|
421
558
|
*/
|
|
422
|
-
async function runClaudeConsultation(queryText, role, workspaceRoot, outputPath, metricsCtx) {
|
|
559
|
+
export async function runClaudeConsultation(queryText, role, workspaceRoot, outputPath, metricsCtx, modelChoice) {
|
|
560
|
+
// Absent an explicit choice (direct callers), resolve from config so behavior is identical
|
|
561
|
+
// whether the caller threads it through or not.
|
|
562
|
+
const choice = modelChoice ?? resolveLaneModelChoice(workspaceRoot, 'claude', DEFAULT_CLAUDE_MODEL);
|
|
423
563
|
const chunks = [];
|
|
424
564
|
const startTime = Date.now();
|
|
425
565
|
let sdkResult;
|
|
@@ -439,7 +579,7 @@ async function runClaudeConsultation(queryText, role, workspaceRoot, outputPath,
|
|
|
439
579
|
allowedTools: ['Read', 'Glob', 'Grep'],
|
|
440
580
|
permissionMode: 'bypassPermissions',
|
|
441
581
|
allowDangerouslySkipPermissions: true,
|
|
442
|
-
model:
|
|
582
|
+
model: choice.id,
|
|
443
583
|
maxTurns: CLAUDE_MAX_TURNS,
|
|
444
584
|
maxBudgetUsd: 25,
|
|
445
585
|
cwd: workspaceRoot,
|
|
@@ -480,7 +620,8 @@ async function runClaudeConsultation(queryText, role, workspaceRoot, outputPath,
|
|
|
480
620
|
errorMessage = (err instanceof Error ? err.message : String(err)).substring(0, 500);
|
|
481
621
|
exitCode = 1;
|
|
482
622
|
}
|
|
483
|
-
|
|
623
|
+
discardStaleOutput(outputPath);
|
|
624
|
+
throw annotateModelError(err, 'claude', choice);
|
|
484
625
|
}
|
|
485
626
|
finally {
|
|
486
627
|
if (savedClaudeCode !== undefined) {
|
|
@@ -491,6 +632,7 @@ async function runClaudeConsultation(queryText, role, workspaceRoot, outputPath,
|
|
|
491
632
|
const duration = (Date.now() - startTime) / 1000;
|
|
492
633
|
const usage = sdkResult ? extractUsage('claude', '', sdkResult) : null;
|
|
493
634
|
recordMetrics(metricsCtx, {
|
|
635
|
+
modelId: choice.id,
|
|
494
636
|
durationSeconds: duration,
|
|
495
637
|
inputTokens: usage?.inputTokens ?? null,
|
|
496
638
|
cachedInputTokens: usage?.cachedInputTokens ?? null,
|
|
@@ -519,6 +661,18 @@ const AGY_PRINT_TIMEOUT = '5m'; // passed to `agy --print-timeout`
|
|
|
519
661
|
const AGY_TIMEOUT_MS = 6 * 60 * 1000; // Codev-owned hard cap (> agy's own timeout)
|
|
520
662
|
// OAuth banner appears before any review text; only scan the early stream.
|
|
521
663
|
const AGY_MARKER_SCAN_LIMIT = 8192;
|
|
664
|
+
// Bounded tail of agy's own output retained for a configured-lane hard failure. agy's rejection
|
|
665
|
+
// text is the only thing that explains WHY a model id was refused, but it lands in an error
|
|
666
|
+
// message, so it is capped rather than accumulated.
|
|
667
|
+
const AGY_FAILURE_TAIL_MAX_CHARS = 2000;
|
|
668
|
+
/**
|
|
669
|
+
* How long a prober waits, marker-free, before publishing `auth` to the shared
|
|
670
|
+
* cache (#1077). The OAuth banner is the very first thing an unauthenticated agy
|
|
671
|
+
* emits, so silence this far in is good evidence we are signed in — and it lets
|
|
672
|
+
* the processes waiting on our verdict get moving instead of stalling behind a
|
|
673
|
+
* review that may run for minutes.
|
|
674
|
+
*/
|
|
675
|
+
const AGY_AUTH_GRACE_MS = 3000;
|
|
522
676
|
// agy's own print-timeout message: on an agentic task that outruns --print-timeout,
|
|
523
677
|
// it returns this (often with a "monitoring the task" note) instead of a review.
|
|
524
678
|
// Treat it as a non-response → non-blocking skip rather than a garbage "review".
|
|
@@ -572,6 +726,12 @@ export function resolveAgyBin() {
|
|
|
572
726
|
const override = process.env.CODEV_AGY_BIN;
|
|
573
727
|
if (override)
|
|
574
728
|
return isRealAgyCli(override) ? override : null;
|
|
729
|
+
// Past this point we go looking for the developer's real install, so this is
|
|
730
|
+
// the true chokepoint for the test-isolation guard (#1323) — not the spawn
|
|
731
|
+
// sites. Resolution is not passive: the PATH branch below runs
|
|
732
|
+
// `agyRespondsToVersion`, which *executes* the candidate binary. Guarding only
|
|
733
|
+
// the spawn would still let a suite run the real agy.
|
|
734
|
+
assertAgyLaneAllowedUnderTest();
|
|
575
735
|
// Canonical install path — trusted location; realpath-reject the IDE only.
|
|
576
736
|
const preferred = path.join(homedir(), '.local', 'bin', 'agy');
|
|
577
737
|
if (isRealAgyCli(preferred))
|
|
@@ -629,10 +789,15 @@ function writeConsultOutput(outputPath, content) {
|
|
|
629
789
|
fs.writeFileSync(outputPath, content);
|
|
630
790
|
console.error(`\nOutput written to: ${outputPath}`);
|
|
631
791
|
}
|
|
632
|
-
function recordAgyMetrics(metricsCtx, startTime, exitCode, errorMessage
|
|
792
|
+
function recordAgyMetrics(metricsCtx, startTime, exitCode, errorMessage,
|
|
793
|
+
// No default: every caller states the id or states null. A default would quietly reintroduce
|
|
794
|
+
// the silent-NULL path that making modelId required on MetricsRecord exists to prevent.
|
|
795
|
+
modelId) {
|
|
633
796
|
if (!metricsCtx)
|
|
634
797
|
return;
|
|
635
798
|
recordMetrics(metricsCtx, {
|
|
799
|
+
// Null on a skip with no model configured — "no model was chosen", not "we forgot".
|
|
800
|
+
modelId,
|
|
636
801
|
durationSeconds: (Date.now() - startTime) / 1000,
|
|
637
802
|
// agy --print emits plain text, no token usage → cost rows degrade gracefully (null).
|
|
638
803
|
inputTokens: null,
|
|
@@ -649,18 +814,42 @@ function recordAgyMetrics(metricsCtx, startTime, exitCode, errorMessage) {
|
|
|
649
814
|
* prompt, and NEVER blocks the run: a missing/unauthed/invalid CLI or a
|
|
650
815
|
* timeout/error produces a non-blocking COMMENT skip instead of throwing.
|
|
651
816
|
*/
|
|
652
|
-
async function runAgyConsultation(queryText, role, workspaceRoot, outputPath, metricsCtx) {
|
|
817
|
+
async function runAgyConsultation(queryText, role, workspaceRoot, outputPath, metricsCtx, modelChoice) {
|
|
653
818
|
const startTime = Date.now();
|
|
819
|
+
// `undefined` means "resolve it yourself" (direct callers); an explicit `null` means "no model
|
|
820
|
+
// configured", which must stay distinguishable from "not yet resolved".
|
|
821
|
+
const choice = modelChoice === undefined
|
|
822
|
+
? resolveOptionalLaneModelChoice(workspaceRoot, 'gemini')
|
|
823
|
+
: modelChoice;
|
|
824
|
+
// The test-isolation guard (#1323) lives inside resolveAgyBin, at the point
|
|
825
|
+
// where an unpinned lookup would reach the real install. It throws rather than
|
|
826
|
+
// falling through to the non-blocking skip below — deliberately: a misconfigured
|
|
827
|
+
// test must fail loudly instead of passing on a machine that happens not to have
|
|
828
|
+
// agy installed while spawning the real CLI on one that does.
|
|
654
829
|
const bin = resolveAgyBin();
|
|
655
830
|
if (!bin) {
|
|
656
831
|
const reason = 'agy CLI not found (install: https://antigravity.google/cli/install.sh)';
|
|
657
832
|
const content = agySkipContent(reason);
|
|
658
833
|
process.stdout.write(content);
|
|
659
834
|
writeConsultOutput(outputPath, content);
|
|
660
|
-
recordAgyMetrics(metricsCtx, startTime, 0, reason);
|
|
835
|
+
recordAgyMetrics(metricsCtx, startTime, 0, reason, choice?.id ?? null);
|
|
661
836
|
console.error(`\n[gemini (agy) skipped: ${reason}]`);
|
|
662
837
|
return;
|
|
663
838
|
}
|
|
839
|
+
// Pre-flight the shared auth cache BEFORE spawning (#1077). An unauthenticated
|
|
840
|
+
// agy opens a browser tab before it prints the OAuth URL we detect below, so
|
|
841
|
+
// post-spawn detection cannot prevent the tab — only not spawning can. Across a
|
|
842
|
+
// CMAP burst this collapses N stranded tabs into at most one per TTL window.
|
|
843
|
+
const preflight = await preflightAgyAuth(bin);
|
|
844
|
+
if (preflight.action === 'skip') {
|
|
845
|
+
const reason = preflight.reason ?? 'agy unauthenticated (cached)';
|
|
846
|
+
const content = agySkipContent(reason);
|
|
847
|
+
process.stdout.write(content);
|
|
848
|
+
writeConsultOutput(outputPath, content);
|
|
849
|
+
recordAgyMetrics(metricsCtx, startTime, 0, reason, choice?.id ?? null);
|
|
850
|
+
console.error(`\n[gemini (agy) skipped without spawning: ${reason}]`);
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
664
853
|
// agy has no system-prompt flag — fold the role into the prompt (hermes precedent).
|
|
665
854
|
// Prepend strict constraint directive to force agy to remain on-task, prevent exploratory actions
|
|
666
855
|
// that lead to wandering off-task, and avoid unrelated local skills/directories (Issue #1032).
|
|
@@ -693,6 +882,11 @@ async function runAgyConsultation(queryText, role, workspaceRoot, outputPath, me
|
|
|
693
882
|
const args = ['--sandbox', '--print-timeout', AGY_PRINT_TIMEOUT];
|
|
694
883
|
for (const d of addDirs)
|
|
695
884
|
args.push('--add-dir', d);
|
|
885
|
+
// Omitted entirely when unconfigured, so an unconfigured lane's argv is byte-identical to
|
|
886
|
+
// pre-1286 and agy keeps choosing its own model. Must precede --print: agy parses --print as a
|
|
887
|
+
// string-valued option, so its value has to be the immediately following argument.
|
|
888
|
+
if (choice)
|
|
889
|
+
args.push('--model', choice.id);
|
|
696
890
|
// agy 1.0.10 defines --print as a string-valued option, so its prompt must
|
|
697
891
|
// immediately follow the flag rather than another option such as --sandbox.
|
|
698
892
|
args.push('--print', promptArg);
|
|
@@ -704,7 +898,7 @@ async function runAgyConsultation(queryText, role, workspaceRoot, outputPath, me
|
|
|
704
898
|
catch { /* best-effort */ }
|
|
705
899
|
}
|
|
706
900
|
};
|
|
707
|
-
return new Promise((resolve) => {
|
|
901
|
+
return new Promise((resolve, reject) => {
|
|
708
902
|
const proc = spawn(bin, args, {
|
|
709
903
|
cwd: workspaceRoot,
|
|
710
904
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -712,6 +906,25 @@ async function runAgyConsultation(queryText, role, workspaceRoot, outputPath, me
|
|
|
712
906
|
const outChunks = [];
|
|
713
907
|
let scanBuf = '';
|
|
714
908
|
let settled = false;
|
|
909
|
+
// stderr is watched for auth markers but otherwise discarded today, so a hard failure would
|
|
910
|
+
// have nothing but an exit code to report. Retain a bounded tail of BOTH streams: agy's own
|
|
911
|
+
// text is the only thing that explains *why* a model was rejected, and this lands in an error
|
|
912
|
+
// message, so it must not be unbounded.
|
|
913
|
+
let outputTail = '';
|
|
914
|
+
// When we hold the probe lock, other consult processes are polling the cache
|
|
915
|
+
// for our verdict — publish it as soon as it is knowable, and always release
|
|
916
|
+
// the lock, whatever this run turns into.
|
|
917
|
+
const graceTimer = preflight.isProber
|
|
918
|
+
? setTimeout(() => preflight.publish('auth'), AGY_AUTH_GRACE_MS)
|
|
919
|
+
: null;
|
|
920
|
+
const publishAuth = (state) => {
|
|
921
|
+
if (graceTimer)
|
|
922
|
+
clearTimeout(graceTimer);
|
|
923
|
+
if (state)
|
|
924
|
+
preflight.publish(state);
|
|
925
|
+
else
|
|
926
|
+
preflight.release();
|
|
927
|
+
};
|
|
715
928
|
const settleSkip = (reason, exitCode = 0) => {
|
|
716
929
|
if (settled)
|
|
717
930
|
return;
|
|
@@ -722,10 +935,14 @@ async function runAgyConsultation(queryText, role, workspaceRoot, outputPath, me
|
|
|
722
935
|
}
|
|
723
936
|
catch { /* already gone */ }
|
|
724
937
|
cleanup();
|
|
938
|
+
// No-op if a verdict was already published (e.g. the OAuth-marker path);
|
|
939
|
+
// otherwise this just releases the lock — a timeout or a spawn failure is
|
|
940
|
+
// not evidence either way about authentication.
|
|
941
|
+
publishAuth();
|
|
725
942
|
const content = agySkipContent(reason);
|
|
726
943
|
process.stdout.write(content);
|
|
727
944
|
writeConsultOutput(outputPath, content);
|
|
728
|
-
recordAgyMetrics(metricsCtx, startTime, exitCode, reason);
|
|
945
|
+
recordAgyMetrics(metricsCtx, startTime, exitCode, reason, choice?.id ?? null);
|
|
729
946
|
console.error(`\n[gemini (agy) skipped: ${reason}]`);
|
|
730
947
|
resolve();
|
|
731
948
|
};
|
|
@@ -733,9 +950,23 @@ async function runAgyConsultation(queryText, role, workspaceRoot, outputPath, me
|
|
|
733
950
|
const watch = (buf, isStdout) => {
|
|
734
951
|
if (isStdout)
|
|
735
952
|
outChunks.push(buf);
|
|
953
|
+
outputTail = (outputTail + buf.toString('utf-8')).slice(-AGY_FAILURE_TAIL_MAX_CHARS);
|
|
736
954
|
if (scanBuf.length < AGY_MARKER_SCAN_LIMIT) {
|
|
737
955
|
scanBuf += buf.toString('utf-8');
|
|
738
956
|
if (AGY_OAUTH_MARKERS.some((m) => scanBuf.includes(m))) {
|
|
957
|
+
// The one place we have positive proof of being signed out, so it is
|
|
958
|
+
// written unconditionally rather than through the once-only publish:
|
|
959
|
+
// - If our own grace timer already guessed `auth` (agy took longer
|
|
960
|
+
// than AGY_AUTH_GRACE_MS to emit its banner), that guess would
|
|
961
|
+
// otherwise stand for the full auth TTL and every burst in that
|
|
962
|
+
// window would spawn tabs again.
|
|
963
|
+
// - A non-prober that failed open and spawned holds real evidence
|
|
964
|
+
// too; discarding it would leave a misfired guess uncorrected
|
|
965
|
+
// until the TTL lapsed, instead of on the very next spawn.
|
|
966
|
+
// recordAgyAuthState carries its own disabled-guard, so this is safe
|
|
967
|
+
// on every path.
|
|
968
|
+
recordAgyAuthState('unauth', bin);
|
|
969
|
+
publishAuth('unauth');
|
|
739
970
|
settleSkip('agy not authenticated — run `agy` once to sign in (OAuth)', 1);
|
|
740
971
|
}
|
|
741
972
|
}
|
|
@@ -752,7 +983,48 @@ async function runAgyConsultation(queryText, role, workspaceRoot, outputPath, me
|
|
|
752
983
|
clearTimeout(timer);
|
|
753
984
|
cleanup();
|
|
754
985
|
const raw = Buffer.concat(outChunks).toString('utf-8').trim();
|
|
755
|
-
|
|
986
|
+
// THE PHASE 3 INVARIANT: a skip may only be reached for an ENVIRONMENT cause.
|
|
987
|
+
//
|
|
988
|
+
// Configuring `consult.models.gemini` is opting out of "quietly proceed without this lane" —
|
|
989
|
+
// a non-zero exit then means the model was probably rejected, and swallowing that as a
|
|
990
|
+
// COMMENT skip would let a typo'd model id silently reduce every review to two lanes.
|
|
991
|
+
//
|
|
992
|
+
// Deliberately narrow: ONLY a non-zero exit hard-fails. Auth, timeout, non-response and
|
|
993
|
+
// empty output stay skips even when configured, because those are environment causes and the
|
|
994
|
+
// degraded-agy lane (#1032/#1033) must keep its non-blocking property. Widening this to
|
|
995
|
+
// "any failure" would wedge phases for workspaces whose agy is merely unauthenticated.
|
|
996
|
+
// Environment causes are classified FIRST. agy can emit its non-response marker *and* exit
|
|
997
|
+
// non-zero, and checking the exit code before the marker would misfile that timeout as a
|
|
998
|
+
// configuration failure — breaking the "timeout stays a skip in both cases" half of the
|
|
999
|
+
// invariant for exactly the degraded lane it exists to protect. (Found by codex at review.)
|
|
1000
|
+
// ONLY the non-response marker, deliberately — NOT empty stdout. A rejected model id writes
|
|
1001
|
+
// its error to stderr and exits non-zero with empty stdout, so treating "no stdout" as an
|
|
1002
|
+
// environment cause would make the hard failure unreachable for the exact case it exists to
|
|
1003
|
+
// catch. (My own stale-review test caught that overcorrection.) Empty stdout still means
|
|
1004
|
+
// "no review" on the zero-exit path below.
|
|
1005
|
+
// Checked against BOTH streams: agy may print its timeout notice to stderr, and matching
|
|
1006
|
+
// stdout alone would hard-fail a configured lane on a plain timeout — the same invariant hole
|
|
1007
|
+
// twice over. `outputTail` is capped, but a timeout notice is by nature near the end of the
|
|
1008
|
+
// stream, so the tail is where it lands. (Found by claude at review.)
|
|
1009
|
+
const timedOutProducing = raw.includes(AGY_NONRESPONSE_MARKER) || outputTail.includes(AGY_NONRESPONSE_MARKER);
|
|
1010
|
+
// `code === null` means agy was killed by a signal (OOM, external kill) — an environment
|
|
1011
|
+
// cause, not a rejected model, so it must not hard-fail either. `code !== 0` alone is true
|
|
1012
|
+
// for null and would misfile it. (Found by claude at review.)
|
|
1013
|
+
if (code !== null && code !== 0 && choice && !timedOutProducing) {
|
|
1014
|
+
publishAuth();
|
|
1015
|
+
recordAgyMetrics(metricsCtx, startTime, code, `agy exited with code ${code}`, choice?.id ?? null);
|
|
1016
|
+
console.error(`\n[gemini (agy) FAILED: configured model "${choice.id}" — see error]`);
|
|
1017
|
+
// "No review file" must mean none EXISTS, not merely that this run wrote none.
|
|
1018
|
+
discardStaleOutput(outputPath);
|
|
1019
|
+
const providerError = new Error(`agy exited with code ${code}.` +
|
|
1020
|
+
(outputTail.trim() ? `\n\nagy output (last ${AGY_FAILURE_TAIL_MAX_CHARS} chars):\n${outputTail.trim()}` : ''));
|
|
1021
|
+
reject(annotateModelError(providerError, 'gemini', choice));
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
if (code !== 0 || raw.length === 0 || timedOutProducing) {
|
|
1025
|
+
// A broken run tells us nothing about auth — release without a verdict
|
|
1026
|
+
// and let the next call re-probe.
|
|
1027
|
+
publishAuth();
|
|
756
1028
|
const reason = code !== 0
|
|
757
1029
|
? `agy exited with code ${code}`
|
|
758
1030
|
: raw.includes(AGY_NONRESPONSE_MARKER)
|
|
@@ -761,28 +1033,50 @@ async function runAgyConsultation(queryText, role, workspaceRoot, outputPath, me
|
|
|
761
1033
|
const content = agySkipContent(reason);
|
|
762
1034
|
process.stdout.write(content);
|
|
763
1035
|
writeConsultOutput(outputPath, content);
|
|
764
|
-
recordAgyMetrics(metricsCtx, startTime, code ?? 1, reason);
|
|
1036
|
+
recordAgyMetrics(metricsCtx, startTime, code ?? 1, reason, choice?.id ?? null);
|
|
765
1037
|
console.error(`\n[gemini (agy) skipped: ${reason}]`);
|
|
766
1038
|
resolve();
|
|
767
1039
|
return;
|
|
768
1040
|
}
|
|
1041
|
+
// A real review is conclusive proof agy is signed in.
|
|
1042
|
+
publishAuth('auth');
|
|
769
1043
|
// Plain-text stdout IS the review.
|
|
770
1044
|
process.stdout.write(raw);
|
|
771
1045
|
writeConsultOutput(outputPath, raw);
|
|
772
|
-
recordAgyMetrics(metricsCtx, startTime, 0, null);
|
|
1046
|
+
recordAgyMetrics(metricsCtx, startTime, 0, null, choice?.id ?? null);
|
|
773
1047
|
console.error(`\n[gemini (agy) completed in ${((Date.now() - startTime) / 1000).toFixed(1)}s]`);
|
|
774
1048
|
resolve();
|
|
775
1049
|
});
|
|
776
1050
|
});
|
|
777
1051
|
}
|
|
1052
|
+
/**
|
|
1053
|
+
* Record the model a lane actually ran, so a transcript answers "what did this use?".
|
|
1054
|
+
*
|
|
1055
|
+
* Logged from the dispatch branch that owns the resolved `choice`, NOT re-derived for display: a
|
|
1056
|
+
* second resolution path is exactly how `--model-id` came to be documented, parsed, and inert.
|
|
1057
|
+
* Naming the source too means a surprising id points at the file to edit.
|
|
1058
|
+
*/
|
|
1059
|
+
function logResolvedModel(lane, id, key, effort) {
|
|
1060
|
+
const from = key ? ` (from ${key})` : '';
|
|
1061
|
+
const at = effort ? ` at ${effort} reasoning effort` : '';
|
|
1062
|
+
console.error(`[${lane.toUpperCase()}] model: ${id}${at}${from}`);
|
|
1063
|
+
}
|
|
778
1064
|
/**
|
|
779
1065
|
* Run the consultation — dispatches to the correct model runner.
|
|
780
1066
|
*/
|
|
781
|
-
async function runConsultation(model, query, workspaceRoot, role, outputPath, metricsCtx, generalMode) {
|
|
1067
|
+
async function runConsultation(model, query, workspaceRoot, role, outputPath, metricsCtx, generalMode, modelIdOverride) {
|
|
1068
|
+
// Fail before dispatch if the selected lane cannot honour the override. Checked here rather than
|
|
1069
|
+
// per-branch so a lane that never reads it can't silently ignore it (codex caught exactly that for
|
|
1070
|
+
// hermes). Syntax is validated per-lane in resolveLaneModelChoice.
|
|
1071
|
+
if (modelIdOverride !== undefined) {
|
|
1072
|
+
assertLaneAcceptsModelOverride(model);
|
|
1073
|
+
}
|
|
782
1074
|
// SDK-based models
|
|
783
1075
|
if (model === 'claude') {
|
|
784
1076
|
const startTime = Date.now();
|
|
785
|
-
|
|
1077
|
+
const choice = resolveLaneModelChoice(workspaceRoot, 'claude', DEFAULT_CLAUDE_MODEL, modelIdOverride);
|
|
1078
|
+
logResolvedModel(model, choice.id, choice.key);
|
|
1079
|
+
await runClaudeConsultation(query, role, workspaceRoot, outputPath, metricsCtx, choice);
|
|
786
1080
|
const duration = (Date.now() - startTime) / 1000;
|
|
787
1081
|
logQuery(workspaceRoot, model, query, duration);
|
|
788
1082
|
console.error(`\n[${model} completed in ${duration.toFixed(1)}s]`);
|
|
@@ -790,7 +1084,10 @@ async function runConsultation(model, query, workspaceRoot, role, outputPath, me
|
|
|
790
1084
|
}
|
|
791
1085
|
if (model === 'codex') {
|
|
792
1086
|
const startTime = Date.now();
|
|
793
|
-
|
|
1087
|
+
const choice = resolveLaneModelChoice(workspaceRoot, 'codex', DEFAULT_CODEX_MODEL, modelIdOverride);
|
|
1088
|
+
const effort = resolveReasoningEffort(loadConfig(workspaceRoot).consult) ?? DEFAULT_CODEX_REASONING_EFFORT;
|
|
1089
|
+
logResolvedModel(model, choice.id, choice.key, effort);
|
|
1090
|
+
await runCodexConsultation(query, role, workspaceRoot, outputPath, metricsCtx, choice, effort);
|
|
794
1091
|
const duration = (Date.now() - startTime) / 1000;
|
|
795
1092
|
logQuery(workspaceRoot, model, query, duration);
|
|
796
1093
|
console.error(`\n[${model} completed in ${duration.toFixed(1)}s]`);
|
|
@@ -800,7 +1097,10 @@ async function runConsultation(model, query, workspaceRoot, role, outputPath, me
|
|
|
800
1097
|
// and non-blocking skip (see runAgyConsultation).
|
|
801
1098
|
if (model === 'gemini') {
|
|
802
1099
|
const startTime = Date.now();
|
|
803
|
-
|
|
1100
|
+
const choice = resolveOptionalLaneModelChoice(workspaceRoot, 'gemini', modelIdOverride);
|
|
1101
|
+
// No configured id means agy chooses; say so rather than printing a value we did not set.
|
|
1102
|
+
logResolvedModel(model, choice?.id ?? "agy's own default", choice?.key ?? null);
|
|
1103
|
+
await runAgyConsultation(query, role, workspaceRoot, outputPath, metricsCtx, choice);
|
|
804
1104
|
logQuery(workspaceRoot, model, query, (Date.now() - startTime) / 1000);
|
|
805
1105
|
return;
|
|
806
1106
|
}
|
|
@@ -876,6 +1176,8 @@ async function runConsultation(model, query, workspaceRoot, role, outputPath, me
|
|
|
876
1176
|
if (metricsCtx) {
|
|
877
1177
|
const usage = extractUsage(model, rawOutput);
|
|
878
1178
|
recordMetrics(metricsCtx, {
|
|
1179
|
+
// Subprocess lanes (hermes) expose no model selector — see MODEL_CONFIGURABLE_LANES.
|
|
1180
|
+
modelId: null,
|
|
879
1181
|
durationSeconds: duration,
|
|
880
1182
|
inputTokens: usage?.inputTokens ?? null,
|
|
881
1183
|
cachedInputTokens: usage?.cachedInputTokens ?? null,
|
|
@@ -901,6 +1203,7 @@ async function runConsultation(model, query, workspaceRoot, role, outputPath, me
|
|
|
901
1203
|
if (metricsCtx) {
|
|
902
1204
|
const duration = (Date.now() - startTime) / 1000;
|
|
903
1205
|
recordMetrics(metricsCtx, {
|
|
1206
|
+
modelId: null,
|
|
904
1207
|
durationSeconds: duration,
|
|
905
1208
|
inputTokens: null,
|
|
906
1209
|
cachedInputTokens: null,
|
|
@@ -1774,7 +2077,7 @@ export async function consult(options) {
|
|
|
1774
2077
|
}
|
|
1775
2078
|
}
|
|
1776
2079
|
const isGeneralMode = !hasType;
|
|
1777
|
-
await runConsultation(model, query, workspaceRoot, role, outputPath, metricsCtx, isGeneralMode);
|
|
2080
|
+
await runConsultation(model, query, workspaceRoot, role, outputPath, metricsCtx, isGeneralMode, options.modelId);
|
|
1778
2081
|
}
|
|
1779
2082
|
// Exported for testing
|
|
1780
2083
|
export { getDiffStat as _getDiffStat, buildSpecQuery as _buildSpecQuery, buildPlanQuery as _buildPlanQuery, buildPRQuery as _buildPRQuery, composePRQueryText as _composePRQueryText, computeLocalPRDiff as _computeLocalPRDiff, resolveIntegrationBase as _resolveIntegrationBase, resolveArchitectQuery as _resolveArchitectQuery, computePersistentOutputPath as _computePersistentOutputPath, MODEL_CONFIGS as _MODEL_CONFIGS, MODEL_ALIASES as _MODEL_ALIASES, runAgyConsultation as _runAgyConsultation, agySkipContent as _agySkipContent, };
|