Viney Claude Opus 5 (1M context) commited on
Commit
2248b5b
·
1 Parent(s): d2a33ff

fix: close four review minors on the attention-ordered brief

Browse files

- tone_strip._reading split on the Unicode arrow only while _SERIES_RE
already accepted "->" as well, so an upstream ASCII normalisation would
have kept the rate series working while the plain-language reading
silently vanished. Both halves of the parser are now tolerant.

- test_kpi_footnote_html_is_byte_identical_without_source_url copied the
footnote composition out of _render_quarter_kpis and asserted on the
copy, so changing the separator left it green while it claimed to be a
regression net. Replaced with a spy on verdict.st.markdown driving the
real renderer -- confirmed to fail when the separator is changed, which
the old test did not. test_kpi_source_note_is_exact_empty_string...
is kept as-is.

- attention_view._evasion_deltas duplicated evasion_deltas; it now
delegates, with a test pinning that the two agree across every delta
shape including a non-string kind.

- Roadmap: record explicitly that the consensus-archive work must add a
live reader of display_policy["market_expectations_aligned"]. This
branch deleted market_read.py, the flag's only (dead) consumer, and no
roadmap item was carrying the requirement.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

dashboard/attention_view.py CHANGED
@@ -58,10 +58,10 @@ def _fmt_period(period: str) -> str:
58
 
59
 
60
  def _evasion_deltas(brief: dict) -> list[dict]:
61
- return [
62
- d for d in (brief.get("quarter_deltas") or [])
63
- if isinstance(d, dict) and d.get("kind") == "recurring_evasion"
64
- ]
65
 
66
 
67
  def _heatmap(clusters: list[dict]) -> str:
 
58
 
59
 
60
  def _evasion_deltas(brief: dict) -> list[dict]:
61
+ """Kept as the in-module name the heatmap view reads; the selection itself
62
+ lives in `evasion_deltas` below, which The Brief's summary panel and
63
+ verdict.brief_block_order also call."""
64
+ return evasion_deltas(brief)
65
 
66
 
67
  def _heatmap(clusters: list[dict]) -> str:
