@synkro-sh/cli 1.4.82 → 1.4.84
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/bootstrap.js +49 -51
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -1991,7 +1991,7 @@ async function main() {
|
|
|
1991
1991
|
const tagStr = tag(rt, config);
|
|
1992
1992
|
|
|
1993
1993
|
if (config.silent) {
|
|
1994
|
-
outputJson({ systemMessage: tagStr + ' editGuard
|
|
1994
|
+
outputJson({ systemMessage: tagStr + ' editGuard \u2192 skipped (silent mode)' });
|
|
1995
1995
|
return;
|
|
1996
1996
|
}
|
|
1997
1997
|
|
|
@@ -2013,7 +2013,7 @@ async function main() {
|
|
|
2013
2013
|
try {
|
|
2014
2014
|
gradeResp = await localGrade('edit', graderPrompt);
|
|
2015
2015
|
} catch {
|
|
2016
|
-
outputJson({ systemMessage: tagStr + ' editGuard ' + fileShort + '
|
|
2016
|
+
outputJson({ systemMessage: tagStr + ' editGuard ' + fileShort + ' \u2192 local grader unavailable, skipped' });
|
|
2017
2017
|
return;
|
|
2018
2018
|
}
|
|
2019
2019
|
|
|
@@ -2034,7 +2034,7 @@ async function main() {
|
|
|
2034
2034
|
ccModel: transcript.ccModel,
|
|
2035
2035
|
});
|
|
2036
2036
|
outputJson({
|
|
2037
|
-
systemMessage: tagStr + ' editGuard ' + fileShort + '
|
|
2037
|
+
systemMessage: tagStr + ' editGuard ' + fileShort + ' \u2192 blocked: ' + guardReason,
|
|
2038
2038
|
hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: denyReason, additionalContext: denyReason },
|
|
2039
2039
|
});
|
|
2040
2040
|
return;
|
|
@@ -2047,7 +2047,7 @@ async function main() {
|
|
|
2047
2047
|
rulesChecked: config.rules, violatedRules,
|
|
2048
2048
|
ccModel: transcript.ccModel,
|
|
2049
2049
|
});
|
|
2050
|
-
outputJson({ systemMessage: tagStr + ' editGuard ' + fileShort + '
|
|
2050
|
+
outputJson({ systemMessage: tagStr + ' editGuard ' + fileShort + ' \u2192 warning: ' + guardReason, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: 'Synkro local edit judge (audit). ' + guardReason } });
|
|
2051
2051
|
return;
|
|
2052
2052
|
}
|
|
2053
2053
|
|
|
@@ -2058,7 +2058,7 @@ async function main() {
|
|
|
2058
2058
|
rulesChecked: config.rules, violatedRules: [],
|
|
2059
2059
|
ccModel: transcript.ccModel,
|
|
2060
2060
|
});
|
|
2061
|
-
const passLine = tagStr + ' editGuard ' + fileShort + '
|
|
2061
|
+
const passLine = tagStr + ' editGuard ' + fileShort + ' \u2192 pass: ' + (verdict.reason || 'no policy violations detected');
|
|
2062
2062
|
outputJson({ systemMessage: passLine, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: 'Synkro local edit judge. ' + (verdict.reason || 'no policy violations detected') } });
|
|
2063
2063
|
return;
|
|
2064
2064
|
}
|
|
@@ -2093,13 +2093,13 @@ async function main() {
|
|
|
2093
2093
|
const resp = await postWithRetry(GATEWAY_URL + '/api/v1/hook/judge', body, jwt, 8000);
|
|
2094
2094
|
|
|
2095
2095
|
if (!resp) {
|
|
2096
|
-
log('editGuard ' + fileShort + '
|
|
2096
|
+
log('editGuard ' + fileShort + ' \u2192 error (timeout)');
|
|
2097
2097
|
outputEmpty();
|
|
2098
2098
|
return;
|
|
2099
2099
|
}
|
|
2100
2100
|
|
|
2101
2101
|
if (!resp.hook_response || typeof resp.hook_response !== 'object') {
|
|
2102
|
-
log('editGuard ' + fileShort + '
|
|
2102
|
+
log('editGuard ' + fileShort + ' \u2192 pass (no hook_response)');
|
|
2103
2103
|
outputEmpty();
|
|
2104
2104
|
return;
|
|
2105
2105
|
}
|
|
@@ -2108,7 +2108,7 @@ async function main() {
|
|
|
2108
2108
|
const decision = hookResp?.hookSpecificOutput?.permissionDecision;
|
|
2109
2109
|
|
|
2110
2110
|
if (decision === 'deny' || decision === 'ask') {
|
|
2111
|
-
log('editGuard ' + fileShort + '
|
|
2111
|
+
log('editGuard ' + fileShort + ' \u2192 BLOCKED');
|
|
2112
2112
|
// Strip permissionDecision \u2014 we use systemMessage only
|
|
2113
2113
|
const cleaned = { ...hookResp };
|
|
2114
2114
|
if (cleaned.hookSpecificOutput) {
|
|
@@ -2119,7 +2119,7 @@ async function main() {
|
|
|
2119
2119
|
outputJson(cleaned);
|
|
2120
2120
|
} else {
|
|
2121
2121
|
const reason = hookResp.reason || '';
|
|
2122
|
-
log('editGuard ' + fileShort + '
|
|
2122
|
+
log('editGuard ' + fileShort + ' \u2192 pass' + (reason ? ': ' + reason : ''));
|
|
2123
2123
|
outputJson(hookResp);
|
|
2124
2124
|
}
|
|
2125
2125
|
} catch (err) {
|
|
@@ -2594,7 +2594,7 @@ async function main() {
|
|
|
2594
2594
|
const rt = await route(config);
|
|
2595
2595
|
|
|
2596
2596
|
if (config.silent) {
|
|
2597
|
-
outputJson({ systemMessage: '[synkro:' + rt + ':cveScan] ' + fileShort + '
|
|
2597
|
+
outputJson({ systemMessage: '[synkro:' + rt + ':cveScan] ' + fileShort + ' \u2192 skipped (silent mode)' });
|
|
2598
2598
|
return;
|
|
2599
2599
|
}
|
|
2600
2600
|
|
|
@@ -2603,7 +2603,7 @@ async function main() {
|
|
|
2603
2603
|
// Reconstruct proposed content
|
|
2604
2604
|
const proposed = reconstructContent(toolName, toolInput, filePath, cwd);
|
|
2605
2605
|
if (!proposed) {
|
|
2606
|
-
outputJson({ systemMessage: cveTag + ' ' + fileShort + '
|
|
2606
|
+
outputJson({ systemMessage: cveTag + ' ' + fileShort + ' \u2192 skip (no content)' });
|
|
2607
2607
|
return;
|
|
2608
2608
|
}
|
|
2609
2609
|
|
|
@@ -2632,7 +2632,7 @@ async function main() {
|
|
|
2632
2632
|
});
|
|
2633
2633
|
cveResp = await resp.json();
|
|
2634
2634
|
} catch {
|
|
2635
|
-
outputJson({ systemMessage: cveTag + ' ' + fileShort + '
|
|
2635
|
+
outputJson({ systemMessage: cveTag + ' ' + fileShort + ' \u2192 error (timeout)' });
|
|
2636
2636
|
return;
|
|
2637
2637
|
}
|
|
2638
2638
|
|
|
@@ -2669,7 +2669,7 @@ async function main() {
|
|
|
2669
2669
|
const top3 = findings.slice(0, 3).map(formatFinding).join('; ');
|
|
2670
2670
|
const count = findings.length;
|
|
2671
2671
|
const label = count === 1 ? 'advisory' : 'advisories';
|
|
2672
|
-
const cveMsg = cveTag + ' ' + fileShort + '
|
|
2672
|
+
const cveMsg = cveTag + ' ' + fileShort + ' \u2192 ' + count + ' ' + label;
|
|
2673
2673
|
const ctx = 'CVE: ' + top3 + '\\nFix all issues before retrying. Do NOT ask the user to make the edit manually \u2014 upgrade the vulnerable dependencies yourself.';
|
|
2674
2674
|
|
|
2675
2675
|
const cveIds = findings.slice(0, 10).map((f: any) =>
|
|
@@ -2689,7 +2689,7 @@ async function main() {
|
|
|
2689
2689
|
return;
|
|
2690
2690
|
}
|
|
2691
2691
|
|
|
2692
|
-
outputJson({ systemMessage: cveTag + ' ' + fileShort + '
|
|
2692
|
+
outputJson({ systemMessage: cveTag + ' ' + fileShort + ' \u2192 clean' });
|
|
2693
2693
|
} catch (err) {
|
|
2694
2694
|
process.stderr.write('[synkro] cveGuard error: ' + String(err) + '\\n');
|
|
2695
2695
|
outputEmpty();
|
|
@@ -2698,7 +2698,7 @@ async function main() {
|
|
|
2698
2698
|
|
|
2699
2699
|
main();
|
|
2700
2700
|
`;
|
|
2701
|
-
BASH_JUDGE_TS = `#!/usr/bin/env bun
|
|
2701
|
+
BASH_JUDGE_TS = String.raw`#!/usr/bin/env bun
|
|
2702
2702
|
import process from 'node:process';
|
|
2703
2703
|
import {
|
|
2704
2704
|
loadJwt, ensureFreshJwt, detectRepo, loadConfig, route, tag, localGrade,
|
|
@@ -2751,17 +2751,17 @@ async function main() {
|
|
|
2751
2751
|
if (!jwt) { outputEmpty(); return; }
|
|
2752
2752
|
jwt = await ensureFreshJwt(jwt);
|
|
2753
2753
|
|
|
2754
|
-
//
|
|
2754
|
+
// ─── Install protection: server-side pkg-scan (CVE + typosquat + tarball + reputation) ───
|
|
2755
2755
|
let installScanMsg = '';
|
|
2756
2756
|
if (toolName === 'Bash') {
|
|
2757
2757
|
const pkgInstallMatch = command.match(
|
|
2758
|
-
/^(
|
|
2758
|
+
/^(?:.*&&\s*|.*;\s*)?(?:npm\s+(?:install|i|add)|pnpm\s+(?:add|install|i)|yarn\s+add|bun\s+(?:add|install|i)|(?:uv\s+)?pip3?\s+install|go\s+get|cargo\s+add|gem\s+install|composer\s+require)\s+([^|;&><]+)/
|
|
2759
2759
|
);
|
|
2760
|
-
const isPip = /(?:
|
|
2760
|
+
const isPip = /(?:uv\s+)?pip3?\s+install/.test(command);
|
|
2761
2761
|
if (pkgInstallMatch) {
|
|
2762
2762
|
const rawArgs = pkgInstallMatch[1];
|
|
2763
2763
|
const packages: Array<{ name: string; version: string; ecosystem: string }> = [];
|
|
2764
|
-
const tokens = rawArgs.split(
|
|
2764
|
+
const tokens = rawArgs.split(/\s+/);
|
|
2765
2765
|
let skipNext = false;
|
|
2766
2766
|
for (const token of tokens) {
|
|
2767
2767
|
if (skipNext) { skipNext = false; continue; }
|
|
@@ -2803,11 +2803,9 @@ async function main() {
|
|
|
2803
2803
|
const blockSignals = pkgResults
|
|
2804
2804
|
.flatMap((p: any) => (p.signals || []).filter((s: any) => s.severity === 'critical' || s.severity === 'high'))
|
|
2805
2805
|
.slice(0, 5);
|
|
2806
|
-
const scanMsg = '[synkro:installScan] ' + cmdShort + '
|
|
2807
|
-
const details = blockSignals.map((s: any) => s.detail).join('
|
|
2808
|
-
'
|
|
2809
|
-
const ctx = details + '
|
|
2810
|
-
Do NOT install packages with security risks. Use a patched version or a different package.';
|
|
2806
|
+
const scanMsg = '[synkro:installScan] ' + cmdShort + ' → blocked';
|
|
2807
|
+
const details = blockSignals.map((s: any) => s.detail).join('\n');
|
|
2808
|
+
const ctx = details + '\nDo NOT install packages with security risks. Use a patched version or a different package.';
|
|
2811
2809
|
|
|
2812
2810
|
const config = await loadConfig(jwt);
|
|
2813
2811
|
for (const p of pkgResults) {
|
|
@@ -2848,7 +2846,7 @@ Do NOT install packages with security risks. Use a patched version or a differen
|
|
|
2848
2846
|
installScanMsg = '[synkro:installScan] ' + summary;
|
|
2849
2847
|
} else {
|
|
2850
2848
|
const scannedPkgs = packages.map(p => p.name + '@' + p.version).join(', ');
|
|
2851
|
-
installScanMsg = '[synkro:installScan] ' + scannedPkgs + '
|
|
2849
|
+
installScanMsg = '[synkro:installScan] ' + scannedPkgs + ' → clean';
|
|
2852
2850
|
}
|
|
2853
2851
|
} catch (e) {
|
|
2854
2852
|
log('bashGuard pkg-scan failed: ' + String(e));
|
|
@@ -2864,7 +2862,7 @@ Do NOT install packages with security risks. Use a patched version or a differen
|
|
|
2864
2862
|
const tagStr = tag(rt, config);
|
|
2865
2863
|
|
|
2866
2864
|
if (config.silent) {
|
|
2867
|
-
const msg = (installScanMsg ? installScanMsg + '\\n' : '') + tagStr + ' bashGuard
|
|
2865
|
+
const msg = (installScanMsg ? installScanMsg + '\\n' : '') + tagStr + ' bashGuard → skipped (silent mode)';
|
|
2868
2866
|
outputJson({ systemMessage: msg, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: msg } });
|
|
2869
2867
|
return;
|
|
2870
2868
|
}
|
|
@@ -2883,7 +2881,7 @@ Do NOT install packages with security risks. Use a patched version or a differen
|
|
|
2883
2881
|
try {
|
|
2884
2882
|
gradeResp = await localGrade('bash', graderPrompt);
|
|
2885
2883
|
} catch {
|
|
2886
|
-
outputJson({ systemMessage: tagStr + ' bashGuard
|
|
2884
|
+
outputJson({ systemMessage: tagStr + ' bashGuard → local grader unavailable, skipped' });
|
|
2887
2885
|
return;
|
|
2888
2886
|
}
|
|
2889
2887
|
|
|
@@ -2895,7 +2893,7 @@ Do NOT install packages with security risks. Use a patched version or a differen
|
|
|
2895
2893
|
const guardReason = (verdict.ruleId ? '(' + verdict.ruleId + ') ' : '') + (verdict.reason || 'policy violation');
|
|
2896
2894
|
|
|
2897
2895
|
if (mode === 'audit') {
|
|
2898
|
-
const reason = tagStr + ' bashGuard
|
|
2896
|
+
const reason = tagStr + ' bashGuard → warning' + (verdict.ruleId ? ' (' + verdict.ruleId + ')' : '') + ': ' + (verdict.reason || 'policy violation');
|
|
2899
2897
|
const combined = (installScanMsg ? installScanMsg + '\\n' : '') + reason;
|
|
2900
2898
|
outputJson({ systemMessage: combined, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: combined } });
|
|
2901
2899
|
dispatchCapture(jwt, 'bash', 'warning', verdict.severity || 'medium', verdict.category || 'security',
|
|
@@ -2904,7 +2902,7 @@ Do NOT install packages with security risks. Use a patched version or a differen
|
|
|
2904
2902
|
recentUserMessages: transcript.recentUserMessages, ccModel: transcript.ccModel,
|
|
2905
2903
|
});
|
|
2906
2904
|
} else {
|
|
2907
|
-
const reason = tagStr + ' bashGuard
|
|
2905
|
+
const reason = tagStr + ' bashGuard → blocked' + (verdict.ruleId ? ' (' + verdict.ruleId + ')' : '') + ': ' + (verdict.reason || 'policy violation') + '. Ask the user for explicit consent before retrying.';
|
|
2908
2906
|
const combined = (installScanMsg ? installScanMsg + '\\n' : '') + reason;
|
|
2909
2907
|
outputJson({
|
|
2910
2908
|
systemMessage: combined,
|
|
@@ -2917,7 +2915,7 @@ Do NOT install packages with security risks. Use a patched version or a differen
|
|
|
2917
2915
|
});
|
|
2918
2916
|
}
|
|
2919
2917
|
} else {
|
|
2920
|
-
const reason = tagStr + ' bashGuard
|
|
2918
|
+
const reason = tagStr + ' bashGuard → pass: ' + (verdict.reason || 'no policy violations detected');
|
|
2921
2919
|
const combined = (installScanMsg ? installScanMsg + '\\n' : '') + reason;
|
|
2922
2920
|
outputJson({ systemMessage: combined, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: combined } });
|
|
2923
2921
|
dispatchCapture(jwt, 'bash', 'pass', 'audit', verdict.category || 'trivial_utility',
|
|
@@ -2930,7 +2928,7 @@ Do NOT install packages with security risks. Use a patched version or a differen
|
|
|
2930
2928
|
return;
|
|
2931
2929
|
}
|
|
2932
2930
|
|
|
2933
|
-
//
|
|
2931
|
+
// ─── Cloud grading ───
|
|
2934
2932
|
const isHeadless = ['acceptEdits', 'bypassPermissions', 'plan', 'auto'].includes(permissionMode)
|
|
2935
2933
|
|| process.env.SYNKRO_HEADLESS === '1';
|
|
2936
2934
|
|
|
@@ -2957,7 +2955,7 @@ Do NOT install packages with security risks. Use a patched version or a differen
|
|
|
2957
2955
|
const resp = await postWithRetry(GATEWAY_URL + '/api/v1/hook/judge', body, jwt, 8000);
|
|
2958
2956
|
|
|
2959
2957
|
if (!resp) {
|
|
2960
|
-
log('bashGuard ' + cmdShort + '
|
|
2958
|
+
log('bashGuard ' + cmdShort + ' → error (timeout)');
|
|
2961
2959
|
if (installScanMsg) {
|
|
2962
2960
|
outputJson({ systemMessage: installScanMsg, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: installScanMsg } });
|
|
2963
2961
|
} else { outputEmpty(); }
|
|
@@ -2965,7 +2963,7 @@ Do NOT install packages with security risks. Use a patched version or a differen
|
|
|
2965
2963
|
}
|
|
2966
2964
|
|
|
2967
2965
|
if (!resp.hook_response || typeof resp.hook_response !== 'object') {
|
|
2968
|
-
log('bashGuard ' + cmdShort + '
|
|
2966
|
+
log('bashGuard ' + cmdShort + ' → pass (no hook_response)');
|
|
2969
2967
|
if (installScanMsg) {
|
|
2970
2968
|
outputJson({ systemMessage: installScanMsg, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: installScanMsg } });
|
|
2971
2969
|
} else { outputEmpty(); }
|
|
@@ -3041,7 +3039,7 @@ async function main() {
|
|
|
3041
3039
|
const tagStr = tag(rt, config);
|
|
3042
3040
|
|
|
3043
3041
|
if (config.silent) {
|
|
3044
|
-
const msg = tagStr + ' agentGuard
|
|
3042
|
+
const msg = tagStr + ' agentGuard \u2192 skipped (silent mode)';
|
|
3045
3043
|
outputJson({ systemMessage: msg, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: msg } });
|
|
3046
3044
|
return;
|
|
3047
3045
|
}
|
|
@@ -3064,7 +3062,7 @@ async function main() {
|
|
|
3064
3062
|
try {
|
|
3065
3063
|
gradeResp = await localGrade('bash', graderPrompt);
|
|
3066
3064
|
} catch {
|
|
3067
|
-
outputJson({ systemMessage: tagStr + ' agentGuard
|
|
3065
|
+
outputJson({ systemMessage: tagStr + ' agentGuard \u2192 local grader unavailable, skipped' });
|
|
3068
3066
|
return;
|
|
3069
3067
|
}
|
|
3070
3068
|
|
|
@@ -3077,7 +3075,7 @@ async function main() {
|
|
|
3077
3075
|
const guardReason = (verdict.ruleId ? '(' + verdict.ruleId + ') ' : '') + (verdict.reason || 'policy violation');
|
|
3078
3076
|
|
|
3079
3077
|
if (mode === 'audit') {
|
|
3080
|
-
const reason = tagStr + ' agentGuard
|
|
3078
|
+
const reason = tagStr + ' agentGuard \u2192 warning' + (verdict.ruleId ? ' (' + verdict.ruleId + ')' : '') + ': ' + (verdict.reason || 'policy violation');
|
|
3081
3079
|
outputJson({ systemMessage: reason, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: reason } });
|
|
3082
3080
|
dispatchCapture(jwt, 'agent', 'warning', verdict.severity || 'medium', verdict.category || 'security',
|
|
3083
3081
|
toolName, gitRepo, sessionId, config.captureDepth, {
|
|
@@ -3085,7 +3083,7 @@ async function main() {
|
|
|
3085
3083
|
recentUserMessages: transcript.recentUserMessages, ccModel: transcript.ccModel,
|
|
3086
3084
|
});
|
|
3087
3085
|
} else {
|
|
3088
|
-
const reason = tagStr + ' agentGuard
|
|
3086
|
+
const reason = tagStr + ' agentGuard \u2192 blocked' + (verdict.ruleId ? ' (' + verdict.ruleId + ')' : '') + ': ' + (verdict.reason || 'policy violation') + '. Ask the user for explicit consent before retrying.';
|
|
3089
3087
|
outputJson({
|
|
3090
3088
|
systemMessage: reason,
|
|
3091
3089
|
hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: reason, additionalContext: reason },
|
|
@@ -3097,7 +3095,7 @@ async function main() {
|
|
|
3097
3095
|
});
|
|
3098
3096
|
}
|
|
3099
3097
|
} else {
|
|
3100
|
-
const reason = tagStr + ' agentGuard
|
|
3098
|
+
const reason = tagStr + ' agentGuard \u2192 pass: ' + (verdict.reason || 'no policy violations detected');
|
|
3101
3099
|
outputJson({ systemMessage: reason, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: reason } });
|
|
3102
3100
|
dispatchCapture(jwt, 'agent', 'pass', 'audit', verdict.category || 'subagent_spawn',
|
|
3103
3101
|
toolName, gitRepo, sessionId, config.captureDepth, {
|
|
@@ -3136,13 +3134,13 @@ async function main() {
|
|
|
3136
3134
|
const resp = await postWithRetry(GATEWAY_URL + '/api/v1/hook/judge', body, jwt, 8000);
|
|
3137
3135
|
|
|
3138
3136
|
if (!resp) {
|
|
3139
|
-
log('agentGuard ' + promptShort + '
|
|
3137
|
+
log('agentGuard ' + promptShort + ' \u2192 error (timeout)');
|
|
3140
3138
|
outputEmpty();
|
|
3141
3139
|
return;
|
|
3142
3140
|
}
|
|
3143
3141
|
|
|
3144
3142
|
if (!resp.hook_response || typeof resp.hook_response !== 'object') {
|
|
3145
|
-
log('agentGuard ' + promptShort + '
|
|
3143
|
+
log('agentGuard ' + promptShort + ' \u2192 pass (no hook_response)');
|
|
3146
3144
|
outputEmpty();
|
|
3147
3145
|
return;
|
|
3148
3146
|
}
|
|
@@ -3237,7 +3235,7 @@ async function main() {
|
|
|
3237
3235
|
const tagStr = tag(rt, config);
|
|
3238
3236
|
|
|
3239
3237
|
if (config.silent) {
|
|
3240
|
-
outputJson({ systemMessage: tagStr + ' planReview
|
|
3238
|
+
outputJson({ systemMessage: tagStr + ' planReview \u2192 skipped (silent mode)' });
|
|
3241
3239
|
return;
|
|
3242
3240
|
}
|
|
3243
3241
|
|
|
@@ -3254,7 +3252,7 @@ async function main() {
|
|
|
3254
3252
|
try {
|
|
3255
3253
|
gradeResp = await localGrade('plan', graderPrompt);
|
|
3256
3254
|
} catch {
|
|
3257
|
-
outputJson({ systemMessage: tagStr + ' planReview
|
|
3255
|
+
outputJson({ systemMessage: tagStr + ' planReview \u2192 local grader unavailable, skipped' });
|
|
3258
3256
|
return;
|
|
3259
3257
|
}
|
|
3260
3258
|
|
|
@@ -3265,7 +3263,7 @@ async function main() {
|
|
|
3265
3263
|
if (!verdict.ok) {
|
|
3266
3264
|
const reviewMsg = (verdict.ruleId ? '(first: ' + verdict.ruleId + ') ' : '') + (verdict.reason || 'check org rules during implementation');
|
|
3267
3265
|
appendReviewToPlan(planFile, '\\u26a0\\ufe0f Advisory \\u2014 ' + reviewMsg);
|
|
3268
|
-
const advLine = tagStr + ' planReview
|
|
3266
|
+
const advLine = tagStr + ' planReview \u2192 ' + reviewMsg;
|
|
3269
3267
|
outputJson({ systemMessage: advLine, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: 'Synkro local plan judge (advisory). ' + reviewMsg } });
|
|
3270
3268
|
dispatchCapture(jwt, 'plan_review', 'advisory', verdict.severity || 'medium', verdict.category || 'general',
|
|
3271
3269
|
'ExitPlanMode', gitRepo, sessionId, config.captureDepth, {
|
|
@@ -3275,7 +3273,7 @@ async function main() {
|
|
|
3275
3273
|
} else {
|
|
3276
3274
|
const reviewMsg = verdict.reason || 'no relevant org rules for this plan';
|
|
3277
3275
|
appendReviewToPlan(planFile, '\\u2705 Clean \\u2014 ' + reviewMsg);
|
|
3278
|
-
const cleanLine = tagStr + ' planReview
|
|
3276
|
+
const cleanLine = tagStr + ' planReview \u2192 clean: ' + reviewMsg;
|
|
3279
3277
|
outputJson({ systemMessage: cleanLine, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: 'Synkro local plan judge. ' + reviewMsg } });
|
|
3280
3278
|
dispatchCapture(jwt, 'plan_review', 'clean', 'audit', verdict.category || 'general',
|
|
3281
3279
|
'ExitPlanMode', gitRepo, sessionId, config.captureDepth, {
|
|
@@ -3299,7 +3297,7 @@ async function main() {
|
|
|
3299
3297
|
const resp = await postWithRetry(GATEWAY_URL + '/api/v1/hook/judge', body, jwt, 12000);
|
|
3300
3298
|
|
|
3301
3299
|
if (!resp) {
|
|
3302
|
-
log('planReview
|
|
3300
|
+
log('planReview \u2192 error (timeout)');
|
|
3303
3301
|
outputEmpty();
|
|
3304
3302
|
return;
|
|
3305
3303
|
}
|
|
@@ -3311,7 +3309,7 @@ async function main() {
|
|
|
3311
3309
|
if (decision) {
|
|
3312
3310
|
const reason = hookResp?.hookSpecificOutput?.permissionDecisionReason || 'check org rules';
|
|
3313
3311
|
appendReviewToPlan(planFile, '\\u26a0\\ufe0f Advisory \\u2014 ' + reason);
|
|
3314
|
-
outputJson({ systemMessage: tagStr + ' planReview
|
|
3312
|
+
outputJson({ systemMessage: tagStr + ' planReview \u2192 advisory: ' + reason });
|
|
3315
3313
|
} else {
|
|
3316
3314
|
const cloudMsg = hookResp.systemMessage || '';
|
|
3317
3315
|
if (cloudMsg) appendReviewToPlan(planFile, '\\u2705 ' + cloudMsg);
|
|
@@ -3401,9 +3399,9 @@ async function main() {
|
|
|
3401
3399
|
const tagStr = tag('local', config);
|
|
3402
3400
|
|
|
3403
3401
|
if (!findings) {
|
|
3404
|
-
outputJson({ systemMessage: tagStr + ' stop
|
|
3402
|
+
outputJson({ systemMessage: tagStr + ' stop \u2192 0 issues across ' + edits + ' edit(s), session complete' });
|
|
3405
3403
|
} else {
|
|
3406
|
-
outputJson({ systemMessage: tagStr + ' stop
|
|
3404
|
+
outputJson({ systemMessage: tagStr + ' stop \u2192 ' + findings + ' finding(s): ' + autoFixed + ' auto-fixed, ' + open + ' open' });
|
|
3407
3405
|
}
|
|
3408
3406
|
} catch (err) {
|
|
3409
3407
|
process.stderr.write('[synkro] stopSummary error: ' + String(err) + '\\n');
|
|
@@ -3466,9 +3464,9 @@ async function main() {
|
|
|
3466
3464
|
if (!openFindings) {
|
|
3467
3465
|
outputJson({ systemMessage: routeLine });
|
|
3468
3466
|
} else if (openFindings === 1) {
|
|
3469
|
-
outputJson({ systemMessage: routeLine + '\\n' + tagStr + ' session start
|
|
3467
|
+
outputJson({ systemMessage: routeLine + '\\n' + tagStr + ' session start \u2192 1 open finding in this repo from a prior session.' });
|
|
3470
3468
|
} else {
|
|
3471
|
-
outputJson({ systemMessage: routeLine + '\\n' + tagStr + ' session start
|
|
3469
|
+
outputJson({ systemMessage: routeLine + '\\n' + tagStr + ' session start \u2192 ' + openFindings + ' open findings in this repo from prior sessions.' });
|
|
3472
3470
|
}
|
|
3473
3471
|
} catch (err) {
|
|
3474
3472
|
process.stderr.write('[synkro] sessionStart error: ' + String(err) + '\\n');
|
|
@@ -6398,7 +6396,7 @@ function writeConfigEnv(opts) {
|
|
|
6398
6396
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
6399
6397
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
6400
6398
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
6401
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.4.
|
|
6399
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.4.84")}`
|
|
6402
6400
|
];
|
|
6403
6401
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
6404
6402
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|