3971c26dc1
- Place workflow YAML in .workflows/ (dot-prefix convention) - Do not run uwf workflow add — use directly via uwf thread start - Fixes agent hallucination issue where registration was faked 小橘 <xiaoju@shazhou.work>
698 lines
28 KiB
YAML
698 lines
28 KiB
YAML
name: normalize-bun-monorepo
|
|
graph:
|
|
ci:
|
|
done:
|
|
role: solve-issue-workflow
|
|
prompt: CI configured. Register solve-issue workflow for repo at {{{repoPath}}}.
|
|
failed:
|
|
role: solve-issue-workflow
|
|
prompt: CI setup failed ({{{reason}}}), but continue. Register solve-issue workflow for repo at {{{repoPath}}}.
|
|
biome:
|
|
done:
|
|
role: package-metadata
|
|
prompt: Biome configured. Standardize package metadata for repo at {{{repoPath}}}.
|
|
failed:
|
|
role: package-metadata
|
|
prompt: Biome setup failed ({{{reason}}}), but continue. Standardize package metadata for repo at {{{repoPath}}}.
|
|
$START:
|
|
_:
|
|
role: workspace
|
|
prompt: Set up bun workspace structure for repo at {{{repoPath}}}.
|
|
release:
|
|
done:
|
|
role: testing
|
|
prompt: Release pipeline configured. Set up vitest for repo at {{{repoPath}}}.
|
|
failed:
|
|
role: testing
|
|
prompt: Release pipeline failed ({{{reason}}}), but continue. Set up vitest for repo at {{{repoPath}}}.
|
|
testing:
|
|
done:
|
|
role: ci
|
|
prompt: Testing configured. Set up Gitea CI for repo at {{{repoPath}}}.
|
|
failed:
|
|
role: ci
|
|
prompt: Testing setup failed ({{{reason}}}), but continue. Set up Gitea CI for repo at {{{repoPath}}}.
|
|
committer:
|
|
failed:
|
|
role: $END
|
|
prompt: "Commit failed: {{{reason}}}."
|
|
committed:
|
|
role: $END
|
|
prompt: "Normalization committed: {{{commitHash}}}."
|
|
no_changes:
|
|
role: $END
|
|
prompt: Repo already normalized, no changes needed.
|
|
workspace:
|
|
done:
|
|
role: typescript
|
|
prompt: Workspace ready. Configure TypeScript for repo at {{{repoPath}}}.
|
|
failed:
|
|
role: typescript
|
|
prompt: Workspace setup failed ({{{reason}}}), but continue. Configure TypeScript for repo at {{{repoPath}}}.
|
|
guardrails:
|
|
done:
|
|
role: committer
|
|
prompt: All normalization complete. Commit changes in repo at {{{repoPath}}}.
|
|
failed:
|
|
role: committer
|
|
prompt: Guardrails failed ({{{reason}}}), but commit whatever was done in repo at {{{repoPath}}}.
|
|
typescript:
|
|
done:
|
|
role: biome
|
|
prompt: TypeScript configured. Set up Biome for repo at {{{repoPath}}}.
|
|
failed:
|
|
role: biome
|
|
prompt: TypeScript setup failed ({{{reason}}}), but continue. Set up Biome for repo at {{{repoPath}}}.
|
|
package-metadata:
|
|
done:
|
|
role: release
|
|
prompt: Package metadata standardized. Configure release pipeline for repo at {{{repoPath}}}.
|
|
failed:
|
|
role: release
|
|
prompt: Package metadata failed ({{{reason}}}), but continue. Configure release pipeline for repo at {{{repoPath}}}.
|
|
solve-issue-workflow:
|
|
done:
|
|
role: guardrails
|
|
prompt: Solve-issue workflow placed in .workflows/. Install guardrails for repo at {{{repoPath}}}.
|
|
failed:
|
|
role: guardrails
|
|
prompt: Solve-issue workflow failed ({{{reason}}}), but continue. Install guardrails for repo at {{{repoPath}}}.
|
|
roles:
|
|
ci:
|
|
goal: You configure Gitea Actions CI for build, lint, and test on push/PR.
|
|
output: Describe the CI pipeline configured. Set $status to done or failed.
|
|
procedure: |
|
|
cd into the repo path from your task prompt.
|
|
|
|
IMPORTANT: If `.gitea/workflows/ci.yml` already exists, review it for completeness but don't overwrite unless it's missing key steps.
|
|
If `.github/workflows/` exists (GitHub Actions), keep it — add `.gitea/workflows/` alongside it.
|
|
|
|
Create `.gitea/workflows/ci.yml` (if not present):
|
|
```yaml
|
|
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: ['*']
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
check:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: oven-sh/setup-bun@v2
|
|
|
|
- run: bun install
|
|
|
|
- name: Build
|
|
run: bun run build
|
|
|
|
- name: Lint
|
|
run: bun run check
|
|
|
|
- name: Test
|
|
run: bun run test:ci
|
|
```
|
|
|
|
## Verification
|
|
```bash
|
|
# 1. CI file exists
|
|
test -f .gitea/workflows/ci.yml
|
|
# 2. YAML is valid
|
|
node -e "
|
|
const fs = require('fs');
|
|
const content = fs.readFileSync('.gitea/workflows/ci.yml', 'utf8');
|
|
if (!content.includes('bun')) { console.error('Missing bun setup'); process.exit(1); }
|
|
if (!content.includes('test')) { console.error('Missing test step'); process.exit(1); }
|
|
console.log('CI YAML looks valid');
|
|
"
|
|
# 3. Required root scripts exist for CI to work
|
|
node -e "
|
|
const pkg = require('./package.json');
|
|
const required = ['build', 'check', 'test:ci'];
|
|
const missing = required.filter(s => !pkg.scripts?.[s]);
|
|
if (missing.length) { console.error('Missing scripts for CI:', missing.join(', ')); process.exit(1); }
|
|
console.log('All CI-required scripts present');
|
|
"
|
|
```
|
|
|
|
Post-condition: CI file exists, YAML references bun and test, all required scripts exist in package.json.
|
|
description: Set up Gitea CI workflow
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: done
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities:
|
|
- ci-config
|
|
biome:
|
|
goal: You configure Biome for consistent code quality across the monorepo.
|
|
output: List what was configured and any remaining lint issues. Set $status to done or failed.
|
|
procedure: |
|
|
cd into the repo path from your task prompt.
|
|
|
|
IMPORTANT: Be idempotent — if biome.json already exists, merge missing settings rather than overwriting.
|
|
|
|
Check and fix:
|
|
1. Install biome: add `@biomejs/biome` to root devDependencies (skip if already present)
|
|
2. Root `biome.json` must exist with at minimum:
|
|
- `files.includes`: `["**", "!**/dist", "!**/node_modules"]`
|
|
- `formatter`: indentStyle space, indentWidth 2, lineWidth 100
|
|
- `javascript.formatter`: quoteStyle double, semicolons always
|
|
- `linter.rules.nursery.noConsole: "error"` (production code)
|
|
- Override for test files (`**/__tests__/**`): `noConsole: "off"`, `noExplicitAny: "off"`
|
|
- `assist.actions.source.organizeImports: "on"`
|
|
If biome.json already exists, only add missing fields — preserve existing customizations.
|
|
3. Root scripts must include: `"check"` (should include `biome check .`), `"format": "biome format --write ."`
|
|
4. Run `bunx biome check .` — fix auto-fixable issues with `bunx biome check . --fix`
|
|
5. Remaining unfixable issues: list them but don't block
|
|
|
|
## Verification
|
|
```bash
|
|
# 1. biome.json exists
|
|
test -f biome.json
|
|
# 2. biome is installed
|
|
bunx biome --version
|
|
# 3. check runs (exit 0 or list remaining issues)
|
|
bunx biome check . 2>&1 || true
|
|
```
|
|
|
|
Post-condition: `biome.json` exists, `bunx biome check .` runs (may have warnings but no infrastructure errors).
|
|
description: Configure Biome linter and formatter
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: done
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities:
|
|
- linter-config
|
|
release:
|
|
goal: "You set up the complete release pipeline: changesets for version management, publish script for npm release."
|
|
output: Describe what was configured. Set $status to done or failed.
|
|
procedure: |
|
|
cd into the repo path from your task prompt.
|
|
|
|
IMPORTANT: Be idempotent — skip steps that are already done.
|
|
|
|
## Part 1: Changesets
|
|
1. Install: add `@changesets/cli` to root devDependencies (skip if present), run `bun install`
|
|
2. If `.changeset/config.json` does not exist, run `bunx changeset init`
|
|
3. Verify `.changeset/config.json` has:
|
|
- `"access": "public"` (for @scoped packages)
|
|
- `"baseBranch": "main"`
|
|
4. Add `.changeset/README.md` if missing
|
|
|
|
## Part 2: Publish Script
|
|
5. Create `scripts/publish-all.mjs` (skip if already exists and looks correct):
|
|
- Scan `packages/` for non-private packages (skip `"private": true`)
|
|
- Determine publish order by resolving workspace dependency graph (dependees before dependents)
|
|
- For each package in order:
|
|
a. Replace `"workspace:^"` deps with actual versions from workspace
|
|
b. Run `npm publish --access public --ignore-scripts` (MUST use --ignore-scripts to bypass prepublishOnly guardrail)
|
|
c. Restore original package.json
|
|
- Support flags: `--dry-run`, `--tag <name>`
|
|
- Handle errors: if one package fails, restore and continue
|
|
CRITICAL: The publish command MUST include `--ignore-scripts` because the guardrails role adds a `prepublishOnly` script that blocks direct publishing.
|
|
|
|
## Part 3: Root Scripts
|
|
6. Root scripts must include:
|
|
- `"changeset": "bunx changeset"`
|
|
- `"version": "bunx changeset version"`
|
|
- `"release": "bun run build && bun run test && node scripts/publish-all.mjs"`
|
|
|
|
## Verification
|
|
```bash
|
|
# 1. changeset config exists and is valid
|
|
test -f .changeset/config.json
|
|
node -e "const c = require('./.changeset/config.json'); console.log('access:', c.access, 'baseBranch:', c.baseBranch)"
|
|
# 2. changeset status works
|
|
bunx changeset status 2>&1 || true
|
|
# 3. publish script exists and uses --ignore-scripts
|
|
test -f scripts/publish-all.mjs
|
|
grep -q 'ignore-scripts' scripts/publish-all.mjs
|
|
# 4. dry run works
|
|
node scripts/publish-all.mjs --dry-run
|
|
```
|
|
|
|
Post-condition: All verification commands pass.
|
|
description: Configure changesets and publish pipeline
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: done
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities:
|
|
- changeset-config
|
|
- release-config
|
|
testing:
|
|
goal: You set up vitest test infrastructure across the monorepo.
|
|
output: List what was configured per package. Set $status to done or failed.
|
|
procedure: |
|
|
cd into the repo path from your task prompt.
|
|
|
|
IMPORTANT: Be idempotent — do NOT overwrite existing vitest.config.ts or test files.
|
|
|
|
Check and fix:
|
|
1. Add `vitest` to root devDependencies (skip if present), run `bun install`
|
|
2. For each package under `packages/`:
|
|
- If `vitest.config.ts` does NOT already exist, create it:
|
|
```ts
|
|
import { defineConfig } from "vitest/config";
|
|
export default defineConfig({
|
|
test: {
|
|
include: ["src/__tests__/**/*.test.ts"],
|
|
},
|
|
});
|
|
```
|
|
- If package.json has no `"test"` script, add: `"test": "vitest run --passWithNoTests"`, `"test:ci": "vitest run --passWithNoTests"`
|
|
- Create `src/__tests__/` directory if it doesn't exist
|
|
3. Root package.json scripts must include:
|
|
- `"test": "bun run --filter './packages/*' test"`
|
|
- `"test:ci": "bun run --filter './packages/*' test:ci"`
|
|
|
|
## Verification
|
|
```bash
|
|
# 1. vitest is installed
|
|
bunx vitest --version
|
|
# 2. each package has vitest config
|
|
for d in packages/*/; do
|
|
if [ -f "$d/vitest.config.ts" ]; then echo "$d: ✅"; else echo "$d: ❌ missing vitest.config.ts"; fi
|
|
done
|
|
# 3. root test script works
|
|
bun run test 2>&1 || true
|
|
```
|
|
|
|
Post-condition: `bun run test` runs without infrastructure errors (no tests is OK, test failures are OK).
|
|
description: Configure vitest for all packages
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: done
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities:
|
|
- test-config
|
|
committer:
|
|
goal: You commit all the changes made by previous roles in a single clean commit.
|
|
output: List files changed and commit hash. Set $status to committed or no_changes.
|
|
procedure: |
|
|
cd into the repo path from your task prompt.
|
|
|
|
1. Review all changes: `git diff --stat` and `git status`
|
|
2. Verify key files exist from previous roles (spot-check):
|
|
```bash
|
|
echo "=== Spot-check ==="
|
|
if [ -f tsconfig.json ]; then echo "✅ tsconfig.json"; else echo "ℹ️ tsconfig.json (skipped for JS/MJS)"; fi
|
|
for f in .gitignore biome.json .changeset/config.json .gitea/workflows/ci.yml .githooks/pre-push; do
|
|
test -f "$f" && echo "✅ $f" || echo "⚠️ MISSING: $f"
|
|
done
|
|
node -e "
|
|
const p = require('./package.json');
|
|
const required = ['build', 'check', 'test', 'test:ci', 'format', 'preinstall', 'prepublishOnly'];
|
|
const missing = required.filter(s => !p.scripts?.[s]);
|
|
if (missing.length) console.log('⚠️ Missing scripts:', missing.join(', '));
|
|
else console.log('✅ All scripts present');
|
|
if (!p.packageManager) console.log('⚠️ Missing packageManager');
|
|
else console.log('✅ packageManager:', p.packageManager);
|
|
"
|
|
```
|
|
List any missing items as warnings but still commit what exists.
|
|
3. If no changes: set $status=no_changes
|
|
4. Stage all: `git add -A`
|
|
5. Commit: `git commit -m "chore: normalize to bun monorepo conventions"`
|
|
6. Push: `git push`
|
|
|
|
Post-condition: Clean commit pushed, `git status` shows clean working tree.
|
|
description: Commits all normalization changes
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: committed
|
|
commitHash:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: no_changes
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities: []
|
|
workspace:
|
|
goal: You set up the foundational bun workspace configuration for a monorepo.
|
|
output: List what was changed. Set $status to done (workspace working) or failed (with reason).
|
|
procedure: |
|
|
cd into the repo path provided in your task prompt.
|
|
|
|
IMPORTANT: Be idempotent — check before modifying. If something is already correct, skip it.
|
|
|
|
Check and fix:
|
|
1. Root `package.json` must have `"workspaces": ["packages/*"]`
|
|
2. Root `package.json` must have `"private": true`
|
|
3. If packages exist in other locations (e.g. root src/, top-level dirs), migrate them under `packages/`
|
|
4. Each package under `packages/` must have its own `package.json` with `"name"` and `"type": "module"`
|
|
5. `.gitignore` must exist and include at minimum:
|
|
```
|
|
node_modules/
|
|
dist/
|
|
*.tsbuildinfo
|
|
```
|
|
If `.gitignore` is missing or doesn't cover these, append the missing entries (don't overwrite existing content).
|
|
6. If node_modules/ is already tracked in git, remove it: `git rm -r --cached node_modules/ */node_modules/ 2>/dev/null`
|
|
7. Run `bun install` to verify workspace resolution works
|
|
|
|
## Verification (must all pass)
|
|
```bash
|
|
# 1. bun install works
|
|
bun install
|
|
# 2. gitignore covers essentials
|
|
grep -q 'node_modules' .gitignore
|
|
grep -q 'dist' .gitignore
|
|
# 3. no node_modules tracked
|
|
test -z "$(git ls-files | grep node_modules)"
|
|
# 4. all packages have package.json
|
|
for d in packages/*/; do test -f "$d/package.json" || echo "MISSING: $d/package.json"; done
|
|
```
|
|
|
|
Post-condition: All verification commands pass.
|
|
description: Ensure bun workspace structure
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: done
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities:
|
|
- workspace-setup
|
|
guardrails:
|
|
goal: You configure enforcement mechanisms that block npm/pnpm/yarn usage and direct npm publish.
|
|
output: List what guardrails were installed. Set $status to done or failed.
|
|
procedure: |
|
|
cd into the repo path from your task prompt.
|
|
|
|
IMPORTANT: Be idempotent — check before adding.
|
|
|
|
## 1. Block wrong package manager
|
|
Add to root `package.json` (if not already present):
|
|
- `"packageManager": "bun@<version>"` — use the version from `bun --version`
|
|
- `"scripts.preinstall": "npx only-allow bun"` — blocks npm/pnpm/yarn install
|
|
|
|
## 2. Block direct npm publish
|
|
Add to root `package.json` (if not already present):
|
|
- `"scripts.prepublishOnly": "echo 'Use bun run release instead' && exit 1"`
|
|
|
|
For each non-private package under `packages/`:
|
|
- Add `"scripts.prepublishOnly": "echo 'Use bun run release from repo root' && exit 1"` to their package.json (if not present)
|
|
|
|
If `scripts/publish-all.mjs` exists, verify it uses `--ignore-scripts` in the npm publish command.
|
|
If it doesn't, add `--ignore-scripts` to the publish command.
|
|
|
|
## 3. Git hooks
|
|
Create `.githooks/pre-push` (if not already present):
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
echo "🔍 Running checks..."
|
|
bun run check
|
|
echo "🧪 Running tests..."
|
|
bun run test
|
|
echo "✅ All checks passed!"
|
|
```
|
|
Make it executable: `chmod +x .githooks/pre-push`
|
|
Configure git to use hooks dir: `git config core.hooksPath .githooks`
|
|
|
|
## Verification
|
|
```bash
|
|
# 1. packageManager field exists
|
|
node -e "const p = require('./package.json'); if (!p.packageManager) { console.error('❌ missing packageManager'); process.exit(1); } console.log('✅ packageManager:', p.packageManager)"
|
|
# 2. preinstall guard exists
|
|
node -e "const p = require('./package.json'); if (!p.scripts?.preinstall?.includes('only-allow')) { console.error('❌ missing preinstall guard'); process.exit(1); } console.log('✅ preinstall guard')"
|
|
# 3. npm install is blocked (with timeout to prevent hang)
|
|
timeout 10 npm install 2>&1 | head -5 || true
|
|
# 4. prepublishOnly exists
|
|
node -e "const p = require('./package.json'); if (!p.scripts?.prepublishOnly) { console.error('❌ missing prepublishOnly'); process.exit(1); } console.log('✅ prepublishOnly guard')"
|
|
# 5. publish script uses --ignore-scripts
|
|
if [ -f scripts/publish-all.mjs ]; then grep -q 'ignore-scripts' scripts/publish-all.mjs && echo '✅ publish uses --ignore-scripts' || echo '❌ publish missing --ignore-scripts'; fi
|
|
# 6. git hooks configured
|
|
test -f .githooks/pre-push && echo '✅ pre-push hook' || echo '❌ missing pre-push hook'
|
|
```
|
|
|
|
Post-condition: All verification checks pass.
|
|
description: Install project guardrails to prevent wrong package manager and publish workflow
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: done
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities:
|
|
- guardrails
|
|
typescript:
|
|
goal: You configure TypeScript for a bun monorepo with composite project references.
|
|
output: List what was configured. Set $status to done or failed.
|
|
procedure: |-
|
|
cd into the repo path from your task prompt.
|
|
|
|
IMPORTANT: Be idempotent — if tsconfig.json already exists with correct settings, don't overwrite.
|
|
|
|
## Step 0: Detect if project needs TypeScript compilation
|
|
|
|
```bash
|
|
TS_FILES=$(find packages/ -name '*.ts' -o -name '*.tsx' | grep -v node_modules | grep -v dist | grep -v '.d.ts' | head -5)
|
|
```
|
|
|
|
**If there are NO .ts/.tsx source files** (pure JS/MJS project):
|
|
- Do NOT create root tsconfig.json
|
|
- Do NOT add `bunx tsc --build` as the build script
|
|
- Do NOT add typescript/bun-types to devDependencies unless already present
|
|
- Preserve the existing `build` script (e.g. vite build, esbuild, etc.)
|
|
- If no build script exists, add one based on the project's bundler (check for vite.config, esbuild, etc.)
|
|
- Set $status=done with note "JS/MJS project — skipped TypeScript setup"
|
|
- STOP HERE.
|
|
|
|
**If .ts/.tsx files exist**, continue with full TypeScript setup:
|
|
|
|
Check and fix:
|
|
1. Root `tsconfig.json` must exist with:
|
|
- `"compilerOptions"`: target ES2022, module NodeNext, moduleResolution NodeNext, strict true, composite true, declaration true, declarationMap true, sourceMap true
|
|
- `"references"`: array with `{ "path": "packages/<name>" }` for each package
|
|
- `"files": []` (root does not compile files directly)
|
|
2. Each package must have `tsconfig.json` with:
|
|
- `"extends": "../../tsconfig.json"` (inherit root config)
|
|
- `"compilerOptions": { "rootDir": "src", "outDir": "dist" }`
|
|
- `"include": ["src"]`
|
|
- `"references"` to sibling packages it depends on
|
|
3. Root scripts must include: `"build": "bunx tsc --build"`, `"typecheck": "bunx tsc --build"`
|
|
4. `devDependencies` at root: `typescript`, `bun-types`, `@types/node`
|
|
|
|
## Verification
|
|
```bash
|
|
if [ ! -f tsconfig.json ]; then
|
|
echo "JS/MJS project — no tsconfig needed"
|
|
node -e "const p = require('./package.json'); if (!p.scripts?.build) { console.error('Missing build script'); process.exit(1); } console.log('build:', p.scripts.build)"
|
|
bun run build
|
|
exit 0
|
|
fi
|
|
test -f tsconfig.json
|
|
for d in packages/*/; do test -f "$d/tsconfig.json" || echo "MISSING: $d/tsconfig.json"; done
|
|
bunx tsc --build
|
|
```
|
|
|
|
Post-condition: For TS projects — `bunx tsc --build` succeeds. For JS/MJS projects — `bun run build` succeeds.
|
|
description: Configure TypeScript with project references
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: done
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities:
|
|
- typescript-config
|
|
package-metadata:
|
|
goal: You ensure every package has consistent metadata for publishing and discoverability.
|
|
output: List what was standardized per package. Set $status to done or failed.
|
|
procedure: |
|
|
cd into the repo path from your task prompt.
|
|
|
|
IMPORTANT: Be idempotent — skip fields that are already correctly set.
|
|
|
|
For each package under `packages/`:
|
|
1. `"type": "module"` — must be set
|
|
2. `"files": ["src", "dist", "package.json"]` — for published packages (non-private)
|
|
3. `"publishConfig": { "access": "public" }` — for @scoped public packages (non-private)
|
|
4. `"repository"` — must point to the correct git remote and directory
|
|
- Read remote URL: `git remote get-url origin`
|
|
- Set `"directory": "packages/<name>"`
|
|
5. `"exports"` — conditional exports for TypeScript packages:
|
|
```json
|
|
".": {
|
|
"bun": "./src/index.ts",
|
|
"types": "./dist/index.d.ts",
|
|
"import": "./dist/index.js"
|
|
}
|
|
```
|
|
Skip if package has no `src/index.ts`.
|
|
6. Private packages (server, frontend, tools) must have `"private": true` and can skip publishConfig/files
|
|
7. Each package should have a `"scripts"` section with at least `"test"` if tests exist
|
|
8. Workspace dependencies should use `"workspace:^"` protocol, not version numbers
|
|
- Check: `grep -r '"@uncaged/' packages/*/package.json | grep -v 'workspace:'`
|
|
|
|
## Verification
|
|
```bash
|
|
# Check every non-private package has required fields
|
|
for d in packages/*/; do
|
|
pkg="$d/package.json"
|
|
test -f "$pkg" || continue
|
|
node -e "
|
|
const p = require('./$pkg');
|
|
if (p.private) { console.log('$d: private, skip'); process.exit(0); }
|
|
const issues = [];
|
|
if (p.type !== 'module') issues.push('missing type:module');
|
|
if (!p.exports) issues.push('missing exports');
|
|
if (!p.publishConfig) issues.push('missing publishConfig');
|
|
if (!p.files) issues.push('missing files');
|
|
if (issues.length) console.log('$d:', issues.join(', '));
|
|
else console.log('$d: OK');
|
|
"
|
|
done
|
|
# No hardcoded workspace deps
|
|
! grep -r '"@uncaged/' packages/*/package.json | grep -v 'workspace:' | grep -v node_modules
|
|
```
|
|
|
|
Post-condition: Verification script shows OK for all non-private packages, no hardcoded workspace versions.
|
|
description: Standardize package.json metadata across all packages
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: done
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities:
|
|
- package-config
|
|
solve-issue-workflow:
|
|
goal: You place a solve-issue workflow YAML in .workflows/ so the project can use uwf thread start .workflows/solve-issue.yaml for issue resolution.
|
|
output: Describe the workflow registered. Set $status to done or failed.
|
|
procedure: |-
|
|
cd into the repo path from your task prompt.
|
|
|
|
1. Check if `uwf` CLI is available: `which uwf`
|
|
- If not available: set $status=failed, reason="uwf CLI not installed"
|
|
2. Check if `.workflows/solve-issue.yaml` already exists:
|
|
- If it exists and looks correct (has planner/developer/reviewer/tester/committer roles), skip. Set $status=done.
|
|
3. Create `.workflows/solve-issue.yaml` adapted for this project:
|
|
- Copy the standard solve-issue workflow structure (planner -> developer -> reviewer -> tester -> committer)
|
|
- Adjust the developer role procedure to use this project's test runner and build commands
|
|
- The workflow should reference the correct repo path and build toolchain (bun)
|
|
NOTE: Place the file in `.workflows/` (dot-prefix), NOT `workflows/`. Do NOT run `uwf workflow add`. The file is used directly via `uwf thread start .workflows/solve-issue.yaml`.
|
|
|
|
## Verification
|
|
```bash
|
|
test -f .workflows/solve-issue.yaml
|
|
node -e "
|
|
const fs = require('fs');
|
|
const content = fs.readFileSync('.workflows/solve-issue.yaml', 'utf8');
|
|
const required = ['planner', 'developer', 'reviewer', 'tester', 'committer'];
|
|
const missing = required.filter(r => !content.includes(r + ':'));
|
|
if (missing.length) { console.error('Missing roles:', missing.join(', ')); process.exit(1); }
|
|
console.log('All roles present');
|
|
"
|
|
```
|
|
|
|
Post-condition: `.workflows/solve-issue.yaml` exists with all 5 roles.
|
|
description: Register solve-issue workflow for the project
|
|
frontmatter:
|
|
oneOf:
|
|
- properties:
|
|
$status:
|
|
const: done
|
|
repoPath:
|
|
type: string
|
|
- properties:
|
|
$status:
|
|
const: failed
|
|
reason:
|
|
type: string
|
|
repoPath:
|
|
type: string
|
|
capabilities:
|
|
- workflow-config
|
|
description: Normalize an existing project to @uncaged bun monorepo conventions. Supports both TypeScript and JS/MJS projects. Each role handles one configuration layer. All roles allow fail.
|