dashboard/tone_strip.py CHANGED
@@ -31,6 +31,10 @@ from dashboard.theme import (
31
  # tone_drift.compute_tone_trend's `trajectory = "→".join(...)`.
32
  _SERIES_RE = re.compile(r"\d+(?:\.\d+)?(?:\s*(?:→|->)\s*\d+(?:\.\d+)?)+")
33
  _NUMBER_RE = re.compile(r"\d+(?:\.\d+)?")
 
 
 
 
34
 
35
 
36
  def parse_rates(computed_metric: str) -> list[float]:
@@ -56,9 +60,10 @@ def tone_deltas(brief: dict) -> list[dict]:
56
  def _reading(computed_metric: str) -> str:
57
  """The analyser's plain-language reading, e.g. "more cautious".
58
 
59
- tone_drift formats it as the trailing "→ <reading>" segment.
 
60
  """
61
- parts = str(computed_metric or "").split("→")
62
  return parts[-1].strip() if len(parts) > 1 else ""
63
 
64
 
 
31
  # tone_drift.compute_tone_trend's `trajectory = "→".join(...)`.
32
  _SERIES_RE = re.compile(r"\d+(?:\.\d+)?(?:\s*(?:→|->)\s*\d+(?:\.\d+)?)+")
33
  _NUMBER_RE = re.compile(r"\d+(?:\.\d+)?")
34
+ # Same two arrow forms _SERIES_RE accepts. Splitting on the Unicode arrow
35
+ # alone would keep the rate series working under an upstream ASCII
36
+ # normalisation while silently dropping the plain-language reading.
37
+ _ARROW_RE = re.compile(r"→|->")
38
 
39
 
40
  def parse_rates(computed_metric: str) -> list[float]:
 
60
  def _reading(computed_metric: str) -> str:
61
  """The analyser's plain-language reading, e.g. "more cautious".
62
 
63
+ tone_drift formats it as the trailing "→ <reading>" segment. Both arrow
64
+ forms _SERIES_RE accepts are honoured here too.
65
  """
66
+ parts = _ARROW_RE.split(str(computed_metric or ""))
67
  return parts[-1].strip() if len(parts) > 1 else ""
68
 
69
 
docs/superpowers/specs/2026-08-28-attention-dashboard-roadmap.md CHANGED
@@ -78,6 +78,15 @@ switched off by the app's own fail-closed alignment gate. No UI change can turn
78
  it on. Only a point-in-time consensus archive carrying our own verifiable
79
  capture timestamp can.
80
 
 
 
 
 
 
 
 
 
 
81
  **2. No base rate exists.** `analysis/textdiff.py:665-673` diffs the latest
82
  10-Q against exactly one prior 10-Q. Significance thresholds are module
83
  constants (`textdiff.py:31-33`, `:61-62`). `compute_lexicon_trend`
 
78
  it on. Only a point-in-time consensus archive carrying our own verifiable
79
  capture timestamp can.
80
 
81
+ Follow-on requirement, carried here explicitly: **the archive work is not done
82
+ until a live screen reads `display_policy["market_expectations_aligned"]`.**
83
+ The flag is produced on every run and, as of the attention-ordered-brief branch,
84
+ read by nothing -- that branch deleted `dashboard/market_read.py`, its only
85
+ consumer, and that consumer was dead code (no screen routed to it). A flag
86
+ computed and never consulted is indistinguishable from a flag that is wrong, so
87
+ whichever work item lands the consensus archive must ADD a real consumer, not
88
+ merely flip the hardcoded `False` at `agent/graph.py:665` to a computed value.
89
+
90
  **2. No base rate exists.** `analysis/textdiff.py:665-673` diffs the latest
91
  10-Q against exactly one prior 10-Q. Significance thresholds are module
92
  constants (`textdiff.py:31-33`, `:61-62`). `compute_lexicon_trend`
tests/test_brief_order.py CHANGED
@@ -443,3 +443,38 @@ def test_render_keeps_zone_3_inside_the_expander_and_everything_else_above_it(
443
  # Order is preserved within each side, not merely partitioned.
444
  assert above == [k for k in order if k not in set(mod.ZONE_3)]
445
  assert inside == [k for k in order if k in set(mod.ZONE_3)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  # Order is preserved within each side, not merely partitioned.
444
  assert above == [k for k in order if k not in set(mod.ZONE_3)]
445
  assert inside == [k for k in order if k in set(mod.ZONE_3)]
446
+
447
+
448
+ def test_private_evasion_deltas_delegates_to_the_public_one():
449
+ """Two near-identical four-line comprehensions answered the same question.
450
+ _evasion_deltas now delegates; this pins that they agree on every shape a
451
+ persisted delta list can take -- missing key, None, empty, non-dict
452
+ entries, and a non-string `kind` (where the two spellings,
453
+ `d.get("kind") == ...` and `str(d.get("kind") or "") == ...`, could
454
+ conceivably have diverged)."""
455
+ from dashboard.attention_view import _evasion_deltas, evasion_deltas
456
+
457
+ cases = [
458
+ {},
459
+ {"quarter_deltas": None},
460
+ {"quarter_deltas": []},
461
+ {"quarter_deltas": [{}]},
462
+ {"quarter_deltas": [{"kind": None}]},
463
+ {"quarter_deltas": [{"kind": ""}]},
464
+ {"quarter_deltas": [{"kind": 5}]},
465
+ {"quarter_deltas": [{"kind": True}]},
466
+ {"quarter_deltas": [{"kind": ["recurring_evasion"]}]},
467
+ {"quarter_deltas": ["not-a-dict", None, 7]},
468
+ {"quarter_deltas": [
469
+ _delta("recurring_evasion", "margin"),
470
+ _delta("risk_added", "supply"),
471
+ _delta("recurring_evasion", "pricing"),
472
+ ]},
473
+ ]
474
+
475
+ for brief in cases:
476
+ assert _evasion_deltas(brief) == evasion_deltas(brief), brief
477
+
478
+ # Not vacuous: the last case must actually select something, in order.
479
+ selected = _evasion_deltas(cases[-1])
480
+ assert [d["term"] for d in selected] == ["margin", "pricing"]
tests/test_tone_strip.py CHANGED
@@ -164,3 +164,40 @@ def test_render_tone_strip_never_calls_markdown_when_metric_has_no_numbers(monke
164
  ]})
165
 
166
  assert calls == []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  ]})
165
 
166
  assert calls == []
167
+
168
+
169
+ _ASCII_METRIC = (
170
+ "hedge-word rate 27->13->15->55 per 10k words over FY2025->Q32026 "
171
+ "(rising 3 quarters) -> more cautious"
172
+ )
173
+
174
+
175
+ def test_reading_accepts_both_arrow_forms():
176
+ """_SERIES_RE already tolerates "->" as well as "→"; _reading split on the
177
+ Unicode arrow alone. An upstream ASCII normalisation would therefore keep
178
+ the rate series working while the plain-language reading silently
179
+ vanished -- half a tolerant parser is worse than none."""
180
+ from dashboard.tone_strip import _reading
181
+
182
+ assert _reading(_METRIC) == "more cautious"
183
+ assert _reading(_ASCII_METRIC) == "more cautious"
184
+ assert _reading("rate 1->2 per 10k words → less assertive") == "less assertive"
185
+ assert _reading("no arrows at all") == ""
186
+ assert _reading("") == ""
187
+
188
+
189
+ def test_render_tone_strip_shows_the_reading_for_an_ascii_series(monkeypatch):
190
+ """End to end through render: the ASCII form must produce the sparkline
191
+ AND the reading, not the sparkline alone."""
192
+ import dashboard.tone_strip as mod
193
+
194
+ captured: list[str] = []
195
+ monkeypatch.setattr(
196
+ mod.st, "markdown", lambda html, **kw: captured.append(str(html))
197
+ )
198
+
199
+ mod.render_tone_strip({"quarter_deltas": [_tone_delta(_ASCII_METRIC)]})
200
+
201
+ joined = "".join(captured)
202
+ assert "<svg" in joined
203
+ assert "more cautious" in joined
tests/test_verdict.py CHANGED
@@ -278,42 +278,58 @@ def test_kpi_source_note_is_exact_empty_string_without_source_url():
278
  assert _kpi_source_note({"source_url": ""}) == ""
