Commit Graph
28 Commits
Author SHA1 Message Date
weichen f1302ed5b3 Enable canonical versioned Go module consumption
Why: Allow consumers to download an immutable module revision without nested source checkouts or local path replacements.

Evidence: SELF package tests and the prior canonical-path rejection are recorded in the Dev dependency-workspace task card; remote consumption is replayed against the committed candidate.

Impact: Change the module identity and its Go imports while preserving API behavior. Existing historical submodule revisions remain buildable.

Refs: Versioned dependencies U1/U3; feature/dependency-workspace
2026-10-13 15:47:16 +00:00
weichen bc1e0a36f7 Close the account lifecycle leftovers: atomicity, bootstrap lock, redeem guard, credential delivery
ci / vet-and-test (pull_request) Successful in 51s
Why: The login recovery contract leftovers and KTD12/KTD14 require:
concurrent same-name account creation must not overwrite the winner,
first-admin bootstrap must serialize across processes, the redeem
endpoint backoff must be shared across instances, revoked API keys
must close established SSE streams, and CLI credentials need an
env-DSN path plus a non-interactive 0600 file delivery mode.

Evidence: go test ./... green; new tests cover 16-way concurrent
create (1 win/15 conflict, winner credentials intact), 8-way
concurrent bootstrap (single admin, refuse takeover after), redeem
guard shared across two store handles on one DB, SSE stream closed
after key revocation within the recheck window, and HTTP 429 after
the failure cap (SELF worktree run; CI is the GATE, PG via test-pg).

Impact: Migration v29 (redeem_attempts); CreateAccount becomes a
single-row INSERT with unique-violation conflict; BootstrapFirstAdmin
advisory-locks (PG) / rechecks (SQLite) and commits admin+key+audit in
one transaction; SSE revalidation covers API-key streams; redeem
backoff moves to the shared DB; CLI gains AGENT_SYSTEM_DSN fallback
and --out file delivery for create/reset-password/issue-login-key/
bootstrap-admin.

Refs: docs/svc-deploy/2026-10-13-login-recovery-contract.md leftovers;
proposal r2 KTD12/KTD14/R5/R11.
2026-10-13 06:05:45 +00:00
weichen 367dc207b3 Add the generative-ui plugin, capability gating, and surface projection
ci / vet-and-test (pull_request) Successful in 42s
Why: Generative UI U3 - the agent needs a real submission path and the
next turn needs to see prior pages: a built-in in-process plugin
registers generative-ui.present (exposeAsTool) carrying the catalog
(prompt=validation single source) with a schema-repair strategy
measured against real MiniMax-M3 deviations; the command bus gains an
owner-scoped tool gate so a disabled plugin stops injecting its tool
(execution guard remains in surfacesvc); ctxasm projects saved surfaces
back into context so the model can revise existing structure; doc-refs
are authorized against the owner's real artifacts.

Evidence: unit suites green (genui guards/epoch/doc-ref, gate fail-closed,
projection content); full go test ./... green; cmdbus/ctxasm also green
under AGENT_PG_TEST_DSN; real-model closed loop (env-gated
TestRealModelSurfaceLoop) passes: task->spec->save->projection->revise
with revision 1->2 and structure change, CNY 0.08 total.

Impact: New internal/genui package; additive cmdbus/ctxasm/runmgr/
runtime hooks; no storage or contract changes (U2 layer untouched).

Refs: Documents proposal r2 U3; Core PR #25/#26; Backend #143; Dev task
feature/generative-ui-u3
2026-10-11 10:38:15 +00:00
weichen 21b8461525 Add R4 escalation reminders and the structured source-id evidence ledger (E4)
ci / vet-and-test (pull_request) Successful in 43s
Why: The plan's E4 remainder under the MiniMax-only constraint: the
harness must detect the model going in circles and inject a
change-of-strategy instruction (R4 - the model cannot be trusted to
notice its own repeat-fail loop), and number sourcing needs addressable
evidence: tool results carry [src_N|tool] tags so "found in materials"
becomes "found in source src_N" for both the model and the fact-check
notice.

Why: Failure counting lives in one place (onEvent end, keyed by the
slot status) because tool execution is parallel; the ledger and tag
append are serialized by the same mutex, and escalation reminders fire
once per condition streak - following the dual-speed nudge finding that
MiniMax ignores vague reminders but follows concrete instructions.

Evidence: go test ./... green; new anchors TestEscalationOnConsecutive
ToolFailures, TestEscalationOnZeroHitSearches, TestEvidenceLedger
TagsSource, TestEvidenceLedgerSkipsNonEvidenceTools. Live before/
after comparison runs on the Dev side per ruling 6.

