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>
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>
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>
Why: Downstream products must extend the base through a public package and host API instead of editing internal code.
Evidence: go test ./... passed, including plugin v2 assets, sidecar startup, migration v13, pending confirms, HITL timeout, hash embedder, command pairs, and the extension surface snapshot.
Impact: apiVersion 2.0-experimental rejects empty network allowlists for declarative HTTP. Hash embeddings stay opt-in via models.embedding.provider=hash. Plugin secrets resolve per owner at execution time.
Refs: docs/proposals/2026-10-01-plugin-contract-v2.md
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: Squad steps previously ran without tools, and the product had no way to make the squad the conversation entry without losing streaming, cards, or the deliverable guard.
Evidence: go test ./... -count=1 passed, including streaming, cardflow, false-deliverable rejection, tool allowlist, model routing, usage, cancel, and turn and tool budgets.
Impact: runtime.entry defaults to direct. squad uses one kernel step for simple work and the leader for the rest. squad_orchestrate is hidden in that mode. The default is not switched.
Refs: deliverable-quality-system B3-B5
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: Layout rules alone do not produce conclusion-first documents, extra views, or infographics, and nothing scored a deliverable before it was returned.
Evidence: go test ./internal/prompts/ ./internal/quality/ ./internal/tools/ ./internal/squadadapter/ ./eval/ -count=1 and the house-style unittest passed in the previous session.
Impact: Every task inherits content rules. Meetings, reports, and comparisons can name a view family. Long documents without a visual summary warn. quality_review and the squad checker share one scorecard.
Refs: deliverable-quality-system A1-A5
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: The first commit picked up __pycache__ created while running the
house-style suite. Bytecode is not part of the skill and should not be
seeded or reviewed.
Evidence: git rm of the cached pyc files; .gitignore now ignores
__pycache__ and *.pyc.
Impact: The skill tree contains only source. Seed already skips
__pycache__ directories.
Refs: feature/agent-professional-deliverables
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: Generated files kept Word's default theme, US Letter pages,
hand-typed bullets and empty sections. Recipes only showed library
calls, the prompt had no craft standard, and seeded skills could not
be upgraded once written.
Evidence: go test ./... passed. The house-style suite covers three
themes across docx, pptx and xlsx, and rejects a document that repeats
the diagnosed layout failures. lint on the sample minutes exits 1.
Impact: Every run gets a resident quality standard. Office files use
house-style (switchable themes, templates, imitation) and must pass
lint. Skill seeding upgrades untouched builtins and keeps user edits.
Uploads land in inputs/, and the default style is a setting.
Refs: feature/agent-professional-deliverables
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: Main moved the deliverable recipes into skills after this branch
recorded the false-file rule, so the prompt has to keep both.
Evidence: go test ./internal/prompts/ ./internal/runtime/ passed.
The resolved prompt is version 2 and points at the skill library.
Impact: This branch contains the B10 assembly and still rejects a final
reply that claims a file it did not create.
Refs: feature/chat-timeline-preview
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: the full-agent batch left three B10 sub-items open - the
composition root lacked MCP server injection and a Subagent factory,
builtin squad roles carried no explicit Tools/Skills/BashPermission
declarations, and the three Python deliverable recipes still lived
inline in the base.deliverables prompt instead of the skills system.
Evidence: go vet ./... clean; go test ./... 21 packages ok. New cases:
skills seeding idempotency with user-edit preservation and sorted
builtin names; the SubagentFactory bridge mapping delegation fields
into SpawnSubagent task briefs and status/errors back; builtin-role
assertions (all four explicit bash permissions, researcher
search+fetch, reviewer grep+glob, writer ask + 3 skills +
run_python/load_skill); MCP manager cache reuse/rebuild/disable
behavior including invalid JSON and config races.
Impact: internal/skills embeds docx/xlsx/pptx-author SKILL.md and
seeds <data>/skills at startup; base.deliverables references the
skills and keeps only import one-liners; squadadapter.AgentNativeOptions
now receives rc and gains SubagentFactory(rc); app.go adds
tools.mcp.servers loading with a config-keyed manager cache (old
manager closed on rebuild).
Refs: Dev task feature/full-agent-b10-r2 (verifier follow-ups).
Why: the full-agent batch (Agent-Native PR #3, Agent-Squad PR #3) made
roles capable of declaring model/tools/skills/bash execution, but the
product composition root had no path to register the kernel backend or
inject search/exec/skills config.
Evidence: go vet ./... clean; go test ./... 19 packages ok. New cases:
buildBackends registers agent-native only when composition-root options
are enabled (default backend stays agent-system, per the parity
progressive-enablement clause) and resolves explicit
Backend:agent-native roles; InterpreterExecConfigForKernel validates
absolute interpreter paths and the env whitelist reused from the
product exec tools.
Impact: deps/agent-native pinned to f9ab2ef and deps/agent-squad to
9a402e4; app.go resolves settings.models.chat, tools.tavily.*,
runtime.exec, and <data>/skills into squad.AgentNativeConfig per run;
squadadapter exposes the AgentNativeOptions hook and buildBackends.
Refs: Dev task feature/full-agent-r1 batch B10.
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>
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>
Why: string writes of .docx/.xlsx/.pdf produce files that will not open,
and generated binary artifacts were skipped by search entirely.
Evidence: go test ./... 19 packages ok. Office extensions are refused
with a pointer to run_python plus register_artifact. A docgen docx is
searchable after WriteArtifact; unparseable bytes are not indexed.
Impact: write_artifact and fs_write_file no longer accept those
extensions. Text artifacts index as before. Merge after the interpreter
PR so the error text names tools that exist.
Refs: task feature/binary-doc-index; supersedes Dev #99 / Backend #27
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: deliverable prompts already tell the model to generate Office files
with run_python and register them, but the executors were never
registered, so calls missed the registry and fell back to text-only
write_artifact.
Evidence: go test ./... — 19 packages ok, including echo/script-retention,
empty-script and runtime.exec gate, process-group timeout, python ZIP
magic, and ExecuteTool backfill of register_artifact after run_python.
Scripts stay under the session .agent/ directory; bash/python3 are
resolved to absolute paths; timeout kills the process group.
Impact: models can execute workspace scripts and register binary
deliverables. runtime.exec=false still fail-closes the whole family.
Office extensions now get real MIME types so binary bytes are not
indexed as text.
Refs: task feature/exec-interpreters
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: two field reports against the live build — deliverable cards never
appeared in chat (only model-written filenames) and the artifacts panel
felt dead. Root cause found in runmgr.ExecuteTool: registry tools that
write artifacts via rc.WriteArtifact never had res.Artifact set (only
the oversized-result path did), so llm.go never emitted artifact_ref
parts for real tool output; the unit suite passed via fakes that set
it directly. Architecturally, document generation moves back to the
agent (user directive): system provides execution primitives and the
delivery bridge, not domain tools like write_docx.
Evidence:
- runmgr: toolCtx tracks artifacts written during a call and
ExecuteTool backfills res.Artifact (new runmgr test proves
write_artifact now surfaces one; negative test: no phantom artifact)
- new tools/register_artifact: bridge from workspace files (binary
docx/xlsx/pptx/pdf/images, <=10MB) to deliverable artifacts;
run_shell/run_python interpreter executors are designed
(script-to-disk + whitelisted bash/python3, sandbox cwd, caps) and
land in a follow-up batch behind the security gate decision
- removed builtin write_docx + its prompt; write_artifact prompt now
text-only with explicit no-binary guidance; new always-on base
prompt base.deliverables teaches the generate->register->summarize
workflow with python-docx/openpyxl/python-pptx recipes;
task.doc-minutes rewritten to the workflow
- final-output contract: inline <think> blocks in streamed content are
split into thinking (process) parts so the final reply stays clean
(unit + runner tests)
- go test ./... 19 packages ok; vet clean
Impact: every tool artifact now lands as an in-chat deliverable card;
mock #doc unchanged as demo fixture; binary office mimes stay out of
the text index; write_docx callers see the tool gone (prompt reroutes
them).
Refs: task feature/agent-native-deliverables-r1
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 adjudicated preview plan needs server-side OG fetching for link
cards, and the proposal's reserved-capability items call for the fs tool
family to exist behind a default-off gate (implemented, not offered).
Evidence: GET /api/url-preview fetches and parses og:title/description/
site_name/image/favicon with a 5s timeout, 256KB body cap, text/html
content check, TTL cache, and SSRF guards enforced at dial time (loopback
/private/link-local/multicast/reserved/CGNAT rejected per hop, anti DNS-
rebind; AS_URL_PREVIEW_ALLOW_PRIVATE=1 exists for local testing only,
default fail-closed; errors return sanitized cards, never internal
addresses). fs_read_file/fs_write_file/fs_list_dir register as Hidden
tools sandboxed under <root>/<owner>/<conversationId>: traversal,
absolute paths, backslashes, and symlink escape rejected; 1MB/2MB size
caps; writes register an artifact so workspace files stay visible in the
panel. ToolDesc.Hidden gates both model visibility (runctx.Tools) and
/api/tools listing on runtime.fsTools, and registry.Execute re-checks
fail-closed. ToolExecCtx gains OwnerID/WorkspaceRoot/SettingBool.
go test ./... green (fs negative matrix, SSRF negatives, endpoint
fail-closed, cache).
Impact: link previews work end to end once the frontend wires the
fetcher; fs tools are inert until runtime.fsTools is enabled.
Refs: task feature/file-preview-caps; core 4d29301.
Why: Local.Put joined the caller-supplied id straight into the store directory, and store.UpdateArtifactContent feeds the HTTP path parameter into it, so a traversal id (encoded ../ in the artifact path) reaches an arbitrary-path file write; Get/Delete took stored refs unvalidated too. The 2026-09-30 deep security scan flagged the unsanitized join as the one actionable finding after triage.
Evidence: new internal/blobstore tests cover rejection of empty/dot/dotdot/traversal/absolute/backslash/NUL ids with no residue in the store dir, a normal Put/Get/Delete roundtrip, and refusal of out-of-store refs for Get and Delete; go vet ./... and go test -count=1 ./... pass.
Impact: internal/blobstore only; plain-filename ids (the only form produced today via newID and artifact path params) keep working; no schema, API, or caller change.
Refs: Dev-side task fix/blobstore-id-hardening (gitlink pin follows after combined verification)
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)
Why: generated deliverables (e.g. meeting-minutes docx) had no reliable
download path — the content endpoint set no Content-Disposition, so the
filename only survived via the front-end <a download> attribute, and
contentTypeOf returned text/plain for any artifact whose MIME column was
empty, mangling office/pdf uploads.
Evidence: artifactContent now always sets Content-Disposition (inline by
default, attachment with ?download=1) with an RFC 5987 filename* for
non-ASCII names plus an ASCII fallback; contentTypeOf consults an
explicit office-format extension table then mime.TypeByExtension before
the kind fallbacks. New tests cover disposition on both modes, the
encoded Chinese filename, and the extension/mime precedence chain;
go test ./... green.
Impact: front-ends can link direct download URLs and browsers receive
correct file types for docx/xlsx/pptx/pdf/csv/md regardless of the
stored MIME value.
Refs: task feature/chat-order-artifact-files.
Why: conversation transcripts were the only project channel not
readable across sessions (artifacts/knowledge are already shared),
which caused duplicate parallel work; see proposal
2026-09-30-cross-session-reading.
Evidence: runmgr/crossread_test.go covers the full gate matrix
(project gate on/off x outbound flag x private target x cross-project
x cross-tenant x self-read x archived x limit clamping) against a real
store + settings chain; store tests cover migration v11, flag
persistence and tenant isolation; tools/peers_test.go covers args
validation, transcript rendering and the untrusted-content banner;
go test ./... green.
Impact: setting crossSession.read (default off, schema-driven);
conversation columns allow_cross_read (default true) and cross_private
(default false) with PATCH support; builtin tools list_conversations
and read_conversation gated fail-closed in runmgr toolCtx; nested
agent-system-core pin bumped to fd44179 (Core PR #6).
Refs: Agent-System-Documents proposals/2026-09-30-cross-session-reading.md
(Dev task feature/cross-session-reading).
Why: the user ruled out self-registration (2026-09-30): accounts are
created only by admins who set an initial password; first login (and
first login after any admin reset) must force a password change.
Evidence:
- migration v10 auth_accounts (users password/must_change/is_admin +
sessions table; upgrade test walks v1<->v10 both directions).
- argon2id hash/verify with PHC encoding; store tests cover hash
roundtrip, duplicate-owner conflict, must-change lifecycle, session
keep/except semantics.
- e2e TestAdminAccountFlow: static login page reachable without auth,
wrong password 401, login sets HttpOnly cookie + mustChangePassword,
admin creates user (409 on duplicate), non-admin create 403, forced
change clears flag and old password dies, admin reset revokes sessions
and re-arms forced change, API-key channel untouched, 5-fail backoff
429, logout kills session. Full go test ./... green.
Impact: middleware now accepts Bearer key OR session cookie and exempts
static + /api/auth/login (also fixes the latent case where the login
page itself could 401). Embedded no-auth mode unchanged.
Refs: proposal 2026-09-30-ui-redesign-and-auth.md section 5 (admin-issued
variant, user decision 2026-09-30)
Why: Agent-Native ships a Tavily integration (key-pool rotation,
markdown output, fallback copy) that the backend never registered, so
the catalog's WebSearch prompt had no carrier; wiring the tool gives it
one and gives the agent live-web reach.
Evidence: 4 new tool tests (registration, markdown formatting, empty
query, failure fallback carried inside the error to match registry
replay semantics); go test ./... 16 packages ok; live boot check - no
keys means not registered, two keys log registration with both tools
in /api/tools and 46 library modules in /api/prompts.
Impact: tools.tavily.apiKeys/endpoint settings (restart effect; empty
pool means the tool is absent, no silent degradation); tool.tavily_search
and tool.web_search prompt modules inject citation discipline (cite
sources, keep inference separate, fall back to workspace materials on
failure); library floor raised to 46.
Refs: feature/tavily-search-tool task card; guide disposition table in
Documents.
Why: the porting filter excluded templates without a named roadmap slot,
but the user's bar was anything portable; wizard, memory extraction,
session memory and in-place doc updates all have carriers (delegation
today, memory/doc-editing slots later).
Evidence: go test ./... 16 packages ok with the library floor raised to
44; module format checks unchanged.
Impact: +agent.docs-wizard, +agent.memory-extractor, +aux.session-memory,
+aux.magic-docs; no wiring change.
Refs: feature/prompt-catalog-coverage task card; guide section 9 in
Documents lists the full disposition.
Why: upstream merged prompt_modules as migration v8; the version
namespace is linear so the rebased task-sidebar work moves to v9.
Evidence: go vet + full go test ./... green; migration upgrade test now
walks v1<->v9 (up and down paths exercised for real).
Impact: fresh databases apply v8 (prompts) then v9 (conversation flags);
no released v8 conversation_flags ever existed, so no deployed database
can hold the old numbering.
Why: a non-nil Authenticator with Enabled=false is the embedded no-auth
mode; reporting auth=true there made the sidebar account footer show
the wrong identity state (found in the live headless walk).
Evidence: restarted binary now returns {"auth":false,...} in embedded
mode; TestTaskListAndFlags still green.
Impact: response field value only.
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: prompts lived inline in Go (profile const, subagent string, squad
role one-liners, tool descriptions) - every copy change shipped code,
and task guidance like meeting-minutes quality lived permanently in the
base prompt whether or not the task was at hand.
Evidence: new prompts package tests (library integrity, default
assembly, skill triggering incl. attachment gate and command bypass,
priority supersession, override chain drift, command match, frontmatter
parse); composite make test green; runtime check on a live server
(40 modules across 7 layers, override round-trip, /minutes starts a
run instead of hitting the command bus).
Impact: 40 builtin modules as embed data (5 base + 1 env + 12 task
skills + 10 agent roles + 7 tool descriptions + 3 aux templates + 2
styles); migration v8 adds prompt_modules for user overrides with
basedOnVersion drift markers; ctxasm assembles multi-segment system
messages with per-module observability; subagent/squad/tool copy now
resolve from the library with inline fallbacks; skill commands surface
in the / menu and route to runs; default profile SystemPrompt empties
onto the library base; pins deps/agent-system-core to the contract
commit.
Refs: feature/prompt-library task card; design guide in Documents.
Why: attachments were hard-truncated at 16k chars (most of a meeting
transcript silently dropped), injection carried no task guidance, the
builtin profile prompt was one generic line, subagents were capped at
300 chars, and docx tables were appended after all paragraphs losing
document order - together these produced sparse meeting minutes.
Evidence: go test ./... 16 packages ok incl. new ctxasm limit tests and
docx order assertions (heading->para->table->para); composite make test
green over the pinned combo.
Impact: attachment ceiling is 48k chars (settings
context.maxAttachmentChars), truncated on rune boundaries and observable
in the context report; the builtin prompt demands full-coverage
structured markdown for document tasks and upgrades stale builtin rows
on boot; budget.maxTokens now reaches the provider; subagents may write
full-length results; docx tables stay in place.
Refs: feature/chat-live-quality task card.
Why: T4 workspaces are declared by plugins via provides.workspaces (Core PluginWorkspace is the authoritative type); the host must surface the merged overlay for the frontend to render in OverlayHost.
Evidence: go test green - plugins suite new TestWorkspacesOverlay (manifest + workspaces/main.json loads, ListWorkspaces returns the declaration with shortcut and body); full internal sweep unchanged.
Impact: plugins host loads workspaces/*.json assets and exposes ListWorkspaces; server adds GET /api/workspaces passthrough; no behavior change without the manifest key.
Refs: docs/proposals/2026-09-30-ui-inbox-command-workspace.md T4; task card feature/workspaces-r1
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
Why: The frontend appends the confirmation receipt locally so it appears
immediately; returning the server-persisted message (with its id) keeps the
authoritative reconcile duplicate-free.
Evidence: go build green; covered by combo test in Dev.
Impact: response shape gains receipt field (additive).
Refs: proposal 2026-09-30-ui-inbox-command-workspace
Why: T2 of the interaction foundation — activity cards as first-class state
objects behind the right-rail inbox (proposal D25): upload ingest cards
(SR-A5 failures explicit, artifact retrievable), HITL projection cards
(double-presence, ref-linked two-way sync), squad orchestration cards and
the mock #upload demo of the full card lifecycle.
Evidence: go test ./... green across 14 packages incl. new cardsvc suite
(lifecycle, action labels and idempotency, pin/dismiss, owner isolation,
resolve-by-ref idempotency) and updated migration test (v6 activity_cards,
both dialects); events flow through the session event buffer (persist, seq,
replay); receipts appended to the conversation timeline on card actions.
Impact: additive; cards disabled (SetCards nil) degenerates to the T0
baseline; upload cards persist at project level per the v1 inbox boundary
(conversation-scoped inbox; project-level aggregation is follow-up).
Refs: modules/documents docs/proposals/2026-09-30-ui-inbox-command-workspace.md
Why: startup had only defaults and CLI flags; dev/test/prod operation needs
the standard baseline (explicit file, environment, explicit-only CLI) and a
read-only diagnostic.
Evidence: internal/config unit tests cover precedence, unset-CLI no-override,
presence-based file semantics, unknown-key/missing-file errors, env bool
parsing, explain source labelling and DSN redaction; full suite 12 packages
pass; live run of config explain with envs/prod.json shows correct layer
attribution and redaction.
Impact: serve gains --config and AGENT_SYSTEM_* env overrides (behavior
unchanged when neither is used); new config explain subcommand; envs/
examples and PROJECT.md configuration section.
Refs: documents docs/proposals/2026-09-30-configuration-surface.md; standards/configuration.md
Why: backend main pinned core 019617e (unfetchable post-migration) and the
store List* functions returned nil slices that encode as JSON null, which
crashed the frontend nav with .map on null (the 2026-09-30 white-screen).
Evidence: go test ./... across all packages; store regression
TestEmptyListsSerializeAsEmptyArrays asserts [] for empty project lists.
Impact: all 17 store list sites now initialize empty slices; build-blocker
core pin resolved; frontend no longer receives null for empty lists.
Refs: documents/records/2026-09-30-history-migration.md
Details (original message):
Add the vector RAG pipeline: paragraph chunker, OpenAI-compatible embeddings and rerank clients, dual-tier vector store with cosine search, and RRF hybrid retrieval