@ttfw/envoi 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +238 -0
- package/dist/commands/app.d.ts +2 -0
- package/dist/commands/app.d.ts.map +1 -0
- package/dist/commands/app.js +31 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/autonomy.d.ts +6 -0
- package/dist/commands/autonomy.d.ts.map +1 -0
- package/dist/commands/autonomy.js +89 -0
- package/dist/commands/autonomy.js.map +1 -0
- package/dist/commands/builder.d.ts +13 -0
- package/dist/commands/builder.d.ts.map +1 -0
- package/dist/commands/builder.js +142 -0
- package/dist/commands/builder.js.map +1 -0
- package/dist/commands/idea.d.ts +12 -0
- package/dist/commands/idea.d.ts.map +1 -0
- package/dist/commands/idea.js +79 -0
- package/dist/commands/idea.js.map +1 -0
- package/dist/commands/init.d.ts +18 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +423 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mode.d.ts +13 -0
- package/dist/commands/mode.d.ts.map +1 -0
- package/dist/commands/mode.js +96 -0
- package/dist/commands/mode.js.map +1 -0
- package/dist/commands/onboard.d.ts +37 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +743 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/pr-note.d.ts +8 -0
- package/dist/commands/pr-note.d.ts.map +1 -0
- package/dist/commands/pr-note.js +27 -0
- package/dist/commands/pr-note.js.map +1 -0
- package/dist/commands/undo.d.ts +7 -0
- package/dist/commands/undo.d.ts.map +1 -0
- package/dist/commands/undo.js +59 -0
- package/dist/commands/undo.js.map +1 -0
- package/dist/commands/update.d.ts +24 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +248 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/constants/report_codes.d.ts +29 -0
- package/dist/constants/report_codes.d.ts.map +1 -0
- package/dist/constants/report_codes.js +69 -0
- package/dist/constants/report_codes.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +675 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/autonomy.d.ts +16 -0
- package/dist/lib/autonomy.d.ts.map +1 -0
- package/dist/lib/autonomy.js +38 -0
- package/dist/lib/autonomy.js.map +1 -0
- package/dist/lib/blocked.d.ts +87 -0
- package/dist/lib/blocked.d.ts.map +1 -0
- package/dist/lib/blocked.js +134 -0
- package/dist/lib/blocked.js.map +1 -0
- package/dist/lib/branding.d.ts +13 -0
- package/dist/lib/branding.d.ts.map +1 -0
- package/dist/lib/branding.js +19 -0
- package/dist/lib/branding.js.map +1 -0
- package/dist/lib/claude.d.ts +42 -0
- package/dist/lib/claude.d.ts.map +1 -0
- package/dist/lib/claude.js +291 -0
- package/dist/lib/claude.js.map +1 -0
- package/dist/lib/config.d.ts +71 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +410 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/diff.d.ts +150 -0
- package/dist/lib/diff.d.ts.map +1 -0
- package/dist/lib/diff.js +257 -0
- package/dist/lib/diff.js.map +1 -0
- package/dist/lib/doctor.d.ts +67 -0
- package/dist/lib/doctor.d.ts.map +1 -0
- package/dist/lib/doctor.js +211 -0
- package/dist/lib/doctor.js.map +1 -0
- package/dist/lib/fingerprint.d.ts +27 -0
- package/dist/lib/fingerprint.d.ts.map +1 -0
- package/dist/lib/fingerprint.js +116 -0
- package/dist/lib/fingerprint.js.map +1 -0
- package/dist/lib/fs.d.ts +93 -0
- package/dist/lib/fs.d.ts.map +1 -0
- package/dist/lib/fs.js +179 -0
- package/dist/lib/fs.js.map +1 -0
- package/dist/lib/git.d.ts +177 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +355 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/git_branching.d.ts +84 -0
- package/dist/lib/git_branching.d.ts.map +1 -0
- package/dist/lib/git_branching.js +327 -0
- package/dist/lib/git_branching.js.map +1 -0
- package/dist/lib/gitignore.d.ts +26 -0
- package/dist/lib/gitignore.d.ts.map +1 -0
- package/dist/lib/gitignore.js +119 -0
- package/dist/lib/gitignore.js.map +1 -0
- package/dist/lib/guardrails.d.ts +232 -0
- package/dist/lib/guardrails.d.ts.map +1 -0
- package/dist/lib/guardrails.js +323 -0
- package/dist/lib/guardrails.js.map +1 -0
- package/dist/lib/history.d.ts +110 -0
- package/dist/lib/history.d.ts.map +1 -0
- package/dist/lib/history.js +236 -0
- package/dist/lib/history.js.map +1 -0
- package/dist/lib/index.d.ts +29 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +29 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/json-extract.d.ts +42 -0
- package/dist/lib/json-extract.d.ts.map +1 -0
- package/dist/lib/json-extract.js +201 -0
- package/dist/lib/json-extract.js.map +1 -0
- package/dist/lib/judge.d.ts +237 -0
- package/dist/lib/judge.d.ts.map +1 -0
- package/dist/lib/judge.js +501 -0
- package/dist/lib/judge.js.map +1 -0
- package/dist/lib/lock.d.ts +79 -0
- package/dist/lib/lock.d.ts.map +1 -0
- package/dist/lib/lock.js +254 -0
- package/dist/lib/lock.js.map +1 -0
- package/dist/lib/migration.d.ts +9 -0
- package/dist/lib/migration.d.ts.map +1 -0
- package/dist/lib/migration.js +74 -0
- package/dist/lib/migration.js.map +1 -0
- package/dist/lib/paths.d.ts +18 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +27 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/preflight.d.ts +33 -0
- package/dist/lib/preflight.d.ts.map +1 -0
- package/dist/lib/preflight.js +177 -0
- package/dist/lib/preflight.js.map +1 -0
- package/dist/lib/prompt_budget.d.ts +18 -0
- package/dist/lib/prompt_budget.d.ts.map +1 -0
- package/dist/lib/prompt_budget.js +36 -0
- package/dist/lib/prompt_budget.js.map +1 -0
- package/dist/lib/report.d.ts +102 -0
- package/dist/lib/report.d.ts.map +1 -0
- package/dist/lib/report.js +347 -0
- package/dist/lib/report.js.map +1 -0
- package/dist/lib/reviewer-flow.d.ts +80 -0
- package/dist/lib/reviewer-flow.d.ts.map +1 -0
- package/dist/lib/reviewer-flow.js +138 -0
- package/dist/lib/reviewer-flow.js.map +1 -0
- package/dist/lib/reviewer.d.ts +53 -0
- package/dist/lib/reviewer.d.ts.map +1 -0
- package/dist/lib/reviewer.js +199 -0
- package/dist/lib/reviewer.js.map +1 -0
- package/dist/lib/risk.d.ts +127 -0
- package/dist/lib/risk.d.ts.map +1 -0
- package/dist/lib/risk.js +192 -0
- package/dist/lib/risk.js.map +1 -0
- package/dist/lib/rollback.d.ts +143 -0
- package/dist/lib/rollback.d.ts.map +1 -0
- package/dist/lib/rollback.js +244 -0
- package/dist/lib/rollback.js.map +1 -0
- package/dist/lib/schema.d.ts +47 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/schema.js +91 -0
- package/dist/lib/schema.js.map +1 -0
- package/dist/lib/scope.d.ts +89 -0
- package/dist/lib/scope.d.ts.map +1 -0
- package/dist/lib/scope.js +135 -0
- package/dist/lib/scope.js.map +1 -0
- package/dist/lib/self_update.d.ts +13 -0
- package/dist/lib/self_update.d.ts.map +1 -0
- package/dist/lib/self_update.js +172 -0
- package/dist/lib/self_update.js.map +1 -0
- package/dist/lib/state.d.ts +143 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +258 -0
- package/dist/lib/state.js.map +1 -0
- package/dist/lib/tick.d.ts +310 -0
- package/dist/lib/tick.d.ts.map +1 -0
- package/dist/lib/tick.js +424 -0
- package/dist/lib/tick.js.map +1 -0
- package/dist/lib/transport.d.ts +145 -0
- package/dist/lib/transport.d.ts.map +1 -0
- package/dist/lib/transport.js +237 -0
- package/dist/lib/transport.js.map +1 -0
- package/dist/lib/verdict_labels.d.ts +5 -0
- package/dist/lib/verdict_labels.d.ts.map +1 -0
- package/dist/lib/verdict_labels.js +25 -0
- package/dist/lib/verdict_labels.js.map +1 -0
- package/dist/lib/verify-safety.d.ts +63 -0
- package/dist/lib/verify-safety.d.ts.map +1 -0
- package/dist/lib/verify-safety.js +123 -0
- package/dist/lib/verify-safety.js.map +1 -0
- package/dist/lib/verify.d.ts +139 -0
- package/dist/lib/verify.d.ts.map +1 -0
- package/dist/lib/verify.js +311 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/lib/workspace_state.d.ts +79 -0
- package/dist/lib/workspace_state.d.ts.map +1 -0
- package/dist/lib/workspace_state.js +283 -0
- package/dist/lib/workspace_state.js.map +1 -0
- package/dist/runner/builder.d.ts +58 -0
- package/dist/runner/builder.d.ts.map +1 -0
- package/dist/runner/builder.js +775 -0
- package/dist/runner/builder.js.map +1 -0
- package/dist/runner/builder_parse.d.ts +37 -0
- package/dist/runner/builder_parse.d.ts.map +1 -0
- package/dist/runner/builder_parse.js +76 -0
- package/dist/runner/builder_parse.js.map +1 -0
- package/dist/runner/index.d.ts +9 -0
- package/dist/runner/index.d.ts.map +1 -0
- package/dist/runner/index.js +7 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/runner/loop.d.ts +51 -0
- package/dist/runner/loop.d.ts.map +1 -0
- package/dist/runner/loop.js +221 -0
- package/dist/runner/loop.js.map +1 -0
- package/dist/runner/orchestrator.d.ts +67 -0
- package/dist/runner/orchestrator.d.ts.map +1 -0
- package/dist/runner/orchestrator.js +376 -0
- package/dist/runner/orchestrator.js.map +1 -0
- package/dist/runner/tick.d.ts +10 -0
- package/dist/runner/tick.d.ts.map +1 -0
- package/dist/runner/tick.js +1639 -0
- package/dist/runner/tick.js.map +1 -0
- package/dist/types/blocked.d.ts +52 -0
- package/dist/types/blocked.d.ts.map +1 -0
- package/dist/types/blocked.js +8 -0
- package/dist/types/blocked.js.map +1 -0
- package/dist/types/builder.d.ts +25 -0
- package/dist/types/builder.d.ts.map +1 -0
- package/dist/types/builder.js +7 -0
- package/dist/types/builder.js.map +1 -0
- package/dist/types/claude.d.ts +86 -0
- package/dist/types/claude.d.ts.map +1 -0
- package/dist/types/claude.js +48 -0
- package/dist/types/claude.js.map +1 -0
- package/dist/types/config.d.ts +384 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +7 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/lock.d.ts +21 -0
- package/dist/types/lock.d.ts.map +1 -0
- package/dist/types/lock.js +8 -0
- package/dist/types/lock.js.map +1 -0
- package/dist/types/preflight.d.ts +49 -0
- package/dist/types/preflight.d.ts.map +1 -0
- package/dist/types/preflight.js +8 -0
- package/dist/types/preflight.js.map +1 -0
- package/dist/types/report.d.ts +161 -0
- package/dist/types/report.d.ts.map +1 -0
- package/dist/types/report.js +8 -0
- package/dist/types/report.js.map +1 -0
- package/dist/types/reviewer.d.ts +66 -0
- package/dist/types/reviewer.d.ts.map +1 -0
- package/dist/types/reviewer.js +5 -0
- package/dist/types/reviewer.js.map +1 -0
- package/dist/types/state.d.ts +124 -0
- package/dist/types/state.d.ts.map +1 -0
- package/dist/types/state.js +20 -0
- package/dist/types/state.js.map +1 -0
- package/dist/types/task.d.ts +117 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +7 -0
- package/dist/types/task.js.map +1 -0
- package/dist/types/workspace_state.d.ts +125 -0
- package/dist/types/workspace_state.d.ts.map +1 -0
- package/dist/types/workspace_state.js +10 -0
- package/dist/types/workspace_state.js.map +1 -0
- package/envoi.config.json +191 -0
- package/package.json +52 -0
- package/relais/prompts/.gitkeep +0 -0
- package/relais/prompts/builder.system.txt +13 -0
- package/relais/prompts/builder.user.txt +15 -0
- package/relais/prompts/orchestrator.system.txt +37 -0
- package/relais/prompts/orchestrator.user.txt +34 -0
- package/relais/prompts/reviewer.system.txt +33 -0
- package/relais/prompts/reviewer.user.txt +35 -0
- package/relais/schemas/.gitkeep +0 -0
- package/relais/schemas/builder_result.schema.json +29 -0
- package/relais/schemas/report.schema.json +195 -0
- package/relais/schemas/reviewer_result.schema.json +70 -0
- package/relais/schemas/task.schema.json +155 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reviewer flow integration for pre-builder risk checks.
|
|
3
|
+
*
|
|
4
|
+
* Integrates the reviewer into the tick flow to be called pre-builder when
|
|
5
|
+
* risk is detected. Handles reviewer decisions and returns appropriate stop
|
|
6
|
+
* codes or proceeds to builder.
|
|
7
|
+
*/
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { readFile } from 'node:fs/promises';
|
|
10
|
+
import { invokeReviewer } from './reviewer.js';
|
|
11
|
+
import { shouldTriggerReviewer } from './risk.js';
|
|
12
|
+
/**
|
|
13
|
+
* Handles reviewer decision and returns appropriate stop code or null.
|
|
14
|
+
*
|
|
15
|
+
* @param decision - Reviewer decision object from parsed output
|
|
16
|
+
* @returns ReviewerFlowResult with stopCode or null (proceed)
|
|
17
|
+
*/
|
|
18
|
+
export function handleReviewerDecision(decision) {
|
|
19
|
+
if (decision.decision === 'proceed') {
|
|
20
|
+
return { stopCode: null };
|
|
21
|
+
}
|
|
22
|
+
if (decision.decision === 'force_patch') {
|
|
23
|
+
return { stopCode: 'STOP_REVIEWER_FORCED_PATCH' };
|
|
24
|
+
}
|
|
25
|
+
if (decision.decision === 'ask_question') {
|
|
26
|
+
if (!decision.question) {
|
|
27
|
+
// Invalid decision - missing question, default to force_patch
|
|
28
|
+
return { stopCode: 'STOP_REVIEWER_FORCED_PATCH' };
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
stopCode: 'STOP_REVIEWER_ASK_QUESTION',
|
|
32
|
+
question: {
|
|
33
|
+
prompt: decision.question.prompt,
|
|
34
|
+
choices: decision.question.choices,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// Unknown decision - default to force_patch for safety
|
|
39
|
+
return { stopCode: 'STOP_REVIEWER_FORCED_PATCH' };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Runs reviewer if needed based on risk flags and configuration.
|
|
43
|
+
*
|
|
44
|
+
* This function should be called pre-builder when risk is detected.
|
|
45
|
+
* It checks if reviewer should be triggered, invokes it if needed, and
|
|
46
|
+
* handles the decision.
|
|
47
|
+
*
|
|
48
|
+
* @param config - Envoi configuration
|
|
49
|
+
* @param context - Reviewer flow context
|
|
50
|
+
* @returns Promise resolving to ReviewerFlowResult
|
|
51
|
+
*/
|
|
52
|
+
export async function runReviewerIfNeeded(config, context) {
|
|
53
|
+
// Reviewer must be configured
|
|
54
|
+
if (!config.reviewer) {
|
|
55
|
+
return { stopCode: null };
|
|
56
|
+
}
|
|
57
|
+
// Check if reviewer should be triggered
|
|
58
|
+
if (!shouldTriggerReviewer(config.reviewer, context.riskFlags)) {
|
|
59
|
+
return { stopCode: null };
|
|
60
|
+
}
|
|
61
|
+
// Check authentication
|
|
62
|
+
const authCheck = await import('./reviewer.js').then((m) => m.checkReviewerAuth());
|
|
63
|
+
if (!authCheck.authenticated) {
|
|
64
|
+
// Degrade gracefully - log error but proceed (or default to force_patch if pre-build)
|
|
65
|
+
return {
|
|
66
|
+
stopCode: 'STOP_REVIEWER_FORCED_PATCH',
|
|
67
|
+
reviewerError: `Reviewer authentication failed: ${authCheck.reason || 'unknown reason'}`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Build reviewer prompt
|
|
71
|
+
const reviewerConfig = config.reviewer;
|
|
72
|
+
const workspaceDir = config.workspace_dir;
|
|
73
|
+
const userPromptPath = join(workspaceDir, reviewerConfig.user_prompt_file);
|
|
74
|
+
const systemPromptPath = join(workspaceDir, reviewerConfig.system_prompt_file);
|
|
75
|
+
let userPrompt;
|
|
76
|
+
let systemPrompt;
|
|
77
|
+
try {
|
|
78
|
+
userPrompt = await readFile(userPromptPath, 'utf-8');
|
|
79
|
+
systemPrompt = await readFile(systemPromptPath, 'utf-8');
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
return {
|
|
83
|
+
stopCode: 'STOP_REVIEWER_FORCED_PATCH',
|
|
84
|
+
reviewerError: `Failed to read reviewer prompt files: ${error instanceof Error ? error.message : String(error)}`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Interpolate placeholders in user prompt
|
|
88
|
+
const replacements = {
|
|
89
|
+
'{{RISK_FLAGS}}': context.riskFlags.join(', ') || 'none',
|
|
90
|
+
'{{TASK_JSON}}': context.task ? JSON.stringify(context.task, null, 2) : 'null',
|
|
91
|
+
'{{LAST_REPORT_MD}}': context.lastReportMd || '',
|
|
92
|
+
'{{DIFF_PATCH_OR_EMPTY}}': context.diffPatch || '',
|
|
93
|
+
'{{VERIFY_LOG_EXCERPT_OR_EMPTY}}': context.verifyLogExcerpt || '',
|
|
94
|
+
'{{TOUCHED_PATHS}}': context.touchedPaths.join('\n') || 'none',
|
|
95
|
+
};
|
|
96
|
+
for (const [placeholder, value] of Object.entries(replacements)) {
|
|
97
|
+
userPrompt = userPrompt.replace(new RegExp(placeholder.replace(/[{}]/g, '\\$&'), 'g'), value);
|
|
98
|
+
}
|
|
99
|
+
// Invoke reviewer
|
|
100
|
+
const invocationConfig = {
|
|
101
|
+
command: reviewerConfig.command,
|
|
102
|
+
model: reviewerConfig.model,
|
|
103
|
+
maxTurns: reviewerConfig.max_turns,
|
|
104
|
+
timeout: config.runner.max_tick_seconds * 1000, // Convert to milliseconds
|
|
105
|
+
};
|
|
106
|
+
const reviewerContext = {
|
|
107
|
+
prompt: userPrompt,
|
|
108
|
+
systemPrompt: systemPromptPath,
|
|
109
|
+
};
|
|
110
|
+
const invocationResult = await invokeReviewer(invocationConfig, reviewerContext);
|
|
111
|
+
if (!invocationResult.success) {
|
|
112
|
+
// Reviewer invocation failed - degrade gracefully
|
|
113
|
+
return {
|
|
114
|
+
stopCode: 'STOP_REVIEWER_FORCED_PATCH',
|
|
115
|
+
reviewerError: invocationResult.error,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// Parse and validate reviewer output
|
|
119
|
+
let decision;
|
|
120
|
+
try {
|
|
121
|
+
// The result should match reviewer_result.schema.json structure
|
|
122
|
+
const parsed = invocationResult.result;
|
|
123
|
+
if (!parsed.decision ||
|
|
124
|
+
!['proceed', 'force_patch', 'ask_question'].includes(parsed.decision)) {
|
|
125
|
+
throw new Error(`Invalid decision: ${parsed.decision}`);
|
|
126
|
+
}
|
|
127
|
+
decision = parsed;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
return {
|
|
131
|
+
stopCode: 'STOP_REVIEWER_FORCED_PATCH',
|
|
132
|
+
reviewerError: `Failed to parse reviewer decision: ${error instanceof Error ? error.message : String(error)}`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Handle the decision
|
|
136
|
+
return handleReviewerDecision(decision);
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=reviewer-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewer-flow.js","sourceRoot":"","sources":["../../src/lib/reviewer-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex CLI wrapper for invoking reviewer with proper flags.
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to invoke the reviewer, parse responses, and check authentication.
|
|
5
|
+
*/
|
|
6
|
+
import type { ReviewerInvocationConfig, ReviewerContext, ReviewerInvocationResult } from '../types/reviewer.js';
|
|
7
|
+
/**
|
|
8
|
+
* Checks if reviewer authentication is configured.
|
|
9
|
+
*
|
|
10
|
+
* Checks for CODEX_API_KEY environment variable presence as a best-effort
|
|
11
|
+
* authentication check (V1 implementation).
|
|
12
|
+
*
|
|
13
|
+
* @returns Object with authentication status
|
|
14
|
+
*/
|
|
15
|
+
export declare function checkReviewerAuth(): {
|
|
16
|
+
authenticated: boolean;
|
|
17
|
+
reason?: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Parses the JSON response from Codex CLI and extracts the result.
|
|
21
|
+
*
|
|
22
|
+
* Handles two formats:
|
|
23
|
+
* 1. Wrapper format: { result: 'JSON string', ... } - parses the .result field as JSON
|
|
24
|
+
* 2. Direct JSON format: { ... } - uses the parsed JSON directly
|
|
25
|
+
*
|
|
26
|
+
* @param stdout - Standard output from CLI process
|
|
27
|
+
* @returns Parsed result object
|
|
28
|
+
* @throws {Error} If JSON parsing fails
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseReviewerOutput(stdout: string): object;
|
|
31
|
+
/**
|
|
32
|
+
* Invokes Codex CLI reviewer with the given configuration and context.
|
|
33
|
+
*
|
|
34
|
+
* @param config - Codex CLI reviewer configuration
|
|
35
|
+
* @param context - Reviewer context including prompt and optional system prompt
|
|
36
|
+
* @returns Promise resolving to ReviewerInvocationResult (success or error)
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const result = await invokeReviewer(config, {
|
|
41
|
+
* prompt: 'Review this code...',
|
|
42
|
+
* systemPrompt: '/path/to/system.txt'
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* if (result.success) {
|
|
46
|
+
* console.log('Review result:', result.result);
|
|
47
|
+
* } else {
|
|
48
|
+
* console.error('Review failed:', result.error);
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function invokeReviewer(config: ReviewerInvocationConfig, context: ReviewerContext): Promise<ReviewerInvocationResult>;
|
|
53
|
+
//# sourceMappingURL=reviewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewer.d.ts","sourceRoot":"","sources":["../../src/lib/reviewer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,wBAAwB,EAAE,eAAe,EAAE,wBAAwB,EAAiC,MAAM,sBAAsB,CAAC;AAE/I;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,IAAI;IAAE,aAAa,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAe/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA8B1D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,wBAAwB,EAChC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,wBAAwB,CAAC,CAyHnC"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex CLI wrapper for invoking reviewer with proper flags.
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to invoke the reviewer, parse responses, and check authentication.
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
/**
|
|
8
|
+
* Checks if reviewer authentication is configured.
|
|
9
|
+
*
|
|
10
|
+
* Checks for CODEX_API_KEY environment variable presence as a best-effort
|
|
11
|
+
* authentication check (V1 implementation).
|
|
12
|
+
*
|
|
13
|
+
* @returns Object with authentication status
|
|
14
|
+
*/
|
|
15
|
+
export function checkReviewerAuth() {
|
|
16
|
+
const apiKey = process.env.CODEX_API_KEY;
|
|
17
|
+
if (!apiKey) {
|
|
18
|
+
return {
|
|
19
|
+
authenticated: false,
|
|
20
|
+
reason: 'CODEX_API_KEY environment variable not set',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (apiKey.trim().length === 0) {
|
|
24
|
+
return {
|
|
25
|
+
authenticated: false,
|
|
26
|
+
reason: 'CODEX_API_KEY environment variable is empty',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { authenticated: true };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parses the JSON response from Codex CLI and extracts the result.
|
|
33
|
+
*
|
|
34
|
+
* Handles two formats:
|
|
35
|
+
* 1. Wrapper format: { result: 'JSON string', ... } - parses the .result field as JSON
|
|
36
|
+
* 2. Direct JSON format: { ... } - uses the parsed JSON directly
|
|
37
|
+
*
|
|
38
|
+
* @param stdout - Standard output from CLI process
|
|
39
|
+
* @returns Parsed result object
|
|
40
|
+
* @throws {Error} If JSON parsing fails
|
|
41
|
+
*/
|
|
42
|
+
export function parseReviewerOutput(stdout) {
|
|
43
|
+
let parsed;
|
|
44
|
+
try {
|
|
45
|
+
parsed = JSON.parse(stdout);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
throw new Error(`Failed to parse JSON response: ${error instanceof Error ? error.message : String(error)}`);
|
|
49
|
+
}
|
|
50
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
51
|
+
throw new Error('Parsed response is not an object');
|
|
52
|
+
}
|
|
53
|
+
const obj = parsed;
|
|
54
|
+
// Check if it's a wrapper format with .result field
|
|
55
|
+
if (typeof obj.result === 'string') {
|
|
56
|
+
try {
|
|
57
|
+
// Parse the nested JSON string
|
|
58
|
+
const nestedParsed = JSON.parse(obj.result);
|
|
59
|
+
if (typeof nestedParsed === 'object' && nestedParsed !== null) {
|
|
60
|
+
return nestedParsed;
|
|
61
|
+
}
|
|
62
|
+
// If nested parse didn't yield an object, fall through to return wrapper
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// If parsing .result fails, fall through to return wrapper
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Return direct JSON or wrapper object
|
|
69
|
+
return parsed;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Invokes Codex CLI reviewer with the given configuration and context.
|
|
73
|
+
*
|
|
74
|
+
* @param config - Codex CLI reviewer configuration
|
|
75
|
+
* @param context - Reviewer context including prompt and optional system prompt
|
|
76
|
+
* @returns Promise resolving to ReviewerInvocationResult (success or error)
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const result = await invokeReviewer(config, {
|
|
81
|
+
* prompt: 'Review this code...',
|
|
82
|
+
* systemPrompt: '/path/to/system.txt'
|
|
83
|
+
* });
|
|
84
|
+
*
|
|
85
|
+
* if (result.success) {
|
|
86
|
+
* console.log('Review result:', result.result);
|
|
87
|
+
* } else {
|
|
88
|
+
* console.error('Review failed:', result.error);
|
|
89
|
+
* }
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export async function invokeReviewer(config, context) {
|
|
93
|
+
const startTime = Date.now();
|
|
94
|
+
// Build CLI arguments
|
|
95
|
+
const args = [
|
|
96
|
+
'-p', // prompt mode (non-interactive)
|
|
97
|
+
'--model',
|
|
98
|
+
config.model,
|
|
99
|
+
'--max-turns',
|
|
100
|
+
config.maxTurns.toString(),
|
|
101
|
+
];
|
|
102
|
+
// Add optional system-prompt flag
|
|
103
|
+
if (context.systemPrompt) {
|
|
104
|
+
args.push('--system-prompt', context.systemPrompt);
|
|
105
|
+
}
|
|
106
|
+
// Add the prompt as the last argument
|
|
107
|
+
args.push(context.prompt);
|
|
108
|
+
return new Promise((resolve) => {
|
|
109
|
+
let stdout = '';
|
|
110
|
+
let stderr = '';
|
|
111
|
+
let timeoutId = null;
|
|
112
|
+
// Spawn the process (shell: false for security)
|
|
113
|
+
const child = spawn(config.command, args, {
|
|
114
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
115
|
+
shell: false,
|
|
116
|
+
});
|
|
117
|
+
// Set up timeout
|
|
118
|
+
if (config.timeout > 0) {
|
|
119
|
+
timeoutId = setTimeout(() => {
|
|
120
|
+
child.kill('SIGTERM');
|
|
121
|
+
const durationMs = Date.now() - startTime;
|
|
122
|
+
resolve({
|
|
123
|
+
success: false,
|
|
124
|
+
error: `Codex CLI invocation timed out after ${config.timeout}ms`,
|
|
125
|
+
exitCode: 124, // Standard timeout exit code
|
|
126
|
+
stderr,
|
|
127
|
+
durationMs,
|
|
128
|
+
});
|
|
129
|
+
}, config.timeout);
|
|
130
|
+
}
|
|
131
|
+
// Capture stdout
|
|
132
|
+
child.stdout?.on('data', (data) => {
|
|
133
|
+
stdout += data.toString();
|
|
134
|
+
});
|
|
135
|
+
// Capture stderr
|
|
136
|
+
child.stderr?.on('data', (data) => {
|
|
137
|
+
stderr += data.toString();
|
|
138
|
+
});
|
|
139
|
+
// Handle process completion
|
|
140
|
+
child.on('close', (code) => {
|
|
141
|
+
if (timeoutId) {
|
|
142
|
+
clearTimeout(timeoutId);
|
|
143
|
+
}
|
|
144
|
+
const durationMs = Date.now() - startTime;
|
|
145
|
+
const exitCode = code ?? 0;
|
|
146
|
+
// If process was killed by timeout, error was already handled
|
|
147
|
+
if (code === null && timeoutId) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Try to parse the output
|
|
151
|
+
try {
|
|
152
|
+
const parsed = parseReviewerOutput(stdout);
|
|
153
|
+
// Basic validation: ensure it's an object
|
|
154
|
+
// Full schema validation will be added in WP-072 when reviewer_result.schema.json exists
|
|
155
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
156
|
+
resolve({
|
|
157
|
+
success: false,
|
|
158
|
+
error: 'Reviewer output is not a valid object',
|
|
159
|
+
exitCode,
|
|
160
|
+
stderr,
|
|
161
|
+
durationMs,
|
|
162
|
+
});
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
resolve({
|
|
166
|
+
success: true,
|
|
167
|
+
result: parsed,
|
|
168
|
+
raw: JSON.parse(stdout), // Keep original wrapper if present
|
|
169
|
+
exitCode,
|
|
170
|
+
durationMs,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
resolve({
|
|
175
|
+
success: false,
|
|
176
|
+
error: `Failed to parse reviewer output: ${error instanceof Error ? error.message : String(error)}`,
|
|
177
|
+
exitCode,
|
|
178
|
+
stderr,
|
|
179
|
+
durationMs,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
// Handle process errors
|
|
184
|
+
child.on('error', (error) => {
|
|
185
|
+
if (timeoutId) {
|
|
186
|
+
clearTimeout(timeoutId);
|
|
187
|
+
}
|
|
188
|
+
const durationMs = Date.now() - startTime;
|
|
189
|
+
resolve({
|
|
190
|
+
success: false,
|
|
191
|
+
error: `Failed to spawn Codex CLI process: ${error.message}`,
|
|
192
|
+
exitCode: 1,
|
|
193
|
+
stderr,
|
|
194
|
+
durationMs,
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=reviewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewer.js","sourceRoot":"","sources":["../../src/lib/reviewer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Risk scoring and reviewer trigger logic.
|
|
3
|
+
*
|
|
4
|
+
* Determines when the reviewer should be invoked based on deterministic
|
|
5
|
+
* risk signals: high-risk file paths, diff fraction thresholds, repeated
|
|
6
|
+
* stops, verification failures, and budget warnings.
|
|
7
|
+
*/
|
|
8
|
+
import type { DiffAnalysis } from './diff.js';
|
|
9
|
+
import type { ReviewerConfig, ReviewerTriggerConfig } from '../types/config.js';
|
|
10
|
+
import type { TaskScope, DiffLimits } from '../types/task.js';
|
|
11
|
+
import type { RiskFlags } from '../types/reviewer.js';
|
|
12
|
+
/**
|
|
13
|
+
* Stop history entry representing a single stop event.
|
|
14
|
+
*/
|
|
15
|
+
export interface StopHistoryEntry {
|
|
16
|
+
/** Tick number when the stop occurred */
|
|
17
|
+
tick: number;
|
|
18
|
+
/** Verdict of the stop (should be 'stop') */
|
|
19
|
+
verdict: 'stop';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Checks if any paths match high-risk glob patterns.
|
|
23
|
+
*
|
|
24
|
+
* Uses micromatch to check paths against high_risk_globs patterns.
|
|
25
|
+
*
|
|
26
|
+
* @param paths - Array of file paths to check
|
|
27
|
+
* @param highRiskGlobs - Array of glob patterns for high-risk files
|
|
28
|
+
* @returns Array of paths that match high-risk patterns
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const riskyPaths = checkHighRiskGlobs(
|
|
32
|
+
* ['src/auth.ts', 'src/utils.ts'],
|
|
33
|
+
* ['src/auth*.ts', 'src/*secret*']
|
|
34
|
+
* );
|
|
35
|
+
*/
|
|
36
|
+
export declare function checkHighRiskGlobs(paths: string[], highRiskGlobs: string[]): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Checks if diff fraction exceeds threshold.
|
|
39
|
+
*
|
|
40
|
+
* Calculates files_touched/max_files_touched or lines_changed/max_lines_changed
|
|
41
|
+
* and checks if either fraction >= threshold.
|
|
42
|
+
*
|
|
43
|
+
* @param analysis - Diff analysis result
|
|
44
|
+
* @param limits - Diff limits from task
|
|
45
|
+
* @param threshold - Fraction threshold (0.0 to 1.0)
|
|
46
|
+
* @returns True if diff fraction >= threshold
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* const analysis = { files_touched: 8, lines_changed: 300, ... };
|
|
50
|
+
* const limits = { max_files_touched: 10, max_lines_changed: 400 };
|
|
51
|
+
* const nearCap = checkDiffFraction(analysis, limits, 0.8);
|
|
52
|
+
*/
|
|
53
|
+
export declare function checkDiffFraction(analysis: DiffAnalysis, limits: DiffLimits, threshold: number): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Checks if there are repeated stops within a time window.
|
|
56
|
+
*
|
|
57
|
+
* Counts STOP verdicts in stop_history within the specified window
|
|
58
|
+
* and checks if count >= maxStops.
|
|
59
|
+
*
|
|
60
|
+
* @param stopHistory - Array of stop history entries
|
|
61
|
+
* @param window - Time window in ticks
|
|
62
|
+
* @param maxStops - Maximum number of stops allowed in window
|
|
63
|
+
* @param currentTick - Current tick number
|
|
64
|
+
* @returns True if repeated stops detected
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* const history = [
|
|
68
|
+
* { tick: 5, verdict: 'stop' },
|
|
69
|
+
* { tick: 8, verdict: 'stop' },
|
|
70
|
+
* { tick: 12, verdict: 'stop' }
|
|
71
|
+
* ];
|
|
72
|
+
* const repeated = checkRepeatedStops(history, 10, 2, 12);
|
|
73
|
+
*/
|
|
74
|
+
export declare function checkRepeatedStops(stopHistory: StopHistoryEntry[], window: number, maxStops: number, currentTick: number): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Computes risk flags based on various risk signals.
|
|
77
|
+
*
|
|
78
|
+
* Returns an array of risk flag strings indicating which risk conditions
|
|
79
|
+
* have been triggered.
|
|
80
|
+
*
|
|
81
|
+
* @param params - Parameters for risk computation
|
|
82
|
+
* @param params.analysis - Diff analysis result
|
|
83
|
+
* @param params.limits - Diff limits from task
|
|
84
|
+
* @param params.scope - Task scope configuration
|
|
85
|
+
* @param params.trigger - Reviewer trigger configuration
|
|
86
|
+
* @param params.stopHistory - Array of stop history entries
|
|
87
|
+
* @param params.currentTick - Current tick number
|
|
88
|
+
* @param params.verifyFailed - Whether verification failed
|
|
89
|
+
* @param params.budgetWarning - Whether budget warning threshold reached
|
|
90
|
+
* @returns Array of risk flag strings
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* const flags = computeRiskFlags({
|
|
94
|
+
* analysis,
|
|
95
|
+
* limits,
|
|
96
|
+
* scope,
|
|
97
|
+
* trigger,
|
|
98
|
+
* stopHistory: [],
|
|
99
|
+
* currentTick: 10,
|
|
100
|
+
* verifyFailed: false,
|
|
101
|
+
* budgetWarning: false
|
|
102
|
+
* });
|
|
103
|
+
*/
|
|
104
|
+
export declare function computeRiskFlags(params: {
|
|
105
|
+
analysis: DiffAnalysis;
|
|
106
|
+
limits: DiffLimits;
|
|
107
|
+
scope: TaskScope;
|
|
108
|
+
trigger: ReviewerTriggerConfig;
|
|
109
|
+
stopHistory: StopHistoryEntry[];
|
|
110
|
+
currentTick: number;
|
|
111
|
+
verifyFailed: boolean;
|
|
112
|
+
budgetWarning: boolean;
|
|
113
|
+
}): RiskFlags[];
|
|
114
|
+
/**
|
|
115
|
+
* Determines if reviewer should be triggered based on risk flags and config.
|
|
116
|
+
*
|
|
117
|
+
* Returns true if reviewer is enabled and any trigger condition is met.
|
|
118
|
+
*
|
|
119
|
+
* @param config - Reviewer configuration
|
|
120
|
+
* @param riskFlags - Array of risk flags from computeRiskFlags
|
|
121
|
+
* @returns True if reviewer should be triggered
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* const shouldTrigger = shouldTriggerReviewer(config, ['high_risk_path', 'diff_near_cap']);
|
|
125
|
+
*/
|
|
126
|
+
export declare function shouldTriggerReviewer(config: ReviewerConfig, riskFlags: RiskFlags[]): boolean;
|
|
127
|
+
//# sourceMappingURL=risk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk.d.ts","sourceRoot":"","sources":["../../src/lib/risk.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,EAAE,MAAM,EAAE,GACtB,MAAM,EAAE,CAOV;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAiBT;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,gBAAgB,EAAE,EAC/B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAYT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;CACxB,GAAG,SAAS,EAAE,CAsFd;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,SAAS,EAAE,GACrB,OAAO,CAQT"}
|