@@ -265,6 +265,95 @@ def test_build_payload_skips_loaded_agents_instructions_block(self):
265265 self .assertEqual (payload ["thread" ]["title" ], "actual request" )
266266 self .assertNotIn ("AI AGENT PROTOCOLS" , raw_payload )
267267
268+ def test_build_payload_skips_loaded_skill_content_block (self ):
269+ from sync import build_payload_from_hook
270+
271+ skill_block = """<skill>
272+ <name>claude-code-setup:spec-driven-planning</name>
273+ <path>/Users/buru/Library/Mobile Documents/com~apple~CloudDocs/dotfiles/config/claude/skills/spec-driven-planning/SKILL.md</path>
274+ ---
275+ name: spec-driven-planning
276+ description: Use this skill whenever the user asks for a spec.
277+ ---
278+
279+ # Spec-Driven Planning
280+ Do not upload this loaded skill body.
281+ </skill>"""
282+ with tempfile .TemporaryDirectory () as tmpdir :
283+ transcript = Path (tmpdir ) / "session.jsonl"
284+ transcript .write_text (
285+ "\n " .join (
286+ [
287+ json .dumps ({"type" : "session_meta" , "payload" : {"id" : "codex-skill" , "cwd" : "/Users/alice/work/jieli" }}),
288+ json .dumps (
289+ {
290+ "type" : "response_item" ,
291+ "payload" : {
292+ "type" : "message" ,
293+ "role" : "user" ,
294+ "content" : [{"type" : "input_text" , "text" : skill_block }],
295+ },
296+ }
297+ ),
298+ json .dumps (
299+ {
300+ "type" : "response_item" ,
301+ "payload" : {
302+ "type" : "message" ,
303+ "role" : "user" ,
304+ "content" : [{"type" : "input_text" , "text" : "actual request" }],
305+ },
306+ }
307+ ),
308+ ]
309+ )
310+ + "\n " ,
311+ encoding = "utf-8" ,
312+ )
313+
314+ payload = build_payload_from_hook (
315+ {"session_id" : "codex-skill" , "transcript_path" : str (transcript )},
316+ base_url = "https://jieli.example.test" ,
317+ )
318+
319+ raw_payload = json .dumps (payload , ensure_ascii = False )
320+ self .assertEqual (len (payload ["thread" ]["messages" ]), 1 )
321+ self .assertEqual (payload ["thread" ]["messages" ][0 ]["content" ], "actual request" )
322+ self .assertNotIn ("Spec-Driven Planning" , raw_payload )
323+ self .assertNotIn ("SKILL.md" , raw_payload )
324+
325+ def test_build_payload_strips_local_markdown_link_targets (self ):
326+ from sync import build_payload_from_hook
327+
328+ message = "use [$claude-code-setup:spec-driven-planning](/Users/buru/Library/Mobile Documents/com~apple~CloudDocs/dotfiles/config/claude/skills/spec-driven-planning/SKILL.md)"
329+ with tempfile .TemporaryDirectory () as tmpdir :
330+ transcript = Path (tmpdir ) / "session.jsonl"
331+ transcript .write_text (
332+ json .dumps ({"type" : "session_meta" , "payload" : {"id" : "codex-link" , "cwd" : "/Users/alice/work/jieli" }})
333+ + "\n "
334+ + json .dumps (
335+ {
336+ "type" : "response_item" ,
337+ "payload" : {
338+ "type" : "message" ,
339+ "role" : "user" ,
340+ "content" : [{"type" : "input_text" , "text" : message }],
341+ },
342+ }
343+ )
344+ + "\n " ,
345+ encoding = "utf-8" ,
346+ )
347+
348+ payload = build_payload_from_hook (
349+ {"session_id" : "codex-link" , "transcript_path" : str (transcript )},
350+ base_url = "https://jieli.example.test" ,
351+ )
352+
353+ content = payload ["thread" ]["messages" ][0 ]["content" ]
354+ self .assertEqual (content , "use $claude-code-setup:spec-driven-planning" )
355+ self .assertNotIn ("/Users/buru" , json .dumps (payload , ensure_ascii = False ))
356+
268357 def test_build_payload_includes_raw_repo_url_from_git_remote (self ):
269358 from sync import build_payload_from_hook
270359
0 commit comments