Skip to content

Latest commit

 

History

History
277 lines (206 loc) · 10.9 KB

File metadata and controls

277 lines (206 loc) · 10.9 KB

Contributing to Prospec

Thank you for considering contributing to Prospec! This guide will help you get started.

Development Setup

This project uses pnpm for development (Node 22.13+, pnpm 11+).

# Clone the repository
git clone https://github.com/benwu95/prospec.git
cd prospec

# Install dependencies
pnpm install

# First-time local install: build, then register the `prospec` bin globally
pnpm run build && pnpm add -g .

# After making changes, just rebuild — the global bin picks up the new dist/
pnpm run build

# Verify
prospec --help

# Remove it when finished
pnpm uninstall -g prospec

First-time global install needs pnpm setup run once to configure the global bin directory.

Running the working-tree CLI

pnpm cli <args> runs the CLI straight from src/ — no build, no install, always exactly HEAD:

pnpm cli status
pnpm cli check

Use this for quick checks and in scripts. It is not what the skills read, though: every skill's startup probe runs prospec --version from PATH and STOPs when that binary is older than MINIMUM_CLI_VERSION, because its deterministic steps call commands only that version ships. So to dogfood the skills on prospec itself, put a build of the working tree on PATH — either the global bin above, or the release-shaped standalone binary:

pnpm bundle                                                    # bakes package.json's version in
bun build ./dist/cli-bundle.js --compile --minify --outfile ~/.prospec/bin/prospec
prospec --version                                              # must be >= MINIMUM_CLI_VERSION

MINIMUM_CLI_VERSION (src/types/version.ts) names the version that ships the commands the skills call, so during development it runs ahead of package.json until the release bumps to match. Never lower it to make a probe pass — that lets an older binary without those commands through.

Development Workflow

# Watch mode (recompile on change)
pnpm run dev

# Run all tests
pnpm test

# Run tests in watch mode
pnpm run test:watch

# Type check
pnpm run typecheck

# Lint
pnpm run lint

# Re-derive the factual counts the docs declare (test totals, .hbs inventory)
pnpm counts

# Same, read-only: exits 1 on drift (this form measures the suite itself).
# CI instead runs `pnpm run counts:check --from vitest-report.json`, reusing
# the report `pnpm run test:coverage` wrote — so a stale count fails the PR.
pnpm counts:check

# Deployed agent artifacts fresh vs their source templates.
pnpm agents:check

# Module knowledge synced with source. IMPORTANT: run this AFTER the feature
# commit and before pushing — it diffs `git merge-base origin/main HEAD`..HEAD,
# so before the commit the range is empty and it prints a "commit first, then
# re-run" skip, never a real pass. Editing a shipped `.hbs` + `pnpm bundle` also
# makes `lib` source-touched via the regenerated `src/lib/bundled-templates.ts`,
# so stamp `lib` too — `prospec knowledge update --change` lists it as stamp-only.
pnpm knowledge:check

Project Structure

src/
├── cli/          — Commander.js commands + formatters
├── services/     — Business logic (one service per command)
├── lib/          — Pure utility functions
├── types/        — Zod schemas + TypeScript types
└── templates/    — Handlebars templates (.hbs)

tests/
├── unit/         — Unit tests (lib + services)
├── contract/     — Contract tests (CLI output + Skill format)
├── integration/  — Integration tests (multi-service flows)
└── e2e/          — End-to-end tests (real CLI process)

Coding Standards

  • Language: TypeScript strict mode, no any
  • Style: Follow ESLint + Prettier configuration
  • Naming: camelCase for variables/functions, PascalCase for types/classes
  • Imports: Use .js extension for relative imports (ESM)
  • Error handling: Use custom error classes from src/types/errors.ts
  • Testing: Every new service/feature requires tests

Dependency Management

Development is pnpm-only; the single lockfile is pnpm-lock.yaml.

When you add, remove, or upgrade a dependency, run pnpm install and commit the updated pnpm-lock.yaml:

pnpm install   # updates pnpm-lock.yaml

CI runs pnpm install --frozen-lockfile on every push/PR — if the lockfile drifts from package.json, CI fails.

Notes:

  • pnpm 11+ and Node 22.13+ are required (pnpm 11 needs Node ≥ 22.13; enforced via engines). Build-script approvals (e.g. esbuild) live in pnpm-workspace.yaml under allowBuilds.
  • End users installing the published CLI can still use npm or pnpm — the pnpm-only rule applies to developing this repo, not to consuming it.

Making Changes

1. Create a branch

git checkout -b feature/your-feature-name

2. Use Prospec's own SDD workflow

Prospec uses itself for development! Use the Skills:

# Describe your change
/prospec-new-story your-feature

# Generate implementation plan + delta-spec
/prospec-plan

# Break down tasks
/prospec-tasks

# Implement (work on the working tree — don't commit yet)
/prospec-implement

