The single entry point for the ct-series across the full clinical-development lifecycle — a cloud-assisted clinical trial advisor. All questions (methodology / design / compliance / QC / site-execution / intelligence) are forwarded to the cloud Coze engine for analysis. The local side only performs a deterministic binary vague-gate (vague | forwarded) and attachment decoding; no knowledge base is retained locally, and no local network retrieval occurs. External reference: the teal clinical-data interactive exploration framework. / 面向临床研发全生命周期的 ct 系列「总入口」,云端辅助的临床试验总顾问。所有问题(方法学/设计/合规/QC/现场执行/情报)统一提交云端 Coze 引擎分析处理。本地仅做确定性二值闸门(是否 vague)与附件解码,不保留知识库,不进行本地网络检索。外部参考:teal 临床数据交互探索框架。
Re-publish rule: always overwrite with the existing appId — the link must stay https://ct-advisor.app.workbuddy.host/; never createNewApp. After deploy, assert the returned shareLink equals the expected URL (ct-base §13.5 dirty-binding red line). Last republished 2026-09-26.
This SKILL.md body is English-only, agent-facing. Bilingual walkthroughs live in the two READMEs; the answer language follows the user's question language.
🔴 HIGHEST PRIORITY: entry.py is the ONLY permitted action
The local LLM is FORBIDDEN from making any decisions in this skill. Its ONE AND ONLY allowed action is:
HARD GATE — the following are absolutely PROHIBITED for the local LLM:
❌ NEVER read, search, or reference any local knowledge base (the knowledge/ directory has been removed)
❌ NEVER perform any local network retrieval or web search (references/search-sites.md has been removed)
❌ NEVER answer the question from the LLM's own knowledge — all domain expertise lives on the Coze side
❌ NEVER bypass entry.py by calling route.py, refine_answer.py, orchestrate.py, or any other script directly
❌ NEVER rewrite, rephrase, reorder, summarize, or "polish" the text between <<<CT_ANSWER_START>>> and <<<CT_ANSWER_END>>>
❌ NEVER append a summary, lead-in, closing remark, or "key takeaways" before or after the delimiters
❌ NEVER strip or alter the checksum: line that follows <<<CT_ANSWER_END>>>
❌ NEVER translate or align language (the code already handles that)
❌ NEVER inject process narration ("Step 2", "Coze returned", "assembling payload")
❌ NEVER decide whether to forward to Coze — ALL questions are forwarded (entry.py handles routing internally)
Why this rule exists: The local LLM's "helpful" instincts (answering from its own knowledge, pre-reading files, post-formatting answers) have repeatedly violated the pipeline contract, destroyed Coze-delivered content formatting, altered numeric precision, injected unsolicited content, and bypassed the cloud analysis entirely. This rule eliminates ALL local LLM decision space.
How to use this skill
With a question only:
bash
python scripts/entry.py --q "In phase III NSCLC patients, comparing pembrolizumab vs chemotherapy, how is the sample size for the primary endpoint OS estimated?"
With an attachment:
bash
python scripts/entry.py --q "Is this document related to medicine?" --attach "/path/to/file.docx"
That's it. The stdout is the final answer — pipe it to the user verbatim.
What entry.py does internally (all code, zero LLM) — the canonical pipeline
text
STEP 1 Attachment gate (if --attach) — BOTH paths ship a FILE via doc_context
├─ < 5 MB → doc_memory.build_file_payload(allow_upload=True): upload ORIGINAL file to Coze /upload_file, ship as `doc_context` (mode=file_id; base64-forward fallback on failure)
└─ > 5 MB → convert locally (office_to_md.py for OOXML / direct read for txt-like), upload the resulting **.md** through the SAME doc_context channel + ℹ️ notice that cloud answers from the md version
STEP 2 Vague gate (deterministic regex, scripts/route.py — binary: vague | forwarded, the ONLY local gate): vague → clarify_loop.py (≤3 rounds) → questions to user, stop; forwarded → continue (Coze re-judges difficulty with its own LLM; timeout tier via route.timeout_tier)
STEP 3 Forward to Coze — orchestrate.run_orchestrate(payload): parallel Coze /run fire + local ct-skill prefetch → merge
STEP 4 Delegate stitch — if Coze returns <<<CT_TOOL_DELEGATE>>>, entry.py auto-runs refine_answer.py --card-inline (code, no LLM)
STEP 5 Output — stdout wrapped in <<<CT_ANSWER_START/END>>> + sha256 checksum
LLM-forbidden zone: every STEP above is executed by code. The local LLM
never picks the channel, never judges difficulty, never decides forwarding.
Output format:
text
<<<CT_ANSWER_START>>>
{answer text from Coze}
<<<CT_ANSWER_END>>>
checksum: {sha256[:16]}
🔴 sha256 Anti-tamper Check (HARD GATE):
After receiving the stdout from entry.py, the local LLM MUST verify the checksum before passing the answer to the user:
python
import hashlib, re
stdout = "...(entry.py output)..."
m = re.search(r'<<<CT_ANSWER_START>>>\n(.*?)\n<<<CT_ANSWER_END>>>\nchecksum: (.+)', stdout, re.DOTALL)
if m:
answer, expected_checksum = m.group(1), m.group(2).strip()
actual_checksum = hashlib.sha256(answer.encode("utf-8")).hexdigest()[:16]
if actual_checksum != expected_checksum:
# TAMPER DETECTED — do NOT pass to user
print("⚠️ answer integrity check failed, please retry.")
else:
# OK — pass answer verbatim
print(answer)
If the checksum does not match, the local LLM MUST NOT deliver the answer to the user. This prevents any silent tampering.
🔴 Single-run discipline (performance · as mandatory as the HARD GATE): entry.py is one complete Coze remote call and the main time cost of a single Q&A. The local LLM may call entry.py only ONCE per question and must capture its entire stdout into memory/a variable. The sha256 check MUST run against that SAME captured result — re-calling entry.py purely to perform the check is strictly forbidden (it sends an identical request to the Coze backend again, doubling the latency; in practice this once caused "the same question sent 2–3 times, a single Q&A dragging to 4 minutes"). If you need to persist output, write the stdout already captured from the first run rather than re-running.
Verification discipline (L3, 2026-09-25): The sha256 integrity check MUST be performed inline against the stdout captured in memory from the SAME entry.py call — i.e. immediately after capture, do re.search + hashlib.sha256 comparison in memory. Forbidden: writing stdout to a temp file just for the check, extra tool round-trips, or post-hoc temp-file cleanup. One extra file write/read/delete round-trip only adds agent-side latency and contributes nothing to the answer itself.
This skill has implemented three performance optimizations; see PERF_SOP.md for details:
L1 Resident orchestration service (scripts/serve.py + entry.py client): heavy modules are warmed up once, so local overhead → 0.
L2 Parallel warm-up (scripts/orchestrate.py): eliminates stacked serial imports.
L3 Inline verification discipline (see "Verification discipline" above): sha256 must be done inline in memory; writing temp files is forbidden.
⚠️ Deployment restriction (important): the skill directory lives on a network share whose ACL is creator-owner — you can create new files, but overwriting pre-installed existing files raises PermissionError 13, and deletion is also blocked by a trash hook. Therefore, any change to scripts/*.py / SKILL.md should be written as a same-directory .new copy, then overwritten on the user's local machine with move /Y (command in PERF_SOP.md §4, or run scripts/_perf_deploy.py).
Version drift: the resident service caches code; after updating skill files, the old service still runs old code until its 600s idle timeout. entry.py has a built-in /version probe that, before reusing an old service, compares the local orchestrate.py mtime — if the local copy is newer it auto-shuts-down the old service and launches the new version, with no manual restart needed.
Requirements
Item
Requirement
Runtime
python3 stdlib only
Sibling skills
Tier A · listed on SkillHub (non-confidential input, publicly released): ct-registry / ct-safety / ct-literature / ct-samplesize — auto-routed via Coze need_tool (entry.py handles card-inline execution). Tier A · NOT yet listed: ct-pipeline / ct-synthdata → unpublished_a, answer from Coze draft. Tier B (confidential input, not publicly released): ct-protocol / ct-csr / ct-analysis / ct-sdtm / ct-eligibility etc. — never installable.
Refiner (Coze)
scripts/entry.py (internal orchestrator via scripts/orchestrate.py) POSTs payload to ct-advisor.coze.site/run. Credential embedded in adapters/coze_token_embedded.py (obfuscated public token — keep as-is). 90s timeout / 300s long timeout.
External Refs
teal (insightsengineering) — clinical-data interactive exploration framework; Docling — structured PDF parsing. See "External Tool References".
Single gate = 5 MB, decided FIRST inside entry.py (v1.1.0 workflow correction, 2026-09-25). BOTH paths deliver a FILE to Coze through the same doc_context channel.
Size
Behavior
Channel
< 5 MB
Upload the original file directly — never converted locally
doc_memory.build_file_payload(allow_upload=True) → Coze /upload_file → doc_context (mode=file_id); on upload failure auto-degrades to the base64 forward channel (mode=file)
> 5 MB
Convert to Markdown locally, then upload the resulting .md as the attachment — same doc_context channel — plus an ℹ️ notice that the cloud answers from the md version
scripts/office_to_md.py (stdlib-only; OOXML) or direct read (.txt/.md/.csv/.tsv/.json); unsupported formats get an explicit user prompt
Coze decodes the original file natively for any Office format (OLE2 .doc/.xls/.ppt included), so fidelity is higher than any local conversion — this is why the <5 MB path uploads instead of converting.
Governance pointer: layered conversion strategy, user prompts and confidentiality boundary are consolidated in ct-base §6.7; the shared converter lives in ct-base/scripts/office_to_md.py (vendored copy).
Deliverable boundary — the revised document is never returned (v1.24). This skill's deliverable is text only: it does not generate, export, or hand back a modified document file. When the user asks for the revised file back, state plainly on the first line that this feature is not available — only written suggestions are provided, then give the suggestions as text the user can copy.
Quality Gate & Stop Rules
Presentation rules (user-mandated, hard) — deliver only the answer text between <<<CT_ANSWER_START>>> and <<<CT_ANSWER_END>>>. Never emit any workflow / process narration to the user.
🔔 Forward-mode user notice (the ONLY allowed process message) — entry.py emits a brief notice to stderr before firing the Coze call. The local LLM should not add any additional process chatter.
Outbound Authorization Gate
Runs automatically inside entry.py → scripts/orchestrate.py before each outbound HTTP call (agent never triggers it manually). Endpoint https://ct-advisor.coze.site/run is in auto_approve_endpoints by default, so it never prompts. If the user wants another endpoint whitelisted across sessions, the USER adds it explicitly to config.json — the agent MUST NOT edit config.json.
teal (insightsengineering, install.packages('teal')) — clinical-data interactive exploration framework for building Shiny review apps; reference model for the data-review integration mode.
On defect detection or explicit user request, adapters/bug_report.py offers a sanitized 11-key report to https://ct-bugreport.coze.site/run. Two-stage confirmation mandatory.