diff --git a/src/product/generation/workforce-persona-writer.test.ts b/src/product/generation/workforce-persona-writer.test.ts index f070ab9b..2460f2f2 100644 --- a/src/product/generation/workforce-persona-writer.test.ts +++ b/src/product/generation/workforce-persona-writer.test.ts @@ -105,6 +105,36 @@ describe('workforce persona workflow writer', () => { expect(parsed.metadata).toMatchObject({ workflowName: 'persona' }); }); + it('accepts multiline run options when cwd is explicit', () => { + const parsed = parsePersonaWorkflowResponse(JSON.stringify({ + artifact: { + path: 'workflows/generated/persona.ts', + content: multilineRunSource(), + }, + metadata: { + workflowName: 'persona', + agents: ['lead'], + }, + }), 'workflows/generated/persona.ts'); + + expect(parsed.responseFormat).toBe('structured-json'); + expect(parsed.content).toContain('cwd: process.cwd()'); + expect(parsed.metadata).toMatchObject({ workflowName: 'persona' }); + }); + + it('still rejects persona artifacts that run without an explicit cwd', () => { + expect(() => parsePersonaWorkflowResponse(JSON.stringify({ + artifact: { + path: 'workflows/generated/persona.ts', + content: workflowSource().replace('.run({ cwd: process.cwd() });', '.run();'), + }, + metadata: { + workflowName: 'persona', + agents: ['lead'], + }, + }), 'workflows/generated/persona.ts')).toThrow(/explicit cwd/); + }); + it('recovers expected artifact content from disk when structured output omits inline content', () => { const repoRoot = mkdtempSync(join(tmpdir(), 'ricky-persona-response-')); const artifactPath = 'workflows/generated/persona.ts'; @@ -644,6 +674,18 @@ function workflowSource(): string { ].join('\n'); } +function multilineRunSource(): string { + return workflowSource().replace( + ' .run({ cwd: process.cwd() });', + [ + ' .run({', + ' cwd: process.cwd(),', + ' timeoutMs: 120000,', + ' });', + ].join('\n'), + ); +} + function spec(overrides: { description?: string; targetFiles?: string[] } = {}): NormalizedWorkflowSpec { const description = overrides.description ?? 'Generate a workflow for deterministic product work.'; const rawPayload: RawSpecPayload = { diff --git a/src/product/generation/workforce-persona-writer.ts b/src/product/generation/workforce-persona-writer.ts index 1967d1da..d958eb67 100644 --- a/src/product/generation/workforce-persona-writer.ts +++ b/src/product/generation/workforce-persona-writer.ts @@ -723,11 +723,15 @@ function validateArtifactContent(content: string): void { if (!/\bworkflow\(/.test(content)) { throw new WorkforcePersonaWriterError('Workforce persona artifact does not call workflow().'); } - if (!/\.run\(\{ cwd: process\.cwd\(\) \}\)/.test(content)) { + if (!hasExplicitRunCwd(content)) { throw new WorkforcePersonaWriterError('Workforce persona artifact must run with explicit cwd.'); } } +function hasExplicitRunCwd(content: string): boolean { + return /\.run\s*\(\s*\{[\s\S]*?\bcwd\s*:\s*process\.cwd\s*\(\s*\)[\s\S]*?\}\s*\)/.test(content); +} + function validateMetadata(metadata: Record): void { if (Object.keys(metadata).length === 0) { throw new WorkforcePersonaWriterError('Workforce persona response metadata block is required.');