@synkro-sh/cli 1.4.10 → 1.4.11

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
@@ -132,7 +132,7 @@ function installCCHooks(settingsPath, config) {
132
132
  {
133
133
  type: "command",
134
134
  command: config.bashJudgeScriptPath,
135
- timeout: 15
135
+ timeout: 30
136
136
  }
137
137
  ],
138
138
  [SYNKRO_MARKER]: true
@@ -709,8 +709,17 @@ ensure_fresh_jwt() {
709
709
 
710
710
  ensure_fresh_jwt
711
711
 
712
- # Resolve tier + capture_depth live from /cli/me every call. Default to local_only (fail-safe).
713
- ME_RESP=$(curl -sS "\${GATEWAY_URL}/api/v1/cli/me" -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null || echo "")
712
+ # Parallel fetch: /cli/me + rules in background, wait for both.
713
+ _ME_TMP=$(mktemp -t synkro-me.XXXXXX)
714
+ _RULES_TMP=$(mktemp -t synkro-rules.XXXXXX)
715
+ trap "rm -f \\"$_ME_TMP\\" \\"$_RULES_TMP\\"" EXIT
716
+ curl -sS "\${GATEWAY_URL}/api/v1/cli/me" -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null > "$_ME_TMP" &
717
+ _ME_PID=$!
718
+ curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules" -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null > "$_RULES_TMP" &
719
+ _RULES_PID=$!
720
+ wait $_ME_PID 2>/dev/null; wait $_RULES_PID 2>/dev/null
721
+
722
+ ME_RESP=$(cat "$_ME_TMP" 2>/dev/null || echo "")
714
723
  SYNKRO_INFERENCE_TIER=$(echo "$ME_RESP" | jq -r '.tier // empty' 2>/dev/null)
715
724
  SYNKRO_CAPTURE_DEPTH=$(echo "$ME_RESP" | jq -r '.capture_depth // empty' 2>/dev/null)
716
725
  SYNKRO_INFERENCE_TIER="\${SYNKRO_INFERENCE_TIER:-fast}"
@@ -721,32 +730,14 @@ if command -v claude >/dev/null 2>&1; then
721
730
  USE_LOCAL=true
722
731
  fi
723
732
 
724
- # Prefer local grading whenever it's available \u2014 the local-cc channel beats
725
- # the cloud fast tier on latency, and it's available regardless of the
726
- # server-assigned tier. Fall through to the cloud curl only when neither
727
- # the channel nor a usable \`claude\` CLI is reachable.
728
733
  if synkro_channel_up || { [ "$SYNKRO_INFERENCE_TIER" = "free" ] && command -v claude >/dev/null 2>&1; }; then
729
- # \u2500\u2500\u2500 LOCAL PATH: channel-grader first, then \`claude --print\` cold fallback. \u2500\u2500\u2500
730
-
731
734
  RULES_CACHE="$HOME/.synkro/.rules-cache-bash"
732
- ORG_RULES="[]"
733
- if [ "$SYNKRO_CAPTURE_DEPTH" = "local_only" ]; then
734
- ORG_RULES=$(curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules" \\
735
- -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null \\
736
- | jq -c '[.rules[]? | select(.hook_stage == "pre" or .hook_stage == "both" or .hook_stage == null) | {rule_id, text, severity, category}]' 2>/dev/null || echo "[]")
737
- if [ -n "$ORG_RULES" ] && [ "$ORG_RULES" != "null" ] && [ "$ORG_RULES" != "[]" ]; then
738
- printf '%s' "$ORG_RULES" > "$RULES_CACHE" 2>/dev/null || true
739
- elif [ -f "$RULES_CACHE" ]; then
740
- ORG_RULES=$(cat "$RULES_CACHE" 2>/dev/null || echo "[]")
741
- fi
742
- else
743
- ORG_RULES=$(printf '%s' "$COMMAND" | head -c 4000 \\
744
- | jq -Rs '{content: .}' \\
745
- | curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules?top_k=15" \\
746
- -X POST -H "Content-Type: application/json" \\
747
- -H "Authorization: Bearer $JWT" \\
748
- -d @- --max-time 2 2>/dev/null \\
749
- | jq -c '[.rules[]? | select(.hook_stage == "pre" or .hook_stage == "both" or .hook_stage == null) | {rule_id, text, severity, category}]' 2>/dev/null || echo "[]")
735
+ RULES_JQ='[.rules[]? | select(.hook_stage == "pre" or .hook_stage == "both" or .hook_stage == null) | {rule_id, text, severity, category}]'
736
+ ORG_RULES=$(jq -c "$RULES_JQ" "$_RULES_TMP" 2>/dev/null || echo "[]")
737
+ if [ -n "$ORG_RULES" ] && [ "$ORG_RULES" != "null" ] && [ "$ORG_RULES" != "[]" ]; then
738
+ printf '%s' "$ORG_RULES" > "$RULES_CACHE" 2>/dev/null || true
739
+ elif [ -f "$RULES_CACHE" ]; then
740
+ ORG_RULES=$(cat "$RULES_CACHE" 2>/dev/null || echo "[]")
750
741
  fi
751
742
  if [ -z "$ORG_RULES" ] || [ "$ORG_RULES" = "null" ]; then ORG_RULES="[]"; fi
752
743
 
@@ -831,7 +822,9 @@ if [ "$VERDICT" != "__LOCAL_XML_PARSED__" ]; then
831
822
  ALTERNATIVE=$(echo "$VERDICT" | jq -r '.alternative // ""' 2>/dev/null)
832
823
  CATEGORY=$(echo "$VERDICT" | jq -r '.category // "destructive_command"' 2>/dev/null)
833
824
  RISK_LEVEL=$(echo "$VERDICT" | jq -r '.risk_level // empty' 2>/dev/null)
825
+ VIOLATED_RULES=$(echo "$VERDICT" | jq -c '.violated_rules // []' 2>/dev/null)
834
826
  fi
827
+ VIOLATED_RULES="\${VIOLATED_RULES:-[]}"
835
828
  # Defaults if any var is empty (defensive \u2014 XML primer should always emit them).
836
829
  SEVERITY="\${SEVERITY:-audit}"
837
830
  VERDICT_KIND="\${VERDICT_KIND:-warn}"
@@ -951,6 +944,7 @@ if [ "$USE_LOCAL" = "true" ] && [ -n "$VERDICT_KIND" ]; then
951
944
  --arg reasoning "$REASONING" \\
952
945
  --arg alternative "$ALTERNATIVE" \\
953
946
  --argjson rules_checked "\${ORG_RULES:-[]}" \\
947
+ --argjson violated_rules "\${VIOLATED_RULES:-[]}" \\
954
948
  --argjson recent_user_messages "\${RECENT_USER_MESSAGES:-[]}" \\
955
949
  '{
956
950
  event_id: $event_id,
@@ -963,7 +957,8 @@ if [ "$USE_LOCAL" = "true" ] && [ -n "$VERDICT_KIND" ]; then
963
957
  model: $model,
964
958
  tool_name: $tool_name,
965
959
  capture_depth: $capture_depth,
966
- rules_checked: $rules_checked
960
+ rules_checked: $rules_checked,
961
+ violated_rules: $violated_rules
967
962
  } + (if $repo != "" then {repo: $repo} else {} end)
