Handbook
Teams exploratory read — findings
Dual architecture: TEAMS-READ-DUAL-ARCHITECTURE.md. Cockpit harness: teams-exploratory-harvest.md.
Updated
§0 Code baseline (static audit)
Expected capabilities from current code before live probes. Observed column filled after Phase 3 live walkthrough.
Mechanisms
| Mechanism | Implementation | Status |
|---|---|---|
| DOM evaluate | teams_readonly.py via TeamsEvaluateScriptId |
Production |
| Chunk + scroll | teams_chunk.teams_harvest_messages_chunk |
Production |
| HTML snapshot parser | connectors/teams.py _TeamsListParser |
Legacy / fixtures only |
| In-page REST | — | TBD live |
| Microsoft Graph | Cockpit org/sync_service.py (not Teams-specific) |
TBD live |
Field matrix (expected from code)
| Field | Chat (chunk) | Channel post | Reply thread | Primary (code) | Fallback |
|---|---|---|---|---|---|
Stable message id (data-mid) |
Yes | Yes | Yes | DOM evaluate | teams:row:N synthetic |
| Thread / reply chain id | data-reply-chain-id |
Same | Same | DOM evaluate | item_id |
| Author display name | Yes | Yes | Yes | [data-tid=message-author] |
aria-label / line parse |
| Author email / AAD id | No | No | No | — | TBD live |
| Timestamp ISO | time[datetime] when present |
Same | Same | DOM | received_hint |
| Body preview | ~500 chars | Same | Same | DOM innerText | — |
| Full body | No (chunk) | No (chunk) | Partial | teams_read_thread_replies |
TBD live |
| @mentions | No | No | No | — | TBD live |
| Reactions | No | No | No | — | TBD live |
| Attachments metadata | No (evaluate) | No | No | Legacy HTML parser only | TBD live |
| Deep link URL | location.href |
Same | Same | DOM | — |
| Container label | Teams/Chat (query) |
channel query | thread url | Consumer + wire | — |
| Read/unread | No | No | No | — | TBD live |
| Edited / deleted | No | No | No | — | TBD live |
LCDL task inventory
task_id |
Contract path | Evaluate scripts used |
|---|---|---|
teams_probe_health |
contracts/teams_probe_health/v1/ |
teams_page_health |
teams_list_chats |
contracts/teams_list_chats/v1/ |
teams_harvest_chat_list |
teams_list_channels |
contracts/teams_list_channels/v1/ |
teams_harvest_channel_list |
teams_list_chat_messages_chunk |
contracts/teams_list_chat_messages_chunk/v1/ |
harvest + scroll + restore |
teams_list_channel_posts_chunk |
contracts/teams_list_channel_posts_chunk/v1/ |
harvest + scroll |
teams_read_thread_replies |
contracts/teams_read_thread_replies/v1/ |
harvest (thread context) |
Scroll behavior (code)
teams_message_scroll_step accepts direction (up/down), walks scrollable ancestors from message rows, and uses wheel / scrollIntoView fallbacks. Default chat chunk harvest scrolls up for older history (teams_chunk.scroll_direction).
§1 Live probe results (2026-06-09)
Tab: https://teams.microsoft.com/v2/ · CDP: :9222 · Evidence: workbench/teams-exploratory/20260609T060019Z/
| Field | Observed | Mechanism | Notes |
|---|---|---|---|
| Stable message id | Yes | DOM | item_id e.g. 1769031292996 |
| Author display name | Partial | DOM | Sometimes merged into title line |
| Timestamp ISO | No | DOM | created_at null in sample |
| Body preview | Partial | DOM | Title/subject line; body_preview often null on wire |
| @mentions | No | DOM probe | 0 nodes with current selectors |
| Attachments metadata | No | DOM probe | 0 file cards in message pane |
| Scroll older (up) | No | DOM | scrollHeight: 0 on picked container |
| Scroll more rows (down) | Yes | LCDL chunk | total_seen 48→49 |
| Chat list inventory | No | DOM | 0 chats — sidebar not harvested |
| Chunk parity 1 vs 5 | Yes | LCDL | first_row_parity: true |
Full report: teams-exploratory-walkthrough-20260609.md.
§2 Run 2 backlog
| Priority | Task | Repo | Status |
|---|---|---|---|
| P0 | Wire pick_teams_cdp_page_target into connectors/teams.py attach |
cockpit | Done — teams_cdp_attach.py |
| P0 | Fix scroll container detection for upward history | lcdl teams_readonly.py |
Done — direction + ancestor picker |
| P1 | Improve author/body split in teams_harvest_message_rows |
lcdl | Done — author/body selectors |
| P1 | teams_list_chats when chat list sidebar visible |
lcdl + consumer loop | Done — bounded loop in _run_teams_sync_lcdl |
| P1 | Date-window guided ingest + TeamsHarvestWindow |
cockpit | Done — guided-teams-ingest.sh, run 262–263 |
| P2 | teams_harvest_mentions evaluate script |
lcdl | Deferred |
| P2 | teams_list_shared_files_metadata (no download) |
lcdl | Deferred |
| P2 | Channel post routine sync loop | cockpit teams.py |
Deferred (optional run 2b) |
| P3 | Live test fixtures: reuse tab, CDP 9222, no page.close() |
lcdl + cockpit tests | Done (run 1) |
| P3 | Graph /me/chats feasibility with existing MSAL |
cockpit (optional) | Deferred |
Run 2 report: teams-bounded-harvest-20260609.md.
§3 Run 3 backlog (global message search)
Guided 7-day runs (sync 262–263) harvested one open chat (~12 rows) because teams_list_chats=0. Cross-chat week coverage needs global Teams search, not per-chat Find in chat.
| Priority | Task | Repo | Status |
|---|---|---|---|
| P0 | teams_search_messages_chunk — *, Messages scope, date range, Next, click hit |
lcdl + contract | Planned |
| P0 | Wire search-first fallback in _run_teams_sync_lcdl when window set or chat list empty |
cockpit | Planned |
| P1 | Offline fixtures + live probe for search result rows | lcdl tests | Planned |
| P1 | Highlighted-message harvest after result click | lcdl teams_readonly.py |
Planned |
DOM anchors (live probe 2026-06-09): AUTOSUGGEST_INPUT, ms-searchux-popup, title-bar-toggle-search-btn. Dual-arch: TEAMS-READ-DUAL-ARCHITECTURE.md.