--- phase: 01-foundation plan: 01 type: execute wave: 1 depends_on: [] files_modified: - packages/branding/package.json - packages/branding/tsconfig.json - packages/branding/src/index.ts - packages/branding/src/vocab.ts - packages/branding/src/vocab.test.ts - packages/branding/vitest.config.ts - vitest.config.ts autonomous: true requirements: [FOUND-01] must_haves: truths: - "import { VOCAB } from '@paperclipai/branding' resolves and returns an object with all required vocabulary keys" - "VOCAB.company equals 'Workspace', VOCAB.ceo equals 'Project Manager', VOCAB.appName equals 'Nexus'" - "Unit tests pass confirming every VOCAB key has the correct string value" artifacts: - path: "packages/branding/package.json" provides: "Workspace package definition" contains: "@paperclipai/branding" - path: "packages/branding/src/vocab.ts" provides: "VOCAB constant with all display strings" exports: ["VOCAB", "VocabKey"] - path: "packages/branding/src/index.ts" provides: "Package barrel export" exports: ["VOCAB", "VocabKey"] - path: "packages/branding/src/vocab.test.ts" provides: "Unit tests for VOCAB shape and values" min_lines: 20 key_links: - from: "packages/branding/src/index.ts" to: "packages/branding/src/vocab.ts" via: "re-export" pattern: "export.*from.*vocab" - from: "vitest.config.ts" to: "packages/branding" via: "projects array entry" pattern: "packages/branding" --- Create the `packages/branding/` workspace package that centralizes all Nexus fork-specific display strings in a single `VOCAB` constant. This is the string mutation surface that all downstream phases (2, 3, 4) will import from. Purpose: Isolate all Nexus vocabulary from upstream Paperclip code so that rebase operations never conflict on display strings. Output: A working, tested `@paperclipai/branding` package importable by any workspace member. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-foundation/01-RESEARCH.md From packages/shared/package.json: ```json { "name": "@paperclipai/shared", "version": "0.3.1", "license": "MIT", "type": "module", "exports": { ".": "./src/index.ts", "./*": "./src/*.ts" }, "publishConfig": { "access": "public", "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" }, "./*": { "types": "./dist/*.d.ts", "import": "./dist/*.js" } }, "main": "./dist/index.js", "types": "./dist/index.d.ts" }, "files": ["dist"], "scripts": { "build": "tsc", "clean": "rm -rf dist", "typecheck": "tsc --noEmit" } } ``` From packages/shared/tsconfig.json: ```json { "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "dist", "rootDir": "src" }, "include": ["src"] } ``` From vitest.config.ts (root): ```typescript import { defineConfig } from "vitest/config"; export default defineConfig({ test: { projects: ["packages/db", "packages/adapters/opencode-local", "server", "ui", "cli"], }, }); ``` From pnpm-workspace.yaml (confirms packages/* glob): ```yaml packages: - packages/* - packages/adapters/* - packages/plugins/* - packages/plugins/examples/* - server - ui - cli ``` Task 1: Scaffold branding package and write VOCAB constant with tests packages/branding/package.json, packages/branding/tsconfig.json, packages/branding/src/vocab.ts, packages/branding/src/vocab.test.ts, packages/branding/src/index.ts, packages/branding/vitest.config.ts /Volumes/UsbNvme/repos/nexus/packages/shared/package.json, /Volumes/UsbNvme/repos/nexus/packages/shared/tsconfig.json, /Volumes/UsbNvme/repos/nexus/packages/shared/src/index.ts, /Volumes/UsbNvme/repos/nexus/pnpm-workspace.yaml - Test: VOCAB has key "company" with value "Workspace" - Test: VOCAB has key "companies" with value "Workspaces" - Test: VOCAB has key "ceo" with value "Project Manager" - Test: VOCAB has key "board" with value "Owner" - Test: VOCAB has key "hire" with value "Add" - Test: VOCAB has key "fire" with value "Remove" - Test: VOCAB has key "appName" with value "Nexus" - Test: VOCAB has key "tagline" with value "Open-source orchestration for your agents" - Test: VocabKey type is exported (TypeScript compilation succeeds) - Test: All VOCAB values are non-empty strings 1. Create `packages/branding/package.json` following the `packages/shared/package.json` pattern exactly: - `"name": "@paperclipai/branding"` (keep @paperclipai scope per upstream sync constraint) - `"version": "0.1.0"` - `"license": "MIT"` - `"type": "module"` - `"exports": { ".": "./src/index.ts", "./*": "./src/*.ts" }` - `"publishConfig"` with dist paths matching shared pattern - `"files": ["dist"]` - `"scripts": { "build": "tsc", "clean": "rm -rf dist", "typecheck": "tsc --noEmit" }` - `"devDependencies": { "typescript": "^5.7.3" }` — no runtime dependencies 2. Create `packages/branding/tsconfig.json`: ```json { "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "dist", "rootDir": "src" }, "include": ["src"] } ``` 3. Create `packages/branding/vitest.config.ts`: ```typescript import { defineConfig } from "vitest/config"; export default defineConfig({ test: { include: ["src/**/*.test.ts"], }, }); ``` 4. Create `packages/branding/src/vocab.ts` with the VOCAB constant: ```typescript export const VOCAB = { // Entity renames (display only — code identifiers unchanged) company: "Workspace", companies: "Workspaces", ceo: "Project Manager", board: "Owner", hire: "Add", fire: "Remove", // Brand name appName: "Nexus", tagline: "Open-source orchestration for your agents", } as const; export type VocabKey = keyof typeof VOCAB; ``` 5. Create `packages/branding/src/index.ts`: ```typescript export { VOCAB, type VocabKey } from "./vocab.js"; ``` 6. Create `packages/branding/src/vocab.test.ts` — RED first (write tests before verifying they pass): ```typescript import { describe, it, expect } from "vitest"; import { VOCAB } from "./vocab.js"; describe("VOCAB", () => { it("maps company to Workspace", () => { expect(VOCAB.company).toBe("Workspace"); }); it("maps companies to Workspaces", () => { expect(VOCAB.companies).toBe("Workspaces"); }); it("maps ceo to Project Manager", () => { expect(VOCAB.ceo).toBe("Project Manager"); }); it("maps board to Owner", () => { expect(VOCAB.board).toBe("Owner"); }); it("maps hire to Add", () => { expect(VOCAB.hire).toBe("Add"); }); it("maps fire to Remove", () => { expect(VOCAB.fire).toBe("Remove"); }); it("has appName as Nexus", () => { expect(VOCAB.appName).toBe("Nexus"); }); it("has a non-empty tagline", () => { expect(VOCAB.tagline).toBe("Open-source orchestration for your agents"); }); it("all values are non-empty strings", () => { for (const [key, value] of Object.entries(VOCAB)) { expect(typeof value).toBe("string"); expect(value.length).toBeGreaterThan(0); } }); }); ``` 7. Run `pnpm install` from repo root to link the new workspace package. 8. Run tests to confirm GREEN: `pnpm vitest run --project packages/branding` cd /Volumes/UsbNvme/repos/nexus && pnpm vitest run --project packages/branding - packages/branding/package.json contains `"name": "@paperclipai/branding"` - packages/branding/package.json contains `"type": "module"` - packages/branding/package.json contains `"exports"` - packages/branding/src/vocab.ts contains `export const VOCAB` - packages/branding/src/vocab.ts contains `as const` - packages/branding/src/vocab.ts contains `company: "Workspace"` - packages/branding/src/vocab.ts contains `ceo: "Project Manager"` - packages/branding/src/vocab.ts contains `appName: "Nexus"` - packages/branding/src/vocab.ts contains `export type VocabKey` - packages/branding/src/index.ts contains `export { VOCAB` - packages/branding/src/vocab.test.ts contains `describe("VOCAB"` - packages/branding/tsconfig.json contains `extends": "../../tsconfig.base.json"` - `pnpm vitest run --project packages/branding` exits 0 with all tests passing All 9 VOCAB tests pass. Package exports VOCAB and VocabKey. Package is linked in pnpm workspace. Task 2: Register branding package in root vitest config vitest.config.ts /Volumes/UsbNvme/repos/nexus/vitest.config.ts Edit `vitest.config.ts` at the repo root to add `"packages/branding"` to the `projects` array: ```typescript import { defineConfig } from "vitest/config"; export default defineConfig({ test: { projects: ["packages/db", "packages/adapters/opencode-local", "server", "ui", "cli", "packages/branding"], }, }); ``` The only change is appending `"packages/branding"` to the end of the existing `projects` array. After editing, run `pnpm vitest run --project packages/branding` to confirm the root config picks up the new project. cd /Volumes/UsbNvme/repos/nexus && pnpm vitest run --project packages/branding - vitest.config.ts contains `"packages/branding"` in the projects array - `pnpm vitest run --project packages/branding` exits 0 Root vitest config includes branding package. Running `pnpm vitest run --project packages/branding` from root succeeds. 1. `pnpm vitest run --project packages/branding` — all VOCAB tests pass 2. `node -e "const b = await import('./packages/branding/src/index.ts'); console.log(b.VOCAB.appName)"` — prints "Nexus" (requires tsx or similar TS runner) 3. `test -f packages/branding/package.json && echo OK` — package.json exists - `@paperclipai/branding` package exists at `packages/branding/` - `VOCAB` constant exports 8 keys: company, companies, ceo, board, hire, fire, appName, tagline - All values are correct Nexus display strings - Unit tests pass via vitest - Package is registered in root vitest config After completion, create `.planning/phases/01-foundation/01-01-SUMMARY.md`