968
963
  + (if $session_id != "" then {session_id: $session_id} else {} end)
969
964
  + (if $tool_use_id != "" then {tool_use_id: $tool_use_id} else {} end)
@@ -1217,34 +1212,30 @@ ensure_fresh_jwt() {
1217
1212
  ensure_fresh_jwt
1218
1213
 
1219
1214
 
1220
- # Resolve tier + capture_depth live from /cli/me every call. Default to local_only (fail-safe).
1221
- ME_RESP=$(curl -sS "\${GATEWAY_URL}/api/v1/cli/me" -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null || echo "")
1215
+ # Parallel fetch: /cli/me + rules in background, wait for both.
1216
+ _ME_TMP=$(mktemp -t synkro-me.XXXXXX)
1217
+ _RULES_TMP=$(mktemp -t synkro-rules.XXXXXX)
1218
+ trap "rm -f \\"$_ME_TMP\\" \\"$_RULES_TMP\\"" EXIT
1219
+ curl -sS "\${GATEWAY_URL}/api/v1/cli/me" -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null > "$_ME_TMP" &
1220
+ _ME_PID=$!
1221
+ curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules" -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null > "$_RULES_TMP" &
1222
+ _RULES_PID=$!
1223
+ wait $_ME_PID 2>/dev/null; wait $_RULES_PID 2>/dev/null
1224
+
1225
+ ME_RESP=$(cat "$_ME_TMP" 2>/dev/null || echo "")
1222
1226
  SYNKRO_INFERENCE_TIER=$(echo "$ME_RESP" | jq -r '.tier // empty' 2>/dev/null)
1223
1227
  SYNKRO_CAPTURE_DEPTH=$(echo "$ME_RESP" | jq -r '.capture_depth // empty' 2>/dev/null)
1224
1228
  SYNKRO_INFERENCE_TIER="\${SYNKRO_INFERENCE_TIER:-fast}"
1225
1229
  SYNKRO_CAPTURE_DEPTH="\${SYNKRO_CAPTURE_DEPTH:-local_only}"
1226
1230
 
1227
1231
  if synkro_channel_up || { [ "$SYNKRO_INFERENCE_TIER" = "free" ] && command -v claude >/dev/null 2>&1; }; then
1228
- # \u2500\u2500\u2500 LOCAL PATH: channel-grader first, then \`claude --print\` cold fallback. \u2500\u2500\u2500
1229
1232
  RULES_CACHE="$HOME/.synkro/.rules-cache-edit"
1230
- ORG_RULES="[]"
1231
- if [ "$SYNKRO_CAPTURE_DEPTH" = "local_only" ]; then
1232
- ORG_RULES=$(curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules" \\
1233
- -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null \\
1234
- | jq -c '[.rules[]? | select(.hook_stage == "pre" or .hook_stage == "both" or .hook_stage == null) | {rule_id, text, severity, category, mode}]' 2>/dev/null || echo "[]")
1235
- if [ -n "$ORG_RULES" ] && [ "$ORG_RULES" != "null" ] && [ "$ORG_RULES" != "[]" ]; then
1236
- printf '%s' "$ORG_RULES" > "$RULES_CACHE" 2>/dev/null || true
1237
- elif [ -f "$RULES_CACHE" ]; then
1238
- ORG_RULES=$(cat "$RULES_CACHE" 2>/dev/null || echo "[]")
1239
- fi
1240
- else
1241
- ORG_RULES=$(printf '%s' "$PROPOSED" | head -c 8000 \\
1242
- | jq -Rs '{content: .}' \\
1243
- | curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules?top_k=20" \\
1244
- -X POST -H "Content-Type: application/json" \\
1245
- -H "Authorization: Bearer $JWT" \\
1246
- -d @- --max-time 2 2>/dev/null \\
1247
- | jq -c '[.rules[]? | select(.hook_stage == "pre" or .hook_stage == "both" or .hook_stage == null) | {rule_id, text, severity, category, mode}]' 2>/dev/null || echo "[]")
1233
+ RULES_JQ='[.rules[]? | select(.hook_stage == "pre" or .hook_stage == "both" or .hook_stage == null) | {rule_id, text, severity, category, mode}]'
1234
+ ORG_RULES=$(jq -c "$RULES_JQ" "$_RULES_TMP" 2>/dev/null || echo "[]")
1235
+ if [ -n "$ORG_RULES" ] && [ "$ORG_RULES" != "null" ] && [ "$ORG_RULES" != "[]" ]; then
1236
+ printf '%s' "$ORG_RULES" > "$RULES_CACHE" 2>/dev/null || true
1237
+ elif [ -f "$RULES_CACHE" ]; then
1238
+ ORG_RULES=$(cat "$RULES_CACHE" 2>/dev/null || echo "[]")
1248
1239
  fi
1249
1240
  if [ -z "$ORG_RULES" ] || [ "$ORG_RULES" = "null" ]; then ORG_RULES="[]"; fi
1250
1241
 
@@ -1661,30 +1652,25 @@ if [ -n "$SESSION_ID" ] && [ -n "$TOOL_USE_ID" ]; then
1661
1652
  ) &
