Why: docx deliverables were plain text saved with a .docx name (no
headings/tables/styles), and the artifact_ref part was marked Process
so the deliverable vanished into the collapsed process section — the
user saw only model-written text like "📄 xxx.docx 工件 ID …" instead
of an openable, formatted document delivered in the conversation.
Evidence:
- new internal/docgen: Markdown -> styled OOXML (Title/Heading1-4,
numbered+bullet lists with numbering.xml, GFM tables with shaded
header, quotes, code blocks, bold/italic/strike, real hyperlinks);
zero third-party deps; tests cover zip structure, XML well-formedness,
numbering refs, hyperlink rels, escaping, plain-text fallback
- ingest round-trip test proves generated docx parses back to blocks
- new write_docx builtin tool (markdown in -> styled .docx artifact);
write_artifact prompt now routes Word docs to it; task.doc-minutes
output contract requires write_docx delivery
- llm.go: artifact refs collected as deliverables and appended as
content parts AFTER the final text (pinned tail, not process); mock
#dogfood path generates a real styled docx; runmgr skips string
indexing for binary office mimes
- go test ./... 19 packages ok (incl. new e2e asserting <w:tbl> and
title text inside the artifact served by the API)
Impact: model-written documents open in Word/WPS with real layout and
preview with formatting (mammoth maps Heading1-4 to h1-h4); every tool
artifact now lands as a visible in-chat card; no behavior change for
text artifacts.
Refs: task feature/deliverable-docx-r1
Why: D48-D51 approved — cross-session inbox so todos are not lost across
conversations.
Evidence: store v12 index + ListProjectCards aggregate (D49 verdict:
project cards any status + per-conversation action_required only);
cardsvc project-stream emit/mirror via project:<id> pseudo-key (helpers
in core PR #11/#12) and ToProject (idempotent via ref, dismisses origin,
refuses flow-bound hitl/cmd cards); runmgr scope=project ownership;
llm.go scope param on submit_card/card_begin; server routes
GET /api/projects/{id}/cards, POST /api/cards/{id}/to_project, events
scope=project; vendored core synced; new tests ToProject/,
TestLLMRunnerCardScopeProject, e2e TestProjectInbox; e2e server now
wires production card emitter (no-op before).
Impact: additive; no change to existing conversation flows.
Refs: documents proposal 2026-09-30-card-stream-artifact-unify-project-inbox.md (D48-D52).
Why: D46/D47 approved — artifact_ref parts left only a name line in model
context (next-turn amnesia on big tool results), and artifacts had no
inbox presence unlike submit_card products.
Evidence: ctxasm ArtifactResolver backfills UTF-8 artifact text with the
card char limit (Truncations + artifact(n) observable; binary keeps
placeholder); runmgr runCtx.Artifact; llm.go auto-creates a result facade
card (summary kv + doc-ref) when a tool result is truncated, suppressed
when the run already submitted an explicit card; mock #doc demos the
facade; new tests TestAssembleInputArtifactBackfill,
TestLLMRunnerArtifactFacadeCard/Suppressed, e2e TestArtifactFacadeCard.
Impact: frontend unchanged — artifact chips and doc-ref already resolve
via docBridge; no wire protocol change.
Refs: documents proposal 2026-09-30-card-stream-artifact-unify-project-inbox.md (D46/D47).
Why: D44/D45 approved — card content streaming lets users watch long
artifacts materialize in the inbox instead of a single submit_card blob.
Evidence: cardsvc Append with 250ms emit throttle (persist-every-append);
runmgr Begin/Append/CommitStreamCard + finishRun fallback marking
uncommitted stream cards done/failed with warn tone; llm.go declares the
three tools under ui.cardflow with hallucination rejection; mock
#cardstream demo; new unit tests (TestLLMRunnerCardStreamTools/Gated,
TestAppendStreamThrottleAndMerge) and e2e TestMockCardflowStreamLoop.
Impact: no change to existing submit_card path or wire protocol;
card.updated payload already carried full cards (projection semantics).
Refs: documents proposal 2026-09-30-card-stream-artifact-unify-project-inbox.md (D44/D45).
Why: the task-centric sidebar (approved option A) needs a cross-project
conversation list, server-authoritative pinned/archived state, and an
identity endpoint for the sidebar account footer.
Evidence:
- migration v8 conversation_flags (sqlite/postgres up+down; the upgrade
test walks v1<->v8 for real); store and e2e tests cover pinned-first
ordering, archived filtering with ?archived=1, tenant-isolation
negatives (cross-owner flag write -> NotFound), and /api/me shape
(owner/name/auth) in embedded mode.
- go vet + full go test ./... pass.
Impact: additive columns/APIs; existing endpoints unchanged (PATCH gains
optional pinned/archived fields; responses keep prior shape).
Refs: core bump deps/agent-system-core -> 1dc08fc (Conversation flags)
Why: T3 of the interaction foundation - unify button/card/slash/chat entries onto one command bus (D27) composing the Agent-Command library (D30), with danger=high commands gated behind inline confirm cards and every dispatch leaving the same audit envelope.
Evidence: go test green - cmdbus suite (four-entrance audit symmetry, high-danger confirm lifecycle incl. cancel/expiry/handler-reject, audit-unavailable yields unknown, plugin spec fail-closed, schema scalar validation) and server e2e (danger command via POST /api/commands -> confirm card -> card action confirm -> committed receipt -> audit query ordered accepted->committed); legacy /help,/new,/mock,/model,/profile contract preserved through the bus; store migration v7 command_audit (both dialects) with roundtrip test updated.
Impact: new internal/cmdbus (L1 package per D33), server routes POST /api/commands/{id} + GET /api/commands/audit + registry-driven GET /api/commands, postMessage chat-entrance dispatch when the intent gate matches a registered command, plugins host OnCommands overlay, module cards policy/modules/{cmdbus,cardsvc}.md; pending confirm state is process-local (documented limitation).
Refs: docs/proposals/2026-09-30-ui-inbox-command-workspace.md T3; task card feature/command-bus-r1