Skip to content

Transform Lace persona system: Orchestrator-first approach#317

Open
obra wants to merge 1 commit intomainfrom
socratic-pm
Open

Transform Lace persona system: Orchestrator-first approach#317
obra wants to merge 1 commit intomainfrom
socratic-pm

Conversation

@obra
Copy link
Copy Markdown
Owner

@obra obra commented Sep 18, 2025

Summary

This PR transforms Lace's persona system to default to a thoughtful orchestrator that understands user goals before delegating implementation, rather than immediately jumping into coding.

Problem

Currently, Lace acts as a "yes man" coder - when users say "build me a todo list", it just builds one without understanding what they're actually trying to accomplish. This often leads to building the wrong thing.

Solution

Transform the default lace persona from a coder to an intelligent orchestrator that:

  • Focuses on understanding user goals through contextual elicitation
  • Asks intelligent follow-up questions based on what's been shared (not scripted questions)
  • Delegates implementation work to specialized agents
  • Coordinates multiple agents working in parallel when beneficial

Key Changes

1. New Lace Persona (Orchestrator)

  • Created new lace.md focused on goal clarification and orchestration
  • Knows how to use task management tools (task_add, task_list, etc.)
  • Understands async vs sync delegation patterns
  • Documents how to spawn agents with "new:coder:provider/model" format

2. Explicit Coder Persona

  • Renamed old lace.md to coder.md for explicit coding tasks
  • Consolidated coding-agent content into coder (removed duplicate)
  • Coder agents handle all programming and implementation work

3. Internal Persona Marking

  • Renamed internal personas with underscore prefix for clarity:
    • helper-agent_helper-agent
    • session-summary_session-summary
  • Makes it clear which personas are for public use vs internal system use

Testing

  • Updated all tests to reflect new persona structure
  • Added comprehensive tests for new lace persona behavior
  • All tests passing (147 passed, 7 skipped - external service tests)

Impact

This change makes Lace default to being a thoughtful partner who:

  1. Understands what users are ACTUALLY trying to do
  2. Creates well-defined tasks with clear success criteria
  3. Delegates work to appropriate specialists (coder agents)
  4. Maintains strategic oversight while implementation happens

The goal is to make the human partner "superhuman" through excellent project management and coordination, not just immediate code generation.

Breaking Changes

None for end users. The system still defaults to the 'lace' persona, it just behaves differently now (better!). Users who want the old behavior can explicitly request the 'coder' persona.

## Summary
- Transform default 'lace' persona from coder to thoughtful orchestrator
- Create explicit 'coder' persona for programming tasks
- Mark internal personas with underscore prefix (_helper-agent, _session-summary)

## Changes

### New Lace Persona (Orchestrator)
- Focuses on understanding user goals through contextual elicitation
- Asks intelligent follow-up questions based on what's been shared
- Delegates implementation work to specialized agents (particularly 'coder')
- Knows how to use task management tools (task_add, task_list, etc.)
- Understands async vs sync delegation patterns

### Persona Restructuring
- Renamed old 'lace.md' to 'coder.md' (the coding-focused persona)
- Consolidated 'coding-agent' content into 'coder' and removed duplicate
- Marked internal personas with underscore prefix for clarity
- Created new 'lace.md' focused on orchestration and goal clarification

### Task Delegation
- Documented how to use task_add with "new:coder:provider/model" format
- Explained difference between async tasks (parallel work) and sync delegation
- Added clear instructions for spawning multiple agents for independent work

## Test Updates
- Updated all tests to reflect new persona names
- Added comprehensive tests for new lace persona behavior
- All tests passing (except external service integration tests)

This change makes Lace default to being a thoughtful partner who clarifies goals
before jumping into implementation, improving the overall user experience.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 18, 2025

Walkthrough

Persona identifiers renamed in tests (coding-agent → coder; helper-agent → _helper-agent) and a new internal persona (_session-summary) added. coder.md inserts interaction-patterns and environment includes. lace.md is rewritten to a single explicit persona spec. New lace persona test suite added; other tests updated to new identifiers and expectations.

Changes

