cycode 3.17.3.dev3__py3-none-any.whl → 3.17.3.dev4__py3-none-any.whl

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.
cycode/__init__.py CHANGED
@@ -5,4 +5,4 @@ import time as _time
5
5
  # end-to-end scan duration from the moment the user actually triggered it.
6
6
  _BOOT_WALL: float = _time.time()
7
7
 
8
- __version__ = '3.17.3.dev3' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
8
+ __version__ = '3.17.3.dev4' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
@@ -157,6 +157,15 @@ class IDE(ABC):
157
157
  event (e.g. Cursor reading Claude Code hooks from ~/.claude/settings.json).
158
158
  """
159
159
 
160
+ def is_synthetic_prompt(self, raw_payload: dict) -> bool:
161
+ """Return True when a prompt event carries IDE/harness-generated content
162
+ rather than text the user typed.
163
+
164
+ Synthetic prompts are skipped without scanning or telemetry.
165
+ Default: False. Override for IDEs that inject synthetic user turns.
166
+ """
167
+ return False
168
+
160
169
  @abstractmethod
161
170
  def parse_hook_payload(self, raw_payload: dict) -> AIHookPayload:
162
171
  """Normalize a raw stdin payload into the canonical ``AIHookPayload``."""
@@ -22,6 +22,10 @@ logger = get_logger('AI Guardrails Claude Code')
22
22
 
23
23
  _CLAUDE_CODE_EVENT_NAMES = frozenset({'UserPromptSubmit', 'PreToolUse'})
24
24
 
25
+ # When a fork/subagent completes, the harness injects its result into the parent
26
+ # session as a synthetic user turn, which fires UserPromptSubmit.
27
+ _SYNTHETIC_PROMPT_PREFIXES = ('<task-notification>',)
28
+
25
29
  _USER_HOOKS_DIR = Path.home() / '.claude'
26
30
  _HOOKS_FILE_NAME = 'settings.json'
27
31
  _REPO_SUBDIR = '.claude'
@@ -284,6 +288,12 @@ class ClaudeCode(IDE):
284
288
  # processed as Claude Code events.
285
289
  return raw_payload.get('hook_event_name', '') in _CLAUDE_CODE_EVENT_NAMES and 'transcript_path' in raw_payload
286
290
 
291
+ def is_synthetic_prompt(self, raw_payload: dict) -> bool:
292
+ if raw_payload.get('hook_event_name') != 'UserPromptSubmit':
293
+ return False
294
+ prompt = raw_payload.get('prompt') or ''
295
+ return prompt.lstrip().startswith(_SYNTHETIC_PROMPT_PREFIXES)
296
+
287
297
  def parse_hook_payload(self, raw_payload: dict) -> AIHookPayload:
288
298
  hook_event_name = raw_payload.get('hook_event_name', '')
289
299
  tool_name = raw_payload.get('tool_name', '')
@@ -116,6 +116,14 @@ def scan_command(
116
116
  output_json(ide_integration.build_hook_response(HookDecision.allow(AiHookEventType.PROMPT)))
117
117
  return
118
118
 
119
+ # Fork/subagent completions arrive as synthetic user turns (e.g. Claude Code's
120
+ # <task-notification>); they are agent-generated, not user prompts - skip before
121
+ # parse_hook_payload, which reads the transcript and IDE config from disk.
122
+ if ide_integration.is_synthetic_prompt(payload):
123
+ logger.debug('Synthetic prompt detected, skipping scan')
124
+ output_json(ide_integration.build_hook_response(HookDecision.allow(AiHookEventType.PROMPT)))
125
+ return
126
+
119
127
  unified_payload = ide_integration.parse_hook_payload(payload)
120
128
  event_name = unified_payload.event_name
121
129
  logger.debug(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cycode
3
- Version: 3.17.3.dev3
3
+ Version: 3.17.3.dev4
4
4
  Summary: Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.
5
5
  License-Expression: MIT
6
6
  License-File: LICENCE
@@ -1,4 +1,4 @@
1
- cycode/__init__.py,sha256=rgVcASSONng6midnbKoXWeT9KedU31Q1WW54byov1rQ,396
1
+ cycode/__init__.py,sha256=VA0uw_JcyBxIL4fAcfbi56HxYm2tdrH7pzUcUAbFpWQ,396
2
2
  cycode/__main__.py,sha256=Z3bD5yrA7yPvAChcADQrqCaZd0ChGI1gdiwALwbWJ6U,104
3
3
  cycode/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  cycode/cli/app.py,sha256=AlR2durAEbsa47PDfIj7JtMvJDWA_Dq6wPtVuMJYSCs,10250
@@ -10,8 +10,8 @@ cycode/cli/apps/ai_guardrails/consts.py,sha256=Js2QtSNYG9Kt0eo3vepRd5TFciCeJHEC9
10
10
  cycode/cli/apps/ai_guardrails/hooks_manager.py,sha256=_8EjjpaDoeUrlh6gDXechWyev0LIGEZgcA9YJBl21xw,9314
11
11
  cycode/cli/apps/ai_guardrails/ides/__init__.py,sha256=9FPz984poZWPX6S6abuo-PThiXgJ_WpoUv47wiSXnKQ,2639
12
12
  cycode/cli/apps/ai_guardrails/ides/_plugin_utils.py,sha256=XPIc9pZFEgdGVTSSAl9yqI48F88GKlFnJ5FsLUhHjCE,3981
13
- cycode/cli/apps/ai_guardrails/ides/base.py,sha256=EvlAgGMkc9FlQehh_0XMhMOisuOGB8NGp-_GI7nj444,7860
14
- cycode/cli/apps/ai_guardrails/ides/claude_code.py,sha256=kjFoLRAJLZjhJdxpdU8HZgpJhVDvhyp9fwsfN_NzfwQ,14608
13
+ cycode/cli/apps/ai_guardrails/ides/base.py,sha256=RZintDpwWgl0l1cBVKccG4ek1jkTMuzRJ-hq91V5ehc,8224
14
+ cycode/cli/apps/ai_guardrails/ides/claude_code.py,sha256=ejLGzuVxrnVNOToJl--7HaTFTDI_N3jru8ZC8K0iIo8,15086
15
15
  cycode/cli/apps/ai_guardrails/ides/codex.py,sha256=1nI0TPeCgg2zI1PCVmLi0GouD8HGwGoa6RsIshDDa9c,11972
16
16
  cycode/cli/apps/ai_guardrails/ides/copilot.py,sha256=HYPoLd__CslG6z0LtfGshli-nJa-2ebiVuwM_tSM6ls,19109
17
17
  cycode/cli/apps/ai_guardrails/ides/cursor.py,sha256=-Jr76dD8m2xwvb0i93LtwjaloB_oon0OjBUPkv1K6f0,5633
@@ -21,7 +21,7 @@ cycode/cli/apps/ai_guardrails/scan/consts.py,sha256=drAslw6vW3kxmbCs2qPCUbUPR7PJ
21
21
  cycode/cli/apps/ai_guardrails/scan/handlers.py,sha256=pf5PrUIVnGLEEE6QKPny9at5V6Ms5u2IEtFP72hKgqA,15523
22
22
  cycode/cli/apps/ai_guardrails/scan/payload.py,sha256=pvT3UUqNMvdK3EVzzPjy4JMlOrF-WgxZ3fHN2AtN5eA,1126
23
23
  cycode/cli/apps/ai_guardrails/scan/policy.py,sha256=BZoNNdDQ9tqnfwhB4X1-bDtudaOQc_gXizm3IVwa28o,3351
24
- cycode/cli/apps/ai_guardrails/scan/scan_command.py,sha256=1qvPIdMlm8B5bW67sOA7qTS_dARkiUZcIpn4yNSAGh4,6606
24
+ cycode/cli/apps/ai_guardrails/scan/scan_command.py,sha256=G4pJ-ctTezft55pC0-AGf4HG3gtNp_EhoTiBX1_YP7w,7088
25
25
  cycode/cli/apps/ai_guardrails/scan/types.py,sha256=lDttkYFBfOkdMEEaRbq1IT2QTK0R-7Ht3T8vZdyB3b4,1038
26
26
  cycode/cli/apps/ai_guardrails/scan/utils.py,sha256=QzR_zmivDYwg2-F8g4bFfsycHhNo-pPuJly0P_l0gm8,2879
27
27
  cycode/cli/apps/ai_guardrails/session_start_command.py,sha256=05Li-ON2U1BU_8CR2YYw1y5HVvoWPTf19ne--EgPqmQ,5921
@@ -210,8 +210,8 @@ cycode/cyclient/report_client.py,sha256=Scq30NeJPzgXv0hPLO1U05AdE9i_2iu6cIrSKpEJ
210
210
  cycode/cyclient/scan_client.py,sha256=6TK5FQkfrvV7PHqRnUzEn1PBNd2oPYVamvIixcUfe3c,16755
211
211
  cycode/cyclient/scan_config_base.py,sha256=mXsPZGYCtp85rv5GIige40yQZXuRcEKUW-VQJ0vgFzk,1201
212
212
  cycode/logger.py,sha256=EfZGRK6VC5rE_LAjIcRrHFiQCueylCDXoG6bvGkrIME,2111
213
- cycode-3.17.3.dev3.dist-info/METADATA,sha256=N5ucWK2_MHWg5DJn0tHPJvGXG3L5Qnn55ed36wPL_eI,89246
214
- cycode-3.17.3.dev3.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
215
- cycode-3.17.3.dev3.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
216
- cycode-3.17.3.dev3.dist-info/licenses/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
217
- cycode-3.17.3.dev3.dist-info/RECORD,,
213
+ cycode-3.17.3.dev4.dist-info/METADATA,sha256=oXPq8qCG2UBNS4GDCmUbkVKo9pSTcopKjTETFKDwf1I,89246
214
+ cycode-3.17.3.dev4.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
215
+ cycode-3.17.3.dev4.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
216
+ cycode-3.17.3.dev4.dist-info/licenses/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
217
+ cycode-3.17.3.dev4.dist-info/RECORD,,