@synkro-sh/cli 1.7.37 → 1.7.39
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 +63 -58
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -146,7 +146,15 @@ function installCCHooks(settingsPath, config) {
|
|
|
146
146
|
type: "command",
|
|
147
147
|
command: config.bashJudgeScriptPath,
|
|
148
148
|
timeout: 50
|
|
149
|
-
}
|
|
149
|
+
},
|
|
150
|
+
// skill-judge shares this entry so CC runs it in parallel and waits for it
|
|
151
|
+
// before processing denies — its verdict is its OWN system-message block,
|
|
152
|
+
// separate from bashGuard. No-ops on pure reads (empty command).
|
|
153
|
+
...config.skillJudgeScriptPath ? [{
|
|
154
|
+
type: "command",
|
|
155
|
+
command: config.skillJudgeScriptPath,
|
|
156
|
+
timeout: 50
|
|
157
|
+
}] : []
|
|
150
158
|
],
|
|
151
159
|
[SYNKRO_MARKER]: true
|
|
152
160
|
});
|
|
@@ -167,7 +175,13 @@ function installCCHooks(settingsPath, config) {
|
|
|
167
175
|
type: "command",
|
|
168
176
|
command: config.cvePrecheckScriptPath,
|
|
169
177
|
timeout: 10
|
|
170
|
-
}
|
|
178
|
+
},
|
|
179
|
+
// skill-judge — its OWN system-message block, parallel with edit-precheck.
|
|
180
|
+
...config.skillJudgeScriptPath ? [{
|
|
181
|
+
type: "command",
|
|
182
|
+
command: config.skillJudgeScriptPath,
|
|
183
|
+
timeout: 50
|
|
184
|
+
}] : []
|
|
171
185
|
],
|
|
172
186
|
[SYNKRO_MARKER]: true
|
|
173
187
|
});
|
|
@@ -395,6 +409,12 @@ function installCursorHooks(hooksJsonPath, config) {
|
|
|
395
409
|
failClosed: false,
|
|
396
410
|
[SYNKRO_MARKER2]: true
|
|
397
411
|
});
|
|
412
|
+
if (config.skillJudgeScriptPath) h.beforeShellExecution.push({
|
|
413
|
+
command: bunRunCmd(config.skillJudgeScriptPath),
|
|
414
|
+
timeout: 30,
|
|
415
|
+
failClosed: false,
|
|
416
|
+
[SYNKRO_MARKER2]: true
|
|
417
|
+
});
|
|
398
418
|
pushCcHook(h, "afterShellExecution", config.bashFollowupScriptPath, { timeout: 10 });
|
|
399
419
|
h.preToolUse = h.preToolUse ?? [];
|
|
400
420
|
h.preToolUse.push({
|
|
@@ -418,10 +438,21 @@ function installCursorHooks(hooksJsonPath, config) {
|
|
|
418
438
|
matcher: "Shell|Bash|Read|ReadFile|Grep|Glob|terminal|run_terminal_cmd|execute_command|read_file|grep_search|file_search|list_dir|codebase_search|delete_file",
|
|
419
439
|
[SYNKRO_MARKER2]: true
|
|
420
440
|
});
|
|
441
|
+
if (config.skillJudgeScriptPath) h.preToolUse.push({
|
|
442
|
+
command: bunRunCmd(config.skillJudgeScriptPath),
|
|
443
|
+
timeout: 30,
|
|
444
|
+
failClosed: false,
|
|
445
|
+
matcher: "Shell|Bash|terminal|run_terminal_cmd|execute_command",
|
|
446
|
+
[SYNKRO_MARKER2]: true
|
|
447
|
+
});
|
|
421
448
|
pushCcHook(h, "preToolUse", config.editPrecheckScriptPath, {
|
|
422
449
|
timeout: 30,
|
|
423
450
|
matcher: "Write|Edit|StrReplace|MultiEdit|NotebookEdit|edit_file|reapply|edit_notebook|ApplyPatch|apply_patch"
|
|
424
451
|
});
|
|
452
|
+
if (config.skillJudgeScriptPath) pushCcHook(h, "preToolUse", config.skillJudgeScriptPath, {
|
|
453
|
+
timeout: 30,
|
|
454
|
+
matcher: "Write|Edit|StrReplace|MultiEdit|NotebookEdit|edit_file|reapply|edit_notebook|ApplyPatch|apply_patch"
|
|
455
|
+
});
|
|
425
456
|
pushCcHook(h, "preToolUse", config.cwePrecheckScriptPath, {
|
|
426
457
|
timeout: 30,
|
|
427
458
|
matcher: "Write|Edit|StrReplace|MultiEdit|NotebookEdit|edit_file|reapply|edit_notebook|ApplyPatch|apply_patch"
|
|
@@ -738,7 +769,7 @@ var init_skillParser = __esm({
|
|
|
738
769
|
function stubHook(surface, optsLiteral) {
|
|
739
770
|
return "#!/usr/bin/env bun\nimport { runStub } from './_synkro-stub-common.ts';\nrunStub(" + JSON.stringify(surface) + ", " + optsLiteral + ");\n";
|
|
740
771
|
}
|
|
741
|
-
var STUB_COMMON_TS, STUB_EDIT_PRECHECK_TS, STUB_CWE_PRECHECK_TS, STUB_CVE_PRECHECK_TS, STUB_BASH_JUDGE_TS, STUB_INSTALL_SCAN_TS, STUB_AGENT_JUDGE_TS, STUB_MCP_GATE_TS, STUB_PLAN_JUDGE_TS, STUB_STOP_SUMMARY_TS, STUB_SESSION_START_TS, STUB_TRANSCRIPT_SYNC_TS, STUB_USER_PROMPT_SUBMIT_TS, STUB_BASH_FOLLOWUP_TS, STUB_TASK_ACTIVATE_INTENT_TS, STUB_CURSOR_BASH_JUDGE_TS, STUB_CURSOR_EDIT_CAPTURE_TS, STUB_CURSOR_AGENT_CAPTURE_TS;
|
|
772
|
+
var STUB_COMMON_TS, STUB_EDIT_PRECHECK_TS, STUB_CWE_PRECHECK_TS, STUB_CVE_PRECHECK_TS, STUB_BASH_JUDGE_TS, STUB_SKILL_JUDGE_TS, STUB_INSTALL_SCAN_TS, STUB_AGENT_JUDGE_TS, STUB_MCP_GATE_TS, STUB_PLAN_JUDGE_TS, STUB_STOP_SUMMARY_TS, STUB_SESSION_START_TS, STUB_TRANSCRIPT_SYNC_TS, STUB_USER_PROMPT_SUBMIT_TS, STUB_BASH_FOLLOWUP_TS, STUB_TASK_ACTIVATE_INTENT_TS, STUB_CURSOR_BASH_JUDGE_TS, STUB_CURSOR_SKILL_JUDGE_TS, STUB_CURSOR_EDIT_CAPTURE_TS, STUB_CURSOR_AGENT_CAPTURE_TS;
|
|
742
773
|
var init_hookScriptsTs = __esm({
|
|
743
774
|
"cli/installer/hookScriptsTs.ts"() {
|
|
744
775
|
"use strict";
|
|
@@ -839,34 +870,6 @@ function filePathFromToolInput(ti: any): string {
|
|
|
839
870
|
return ti.file_path || ti.notebook_path || ti.path || ti.target_file || '';
|
|
840
871
|
}
|
|
841
872
|
|
|
842
|
-
// Latest real human message from a CC transcript (JSONL). Scans from the end for a
|
|
843
|
-
// user turn, skipping sidechain (sub-agent) turns, meta entries, tool-result-only
|
|
844
|
-
// turns, and the synthetic local-command/caveat wrappers. Returns '' if none found.
|
|
845
|
-
function latestUserText(transcript: string): string {
|
|
846
|
-
const lines = transcript.split('\n');
|
|
847
|
-
for (let i = lines.length - 1; i >= 0; i--) {
|
|
848
|
-
const ln = lines[i].trim();
|
|
849
|
-
if (!ln) continue;
|
|
850
|
-
let o: any;
|
|
851
|
-
try { o = JSON.parse(ln); } catch { continue; }
|
|
852
|
-
if (o && (o.isSidechain || o.isMeta)) continue;
|
|
853
|
-
const m = o && o.message;
|
|
854
|
-
const role = (m && m.role) || (o && o.type);
|
|
855
|
-
if (role !== 'user') continue;
|
|
856
|
-
const c = m && m.content;
|
|
857
|
-
let text = '';
|
|
858
|
-
if (typeof c === 'string') text = c;
|
|
859
|
-
else if (Array.isArray(c)) {
|
|
860
|
-
text = c.filter((b: any) => b && b.type === 'text' && typeof b.text === 'string').map((b: any) => b.text).join(' ');
|
|
861
|
-
}
|
|
862
|
-
text = text.trim();
|
|
863
|
-
if (!text) continue;
|
|
864
|
-
if (text.startsWith('<local-command') || text.startsWith('<command-') || text.startsWith('Caveat:') || text.startsWith('<system-reminder')) continue;
|
|
865
|
-
return text;
|
|
866
|
-
}
|
|
867
|
-
return '';
|
|
868
|
-
}
|
|
869
|
-
|
|
870
873
|
interface StubOpts {
|
|
871
874
|
needsFile?: boolean;
|
|
872
875
|
needsTranscript?: boolean;
|
|
@@ -914,29 +917,6 @@ export async function runStub(surface: string, opts: StubOpts = {}): Promise<voi
|
|
|
914
917
|
// Gather host-only inputs the container can't read.
|
|
915
918
|
const envelope: any = { payload, harness, cwd: root || cwd, sessionId, synkroFileText };
|
|
916
919
|
|
|
917
|
-
// Sub-agent attribution (host-side — the container has no access to ~/.claude).
|
|
918
|
-
// A spawned sub-agent's tool-call hooks carry the ROOT session_id but a sidechain
|
|
919
|
-
// transcript at agent-<id>.jsonl (vs the main <session_id>.jsonl). Detect it from
|
|
920
|
-
// transcript_path, and read the ROOT transcript for the human turn that dispatched
|
|
921
|
-
// this (the sub-agent's own transcript starts with the task prompt, not the human).
|
|
922
|
-
try {
|
|
923
|
-
const tpath = typeof payload.transcript_path === 'string' ? payload.transcript_path : '';
|
|
924
|
-
const tbase = tpath.split('/').pop() || '';
|
|
925
|
-
const am = tbase.match(/^agent-(.+)\.jsonl$/);
|
|
926
|
-
if (am) {
|
|
927
|
-
envelope.isSubagent = true;
|
|
928
|
-
envelope.agentId = am[1];
|
|
929
|
-
try {
|
|
930
|
-
const dir = tpath.slice(0, tpath.length - tbase.length);
|
|
931
|
-
const rootPath = dir + sessionId + '.jsonl';
|
|
932
|
-
if (rootPath !== tpath && existsSync(rootPath)) {
|
|
933
|
-
const msg = latestUserText(readFileSync(rootPath, 'utf-8'));
|
|
934
|
-
if (msg) envelope.triggeringMessage = msg.slice(0, 2000);
|
|
935
|
-
}
|
|
936
|
-
} catch {}
|
|
937
|
-
}
|
|
938
|
-
} catch {}
|
|
939
|
-
|
|
940
920
|
if (opts.needsFile) {
|
|
941
921
|
const fp = filePathFromToolInput(payload.tool_input || {});
|
|
942
922
|
if (fp && existsSync(fp)) {
|
|
@@ -961,7 +941,12 @@ export async function runStub(surface: string, opts: StubOpts = {}): Promise<voi
|
|
|
961
941
|
// result (the server waits up to 30s for the completion grade), so it needs a
|
|
962
942
|
// wait above that budget — not the 6s telemetry default — or the stub abandons
|
|
963
943
|
// the request before the result lands and the completion shows up a hook late.
|
|
964
|
-
|
|
944
|
+
// prompt-submit is the opposite: it's INTERACTIVE (blocks the user's prompt from
|
|
945
|
+
// being sent) under a short 5s hook timeout, so it gets ONE short attempt (below)
|
|
946
|
+
// and a tight per-attempt budget that fits inside 5s — never the 6s×3 telemetry path.
|
|
947
|
+
const timeoutMs = surface === 'bash-followup' ? 32000
|
|
948
|
+
: surface === 'prompt-submit' ? 3500
|
|
949
|
+
: (opts.telemetry ? 6000 : 28000);
|
|
965
950
|
// Cloud has no local container to reach. Post the SAME envelope to the org's grader
|
|
966
951
|
// via the gateway's /grade/submit as role 'scan:<surface>'; the container runs
|
|
967
952
|
// scanRouter (runScan) server-side and returns the SAME shaped decision — so cloud
|
|
@@ -987,7 +972,11 @@ export async function runStub(surface: string, opts: StubOpts = {}): Promise<voi
|
|
|
987
972
|
// — the server side is idempotent-ish (completion in-flight guard, dup evidence
|
|
988
973
|
// is harmless). Blocking hooks make ONE attempt: their response IS the verdict
|
|
989
974
|
// and a retry would double-grade. Normal case: first attempt wins, no delay.
|
|
990
|
-
|
|
975
|
+
// prompt-submit is EXCLUDED from the retry: it runs on the interactive prompt
|
|
976
|
+
// path under a 5s hook timeout, and 3×6s+backoff (19.5s) blew that budget and
|
|
977
|
+
// fired "hook timed out after 5s" on every prompt whenever the server was slow.
|
|
978
|
+
// Dropping an occasional prompt tick is harmless; stalling the user is not.
|
|
979
|
+
const attempts = (opts.telemetry && surface !== 'prompt-submit') ? 3 : 1;
|
|
991
980
|
let text = '';
|
|
992
981
|
for (let i = 0; i < attempts; i++) {
|
|
993
982
|
try {
|
|
@@ -1006,6 +995,7 @@ export async function runStub(surface: string, opts: StubOpts = {}): Promise<voi
|
|
|
1006
995
|
STUB_CWE_PRECHECK_TS = stubHook("cwe-precheck", "{ needsFile: true, needsTranscript: true }");
|
|
1007
996
|
STUB_CVE_PRECHECK_TS = stubHook("cve-precheck", "{ needsFile: true, needsTranscript: true }");
|
|
1008
997
|
STUB_BASH_JUDGE_TS = stubHook("bash-judge", "{ needsTranscript: true }");
|
|
998
|
+
STUB_SKILL_JUDGE_TS = stubHook("skill-judge", "{ needsFile: true, needsTranscript: true }");
|
|
1009
999
|
STUB_INSTALL_SCAN_TS = stubHook("install-scan", "{ needsTranscript: true }");
|
|
1010
1000
|
STUB_AGENT_JUDGE_TS = stubHook("agent-judge", "{ needsTranscript: true }");
|
|
1011
1001
|
STUB_MCP_GATE_TS = stubHook("mcp-gate", "{ needsTranscript: true }");
|
|
@@ -1035,6 +1025,7 @@ try {
|
|
|
1035
1025
|
process.stdout.write('{}\\n');
|
|
1036
1026
|
`;
|
|
1037
1027
|
STUB_CURSOR_BASH_JUDGE_TS = stubHook("bash-judge", "{ needsTranscript: true, harness: 'cursor' }");
|
|
1028
|
+
STUB_CURSOR_SKILL_JUDGE_TS = stubHook("skill-judge", "{ needsFile: true, needsTranscript: true, harness: 'cursor' }");
|
|
1038
1029
|
STUB_CURSOR_EDIT_CAPTURE_TS = stubHook("edit-precheck", "{ needsFile: true, needsTranscript: true, harness: 'cursor' }");
|
|
1039
1030
|
STUB_CURSOR_AGENT_CAPTURE_TS = stubHook("agent-judge", "{ needsTranscript: true, harness: 'cursor' }");
|
|
1040
1031
|
}
|
|
@@ -3815,6 +3806,10 @@ async function dockerInstall(opts = {}) {
|
|
|
3815
3806
|
// interactive AskUserQuestion poll and fall through to generate-the-fix. Only
|
|
3816
3807
|
// passed when the operator set it; otherwise the image default (1) applies.
|
|
3817
3808
|
...process.env.SYNKRO_FIX_POLL ? ["-e", `SYNKRO_FIX_POLL=${process.env.SYNKRO_FIX_POLL}`] : [],
|
|
3809
|
+
// Route CWE grades to the cloud /api/v1/cwe-scan endpoint (arm-C: full-catalog
|
|
3810
|
+
// retrieval + ensemble) instead of the local single-prompt path. Grading stays
|
|
3811
|
+
// local for every other surface. Benchmark lever; default off.
|
|
3812
|
+
...process.env.SYNKRO_CWE_VIA_ENDPOINT ? ["-e", `SYNKRO_CWE_VIA_ENDPOINT=${process.env.SYNKRO_CWE_VIA_ENDPOINT}`] : [],
|
|
3818
3813
|
// Connected repo — the server seeds the local app + ruleset named after it.
|
|
3819
3814
|
...opts.connectedRepo ? ["-e", `SYNKRO_CONNECTED_REPO=${opts.connectedRepo}`] : [],
|
|
3820
3815
|
// Real account identity (from config.env via process.env) — telemetry is
|
|
@@ -4728,6 +4723,8 @@ function ensureSynkroDir() {
|
|
|
4728
4723
|
function writeHookScripts() {
|
|
4729
4724
|
const installExtractCorePath = join11(HOOKS_DIR, "installExtractCore.ts");
|
|
4730
4725
|
const bashScriptPath = join11(HOOKS_DIR, "cc-bash-judge.ts");
|
|
4726
|
+
const skillJudgeScriptPath = join11(HOOKS_DIR, "cc-skill-judge.ts");
|
|
4727
|
+
const cursorSkillJudgePath = join11(HOOKS_DIR, "cursor-skill-judge.ts");
|
|
4731
4728
|
const bashFollowupScriptPath = join11(HOOKS_DIR, "cc-bash-followup.ts");
|
|
4732
4729
|
const editPrecheckScriptPath = join11(HOOKS_DIR, "cc-edit-precheck.ts");
|
|
4733
4730
|
const cwePrecheckScriptPath = join11(HOOKS_DIR, "cc-cwe-precheck.ts");
|
|
@@ -4751,6 +4748,8 @@ function writeHookScripts() {
|
|
|
4751
4748
|
const stubFiles = [
|
|
4752
4749
|
[stubCommonPath, STUB_COMMON_TS],
|
|
4753
4750
|
[bashScriptPath, STUB_BASH_JUDGE_TS],
|
|
4751
|
+
[skillJudgeScriptPath, STUB_SKILL_JUDGE_TS],
|
|
4752
|
+
[cursorSkillJudgePath, STUB_CURSOR_SKILL_JUDGE_TS],
|
|
4754
4753
|
[bashFollowupScriptPath, STUB_BASH_FOLLOWUP_TS],
|
|
4755
4754
|
[editPrecheckScriptPath, STUB_EDIT_PRECHECK_TS],
|
|
4756
4755
|
[cwePrecheckScriptPath, STUB_CWE_PRECHECK_TS],
|
|
@@ -4782,6 +4781,8 @@ function writeHookScripts() {
|
|
|
4782
4781
|
}
|
|
4783
4782
|
return {
|
|
4784
4783
|
bashScript: bashScriptPath,
|
|
4784
|
+
skillJudgeScript: skillJudgeScriptPath,
|
|
4785
|
+
cursorSkillJudgeScript: cursorSkillJudgePath,
|
|
4785
4786
|
bashFollowupScript: bashFollowupScriptPath,
|
|
4786
4787
|
editPrecheckScript: editPrecheckScriptPath,
|
|
4787
4788
|
cwePrecheckScript: cwePrecheckScriptPath,
|
|
@@ -4829,7 +4830,7 @@ function writeConfigEnv(opts) {
|
|
|
4829
4830
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
4830
4831
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
4831
4832
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
4832
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.7.
|
|
4833
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.7.39")}`
|
|
4833
4834
|
];
|
|
4834
4835
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
4835
4836
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -5472,6 +5473,7 @@ async function installCommand(opts = {}) {
|
|
|
5472
5473
|
hasClaudeCode = true;
|
|
5473
5474
|
installCCHooks(agent.settingsPath, {
|
|
5474
5475
|
bashJudgeScriptPath: scripts.bashScript,
|
|
5476
|
+
skillJudgeScriptPath: scripts.skillJudgeScript,
|
|
5475
5477
|
bashFollowupScriptPath: scripts.bashFollowupScript,
|
|
5476
5478
|
editPrecheckScriptPath: scripts.editPrecheckScript,
|
|
5477
5479
|
cwePrecheckScriptPath: scripts.cwePrecheckScript,
|
|
@@ -5492,6 +5494,7 @@ async function installCommand(opts = {}) {
|
|
|
5492
5494
|
hasCursor = true;
|
|
5493
5495
|
installCursorHooks(agent.settingsPath, {
|
|
5494
5496
|
bashJudgeScriptPath: scripts.cursorBashJudgeScript,
|
|
5497
|
+
skillJudgeScriptPath: scripts.cursorSkillJudgeScript,
|
|
5495
5498
|
editCaptureScriptPath: scripts.cursorEditCaptureScript,
|
|
5496
5499
|
agentCaptureScriptPath: scripts.cursorAgentCaptureScript,
|
|
5497
5500
|
bashFollowupScriptPath: scripts.bashFollowupScript,
|
|
@@ -5970,6 +5973,7 @@ function reconcileHarness() {
|
|
|
5970
5973
|
if (wantCC) {
|
|
5971
5974
|
installCCHooks(ccSettings, {
|
|
5972
5975
|
bashJudgeScriptPath: scripts.bashScript,
|
|
5976
|
+
skillJudgeScriptPath: scripts.skillJudgeScript,
|
|
5973
5977
|
bashFollowupScriptPath: scripts.bashFollowupScript,
|
|
5974
5978
|
editPrecheckScriptPath: scripts.editPrecheckScript,
|
|
5975
5979
|
cwePrecheckScriptPath: scripts.cwePrecheckScript,
|
|
@@ -6002,6 +6006,7 @@ function reconcileHarness() {
|
|
|
6002
6006
|
if (wantCursor) {
|
|
6003
6007
|
installCursorHooks(cursorHooks, {
|
|
6004
6008
|
bashJudgeScriptPath: scripts.cursorBashJudgeScript,
|
|
6009
|
+
skillJudgeScriptPath: scripts.cursorSkillJudgeScript,
|
|
6005
6010
|
editCaptureScriptPath: scripts.cursorEditCaptureScript,
|
|
6006
6011
|
agentCaptureScriptPath: scripts.cursorAgentCaptureScript,
|
|
6007
6012
|
bashFollowupScriptPath: scripts.bashFollowupScript,
|
|
@@ -9027,7 +9032,7 @@ var args = process.argv.slice(2);
|
|
|
9027
9032
|
var cmd = args[0] || "";
|
|
9028
9033
|
var subArgs = args.slice(1);
|
|
9029
9034
|
function printVersion() {
|
|
9030
|
-
console.log("1.7.
|
|
9035
|
+
console.log("1.7.39");
|
|
9031
9036
|
}
|
|
9032
9037
|
function printHelp2() {
|
|
9033
9038
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|