github-actions[bot] commited on
Commit
f018656
·
1 Parent(s): 2575dda

Deploy 58acaca

Browse files

The bench header names the construct, not the prompt

Source: https://github.com/WINTER4000/turingDNA/commit/58acacaad14a5c8f4ad07cddf1b41699cd81d8c9

dee/static/app.js CHANGED
@@ -9847,6 +9847,29 @@ function runOracle(opts){
9847
  function setMeta() {
9848
  metaEl.textContent = `${plasmid.length.toLocaleString()} bp · ${plasmid.topology} · GC ${plasmid.gc}%`
9849
  + ((plasmid.features || []).length ? ` · ${plasmid.features.length} features` : '');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9850
  }
9851
 
9852
  function _renderPlasmidMeta() {
@@ -10988,6 +11011,14 @@ function runOracle(opts){
10988
  /* What Turing reads and drives. The agent could already paint a construct
10989
  but had no idea a second one was open, so it could not answer "switch to
10990
  the other vector" — the most ordinary thing to ask once tabs exist. */
 
 
 
 
 
 
 
 
10991
  window.TDPlasmid.tabs = function () {
10992
  return plasmidTabs ? plasmidTabs.list() : [];
10993
  };
 
9847
  function setMeta() {
9848
  metaEl.textContent = `${plasmid.length.toLocaleString()} bp · ${plasmid.topology} · GC ${plasmid.gc}%`
9849
  + ((plasmid.features || []).length ? ` · ${plasmid.features.length} features` : '');
9850
+ syncBenchSpecimen();
9851
+ }
9852
+
9853
+ /* The bench header names what is on the bench.
9854
+
9855
+ It did not. Opening the bench from a live run labelled the specimen chip
9856
+ with the RUN's title — the sentence the scientist had just typed — and
9857
+ the sub-line with the literal words "live run", so a 19,895 bp pCambia
9858
+ showed up in its own header as "add a cds of fugfp upstream LUX-G and
9859
+ annotate it". The construct's identity was on screen twice (the map
9860
+ centre, the name field) and wrong in the one place that is supposed to
9861
+ be the answer to "what am I working on".
9862
+
9863
+ Called from setMeta, which every render path already goes through, so
9864
+ the header tracks tab switches and edits without another hook. */
9865
+ function syncBenchSpecimen() {
9866
+ if (!plasmid) return;
9867
+ if (document.body.getAttribute('data-bench') !== 'open') return;
9868
+ if (!window.TDBench || !window.TDBench.update) return;
9869
+ window.TDBench.update({
9870
+ name: plasmid.name || 'Construct',
9871
+ sub: `${(plasmid.length || 0).toLocaleString()} bp · ${plasmid.topology || ''}`.trim(),
9872
+ });
9873
  }
9874
 
9875
  function _renderPlasmidMeta() {
 
11011
  /* What Turing reads and drives. The agent could already paint a construct
11012
  but had no idea a second one was open, so it could not answer "switch to
11013
  the other vector" — the most ordinary thing to ask once tabs exist. */
11014
+ /* The identity of what the editor is holding, for whoever has to name it
11015
+ before a render has happened — the Cockpit opens the bench from a tool
11016
+ result and needs the construct, not the conversation, in the header. */
11017
+ window.TDPlasmid.construct = function () {
11018
+ if (!plasmid) return null;
11019
+ return { name: plasmid.name || '', length: plasmid.length || 0,
11020
+ topology: plasmid.topology || '' };
11021
+ };
11022
  window.TDPlasmid.tabs = function () {
11023
  return plasmidTabs ? plasmidTabs.list() : [];
11024
  };
dee/static/cockpit.js CHANGED
@@ -1729,8 +1729,23 @@
1729
  try {
1730
  if (window.TDBench && window.TDBench.openConstruct &&
1731
  document.body.getAttribute("data-bench") !== "open") {
 
 
 
 
 
 
 
 
 
 
 
 
1732
  window.TDBench.openConstruct({
1733
- name: currentTitle() || "Construct", sub: "live run",
 
 
 
1734
  phaseIdx: 0, route: view,
1735
  });
1736
  return;
 
1729
  try {
1730
  if (window.TDBench && window.TDBench.openConstruct &&
1731
  document.body.getAttribute("data-bench") !== "open") {
1732
+ /* Name the bench after the CONSTRUCT, not the sentence that
1733
+ started the run. This used to pass currentTitle() — the
1734
+ user's own prompt — plus the literal sub-line "live run",
1735
+ so opening the bench off a plasmid tool put "add a cds of
1736
+ fugfp upstream LUX-G and annotate it" in the header of a
1737
+ 19,895 bp pCambia. The run's title belongs to the run; it
1738
+ is already on the transcript. */
1739
+ var c = null;
1740
+ try {
1741
+ c = (window.TDPlasmid && window.TDPlasmid.construct)
1742
+ ? window.TDPlasmid.construct() : null;
1743
+ } catch (e) { c = null; }
1744
  window.TDBench.openConstruct({
1745
+ name: (c && c.name) || currentTitle() || "Construct",
1746
+ sub: c ? (Number(c.length || 0).toLocaleString() + " bp · "
1747
+ + c.topology).trim()
1748
+ : "live run",
1749
  phaseIdx: 0, route: view,
1750
  });
1751
  return;
dee/static/index.html CHANGED
@@ -112,7 +112,7 @@
112
  <!-- ?v= query bumps invalidate browser + iframe asset caches when app.css /
113
  app.js change. Bump these numbers whenever you ship a frontend update —
114
  without them, users keep getting the stale file for up to a week. -->
115
- <link rel="stylesheet" href="/static/app.css?v=20260828-anchor" />
116
  <!-- The work catalog + the draggable rail. Kept out of app.css so two new
117
  self-contained surfaces stay reviewable; every colour is an app.css
118
  token, so both themes work with nothing added. -->
@@ -3140,12 +3140,12 @@
3140
  <!-- Cloning reference data must load before app.js so the Designer
3141
  can read VECTORS / ENZYMES / CLONING_METHODS / TAGS / LINKERS. -->
3142
  <script src="/static/cloning_db.js?v=20260530-ui-polish" defer></script>
3143
- <script src="/static/context.js?v=20260828-anchor" defer></script>
3144
- <script src="/static/lineage.js?v=20260828-anchor" defer></script>
3145
  <!-- Before app.js: it mounts a strip at init. Both are `defer`, so they
3146
  run in document order. -->
3147
- <script src="/static/tabs.js?v=20260828-anchor" defer></script>
3148
- <script src="/static/app.js?v=20260828-anchor" defer></script>
3149
  <!-- The decision trace, BEFORE cockpit.js: applyEvent calls TDTrace.push
3150
  on the very first event, and both are `defer`, so document order is
3151
  load order. Loading it after would drop the opening events of a
@@ -3154,7 +3154,7 @@
3154
  <!-- THE COCKPIT — the persistent orchestrator rail. Loads after app.js so
3155
  TDBench/TDStructure exist when a tool result asks the workspace to
3156
  render something. This is the only conversation surface in the app. -->
3157
- <script src="/static/cockpit.js?v=20260828-anchor" defer></script>
3158
  <!-- structcard before catalog: the catalog calls TDStructCard.observe as
3159
  soon as it paints. Both are defer, so document order is load order. -->
3160
  <script src="/static/structcard.js?v=20260811-buildC" defer></script>
 
112
  <!-- ?v= query bumps invalidate browser + iframe asset caches when app.css /
113
  app.js change. Bump these numbers whenever you ship a frontend update —
114
  without them, users keep getting the stale file for up to a week. -->
115
+ <link rel="stylesheet" href="/static/app.css?v=20260829-specimen" />
116
  <!-- The work catalog + the draggable rail. Kept out of app.css so two new
117
  self-contained surfaces stay reviewable; every colour is an app.css
118
  token, so both themes work with nothing added. -->
 
3140
  <!-- Cloning reference data must load before app.js so the Designer
3141
  can read VECTORS / ENZYMES / CLONING_METHODS / TAGS / LINKERS. -->
3142
  <script src="/static/cloning_db.js?v=20260530-ui-polish" defer></script>
3143
+ <script src="/static/context.js?v=20260829-specimen" defer></script>
3144
+ <script src="/static/lineage.js?v=20260829-specimen" defer></script>
3145
  <!-- Before app.js: it mounts a strip at init. Both are `defer`, so they
3146
  run in document order. -->
3147
+ <script src="/static/tabs.js?v=20260829-specimen" defer></script>
3148
+ <script src="/static/app.js?v=20260829-specimen" defer></script>
3149
  <!-- The decision trace, BEFORE cockpit.js: applyEvent calls TDTrace.push
3150
  on the very first event, and both are `defer`, so document order is
3151
  load order. Loading it after would drop the opening events of a
 
3154
  <!-- THE COCKPIT — the persistent orchestrator rail. Loads after app.js so
3155
  TDBench/TDStructure exist when a tool result asks the workspace to
3156
  render something. This is the only conversation surface in the app. -->
3157
+ <script src="/static/cockpit.js?v=20260829-specimen" defer></script>
3158
  <!-- structcard before catalog: the catalog calls TDStructCard.observe as
3159
  soon as it paints. Both are defer, so document order is load order. -->
3160
  <script src="/static/structcard.js?v=20260811-buildC" defer></script>
tests/test_bench_header.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """The bench header names the construct, not the sentence that started the run.
2
+
3
+ A wiring assertion because the failure is silent and cosmetic-looking: the
4
+ header still renders, still styled, just describing the wrong thing. Opening
5
+ the bench from a live run labelled the specimen chip with the RUN's title, so
6
+ a 19,895 bp pCambia announced itself as "add a cds of fugfp upstream LUX-G
7
+ and annotate it" with "live run" underneath — while its real name sat in the
8
+ map centre two inches below.
9
+ """
10
+ import re
11
+
12
+ _APP_JS = "dee/static/app.js"
13
+ _COCKPIT_JS = "dee/static/cockpit.js"
14
+ _INDEX = "dee/static/index.html"
15
+
16
+
17
+ def _read(p):
18
+ with open(p, encoding="utf-8") as fh:
19
+ return fh.read()
20
+
21
+
22
+ def test_the_cockpit_opens_the_bench_with_the_construct_not_the_prompt():
23
+ js = _read(_COCKPIT_JS)
24
+ m = re.search(r"function gotoView\(view\)\s*\{(.*?)\n \}", js, re.S)
25
+ assert m, "gotoView moved — re-point this guard"
26
+ body = m.group(1)
27
+ assert "TDPlasmid.construct" in body, \
28
+ "gotoView must ask the editor what is loaded before naming the bench"
29
+ # the run's own title is the FALLBACK, never the first choice
30
+ name_line = re.search(r"name:\s*(.+)", body).group(1)
31
+ assert name_line.index("c.name") < name_line.index("currentTitle"), \
32
+ "the construct's name must win over the run title"
33
+ assert '"live run"' in body and "c ?" in body, \
34
+ "'live run' must only be the no-construct fallback"
35
+
36
+
37
+ def test_the_editor_exposes_what_it_is_holding():
38
+ js = _read(_APP_JS)
39
+ assert re.search(r"window\.TDPlasmid\.construct\s*=\s*function", js), \
40
+ "the Cockpit reads this to label the bench before any render runs"
41
+
42
+
43
+ def test_every_render_path_refreshes_the_header():
44
+ """setMeta is the choke point every render already goes through, so the
45
+ header follows tab switches and edits without a second hook."""
46
+ js = _read(_APP_JS)
47
+ m = re.search(r"function setMeta\(\)\s*\{(.*?)\n \}", js, re.S)
48
+ assert m, "setMeta moved — re-point this guard"
49
+ assert "syncBenchSpecimen()" in m.group(1)
50
+ sync = re.search(r"function syncBenchSpecimen\(\)\s*\{(.*?)\n \}", js, re.S)
51
+ assert sync, "syncBenchSpecimen missing"
52
+ b = sync.group(1)
53
+ assert "plasmid.name" in b and "plasmid.length" in b and "plasmid.topology" in b
54
+ assert 'data-bench' in b, "must not touch the header outside bench mode"
55
+
56
+
57
+ def test_the_cache_bust_token_moved_with_the_js():
58
+ """/static/* is served max-age=31536000; the ?v= token is the ONLY
59
+ invalidation. Shipping app.js without bumping it ships nothing."""
60
+ html = _read(_INDEX)
61
+ for asset in ("app.js", "cockpit.js"):
62
+ m = re.search(re.escape("/static/" + asset) + r"\?v=([0-9A-Za-z-]+)", html)
63
+ assert m, asset + " lost its cache-bust token"
64
+ assert m.group(1) != "20260828-anchor", \
65
+ asset + " still carries the pre-fix token"