@lsctech/polaris 0.5.7 → 0.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autoresearch/index.js +30 -1
- package/dist/autoresearch/sol-evaluation-writer.js +135 -0
- package/dist/autoresearch/sol-evidence-normalizer.js +337 -0
- package/dist/autoresearch/sol-recommendations.js +130 -0
- package/dist/autoresearch/sol-report-renderer.js +282 -0
- package/dist/autoresearch/sol-run-health-bridge.js +246 -0
- package/dist/autoresearch/sol-scorecard-calculator.js +865 -0
- package/dist/cli/autoresearch.js +77 -0
- package/dist/cli/medic.js +65 -0
- package/dist/cluster-state/store.js +56 -0
- package/dist/config/defaults.js +3 -0
- package/dist/config/validator.js +141 -0
- package/dist/finalize/artifact-policy.js +2 -0
- package/dist/finalize/github.js +13 -9
- package/dist/finalize/index.js +231 -5
- package/dist/finalize/linear.js +8 -4
- package/dist/finalize/medic-gate.js +42 -0
- package/dist/finalize/steps/08-create-pr.js +2 -2
- package/dist/finalize/steps/11-update-linear.js +2 -2
- package/dist/loop/parent.js +234 -28
- package/dist/loop/worker-packet.js +19 -1
- package/dist/medic/run-health-consult.js +381 -0
- package/dist/medic/treatment-packets.js +169 -0
- package/dist/qc/artifacts.js +27 -0
- package/dist/qc/orchestration.js +3 -2
- package/dist/qc/providers/coderabbit.js +114 -11
- package/dist/qc/repair-loop.js +49 -14
- package/dist/qc/runner.js +10 -2
- package/dist/qc/schemas.js +1 -0
- package/dist/run-health/foreman-symptoms.js +100 -0
- package/dist/run-health/index.js +301 -0
- package/dist/run-health/qc-escalation.js +155 -0
- package/dist/run-health/schema.js +123 -0
- package/dist/types/sol-metrics.js +108 -0
- package/dist/types/sol-scorecard.js +148 -0
- package/package.json +1 -1
package/dist/loop/parent.js
CHANGED
|
@@ -48,6 +48,11 @@ const child_selector_js_1 = require("../runtime/scheduling/child-selector.js");
|
|
|
48
48
|
const index_js_3 = require("../tracker/index.js");
|
|
49
49
|
const lifecycle_transition_js_1 = require("../tracker/lifecycle-transition.js");
|
|
50
50
|
const local_graph_js_1 = require("../tracker/local-graph.js");
|
|
51
|
+
const index_js_4 = require("../run-health/index.js");
|
|
52
|
+
const foreman_symptoms_js_1 = require("../run-health/foreman-symptoms.js");
|
|
53
|
+
const qc_escalation_js_1 = require("../run-health/qc-escalation.js");
|
|
54
|
+
const run_health_consult_js_1 = require("../medic/run-health-consult.js");
|
|
55
|
+
const treatment_packets_js_1 = require("../medic/treatment-packets.js");
|
|
51
56
|
const CLAIM_TTL_MS = 30 * 60 * 1000;
|
|
52
57
|
/**
|
|
53
58
|
* Returns the list of files touched by a git commit, or null when the commit
|
|
@@ -916,11 +921,30 @@ async function runParentLoop(options) {
|
|
|
916
921
|
error: msg,
|
|
917
922
|
timestamp: new Date().toISOString(),
|
|
918
923
|
});
|
|
924
|
+
(0, foreman_symptoms_js_1.appendForemanSymptom)({
|
|
925
|
+
runId: state.run_id,
|
|
926
|
+
clusterId: state.cluster_id,
|
|
927
|
+
code: "foreman-qc-runtime-failure",
|
|
928
|
+
message: `QC run at completed-cluster trigger threw a runtime error: ${msg}`,
|
|
929
|
+
evidenceRefs: [telemetryFile],
|
|
930
|
+
repoRoot,
|
|
931
|
+
config,
|
|
932
|
+
});
|
|
919
933
|
// Non-fatal: proceed to cluster-complete without repair loop.
|
|
920
934
|
initialQcResult = null;
|
|
921
935
|
}
|
|
922
936
|
const hasFindings = initialQcResult !== null &&
|
|
923
937
|
initialQcResult.results.some((r) => r.findings.length > 0 && r.status !== "passed" && r.status !== "skipped");
|
|
938
|
+
// Append QC escalation symptoms for initial findings (blocking / parse failures / etc.)
|
|
939
|
+
if (initialQcResult !== null && initialQcResult.results.length > 0) {
|
|
940
|
+
(0, qc_escalation_js_1.appendQcEscalationSymptoms)({
|
|
941
|
+
runId: state.run_id,
|
|
942
|
+
clusterId: state.cluster_id,
|
|
943
|
+
qcResults: initialQcResult.results,
|
|
944
|
+
afterRepair: false,
|
|
945
|
+
repoRoot,
|
|
946
|
+
});
|
|
947
|
+
}
|
|
924
948
|
if (initialQcResult !== null && hasFindings) {
|
|
925
949
|
const maxRepairRounds = config.qc.maxRepairRounds ?? repair_loop_js_1.DEFAULT_MAX_REPAIR_ROUNDS;
|
|
926
950
|
const priorLoopState = state.qc_repair_loop ?? null;
|
|
@@ -1021,6 +1045,22 @@ async function runParentLoop(options) {
|
|
|
1021
1045
|
summary: repairLoopResult.summary,
|
|
1022
1046
|
timestamp: new Date().toISOString(),
|
|
1023
1047
|
});
|
|
1048
|
+
// Append QC escalation symptoms for non-passing outcomes and post-repair findings.
|
|
1049
|
+
(0, qc_escalation_js_1.appendRepairLoopOutcomeSymptom)({
|
|
1050
|
+
runId: state.run_id,
|
|
1051
|
+
clusterId: state.cluster_id,
|
|
1052
|
+
repairResult: repairLoopResult,
|
|
1053
|
+
repoRoot,
|
|
1054
|
+
});
|
|
1055
|
+
if (repairLoopResult.final_qc_results.length > 0 && repairLoopResult.rounds_completed > 0) {
|
|
1056
|
+
(0, qc_escalation_js_1.appendQcEscalationSymptoms)({
|
|
1057
|
+
runId: state.run_id,
|
|
1058
|
+
clusterId: state.cluster_id,
|
|
1059
|
+
qcResults: repairLoopResult.final_qc_results,
|
|
1060
|
+
afterRepair: true,
|
|
1061
|
+
repoRoot,
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1024
1064
|
}
|
|
1025
1065
|
catch (err) {
|
|
1026
1066
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1030,11 +1070,90 @@ async function runParentLoop(options) {
|
|
|
1030
1070
|
error: msg,
|
|
1031
1071
|
timestamp: new Date().toISOString(),
|
|
1032
1072
|
});
|
|
1073
|
+
(0, foreman_symptoms_js_1.appendForemanSymptom)({
|
|
1074
|
+
runId: state.run_id,
|
|
1075
|
+
clusterId: state.cluster_id,
|
|
1076
|
+
code: "foreman-qc-runtime-failure",
|
|
1077
|
+
message: `QC repair loop threw a runtime error: ${msg}`,
|
|
1078
|
+
evidenceRefs: [telemetryFile],
|
|
1079
|
+
repoRoot,
|
|
1080
|
+
config,
|
|
1081
|
+
});
|
|
1033
1082
|
// Non-fatal: proceed to cluster-complete.
|
|
1034
1083
|
}
|
|
1035
1084
|
}
|
|
1036
1085
|
}
|
|
1037
1086
|
// ── End QC repair loop ─────────────────────────────────────────────────
|
|
1087
|
+
// ── Run-health Medic consult ────────────────────────────────────────────
|
|
1088
|
+
// If the run recorded health symptoms and no Medic decision exists yet,
|
|
1089
|
+
// dispatch Medic to diagnose and optionally emit bounded treatment packets.
|
|
1090
|
+
if (!dryRun) {
|
|
1091
|
+
const runHealthReport = (0, index_js_4.readRunHealthReport)(state.run_id, repoRoot);
|
|
1092
|
+
if (runHealthReport && !(0, index_js_4.isMedicGateSatisfied)(runHealthReport)) {
|
|
1093
|
+
const maxTreatmentRounds = config.qc?.maxRepairRounds ?? repair_loop_js_1.DEFAULT_MAX_REPAIR_ROUNDS;
|
|
1094
|
+
const medicDispatchId = (0, node_crypto_1.randomUUID)();
|
|
1095
|
+
const medicResultPath = (0, node_path_1.join)(repoRoot, ".polaris", "clusters", state.cluster_id, "results", `medic-run-health-${medicDispatchId}.json`);
|
|
1096
|
+
const medicPacket = {
|
|
1097
|
+
role: "medic-run-health",
|
|
1098
|
+
run_id: state.run_id,
|
|
1099
|
+
dispatch_id: medicDispatchId,
|
|
1100
|
+
cluster_id: state.cluster_id,
|
|
1101
|
+
run_health_report_path: (0, index_js_4.getRunHealthReportPath)(state.run_id, repoRoot),
|
|
1102
|
+
qc_artifact_refs: Array.from(new Set([
|
|
1103
|
+
...runHealthReport.evidence_refs,
|
|
1104
|
+
...runHealthReport.symptoms.flatMap((s) => s.evidence_refs),
|
|
1105
|
+
])),
|
|
1106
|
+
telemetry_path: telemetryFile,
|
|
1107
|
+
cluster_state_path: (0, node_path_1.join)(repoRoot, ".polaris", "clusters", state.cluster_id, "state.json"),
|
|
1108
|
+
policy_limits: { max_treatment_rounds: maxTreatmentRounds },
|
|
1109
|
+
result_path: medicResultPath,
|
|
1110
|
+
allowed_write_paths: [
|
|
1111
|
+
"smartdocs/medic/charts",
|
|
1112
|
+
".polaris/runs",
|
|
1113
|
+
".polaris/clusters",
|
|
1114
|
+
".taskchain_artifacts",
|
|
1115
|
+
],
|
|
1116
|
+
prohibited_write_paths: [],
|
|
1117
|
+
};
|
|
1118
|
+
try {
|
|
1119
|
+
await (0, run_health_consult_js_1.runMedicRunHealthConsult)({
|
|
1120
|
+
packet: medicPacket,
|
|
1121
|
+
repoRoot,
|
|
1122
|
+
stateFile,
|
|
1123
|
+
telemetryFile,
|
|
1124
|
+
branch: state.branch ?? getCurrentBranch(repoRoot),
|
|
1125
|
+
validationCommands: ["npm run build", "npm test"],
|
|
1126
|
+
maxConcurrentWorkers,
|
|
1127
|
+
dryRun,
|
|
1128
|
+
dispatchTreatmentWorkerFn: (input) => (0, treatment_packets_js_1.dispatchTreatmentWorker)({
|
|
1129
|
+
...input,
|
|
1130
|
+
repoRoot,
|
|
1131
|
+
dispatch: (workerPacket) => adapter.dispatch(workerPacket, { provider: providerName }),
|
|
1132
|
+
}),
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
catch (err) {
|
|
1136
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1137
|
+
appendTelemetry(telemetryFile, {
|
|
1138
|
+
event: "medic-run-health-consult-error",
|
|
1139
|
+
run_id: state.run_id,
|
|
1140
|
+
cluster_id: state.cluster_id,
|
|
1141
|
+
error: msg,
|
|
1142
|
+
timestamp: new Date().toISOString(),
|
|
1143
|
+
});
|
|
1144
|
+
(0, foreman_symptoms_js_1.appendForemanSymptom)({
|
|
1145
|
+
runId: state.run_id,
|
|
1146
|
+
clusterId: state.cluster_id,
|
|
1147
|
+
code: "foreman-medic-runtime-failure",
|
|
1148
|
+
message: `Medic run-health consult threw a runtime error: ${msg}`,
|
|
1149
|
+
evidenceRefs: [telemetryFile],
|
|
1150
|
+
repoRoot,
|
|
1151
|
+
config,
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
// ── End run-health Medic consult ───────────────────────────────────────
|
|
1038
1157
|
// All children completed — write final state and halt
|
|
1039
1158
|
if (!dryRun) {
|
|
1040
1159
|
logStatus(notificationFormat, "COMPLETE");
|
|
@@ -1143,6 +1262,15 @@ async function runParentLoop(options) {
|
|
|
1143
1262
|
reason: msg,
|
|
1144
1263
|
timestamp: new Date().toISOString(),
|
|
1145
1264
|
});
|
|
1265
|
+
(0, foreman_symptoms_js_1.appendForemanSymptom)({
|
|
1266
|
+
runId: state.run_id,
|
|
1267
|
+
clusterId: state.cluster_id,
|
|
1268
|
+
code: "foreman-dispatch-boundary-repair",
|
|
1269
|
+
message: `Dispatch boundary violation: ${msg}`,
|
|
1270
|
+
evidenceRefs: [telemetryFile],
|
|
1271
|
+
repoRoot,
|
|
1272
|
+
config,
|
|
1273
|
+
});
|
|
1146
1274
|
}
|
|
1147
1275
|
return {
|
|
1148
1276
|
haltReason: 'worker-error',
|
|
@@ -1502,6 +1630,43 @@ async function runParentLoop(options) {
|
|
|
1502
1630
|
sealedResult['status'] = 'failed';
|
|
1503
1631
|
}
|
|
1504
1632
|
finalWorkerSummary = sealedResult;
|
|
1633
|
+
// ── Ingest worker-reported run-health symptoms ────────────────────────
|
|
1634
|
+
// Only process when worker reports at least one symptom. Errors are
|
|
1635
|
+
// logged to telemetry but never block the run — symptom reporting is
|
|
1636
|
+
// advisory, not a gate.
|
|
1637
|
+
const rawSymptoms = sealedResult['run_health_symptoms'];
|
|
1638
|
+
if (!dryRun && Array.isArray(rawSymptoms) && rawSymptoms.length > 0) {
|
|
1639
|
+
const dispatchRecord = state.open_children_meta?.[nextChild]?.dispatch_record;
|
|
1640
|
+
try {
|
|
1641
|
+
(0, index_js_4.upsertWorkerSymptoms)({
|
|
1642
|
+
runId: state.run_id,
|
|
1643
|
+
clusterId: state.cluster_id,
|
|
1644
|
+
childId: nextChild,
|
|
1645
|
+
workerId: dispatchRecord?.worker_id,
|
|
1646
|
+
provider: dispatchRecord?.provider,
|
|
1647
|
+
symptoms: rawSymptoms,
|
|
1648
|
+
repoRoot,
|
|
1649
|
+
});
|
|
1650
|
+
appendTelemetry(telemetryFile, {
|
|
1651
|
+
event: "run-health-symptoms-ingested",
|
|
1652
|
+
run_id: state.run_id,
|
|
1653
|
+
child_id: nextChild,
|
|
1654
|
+
symptom_count: rawSymptoms.length,
|
|
1655
|
+
timestamp: new Date().toISOString(),
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1658
|
+
catch (symptomErr) {
|
|
1659
|
+
const symptomMsg = symptomErr instanceof Error ? symptomErr.message : String(symptomErr);
|
|
1660
|
+
appendTelemetry(telemetryFile, {
|
|
1661
|
+
event: "run-health-ingest-error",
|
|
1662
|
+
run_id: state.run_id,
|
|
1663
|
+
child_id: nextChild,
|
|
1664
|
+
error: symptomMsg,
|
|
1665
|
+
timestamp: new Date().toISOString(),
|
|
1666
|
+
});
|
|
1667
|
+
// ponytail: consider surfacing ingest errors to operator via logStatus in a future pass
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1505
1670
|
}
|
|
1506
1671
|
catch (error) {
|
|
1507
1672
|
const msg = error instanceof Error ? error.message : String(error);
|
|
@@ -1514,6 +1679,15 @@ async function runParentLoop(options) {
|
|
|
1514
1679
|
result_file: packet.result_file_contract.result_file,
|
|
1515
1680
|
timestamp: new Date().toISOString(),
|
|
1516
1681
|
});
|
|
1682
|
+
(0, foreman_symptoms_js_1.appendForemanSymptom)({
|
|
1683
|
+
runId: state.run_id,
|
|
1684
|
+
clusterId: state.cluster_id,
|
|
1685
|
+
code: "foreman-packet-repair",
|
|
1686
|
+
message: `Failed to read sealed result file for ${nextChild}: ${msg}`,
|
|
1687
|
+
evidenceRefs: [telemetryFile],
|
|
1688
|
+
repoRoot,
|
|
1689
|
+
config,
|
|
1690
|
+
});
|
|
1517
1691
|
}
|
|
1518
1692
|
return {
|
|
1519
1693
|
haltReason: 'worker-error',
|
|
@@ -1540,6 +1714,15 @@ async function runParentLoop(options) {
|
|
|
1540
1714
|
error: errMsg,
|
|
1541
1715
|
timestamp: new Date().toISOString(),
|
|
1542
1716
|
});
|
|
1717
|
+
(0, foreman_symptoms_js_1.appendForemanSymptom)({
|
|
1718
|
+
runId: state.run_id,
|
|
1719
|
+
clusterId: state.cluster_id,
|
|
1720
|
+
code: "foreman-wrong-run-telemetry",
|
|
1721
|
+
message: errMsg,
|
|
1722
|
+
evidenceRefs: [telemetryFile],
|
|
1723
|
+
repoRoot,
|
|
1724
|
+
config,
|
|
1725
|
+
});
|
|
1543
1726
|
}
|
|
1544
1727
|
return {
|
|
1545
1728
|
haltReason: 'worker-error',
|
|
@@ -1709,6 +1892,15 @@ async function runParentLoop(options) {
|
|
|
1709
1892
|
error: errMsg,
|
|
1710
1893
|
timestamp: new Date().toISOString(),
|
|
1711
1894
|
});
|
|
1895
|
+
(0, foreman_symptoms_js_1.appendForemanSymptom)({
|
|
1896
|
+
runId: state.run_id,
|
|
1897
|
+
clusterId: state.cluster_id,
|
|
1898
|
+
code: "foreman-state-repair",
|
|
1899
|
+
message: `State file validation failed after worker execution; using pre-dispatch fallback: ${errMsg}`,
|
|
1900
|
+
evidenceRefs: [telemetryFile],
|
|
1901
|
+
repoRoot,
|
|
1902
|
+
config,
|
|
1903
|
+
});
|
|
1712
1904
|
state = stateBeforeDispatch;
|
|
1713
1905
|
}
|
|
1714
1906
|
else if (!dryRun) {
|
|
@@ -1747,6 +1939,15 @@ async function runParentLoop(options) {
|
|
|
1747
1939
|
error: errMsg,
|
|
1748
1940
|
timestamp: new Date().toISOString(),
|
|
1749
1941
|
});
|
|
1942
|
+
(0, foreman_symptoms_js_1.appendForemanSymptom)({
|
|
1943
|
+
runId: state.run_id,
|
|
1944
|
+
clusterId: state.cluster_id,
|
|
1945
|
+
code: "foreman-state-repair",
|
|
1946
|
+
message: `State reload threw after worker execution; using pre-dispatch fallback: ${errMsg}`,
|
|
1947
|
+
evidenceRefs: [telemetryFile],
|
|
1948
|
+
repoRoot,
|
|
1949
|
+
config,
|
|
1950
|
+
});
|
|
1750
1951
|
state = stateBeforeDispatch;
|
|
1751
1952
|
}
|
|
1752
1953
|
else if (!dryRun) {
|
|
@@ -2031,35 +2232,40 @@ async function runParentLoop(options) {
|
|
|
2031
2232
|
};
|
|
2032
2233
|
}
|
|
2033
2234
|
// ── Step 05 (post-dispatch): Re-check budget before next iteration ───
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2235
|
+
// Skip when open_children is empty: the cluster is complete and the
|
|
2236
|
+
// top-of-loop nextChild === null path handles cluster-complete and QC
|
|
2237
|
+
// repair-loop. Halting here would bypass QC repair on final-child completion.
|
|
2238
|
+
if (state.open_children.length > 0) {
|
|
2239
|
+
const postBudgetCheck = (0, budget_js_1.checkBudget)({
|
|
2240
|
+
childrenCompleted: state.context_budget.children_completed,
|
|
2241
|
+
lastChildStatus: workerStatus,
|
|
2242
|
+
policy: budgetPolicy,
|
|
2243
|
+
});
|
|
2244
|
+
if (postBudgetCheck.status === 'exhausted') {
|
|
2245
|
+
const nextPending = state.open_children[0] ?? null;
|
|
2246
|
+
if (!dryRun) {
|
|
2247
|
+
(0, checkpoint_js_1.writeStateAtomic)(stateFile, {
|
|
2248
|
+
...state,
|
|
2249
|
+
status: "budget-exhausted",
|
|
2250
|
+
step_cursor: "budget-check",
|
|
2251
|
+
next_open_child: nextPending,
|
|
2252
|
+
});
|
|
2253
|
+
appendTelemetry(telemetryFile, {
|
|
2254
|
+
event: "budget-exhausted",
|
|
2255
|
+
run_id: state.run_id,
|
|
2256
|
+
children_completed: state.context_budget.children_completed,
|
|
2257
|
+
next_child: nextPending,
|
|
2258
|
+
reason: postBudgetCheck.reason,
|
|
2259
|
+
timestamp: new Date().toISOString(),
|
|
2260
|
+
});
|
|
2261
|
+
}
|
|
2262
|
+
return {
|
|
2263
|
+
haltReason: 'budget-exhausted',
|
|
2264
|
+
childrenDispatched,
|
|
2265
|
+
haltingChild: nextPending ?? undefined,
|
|
2266
|
+
message: postBudgetCheck.reason,
|
|
2267
|
+
};
|
|
2056
2268
|
}
|
|
2057
|
-
return {
|
|
2058
|
-
haltReason: 'budget-exhausted',
|
|
2059
|
-
childrenDispatched,
|
|
2060
|
-
haltingChild: nextPending ?? undefined,
|
|
2061
|
-
message: postBudgetCheck.reason,
|
|
2062
|
-
};
|
|
2063
2269
|
}
|
|
2064
2270
|
// ── Step 06: CONTINUE (back to step 02) ─────────────────────────────
|
|
2065
2271
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* accept BootstrapPacket transparently accept WorkerPacket.
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.REPAIR_RETURN_CONTRACT = exports.STARTUP_RETURN_CONTRACT = exports.PREFLIGHT_RETURN_CONTRACT = exports.WORKER_PROHIBITED_WRITE_PATHS = exports.FINALIZE_RETURN_CONTRACT = exports.IMPL_RETURN_CONTRACT = void 0;
|
|
14
|
+
exports.REPAIR_RETURN_CONTRACT = exports.STARTUP_RETURN_CONTRACT = exports.PREFLIGHT_RETURN_CONTRACT = exports.WORKER_SYMPTOM_CATEGORIES = exports.WORKER_PROHIBITED_WRITE_PATHS = exports.FINALIZE_RETURN_CONTRACT = exports.IMPL_RETURN_CONTRACT = void 0;
|
|
15
15
|
exports.roleContextForWorkerRole = roleContextForWorkerRole;
|
|
16
16
|
exports.isWorkerPacket = isWorkerPacket;
|
|
17
17
|
exports.getWorkerCommitPolicy = getWorkerCommitPolicy;
|
|
@@ -130,6 +130,21 @@ exports.WORKER_PROHIBITED_WRITE_PATHS = [
|
|
|
130
130
|
".polaris/runs/",
|
|
131
131
|
"**/telemetry.jsonl",
|
|
132
132
|
];
|
|
133
|
+
// ── Worker symptom reporting ──────────────────────────────────────────────────
|
|
134
|
+
/**
|
|
135
|
+
* Canonical symptom categories workers may use in their sealed result.
|
|
136
|
+
* Workers observe and report — they do NOT diagnose root cause.
|
|
137
|
+
*
|
|
138
|
+
* Include run_health_symptoms in the sealed result only when at least one
|
|
139
|
+
* symptom occurred. When no symptoms occurred, omit the field entirely.
|
|
140
|
+
*/
|
|
141
|
+
exports.WORKER_SYMPTOM_CATEGORIES = [
|
|
142
|
+
"worker-blocked", // Could not proceed (missing info, approval needed, out-of-scope)
|
|
143
|
+
"validation-failed", // Build / test / lint validation commands failed
|
|
144
|
+
"repeated-rework", // Same fix attempted multiple times without success
|
|
145
|
+
"unclear-requirements", // Requirements are contradictory or too ambiguous to act on
|
|
146
|
+
"unusual-assumption", // Had to assume something outside normal scope to proceed
|
|
147
|
+
];
|
|
133
148
|
function getWorkerCommitPolicy(packet) {
|
|
134
149
|
return {
|
|
135
150
|
allowedScope: [...packet.instructions.allowed_scope],
|
|
@@ -255,6 +270,9 @@ function compileImplPacket(input) {
|
|
|
255
270
|
`Create exactly ONE git commit: [${input.childId}] ${childTitle}.`,
|
|
256
271
|
`Do NOT modify open_children or completed_children in ${input.stateFile}. The parent runtime (loop continue) owns that state transition.`,
|
|
257
272
|
`Append a telemetry event to ${input.telemetryFile}.`,
|
|
273
|
+
`If you encountered any struggle signals during execution, include a "run_health_symptoms" array in your sealed result. ` +
|
|
274
|
+
`Use one of these categories: ${exports.WORKER_SYMPTOM_CATEGORIES.join(', ')}. ` +
|
|
275
|
+
`Report what you observed — do NOT diagnose root cause. Omit the field if no symptoms occurred.`,
|
|
258
276
|
`Write compact return JSON to stdout (fields: ${exports.IMPL_RETURN_CONTRACT.join(', ')}). next_recommended_action MUST be exactly "continue" on success, "stop" on unresolvable blocker, or "investigate" if manual review is needed.`,
|
|
259
277
|
`TERMINATE SESSION IMMEDIATELY. Do not select or execute the next child.`,
|
|
260
278
|
];
|