Skip to content

Add Card author with versioned Chat drafts and explicit Save - #130

Open
Lancetnik wants to merge 3 commits into
feat/capabilities-refreshfrom
feat/card-author
Open

Lancetnik wants to merge 3 commits into
feat/capabilities-refreshfrom
feat/card-author

Conversation

@Lancetnik

@Lancetnik Lancetnik commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Why are these changes needed?

An unknown Card can now be authored, drawn and revised in the current Chat without first installing a Card file. The default-on bundled card-author Skill is independent of rich-views; it exposes the existing vocabulary, worked examples and structured draft operations on demand.

  • Store validated definitions and expanded surfaces as typed Chat events, with independent draft identities and append-only versions. Exact reads and conversational restoration survive restart and compaction; instance edits keep their ordinary A2UI behavior.
  • Add a shell Save form beside each current draft and a conversational Save operation using the same domain boundary. Save writes a complete Profile Card definition, keeps current values separate, and becomes available through ordinary Card discovery on the next Turn.
  • Require explicit Replace or Save as copy for name/file conflicts, reject obsolete references and changed destination tokens, write atomically, and reconcile retries when the file commits before status logging succeeds. A YAML comment receipt identifies an exact retry; no draft directory or independent persisted draft state is added.
  • Share definition validation between files and drafts, retaining supported media/input properties and rejecting invalid schemas, examples, primitive properties and unscoped bindings. Add the domain terms, accepted ADR 0042 and usage documentation.

Stacked on #129. The PR base is feat/capabilities-refresh at ac7c4d7; the diff contains only the Card author work. Retarget to main after #129 merges.

Related issue number

Closes #88.

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: full Python suite 2345 passed, 4 skipped; feature acceptance/validator suite 37 passed, including cancellation/compaction recovery. Card author and owned-store coverage passed on Python 3.12 and 3.13 as well (43 tests per version). mypy, strict SPA checks, 543 SPA tests including OpenAPI route/schema contracts, and the source build passed. Updated the AST knowledge graph.

Live ordinary Chrome pass on an isolated Profile: two drafts, revisions of each, current-only Save controls, free Save, Replace, Save as copy, Chat restoration, server restart/replay, and a registered interaction retaining edited data after reload. App console/network errors: none.

Independent Standards and Spec reviews completed; all findings were corrected and the final reports have no outstanding findings.

AI assistance

Implemented and reviewed with Codex. This is a draft PR for human ownership review.

  • 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.

@github-actions

github-actions Bot commented Oct 6, 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 121 9 34 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 271 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/cards/__init__.py 281 24 128 18 90%
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 440 175 120 17 57%
src/assistant/gateway/core.py 847 105 230 39 85%
src/assistant/gateway/openapi_schema.py 26 0 6 1 97%
src/assistant/gateway/profile_manager.py 408 43 118 23 87%
src/assistant/gateway/repair.py 66 3 26 1 96%
src/assistant/gateway/routes/card.py 24 4 0 0 83%
src/assistant/gateway/routes/chat.py 71 1 14 1 98%
src/assistant/gateway/routes/common.py 20 1 8 1 93%
src/assistant/gateway/routes/connection.py 167 2 42 2 98%
src/assistant/gateway/routes/file.py 170 4 58 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 222 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 19 3 2 0 86%
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 7 46 9 94%
src/assistant/scheduler_lock.py 33 0 4 1 97%
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 54 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 18 56 7 89%
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 15266 2045 3996 488 85%

42 files skipped due to complete coverage.

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.

1 participant