Planning artifacts (milestones v1.0-v1.2.1, v1.3 queue, PROJECT.md, STATE.md, config) now live alongside the code they describe. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 KiB
11 KiB
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-foundation | 01 | execute | 1 |
|
true |
|
|
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.
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-foundation/01-RESEARCH.mdFrom packages/shared/package.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:
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}
From vitest.config.ts (root):
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):
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
<success_criteria>
@paperclipai/brandingpackage exists atpackages/branding/VOCABconstant 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 </success_criteria>