1662
1653
  fi
1663
1654
 
1664
- # Resolve tier + capture_depth live from /cli/me every call. Default to local_only (fail-safe).
1665
- ME_RESP=$(curl -sS "\${GATEWAY_URL}/api/v1/cli/me" -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null || echo "")
1655
+ # Parallel fetch: /cli/me + rules in background, wait for both.
1656
+ _ME_TMP=$(mktemp -t synkro-me.XXXXXX)
1657
+ _RULES_TMP=$(mktemp -t synkro-rules.XXXXXX)
1658
+ trap "rm -f \\"$_ME_TMP\\" \\"$_RULES_TMP\\"" EXIT
1659
+ curl -sS "\${GATEWAY_URL}/api/v1/cli/me" -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null > "$_ME_TMP" &
1660
+ _ME_PID=$!
1661
+ curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules" -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null > "$_RULES_TMP" &
1662
+ _RULES_PID=$!
1663
+ wait $_ME_PID 2>/dev/null; wait $_RULES_PID 2>/dev/null
1664
+
1665
+ ME_RESP=$(cat "$_ME_TMP" 2>/dev/null || echo "")
1666
1666
  SYNKRO_INFERENCE_TIER=$(echo "$ME_RESP" | jq -r '.tier // empty' 2>/dev/null)
