@cluesmith/codev 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/bin/af.js +2 -2
- package/bin/afx.js +8 -0
- package/bin/consult.js +2 -1
- package/bin/team.js +2 -1
- package/{dashboard/dist/assets/index-nr0cXxtf.css → dashboard-dist/assets/index-BWYZtvwm.css} +1 -1
- package/dashboard-dist/assets/index-Dn9zmcKp.js +195 -0
- package/dashboard-dist/assets/index-Dn9zmcKp.js.map +1 -0
- package/{dashboard/dist → dashboard-dist}/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +27 -19
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/architect.d.ts +4 -4
- package/dist/agent-farm/commands/architect.d.ts.map +1 -1
- package/dist/agent-farm/commands/architect.js +23 -12
- package/dist/agent-farm/commands/architect.js.map +1 -1
- package/dist/agent-farm/commands/attach.d.ts.map +1 -1
- package/dist/agent-farm/commands/attach.js +101 -11
- package/dist/agent-farm/commands/attach.js.map +1 -1
- package/dist/agent-farm/commands/bench.d.ts +1 -1
- package/dist/agent-farm/commands/bench.js +1 -1
- package/dist/agent-farm/commands/cron.js +1 -1
- package/dist/agent-farm/commands/cron.js.map +1 -1
- package/dist/agent-farm/commands/db.d.ts +3 -3
- package/dist/agent-farm/commands/db.js +4 -4
- package/dist/agent-farm/commands/db.js.map +1 -1
- package/dist/agent-farm/commands/open.js +2 -2
- package/dist/agent-farm/commands/open.js.map +1 -1
- package/dist/agent-farm/commands/rename.js +1 -1
- package/dist/agent-farm/commands/rename.js.map +1 -1
- package/dist/agent-farm/commands/send.js +3 -3
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/shell.js +3 -3
- package/dist/agent-farm/commands/shell.js.map +1 -1
- package/dist/agent-farm/commands/spawn-roles.d.ts +9 -5
- package/dist/agent-farm/commands/spawn-roles.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-roles.js +48 -28
- package/dist/agent-farm/commands/spawn-roles.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts +5 -5
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +80 -13
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts +6 -6
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +90 -53
- 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 +48 -3
- package/dist/agent-farm/commands/status.js.map +1 -1
- package/dist/agent-farm/commands/team-update.d.ts +1 -1
- package/dist/agent-farm/commands/team-update.js +1 -1
- package/dist/agent-farm/commands/team.d.ts +1 -1
- package/dist/agent-farm/commands/team.js +1 -1
- package/dist/agent-farm/commands/tower-cloud.d.ts +2 -2
- package/dist/agent-farm/commands/tower-cloud.js +3 -3
- package/dist/agent-farm/commands/tower-cloud.js.map +1 -1
- package/dist/agent-farm/commands/tower.js +2 -2
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/db/index.d.ts.map +1 -1
- package/dist/agent-farm/db/index.js +47 -0
- package/dist/agent-farm/db/index.js.map +1 -1
- 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 +1 -1
- package/dist/agent-farm/db/types.d.ts +1 -1
- package/dist/agent-farm/lib/cloud-config.js +2 -2
- package/dist/agent-farm/lib/cloud-config.js.map +1 -1
- package/dist/agent-farm/lib/tower-client.d.ts +6 -230
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tower-client.js +6 -293
- package/dist/agent-farm/lib/tower-client.js.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +1 -1
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/message-write.d.ts +24 -0
- package/dist/agent-farm/servers/message-write.d.ts.map +1 -0
- package/dist/agent-farm/servers/message-write.js +63 -0
- package/dist/agent-farm/servers/message-write.js.map +1 -0
- package/dist/agent-farm/servers/overview.d.ts +4 -1
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +38 -5
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/send-buffer.d.ts +4 -3
- package/dist/agent-farm/servers/send-buffer.d.ts.map +1 -1
- package/dist/agent-farm/servers/send-buffer.js +7 -4
- package/dist/agent-farm/servers/send-buffer.js.map +1 -1
- package/dist/agent-farm/servers/tower-cron-parser.js +1 -1
- package/dist/agent-farm/servers/tower-cron-parser.js.map +1 -1
- package/dist/agent-farm/servers/tower-cron.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-cron.js +4 -5
- package/dist/agent-farm/servers/tower-cron.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +6 -5
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +19 -16
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +19 -4
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +2 -2
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +47 -18
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-tunnel.js +2 -2
- package/dist/agent-farm/servers/tower-tunnel.js.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts +9 -6
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +12 -6
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/state.js +1 -1
- package/dist/agent-farm/state.js.map +1 -1
- package/dist/agent-farm/types.d.ts +11 -2
- package/dist/agent-farm/types.d.ts.map +1 -1
- package/dist/agent-farm/utils/config.d.ts +11 -0
- package/dist/agent-farm/utils/config.d.ts.map +1 -1
- package/dist/agent-farm/utils/config.js +21 -0
- package/dist/agent-farm/utils/config.js.map +1 -1
- package/dist/agent-farm/utils/harness.d.ts +85 -0
- package/dist/agent-farm/utils/harness.d.ts.map +1 -0
- package/dist/agent-farm/utils/harness.js +212 -0
- package/dist/agent-farm/utils/harness.js.map +1 -0
- package/dist/agent-farm/utils/server-utils.d.ts +13 -0
- package/dist/agent-farm/utils/server-utils.d.ts.map +1 -1
- package/dist/agent-farm/utils/server-utils.js +38 -0
- package/dist/agent-farm/utils/server-utils.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +19 -5
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.js +2 -2
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/consult/index.d.ts +37 -3
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +220 -150
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +54 -8
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/porch/artifacts.d.ts +69 -0
- package/dist/commands/porch/artifacts.d.ts.map +1 -0
- package/dist/commands/porch/artifacts.js +368 -0
- package/dist/commands/porch/artifacts.js.map +1 -0
- package/dist/commands/porch/checks.d.ts +8 -1
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +98 -1
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/index.d.ts +18 -7
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +299 -61
- 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 +72 -74
- package/dist/commands/porch/next.js.map +1 -1
- package/dist/commands/porch/notify.d.ts +2 -2
- package/dist/commands/porch/notify.js +5 -5
- package/dist/commands/porch/notify.js.map +1 -1
- package/dist/commands/porch/prompts.d.ts +2 -1
- package/dist/commands/porch/prompts.d.ts.map +1 -1
- package/dist/commands/porch/prompts.js +23 -14
- package/dist/commands/porch/prompts.js.map +1 -1
- package/dist/commands/porch/state.d.ts +27 -2
- package/dist/commands/porch/state.d.ts.map +1 -1
- package/dist/commands/porch/state.js +96 -9
- package/dist/commands/porch/state.js.map +1 -1
- package/dist/commands/porch/types.d.ts +8 -0
- package/dist/commands/porch/types.d.ts.map +1 -1
- package/dist/lib/config.d.ts +14 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +7 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/forge-contracts.d.ts +10 -1
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/forge.d.ts.map +1 -1
- package/dist/lib/forge.js +25 -7
- package/dist/lib/forge.js.map +1 -1
- package/dist/lib/team-github.d.ts +49 -0
- package/dist/lib/team-github.d.ts.map +1 -1
- package/dist/lib/team-github.js +115 -6
- package/dist/lib/team-github.js.map +1 -1
- package/dist/terminal/pty-manager.d.ts.map +1 -1
- package/dist/terminal/pty-manager.js +2 -0
- package/dist/terminal/pty-manager.js.map +1 -1
- package/dist/terminal/ws-protocol.d.ts +10 -8
- package/dist/terminal/ws-protocol.d.ts.map +1 -1
- package/dist/terminal/ws-protocol.js +3 -0
- package/dist/terminal/ws-protocol.js.map +1 -1
- package/package.json +28 -25
- package/scripts/forge/gitea/auth-status.sh +0 -0
- package/scripts/forge/gitea/issue-comment.sh +0 -0
- package/scripts/forge/gitea/issue-list.sh +0 -0
- package/scripts/forge/gitea/issue-view.sh +0 -0
- package/scripts/forge/gitea/pr-exists.sh +4 -1
- package/scripts/forge/gitea/pr-list.sh +0 -0
- package/scripts/forge/gitea/pr-merge.sh +0 -0
- package/scripts/forge/gitea/pr-view.sh +0 -0
- package/scripts/forge/gitea/recently-closed.sh +0 -0
- package/scripts/forge/gitea/recently-merged.sh +0 -0
- package/scripts/forge/gitea/repo-archive.sh +0 -0
- package/scripts/forge/gitea/user-identity.sh +0 -0
- package/scripts/forge/github/auth-status.sh +0 -0
- package/scripts/forge/github/issue-comment.sh +0 -0
- package/scripts/forge/github/issue-list.sh +2 -2
- package/scripts/forge/github/issue-view.sh +0 -0
- package/scripts/forge/github/on-it-timestamps.sh +0 -0
- package/scripts/forge/github/pr-diff.sh +0 -0
- package/scripts/forge/github/pr-exists.sh +3 -1
- package/scripts/forge/github/pr-list.sh +2 -2
- package/scripts/forge/github/pr-merge.sh +0 -0
- package/scripts/forge/github/pr-search.sh +0 -0
- package/scripts/forge/github/pr-view.sh +0 -0
- package/scripts/forge/github/recently-closed.sh +0 -0
- package/scripts/forge/github/recently-merged.sh +0 -0
- package/scripts/forge/github/repo-archive.sh +0 -0
- package/scripts/forge/github/team-activity.sh +0 -0
- package/scripts/forge/github/user-identity.sh +0 -0
- package/scripts/forge/gitlab/auth-status.sh +0 -0
- package/scripts/forge/gitlab/issue-comment.sh +0 -0
- package/scripts/forge/gitlab/issue-list.sh +0 -0
- package/scripts/forge/gitlab/issue-view.sh +0 -0
- package/scripts/forge/gitlab/pr-diff.sh +0 -0
- package/scripts/forge/gitlab/pr-exists.sh +3 -1
- package/scripts/forge/gitlab/pr-list.sh +0 -0
- package/scripts/forge/gitlab/pr-merge.sh +0 -0
- package/scripts/forge/gitlab/pr-search.sh +0 -0
- package/scripts/forge/gitlab/pr-view.sh +0 -0
- package/scripts/forge/gitlab/recently-closed.sh +0 -0
- package/scripts/forge/gitlab/recently-merged.sh +0 -0
- package/scripts/forge/gitlab/repo-archive.sh +0 -0
- package/scripts/forge/gitlab/user-identity.sh +0 -0
- package/scripts/forge/linear/auth-status.sh +15 -0
- package/scripts/forge/linear/issue-comment.sh +38 -0
- package/scripts/forge/linear/issue-list.sh +35 -0
- package/scripts/forge/linear/issue-view.sh +37 -0
- package/scripts/forge/linear/recently-closed.sh +45 -0
- package/scripts/forge/linear/user-identity.sh +15 -0
- package/scripts/postinstall.mjs +51 -0
- package/skeleton/.claude/skills/afx/SKILL.md +144 -0
- package/skeleton/.claude/skills/codev/SKILL.md +3 -3
- package/skeleton/.claude/skills/consult/SKILL.md +1 -1
- package/skeleton/.claude/skills/porch/SKILL.md +2 -2
- package/skeleton/.claude/skills/update-arch-docs/SKILL.md +107 -0
- package/skeleton/DEPENDENCIES.md +1 -1
- package/skeleton/builders.md +4 -4
- package/skeleton/protocol-schema.json +2 -2
- package/skeleton/protocols/air/builder-prompt.md +6 -6
- package/skeleton/protocols/air/prompts/pr.md +17 -5
- package/skeleton/protocols/air/protocol.md +1 -2
- package/skeleton/protocols/aspir/builder-prompt.md +28 -6
- package/skeleton/protocols/aspir/prompts/review.md +11 -0
- package/skeleton/protocols/aspir/protocol.json +9 -1
- package/skeleton/protocols/aspir/protocol.md +1 -1
- package/skeleton/protocols/aspir/templates/plan.md +0 -20
- package/skeleton/protocols/aspir/templates/spec.md +0 -28
- package/skeleton/protocols/bugfix/builder-prompt.md +6 -6
- package/skeleton/protocols/bugfix/prompts/pr.md +16 -4
- package/skeleton/protocols/experiment/builder-prompt.md +15 -0
- package/skeleton/protocols/experiment/protocol.md +1 -6
- package/skeleton/protocols/maintain/builder-prompt.md +12 -11
- package/skeleton/protocols/maintain/prompts/maintain.md +88 -0
- package/skeleton/protocols/maintain/prompts/review.md +84 -0
- package/skeleton/protocols/maintain/protocol.json +14 -68
- package/skeleton/protocols/maintain/protocol.md +163 -394
- package/skeleton/protocols/maintain/templates/maintenance-run.md +18 -49
- package/skeleton/protocols/protocol-schema.json +1 -1
- package/skeleton/protocols/research/builder-prompt.md +85 -0
- package/skeleton/protocols/research/protocol.json +118 -0
- package/skeleton/protocols/research/protocol.md +169 -0
- package/skeleton/protocols/spike/builder-prompt.md +1 -1
- package/skeleton/protocols/spike/protocol.md +4 -4
- package/skeleton/protocols/spir/builder-prompt.md +28 -5
- package/skeleton/protocols/spir/prompts/review.md +11 -0
- package/skeleton/protocols/spir/protocol.json +9 -1
- package/skeleton/protocols/spir/protocol.md +6 -5
- package/skeleton/protocols/spir/templates/plan.md +0 -20
- package/skeleton/protocols/spir/templates/spec.md +0 -28
- package/skeleton/resources/commands/agent-farm.md +84 -84
- package/skeleton/resources/commands/codev.md +1 -1
- package/skeleton/resources/commands/consult.md +16 -7
- package/skeleton/resources/commands/overview.md +14 -15
- package/skeleton/resources/risk-triage.md +2 -2
- package/skeleton/resources/workflow-reference.md +14 -14
- package/skeleton/roles/architect.md +39 -39
- package/skeleton/roles/builder.md +22 -14
- package/skeleton/templates/AGENTS.md +5 -3
- package/skeleton/templates/CLAUDE.md +5 -3
- package/skeleton/templates/arch.md +100 -30
- package/skeleton/templates/cheatsheet.md +12 -12
- package/skeleton/templates/lessons-learned.md +45 -7
- package/templates/3d-viewer.html +16 -18
- package/templates/tower.html +1 -1
- package/dashboard/dist/assets/index-CTrlY11L.js +0 -194
- package/dashboard/dist/assets/index-CTrlY11L.js.map +0 -1
- package/skeleton/.claude/skills/af/SKILL.md +0 -146
- package/skeleton/porch/prompts/understand.md +0 -61
- package/skeleton/porch/prompts/verify.md +0 -58
- package/skeleton/protocols/maintain/prompts/audit.md +0 -111
- package/skeleton/protocols/maintain/prompts/clean.md +0 -91
- package/skeleton/protocols/maintain/prompts/sync.md +0 -113
- package/skeleton/protocols/maintain/prompts/verify.md +0 -110
- package/skeleton/protocols/tick/builder-prompt.md +0 -65
- package/skeleton/protocols/tick/consult-types/impl-review.md +0 -72
- package/skeleton/protocols/tick/consult-types/plan-review.md +0 -59
- package/skeleton/protocols/tick/consult-types/pr-review.md +0 -72
- package/skeleton/protocols/tick/consult-types/spec-review.md +0 -55
- package/skeleton/protocols/tick/protocol.json +0 -151
- package/skeleton/protocols/tick/protocol.md +0 -277
- package/skeleton/protocols/tick/templates/plan.md +0 -67
- package/skeleton/protocols/tick/templates/review.md +0 -89
- package/skeleton/protocols/tick/templates/spec.md +0 -61
|
@@ -14,14 +14,19 @@ import chalk from 'chalk';
|
|
|
14
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
|
+
import { getResolver } from '../porch/artifacts.js';
|
|
17
18
|
import { MetricsDB } from './metrics.js';
|
|
18
19
|
import { extractUsage, extractReviewText } from './usage-extractor.js';
|
|
19
20
|
import { executeForgeCommandSync } from '../../lib/forge.js';
|
|
20
21
|
const MODEL_CONFIGS = {
|
|
21
22
|
gemini: { cli: 'gemini', args: ['--model', 'gemini-3-pro-preview'], envVar: 'GEMINI_SYSTEM_MD' },
|
|
23
|
+
hermes: { cli: 'hermes', args: ['chat', '-q'], envVar: null },
|
|
22
24
|
};
|
|
23
25
|
// Models that use an Agent SDK instead of CLI subprocess
|
|
24
26
|
const SDK_MODELS = ['claude', 'codex'];
|
|
27
|
+
// Prevent E2BIG when passing very large prompts to CLI backends.
|
|
28
|
+
// Large payloads are written to a temp file and referenced in the query.
|
|
29
|
+
const CLI_PROMPT_INLINE_MAX_CHARS = 100_000;
|
|
25
30
|
// Claude Agent SDK turn limit. Claude explores the codebase with Read/Glob/Grep
|
|
26
31
|
// tools before producing its verdict, so it needs a generous turn budget.
|
|
27
32
|
const CLAUDE_MAX_TURNS = 200;
|
|
@@ -130,46 +135,28 @@ function loadDotenv(workspaceRoot) {
|
|
|
130
135
|
}
|
|
131
136
|
}
|
|
132
137
|
/**
|
|
133
|
-
* Find
|
|
134
|
-
*
|
|
138
|
+
* Find spec content by project ID using the artifact resolver.
|
|
139
|
+
* Returns a ContentRef with content and label, or null if not found.
|
|
135
140
|
*/
|
|
136
|
-
function
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (matches.length > 1) {
|
|
144
|
-
const list = matches.map(f => ` - codev/specs/${f}`).join('\n');
|
|
145
|
-
throw new Error(`Multiple spec files match '${unpadded}' or '${padded}':\n${list}`);
|
|
146
|
-
}
|
|
147
|
-
if (matches.length === 1) {
|
|
148
|
-
return path.join(specsDir, matches[0]);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return null;
|
|
141
|
+
function findSpecContent(workspaceRoot, id) {
|
|
142
|
+
const resolver = getResolver(workspaceRoot);
|
|
143
|
+
const content = resolver.getSpecContent(id, '');
|
|
144
|
+
if (!content)
|
|
145
|
+
return null;
|
|
146
|
+
const label = resolver.findSpecBaseName(id, '') ?? id;
|
|
147
|
+
return { content, label };
|
|
152
148
|
}
|
|
153
149
|
/**
|
|
154
|
-
* Find
|
|
155
|
-
*
|
|
150
|
+
* Find plan content by project ID using the artifact resolver.
|
|
151
|
+
* Returns a ContentRef with content and label, or null if not found.
|
|
156
152
|
*/
|
|
157
|
-
function
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (matches.length > 1) {
|
|
165
|
-
const list = matches.map(f => ` - codev/plans/${f}`).join('\n');
|
|
166
|
-
throw new Error(`Multiple plan files match '${unpadded}' or '${padded}':\n${list}`);
|
|
167
|
-
}
|
|
168
|
-
if (matches.length === 1) {
|
|
169
|
-
return path.join(plansDir, matches[0]);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return null;
|
|
153
|
+
function findPlanContent(workspaceRoot, id) {
|
|
154
|
+
const resolver = getResolver(workspaceRoot);
|
|
155
|
+
const content = resolver.getPlanContent(id, '');
|
|
156
|
+
if (!content)
|
|
157
|
+
return null;
|
|
158
|
+
const baseName = resolver.findSpecBaseName(id, '') ?? id;
|
|
159
|
+
return { content, label: baseName };
|
|
173
160
|
}
|
|
174
161
|
/**
|
|
175
162
|
* Check if running in a builder worktree
|
|
@@ -310,11 +297,11 @@ export async function runCodexConsultation(queryText, role, workspaceRoot, outpu
|
|
|
310
297
|
try {
|
|
311
298
|
const codex = new Codex({
|
|
312
299
|
config: {
|
|
313
|
-
|
|
300
|
+
model_instructions_file: tempFile,
|
|
314
301
|
},
|
|
315
302
|
});
|
|
316
303
|
const thread = codex.startThread({
|
|
317
|
-
model: 'gpt-5.
|
|
304
|
+
model: 'gpt-5.4',
|
|
318
305
|
sandboxMode: 'read-only',
|
|
319
306
|
modelReasoningEffort: 'medium',
|
|
320
307
|
workingDirectory: workspaceRoot,
|
|
@@ -509,28 +496,72 @@ async function runConsultation(model, query, workspaceRoot, role, outputPath, me
|
|
|
509
496
|
let tempFile = null;
|
|
510
497
|
const env = {};
|
|
511
498
|
let cmd;
|
|
499
|
+
// When true, the query is written to the child's stdin instead of argv.
|
|
500
|
+
// Used for gemini to avoid V8 heap exhaustion on large prompts (#680).
|
|
501
|
+
let stdinPayload = null;
|
|
512
502
|
if (model === 'gemini') {
|
|
513
503
|
// Gemini uses GEMINI_SYSTEM_MD env var for role
|
|
514
504
|
tempFile = path.join(tmpdir(), `codev-role-${Date.now()}.md`);
|
|
515
505
|
fs.writeFileSync(tempFile, role);
|
|
516
506
|
env['GEMINI_SYSTEM_MD'] = tempFile;
|
|
507
|
+
// Bugfix #680: gemini-cli v0.37.x crashes on large PR diffs (>500KB) due to
|
|
508
|
+
// V8 old-space exhaustion in the spawned subprocess. Mitigations:
|
|
509
|
+
// 1. Bump heap via NODE_OPTIONS (survives gemini-cli's internal relaunch).
|
|
510
|
+
// 2. Pipe the prompt via stdin instead of argv — avoids ARG_MAX and keeps
|
|
511
|
+
// V8 from holding the full prompt buffer twice.
|
|
512
|
+
env['NODE_OPTIONS'] = [process.env.NODE_OPTIONS ?? '', '--max-old-space-size=8192']
|
|
513
|
+
.join(' ')
|
|
514
|
+
.trim();
|
|
515
|
+
stdinPayload = query;
|
|
517
516
|
// Use --output-format json to capture token usage/cost in structured output.
|
|
518
517
|
// Never use --yolo — it allows Gemini to write files (#370).
|
|
519
|
-
|
|
518
|
+
// No positional query arg: prompt arrives on stdin (triggers non-interactive mode).
|
|
519
|
+
cmd = [config.cli, '--output-format', 'json', ...config.args];
|
|
520
|
+
}
|
|
521
|
+
else if (model === 'hermes') {
|
|
522
|
+
// Hermes does not have a dedicated system prompt flag for single-shot mode.
|
|
523
|
+
// Include role context at the top of the prompt.
|
|
524
|
+
const hermesPrompt = `${role}\n\n---\n\n${query}`;
|
|
525
|
+
// Large inline CLI args can exceed OS ARG_MAX and fail with E2BIG.
|
|
526
|
+
// For very large prompts, write the full prompt to a temp file and pass
|
|
527
|
+
// an instruction that points Hermes at that file.
|
|
528
|
+
if (hermesPrompt.length > CLI_PROMPT_INLINE_MAX_CHARS) {
|
|
529
|
+
tempFile = path.join(tmpdir(), `codev-consult-prompt-${Date.now()}.md`);
|
|
530
|
+
fs.writeFileSync(tempFile, hermesPrompt);
|
|
531
|
+
const instruction = [
|
|
532
|
+
`Read the full consultation prompt from this file: ${tempFile}`,
|
|
533
|
+
'You have file access. Read files directly from disk to review code.',
|
|
534
|
+
].join('\n\n');
|
|
535
|
+
cmd = [config.cli, ...config.args, instruction];
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
cmd = [config.cli, ...config.args, hermesPrompt];
|
|
539
|
+
}
|
|
520
540
|
}
|
|
521
541
|
else {
|
|
522
542
|
throw new Error(`Unknown model: ${model}`);
|
|
523
543
|
}
|
|
524
|
-
// Execute with passthrough stdio
|
|
525
|
-
// Use 'ignore' for stdin
|
|
544
|
+
// Execute with passthrough stdio.
|
|
545
|
+
// Use 'ignore' for stdin when no payload — prevents blocking when spawned as subprocess.
|
|
546
|
+
// Use 'pipe' when we need to stream the prompt in (e.g. gemini, see #680).
|
|
526
547
|
const fullEnv = { ...process.env, ...env };
|
|
527
548
|
const startTime = Date.now();
|
|
549
|
+
const stdinMode = stdinPayload !== null ? 'pipe' : 'ignore';
|
|
528
550
|
return new Promise((resolve, reject) => {
|
|
529
551
|
const proc = spawn(cmd[0], cmd.slice(1), {
|
|
530
552
|
cwd: workspaceRoot,
|
|
531
553
|
env: fullEnv,
|
|
532
|
-
stdio: [
|
|
554
|
+
stdio: [stdinMode, 'pipe', 'inherit'],
|
|
533
555
|
});
|
|
556
|
+
if (stdinPayload !== null && proc.stdin) {
|
|
557
|
+
proc.stdin.on('error', (err) => {
|
|
558
|
+
// EPIPE can happen if the child exits before reading all input — not fatal.
|
|
559
|
+
if (err.code !== 'EPIPE') {
|
|
560
|
+
reject(err);
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
proc.stdin.end(stdinPayload, 'utf-8');
|
|
564
|
+
}
|
|
534
565
|
const chunks = [];
|
|
535
566
|
if (proc.stdout) {
|
|
536
567
|
proc.stdout.on('data', (chunk) => {
|
|
@@ -660,33 +691,39 @@ function fetchPRDiff(prId) {
|
|
|
660
691
|
}
|
|
661
692
|
}
|
|
662
693
|
/**
|
|
663
|
-
*
|
|
664
|
-
*
|
|
694
|
+
* Compose the PR review prompt text from already-fetched pieces.
|
|
695
|
+
*
|
|
696
|
+
* Split from the I/O wrapper so it can be tested without mocking the forge
|
|
697
|
+
* layer. Points the model at a temp-file path rather than inlining the diff:
|
|
698
|
+
* large (~800KB+) inlined diffs blow past the gemini-cli JSON path and bloat
|
|
699
|
+
* prompts for all models (#684).
|
|
665
700
|
*/
|
|
666
|
-
function
|
|
667
|
-
const
|
|
668
|
-
const
|
|
669
|
-
const
|
|
701
|
+
function composePRQueryText(params) {
|
|
702
|
+
const { prId, info, changedFiles, comments, diffPath, diffBytes, diffLines } = params;
|
|
703
|
+
const fileList = changedFiles.map(f => `- ${f}`).join('\n');
|
|
704
|
+
const diffSizeKb = (diffBytes / 1024).toFixed(1);
|
|
670
705
|
return `Review Pull Request #${prId}
|
|
671
706
|
|
|
672
707
|
## PR Info
|
|
673
708
|
\`\`\`json
|
|
674
|
-
${
|
|
709
|
+
${info}
|
|
675
710
|
\`\`\`
|
|
676
711
|
|
|
677
|
-
## Changed Files
|
|
712
|
+
## Changed Files (${changedFiles.length})
|
|
678
713
|
${fileList}
|
|
679
714
|
|
|
680
715
|
## PR Diff
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
716
|
+
The full PR diff is **not inlined** in this prompt to keep the payload small. It has been written to this path on disk:
|
|
717
|
+
|
|
718
|
+
**Diff file**: \`${diffPath}\`
|
|
719
|
+
**Size**: ${diffSizeKb} KB (${diffBytes} bytes, ${diffLines} lines)
|
|
684
720
|
|
|
685
721
|
## How to Review
|
|
686
|
-
|
|
722
|
+
1. **Read the diff file** from \`${diffPath}\` to see the exact changes (use the Read tool or \`cat\`).
|
|
723
|
+
2. You have **full filesystem access** — read any project files from disk for surrounding context beyond what the diff shows.
|
|
687
724
|
|
|
688
725
|
## Comments
|
|
689
|
-
${
|
|
726
|
+
${comments}
|
|
690
727
|
|
|
691
728
|
---
|
|
692
729
|
|
|
@@ -708,25 +745,58 @@ CONFIDENCE: [HIGH | MEDIUM | LOW]
|
|
|
708
745
|
|
|
709
746
|
KEY_ISSUES: [List of critical issues if any, or "None"]`;
|
|
710
747
|
}
|
|
748
|
+
/**
|
|
749
|
+
* Build query for PR review.
|
|
750
|
+
*
|
|
751
|
+
* Writes the full PR diff to a temp file and points the model at the path
|
|
752
|
+
* instead of inlining it. Inlining large diffs (~800KB+) caused gemini-cli's
|
|
753
|
+
* JSON output path to fail with "Unexpected end of JSON input" in 0.3s
|
|
754
|
+
* (#684); it also bloats prompts for Claude/Codex. This mirrors the pattern
|
|
755
|
+
* used by buildImplQuery.
|
|
756
|
+
*
|
|
757
|
+
* The temp file is left in place for the model to read during consultation.
|
|
758
|
+
* OS /tmp rotation handles cleanup.
|
|
759
|
+
*/
|
|
760
|
+
function buildPRQuery(prId) {
|
|
761
|
+
const prData = fetchPRData(prId);
|
|
762
|
+
const diff = fetchPRDiff(prId);
|
|
763
|
+
// Private-per-user dir to avoid world-readable /tmp diffs + symlink/clobber
|
|
764
|
+
// races: mkdtempSync creates a fresh dir owned by us; writeFileSync with
|
|
765
|
+
// flag 'wx' refuses to follow a symlink or overwrite an existing file.
|
|
766
|
+
const diffDir = fs.mkdtempSync(path.join(tmpdir(), 'codev-pr-'));
|
|
767
|
+
const diffPath = path.join(diffDir, `pr-${prId}.diff`);
|
|
768
|
+
fs.writeFileSync(diffPath, diff, { encoding: 'utf-8', mode: 0o600, flag: 'wx' });
|
|
769
|
+
const diffBytes = Buffer.byteLength(diff, 'utf-8');
|
|
770
|
+
const diffLines = diff ? diff.split('\n').length : 0;
|
|
771
|
+
return composePRQueryText({
|
|
772
|
+
prId,
|
|
773
|
+
info: prData.info,
|
|
774
|
+
changedFiles: prData.changedFiles,
|
|
775
|
+
comments: prData.comments,
|
|
776
|
+
diffPath,
|
|
777
|
+
diffBytes,
|
|
778
|
+
diffLines,
|
|
779
|
+
});
|
|
780
|
+
}
|
|
711
781
|
/**
|
|
712
782
|
* Build query for spec review
|
|
713
783
|
*/
|
|
714
|
-
function buildSpecQuery(
|
|
715
|
-
let query = `Review Specification: ${
|
|
784
|
+
function buildSpecQuery(spec, plan) {
|
|
785
|
+
let query = `Review Specification: ${spec.label}
|
|
786
|
+
|
|
787
|
+
## Specification
|
|
788
|
+
|
|
789
|
+
${spec.content}
|
|
716
790
|
|
|
717
|
-
Please read and review this specification:
|
|
718
|
-
- Spec file: ${specPath}
|
|
719
791
|
`;
|
|
720
|
-
if (
|
|
721
|
-
query +=
|
|
722
|
-
}
|
|
723
|
-
query += `
|
|
724
|
-
## How to Review
|
|
725
|
-
**Read the files listed above directly from disk.** You have full filesystem access.
|
|
726
|
-
Do NOT rely on \`git diff\` or \`git log\` to review content — diffs may be truncated or miss uncommitted work.
|
|
727
|
-
Open the spec file, read it in full, and evaluate it directly.
|
|
792
|
+
if (plan) {
|
|
793
|
+
query += `## Plan
|
|
728
794
|
|
|
729
|
-
|
|
795
|
+
${plan.content}
|
|
796
|
+
|
|
797
|
+
`;
|
|
798
|
+
}
|
|
799
|
+
query += `Please review:
|
|
730
800
|
1. Clarity and completeness of requirements
|
|
731
801
|
2. Technical feasibility
|
|
732
802
|
3. Edge cases and error scenarios
|
|
@@ -749,7 +819,7 @@ KEY_ISSUES: [List of critical issues if any, or "None"]`;
|
|
|
749
819
|
* Build query for implementation review.
|
|
750
820
|
* Accepts spec/plan paths and optional diff reference override.
|
|
751
821
|
*/
|
|
752
|
-
function buildImplQuery(workspaceRoot,
|
|
822
|
+
function buildImplQuery(workspaceRoot, spec, plan, planPhase, diffRef) {
|
|
753
823
|
// Get compact diff summary
|
|
754
824
|
let diffStat = '';
|
|
755
825
|
let changedFiles = [];
|
|
@@ -766,15 +836,15 @@ function buildImplQuery(workspaceRoot, specPath, planPath, planPhase, diffRef) {
|
|
|
766
836
|
if (planPhase) {
|
|
767
837
|
query += ` — Phase: ${planPhase}`;
|
|
768
838
|
}
|
|
769
|
-
query +=
|
|
770
|
-
if (
|
|
771
|
-
query +=
|
|
839
|
+
query += '\n\n';
|
|
840
|
+
if (spec) {
|
|
841
|
+
query += `## Specification\n\n${spec.content}\n\n`;
|
|
772
842
|
}
|
|
773
|
-
if (
|
|
774
|
-
query +=
|
|
843
|
+
if (plan) {
|
|
844
|
+
query += `## Plan\n\n${plan.content}\n\n`;
|
|
775
845
|
}
|
|
776
846
|
if (planPhase) {
|
|
777
|
-
query +=
|
|
847
|
+
query += `## REVIEW SCOPE — CURRENT PLAN PHASE ONLY\n`;
|
|
778
848
|
query += `You are reviewing **plan phase "${planPhase}" ONLY**.\n`;
|
|
779
849
|
query += `Read the plan, find the section for "${planPhase}", and scope your review to ONLY the work described in that phase.\n\n`;
|
|
780
850
|
query += `**DO NOT** request changes for work that belongs to other plan phases.\n`;
|
|
@@ -792,7 +862,7 @@ function buildImplQuery(workspaceRoot, specPath, planPath, planPhase, diffRef) {
|
|
|
792
862
|
query += `Do NOT rely on git diffs to determine the current state of code — diffs miss uncommitted changes in worktrees.\n`;
|
|
793
863
|
}
|
|
794
864
|
else {
|
|
795
|
-
query += `\n## Instructions\n\
|
|
865
|
+
query += `\n## Instructions\n\nExplore the filesystem to find and review the implementation changes.\n`;
|
|
796
866
|
}
|
|
797
867
|
query += `
|
|
798
868
|
Please review:
|
|
@@ -816,22 +886,22 @@ KEY_ISSUES: [List of critical issues if any, or "None"]`;
|
|
|
816
886
|
/**
|
|
817
887
|
* Build query for plan review
|
|
818
888
|
*/
|
|
819
|
-
function buildPlanQuery(
|
|
820
|
-
let query = `Review Implementation Plan: ${
|
|
889
|
+
function buildPlanQuery(plan, spec) {
|
|
890
|
+
let query = `Review Implementation Plan: ${plan.label}
|
|
891
|
+
|
|
892
|
+
## Plan
|
|
893
|
+
|
|
894
|
+
${plan.content}
|
|
821
895
|
|
|
822
|
-
Please read and review this implementation plan:
|
|
823
|
-
- Plan file: ${planPath}
|
|
824
896
|
`;
|
|
825
|
-
if (
|
|
826
|
-
query +=
|
|
827
|
-
}
|
|
828
|
-
query += `
|
|
829
|
-
## How to Review
|
|
830
|
-
**Read the files listed above directly from disk.** You have full filesystem access.
|
|
831
|
-
Do NOT rely on \`git diff\` or \`git log\` to review content — diffs may be truncated or miss uncommitted work.
|
|
832
|
-
Open the plan file (and spec if provided), read them in full, and evaluate the plan directly.
|
|
897
|
+
if (spec) {
|
|
898
|
+
query += `## Specification (for context)
|
|
833
899
|
|
|
834
|
-
|
|
900
|
+
${spec.content}
|
|
901
|
+
|
|
902
|
+
`;
|
|
903
|
+
}
|
|
904
|
+
query += `Please review:
|
|
835
905
|
1. Alignment with specification requirements
|
|
836
906
|
2. Implementation approach and architecture
|
|
837
907
|
3. Task breakdown and ordering
|
|
@@ -854,7 +924,7 @@ KEY_ISSUES: [List of critical issues if any, or "None"]`;
|
|
|
854
924
|
* Build query for phase-scoped review.
|
|
855
925
|
* Uses git show HEAD for the phase's atomic commit diff.
|
|
856
926
|
*/
|
|
857
|
-
function buildPhaseQuery(workspaceRoot, planPhase,
|
|
927
|
+
function buildPhaseQuery(workspaceRoot, planPhase, spec, plan) {
|
|
858
928
|
let phaseDiff = '';
|
|
859
929
|
try {
|
|
860
930
|
phaseDiff = execSync('git show HEAD', { cwd: workspaceRoot, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 });
|
|
@@ -862,11 +932,11 @@ function buildPhaseQuery(workspaceRoot, planPhase, specPath, planPath) {
|
|
|
862
932
|
catch {
|
|
863
933
|
// If git show fails, reviewer explores filesystem
|
|
864
934
|
}
|
|
865
|
-
let query = `Review Phase Implementation: "${planPhase}"\n\n
|
|
866
|
-
if (
|
|
867
|
-
query +=
|
|
868
|
-
if (
|
|
869
|
-
query +=
|
|
935
|
+
let query = `Review Phase Implementation: "${planPhase}"\n\n`;
|
|
936
|
+
if (spec)
|
|
937
|
+
query += `## Specification\n\n${spec.content}\n\n`;
|
|
938
|
+
if (plan)
|
|
939
|
+
query += `## Plan\n\n${plan.content}\n\n`;
|
|
870
940
|
query += `
|
|
871
941
|
## REVIEW SCOPE — CURRENT PLAN PHASE ONLY
|
|
872
942
|
You are reviewing **plan phase "${planPhase}" ONLY**.
|
|
@@ -937,36 +1007,36 @@ function resolveBuilderQuery(workspaceRoot, type, options) {
|
|
|
937
1007
|
const projectId = projectState.id;
|
|
938
1008
|
switch (type) {
|
|
939
1009
|
case 'spec': {
|
|
940
|
-
const
|
|
941
|
-
if (!
|
|
942
|
-
throw new Error(`Spec ${projectId} not found
|
|
943
|
-
const
|
|
944
|
-
console.error(`Spec: ${
|
|
945
|
-
if (
|
|
946
|
-
console.error(`Plan: ${
|
|
947
|
-
return buildSpecQuery(
|
|
1010
|
+
const spec = findSpecContent(workspaceRoot, projectId);
|
|
1011
|
+
if (!spec)
|
|
1012
|
+
throw new Error(`Spec ${projectId} not found`);
|
|
1013
|
+
const plan = findPlanContent(workspaceRoot, projectId);
|
|
1014
|
+
console.error(`Spec: ${spec.label}`);
|
|
1015
|
+
if (plan)
|
|
1016
|
+
console.error(`Plan: ${plan.label}`);
|
|
1017
|
+
return buildSpecQuery(spec, plan);
|
|
948
1018
|
}
|
|
949
1019
|
case 'plan': {
|
|
950
|
-
const
|
|
951
|
-
if (!
|
|
952
|
-
throw new Error(`Plan ${projectId} not found
|
|
953
|
-
const
|
|
954
|
-
console.error(`Plan: ${
|
|
955
|
-
if (
|
|
956
|
-
console.error(`Spec: ${
|
|
957
|
-
return buildPlanQuery(
|
|
1020
|
+
const plan = findPlanContent(workspaceRoot, projectId);
|
|
1021
|
+
if (!plan)
|
|
1022
|
+
throw new Error(`Plan ${projectId} not found`);
|
|
1023
|
+
const spec = findSpecContent(workspaceRoot, projectId);
|
|
1024
|
+
console.error(`Plan: ${plan.label}`);
|
|
1025
|
+
if (spec)
|
|
1026
|
+
console.error(`Spec: ${spec.label}`);
|
|
1027
|
+
return buildPlanQuery(plan, spec);
|
|
958
1028
|
}
|
|
959
1029
|
case 'impl': {
|
|
960
|
-
const
|
|
961
|
-
const
|
|
1030
|
+
const spec = findSpecContent(workspaceRoot, projectId);
|
|
1031
|
+
const plan = findPlanContent(workspaceRoot, projectId);
|
|
962
1032
|
console.error(`Project: ${projectId}`);
|
|
963
|
-
if (
|
|
964
|
-
console.error(`Spec: ${
|
|
965
|
-
if (
|
|
966
|
-
console.error(`Plan: ${
|
|
1033
|
+
if (spec)
|
|
1034
|
+
console.error(`Spec: ${spec.label}`);
|
|
1035
|
+
if (plan)
|
|
1036
|
+
console.error(`Plan: ${plan.label}`);
|
|
967
1037
|
if (options.planPhase)
|
|
968
1038
|
console.error(`Plan phase: ${options.planPhase}`);
|
|
969
|
-
return buildImplQuery(workspaceRoot,
|
|
1039
|
+
return buildImplQuery(workspaceRoot, spec, plan, options.planPhase);
|
|
970
1040
|
}
|
|
971
1041
|
case 'pr': {
|
|
972
1042
|
const prId = findPRForCurrentBranch(workspaceRoot);
|
|
@@ -978,14 +1048,14 @@ function resolveBuilderQuery(workspaceRoot, type, options) {
|
|
|
978
1048
|
if (!currentPhase) {
|
|
979
1049
|
throw new Error('No current plan phase detected. Use --plan-phase to specify.');
|
|
980
1050
|
}
|
|
981
|
-
const
|
|
982
|
-
const
|
|
1051
|
+
const spec = findSpecContent(workspaceRoot, projectId);
|
|
1052
|
+
const plan = findPlanContent(workspaceRoot, projectId);
|
|
983
1053
|
console.error(`Phase: ${currentPhase}`);
|
|
984
|
-
if (
|
|
985
|
-
console.error(`Spec: ${
|
|
986
|
-
if (
|
|
987
|
-
console.error(`Plan: ${
|
|
988
|
-
return buildPhaseQuery(workspaceRoot, currentPhase,
|
|
1054
|
+
if (spec)
|
|
1055
|
+
console.error(`Spec: ${spec.label}`);
|
|
1056
|
+
if (plan)
|
|
1057
|
+
console.error(`Plan: ${plan.label}`);
|
|
1058
|
+
return buildPhaseQuery(workspaceRoot, currentPhase, spec, plan);
|
|
989
1059
|
}
|
|
990
1060
|
case 'integration': {
|
|
991
1061
|
const prId = findPRForCurrentBranch(workspaceRoot);
|
|
@@ -1010,24 +1080,24 @@ function resolveArchitectQuery(workspaceRoot, type, options) {
|
|
|
1010
1080
|
const issueId = options.issue;
|
|
1011
1081
|
switch (type) {
|
|
1012
1082
|
case 'spec': {
|
|
1013
|
-
const
|
|
1014
|
-
if (!
|
|
1015
|
-
throw new Error(`Spec ${issueId} not found
|
|
1016
|
-
const
|
|
1017
|
-
console.error(`Spec: ${
|
|
1018
|
-
if (
|
|
1019
|
-
console.error(`Plan: ${
|
|
1020
|
-
return buildSpecQuery(
|
|
1083
|
+
const spec = findSpecContent(workspaceRoot, issueId);
|
|
1084
|
+
if (!spec)
|
|
1085
|
+
throw new Error(`Spec ${issueId} not found`);
|
|
1086
|
+
const plan = findPlanContent(workspaceRoot, issueId);
|
|
1087
|
+
console.error(`Spec: ${spec.label}`);
|
|
1088
|
+
if (plan)
|
|
1089
|
+
console.error(`Plan: ${plan.label}`);
|
|
1090
|
+
return buildSpecQuery(spec, plan);
|
|
1021
1091
|
}
|
|
1022
1092
|
case 'plan': {
|
|
1023
|
-
const
|
|
1024
|
-
if (!
|
|
1025
|
-
throw new Error(`Plan ${issueId} not found
|
|
1026
|
-
const
|
|
1027
|
-
console.error(`Plan: ${
|
|
1028
|
-
if (
|
|
1029
|
-
console.error(`Spec: ${
|
|
1030
|
-
return buildPlanQuery(
|
|
1093
|
+
const plan = findPlanContent(workspaceRoot, issueId);
|
|
1094
|
+
if (!plan)
|
|
1095
|
+
throw new Error(`Plan ${issueId} not found`);
|
|
1096
|
+
const spec = findSpecContent(workspaceRoot, issueId);
|
|
1097
|
+
console.error(`Plan: ${plan.label}`);
|
|
1098
|
+
if (spec)
|
|
1099
|
+
console.error(`Spec: ${spec.label}`);
|
|
1100
|
+
return buildPlanQuery(plan, spec);
|
|
1031
1101
|
}
|
|
1032
1102
|
case 'impl': {
|
|
1033
1103
|
const pr = findPRForIssue(workspaceRoot, issueId);
|
|
@@ -1039,14 +1109,14 @@ function resolveArchitectQuery(workspaceRoot, type, options) {
|
|
|
1039
1109
|
// May already be fetched
|
|
1040
1110
|
}
|
|
1041
1111
|
const mergeBase = execSync(`git merge-base main origin/${pr.headRefName}`, { cwd: workspaceRoot, encoding: 'utf-8' }).trim();
|
|
1042
|
-
const
|
|
1043
|
-
const
|
|
1112
|
+
const spec = findSpecContent(workspaceRoot, issueId);
|
|
1113
|
+
const plan = findPlanContent(workspaceRoot, issueId);
|
|
1044
1114
|
console.error(`Project: ${issueId} (PR #${pr.number}, branch: ${pr.headRefName})`);
|
|
1045
|
-
if (
|
|
1046
|
-
console.error(`Spec: ${
|
|
1047
|
-
if (
|
|
1048
|
-
console.error(`Plan: ${
|
|
1049
|
-
return buildImplQuery(workspaceRoot,
|
|
1115
|
+
if (spec)
|
|
1116
|
+
console.error(`Spec: ${spec.label}`);
|
|
1117
|
+
if (plan)
|
|
1118
|
+
console.error(`Plan: ${plan.label}`);
|
|
1119
|
+
return buildImplQuery(workspaceRoot, spec, plan, options.planPhase, `${mergeBase}..origin/${pr.headRefName}`);
|
|
1050
1120
|
}
|
|
1051
1121
|
case 'pr': {
|
|
1052
1122
|
const pr = findPRForIssue(workspaceRoot, issueId);
|
|
@@ -1161,7 +1231,7 @@ export async function consult(options) {
|
|
|
1161
1231
|
}
|
|
1162
1232
|
}
|
|
1163
1233
|
// Add file access instruction for Gemini
|
|
1164
|
-
if (model === 'gemini') {
|
|
1234
|
+
if (model === 'gemini' || model === 'hermes') {
|
|
1165
1235
|
query += '\n\nYou have file access. Read files directly from disk to review code.';
|
|
1166
1236
|
}
|
|
1167
1237
|
// Show the query/prompt being sent
|
|
@@ -1199,5 +1269,5 @@ export async function consult(options) {
|
|
|
1199
1269
|
await runConsultation(model, query, workspaceRoot, role, outputPath, metricsCtx, isGeneralMode);
|
|
1200
1270
|
}
|
|
1201
1271
|
// Exported for testing
|
|
1202
|
-
export { getDiffStat as _getDiffStat, buildSpecQuery as _buildSpecQuery, buildPlanQuery as _buildPlanQuery, computePersistentOutputPath as _computePersistentOutputPath, };
|
|
1272
|
+
export { getDiffStat as _getDiffStat, buildSpecQuery as _buildSpecQuery, buildPlanQuery as _buildPlanQuery, buildPRQuery as _buildPRQuery, composePRQueryText as _composePRQueryText, computePersistentOutputPath as _computePersistentOutputPath, };
|
|
1203
1273
|
//# sourceMappingURL=index.js.map
|