Skip to content

[persona-kit 2/8] Move harness-kit + workload-router persona code into persona-kit (no behavior change) #65

@willwashburn

Description

@willwashburn

Part of the persona-kit consolidation. Depends on #64. This is issue 2 of 8.

Goal

Move the persona-domain code currently fractured across packages/harness-kit/ and packages/workload-router/ into the new packages/persona-kit/. No behavior changes, no API redesign yet — this is a code relocation. New top-level orchestration API lands in 3/8.

What moves

From packages/harness-kit/src/index.ts

All public exports — harness-kit's entire surface is persona-shaped:

  • Functions: buildInteractiveSpec, useRunnablePersona, resolveMcpServersLenient, resolveStringMapLenient.
  • Types: BuildInteractiveSpecInput, InteractiveSpec, InteractiveConfigFile, plus any helper types these reference.
  • Plus internal helpers used by the above.

After this PR, packages/harness-kit/src/index.ts should be a re-export shim that imports from @agentworkforce/persona-kit and re-exports the same names. (Deletion is 6/8 — keeping the shim here means workforce CLI keeps building.)

From packages/workload-router/src/index.ts

  • Constants: HARNESS_VALUES, PERSONA_TIERS, PERSONA_TAGS, SIDECAR_MD_MODES, PERMISSION_MODES, CODEX_SANDBOX_MODES, CODEX_APPROVAL_POLICIES, SKILL_SOURCE_KINDS, HARNESS_SKILL_TARGETS, BUILT_IN_PERSONA_INTENTS, PERSONA_INTENTS.
  • Types: Harness, PersonaTier, PersonaTag, PersonaIntent, HarnessSettings, PersonaRuntime, PersonaSkill, PersonaInputSpec, PersonaPermissions, PersonaMount, McpServerSpec, PersonaSpec, HarnessSkillTarget, SkillMaterializationOptions, SkillInstall, SkillMaterializationPlan, PersonaInstallContext, PersonaContext, SidecarMdMode, CodexSandboxMode, CodexApprovalPolicy, PermissionMode.
  • Functions: materializeSkills, materializeSkillsFor, parseSkills, parsePersonaSpec (and any other persona-shape parsers around lines 1190–1290), buildInstallArtifacts, resolveSkillSource, harness-skill-rules helpers (~lines 354–600).
  • Tests that cover the moved code — port from workload-router/src/index.test.ts to persona-kit/src/*.test.ts (split by file).

After this PR, packages/workload-router/src/index.ts keeps these symbols available to its own internal consumers via re-export from @agentworkforce/persona-kit. The actual deletion of those re-exports is 5/8.

From packages/cli/src/local-personas.ts

This file is currently CLI-internal. The persona-loading cascade and tier-merge logic need to be public. Promote:

  • loadLocalPersonas (or its successor) → renamed to loadPersonas in persona-kit, with a clean options shape { searchDirs, cwd, extraDirs }.
  • Tier-resolution logic → resolvePersonaTier(spec, tier) in persona-kit.
  • Persona-cascade override merging → keep as internal helpers within persona-kit but unit-test them directly.

From packages/cli/src/cli.ts

This file is the workforce CLI entry. Lift these side-effecting helpers out of it into persona-kit (keep them in their own files inside persona-kit for clarity):

  • Sidecar markdown writer (packages/persona-kit/src/sidecars.ts): resolves claudeMd / agentsMd / claudeMdContent / agentsMdContent, writes the file, returns a restore handle.
  • Mount policy applier (packages/persona-kit/src/mount.ts): the @relayfile/local-mount integration. Returns an undo handle.
  • Input rendering (packages/persona-kit/src/inputs.ts): env-substitution into systemPrompt and per-input env binding.
  • Skill install runner (packages/persona-kit/src/skills.ts): child_process.spawn loop over materializeSkills output. Exit-code-aware abort. Returns a cleanup handle that removes installs[*].cleanupPaths.

The CLI keeps: argv parsing, persona-picking UX, session recording, routing-profile lookup. CLI migration to import these from persona-kit is 4/8.

Package layout after this PR

packages/persona-kit/
  package.json
  tsconfig.json
  README.md
  src/
    index.ts            // top-level barrel (no new API yet — just re-exports)
    types.ts            // PersonaSpec, PersonaSkill, PersonaMount, etc.
    constants.ts        // HARNESS_VALUES, PERSONA_TIERS, HARNESS_SKILL_TARGETS, etc.
    parse.ts            // parsePersonaSpec, parseSkills, parseInputs, parseMount
    load.ts             // loadPersonas (cascade), resolvePersonaTier
    interactive-spec.ts // buildInteractiveSpec (moved from harness-kit)
    skills.ts           // materializeSkills + runSkillInstalls (the side-effecting runner)
    mount.ts            // applyPersonaMount + undo handle
    sidecars.ts         // writePersonaSidecars + restore handle
    inputs.ts           // renderPersonaInputs
    mcp.ts              // resolveMcpServersLenient + helpers
    *.test.ts           // tests co-located with each file

Tasks

  • Move every symbol listed above from harness-kit/workload-router/cli into persona-kit, preserving exact function signatures and behavior.
  • Co-locate tests in persona-kit; port test cases from workload-router/src/index.test.ts for the moved functions.
  • Update packages/harness-kit/src/index.ts to re-export everything it used to export from @agentworkforce/persona-kit. Add @agentworkforce/persona-kit as a dep on harness-kit.
  • Update packages/workload-router/src/index.ts to re-export the moved symbols from @agentworkforce/persona-kit. Add @agentworkforce/persona-kit as a dep on workload-router. workload-router's own internal code (PersonaSelection, RoutingProfile, personaCatalog) keeps using these via the re-export.
  • Update packages/cli/src/local-personas.ts to delegate to loadPersonas / resolvePersonaTier from persona-kit. Keep the CLI's existing shape so 4/8 can do the deeper rewrite.
  • Update packages/cli/src/cli.ts to call the lifted skill/mount/sidecar/input helpers from persona-kit (still imperatively wired, no orchestration change).
  • No file outside packages/persona-kit/, packages/harness-kit/, packages/workload-router/, packages/cli/, and lockfile/workspace files should change.

Constraints

  • Behavior must be byte-identical. This is a move, not a redesign. The new top-level orchestration API (buildPersonaSpawnPlan, executePersonaSpawnPlan) is 3/8.
  • harness-kit and workload-router both still build and pass their tests — via re-export shims — until 5/8 and 6/8 delete them.
  • Don't touch the personaCatalog auto-generated registry or the routing-profile types in workload-router. Those are not persona-instantiation; they stay.

Verification

  • pnpm -r build succeeds.
  • pnpm -r test passes — both the new persona-kit tests and the unchanged workforce CLI tests.
  • Manual smoke test: agentworkforce <persona-with-skills> against each of the three harnesses (claude, codex, opencode) installs the same skills, writes the same sidecars, applies the same mount, and spawns with the same argv as before this PR.
  • grep for @agentworkforce/harness-kit and @agentworkforce/workload-router across the monorepo — confirm everything still resolves.

Reference

Plan section 1.2. Run tests after each subsection of the move (parsers, then plan-build, then loaders, then helpers) — don't move everything at once and debug at the end.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions