diff --git a/cli/src/commands/refresh/prompts.ts b/cli/src/commands/refresh/prompts.ts index 92de8aa81f..0828342202 100644 --- a/cli/src/commands/refresh/prompts.ts +++ b/cli/src/commands/refresh/prompts.ts @@ -1,6 +1,3 @@ -import { existsSync } from "node:fs"; -import { join } from "node:path"; -import process from "node:process"; import { colors } from "@cliffy/ansi/colors"; import { Command } from "@cliffy/command"; import { Select } from "@cliffy/prompt/select"; @@ -186,37 +183,6 @@ interface CommandOptions { async function promptsAction(opts: CommandOptions): Promise { await refreshPrompts({ yes: opts.yes === true }); - await refreshRtNamespaceIfPresent(opts); -} - -/** - * Keep an existing `rt.d.ts` resource-type namespace in sync when the user - * runs `wmill refresh prompts`. `wmill init` already generates it on first - * bind; here we only refresh it when the file is already present (so we never - * introduce it into projects that don't use it). Best-effort: a missing - * workspace/login or offline run just skips with a warning rather than failing - * the whole refresh. - * - * Not wired into the shared `refreshPrompts` helper on purpose — `wmill init` - * regenerates the namespace itself, and `refreshPrompts` must stay - * network-free for its other callers. - */ -async function refreshRtNamespaceIfPresent(opts: CommandOptions): Promise { - const rtPath = join(process.cwd(), "rt.d.ts"); - if (!existsSync(rtPath)) return; - - try { - const { generateRTNamespace } = await import( - "../resource-type/resource-type.ts" - ); - await generateRTNamespace(opts as any); - } catch (error) { - log.warn( - `Could not refresh rt.d.ts resource type namespace: ${ - error instanceof Error ? error.message : error - }` - ); - } } const command = new Command() diff --git a/cli/src/commands/workspace/fork.ts b/cli/src/commands/workspace/fork.ts index e08177db6c..76866361ef 100644 --- a/cli/src/commands/workspace/fork.ts +++ b/cli/src/commands/workspace/fork.ts @@ -12,9 +12,15 @@ import { isGitRepository, renameCurrentGitBranch, } from "../../utils/git.ts"; +import process from "node:process"; import { WM_FORK_PREFIX } from "../../core/constants.ts"; import { tryResolveBranchWorkspace } from "../../core/context.ts"; -import { findWorkspaceByGitBranch, readConfigFile } from "../../core/conf.ts"; +import { + findWorkspaceByGitBranch, + getEffectiveGitBranch, + getWorkspaceNames, + readConfigFile, +} from "../../core/conf.ts"; async function createWorkspaceFork( opts: GlobalOptions & { @@ -36,48 +42,70 @@ async function createWorkspaceFork( throw new Error("Could not get git branch name"); } - // `--from-branch` enables the "already on a working branch" workflow: the - // fork is based on (the parent), and the current branch is - // later renamed onto the fork branch. Without it, the fork is based on the - // current branch and the user checks out a fresh fork branch. - const fromBranch = opts.fromBranch; + const config = await readConfigFile({ warnIfMissing: false }); + const originalBranchIfForked = getOriginalBranchForWorkspaceForks(currentBranch); - let workspace; - if (fromBranch) { - if (fromBranch === currentBranch) { + // A "base branch" is one we must not rename onto a fork branch: mapped to a + // workspace in wmill.yaml, or a conventional default (main/master). + const isBaseBranch = (branch: string): boolean => + branch === "main" || + branch === "master" || + findWorkspaceByGitBranch(config.workspaces, branch) !== undefined; + + // Decide the base branch the fork links to, and whether to rename the + // current working branch onto the fork branch. Auto-detected from where you + // are; `--from-branch` is the explicit/non-interactive override. + let clonedBranchName: string; + let renameCurrent: boolean; + + if (opts.fromBranch) { + // Explicit override: base on , rename the current branch. + if (opts.fromBranch === currentBranch) { throw new Error( `--from-branch is for converting a *different* working branch into the fork branch, but you are already on \`${currentBranch}\`. ` + - `Either omit --from-branch (a fresh fork branch is created with \`git checkout -b\`), or check out the working branch you want to convert first.`, + `Omit --from-branch to create a fresh fork branch with \`git checkout -b\`.`, ); } - const config = await readConfigFile({ warnIfMissing: false }); - // Protect base branches. This workflow renames the *current* branch onto - // the fork branch, so refuse when the current branch is itself a base - // branch — either mapped to a workspace in wmill.yaml, or a conventional - // default (main/master). Renaming one of those would clobber it; the user - // must check out a disposable working branch first. Fail fast, before any - // fork workspace or git branch is created. - const currentBranchIsBase = - currentBranch === "main" || - currentBranch === "master" || - findWorkspaceByGitBranch(config.workspaces, currentBranch) !== undefined; - if (currentBranchIsBase) { + if (isBaseBranch(currentBranch)) { throw new Error( `Refusing to rename your current branch \`${currentBranch}\` — it looks like a base branch (mapped to a workspace in wmill.yaml, or main/master). ` + - `The --from-branch workflow turns a *disposable working branch* into the fork branch. ` + - `Check out the working branch you want to convert first, or omit --from-branch to create a fresh fork branch with \`git checkout -b\`.`, + `Check out the disposable working branch you want to convert first.`, ); } - const match = findWorkspaceByGitBranch(config.workspaces, fromBranch); - if (!match) { + if (!findWorkspaceByGitBranch(config.workspaces, opts.fromBranch)) { throw new Error( - `Could not find a workspace mapped to branch \`${fromBranch}\` in wmill.yaml's workspaces section. ` + + `Could not find a workspace mapped to branch \`${opts.fromBranch}\` in wmill.yaml's workspaces section. ` + `Pass the base branch your fork should be based on (e.g. the branch bound to the parent workspace).`, ); } - workspace = await tryResolveBranchWorkspace(opts, match[0]); + clonedBranchName = opts.fromBranch; + renameCurrent = true; + } else if (originalBranchIfForked) { + // Fork of a fork: link to the original branch; user checks out a new branch. + log.info(`You are creating a fork of a fork. The branch will be linked to the original branch this was forked from, i.e. \`${originalBranchIfForked}\`, for all settings and overrides.`); + clonedBranchName = originalBranchIfForked; + renameCurrent = false; + } else if (isBaseBranch(currentBranch)) { + // On a base branch: base the fork on it; user checks out a fresh fork branch. + clonedBranchName = currentBranch; + renameCurrent = false; } else { + // On a non-base working branch: offer to base the fork on it and rename it. + clonedBranchName = await resolveWorkingBranchBase(config, opts, currentBranch); + renameCurrent = true; + } + + // Resolve the parent workspace. When the base differs from the current + // branch (the rename workflows), resolve via the base branch's workspace; + // otherwise use plain branch resolution. + let workspace; + if (clonedBranchName === currentBranch) { workspace = await tryResolveBranchWorkspace(opts); + } else { + const baseMatch = findWorkspaceByGitBranch(config.workspaces, clonedBranchName); + workspace = baseMatch + ? await tryResolveBranchWorkspace(opts, baseMatch[0]) + : await tryResolveBranchWorkspace(opts); } if (!workspace) { @@ -86,22 +114,6 @@ async function createWorkspaceFork( log.info(`You are forking workspace (${workspace.workspaceId})`) - const originalBranchIfForked = getOriginalBranchForWorkspaceForks(currentBranch); - - let clonedBranchName: string | null; - if (fromBranch) { - clonedBranchName = fromBranch; - } else if (originalBranchIfForked) { - log.info(`You are creating a fork of a fork. The branch will be linked to the original branch this was forked from, i.e. \`${originalBranchIfForked}\`, for all settings and overrides.`); - clonedBranchName = originalBranchIfForked; - } else { - clonedBranchName = currentBranch; - } - - if (!clonedBranchName) { - throw new Error("Failed to get current branch name, aborting operation"); - } - if (opts.workspace) { log.info( colors.red.bold( @@ -301,11 +313,13 @@ async function createWorkspaceFork( const newBranchName = `${WM_FORK_PREFIX}/${clonedBranchName}/${workspaceId}` - // Workflow B (`--from-branch`): turn the current working branch into the - // fork branch in place so its commits become the fork's. Workflow A: leave - // the user on their base branch and have them check out a fresh fork branch. + // Rename workflow: turn the current working branch into the fork branch in + // place so its commits become the fork's. (Consent was already established — + // by `--from-branch`, or the interactive prompt for a non-base branch.) + // Otherwise: leave the user on their branch and have them check out a fresh + // fork branch. let onForkBranch = false; - if (fromBranch) { + if (renameCurrent) { if (currentBranch === newBranchName) { onForkBranch = true; log.info(colors.green(`Your current branch is already \`${newBranchName}\`.`)); @@ -315,27 +329,13 @@ async function createWorkspaceFork( `Check out the fork branch yourself (e.g. \`git checkout ${newBranchName}\`).`, ); } else { - let doRename = opts.yes === true; - if (!doRename) { - const { Select } = await import("@cliffy/prompt/select"); - const choice = await Select.prompt({ - message: `Rename your current branch \`${currentBranch}\` → \`${newBranchName}\` so its commits become the fork's branch?`, - options: [ - { name: "Yes, rename it", value: "confirm" }, - { name: "No, I'll switch branches myself", value: "cancel" }, - ], - }); - doRename = choice === "confirm"; - } - if (doRename) { - renameCurrentGitBranch(newBranchName); - onForkBranch = true; - log.info( - colors.green( - `Renamed \`${currentBranch}\` → \`${newBranchName}\`. Your existing commits are now on the fork branch.`, - ), - ); - } + renameCurrentGitBranch(newBranchName); + onForkBranch = true; + log.info( + colors.green( + `Renamed \`${currentBranch}\` → \`${newBranchName}\`. Your existing commits are now on the fork branch.`, + ), + ); } } @@ -356,6 +356,71 @@ To merge changes back to the parent workspace, you can: See: https://www.windmill.dev/docs/advanced/workspace_forks`); } +/** + * When `wmill workspace fork` is run from a non-base working branch, confirm + * the user wants to turn it into a fork branch, and resolve which base branch + * the fork should be linked to. Throws in non-interactive mode (where the user + * must pass `--from-branch ` instead). + */ +async function resolveWorkingBranchBase( + config: Awaited>, + opts: { yes?: boolean }, + currentBranch: string, +): Promise { + const interactive = process.stdin.isTTY && opts.yes !== true; + if (!interactive) { + throw new Error( + `You are on working branch \`${currentBranch}\`, which is not a base branch. ` + + `Pass --from-branch to base the fork on a base branch and rename this branch onto the fork branch, ` + + `or check out a base branch and run \`wmill workspace fork\` to create a fresh fork branch.`, + ); + } + + const { Select } = await import("@cliffy/prompt/select"); + const proceed = await Select.prompt({ + message: `You're on working branch \`${currentBranch}\`, not a base branch. Base a fork on it and rename it onto the fork branch?`, + options: [ + { name: "Yes, base the fork on this branch and rename it", value: "yes" }, + { name: "No, cancel", value: "no" }, + ], + }); + if (proceed !== "yes") { + throw new Error("Fork cancelled. Check out a base branch to create a fresh fork branch instead."); + } + + const baseBranches = listConfiguredBaseBranches(config); + if (baseBranches.length === 0) { + throw new Error( + `No base branches are configured in wmill.yaml's workspaces section, so the fork can't be linked to a parent. ` + + `Add the parent workspace to wmill.yaml, or pass --from-branch .`, + ); + } + if (baseBranches.length === 1) { + log.info(`Basing the fork on \`${baseBranches[0]}\`.`); + return baseBranches[0]; + } + return await Select.prompt({ + message: "Which base branch is this fork based on (the parent)?", + options: baseBranches.map((b) => ({ name: b, value: b })), + }); +} + +/** + * Base branches configured in wmill.yaml, mirroring how `findWorkspaceByGitBranch` + * keys them (effective git branch = `gitBranch ?? workspaceName`, reserved keys + * excluded) so the chosen base resolves to a workspace afterwards. + */ +function listConfiguredBaseBranches( + config: Awaited>, +): string[] { + const workspaces = config.workspaces; + const branches = new Set(); + for (const name of getWorkspaceNames(workspaces)) { + branches.add(getEffectiveGitBranch(name, workspaces![name])); + } + return [...branches]; +} + async function deleteWorkspaceFork( opts: GlobalOptions & { yes?: boolean; diff --git a/cli/src/commands/workspace/workspace.ts b/cli/src/commands/workspace/workspace.ts index 58e516323b..5628213b75 100644 --- a/cli/src/commands/workspace/workspace.ts +++ b/cli/src/commands/workspace/workspace.ts @@ -814,9 +814,9 @@ const command = new Command() ) .option( "--from-branch ", - "Fork based on this base branch (its bound workspace is the parent) and rename your current working branch onto the fork branch wm-fork//. Use when you're already on a branch (e.g. with forked-datatable edits) you want to turn into the fork. Omit to base the fork on the current branch and check out a fresh fork branch instead." + "Non-interactive override for the 'turn my current working branch into the fork' workflow: base the fork on (its bound workspace is the parent) and rename the current branch onto wm-fork//. Usually unneeded — from a working branch `wmill workspace fork` offers this interactively; from a base branch it creates a fresh fork branch." ) - .option("-y --yes", "Skip interactive prompts (defaults datatable behavior to 'skip', and confirms the --from-branch rename)") + .option("-y --yes", "Skip interactive prompts (defaults datatable behavior to 'skip'). On a non-base branch, requires --from-branch since the base branch can't be prompted for.") .action(createWorkspaceFork as any) .command("delete-fork") .description("Delete a forked workspace and git branch") diff --git a/cli/src/guidance/core.ts b/cli/src/guidance/core.ts index 4d2e6460e1..25890e1923 100644 --- a/cli/src/guidance/core.ts +++ b/cli/src/guidance/core.ts @@ -156,10 +156,12 @@ Only deploy when the user explicitly asks to deploy, publish, push, or ship — A **fork** is an isolated copy of a workspace for parallel or experimental work — make changes (including to datatables, which are cloned per fork) without touching the parent, then merge back after review. Each fork is paired with a git branch named \`wm-fork//\`. Forks require a git repo. -Create one with \`wmill workspace fork\`. There are two branch workflows — pick by where you are: +Just run \`wmill workspace fork\` — it adapts to where you are: -- **Starting from the base branch** (no in-progress work to carry over): run \`wmill workspace fork\`. It bases the fork on your current branch and prints a \`git checkout -b wm-fork//\` to start the fork branch. -- **Already on a working branch you want to turn into the fork** (e.g. you've branched and already edited a forked datatable): run \`wmill workspace fork --from-branch \`. It bases the fork on \`\` (the parent's branch) and renames your current branch onto \`wm-fork//\` in place, preserving its commits. +- **On a base branch** (e.g. \`main\`, or a branch bound to a workspace): it bases the fork on that branch and prints a \`git checkout -b wm-fork//\` to start a fresh fork branch. +- **On a working branch** (e.g. you've branched and already edited a forked datatable): it offers to base the fork on that branch and rename it onto \`wm-fork//\` in place, preserving its commits — asking which base branch is the parent if there's more than one. + +For non-interactive runs from a working branch, pass \`--from-branch \` to skip the prompts. The CLI refuses to rename a base branch. Merge a fork back into its parent with \`wmill workspace merge\` (or the Merge UI on the fork's home page). Full reference: https://www.windmill.dev/docs/advanced/workspace_forks diff --git a/cli/src/guidance/freshness.ts b/cli/src/guidance/freshness.ts index ca50320c5a..02590b7235 100644 --- a/cli/src/guidance/freshness.ts +++ b/cli/src/guidance/freshness.ts @@ -105,14 +105,16 @@ export function currentPromptsHash(nonDottedPaths: boolean): string { } /** - * Read AGENTS.wmill.md in the current working directory, compare its embedded - * hash to the current CLI's hash, and print a one-line warning if they + * Read the managed guidance file in the current working directory, compare its + * embedded hash to the current CLI's hash, and print a one-line warning if they * differ. Silent on every other code path (no managed file, no marker, * matching hash, IO error, …) so it never gets in the user's way. * - * Back-compat: if only the legacy `AGENTS.cli.md` is present (no - * `AGENTS.wmill.md` yet), warn that the managed file should be migrated — - * `wmill refresh prompts` renames it and rewrites the include. + * Back-compat: prefers `AGENTS.wmill.md` but falls back to the legacy + * `AGENTS.cli.md` and runs the exact same staleness check on it. We do NOT + * warn merely because the old filename is in use — an up-to-date `AGENTS.cli.md` + * stays quiet; only a stale hash (which `wmill refresh prompts` fixes, and + * which also migrates the filename) trips the warning. */ export async function warnIfPromptsStale(opts?: { cwd?: string; @@ -122,18 +124,17 @@ export async function warnIfPromptsStale(opts?: { if (opts?.argv && !shouldRunFreshnessCheck(opts.argv)) return; const cwd = opts?.cwd ?? process.cwd(); - const path = `${cwd}/${AGENTS_WMILL_FILENAME}`; + // Prefer the current filename; fall back to the legacy one for back-compat. + let fileName = AGENTS_WMILL_FILENAME; + let path = `${cwd}/${fileName}`; if (!(await stat(path).catch(() => null))) { - // No AGENTS.wmill.md. If the legacy AGENTS.cli.md is still around, nudge - // the user to migrate it; otherwise this project just isn't wmill-managed. - const legacyPath = `${cwd}/${LEGACY_AGENTS_CLI_FILENAME}`; - if (await stat(legacyPath).catch(() => null)) { - emitWarning( - "Your AGENTS.cli.md is using the old managed filename. Run `wmill refresh prompts` to migrate it to AGENTS.wmill.md." - ); + fileName = LEGACY_AGENTS_CLI_FILENAME; + path = `${cwd}/${fileName}`; + if (!(await stat(path).catch(() => null))) { + // Neither file present — this project just isn't wmill-managed. + return; } - return; } let content: string; @@ -145,10 +146,10 @@ export async function warnIfPromptsStale(opts?: { const stored = extractPromptsHash(content); if (!stored) { - // Older AGENTS.wmill.md without a marker. Warn so the user re-runs - // refresh and picks up the new format. + // Managed file without a marker. Warn so the user re-runs refresh and + // picks up the new format (and the new filename). emitWarning( - "Your AGENTS.wmill.md predates prompt versioning. Run `wmill refresh prompts` to refresh and add a version marker." + `Your ${fileName} predates prompt versioning. Run \`wmill refresh prompts\` to refresh and add a version marker.` ); return; } @@ -170,7 +171,7 @@ export async function warnIfPromptsStale(opts?: { const current = currentPromptsHash(nonDottedPaths); if (stored !== current) { emitWarning( - "Your AGENTS.wmill.md is out of date. Run `wmill refresh prompts` to refresh." + `Your ${fileName} is out of date. Run \`wmill refresh prompts\` to refresh.` ); } } diff --git a/cli/src/guidance/skills.gen.ts b/cli/src/guidance/skills.gen.ts index a1999b7e7e..f16584d005 100644 --- a/cli/src/guidance/skills.gen.ts +++ b/cli/src/guidance/skills.gen.ts @@ -6762,8 +6762,8 @@ workspace related commands - \`--create-workspace-name \` - Specify the workspace name. Ignored if --create is not specified or the workspace already exists. Will default to the workspace id. - \`--color \` - Workspace color (hex code, e.g. #ff0000) - \`--datatable-behavior \` - How to handle datatables: skip, schema_only, or schema_and_data (default: interactive prompt) - - \`--from-branch \` - Fork based on this base branch (its bound workspace is the parent) and rename your current working branch onto the fork branch wm-fork//. Use when you're already on a branch (e.g. with forked-datatable edits) you want to turn into the fork. Omit to base the fork on the current branch and check out a fresh fork branch instead. - - \`-y --yes\` - Skip interactive prompts (defaults datatable behavior to 'skip', and confirms the --from-branch rename) + - \`--from-branch \` - Non-interactive override for the 'turn my current working branch into the fork' workflow: base the fork on (its bound workspace is the parent) and rename the current branch onto wm-fork//. Usually unneeded — from a working branch \`wmill workspace fork\` offers this interactively; from a base branch it creates a fresh fork branch. + - \`-y --yes\` - Skip interactive prompts (defaults datatable behavior to 'skip'). On a non-base branch, requires --from-branch since the base branch can't be prompted for. - \`workspace delete-fork \` - Delete a forked workspace and git branch - \`-y --yes\` - Skip confirmation prompt - \`workspace merge\` - Compare and deploy changes between a fork and its parent workspace diff --git a/cli/test/guidance_writer_unit.test.ts b/cli/test/guidance_writer_unit.test.ts index 2363792832..4ee068c83c 100644 --- a/cli/test/guidance_writer_unit.test.ts +++ b/cli/test/guidance_writer_unit.test.ts @@ -614,4 +614,64 @@ describe("prompts freshness — additional invariants", () => { expect(stdoutJoined).not.toContain("out of date"); }); }); + + // Back-compat: a legacy AGENTS.cli.md is still hash-checked, and we do NOT + // warn merely because of the old filename — only when it's actually stale. + test("warnIfPromptsStale stays silent for an up-to-date legacy AGENTS.cli.md", async () => { + await withTempDir(async (tempDir) => { + const content = injectPromptsHashMarker( + "# Windmill CLI Agent Instructions\nbody\n", + currentPromptsHash(false) + ); + await writeFile(join(tempDir, "AGENTS.cli.md"), content, "utf8"); + + const stderrWrites: string[] = []; + const originalStderr = process.stderr.write.bind(process.stderr); + // @ts-expect-error — overriding write for the test + process.stderr.write = (chunk: any) => { + stderrWrites.push(String(chunk)); + return true; + }; + try { + await warnIfPromptsStale({ + cwd: tempDir, + nonDottedPaths: false, + argv: ["node", "wmill", "sync", "push"], + }); + } finally { + process.stderr.write = originalStderr; + } + expect(stderrWrites.join("")).toBe(""); + }); + }); + + test("warnIfPromptsStale warns (naming the legacy file) for a stale AGENTS.cli.md", async () => { + await withTempDir(async (tempDir) => { + await writeFile( + join(tempDir, "AGENTS.cli.md"), + "# Windmill CLI Agent Instructions\n\nbody\n", + "utf8" + ); + + const stderrWrites: string[] = []; + const originalStderr = process.stderr.write.bind(process.stderr); + // @ts-expect-error — overriding write for the test + process.stderr.write = (chunk: any) => { + stderrWrites.push(String(chunk)); + return true; + }; + try { + await warnIfPromptsStale({ + cwd: tempDir, + nonDottedPaths: false, + argv: ["node", "wmill", "sync", "push"], + }); + } finally { + process.stderr.write = originalStderr; + } + const out = stderrWrites.join(""); + expect(out).toContain("out of date"); + expect(out).toContain("AGENTS.cli.md"); + }); + }); }); diff --git a/system_prompts/auto-generated/cli/cli-commands.md b/system_prompts/auto-generated/cli/cli-commands.md index 4132379e53..86c43bedac 100644 --- a/system_prompts/auto-generated/cli/cli-commands.md +++ b/system_prompts/auto-generated/cli/cli-commands.md @@ -726,8 +726,8 @@ workspace related commands - `--create-workspace-name ` - Specify the workspace name. Ignored if --create is not specified or the workspace already exists. Will default to the workspace id. - `--color ` - Workspace color (hex code, e.g. #ff0000) - `--datatable-behavior ` - How to handle datatables: skip, schema_only, or schema_and_data (default: interactive prompt) - - `--from-branch ` - Fork based on this base branch (its bound workspace is the parent) and rename your current working branch onto the fork branch wm-fork//. Use when you're already on a branch (e.g. with forked-datatable edits) you want to turn into the fork. Omit to base the fork on the current branch and check out a fresh fork branch instead. - - `-y --yes` - Skip interactive prompts (defaults datatable behavior to 'skip', and confirms the --from-branch rename) + - `--from-branch ` - Non-interactive override for the 'turn my current working branch into the fork' workflow: base the fork on (its bound workspace is the parent) and rename the current branch onto wm-fork//. Usually unneeded — from a working branch `wmill workspace fork` offers this interactively; from a base branch it creates a fresh fork branch. + - `-y --yes` - Skip interactive prompts (defaults datatable behavior to 'skip'). On a non-base branch, requires --from-branch since the base branch can't be prompted for. - `workspace delete-fork ` - Delete a forked workspace and git branch - `-y --yes` - Skip confirmation prompt - `workspace merge` - Compare and deploy changes between a fork and its parent workspace diff --git a/system_prompts/auto-generated/prompts.ts b/system_prompts/auto-generated/prompts.ts index f4909eddba..f22caeaa4c 100644 --- a/system_prompts/auto-generated/prompts.ts +++ b/system_prompts/auto-generated/prompts.ts @@ -3277,8 +3277,8 @@ workspace related commands - \`--create-workspace-name \` - Specify the workspace name. Ignored if --create is not specified or the workspace already exists. Will default to the workspace id. - \`--color \` - Workspace color (hex code, e.g. #ff0000) - \`--datatable-behavior \` - How to handle datatables: skip, schema_only, or schema_and_data (default: interactive prompt) - - \`--from-branch \` - Fork based on this base branch (its bound workspace is the parent) and rename your current working branch onto the fork branch wm-fork//. Use when you're already on a branch (e.g. with forked-datatable edits) you want to turn into the fork. Omit to base the fork on the current branch and check out a fresh fork branch instead. - - \`-y --yes\` - Skip interactive prompts (defaults datatable behavior to 'skip', and confirms the --from-branch rename) + - \`--from-branch \` - Non-interactive override for the 'turn my current working branch into the fork' workflow: base the fork on (its bound workspace is the parent) and rename the current branch onto wm-fork//. Usually unneeded — from a working branch \`wmill workspace fork\` offers this interactively; from a base branch it creates a fresh fork branch. + - \`-y --yes\` - Skip interactive prompts (defaults datatable behavior to 'skip'). On a non-base branch, requires --from-branch since the base branch can't be prompted for. - \`workspace delete-fork \` - Delete a forked workspace and git branch - \`-y --yes\` - Skip confirmation prompt - \`workspace merge\` - Compare and deploy changes between a fork and its parent workspace diff --git a/system_prompts/auto-generated/skills/cli-commands/SKILL.md b/system_prompts/auto-generated/skills/cli-commands/SKILL.md index a04bd0c5b5..13d423dad7 100644 --- a/system_prompts/auto-generated/skills/cli-commands/SKILL.md +++ b/system_prompts/auto-generated/skills/cli-commands/SKILL.md @@ -731,8 +731,8 @@ workspace related commands - `--create-workspace-name ` - Specify the workspace name. Ignored if --create is not specified or the workspace already exists. Will default to the workspace id. - `--color ` - Workspace color (hex code, e.g. #ff0000) - `--datatable-behavior ` - How to handle datatables: skip, schema_only, or schema_and_data (default: interactive prompt) - - `--from-branch ` - Fork based on this base branch (its bound workspace is the parent) and rename your current working branch onto the fork branch wm-fork//. Use when you're already on a branch (e.g. with forked-datatable edits) you want to turn into the fork. Omit to base the fork on the current branch and check out a fresh fork branch instead. - - `-y --yes` - Skip interactive prompts (defaults datatable behavior to 'skip', and confirms the --from-branch rename) + - `--from-branch ` - Non-interactive override for the 'turn my current working branch into the fork' workflow: base the fork on (its bound workspace is the parent) and rename the current branch onto wm-fork//. Usually unneeded — from a working branch `wmill workspace fork` offers this interactively; from a base branch it creates a fresh fork branch. + - `-y --yes` - Skip interactive prompts (defaults datatable behavior to 'skip'). On a non-base branch, requires --from-branch since the base branch can't be prompted for. - `workspace delete-fork ` - Delete a forked workspace and git branch - `-y --yes` - Skip confirmation prompt - `workspace merge` - Compare and deploy changes between a fork and its parent workspace