Impact: knowledge/web/tavily searches, fs_read_file and the workspace
read_file/grep results now end with a source tag and enter the run
ledger (2k-char head); two consecutive tool failures or two empty
search results inject a concrete change-of-strategy reminder;
base.deliverables v7 and agent-sub-research v3 explain the tags;
fact-check notice points at src results. Non-evidence tools and
failures are unchanged.

Refs: proposal 2026-10-10-agent-delegation-routing-sandbox.md (E4,
R4); Dev task feature/agent-e4-escalation-ledger.
2026-10-10 17:41:38 +00:00
weichen 8355794e45 Merge remote-tracking branch 'origin/main' into feature/dual-speed-real-path
# Conflicts:
#	internal/runtime/llm_direct.go
#	internal/runtime/llm_test.go
2026-10-10 10:05:38 +00:00
weichen b3f885f215 Strip inline think blocks from subagent summaries and card bodies
ci / vet-and-test (pull_request) Successful in 43s
Why: the round-6 real-model dual-speed run showed MiniMax writing its
reasoning as inline <think> blocks; finishChild's partsText fed them into
the background notice turn and the inbox result card verbatim.
Evidence: new runmgr test covers closed-block stripping with body preserved
and conservative handling of unclosed blocks; go test ./... 32 pkgs green.
Impact: partsText removes closed <think>...</think> spans before summary,
notice, and card assembly; unclosed blocks are kept as-is.
Refs: Dev task feature/dual-speed-real-path.
2026-10-10 10:01:15 +00:00
weichen 3f2c7c7033 Nudge long-running turns onto the dual-speed path via the kernel reminder hook
Why: the dual-speed slow lane shipped as an observable capability plus soft
prompt guidance, but on the real (non-mock) path models routinely grind
through heavy document tasks synchronously for minutes with zero user-visible
output - the pattern only engages when the model happens to think of it.
Evidence: five new unit tests over an injected clock cover fire-after-threshold,
quiet-before-threshold, disabled-by-setting, and the replied/delegated guard
paths (reminders observed in the captured kernel requests); full go test
./... 32 pkgs green. Real-model run recorded in the Dev task card.
Impact: runDirect tracks run start, user-reply, and background-delegation
state; reminders() injects a one-shot dual-speed nudge (SR-B10) once elapsed
time crosses runtime.dualSpeedNudgeSeconds (default 75s, 0 disables) while
the user has neither a reply nor a background lane. New setting registered.
Refs: Dev task feature/dual-speed-real-path; SR-B10 (RDM requirements/01 V2.1).
2026-10-10 09:11:18 +00:00
weichen 4df81ef1da Enable parallel tool execution, fix delegate truncation, sandbox deps layer
ci / vet-and-test (pull_request) Successful in 43s
Why: Real runs were fully serial: the direct path never set the kernel's
parallel tool mode, delegate_task handed the parent only the child's
160-char summary (the full text was dropped), MiniMax streamed its
reasoning inside content <think> blocks, and the EXT-16 sandbox hid
~/.local so python-docx/openpyxl/pptx could not even import. All four
were measured defects (F1/F2/F3/F5) in the delegation/routing proposal.

