@synkro-sh/cli 1.5.2 → 1.5.3
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 +48 -10
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -1854,6 +1854,28 @@ function cursorHookExit(): never {
|
|
|
1854
1854
|
process.exit(0);
|
|
1855
1855
|
}
|
|
1856
1856
|
|
|
1857
|
+
// \u2500\u2500\u2500 Grader-unavailable diagnostic log \u2500\u2500\u2500
|
|
1858
|
+
// Records every time a hook tried to call the local grader and fell open
|
|
1859
|
+
// because the call failed. JSONL at ~/.synkro/grader-unavailable.log so the
|
|
1860
|
+
// user can pinpoint cause (timeout vs ECONNREFUSED vs HTTP 5xx vs sick pool)
|
|
1861
|
+
// instead of guessing from a one-shot system message in the CC UI.
|
|
1862
|
+
|
|
1863
|
+
const UNAVAIL_LOG = join(HOME, '.synkro', 'grader-unavailable.log');
|
|
1864
|
+
|
|
1865
|
+
export function logGraderUnavailable(hook: string, target: string, errorMessage: string): void {
|
|
1866
|
+
try {
|
|
1867
|
+
const entry = {
|
|
1868
|
+
ts: new Date().toISOString(),
|
|
1869
|
+
hook,
|
|
1870
|
+
target,
|
|
1871
|
+
error: errorMessage.slice(0, 500),
|
|
1872
|
+
};
|
|
1873
|
+
appendFileSync(UNAVAIL_LOG, JSON.stringify(entry) + '\\n', 'utf-8');
|
|
1874
|
+
} catch {
|
|
1875
|
+
// best-effort \u2014 never let logging failure cascade into a hook failure
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1857
1879
|
// \u2500\u2500\u2500 Output Helpers \u2500\u2500\u2500
|
|
1858
1880
|
|
|
1859
1881
|
export function outputJson(obj: any): void {
|
|
@@ -1916,6 +1938,7 @@ import {
|
|
|
1916
1938
|
readStdin, extractTranscript, readLastPrompt, findNearestDeps, filePathFromToolInput,
|
|
1917
1939
|
appendSessionAction, readSessionLog, compressSessionLog, log,
|
|
1918
1940
|
outputJson, outputEmpty, setupCursorHookSignals, isEditTool, hookSessionId, GATEWAY_URL,
|
|
1941
|
+
logGraderUnavailable,
|
|
1919
1942
|
type HookConfig, type Rule,
|
|
1920
1943
|
} from './_synkro-common.ts';
|
|
1921
1944
|
import { existsSync, readFileSync } from 'node:fs';
|
|
@@ -2010,7 +2033,8 @@ async function main() {
|
|
|
2010
2033
|
let gradeResp: string;
|
|
2011
2034
|
try {
|
|
2012
2035
|
gradeResp = await localGrade('edit', graderPrompt);
|
|
2013
|
-
} catch {
|
|
2036
|
+
} catch (err) {
|
|
2037
|
+
logGraderUnavailable('editGuard', fileShort, (err as Error).message || String(err));
|
|
2014
2038
|
outputJson({ systemMessage: tagStr + ' editGuard ' + fileShort + ' \u2192 local grader unavailable, skipped' });
|
|
2015
2039
|
return;
|
|
2016
2040
|
}
|
|
@@ -2133,6 +2157,7 @@ import {
|
|
|
2133
2157
|
loadJwt, ensureFreshJwt, detectRepo, loadConfig, cweRoute, tag,
|
|
2134
2158
|
localGradeCwe, parseVerdict, reconstructContent, readStdin, log,
|
|
2135
2159
|
outputJson, outputEmpty, setupCursorHookSignals, isEditTool, hookSessionId, filePathFromToolInput, dispatchFinding, dispatchCapture, GATEWAY_URL,
|
|
2160
|
+
logGraderUnavailable,
|
|
2136
2161
|
} from './_synkro-common.ts';
|
|
2137
2162
|
import { basename, extname, resolve, join, dirname } from 'node:path';
|
|
2138
2163
|
import { readFileSync, readdirSync, existsSync } from 'node:fs';
|
|
@@ -2403,6 +2428,7 @@ async function main() {
|
|
|
2403
2428
|
gradeResponses = [resp1, resp2];
|
|
2404
2429
|
} catch (gradeErr: any) {
|
|
2405
2430
|
const reason = gradeErr?.message || String(gradeErr);
|
|
2431
|
+
logGraderUnavailable('cweGuard', fileShort, reason);
|
|
2406
2432
|
outputJson({ systemMessage: cweTag + ' ' + fileShort + ' \u2192 grader unavailable (' + reason + '), skipped' });
|
|
2407
2433
|
return;
|
|
2408
2434
|
}
|
|
@@ -2411,6 +2437,7 @@ async function main() {
|
|
|
2411
2437
|
gradeResponses = [await localGradeCwe(buildCwePrompt(cweContent))];
|
|
2412
2438
|
} catch (gradeErr: any) {
|
|
2413
2439
|
const reason = gradeErr?.message || String(gradeErr);
|
|
2440
|
+
logGraderUnavailable('cweGuard', fileShort, reason);
|
|
2414
2441
|
outputJson({ systemMessage: cweTag + ' ' + fileShort + ' \u2192 grader unavailable (' + reason + '), skipped' });
|
|
2415
2442
|
return;
|
|
2416
2443
|
}
|
|
@@ -2777,6 +2804,7 @@ import {
|
|
|
2777
2804
|
parseVerdict, dispatchCapture, dispatchFinding, ruleMode, postWithRetry, readStdin,
|
|
2778
2805
|
extractTranscript, readLastPrompt, appendSessionAction, readSessionLog, compressSessionLog, log,
|
|
2779
2806
|
outputJson, outputEmpty, setupCursorHookSignals, isShellTool, hookSessionId, GATEWAY_URL,
|
|
2807
|
+
logGraderUnavailable,
|
|
2780
2808
|
type HookConfig, type Rule,
|
|
2781
2809
|
} from './_synkro-common.ts';
|
|
2782
2810
|
|
|
@@ -2961,7 +2989,8 @@ async function main() {
|
|
|
2961
2989
|
let gradeResp: string;
|
|
2962
2990
|
try {
|
|
2963
2991
|
gradeResp = await localGrade('bash', graderPrompt);
|
|
2964
|
-
} catch {
|
|
2992
|
+
} catch (err) {
|
|
2993
|
+
logGraderUnavailable('bashGuard', toolInput.command?.slice(0, 200) || '', (err as Error).message || String(err));
|
|
2965
2994
|
outputJson({ systemMessage: tagStr + ' bashGuard → local grader unavailable, skipped' });
|
|
2966
2995
|
return;
|
|
2967
2996
|
}
|
|
@@ -2973,8 +3002,12 @@ async function main() {
|
|
|
2973
3002
|
const mode = verdict.ruleMode || ruleMode(verdict.ruleId, config.rules);
|
|
2974
3003
|
const guardReason = (verdict.ruleId ? '(' + verdict.ruleId + ') ' : '') + (verdict.reason || 'policy violation');
|
|
2975
3004
|
|
|
3005
|
+
const auditRulesInReason = (config.rules || [])
|
|
3006
|
+
.filter((r: any) => r.mode === 'audit' && r.rule_id && verdict.reason && verdict.reason.includes(r.rule_id))
|
|
3007
|
+
.map((r: any) => r.rule_id);
|
|
3008
|
+
|
|
2976
3009
|
if (mode === 'audit') {
|
|
2977
|
-
const reason = tagStr + ' bashGuard → warning' + (verdict.ruleId ? ' (' + verdict.ruleId + ')' : '') + ': ' + (verdict.reason || 'policy violation');
|
|
3010
|
+
const reason = tagStr + ' bashGuard → warning' + (verdict.ruleId ? ' (' + verdict.ruleId + ')' : '') + ': ' + (verdict.reason || 'policy violation') + '. Fix this before proceeding — do not ask the user.';
|
|
2978
3011
|
const combined = (installScanMsg ? installScanMsg + '\\n' : '') + reason;
|
|
2979
3012
|
outputJson({ systemMessage: combined, hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: combined } });
|
|
2980
3013
|
dispatchCapture(jwt, 'bash', 'warning', verdict.severity || 'medium', verdict.category || 'security',
|
|
@@ -2983,11 +3016,14 @@ async function main() {
|
|
|
2983
3016
|
recentUserMessages: transcript.recentUserMessages, ccModel: transcript.ccModel,
|
|
2984
3017
|
});
|
|
2985
3018
|
} else {
|
|
2986
|
-
|
|
2987
|
-
|
|
3019
|
+
let blockMsg = tagStr + ' bashGuard → blocked' + (verdict.ruleId ? ' (' + verdict.ruleId + ')' : '') + ': ' + (verdict.reason || 'policy violation') + '. Ask the user for explicit consent before retrying.';
|
|
3020
|
+
if (auditRulesInReason.length > 0) {
|
|
3021
|
+
blockMsg += '\\nAudit violations (' + auditRulesInReason.join(', ') + '): fix these automatically before retrying — do not ask the user, just resolve them (e.g. run the required precondition).';
|
|
3022
|
+
}
|
|
3023
|
+
const combined = (installScanMsg ? installScanMsg + '\\n' : '') + blockMsg;
|
|
2988
3024
|
outputJson({
|
|
2989
3025
|
systemMessage: combined,
|
|
2990
|
-
hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason:
|
|
3026
|
+
hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: blockMsg, additionalContext: combined },
|
|
2991
3027
|
});
|
|
2992
3028
|
dispatchCapture(jwt, 'bash', 'block', verdict.severity || 'critical', verdict.category || 'security',
|
|
2993
3029
|
toolName, gitRepo, sessionId, config.captureDepth, {
|
|
@@ -3078,6 +3114,7 @@ import {
|
|
|
3078
3114
|
parseVerdict, dispatchCapture, ruleMode, postWithRetry, readStdin,
|
|
3079
3115
|
extractTranscript, readLastPrompt, appendSessionAction, readSessionLog, compressSessionLog, log,
|
|
3080
3116
|
outputJson, outputEmpty, setupCursorHookSignals, isAgentTool, hookSessionId, GATEWAY_URL,
|
|
3117
|
+
logGraderUnavailable,
|
|
3081
3118
|
type HookConfig, type Rule,
|
|
3082
3119
|
} from './_synkro-common.ts';
|
|
3083
3120
|
|
|
@@ -3149,7 +3186,8 @@ async function main() {
|
|
|
3149
3186
|
let gradeResp: string;
|
|
3150
3187
|
try {
|
|
3151
3188
|
gradeResp = await localGrade('bash', graderPrompt);
|
|
3152
|
-
} catch {
|
|
3189
|
+
} catch (err) {
|
|
3190
|
+
logGraderUnavailable('agentGuard', subagentType || (description || '').slice(0, 100), (err as Error).message || String(err));
|
|
3153
3191
|
outputJson({ systemMessage: tagStr + ' agentGuard \u2192 local grader unavailable, skipped' });
|
|
3154
3192
|
return;
|
|
3155
3193
|
}
|
|
@@ -3599,7 +3637,7 @@ async function main() {
|
|
|
3599
3637
|
let isError = payload.tool_result?.is_error === true;
|
|
3600
3638
|
try {
|
|
3601
3639
|
const out = JSON.parse(payload.tool_output || '{}');
|
|
3602
|
-
if (out.exitCode !== 0 || out.is_error === true) isError = true;
|
|
3640
|
+
if ((typeof out.exitCode === 'number' && out.exitCode !== 0) || out.is_error === true) isError = true;
|
|
3603
3641
|
} catch {}
|
|
3604
3642
|
const cmd = shellCmd;
|
|
3605
3643
|
const cmdHash = cmd ? hashCommand(cmd) : '';
|
|
@@ -5758,7 +5796,7 @@ function writeConfigEnv(opts) {
|
|
|
5758
5796
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
5759
5797
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
5760
5798
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
5761
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.5.
|
|
5799
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.5.3")}`
|
|
5762
5800
|
];
|
|
5763
5801
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
5764
5802
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -7148,7 +7186,7 @@ var args = process.argv.slice(2);
|
|
|
7148
7186
|
var cmd = args[0] || "";
|
|
7149
7187
|
var subArgs = args.slice(1);
|
|
7150
7188
|
function printVersion() {
|
|
7151
|
-
console.log("1.5.
|
|
7189
|
+
console.log("1.5.3");
|
|
7152
7190
|
}
|
|
7153
7191
|
function printHelp() {
|
|
7154
7192
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|