diff --git a/src/harness/application/actions/workflowActionService.ts b/src/harness/application/actions/workflowActionService.ts index 801317e8..b654b2a2 100644 --- a/src/harness/application/actions/workflowActionService.ts +++ b/src/harness/application/actions/workflowActionService.ts @@ -12,7 +12,7 @@ import { } from '../workflow'; import { HarnessPolicyBlockedError } from '../policies/policyService'; -import { resolveRuntimeLayout } from '../../../shared/fs/pathHelpers'; +import { resolveRuntimeLayout, toPosixContextPath } from '../../../shared/fs/pathHelpers'; import type { HarnessWorkflowGuideInput } from '../workflow/workflowGuideTypes'; export interface HarnessWorkflowInitInput { @@ -62,7 +62,7 @@ export class HarnessWorkflowActionService { archivePrevious: params.archive_previous, }); - const workflowStatePath = resolveRuntimeLayout(contextPath).prevcFile; + const workflowStatePath = toPosixContextPath(resolveRuntimeLayout(contextPath).prevcFile); const settings = await service.getSettings(); const scale = getScaleName(status.project.scale as ProjectScale); const isAutonomous = settings.autonomous_mode; @@ -131,13 +131,13 @@ export class HarnessWorkflowActionService { error: 'No workflow found. Initialize a workflow first.', suggestion: 'Use workflow-init({ name: "feature-name" }) to start.', note: 'Workflows enable structured PREVC phases. Skip for trivial changes.', - workflowStatePath: resolveRuntimeLayout(contextPath).prevcFile, + workflowStatePath: toPosixContextPath(resolveRuntimeLayout(contextPath).prevcFile), }; } const summary = await service.getSummary(); const status = await service.getStatus(); - const workflowStatePath = resolveRuntimeLayout(contextPath).prevcFile; + const workflowStatePath = toPosixContextPath(resolveRuntimeLayout(contextPath).prevcFile); const orchestration = await service.getPhaseOrchestration(summary.currentPhase); const harness = await service.getHarnessStatus(); @@ -170,7 +170,7 @@ export class HarnessWorkflowActionService { success: false, error: 'No workflow found. Initialize a workflow first.', suggestion: 'Use workflow-init({ name: "feature-name" }) to start.', - workflowStatePath: resolveRuntimeLayout(contextPath).prevcFile, + workflowStatePath: toPosixContextPath(resolveRuntimeLayout(contextPath).prevcFile), }; } diff --git a/src/harness/application/context/contextTools.ts b/src/harness/application/context/contextTools.ts index 03945c34..26e946ef 100644 --- a/src/harness/application/context/contextTools.ts +++ b/src/harness/application/context/contextTools.ts @@ -348,11 +348,11 @@ export const listFilesTool = createInternalTool< async (input) => { const { pattern, cwd, ignore } = input; try { - const files = await glob(pattern, { + const files = (await glob(pattern, { cwd: cwd || process.cwd(), ignore: ignore || ['node_modules/**', '.git/**', 'dist/**'], absolute: false - }); + })).map((file) => file.split(path.sep).join('/')); return { success: true, files, diff --git a/src/harness/application/workflow/plansService.ts b/src/harness/application/workflow/plansService.ts index dea0614a..714c94bd 100644 --- a/src/harness/application/workflow/plansService.ts +++ b/src/harness/application/workflow/plansService.ts @@ -15,7 +15,7 @@ import { } from '../../domain/workflow/plans'; import { PrevcStatusManager } from '../../domain/workflow/status/statusManager'; import { GitService } from '../../../utils/gitService'; -import { resolveRuntimeLayoutFromRepo } from '../../../shared/fs/pathHelpers'; +import { resolveRuntimeLayoutFromRepo, toPosixContextPath } from '../../../shared/fs/pathHelpers'; import type { PrevcPhase } from '../../domain/workflow/types'; export interface HarnessPlansServiceOptions { @@ -87,7 +87,7 @@ export class HarnessPlansService { canAdvanceToReview = gateResult.gates.plan_required.passed; } - const workflowStatePath = resolveRuntimeLayoutFromRepo(this.repoPath).prevcFile; + const workflowStatePath = toPosixContextPath(resolveRuntimeLayoutFromRepo(this.repoPath).prevcFile); const enhancementPrompt = workflowActive ? `PLAN LINKED TO ACTIVE WORKFLOW diff --git a/src/shared/fs/pathHelpers.ts b/src/shared/fs/pathHelpers.ts index ba5f8b3d..a8694956 100644 --- a/src/shared/fs/pathHelpers.ts +++ b/src/shared/fs/pathHelpers.ts @@ -245,6 +245,13 @@ export async function isFile(targetPath: string): Promise { } } +/** + * Normalize an absolute path for cross-platform API responses (forward slashes). + */ +export function toPosixContextPath(absolutePath: string): string { + return absolutePath.split(path.sep).join('/'); +} + /** * Normalize path separators to forward slashes */ diff --git a/src/utils/splashScreen.ts b/src/utils/splashScreen.ts index 53911c8f..170654fe 100644 --- a/src/utils/splashScreen.ts +++ b/src/utils/splashScreen.ts @@ -60,8 +60,8 @@ export function formatSplashDirectory(directory: string, maxLength = 48): string const withTilde = resolved === homeDirectory ? '~' : resolved.startsWith(`${homeDirectory}${path.sep}`) - ? `~${path.sep}${path.relative(homeDirectory, resolved)}` - : resolved; + ? `~/${path.relative(homeDirectory, resolved).split(path.sep).join('/')}` + : resolved.split(path.sep).join('/'); return truncateMiddle(withTilde, maxLength); }