Address PR review feedback (#1741)
- Close first TaskStore before creating second in interactive registration (P1) - Revert defaultWorkflowId default to undefined; set explicitly in onboarding only (P1) - Add alpha-only filter + 2-char min to interactive prefix input (P2) - Move suggestTaskPrefix to @fusion/core, share between CLI and dashboard (P2) - Fix suggestTaskPrefix JSDoc to match implementation (P2)
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
writeProjectIdentity,
|
||||
detectWorkspaceRepos,
|
||||
saveWorkspaceConfig,
|
||||
suggestTaskPrefix,
|
||||
type RegisteredProject,
|
||||
type TaskStore,
|
||||
} from "@fusion/core";
|
||||
@@ -537,19 +538,6 @@ export function suggestProjectName(path: string): string {
|
||||
return parts[parts.length - 1] || "unnamed";
|
||||
}
|
||||
|
||||
/**
|
||||
* FNXC:TaskPrefix 2026-06-24-18:00:
|
||||
* Derive a task prefix from a project name by taking the first 2-4 uppercase
|
||||
* letters. Falls back to "FN" for short names. Used as the suggested default
|
||||
* during project onboarding so each project gets a recognizable prefix.
|
||||
*/
|
||||
export function suggestTaskPrefix(projectName: string): string {
|
||||
const cleaned = projectName.replace(/[^a-zA-Z]/g, "").toUpperCase();
|
||||
if (cleaned.length >= 2 && cleaned.length <= 4) return cleaned;
|
||||
if (cleaned.length > 4) return cleaned.slice(0, 4);
|
||||
return "FN";
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve absolute path and validate it exists.
|
||||
*/
|
||||
@@ -698,6 +686,7 @@ export async function registerProjectInteractive(
|
||||
// Persist workspaceMode in config.json so it's visible/toggleable in the dashboard
|
||||
await store.updateSettings({ workspaceMode: true });
|
||||
}
|
||||
await store.close();
|
||||
console.log(` ✓ Initialized fn at ${absPath}`);
|
||||
} else {
|
||||
throw new ProjectResolutionError(
|
||||
@@ -772,7 +761,8 @@ export async function registerProjectInteractive(
|
||||
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
||||
const prefixInput = await rl.question(`\n Task prefix [${suggestedPrefix}]: `);
|
||||
rl.close();
|
||||
const prefix = prefixInput.trim().toUpperCase() || suggestedPrefix;
|
||||
const rawPrefix = prefixInput.trim().toUpperCase().replace(/[^A-Z]/g, "");
|
||||
const prefix = rawPrefix.length >= 2 ? rawPrefix : suggestedPrefix;
|
||||
|
||||
await store.updateSettings({
|
||||
taskPrefix: prefix,
|
||||
|
||||
@@ -1957,3 +1957,4 @@ export {
|
||||
clearSyncPassphrase,
|
||||
hasSyncPassphraseConfigured,
|
||||
} from "./secrets-sync-passphrase.js";
|
||||
export { suggestTaskPrefix } from "./task-prefix.js";
|
||||
|
||||
@@ -258,7 +258,7 @@ export const DEFAULT_GLOBAL_SETTINGS = {
|
||||
export const DEFAULT_PROJECT_SETTINGS = {
|
||||
globalPause: false,
|
||||
globalPauseReason: undefined,
|
||||
defaultWorkflowId: "builtin:coding",
|
||||
defaultWorkflowId: undefined,
|
||||
enabledBuiltinWorkflowIds: undefined,
|
||||
approvedWorkflowCliCommands: undefined,
|
||||
approvedCliAutonomyAdapters: undefined,
|
||||
|
||||
17
packages/core/src/task-prefix.ts
Normal file
17
packages/core/src/task-prefix.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* FNXC:TaskPrefix 2026-06-24-18:00:
|
||||
* Derive a task prefix from a project name. Strips non-alpha characters, uppercases,
|
||||
* and takes the first 2-4 characters. Falls back to "FN" for names with fewer than
|
||||
* 2 letters. Used during project onboarding (CLI and dashboard) so each project gets
|
||||
* a recognizable prefix for task IDs (e.g. "MYPR" for "my-project").
|
||||
*
|
||||
* Note: the result is the first 2-4 letters of the cleaned (alpha-only, uppercased)
|
||||
* name, NOT the initials of each word. For "my-project" the result is "MYPR"
|
||||
* (first 4 of "MYPROJECT"), not "MP".
|
||||
*/
|
||||
export function suggestTaskPrefix(projectName: string): string {
|
||||
const cleaned = projectName.replace(/[^a-zA-Z]/g, "").toUpperCase();
|
||||
if (cleaned.length >= 2 && cleaned.length <= 4) return cleaned;
|
||||
if (cleaned.length > 4) return cleaned.slice(0, 4);
|
||||
return "FN";
|
||||
}
|
||||
@@ -382,10 +382,10 @@ export const registerProjectRoutes: ApiRouteRegistrar = (ctx) => {
|
||||
*/
|
||||
if (activeProjectWithOutcome.outcome === "registered") {
|
||||
try {
|
||||
const { TaskStore } = await import("@fusion/core");
|
||||
const { TaskStore, suggestTaskPrefix } = await import("@fusion/core");
|
||||
const store = new TaskStore(normalizedPath);
|
||||
await store.init();
|
||||
const prefix = normalizedName.replace(/[^a-zA-Z]/g, "").toUpperCase().slice(0, 4) || "FN";
|
||||
const prefix = suggestTaskPrefix(normalizedName);
|
||||
await store.updateSettings({
|
||||
taskPrefix: prefix,
|
||||
defaultWorkflowId: "builtin:coding",
|
||||
|
||||
Reference in New Issue
Block a user