read.markets/app
Giorgio Gilestro 0060166d32 review: per-surface rider, loosen for portfolio commentary
Reviewer was rejecting legitimate IT portfolio analyses, citing
descriptive risk language as actionable advice:

  reason: "Allocation guidance throughout: 'concentrazione gestibile',
  'non eliminabile', 'bassa esposizione', 'va monitorato'. Treats
  portfolio construction as actionable."

These phrases describe portfolio state (manageable concentration,
non-eliminable risk, low exposure, warrants monitoring) without
directing the user to take action. They are exactly the kind of
prose a portfolio commentary surface is supposed to produce. The
reviewer's generic "no financial advice" rule is too broad here.

Add a `surface` parameter to review_read() with a per-surface rider
mechanism (_SURFACE_RIDERS). The "portfolio" rider:

- Lists DESCRIPTIVE phrasings that are EXPLICITLY permitted:
  attribute naming ("high concentration", "currency exposure"),
  thesis invalidation conditions, impersonal observations about a
  position's sensitivity.
- Tightens the reject list to EXPLICIT calls to action: imperative
  verbs aimed at the reader, "you should", "consider X-ing",
  specific allocation prescriptions, price-target predictions.

portfolio_analysis.analyse() now passes surface="portfolio". All
other reviewer call sites (indicator summary, log, chat, digest)
default to surface=None and keep the generic rules.

tests/conftest.py's autouse review_read stub picks up **_kw so
adding new keyword arguments to review_read doesn't keep breaking
the locale-integration tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 16:44:27 +02:00
..
jobs review: gate strategic-log, portfolio, chat, and digest on reviewer 2026-05-29 14:40:04 +02:00
routers analyze: send the live toggle lang from the frontend, log resolution 2026-05-29 15:32:58 +02:00
services review: per-surface rider, loosen for portfolio commentary 2026-05-29 16:44:27 +02:00
static analyze: send the live toggle lang from the frontend, log resolution 2026-05-29 15:32:58 +02:00
templates settings: drop the broker-list line from the import lede 2026-05-29 15:58:47 +02:00
__init__.py initial commit — cassandra v0.1 2026-05-15 21:56:10 +01:00
auth.py public: landing + pricing + legal pages, apex-ready, lawyer-reviewed 2026-05-24 00:08:02 +02:00
branding.py css: split cassandra.css into per-section files 2026-05-28 12:31:29 +02:00
cli.py docs: drop Phase D.x markers now that the referral loop is closed 2026-05-26 23:09:39 +02:00
config.py cleanup: drop stale tombstones and dead config fields 2026-05-27 19:25:33 +02:00
db.py sync: encrypted cloud backup for portfolios + settings UX rework 2026-05-23 16:15:54 +02:00
logging.py initial commit — cassandra v0.1 2026-05-15 21:56:10 +01:00
main.py routers: extract chat + ops from api.py 2026-05-27 21:43:17 +02:00
models.py models: align translation column naming + add token counts 2026-05-27 21:18:29 +02:00
redis_client.py phase G: data minimisation + passwordless auth + DeepSeek-first LLM 2026-05-18 14:16:57 +01:00
scheduler_main.py scheduler: register email_digest_job at 06:30 UTC 2026-05-25 23:20:06 +02:00
schemas.py news: auto-tag headlines + market-aware cadence + filter UI 2026-05-21 23:25:03 +01:00
templates_env.py mobile: cache-bust static assets so browser picks up CSS/JS edits 2026-05-28 19:20:49 +02:00