github-actions[bot] commited on
Commit
4d448b3
·
1 Parent(s): 8eb015e

Deploy 01b0d87

Browse files

The agent can read the vector catalogue instead of remembering one

Source: https://github.com/WINTER4000/turingDNA/commit/01b0d87657c7fa96b312320edd6058984492315f

dee/core/agent_tools.py CHANGED
@@ -838,6 +838,55 @@ _REGION_RE = re.compile(r"^\s*(\d{1,9})\s*(?:\.\.|-|\u2013|:)\s*(\d{1,9})\s*$")
838
  _PLASMID_MAX_FEATURES = 40
839
 
840
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
841
  def _tool_edit_sequence(args: Dict[str, Any]) -> Dict[str, Any]:
842
  """Change the construct this conversation is working on.
843
 
@@ -1465,6 +1514,10 @@ _TOOLS: Dict[str, Dict[str, Any]] = {
1465
  # Pure UI direction — no compute, no storage, no account needed.
1466
  "focus_on": {"fn": _tool_focus_on, "requires_signin": False},
1467
  "map_plasmid": {"fn": _tool_map_plasmid, "requires_signin": False},
 
 
 
 
1468
  # The only tool that changes the construct. Three flags, each earning its
1469
  # place: signed-in because it writes; confirm because the user must agree
1470
  # to their own DNA being altered; needs_target because the sequence comes
@@ -1545,6 +1598,33 @@ TOOL_SPECS: List[Dict[str, Any]] = [
1545
  },
1546
  },
1547
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1548
  {
1549
  "type": "function",
1550
  "function": {
 
838
  _PLASMID_MAX_FEATURES = 40
839
 
840
 
841
+ def _tool_lookup_vector(args: Dict[str, Any]) -> Dict[str, Any]:
842
+ """What the catalogue says about a cloning backbone — and nothing else.
843
+
844
+ Exists because of a real transcript (2026-08-04): asked to build in
845
+ pCAMBIA1300, fetch_sequence correctly refused (it resolves genes, not
846
+ vectors), and the agent then recited the MCS from memory — inventing SbfI
847
+ and SmaI, dropping XhoI — and began designing a Golden Gate strategy on
848
+ it. The verified entry was in the app the whole time; the agent just had
849
+ no way to read it.
850
+
851
+ Reports the record verbatim. A vector that is not in the catalogue comes
852
+ back ok=False with the near matches, which is a fact to act on rather than
853
+ a gap to fill from recall.
854
+ """
855
+ from dee.core import vectors as _vec
856
+
857
+ name = str(args.get("name") or "").strip()
858
+ if not name:
859
+ return {"ok": False, "error": "Which vector? Give its name, e.g. pET-28a(+)."}
860
+
861
+ entry = _vec.find(name)
862
+ if entry:
863
+ return {"ok": True, "vector": entry, "source": "curated catalogue",
864
+ # Said out loud so the agent passes it on: this is a curated
865
+ # map, not the user's actual plasmid, and the two differ the
866
+ # moment anyone has modified their copy.
867
+ "caveat": ("Curated reference data (Addgene / NEB REBASE / "
868
+ "supplier sheets), not the user's own plasmid. If "
869
+ "they have modified their copy, ask them to paste "
870
+ "or upload it and map that instead."),
871
+ "note": ("These are the ONLY fields known for this vector. Do "
872
+ "not add restriction sites, coordinates or features "
873
+ "that are not listed here.")}
874
+
875
+ near = _vec.search(name, limit=6)
876
+ return {
877
+ "ok": False,
878
+ "kind": "not_in_catalogue",
879
+ "error": (f"“{name}” is not in the vector catalogue "
880
+ f"({_vec.catalogue_size()} backbones)."),
881
+ "did_you_mean": [e.get("name") for e in near],
882
+ # The whole point. A refusal here must not become a memory prompt.
883
+ "next": ("Do NOT describe this vector from memory — no MCS order, no "
884
+ "sizes, no feature coordinates. Either offer one of the "
885
+ "catalogue vectors above, or ask the user to paste/upload "
886
+ "their backbone so map_plasmid can read the real one."),
887
+ }
888
+
889
+
890
  def _tool_edit_sequence(args: Dict[str, Any]) -> Dict[str, Any]:
891
  """Change the construct this conversation is working on.
892
 
 
1514
  # Pure UI direction — no compute, no storage, no account needed.
1515
  "focus_on": {"fn": _tool_focus_on, "requires_signin": False},
1516
  "map_plasmid": {"fn": _tool_map_plasmid, "requires_signin": False},
1517
+ # Reads curated reference data. No auth: knowing what pET-28a is should
1518
+ # not require an account, and gating it would push an anonymous user back
1519
+ # toward the recalled answer this tool exists to replace.
1520
+ "lookup_vector": {"fn": _tool_lookup_vector, "requires_signin": False},
1521
  # The only tool that changes the construct. Three flags, each earning its
1522
  # place: signed-in because it writes; confirm because the user must agree
1523
  # to their own DNA being altered; needs_target because the sequence comes
 
1598
  },
1599
  },
1600
  },
