@synkro-sh/cli 1.1.2 → 1.1.4
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 +32 -20
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -801,22 +801,17 @@ if [ "$SYNKRO_INFERENCE_TIER" = "free" ] && command -v claude >/dev/null 2>&1; t
|
|
|
801
801
|
# ~14s for cold \`claude --print\`. Falls back to direct \`claude --print\`
|
|
802
802
|
# if the daemon binary or primer is missing.
|
|
803
803
|
|
|
804
|
-
#
|
|
805
|
-
#
|
|
806
|
-
#
|
|
807
|
-
#
|
|
808
|
-
#
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
--max-time 1.5 2>/dev/null \\
|
|
812
|
-
| jq -c '[.rules[]? | {rule_id, text, severity, category, mode}]' 2>/dev/null || echo "[]")
|
|
813
|
-
if [ -z "$ORG_RULES" ] || [ "$ORG_RULES" = "null" ]; then ORG_RULES="[]"; fi
|
|
814
|
-
|
|
804
|
+
# The grader retrieves org rules ON DEMAND via the synkro-guardrails MCP
|
|
805
|
+
# server (registered in ~/.claude.json by \`synkro install\`). The primer
|
|
806
|
+
# tells the model to call get_guardrails before judging. We do NOT
|
|
807
|
+
# pre-stuff every rule into the prompt \u2014 that bloats the token budget,
|
|
808
|
+
# confuses the model with irrelevant rules, and breaks at scale. Cosine
|
|
809
|
+
# retrieval inside the MCP server returns only semantically-relevant
|
|
810
|
+
# rules per diff.
|
|
815
811
|
GRADER_PROMPT_FILE=$(mktemp -t synkro-grade.XXXXXX)
|
|
816
812
|
trap "rm -f \\"$GRADER_PROMPT_FILE\\"" EXIT
|
|
817
813
|
printf 'File: %s\\n' "$FILE_PATH" > "$GRADER_PROMPT_FILE"
|
|
818
|
-
printf 'User intent: %s\\n' "\${USER_INTENT:-none stated}" >> "$GRADER_PROMPT_FILE"
|
|
819
|
-
printf 'Org rules: %s\\n\\n' "$ORG_RULES" >> "$GRADER_PROMPT_FILE"
|
|
814
|
+
printf 'User intent: %s\\n\\n' "\${USER_INTENT:-none stated}" >> "$GRADER_PROMPT_FILE"
|
|
820
815
|
printf 'Diff:\\n' >> "$GRADER_PROMPT_FILE"
|
|
821
816
|
printf '%s\\n' "$PROPOSED" >> "$GRADER_PROMPT_FILE"
|
|
822
817
|
|
|
@@ -828,9 +823,17 @@ if [ "$SYNKRO_INFERENCE_TIER" = "free" ] && command -v claude >/dev/null 2>&1; t
|
|
|
828
823
|
|
|
829
824
|
VERDICT_JSON=$(printf '%s' "$CC_RESP" | tr '\\n' ' ' | grep -oE '<synkro-verdict>[^<]*</synkro-verdict>' | tail -1 | sed -E 's|^<synkro-verdict>||; s|</synkro-verdict>$||')
|
|
830
825
|
|
|
826
|
+
# If the local grader failed (timed out, crashed, returned malformed text,
|
|
827
|
+
# prompt overflowed) we MUST still POST to /local-verdict \u2014 server-side
|
|
828
|
+
# STEP 0 literal_match is the deterministic floor for absence-of-feature
|
|
829
|
+
# rules ("every TS file must start with // :)", "never use op inject",
|
|
830
|
+
# etc.) and has to fire regardless of LLM grader success. Falling through
|
|
831
|
+
# with a silent allow here was the bug \u2014 the server never saw the file
|
|
832
|
+
# so literal_match never ran. Default to ok:true so the server's audit
|
|
833
|
+
# path stays out of the way; literal_match runs on truncated content
|
|
834
|
+
# anyway in STEP 0.
|
|
831
835
|
if [ -z "$VERDICT_JSON" ]; then
|
|
832
|
-
|
|
833
|
-
exit 0
|
|
836
|
+
VERDICT_JSON='{"ok":true,"violations":[]}'
|
|
834
837
|
fi
|
|
835
838
|
|
|
836
839
|
LOCAL_BODY=$(jq -n \\
|
|
@@ -1629,14 +1632,23 @@ if __name__ == "__main__":
|
|
|
1629
1632
|
EACH GRADING REQUEST INCLUDES:
|
|
1630
1633
|
- File: the path being written
|
|
1631
1634
|
- User intent: what the user told the agent to do
|
|
1632
|
-
- Org rules: a JSON array of this organization's active policies, each with rule_id, text, severity, category. THESE ARE THE PRIMARY SOURCE OF TRUTH. If a rule's text describes behavior that matches the diff, flag it. Use that rule's rule_id verbatim, not a synthesized one.
|
|
1633
1635
|
- Diff: the proposed file content
|
|
1634
1636
|
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1637
|
+
WORKFLOW \u2014 TWO STEPS, IN THIS ORDER:
|
|
1638
|
+
|
|
1639
|
+
STEP 1: Retrieve the org's relevant rules via the synkro-guardrails MCP server. Call mcp__synkro-guardrails__get_guardrails ONCE with:
|
|
1640
|
+
- query: a one-sentence summary of WHAT THE DIFF DOES \u2014 describe the file's behavior in plain language. Focus on the action, the data flowing in, and the data flowing out (e.g. "route handler that takes user input and runs a database query", "component that reads a token from disk and includes it in an outbound HTTP request", "function that hashes a password before storing it").
|
|
1641
|
+
- top_k: 8
|
|
1642
|
+
|
|
1643
|
+
The server returns the most semantically-relevant rules (mix of cosine + keyword), each with rule_id, text, severity, category. THESE ARE YOUR PRIMARY SOURCE OF TRUTH for this org. If get_guardrails returns nothing or errors, proceed with baseline-only judging.
|
|
1644
|
+
|
|
1645
|
+
STEP 2: Judge the diff. Priority order:
|
|
1646
|
+
1. ORG RULES first. If the diff matches the prose of any returned rule, flag it \u2014 emit the rule's rule_id verbatim and the rule's severity. Don't second-guess the org's rules: a rule that bans an action class covers ALL forms of that action \u2014 splitting arguments across function calls, wrapping in helpers, or renaming a variable does NOT bypass it. The semantic intent of the rule and the diff is what matters, not the literal substring.
|
|
1647
|
+
2. BASELINE security issues (hardcoded real-looking secrets, eval/exec on user input, SQL string concat with untrusted input, MD5/SHA1 for security-sensitive purposes, unsafe deserialization, command injection, path traversal, missing auth on routes that mutate user/billing data, weak random for tokens, broken JWT verification, CORS misconfig, env-dump logging). Flag these even if no org rule covers them \u2014 they're universally bad. Use a sensible snake_case rule_id like \`no-hardcoded-secrets\`, \`eval-on-user-input\`, \`sql-string-concat\`.
|
|
1638
1648
|
3. Stylistic issues, placeholder fixtures, test files (path under /tests/, /__tests__/, *.test.*), and config-only files are NOT security issues \u2014 return ok=true.
|
|
1639
1649
|
|
|
1650
|
+
INDEPENDENCE: Each grade request is INDEPENDENT. Even if you can see prior turns in your context (the daemon reuses one process across grades), treat them as irrelevant. Judge ONLY the current request's File / User intent / Diff plus rules retrieved THIS turn. Prior "allows" do NOT authorize the current request \u2014 re-do the get_guardrails call every grade.
|
|
1651
|
+
|
|
1640
1652
|
OUTPUT RULES \u2014 strictest possible, no exceptions:
|
|
1641
1653
|
|
|
1642
1654
|
1. NO reasoning. NO preamble. NO commentary.
|
|
@@ -2071,7 +2083,7 @@ function writeConfigEnv(opts) {
|
|
|
2071
2083
|
`SYNKRO_GATEWAY_URL=${shellQuoteSingle(safeGateway)}`,
|
|
2072
2084
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
2073
2085
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
2074
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.1.
|
|
2086
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.1.4")}`
|
|
2075
2087
|
];
|
|
2076
2088
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
2077
2089
|
if (safeOrgId) lines.push(`SYNKRO_ORG_ID=${shellQuoteSingle(safeOrgId)}`);
|