Why: Serial-only mutual exclusion is not enough for order-sensitive
tools - the card-stream test failed with out-of-order appends - so the
ordering moved into the kernel (SerialTools partition, Agent-Native
#44); process events pair by CallID (#42) and tool results write back
through the injected call context (#43).

Evidence: go test ./... green, including new regression anchors:
TestDelegateToolReturnsFullText, TestToolEventsPairByCallID,
TestToolExecModeAndSerialSet, TestOpenLLMClientReasoningSplitAuto,
TestSandboxArgvDepsLayer, TestExecEnvJoinsPythonPath.

Impact: Direct runs now execute independent same-turn calls
(searches, reads, delegate_task, review_findings) concurrently by
default (runtime.parallelTools=false restores sequential); card flow,
plans, workflows, exec primitives and file edits keep model-declared
order. delegate_task returns the capped full child text. MiniMax-*
models get reasoning_split=true so thinking streams via
reasoning_content. --exec-deps-dir/AGENT_SYSTEM_EXEC_DEPS_DIR mounts a
read-only dependency layer into the sandbox and merges PYTHONPATH.
Bumps deps/agent-native to c348441.

Refs: proposal 2026-10-10-agent-delegation-routing-sandbox.md (E1,
F1-F5); Agent-Native #42/#43/#44; Dev task feature/agent-e1-parallel-fixes.
2026-10-10 09:02:10 +00:00
weichen 43297795f5 Keep original materials and cleared results reachable across turns
ci / vet-and-test (pull_request) Successful in 48s
Why: Real-run before/after evidence (phase01 card) showed later turns never
re-read the uploaded source (0 original reads in plan-followup) because the
attachment only existed in the current turn's injection and the context window
hard default was 32000 chars - a 25k-char transcript tripped the clear-on-first
request, replacing old tool results with a pointer the model has no tool to
follow. MiniMax is an interleaved-thinking model whose docs require <think>
blocks in assistant history; dropping them degrades later turns.

Evidence: SELF - new tests TestThinkReplayWrapsAssistantHistory,
TestContextWindowScalesFromTokens, TestThinkReplayEnabled,
TestPersistInputTextsAndListWorkspaceInputs; go test ./internal/... passes;
live before/after comparison on the golden task set recorded on the phase02
task card per the new policy clause.

Impact: models.chat.contextWindow/outputReserve/contextBuffer (tokens,
defaults 128k/16k/4k) drive the in-run clear threshold, converted to chars;
cleared tool results spill to <sandbox>/.agent/results with readable paths;
attachment parse text persists as inputs/<name>.md and the env section lists
all workspace inputs every turn; context.thinkReplay (auto|on|off, auto =
MiniMax) replays thinking blocks into request-side assistant history only.
2026-10-09 14:28:39 +00:00
weichen 8c5612a0a3 Split usage accounting end to end, retry by default, and take the WP6 pins (N3 WP6)
ci / vet-and-test (pull_request) Successful in 44s
Why: subagent runs recorded zero tokens, cache hits were invisible in
run records, the usage event skipped terminal paths, and stream retry
existed only on the direct-chat path (audit N20 residual).
Evidence: go test -count=1 ./... green; TestRetryAttemptsMapping
(setting 0=off→-1, N→N), TestDirectRunUsageSplitOnRecord (Last* and
cache land in the run usage), TestSubRunAccountsTokens (subagent
accounting), TestAddUsageAccumulatesSplitFields (handle chain); pins
carry Agent-Native#35/#37/#38/#39, Agent-Squad#41, Core Usage fields.
Impact: run.Usage carries Last*/cache on every path; subagent runs are
accounted; runtime.llmRetries maps onto the library default (setting 0
disables via -1); the verifier wraps retry+fallback explicitly; retry
events surface as process parts.
Refs: Agent-Native#35-#39, Agent-Squad#41, N3 plan WP6
2026-10-07 17:17:56 +00:00
weichen 766a96e817 Wire the memory port: store-backed adapter, loop injection, migration parity (N3 WP5)
ci / vet-and-test (pull_request) Successful in 41s
Why: memory recall lived as a product-side interface assertion with no
library port, AgentSpec.MemoryScope had no consumer, and the model had
no write-back path. The port (Agent-Native#34) now exists; the product
adapts it over memory_entries.
Evidence: go test -count=1 ./... green; TestStoreMemoryRecallScopeAndLimit
(scope filters and limit), TestStoreMemoryAppendRoundtrip (project
context inheritance), TestRunCtxStoreMemory (runCtx outlet),
TestDirectRunInjectsMemoryBlock (the [记忆] block reaches the request
with the pre-migration text shape and deterministic order).
Impact: assembly-side injection removed (the loop injects per request
— same text, no duplication); memory_write available on the kernel
path; recall defaults to all scopes (pre-migration semantics), with
AgentSpec.MemoryScope narrowing where hosts pass it.
Refs: Agent-Native#34, Agent-Squad#38, N3 plan WP5
2026-10-07 16:23:24 +00:00
weichen 9f3fdb26e2 Give conversation runs the intent journal via JournalOnly sessions (N3 WP2)
ci / vet-and-test (pull_request) Successful in 42s
Why: the product conversation path had zero mid-turn durability
(llm_direct ran without Session — intents, recovery pairing, and
side-effect replay semantics never applied). Transcript-as-authority
would have frozen the assembled prefix, so the journal is wired in
JournalOnly mode: recovery runs against the transcript, the context
stays on the ctxasm pipeline, and recovered outcomes inject as a
system note.
Evidence: go test -count=1 ./... green;
TestDirectRunPairsAfterKillSeed (crash-window transcript gets the
crashInterrupted pair, run proceeds) and
TestDirectRunSeedsStoreHistoryOnce (history appears exactly once in
every request, never enters the journal); the forged-marker and
harness suites pass unchanged.
Impact: conversation runs now journal tool intents and recover them on
the next run; no transparent resume (sealed interrupted stays; the
user keeps chatting). Opening the transcript fails soft (falls back to
the old no-session behavior).
Refs: Agent-Native#31, Agent-Squad#35, N3 plan WP2
2026-10-07 15:26:27 +00:00
weichen 1770fac51f Align the forged-marker guard test with the N6 semantics
ci / vet-and-test (pull_request) Successful in 50s
Why: Stop.Replacement no longer rewrites the in-memory assistant; the
correction reaches the model as a user note. The guard's protective
intent is unchanged (forged body never replays as assistant speech).
Evidence: go test -count=1 ./... green.
Impact: test only.
Refs: Agent-Native#30, N3 plan WP1
2026-10-07 15:06:58 +00:00
weichenandCursor a506e137f6 Compose a separate final reply after the work loop
Why: End-of-turn checks were injected as user messages, so the model answered the checker instead of the user, and the last draft was treated as the reply.
Evidence: go test ./internal/runtime/ ./internal/prompts/ ./internal/settings/ ./internal/ctxasm/
Impact: Rejections are system reminders. A main-model compose step writes the user-facing reply when tools were used. Deliverable cards stay after that reply.
Refs: feature/final-reply-compose
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-02 13:37:54 +00:00
weichenandCursor cd74434b4f Stream tool progress and drop hard agent limits
Why: Tool calls stayed invisible until execution finished, and turn, tool, timeout, and output caps stopped long tasks early.
Evidence: go test ./internal/runtime/ ./internal/tools/ ./internal/prompts/ ./internal/squadadapter/ ./internal/runmgr/ ./internal/app/ ./internal/settings/
Impact: tool.call.delta and tool.output reach the client; default profile, subagents, and squad no longer cap turns or tool calls; exec timeout defaults to 600s with no hard ceiling. A profile or subagent maxTurns above 0 still applies.
Refs: feature/stream-display-overhaul
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-02 02:17:02 +00:00
weichenandCursor 46ce1b2c8e Let subagents run in the background and be reviewed
Why: A parent turn should be able to finish while children keep working, and a review should keep only findings that a second pass confirms. Users also need to override a profile's tools, model, and turn cap without adding dispatch tools.
Evidence: go test ./... passed. New cases cover overlay rejection, role mapping, queued notices, and dropping FAIL or unparsed findings.
Impact: Notices live only in memory, and each conversation allows three background children. Squad writer steps now use the writer profile.
Refs: feature/agent-harness-p3b
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 15:29:01 +00:00
weichenandCursor a3ae1b986d Check final replies before the direct run stops
Why: A direct run could stop on a missing file, a failed lint, or an unverified claim. The final turn now checks registered artifacts and asks a tool-less verifier, and nudges stale plans and todos.
Evidence: go test ./... passed. New runtime tests cover missing and empty artifacts, docx lint errors, verifier reject-then-pass, unparseable and failed verifier calls, nil verifier tools, todo reminders, and the false-deliverable fixture.
Impact: Direct runs with runtime.verify (default on for new runs) spend one extra lightweight call on every final turn. Setting it off keeps the previous stop behavior. Squad and SubLLMRunner are unchanged. The agent-native pin stays a34689c.
Refs: feature/agent-harness-p2
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 13:54:15 +00:00
weichenandCursor cfcf95d335 Run direct chat through the native turn loop
Why: deliverable checks, truncation continuation, and tool budgets should live in one loop instead of a second copy inside LLMRunner.
Evidence: go test ./... in backend passed. Existing runtime assertions were unchanged; new tests cover whole-batch tool-cap rejection with parts saved, and length continuation.
Impact: the direct path enables repeat guard and length continuation. Squad still uses the one-shot deliverable predicate and does not set the new kernel switches.
Refs: feature/agent-harness-p1
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 13:28:17 +00:00
weichenandCursor 188c63357c Replay tool calls natively and tighten the deliverable gate
Why: Flattened "[调用工具 …]" history taught the model to imitate calls and invent artifact ids. A single regex correction then accepted the second false claim.
Evidence: ctxasm replay tests cover native tool messages, missing-result pairing, argument compaction, demoted text, and forged-marker stripping. Runtime tests cover forged markers, extension-less claims, two corrections, and the fallback notice.
Impact: Assistant history sent to the model no longer contains flattened tool calls. The direct runner corrects a false deliverable twice, then appends a notice instead of accepting the claim. The squad entry still fails closed on the same predicate. base.deliverables is now v5.
Refs: feature/agent-harness-p0
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 12:29:38 +00:00
weichenandCursor dab8f31f15 Reject a final reply that claims a file it did not create
Why: A turn with no tool call can still say a document was generated and invent an artifact id, and the chat then shows only that text.
Evidence: go test ./internal/runtime/ ./internal/prompts/ -count=1. The guard fires on an unknown art id or a generation claim with no deliverable, cites an existing artifact without firing, and corrects at most once.
Impact: One extra model turn when the reply falsely claims a file. base.deliverables is now version 2 and forbids claiming a file or printing artifact ids.
Refs: feature/chat-timeline-preview
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 06:05:17 +00:00
weichenandCursor a34e61cd01 Record thinking duration and successful tool summaries
Why: After a refresh the timeline had no thinking duration and successful tool rows expanded to nothing, because only failures stored a summary.
Evidence: go test ./internal/runtime/ -count=1 -run 'TestLLMRunnerRecordsThinkingAndToolDuration|TestLLMRunnerToolTurnTextIsProcess|TestLLMRunnerDeliverablePinnedAfterText'
Impact: Thinking parts gain durationMs; tool calls gain durationMs; tool results keep a short success summary. Requires the core duration field.
Refs: feature/chat-timeline-preview
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 06:04:19 +00:00
weichen 370ae1a280 Generate styled Word deliverables and pin artifact cards in chat
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
2026-10-01 02:48:49 +00:00
weichen 73769f3a07 Land project inbox: aggregation, archive-to-project, project SSE (CF3)
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).
2026-09-30 19:11:11 +00:00
weichen 61731cb288 Unify artifact context backfill and facade cards (CF-A)
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).
2026-09-30 18:40:50 +00:00
weichen 24a28730ea Add streaming card tools (card_begin/card_append/card_commit)
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).
2026-09-30 18:19:13 +00:00
weichen 53c6630eca Add submit_card explicit routing with card-as-authority and context backfill (CF1)
Why: 卡流机制(D39–D43)——产物型长内容显式路由进收件箱:模型经 submit_card 提交 result 卡,全文权威在卡片,消息只存引用,上下文回填防失忆。
Evidence: go test ./internal/runtime/(门控/产卡/引用部件)、./internal/ctxasm/(回填/截断/占位)、./internal/server/ 全绿(新增 TestMockCardflowFullLoop:#cardflow → result 卡 + cardId 部件 + finishRun 锚点回填)。
Impact: 新内置工具 submit_card(ui.cardflow 默认关闭,未声明被幻觉调用时拒绝执行);settings 增 ui.cardflow;style-cardflow 模块 + ModuleBody 注入;ctxasm 增 CardResolver 与 card(n) 观测;runmgr 增 SubmitCard/Card 与锚点回填;mock 增 #cardflow。
Refs: Dev 任务卡 feature/cardflow-r1;依赖 core bcfacee(CardPart.CardID)。
2026-09-30 16:30:13 +00:00
weichen ae8e5d0007 Mark artifact reference parts as process output
Why: tool-produced artifact_ref parts were appended without Process,
unlike the tool_call/tool_result parts of the same turn, so on final
reconcile the artifact chip stayed in the reply area instead of folding
into the process summary.

Evidence: llm.go now sets Process: true on PartArtifactRef next to its
tool parts; new TestLLMRunnerArtifactPartIsProcess drives a tool turn
that produces an artifact and asserts the part exists, is marked, and
carries the artifact ref. go test ./... all packages ok.

Impact: persisted assistant messages fold artifact references into the
collapsed process area, consistent with other tool-turn output.

Refs: code review of feature/chat-process-split-r1 (2026-09-30)
2026-09-30 15:33:48 +00:00
weichen 0e76f599fc Mark tool-turn reply text as process so only the final turn reads as the answer
Why: 中栏过程/回复分离(Cursor 式)需要数据基础:工具轮的解说文本与终轮回复在中栏混排,用户难以扫读最终答复。
Evidence: go test ./internal/runtime/ 新增 TestLLMRunnerToolTurnTextIsProcess / TestLLMRunnerPhaseEventsPerTurn(脚本流注入);go test ./... 全绿。
Impact: 持久化助手消息中工具轮 text 部件带 process=true(终态折叠入过程区);终轮文本不变;无契约类型变更。
Refs: 任务卡 feature/chat-process-split-r1;提案 cardflow-and-process-split(编制中)。
2026-09-30 14:49:47 +00:00