-
Notifications
You must be signed in to change notification settings - Fork 0
feat(persona-kit): typed ProactiveCapabilities on PersonaSpec (#1555 PR-B) #169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| { | ||
| "id": "traj_rdhqus1o0ci8", | ||
| "version": 1, | ||
| "task": { | ||
| "title": "Add typed ProactiveCapabilities to persona-kit PersonaSpec" | ||
| }, | ||
| "status": "completed", | ||
| "startedAt": "2026-05-31T10:29:26.181Z", | ||
| "completedAt": "2026-05-31T10:32:51.807Z", | ||
| "agents": [ | ||
| { | ||
| "name": "default", | ||
| "role": "lead", | ||
| "joinedAt": "2026-05-31T10:29:31.307Z" | ||
| } | ||
| ], | ||
| "chapters": [ | ||
| { | ||
| "id": "chap_19bcnrc6w4th", | ||
| "title": "Work", | ||
| "agentName": "default", | ||
| "startedAt": "2026-05-31T10:29:31.307Z", | ||
| "endedAt": "2026-05-31T10:32:51.807Z", | ||
| "events": [ | ||
| { | ||
| "ts": 1780223371308, | ||
| "type": "decision", | ||
| "content": "Preserve capabilities in parsePersonaSpec: Preserve capabilities in parsePersonaSpec", | ||
| "raw": { | ||
| "question": "Preserve capabilities in parsePersonaSpec", | ||
| "chosen": "Preserve capabilities in parsePersonaSpec", | ||
| "alternatives": [], | ||
| "reasoning": "parsePersonaSpec reconstructs PersonaSpec and drops unknown top-level fields, so the new optional field needs parser support for define/parse round-trip" | ||
| }, | ||
| "significance": "high" | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "retrospective": { | ||
| "summary": "Added optional typed proactive capabilities to persona-kit PersonaSpec, exported the canonical types, preserved capabilities through define/parse, regenerated schema, bumped package version to 3.0.34, and validated build/typecheck/test.", | ||
| "approach": "Standard approach", | ||
| "confidence": 0.9 | ||
| }, | ||
| "commits": [], | ||
| "filesChanged": [], | ||
| "projectId": "/private/tmp/wt-pk", | ||
| "tags": [], | ||
| "_trace": { | ||
| "startRef": "a380c74cc90bbe0d9f1bc897b1cbb36808586eea", | ||
| "endRef": "a380c74cc90bbe0d9f1bc897b1cbb36808586eea" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # Trajectory: Add typed ProactiveCapabilities to persona-kit PersonaSpec | ||
|
|
||
| > **Status:** ✅ Completed | ||
| > **Confidence:** 90% | ||
| > **Started:** May 31, 2026 at 12:29 PM | ||
| > **Completed:** May 31, 2026 at 12:32 PM | ||
|
|
||
| --- | ||
|
|
||
| ## Summary | ||
|
|
||
| Added optional typed proactive capabilities to persona-kit PersonaSpec, exported the canonical types, preserved capabilities through define/parse, regenerated schema, bumped package version to 3.0.34, and validated build/typecheck/test. | ||
|
|
||
| **Approach:** Standard approach | ||
|
|
||
| --- | ||
|
|
||
| ## Key Decisions | ||
|
|
||
| ### Preserve capabilities in parsePersonaSpec | ||
| - **Chose:** Preserve capabilities in parsePersonaSpec | ||
| - **Reasoning:** parsePersonaSpec reconstructs PersonaSpec and drops unknown top-level fields, so the new optional field needs parser support for define/parse round-trip | ||
|
|
||
| --- | ||
|
|
||
| ## Chapters | ||
|
|
||
| ### 1. Work | ||
| *Agent: default* | ||
|
|
||
| - Preserve capabilities in parsePersonaSpec: Preserve capabilities in parsePersonaSpec |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,6 +8,7 @@ import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SIDECAR_MD_MODES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from './constants.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CapabilityValue, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CodexApprovalPolicy, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CodexSandboxMode, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Harness, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -29,6 +30,7 @@ import type { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PersonaSkill, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PersonaSpec, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PersonaTag, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ProactiveCapabilities, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SidecarMdMode, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WatchEvent, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WatchRule | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -851,6 +853,44 @@ export function parseMemory(value: unknown, context: string): PersonaMemory | un | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return out; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function parseCapabilityValue(value: unknown, context: string): CapabilityValue { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof value === 'boolean') return value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isObject(value)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(`${context} must be a boolean or object if provided`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (value.enabled !== undefined && typeof value.enabled !== 'boolean') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(`${context}.enabled must be a boolean if provided`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { ...value } as CapabilityValue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function parseCapabilities( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: unknown, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| context: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): ProactiveCapabilities | undefined { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (value === undefined) return undefined; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isObject(value)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(`${context} must be an object if provided`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+856
to
+874
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In JavaScript/TypeScript, To prevent this, we should explicitly check and reject arrays using
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const out: ProactiveCapabilities = {}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { review, issueClaim, conflictAutofix, pullRequest } = value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (review !== undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.review = parseCapabilityValue(review, `${context}.review`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (issueClaim !== undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.issueClaim = parseCapabilityValue(issueClaim, `${context}.issueClaim`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (conflictAutofix !== undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.conflictAutofix = parseCapabilityValue(conflictAutofix, `${context}.conflictAutofix`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (pullRequest !== undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.pullRequest = parseCapabilityValue(pullRequest, `${context}.pullRequest`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Object.keys(out).length > 0 ? out : undefined; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function parseOnEvent(value: unknown, context: string): string | undefined { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (value === undefined) return undefined; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return assertOnEventPath(value, context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -893,6 +933,7 @@ export function parsePersonaSpec(value: unknown, expectedIntent: PersonaIntent): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| integrations, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| schedules, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| watch, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| capabilities, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| memory, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onEvent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } = value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -998,6 +1039,10 @@ export function parsePersonaSpec(value: unknown, expectedIntent: PersonaIntent): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const parsedSchedules = parseSchedules(schedules, `persona[${expectedIntent}].schedules`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const parsedWatch = parseWatch(watch, `persona[${expectedIntent}].watch`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const parsedCapabilities = parseCapabilities( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| capabilities, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `persona[${expectedIntent}].capabilities` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const parsedMemory = parseMemory(memory, `persona[${expectedIntent}].memory`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const parsedOnEvent = parseOnEvent(onEvent, `persona[${expectedIntent}].onEvent`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const parsedSandbox = parseSandbox(sandbox, `persona[${expectedIntent}].sandbox`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1029,6 +1074,7 @@ export function parsePersonaSpec(value: unknown, expectedIntent: PersonaIntent): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...(parsedIntegrations ? { integrations: parsedIntegrations } : {}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...(parsedSchedules ? { schedules: parsedSchedules } : {}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...(parsedWatch ? { watch: parsedWatch } : {}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...(parsedCapabilities ? { capabilities: parsedCapabilities } : {}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...(parsedMemory !== undefined ? { memory: parsedMemory } : {}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...(parsedOnEvent !== undefined ? { onEvent: parsedOnEvent } : {}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Top-level capabilities accepts array. Invalid config gets silently ignored. Reject array input.
Prompt for AI agents