diff --git a/.claude/rules/compound-learning.md b/.claude/rules/compound-learning.md new file mode 100644 index 0000000..13fe018 --- /dev/null +++ b/.claude/rules/compound-learning.md @@ -0,0 +1,21 @@ +# Compound Learning + +Prevent repeated mistakes by systematically promoting learnings. + +## Before Solving a Problem + +Check AGENT_LEARNINGS.md for prior art. If a matching pattern exists, apply it. + +## Promotion Path + +1. **1st occurrence** — fix inline, move on +2. **2nd occurrence** — add to AGENT_LEARNINGS.md (pattern + solution) +3. **3rd occurrence** — promote to `.claude/rules/` (always-loaded, prevents recurrence) +4. **Recurring workflow** — extract to `.claude/skills/` (reusable capability) + +## When Promoting (step 3) + +- Verify the root cause is the same across occurrences +- Write the rule as a constraint ("do X", "never Y"), not a narrative +- Reference the AGENT_LEARNINGS.md entry being promoted +- Remove or link the original entry to avoid duplication diff --git a/.claude/rules/context-management.md b/.claude/rules/context-management.md new file mode 100644 index 0000000..8382dc0 --- /dev/null +++ b/.claude/rules/context-management.md @@ -0,0 +1,59 @@ +# Context Management (ACE-FCA) + +Principles for optimal context window utilization. + +## Context Quality Equation + +Quality output = Correct context + Complete context + Minimal noise + +## Degradation Hierarchy (worst to best) + +1. **Incorrect information** - worst, causes cascading errors (garbage in, garbage out) +2. **Missing information** - leads to assumptions (agent guesses, sometimes wrong) +3. **Excessive noise** - dilutes signal, wastes capacity (truth buried but still there) + +Better to have less correct info than more info with errors. + +## Utilization Target + +Keep context at **40-60%** capacity. Leave room for: + +- Model reasoning +- Output generation +- Error recovery + +## Context Pollution Sources (What) + +These mess up context - compact/summarize immediately: + +- File searches (glob/grep results) +- Code flow traces +- Edit applications +- Test/build logs +- Large JSON blobs from tools + +## Workflow Phases + +Research → Planning → Implementation. Compact after each phase transition. + +## Compaction Triggers (When) + +Use `compacting-context` skill when: + +- Verbose tool output (logs, JSON, search results) +- After completing a phase or milestone +- Before starting new complex task + +## Subagent Usage + +Use `researching-codebase` skill to: + +- Isolate discovery artifacts from main context +- Return structured findings only +- Prevent search noise pollution + +## Output Guidelines + +- Prefer structured summaries over raw dumps +- Extract only relevant portions from large files +- Use targeted searches, not broad sweeps diff --git a/.claude/rules/core-principles.md b/.claude/rules/core-principles.md new file mode 100644 index 0000000..312ba72 --- /dev/null +++ b/.claude/rules/core-principles.md @@ -0,0 +1,64 @@ +# Core Principles + +**MANDATORY for ALL tasks.** These principles override all other guidance when +conflicts arise. + +## User-Centric Principles + +**User Experience, User Joy, User Success** - Every decision optimizes for +user value, clarity, and usability. + +## Code Quality Principles + +**KISS (Keep It Simple, Stupid)** - Simplest solution that works. Clear > clever. + +**DRY (Don't Repeat Yourself)** - Single source of truth. Reference, don't duplicate. + +**YAGNI (You Aren't Gonna Need It)** - Implement only what's requested. No +speculative features. + +## Execution Principles + +**Concise and Focused** - Minimal code/text for task. Touch only task-related code. + +**Reuse and Extend** - Use existing patterns and dependencies. Don't rebuild. + +**Prevent Incoherence** - Spot inconsistencies. Validate against existing patterns. + +**Resolve Ambiguity** - Clarify vague requirements before acting. + +## Decision Principles + +**Rigor and Sufficiency** - Research enough to decide confidently. No more, no less. + +**High-Impact Quick Wins** - Prioritize must-do tasks. Ship fast, iterate. + +**Actionable and Concrete** - Specific deliverables. Measurable outcomes. + +**Root-Cause and First-Principles** - Understand the "why". Solve root problems. + +## Before Starting Any Task + +- [ ] Does this serve user value? +- [ ] Is this the simplest approach? +- [ ] Am I duplicating existing work? +- [ ] Do I actually need this? +- [ ] Am I touching only relevant code? +- [ ] What's the root cause I'm solving? + +## Post-Task Review + +Before finishing, ask yourself: + +- **Did we forget anything?** - Check requirements thoroughly +- **High-ROI enhancements?** - Suggest opportunities (don't implement) +- **Something to delete?** - Remove obsolete/unnecessary code + +**IMPORTANT**: Do NOT alter files based on this review. Only output +suggestions to the user. + +## When in Doubt + +**STOP. Ask the user.** + +Don't assume, don't over-engineer, don't add complexity. diff --git a/.claude/rules/tdd-enforcement.md b/.claude/rules/tdd-enforcement.md new file mode 100644 index 0000000..b32f909 --- /dev/null +++ b/.claude/rules/tdd-enforcement.md @@ -0,0 +1,42 @@ +# TDD Enforcement + +Strict Red-Green-Refactor for TypeScript. Applies to all `src/` contributions except pure docs, config, and build-system changes. + +## The cycle + +### 1. RED — failing test first + +- Add or modify a test under `src/test/*.test.ts` +- Run the relevant `npm run test:*` script; confirm it **fails** for the expected reason +- Commit with `[RED] test: ` prefix if using ralph, or just `test: ` for manual work + +### 2. GREEN — minimum implementation + +- Implement the smallest change that makes the RED test pass +- Do not add extra features, abstractions, or polish in this step +- Run `make validate_quick` to keep iteration fast +- Commit with `[GREEN] feat: ` or `feat: ` + +### 3. REFACTOR — while green + +- Only after the test passes, improve structure (names, decomposition, types) +- Re-run `make validate` — must stay green the entire time +- Commit with `[REFACTOR] : ` or `refactor: : ` + +## Rules + +- **No implementation without a failing test.** Bug fixes require a regression test first. +- **No test without a concrete assertion.** Smoke tests that only call a function without asserting are insufficient. +- **One feature per cycle.** Don't batch multiple RED tests before going GREEN. +- **Validate before push.** `make validate` must pass on the branch head before `git push`. + +## Test stack + +- Framework: `node:test` (stdlib) for unit tests; `@vscode/test-electron` for integration tests via `npm run test` +- Location: `src/test/*.test.ts` mirroring the `src/` structure +- Compile: `tsc -p tsconfig.test.json` emits to `dist-test/` +- Run: `node dist-test/test/.test.js` (wired from `package.json` scripts) + +## Exceptions + +Phase 0 scaffold commits (this PR) are exempt from RED-first since they create the scaffolding itself. All subsequent work is under this rule. diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..152aa1c --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,24 @@ +{ + "attribution": { + "commit": "Co-Authored-By: Claude ", + "pr": "Generated with Claude " + }, + "enabledPlugins": { + "planning@qte77-claude-code-plugins": true, + "commit-helper@qte77-claude-code-plugins": true, + "tdd-core@qte77-claude-code-plugins": true, + "typescript-dev@qte77-claude-code-plugins": true, + "makefile-core@qte77-claude-code-plugins": true, + "docs-governance@qte77-claude-code-plugins": true, + "cc-meta@qte77-claude-code-plugins": true, + "workspace-setup@qte77-claude-code-plugins": true + }, + "extraKnownMarketplaces": { + "qte77-claude-code-plugins": { + "source": { + "source": "github", + "repo": "qte77/claude-code-plugins" + } + } + } +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..4a6907b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + - name: Install dependencies + run: npm ci + - name: Typecheck + run: npm run check-types + - name: Lint + run: npm run lint + - name: Compile + run: node esbuild.js + - name: Compile tests + run: npx tsc --project tsconfig.test.json + - name: Run unit tests + run: | + for suite in llm-service core-components read-tool write-edit-tools ls-grep-glob-tools; do + echo "::group::${suite}" + node "dist-test/test/${suite}.test.js" + echo "::endgroup::" + done diff --git a/.gitignore b/.gitignore index 4d64cca..eeb9e18 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,8 @@ node_modules .env /dist-test /.superdesign + +# CC runtime artifacts — settings.json + rules are tracked config +.claude/* +!.claude/settings.json +!.claude/rules/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9c206fe --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ralph"] + path = ralph + url = https://github.com/qte77/ralph-loop-cc-tdd-wt-vibe-kanban-template.git diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..98e619f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,34 @@ +# Agent Role Boundaries + +Team-mode agent roles for Superdesign contribution sessions. Each role has a scoped mandate; cross-role work requires explicit hand-off. + +## Architect + +- Owns: `src/types/`, `src/providers/` interfaces, ADR docs under `docs/adr/` +- Writes: type signatures, provider contracts, high-level design notes +- Does not: implement concrete providers or UI +- Hand-off: produces a tracked spec before developer implements + +## Developer + +- Owns: `src/services/`, `src/providers/` implementations, `src/test/` +- Writes: TDD-cycle code — RED test first, GREEN impl, REFACTOR +- Runs: `make validate` before every commit; no commit without green +- Does not: design new provider interfaces without architect sign-off + +## Reviewer + +- Owns: PR review comments, `make validate` regression checks, acceptance-criteria verification +- Writes: review feedback, approves/requests-changes +- Runs: `make validate` on PR branch; verifies no new `dist-test/` test failures +- Does not: write feature code in the same session + +## Shared rules + +- Respect the license split: only maintainers mark files `/* @license Enterprise */` +- No changes to existing `src/` code in Phase 0 scaffold PRs +- All three agents must follow `.claude/rules/tdd-enforcement.md` + +## Orchestration + +Ralph TDD loop drives the developer role; architect seeds the PRD; reviewer gates merge. See `ralph/docs/prd.md` once the ralph submodule is initialized. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..5d601f0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,48 @@ +# Superdesign + +Fork of `hbmartin/secure-design` (originally `superdesigndev/superdesign`) — AI design agent VS Code extension. TypeScript stack (esbuild, eslint, vscode-test, node:test). + +## License + +Upstream dual-license: **AGPLv3 + Enterprise Commercial**. See `LICENSE`. + +- Most files are AGPLv3. +- Files carrying `/* @license Enterprise */` at the top are commercially licensed and require a Super Design Enterprise subscription for production use. +- **New contributions**: default to AGPLv3. Add `// SPDX-License-Identifier: AGPL-3.0` header to new source files. Do **not** mark files Enterprise without explicit maintainer direction. + +## Development + +```bash +make validate # typecheck + lint + compile + test (full gate) +make validate_quick # typecheck + lint (fast gate for iteration) +make ralph_run ITERATIONS=5 # run ralph TDD loop +``` + +See `AGENTS.md` for agent role boundaries. + +## TDD + +Strict Red-Green-Refactor enforced per `.claude/rules/tdd-enforcement.md`. Each feature: + +1. Write/adapt a failing test in `src/test/` first +2. Implement minimum code to make it pass +3. Refactor while keeping green + +Test scripts in `package.json` (`test:llm`, `test:core`, etc.) run with `node:test` via compiled output in `dist-test/`. + +## Stack + +- **Runtime**: VS Code extension (`^1.90.0`) +- **Language**: TypeScript `^5.8.3` +- **Bundler**: esbuild +- **Tests**: node:test + vscode-test +- **AI providers**: Claude (Anthropic + Claude Code), OpenAI, OpenRouter, Google +- **UI**: React 19 webview with canvas-based design surface + +## Agents + +This fork maintains CC-native integration. Agent sessions should respect: + +- The TDD rule above +- The file-level license split (AGPL vs Enterprise) +- `AGENTS.md` role boundaries when running team mode diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f02f941 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +.PHONY: help validate validate_quick ralph_run ralph_run_worktree + +.DEFAULT_GOAL := help + +help: ## Show available recipes + @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " \033[36m%-22s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) + +validate: ## Full gate — typecheck + lint + compile + test + npm run check-types + npm run lint + npm run compile + npm run test + +validate_quick: ## Fast gate — typecheck + lint only + npm run check-types + npm run lint + +ralph_run: ## Run ralph TDD loop (override: ITERATIONS=N) + cd ralph && ./scripts/ralph.sh $(ITERATIONS) + +ralph_run_worktree: ## Run ralph in worktree (override: BRANCH=name) + cd ralph && ./scripts/ralph-in-worktree.sh $(BRANCH) diff --git a/config/compound.env b/config/compound.env new file mode 100644 index 0000000..8b382c4 --- /dev/null +++ b/config/compound.env @@ -0,0 +1,7 @@ +RALPH_DEFAULT_MODEL=opus +RALPH_SIMPLE_MODEL=sonnet +RALPH_FIX_MODEL=sonnet +RALPH_MAX_ITERATIONS=25 +RALPH_MAX_FIX_ATTEMPTS=3 +RALPH_VALIDATION_TIMEOUT=120 +RALPH_WORKTREE_SYMLINKS="node_modules" diff --git a/ralph b/ralph new file mode 160000 index 0000000..79f018f --- /dev/null +++ b/ralph @@ -0,0 +1 @@ +Subproject commit 79f018f3ed8e01a688cf1cd4c686e5f14b7ca038 diff --git a/src/test/core-components.test.ts b/src/test/core-components.test.ts new file mode 100644 index 0000000..af75688 --- /dev/null +++ b/src/test/core-components.test.ts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: AGPL-3.0 +import { test } from 'node:test'; +import assert from 'node:assert'; + +test('core-components: placeholder passes', () => { + // TODO(Phase 1): test webview panel lifecycle, command registration, message bus + assert.ok(true); +}); diff --git a/src/test/llm-service.test.ts b/src/test/llm-service.test.ts new file mode 100644 index 0000000..8fa5e5e --- /dev/null +++ b/src/test/llm-service.test.ts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: AGPL-3.0 +import { test } from 'node:test'; +import assert from 'node:assert'; + +test('llm-service: placeholder passes', () => { + // TODO(Phase 1): test provider selection, API key resolution, streaming + assert.ok(true); +}); diff --git a/src/test/ls-grep-glob-tools.test.ts b/src/test/ls-grep-glob-tools.test.ts new file mode 100644 index 0000000..caede21 --- /dev/null +++ b/src/test/ls-grep-glob-tools.test.ts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: AGPL-3.0 +import { test } from 'node:test'; +import assert from 'node:assert'; + +test('ls-grep-glob-tools: placeholder passes', () => { + // TODO(Phase 1): test directory listing, grep semantics, glob expansion + assert.ok(true); +}); diff --git a/src/test/read-tool.test.ts b/src/test/read-tool.test.ts new file mode 100644 index 0000000..b109fa9 --- /dev/null +++ b/src/test/read-tool.test.ts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: AGPL-3.0 +import { test } from 'node:test'; +import assert from 'node:assert'; + +test('read-tool: placeholder passes', () => { + // TODO(Phase 1): test file read boundaries, encoding detection, binary handling + assert.ok(true); +}); diff --git a/src/test/write-edit-tools.test.ts b/src/test/write-edit-tools.test.ts new file mode 100644 index 0000000..66e1b4a --- /dev/null +++ b/src/test/write-edit-tools.test.ts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: AGPL-3.0 +import { test } from 'node:test'; +import assert from 'node:assert'; + +test('write-edit-tools: placeholder passes', () => { + // TODO(Phase 1): test atomic writes, diff application, line-preserving edits + assert.ok(true); +});