Cohort / File(s) Summary
Persona content: coder
packages/core/config/agent-personas/coder.md
Inserted includes sections/interaction-patterns.md and sections/environment.md before sections/tools.md; whitespace normalization; added trailing newline.
Persona content: lace rewrite
packages/core/config/agent-personas/lace.md
Replaced modular includes with a comprehensive, explicit Lace persona spec covering identity, principles, workflows, delegation strategy, context handling, and interaction style; preserves {{context.disclaimer}}.
Example personas tests update
packages/core/src/config/example-personas.test.ts
Renamed persona keys to coder, _helper-agent; added _session-summary; updated registry assertions, path checks, prompt generation, and validation to new identifiers.
New lace persona tests
packages/core/src/config/lace-persona.test.ts
Added suite validating lace and coder prompt generation, content characteristics, default persona fallback to lace, and distinct prompts across lace/coder/_helper-agent.
Integration persona system tests update
packages/core/src/integration/persona-system.test.ts
Refactored usages from coding-agent/helper-agent to coder/_helper-agent; included _session-summary; updated task assignment, agent creation callbacks, and parsing specs to new identifiers.
Agent spawning tests update
packages/core/src/tasks/agent-spawning-personas.test.ts
Updated datasets and expectations from coding-agent/helper-agent to coder/_helper-agent; no production logic changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Caller
  participant PM as PromptManager
  participant PR as personaRegistry
  participant FS as Persona Files

  Dev->>PM: generateSystemPrompt(personaKey?)
  alt personaKey omitted
    PM->>PR: getDefaultPersona()
    PR-->>PM: "lace"
  else personaKey provided
    PM-->>PM: use provided key
  end
  PM->>PR: hasPersona(key)
  PR-->>PM: true/false
  alt found
    PM->>PR: getPersonaPath(key)
    PR-->>PM: path to *.md
    PM->>FS: load persona content
    FS-->>PM: persona markdown
    PM-->>Dev: system prompt (persona-specific)
  else not found
    PM-->>Dev: error
  end
Loading
sequenceDiagram
  autonumber
  actor Orchestrator as Lace Persona
  participant Registry as personaRegistry
  participant Coder as coder persona
  note over Orchestrator: From Understanding to Action

  Orchestrator->>Orchestrator: Parse intent, ask follow-ups
  Orchestrator->>Coder: delegate(task, context)
  Coder-->>Orchestrator: result
  Orchestrator->>Orchestrator: Synthesize & Validate
  Orchestrator-->>Orchestrator: Iterate or finalize
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes


Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Sep 18, 2025

Code Review: Transform Lace persona system - APPROVED

This is an excellent architectural improvement that transforms Lace from a reactive coder to a thoughtful orchestrator. The changes are clean, well-tested, and maintain backward compatibility while fundamentally improving the user experience.

Key Strengths

  • Clear separation between orchestrator (lace) and implementer (coder) personas
  • Focus on understanding user goals before implementation
  • Consistent underscore naming for internal personas
  • Comprehensive test coverage (147 passing tests)
  • No breaking changes for end users

Suggestions for Future Improvements

  • Consider hiding internal personas from public API responses
  • Add integration tests for full orchestration flow
  • Document delegation failure handling patterns
  • Add metrics for multi-agent coordination performance

The implementation follows YAGNI principles, maintains code quality standards, and introduces no security concerns. Ready to merge.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (10)
packages/core/config/agent-personas/lace.md (2)

72-76: Align NewAgentSpec example with actual format/models used in tests

Use a model name we already exercise elsewhere to avoid confusion and ensure copy/paste works.

- - Example: `task_add({ tasks: [{ title: "Implement auth", prompt: "...", assignedTo: "new:coder:anthropic/claude-3" }]})`
+ - Example: `task_add({ tasks: [{ title: "Implement auth", prompt: "...", assignedTo: "new:coder:anthropic/claude-3-sonnet" }]})`

39-48: Add an explicit security/PII guardrail to Working Principles

Make it explicit not to log secrets or sensitive data; aligns with repo guidelines.

 ## Working Principles
@@
 **Maintain Momentum**: While thorough understanding is important, don't get stuck in analysis paralysis. Know when you have enough information to proceed effectively.
+
+**Protect Sensitive Data**: Never log API keys, credentials, or PII. Prefer structured logs with minimal metadata, and mask tokens in any shared context.
packages/core/src/tasks/agent-spawning-personas.test.ts (3)

