@synkro-sh/cli 1.7.37 → 1.7.38

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 CHANGED
@@ -839,34 +839,6 @@ function filePathFromToolInput(ti: any): string {
839
839
  return ti.file_path || ti.notebook_path || ti.path || ti.target_file || '';
840
840
  }
841
841
 
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
842
  interface StubOpts {
871
843
  needsFile?: boolean;
872
844
  needsTranscript?: boolean;
@@ -914,29 +886,6 @@ export async function runStub(surface: string, opts: StubOpts = {}): Promise<voi
914
886
  // Gather host-only inputs the container can't read.
915
887
  const envelope: any = { payload, harness, cwd: root || cwd, sessionId, synkroFileText };
916
888
 
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
889
  if (opts.needsFile) {
941
890
  const fp = filePathFromToolInput(payload.tool_input || {});
942
891
  if (fp && existsSync(fp)) {
@@ -961,7 +910,12 @@ export async function runStub(surface: string, opts: StubOpts = {}): Promise<voi
961
910
  // result (the server waits up to 30s for the completion grade), so it needs a
962
911
  // wait above that budget — not the 6s telemetry default — or the stub abandons
963
912
  // the request before the result lands and the completion shows up a hook late.
964
- const timeoutMs = surface === 'bash-followup' ? 32000 : (opts.telemetry ? 6000 : 28000);
913
+ // prompt-submit is the opposite: it's INTERACTIVE (blocks the user's prompt from
914
+ // being sent) under a short 5s hook timeout, so it gets ONE short attempt (below)
915
+ // and a tight per-attempt budget that fits inside 5s — never the 6s×3 telemetry path.
916
+ const timeoutMs = surface === 'bash-followup' ? 32000
917
+ : surface === 'prompt-submit' ? 3500
918
+ : (opts.telemetry ? 6000 : 28000);
965
919
  // Cloud has no local container to reach. Post the SAME envelope to the org's grader
966
920
  // via the gateway's /grade/submit as role 'scan:<surface>'; the container runs
967
921
  // scanRouter (runScan) server-side and returns the SAME shaped decision — so cloud
@@ -987,7 +941,11 @@ export async function runStub(surface: string, opts: StubOpts = {}): Promise<voi
987
941
  // — the server side is idempotent-ish (completion in-flight guard, dup evidence
988
942
  // is harmless). Blocking hooks make ONE attempt: their response IS the verdict
989
943
  // and a retry would double-grade. Normal case: first attempt wins, no delay.
990
- const attempts = opts.telemetry ? 3 : 1;
944
+ // prompt-submit is EXCLUDED from the retry: it runs on the interactive prompt
945
+ // path under a 5s hook timeout, and 3×6s+backoff (19.5s) blew that budget and
946
+ // fired "hook timed out after 5s" on every prompt whenever the server was slow.
947
+ // Dropping an occasional prompt tick is harmless; stalling the user is not.
948
+ const attempts = (opts.telemetry && surface !== 'prompt-submit') ? 3 : 1;
991
949
  let text = '';
992
950
  for (let i = 0; i < attempts; i++) {
993
951
  try {
@@ -3815,6 +3773,10 @@ async function dockerInstall(opts = {}) {
3815
3773
  // interactive AskUserQuestion poll and fall through to generate-the-fix. Only
3816
3774
  // passed when the operator set it; otherwise the image default (1) applies.
3817
3775
  ...process.env.SYNKRO_FIX_POLL ? ["-e", `SYNKRO_FIX_POLL=${process.env.SYNKRO_FIX_POLL}`] : [],
3776
+ // Route CWE grades to the cloud /api/v1/cwe-scan endpoint (arm-C: full-catalog
3777
+ // retrieval + ensemble) instead of the local single-prompt path. Grading stays
3778
+ // local for every other surface. Benchmark lever; default off.
3779
+ ...process.env.SYNKRO_CWE_VIA_ENDPOINT ? ["-e", `SYNKRO_CWE_VIA_ENDPOINT=${process.env.SYNKRO_CWE_VIA_ENDPOINT}`] : [],
3818
3780
  // Connected repo — the server seeds the local app + ruleset named after it.
3819
3781
  ...opts.connectedRepo ? ["-e", `SYNKRO_CONNECTED_REPO=${opts.connectedRepo}`] : [],
3820
3782
  // Real account identity (from config.env via process.env) — telemetry is
@@ -4829,7 +4791,7 @@ function writeConfigEnv(opts) {
4829
4791
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
4830
4792
  `SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
4831
4793
  `SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
4832
- `SYNKRO_VERSION=${shellQuoteSingle("1.7.37")}`
4794
+ `SYNKRO_VERSION=${shellQuoteSingle("1.7.38")}`
4833
4795
  ];
4834
4796
  if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
4835
4797
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
@@ -9027,7 +8989,7 @@ var args = process.argv.slice(2);
9027
8989
  var cmd = args[0] || "";
9028
8990
  var subArgs = args.slice(1);
9029
8991
  function printVersion() {
9030
- console.log("1.7.37");
8992
+ console.log("1.7.38");
9031
8993
  }
9032
8994
  function printHelp2() {
9033
8995
  console.log(`Synkro CLI \u2014 runtime safety for AI coding agents