@awak-app/simy-cli 0.1.2 → 0.1.4
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 +39 -5
- package/package.json +14 -4
- package/src/agent.js +209 -24
- package/src/backend-executable.js +92 -6
- package/src/console/app.js +9 -7
- package/src/console/index.js +5 -4
- package/src/desktop-executor.js +137 -0
- package/src/index.js +3 -3
- package/src/local-attachments.js +2 -2
- package/src/orchestrator/audit.js +101 -7
- package/src/orchestrator/budget.js +112 -0
- package/src/orchestrator/contract.js +175 -27
- package/src/orchestrator/independent-audit.js +18 -4
- package/src/orchestrator/index.js +1 -0
- package/src/orchestrator/instruction.js +41 -5
- package/src/orchestrator/loop.js +185 -7
- package/src/orchestrator/presentation.js +2 -2
- package/src/orchestrator/problem-solving.js +129 -0
- package/src/orchestrator/recovery.js +271 -0
- package/src/orchestrator/result.js +2 -0
- package/src/orchestrator/retry.js +140 -0
- package/src/orchestrator/shared.js +87 -5
- package/src/provider-stream.js +17 -0
- package/src/repository-inventory.js +117 -0
- package/src/runner.js +128 -108
|
@@ -1,45 +1,105 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
clampAttempts,
|
|
5
4
|
cleanString,
|
|
6
5
|
event,
|
|
7
6
|
looksLikeUiTask,
|
|
8
7
|
stringArray,
|
|
8
|
+
visualEvidenceSurface,
|
|
9
9
|
} from "./shared.js";
|
|
10
|
+
import { budgetState, resolveRunBudgets } from "./budget.js";
|
|
10
11
|
import { classifyRisk } from "./risk.js";
|
|
12
|
+
import {
|
|
13
|
+
DESKTOP_EXECUTION_TARGET,
|
|
14
|
+
normalizeDesktopExecutionTarget,
|
|
15
|
+
} from "../desktop-executor.js";
|
|
11
16
|
|
|
12
17
|
export function createCodingLoopSnapshot({ runId, request, metadata = {} }) {
|
|
13
18
|
const now = new Date().toISOString();
|
|
14
19
|
const baseBranch = cleanString(request.base_branch) || "dev";
|
|
15
20
|
const expectedEvidence = stringArray(request.expected_evidence);
|
|
16
|
-
if (looksLikeUiTask(request.requirement) && !expectedEvidence.includes("ui_evidence_path")) {
|
|
17
|
-
expectedEvidence.push("ui_evidence_path");
|
|
18
|
-
}
|
|
19
21
|
const acceptanceCriteria = stringArray(request.acceptance_criteria);
|
|
20
22
|
const mustNot = stringArray(request.must_not);
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
23
|
+
const charterContext = record(request.charter_context);
|
|
24
|
+
const risk = inheritRisk(classifyRisk(request), record(charterContext.risk));
|
|
25
|
+
const inheritedDesignReview = record(charterContext.design_review);
|
|
26
|
+
const inheritedPromptPolicyReport = record(charterContext.prompt_policy_report);
|
|
27
|
+
const inheritedEvidencePolicy = record(charterContext.evidence_policy);
|
|
28
|
+
const classifiedVisualSurface = visualEvidenceSurface(request.requirement);
|
|
29
|
+
const inheritedVisualSurface = ["web_ui", "browser_extension"].includes(
|
|
30
|
+
inheritedEvidencePolicy.surface,
|
|
31
|
+
)
|
|
32
|
+
? inheritedEvidencePolicy.surface
|
|
33
|
+
: null;
|
|
34
|
+
const visualSurface = classifiedVisualSurface || inheritedVisualSurface;
|
|
35
|
+
const browserEvidenceRequired =
|
|
36
|
+
inheritedEvidencePolicy.browser_required === true || visualSurface !== null;
|
|
37
|
+
if (browserEvidenceRequired && !expectedEvidence.includes("ui_evidence_path")) {
|
|
38
|
+
expectedEvidence.push("ui_evidence_path");
|
|
39
|
+
}
|
|
40
|
+
if (browserEvidenceRequired && !expectedEvidence.includes("browser_screenshot_or_video")) {
|
|
41
|
+
expectedEvidence.push("browser_screenshot_or_video");
|
|
42
|
+
}
|
|
43
|
+
const designSummary = cleanString(
|
|
44
|
+
inheritedDesignReview.summary || request.design_summary,
|
|
45
|
+
);
|
|
46
|
+
const designApprovedBy = cleanString(
|
|
47
|
+
inheritedDesignReview.approved_by || request.design_review_approved_by,
|
|
48
|
+
);
|
|
49
|
+
const designEvidenceUrl = cleanString(
|
|
50
|
+
inheritedDesignReview.evidence_url || request.design_review_url,
|
|
51
|
+
);
|
|
52
|
+
const acceptanceCriteriaSource =
|
|
53
|
+
acceptanceCriteria.length > 0 &&
|
|
54
|
+
cleanString(charterContext.acceptance_criteria_source) === "explicit"
|
|
55
|
+
? "explicit"
|
|
56
|
+
: acceptanceCriteria.length > 0 &&
|
|
57
|
+
cleanString(charterContext.acceptance_criteria_source) === "default"
|
|
58
|
+
? "default"
|
|
59
|
+
: acceptanceCriteria.length > 0
|
|
60
|
+
? "explicit"
|
|
61
|
+
: "default";
|
|
62
|
+
const inheritedRequiredChecks = stringArray(charterContext.required_checks);
|
|
63
|
+
const inheritedNonGoals = stringArray(charterContext.non_goals);
|
|
64
|
+
const inheritedArtifacts = stringArray(charterContext.artifacts_required);
|
|
65
|
+
const inheritedAssumptions = stringArray(charterContext.assumptions);
|
|
66
|
+
const designReviewRequired =
|
|
67
|
+
risk.requires_design_review || inheritedDesignReview.required === true;
|
|
68
|
+
const designReviewApproved =
|
|
69
|
+
inheritedDesignReview.status === "approved" &&
|
|
70
|
+
Boolean(designSummary && designApprovedBy && designEvidenceUrl);
|
|
25
71
|
|
|
26
|
-
|
|
72
|
+
const budgets = resolveRunBudgets(request);
|
|
73
|
+
const executionTarget = normalizeDesktopExecutionTarget(request.execution_target);
|
|
74
|
+
const executionDeviceId = cleanString(request.execution_device_id) || null;
|
|
75
|
+
|
|
76
|
+
const snapshot = {
|
|
27
77
|
id: runId,
|
|
28
78
|
state: "queued",
|
|
29
|
-
metadata: {
|
|
79
|
+
metadata: {
|
|
80
|
+
...metadata,
|
|
81
|
+
execution_location: "local_cli",
|
|
82
|
+
execution_target: executionTarget,
|
|
83
|
+
execution_device_id: executionDeviceId,
|
|
84
|
+
},
|
|
30
85
|
charter: {
|
|
31
86
|
id: `${runId}_charter`,
|
|
32
87
|
requirement: cleanString(request.requirement),
|
|
33
88
|
repository: cleanString(request.repository),
|
|
34
89
|
backend: request.backend === "claude" ? "claude" : "codex",
|
|
90
|
+
execution_target: executionTarget,
|
|
35
91
|
audit_backend:
|
|
36
|
-
|
|
92
|
+
charterContext.audit_backend === "claude" || charterContext.audit_backend === "codex"
|
|
93
|
+
? charterContext.audit_backend
|
|
94
|
+
: request.audit_backend === "claude" || request.audit_backend === "codex"
|
|
37
95
|
? request.audit_backend
|
|
38
96
|
: request.backend === "claude"
|
|
39
97
|
? "claude"
|
|
40
98
|
: "codex",
|
|
41
99
|
base_branch: baseBranch,
|
|
42
|
-
max_attempts:
|
|
100
|
+
max_attempts: budgets.max_attempts,
|
|
101
|
+
retry_budget: budgets.retry_budget,
|
|
102
|
+
token_budget: budgets.token_budget,
|
|
43
103
|
ui_evidence_root: cleanString(request.ui_evidence_root),
|
|
44
104
|
acceptance_criteria:
|
|
45
105
|
acceptanceCriteria.length > 0
|
|
@@ -49,12 +109,18 @@ export function createCodingLoopSnapshot({ runId, request, metadata = {} }) {
|
|
|
49
109
|
"Relevant tests pass and are recorded.",
|
|
50
110
|
`A pull request targets ${baseBranch}.`,
|
|
51
111
|
],
|
|
52
|
-
acceptance_criteria_source:
|
|
112
|
+
acceptance_criteria_source: acceptanceCriteriaSource,
|
|
53
113
|
expected_tests: stringArray(request.expected_tests),
|
|
54
114
|
expected_evidence: expectedEvidence,
|
|
55
|
-
required_checks:
|
|
115
|
+
required_checks:
|
|
116
|
+
inheritedRequiredChecks.length > 0
|
|
117
|
+
? inheritedRequiredChecks
|
|
118
|
+
: stringArray(request.required_checks),
|
|
56
119
|
require_human_approval:
|
|
57
|
-
risk.requires_design_review ||
|
|
120
|
+
risk.requires_design_review ||
|
|
121
|
+
charterContext.require_human_approval === true ||
|
|
122
|
+
(charterContext.require_human_approval !== false &&
|
|
123
|
+
request.require_human_approval !== false),
|
|
58
124
|
must_not:
|
|
59
125
|
mustNot.length > 0
|
|
60
126
|
? mustNot
|
|
@@ -67,32 +133,56 @@ export function createCodingLoopSnapshot({ runId, request, metadata = {} }) {
|
|
|
67
133
|
attachments: Array.isArray(request.attachments) ? request.attachments : [],
|
|
68
134
|
risk,
|
|
69
135
|
design_review: {
|
|
70
|
-
required:
|
|
136
|
+
required: designReviewRequired,
|
|
71
137
|
summary: designSummary || null,
|
|
72
138
|
approved_by: designApprovedBy || null,
|
|
73
139
|
evidence_url: designEvidenceUrl || null,
|
|
74
|
-
status:
|
|
75
|
-
? designSummary && designApprovedBy && designEvidenceUrl
|
|
140
|
+
status: designReviewRequired
|
|
141
|
+
? designReviewApproved || (designSummary && designApprovedBy && designEvidenceUrl)
|
|
76
142
|
? "approved"
|
|
77
143
|
: "missing"
|
|
78
144
|
: "not_required",
|
|
79
145
|
},
|
|
146
|
+
evidence_policy: {
|
|
147
|
+
browser_required: browserEvidenceRequired,
|
|
148
|
+
surface: visualSurface,
|
|
149
|
+
accepted_artifact_kinds: browserEvidenceRequired ? ["image", "video"] : [],
|
|
150
|
+
visual_review_required: browserEvidenceRequired,
|
|
151
|
+
},
|
|
80
152
|
thread_state: {
|
|
81
|
-
original_request:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
153
|
+
original_request:
|
|
154
|
+
cleanString(charterContext.original_request) || cleanString(request.requirement),
|
|
155
|
+
user_goal: cleanString(charterContext.user_goal) || cleanString(request.requirement),
|
|
156
|
+
non_goals:
|
|
157
|
+
inheritedNonGoals.length > 0
|
|
158
|
+
? inheritedNonGoals
|
|
159
|
+
: ["Unrelated refactors", "Server-side execution of repository code"],
|
|
160
|
+
expected_finish_line:
|
|
161
|
+
cleanString(charterContext.expected_finish_line) ||
|
|
162
|
+
`A verified pull request targeting ${baseBranch}.`,
|
|
163
|
+
artifacts_required:
|
|
164
|
+
inheritedArtifacts.length > 0
|
|
165
|
+
? inheritedArtifacts
|
|
166
|
+
: ["pr_url", "commit_sha", "tests_run", ...expectedEvidence],
|
|
86
167
|
failure_count: 0,
|
|
87
|
-
|
|
168
|
+
retry_circuit_breaker: {
|
|
169
|
+
state: "closed",
|
|
170
|
+
reason: null,
|
|
171
|
+
opened_at: null,
|
|
172
|
+
},
|
|
173
|
+
assumptions: inheritedAssumptions,
|
|
88
174
|
},
|
|
89
|
-
prompt_policy_report:
|
|
175
|
+
prompt_policy_report: mergePromptPolicyReport(
|
|
176
|
+
buildPromptPolicyReport(request, risk),
|
|
177
|
+
inheritedPromptPolicyReport,
|
|
178
|
+
),
|
|
90
179
|
created_at: now,
|
|
91
180
|
},
|
|
92
181
|
attempts: [],
|
|
93
182
|
events: [
|
|
94
|
-
event("queued", "
|
|
183
|
+
event("queued", "Agentic loop queued for local orchestration.", {
|
|
95
184
|
execution_location: "local_cli",
|
|
185
|
+
execution_target: DESKTOP_EXECUTION_TARGET,
|
|
96
186
|
}),
|
|
97
187
|
],
|
|
98
188
|
final_audit: null,
|
|
@@ -101,10 +191,68 @@ export function createCodingLoopSnapshot({ runId, request, metadata = {} }) {
|
|
|
101
191
|
created_at: now,
|
|
102
192
|
updated_at: now,
|
|
103
193
|
};
|
|
194
|
+
snapshot.budget = budgetState(snapshot);
|
|
195
|
+
return snapshot;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function inheritRisk(classifiedRisk, inheritedRisk) {
|
|
199
|
+
const weight = { low: 0, medium: 1, high: 2, critical: 3 };
|
|
200
|
+
const inheritedLevel = Object.hasOwn(weight, inheritedRisk.level)
|
|
201
|
+
? inheritedRisk.level
|
|
202
|
+
: "low";
|
|
203
|
+
const level =
|
|
204
|
+
weight[inheritedLevel] > weight[classifiedRisk.level]
|
|
205
|
+
? inheritedLevel
|
|
206
|
+
: classifiedRisk.level;
|
|
207
|
+
const tags = [...new Set([...classifiedRisk.tags, ...stringArray(inheritedRisk.tags)])];
|
|
208
|
+
const requiredControls = [
|
|
209
|
+
...new Set([
|
|
210
|
+
...classifiedRisk.required_controls,
|
|
211
|
+
...stringArray(inheritedRisk.required_controls),
|
|
212
|
+
]),
|
|
213
|
+
];
|
|
214
|
+
const requiresDesignReview =
|
|
215
|
+
classifiedRisk.requires_design_review ||
|
|
216
|
+
inheritedRisk.requires_design_review === true ||
|
|
217
|
+
level === "high" ||
|
|
218
|
+
level === "critical";
|
|
219
|
+
if (requiresDesignReview && !requiredControls.includes("design_review")) {
|
|
220
|
+
requiredControls.push("design_review");
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
level,
|
|
224
|
+
tags,
|
|
225
|
+
requires_design_review: requiresDesignReview,
|
|
226
|
+
required_controls: requiredControls,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function record(value) {
|
|
231
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function mergePromptPolicyReport(current, inherited) {
|
|
235
|
+
const registryId = cleanString(inherited.registry_id);
|
|
236
|
+
if (!registryId) return current;
|
|
237
|
+
return {
|
|
238
|
+
registry_id: registryId,
|
|
239
|
+
matched_policy_ids: uniqueStrings(
|
|
240
|
+
inherited.matched_policy_ids,
|
|
241
|
+
current.matched_policy_ids,
|
|
242
|
+
),
|
|
243
|
+
matched_triggers: uniqueStrings(inherited.matched_triggers, current.matched_triggers),
|
|
244
|
+
risk_level: current.risk_level,
|
|
245
|
+
risk_tags: uniqueStrings(inherited.risk_tags, current.risk_tags),
|
|
246
|
+
reasons: uniqueStrings(inherited.reasons, current.reasons),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function uniqueStrings(...values) {
|
|
251
|
+
return [...new Set(values.flatMap((value) => stringArray(value)))];
|
|
104
252
|
}
|
|
105
253
|
|
|
106
254
|
export function newRunId() {
|
|
107
|
-
return `
|
|
255
|
+
return `agentic_loop_${randomUUID()}`;
|
|
108
256
|
}
|
|
109
257
|
|
|
110
258
|
function buildPromptPolicyReport(request, risk) {
|
|
@@ -56,7 +56,8 @@ export function buildIndependentAuditInstruction(charter, attempt) {
|
|
|
56
56
|
[
|
|
57
57
|
"Finish with exactly one line beginning SIMY_AUDIT_JSON: followed by one JSON object.",
|
|
58
58
|
"Required keys: passed, summary, findings.",
|
|
59
|
-
"Each finding must contain code, severity, target, explanation, and repairability.",
|
|
59
|
+
"Each finding candidate must contain passed, code, severity, target, explanation, and repairability.",
|
|
60
|
+
"Only passed=false entries are findings. Omit passing checks, and never report passed=true evidence as a finding.",
|
|
60
61
|
"Use passed=false when a blocker or major finding remains, or when evidence is unavailable.",
|
|
61
62
|
].join("\n"),
|
|
62
63
|
),
|
|
@@ -76,6 +77,7 @@ export function buildIndependentAudit(execution) {
|
|
|
76
77
|
summary: cleanString(execution?.error || result.summary) || "Independent audit did not return valid evidence.",
|
|
77
78
|
findings: [
|
|
78
79
|
{
|
|
80
|
+
passed: false,
|
|
79
81
|
code: "INDEPENDENT_AUDIT_UNAVAILABLE",
|
|
80
82
|
severity: "blocker",
|
|
81
83
|
target: "independent_audit",
|
|
@@ -87,9 +89,10 @@ export function buildIndependentAudit(execution) {
|
|
|
87
89
|
};
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
const
|
|
92
|
+
const evaluations = result.findings
|
|
91
93
|
.filter((item) => item && typeof item === "object")
|
|
92
94
|
.map((item, index) => ({
|
|
95
|
+
passed: item.passed === true ? true : item.passed === false ? false : null,
|
|
93
96
|
code: cleanString(item.code) || `INDEPENDENT_AUDIT_${index + 1}`,
|
|
94
97
|
severity: cleanString(item.severity).toLowerCase() || "major",
|
|
95
98
|
target: cleanString(item.target) || "pull_request",
|
|
@@ -97,10 +100,21 @@ export function buildIndependentAudit(execution) {
|
|
|
97
100
|
repairability: item.repairability === "manual" ? "manual" : "auto",
|
|
98
101
|
auto_fix_hint: cleanString(item.auto_fix_hint) || null,
|
|
99
102
|
}));
|
|
100
|
-
const
|
|
103
|
+
const findings = evaluations.filter((item) => item.passed === false);
|
|
104
|
+
if (result.passed === false && findings.length === 0) {
|
|
105
|
+
findings.push({
|
|
106
|
+
passed: false,
|
|
107
|
+
code: "INDEPENDENT_AUDIT_FAILED_WITHOUT_FINDING",
|
|
108
|
+
severity: "blocker",
|
|
109
|
+
target: "independent_audit",
|
|
110
|
+
explanation: "The independent auditor returned passed=false without an explicit failed finding.",
|
|
111
|
+
repairability: "manual",
|
|
112
|
+
auto_fix_hint: null,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
101
115
|
const requiresHuman = findings.some((item) => item.repairability === "manual");
|
|
102
116
|
return {
|
|
103
|
-
passed: result.passed === true &&
|
|
117
|
+
passed: result.passed === true && findings.length === 0,
|
|
104
118
|
summary: cleanString(result.summary) || "Independent audit completed.",
|
|
105
119
|
findings,
|
|
106
120
|
requires_human: requiresHuman,
|
|
@@ -3,3 +3,4 @@ export { collectPrEvidence } from "./evidence.js";
|
|
|
3
3
|
export { buildIndependentAuditInstruction } from "./independent-audit.js";
|
|
4
4
|
export { recheckPrReadiness, runCodingLoop } from "./loop.js";
|
|
5
5
|
export { mergeTokenUsage, parseStructuredMarker, parseStructuredResult } from "./result.js";
|
|
6
|
+
export { buildRetryFingerprint, evaluateRetryCircuit } from "./retry.js";
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
import { bullets, looksLikeUiTask, section } from "./shared.js";
|
|
2
|
+
import { problemSolvingResultContract } from "./problem-solving.js";
|
|
2
3
|
|
|
3
4
|
export function buildCodingInstruction(
|
|
4
5
|
charter,
|
|
5
|
-
{
|
|
6
|
+
{
|
|
7
|
+
attemptNumber,
|
|
8
|
+
budget = null,
|
|
9
|
+
previousAttempt = null,
|
|
10
|
+
previousFindings = [],
|
|
11
|
+
promptInterventions = [],
|
|
12
|
+
},
|
|
6
13
|
) {
|
|
7
14
|
const sections = [
|
|
8
|
-
section("role", "You are the local coding executor for a SIMY
|
|
15
|
+
section("role", "You are the local coding executor for a SIMY agentic loop."),
|
|
9
16
|
section(
|
|
10
17
|
"requirement_charter",
|
|
11
18
|
[
|
|
12
19
|
`Requirement: ${charter.requirement}`,
|
|
20
|
+
`Original request: ${charter.thread_state.original_request}`,
|
|
21
|
+
`User goal: ${charter.thread_state.user_goal}`,
|
|
13
22
|
`Repository: ${charter.repository}`,
|
|
23
|
+
`Execution target: Your Desktop (${charter.execution_target || "desktop"})`,
|
|
14
24
|
`Required PR base branch: ${charter.base_branch}`,
|
|
15
25
|
`Risk level: ${charter.risk.level}`,
|
|
16
26
|
`Design summary: ${charter.design_review.summary || "not required"}`,
|
|
17
27
|
`Design approved by: ${charter.design_review.approved_by || "not required"}`,
|
|
18
28
|
`Attempt: ${attemptNumber}/${charter.max_attempts}`,
|
|
29
|
+
`Retry budget: ${Math.max(attemptNumber - 1, 0)}/${charter.retry_budget}`,
|
|
30
|
+
`Token budget remaining: ${budget?.tokens_remaining ?? charter.token_budget}/${charter.token_budget}`,
|
|
19
31
|
`Local evidence root: ${charter.ui_evidence_root || "not required"}`,
|
|
20
32
|
].join("\n"),
|
|
21
33
|
),
|
|
@@ -46,6 +58,9 @@ export function buildCodingInstruction(
|
|
|
46
58
|
[
|
|
47
59
|
previousAttempt ? `Previous attempt summary: ${previousAttempt.summary || "missing"}` : "",
|
|
48
60
|
previousAttempt ? `Previous PR: ${previousAttempt.pr_url || "missing"}` : "",
|
|
61
|
+
previousAttempt
|
|
62
|
+
? `Previous strategy: ${previousAttempt.problem_solving?.strategy || "not recorded"}`
|
|
63
|
+
: "",
|
|
49
64
|
"Findings to repair:",
|
|
50
65
|
bullets(
|
|
51
66
|
previousFindings.map(
|
|
@@ -70,6 +85,18 @@ export function buildCodingInstruction(
|
|
|
70
85
|
}
|
|
71
86
|
|
|
72
87
|
sections.push(
|
|
88
|
+
section(
|
|
89
|
+
"problem_solving_protocol",
|
|
90
|
+
[
|
|
91
|
+
"Treat implementation as hypothesis testing: state assumptions, list plausible causes or approaches, inspect discriminating evidence, then choose the smallest strategy supported by that evidence.",
|
|
92
|
+
attemptNumber > 1
|
|
93
|
+
? "This is a retry. Before editing, generate at least eight distinct MECE hypotheses, select a different primary hypothesis or approach, and do not repeat the previous strategy."
|
|
94
|
+
: "For the first attempt, make uncertainty and the selected implementation hypothesis explicit before editing.",
|
|
95
|
+
attemptNumber > 1
|
|
96
|
+
? "Explain exactly what changed from the previous attempt and why the new evidence supports this strategy."
|
|
97
|
+
: "Record the selected hypothesis, evidence checked, and strategy in the structured result.",
|
|
98
|
+
].join("\n"),
|
|
99
|
+
),
|
|
73
100
|
section(
|
|
74
101
|
"execution_contract",
|
|
75
102
|
[
|
|
@@ -84,7 +111,8 @@ export function buildCodingInstruction(
|
|
|
84
111
|
"result_contract",
|
|
85
112
|
[
|
|
86
113
|
"Finish with exactly one line beginning SIMY_RESULT_JSON: followed by one JSON object.",
|
|
87
|
-
"Required keys: outcome_kind, summary, branch_name, commit_sha, commit_message_headline, pr_url, pr_number, pr_title, pr_base_branch, tests_run, tests_passed, ui_evidence_path, unrelated_changes_detected, secret_scan_passed, changed_files, residual_risks.",
|
|
114
|
+
"Required keys: outcome_kind, summary, branch_name, commit_sha, commit_message_headline, pr_url, pr_number, pr_title, pr_base_branch, tests_run, tests_passed, ui_evidence_path, unrelated_changes_detected, secret_scan_passed, changed_files, residual_risks, problem_solving.",
|
|
115
|
+
problemSolvingResultContract(),
|
|
88
116
|
"Use null for unavailable scalar values and [] for unavailable arrays. Do not claim evidence that was not observed.",
|
|
89
117
|
].join("\n"),
|
|
90
118
|
),
|
|
@@ -129,8 +157,16 @@ export function buildPromptInterventions(
|
|
|
129
157
|
rows.push({
|
|
130
158
|
trigger: "repair_focus",
|
|
131
159
|
title: "Repair focus",
|
|
132
|
-
prompt:
|
|
133
|
-
|
|
160
|
+
prompt:
|
|
161
|
+
"Diagnose the reported gate failures with at least eight distinct hypotheses, select a new strategy supported by evidence, and do not repeat the previous approach.",
|
|
162
|
+
evidence_required: [
|
|
163
|
+
"hypotheses",
|
|
164
|
+
"selected_hypothesis_id",
|
|
165
|
+
"evidence_checked",
|
|
166
|
+
"changed_from_previous",
|
|
167
|
+
"fixed_finding_codes",
|
|
168
|
+
"rerun_report",
|
|
169
|
+
],
|
|
134
170
|
});
|
|
135
171
|
}
|
|
136
172
|
if (humanGuidance.trim()) {
|