1667
1667
  SYNKRO_CAPTURE_DEPTH=$(echo "$ME_RESP" | jq -r '.capture_depth // empty' 2>/dev/null)
1668
1668
  SYNKRO_INFERENCE_TIER="\${SYNKRO_INFERENCE_TIER:-fast}"
1669
1669
  SYNKRO_CAPTURE_DEPTH="\${SYNKRO_CAPTURE_DEPTH:-local_only}"
1670
1670
 
1671
1671
  if synkro_channel_up || { [ "$SYNKRO_INFERENCE_TIER" = "free" ] && command -v claude >/dev/null 2>&1; }; then
1672
- # \u2500\u2500\u2500 LOCAL PATH: channel-grader first, then \`claude --print\` cold fallback. \u2500\u2500\u2500
1673
-
1674
1672
  RULES_CACHE="$HOME/.synkro/.rules-cache-edit-capture"
1675
- RULES_RESP=""
1676
- if [ "$SYNKRO_CAPTURE_DEPTH" = "local_only" ]; then
1677
- RULES_RESP=$(curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules" \\
1678
- -H "Authorization: Bearer $JWT" --max-time 3 2>/dev/null || echo "")
1679
- else
1680
- RULES_RESP=$(printf '%s' "$FILE_CONTENT" | head -c 8000 \\
1681
- | jq -Rs '{content: .}' \\
1682
- | curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules?top_k=20" \\
1683
- -X POST -H "Content-Type: application/json" \\
1684
- -H "Authorization: Bearer $JWT" \\
1685
- -d @- --max-time 2 2>/dev/null || echo "")
1686
- fi
1687
- ORG_RULES=$(echo "$RULES_RESP" | jq -c '[.rules[]? | select(.hook_stage == "post" or .hook_stage == "both" or .hook_stage == null) | {rule_id, text, severity, category}]' 2>/dev/null || echo "[]")
1673
+ ORG_RULES=$(jq -c '[.rules[]? | select(.hook_stage == "post" or .hook_stage == "both" or .hook_stage == null) | {rule_id, text, severity, category}]' "$_RULES_TMP" 2>/dev/null || echo "[]")
1688
1674
  if [ -n "$ORG_RULES" ] && [ "$ORG_RULES" != "null" ] && [ "$ORG_RULES" != "[]" ]; then
1689
1675
  printf '%s' "$ORG_RULES" > "$RULES_CACHE" 2>/dev/null || true
1690
1676
  elif [ -f "$RULES_CACHE" ]; then
@@ -4839,7 +4825,7 @@ function writeConfigEnv(opts) {
4839
4825
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
4840
4826
  `SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
4841
4827
  `SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
4842
- `SYNKRO_VERSION=${shellQuoteSingle("1.4.10")}`
4828
+ `SYNKRO_VERSION=${shellQuoteSingle("1.4.11")}`
4843
4829
  ];
4844
4830
  if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
4845
4831
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);