Skip to content

sdk: migrate persona spawn to @agentworkforce/persona-kit#973

Merged
willwashburn merged 7 commits into
mainfrom
claude/peaceful-meitner-wNwo4
May 25, 2026
Merged

sdk: migrate persona spawn to @agentworkforce/persona-kit#973
willwashburn merged 7 commits into
mainfrom
claude/peaceful-meitner-wNwo4

Conversation

@willwashburn

Copy link
Copy Markdown
Member

Summary

  • Replaces @agentworkforce/harness-kit + @agentworkforce/workload-router with @agentworkforce/persona-kit@^3 in @agent-relay/sdk.
  • Rewrites AgentRelay.spawnPersona to run the full persona-kit lifecycle (skill installs, mount policy, CLAUDE.md / AGENTS.md sidecars, harness config files, persona inputs) via buildPersonaSpawnPlan + executePersonaSpawnPlan. All side effects are reversed in LIFO order when the spawned agent exits.
  • Adds AgentRelay.getPersonaSpawnPlan(id) (and a module-level getPersonaSpawnPlan export) for dry-run inspection of a persona's resolved harness argv, skill installs, mount policy, sidecars, and inputs — no fs writes, no subprocesses.
  • Curated [Unreleased] in CHANGELOG.md with the new behavior, the breaking changes, and migration guidance.

Closes #832.

Why

@agent-relay/sdk's previous spawnPersona only translated a persona's harness/model/system-prompt and silently dropped the rest of the schema — skills, mount policy, sidecar markdown, inputs. The header comment of the old personas.ts documented this explicitly. As #832 framed it: a persona stripped of skills and mounts is just a system prompt, not a persona. This PR consolidates relay onto the same @agentworkforce/persona-kit library the agentworkforce CLI uses, so a persona launched through relay behaves identically to one launched through the CLI.

Scope decisions

  • Tier system dropped entirely. persona-kit v3 has no tier concept (the catalog/intent layer replaced it); relay's tier option, PersonaTier, PersonaTierSpec, and tiered PersonaFile are gone.
  • Persona shape matches workforce. loadPersona returns persona-kit's canonical PersonaSpec; the relay-specific PersonaFile / ResolvedPersona / PersonaSpawnSpec shapes are removed.
  • Relay keeps the search-dir cascade. persona-kit doesn't ship a directory walker, so defaultPersonaSearchDirs, listPersonas, findPersona, and loadPersona stay in @agent-relay/sdk/personas. Everything else (parsing, plan building, side-effect execution) delegates to persona-kit.
  • Skill / mount / sidecar install is always on at spawn. No opt-in flag. The opt-out is getPersonaSpawnPlan(id) + manual spawnPty.

