- Revert leader workspace override: leader keeps personal workspace as
default, team workspace accessible via ToolTeamWorkspaceFromCtx
- Auto-copy: when leader creates team_tasks, scan subject+description
for file paths → copy from personal to team workspace so members can
access them
- Safety: Lstat (reject symlinks), 10MB size cap, .env excluded from
allowed extensions, path traversal blocked
- Prompt hint: clarify members can only access team workspace files,
referenced files are auto-copied
Team members dispatched via team tasks can now read the leader's memory
files (MEMORY.md, memory/*.md) as a fallback when they have no own
memory. Memory writes are blocked for members — only the leader can
save memory files. This follows the existing team_workspace context
propagation pattern: dispatch metadata → RunRequest → context → tools.
Affected tools: read_file (interceptor), memory_get, memory_search,
list_files (interceptor). All include leader fallback with per-user →
global scope cascade.
- Split EnsureUserFilesFunc into EnsureUserProfileFunc (profile + workspace)
and SeedUserFilesFunc (context file seeding) for single-responsibility
- Merge userWorkspaces + userFilesSeeded sync.Maps into unified userSetups
struct to prevent desync between workspace and seeding state
- Add skipIfAnyExist param to SeedUserFiles to encapsulate the
"seed only for brand-new users" logic within the bootstrap package
- Extract getOrCreateUserSetup helper for clean per-user initialization
- Add bootstrap state tests covering all 4 system prompt branches
- Keep legacy EnsureUserFilesFunc as fallback for backward compatibility
- Separate file seeding from workspace resolution so agents without
workspace still get BOOTSTRAP.md and USER.md seeded
- Always seed context files for existing profiles that have zero files
(handles EnsureUserProfile pre-creation via HTTP API)
- Add persistent "USER PROFILE INCOMPLETE" nudge in system prompt when
BOOTSTRAP.md is cleaned up but USER.md remains blank
- Move bootstrap auto-cleanup nudge before session flush so the reminder
is persisted to history
- Add userFilesSeeded sync.Map to avoid redundant seeding calls
- Capture workspace from seeding call to eliminate double DB roundtrip
Replace inline workspace path computation in loop_context.go with composable
WorkspaceLayer pipeline (tenant → team → project → user/chat). Each layer is
a pure function that appends a path segment or is a no-op.
- New workspace_resolver.go: ResolveWorkspace, TenantLayer, TeamLayer,
ProjectLayer (future), UserChatLayer, SanitizePathSegment
- 16 unit tests covering all layer combinations
- Migrate loop_context.go, loop_history.go, team_tasks_mutations.go
- Move sanitizePathSegment from agent to tools package (exported)
- Zero behavior change — identical paths for all scenarios
Add store.RunContext struct that consolidates 27 loop-injected context
values into a single typed struct. RunContext is built once in
loop_context.go and injected via store.WithRunContext(ctx, rc).
24 accessor functions (10 in store/context.go, 14 in tools/context_keys.go)
updated with RunContext fallback — check individual key first, then
RunContext. Consumers (170+ files) require zero changes.
This enables adding new scope fields (e.g. ProjectID) by adding a single
struct field instead of a new context key + With/From function pair.
Move agent/tenant/user/workspace context enrichment, input guard, and
message truncation from runLoop() into dedicated injectContext() method.
Reduces loop.go from 1553 to 1346 LOC. No behavior change.