Skip to content

feat: Screens compose live Card instance references - #137

Open
Lancetnik wants to merge 2 commits into
feat/card-sourcesfrom
feat/screens
Open

Lancetnik wants to merge 2 commits into
feat/card-sourcesfrom
feat/screens

Conversation

@Lancetnik

@Lancetnik Lancetnik commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Why are these changes needed?

Screens give live Cards a place outside Chat. A .screen.yaml file stores a primitive layout and references to saved .card-instance.yaml files; the gateway expands them into one A2UI surface. Reusing a file on multiple Screens, in Files, or through an explicit Chat reference shares its current data. Ordinary Chat snapshots and separately saved copies remain independent.

The screens agent skill creates instances and Screens and opens file references in Chat. A dedicated Screens tab loads them, and Edit Screen opens the existing Files editor to rearrange the layout. Typed file-source events update every reference, simultaneous requests coalesce, and automatic refreshes reuse the source's declared interval. Refresh runs without a model turn. File broadcast history is cleared after delivery; fetched data and refresh results stay bounded and never enter the Screen document.

The loader preserves repeated-template bindings and rejects relative bindings outside them. Profile file confinement, passive historical actions, custom-source approval, and Secret authorization follow the existing instance/source contracts. Drag and write-back boards remain the issue's stated follow-up. ADR 0046 and docs/screens.md document the format and ownership rules.

Stack base: #136 (feat/card-sources), following #129 → #130 → #132 → #133 → #136.

Related issue number

Closes #123

Checks

  • I ran ruff check ., ruff format --check ., and pytest -m "not integration" locally and they pass.
  • If I changed anything under web/, I rebuilt and committed the SPA bundle (npm --prefix web run build).
  • I've included any doc changes needed for this change.
  • I've added or updated tests corresponding to the changes (if relevant).

Validation:

  • Ruff 0.15.18 lint/format, mypy, and uv lock --check pass.
  • Full non-integration Python suite: 3.12 — 2410 passed/4 skipped; 3.13 — 2412 passed/2 skipped; 3.14 — 2410 passed/4 skipped. Integration tests were excluded.
  • npm --prefix web test: 551 passing tests, including the OpenAPI/zod contract gate.
  • npm --prefix web run build: strict Svelte check passes; the rebuilt committed bundle is unchanged.
  • Public Gateway and real AG2 skill tests cover creation, shared refresh, explicit Chat references, independent copies, file edits/restart, code approval, confinement, and bindings. A 140-refresh regression checks live delivery without retained file event history.
  • Headed Chrome: repeated references execute one source, manual and cross-Screen updates agree, hidden tabs/leaving Screens stop refresh, saved actions remain passive, Files edits rearrange Cards and survive reload, all navigation tabs fit, and no console/network errors or model requests occur.
  • GitHub CI: all nine jobs, including the three Python versions and CI status, passed.
  • Independent Standards and Spec reviews: zero remaining findings. graphify update . completed.

AI assistance

Implemented with Codex. Separate automated reviews checked repository standards and issue requirements; their binding and event-history findings were fixed and regression-tested. This remains a draft for contributor review and ownership.

  • I understand the changes in this PR and can explain them in my own words.
  • I have verified that this description accurately reflects the actual diff.
  • If AI assistance was used, I reviewed, tested, and validated the generated code/text before submitting.

@Lancetnik
Lancetnik added this pull request to stack #131 October 7, 2026 05:25
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

Branch coverage