Breaking changes

  • Removed deps: @agentworkforce/harness-kit, @agentworkforce/workload-router.
  • Removed exports from @agent-relay/sdk/personas: PersonaTier, PersonaTierSpec, PersonaFile, ResolvedPersona (relay's local shape), PersonaSpawnSpec, MaterializedConfigFile, buildPersonaSpawnSpec, materializePersonaConfigFiles, restorePersonaConfigFiles.
  • loadPersona(id) now returns PersonaSpec (persona-kit's canonical shape), not the previous relay-local ResolvedPersona.
  • SpawnPersonaOptions: tier is gone; persona now takes a PersonaSpec; new options are skillsInstallRoot, inputValues, envOverrides, cleanupSkillsOnDispose, mount.
  • Personas relying on tiers.* need to be flattened to top-level harness / model / systemPrompt.

Known limitation

The broker's spawnPty API does not yet accept a per-spawn env, so persona-kit's plan.env (persona-author env + resolved input bindings) cannot be forwarded to the spawned PTY today. spawnPersona emits a console.warn listing any env keys it had to drop so the caller can set them in the spawning process env or via options.envOverrides. Wiring env through the broker SDK is a separate task.

Test plan

  • npm run check (workspace @agent-relay/sdk) — clean.
  • npm run build — clean.
  • npx vitest run src/__tests__/personas.test.ts — 14/14 passing. Covers: search-dir cascade, JSON discovery, loadPersona happy path + missing-file error + parse-error surfacing, resolvePersona projection, getPersonaSpawnPlan for claude / codex / opencode, plan JSON round-trip, AgentRelay.spawnPersona + getPersonaSpawnPlan honoring personaDirs, per-call searchDirs override.
  • Manual end-to-end against a persona that exercises the full schema (skills + mount + sidecar + inputs) is still worth doing locally before merge; this sandbox can't reach external skill sources.
  • Other workspaces (packages/openclaw, packages/acp-bridge, packages/gateway, etc.) don't import the persona module — only packages/sdk itself does — so no downstream code changes are required.

Out of scope

  • Routing profiles / personaCatalog (workforce-CLI internals; relay doesn't need them — that's why @agentworkforce/workload-router was dropped, not replaced).
  • Forwarding plan.env through spawnPty — needs a broker-side change to SpawnPtyInput.
  • Cleaning up the legacy docs/ mirror (out of scope per .claude/rules/docs-sync.md; the docs directory will be handled separately).

https://claude.ai/code/session_01498supaqXmpq7yWvmoYawJ


Generated by Claude Code

Replaces @agentworkforce/harness-kit + @agentworkforce/workload-router
with @agentworkforce/persona-kit@^3, and rewrites AgentRelay.spawnPersona
to run the full persona lifecycle (skills install, mount policy,
CLAUDE.md / AGENTS.md sidecars, harness config files, persona inputs)
via persona-kit's buildPersonaSpawnPlan + executePersonaSpawnPlan. All
side effects are reversed when the spawned agent exits.

The relay-side personas module now only owns the search-dir cascade and
file discovery; parsing, plan construction, and execution belong to
persona-kit so relay and the workforce CLI launch personas identically.

Adds AgentRelay.getPersonaSpawnPlan(id) for dry-run inspection of the
plan without filesystem writes or subprocess spawns.

Breaking: the persona tier system is dropped, along with the legacy
relay-side PersonaFile / PersonaTier / ResolvedPersona / PersonaSpawnSpec
types and the buildPersonaSpawnSpec / materializePersonaConfigFiles /
restorePersonaConfigFiles helpers. loadPersona now returns the canonical
PersonaSpec; spawnPersona's `persona` override takes a PersonaSpec; the
`tier` option is gone.

Closes #832.
@willwashburn willwashburn requested a review from khaliqgant as a code owner May 23, 2026 17:49
@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Migrates the SDK to @agentworkforce/persona-kit@^3, rewrites persona parsing to canonical PersonaSpec, adds getPersonaSpawnPlan, and refactors AgentRelay.spawnPersona to build → execute → dispose persona spawn plans with improved env/args handling and cleanup.

Changes

Persona-kit migration and spawn-plan refactor

Layer / File(s) Summary
Dependency migration
packages/sdk/package.json
Replace @agentworkforce/harness-kit and @agentworkforce/workload-router with @agentworkforce/persona-kit (v3).
Persona parsing, load, resolve, and plan glue
packages/sdk/src/personas.ts
Re-export persona-kit types/APIs; add parsePersonaJson validation; listPersonas/findPersona parse .json files and skip malformed conventional shadow files; loadPersona returns on-disk PersonaSpec; add resolvePersona, PersonaSpawnPlanOptions, and getPersonaSpawnPlan; update composePersonaTask to use PersonaSpawnPlan fields.
AgentRelay spawn flow and lifecycle cleanup
packages/sdk/src/relay.ts
SpawnPersonaOptions now accepts persona?: PersonaSpec and execution controls (skillsInstallRoot, inputValues, envOverrides, cleanupSkillsOnDispose, mount); spawnPersona() builds a spawn plan, executes it to obtain an ExecutionHandle (cwd), warns about plan-declared env mismatches, spawns via spawnPty using handle.cwd, disposes the handle on failure and schedules disposal on agent exit; adds AgentRelay.getPersonaSpawnPlan() dry-run API.
Tests: fixtures, spawn-plan assertions, and relay integration
packages/sdk/src/__tests__/personas.test.ts
Replace tier/extends fixtures with personaJson helper producing three standalone persona JSONs; update tests to assert listPersonas/loadPersona/resolvePersona behaviors; add getPersonaSpawnPlan assertions (claude/codex/opencode, JSON round-trip); refocus AgentRelay tests for personaDirs, search overrides, malformed-shadow fallback, and spawn behavior.
Changelog updates
CHANGELOG.md
Document Unreleased entries for getPersonaSpawnPlan, changelog generation change, spawnPersona full lifecycle and cleanup, breaking changes moving to persona-kit and PersonaSpec, and migration guidance to flatten persona tiers.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant AgentRelay.spawnPersona
  participant buildPersonaSpawnPlan
  participant executePersonaSpawnPlan
  participant spawnPty
  participant Agent
  Caller->>AgentRelay.spawnPersona: personaId/options
  AgentRelay.spawnPersona->>buildPersonaSpawnPlan: load/resolve persona
  buildPersonaSpawnPlan-->>AgentRelay.spawnPersona: PersonaSpawnPlan
  AgentRelay.spawnPersona->>executePersonaSpawnPlan: plan, mount, skillsInstallRoot
  executePersonaSpawnPlan-->>AgentRelay.spawnPersona: ExecutionHandle (cwd)
  AgentRelay.spawnPersona->>spawnPty: harness args, cwd
  spawnPty-->>AgentRelay.spawnPersona: Agent (PTY)
  Agent->>Agent: running
  Agent-->>AgentRelay.spawnPersona: exit
  AgentRelay.spawnPersona->>executePersonaSpawnPlan: schedule handle.dispose()
  executePersonaSpawnPlan-->>AgentRelay.spawnPersona: cleanup result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

  • AgentWorkforce/relay#818: Overlapping changes to the SDK persona-spawning pipeline; this PR replaces the earlier harness-kit/workload-router flow with persona-kit's plan/execute model.

Suggested reviewers

  • khaliqgant

Poem

🐰 I dug a spec in the meadow bright,
I built a plan and tuned each arg just right,
Installed the skills and strapped sidecars tight,
Spawned the harness, watched it hum at night,
When the agent sleeps, I tidy up polite.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main change: migrating the SDK's persona spawn functionality to use @agentworkforce/persona-kit.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering summary, detailed scope decisions, breaking changes, test plan, and out-of-scope items. It follows the template with a detailed summary section and testing confirmation.
Linked Issues check ✅ Passed The PR addresses all primary coding objectives from issue #832: dependency migration, delegating persona logic to persona-kit, rewriting spawnPersona for full schema support, adding getPersonaSpawnPlan, and comprehensive test updates.
Out of Scope Changes check ✅ Passed All changes align with the stated scope: package dependency updates, personas.ts refactoring, relay.ts rewrite, test updates, and CHANGELOG documentation. No extraneous changes detected outside the persona-kit migration objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/peaceful-meitner-wNwo4

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d2fbe67af0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/sdk/src/relay.ts
Comment on lines 992 to 994
} catch (err) {
restorePersonaConfigFiles(writes);
await handle.dispose();
throw err;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve original spawn failure when dispose also errors

If spawnPty throws and handle.dispose() also throws, the cleanup error replaces the original spawn failure because await handle.dispose() runs before throw err. In failure cases (for example, invalid CLI args plus unmount/cleanup failure), callers lose the actionable root cause from spawnPty, which makes retries and diagnosis much harder. Wrap dispose in its own try/catch (or suppress secondary errors) so the original spawn exception is always propagated.

Useful? React with 👍 / 👎.

Comment thread packages/sdk/src/relay.ts
...(options.envOverrides !== undefined ? { envOverrides: options.envOverrides } : {}),
...(options.inputValues !== undefined ? { inputValues: options.inputValues } : {}),
};
return getPersonaSpawnPlanImpl(personaId, callOptions);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor persona override in getPersonaSpawnPlan

getPersonaSpawnPlan accepts SpawnPersonaOptions, which includes a persona override, but this method always reloads by personaId and never uses options.persona. Callers that pre-load/modify a persona in memory (the same workflow supported by spawnPersona) will get a plan for on-disk JSON instead of their override, causing dry-run validation to diverge from actual spawn behavior.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/sdk/src/relay.ts (1)

311-352: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

spawnPersona() silently ignores options.model.

SpawnPersonaOptions still exposes model through SpawnOptions, but this path always forwards plan.persona.model. Existing callers that override the model will now get the persona's model instead.

Suggested fix
-        model: plan.persona.model,
+        model: options.model ?? plan.persona.model,

Also applies to: 972-980

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/sdk/src/relay.ts` around lines 311 - 352, spawnPersona silently
ignores caller-provided model because the code always uses plan.persona.model
(from the loaded persona) instead of honoring options.model from
SpawnPersonaOptions/SpawnOptions; update spawnPersona so when constructing or
normalizing the plan it prefers options.model (if provided and non-empty) over
the persona's model and avoid overwriting plan.persona.model with the persona
default when options.model exists; specifically, adjust the code paths that
read/assign plan.persona.model (and the similar block referenced around lines
972-980) to conditionally set model = options.model ?? persona.model (or skip
assignment when options.model is present).
🧹 Nitpick comments (1)
packages/sdk/src/__tests__/personas.test.ts (1)

234-236: 💤 Low value

Consider adding intermediate assertions for nested config access.

Lines 235-236 access parsed.agent['opencode-nano'] directly without verifying that parsed.agent exists. While the current code will throw a TypeError if the structure is malformed (which is acceptable for tests), adding explicit assertions would make failures clearer:

assert.ok(parsed.agent, 'parsed config should have agent field');
assert.equal(parsed.agent['opencode-nano'].model, 'opencode/gpt-5-nano');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/sdk/src/__tests__/personas.test.ts` around lines 234 - 236, The test
directly accesses parsed.agent['opencode-nano'] which can produce an unclear
TypeError if parsed.agent is missing; add an explicit assertion that
parsed.agent exists (e.g., assert.ok(parsed.agent, 'parsed config should have
agent field')) before asserting on parsed.agent['opencode-nano'].model and
parsed.agent['opencode-nano'].prompt so failures report a clear message
referencing parsed and parsed.agent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/sdk/src/personas.ts`:
- Around line 217-223: The code currently throws if a readable candidate file
contains invalid JSON or fails parsePersonaJson validation, which prevents
falling through the cascade; in findPersona, after reading candidateBytes (and
before calling parsePersonaJson), wrap JSON.parse and parsePersonaJson in a
try/catch that treats parse/validation errors as a non-fatal skip (do not
rethrow) so the function continues searching other directories; specifically
update the block that uses readFileSync, candidateBytes,
JSON.parse(candidateBytes) and parsePersonaJson(...) to catch errors from
JSON.parse and parsePersonaJson and ignore them (leaving candidateBytes
undefined or continuing) so bad shadow files don’t block lower-priority persona
matches.

In `@packages/sdk/src/relay.ts`:
- Around line 331-352: The dry-run helper getPersonaSpawnPlan (and the other
dry-run helpers used by spawnPersona) currently ignores options.persona and
always reloads the persona by personaId; change the logic so that if
options.persona is provided it is used as the source PersonaSpec instead of
reloading from personaId, and ensure that downstream plan construction respects
that persona and still merges/overrides inputValues, envOverrides,
skillsInstallRoot and cleanupSkillsOnDispose exactly as spawnPersona would;
update getPersonaSpawnPlan and the corresponding helper(s) referenced by
spawnPersona to prefer options.persona (highest precedence) and fall back to
loading by personaId only when absent.
- Around line 954-956: The dropped-env computation currently compares plan.env
against process.env; change it to compare against the broker's effective startup
env (this.clientOptions.env ?? process.env) so a relay created with options.env
uses the broker's actual env for warnings. Update the filter that builds
droppedEnv to use (this.clientOptions.env ?? process.env)[key] in place of
process.env[key], keeping the rest of the check against plan.env as-is; ensure
you reference the existing variables droppedEnv, plan.env and
this.clientOptions.env in relay.ts when making the change.
- Around line 992-994: The catch block after spawnPty() currently awaits
handle.dispose() and then throws the caught err, but if handle.dispose() itself
throws the dispose error replaces the original spawn error; update the catch to
call handle.dispose() inside its own try/catch (or use finally-like safe
dispose) so any disposal error is caught/logged and does not overwrite the
original err, then rethrow the original spawn error from the outer catch;
reference spawnPty() and handle.dispose() to locate and change that catch block.

---

Outside diff comments:
In `@packages/sdk/src/relay.ts`:
- Around line 311-352: spawnPersona silently ignores caller-provided model
because the code always uses plan.persona.model (from the loaded persona)
instead of honoring options.model from SpawnPersonaOptions/SpawnOptions; update
spawnPersona so when constructing or normalizing the plan it prefers
options.model (if provided and non-empty) over the persona's model and avoid
overwriting plan.persona.model with the persona default when options.model
exists; specifically, adjust the code paths that read/assign plan.persona.model
(and the similar block referenced around lines 972-980) to conditionally set
model = options.model ?? persona.model (or skip assignment when options.model is
present).

---

Nitpick comments:
In `@packages/sdk/src/__tests__/personas.test.ts`:
- Around line 234-236: The test directly accesses parsed.agent['opencode-nano']
which can produce an unclear TypeError if parsed.agent is missing; add an
explicit assertion that parsed.agent exists (e.g., assert.ok(parsed.agent,
'parsed config should have agent field')) before asserting on
parsed.agent['opencode-nano'].model and parsed.agent['opencode-nano'].prompt so
failures report a clear message referencing parsed and parsed.agent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ec10bc3a-41d2-4bb8-af74-5714c5e442f0

📥 Commits

Reviewing files that changed from the base of the PR and between 423184b and d2fbe67.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • CHANGELOG.md
  • packages/sdk/package.json
  • packages/sdk/src/__tests__/personas.test.ts
  • packages/sdk/src/personas.ts
  • packages/sdk/src/relay.ts

Comment thread packages/sdk/src/personas.ts Outdated
Comment thread packages/sdk/src/relay.ts
Comment thread packages/sdk/src/relay.ts
Comment thread packages/sdk/src/relay.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

3 issues found across 6 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/sdk/src/relay.ts
Comment thread packages/sdk/src/relay.ts Outdated
Comment thread packages/sdk/src/relay.ts
Fixes flagged by codex, CodeRabbit, and cubic on PR #973:

- spawnPersona: wrap handle.dispose() in its own try/catch on the
  spawnPty failure path so a dispose error never masks the original
  spawn error (P2, three reviewers).
- getPersonaSpawnPlan: honor options.persona so dry-run plans match
  what spawnPersona would execute for the same options (P2, three
  reviewers).
- spawnPersona: compute dropped-env warning against the broker's
  effective env (this.clientOptions.env ?? process.env) instead of
  always process.env (P3, two reviewers).
- findPersona: tolerate a malformed shadow file at the conventional
  <id>.json path so it doesn't block a valid persona lower in the
  cascade — matches the directory-scan path's existing behavior.

Adds tests for getPersonaSpawnPlan({ persona }) and the
findPersona shadow-file cascade fallthrough; updates the parse-error
test to assert the new cascade semantics.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/sdk/src/__tests__/personas.test.ts`:
- Line 333: The test currently uses assert.notMatch(found?.path ?? '', new
RegExp(shadowDir)) which treats filesystem characters as regex; replace that
assertion with a direct string comparison so the path is compared literally
(e.g., change the assert.notMatch call to a direct inequality check using
assert.notStrictEqual or assert.notEqual against shadowDir), referencing the
found?.path and shadowDir variables and updating the assertion in
personas.test.ts accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6efceb77-8a21-4898-91c2-27da4f604788

📥 Commits

Reviewing files that changed from the base of the PR and between d2fbe67 and 30da4c0.

📒 Files selected for processing (3)
  • packages/sdk/src/__tests__/personas.test.ts
  • packages/sdk/src/personas.ts
  • packages/sdk/src/relay.ts

Comment thread packages/sdk/src/__tests__/personas.test.ts Outdated
persona-kit 3.0.20 made PersonaSpec.harness / .model / .systemPrompt
optional for handler-style (onEvent-driven) personas. Relay only spawns
interactive personas, so resolvePersona now narrows those fields with
explicit runtime guards that throw a clear error instead of letting tsc
fail or the cast silently drop the fields.

Bumps the SDK's persona-kit range to ^3.0.20 so the guard's narrowing
is actually exercised against the new optional shape.

Fixes the 'Publish Fresh Install Build' CI break that pulled 3.0.20 via
the semver range and failed tsc on the previous resolvePersona which
assigned `Harness | undefined` into a `Harness` field.
@willwashburn

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request. also respond/fix any comments made on PR

Copilot AI and others added 2 commits May 25, 2026 18:57
Co-authored-by: willwashburn <957608+willwashburn@users.noreply.github.com>

Copilot AI commented May 25, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request. also respond/fix any comments made on PR

Resolved. I merged latest main into this branch and fixed the merge conflict in packages/sdk/package.json (commit 22219699), then addressed remaining actionable PR comments in SDK (model override in spawnPersona and literal path assertion in personas test) in commit 207c11d5.

@willwashburn willwashburn merged commit 0324498 into main May 25, 2026
43 checks passed
@willwashburn willwashburn deleted the claude/peaceful-meitner-wNwo4 branch May 25, 2026 19:32
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.

Consume @agentworkforce/persona-kit; rewrite spawnPersona to honor full persona schema

3 participants