Install
$ agentstack add skill-bencharoenwong-parallax-workflows-parallax-desk-call-list ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Desk Call List
When not to use
- Single portfolio morning analysis -> use /parallax-morning-brief
- One client meeting prep -> use /parallax-client-review
- Unweighted ticker surveillance -> use /parallax-watchlist-monitor
- Full stock drill-down, technicals, or analyst consensus -> use /parallax-should-i-buy or /parallax-watchlist-monitor
- Book creation/editing -> operator maintains
~/.parallax/desk-book/book.yaml
Gotchas
- JIT-load
_parallax/parallax-conventions.mdfor §0.0 pre-flight, §0.1 tool loading, §0.2 typed integer params, §3 parallel execution, §3.1 annotation/rank separation, §9.1/§9.2 disclosures, §10 render gate, §11 verdict sensitivity, §12 information framing, and §13 audience mode. - JIT-load
_parallax/coverage-matrix.mdbefore Batch A.export_price_seriesis equity-only and FREE, and itssuccess:falseresponse classifies ETFs; ETFs then price viaetf_daily_price. This skill does not calletf_profile. - JIT-load
_parallax/house-view/loader.md§1-§2, §5, and §6. The house view annotates movers but never changes rank order or membership. - JIT-load
_parallax/white-label/integration-pattern.mdbefore Pre-Render. Callload_rm_branding_context("desk call list", audience=)from_parallax/white-label/rm_consumer.py, passing the parsedaudience=invocation flag (orNoneif absent). This visual-only seam blocks voice access and redacts source references. - JIT-load
references/desk-book-format.mdbefore loading/validating any desk book. - JIT-load
references/ranking-and-bounding.mdbefore thresholding, ranking, or rendering bounded sections. - JIT-load
references/talk-tracks.mdbefore drafting per-client talk tracks. desk_call_list_logic.pyis the pure arithmetic layer. Do not put MCP calls or local file writes in it.- Client names and weights never go to Parallax MCP tools; only the deduplicated symbol union leaves the machine.
SCAN_CONCURRENCY = 24applies only to the wide price scan. If the live probe shows rate limiting, use 8.export_price_seriesis FREE;etf_daily_pricecosts 1 token per ETF priced. This skill no longer callsetf_profile. Do not invent numbers.client_safeis supported, but this is primarily an internal RM artifact.
Build one ranked, bounded morning call list for a relationship manager covering many client books.
Usage
/parallax-desk-call-list
/parallax-desk-call-list threshold=4.5 min_impact=0.4 detail_cap=6 subset="Northgate,NG-001"
/parallax-desk-call-list [{"client_name":"Northgate","portfolio":[{"symbol":"AAPL.O","weight":0.12,"asset_class":"equity"}]}] redact_names=true
Defaults:
threshold=5.0unless overridden by bookdefault_threshold_pctmin_impact=0.50pp unless overridden by bookdefault_min_impact_ppdetail_cap=8,news_cap=8,audience=internal_analyst
Workflow
Execute using Parallax MCP tools plus local Python helpers.
Batch 0 - Pre-flight, Book, House View
- Resolve canonical
_parallax/...paths per_parallax/parallax-conventions.md §0.0. - Call
ToolSearchwith query"+Parallax"to load deferred Parallax MCP schemas before the first data call. - Load
references/desk-book-format.md; read inline input or$PARALLAX_DESK_BOOK_PATH, else~/.parallax/desk-book/book.yaml. Validate viadesk_call_list_logic.py. Inline input wholly replaces the saved book. Preserve validation warnings for both input paths. - Apply subset filtering only to the saved book, passing the
redact_namesmode into resolution. Keep only global validation warnings and warnings owned by selected clients. Report unmatched names verbatim unlessredact_names=true; in redacted mode retain and report only the unmatched count, then applyredact_names()so client refs and names are removed. If a non-empty subset matches no clients, refuse to scan under the same disclosure rule. - Compute staleness tier and the sorted deduplicated symbol union
U. - Load active house view per
_parallax/house-view/loader.md§1-§2. Shell out toview_status; do not recompute expiry date math. If absent or invalid, run without view.
If the first Parallax batch after tool loading is empty or cancelled, re-fire the whole batch once before concluding unavailability.
Batch A - Asset-Class Classification and Wide Price Scan
Load _parallax/coverage-matrix.md. Classification is fused with the price scan — the FREE export_price_series doubles as the equity classifier, so no separate classification probe is needed:
- Cached
asset_class→ route directly:equity→export_price_series;etf→etf_daily_price. No probe. - Uncached → call
export_price_series()(FREE, equity-only) as both classifier and equity price source:
{"success": true, ...}with a non-emptypriceslist → equity; take the move and both close dates from the returned series. Cost 0.{"success": false, ...}/ noprices→ ETF; calletf_daily_price()for the move + per-row date.
Keyed on success == false (NOT an empty list — the tool returns a {success:false, error} object for ETFs). This is a deliberate, documented classifier, not the silent substitution coverage-lint guards against: a success:false that is actually a dead equity gets one etf_daily_price probe that also fails and lands in the unpriced/coverage handling, named in the coverage line.
- Only if
export_price_seriesis entirely unavailable (outage): resolve bare tickers to RICs per_parallax/parallax-conventions.md§1, then the static fallback (suffix-less or.P⇒ ETF; otherwise equity).
Then fan out the price scan at SCAN_CONCURRENCY waves, plus one telemetry call:
| Tool | Parameters | Notes | |---|---|---| | get_telemetry | fields: regime_tag, signals, commentary.headline, divergences | Desk-wide market context | | export_price_series equity branch + classifier | symbol=, days=10 as typed integer | FREE. Equity-only; single-symbol calls; the success:false response also classifies ETFs | | etf_daily_price per ETF branch | symbol=, start_date=, end_date= | ETF-only; single-symbol calls; per-row date carries the move's session |
Derive move_pct = (close[-1] / close[-2] - 1) * 100 from the last two closes, which must both be finite. Record both dates — for the ETF branch these come from etf_daily_price rows (which carry the session date, unlike a dateless profile probe). If fewer than two closes return or either close/move is non-finite, mark the symbol unpriced, name it in coverage, and do not treat it as a trigger.
Batch B - Threshold and Scan Integrity
Load references/ranking-and-bounding.md.
- Compute desk scan integrity before the empty-mover path. If priced coverage is below 80%, render SCAN DEGRADED and skip the call list.
- Define movers as
abs(move_pct) > threshold; the boundary is strictly greater. - If more than 40 symbols cross the threshold, auto-raise to the 40th-largest absolute move rounded up to the nearest 0.5 pp, recompute movers, and state the auto-raise.
- If no movers, or movers exist but no client clears
min_impact, render the no-calls short form.
Batch C - Mover Enrichment
For symbols in the mover set only, schedule enrichment in waves of at most 8 concurrent calls across symbols and tools:
| Tool | Parameters | Purpose | |---|---|---| | get_company_info | symbol for every mover | Display name and expected-name oracle | | get_peer_snapshot | symbol for every mover | Current factor scores and target_company | | get_score_analysis | symbol, weeks=4 as typed integer for equity movers only | Four-week score trajectory | | get_news_synthesis | symbol for top news_cap equity movers by desk-wide weighted exposure | One news synthesis per symbol, not per client |
Cross-check get_peer_snapshot.target_company against get_company_info.name. On mismatch, render Ground-truth Integrity, exclude that symbol's scores, but keep the price move in client ranking.
For ETF movers, skip get_score_analysis and get_news_synthesis because ETF coverage is unverified. Render those fields as not available for ETFs; never present their absence as an equity-grade enrichment failure. ETF price moves still drive client ranking.
Batch D - Client Ranking
Zero tool calls. Use desk_call_list_logic.py to compute triggered exposure, signed net impact, direction-agnostic severity, top driver, coverage, rank order, and bounded detail/summary sections. News and house-view tags are annotations only and must not alter rank membership or order.
Pre-Render - Load White-Label Branding
Load _parallax/white-label/integration-pattern.md §2. Import load_rm_branding_context from _parallax/white-label/rm_consumer.py. Call load_rm_branding_context("desk call list", audience=) once, passing the parsed audience= invocation flag (or None if absent) so the seam resolves §13.1 precedence over both the flag and the branding config. Place its header_lines below any House View Preamble. Place its about_lines in About This Report. Read resolved_audience off the returned context for the Output Format audience branches below (e.g. item 12's client_safe omission); do not re-resolve the mode yourself and do not inspect the branding mapping directly. The helper preserves the call list and selects default Parallax if branding is corrupt. The branding is for the desk's firm: one report, one brand.
Render - deterministic gate
Compose the complete report per Output Format, then run it through the shared render gate in one Bash step before replying:
DRAFT="$(mktemp "${TMPDIR:-/tmp}/deskcall.XXXXXX")"
cat > "$DRAFT"
REPORT
python3 "/../_parallax/render_gate.py" --skill desk-call-list ** desk call list`.
3. `# Desk Call List` title with as-of date, session dates, threshold, clients scanned, and clients triggered.
4. Book Staleness Warning, only for warn/stale/unknown tiers.
5. Validation Warnings, whenever validation produced warnings, including renormalisation warnings for inline and saved books.
6. Ground-truth Integrity, only if any mismatch.
7. Market Context: 2-3 sentences from telemetry.
8. Priority Calls: render the informational preface per `_parallax/parallax-conventions.md §12`, then the full ranked table.
9. Client Detail: top `detail_cap` clients. Load `references/talk-tracks.md`; include why-listed arithmetic, positions table, talk track, and likely questions.
10. Also Affected (summary only): ranks after `detail_cap`; group by driving symbol when triggered clients exceed 25.
11. Symbol Movers Reference: symbol, name, move %, four-week score change, news headline, number of clients holding, desk-wide weighted exposure, and house-view tag.
12. Verdict Sensitivity per `_parallax/parallax-conventions.md §11`; omit when the seam's `resolved_audience` is `client_safe`.
13. Next steps: point to `/parallax-client-review`, `/parallax-should-i-buy`, or `/parallax-watchlist-monitor` as appropriate. Do not auto-invoke them.
14. About This Report: first the seam's `about_lines` verbatim — they already carry the `_parallax/white-label/integration-pattern.md §7` branding line, the unconditional currency line, any skipped local-logo basename, and the audience mode/notice lines; do not re-add any of them — then desk-book provenance, redaction state, and a cost note that the equity price scan is FREE (`export_price_series`) while `etf_daily_price` costs 1 token per ETF priced.
15. AI-interaction disclosure per `_parallax/parallax-conventions.md §9.2`.
16. Disclaimer: view-aware per `_parallax/house-view/loader.md §5` if active; otherwise render the standard disclaimer from `_parallax/parallax-conventions.md §9.1`.
## No-Calls and Degraded Short Forms
SCAN DEGRADED starts with `**Scan degraded — results not reliable.**` and names priced count, total symbols, coverage, and up to 10 unpriced symbols.
An empty client or symbol selection starts with `**Scan refused — no clients or symbols selected.**` and never renders a call list or no-calls result. An all-unmatched subset starts with `**Scan refused — subset matched no clients: .**`; under `redact_names=true`, replace the names with ` selector(s) matched no client`. Redacted refusal and partial-match output never contains raw selectors, and client refs are omitted everywhere.
Quiet mornings start with `**No calls indicated.**`, then unique symbols scanned, client books scanned, largest move, threshold, and the `min_impact` pp floor. Include House View Preamble, Branding Header, staleness warning, validation warnings, About This Report, AI disclosure, and disclaimer.
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [bencharoenwong](https://github.com/bencharoenwong)
- **Source:** [bencharoenwong/parallax-workflows](https://github.com/bencharoenwong/parallax-workflows)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.