Name Stmts Miss Branch BrPart Cover
src/assistant/a2ui.py 269 22 80 14 89%
src/assistant/a2ui_skill.py 125 9 36 7 90%
src/assistant/acp/approvals.py 58 1 8 2 95%
src/assistant/acp/chats.py 251 22 56 12 89%
src/assistant/acp/listeners.py 28 1 10 1 95%
src/assistant/acp/serve.py 66 16 4 2 74%
src/assistant/acp/serve_ws.py 103 0 24 3 98%
src/assistant/agent.py 272 31 78 8 88%
src/assistant/attachments.py 57 2 20 0 97%
src/assistant/card_author.py 55 13 14 3 68%
src/assistant/card_drafts.py 157 21 60 16 83%
src/assistant/card_instances.py 221 21 78 18 86%
src/assistant/card_sources/runtime.py 77 17 14 2 77%
src/assistant/card_sources/schema.py 91 13 44 13 81%
src/assistant/card_sources/service.py 235 22 102 23 87%
src/assistant/cards/__init__.py 336 30 152 22 89%
src/assistant/cards/layout.py 35 1 14 1 96%
src/assistant/channels/__init__.py 15 7 6 0 38%
src/assistant/channels/base.py 40 3 4 1 91%
src/assistant/channels/discord.py 136 73 44 1 42%
src/assistant/channels/formatting.py 121 2 32 3 97%
src/assistant/channels/router.py 544 15 186 14 96%
src/assistant/channels/slack.py 165 95 52 1 39%
src/assistant/channels/telegram.py 284 51 96 18 79%
src/assistant/cli.py 498 252 92 8 46%
src/assistant/codex_auth.py 241 67 54 5 71%
src/assistant/coding/bridge_client.py 44 7 4 1 83%
src/assistant/coding/bridge_server.py 115 30 22 4 74%
src/assistant/coding/diff.py 98 13 36 6 84%
src/assistant/coding/model_catalog.py 101 6 30 4 92%
src/assistant/coding/session.py 92 7 18 2 92%
src/assistant/config.py 203 22 58 7 89%
src/assistant/connections.py 264 18 78 14 91%
src/assistant/feedback.py 39 5 4 1 86%
src/assistant/filesearch.py 96 12 48 6 88%
src/assistant/folders.py 264 13 82 4 95%
src/assistant/gateway/app.py 470 180 124 19 58%
src/assistant/gateway/core.py 863 103 230 39 86%
src/assistant/gateway/openapi_schema.py 26 0 6 1 97%
src/assistant/gateway/profile_manager.py 410 43 118 23 87%
src/assistant/gateway/repair.py 66 3 26 1 96%
src/assistant/gateway/routes/card.py 122 14 28 6 87%
src/assistant/gateway/routes/card_instance.py 43 3 4 0 94%
src/assistant/gateway/routes/common.py 39 1 16 1 96%
src/assistant/gateway/routes/connection.py 167 2 42 2 98%
src/assistant/gateway/routes/file.py 194 4 72 6 96%
src/assistant/gateway/routes/folder.py 87 7 8 1 92%
src/assistant/gateway/routes/llm.py 245 17 54 6 92%
src/assistant/gateway/routes/permission.py 55 2 12 2 94%
src/assistant/gateway/routes/profile.py 73 4 8 0 95%
src/assistant/gateway/routes/secret.py 66 5 6 1 92%
src/assistant/gateway/routes/settings.py 190 18 26 8 88%
src/assistant/gateway/routes/skill.py 223 9 30 1 96%
src/assistant/gateway/routes/system.py 239 26 42 4 89%
src/assistant/gateway/routes/task.py 104 7 18 5 90%
src/assistant/gateway/stream_bridge.py 37 0 6 1 98%
src/assistant/gateway/tasks_service.py 407 50 130 17 86%
src/assistant/gateway/wire.py 27 4 6 1 85%
src/assistant/hitl/channel.py 21 2 4 2 84%
src/assistant/hitl/desktop.py 133 12 26 5 89%
src/assistant/hitl/gateway.py 22 4 2 1 79%
src/assistant/hitl/inquiry.py 168 6 36 5 95%
src/assistant/integrations/google_auth.py 136 67 24 0 49%
src/assistant/live_configs.py 116 9 40 13 86%
src/assistant/llm_configs.py 220 5 86 1 98%
src/assistant/memory.py 134 11 44 5 89%
src/assistant/middleware.py 81 2 12 2 96%
src/assistant/observability.py 69 5 10 0 94%
src/assistant/observers.py 97 0 24 1 99%
src/assistant/onboarding.py 64 2 26 0 98%
src/assistant/pairing.py 145 2 46 3 97%
src/assistant/peers.py 150 1 40 3 98%
src/assistant/permissions.py 300 21 106 8 93%
src/assistant/profiles.py 186 2 46 4 97%
src/assistant/provider_catalog.py 94 5 38 5 92%
src/assistant/resources.py 210 6 46 8 95%
src/assistant/scheduler_lock.py 33 0 4 1 97%
src/assistant/screen_skill.py 71 6 20 6 87%
src/assistant/screens.py 89 9 30 7 87%
src/assistant/secrets.py 262 4 78 2 98%
src/assistant/self_tools.py 78 21 18 4 70%
src/assistant/settings.py 175 9 52 7 93%
src/assistant/skills.py 55 3 14 0 96%
src/assistant/skills_install.py 167 19 56 12 86%
src/assistant/state_store.py 163 12 50 6 92%
src/assistant/storage.py 36 4 0 0 89%
src/assistant/system_tools.py 152 45 50 13 66%
src/assistant/tasks/scheduling.py 99 6 30 4 92%
src/assistant/tasks/store.py 168 19 56 7 88%
src/assistant/tasks/summary.py 38 1 2 1 95%
src/assistant/tools/__init__.py 88 5 38 3 94%
src/assistant/tools/_mcp_compat.py 25 3 2 1 85%
src/assistant/tools/approval.py 12 6 4 0 38%
src/assistant/tools/ask.py 14 6 2 0 50%
src/assistant/tools/coding.py 30 7 2 1 75%
src/assistant/tools/docker_sandbox.py 68 20 10 1 68%
src/assistant/tools/files.py 70 18 24 6 74%
src/assistant/tools/finance.py 117 44 48 1 61%
src/assistant/tools/google.py 186 132 36 2 28%
src/assistant/tools/image_gen.py 92 38 28 2 55%
src/assistant/tools/mcp.py 195 14 42 9 89%
src/assistant/tools/weather.py 119 19 34 6 82%
src/assistant/tools/web_fetch.py 30 4 10 3 82%
src/assistant/usage.py 74 7 14 0 85%
src/assistant/voice.py 60 19 12 2 65%
src/assistant/voice_providers.py 72 26 4 0 63%
src/assistant/workspace.py 271 25 88 3 92%
TOTAL 16455 2155 4376 568 85%

49 files skipped due to complete coverage.

@Lancetnik
Lancetnik marked this pull request as ready for review October 10, 2026 16:01

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: screens — user-composed dashboards of live A2UI cards

1 participant