1601
+ {
1602
+ "type": "function",
1603
+ "function": {
1604
+ "name": "lookup_vector",
1605
+ "description": (
1606
+ "Look up a cloning / expression BACKBONE (pET-28a, pUC19, "
1607
+ "pCAMBIA1300, pBI121, …) in the curated catalogue: size, "
1608
+ "promoter, selection markers, MCS enzymes, fusion tags, "
1609
+ "supplier. "
1610
+ "USE THIS whenever a vector is named — fetch_sequence resolves "
1611
+ "GENES and will refuse a vector, and a refusal is NOT "
1612
+ "permission to describe the vector from memory. "
1613
+ "If it is not in the catalogue, say so and offer the near "
1614
+ "matches, or ask the user to paste their backbone and run "
1615
+ "map_plasmid on the real thing. Never state an MCS order, a "
1616
+ "size or a feature coordinate that this tool did not return."
1617
+ ),
1618
+ "parameters": {
1619
+ "type": "object",
1620
+ "properties": {
1621
+ "name": {"type": "string",
1622
+ "description": "Vector name, e.g. 'pCAMBIA1300'."},
1623
+ },
1624
+ "required": ["name"],
1625
+ },
1626
+ },
1627
+ },
1628
  {
1629
  "type": "function",
1630
  "function": {
dee/core/orchestrator.py CHANGED
@@ -135,6 +135,7 @@ _TOOL_UI: Dict[str, Dict[str, Any]] = {
135
  "design_primers": {"view": "primers", "verb": "Checking primers"},
136
  "recommend_promoter": {"view": None, "verb": "Selecting promoter"},
137
  "map_plasmid": {"view": "plasmid", "verb": "Mapping the construct"},
 
138
  "edit_sequence": {"view": "plasmid", "verb": "Editing the construct"},
139
  # No painter: cut sites are an answer, not a canvas. Claiming the Map tab
140
  # for them would tell the user to look at a tab that never changed.
@@ -307,6 +308,12 @@ def _summarize(name: str, result: Dict[str, Any]) -> str:
307
  size = f"{result.get('length'):,} bp"
308
  return (f"{labels} · {size}" if not d
309
  else f"{labels} · {size} ({d:+d})")
 
 
 
 
 
 
310
  if name == "map_plasmid":
311
  n = result.get("feature_count") or 0
312
  return (f"{result.get('length'):,} bp {result.get('topology')} · "
@@ -1871,6 +1878,29 @@ SYSTEM_PROMPT = (
1871
  "propose_round2). You can reach every phase; don't hand the user off to a "
1872
  "tab to do something you can do here.\n\n"
1873
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1874
  "MAKE THE CHANGE, THEN CHECK IT\n"
1875
  "edit_sequence is the one tool that alters the construct. When someone "
1876
  "asks for a mutation, make it — do not describe the edit and leave them "
 
135
  "design_primers": {"view": "primers", "verb": "Checking primers"},
136
  "recommend_promoter": {"view": None, "verb": "Selecting promoter"},
137
  "map_plasmid": {"view": "plasmid", "verb": "Mapping the construct"},
138
+ "lookup_vector": {"view": None, "verb": "Looking up the vector"},
139
  "edit_sequence": {"view": "plasmid", "verb": "Editing the construct"},
140
  # No painter: cut sites are an answer, not a canvas. Claiming the Map tab
141
  # for them would tell the user to look at a tab that never changed.
 
308
  size = f"{result.get('length'):,} bp"
309
  return (f"{labels} · {size}" if not d
310
  else f"{labels} · {size} ({d:+d})")
311
+ if name == "lookup_vector":
312
+ v = result.get("vector") or {}
313
+ if v:
314
+ return (f"{v.get('name')} · {v.get('size_bp'):,} bp · "
315
+ f"{len(v.get('mcs_enzymes') or [])} MCS sites")
316
+ return "not in the catalogue"
317
  if name == "map_plasmid":
318
  n = result.get("feature_count") or 0
319
  return (f"{result.get('length'):,} bp {result.get('topology')} · "
 
1878
  "propose_round2). You can reach every phase; don't hand the user off to a "
1879
  "tab to do something you can do here.\n\n"
1880
 
1881
+ "A TOOL SAYING NO IS AN ANSWER, NOT AN OBSTACLE\n"
1882
+ "When a tool cannot find something, that is a FACT about the world and you "
1883
+ "report it. It is never permission to supply the missing data from "
1884
+ "memory.\n"
1885
+ "This is not hypothetical. Asked to build in pCAMBIA1300, fetch_sequence "
1886
+ "correctly refused — it resolves genes, and a vector backbone is not a "
1887
+ "gene. The reply was \"since I cannot fetch it, I will use its standard, "
1888
+ "well-characterized map\", followed by a recited MCS that invented two "
1889
+ "restriction sites and dropped a real one, and then a cloning strategy "
1890
+ "built on top of it. The refusal was right. Everything after it was "
1891
+ "fabricated, and it was heading for someone's bench.\n"
1892
+ "So, concretely — after ANY failed lookup you must not state from memory: "
1893
+ "a sequence or any part of one; an MCS or restriction-site order; a "
1894
+ "length, coordinate or feature position; a promoter, marker or tag; a "
1895
+ "published value of any kind. You have tools for these. Use the right one "
1896
+ "(lookup_vector for backbones, fetch_sequence for genes, map_plasmid for "
1897
+ "anything the user can paste), or say plainly that you don't have it and "
1898
+ "ask.\n"
1899
+ "\"I know this one\" is exactly the moment to stop. The user cannot tell "
1900
+ "your recall from your tools, and a confident wrong map is worse than no "
1901
+ "map — it is the one failure that costs them a synthesis order and weeks "
1902
+ "at the bench.\n\n"
1903
+
1904
  "MAKE THE CHANGE, THEN CHECK IT\n"
1905
  "edit_sequence is the one tool that alters the construct. When someone "
1906
  "asks for a mutation, make it — do not describe the edit and leave them "
dee/core/vectors.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """The vector catalogue, readable by the agent.
2
+
3
+ WHY THIS EXISTS (2026-08-04, from a live transcript)
4
+ -----------------------------------------------------
5
+ A user asked Turing to build a construct in pCAMBIA1300. `fetch_sequence`
6
+ correctly refused — it resolves GENES via Ensembl/UniProt, and a binary vector
7
+ backbone is not a gene. Turing then wrote:
8
+
9
+ "Since I cannot fetch the raw sequence of pCAMBIA1300 directly from the
10
+ database, I will design the cloning strategy using its standard,
11
+ well-characterized map."
12
+
13
+ ...and recited an MCS from memory:
14
+
15
+ HindIII - SbfI - PstI - SalI - XbaI - BamHI - SmaI - KpnI - SacI - EcoRI
16
+
17
+ The curated entry in dee/static/cloning_db.js — human-verified against Addgene
18
+ and the CAMBIA product sheet — says:
19
+
20
+ EcoRI, KpnI, XbaI, SalI, PstI, HindIII, BamHI, SacI, XhoI
21
+
22
+ SbfI and SmaI were invented; XhoI was dropped. A Golden Gate strategy was
23
+ being designed on top of that. The failure was not the refusal — the refusal
24
+ was correct and honest. The failure is that the app HAD the right answer and
25
+ the agent had no way to reach it, so it filled the gap from recall.
26
+
27
+ SINGLE SOURCE OF TRUTH
28
+ ----------------------
29
+ dee/data/vectors.json is EXTRACTED from cloning_db.js by executing the real
30
+ file (scripts/extract_vectors.js), never retyped — retyping 61 curated records
31
+ is the same transcription risk this module exists to remove. A test asserts
32
+ the two stay in agreement, so drift fails the suite instead of reaching a
33
+ bench.
34
+
35
+ This module reports what the catalogue says and nothing more. It does not
36
+ infer, complete or interpolate: a vector that is not in here comes back as
37
+ "not in the catalogue", which is a fact the agent can act on, rather than an
38
+ invitation to remember one.
39
+ """
40
+ from __future__ import annotations
41
+
42
+ import json
43
+ import os
44
+ import re
45
+ from typing import Any, Dict, List, Optional
46
+
47
+ _DATA = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
48
+ "data", "vectors.json")
49
+
50
+ _CACHE: Optional[Dict[str, Dict[str, Any]]] = None
51
+
52
+
53
+ def _load() -> Dict[str, Dict[str, Any]]:
54
+ global _CACHE
55
+ if _CACHE is None:
56
+ with open(_DATA, encoding="utf-8") as fh:
57
+ _CACHE = json.load(fh)
58
+ return _CACHE
59
+
60
+
61
+ def _norm(name: str) -> str:
62
+ """'pCAMBIA-1300' / 'pCAMBIA 1300' / 'PCAMBIA1300' -> 'pcambia1300'."""
63
+ return re.sub(r"[^a-z0-9]", "", str(name or "").lower())
64
+
65
+
66
+ def find(name: str) -> Optional[Dict[str, Any]]:
67
+ """Exact-ish lookup by id or display name. None when absent.
68
+
69
+ Deliberately NOT fuzzy. A near-match on a vector name is how pUC19 becomes
70
+ pUC18 and a whole cloning design shifts by one polylinker.
71
+ """
72
+ key = _norm(name)
73
+ if not key:
74
+ return None
75
+ data = _load()
76
+ if key in data:
77
+ return data[key]
78
+ for entry in data.values():
79
+ if _norm(entry.get("name", "")) == key or _norm(entry.get("id", "")) == key:
80
+ return entry
81
+ return None
82
+
83
+
84
+ def search(query: str, limit: int = 8) -> List[Dict[str, Any]]:
85
+ """Substring matches, for 'what pCAMBIA vectors do you have?'.
86
+
87
+ Returned so the agent can OFFER real options instead of guessing which
88
+ one the user meant.
89
+ """
90
+ q = _norm(query)
91
+ data = _load()
92
+ if not q:
93
+ return list(data.values())[:limit]
94
+ hits = [e for e in data.values()
95
+ if q in _norm(e.get("name", "")) or q in _norm(e.get("id", ""))]
96
+ return hits[:limit]
97
+
98
+
99
+ def catalogue_size() -> int:
100
+ return len(_load())
101
+
102
+
103
+ def all_names() -> List[str]:
104
+ return sorted(e.get("name", "") for e in _load().values())
dee/data/vectors.json ADDED
@@ -0,0 +1,1809 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "pet28a": {
3
+ "id": "pet28a",
4
+ "name": "pET-28a(+)",
5
+ "host": "e_coli",
6
+ "category": "bacterial_expression",
7
+ "size_bp": 5369,
8
+ "promoter": "T7 lac",
9
+ "induction": "IPTG (0.1–1 mM)",
10
+ "selection": [
11
+ "kanamycin (50 µg/mL)"
12
+ ],
13
+ "copy": "medium",
14
+ "fusion_tag": {
15
+ "n_term": "MGSSHHHHHHSSGLVPRGSHM (His6 + thrombin)",
16
+ "c_term": "LEHHHHHH (His6)"
17
+ },
18
+ "mcs_enzymes": [
19
+ "NcoI",
20
+ "NheI",
21
+ "NdeI",
22
+ "BamHI",
23
+ "EcoRV",
24
+ "EcoRI",
25
+ "SacI",
26
+ "SalI",
27
+ "HindIII",
28
+ "NotI",
29
+ "XhoI"
30
+ ],
31
+ "flanking_5p_max": "AAGGAGATATACCATGGCT",
32
+ "flanking_3p_max": "CTCGAGCACCACCACCACCACCACTGAGATCC",
33
+ "addgene": "69864-3",
34
+ "supplier": "Sigma-Aldrich / Novagen",
35
+ "notes": "Workhorse bacterial expression vector. T7 promoter requires DE3-lysogen host (BL21(DE3), Rosetta, etc.)."
36
+ },
37
+ "pet21a": {
38
+ "id": "pet21a",
39
+ "name": "pET-21a(+)",
40
+ "host": "e_coli",
41
+ "category": "bacterial_expression",
42
+ "size_bp": 5443,
43
+ "promoter": "T7 lac",
44
+ "induction": "IPTG",
45
+ "selection": [
46
+ "ampicillin (100 µg/mL)"
47
+ ],
48
+ "copy": "medium",
49
+ "fusion_tag": {
50
+ "n_term": "T7-tag (MASMTGGQQMG)",
51
+ "c_term": "LEHHHHHH (His6)"
52
+ },
53
+ "mcs_enzymes": [
54
+ "NdeI",
55
+ "NheI",
56
+ "BamHI",
57
+ "EcoRI",
58
+ "SacI",
59
+ "SalI",
60
+ "HindIII",
61
+ "NotI",
62
+ "EagI",
63
+ "XhoI"
64
+ ],
65
+ "flanking_5p_max": "AAGGAGATATACATATG",
66
+ "flanking_3p_max": "CTCGAGCACCACCACCACCACCACTGA",
67
+ "addgene": "69740",
68
+ "supplier": "Sigma / Novagen",
69
+ "notes": "Like pET-28a but amp-resistant and no N-term His tag."
70
+ },
71
+ "pet22b": {
72
+ "id": "pet22b",
73
+ "name": "pET-22b(+)",
74
+ "host": "e_coli",
75
+ "category": "bacterial_expression",
76
+ "size_bp": 5493,
77
+ "promoter": "T7 lac",
78
+ "induction": "IPTG",
79
+ "selection": [
80
+ "ampicillin"
81
+ ],
82
+ "copy": "medium",
83
+ "fusion_tag": {
84
+ "n_term": "pelB signal (periplasmic export)",
85
+ "c_term": "LEHHHHHH"
86
+ },
87
+ "mcs_enzymes": [
88
+ "NdeI",
89
+ "NcoI",
90
+ "BamHI",
91
+ "EcoRI",
92
+ "SacI",
93
+ "SalI",
94
+ "HindIII",
95
+ "NotI",
96
+ "XhoI"
97
+ ],
98
+ "flanking_5p_max": "AAGGAGATATACATATG",
99
+ "flanking_3p_max": "CTCGAGCACCACCACCACCACCACTGA",
100
+ "notes": "pelB signal peptide directs protein to the periplasm — useful for disulfide-containing or toxic proteins."
101
+ },
102
+ "pet32a": {
103
+ "id": "pet32a",
104
+ "name": "pET-32a(+)",
105
+ "host": "e_coli",
106
+ "category": "bacterial_expression",
107
+ "size_bp": 5900,
108
+ "promoter": "T7 lac",
109
+ "induction": "IPTG",
110
+ "selection": [
111
+ "ampicillin"
112
+ ],
113
+ "copy": "medium",
114
+ "fusion_tag": {
115
+ "n_term": "Trx + His6 + S-tag + thrombin",
116
+ "c_term": "His6"
117
+ },
118
+ "mcs_enzymes": [
119
+ "KpnI",
120
+ "BamHI",
121
+ "EcoRI",
122
+ "EcoRV",
123
+ "AvaI",
124
+ "HindIII",
125
+ "SalI",
126
+ "XhoI",
127
+ "NotI"
128
+ ],
129
+ "flanking_5p_max": "GGTACC",
130
+ "flanking_3p_max": "CTCGAG",
131
+ "notes": "N-terminal thioredoxin fusion enhances solubility of difficult proteins."
132
+ },
133
+ "pgex_6p_1": {
134
+ "id": "pgex_6p_1",
135
+ "name": "pGEX-6P-1",
136
+ "host": "e_coli",
137
+ "category": "bacterial_expression",
138
+ "size_bp": 4984,
139
+ "promoter": "tac",
140
+ "induction": "IPTG",
141
+ "selection": [
142
+ "ampicillin"
143
+ ],
144
+ "copy": "medium",
145
+ "fusion_tag": {
146
+ "n_term": "GST + PreScission protease site (LEVLFQ↓GP)",
147
+ "c_term": "none"
148
+ },
149
+ "mcs_enzymes": [
150
+ "BamHI",
151
+ "EcoRI",
152
+ "SmaI",
153
+ "SalI",
154
+ "XhoI",
155
+ "NotI"
156
+ ],
157
+ "flanking_5p_max": "CTGGAAGTTCTGTTCCAGGGGCCC",
158
+ "flanking_3p_max": "TAATAA",
159
+ "supplier": "Cytiva / GE Healthcare",
160
+ "notes": "N-terminal GST fusion (~26 kDa). Purify on glutathione resin, cleave with PreScission to release tag."
161
+ },
162
+ "pmal_c5x": {
163
+ "id": "pmal_c5x",
164
+ "name": "pMAL-c5X",
165
+ "host": "e_coli",
166
+ "category": "bacterial_expression",
167
+ "size_bp": 5677,
168
+ "promoter": "tac",
169
+ "induction": "IPTG",
170
+ "selection": [
171
+ "ampicillin"
172
+ ],
173
+ "copy": "medium",
174
+ "fusion_tag": {
175
+ "n_term": "MBP + Factor Xa site (IEGR↓)",
176
+ "c_term": "none"
177
+ },
178
+ "mcs_enzymes": [
179
+ "NdeI",
180
+ "EcoRI",
181
+ "BamHI",
182
+ "XbaI",
183
+ "SalI",
184
+ "PstI",
185
+ "HindIII"
186
+ ],
187
+ "flanking_5p_max": "GAAGGTAGGTCATATG",
188
+ "flanking_3p_max": "AAGCTT",
189
+ "supplier": "NEB",
190
+ "notes": "N-terminal MBP (~42 kDa) — strong solubility enhancer for difficult proteins."
191
+ },
192
+ "puc19": {
193
+ "id": "puc19",
194
+ "name": "pUC19",
195
+ "host": "e_coli",
196
+ "category": "general_cloning",
197
+ "size_bp": 2686,
198
+ "promoter": "lac (for α-complementation)",
199
+ "induction": "none",
200
+ "selection": [
201
+ "ampicillin"
202
+ ],
203
+ "copy": "high",
204
+ "fusion_tag": {
205
+ "n_term": "none",
206
+ "c_term": "none"
207
+ },
208
+ "mcs_enzymes": [
209
+ "EcoRI",
210
+ "SacI",
211
+ "KpnI",
212
+ "SmaI",
213
+ "BamHI",
214
+ "XbaI",
215
+ "SalI",
216
+ "AccI",
217
+ "HincII",
218
+ "PstI",
219
+ "SphI",
220
+ "HindIII"
221
+ ],
222
+ "flanking_5p_max": "GAATTC",
223
+ "flanking_3p_max": "AAGCTT",
224
+ "notes": "High-copy cloning vector. Blue-white screening via lacZα. No expression machinery — for shuttling DNA only."
225
+ },
226
+ "pbluescript": {
227
+ "id": "pbluescript",
228
+ "name": "pBluescript II SK(+)",
229
+ "host": "e_coli",
230
+ "category": "general_cloning",
231
+ "size_bp": 2961,
232
+ "promoter": "T7, T3 (for in vitro RNA)",
233
+ "induction": "n/a",
234
+ "selection": [
235
+ "ampicillin"
236
+ ],
237
+ "copy": "high",
238
+ "fusion_tag": {
239
+ "n_term": "none",
240
+ "c_term": "none"
241
+ },
242
+ "mcs_enzymes": [
243
+ "KpnI",
244
+ "ApaI",
245
+ "XhoI",
246
+ "SalI",
247
+ "AccI",
248
+ "HincII",
249
+ "ClaI",
250
+ "HindIII",
251
+ "EcoRV",
252
+ "EcoRI",
253
+ "PstI",
254
+ "SmaI",
255
+ "BamHI",
256
+ "SpeI",
257
+ "XbaI",
258
+ "NotI",
259
+ "SacII",
260
+ "SacI"
261
+ ],
262
+ "flanking_5p_max": "GGTACC",
263
+ "flanking_3p_max": "GAGCTC",
264
+ "supplier": "Agilent / Stratagene",
265
+ "notes": "Versatile cloning vector with flanking T7 + T3 promoters for in vitro RNA transcription from either strand."
266
+ },
267
+ "pcdf_duet": {
268
+ "id": "pcdf_duet",
269
+ "name": "pCDFDuet-1",
270
+ "host": "e_coli",
271
+ "category": "bacterial_expression",
272
+ "size_bp": 3781,
273
+ "promoter": "two T7 lac (dual MCS)",
274
+ "induction": "IPTG",
275
+ "selection": [
276
+ "streptomycin (50 µg/mL)"
277
+ ],
278
+ "copy": "low (CDF origin)",
279
+ "fusion_tag": {
280
+ "n_term": "optional His6 (MCS1)",
281
+ "c_term": "optional S-tag (MCS2)"
282
+ },
283
+ "mcs_enzymes": [
284
+ "NcoI",
285
+ "NdeI",
286
+ "BamHI",
287
+ "EcoRI",
288
+ "SacI",
289
+ "NotI",
290
+ "AvrII",
291
+ "PstI",
292
+ "HindIII",
293
+ "XhoI",
294
+ "BglII",
295
+ "KpnI",
296
+ "PacI"
297
+ ],
298
+ "flanking_5p_max": "AAGGAGATATACCATGG",
299
+ "flanking_3p_max": "CTCGAG",
300
+ "notes": "Dual-expression vector for co-expression with pET or pACYC partners (different antibiotics, different origins)."
301
+ },
302
+ "pcdna3_1": {
303
+ "id": "pcdna3_1",
304
+ "name": "pcDNA3.1(+)",
305
+ "host": "mammalian",
306
+ "category": "mammalian_expression",
307
+ "size_bp": 5428,
308
+ "promoter": "CMV",
309
+ "induction": "constitutive",
310
+ "selection": [
311
+ "ampicillin (E. coli)",
312
+ "G418/neomycin (mammalian)"
313
+ ],
314
+ "copy": "episomal in mammalian",
315
+ "fusion_tag": {
316
+ "n_term": "none (optional)",
317
+ "c_term": "none"
318
+ },
319
+ "mcs_enzymes": [
320
+ "NheI",
321
+ "AflII",
322
+ "HindIII",
323
+ "KpnI",
324
+ "BamHI",
325
+ "BstXI",
326
+ "EcoRI",
327
+ "EcoRV",
328
+ "NotI",
329
+ "XhoI",
330
+ "XbaI",
331
+ "ApaI"
332
+ ],
333
+ "flanking_5p_max": "GCTAGC",
334
+ "flanking_3p_max": "CTCGAGTCTAGAGG",
335
+ "supplier": "Invitrogen / Thermo Fisher",
336
+ "notes": "Standard CMV-driven mammalian expression vector. Includes BGH polyA and SV40 ori."
337
+ },
338
+ "pcdna3_4": {
339
+ "id": "pcdna3_4",
340
+ "name": "pcDNA3.4",
341
+ "host": "mammalian",
342
+ "category": "mammalian_expression",
343
+ "size_bp": 5810,
344
+ "promoter": "CMV",
345
+ "induction": "constitutive",
346
+ "selection": [
347
+ "ampicillin",
348
+ "G418"
349
+ ],
350
+ "copy": "episomal",
351
+ "mcs_enzymes": [
352
+ "NotI",
353
+ "NheI",
354
+ "AscI",
355
+ "HindIII",
356
+ "KpnI",
357
+ "EcoRI",
358
+ "BamHI",
359
+ "EcoRV",
360
+ "XhoI"
361
+ ],
362
+ "flanking_5p_max": "GCTAGC",
363
+ "flanking_3p_max": "CTCGAG",
364
+ "supplier": "Thermo Fisher",
365
+ "notes": "Optimized for CHO/HEK293 transient expression. Used for therapeutic antibody / protein production."
366
+ },
367
+ "pegfp_n1": {
368
+ "id": "pegfp_n1",
369
+ "name": "pEGFP-N1",
370
+ "host": "mammalian",
371
+ "category": "mammalian_expression",
372
+ "size_bp": 4733,
373
+ "promoter": "CMV",
374
+ "induction": "constitutive",
375
+ "selection": [
376
+ "kanamycin (E. coli)",
377
+ "G418 (mammalian)"
378
+ ],
379
+ "fusion_tag": {
380
+ "n_term": "none",
381
+ "c_term": "EGFP"
382
+ },
383
+ "mcs_enzymes": [
384
+ "NheI",
385
+ "AgeI",
386
+ "EcoRI",
387
+ "PstI",
388
+ "SalI",
389
+ "AccI",
390
+ "XhoI",
391
+ "BamHI",
392
+ "HindIII",
393
+ "SacII",
394
+ "KpnI",
395
+ "XmaI",
396
+ "SmaI"
397
+ ],
398
+ "flanking_5p_max": "GCTAGC",
399
+ "flanking_3p_max": "GGTACCGCGGGCCCGGGATCC",
400
+ "supplier": "Clontech / Takara",
401
+ "notes": "C-terminal EGFP fusion for live-cell imaging. Insert in frame at the MCS, just before the EGFP ORF."
402
+ },
403
+ "pyes2": {
404
+ "id": "pyes2",
405
+ "name": "pYES2",
406
+ "host": "yeast",
407
+ "category": "yeast_expression",
408
+ "size_bp": 5856,
409
+ "promoter": "GAL1 (galactose-inducible)",
410
+ "induction": "galactose 2%",
411
+ "selection": [
412
+ "ampicillin (E. coli)",
413
+ "URA3 (yeast — ura3- strain required)"
414
+ ],
415
+ "mcs_enzymes": [
416
+ "KpnI",
417
+ "BamHI",
418
+ "BstXI",
419
+ "EcoRI",
420
+ "NotI",
421
+ "XhoI",
422
+ "SphI",
423
+ "XbaI"
424
+ ],
425
+ "flanking_5p_max": "GGTACC",
426
+ "flanking_3p_max": "TCTAGA",
427
+ "supplier": "Invitrogen",
428
+ "notes": "S. cerevisiae GAL1-driven expression. Tight off-state on glucose; strong induction on galactose."
429
+ },
430
+ "ppicz": {
431
+ "id": "ppicz",
432
+ "name": "pPICZ-α",
433
+ "host": "pichia",
434
+ "category": "yeast_expression",
435
+ "size_bp": 3593,
436
+ "promoter": "AOX1 (methanol-inducible)",
437
+ "induction": "methanol",
438
+ "selection": [
439
+ "Zeocin (E. coli + yeast)"
440
+ ],
441
+ "fusion_tag": {
442
+ "n_term": "α-factor signal (secreted)",
443
+ "c_term": "optional Myc + His6"
444
+ },
445
+ "mcs_enzymes": [
446
+ "EcoRI",
447
+ "PmlI",
448
+ "SfiI",
449
+ "BstBI",
450
+ "AvrII",
451
+ "PvuII",
452
+ "NotI",
453
+ "SacII",
454
+ "XbaI"
455
+ ],
456
+ "flanking_5p_max": "GAATTC",
457
+ "flanking_3p_max": "TCTAGA",
458
+ "supplier": "Invitrogen",
459
+ "notes": "Pichia pastoris methanol-inducible expression with secretion signal. High protein yields."
460
+ },
461
+ "pet15b": {
462
+ "id": "pet15b",
463
+ "name": "pET-15b",
464
+ "host": "e_coli",
465
+ "category": "bacterial_expression",
466
+ "size_bp": 5708,
467
+ "promoter": "T7 lac",
468
+ "induction": "IPTG",
469
+ "selection": [
470
+ "ampicillin"
471
+ ],
472
+ "copy": "medium",
473
+ "fusion_tag": {
474
+ "n_term": "MGSSHHHHHHSSGLVPRGSHM (His6 + thrombin)",
475
+ "c_term": "none"
476
+ },
477
+ "mcs_enzymes": [
478
+ "NdeI",
479
+ "XhoI",
480
+ "BamHI"
481
+ ],
482
+ "flanking_5p_max": "AAGGAGATATACATATG",
483
+ "flanking_3p_max": "GGATCCTGA",
484
+ "supplier": "Sigma-Aldrich / Novagen",
485
+ "notes": "Compact pET vector with N-terminal His6 + thrombin cleavage. Smaller MCS than pET-28a."
486
+ },
487
+ "pet30a": {
488
+ "id": "pet30a",
489
+ "name": "pET-30a(+)",
490
+ "host": "e_coli",
491
+ "category": "bacterial_expression",
492
+ "size_bp": 5422,
493
+ "promoter": "T7 lac",
494
+ "induction": "IPTG",
495
+ "selection": [
496
+ "kanamycin"
497
+ ],
498
+ "copy": "medium",
499
+ "fusion_tag": {
500
+ "n_term": "His6 + thrombin + S-tag + enterokinase",
501
+ "c_term": "His6"
502
+ },
503
+ "mcs_enzymes": [
504
+ "NcoI",
505
+ "NdeI",
506
+ "NheI",
507
+ "BamHI",
508
+ "EcoRI",
509
+ "SacI",
510
+ "SalI",
511
+ "HindIII",
512
+ "NotI",
513
+ "XhoI"
514
+ ],
515
+ "flanking_5p_max": "AAGGAGATATACATATG",
516
+ "flanking_3p_max": "CTCGAGCACCACCACCACCACCAC",
517
+ "supplier": "Sigma-Aldrich / Novagen",
518
+ "notes": "Like pET-28a but with N-terminal S-tag and enterokinase site for tag removal."
519
+ },
520
+ "pet3a": {
521
+ "id": "pet3a",
522
+ "name": "pET-3a",
523
+ "host": "e_coli",
524
+ "category": "bacterial_expression",
525
+ "size_bp": 4640,
526
+ "promoter": "T7",
527
+ "induction": "IPTG",
528
+ "selection": [
529
+ "ampicillin"
530
+ ],
531
+ "copy": "medium",
532
+ "fusion_tag": {
533
+ "n_term": "T7 gene 10 leader (11 aa)",
534
+ "c_term": "none"
535
+ },
536
+ "mcs_enzymes": [
537
+ "NdeI",
538
+ "BamHI"
539
+ ],
540
+ "flanking_5p_max": "AAGGAGATATACATATG",
541
+ "flanking_3p_max": "GGATCCTGA",
542
+ "notes": "Minimal pET — tagless expression for downstream crystallography or activity studies."
543
+ },
544
+ "pbad_hisa": {
545
+ "id": "pbad_hisa",
546
+ "name": "pBAD/HisA",
547
+ "host": "e_coli",
548
+ "category": "bacterial_expression",
549
+ "size_bp": 4102,
550
+ "promoter": "araBAD (arabinose-inducible)",
551
+ "induction": "L-arabinose (0.0002–0.2%)",
552
+ "selection": [
553
+ "ampicillin"
554
+ ],
555
+ "copy": "medium",
556
+ "fusion_tag": {
557
+ "n_term": "His6 + Xpress epitope + enterokinase",
558
+ "c_term": "none"
559
+ },
560
+ "mcs_enzymes": [
561
+ "NcoI",
562
+ "PstI",
563
+ "KpnI",
564
+ "EcoRI",
565
+ "BglII",
566
+ "XhoI",
567
+ "EcoRV",
568
+ "NheI",
569
+ "HindIII"
570
+ ],
571
+ "flanking_5p_max": "CCATGG",
572
+ "flanking_3p_max": "AAGCTT",
573
+ "supplier": "Invitrogen",
574
+ "notes": "Tightly tunable expression via arabinose titration. Best for toxic proteins where leaky expression kills cells."
575
+ },
576
+ "pcold_i": {
577
+ "id": "pcold_i",
578
+ "name": "pCold I",
579
+ "host": "e_coli",
580
+ "category": "bacterial_expression",
581
+ "size_bp": 4407,
582
+ "promoter": "cspA (cold-shock)",
583
+ "induction": "15 °C cold shock + IPTG",
584
+ "selection": [
585
+ "ampicillin"
586
+ ],
587
+ "copy": "medium",
588
+ "fusion_tag": {
589
+ "n_term": "His6",
590
+ "c_term": "none"
591
+ },
592
+ "mcs_enzymes": [
593
+ "NdeI",
594
+ "SacI",
595
+ "KpnI",
596
+ "XhoI",
597
+ "BamHI",
598
+ "EcoRI",
599
+ "HindIII"
600
+ ],
601
+ "flanking_5p_max": "CATATG",
602
+ "flanking_3p_max": "GGATCC",
603
+ "supplier": "Takara Bio",
604
+ "notes": "Cold-shock induction at 15 °C improves folding of difficult proteins. Most host proteases inactive at this temperature."
605
+ },
606
+ "ptrc99a": {
607
+ "id": "ptrc99a",
608
+ "name": "pTrc99A",
609
+ "host": "e_coli",
610
+ "category": "bacterial_expression",
611
+ "size_bp": 4176,
612
+ "promoter": "trc (trp/lac hybrid)",
613
+ "induction": "IPTG",
614
+ "selection": [
615
+ "ampicillin"
616
+ ],
617
+ "copy": "medium",
618
+ "fusion_tag": {
619
+ "n_term": "none",
620
+ "c_term": "none"
621
+ },
622
+ "mcs_enzymes": [
623
+ "NcoI",
624
+ "EcoRI",
625
+ "SacI",
626
+ "KpnI",
627
+ "SmaI",
628
+ "BamHI",
629
+ "XbaI",
630
+ "SalI",
631
+ "AccI",
632
+ "HincII",
633
+ "PstI",
634
+ "SphI",
635
+ "HindIII"
636
+ ],
637
+ "flanking_5p_max": "CCATGG",
638
+ "flanking_3p_max": "AAGCTT",
639
+ "supplier": "Pharmacia / Cytiva",
640
+ "notes": "Trc promoter is stronger than lac, weaker than T7 — does not require DE3 strain. Tagless expression."
641
+ },
642
+ "pet_duet": {
643
+ "id": "pet_duet",
644
+ "name": "pETDuet-1",
645
+ "host": "e_coli",
646
+ "category": "bacterial_expression",
647
+ "size_bp": 5420,
648
+ "promoter": "two T7 lac (dual MCS)",
649
+ "induction": "IPTG",
650
+ "selection": [
651
+ "ampicillin"
652
+ ],
653
+ "copy": "medium (ColE1)",
654
+ "fusion_tag": {
655
+ "n_term": "His6 (MCS1)",
656
+ "c_term": "S-tag (MCS2)"
657
+ },
658
+ "mcs_enzymes": [
659
+ "NcoI",
660
+ "BamHI",
661
+ "EcoRI",
662
+ "SacI",
663
+ "NotI",
664
+ "SalI",
665
+ "HindIII",
666
+ "PstI",
667
+ "KpnI",
668
+ "AvrII",
669
+ "XhoI"
670
+ ],
671
+ "flanking_5p_max": "CCATGG",
672
+ "flanking_3p_max": "CTCGAG",
673
+ "notes": "Dual-expression for co-expressing two proteins from one plasmid. Compatible with pCDFDuet, pACYCDuet, pRSFDuet."
674
+ },
675
+ "pacyc_duet": {
676
+ "id": "pacyc_duet",
677
+ "name": "pACYCDuet-1",
678
+ "host": "e_coli",
679
+ "category": "bacterial_expression",
680
+ "size_bp": 4008,
681
+ "promoter": "two T7 lac (dual MCS)",
682
+ "induction": "IPTG",
683
+ "selection": [
684
+ "chloramphenicol (34 µg/mL)"
685
+ ],
686
+ "copy": "low (p15A ori)",
687
+ "fusion_tag": {
688
+ "n_term": "His6 (MCS1)",
689
+ "c_term": "S-tag (MCS2)"
690
+ },
691
+ "mcs_enzymes": [
692
+ "NcoI",
693
+ "BamHI",
694
+ "EcoRI",
695
+ "SacI",
696
+ "NotI",
697
+ "SalI",
698
+ "HindIII",
699
+ "PstI",
700
+ "KpnI",
701
+ "AvrII",
702
+ "XhoI"
703
+ ],
704
+ "flanking_5p_max": "CCATGG",
705
+ "flanking_3p_max": "CTCGAG",
706
+ "notes": "Compatible with pETDuet/pCDFDuet/pRSFDuet for up to 8-protein co-expression. Different antibiotic, different origin."
707
+ },
708
+ "pcoldtf": {
709
+ "id": "pcoldtf",
710
+ "name": "pCold TF",
711
+ "host": "e_coli",
712
+ "category": "bacterial_expression",
713
+ "size_bp": 5821,
714
+ "promoter": "cspA",
715
+ "induction": "15 °C cold shock + IPTG",
716
+ "selection": [
717
+ "ampicillin"
718
+ ],
719
+ "copy": "medium",
720
+ "fusion_tag": {
721
+ "n_term": "Trigger Factor (~48 kDa) + His6 + thrombin",
722
+ "c_term": "none"
723
+ },
724
+ "mcs_enzymes": [
725
+ "KpnI",
726
+ "SacI",
727
+ "BamHI",
728
+ "EcoRI",
729
+ "EcoRV",
730
+ "HindIII",
731
+ "SalI",
732
+ "PstI",
733
+ "XbaI",
734
+ "XhoI"
735
+ ],
736
+ "flanking_5p_max": "GGTACC",
737
+ "flanking_3p_max": "CTCGAG",
738
+ "supplier": "Takara Bio",
739
+ "notes": "Cold-shock + Trigger Factor chaperone fusion — strongest folding-rescue option for aggregation-prone proteins."
740
+ },
741
+ "psb1c3": {
742
+ "id": "psb1c3",
743
+ "name": "pSB1C3",
744
+ "host": "e_coli",
745
+ "category": "general_cloning",
746
+ "size_bp": 2070,
747
+ "promoter": "none (BioBrick assembly)",
748
+ "induction": "n/a",
749
+ "selection": [
750
+ "chloramphenicol"
751
+ ],
752
+ "copy": "high (pUC ori)",
753
+ "fusion_tag": {
754
+ "n_term": "none",
755
+ "c_term": "none"
756
+ },
757
+ "mcs_enzymes": [
758
+ "EcoRI",
759
+ "XbaI",
760
+ "SpeI",
761
+ "PstI",
762
+ "NotI"
763
+ ],
764
+ "flanking_5p_max": "GAATTCGCGGCCGCTTCTAGAG",
765
+ "flanking_3p_max": "TACTAGTAGCGGCCGCTGCAG",
766
+ "notes": "iGEM standard BioBrick assembly vector (RFC 10). Part insertion between BioBrick prefix and suffix."
767
+ },
768
+ "pcdna3_1_neg": {
769
+ "id": "pcdna3_1_neg",
770
+ "name": "pcDNA3.1(-)",
771
+ "host": "mammalian",
772
+ "category": "mammalian_expression",
773
+ "size_bp": 5427,
774
+ "promoter": "CMV",
775
+ "induction": "constitutive",
776
+ "selection": [
777
+ "ampicillin",
778
+ "G418/neomycin"
779
+ ],
780
+ "copy": "episomal",
781
+ "mcs_enzymes": [
782
+ "BamHI",
783
+ "EcoRI",
784
+ "EcoRV",
785
+ "BstXI",
786
+ "NotI",
787
+ "XhoI",
788
+ "XbaI",
789
+ "ApaI",
790
+ "KpnI",
791
+ "HindIII",
792
+ "AflII",
793
+ "NheI"
794
+ ],
795
+ "flanking_5p_max": "GGATCC",
796
+ "flanking_3p_max": "GCTAGC",
797
+ "supplier": "Invitrogen",
798
+ "notes": "Reverse MCS orientation of pcDNA3.1(+). Use when cloning in opposite reading direction is needed."
799
+ },
800
+ "pcdna4_to": {
801
+ "id": "pcdna4_to",
802
+ "name": "pcDNA4/TO",
803
+ "host": "mammalian",
804
+ "category": "mammalian_expression",
805
+ "size_bp": 5078,
806
+ "promoter": "CMV + Tet operator (2× TetO2)",
807
+ "induction": "tetracycline / doxycycline",
808
+ "selection": [
809
+ "ampicillin",
810
+ "Zeocin"
811
+ ],
812
+ "copy": "episomal",
813
+ "mcs_enzymes": [
814
+ "HindIII",
815
+ "KpnI",
816
+ "BamHI",
817
+ "EcoRI",
818
+ "EcoRV",
819
+ "NotI",
820
+ "XhoI",
821
+ "XbaI",
822
+ "ApaI",
823
+ "NheI"
824
+ ],
825
+ "flanking_5p_max": "AAGCTT",
826
+ "flanking_3p_max": "CTCGAG",
827
+ "supplier": "Invitrogen",
828
+ "notes": "Tet-on inducible mammalian expression. Use with T-REx host cell line (stable TetR expression)."
829
+ },
830
+ "pcdh_cmv": {
831
+ "id": "pcdh_cmv",
832
+ "name": "pCDH-CMV-MCS-EF1-Puro",
833
+ "host": "mammalian",
834
+ "category": "lentiviral",
835
+ "size_bp": 7385,
836
+ "promoter": "CMV (transgene) + EF1α (Puro selection)",
837
+ "induction": "constitutive",
838
+ "selection": [
839
+ "ampicillin (E. coli)",
840
+ "puromycin (mammalian)"
841
+ ],
842
+ "copy": "integrated",
843
+ "mcs_enzymes": [
844
+ "EcoRI",
845
+ "BamHI",
846
+ "NheI",
847
+ "XbaI",
848
+ "NotI",
849
+ "SwaI",
850
+ "EcoRV",
851
+ "SalI"
852
+ ],
853
+ "flanking_5p_max": "GAATTC",
854
+ "flanking_3p_max": "GCGGCCGC",
855
+ "supplier": "System Biosciences (SBI)",
856
+ "notes": "3rd-gen lentiviral transfer vector. Co-transfect with pPAX2 + pMD2.G to produce virus. Integrates into host genome."
857
+ },
858
+ "pires2_egfp": {
859
+ "id": "pires2_egfp",
860
+ "name": "pIRES2-EGFP",
861
+ "host": "mammalian",
862
+ "category": "mammalian_expression",
863
+ "size_bp": 5298,
864
+ "promoter": "CMV",
865
+ "induction": "constitutive",
866
+ "selection": [
867
+ "kanamycin (E. coli)",
868
+ "G418 (mammalian)"
869
+ ],
870
+ "copy": "episomal",
871
+ "fusion_tag": {
872
+ "n_term": "none (bicistronic — separate EGFP via IRES)",
873
+ "c_term": "none"
874
+ },
875
+ "mcs_enzymes": [
876
+ "NheI",
877
+ "EcoRI",
878
+ "PstI",
879
+ "SalI",
880
+ "AccI",
881
+ "XhoI",
882
+ "BamHI",
883
+ "BstXI",
884
+ "EcoRV",
885
+ "NotI",
886
+ "XbaI",
887
+ "SacII"
888
+ ],
889
+ "flanking_5p_max": "GCTAGC",
890
+ "flanking_3p_max": "TCTAGA",
891
+ "supplier": "Clontech / Takara",
892
+ "notes": "Bicistronic: gene-of-interest + IRES + EGFP. EGFP marks transfected cells without fusing to your protein."
893
+ },
894
+ "ptre3g": {
895
+ "id": "ptre3g",
896
+ "name": "pTRE3G",
897
+ "host": "mammalian",
898
+ "category": "mammalian_expression",
899
+ "size_bp": 3187,
900
+ "promoter": "PTRE3G (Tet-On 3G inducible)",
901
+ "induction": "doxycycline (1–1000 ng/mL)",
902
+ "selection": [
903
+ "ampicillin"
904
+ ],
905
+ "copy": "episomal",
906
+ "mcs_enzymes": [
907
+ "BamHI",
908
+ "MluI",
909
+ "SalI",
910
+ "NheI",
911
+ "EcoRI",
912
+ "NotI",
913
+ "PvuI",
914
+ "EcoRV",
915
+ "HindIII"
916
+ ],
917
+ "flanking_5p_max": "GGATCC",
918
+ "flanking_3p_max": "AAGCTT",
919
+ "supplier": "Clontech / Takara",
920
+ "notes": "Tightest tet-inducible system. Requires co-expression of Tet-On 3G transactivator (pCMV-Tet3G)."
921
+ },
922
+ "pcmv_ha": {
923
+ "id": "pcmv_ha",
924
+ "name": "pCMV-HA",
925
+ "host": "mammalian",
926
+ "category": "mammalian_expression",
927
+ "size_bp": 3787,
928
+ "promoter": "CMV",
929
+ "induction": "constitutive",
930
+ "selection": [
931
+ "ampicillin"
932
+ ],
933
+ "copy": "episomal",
934
+ "fusion_tag": {
935
+ "n_term": "HA epitope (YPYDVPDYA)",
936
+ "c_term": "none"
937
+ },
938
+ "mcs_enzymes": [
939
+ "SalI",
940
+ "AccI",
941
+ "XbaI",
942
+ "NotI",
943
+ "EcoRI",
944
+ "BglII",
945
+ "KpnI",
946
+ "SacI"
947
+ ],
948
+ "flanking_5p_max": "GTCGAC",
949
+ "flanking_3p_max": "GAGCTC",
950
+ "supplier": "Clontech",
951
+ "notes": "N-terminal HA tag for immunoprecipitation and detection. Anti-HA antibodies are well-validated."
952
+ },
953
+ "p3xflag_cmv10": {
954
+ "id": "p3xflag_cmv10",
955
+ "name": "p3xFLAG-CMV-10",
956
+ "host": "mammalian",
957
+ "category": "mammalian_expression",
958
+ "size_bp": 6259,
959
+ "promoter": "CMV",
960
+ "induction": "constitutive",
961
+ "selection": [
962
+ "ampicillin"
963
+ ],
964
+ "copy": "episomal",
965
+ "fusion_tag": {
966
+ "n_term": "3×FLAG (DYKDHDGDYKDHDIDYKDDDDK) + preprotrypsin signal",
967
+ "c_term": "none"
968
+ },
969
+ "mcs_enzymes": [
970
+ "NotI",
971
+ "HindIII",
972
+ "BglII",
973
+ "EcoRI",
974
+ "EcoRV",
975
+ "BamHI",
976
+ "SalI",
977
+ "KpnI",
978
+ "XbaI",
979
+ "XhoI"
980
+ ],
981
+ "flanking_5p_max": "AAGCTT",
982
+ "flanking_3p_max": "CTCGAG",
983
+ "supplier": "Sigma-Aldrich",
984
+ "notes": "Secreted 3×FLAG fusion. M2 anti-FLAG resin allows highly specific purification + competitive elution with FLAG peptide."
985
+ },
986
+ "plko1": {
987
+ "id": "plko1",
988
+ "name": "pLKO.1-puro",
989
+ "host": "mammalian",
990
+ "category": "lentiviral",
991
+ "size_bp": 7032,
992
+ "promoter": "U6 (shRNA) + PGK (Puro)",
993
+ "induction": "constitutive",
994
+ "selection": [
995
+ "ampicillin (E. coli)",
996
+ "puromycin (mammalian)"
997
+ ],
998
+ "copy": "integrated",
999
+ "mcs_enzymes": [
1000
+ "AgeI",
1001
+ "EcoRI"
1002
+ ],
1003
+ "flanking_5p_max": "ACCGG",
1004
+ "flanking_3p_max": "CTTTTTG",
1005
+ "addgene": "10878",
1006
+ "notes": "Standard lentiviral shRNA knockdown vector. Clone hairpin between AgeI and EcoRI behind U6 promoter."
1007
+ },
1008
+ "lenticrispr_v2": {
1009
+ "id": "lenticrispr_v2",
1010
+ "name": "lentiCRISPR v2",
1011
+ "host": "mammalian",
1012
+ "category": "lentiviral",
1013
+ "size_bp": 13044,
1014
+ "promoter": "EF1α-short (Cas9) + U6 (sgRNA)",
1015
+ "induction": "constitutive",
1016
+ "selection": [
1017
+ "ampicillin",
1018
+ "puromycin"
1019
+ ],
1020
+ "copy": "integrated",
1021
+ "mcs_enzymes": [
1022
+ "BsmBI"
1023
+ ],
1024
+ "flanking_5p_max": "CACCG",
1025
+ "flanking_3p_max": "GTTT",
1026
+ "addgene": "52961",
1027
+ "notes": "Single-plasmid CRISPR/Cas9 + sgRNA + Puro. Golden Gate BsmBI sgRNA cloning. Zhang lab."
1028
+ },
1029
+ "px330": {
1030
+ "id": "px330",
1031
+ "name": "pX330-U6-Chimeric_BB-CBh-hSpCas9",
1032
+ "host": "mammalian",
1033
+ "category": "mammalian_expression",
1034
+ "size_bp": 8484,
1035
+ "promoter": "CBh (Cas9) + U6 (sgRNA)",
1036
+ "induction": "constitutive",
1037
+ "selection": [
1038
+ "ampicillin"
1039
+ ],
1040
+ "copy": "episomal",
1041
+ "mcs_enzymes": [
1042
+ "BbsI"
1043
+ ],
1044
+ "flanking_5p_max": "CACCG",
1045
+ "flanking_3p_max": "GTTT",
1046
+ "addgene": "42230",
1047
+ "notes": "Non-viral all-in-one CRISPR/Cas9 + sgRNA expression. BbsI Golden Gate sgRNA cloning. Zhang lab."
1048
+ },
1049
+ "pgbkt7": {
1050
+ "id": "pgbkt7",
1051
+ "name": "pGBKT7",
1052
+ "host": "yeast",
1053
+ "category": "yeast_expression",
1054
+ "size_bp": 7301,
1055
+ "promoter": "ADH1",
1056
+ "induction": "constitutive",
1057
+ "selection": [
1058
+ "kanamycin (E. coli)",
1059
+ "TRP1 (yeast)"
1060
+ ],
1061
+ "copy": "low",
1062
+ "fusion_tag": {
1063
+ "n_term": "GAL4 DNA-binding domain (1–147) + Myc",
1064
+ "c_term": "none"
1065
+ },
1066
+ "mcs_enzymes": [
1067
+ "NdeI",
1068
+ "NcoI",
1069
+ "SfiI",
1070
+ "EcoRI",
1071
+ "SmaI",
1072
+ "BamHI",
1073
+ "SalI",
1074
+ "PstI"
1075
+ ],
1076
+ "flanking_5p_max": "CATATG",
1077
+ "flanking_3p_max": "AAGCTT",
1078
+ "supplier": "Clontech / Takara",
1079
+ "notes": "Yeast two-hybrid \"bait\" vector. Co-transform with pGADT7 prey in AH109/Y2HGold to screen interactions."
1080
+ },
1081
+ "pgadt7": {
1082
+ "id": "pgadt7",
1083
+ "name": "pGADT7",
1084
+ "host": "yeast",
1085
+ "category": "yeast_expression",
1086
+ "size_bp": 8000,
1087
+ "promoter": "ADH1",
1088
+ "induction": "constitutive",
1089
+ "selection": [
1090
+ "ampicillin (E. coli)",
1091
+ "LEU2 (yeast)"
1092
+ ],
1093
+ "copy": "high",
1094
+ "fusion_tag": {
1095
+ "n_term": "GAL4 activation domain (768–881) + HA",
1096
+ "c_term": "none"
1097
+ },
1098
+ "mcs_enzymes": [
1099
+ "NdeI",
1100
+ "SfiI",
1101
+ "NcoI",
1102
+ "EcoRI",
1103
+ "SmaI",
1104
+ "BamHI",
1105
+ "SacI",
1106
+ "XhoI"
1107
+ ],
1108
+ "flanking_5p_max": "CATATG",
1109
+ "flanking_3p_max": "CTCGAG",
1110
+ "supplier": "Clontech / Takara",
1111
+ "notes": "Yeast two-hybrid \"prey\" vector. Complements pGBKT7 — partner in Matchmaker Y2H system."
1112
+ },
1113
+ "pyd1": {
1114
+ "id": "pyd1",
1115
+ "name": "pYD1",
1116
+ "host": "yeast",
1117
+ "category": "yeast_expression",
1118
+ "size_bp": 5024,
1119
+ "promoter": "GAL1",
1120
+ "induction": "galactose 2%",
1121
+ "selection": [
1122
+ "ampicillin (E. coli)",
1123
+ "TRP1 (yeast)"
1124
+ ],
1125
+ "copy": "medium",
1126
+ "fusion_tag": {
1127
+ "n_term": "AGA2 signal + Aga2p (surface anchor) + HA",
1128
+ "c_term": "Myc"
1129
+ },
1130
+ "mcs_enzymes": [
1131
+ "NheI",
1132
+ "BamHI",
1133
+ "EcoRI",
1134
+ "NotI",
1135
+ "XhoI"
1136
+ ],
1137
+ "flanking_5p_max": "GCTAGC",
1138
+ "flanking_3p_max": "CTCGAG",
1139
+ "supplier": "Invitrogen",
1140
+ "notes": "Yeast surface display: protein displayed on cell wall via Aga1-Aga2 disulfide. Used for directed evolution by FACS."
1141
+ },
1142
+ "pcambia1300": {
1143
+ "id": "pcambia1300",
1144
+ "name": "pCAMBIA1300",
1145
+ "host": "plant",
1146
+ "category": "plant_expression",
1147
+ "size_bp": 8958,
1148
+ "promoter": "CaMV 35S (transgene cassette optional)",
1149
+ "induction": "n/a",
1150
+ "selection": [
1151
+ "kanamycin (bacteria)",
1152
+ "hygromycin (plant)"
1153
+ ],
1154
+ "copy": "low",
1155
+ "mcs_enzymes": [
1156
+ "EcoRI",
1157
+ "KpnI",
1158
+ "XbaI",
1159
+ "SalI",
1160
+ "PstI",
1161
+ "HindIII",
1162
+ "BamHI",
1163
+ "SacI",
1164
+ "XhoI"
1165
+ ],
1166
+ "flanking_5p_max": "GAATTC",
1167
+ "flanking_3p_max": "AAGCTT",
1168
+ "supplier": "CAMBIA",
1169
+ "notes": "Agrobacterium-mediated plant transformation binary vector. T-DNA borders flank the MCS."
1170
+ },
1171
+ "pbi121": {
1172
+ "id": "pbi121",
1173
+ "name": "pBI121",
1174
+ "host": "plant",
1175
+ "category": "plant_expression",
1176
+ "size_bp": 14758,
1177
+ "promoter": "CaMV 35S + NOS",
1178
+ "induction": "constitutive",
1179
+ "selection": [
1180
+ "kanamycin (bacteria + plant)"
1181
+ ],
1182
+ "copy": "low",
1183
+ "mcs_enzymes": [
1184
+ "HindIII",
1185
+ "XbaI",
1186
+ "SmaI",
1187
+ "BamHI",
1188
+ "SacI",
1189
+ "EcoRI"
1190
+ ],
1191
+ "flanking_5p_max": "TCTAGA",
1192
+ "flanking_3p_max": "GAGCTC",
1193
+ "supplier": "Clontech",
1194
+ "notes": "Classic Agrobacterium binary vector. GUS reporter in MCS — replace with your gene via XbaI + SacI."
1195
+ },
1196
+ "pgem_t_easy": {
1197
+ "id": "pgem_t_easy",
1198
+ "name": "pGEM-T Easy",
1199
+ "host": "e_coli",
1200
+ "category": "general_cloning",
1201
+ "size_bp": 3015,
1202
+ "promoter": "T7 + SP6 (in vitro RNA)",
1203
+ "induction": "n/a",
1204
+ "selection": [
1205
+ "ampicillin"
1206
+ ],
1207
+ "copy": "high",
1208
+ "mcs_enzymes": [
1209
+ "EcoRI",
1210
+ "BstZI",
1211
+ "NotI",
1212
+ "NdeI",
1213
+ "SacI",
1214
+ "SacII",
1215
+ "SpeI",
1216
+ "NsiI"
1217
+ ],
1218
+ "flanking_5p_max": "GAATTC",
1219
+ "flanking_3p_max": "GAATTC",
1220
+ "supplier": "Promega",
1221
+ "notes": "TA cloning vector with single 3′-T overhangs for direct ligation of Taq-amplified PCR products. Blue-white screening."
1222
+ },
1223
+ "pjet12": {
1224
+ "id": "pjet12",
1225
+ "name": "pJET1.2/blunt",
1226
+ "host": "e_coli",
1227
+ "category": "general_cloning",
1228
+ "size_bp": 2974,
1229
+ "promoter": "T7 (in vitro)",
1230
+ "induction": "n/a",
1231
+ "selection": [
1232
+ "ampicillin"
1233
+ ],
1234
+ "copy": "high",
1235
+ "mcs_enzymes": [
1236
+ "EcoRV (blunt)",
1237
+ "BglII",
1238
+ "XhoI",
1239
+ "XbaI",
1240
+ "BamHI",
1241
+ "NotI",
1242
+ "NcoI",
1243
+ "HindIII"
1244
+ ],
1245
+ "flanking_5p_max": "AGATCT",
1246
+ "flanking_3p_max": "AAGCTT",
1247
+ "supplier": "Thermo Fisher",
1248
+ "notes": "Blunt-end PCR cloning with positive selection (lethal eco47IR disrupted by insert). No blue-white needed."
1249
+ },
1250
+ "paav_mcs": {
1251
+ "id": "paav_mcs",
1252
+ "name": "pAAV-MCS",
1253
+ "host": "mammalian",
1254
+ "category": "aav",
1255
+ "size_bp": 5311,
1256
+ "promoter": "CMV",
1257
+ "induction": "constitutive",
1258
+ "selection": [
1259
+ "ampicillin"
1260
+ ],
1261
+ "copy": "packaged into AAV particles",
1262
+ "mcs_enzymes": [
1263
+ "EcoRI",
1264
+ "BamHI",
1265
+ "SalI",
1266
+ "PstI",
1267
+ "HindIII",
1268
+ "NotI",
1269
+ "XhoI",
1270
+ "XbaI"
1271
+ ],
1272
+ "flanking_5p_max": "GAATTC",
1273
+ "flanking_3p_max": "AAGCTT",
1274
+ "supplier": "Agilent / Stratagene",
1275
+ "notes": "AAV transfer vector. Co-transfect with pAAV-RC (rep/cap) + pHelper into HEK293 to produce virus. Insert capacity ~4.7 kb between ITRs."
1276
+ },
1277
+ "pfastbac1": {
1278
+ "id": "pfastbac1",
1279
+ "name": "pFastBac1",
1280
+ "host": "insect",
1281
+ "category": "baculovirus",
1282
+ "size_bp": 4776,
1283
+ "promoter": "polyhedrin (PH)",
1284
+ "induction": "baculovirus infection",
1285
+ "selection": [
1286
+ "ampicillin",
1287
+ "gentamicin (bacmid)"
1288
+ ],
1289
+ "copy": "medium",
1290
+ "mcs_enzymes": [
1291
+ "BamHI",
1292
+ "EcoRI",
1293
+ "SacI",
1294
+ "KpnI",
1295
+ "SmaI",
1296
+ "NotI",
1297
+ "XhoI",
1298
+ "XbaI",
1299
+ "SphI",
1300
+ "HindIII"
1301
+ ],
1302
+ "flanking_5p_max": "GGATCC",
1303
+ "flanking_3p_max": "AAGCTT",
1304
+ "supplier": "Invitrogen / Thermo Fisher",
1305
+ "notes": "Bac-to-Bac baculovirus expression. Transpose into DH10Bac bacmid, transfect Sf9/Sf21 cells. Strong PH-driven late expression."
1306
+ },
1307
+ "pfastbac_hta": {
1308
+ "id": "pfastbac_hta",
1309
+ "name": "pFastBac HT A",
1310
+ "host": "insect",
1311
+ "category": "baculovirus",
1312
+ "size_bp": 4856,
1313
+ "promoter": "polyhedrin (PH)",
1314
+ "induction": "baculovirus infection",
1315
+ "selection": [
1316
+ "ampicillin",
1317
+ "gentamicin"
1318
+ ],
1319
+ "copy": "medium",
1320
+ "fusion_tag": {
1321
+ "n_term": "His6 + TEV protease site (ENLYFQ↓G)",
1322
+ "c_term": "none"
1323
+ },
1324
+ "mcs_enzymes": [
1325
+ "BamHI",
1326
+ "EcoRI",
1327
+ "StuI",
1328
+ "SalI",
1329
+ "NotI",
1330
+ "NcoI",
1331
+ "PstI",
1332
+ "HindIII",
1333
+ "KpnI"
1334
+ ],
1335
+ "flanking_5p_max": "GGATCC",
1336
+ "flanking_3p_max": "AAGCTT",
1337
+ "supplier": "Invitrogen / Thermo Fisher",
1338
+ "notes": "Bac-to-Bac with N-terminal His6 + TEV site for cleavable affinity purification. Three frame variants (A/B/C)."
1339
+ },
1340
+ "prsf_duet": {
1341
+ "id": "prsf_duet",
1342
+ "name": "pRSFDuet-1",
1343
+ "host": "e_coli",
1344
+ "category": "bacterial_expression",
1345
+ "size_bp": 3829,
1346
+ "promoter": "two T7 lac (dual MCS)",
1347
+ "induction": "IPTG",
1348
+ "selection": [
1349
+ "kanamycin"
1350
+ ],
1351
+ "copy": "high (RSF ori)",
1352
+ "fusion_tag": {
1353
+ "n_term": "His6 (MCS1)",
1354
+ "c_term": "S-tag (MCS2)"
1355
+ },
1356
+ "mcs_enzymes": [
1357
+ "NcoI",
1358
+ "BamHI",
1359
+ "EcoRI",
1360
+ "SacI",
1361
+ "NotI",
1362
+ "SalI",
1363
+ "HindIII",
1364
+ "PstI",
1365
+ "KpnI",
1366
+ "AvrII",
1367
+ "XhoI"
1368
+ ],
1369
+ "flanking_5p_max": "CCATGG",
1370
+ "flanking_3p_max": "CTCGAG",
1371
+ "notes": "Highest-copy Duet vector. Compatible with pET / pCDF / pACYC Duets for multi-protein co-expression."
1372
+ },
1373
+ "pet24a": {
1374
+ "id": "pet24a",
1375
+ "name": "pET-24a(+)",
1376
+ "host": "e_coli",
1377
+ "category": "bacterial_expression",
1378
+ "size_bp": 5310,
1379
+ "promoter": "T7 lac",
1380
+ "induction": "IPTG",
1381
+ "selection": [
1382
+ "kanamycin"
1383
+ ],
1384
+ "copy": "medium",
1385
+ "fusion_tag": {
1386
+ "n_term": "T7 tag (optional)",
1387
+ "c_term": "LEHHHHHH"
1388
+ },
1389
+ "mcs_enzymes": [
1390
+ "NdeI",
1391
+ "NheI",
1392
+ "BamHI",
1393
+ "EcoRI",
1394
+ "SacI",
1395
+ "SalI",
1396
+ "HindIII",
1397
+ "NotI",
1398
+ "XhoI"
1399
+ ],
1400
+ "flanking_5p_max": "AAGGAGATATACATATG",
1401
+ "flanking_3p_max": "CTCGAGCACCACCACCACCACCAC",
1402
+ "notes": "Kanamycin-resistant version of pET-21a — C-terminal His6 only, no N-tag by default."
1403
+ },
1404
+ "pet43_1a": {
1405
+ "id": "pet43_1a",
1406
+ "name": "pET-43.1a (NusA)",
1407
+ "host": "e_coli",
1408
+ "category": "bacterial_expression",
1409
+ "size_bp": 7287,
1410
+ "promoter": "T7 lac",
1411
+ "induction": "IPTG",
1412
+ "selection": [
1413
+ "ampicillin"
1414
+ ],
1415
+ "copy": "medium",
1416
+ "fusion_tag": {
1417
+ "n_term": "NusA (~55 kDa) + His6 + thrombin",
1418
+ "c_term": "His6 + HSV-tag"
1419
+ },
1420
+ "mcs_enzymes": [
1421
+ "BamHI",
1422
+ "EcoRI",
1423
+ "SacI",
1424
+ "NotI",
1425
+ "EagI",
1426
+ "PstI",
1427
+ "SalI",
1428
+ "HindIII",
1429
+ "XhoI"
1430
+ ],
1431
+ "flanking_5p_max": "GGATCC",
1432
+ "flanking_3p_max": "CTCGAG",
1433
+ "supplier": "Sigma / Novagen",
1434
+ "notes": "NusA is the most effective E. coli solubility tag for aggregation-prone proteins (better than MBP/GST in many cases)."
1435
+ },
1436
+ "ptyb1": {
1437
+ "id": "ptyb1",
1438
+ "name": "pTYB1 (IMPACT)",
1439
+ "host": "e_coli",
1440
+ "category": "bacterial_expression",
1441
+ "size_bp": 7477,
1442
+ "promoter": "T7",
1443
+ "induction": "IPTG",
1444
+ "selection": [
1445
+ "ampicillin"
1446
+ ],
1447
+ "copy": "medium",
1448
+ "fusion_tag": {
1449
+ "n_term": "none",
1450
+ "c_term": "intein + chitin binding domain (CBD)"
1451
+ },
1452
+ "mcs_enzymes": [
1453
+ "NdeI",
1454
+ "NcoI",
1455
+ "NotI",
1456
+ "EcoRI",
1457
+ "BamHI",
1458
+ "EagI",
1459
+ "SmaI",
1460
+ "SapI"
1461
+ ],
1462
+ "flanking_5p_max": "CATATG",
1463
+ "flanking_3p_max": "TGCTCTTCCAAC",
1464
+ "supplier": "NEB (IMPACT system)",
1465
+ "notes": "C-terminal intein + CBD. Self-cleaves on chitin column with DTT — releases tag-free native protein with no proteolysis step."
1466
+ },
1467
+ "pcold_gst": {
1468
+ "id": "pcold_gst",
1469
+ "name": "pCold GST",
1470
+ "host": "e_coli",
1471
+ "category": "bacterial_expression",
1472
+ "size_bp": 5616,
1473
+ "promoter": "cspA (cold-shock)",
1474
+ "induction": "15 °C cold shock + IPTG",
1475
+ "selection": [
1476
+ "ampicillin"
1477
+ ],
1478
+ "copy": "medium",
1479
+ "fusion_tag": {
1480
+ "n_term": "GST + His6 + thrombin",
1481
+ "c_term": "none"
1482
+ },
1483
+ "mcs_enzymes": [
1484
+ "NdeI",
1485
+ "SacI",
1486
+ "KpnI",
1487
+ "XhoI",
1488
+ "BamHI",
1489
+ "EcoRI",
1490
+ "HindIII"
1491
+ ],
1492
+ "flanking_5p_max": "CATATG",
1493
+ "flanking_3p_max": "GGATCC",
1494
+ "supplier": "Takara Bio",
1495
+ "notes": "Cold-shock + GST solubility fusion — useful when both temperature control and GST tag are needed."
1496
+ },
1497
+ "pbr322": {
1498
+ "id": "pbr322",
1499
+ "name": "pBR322",
1500
+ "host": "e_coli",
1501
+ "category": "general_cloning",
1502
+ "size_bp": 4361,
1503
+ "promoter": "tet, amp (native promoters)",
1504
+ "induction": "n/a",
1505
+ "selection": [
1506
+ "ampicillin",
1507
+ "tetracycline"
1508
+ ],
1509
+ "copy": "medium (15–20 / cell)",
1510
+ "mcs_enzymes": [
1511
+ "EcoRI",
1512
+ "HindIII",
1513
+ "BamHI",
1514
+ "SalI",
1515
+ "PstI",
1516
+ "SphI",
1517
+ "ClaI",
1518
+ "NruI",
1519
+ "AvaI",
1520
+ "PvuII",
1521
+ "ScaI",
1522
+ "XmaIII"
1523
+ ],
1524
+ "flanking_5p_max": "GAATTC",
1525
+ "flanking_3p_max": "AAGCTT",
1526
+ "notes": "Classic foundational cloning vector. Lower copy than pUC19 — better for unstable inserts. Two antibiotic markers."
1527
+ },
1528
+ "pentr_d_topo": {
1529
+ "id": "pentr_d_topo",
1530
+ "name": "pENTR/D-TOPO (Gateway)",
1531
+ "host": "e_coli",
1532
+ "category": "gateway",
1533
+ "size_bp": 2580,
1534
+ "promoter": "none (entry clone)",
1535
+ "induction": "n/a",
1536
+ "selection": [
1537
+ "kanamycin"
1538
+ ],
1539
+ "copy": "high",
1540
+ "mcs_enzymes": [
1541
+ "(directional TOPO — CACC overhang)"
1542
+ ],
1543
+ "flanking_5p_max": "CACC",
1544
+ "flanking_3p_max": "",
1545
+ "supplier": "Invitrogen / Thermo Fisher",
1546
+ "notes": "Gateway entry vector. Clone via directional TOPO (5′ CACC overhang), then LR-recombine into any pDEST destination vector."
1547
+ },
1548
+ "pdonr221": {
1549
+ "id": "pdonr221",
1550
+ "name": "pDONR221 (Gateway)",
1551
+ "host": "e_coli",
1552
+ "category": "gateway",
1553
+ "size_bp": 4762,
1554
+ "promoter": "none (donor)",
1555
+ "induction": "n/a",
1556
+ "selection": [
1557
+ "kanamycin",
1558
+ "ccdB counterselection"
1559
+ ],
1560
+ "copy": "high",
1561
+ "mcs_enzymes": [
1562
+ "(attP1 / attP2 — BP clonase)"
1563
+ ],
1564
+ "flanking_5p_max": "GGGGACAAGTTTGTACAAAAAAGCAGGCT",
1565
+ "flanking_3p_max": "GGGGACCACTTTGTACAAGAAAGCTGGGT",
1566
+ "supplier": "Invitrogen",
1567
+ "notes": "Gateway donor vector. BP-recombine attB-flanked PCR product to make entry clone; then LR into destination."
1568
+ },
1569
+ "pbabe_puro": {
1570
+ "id": "pbabe_puro",
1571
+ "name": "pBABE-puro",
1572
+ "host": "mammalian",
1573
+ "category": "retroviral",
1574
+ "size_bp": 5169,
1575
+ "promoter": "5′ MoMuLV LTR (transgene) + SV40 (Puro)",
1576
+ "induction": "constitutive",
1577
+ "selection": [
1578
+ "ampicillin (E. coli)",
1579
+ "puromycin (mammalian)"
1580
+ ],
1581
+ "copy": "integrated",
1582
+ "mcs_enzymes": [
1583
+ "BamHI",
1584
+ "SnaBI",
1585
+ "SalI",
1586
+ "EcoRI",
1587
+ "NheI"
1588
+ ],
1589
+ "flanking_5p_max": "GGATCC",
1590
+ "flanking_3p_max": "GTCGAC",
1591
+ "addgene": "1764",
1592
+ "notes": "Classic Moloney MLV retroviral transfer vector. Co-transfect with packaging plasmids in Phoenix or 293T cells."
1593
+ },
1594
+ "plvx_ires_puro": {
1595
+ "id": "plvx_ires_puro",
1596
+ "name": "pLVX-IRES-Puro",
1597
+ "host": "mammalian",
1598
+ "category": "lentiviral",
1599
+ "size_bp": 8155,
1600
+ "promoter": "CMV (transgene + IRES + Puro)",
1601
+ "induction": "constitutive",
1602
+ "selection": [
1603
+ "ampicillin (E. coli)",
1604
+ "puromycin (mammalian)"
1605
+ ],
1606
+ "copy": "integrated",
1607
+ "mcs_enzymes": [
1608
+ "EcoRI",
1609
+ "BamHI",
1610
+ "XhoI",
1611
+ "NotI",
1612
+ "MluI",
1613
+ "XbaI",
1614
+ "SpeI"
1615
+ ],
1616
+ "flanking_5p_max": "GAATTC",
1617
+ "flanking_3p_max": "GCGGCCGC",
1618
+ "supplier": "Clontech / Takara",
1619
+ "notes": "3rd-gen lentivirus + IRES bicistronic Puro selection. Transgene and Puro from one transcript."
1620
+ },
1621
+ "pmscv_puro": {
1622
+ "id": "pmscv_puro",
1623
+ "name": "pMSCV-puro",
1624
+ "host": "mammalian",
1625
+ "category": "retroviral",
1626
+ "size_bp": 6347,
1627
+ "promoter": "MSCV 5′ LTR + PGK (Puro)",
1628
+ "induction": "constitutive",
1629
+ "selection": [
1630
+ "ampicillin",
1631
+ "puromycin"
1632
+ ],
1633
+ "copy": "integrated",
1634
+ "mcs_enzymes": [
1635
+ "BglII",
1636
+ "HpaI",
1637
+ "XhoI",
1638
+ "EcoRI"
1639
+ ],
1640
+ "flanking_5p_max": "AGATCT",
1641
+ "flanking_3p_max": "GAATTC",
1642
+ "supplier": "Clontech",
1643
+ "notes": "Murine stem cell virus (MSCV) LTR works well in hematopoietic / stem cells where MoMuLV LTR is silenced."
1644
+ },
1645
+ "pci_neo": {
1646
+ "id": "pci_neo",
1647
+ "name": "pCI-neo",
1648
+ "host": "mammalian",
1649
+ "category": "mammalian_expression",
1650
+ "size_bp": 5472,
1651
+ "promoter": "CMV (+ chimeric intron)",
1652
+ "induction": "constitutive",
1653
+ "selection": [
1654
+ "ampicillin",
1655
+ "G418/neomycin"
1656
+ ],
1657
+ "copy": "episomal",
1658
+ "mcs_enzymes": [
1659
+ "NheI",
1660
+ "EcoRI",
1661
+ "SacI",
1662
+ "KpnI",
1663
+ "MluI",
1664
+ "XhoI",
1665
+ "NotI",
1666
+ "XbaI",
1667
+ "BamHI",
1668
+ "SalI"
1669
+ ],
1670
+ "flanking_5p_max": "GCTAGC",
1671
+ "flanking_3p_max": "TCTAGA",
1672
+ "supplier": "Promega",
1673
+ "notes": "CMV + chimeric intron boosts expression ~2-fold over pcDNA3.1 in transient transfections."
1674
+ },
1675
+ "pcag_gfp": {
1676
+ "id": "pcag_gfp",
1677
+ "name": "pCAG-GFP",
1678
+ "host": "mammalian",
1679
+ "category": "mammalian_expression",
1680
+ "size_bp": 6230,
1681
+ "promoter": "CAG (CMV enhancer + chicken β-actin + rabbit β-globin intron)",
1682
+ "induction": "constitutive",
1683
+ "selection": [
1684
+ "ampicillin"
1685
+ ],
1686
+ "copy": "episomal",
1687
+ "fusion_tag": {
1688
+ "n_term": "none",
1689
+ "c_term": "EGFP"
1690
+ },
1691
+ "mcs_enzymes": [
1692
+ "EcoRI",
1693
+ "AgeI",
1694
+ "NheI"
1695
+ ],
1696
+ "flanking_5p_max": "GAATTC",
1697
+ "flanking_3p_max": "ACCGGT",
1698
+ "addgene": "11150",
1699
+ "notes": "CAG promoter gives very strong constitutive expression across many cell types — used in vivo (mouse) and in iPSC."
1700
+ },
1701
+ "pad_cmv_v5_dest": {
1702
+ "id": "pad_cmv_v5_dest",
1703
+ "name": "pAd/CMV/V5-DEST",
1704
+ "host": "mammalian",
1705
+ "category": "adenoviral",
1706
+ "size_bp": 36702,
1707
+ "promoter": "CMV",
1708
+ "induction": "constitutive",
1709
+ "selection": [
1710
+ "ampicillin (E. coli)"
1711
+ ],
1712
+ "copy": "packaged into Ad5 particles",
1713
+ "fusion_tag": {
1714
+ "n_term": "none (optional)",
1715
+ "c_term": "V5 + His6 (optional)"
1716
+ },
1717
+ "mcs_enzymes": [
1718
+ "(attR1 / attR2 — Gateway LR)"
1719
+ ],
1720
+ "flanking_5p_max": "CAAGTTTGTACAAAAAAGCTGAAC",
1721
+ "flanking_3p_max": "CAACTTTGTATAATAAAGTTG",
1722
+ "supplier": "Invitrogen",
1723
+ "notes": "Adenoviral expression via Gateway LR. Linearize with PacI, transfect 293A cells to produce Ad5 virus."
1724
+ },
1725
+ "pcdh1_mcs1": {
1726
+ "id": "pcdh1_mcs1",
1727
+ "name": "pCDH1-MCS1-EF1-copGFP",
1728
+ "host": "mammalian",
1729
+ "category": "lentiviral",
1730
+ "size_bp": 7559,
1731
+ "promoter": "CMV (transgene) + EF1α (copGFP)",
1732
+ "induction": "constitutive",
1733
+ "selection": [
1734
+ "ampicillin (E. coli)",
1735
+ "copGFP flow-sort (mammalian)"
1736
+ ],
1737
+ "copy": "integrated",
1738
+ "mcs_enzymes": [
1739
+ "EcoRI",
1740
+ "BamHI",
1741
+ "NheI",
1742
+ "NotI",
1743
+ "XbaI",
1744
+ "EcoRV",
1745
+ "SwaI",
1746
+ "ClaI",
1747
+ "SalI"
1748
+ ],
1749
+ "flanking_5p_max": "GAATTC",
1750
+ "flanking_3p_max": "GCGGCCGC",
1751
+ "supplier": "System Biosciences (SBI)",
1752
+ "notes": "Lentiviral transfer with copGFP marker — use FACS instead of antibiotic selection for transduced cells."
1753
+ },
1754
+ "px458": {
1755
+ "id": "px458",
1756
+ "name": "pSpCas9(BB)-2A-GFP (PX458)",
1757
+ "host": "mammalian",
1758
+ "category": "mammalian_expression",
1759
+ "size_bp": 9288,
1760
+ "promoter": "CBh (Cas9) + U6 (sgRNA)",
1761
+ "induction": "constitutive",
1762
+ "selection": [
1763
+ "ampicillin (E. coli)",
1764
+ "GFP FACS (mammalian)"
1765
+ ],
1766
+ "copy": "episomal",
1767
+ "fusion_tag": {
1768
+ "n_term": "none",
1769
+ "c_term": "2A-EGFP (Cas9 only)"
1770
+ },
1771
+ "mcs_enzymes": [
1772
+ "BbsI"
1773
+ ],
1774
+ "flanking_5p_max": "CACCG",
1775
+ "flanking_3p_max": "GTTT",
1776
+ "addgene": "48138",
1777
+ "notes": "Cas9 + sgRNA + 2A-GFP. Sort transfected cells by GFP+. Zhang lab."
1778
+ },
1779
+ "pmaltose_e": {
1780
+ "id": "pmaltose_e",
1781
+ "name": "pMAL-p5X (periplasmic)",
1782
+ "host": "e_coli",
1783
+ "category": "bacterial_expression",
1784
+ "size_bp": 5752,
1785
+ "promoter": "tac",
1786
+ "induction": "IPTG",
1787
+ "selection": [
1788
+ "ampicillin"
1789
+ ],
1790
+ "copy": "medium",
1791
+ "fusion_tag": {
1792
+ "n_term": "malE signal + MBP + Factor Xa",
1793
+ "c_term": "none"
1794
+ },
1795
+ "mcs_enzymes": [
1796
+ "NdeI",
1797
+ "EcoRI",
1798
+ "BamHI",
1799
+ "XbaI",
1800
+ "SalI",
1801
+ "PstI",
1802
+ "HindIII"
1803
+ ],
1804
+ "flanking_5p_max": "GAAGGTAGGTCATATG",
1805
+ "flanking_3p_max": "AAGCTT",
1806
+ "supplier": "NEB",
1807
+ "notes": "Periplasmic variant of pMAL — malE signal exports fusion to periplasm. Cytoplasmic MBP folding bypassed."
1808
+ }
1809
+ }
tests/test_confirm_gate.py CHANGED
@@ -302,6 +302,7 @@ _GATED = {
302
  _UNGATED = {
303
  # compute and return; nothing persists
304
  "fetch_sequence", "fold_structure", "map_plasmid", "find_cut_sites",
 
305
  "design_crispr_guides", "design_primers", "design_variant_library",
306
  "recommend_promoter", "check_interactions", "check_prior_art",
307
  "propose_round2",
 
302
  _UNGATED = {
303
  # compute and return; nothing persists
304
  "fetch_sequence", "fold_structure", "map_plasmid", "find_cut_sites",
305
+ "lookup_vector", # reads curated reference data; writes nothing
306
  "design_crispr_guides", "design_primers", "design_variant_library",
307
  "recommend_promoter", "check_interactions", "check_prior_art",
308
  "propose_round2",
tests/test_vector_lookup.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """The agent must not fill a failed lookup from memory.
2
+
3
+ From a live transcript, 2026-08-04. A user asked Turing to build a construct
4
+ in pCAMBIA1300. `fetch_sequence` refused — correctly; it resolves genes via
5
+ Ensembl/UniProt and a binary vector backbone is not a gene. Turing then wrote:
6
+
7
+ "Since I cannot fetch the raw sequence of pCAMBIA1300 directly from the
8
+ database, I will design the cloning strategy using its standard,
9
+ well-characterized map."
10
+
11
+ and recited an MCS:
12
+
13
+ HindIII - SbfI - PstI - SalI - XbaI - BamHI - SmaI - KpnI - SacI - EcoRI
14
+
15
+ The curated entry, human-verified against Addgene and the CAMBIA sheet, is:
16
+
17
+ EcoRI, KpnI, XbaI, SalI, PstI, HindIII, BamHI, SacI, XhoI
18
+
19
+ SbfI and SmaI do not appear in it. XhoI, which does, was dropped. A Golden
20
+ Gate strategy was then being designed on that map.
21
+
22
+ The refusal was not the bug. The bug is that the app HELD the verified answer
23
+ in a frontend-only file the agent could not read, so the only path it had left
24
+ was recall — and recall in this product reaches a synthesis order.
25
+
26
+ Two things are tested here:
27
+ 1. the data the agent now reads is the SAME data the UI shows (no second,
28
+ drifting copy of 61 curated records);
29
+ 2. a miss returns a refusal that closes the door on remembering, rather than
30
+ an empty result that invites it.
31
+ """
32
+ import json
33
+ import os
34
+ import re
35
+
36
+ from dee.core import agent_tools as t
37
+ from dee.core import orchestrator as orch
38
+ from dee.core import vectors as vec
39
+
40
+ _JS = "dee/static/cloning_db.js"
41
+ _JSON = "dee/data/vectors.json"
42
+
43
+
44
+ def _read(p):
45
+ with open(p, encoding="utf-8") as fh:
46
+ return fh.read()
47
+
48
+
49
+ # --------------------------------------------------------------------------- #
50
+ # one source of truth
51
+ # --------------------------------------------------------------------------- #
52
+ def test_the_catalogue_is_not_a_second_hand_copy():
53
+ """vectors.json is EXTRACTED from cloning_db.js by executing the real file
54
+ (scripts/extract_vectors.js). If the two ever drift, the agent and the UI
55
+ are telling a scientist different things about the same plasmid — which is
56
+ the original bug with extra steps."""
57
+ js = _read(_JS)
58
+ data = json.loads(_read(_JSON))
59
+ # Scope to the VECTORS block. cloning_db.js also defines ENZYMES, METHODS,
60
+ # TAGS and LINKERS at the same indent, and a bare `^ (\w+): {` sweeps
61
+ # all of them — the first version of this test failed on `gibson` and
62
+ # `golden_gate`, which are cloning METHODS and correctly absent here.
63
+ start = js.index("window.VECTORS = Object.freeze({")
64
+ end = js.index("\n});", start)
65
+ block = js[start:end]
66
+ ids_in_js = set(re.findall(r"^ ([a-z0-9_]+): \{", block, re.M))
67
+
68
+ missing = set(data) - ids_in_js
69
+ assert not missing, f"in vectors.json but not in cloning_db.js: {sorted(missing)}"
70
+ dropped = ids_in_js - set(data)
71
+ assert not dropped, f"UI knows these vectors, the agent does not: {sorted(dropped)}"
72
+ assert len(data) == len(ids_in_js) > 50, (len(data), len(ids_in_js))
73
+
74
+
75
+ def test_the_extractor_is_committed_so_the_json_can_be_rebuilt():
76
+ """A generated file with no generator is a hand-maintained file wearing a
77
+ disguise, and the next person will retype into it."""
78
+ assert os.path.exists("scripts/extract_vectors.js")
79
+ src = _read("scripts/extract_vectors.js")
80
+ assert "cloning_db.js" in src and "VECTORS" in src
81
+
82
+
83
+ # --------------------------------------------------------------------------- #
84
+ # the specific plasmid that broke
85
+ # --------------------------------------------------------------------------- #
86
+ def test_pcambia1300_resolves_to_the_verified_record():
87
+ out = t.execute_tool("lookup_vector", {"name": "pCAMBIA1300"},
88
+ auth_anonymous=True)
89
+ assert out["ok"] is True
90
+ v = out["vector"]
91
+ assert v["name"] == "pCAMBIA1300"
92
+ assert v["size_bp"] == 8958
93
+ assert v["mcs_enzymes"] == ["EcoRI", "KpnI", "XbaI", "SalI", "PstI",
94
+ "HindIII", "BamHI", "SacI", "XhoI"]
95
+
96
+
97
+ def test_the_invented_sites_are_not_in_the_real_record():
98
+ """The exact fabrication. SbfI and SmaI were recited into a cloning plan
99
+ for this vector; neither is in its curated MCS."""
100
+ v = vec.find("pCAMBIA1300")
101
+ for invented in ("SbfI", "SmaI"):
102
+ assert invented not in v["mcs_enzymes"], invented
103
+ # ...and the one that was dropped really is there
104
+ assert "XhoI" in v["mcs_enzymes"]
105
+
106
+
107
+ def test_a_vector_name_is_matched_the_way_people_type_it():
108
+ for spelling in ("pCAMBIA1300", "pcambia1300", "PCAMBIA-1300", "pCAMBIA 1300"):
109
+ assert vec.find(spelling), spelling
110
+
111
+
112
+ def test_matching_is_not_fuzzy():
113
+ """A near-match is how pUC19 silently becomes pUC18 and the whole
114
+ polylinker shifts. Better to miss and ask."""
115
+ assert vec.find("pCAMBIA1301") is None or \
116
+ vec.find("pCAMBIA1301")["name"] == "pCAMBIA1301"
117
+ assert vec.find("pCAM") is None
118
+
119
+
120
+ # --------------------------------------------------------------------------- #
121
+ # a miss must close the door, not open it
122
+ # --------------------------------------------------------------------------- #
123
+ def test_an_unknown_vector_is_refused_with_an_instruction_not_to_remember():
124
+ out = t.execute_tool("lookup_vector", {"name": "pNOTAREALVECTOR9000"},
125
+ auth_anonymous=True)
126
+ assert out["ok"] is False
127
+ assert out["kind"] == "not_in_catalogue"
128
+ nxt = out["next"].lower()
129
+ assert "memory" in nxt
130
+ # it must name the legitimate ways forward, or "don't guess" is a dead end
131
+ assert "paste" in nxt or "upload" in nxt
132
+ assert "map_plasmid" in out["next"]
133
+
134
+
135
+ def test_a_hit_still_says_it_is_reference_data_not_their_plasmid():
136
+ """A curated map and the user's actual tube diverge the moment they have
137
+ modified their copy. Presenting one as the other is a quieter version of
138
+ the same error."""
139
+ out = t.execute_tool("lookup_vector", {"name": "pET-28a(+)"},
140
+ auth_anonymous=True)
141
+ assert out["ok"] is True
142
+ assert "not the user's own plasmid" in out["caveat"]
143
+ assert "do not add" in out["note"].lower()
144
+
145
+
146
+ def test_the_tool_is_reachable_without_an_account():
147
+ """Gating it would push an anonymous user straight back to the recalled
148
+ answer this tool exists to replace."""
149
+ assert t._TOOLS["lookup_vector"]["requires_signin"] is False
150
+
151
+
152
+ # --------------------------------------------------------------------------- #
153
+ # the general rule, not just this plasmid
154
+ # --------------------------------------------------------------------------- #
155
+ def test_the_prompt_forbids_filling_a_failed_lookup_from_memory():
156
+ """The vector tool fixes one instance. The rule has to cover the class —
157
+ sequences, coordinates, promoters, published values."""
158
+ p = orch.build_system_prompt(False, {}, "")
159
+ assert "A TOOL SAYING NO IS AN ANSWER" in p
160
+ for forbidden in ("restriction-site order", "coordinate", "promoter"):
161
+ assert forbidden in p, forbidden
162
+ assert "lookup_vector" in p
163
+
164
+
165
+ def test_the_tool_description_points_away_from_fetch_sequence():
166
+ """The wrong-tool call is what started this: fetch_sequence was given a
167
+ vector name with organism='synthetic'."""
168
+ spec = next(s for s in orch.TOOL_SPECS
169
+ if s["function"]["name"] == "lookup_vector")
170
+ desc = spec["function"]["description"]
171
+ assert "fetch_sequence" in desc
172
+ assert "refusal is NOT" in desc