Rename Castle -> Wild PC across the repo

Repo-side rename only (Phases 1-3 of the migration plan); the live box
(~/.castle, systemd units, /data/castle, domains) is a separate cutover.

- Slug `castle` -> `wildpc`: CLI command, module names (wildpc_core/cli/api),
  dist names, entry point `wildpc = wildpc_cli.main:main`.
- Identifiers: CastleConfig/NATSClient/DirError/MDNS -> Wildpc*.
- Env/constants: CASTLE_* -> WILDPC_*; ~/.castle -> ~/.wildpc, castle.yaml ->
  wildpc.yaml, /data/castle -> /data/wildpc.
- Systemd UNIT_PREFIX castle- -> wildpc-; own programs castle-api/gateway/etc.
- Display prose "Castle" -> "Wild PC" in docs, agent-guide files, README, frontend.
- Package dirs and bootstrap yaml renamed via git mv; lockfiles regenerated;
  redundant nested uv.lock files dropped (workspace root lock is authoritative).

Tests: core 273, cli 47, wildpc-api 120 all pass. Frontend type-checks + builds.
Fixed a stale test fixture (secret_env_path kind arg) broken pre-rename.
This commit is contained in:
2026-07-18 22:55:08 -07:00
parent 25d7a522cc
commit 05b28cb584
190 changed files with 2428 additions and 3337 deletions

View File