279
 
280
 
281
- def test_kpi_footnote_html_is_byte_identical_without_source_url():
282
  """Regression net for the footnote composition in _render_quarter_kpis.
283
 
284
- _render_quarter_kpis calls st.markdown(...), so the footnote string
285
- itself isn't reachable without Streamlit. This mirrors the exact
286
- composition from dashboard/verdict.py (the lines immediately above the
287
- st.markdown call):
288
-
289
- source_note = _kpi_source_note(latest)
290
- source_html = f' · {source_note}' if source_note else ""
291
- footnote = f'...{brief_quarter_note_text}{source_html}</div>'
292
-
293
- and asserts that when source_note is "" (no source_url), source_html is
294
- also exactly "" -- so the surrounding footnote text is byte-identical
295
- to what it was before this feature existed, with no dangling separator.
296
  """
297
- from dashboard.verdict import _kpi_source_note
 
 
298
  from dashboard.i18n import t
299
 
300
  base_text = t("brief_quarter_note").format(section=t("nav_financials"))
301
 
302
- no_url_note = _kpi_source_note({})
303
- no_url_html = f' · {no_url_note}' if no_url_note else ""
304
- assert no_url_html == ""
305
- footnote_without_url = f'{base_text}{no_url_html}'
306
- assert footnote_without_url == base_text
307
-
308
- with_url_note = _kpi_source_note({
309
- "source_url": "https://www.sec.gov/Archives/edgar/data/320193/x.htm",
310
- "accession": "0000320193-26-000081",
311
- })
312
- with_url_html = f' · {with_url_note}' if with_url_note else ""
313
- footnote_with_url = f'{base_text}{with_url_html}'
314
-
315
- assert footnote_with_url != footnote_without_url
316
- assert footnote_with_url == f'{base_text} · {with_url_note}'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
 
318
 
319
  def test_market_band_cells_exclude_commodity_reference_numbers():
 
278
  assert _kpi_source_note({"source_url": ""}) == ""
279
 
280
 
281
+ def test_kpi_footnote_composition_goes_through_the_production_renderer(monkeypatch):
282
  """Regression net for the footnote composition in _render_quarter_kpis.
283
 
284
+ This test used to mirror the composition (`source_html = f' . {note}' if
285
+ note else ""`) into itself and assert on the copy, so changing the
286
+ separator in verdict.py left it green while it claimed to be a regression
287
+ net. It now spies on verdict.st.markdown and drives the real renderer, so
288
+ the assertions are about the HTML the user actually receives.
 
 
 
 
 
 
 
289
  """
290
+ import dashboard.verdict as mod
291
+ import dashboard.financials as fin
292
+ import storage.metrics_db as mdb
293
  from dashboard.i18n import t
294
 
295
  base_text = t("brief_quarter_note").format(section=t("nav_financials"))
296
 
297
+ def _row(source_url):
298
+ return {
299
+ "period": "Q32026", "form_type": "10-Q", "period_basis": "quarterly",
300
+ "revenue": 94_000_000_000.0, "eps": 1.57,
301
+ "gross_margin": 0.469, "operating_margin": 0.301,
302
+ "free_cash_flow": 24_000_000_000.0,
303
+ "accession": "0000320193-26-000081", "source_url": source_url,
304
+ }
305
+
306
+ def _render(source_url) -> str:
307
+ captured: list[str] = []
308
+ monkeypatch.setattr(mdb, "get_all_metrics", lambda ticker: [_row(source_url)])
309
+ monkeypatch.setattr(fin, "_display_rows", lambda rows: [_row(source_url)])
310
+ monkeypatch.setattr(mod.st, "markdown", lambda html, **kw: captured.append(str(html)))
311
+ mod._render_quarter_kpis("AAPL")
312
+ return "".join(captured)
313
+
314
+ url = "https://www.sec.gov/Archives/edgar/data/320193/000032019326000081/x.htm"
315
+ with_url = _render(url)
316
+ without_url = _render(None)
317
+
318
+ # The renderer's try/except swallows failures and returns -- an empty
319
+ # capture would make every assertion below vacuous.
320
+ assert base_text in without_url
321
+ assert base_text in with_url
322
+
323
+ # No dangling separator, no empty span, nothing at all after the note.
324
+ assert f'{base_text}</div>' in without_url
325
+ assert "<a href=" not in without_url
326
+
327
+ # The link path adds exactly the separator plus the anchor, and removing
328
+ # that one segment reproduces the no-URL output byte for byte.
329
+ note = mod._kpi_source_note({"source_url": url, "accession": "0000320193-26-000081"})
330
+ assert note
331
+ assert f'{base_text} . {note}</div>'.replace(" . ", " · ") in with_url
332
+ assert with_url.replace(f' · {note}', "") == without_url
333
 
334
 
335
  def test_market_band_cells_exclude_commodity_reference_numbers():