Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/core/artifact-graph/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as path from 'node:path';
import fg from 'fast-glob';
import type { CompletedSet } from './types.js';
import type { ArtifactGraph } from './graph.js';
import { FileSystemUtils } from '../../utils/file-system.js';

/**
* Detects which artifacts are completed by checking file existence in the change directory.
Expand Down Expand Up @@ -54,8 +55,10 @@ function isGlobPattern(pattern: string): boolean {

/**
* Checks if a glob pattern has any matches.
* Normalizes Windows backslashes to forward slashes for cross-platform glob compatibility.
*/
function hasGlobMatches(pattern: string): boolean {
const matches = fg.sync(pattern, { onlyFiles: true });
const normalizedPattern = FileSystemUtils.toPosixPath(pattern);
const matches = fg.sync(normalizedPattern, { onlyFiles: true });
return matches.length > 0;
}
3 changes: 2 additions & 1 deletion src/core/converters/json-converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'path';
import { MarkdownParser } from '../parsers/markdown-parser.js';
import { ChangeParser } from '../parsers/change-parser.js';
import { Spec, Change } from '../schemas/index.js';
import { FileSystemUtils } from '../../utils/file-system.js';

export class JsonConverter {
convertSpecToJson(filePath: string): string {
Expand Down Expand Up @@ -43,7 +44,7 @@ export class JsonConverter {
}

private extractNameFromPath(filePath: string): string {
const normalizedPath = filePath.replaceAll('\\', '/');
const normalizedPath = FileSystemUtils.toPosixPath(filePath);
const parts = normalizedPath.split('/');

for (let i = parts.length - 1; i >= 0; i--) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export class UpdateCommand {

if (updatedSlashFiles.length > 0) {
// Normalize to forward slashes for cross-platform log consistency
const normalized = updatedSlashFiles.map((p) => p.replace(/\\/g, '/'));
const normalized = updatedSlashFiles.map((p) => FileSystemUtils.toPosixPath(p));
summaryParts.push(`Updated slash commands: ${normalized.join(', ')}`);
}

Expand Down
7 changes: 4 additions & 3 deletions src/core/validation/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import { SpecSchema, ChangeSchema, Spec, Change } from '../schemas/index.js';
import { MarkdownParser } from '../parsers/markdown-parser.js';
import { ChangeParser } from '../parsers/change-parser.js';
import { ValidationReport, ValidationIssue, ValidationLevel } from './types.js';
import {
import {
MIN_PURPOSE_LENGTH,
MAX_REQUIREMENT_TEXT_LENGTH,
VALIDATION_MESSAGES
VALIDATION_MESSAGES
} from './constants.js';
import { parseDeltaSpec, normalizeRequirementName } from '../parsers/requirement-blocks.js';
import { FileSystemUtils } from '../../utils/file-system.js';

export class Validator {
private strictMode: boolean;
Expand Down Expand Up @@ -359,7 +360,7 @@ export class Validator {
}

private extractNameFromPath(filePath: string): string {
const normalizedPath = filePath.replaceAll('\\', '/');
const normalizedPath = FileSystemUtils.toPosixPath(filePath);
const parts = normalizedPath.split('/');

// Look for the directory name after 'specs' or 'changes'
Expand Down
8 changes: 8 additions & 0 deletions src/utils/file-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ function findMarkerIndex(
}

export class FileSystemUtils {
/**
* Converts a path to use forward slashes (POSIX style).
* Essential for cross-platform compatibility with glob libraries like fast-glob.
*/
static toPosixPath(p: string): string {
return p.replace(/\\/g, '/');
}

private static isWindowsBasePath(basePath: string): boolean {
return /^[A-Za-z]:[\\/]/.test(basePath) || basePath.startsWith('\\');
}
Expand Down
Loading