# Adversarial review → fix loop (verifier-confirmed criticals auto-fixed)
/prospec-review

# Verify; at grade S/A it prompts you to commit — one atomic commit folding
# implement + review + verify fixes (prospec prompts, never auto-commits)
/prospec-verify

# Archive + sync Feature Specs / Knowledge
/prospec-archive

# (periodic) promote recurring lessons into shared team rules
/prospec-learn

The commit boundary is after /prospec-verify reaches grade S/A — implement, review, and verify all operate on the working tree first, then land as a single atomic-by-feature commit. See README — Quality Gates & Self-Improvement.

3. Write tests

  • Unit tests for new services/utilities
  • Contract tests if adding new Skills or CLI output formats
  • E2E tests for new CLI commands

4. Commit

Follow Conventional Commits:

feat(scope): add new feature
fix(scope): fix specific bug
docs: update documentation
test: add or update tests
refactor(scope): restructure code
chore: dependency updates, config changes

A completed change lands as two commits, in this order:

  1. The change itself (feat: / fix: / docs: / …). Its boundary is /prospec-verify reaching grade S/A — one atomic commit folding the implementation, the review fixes, the verify fixes, every source-touched module README, and any re-derived factual counts.
  2. The archive commit, written after /prospec-archive. It carries the Feature Spec graduation, the prospec/specs/_archived-history/ summary, and the refreshed raw-scan.md. Its subject line is not standardised — docs(archive): archive <name>, docs(spec): graduate <subject> requirements, docs(specs): archive <name> and chore: archive <name> have all been used within one six-week span — so take the wording from git log and treat the contents listed above as the stable part.

The message rules live in prospec/CONSTITUTION.md[MUST] Atomic Commits and Format Requirements, in its Verify clause: conventional prefix; subject and body in English; body as a bulleted list, never prose paragraphs; one concern per commit; no AI co-authorship attribution. The allowed types are feat, fix, refactor, test, docs, chore, perf, and ci.

5. Submit a Pull Request

/submit-pr walks this section end to end (branch → push → body → open). It is maintainer tooling for this repo, like /release — not a prospec SDD skill. This section stays the authority; the skill only executes it.

  • One issue → one change → one PR. Open the PR from the change's branch; let the merge close the issue rather than closing it by hand.
  • Register the issue on the change itself, at scaffold time: prospec change story <name> --issue "#NN". That writes issue: "#NN" into the change's metadata.yaml, and prospec status plus the archive summary (and its committed prospec/specs/_archived-history/ copy) then carry the link. The division is deliberate: the field is the mechanical record — optional, free-form (whitespace collapses to one line), no shape check and no forge API — and this section is where the convention around it is explained. Without the field the link survives only in commit and PR prose, recoverable by nothing but a human reading it; without this section the field is a string with no stated meaning. Field format and its no-validation stance: src/templates/skills/references/metadata-format.hbs`issue`.
  • Land the change as two commits — the feature commit at /prospec-verify grade S/A, then the archive commit — as specified in §4 Commit. Push both before opening the PR.
  • Write the PR body in Traditional Chinese (Taiwan). This is a house convention, not a consequence of the Constitution's [MUST] Language Policy — that rule is defined over repo paths (.prospec/changes/** and friends), and a PR body is not one. The code, commit messages, and trust zone inside the same PR stay English.
  • Structure the body as bullets covering what changed and why, and end with Closes #NN.
  • Never append an AI attribution footer. This repo carries no AI co-authorship in commit messages or PR bodies.
  • Ensure pnpm test, pnpm typecheck, pnpm lint, and prospec check pass. CI additionally gates pnpm run counts:check — a stale factual count fails the PR.

Adding a New Skill

  1. Add skill definition to src/types/skill.ts (SKILL_DEFINITIONS array)
  2. Create template at src/templates/skills/your-skill-name.hbs
  3. If the skill needs references, create src/templates/skills/references/your-ref.hbs and map it in getSkillReferences (src/services/agent-sync.service.ts)
  4. Update contract tests in tests/contract/skill-format.test.ts — bump the SKILL_DEFINITIONS length assertion and write section-scoped structure assertions: slice to the section under test, assert distinctive in-section content, then mutation-verify (delete the section and confirm the test goes red). A bare toContain over the whole rendered template false-greens against incidental text (team rule _playbook.md PB-001).
  5. Run prospec agent sync to generate the new Skill files

Adding a New CLI Command

  1. Create service at src/services/your-command.service.ts
  2. Create command at src/cli/commands/your-command.ts
  3. Create formatter at src/cli/formatters/your-command-output.ts
  4. Register in src/cli/index.ts
  5. Add unit tests for the service
  6. Add E2E tests in tests/e2e/cli.test.ts

Reporting Issues

  • Use GitHub Issues for bug reports and feature requests
  • Include steps to reproduce for bugs
  • Include your Node.js version and OS

License

By contributing, you agree that your contributions will be licensed under the MIT License.