1-1: Add ABOUTME header per repo guidelines

Top-of-file ABOUTME comment is required for all *.ts files.

+// ABOUTME: Tests agent spawning via NewAgentSpec, ensuring persona/provider/model plumb through and events fire.
 import { describe, it, expect, beforeEach, vi, type MockedFunction } from 'vitest';

37-45: Remove unused variable in test

_taskId is never used.

-    const _taskId = await taskManager.createTask(
+    await taskManager.createTask(
       {
         title: 'Test Task',
         prompt: 'Do something',
         assignedTo: agentSpec,
       },
       context
     );

150-156: Rename test to match actual event payload

Event does not include persona; either include persona in the event (requires prod code change) or rename for accuracy. Suggest renaming the test title now.

-  it('emits agent spawned event with persona information', async () => {
+  it('emits agent spawned event with provider/model information', async () => {
packages/core/src/integration/persona-system.test.ts (3)

1-1: Add ABOUTME header per repo guidelines

Missing ABOUTME comment.

+// ABOUTME: Integration tests for persona registry, prompt generation, NewAgentSpec parsing, and task workflow.
 import { describe, it, expect, beforeEach, vi } from 'vitest';

161-174: Eliminate any in tests; guard then cast to branded type

Follow “assert by parsing to unknown then validating before casting”.

-    for (const spec of specs) {
-      const agentSpec = spec as any; // Type assertion for test
-
-      // Should be recognized as valid NewAgentSpec
-      expect(isNewAgentSpec(agentSpec)).toBe(true);
-
-      // Should parse correctly
-      const parsed = parseNewAgentSpec(agentSpec);
+    for (const spec of specs) {
+      // Should be recognized as valid NewAgentSpec
+      expect(isNewAgentSpec(spec)).toBe(true);
+      // Should parse correctly (safe cast after guard)
+      const parsed = parseNewAgentSpec(spec as ReturnType<typeof String> & import('~/threads/types').NewAgentSpec);

Additional import (optional for clarity):

+// import type { NewAgentSpec } from '~/threads/types';

177-184: Remove unnecessary any in negative-format test

No cast needed; these are plain strings.

-    for (const oldFormat of oldFormats) {
-      const spec = oldFormat as any;
-      expect(isNewAgentSpec(spec)).toBe(false);
-    }
+    for (const oldFormat of oldFormats) {
+      expect(isNewAgentSpec(oldFormat)).toBe(false);
+    }
packages/core/src/config/example-personas.test.ts (1)

1-1: Add ABOUTME header per repo guidelines

ABOUTME header is required for *.ts files.

+// ABOUTME: Sanity checks for bundled personas: discovery, paths, prompts, and validation.
 import { describe, it, expect } from 'vitest';
packages/core/src/config/lace-persona.test.ts (1)

55-66: Strengthen default-persona assertion

Actually exercise the default parameter path by omitting the persona argument.

-  it('default agent uses lace persona', async () => {
+  it('default agent uses lace persona', async () => {
     // This is implicit in Agent constructor: this._persona = config.persona || 'lace';
     // We're verifying the fallback behavior
     const promptManager = new PromptManager({});
 
-    // When no persona is specified, it should use 'lace'
-    const defaultPrompt = await promptManager.generateSystemPrompt('lace');
+    // When no persona is specified, it should use 'lace'
+    const defaultPrompt = await promptManager.generateSystemPrompt();
     const explicitLacePrompt = await promptManager.generateSystemPrompt('lace');
 
     expect(defaultPrompt).toBe(explicitLacePrompt);
   });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between 0ff06de and bee72d5.

📒 Files selected for processing (6)
  • packages/core/config/agent-personas/coder.md (3 hunks)
  • packages/core/config/agent-personas/lace.md (1 hunks)
  • packages/core/src/config/example-personas.test.ts (4 hunks)
  • packages/core/src/config/lace-persona.test.ts (1 hunks)
  • packages/core/src/integration/persona-system.test.ts (4 hunks)
  • packages/core/src/tasks/agent-spawning-personas.test.ts (6 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
packages/core/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

In core, use ~/* path aliases for internal imports and omit file extensions in import specifiers

Files:

  • packages/core/src/config/lace-persona.test.ts
  • packages/core/src/tasks/agent-spawning-personas.test.ts
  • packages/core/src/config/example-personas.test.ts
  • packages/core/src/integration/persona-system.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Never use inline dynamic imports in type positions; declare imports at the top instead
Each file starts with a // ABOUTME: comment describing its purpose
TypeScript strict: prefer unknown over any; avoid any entirely
Always await Promises or explicitly use void (no floating promises)
No unsafe assignments; do not assign values of type any without proper typing or narrowing
Remove unused imports and variables
Explain the WHY any time a linting rule is disabled in code
Never log API keys or sensitive content; prefer structured log objects with metadata

Files:

  • packages/core/src/config/lace-persona.test.ts
  • packages/core/src/tasks/agent-spawning-personas.test.ts
  • packages/core/src/config/example-personas.test.ts
  • packages/core/src/integration/persona-system.test.ts
packages/core/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not use console.* for server-side debugging; use the repository logger

Files:

  • packages/core/src/config/lace-persona.test.ts
  • packages/core/src/tasks/agent-spawning-personas.test.ts
  • packages/core/src/config/example-personas.test.ts
  • packages/core/src/integration/persona-system.test.ts
**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{test,spec}.{ts,tsx}: Co-locate tests next to sources; name tests *.test.ts(x) or *.spec.ts(x)
Tests should import real production types and use typed mocks
Use factory fixtures with Partial for building test data
Assert by parsing to unknown then validating before casting in tests
Ban any and @ts-ignore in tests; if unavoidable, localize to one line with a TODO
Use tempdir utilities when creating temporary directories in tests

Files:

  • packages/core/src/config/lace-persona.test.ts
  • packages/core/src/tasks/agent-spawning-personas.test.ts
  • packages/core/src/config/example-personas.test.ts
  • packages/core/src/integration/persona-system.test.ts
🧬 Code graph analysis (4)
packages/core/src/config/lace-persona.test.ts (1)
packages/core/src/config/prompt-manager.ts (1)
  • PromptManager (27-143)
packages/core/src/tasks/agent-spawning-personas.test.ts (1)
packages/core/src/threads/types.ts (1)
  • createNewAgentSpec (538-540)
packages/core/src/config/example-personas.test.ts (1)
packages/core/src/config/persona-registry.ts (1)
  • personaRegistry (162-162)
packages/core/src/integration/persona-system.test.ts (5)
packages/core/src/agents/agent.ts (3)
  • AgentConfig (33-44)
  • provider (684-689)
  • model (696-699)
packages/core/src/tasks/task-manager.ts (2)
  • AgentCreationCallback (11-16)
  • TaskManager (18-336)
packages/core/src/threads/types.ts (2)
  • createNewAgentSpec (538-540)
  • isNewAgentSpec (534-536)
packages/core/src/config/prompt-manager.ts (1)
  • PromptManager (27-143)
packages/core/src/config/prompts.ts (1)
  • loadPromptConfig (58-75)
🔇 Additional comments (2)
packages/core/config/agent-personas/lace.md (1)

87-99: Verified: template variables and task/delegate tools are present

Found {{context.workingDirectory}} and {{context.platform}} in packages/core/config/agent-personas/lace.md; {{context.disclaimer}} in packages/core/config/agent-personas/coder.md and _helper-agent.md; context tests in packages/core/src/tools/context-working-directory.test.ts. Tools 'delegate' and task verbs ('task_add','task_list','task_view','task_add_note','task_complete') are implemented/registered in packages/core/src/tools/implementations/delegate.ts, packages/core/src/tools/implementations/task-manager/tools.ts and packages/core/src/tools/tool-catalog.ts.

packages/core/config/agent-personas/coder.md (1)

22-25: Includes exist; duplicates found — confirm render order before tools

interaction-patterns.md and environment.md exist at packages/core/config/agent-personas/sections and are included in:

  • packages/core/config/agent-personas/coder.md — lines 22, 24
  • packages/core/config/agent-personas/_helper-agent.md — lines 22, 24

Ensure these includes are rendered before any tools sections and remove or consolidate the duplicate includes if unintentional.

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