Move src/ → apps/server/ and packages/web/ → apps/web/ to adopt standard monorepo conventions (apps/ for runnable apps, packages/ for reusable libraries). Update all config files, shared package imports, test fixtures, and documentation to reflect new paths. Key fixes: - Update workspace config to ["apps/*", "packages/*"] - Update tsconfig.json rootDir/include for apps/server/ - Add apps/web/** to vitest exclude list - Update drizzle.config.ts schema path - Fix ensure-schema.ts migration path detection (3 levels up in dev, 2 levels up in dist) - Fix tests/integration/cli-server.test.ts import paths - Update packages/shared imports to apps/server/ paths - Update all docs/ files with new paths
68 lines
1.9 KiB
TypeScript
68 lines
1.9 KiB
TypeScript
/**
|
|
* Branch Naming Utility
|
|
*
|
|
* Pure functions for computing deterministic branch names
|
|
* in the initiative → phase → task branch hierarchy.
|
|
*/
|
|
|
|
/**
|
|
* Task categories that run on the project's default branch (no initiative branch needed).
|
|
*/
|
|
export const PLANNING_CATEGORIES = ['research', 'discuss', 'plan', 'detail', 'refine'] as const;
|
|
|
|
/**
|
|
* Task categories that require an initiative branch.
|
|
*/
|
|
export const EXECUTION_CATEGORIES = ['execute', 'verify', 'merge', 'review'] as const;
|
|
|
|
/**
|
|
* Check if a task category is a planning category (runs on default branch).
|
|
*/
|
|
export function isPlanningCategory(category: string): boolean {
|
|
return (PLANNING_CATEGORIES as readonly string[]).includes(category);
|
|
}
|
|
|
|
/**
|
|
* Convert a name to a URL/branch-safe slug.
|
|
* Lowercase, replace non-alphanumeric runs with single hyphens, trim hyphens.
|
|
*/
|
|
export function slugify(name: string): string {
|
|
return name
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-|-$/g, '');
|
|
}
|
|
|
|
/**
|
|
* Generate an initiative branch name from the initiative name.
|
|
* Format: `cw/<slugified-name>`
|
|
*/
|
|
export function generateInitiativeBranch(name: string): string {
|
|
return `cw/${slugify(name)}`;
|
|
}
|
|
|
|
/**
|
|
* Compute the initiative branch name.
|
|
* Returns the branch as-is if set, or null if unset.
|
|
*/
|
|
export function initiativeBranchName(branch: string | null): string | null {
|
|
return branch;
|
|
}
|
|
|
|
/**
|
|
* Compute a phase branch name.
|
|
* Format: `<initiativeBranch>-phase-<slugified-phase-name>`
|
|
*/
|
|
export function phaseBranchName(initiativeBranch: string, phaseName: string): string {
|
|
return `${initiativeBranch}-phase-${slugify(phaseName)}`;
|
|
}
|
|
|
|
/**
|
|
* Compute a task branch name.
|
|
* Format: `<initiativeBranch>-task-<taskId>`
|
|
* Uses the raw task ID (already unique) to avoid collisions.
|
|
*/
|
|
export function taskBranchName(initiativeBranch: string, taskId: string): string {
|
|
return `${initiativeBranch}-task-${taskId}`;
|
|
}
|