@@ -26,7 +26,7 @@ export function ConfigPanel({ deployment, configSection, onRefetch }: ConfigPane
const navigate = useNavigate()
const qc = useQueryClient()
const [message, setMessage] = useState<{ type: "ok" | "error"; text: string } | null>(null)
// A deployment edit only persists to castle.yaml; the unit/process still need
// A deployment edit only persists to wildpc.yaml; the unit/process still need
// a deploy (regenerate) + restart to actually take effect.
const [pendingApply, setPendingApply] = useState(false)
const [applying, setApplying] = useState(false)
@@ -43,8 +43,8 @@ export function ConfigPanel({ deployment, configSection, onRefetch }: ConfigPane
setMessage({
type: "ok",
text: isDeployment
? "Saved to castle.yaml — not live yet; apply to converge."
: "Saved to castle.yaml",
? "Saved to wildpc.yaml — not live yet; apply to converge."
: "Saved to wildpc.yaml",
})
if (isDeployment) setPendingApply(true)
onRefetch()
@@ -67,7 +67,7 @@ export function ConfigPanel({ deployment, configSection, onRefetch }: ConfigPane
qc.invalidateQueries()
onRefetch()
} catch (e: unknown) {
// A self-apply of castle-api restarts it, killing the connection — expected.
// A self-apply of wildpc-api restarts it, killing the connection — expected.
if (e instanceof TypeError) {
setPendingApply(false)
setMessage({ type: "ok", text: "Applied — the service is restarting." })

View File

@@ -26,7 +26,7 @@ const KIND_INFO: Record<DeploymentKind, { label: string; hint: string }> = {
static: { label: "Static", hint: "Static site served by the gateway" },
}
/** Create a deployment in castle.yaml, then deploy (and start, for a service).
/** Create a deployment in wildpc.yaml, then deploy (and start, for a service).
* A pick-a-kind wizard: the chosen kind sets the manager and shows only its
* relevant fields. Reachable standalone or prefilled from a program page. */
export function CreateDeploymentForm({

View File

@@ -93,7 +93,7 @@ export function JobFields({ job, onSave, onDelete }: Props) {
width="w-48"
mono
placeholder="0 2 * * *"
hint="Cron expression — castle generates a systemd timer that runs the job on this schedule."
hint="Cron expression — wildpc generates a systemd timer that runs the job on this schedule."
/>
<Field label="Launch" hint="How the job runs on each tick, then exits: the launcher and its target (a console script, command/argv, image, node script, or compose file).">
<div className="flex items-center gap-2">
@@ -124,7 +124,7 @@ export function JobFields({ job, onSave, onDelete }: Props) {
onSave={handleSave}
onDelete={onDelete ? () => onDelete(job.id) : undefined}
deleteLabel="Remove job"
confirmMessage={`Remove job "${job.id}" from castle.yaml? Run a deploy afterward to tear down its timer.`}
confirmMessage={`Remove job "${job.id}" from wildpc.yaml? Run a deploy afterward to tear down its timer.`}
/>
</div>
)

View File

@@ -95,7 +95,7 @@ export function ProgramFields({ program, onSave, onDelete }: Props) {
onChange={setSource}
mono
placeholder="/data/repos/my-prog"
hint="The working copy on disk. Castle runs dev verbs and builds here. Absolute path, or repo:<name> for castle's own programs."
hint="The working copy on disk. Wild PC runs dev verbs and builds here. Absolute path, or repo:<name> for wildpc's own programs."
/>
<Field
label="Stack"
@@ -119,7 +119,7 @@ export function ProgramFields({ program, onSave, onDelete }: Props) {
onChange={setRepo}
mono
placeholder="https://github.com/me/x.git"
hint="Git URL so 'castle program clone' can fetch the source on a fresh machine. An existing working copy at Source takes precedence."
hint="Git URL so 'wildpc program clone' can fetch the source on a fresh machine. An existing working copy at Source takes precedence."
/>
<TextField
label="Ref"
@@ -134,7 +134,7 @@ export function ProgramFields({ program, onSave, onDelete }: Props) {
value={deps}
onChange={setDeps}
placeholder="pandoc, poppler-utils"
hint="OS packages the program needs. Listed for reference — castle does not install them."
hint="OS packages the program needs. Listed for reference — wildpc does not install them."
/>
<Field

View File

@@ -201,7 +201,7 @@ export function ServiceFields({ service, onSave, onDelete }: Props) {
width="w-32"
mono
placeholder="9001"
hint="The port the service listens on. Castle health-checks and proxies this port; map it to the program's own var with ${port} in Environment."
hint="The port the service listens on. Wild PC health-checks and proxies this port; map it to the program's own var with ${port} in Environment."
/>
<TextField
label="Health path"
@@ -210,7 +210,7 @@ export function ServiceFields({ service, onSave, onDelete }: Props) {
width="w-48"
mono
placeholder="/health"
hint="HTTP path castle polls to report up/down."
hint="HTTP path wildpc polls to report up/down."
/>
<Field
label="Reach"
@@ -263,7 +263,7 @@ export function ServiceFields({ service, onSave, onDelete }: Props) {
onSave={handleSave}
onDelete={onDelete ? () => onDelete(service.id) : undefined}
deleteLabel="Remove service"
confirmMessage={`Remove service "${service.id}" from castle.yaml? Run a deploy afterward to tear down its unit.`}
confirmMessage={`Remove service "${service.id}" from wildpc.yaml? Run a deploy afterward to tear down its unit.`}
/>
</div>
)

View File

@@ -15,7 +15,7 @@ interface Props {
/** Edit a tool's (path) deployment config. A path deployment has no launcher,
* port, or schedule — only a description and its `tool_schema` (the neutral
* tool-call definition handed to agents), plus its manager. It has no run env:
* a tool is a CLI on PATH, invoked from a shell with castle out of the loop, so
* a tool is a CLI on PATH, invoked from a shell with wildpc out of the loop, so
* `defaults.env` is never applied (deploy.py only wires env for systemd units). */
export function ToolFields({ tool, onSave, onDelete }: Props) {
const m = tool.manifest

View File

@@ -170,7 +170,7 @@ export function useEnvSecrets(initial: Record<string, string>) {
Use <code className="font-mono">${"{port}"}</code>,{" "}
<code className="font-mono">${"{data_dir}"}</code>,{" "}
<code className="font-mono">${"{name}"}</code>,{" "}
<code className="font-mono">${"{public_url}"}</code> for castle's computed values,
<code className="font-mono">${"{public_url}"}</code> for wildpc's computed values,
and <code className="font-mono">${"{secret:NAME}"}</code> for secrets.
</p>
{Object.entries(env).map(([key, val]) => (