diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index becb16f..1d485bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,8 +1,17 @@ name: Release +# Manual, no script. Cut a release by running this workflow with a version: +# • GitHub UI: Actions → Release → "Run workflow" → enter version (e.g. 0.4.0) +# • CLI: gh workflow run release.yml -f version=0.4.0 +# It bumps the version in both manifests on main, commits, tags +# devline--v (matching `claude plugin tag`), and creates the GitHub Release. on: - push: - tags: ["v*"] + workflow_dispatch: + inputs: + version: + description: "Version to release, e.g. 0.4.0" + required: true + type: string permissions: contents: write @@ -13,25 +22,43 @@ jobs: steps: - uses: actions/checkout@v4 with: + ref: main fetch-depth: 0 - - name: Generate changelog - id: changelog + - name: Bump, tag, and release + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ inputs.version }} run: | - PREV_TAG=$(git tag --sort=-v:refname | sed -n '2p') - if [ -n "$PREV_TAG" ]; then - LOG=$(git log "$PREV_TAG"..HEAD --pretty=format:"- %s (%h)" --no-merges) + echo "$VERSION" | grep -qP '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$' \ + || { echo "::error::'$VERSION' is not semver (e.g. 0.4.0)"; exit 1; } + tag="devline--v$VERSION" + if git rev-parse "refs/tags/$tag" >/dev/null 2>&1; then + echo "::error::$tag already exists"; exit 1 + fi + + # Bump the version in both manifests (keeping them in agreement). + for f in .claude-plugin/plugin.json .claude-plugin/marketplace.json; do + jq --arg v "$VERSION" ' + (if .version then .version = $v else . end) + | (if .plugins then .plugins |= map(if .version then .version = $v else . end) else . end) + ' "$f" > "$f.tmp" && mv "$f.tmp" "$f" + done + + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add .claude-plugin/plugin.json .claude-plugin/marketplace.json + git commit -m "chore: release v$VERSION" + git push origin HEAD:main + + # Changelog since the previous release tag. + prev=$(git tag --list 'devline--v*' --sort=-version:refname | head -1) + if [ -n "$prev" ]; then + notes=$(git log "$prev..HEAD" --pretty=format:'- %s (%h)' --no-merges) else - LOG=$(git log --pretty=format:"- %s (%h)" --no-merges) + notes=$(git log --pretty=format:'- %s (%h)' --no-merges) fi - { - echo "body<> "$GITHUB_OUTPUT" - - - name: Create GitHub release - uses: softprops/action-gh-release@v2 - with: - body: ${{ steps.changelog.outputs.body }} - generate_release_notes: false + + git tag "$tag" + git push origin "$tag" + printf '%s\n' "$notes" | gh release create "$tag" --title "$tag" --notes-file - diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 953a590..5d03247 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -15,7 +15,7 @@ jobs: - name: Check hook scripts are executable run: | failed=0 - for f in hooks/scripts/*.sh skills/*/scripts/*.sh; do + for f in hooks/scripts/*.sh skills/*/scripts/*.sh install.sh; do [ -f "$f" ] || continue if [ ! -x "$f" ]; then echo "::error file=$f::Not executable" @@ -28,6 +28,7 @@ jobs: run: | sudo apt-get install -y shellcheck find hooks/scripts skills/*/scripts -name '*.sh' -print0 | xargs -0 shellcheck + shellcheck install.sh - name: Validate JSON run: | diff --git a/README.md b/README.md index 00355fe..03cc772 100644 --- a/README.md +++ b/README.md @@ -50,16 +50,25 @@ Every finding from every review gets fixed. There's no "pass with warnings." If ## Install +### Quick install + +```bash +curl -fsSL https://raw.githubusercontent.com/Conava/claude-devline/main/install.sh | bash +``` + +Installs Claude Code (if missing), the devline plugin, and the recommended companions (RTK, Ponytail, Basic Memory). Works on **Linux** (apt/pacman/dnf/zypper/apk), **macOS** (Homebrew), and **Windows via WSL or Git Bash** — it prompts before installing any missing underlying tool. Review the script first if you like. Flags: `--minimal` (devline only), `--skip-rtk`/`--skip-ponytail`/`--skip-memory`, `--yes` (non-interactive). Example: `curl -fsSL https://raw.githubusercontent.com/Conava/claude-devline/main/install.sh | bash -s -- --minimal`. + ### From the marketplace ```bash -claude plugin add devline +claude plugin marketplace add Conava/claude-devline +claude plugin install devline@devline ``` ### From source ```bash -git clone https://github.com/devline-io/claude-devline.git +git clone https://github.com/Conava/claude-devline.git claude --plugin-dir ./claude-devline ``` @@ -75,7 +84,7 @@ Then run `/devline:setup` in your project. It creates a `CLAUDE.md` (project con Devline is built for `--dangerously-skip-permissions` mode. Agents need to read files, write code, and run builds without prompting on every tool call. -Safety comes from hooks, not permission dialogs. The plugin ships 85+ security rules that block destructive operations before they execute. Force pushes, `rm -rf` outside the working dir, credential exposure, publishing commands, database destructive operations -- all blocked. See [Security Hooks](#security-hooks). +Safety comes from hooks, not permission dialogs. The plugin ships ~19 focused security rules that block irreversible or destructive operations before they execute. Force pushes, `rm -rf` outside the working dir, credential exposure, publishing commands, database destructive operations -- all blocked. See [Security Hooks](#security-hooks). ```bash claude --dangerously-skip-permissions @@ -85,6 +94,28 @@ It works without bypass mode too. You'll just get prompted frequently during par --- +## Recommended companions + +Optional, but they make devline leaner and more capable — `/devline:setup` offers to install all three. The [quick installer](#quick-install) sets up all three automatically, and wires Basic Memory through a per-session MCP wrapper so parallel Claude sessions each bind to their own repo's `memory/` project (multi-session-safe). + +- **[RTK](https://github.com/rtk-ai/rtk)** — a CLI proxy that filters command-output noise for 60-90% token savings. devline runs many parallel agents issuing Bash commands, so it compounds. + ```bash + curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh + rtk init -g + ``` +- **[Basic Memory](https://github.com/basicmachines-co/basic-memory)** — local-first, per-project memory stored as plain Markdown you commit to the repo, retrieved on demand so it never bloats context. Persistent cross-session recall in any Claude Code session, not just devline. + ```bash + uv tool install basic-memory + claude mcp add basic-memory -- uvx basic-memory mcp + ``` +- **[Ponytail](https://github.com/DietrichGebert/ponytail)** — a separate Claude Code plugin that keeps generated code minimal (YAGNI, stdlib-first, shortest working diff). It composes with devline: devline enforces the process, ponytail keeps the code it produces lean. + ``` + /plugin marketplace add DietrichGebert/ponytail + /plugin install ponytail@ponytail + ``` + +--- + ## Commands | Command | What it does | @@ -93,11 +124,11 @@ It works without bypass mode too. You'll just get prompted frequently during par | `/devline:brainstorm ` | Refine an idea into a feature spec | | `/devline:plan ` | Create a TDD implementation plan | | `/devline:implement` | Implement tasks from an existing plan | +| `/devline:quick ` | Fast lane -- implement, review, and commit a small change | | `/devline:review` | Code review of recent changes | | `/devline:debug ` | Systematic root cause analysis | -| `/devline:deep-review` | Final merge-readiness audit | -| `/devline:cve-patcher ` | Patch vulnerabilities across repos | -| `/devline:migrate ` | Major version migrations with breaking changes | +| `/devline:deep-review` | Final merge-readiness audit (runs the reviewer at `scope: branch`) | +| `/devline:deps [--migrate] ` | Patch CVEs, or migrate a major version with `--migrate` | | `/devline:design` | Standalone component or theme design | | `/writing` | Write, edit, or translate text — anti-AI-pattern rewriting for general text; citation contract enforcement for scientific writing | | `/brand` | Brand voice, visual identity, messaging | @@ -241,7 +272,7 @@ Cross-cutting review that catches what per-task reviewers can't see: The deep review can't defer findings. Every issue must be fixed. The escalation ladder: implementer fixes -> debugger investigates root cause -> planner redesigns approach -> ask user for guidance. -Only a structured APPROVED verdict from the deep-review agent moves the pipeline forward. Partial output, timeouts, or ambiguous responses trigger a relaunch. +Only a structured APPROVED verdict from the reviewer (`scope: branch`, running on Opus) moves the pipeline forward. Partial output, timeouts, or ambiguous responses trigger a relaunch. @@ -249,32 +280,29 @@ Only a structured APPROVED verdict from the deep-review agent moves the pipeline ## Agents -Ten specialized agents, each with a defined role and model assignment. +Seven specialized agents, each with a defined role and model assignment. ```mermaid %%{init: {'theme': 'neutral'}}%% flowchart TB subgraph opus["Opus — complex reasoning"] planner["Planner\nArchitecture, TDD task design"] - deepreview["Deep Review\nFinal gate, cross-task audit"] debugger["Debugger\nScientific root cause analysis"] - migrator["Dep. Migrator\nBreaking change migrations"] end subgraph sonnet["Sonnet — fast execution"] - implementer["Implementer\nTDD implementation"] - reviewer["Reviewer\nCorrectness, security, perf"] + implementer["Implementer\nTDD impl, build/CI/Docker/IaC"] + reviewer["Reviewer\nPer-task + scope:branch deep review"] frontend["Frontend Planner\nDesign system, HTML previews"] - devops["DevOps\nCI/CD, Docker, infra"] docskeeper["Docs Keeper\nREADME, docs/ sweep"] - patcher["Dep. Patcher\nCVE patches, version bumps"] + dependency["Dependency\nCVE patches + migrations"] end classDef opusNode fill:#fce7f3,stroke:#db2777,color:#831843 classDef sonnetNode fill:#dbeafe,stroke:#2563eb,color:#1e3a5f - class planner,deepreview,debugger,migrator opusNode - class implementer,reviewer,frontend,devops,docskeeper,patcher sonnetNode + class planner,debugger opusNode + class implementer,reviewer,frontend,docskeeper,dependency sonnetNode ```
@@ -283,15 +311,12 @@ flowchart TB | Agent | Model | What it does | |-------|-------|-------------| | **Planner** | Opus | Traces execution paths, maps blast radius, designs dependency-ordered tasks with test cases and acceptance criteria. Returns NEEDS_INPUT for ambiguous decisions instead of guessing. | -| **Implementer** | Sonnet | One task, one agent, strict TDD. Runs in a git worktree. Validates spec against actual codebase before writing code. Commits only specific files -- never `git add .` | -| **Reviewer** | Sonnet | 10-layer review: correctness, spec compliance, integration contracts, security (OWASP + multi-tenant), performance (N+1, blocking ops), code quality, plan compliance, test assertion quality, stale artifacts, mandatory test run. | -| **Deep Review** | Opus | Builds and tests first (any failure = HAS_FINDINGS). Then: security audit, architecture review, regression check, feature-goal trace, cross-task integration sweep, stale artifact detection, test quality, plan compliance, operational readiness. | +| **Implementer** | Sonnet | One task, one agent, strict TDD. Runs in a git worktree. Also handles build systems, CI/CD, Docker, and infrastructure-as-code tasks. Validates spec against actual codebase before writing code. Commits only specific files -- never `git add .` | +| **Reviewer** | Sonnet (Opus for `scope: branch`) | Per-task review (`scope: task`): correctness, spec compliance, integration contracts, security (OWASP + multi-tenant), performance, code quality, plan compliance, test assertion quality, stale artifacts, mandatory test run. As the final gate (`scope: branch`, Opus) it builds and tests first (any failure = HAS_FINDINGS), then runs the cross-task integration sweep, feature-goal trace, regression check, and branch-level architecture review. | | **Debugger** | Opus | Six-phase scientific method: check known patterns, reproduce, gather evidence, hypothesize (2-3 ranked), test hypotheses, verify and prevent. Can operate standalone or as a pipeline planner for failed review loops. | | **Frontend Planner** | Sonnet | Six modes: pipeline (brainstorm-to-design-system), showcase (N HTML variations), component (single piece), extend (add to system), harmonize (match project theme), brand (persistent identity). Searches curated CSV database with BM25, not LLM generation. | -| **DevOps** | Sonnet | Build systems, CI/CD pipelines, Docker, infrastructure as code, dev environment. TDD approach where applicable -- writes validation scripts before infra changes. | | **Docs Keeper** | Sonnet | Proactive documentation sweep. Reads `git diff` and plan, scans ALL docs for staleness, completeness, and formatting issues. Checks internal links, code examples, and renamed references. | -| **Dep. Patcher** | Sonnet | Simple version bumps for CVE patches. Detects ecosystem (npm, Maven, Gradle, pip, cargo, etc.), checks if package is affected, updates, verifies build/tests, commits. | -| **Dep. Migrator** | Opus | Complex migrations with breaking changes. Researches migration guides, runs ecosystem tools (OpenRewrite, Rector, codemods), refactors code, verifies everything compiles and passes. | +| **Dependency** | Sonnet (Opus for migrations) | Both CVE/version patches and major-version migrations. Detects ecosystem (npm, Maven, Gradle, pip, cargo, etc.), checks if the package is affected, updates, verifies build/tests, commits. For migrations (opus, migration block on) it researches guides, runs ecosystem tools (OpenRewrite, Rector, codemods), and refactors breaking changes. |
@@ -309,15 +334,12 @@ claude-devline/ | |-- agents/ # Agent definitions (one .md per agent) | |-- planner.md -| |-- implementer.md -| |-- reviewer.md -| |-- deep-review.md +| |-- implementer.md # also handles build/CI/Docker/IaC tasks +| |-- reviewer.md # per-task review + scope:branch deep review | |-- debugger.md | |-- frontend-planner.md -| |-- devops.md | |-- docs-keeper.md -| |-- dependency-patcher.md -| |-- dependency-migrator.md +| |-- dependency.md # CVE patches + major-version migrations | +-- references/ # Shared agent templates | |-- plan-format.md | +-- frontend-output-templates.md @@ -335,9 +357,8 @@ claude-devline/ +-- hooks/ # Security rules (PreToolUse, PreCompact, SubagentStop) |-- hooks.json +-- scripts/ - |-- validate-bash.sh # 85+ bash command security rules + |-- validate-bash.sh # ~19 bash command security rules |-- validate-write.sh # Credential and secret detection - |-- enforce-branch.sh # Protected branch enforcement |-- pre-compact.sh # Pipeline state preservation +-- subagent-stop.sh # Agent completion logging ``` @@ -349,18 +370,12 @@ Agents don't start from scratch. Knowledge bases (the `kb-*` skills) get injecte | Knowledge Base | Injected Into | What It Provides | |----------------|---------------|-----------------| -| `kb-tdd-workflow` | Implementer, DevOps, Debugger | Test level selection (unit vs integration vs E2E), Red-Green-Refactor cycle, framework detection, what NOT to test | -| `kb-blast-radius` | Planner, Reviewer, Deep Review | Reverse dependency tracing -- "if I change file X, what breaks?" Grep-based import analysis across 12 languages | +| `kb-tdd-workflow` | Implementer, Debugger | Test level selection (unit vs integration vs E2E), Red-Green-Refactor cycle, framework detection, what NOT to test | +| `kb-blast-radius` | Planner, Reviewer | Reverse dependency tracing -- "if I change file X, what breaks?" Grep-based import analysis across 12 languages | | `kb-design` | Frontend Planner | 67 styles, 161 palettes, 57 fonts, 160 animations, 161 industry rules, token architecture, accessibility priorities | -| `kb-debugging` | Debugger | Bug pattern recognition, language-specific debugging tools, common error catalogs | -| `kb-cloud-infra` | DevOps | Provider detection, container best practices, IaC principles, CI/CD pipeline patterns | -| `kb-documentation` | Docs Keeper | README standards, API doc structure, architecture doc templates, Diataxis framework | -| `kb-dependency-management` | Dep. Patcher | Ecosystem detection for 10+ package managers, version update mechanics, verification commands | -| `kb-dependency-migration` | Dep. Migrator | Three-phase migration process: research, execute (with tooling), verify | +| `kb-dependency-management` | Dependency | Ecosystem detection for 10+ package managers, version update mechanics, verification commands | | `find-docs` | All agents | Context7 integration for live library documentation lookup | -Agents also read `CLAUDE.md` in your project root for lessons learned from previous pipeline runs. The pipeline gets smarter over time. - --- @@ -447,47 +462,33 @@ When the orchestrator loses context (compaction, new conversation, crash), it re --- -## Lessons System - -Agents discover non-obvious codebase patterns during implementation, review, and debugging. These get appended to `CLAUDE.md` in your project root: - -``` -**Pattern**: [what triggers it] | **Reason**: [why] | **Solution**: [how to prevent it] -``` - -The planner reads lessons before designing the plan. The reviewer and debugger read them at task start. Past mistakes inform future runs -- the pipeline learns from itself. - ---- - ## Security Hooks The plugin ships PreToolUse hooks that validate every Bash command, file write, and branch operation before execution.
-What's blocked (85+ rules) +What's blocked (~19 rules) + +The hooks stop irreversible or destructive actions and credential exposure -- not workflow policy. (Protected-branch pushes, commit-message format, tags/releases, and squash-merge enforcement were removed on the scrub branch.) | Category | Examples | |----------|---------| -| **Destructive filesystem** | `rm -rf /`, paths outside working dir, non-git directories, wildcards | -| **Git destructive** | Force push, hard reset, force clean, stash drop/clear | -| **Protected branches** | Push, rebase, delete, force create on main/master/develop/release/production/staging | -| **Publishing** | `npm publish`, `cargo publish`, `docker push`, `git tag`, `gh release create`, `twine upload` | +| **Destructive filesystem** | `rm -rf` on system paths, outside the working dir, in non-git directories, or with wildcards; `mkfs`/`fdisk`/`dd` to devices | +| **Git history** | Force push (`--force`, `-f`, `--force-with-lease`) | +| **Publishing & releases** | `npm publish`, `cargo publish`, `mvn deploy`, `gradle publish`, `twine upload`, `gem push`, `dotnet nuget push`; `docker`/`podman`/`buildah push` | | **GitHub mutations** | `gh pr merge/close/reopen`, `gh issue close/delete/comment` | -| **Database** | `DROP TABLE/DATABASE/SCHEMA`, `TRUNCATE`, bulk `DELETE FROM` | -| **Credentials** | AWS keys (AKIA pattern), private keys, JWTs, GitHub/GitLab tokens, hardcoded passwords, `.env` secrets | -| **External mutations** | HTTP POST/PUT/DELETE to non-localhost, SSH/SCP to remote hosts, service control | -| **System files** | Writing to /etc, /sys, /proc, shell profiles, SSH config | -| **Commit format** | Conventional commits validation (customizable regex) | -| **Pipeline artifacts** | Blocks `git add .devline/` to prevent committing pipeline state | +| **Database** | `DROP TABLE/DATABASE/SCHEMA/INDEX/VIEW`, `TRUNCATE`, bulk `DELETE FROM` | +| **Credentials** | AWS keys (AKIA), private keys, JWTs, GitHub/GitLab tokens, hardcoded passwords/API keys in file content; printing secret env vars; sending secrets to external URLs | +| **External mutations** | HTTP POST/PUT/DELETE/PATCH to non-localhost (asks first), remote SSH/SCP (asks first), `systemctl`/`service` start/stop/restart | +| **Process & system** | `kill -9 1`, `chmod 777`, modifying SSH `authorized_keys`, piping `curl`/`wget` into a shell (asks first), `;rm`/backtick-rm injection |
Smart exemptions -- **Test files** skip credential detection. Test code legitimately contains fake API keys and tokens. Detected by path patterns: `/test/`, `/__tests__/`, `.test.`, `.spec.`, `/fixtures/`, `/testdata/`. -- **Documentation and config** can be edited directly on protected branches. Markdown, JSON, YAML, Dockerfiles, Makefiles -- these don't need a feature branch for a typo fix. -- **Merge style** is configurable. The hook enforces whatever merge strategy you've configured (squash, merge, or rebase) when merging into protected branches. +- **Test files** skip credential detection. Test code legitimately contains fake API keys and tokens. Detected by path patterns: `/test/`, `/tests/`, `/__tests__/`, `.test.`, `.spec.`, `/fixtures/`, `/testdata/`. +- **Common placeholder passwords** (`test`, `example`, `placeholder`, `changeme`, `dummy`, ...) are allowed, so examples and docs don't trip the secret scanner.
@@ -574,51 +575,39 @@ auto_approve_plan: true --- ``` -**Jira ticket conventions:** +**Jira branch naming:** ```yaml --- branch_format: "PROJ-{ticket}/{title}" branch_kinds: "PROJ" -commit_format: "PROJ-123: description" -commit_format_regex: "^[A-Z]+-[0-9]+: .+" --- ``` -**Emoji commits:** +**Always take the fast lane for small changes:** ```yaml --- -commit_format: "emoji description" -commit_format_regex: "^(✨|🐛|♻️|📝|🔧|✅|🔨|🚀|⬆️|⏪) .+" +fast_lane: always --- ```
All settings -#### Approval gates +#### Pipeline gates | Setting | Default | Description | |---------|---------|-------------| | `auto_approve_brainstorm` | `false` | Skip approval after brainstorming | | `auto_approve_plan` | `false` | Skip approval after planning | +| `fast_lane` | `auto` | Fast-lane small changes to implement -> review -> commit. `auto` = detect, `always` = force, `off` = always run the full pipeline | #### Branching strategy | Setting | Default | Description | |---------|---------|-------------| -| `enforce_feature_branches` | `false` | Block source edits on protected branches | | `branch_format` | `"{kind}/{title}"` | Branch naming (`{kind}`, `{title}` placeholders) | | `branch_kinds` | `"feat\|fix\|refactor\|docs\|chore\|test\|ci"` | Allowed branch kinds | -| `protected_branches` | `"(main\|master\|develop\|release\|production\|staging)"` | Protected branches regex | -| `merge_style` | `"squash"` | How to merge into protected: `squash`, `merge`, `rebase` | - -#### Commit conventions - -| Setting | Default | Description | -|---------|---------|-------------| -| `commit_format` | `"kind(scope): details"` | Human-readable format shown in errors | -| `commit_format_regex` | conventional commits | Regex for validation | -| `direct_edit_extensions` | `"(md\|txt\|json\|yaml\|...)"` | Extensions editable directly on protected branches | +| `protected_branches` | `"(main\|master\|develop\|release\|production\|staging)"` | Branches the pipeline auto-creates a feature branch off of | #### Framework overrides @@ -639,7 +628,7 @@ commit_format_regex: "^(✨|🐛|♻️|📝|🔧|✅|🔨|🚀|⬆️|⏪) .+" | `dep_verify_build` | `true` | Run build check | | `dep_verify_tests` | `true` | Run test suite | -CVE patcher uses `cve_` prefix, migration uses `migrate_` prefix (same keys, independent overrides). +The `deps` skill (patch mode) also honors `cve_`-prefixed overrides (e.g. `cve_verify_build`), which take priority over the generic `dep_` keys. Migrate mode always runs build and test verification (not configurable).
@@ -673,10 +662,10 @@ The debugger reproduces the issue, gathers evidence (logs, stack traces, git bla Patch CVEs across repos ``` -/devline:cve-patcher CVE-2024-38816 CVE-2024-38819 --repos api-service web-frontend +/devline:deps CVE-2024-38816 CVE-2024-38819 --repos api-service web-frontend ``` -Researches each CVE (affected package, versions, fix version, severity), then launches parallel patcher agents per repository. Each agent detects the ecosystem, checks if the dependency is present and affected, bumps the version, verifies build and tests pass, and commits. +Researches each CVE (affected package, versions, fix version, severity), then launches parallel dependency agents per repository. Each agent detects the ecosystem, checks if the dependency is present and affected, bumps the version, verifies build and tests pass, and commits. @@ -684,7 +673,7 @@ Researches each CVE (affected package, versions, fix version, severity), then la Migrate a major version ``` -/devline:migrate spring-boot from 2.7 to 3.2 +/devline:deps --migrate spring-boot from 2.7 to 3.2 ``` Researches the official migration guide, finds available tooling (OpenRewrite recipes for Spring Boot), compiles a breaking-changes checklist (javax to jakarta namespace, security config changes), runs the migration tool, handles remaining manual changes, and verifies everything compiles and tests pass. @@ -722,12 +711,7 @@ Scans the text against 60+ known AI writing patterns (negative parallelism, tric - **`/compact` at ~70% context.** The PreCompact hook preserves pipeline state automatically. Pass focus instructions: `/compact Focus on the API changes`. - **Use `/devline:implement` for well-defined tasks.** Skip brainstorming when you already know exactly what to build. - **Use `/devline:debug` instead of manual debugging.** The scientific method catches root causes faster than reading code and guessing. -- **Install [RTK](https://github.com/rtk-ai/rtk) for 60-90% token savings.** A CLI proxy that filters noise from command output. Run `/devline:setup` to install, or: - -```bash -curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh -rtk init -g -``` +- **Install the [recommended companions](#recommended-companions).** RTK, Basic Memory, and Ponytail — `/devline:setup` offers all three. --- diff --git a/agents/debugger.md b/agents/debugger.md index 63bc484..bec7c94 100644 --- a/agents/debugger.md +++ b/agents/debugger.md @@ -4,15 +4,14 @@ description: "Use this agent for bugs, test failures, or unexpected behavior. Fo tools: Read, Write, Edit, Bash, Grep, Glob, Skill, ToolSearch model: opus -skills: kb-debugging, find-docs +skills: find-docs --- You are a senior software engineer specializing in systematic debugging. You follow the scientific method — reproduce, gather evidence, form hypotheses, and confirm them before making changes. -## Scientific Debugging Process +For bug-pattern recognition (null/race/deadlock/leak/serialization catalogs) and language-specific debugging tools, consult `references/debugging.md`. -### Phase 0: Check Known Patterns -- **Read `CLAUDE.md`** — check the `## Lessons and Memory` section for known codebase patterns from previous pipeline runs. A past agent may have already documented the exact pattern causing this bug. If a lesson matches the symptoms, use it to skip directly to a targeted hypothesis. +## Scientific Debugging Process ### Phase 1: Reproduce - Get the exact error message, stack trace, or symptom description diff --git a/agents/deep-review.md b/agents/deep-review.md deleted file mode 100644 index 9e1c2cf..0000000 --- a/agents/deep-review.md +++ /dev/null @@ -1,234 +0,0 @@ ---- -name: deep-review -description: "Final quality gate. Comprehensive review covering security, credentials, code quality, tech debt, conventions, plan compliance, and architecture. Runs on any completed implementation.\n\n\nContext: All tasks implemented and reviewed\nuser: \"Everything is reviewed, do the final deep review\"\nassistant: \"I'll use the deep-review agent for the final quality review.\"\n\n" -tools: Read, Grep, Glob, Bash -model: opus -color: red -skills: kb-blast-radius, find-docs ---- - -You are a senior staff engineer performing the final quality gate before merge. You are a read-only reviewer — every task was already tested by its implementer and verified by its per-task reviewer. Your job is to catch what they **cannot** see: cross-task integration failures, regressions in existing functionality, broken end-to-end feature flows, and security issues that only emerge when all tasks are combined. Do not re-review what per-task reviewers already checked (individual code quality, naming, single-file correctness) — focus on the whole-branch picture. - -**Non-negotiable gate:** Run the build and tests. If anything fails to compile or any test fails, the verdict is **HAS_MAJOR_FINDINGS** — no exceptions, no "pre-existing" excuses, no "unrelated" dismissals. The branch must be green to merge. - -**Three most important checks:** -1. **Build & test gate** — run the project's compile and test commands. Any failure = major finding. -2. **Regression check** — read test files and test reports (e.g. `build/reports/tests/`). Look for weakened assertions, behavioral changes, and gaps in coverage. -3. **Feature goal verification** — trace the feature from trigger to result end-to-end. Green unit tests mean nothing if the feature doesn't actually work. - -## Review Process - -Work through every section. Skip sections that genuinely don't apply, but err on the side of reviewing. - -### 0. Build & Test Gate (MANDATORY — run first) - -Run the project's compile and full test suite. This is not optional. - -```bash -# Adapt to the project's build system (Gradle, Maven, npm, cargo, etc.) -./gradlew build 2>&1 | tail -80 -``` - -- **Any compilation error** = major finding. Report every `e:` error line. -- **Any test failure** = major finding. Report failing test names and assertion messages. -- **Do not dismiss failures as "pre-existing" or "unrelated."** If it fails on this branch, it's this branch's problem. -- If the build succeeds, note it and proceed. If it fails, continue the review (to catch all issues in one pass) but the verdict MUST be HAS_MAJOR_FINDINGS. - -### 1. Security Audit - -Examine all changed files for vulnerabilities: - -**Secrets & Credentials:** -- Hardcoded API keys, tokens, passwords, connection strings in source -- Secrets in test fixtures, mock data, or comments -- `.env` files committed or missing from `.gitignore` -- Private keys, certificates, JWTs in source - -**Injection:** -- SQL/NoSQL injection — string concatenation in queries instead of parameterized queries -- Command injection — user input in shell commands, `exec`, `eval` -- Path traversal — user-controlled file paths without sanitization -- XSS — unescaped user input rendered in HTML, templates, or JSX -- Template injection — user input in server-side templates - -**Authentication & Authorization:** -- Missing auth checks on protected routes or endpoints -- Broken access control — can user A access user B's data? -- Token handling — stored securely? Proper expiry and revocation? -- Missing or misconfigured CSRF protection on state-changing operations -- Privilege escalation paths - -**Data Exposure:** -- Error messages leaking internal details (stack traces, SQL errors, file paths) -- Sensitive data in logs (passwords, tokens, PII) -- Overly permissive CORS configuration -- Missing security headers (CSP, X-Frame-Options, HSTS, X-Content-Type-Options) -- API responses returning more data than the client needs - -**Dependencies:** -- Run the project's dependency audit tool (`npm audit`, `pip-audit`, `cargo audit`, etc.) if applicable -- Known CVEs in added or updated dependencies -- Unpinned dependency versions that could drift - -### 2. Architecture & Cross-Cutting Concerns - -Per-task reviewers already checked individual code quality — don't re-review single-file correctness, naming, or style. Focus on what only emerges at branch level: - -- Does the overall architecture match the plan's design decisions? -- Are there new coupling points between tasks that will make future changes harder? -- Is state management consistent across tasks? (e.g., one task caches, another doesn't) -- Code duplication **across tasks** (same pattern reimplemented in two tasks that could share a utility) -- Race conditions or ordering issues that only emerge when tasks interact - -### 3. Regression Check - -Read test files and test reports — check `build/reports/tests/`, `test-results/`, or equivalent for the latest results: -- Tests modified to make them pass (check git diff — did an implementer weaken an assertion?) -- Behavioral changes in existing functionality without test coverage -- Side effects: did changes to shared modules break unrelated features? - -Regressions are **major/critical** findings. A feature that breaks existing functionality is not merge-ready. - -### 4. Feature Goal Verification - -**Most important section.** For each goal: -- **Trace the execution path** from user action to expected result. Read the actual code — follow the call chain through every handler, observer, callback, and state update. -- **Verify the chain is connected.** If component A should notify component B, confirm the notification actually fires and B handles it. -- **Run integration/E2E tests** if they exist. If they should exist but don't, flag as major. -- **Check the feature-goal tests** from the plan. Were they implemented? Do they test what they claim? - -If a feature goal is not verifiably working end-to-end, this is a **major/critical** finding — even if all unit tests pass. - -### 5. Cross-Task Integration Sweep - -This catches the #1 class of bugs per-task reviewers miss — integration contracts spanning task boundaries where each side passes review in isolation but the connection is broken. - -Read the task specs in the plan file (`.devline/plan.md` or `.devline/plan-phase-*.md`) for integration points and interface contracts across tasks. For each: -1. **Trace both sides.** If Task A creates an event type and Task B should dispatch it, verify Task B's code contains the dispatch call. -2. **Search for orphaned declarations.** `grep` for event types, interface methods, webhook event names, and enum values declared but never referenced from another file. -3. **Verify listener/handler registration.** If Task A creates a listener and Task B should trigger it, confirm the registration exists and the trigger fires. - -Broken cross-task connections are **major/critical** findings. - -### 6. Stale Artifact, Unused Code & Duplicate Detection - -**Unused imports:** For every changed file, check that all imports are used. Grep for each imported name in the file — if it only appears in the import statement, it's unused. This is a minor finding per file, but flag every instance. - -**Stale references in comments/docs:** After refactoring (renames, moves, deletions), search for the old class/method/field names across the codebase. Comments, Javadoc `@link`/`@see` tags, and string literals referencing renamed or deleted symbols are common — these cause "cannot resolve symbol" in IDEs. Check: -```bash -# For each renamed/deleted class, search for stale references -grep -rn "OldClassName" --include="*.kt" --include="*.java" src/ -``` - -**Duplicate code:** Look for near-identical code blocks across the changeset — copy-pasted methods, repeated query patterns, duplicated validation logic. Consolidation opportunities are minor findings. - -**Stale code:** Methods, classes, or fields that were part of the old implementation but are no longer called after the refactor. Grep for the method/class name — if it's only defined but never referenced, flag it. - -**Duplicate class/component declarations:** Search for classes defined in multiple files. - -**Scaffold/placeholder files:** Check for generic placeholder files that should have been replaced. - -### 7. Test Quality - -Read test files — check that they're meaningful: -- **Weak assertion audit:** `.not.toBeNull()`, `.toBeDefined()`, `.toContain()` where specific value checks are warranted -- **Mock-vs-reality check:** Synchronous mocks of deferred operations (repository.save() vs saveAndFlush(), async dispatch mocked as sync) -- **Security test completeness:** Auth-protected endpoints need tests for BOTH permitted success AND forbidden rejection -- Edge cases covered (empty, null, boundary, error paths) -- Integration points tested with real dependencies where it matters -- Descriptive test naming - -### 8. Plan Compliance - -Read `.devline/plan.md`: -- Every acceptance criterion — implemented AND tested -- No scope creep -- Nothing skipped or partially implemented -- Standalone improvement tasks completed -- Architecture matches plan's design decisions - -### 9. Operational Readiness - -- Error handling produces useful debugging information -- Logging present but not excessive — no sensitive data logged -- Configuration externalized -- Inline docs present for complex or non-obvious logic - -## Confidence-Based Filtering - -- **Report** if >80% confident it is a real issue -- Skip stylistic preferences unless they violate project conventions -- Skip issues in unchanged code unless they are security vulnerabilities -- Consolidate similar issues ("5 endpoints missing input validation" not 5 separate findings) -- Prioritize issues that could cause bugs, security vulnerabilities, or data loss - -## Output Format - -Every finding classified as **minor** or **major/critical**: -- **Minor**: style, small quality issues, minor tech debt, documentation gaps -- **Major/critical**: security vulnerabilities, correctness bugs, regressions, unmet feature goals, broken end-to-end functionality, build/test failures - -**No deferral.** The deep review is the final quality gate. Every finding — minor or major — must be fixed before the branch can merge. Do not mark anything as "can be addressed later" or "nice to have." If it's worth reporting, it's worth fixing. - -```markdown -## Deep Review: [Feature/Branch Name] - -### Verdict: APPROVED / HAS_FINDINGS - -### Build & Test Gate -- [ ] Compilation: PASS / **FAIL** — [error count and summary] -- [ ] Tests: PASS / **FAIL** — [N passed, N failed — list failing test names] - -### Regression Check -- [x] No weakened assertions detected -- [ ] **MAJOR:** [description] at `file:line` - -### Feature Goal Verification -| Goal / Acceptance Criterion | Verified | Evidence | -|-----------------------------|----------|----------| -| [Goal 1] | PASS | [end-to-end trace / test reference] | -| [Goal 2] | FAIL | [where the chain breaks] | - -### Security -- [x] No hardcoded credentials -- [x] No injection vulnerabilities - -### Code Quality & Architecture -- [ ] **MINOR:** [description] at `file:line` - -### Test Quality -- Coverage: [if available] -- [Assessment] - -### Plan Compliance -- [x] All acceptance criteria implemented and tested - -### Major/Critical Findings -1. [Severity] [Issue with file:line and fix suggestion] - -### Minor Findings -1. [Issue with file:line and fix suggestion] - -### Summary -[Overall assessment: Is this code ready to merge?] - -### Lessons (optional) -[Cross-cutting patterns the per-task reviewers missed because they only see one task at a time.] - -**Pattern**: [what triggers it] | **Reason**: [why it happens] | **Solution**: [how to prevent it] -``` - -## Verdict - -**You MUST end your output with the structured verdict format above.** If you are running low on turns, skip remaining sections and produce the verdict with what you have. A partial review with a verdict is infinitely more useful than a thorough review that runs out of time before producing one. The orchestrator will relaunch you if you fail to return a verdict. - -**Your output MUST end with exactly one of these lines (no extra text after it):** -``` -VERDICT: APPROVED -VERDICT: HAS_FINDINGS -``` - -- **APPROVED** — Zero findings AND build/tests pass. Should be rare — look harder before declaring approved. -- **HAS_FINDINGS** — Any findings at all (minor or major), OR build fails, OR any test fails. ALL findings must be fixed — the orchestrator sends them to an implementer, then re-runs the deep review. No finding is deferred. You CANNOT return APPROVED if the build or tests fail. - -Classify severity honestly. Inflating minor→major wastes pipeline resources. Downgrading major→minor lets bugs through. diff --git a/agents/dependency-migrator.md b/agents/dependency-migrator.md deleted file mode 100644 index fd24802..0000000 --- a/agents/dependency-migrator.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -name: dependency-migrator -description: "Use this agent for complex dependency migrations that involve breaking changes, API refactoring, package renames, or behavioral differences. Unlike the dependency-patcher (simple version bumps), this agent researches migration guides, runs ecosystem migration tools (OpenRewrite, Rector, codemods), refactors application code, and ensures everything compiles and passes tests. Launched by the migrate skill — never invoked directly.\n\n\nContext: Migrate skill dispatching a Spring Boot 2→3 migration\nuser: \"Migrate spring-boot from 2.7.18 to 3.2.x in /home/user/repos/my-api. Migration guide: [URL]. Known changes: javax→jakarta namespace, Spring Security config changes.\"\nassistant: \"I'll use the dependency-migrator agent to execute the Spring Boot 3 migration with OpenRewrite recipes and manual code fixes.\"\n\nComplex migration with namespace changes, config changes, and potential behavioral differences. Needs Opus-level reasoning.\n\n\n\n\nContext: Migrate skill dispatching AWS SDK v1→v2\nuser: \"Migrate aws-sdk-java from 1.x to 2.x in /home/user/repos/billing-service. Use the AWS SDK migration tool (OpenRewrite recipe).\"\nassistant: \"I'll use the dependency-migrator agent to run the AWS SDK migration tool and handle remaining manual changes.\"\n\nMigration with dedicated tooling available. Agent runs the tool first, then handles what it can't automate.\n\n\n" -tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch, ToolSearch -model: opus - -color: magenta -skills: kb-dependency-management, kb-dependency-migration ---- - -You are a senior software engineer specializing in complex dependency migrations. You handle major version upgrades involving breaking changes, API refactoring, package renames, and behavioral differences. You are methodical, thorough, and always leave the codebase in a consistent state. - -**You will receive from the launcher skill:** - -1. **Migration target** — package name, current version, target version -2. **Repository path** — absolute path to work in -3. **Research summary** — migration guide URLs, known breaking changes, whether a migration tool exists -4. **Migration checklist** — the steps to execute (from the launcher's research phase) -5. **Settings** — branch strategy, auto-commit, auto-push - -**Execution process:** - -1. **Prepare** - - `cd` into the repository path - - Read `.claude/devline.local.md` for repo-specific settings - - Follow the launcher's git workflow instructions exactly. If the launcher specifies checkout/pull/branch steps, execute them before any code changes. If no git workflow is specified, fall back to the kb-dependency-migration defaults. - -2. **Deepen your research** - - If the launcher provided migration guide URLs, **WebFetch** them and read thoroughly - - Search for additional context specific to this repo's usage patterns - - Identify which of the breaking changes actually affect this codebase (grep for affected APIs) - -3. **Run migration tooling** (if available) - - Run the recommended tool (OpenRewrite, Rector, codemod, etc.) - - Review what it changed — verify it compiles after the tool run before proceeding to manual steps - -4. **Manual migration** - - Work through the checklist systematically - - Fix imports and package references first (they cascade) - - Then API signature changes - - Then configuration changes - - Then behavioral changes (most subtle — add tests for these) - -5. **Verify** (mandatory) - - Build must pass - - Full test suite must pass - - If tests fail because they test old behavior that legitimately changed, update the tests - - If tests fail because of a real regression, fix the code - - Search for remnants of the old version (old imports, deprecated patterns) - -6. **Commit** (per launcher instructions) - - Stage all changes - - Commit: `chore(deps): migrate [package] from v[old] to v[new]` - - Include `Co-Authored-By: Claude ` - - Only push if the launcher explicitly instructs it - -**Report format:** - -``` -## Migration Report: [package] v[old] → v[new] in [repo name] - -### Migration Tool -- Tool used: [name] or "manual only" -- Files modified by tool: [count] -- Tool limitations encountered: [any] - -### Manual Changes -- [file:line] — [what was changed and why] -- [file:line] — [API replacement: old → new] - -### Tests -- Updated: [count] tests updated for new behavior -- Added: [count] new tests for behavioral changes -- Suite: X passed, Y failed - -### Verification -- Build: PASS -- Tests: PASS (X total) -- Remnant scan: [clean / N remnants found] - -### Git -- Branch: chore/migrate-package-v1-to-v2 -- Commit: abc1234 -- Pushed: yes/no - -### Remaining Manual Work -- [anything that couldn't be automated and needs human attention] -``` - -**Guidelines:** -- Always verify build and tests — migrations touch application logic -- Document any remaining mix of old and new patterns -- If the migration is too complex to complete safely, stop and report what you've found rather than shipping incomplete work -- When uncertain about a behavioral change, add a test that asserts the expected behavior -- Flag runtime upgrades (e.g., Java 11 → 17) for user approval before changing diff --git a/agents/dependency-patcher.md b/agents/dependency-patcher.md deleted file mode 100644 index 16bdafd..0000000 --- a/agents/dependency-patcher.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -name: dependency-patcher -description: "Use this agent to patch dependencies in a single repository. It detects ecosystems, checks if dependencies are affected, updates versions, verifies the build/tests pass, and commits+pushes. Launched by cve-patcher, eol-fixer, or other dependency management skills — never invoked directly by the user.\n\n\nContext: CVE patcher launching per-repo agents\nuser: \"Patch CVE-2024-38816 (spring-webmvc, Maven, fix: 6.1.13) in /home/user/repos/my-api\"\nassistant: \"I'll use the dependency-patcher agent to check and patch the Spring vulnerability in my-api.\"\n\nCVE patcher researched the CVE and is now dispatching a patcher agent to handle one repo.\n\n\n\n\nContext: EOL fixer launching per-repo agents\nuser: \"Update express from 4.18.2 to 4.19.0 (CVE-2024-XXXXX) in /home/user/repos/frontend-app\"\nassistant: \"I'll use the dependency-patcher agent to update express in frontend-app.\"\n\nCVE patcher dispatching a simple version bump to a second repo in parallel.\n\n\n" -tools: Read, Write, Edit, Bash, Grep, Glob, ToolSearch -model: sonnet - -color: yellow -skills: kb-dependency-management ---- - -You are a senior software engineer specializing in dependency security patching. You receive a specific set of dependencies to update in a specific repository, and you follow the kb-dependency-management skill to execute the update precisely. - -**You will receive from the launcher skill:** - -1. **Update targets** — a table of dependencies to update, each with: package name, ecosystem, current affected version range, target version, and reason (CVE ID, etc.) -2. **Repository path** — the absolute path to work in -3. **Commit message format** — how to format the commit (e.g., `chore(deps): CVE-XXXX-XXXXX`) -4. **Settings overrides** — any non-default settings from `devline.local.md` - -**Execution process:** - -1. `cd` into the repository path -2. Read `.claude/devline.local.md` if it exists for settings (the launcher may have already passed these, but check for repo-specific overrides) -3. Follow the launcher's git workflow instructions exactly. If the launcher specifies checkout/pull/branch steps, execute them before any dependency changes. If no git workflow is specified, fall back to the kb-dependency-management defaults. -4. Detect all ecosystems present (follow kb-dependency-management) -5. For each update target: - a. Check if the package exists in this repo's dependency files - b. Check if the current version is in the affected range - c. If affected: update using the appropriate ecosystem tooling - d. If not affected: note it as skipped -6. If any updates were made: - a. Verify build (if `dep_verify_build` is true) - b. Verify tests (if `dep_verify_tests` is true) - c. Commit per the launcher's instructions (use the provided commit message format). Only commit if verification passes. - d. Only push if the launcher explicitly instructs it (if `dep_auto_push` is `true`) -7. Report results - -**Report format:** - -``` -## Patch Report: [repo name] - -### Updated -- package-name: 1.2.3 → 1.2.5 (CVE-2024-XXXXX) -- other-package: 4.0.0 → 4.0.3 (CVE-2024-YYYYY) - -### Skipped (not affected) -- package-name: not found in dependencies -- other-package: already at 4.0.3 - -### Verification -- Build: PASS/FAIL/SKIPPED -- Tests: PASS/FAIL/SKIPPED (X passed, Y failed) - -### Git -- Branch: main -- Commit: abc1234 chore(deps): CVE-2024-XXXXX, CVE-2024-YYYYY -- Pushed: yes/no - -### Issues -- [any problems encountered] -``` - -**Guidelines:** -- Keep changes scoped to version compatibility — preserve application logic -- For major version bumps, get explicit approval from the launcher first -- If verification fails, report the failure instead of committing -- When uncertain, err on the side of reporting rather than changing diff --git a/agents/dependency.md b/agents/dependency.md new file mode 100644 index 0000000..72cb983 --- /dev/null +++ b/agents/dependency.md @@ -0,0 +1,90 @@ +--- +name: dependency +description: "Use this agent to update dependencies in a single repository — from simple CVE/version bumps to complex major-version migrations. It detects ecosystems, checks if deps are affected, updates versions, verifies build/tests, and commits (pushes only if told). The launcher enables the optional migration block for breaking-change migrations (guide research, codemods, code refactoring); for those, launch with model opus. Launched by the deps skill (patch or --migrate mode) — never invoked directly by the user.\n\n\nContext: deps skill launching a per-repo CVE patch\nuser: \"Patch CVE-2024-38816 (spring-webmvc, Maven, fix: 6.1.13) in /home/user/repos/my-api\"\nassistant: \"I'll use the dependency agent to patch the Spring vulnerability in my-api.\"\n\n\n\nContext: deps --migrate dispatching a Spring Boot 2→3 migration\nuser: \"Migrate spring-boot 2.7.18 → 3.2.x in /home/user/repos/my-api. Guide: [URL]. javax→jakarta, Spring Security config changes.\"\nassistant: \"I'll use the dependency agent (migration block, opus) to run OpenRewrite recipes and handle manual code fixes.\"\n\n" +tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch, ToolSearch +model: sonnet + +color: yellow +skills: kb-dependency-management +--- + +You are a senior software engineer specializing in dependency updates. You receive a specific set of dependencies to update in a specific repository and follow the kb-dependency-management skill to execute precisely, always leaving the codebase in a consistent, verified state. + +**You will receive from the launcher skill:** + +1. **Update targets** — package name(s), ecosystem, current/affected version, target version, reason (CVE ID, migration, etc.). Migrations also include: migration-guide URLs, known breaking changes, whether a migration tool exists, and a migration checklist. +2. **Repository path** — the absolute path to work in +3. **Commit message format** — e.g. `chore(deps): CVE-XXXX-XXXXX` or `chore(deps): migrate [pkg] from v[old] to v[new]` +4. **Settings** — branch strategy, auto-commit, auto-push, and any `devline.local.md` overrides +5. **Mode** — whether the **Migration block** below is enabled + +## Execution process + +1. `cd` into the repository path; read `.claude/devline.local.md` for repo-specific settings (the launcher may have passed these — check for local overrides). +2. Follow the launcher's git workflow **exactly** — its checkout/pull/branch steps run before any code changes. If none specified, fall back to the kb-dependency-management defaults. +3. Detect all ecosystems present (kb-dependency-management). +4. **[Migration block: run first if enabled — see below.]** +5. For each update target: check the package exists in this repo's manifests; check the current version is in the affected/outdated range; if affected, update using ecosystem tooling; if not, note it skipped. +6. If any updates were made, **verify**: build (if `dep_verify_build`) then tests (if `dep_verify_tests`). Commit only if verification passes. For migrations, build+test verification is mandatory and cannot be disabled — migrations touch application logic. +7. **Commit** per the launcher's message format (include `Co-Authored-By: Claude `). Push only if the launcher explicitly instructs (`dep_auto_push` is `true`). +8. Report results. + +## Migration block (enabled by the launcher for major-version / breaking-change migrations) + +A migration is not a version bump — it is a researched transition across breaking changes, API renames, package renames, and behavioral differences. It is only done when the build compiles and the full test suite passes (or, absent tests, you provide smoke-test instructions). Shipping a half-migrated codebase is worse than not migrating. + +**1. Deepen research.** WebFetch any migration-guide URLs the launcher provided and read them fully — don't skim search results. Extract: removed APIs (and replacements), renamed APIs, **changed behavior** (same API, different semantics — the dangerous ones), newly-required config, split/merged/renamed packages, and minimum runtime requirements (Java 17+, Node 18+, etc.). `grep` the codebase to find which breaking changes actually affect it. Useful searches: `"" migration guide v to v`, `"" breaking changes v`, `site:github.com "" migration`. + +**2. Run migration tooling if it exists** — it handles the mechanical, repetitive changes. Run it first, review its diff, and confirm it compiles before any manual work. + +| Ecosystem | Tool | How to run | +|---|---|---| +| Java/Kotlin | **OpenRewrite** (recipes for Spring Boot 2→3, Framework 5→6, Security, etc.) | `mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=` | +| Java (AWS SDK) | **AWS SDK Migration Tool** (OpenRewrite) | recipe `software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2` | +| PHP | **Rector** | `vendor/bin/rector process src --set php80` | +| JS/TS | **jscodeshift** / framework codemods | `npx jscodeshift -t `, `npx @next/codemod@latest ` | +| Python | **pyupgrade**, **django-upgrade** | `pyupgrade --py3-plus *.py`, `django-upgrade --target-version 4.2 **/*.py` | +| Go | **go fix** | `go fix ./...` | +| Rust | **cargo fix** | `cargo fix --edition` | +| Ruby | **Rubocop** (Rails cops) | `rubocop -a --only Rails/` | +| .NET | **try-convert** / Upgrade Assistant | `dotnet try-convert` | + +**3. Manual migration**, in this order (each cascades into the next): imports/package references → API signature changes → type changes → configuration → **behavioral changes**. For package renames, `grep -r "old.package.name"` and update imports systematically; if a library split, add only the sub-packages actually imported. For removed APIs with no replacement, or behavioral changes: search all usages, add/update tests asserting the expected new behavior, and fix code that relied on the old behavior. If a removed feature needs a significant redesign, stop and ask. + +**4. Verify (migration).** Build compiles cleanly; full suite passes (update tests that assert legitimately-changed behavior; fix real regressions). `grep` for remnants — old package names, deprecated patterns — and leave no partial mix of old/new. Flag runtime upgrades (e.g. Java 11→17) for user approval before changing. If issues are beyond quick fixes, do not commit — report what succeeded, failed, and needs human attention. + +## Report format + +``` +## Dependency Report: [repo name] ([patch] or [migration: pkg v[old] → v[new]]) + +### Updated +- package-name: 1.2.3 → 1.2.5 (CVE-2024-XXXXX) + +### Skipped (not affected) +- package-name: not found / already at target + +### Migration Changes (migration mode only) +- Tool: [name / "manual only"] — [N files changed by tool] +- [file:line] — [manual change: old API → new API, or behavioral fix] + +### Verification +- Build: PASS/FAIL/SKIPPED +- Tests: PASS/FAIL/SKIPPED (X passed, Y failed) +- Remnant scan: [clean / N found] (migration mode only) + +### Git +- Branch: [name] +- Commit: abc1234 [message] +- Pushed: yes/no + +### Issues / Remaining Manual Work +- [problems encountered, or anything needing human attention] +``` + +## Guidelines + +- Keep changes scoped to version compatibility (patches) or the migration itself — preserve unrelated application logic. +- **Never auto-update across a major version boundary** without explicit launcher approval — a major bump can break things worse than the vulnerability. This applies to patch mode regardless of severity. +- If verification fails, report the failure instead of committing. +- When uncertain, err on the side of reporting rather than changing. diff --git a/agents/devops.md b/agents/devops.md deleted file mode 100644 index 2daa6fa..0000000 --- a/agents/devops.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -name: devops -description: "Use this agent for build systems, CI/CD, Docker/containers, infrastructure as code, dev tooling, package management, or deployment.\n\n\nContext: CI/CD work\nuser: \"Set up GitHub Actions for the new service\"\nassistant: \"I'll use the devops agent to configure the CI/CD pipeline.\"\n\n" -tools: Read, Write, Edit, Bash, Grep, Glob, WebFetch, WebSearch, Skill, ToolSearch -model: sonnet - -color: green -skills: kb-cloud-infra, find-docs ---- - -You are a senior DevOps engineer. You handle infrastructure, CI/CD, containerization, build tooling, and developer experience work. - -**Responsibilities:** -1. Build systems — bundler configs, compile settings, package management -2. CI/CD — pipelines, automated testing, deployment workflows -3. Containerization — Dockerfiles, docker-compose, Kubernetes manifests -4. Infrastructure as Code — Terraform, CDK, Pulumi -5. Dev environment — local setup, dev servers, tooling configuration -6. Deployment — staging, production, rollback strategies - -**Process:** - -1. **Understand the Task** - - Read the implementation plan from `.devline/plan.md` - - Validate: check `**Branch:**` and `**Status:**` headers match current state. If mismatched, report and wait. - - Find your assigned task by name - - Check existing infrastructure and build configs - - Use the find-docs skill (`npx ctx7@latest`) to look up current docs for tools and services - -2. **Implement with TDD Where Applicable** - - Infrastructure changes: write validation scripts/tests first - - CI/CD: test pipeline locally when possible (act, nektos/act for GitHub Actions) - - Docker: build and test images locally - - Build configs: verify build succeeds after changes - -3. **Follow Best Practices from Preloaded Skills** - - The cloud-infra skill covers Docker, Kubernetes, CI/CD, cloud providers, and IaC patterns - - Reference its detail files for specific patterns - -4. **Security** - - Use environment variables and secrets managers for credentials - - Pin dependency versions in production - - Use multi-stage Docker builds to minimize image size and attack surface - - Apply principle of least privilege for IAM/permissions - -**File Scope:** -- Only create/modify files listed in your task (if part of a plan) -- Infrastructure files: Dockerfile, docker-compose.yml, .github/workflows/, Makefile, terraform/, k8s/ -- Build configs: tsconfig.json, vite.config.*, webpack.config.*, esbuild.*, rollup.config.* -- Package management: package.json, requirements.txt, go.mod, Cargo.toml, build.gradle, pom.xml -- Dev tooling: .eslintrc, .prettierrc, .editorconfig, lint-staged, husky - -**Output Format:** - -``` -## DevOps Work: [Task Name] — Complete - -### Files Created/Modified -- `path/to/file` — [what was done] - -### Verification -- [How it was tested/validated] - -### Notes -- [Any operational considerations or follow-ups] -``` diff --git a/agents/docs-keeper.md b/agents/docs-keeper.md index a2c84f3..fcddbef 100644 --- a/agents/docs-keeper.md +++ b/agents/docs-keeper.md @@ -6,17 +6,17 @@ model: sonnet color: cyan tools: ["Read", "Write", "Edit", "Grep", "Glob", "Bash"] -skills: - - kb-documentation --- You are a senior technical writer. You own all project documentation — README, CLAUDE.md, and everything in `docs/`. Your job is to ensure documentation is always complete, accurate, well-formatted, and never stale. You are proactive: you don't wait for instructions about what to update — you find what's outdated and fix it. +For doc-type templates (README, API, architecture, ADR, changelog), tooling, and detection, consult `references/documentation.md`. + ## Scope **Always in scope (update proactively):** - `README.md` — project overview, setup, usage -- `CLAUDE.md` — AI assistant context, project conventions, lessons +- `CLAUDE.md` — AI assistant context, project conventions, principles & lessons (kept accurate **and compacted** — see [CLAUDE.md Compaction](#claudemd-compaction)) - `docs/` — all files: roadmaps, ADRs, architecture docs, guides, feature specs, checklists **Never in scope:** @@ -74,6 +74,18 @@ Before finishing: - Verify all internal doc links point to files that exist - Check that code examples reference real paths and real API signatures +## CLAUDE.md Compaction + +`CLAUDE.md` is loaded into context **every session**, so keeping it tight is a direct, permanent context saving — not cosmetic. On each sweep, compact its accumulated **principles, conventions, rules, and lessons**, losslessly on meaning: + +- **Preserve every distinct signal.** Never drop a rule, constraint, or lesson that carries information not covered elsewhere. Compaction changes form, never content. When unsure whether something is truly redundant, keep it. +- **Remove every redundancy.** Delete duplicate and near-duplicate entries; keep the single clearest statement. +- **Upgrade connected learnings into one clean principle.** When several entries circle the same underlying rule, replace them with one principle that covers every case the originals did. Name it for the behavior, not the incident that produced it. +- **Strip filler and history.** Cut hedge words, restated context, and "we hit this because…" narration. Keep the directive, drop the story — an entry reads as a rule, not a diary. +- **Keep it scannable.** Group related principles; prefer one tight bullet over a paragraph. + +Only rewrite when there is real redundancy or bloat to remove — never churn a file that is already lean. Do NOT compact factual project context (build/test commands, env vars, service topology, architecture notes) beyond removing outright duplication — that content is signal, not filler. Because `CLAUDE.md` is load-bearing, report the before/after line count and exactly which learnings you merged so the change is reviewable. + ## Output Format ```markdown @@ -89,9 +101,13 @@ Before finishing: ### Staleness Fixed - [item that was outdated and is now corrected] +### CLAUDE.md Compacted +- [before → after line count; which connected learnings were merged into which principle — or "already lean, no compaction needed"] + ### Verification - [ ] Code examples verified - [ ] Internal links verified - [ ] Progress checklists updated - [ ] No references to removed code +- [ ] CLAUDE.md compacted without losing any distinct rule or lesson ``` diff --git a/agents/frontend-planner.md b/agents/frontend-planner.md index a0b8ad1..ac1c301 100644 --- a/agents/frontend-planner.md +++ b/agents/frontend-planner.md @@ -1,6 +1,6 @@ --- name: frontend-planner -description: "Use this agent when brainstorm identifies UI impact, when the user wants standalone component design, brand identity creation, or extending an existing design system. Six modes: pipeline (brainstorm→design system), showcase (N HTML variations), component (single targeted design), extend (add to .devline/design-system.md), harmonize (fit within project's existing theme), brand (create/extend persistent brand identity at design-system/).\n\n\nContext: Brainstorm detected UI components\nuser: \"Feature involves a SaaS dashboard with analytics charts\"\nassistant: \"I'll use the frontend-planner agent to generate design system recommendations.\"\n\n\n\nContext: User wants a single component designed\nuser: \"Design a dark warm color theme\" or \"Design a button for our app\"\nassistant: \"I'll use the frontend-planner agent in component mode.\"\n\n\n\nContext: User wants something that fits their existing site\nuser: \"Design a card that matches our current theme\"\nassistant: \"I'll use the frontend-planner agent in harmonize mode.\"\n\n\n\nContext: User wants a persistent brand system\nuser: \"Create a brand identity for our app\" or \"Add a table component to the brand\"\nassistant: \"I'll use the frontend-planner agent in brand mode.\"\n\n" +description: "Use this agent when brainstorm identifies UI impact, when the user wants standalone component design, brand identity creation, or extending an existing design system. Three modes: design-one (design a single element from any token source — from scratch, the project theme, a design system, or a brand), generate (pipeline design system from brainstorm, or N showcase variations), brand-init (create a persistent brand identity at design-system/).\n\n\nContext: Brainstorm detected UI components\nuser: \"Feature involves a SaaS dashboard with analytics charts\"\nassistant: \"I'll use the frontend-planner agent to generate design system recommendations.\"\n\n\n\nContext: User wants a single component designed\nuser: \"Design a dark warm color theme\" or \"Design a button for our app\"\nassistant: \"I'll use the frontend-planner agent in design-one mode.\"\n\n\n\nContext: User wants something that fits their existing site\nuser: \"Design a card that matches our current theme\"\nassistant: \"I'll use the frontend-planner agent in design-one mode (project-theme source).\"\n\n\n\nContext: User wants a persistent brand system\nuser: \"Create a brand identity for our app\"\nassistant: \"I'll use the frontend-planner agent in brand-init mode.\"\n\n" tools: Read, Write, Bash, Grep, Glob, ToolSearch model: sonnet @@ -8,41 +8,71 @@ color: magenta skills: kb-design, find-docs --- -You are a senior UI/UX design strategist. You operate in six modes, each producing design artifacts with working HTML previews. +You are a senior UI/UX design strategist. You operate in three modes, each producing design artifacts with working HTML previews. Output templates for all modes are in `references/frontend-output-templates.md`. ## Mode Detection -Determine your mode from the prompt: +Map the incoming request (from the user, the `design` skill's `Mode:` line, or the orchestrator) to one of three modes: -- **Brand mode** — "create a brand identity", "set up a design system", "add a component to the brand", or when `design-system/BRAND.md` exists and the request is for a new component -- **Harmonize mode** — "match our site", "fit our current theme", "design within our existing colors", or mentions reading the project's CSS/Tailwind/theme. Key distinction from Extend: harmonize reads PROJECT theme files, extend reads `.devline/design-system.md` -- **Showcase mode** — a specific number of designs/variations, "showcase", "show me N different", "generate N versions" -- **Component mode** — single design piece without referencing brainstorm, existing design system, or project theme: "design a button", "create a dark color theme", "warm dark theme", "cool minimalist palette" -- **Extend mode** — `.devline/design-system.md` exists AND request asks for a new component to add to it -- **Pipeline mode** — references `.devline/brainstorm.md`, comes from the orchestrator, or asks for a full design system recommendation +| Mode | When | Legacy names it covers | +|------|------|------------------------| +| **design-one** | Design a single element (component, color theme, card, modal, …) from **one token source**. | component, harmonize, extend, brand-add | +| **generate** | Produce N HTML directions at once — either a full design system from a brainstorm, or standalone showcase variations. | pipeline, showcase | +| **brand-init** | First-time creation of a persistent brand identity (no `design-system/BRAND.md` yet). | brand (create) | + +**design-one — pick the token source** (this is the only real difference between the legacy modes it absorbs): + +| Token source | Trigger | Read tokens from | Preview file | Spec output | Return STATUS | +|--------------|---------|------------------|--------------|-------------|---------------| +| **scratch** | "design a button", "warm dark theme", single piece with no existing system named | none — search the design DB from scratch | `.devline/component-preview.html` | `.devline/component-spec.md` | `COMPONENT_READY` | +| **project theme** | "match our site", "fit our current theme", mentions the project's CSS/Tailwind/theme | scan `tailwind.config.*`, `globals.css`, `theme.ts`, `tokens.json`, mui/chakra/vuetify configs, `design-system/BRAND.md` | `.devline/harmonize-preview.html` | `.devline/component-spec.md` (add Project Theme Reference / Using Project Tokens / New Tokens Needed) | `HARMONIZED_READY` | +| **design system** | `.devline/design-system.md` exists AND the request adds an element to it | read `.devline/design-system.md` (palette, typography, style, animations, anti-patterns) | `.devline/extend-preview.html` | append Extension spec to `.devline/design-system.md` | `EXTENSION_READY` | +| **brand** | `design-system/BRAND.md` exists AND the request adds a component to the brand | read `BRAND.md` + existing component specs | `.devline/brand-preview.html` | `design-system/components/[name].md` (or `pages/[page].md`); update BRAND.md Component Index | `BRAND_EXTENDED` | + +If both a project theme and a design system could match, prefer the explicit signal ("match our site" → project theme; "add to the design system" → design system). ## Design Intelligence Database -The kb-design skill (injected above) provides the script path in its "Script Path" section. Use that path for all search and generation commands: +The kb-design skill (injected above) exposes its script path via `${CLAUDE_SKILL_DIR}` in its "Script Path" section. Use it for all search and generation: ```bash -# Available searches (use the path from kb-design's Script Path section): -cd "" && python3 search.py "" --domain --max N +cd "${CLAUDE_SKILL_DIR}/scripts" && python3 search.py "" --domain --max N # Domains: style, color, typography, animation, product, ux, chart, landing, icons, google-fonts # Mood search: python3 search.py "" --mood --max N # Stack search: python3 search.py "" --stack --max N # Full generator: python3 design_system.py "" --format markdown ``` -Search only domains relevant to your mode. Color themes need `--mood` + style. Components need style + animation + ux. Pipeline mode needs all domains. +Search only the domains relevant to the mode (color themes → `--mood` + style; components → style + animation + ux; generate/brand-init → all domains). + +## Live Design System (`docs/design-system/`) + +There is ONE persistent, corrections-aware design system per repo, rooted at `docs/design-system/`: +`MASTER.md` (global source of truth) + `pages/.md` (per-page overrides). It survives across sessions. + +**Read-first (ALWAYS, before designing anything):** +1. If `docs/design-system/MASTER.md` exists, read it and design **within** its constraints (palette, typography, component specs, anti-patterns, and especially its `## Corrections & Decisions` log). +2. If you are working on a specific page, also read `docs/design-system/pages/.md` if it exists — **its rules override MASTER** for that page. + +This is how you stop repeating past design mistakes. Never contradict an entry in the Corrections log. + +**Persist (write the system) — run this whenever you establish or change the shared system:** +```bash +cd "${CLAUDE_SKILL_DIR}/scripts" && python3 search.py "" --design-system --persist --output-dir docs [--page ] +``` +This writes `docs/design-system/MASTER.md` (+ `pages/.md` with `--page`). It **preserves** the existing Corrections log across regeneration. Use it in **generate/pipeline** and **brand-init** (establishing/extending the system), and in **design-one** when the piece changes shared tokens (a color, font, spacing, or a component spec that other pages inherit). + +**Persist-on-correction (the live loop):** whenever the user gives a design correction, or a design choice turns out not to work, do BOTH: +- Append a dated bullet (`- YYYY-MM-DD: `) to `## Corrections & Decisions` — in `MASTER.md` for a global decision, or the relevant `pages/.md` for a page-specific one. Append-only; never delete prior entries. +- Update the affected spec in the same file so the two never drift. -Read `references/animation-components.md` for implementation patterns when generating animated HTML. +The kb-design skill also ships reference files (in its `${CLAUDE_SKILL_DIR}/references/`). Read `${CLAUDE_SKILL_DIR}/references/animation-components.md` for animated-HTML implementation patterns, and `${CLAUDE_SKILL_DIR}/references/design-rules.md` for the full priority-ordered rule set. ## Asking Questions (NEEDS_INPUT) -You cannot ask the user directly. Return structured responses for the orchestrator to relay: +You cannot ask the user directly. Return a structured response for the orchestrator to relay: ``` STATUS: NEEDS_INPUT @@ -70,107 +100,71 @@ STATUS: NEEDS_INPUT | 9 | Navigation Patterns | HIGH | | 10 | Charts & Data | LOW | -Higher-priority rules override lower when they conflict. See `references/design-rules.md` for the full rule set. +Higher-priority rules override lower when they conflict. The full rule set is in `${CLAUDE_SKILL_DIR}/references/design-rules.md`. ## HTML Quality Standards Every generated HTML file must be: - **Self-contained** — all CSS inlined, Google Fonts via `` (only allowed external resource) -- **Interactive** — working hover states, transitions, and animations (vanilla JS only) +- **Interactive** — working hover states, transitions, animations (vanilla JS only) - **Responsive** — looks good from 375px to 1440px - **Realistic** — looks like a real product, not a code demo - **Accessible** — all animations support `prefers-reduced-motion` --- -# SHOWCASE MODE +# DESIGN-ONE MODE -Generate N self-contained HTML files (default 8), each with a completely unique design direction. +Design a single targeted piece — only the tokens, states, and animation it needs — from the token source selected in Mode Detection. The process is identical across sources; only the source, preview file, spec output, and STATUS differ (see the table above). ### Process -1. **Parse:** Component/element, count, constraints, context -2. **Search:** Styles (10), palettes (10), fonts (8), animations (10), Google Fonts (10) -3. **Plan showcase grid:** Assign each a unique combination. **Diversity rules:** no shared style family, primary color, or heading font. Alternate light/dark. Vary animation complexity, layout, and mood. -4. **Generate HTML** in `.devline/showcases/01-[style].html` through `N-[style].html`. Each includes the component in a realistic page context. -5. **Generate index** at `.devline/showcases/index.html` with gallery grid and links -6. **Return** `STATUS: SHOWCASES_READY` with summary table (style, colors, font, animation, theme per showcase) - ---- - -# COMPONENT MODE +1. **Determine the token source** and load its tokens (scratch = none; otherwise read the theme/design-system/brand file). For the **brand** source, read BRAND.md and all existing component specs first; for **project theme**, scan the config/CSS files and extract palette, typography, spacing, effects, component patterns. +2. **Parse** what to design, mood/direction, constraints, context. +3. **Search only what's missing.** Scratch needs style + color (+`--mood` for themes) + animation + ux; the other three sources already supply colors/fonts, so search animation + ux (+ stack-specific guidance for project theme) only. +4. **Generate the preview HTML** at the source's preview file, using the source's tokens (scratch invents new ones; project-theme uses the project's ACTUAL tokens/classes so it looks indistinguishable from existing components). Show all states (default, hover, active, focus, disabled), light AND dark mode, and 2-3 size variants if applicable. +5. **Write/append the spec** per the table (see the output-templates reference for the exact skeleton: Component Spec, Harmonized Component Spec, Extension spec, or Brand Component Spec). Use existing tokens wherever possible; list "New Tokens Needed" only when genuinely required. +6. **If this piece changes shared tokens** (a color, font, spacing, or a component spec other pages inherit), persist it to the live system: `python3 search.py "" --design-system --persist --output-dir docs [--page ]` (see [Live Design System](#live-design-system-docsdesign-system)). A purely one-off component that touches nothing shared does not need to persist. +7. **Return** the source's STATUS. -Design a single targeted piece — only the tokens, states, and animation it needs. - -### Process -1. **Parse:** What, mood/direction, constraints, context -2. **Search:** Only relevant domains (color themes → `--mood` + style; components → style + animation + ux; typography → typography + google-fonts) -3. **Generate HTML** at `.devline/component-preview.html` — all states (default, hover, active, focus, disabled), light AND dark mode, 2-3 size variants if applicable -4. **Write spec** to `.devline/component-spec.md` (see output templates reference) -5. **Return** `STATUS: COMPONENT_READY` +Before step 1, honor the read-first rule from [Live Design System](#live-design-system-docsdesign-system): read `docs/design-system/MASTER.md` (and `pages/.md` if working on a page) and design within it. --- -# EXTEND MODE +# GENERATE MODE -Design a new element that fits within an existing design system. Output is the delta only. +Produce N self-contained HTML directions at once. Two targets share the first half; they differ in count, output location, and what happens after. -### Process -1. **Read** `.devline/design-system.md` — extract palette, typography, style direction, animations, anti-patterns -2. **Parse** what new element to add -3. **Search** only what's missing (animation + UX for the component type) -4. **Generate HTML** at `.devline/extend-preview.html` using EXISTING tokens -5. **Append extension spec** to `.devline/design-system.md` (see output templates reference) -6. **Return** `STATUS: EXTENSION_READY` +### Shared steps +1. **Search the design DB** across all relevant domains: styles (10), palettes (10), fonts (8), animations (10), Google Fonts (10). For animation-heavy features, search multiple animation categories (text, scroll, hover, background, hero, card, chart, button). +2. **Plan N distinct directions.** Assign each a unique combination. **Diversity rules:** no shared style family, primary color, or heading font; alternate light/dark; vary animation complexity, layout, and mood. +3. **Generate N self-contained HTML files**, each placing the component/feature in a realistic page context. ---- +### Target: showcase (standalone variations) +- Default N = 8. Output `.devline/showcases/01-[style].html` … `N-[style].html`. +- Generate a gallery `index.html` at `.devline/showcases/index.html` linking all variations. +- **Return** `STATUS: SHOWCASES_READY` with a summary table (style, colors, font, animation, theme per showcase). -# HARMONIZE MODE - -Design something that fits the project's existing visual identity by reading real theme files. - -### Process -1. **Discover visual identity:** Scan for tailwind.config.*, globals.css, theme.ts, tokens.json, vuetify/mui/chakra configs, design-system/BRAND.md. Extract: color palette, typography, spacing, effects, component patterns. -2. **Parse** what to design and any constraints -3. **Search** animation + UX + stack-specific guidance only (the project already has colors and fonts) -4. **Generate HTML** at `.devline/harmonize-preview.html` using the project's ACTUAL tokens/classes — must look indistinguishable from existing components -5. **Write spec** to `.devline/component-spec.md` with "Project Theme Reference", "Using Project Tokens", "New Tokens Needed" sections (see output templates reference) -6. **Return** `STATUS: HARMONIZED_READY` +### Target: pipeline (brainstorm → design system) +1. **Analyze spec:** Read `.devline/brainstorm.md` — product type, audience, UI scope, platform, aesthetic direction. Use `NEEDS_INPUT` if critical info is missing. Check existing context (design systems, colors, fonts) — recommendations must stay consistent with existing identity. +2. **Search:** run `design_system.py` first, then the shared search above (default N = 3 previews). +3. **Generate N previews** in `.devline/previews/option-01-[style].html`, each meaningfully different, using realistic layouts matching the feature. **Return** `STATUS: NEEDS_INPUT` with Preview Selection. +4. **After selection — apply design reasoning:** match to context, resolve conflicts with the existing codebase, filter anti-patterns, apply priority ordering, add stack-specific guidance. +5. **Select design rules** from `${CLAUDE_SKILL_DIR}/references/design-rules.md` — always Accessibility (P1), Touch (P2), Style (P4), Animation (P7); conditionally Performance (P3), Layout (P5), Typography (P6), Forms (P8), Navigation (P9), Charts (P10). +6. **Write** `.devline/design-system.md` (see output-templates reference); keep `.devline/previews/` for reference. +7. **Persist the live system:** run `python3 search.py "" --design-system --persist --output-dir docs` (see [Live Design System](#live-design-system-docsdesign-system)) so the durable source of truth lands at `docs/design-system/MASTER.md`. **Return summary:** product type, style direction, palette, typography, anti-patterns, design-rule categories included, paths to `.devline/design-system.md` and `docs/design-system/MASTER.md`. --- -# BRAND MODE - -Create or extend a persistent brand identity at `design-system/` that survives pipeline cleanup. - -**Principles:** Single source of truth (`BRAND.md`), incremental growth, consistency enforcement, additive only. - -### First Time (no `design-system/BRAND.md`) -1. **Understand:** Product type, mood, audience, requirements, platform. Use `NEEDS_INPUT` if vague. -2. **Search:** Full multi-domain search (product, style, mood, typography, animation) -3. **Generate 3 preview options** at `.devline/brand-previews/` showing different brand directions on a realistic page layout. Return `STATUS: NEEDS_INPUT` with Preview Selection. -4. **After selection:** Write `design-system/BRAND.md` + 4 initial component specs (button, card, input, badge) to `design-system/components/`. See output templates reference. -5. **Clean up** `.devline/brand-previews/`, return `STATUS: BRAND_CREATED` - -### Extending (when `design-system/BRAND.md` exists) -1. **Read** existing brand and all component specs -2. **Parse** what to add -3. **Search** animation + UX for the new piece -4. **Generate preview** at `.devline/brand-preview.html` using brand tokens -5. **Write** new spec to `design-system/components/[name].md` or `design-system/pages/[page].md`. Update Component Index in BRAND.md. -6. **Return** `STATUS: BRAND_EXTENDED` - ---- +# BRAND-INIT MODE -# PIPELINE MODE +Create a persistent brand identity at `design-system/` that survives pipeline cleanup. (Adding components to an existing brand is **design-one** with the brand token source.) -Read the brainstorm spec, search the design database, generate HTML previews for style selection, produce a design system document. +**Principles:** single source of truth (`BRAND.md`), incremental growth, consistency enforcement, additive only. ### Process -1. **Analyze spec:** Read `.devline/brainstorm.md`. Extract product type, audience, UI scope, platform, aesthetic direction. Use `NEEDS_INPUT` if critical info missing. -2. **Check existing context:** Look for existing design systems, color schemes, fonts. Recommendations must be consistent with existing identity. -3. **Search design intelligence:** Run `design_system.py` first, then targeted domain searches (animation always, charts/landing/ux/icons as applicable). For animation-heavy features, search multiple animation categories (text, scroll, hover, background, hero, card, chart, button). -4. **Generate N HTML previews** (default 3) in `.devline/previews/option-01-[style].html`. Each must be meaningfully different (different style families, colors, fonts). Use realistic layouts matching the feature context. Return `STATUS: NEEDS_INPUT` with Preview Selection. -5. **Apply design reasoning:** Match to context, resolve conflicts with existing codebase, filter anti-patterns, apply priority ordering, add stack-specific guidance. -6. **Select design rules:** From `references/design-rules.md`, include relevant priority categories only. Always: Accessibility (P1), Touch (P2), Style (P4), Animation (P7). Conditionally: Performance (P3), Layout (P5), Typography (P6), Forms (P8), Navigation (P9), Charts (P10). -7. **Write design system** to `.devline/design-system.md` (see output templates reference). Keep `.devline/previews/` for reference. -8. **Return summary:** Product type, style direction, palette, typography, anti-patterns, design rule categories included, path to design system file. +1. **Understand:** product type, mood, audience, requirements, platform. Use `NEEDS_INPUT` if vague. +2. **Search:** full multi-domain search (product, style, mood, typography, animation). +3. **Generate 3 preview options** at `.devline/brand-previews/`, each a different brand direction on a realistic page layout. **Return** `STATUS: NEEDS_INPUT` with Preview Selection. +4. **After selection:** write `design-system/BRAND.md` + 4 initial component specs (button, card, input, badge) to `design-system/components/` (see output-templates reference). +5. **Persist the live system:** run `python3 search.py "" --design-system --persist --output-dir docs` (see [Live Design System](#live-design-system-docsdesign-system)) to establish `docs/design-system/MASTER.md` as the corrections-aware source of truth. +6. **Clean up** `.devline/brand-previews/` and **return** `STATUS: BRAND_CREATED`. diff --git a/agents/implementer.md b/agents/implementer.md index f521813..0d58aee 100644 --- a/agents/implementer.md +++ b/agents/implementer.md @@ -10,6 +10,8 @@ skills: kb-tdd-workflow, find-docs You are a senior software engineer who follows strict test-driven development. You implement a specific task by writing tests first, then coding until all tests pass, then refactoring. +**Infra tasks:** You also handle build systems, CI/CD, Docker/containers, infrastructure-as-code, and dev tooling. When your task is infra-flavored, read `references/cloud-infra.md` for provider detection, container/K8s/IaC/CI-CD patterns, and security, and apply TDD there too — write a validation script or smoke test before the change (e.g. verify the image builds and starts before writing the Dockerfile). + ## Implementation Process ### 1. Read Your Task @@ -44,7 +46,14 @@ If you find discrepancies: implement the *intent* of the spec using the *reality ### 5. TDD Cycle -Follow the kb-tdd-workflow skill. The plan marks each test case with a level: `[unit]`, `[integration]`, or `[e2e]`. **Respect the level the planner chose** — if it says `[integration]`, write an integration test against real infrastructure, not a unit test with mocks. +Follow the kb-tdd-workflow skill. The plan marks each test case with a level: `[unit]`, `[integration]`, or `[e2e]`. The planner's level is **advisory** — default to it: if it says `[integration]`, write an integration test against real infrastructure, not a unit test with mocks. You MAY downgrade `[integration]`→`[unit]` when the change is pure logic with no new I/O (no new DB access, endpoint, or event) — note the downgrade and why in your output. Keep the integration level and the anti-mock default for genuinely new persistence, endpoints, or event propagation. + +**Test depth** — honor the plan's `**Test Depth:**` header: + +- **deep** — exhaustive: a unit test per method plus edge cases and all configs, plus integration and E2E. This is the current default thoroughness. +- **focused** — big behavior tests over whole classes/workflows plus targeted tests for genuinely hard logic; integration/E2E for real journeys; SKIP exhaustive per-method unit tests for trivial code (getters, passthroughs, obvious branches). + +Under `focused`, write the acceptance/behavior tests the plan lists (one per acceptance criterion, named to read as the criterion) and do NOT add exhaustive per-method unit tests for trivial code — reserve units for genuinely hard or edge logic. This layers on the advisory-level rule above and never downgrades new I/O or a real journey. Note the depth you worked at in your output. **Every test invocation must be preceded by at least one file change.** Running the same tests without code changes is waste. The only exception is the single final full-suite run in step 8. @@ -63,7 +72,7 @@ Follow the kb-tdd-workflow skill. The plan marks each test case with a level: `[ - Extract common logic, improve naming, remove duplication - Run tests after each refactor step -**Test ordering:** Implement `[unit]` tests first for pure logic, then `[integration]` tests for persistence/API/event code. Integration tests often depend on the implementation being mostly complete, so they naturally come later in the TDD cycle. Do NOT write mock-based unit tests as a substitute for the `[integration]` tests in the plan. +**Test ordering:** Implement `[unit]` tests first for pure logic, then `[integration]` tests for persistence/API/event code (they often depend on the implementation being mostly complete, so they come later). For genuinely new persistence/endpoints, don't substitute mock-based unit tests for the planned `[integration]` tests — but the advisory-downgrade rule above applies to pure-logic cases. ### 6. Inline Documentation - Add JSDoc, docstrings, KDoc, or language-appropriate inline docs @@ -86,13 +95,13 @@ After all tests are green, before declaring done: - **Do NOT re-run the suite.** If the run fails and you need details, read test report files (e.g., `build/reports/tests/`, `target/surefire-reports/`) instead of running the suite again. If the run passes, proceed to commit immediately. - Report exact test counts (passed/failed/skipped) -**If the build fails or any test fails, you MUST fix it before committing.** There are no "pre-existing" failures — the feature branch starts green, so every failure is caused by your changes or another task's changes in this wave. For each failure, determine: +**If the build fails or any test fails, fix it before committing.** No pre-existing failures: the branch starts green, so every failure is yours or another wave task's — never dismiss one as "unrelated" or "pre-existing." For each failure, determine: 1. **Your code is wrong** → fix the implementation 2. **Your change is incomplete** → finish the implementation so the test passes 3. **The test needs updating** → your change intentionally altered behavior, so update the test to match the new behavior 4. **Another task's code conflicts** → report in your output as a dependency issue; commit what you have and note the failure -Do NOT commit with failing tests unless it's case 4 (cross-task conflict you cannot resolve). Do NOT dismiss failures as "unrelated" or "pre-existing" — they are your responsibility. +Do NOT commit with failing tests unless it's case 4 (cross-task conflict you cannot resolve). ### 9. Commit ```bash @@ -110,6 +119,7 @@ Output the report (see format below) and make zero additional tool calls. - **Exception:** If your changes break existing tests, update those test files even if not in "Files owned" - Use mocks/stubs for dependencies from other tasks - Report missing dependencies +- **Infra tasks** typically own: `Dockerfile`, `docker-compose.yml`, `.github/workflows/`, `Makefile`, `terraform/`, `k8s/`; build configs (`tsconfig.json`, `vite.config.*`, `webpack.config.*`, `rollup.config.*`); package manifests (`package.json`, `go.mod`, `Cargo.toml`, `build.gradle`, `pom.xml`); dev tooling (`.eslintrc`, `.prettierrc`, `.editorconfig`, husky/lint-staged). ## Build Tool Rules @@ -158,11 +168,7 @@ Minimize build invocations — each cold start adds 10-15s overhead. - X tests passed, Y failed, Z skipped ### Notes +- Test depth worked at: [deep | focused] - [Deviations from plan or issues discovered] - [Dependencies on other tasks] - -### Lessons (optional) -[Non-obvious codebase patterns worth remembering] - -**Pattern**: [what triggers it] | **Reason**: [why it happens] | **Solution**: [how to prevent it] ``` diff --git a/agents/planner.md b/agents/planner.md index c190e98..a09130e 100644 --- a/agents/planner.md +++ b/agents/planner.md @@ -17,7 +17,6 @@ You are a senior software architect. You take a feature specification, deeply un Before designing anything, understand what you're working with at execution-path depth. **Mandatory reads:** -- **`CLAUDE.md`** — check `## Lessons and Memory` for known pitfalls from previous runs - **`.devline/brainstorm.md`** — your primary input: feature spec, architecture impact, scope boundaries - **`.devline/design-system.md`** — if it exists, use as design constraints for UI tasks - **Existing codebase** — architecture, patterns, conventions, naming, test style @@ -121,8 +120,7 @@ Each task is a spec for one agent running in an isolated worktree. The plan must be **complete** (the implementer has all the context to understand the goal and constraints) but not **prescriptive** (don't write pseudocode or step-by-step instructions). Give the why, the what, and the boundaries — trust the implementer with the how. **Agent and model selection per task:** -- **implementer** — feature/application code (default) -- **devops** — build, CI/CD, Docker, infrastructure, tooling +- **implementer** — feature/application code (default); also handles build, CI/CD, Docker, infrastructure-as-code, and tooling (infra) tasks - **debugger** — fixing failing tests or unexpected behavior - **sonnet** (default) — standard tasks with clear specs - **opus** — complex architectural reasoning, large refactors, tricky logic, tasks touching many integration points diff --git a/agents/references/cloud-infra.md b/agents/references/cloud-infra.md new file mode 100644 index 0000000..5a41de3 --- /dev/null +++ b/agents/references/cloud-infra.md @@ -0,0 +1,210 @@ +# Cloud & Infrastructure Reference + +On-demand knowledge for infra tasks (build, CI/CD, Docker/containers, IaC, deployment). The implementer reads this when a task is infrastructure-flavored. Use the find-docs skill (`npx ctx7@latest`) for current cloud SDK and service docs. + +## Provider / Ecosystem Detection + +Before writing infra code, detect what the project uses: + +1. `terraform/`, `.tf` → Terraform/OpenTofu +2. `Dockerfile`, `docker-compose.yml` → Docker +3. `k8s/`, `kubernetes/`, Helm charts → Kubernetes +4. `serverless.yml` → Serverless Framework +5. `cdk.json` / `Pulumi.yaml` → CDK/Pulumi +6. `.github/workflows/` → GitHub Actions +7. `Jenkinsfile`, `.gitlab-ci.yml`, `azure-pipelines.yml` → other CI/CD +8. `.claude/devline.local.md` `cloud_provider` override + +Apply TDD to infra too: write a validation script or smoke test before the change (e.g., a test that the Docker image builds and starts before writing the Dockerfile). + +## Containerization + +**Dockerfile:** multi-stage builds; pin base image versions (not `latest`); order layers least→most frequently changing; `.dockerignore`; run as non-root; health checks in prod; one process per container. + +**Compose:** named volumes for persistence; networks for isolation; `.env` for config; pin image versions in prod. + +### Multi-stage Dockerfile (Node.js) +```dockerfile +FROM node:20-alpine AS builder +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +FROM node:20-alpine +WORKDIR /app +RUN addgroup -g 1001 app && adduser -u 1001 -G app -s /bin/sh -D app +COPY --from=builder /app/dist ./dist +COPY --from=builder /app/node_modules ./node_modules +USER app +EXPOSE 3000 +HEALTHCHECK CMD wget -q --spider http://localhost:3000/health || exit 1 +CMD ["node", "dist/index.js"] +``` + +### Multi-stage Dockerfile (Go) +```dockerfile +FROM golang:1.22-alpine AS builder +WORKDIR /app +COPY go.* ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -o server . + +FROM scratch +COPY --from=builder /app/server /server +EXPOSE 8080 +ENTRYPOINT ["/server"] +``` + +### Docker Compose +```yaml +services: + api: + build: . + ports: ["3000:3000"] + environment: + DATABASE_URL: postgres://user:pass@db:5432/app + depends_on: + db: { condition: service_healthy } + db: + image: postgres:16-alpine + environment: + POSTGRES_DB: app + POSTGRES_USER: user + POSTGRES_PASSWORD: pass + volumes: [pgdata:/var/lib/postgresql/data] + healthcheck: + test: pg_isready -U user -d app + interval: 5s + retries: 5 +volumes: + pgdata: +``` + +### Kubernetes (Deployment / Service / HPA) +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: { name: api } +spec: + replicas: 3 + selector: { matchLabels: { app: api } } + template: + metadata: { labels: { app: api } } + spec: + containers: + - name: api + image: api:latest + ports: [{ containerPort: 3000 }] + resources: + requests: { cpu: 100m, memory: 128Mi } + limits: { cpu: 500m, memory: 512Mi } + livenessProbe: { httpGet: { path: /health, port: 3000 } } + readinessProbe: { httpGet: { path: /ready, port: 3000 } } +--- +apiVersion: v1 +kind: Service +metadata: { name: api } +spec: + selector: { app: api } + ports: [{ port: 80, targetPort: 3000 }] +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: { name: api } +spec: + scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: api } + minReplicas: 2 + maxReplicas: 10 + metrics: + - type: Resource + resource: { name: cpu, target: { type: Utilization, averageUtilization: 70 } } +``` + +**Helm:** `values.yaml` for env-specific config; template deployment/service/ingress; `helm lint` before deploy; pin chart versions in prod. + +## Infrastructure as Code + +All infra in version-controlled code; modules/components for reuse; separate dev/staging/prod via variables; remote state (Terraform); plan before apply. + +**Security:** never hardcode credentials; IAM roles/service accounts over access keys; encrypt at rest and in transit; least privilege; enable audit logging. + +## CI/CD Pipelines + +Stages: Build → Test → Security (dep scan, SAST, secrets) → Package → Deploy → Verify (smoke/health). + +**Best practices:** fail fast (quick checks first); cache dependencies; env-specific config; rollback strategies; never deploy without tests passing; pin action versions to SHAs; short-lived tokens/OIDC; tag Docker images with commit SHA (not `latest`) in prod; store test reports/coverage as artifacts. + +### GitHub Actions (CI + Docker build/push) +```yaml +name: CI +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: { node-version: 20 } + - run: npm ci + - run: npm test + - run: npm run lint + docker: + needs: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: docker/login-action@v3 + with: { registry: ghcr.io, username: ${{ github.actor }}, password: ${{ secrets.GITHUB_TOKEN }} } + - uses: docker/build-push-action@v5 + with: { push: true, tags: "ghcr.io/${{ github.repository }}:${{ github.sha }}" } +``` + +### GitLab CI +```yaml +stages: [test, build, deploy] +test: + stage: test + image: node:20 + script: [npm ci, npm test, npm run lint] +build: + stage: build + image: docker:latest + services: [docker:dind] + script: + - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . + - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA +deploy: + stage: deploy + only: [main] + script: [echo "deploy command"] +``` + +## AWS Patterns + +**Common architectures:** Serverless (API Gateway → Lambda → DynamoDB/S3/SQS); Container (ALB → ECS Fargate → RDS/ElastiCache/S3); Full-stack (CloudFront → S3 static + ALB → ECS/EKS → RDS/ElastiCache). + +**CDK snippets:** +```typescript +const fn = new lambda.Function(this, 'Handler', { + runtime: lambda.Runtime.NODEJS_20_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('lambda'), + environment: { TABLE_NAME: table.tableName }, +}); +table.grantReadWriteData(fn); + +const api = new apigateway.RestApi(this, 'Api'); +api.root.addResource('items').addMethod('GET', new apigateway.LambdaIntegration(fn)); + +new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Service', { + taskImageOptions: { image: ecs.ContainerImage.fromAsset('./app'), environment: { DB_HOST: db.instanceEndpoint.hostname } }, + desiredCount: 2, +}); +``` + +**Security:** IAM roles not access keys; CloudTrail audit logging; Secrets Manager for credentials; KMS encryption at rest; VPC isolation; GuardDuty; least-privilege security groups. + +**Cost:** Savings Plans/Reserved for predictable load; Spot for fault-tolerant batch; right-size from CloudWatch; S3 lifecycle policies; billing alerts. diff --git a/agents/references/debugging.md b/agents/references/debugging.md new file mode 100644 index 0000000..06a560e --- /dev/null +++ b/agents/references/debugging.md @@ -0,0 +1,50 @@ +# Debugging Reference + +On-demand pattern recognition and tooling for the debugger. The core scientific process (Reproduce → Evidence → Hypothesize → Test → Fix → Verify) lives in the agent; this is the supplementary catalog. Use find-docs (`npx ctx7@latest`) for current docs on any tool here. + +## Common Bug Patterns (symptoms → causes → investigation) + +**Null / undefined** (`NullPointerException`, `TypeError: Cannot read properties of undefined`, `AttributeError: 'NoneType'`): uninitialized var used before assignment; error path returns null/undefined; optional field accessed without check; Promise not awaited; array index out of bounds. → Find the exact null variable, trace back to where it should be assigned, check every code path (is there one that skips assignment?), check for async timing gaps. + +**Off-by-one** (index out of bounds, missing first/last, loop runs ±1): `<` vs `<=`; 0- vs 1-indexed; fence-post (N items → N-1 separators); exclusive slice end. → Check index 0, length-1, length; trace the loop for 0, 1, 2 elements; confirm inclusive vs exclusive end. + +**Race conditions** (intermittent, works in debugger, different result each run): shared mutable state without synchronization; check-then-act without atomicity; ordering assumed without guarantees; stale closures. → Identify shared mutable state, check synchronization (mutex/lock/atomic/channel), log with timestamps + thread/goroutine IDs, use race detectors (`go test -race`, TSan). + +**Memory leaks** (growing memory, OOM, slowdown over time): listeners added never removed; cache without eviction; closures holding large objects; unclosed connections/handles/streams; circular references. → Profile over time, take heap snapshots at intervals, diff them for growing objects. + +**Deadlocks** (hang, no CPU, logs stop): mutual lock waits; channel send/receive with no counterpart; DB transaction lock contention. → Thread/goroutine dump, find blocked threads and what they wait on, check lock ordering consistency, check unbuffered channels with no receiver. + +**Serialization** (wrong types after parse, missing fields, date/encoding errors): JSON number precision loss (large ints in JS); timezone (UTC vs local); encoding mismatch (UTF-8 vs Latin-1); missing fields → null; field-name case sensitivity. → Log raw serialized data before parse, compare expected vs actual types, verify both sides agree on names/types. + +**Connection / timeout** (`ECONNREFUSED`, timeouts, intermittent 5xx): service not running; wrong host/port; pool exhausted; firewall/DNS/TLS. → Verify target reachable, check config, monitor pool metrics, look for connection leaks, test with curl/telnet. + +**Integration issues:** check API contracts (caller sends what callee expects); verify serialization; check timeouts/retries/error handling. + +**State management:** mutation where it shouldn't happen; stale closures/cached values/shallow copies; invalid state transitions. + +## Debugging Tools by Language + +**JS/TS:** `console.log/table/trace`, `debugger`, Chrome DevTools, `node --inspect`; `debug` package, `why-is-node-running`, `clinic.js`. Errors: `Cannot read properties of undefined` (trace to source), `X is not defined` (scope/import/spelling), unhandled rejection (missing `.catch`/`try`), `ECONNREFUSED` (service down/wrong port). + +**Python:** `breakpoint()` / `pdb`, `traceback.print_exc()`, `python -m pdb`; `ipdb`, `rich.traceback`, `py-spy` (sampling profiler, no code changes), `memory_profiler`. Errors: `AttributeError: 'NoneType'` (unexpected None), `ImportError` (path/venv/`__init__.py`), `KeyError` (use `.get()`), `IndentationError` (tabs vs spaces). + +**Go:** `fmt.Printf("%+v")`, `runtime/pprof`, `runtime.Stack()`; `dlv` (Delve), `go test -race`, `go vet`, `go tool pprof -http=:8080`. Errors: nil pointer deref (check pointer returns), deadlock (channel/mutex), data race (`-race`). + +**Java/Kotlin:** IDE debugger, `jstack ` thread dumps, `-verbose:gc`; VisualVM, JProfiler, Arthas, async-profiler. Errors: NPE (Optional/null safety), `ClassNotFoundException` (classpath), `OutOfMemoryError` (heap dump + MAT/VisualVM), `ConcurrentModificationException` (mutating while iterating). + +**Rust:** `dbg!()`, `println!("{:?}")`, `RUST_BACKTRACE=1`, `RUST_LOG=debug`; `rust-gdb`/`rust-lldb`, `cargo flamegraph`, `cargo clippy`, `miri`. Errors: borrow checker (restructure ownership or `Rc`/`Arc`), `unwrap()` panic (handle `Option`/`Result`), lifetime errors. + +## General Techniques + +**Git bisect** — binary-search the breaking commit: +```bash +git bisect start +git bisect bad # current is broken +git bisect good v1.0 # this worked +# test each checkout, mark good/bad +git bisect reset +``` + +**Rubber duck** — explain the problem step-by-step out loud; articulating often reveals it. + +**Structured printf** — print at function entry (inputs), decision points (conditions), and exit (outputs); remove all after fixing. diff --git a/agents/references/documentation.md b/agents/references/documentation.md new file mode 100644 index 0000000..bd3ecc8 --- /dev/null +++ b/agents/references/documentation.md @@ -0,0 +1,125 @@ +# Documentation Reference + +On-demand guidance for the docs-keeper: separate documentation files (README, API docs, architecture, guides). Inline code docs (JSDoc, docstrings) are the implementer's job — don't duplicate them. + +## Documentation Detection + +Before writing, check what exists: `docs/`, `README.md`, `CHANGELOG.md`; doc generators (`typedoc.json`, `mkdocs.yml`, `docusaurus.config.js`, `.readthedocs.yml`, javadoc); `.claude/devline.local.md` `doc_format` override. Match the existing format, style, and structure. + +## Writing Standards + +Present tense, active voice, second person ("Run the command"). Lead with the most important info; hierarchical headings. Code examples must be copy-pasteable, runnable, with language identifiers. Tables for structured reference data. Update what exists — only create new files when a genuinely new topic has no home. + +## Documentation Types + +**README** — name + one-line description; prerequisites/setup; quick start; commands (build/test/run); project structure; contributing (if OSS). +**API** — endpoint list (methods+paths); request/response schemas with examples; auth; error codes; rate limits/pagination. +**Architecture** — system overview + component diagram; data flow; key design decisions + rationale; tech stack; deployment. +**User guides** — getting-started tutorial; feature walkthroughs; FAQ/troubleshooting; config reference. + +## Templates + +### README +```markdown +# Project Name +One-line description. + +## Prerequisites +- [Requirement] (version X.Y+) + +## Quick Start +​```bash +git clone && cd project-name +[install command] +[run command] +​``` + +## Usage +### [Feature] +[Description and examples] + +## Development +### Setup / Testing / Building +​```bash +[commands] +​``` + +## Project Structure +​``` +src/ +├── [dir]/ # [Purpose] +└── [file] # [Purpose] +​``` + +## Contributing / License +``` + +### API Reference +```markdown +# API Reference + +## Authentication +[How to authenticate] + +## Endpoints +### Create [Resource] — `POST /api/resource` +**Request Body:** +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| name | string | Yes | Resource name | + +**Response:** `201 Created` +​```json +{ "id": "abc123", "name": "Example" } +​``` + +**Errors:** | Code | Description | — 400 Invalid input, 401 Unauthorized + +### List [Resources] — `GET /api/resources?page=1&limit=20` +**Query Parameters:** | Parameter | Type | Default | Description | — page (int, 1), limit (int, 20) +``` + +### Architecture +```markdown +# Architecture Overview + +## System Diagram +[Description or ASCII diagram] + +## Components +### [Component] +- **Purpose / Technology / Key files:** ... + +## Data Flow +1. [User action] → 2. [Processing] → 3. [Response] + +## Design Decisions +| Decision | Choice | Rationale | +|----------|--------|-----------| +| Database | PostgreSQL | ACID needed for financial data | + +## Deployment +[How/where deployed] +``` + +### Changelog (Keep a Changelog style) +```markdown +# Changelog +## [Unreleased] +### Added / Changed / Fixed / Removed +- ... +## [1.0.0] - 2024-01-15 +### Added +- Initial release +``` + +### ADR +Follow the project's existing ADR format. If none: **Status, Date, Context, Decision, Rationale, Consequences**. + +## Documentation Tools + +**Static site generators:** MkDocs (`mkdocs.yml`, Material theme, `mkdocs serve`); Docusaurus (`docusaurus.config.js`, versioning/i18n/search, MDX); VitePress (`.vitepress/config.js`, Vue-powered, fast HMR). + +**API docs:** OpenAPI/Swagger (`openapi.yaml`; Swagger UI, Redoc, Stoplight; generate client SDKs); TypeDoc (`typedoc.json`, from TSDoc); Javadoc (`@param`/`@return`/`@throws`); Godoc (first sentence = summary); Rustdoc (`cargo doc`, runs doc tests). + +**Inline doc formats** (implementer's responsibility — for reference): JSDoc (`@param {type} name - desc`, `@returns`, `@throws`); Python docstrings (Args/Returns/Raises); KDoc (`@param name`, `@return`, `@throws`). diff --git a/agents/references/frontend-output-templates.md b/agents/references/frontend-output-templates.md index b662fed..8b5317f 100644 --- a/agents/references/frontend-output-templates.md +++ b/agents/references/frontend-output-templates.md @@ -1,5 +1,59 @@ # Frontend Planner — Output Templates +Fill these skeletons and write them to the paths shown. Four tables recur across skeletons — they are defined ONCE here as **canonical**; each skeleton names the subset/delta it uses instead of repeating them. + +## Canonical Tables + +### Semantic Color Palette (16 roles) +| Role | Light | Dark | Usage | +|------|-------|------|-------| +| Primary | #xxx | #xxx | Interactive elements, CTAs, links | +| On Primary | #xxx | #xxx | Text/icons on primary | +| Secondary | #xxx | #xxx | Supporting elements | +| On Secondary | #xxx | #xxx | Text/icons on secondary | +| Accent | #xxx | #xxx | Highlights, badges, notifications | +| On Accent | #xxx | #xxx | Text/icons on accent | +| Background | #xxx | #xxx | Page background | +| Foreground | #xxx | #xxx | Default text | +| Card | #xxx | #xxx | Card/panel surfaces | +| Card Foreground | #xxx | #xxx | Text on cards | +| Muted | #xxx | #xxx | Disabled, secondary surfaces | +| Muted Foreground | #xxx | #xxx | Secondary/placeholder text | +| Border | #xxx | #xxx | Borders, dividers | +| Destructive | #xxx | #xxx | Error, danger | +| On Destructive | #xxx | #xxx | Text on destructive | +| Ring | #xxx | #xxx | Focus rings | + +Deltas: **Brand identity** adds two rows — Success and Warning (Light/Dark/Usage). A **color-theme** spec uses a 12-role subset (Primary, On Primary, Secondary, On Secondary, Accent, Background, Foreground, Card, Muted, Border, Destructive, Ring). A **component** spec uses only the component-scoped tokens it needs (see Component Spec). The **design-system** doc lists these roles single-mode as `| Role | Hex | Usage |`. + +### States & Variants +| State | Background | Border | Text | Shadow | Transform | +|-------|-----------|--------|------|--------|-----------| +| Default | ... | ... | ... | ... | — | +| Hover | ... | ... | ... | ... | translateY(-1px) | +| Active | ... | ... | ... | ... | translateY(0) | +| Focus | ... | ... | ... | ring | — | +| Disabled | ... | ... | ... | none | — | + +### Motion & Animation +| Pattern | Duration | Easing | Usage | +|---------|----------|--------|-------| +| Hover lift | 200ms | ease-out | Cards, buttons | +| Press | 150ms | ease-in | Active state | +| Fade in | 200ms | ease-out | Appearing elements | +| Slide in | 300ms | ease-out | Panels, drawers | +| Stagger | 50ms per item | ease-out | Lists, grids | + +**Reduced motion:** all animations collapse to opacity-only or instant transitions. + +### Contrast Verification +| Pair | Light Ratio | Dark Ratio | WCAG AA | WCAG AAA | +|------|------------|------------|---------|----------| +| Foreground / Background | X:1 | X:1 | PASS/FAIL | PASS/FAIL | +| On Primary / Primary | X:1 | X:1 | PASS/FAIL | PASS/FAIL | + +--- + ## Component Spec (`.devline/component-spec.md`) ```markdown @@ -9,7 +63,7 @@ **Generated:** [date] ## Color Tokens -[ONLY the tokens this component needs] +[ONLY the component-scoped tokens this component needs — not the full palette] | Token | Light | Dark | Usage | |-------|-------|------|-------| @@ -21,35 +75,22 @@ | --component-focus-ring | #xxx | #xxx | Focus ring | ## Typography -[Only if relevant] -- Font: [name] — [why it fits] -- Size: [value] | Weight: [value] | Line-height: [value] +[Only if relevant] Font: [name] — [why] | Size / Weight / Line-height: [values] ## States & Variants -| State | Background | Border | Text | Shadow | Transform | -|-------|-----------|--------|------|--------|-----------| -| Default | ... | ... | ... | ... | — | -| Hover | ... | ... | ... | ... | translateY(-1px) | -| Active | ... | ... | ... | ... | translateY(0) | -| Focus | ... | ... | ... | ring | — | -| Disabled | ... | ... | ... | none | — | +Canonical States & Variants table (above). ## Animation -- **Interaction**: [specific animation with timing] -- **Library**: [CSS only / Motion / etc.] -- **Reduced motion**: [fallback behavior] +Canonical Motion & Animation table (above) — list only the patterns this component uses. Library: [CSS only / Motion / etc.]. Reduced motion: [fallback]. ## CSS Implementation -[Complete CSS with all states, using tokens above] +[Complete CSS with all states, using the tokens above] ## Accessibility -- Touch target: [size] -- Focus indicator: [description] -- ARIA: [required attributes] -- Contrast: [ratio for each text/bg pair] +- Touch target: [size] | Focus indicator: [description] | ARIA: [attributes] | Contrast: [ratio per text/bg pair] ## Preview -Open `.devline/component-preview.html` to see the component in context. +Open `.devline/component-preview.html`. ``` ## Color Theme Spec (alternative component-spec format) @@ -61,38 +102,21 @@ Open `.devline/component-preview.html` to see the component in context. **Generated:** [date] ## Palette - -| Role | Light Mode | Dark Mode | Usage | -|------|-----------|-----------|-------| -| Primary | #xxx | #xxx | Interactive elements, CTAs | -| On Primary | #xxx | #xxx | Text/icons on primary | -| Secondary | #xxx | #xxx | Supporting elements | -| On Secondary | #xxx | #xxx | Text/icons on secondary | -| Accent | #xxx | #xxx | Highlights, badges | -| Background | #xxx | #xxx | Page background | -| Foreground | #xxx | #xxx | Default text | -| Card | #xxx | #xxx | Card surfaces | -| Muted | #xxx | #xxx | Disabled, secondary surfaces | -| Border | #xxx | #xxx | Borders, dividers | -| Destructive | #xxx | #xxx | Error, danger | -| Ring | #xxx | #xxx | Focus rings | +Canonical Semantic Color Palette (above), 12-role subset. ## Contrast Verification -| Pair | Ratio | WCAG AA | WCAG AAA | -|------|-------|---------|----------| -| Foreground on Background | X:1 | PASS/FAIL | PASS/FAIL | -| On Primary on Primary | X:1 | PASS/FAIL | PASS/FAIL | +Canonical Contrast Verification table (above). ## CSS Variables -```css +​```css :root { /* Light */ } .dark { /* Dark */ } -``` +​``` ## Tailwind Config -```js +​```js [Tailwind theme extension] -``` +​``` ``` ## Harmonized Component Spec (`.devline/component-spec.md`) @@ -119,13 +143,13 @@ Open `.devline/component-preview.html` to see the component in context. [ONLY if the component requires something not in the project's theme — ideally empty] ### States & Animation -[Using the project's existing transition timing and patterns] +Canonical States & Variants + Motion & Animation tables (above), using the project's existing transition timing and patterns. ### CSS / Component Code [Uses existing project tokens exclusively] ## Preview -Open `.devline/harmonize-preview.html` +Open `.devline/harmonize-preview.html`. ``` ## Extension Spec (appended to `.devline/design-system.md`) @@ -141,10 +165,10 @@ Open `.devline/harmonize-preview.html` | Token | Value | Usage | ### Component Spec -[States, variants, CSS — using existing tokens where possible] +States/variants and CSS — canonical States & Variants table (above), using existing tokens where possible. ### Animation -[New animation if needed, or reference to existing] +Canonical Motion & Animation table (above) — new pattern if needed, else reference an existing one. ### Integration Notes [How this connects to existing components] @@ -155,62 +179,37 @@ Open `.devline/harmonize-preview.html` ```markdown # Brand Identity: [Project Name] -**Created:** [date] -**Last Updated:** [date] -**Product Type:** [category] -**Platform:** [web/mobile/desktop] — [framework] +**Created:** [date] | **Last Updated:** [date] +**Product Type:** [category] | **Platform:** [web/mobile/desktop] — [framework] ## Brand Personality [2-3 sentences] ## Style Direction -**Primary Style:** [style name] — [rationale] -**Secondary Style:** [complement/contrast] +**Primary Style:** [name] — [rationale] | **Secondary Style:** [complement/contrast] ## Color System - ### Semantic Tokens -| Role | Light Mode | Dark Mode | Usage | -|------|-----------|-----------|-------| -| Primary | #xxx | #xxx | Interactive elements, CTAs, links | -| On Primary | #xxx | #xxx | Text/icons on primary | -| Secondary | #xxx | #xxx | Supporting elements | -| On Secondary | #xxx | #xxx | Text/icons on secondary | -| Accent | #xxx | #xxx | Highlights, badges, notifications | -| On Accent | #xxx | #xxx | Text/icons on accent | -| Background | #xxx | #xxx | Page background | -| Foreground | #xxx | #xxx | Default text | -| Card | #xxx | #xxx | Card/panel surfaces | -| Card Foreground | #xxx | #xxx | Text on cards | -| Muted | #xxx | #xxx | Disabled, secondary surfaces | -| Muted Foreground | #xxx | #xxx | Secondary/placeholder text | -| Border | #xxx | #xxx | Borders, dividers | -| Destructive | #xxx | #xxx | Error, danger | -| On Destructive | #xxx | #xxx | Text on destructive | -| Ring | #xxx | #xxx | Focus rings | +Canonical Semantic Color Palette (above), all 16 roles, PLUS two brand rows: | Success | #xxx | #xxx | Success states | | Warning | #xxx | #xxx | Warning states | ### Contrast Verification -| Pair | Light Ratio | Dark Ratio | WCAG AA | -|------|------------|------------|---------| -| Foreground / Background | X:1 | X:1 | PASS | +Canonical Contrast Verification table (above). ### CSS Variables -```css +​```css :root { --primary: [hsl]; /* ... */ } .dark { --primary: [hsl]; /* ... */ } -``` +​``` ### Tailwind Config -```js +​```js colors: { primary: 'hsl(var(--primary))', /* ... */ } -``` +​``` ## Typography -**Heading Font:** [name] — [mood, weight range] -**Body Font:** [name] — [mood, weight range] -**Mono Font:** [name] — [for code/data] +**Heading / Body / Mono Font:** [name] — [mood, weight range] each ### Type Scale | Level | Size | Weight | Line Height | Letter Spacing | Usage | @@ -225,9 +224,9 @@ colors: { primary: 'hsl(var(--primary))', /* ... */ } | Tiny | 0.75rem | 500 | 1.4 | 0.02em | Badges, overlines | ### Google Fonts Import -```css +​```css @import url('[url]'); -``` +​``` ## Spacing System | Token | Value | Usage | @@ -257,27 +256,14 @@ colors: { primary: 'hsl(var(--primary))', /* ... */ } | --shadow-lg | [value] | Modals, floating elements | ## Motion & Animation -**Library:** [CSS only / Motion / GSAP] -**Base timing:** [e.g., 200ms ease-out] - -| Pattern | Duration | Easing | Usage | -|---------|----------|--------|-------| -| Hover lift | 200ms | ease-out | Cards, buttons | -| Press | 150ms | ease-in | Active state | -| Fade in | 200ms | ease-out | Appearing elements | -| Slide in | 300ms | ease-out | Panels, drawers | -| Stagger | 50ms per item | ease-out | Lists, grids | - -**Reduced motion:** All animations collapse to opacity-only or instant transitions. +**Library:** [CSS only / Motion / GSAP] | **Base timing:** [e.g., 200ms ease-out] +Canonical Motion & Animation table (above). ## Anti-Patterns [Product-specific anti-patterns from reasoning rules] ## Component Index -- [Button](components/button.md) -- [Card](components/card.md) -- [Input](components/input.md) -- [Badge](components/badge.md) +- [Button](components/button.md) · [Card](components/card.md) · [Input](components/input.md) · [Badge](components/badge.md) ``` ## Brand Component Spec (`design-system/components/[name].md`) @@ -292,10 +278,7 @@ colors: { primary: 'hsl(var(--primary))', /* ... */ } [List all variants with token mappings] ## States -| State | Background | Border | Text | Shadow | Transform | -|-------|-----------|--------|------|--------|-----------| -| Default | var(--primary) | — | var(--on-primary) | var(--shadow-sm) | — | -| Hover | [derived] | — | var(--on-primary) | var(--shadow-md) | translateY(-1px) | +Canonical States & Variants table (above), with cells referencing BRAND.md tokens (e.g. Default bg = var(--primary), text = var(--on-primary), shadow = var(--shadow-sm)). ## Sizes | Size | Padding | Font Size | Min Height | Icon Size | @@ -316,29 +299,18 @@ colors: { primary: 'hsl(var(--primary))', /* ... */ } ```markdown # Design System — [Feature Name] -**Product Type:** [matched category] -**Platform:** [web/mobile/desktop] — [framework] +**Product Type:** [matched category] | **Platform:** [web/mobile/desktop] — [framework] **Generated:** [date] ## Style Direction -**Primary Style:** [style name] — [why it fits] -**Secondary Style:** [style name] — [complement/contrast] -**Layout Pattern:** [recommended pattern] +**Primary Style:** [name] — [why] | **Secondary Style:** [complement] | **Layout Pattern:** [recommended] ## Color Palette -| Role | Hex | Usage | -|------|-----|-------| -| Primary | #XXXXXX | [usage] | -| On Primary | #XXXXXX | Text/icons on primary | -| [... full 16-role palette ...] | - -**Color Mood:** [from reasoning rules] -**Notes:** [contrast, WCAG compliance] +Canonical Semantic Color Palette (above), 16 roles, single-mode: `| Role | Hex | Usage |`. +**Color Mood:** [from reasoning rules] | **Notes:** [contrast, WCAG compliance] ## Typography -**Heading Font:** [name] — **Body Font:** [name] -**Google Fonts Import:** `@import url('[url]');` -**Tailwind Config:** [font config] +**Heading / Body Font:** [names] | **Google Fonts Import:** `@import url('[url]');` | **Tailwind Config:** [font config] ## Key Effects [Animation and transition recommendations] diff --git a/agents/references/plan-format.md b/agents/references/plan-format.md index 006d0e8..8b566ce 100644 --- a/agents/references/plan-format.md +++ b/agents/references/plan-format.md @@ -7,6 +7,7 @@ **Created:** [ISO 8601 date] **Status:** active **Phase:** [N of M — or "single" for non-phased plans] +**Test Depth:** [deep | focused — carried from the brainstorm] ## Architecture Overview [High-level design: components, data flow, key abstractions. Component diagram if helpful.] @@ -16,6 +17,19 @@ |----------|--------|-----------|------------------------| | ... | ... | ... | ... | +## Test Depth + +Carried from the brainstorm; drives how test cases are generated per task. Two levels: + +- **deep** — exhaustive: a unit test per method plus edge cases and all configs, plus integration and E2E. This is the current default thoroughness. +- **focused** — big behavior tests over whole classes/workflows plus targeted tests for genuinely hard logic; integration/E2E for real journeys; SKIP exhaustive per-method unit tests for trivial code (getters, passthroughs, obvious branches). + +Generate each task's Test Cases per depth: +- **deep** — per-method units + edge cases + integration + E2E. +- **focused** — one test per acceptance criterion (workflow/class level) + units only for genuinely hard logic. + +The acceptance criteria from `.devline/brainstorm.md` map **1:1** to the feature/acceptance tests: each criterion becomes exactly one behavior/workflow-level test, named to read as the criterion. The final wave SHOULD still include an E2E task for real journeys (see Feature E2E Task); per-test `[unit]`/`[integration]`/`[e2e]` tagging and the integration size-gate are unchanged under either depth. + ## Dependency Graph This is the SINGLE SOURCE OF TRUTH for task ordering. Everything about which tasks run when, what depends on what, and which tasks can parallelize is defined here and ONLY here. @@ -33,7 +47,7 @@ Rules enforced by the orchestrator: ## Tasks ### Task 1: [Name] -**Agent:** [implementer / devops / debugger] +**Agent:** [implementer / debugger] **Model:** [sonnet (default) / opus — use opus for tasks requiring complex architectural reasoning, large refactors, or tricky logic] **UI:** [yes / no] **Files owned:** [exact list of files this task creates/modifies] @@ -70,7 +84,7 @@ For UI tasks, additionally specify: ## Feature E2E Task -The final wave MUST include a dedicated E2E test task. This task writes no implementation code — only end-to-end tests that verify the feature works as a whole, including interactions with pre-existing code. +The final wave SHOULD include a dedicated E2E task ONLY for features with a genuine multi-step cross-boundary journey; skip it for single-component changes, pure-logic changes, and bugfixes (per-task integration tests already cover that surface). When included, this task writes no implementation code — only end-to-end tests that verify the feature works as a whole, including interactions with pre-existing code. ### Task N: Feature E2E Tests **Agent:** implementer diff --git a/agents/reviewer.md b/agents/reviewer.md index 534f30c..0ba2e29 100644 --- a/agents/reviewer.md +++ b/agents/reviewer.md @@ -1,6 +1,6 @@ --- name: reviewer -description: "Use this agent to review implemented code for correctness, security, performance, and quality. Provides actionable feedback with file:line references. Runs after each task implementation.\n\n\nContext: Implementer finished a task\nuser: \"Implementation of the auth module is done, review it\"\nassistant: \"I'll use the reviewer agent to review the auth module.\"\n\n" +description: "Use this agent to review implemented code for correctness, security, performance, and quality. Provides actionable feedback with file:line references. Default `scope: task` runs after each task implementation; `scope: branch` is the final merge-readiness gate over the whole branch (launch it with model opus).\n\n\nContext: Implementer finished a task\nuser: \"Implementation of the auth module is done, review it\"\nassistant: \"I'll use the reviewer agent to review the auth module.\"\n\n\n\nContext: All tasks implemented and task-reviewed\nuser: \"Everything is reviewed, do the final deep review\"\nassistant: \"I'll use the reviewer agent with scope: branch for the final quality gate.\"\n\n" tools: Read, Grep, Glob, Bash, Skill model: sonnet @@ -10,159 +10,124 @@ skills: kb-blast-radius, find-docs You are a senior software engineer performing code review. You catch real issues — correctness, security, performance, integration — with specific, actionable feedback. -## Review Process - -1. **Understand Context** - - Read `CLAUDE.md` — check `## Lessons and Memory` for known codebase pitfalls from previous runs. Use these as additional review checkpoints — if a lesson describes a pattern, verify the implementation avoids it. - - Read `.devline/plan.md` — find the task being reviewed - - Read its **Spec** (signatures, behavior, inputs, outputs, errors, integration points), Acceptance Criteria, and Test Cases - - Understand what the code is supposed to do - -2. **Correctness Review** - - Does the logic match the requirements? - - Are edge cases handled? - - Are error paths covered? - - Do the tests actually test meaningful behavior (not just coverage)? - - Are there logic errors, off-by-one, or race conditions? - -3. **Spec Compliance & Integration** - Read the task's Spec from the plan. Verify: - - **Signatures and behavior** match the spec — correct parameter types, return types, and step-by-step behavior - - **Error handling** matches the spec — each error case handled as specified (throw, return error, log, retry) - - **Integration points:** For each integration point in the spec, verify the call/event/hook exists in code. `grep` the codebase to verify the other side exists too — a declaration without a callsite is a dead integration. Flag as blocking. - - **Observer/event chains:** For every state change, verify the required notify/emit/dispatch calls are present. A state change without notification is the #1 silent integration failure. - - **Lifecycle integration:** New components must register with existing lifecycle (init, update, cleanup). Verify they do. - - **Constraints:** If the spec lists platform limitations or framework quirks, verify the implementation respects them. - -4. **Security Review** - - Input validation on all external data - - No SQL injection, XSS, command injection vulnerabilities - - No hardcoded secrets or credentials - - Proper authentication/authorization checks - - Safe handling of sensitive data (no logging secrets) - - Secure defaults (HTTPS, encrypted storage) - - **Authorization scope verification (multi-tenant):** If the endpoint accepts a scope identifier from the URL path (e.g., `orgId`, `tenantId`), verify it is validated against the authenticated identity (JWT/session) — not trusted from the path alone. Path-variable scope without identity cross-check enables cross-tenant access. - - **Public endpoint identity safety:** If a public (unauthenticated) endpoint creates persistent records, verify it cannot accept caller-supplied identity fields (userId, email) that would enable impersonation. Identity must come from a verified source (JWT, session, server-side lookup). - - **Scope parameter completeness:** For scoped data access (multi-tenant, org-scoped), verify repository queries include the scope parameter explicitly — not relying solely on framework-level filters (Hibernate `@Filter`, row-level security) that may be inactive in background jobs, tests, or service-layer helpers. - -5. **Performance Review** - - No unnecessary database queries (N+1 problem) - - Appropriate use of caching - - No blocking operations in async contexts - - Efficient algorithms for the data size - - No memory leaks (unclosed resources, growing collections) - -6. **Code Quality Review** - - Follows existing codebase conventions - - Good naming (variables, functions, classes) - - Appropriate abstraction level - - No dead code or commented-out code - - Tests are maintainable and clear - -7. **Plan Compliance** - - Every acceptance criterion listed in the task — implemented AND tested - - No significant scope creep beyond the spec without justification - -8. **Test Assertion Quality** - Check for recurring anti-patterns that create false confidence: - - **Happy-path-only security tests:** Auth-protected code needs tests for both permitted AND forbidden roles - - **Weak assertions:** `.not.toBeNull()` or `.toBeDefined()` when a specific value should be asserted - - **Mocks masking real behavior:** Synchronous mocks of deferred operations (e.g., mocking `save()` when real code uses `saveAndFlush()`) - - **Presence-not-correctness:** Checking "X exists" instead of "X is correct" - - **Variant coverage gaps:** When a component has N variants (states, types, modes), verify each has at least one DOM-level assertion — not just the special-case variant. Weak assertions like import-absence or source-text checks on common variants are insufficient. - - **Overly broad source-level assertions:** "Does not contain X" tests using short tokens (e.g., `source.includes('Menu')`) will produce false positives as the codebase grows. The token must uniquely identify the construct being guarded — use `'{ Menu }'` or `"from 'lucide-react'"`, not the bare name. - - **Full-function mocks hiding internal bugs:** When a test mocks an entire function at the import boundary, property-access bugs inside the function are never exercised. For critical cross-cutting functions, verify at least one test exercises the real implementation. - -9. **Stale Artifact Detection** - When tasks create new files that replace or split existing ones: - - Check for duplicate class/component declarations across files - - Check for scaffold/placeholder files that should have been replaced - - Check for stale imports/references after file renames or splits - -10. **Run Tests (MANDATORY)** - - Execute the test suite once with `timeout: 300000` - - If you need failure details, read test report files (e.g., `build/reports/tests/`) instead of re-running - - **Any compilation error or test failure is automatically a BLOCKING finding.** The feature branch starts green — there are no "pre-existing" failures. Every failure on this branch was introduced by the implementation. Do not dismiss failures as "unrelated," "pre-existing," "from another task," or "a known issue." If it fails, it's blocking. - - For each failure, identify the cause: wrong implementation, incomplete change, or test that needs updating. Include this analysis in the finding. - - Verify coverage of critical paths +## Scope -## Output Format +The launcher passes one of two scopes: -```markdown -## Code Review: [Task / Description] +- **`scope: task`** (default) — review one just-implemented task from the plan. Runs after each task. +- **`scope: branch`** — the final merge-readiness gate over the whole branch, after every task is implemented and task-reviewed. **Launch this scope with model opus.** You are read-only; every task was already tested by its implementer and passed per-task review, so don't re-review single-file quality, naming, or correctness. Focus on what per-task review cannot see — the whole-branch picture in `## Branch scope`. Also run the shared review below, but consolidate rather than re-flag task-level findings. -### Verdict: CLEAN / HAS_BLOCKING / DEFERRED_ONLY +## Review Process (both scopes) -### Blocking Findings -[Findings that must be fixed before the task can be marked done] +1. **Understand context** — Read `.devline/plan.md`. For `scope: task`, find the task under review and read its **Spec** (signatures, behavior, inputs, outputs, errors, integration points), Acceptance Criteria, and Test Cases. For `scope: branch`, read the specs across all tasks. Also note the plan's `**Test Depth:**` header — it calibrates how strictly you assess test coverage (see **Test depth** below). Understand what the code is supposed to do. -1. **[Category]** `file:line` — [Description] - - **Severity:** [critical / warning] - - **Classification:** blocking - - **Why:** [Impact if not fixed] - - **Fix:** [Specific, concrete fix — "change line 42 to use atomic remove()"] +2. **Correctness** — Logic matches requirements; edge cases and error paths handled; no off-by-one or race conditions; tests exercise meaningful behavior, not just coverage. + +3. **Spec compliance & integration** — Against the task Spec, verify: + - Signatures, behavior, and error handling match the spec (correct types, each error case handled as specified). + - **Integration points:** for each one, `grep` that both sides exist — a declaration without a callsite is a dead integration (blocking). + - **Observer/event chains:** every state change fires the required notify/emit/dispatch. A state change without notification is the #1 silent integration failure. + - **Lifecycle:** new components register with existing lifecycle (init, update, cleanup). + - **Constraints:** implementation respects any platform/framework limitations the spec lists. + +4. **Security** + - Input validation on all external data; no SQL/NoSQL/command/template injection, XSS, or path traversal. + - No hardcoded secrets or credentials (including in test fixtures, mock data, comments); no secrets in logs; `.env` gitignored. + - Proper authn/authz on protected routes; no broken access control (can user A reach user B's data?); secure token handling (expiry, revocation); CSRF on state-changing ops; secure defaults (HTTPS, encrypted storage). + - **Authorization scope (multi-tenant):** a scope identifier from the URL path (`orgId`, `tenantId`) must be validated against the authenticated identity (JWT/session), not trusted from the path. + - **Public endpoint identity safety:** a public endpoint that creates records must not accept caller-supplied identity fields (userId, email) — identity comes from a verified source. + - **Scope parameter completeness:** scoped queries include the scope parameter explicitly, not relying solely on framework filters (Hibernate `@Filter`, RLS) that may be inactive in jobs/tests/helpers. + - Data exposure: error messages don't leak internals; CORS not overly permissive; security headers present (CSP, X-Frame-Options, HSTS); responses don't over-return data. + +5. **Performance** — No N+1 queries; appropriate caching; no blocking ops in async contexts; efficient algorithms for the data size; no leaks (unclosed resources, growing collections). + +6. **Code quality** — Follows codebase conventions; good naming; appropriate abstraction; no dead or commented-out code; tests maintainable and clear. + +7. **Plan compliance** — Every acceptance criterion implemented AND tested; no significant unjustified scope creep. + +8. **Test assertion quality** — Watch for false-confidence anti-patterns: + - **Happy-path-only security tests** — auth-protected code needs both permitted AND forbidden roles. + - **Weak assertions** — `.not.toBeNull()`/`.toBeDefined()` where a specific value should be checked. + - **Mocks masking reality** — sync mocks of deferred ops (mocking `save()` when code uses `saveAndFlush()`; async dispatch mocked as sync). + - **Presence-not-correctness** — checking "X exists" instead of "X is correct". + - **Variant coverage gaps** — N variants need at least one DOM-level assertion each, not just the special case. + - **Overly broad source-level assertions** — "does not contain X" with short tokens (`source.includes('Menu')`) false-positives as the codebase grows; the token must uniquely identify the construct (`'{ Menu }'`, `"from 'lucide-react'"`). + - **Full-function mocks hiding internal bugs** — mocking an entire function at the import boundary skips its internal property-access bugs; critical cross-cutting functions need at least one test exercising the real implementation. + +9. **Stale artifact detection** — When tasks add files that replace/split existing ones: duplicate class/component declarations across files; scaffold/placeholder files that should have been replaced; stale imports/references after renames or splits. + +10. **Run tests (MANDATORY)** — Execute the suite once with `timeout: 300000`. For failure detail, read report files (`build/reports/tests/`, `target/surefire-reports/`) instead of re-running. **No pre-existing failures: the branch starts green, so every compile error or test failure was introduced here — never dismiss one as "pre-existing," "unrelated," or "from another task." Any compile error or test failure is automatically BLOCKING.** For each failure, name the cause (wrong impl, incomplete change, or a test that needs updating) in the finding. + +## Test depth (both scopes) + +Read the plan's `**Test Depth:**` header and calibrate coverage expectations: + +- **deep** — current thoroughness stands: expect per-method units, edge cases, and all configs covered, plus integration/E2E. +- **focused** — do NOT flag "missing unit test for trivial method X" (getters, passthroughs, obvious branches) as an issue. Instead verify that (1) every acceptance criterion is covered by a behavior/workflow-level test, and (2) genuinely hard or edge logic has targeted tests. New I/O still needs its `[integration]` test and real journeys still need E2E — `focused` does not waive those. -### Deferred Findings -[Minor quality/style findings collected for batch-fix after all tasks complete] +## Branch scope (scope: branch only) +The final gate before merge. In addition to the shared review above, catch what only emerges when all tasks combine. These are **major/critical** findings. + +- **Cross-task integration sweep** — The #1 class of bugs per-task review misses: contracts spanning task boundaries where each side passes review in isolation but the connection is broken. From the plan's task specs, for each integration point: trace both sides (if Task A defines an event type and Task B should dispatch it, verify B's code contains the dispatch); `grep` for orphaned declarations (event types, interface methods, webhook names, enum values declared but never referenced from another file); verify listener/handler registration and that the trigger fires. +- **Feature-goal end-to-end trace** — Green unit tests mean nothing if the feature doesn't work. For each feature goal / acceptance criterion, trace the execution path from user action to result through every handler, observer, callback, and state update; confirm the chain is connected (A notifies B, B handles it). Run integration/E2E tests if they exist; if they should exist but don't, flag major. Check the plan's feature-goal tests were implemented and test what they claim. A goal not verifiably working end-to-end is major/critical even if all unit tests pass. +- **Branch-level architecture & cross-cutting** — Does the overall architecture match the plan's design decisions? New coupling points between tasks that harden future change? Consistent state management across tasks (one caches, another doesn't)? Code duplication **across tasks** (same pattern reimplemented in two tasks that could share a utility)? Race/ordering issues that only emerge when tasks interact? Also: run the project's dependency audit (`npm audit`, `pip-audit`, `cargo audit`) for CVEs in added/updated deps. + +## Output Format + +```markdown +## Review: [Task / Branch — Description] + +### Verdict: [see Verdicts below] + +### Findings 1. **[Category]** `file:line` — [Description] - - **Severity:** [warning / suggestion] - - **Classification:** deferrable + - **Severity:** [critical / warning / suggestion] + - **Classification:** [blocking / deferrable] ← task scope only; branch scope = all must fix - **Why:** [Impact if not fixed] - - **Fix:** [Specific suggestion] + - **Fix:** [Specific, concrete fix — e.g. "change line 42 to use atomic remove()"] ### Test Results -- X passed, Y failed -- [Details of any failures] +- X passed, Y failed — [details of any failures] ### Summary -[2-3 sentences on overall quality] - -### Lessons (optional) -[Non-obvious patterns about this codebase that would cause the same mistake in a different task.] - -**Pattern**: [what triggers it] | **Reason**: [why it happens] | **Solution**: [how to prevent it] +[2-3 sentences on overall quality / merge-readiness] ``` +For `scope: branch`, also include a Feature Goal Verification table (Goal | Verified PASS/FAIL | Evidence: end-to-end trace or test reference). + ## Verdicts -**Your output MUST end with exactly one of these lines (no extra text after it):** +**Your output MUST end with exactly one verdict line and no text after it.** + +**`scope: task`** — deferral allowed: ``` VERDICT: CLEAN VERDICT: HAS_BLOCKING VERDICT: DEFERRED_ONLY ``` +- **CLEAN** — Zero findings. Rare; look harder first. +- **HAS_BLOCKING** — At least one blocking finding; must be fixed before the task ships. +- **DEFERRED_ONLY** — Only minor findings; the task proceeds, they're batch-fixed later. -- **CLEAN** — Zero findings. Should be rare — look harder before declaring CLEAN. -- **HAS_BLOCKING** — At least one blocking finding. Must be fixed before the task ships. -- **DEFERRED_ONLY** — Only minor findings. The task proceeds — these are batch-fixed later. +**`scope: branch`** — no deferral (final gate; every finding must be fixed before merge): +``` +VERDICT: APPROVED +VERDICT: HAS_FINDINGS +``` +- **APPROVED** — Zero findings AND build/tests pass. Rare; look harder first. +- **HAS_FINDINGS** — Any finding (minor or major), OR build/test failure. The orchestrator sends findings to an implementer and re-runs you. You CANNOT return APPROVED if the build or tests fail. -If you are running low on turns, skip remaining review sections and produce the verdict with what you have. A partial review with a verdict is more useful than a thorough review that never produces one. +If you are running low on turns, skip remaining sections and produce the verdict with what you have — a partial review with a verdict beats a thorough one that never returns. The orchestrator relaunches you if you fail to return a verdict. -## Classification Guide +## Classification Guide (scope: task) -**Blocking** — fix now: -- **Any compilation error or test failure** — no exceptions, no "pre-existing" dismissals -- Correctness bugs, logic errors, race conditions -- Security vulnerabilities (injection, auth bypass, credential exposure) -- Spec violations, missing integration points, broken observer/event chains -- Missing tests for critical paths -- Missing acceptance criteria from the plan -- Performance issues causing visible degradation +**Blocking** — any compile error or test failure (no "pre-existing" dismissals); correctness bugs, logic errors, race conditions; security vulnerabilities (injection, auth bypass, credential exposure); spec violations, missing integration points, broken observer/event chains; missing tests for critical paths; missing acceptance criteria; performance issues causing visible degradation. -**Deferrable** — batch-fix later: -- Naming, code style, minor readability -- Documentation gaps -- Minor code quality (extract method, reduce duplication) -- Non-critical warnings -- Better patterns that aren't wrong as-is +**Deferrable** — naming, style, minor readability; documentation gaps; minor quality (extract method, reduce duplication); non-critical warnings; better-but-not-wrong patterns. -When in doubt, classify as blocking — false deferrals are worse than false blocks. +When in doubt, classify as blocking — false deferrals are worse than false blocks. (In `scope: branch` there is no deferral: classify each finding minor or major/critical, but ALL must be fixed. Inflating minor→major wastes pipeline resources; downgrading major→minor lets bugs through.) ## Re-review Discipline -When re-reviewing after a fix cycle, check only two things: -1. Were the previously reported blocking findings actually fixed? -2. Did the fix introduce new regressions or bugs? - -Genuinely new findings discovered during re-review go into **deferrable** unless they are security vulnerabilities or correctness bugs. The goal of re-review is convergence. +When re-reviewing after a fix cycle, check only: (1) were the previously reported blocking findings actually fixed? (2) did the fix introduce new regressions? Genuinely new findings go into deferrable unless they are security vulnerabilities or correctness bugs. The goal is convergence. diff --git a/hooks/hooks.json b/hooks/hooks.json index 74a7668..1054094 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -19,11 +19,6 @@ "type": "command", "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/validate-write.sh", "timeout": 10 - }, - { - "type": "command", - "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/enforce-branch.sh", - "timeout": 5 } ] } diff --git a/hooks/scripts/enforce-branch.sh b/hooks/scripts/enforce-branch.sh deleted file mode 100755 index 982d645..0000000 --- a/hooks/scripts/enforce-branch.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/bash -set -eo pipefail -trap 'exit 0' ERR - -# Devline workflow hook: enforce feature branch before code changes -# Blocks Write/Edit on protected branches for source code files -# Allows non-code files (docs, configs) to be edited directly on protected branches -# Reads configuration from .claude/devline.local.md if present - -input=$(cat) -file_path=$(printf '%s\n' "$input" | jq -r '.tool_input.file_path // empty' 2>/dev/null || true) -cwd=$(printf '%s\n' "$input" | jq -r '.cwd // empty' 2>/dev/null || true) - -if [[ -z "$file_path" || -z "$cwd" ]]; then - exit 0 -fi - -# Allow writes to .devline/ directory (pipeline artifacts) -if [[ "$file_path" == *"/.devline/"* || "$file_path" == ".devline/"* ]]; then - exit 0 -fi - -# Only enforce in git repositories -if ! git -C "$cwd" rev-parse --is-inside-work-tree &>/dev/null; then - exit 0 -fi - -# Defaults -ENFORCE_FEATURE_BRANCHES="false" -PROTECTED_BRANCHES='(main|master|develop|release|production|staging)' - -# Files allowed to be edited directly on protected branches -# Matches by extension and specific filenames -ALLOWED_EXTENSIONS='(md|txt|json|yaml|yml|toml|ini|cfg|conf|lock|gitignore|gitattributes|editorconfig|prettierrc|eslintrc|stylelintrc)' -ALLOWED_FILES='(README|LICENSE|CHANGELOG|CONTRIBUTING|CODE_OF_CONDUCT|SECURITY|CLAUDE|Makefile|Dockerfile|Procfile|Brewfile)' - -# Read overrides from devline.local.md -git_root=$(git -C "$cwd" rev-parse --show-toplevel 2>/dev/null || echo "$cwd") -LOCAL_MD="$git_root/.claude/devline.local.md" - -if [[ -f "$LOCAL_MD" ]]; then - FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$LOCAL_MD") - - custom_enforce=$(echo "$FRONTMATTER" | grep '^enforce_feature_branches:' | sed 's/enforce_feature_branches: *//' | sed 's/^"\(.*\)"$/\1/' || true) - if [[ -n "$custom_enforce" ]]; then - ENFORCE_FEATURE_BRANCHES="$custom_enforce" - fi - - custom_protected=$(echo "$FRONTMATTER" | grep '^protected_branches:' | sed 's/protected_branches: *//' | sed 's/^"\(.*\)"$/\1/' || true) - if [[ -n "$custom_protected" ]]; then - PROTECTED_BRANCHES="$custom_protected" - fi - - # Read additional allowed extensions from devline.local.md - custom_allowed=$(echo "$FRONTMATTER" | grep '^direct_edit_extensions:' | sed 's/direct_edit_extensions: *//' | sed 's/^"\(.*\)"$/\1/' || true) - if [[ -n "$custom_allowed" ]]; then - ALLOWED_EXTENSIONS="$custom_allowed" - fi -fi - -# Feature branch enforcement is opt-in (default: off) -# When off, users can freely edit and commit on protected branches — only push is blocked (by validate-bash.sh) -if [[ "$ENFORCE_FEATURE_BRANCHES" != "true" ]]; then - exit 0 -fi - -current_branch=$(git -C "$cwd" symbolic-ref --short HEAD 2>/dev/null || echo "") - -if [[ -z "$current_branch" ]]; then - exit 0 -fi - -# Only enforce on protected branches -if ! printf '%s\n' "$current_branch" | grep -qEi "^$PROTECTED_BRANCHES$"; then - exit 0 -fi - -# Extract filename from path -filename=$(basename "$file_path") -extension="${filename##*.}" - -# Allow files with permitted extensions -if [[ "$filename" != "$extension" ]] && printf '%s' "$extension" | grep -qEi "^$ALLOWED_EXTENSIONS$"; then - exit 0 -fi - -# Allow specific filenames (no extension or special names) -if printf '%s' "$filename" | grep -qEi "^$ALLOWED_FILES$"; then - exit 0 -fi - -# Allow dotfiles/configs at project root -if [[ "$filename" == .* && "$filename" != ".env" ]]; then - exit 0 -fi - -# Block: this is a source code file on a protected branch -branch_format="{kind}/{title}" -branch_kinds="feat, fix, refactor, docs, chore, test, ci" -commit_hint="Commits must use conventional format: kind(scope): details." - -if [[ -f "$LOCAL_MD" ]]; then - FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$LOCAL_MD") - custom_format=$(echo "$FRONTMATTER" | grep '^branch_format:' | sed 's/branch_format: *//' | sed 's/^"\(.*\)"$/\1/' || true) - custom_kinds=$(echo "$FRONTMATTER" | grep '^branch_kinds:' | sed 's/branch_kinds: *//' | sed 's/^"\(.*\)"$/\1/' | sed 's/|/, /g' || true) - custom_commit=$(echo "$FRONTMATTER" | grep '^commit_format:' | sed 's/commit_format: *//' | sed 's/^"\(.*\)"$/\1/' || true) - if [[ -n "$custom_format" ]]; then - branch_format="$custom_format" - fi - if [[ -n "$custom_kinds" ]]; then - branch_kinds="$custom_kinds" - fi - if [[ -n "$custom_commit" ]]; then - commit_hint="Commit convention: $custom_commit" - fi -fi - -branch_hint="git checkout -b . Format: $branch_format. Kinds: $branch_kinds." - -echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\"},\"systemMessage\":\"BLOCKED: Cannot edit source code on protected branch '$current_branch'. Create a feature branch first. $branch_hint $commit_hint\"}" >&2 -exit 2 diff --git a/hooks/scripts/validate-bash.sh b/hooks/scripts/validate-bash.sh index 1363598..50ce132 100755 --- a/hooks/scripts/validate-bash.sh +++ b/hooks/scripts/validate-bash.sh @@ -5,9 +5,11 @@ set -eo pipefail # rather than showing "hook error" to the user. Exit 0 = action proceeds. trap 'exit 0' ERR -# Devline security hook: validate Bash commands in bypass mode -# Blocks destructive, dangerous, and credential-leaking commands -# Reads configuration from .claude/devline.local.md if present +# Devline security hook: validate Bash commands in bypass mode. +# Guards against IRREVERSIBLE / destructive damage and credential exposure. +# Workflow-policy checks (commit-message format, protected-branch pushes, +# tags/releases, squash-merge, reset/clean/stash-drop) were removed on the +# scrub branch — this stops catastrophe, not process. input=$(cat) command=$(printf '%s\n' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null || true) @@ -35,55 +37,6 @@ ask() { exit 0 } -# ============================================================================= -# CONFIGURATION -# ============================================================================= - -# Defaults -PROTECTED_BRANCHES='(main|master|develop|release|production|staging)' -MERGE_STYLE="squash" - -# Read overrides from devline.local.md -if [[ -n "$cwd" ]]; then - git_root=$(git -C "$cwd" rev-parse --show-toplevel 2>&3 || echo "$cwd") - LOCAL_MD="$git_root/.claude/devline.local.md" - if [[ -f "$LOCAL_MD" ]]; then - FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$LOCAL_MD") - - # Read protected_branches as pipe-separated regex group: (main|master|custom) - custom_protected=$(echo "$FRONTMATTER" | grep '^protected_branches:' | sed 's/protected_branches: *//' | sed 's/^"\(.*\)"$/\1/' || true) - if [[ -n "$custom_protected" ]]; then - PROTECTED_BRANCHES="$custom_protected" - fi - - # Read merge_style: squash (default), merge, rebase - custom_merge=$(echo "$FRONTMATTER" | grep '^merge_style:' | sed 's/merge_style: *//' | sed 's/^"\(.*\)"$/\1/' || true) - if [[ -n "$custom_merge" ]]; then - MERGE_STYLE="$custom_merge" - fi - fi -fi - -# Helper: check if current branch is protected -on_protected_branch() { - if [[ -z "$cwd" ]]; then - return 1 - fi - local current - current=$(git -C "$cwd" symbolic-ref --short HEAD 2>&3 || echo "") - if [[ -z "$current" ]]; then - return 1 - fi - printf '%s' "$current" | grep -qPi "^$PROTECTED_BRANCHES$" -} - -# Helper: get current branch name -current_branch() { - if [[ -n "$cwd" ]]; then - git -C "$cwd" symbolic-ref --short HEAD 2>&3 || echo "" - fi -} - # ============================================================================= # DESTRUCTIVE FILESYSTEM OPERATIONS (always hard deny) # ============================================================================= @@ -130,7 +83,7 @@ if printf '%s' "$command" | grep -qPi '(mkfs|fdisk|dd\s+.*of=/dev)'; then fi # ============================================================================= -# GIT — ALWAYS BLOCKED (destructive regardless of branch) +# GIT — IRREVERSIBLE HISTORY / WORKING-COPY LOSS # ============================================================================= # Force push (--force, -f, --force-with-lease) @@ -138,133 +91,14 @@ if printf '%s' "$command" | grep -qPi 'git\s+push\s+.*(--force|--force-with-leas deny "Force push not allowed. Use normal push." fi -# git reset --hard -if printf '%s' "$command" | grep -qPi 'git\s+reset\s+--hard'; then - deny "git reset --hard is destructive. Use git stash or git checkout instead." -fi - -# git clean -f -if printf '%s' "$command" | grep -qPi 'git\s+clean\s+(-[a-zA-Z]*f|--force)'; then - deny "git clean -f deletes untracked files permanently. Not allowed." -fi - -# git checkout --force -if printf '%s' "$command" | grep -qPi 'git\s+checkout\s+--force'; then - deny "git checkout --force discards local changes. Not allowed." -fi - -# git stash drop/clear -if printf '%s' "$command" | grep -qPi 'git\s+stash\s+(drop|clear)'; then - deny "git stash drop/clear is destructive. Not allowed." -fi - -# ============================================================================= -# GIT — PROTECTED BRANCH OPERATIONS -# ============================================================================= - -# Block deleting protected branches (hard deny, both -d and -D) -if printf '%s' "$command" | grep -qP "git\s+branch\s+(-[a-zA-Z]*[dD])\s+$PROTECTED_BRANCHES(\s|$)"; then - deny "Deleting protected branch not allowed." -fi - -# git branch -D on non-protected branches: ask (squash-merged branches need force delete) -# git branch -d on non-protected branches: allow (safe delete, git checks merge status) -# Note: case-SENSITIVE match — -D only, not -d -# Exception: worktree-agent-* branches are temporary cleanup — always safe to force-delete -if printf '%s' "$command" | grep -qP 'git\s+branch\s+(-[a-zA-Z]*D)' && \ - ! printf '%s' "$command" | grep -qP 'git\s+branch\s+(-[a-zA-Z]*D)\s+worktree-agent-'; then - ask "Force-deleting a branch. This is needed after squash-merge since git can't verify the merge." +# Hard reset — discards uncommitted work irreversibly +if printf '%s' "$command" | grep -qPi 'git\s+reset\s+.*--hard'; then + deny "git reset --hard discards uncommitted work. Stash or commit first, or run it manually." fi -# Block push to protected branches -if printf '%s' "$command" | grep -qPi "git\s+push\s+(\S+\s+)?$PROTECTED_BRANCHES(\s|$|:)"; then - deny "Pushing to protected branch not allowed. Create a PR instead." -fi - -# Block force-creating/resetting protected branches -if printf '%s' "$command" | grep -qPi "git\s+checkout\s+-B\s+$PROTECTED_BRANCHES(\s|$)"; then - deny "Force-creating/resetting protected branch not allowed." -fi - -# Block rebase on protected branches -if printf '%s' "$command" | grep -qPi 'git\s+rebase' && on_protected_branch; then - deny "Rebasing on protected branch '$(current_branch)' not allowed." -fi - -# --- Merge into protected branches --- -if printf '%s' "$command" | grep -qPi "git\s+merge\s+" && on_protected_branch; then - branch=$(current_branch) - case "$MERGE_STYLE" in - squash) - if printf '%s' "$command" | grep -qPi 'git\s+merge\s+--squash\s'; then - ask "Squash-merging into protected branch '$branch'." - else - deny "Only squash merges allowed on protected branch '$branch'. Use: git merge --squash " - fi - ;; - merge) - if printf '%s' "$command" | grep -qPi 'git\s+merge\s+--no-ff\s'; then - ask "Merging into protected branch '$branch' with merge commit." - else - deny "Only --no-ff merges allowed on protected branch '$branch'. Use: git merge --no-ff " - fi - ;; - rebase) - deny "Merge not allowed on protected branch '$branch' with rebase merge style. Rebase the feature branch then fast-forward." - ;; - *) - ask "Merging into protected branch '$branch'." - ;; - esac -fi - -# ============================================================================= -# PIPELINE ARTIFACT PROTECTION -# ============================================================================= - -if printf '%s' "$command" | grep -qPi 'git\s+(add|stage)\s'; then - if printf '%s' "$command" | grep -qPi '(\.devline/|\.devline\s)'; then - deny "Pipeline artifacts (.devline/ directory) must never be staged or committed." - fi -fi - -# ============================================================================= -# COMMIT MESSAGE FORMAT -# ============================================================================= - -if printf '%s' "$command" | grep -qP 'git\s+commit\s+.*-m\s'; then - msg="" - if printf '%s' "$command" | grep -qP '\-m\s+"'; then - msg=$(printf '%s' "$command" | grep -oP '\-m\s+"\K[^"]+' | head -1) - elif printf '%s' "$command" | grep -qP "\-m\s+'"; then - msg=$(printf '%s' "$command" | grep -oP "\-m\s+'\K[^']+" | head -1) - fi - - # shellcheck disable=SC2016 - if [[ -n "$msg" && "$msg" != '$(cat'* && "$msg" != '$('* ]]; then - first_line=$(printf '%s' "$msg" | head -1 | sed 's/^[[:space:]]*//') - if [[ -n "$first_line" ]]; then - custom_regex="" - if [[ -n "$cwd" ]]; then - git_root=$(git -C "$cwd" rev-parse --show-toplevel 2>&3 || echo "$cwd") - LOCAL_MD="$git_root/.claude/devline.local.md" - if [[ -f "$LOCAL_MD" ]]; then - custom_regex=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$LOCAL_MD" | grep '^commit_format_regex:' | sed 's/commit_format_regex: *//' | sed 's/^"\(.*\)"$/\1/' || true) - fi - fi - - if [[ -n "$custom_regex" ]]; then - if ! printf '%s' "$first_line" | grep -qP "$custom_regex"; then - custom_desc=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$LOCAL_MD" | grep '^commit_format:' | sed 's/commit_format: *//' | sed 's/^"\(.*\)"$/\1/' || true) - deny "Commit message does not match project convention: ${custom_desc:-$custom_regex}" - fi - else - if ! printf '%s' "$first_line" | grep -qP '^(feat|fix|refactor|docs|chore|test|ci|style|perf|build|revert)(\([a-zA-Z0-9._-]+\))?: .+'; then - deny "Commit message must follow conventional format: kind(scope): details. Valid kinds: feat, fix, refactor, docs, chore, test, ci, style, perf, build, revert." - fi - fi - fi - fi +# git clean with a force flag — deletes untracked files irreversibly +if printf '%s' "$command" | grep -qPi 'git\s+clean\s+.*(--force|-\w*f)'; then + deny "git clean -f permanently deletes untracked files. Review with 'git clean -n' first, or run it manually." fi # ============================================================================= @@ -281,16 +115,8 @@ if printf '%s' "$command" | grep -qPi '(docker\s+push|podman\s+push|buildah\s+pu deny "Container image push not allowed autonomously. Run this manually." fi -# Git tags and releases -if printf '%s' "$command" | grep -qPi 'git\s+tag\s'; then - deny "Creating git tags not allowed autonomously. Run this manually." -fi -if printf '%s' "$command" | grep -qPi 'gh\s+release\s+create'; then - deny "Creating GitHub releases not allowed autonomously. Run this manually." -fi - # ============================================================================= -# GITHUB MUTATIONS (affects shared state) +# GITHUB SHARED-STATE MUTATIONS (affects state outside your working copy) # ============================================================================= # PR merge/close/reopen diff --git a/hooks/scripts/validate-write.sh b/hooks/scripts/validate-write.sh index 153650b..4890782 100755 --- a/hooks/scripts/validate-write.sh +++ b/hooks/scripts/validate-write.sh @@ -2,8 +2,10 @@ set -eo pipefail trap 'exit 0' ERR -# Devline security hook: validate Write/Edit operations in bypass mode -# Blocks writing credentials, secrets, and sensitive content to files +# Devline security hook: scan Write/Edit content for hardcoded secrets. +# Path-based blocks (system files, shell profiles, ssh config, .env writes) +# were removed on the scrub branch — those blocked legitimate dotfile/.env +# edits. This scans file CONTENT for credentials only. input=$(cat) file_path=$(printf '%s\n' "$input" | jq -r '.tool_input.file_path // empty' 2>/dev/null || true) @@ -19,26 +21,7 @@ if printf '%s\n' "$file_path" | grep -qEi '(/test/|/tests/|/__tests__/|\.test\.| is_test_file=true fi -# --- Block writing to sensitive system files --- - -if printf '%s\n' "$file_path" | grep -qEi '^/(etc|sys|proc|boot|usr/sbin)/'; then - echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny"},"systemMessage":"BLOCKED: Writing to system paths is not allowed in bypass mode."}' >&2 - exit 2 -fi - -# Block overwriting shell profiles -if printf '%s\n' "$file_path" | grep -qEi '(\.bashrc|\.zshrc|\.profile|\.bash_profile|\.zprofile)$'; then - echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny"},"systemMessage":"BLOCKED: Modifying shell profiles is not allowed in bypass mode."}' >&2 - exit 2 -fi - -# Block writing to SSH config -if printf '%s\n' "$file_path" | grep -qEi '\.ssh/(config|authorized_keys|known_hosts|id_)'; then - echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny"},"systemMessage":"BLOCKED: Modifying SSH configuration is not allowed in bypass mode."}' >&2 - exit 2 -fi - -# --- Block writing hardcoded secrets --- +# --- Block writing hardcoded secrets into source --- if [[ -n "$content" && "$is_test_file" != "true" ]]; then # Detect AWS access keys (AKIA pattern) @@ -81,14 +64,5 @@ if [[ -n "$content" && "$is_test_file" != "true" ]]; then fi fi -# --- Block writing to .env files (should use .env.example instead) --- - -if printf '%s\n' "$file_path" | grep -qE '\.env$' && ! printf '%s\n' "$file_path" | grep -qE '\.env\.(example|template|sample)$'; then - if [[ -n "$content" ]] && printf '%s\n' "$content" | grep -qEi '(KEY|SECRET|TOKEN|PASSWORD)\s*=\s*[^\s$]'; then - echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny"},"systemMessage":"BLOCKED: Writing secrets to .env file. Use .env.example with placeholder values instead."}' >&2 - exit 2 - fi -fi - # All checks passed exit 0 diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..5e1ed7f --- /dev/null +++ b/install.sh @@ -0,0 +1,236 @@ +#!/usr/bin/env bash +set -euo pipefail + +# devline one-command installer. +# +# Installs Claude Code (if missing), the devline plugin, and the recommended +# companions (RTK, Ponytail, Basic Memory). Cross-platform: Linux (apt, pacman, +# dnf, zypper, apk), macOS (Homebrew), and Windows via WSL or Git Bash. +# +# Safe to re-run — every step checks first, and optional steps warn-and-continue +# instead of aborting. Missing UNDERLYING tools (a package manager, uv, node, jq, +# git, gh, Claude Code) are offered before installing; the devline plugin and the +# companions install by default (gate them with --minimal / --skip-*). +# +# Review this script before running it. Usage: +# bash install.sh # everything (prompts before installing missing tools) +# bash install.sh --yes # assume "yes" to every prompt (non-interactive / CI) +# bash install.sh --minimal # devline only, no companions +# bash install.sh --skip-rtk --skip-ponytail --skip-memory # skip specific companions +# +# On Windows: run inside WSL (recommended) or Git Bash. No native PowerShell installer. + +# ---- flags ------------------------------------------------------------------ +MINIMAL=0; SKIP_RTK=0; SKIP_PONYTAIL=0; SKIP_MEMORY=0; ASSUME_YES=0 +for arg in "$@"; do + case "$arg" in + --minimal) MINIMAL=1 ;; + --skip-rtk) SKIP_RTK=1 ;; + --skip-ponytail) SKIP_PONYTAIL=1 ;; + --skip-memory) SKIP_MEMORY=1 ;; + -y|--yes) ASSUME_YES=1 ;; + -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; + *) echo "[devline] unknown option: $arg (ignored)" ;; + esac +done + +# ---- helpers ---------------------------------------------------------------- +log() { printf '[devline] %s\n' "$*"; } +warn() { printf '[devline] WARNING: %s\n' "$*" >&2; } + +# Run an optional step: warn and continue on failure, never abort the script. +step() { + local desc="$1"; shift + if "$@"; then return 0; else warn "$desc failed — continuing (see the tool's repo for manual install)."; return 0; fi +} + +# Ask before installing an underlying tool. Yes if --yes or no TTY; else prompt. +confirm() { + [ "$ASSUME_YES" -eq 1 ] && return 0 + [ -e /dev/tty ] || return 0 + local ans="" + printf '[devline] %s [Y/n] ' "$1" > /dev/tty + read -r ans < /dev/tty || return 0 + case "$ans" in [nN]|[nN][oO]) return 1 ;; *) return 0 ;; esac +} + +INSTALLED=(); NOTES=(); CLAUDE_JUST_INSTALLED=0 + +# sudo only when not already root and sudo exists. +SUDO="" +if [ "$(id -u 2>/dev/null || echo 0)" -ne 0 ] && command -v sudo >/dev/null 2>&1; then SUDO="sudo"; fi + +# ---- OS / package-manager detection ----------------------------------------- +OS="$(uname -s)" +PM="" +case "$OS" in + Darwin) command -v brew >/dev/null 2>&1 && PM=brew ;; + Linux) for c in apt-get pacman dnf zypper apk; do command -v "$c" >/dev/null 2>&1 && { PM="$c"; break; }; done ;; + MINGW*|MSYS*|CYGWIN*) for c in winget scoop choco pacman; do command -v "$c" >/dev/null 2>&1 && { PM="$c"; break; }; done ;; +esac + +# macOS with no Homebrew → offer to install it (the default PM there). +if [ "$OS" = "Darwin" ] && [ -z "$PM" ] && confirm "Homebrew is not installed (recommended on macOS). Install it now?"; then + step "install Homebrew" /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + for b in /opt/homebrew/bin/brew /usr/local/bin/brew; do [ -x "$b" ] && { eval "$("$b" shellenv)"; PM=brew; break; }; done +fi +log "OS: $OS, package manager: ${PM:-none detected}" + +# pkg_install — map to the detected PM and install. +pkg_install() { + local pkg="$1" m="$1" + case "$PM" in + apt-get) case "$pkg" in node) m=nodejs;; esac; $SUDO apt-get update -qq && $SUDO apt-get install -y "$m" ;; + pacman) case "$pkg" in node) m=nodejs;; gh) m=github-cli;; esac; $SUDO pacman -S --noconfirm "$m" ;; + dnf) case "$pkg" in node) m=nodejs;; esac; $SUDO dnf install -y "$m" ;; + zypper) case "$pkg" in node) m=nodejs;; esac; $SUDO zypper --non-interactive install "$m" ;; + apk) case "$pkg" in node) m=nodejs;; gh) m=github-cli;; esac; $SUDO apk add "$m" ;; + brew) case "$pkg" in node) m=node;; esac; brew install "$m" ;; + winget) case "$pkg" in git) m=Git.Git;; jq) m=jqlang.jq;; gh) m=GitHub.cli;; node) m=OpenJS.NodeJS;; uv) m=astral-sh.uv;; curl) m=cURL.cURL;; *) m="$pkg";; esac + winget install -e --id "$m" --accept-source-agreements --accept-package-agreements ;; + scoop) scoop install "$pkg" ;; + choco) choco install -y "$pkg" ;; + *) warn "no known package manager — install '$pkg' manually"; return 1 ;; + esac +} + +# ensure_tool — offer to install a missing underlying tool. +ensure_tool() { + local cmd="$1" human="$2" + command -v "$cmd" >/dev/null 2>&1 && { log "present: $cmd"; return 0; } + [ -n "$PM" ] || { warn "$human missing and no package manager detected — install it manually."; return 1; } + if confirm "$human is needed and missing. Install via $PM?"; then + step "install $human" pkg_install "$cmd"; command -v "$cmd" >/dev/null 2>&1 + else + return 1 + fi +} + +# uv — package manager first (widely packaged), official astral installer as fallback. +ensure_uv() { + command -v uv >/dev/null 2>&1 && { log "present: uv"; return 0; } + if [ -n "$PM" ] && confirm "uv (Python tool, needed for Basic Memory) is missing. Install via $PM?"; then + if step "install uv ($PM)" pkg_install uv && command -v uv >/dev/null 2>&1; then return 0; fi + warn "uv not available via $PM — falling back to the official installer." + fi + if confirm "Install uv via the official astral.sh installer?"; then + step "install uv (astral)" bash -c 'curl -LsSf https://astral.sh/uv/install.sh | sh' + export PATH="$HOME/.local/bin:$PATH"; command -v uv >/dev/null 2>&1 + else + return 1 + fi +} + +# ---- prerequisites ---------------------------------------------------------- +ensure_tool git "git" || warn "git is required for most devline features." +ensure_tool curl "curl" || true +ensure_tool jq "jq" || warn "jq is required by devline's hooks." +ensure_tool gh "GitHub CLI (gh)" || warn "gh is optional — needed for PR/issue features. https://cli.github.com/" + +# ---- Claude Code (official installer first, npm fallback) ------------------- +if command -v claude >/dev/null 2>&1; then + log "Claude Code already installed" +elif confirm "Claude Code is not installed. Install it (official installer)?"; then + step "install Claude Code" bash -c 'curl -fsSL https://claude.ai/install.sh | bash' + if ! command -v claude >/dev/null 2>&1 && command -v npm >/dev/null 2>&1; then + warn "official installer didn't put 'claude' on PATH — trying npm." + step "install Claude Code (npm)" bash -c 'npm install -g @anthropic-ai/claude-code' + fi + if command -v claude >/dev/null 2>&1; then CLAUDE_JUST_INSTALLED=1; NOTES+=("Run 'claude' once to authenticate (browser login)."); fi +fi + +have_claude() { command -v claude >/dev/null 2>&1; } +have_claude || warn "claude CLI not on PATH — skipping plugin/MCP steps. Re-run after installing + authenticating Claude Code." + +# ---- devline plugin (installs by default) ---------------------------------- +if have_claude; then + log "installing devline plugin" + claude plugin marketplace add Conava/claude-devline || true + claude plugin install devline@devline || true + INSTALLED+=("devline plugin") +fi + +# ---- RTK (official installer first, brew fallback) ------------------------- +if [ "$MINIMAL" -eq 0 ] && [ "$SKIP_RTK" -eq 0 ]; then + if command -v rtk >/dev/null 2>&1; then + log "RTK already installed"; INSTALLED+=("RTK (already present)") + else + log "installing RTK" + step "install RTK" bash -c 'curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh' + export PATH="$HOME/.local/bin:$PATH" + if ! command -v rtk >/dev/null 2>&1 && [ "$PM" = brew ]; then step "install RTK (brew)" bash -c 'brew install rtk-ai/tap/rtk'; fi + if command -v rtk >/dev/null 2>&1; then step "rtk init -g" rtk init -g; INSTALLED+=("RTK"); fi + fi +else + log "skipping RTK" +fi + +# ---- Ponytail plugin (installs by default) --------------------------------- +if [ "$MINIMAL" -eq 0 ] && [ "$SKIP_PONYTAIL" -eq 0 ]; then + if have_claude; then + log "installing Ponytail plugin" + claude plugin marketplace add DietrichGebert/ponytail || true + claude plugin install ponytail@ponytail || true + INSTALLED+=("Ponytail plugin") + fi +else + log "skipping Ponytail" +fi + +# ---- Basic Memory (installs by default; offers uv if missing) -------------- +if [ "$MINIMAL" -eq 0 ] && [ "$SKIP_MEMORY" -eq 0 ]; then + log "installing Basic Memory" + if ensure_uv; then + export PATH="$HOME/.local/bin:$PATH" + step "uv tool install basic-memory" uv tool install basic-memory + # Per-session MCP wrapper — quoted heredoc so nothing expands at write time. + mkdir -p "$HOME/.claude/mcp" + cat > "$HOME/.claude/mcp/basic-memory-cwd.sh" <<'WRAPPER' +#!/usr/bin/env bash +# Per-session Basic Memory MCP server, bound to the current repo's project. +# One stdio server per Claude session (in that session's cwd) → each session +# pins to its own repo via --project, so parallel sessions never clobber a +# shared "active project". +export PATH="$HOME/.local/bin:$PATH" +repo=$(git rev-parse --show-toplevel 2>/dev/null) +if [ -n "$repo" ]; then + name=$(basename "$repo") + if ! basic-memory project list 2>/dev/null | grep -qw "$name"; then + mkdir -p "$repo/memory" + basic-memory project add "$name" "$repo/memory" >/dev/null 2>&1 || true + fi + exec basic-memory mcp --project "$name" +fi +exec basic-memory mcp +WRAPPER + chmod +x "$HOME/.claude/mcp/basic-memory-cwd.sh" + log "wrote $HOME/.claude/mcp/basic-memory-cwd.sh" + if have_claude; then + claude mcp remove basic-memory >/dev/null 2>&1 || true + step "register basic-memory MCP" claude mcp add --scope user basic-memory -- bash "$HOME/.claude/mcp/basic-memory-cwd.sh" + claude plugin marketplace add basicmachines-co/basic-memory-plugins || true + claude plugin install basic-memory@basicmachines-co || true + fi + INSTALLED+=("Basic Memory (per-session MCP wrapper)") + else + warn "uv unavailable — skipped Basic Memory. Install uv, then re-run." + fi +else + log "skipping Basic Memory" +fi + +# ---- summary ---------------------------------------------------------------- +echo +log "===== install summary =====" +if [ "${#INSTALLED[@]}" -eq 0 ]; then + log "nothing new installed" +else + for item in "${INSTALLED[@]}"; do log "installed: $item"; done +fi +echo +log "Next steps:" +[ "$CLAUDE_JUST_INSTALLED" -eq 1 ] && log " 1. Run 'claude' once to authenticate (browser login)." +log " * Restart Claude Code so new MCP servers and plugins load." +log " * Run '/devline:setup' inside each project to configure it." +case "$OS" in MINGW*|MSYS*|CYGWIN*) log " * On Windows, WSL gives the smoothest experience if anything above failed." ;; esac +for note in "${NOTES[@]-}"; do [ -n "$note" ] && log " note: $note"; done diff --git a/release.sh b/release.sh deleted file mode 100755 index 8b2cc39..0000000 --- a/release.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Usage: ./release.sh -# Example: ./release.sh 0.3.0 -# -# Bumps version in plugin.json and marketplace.json, commits, tags, and pushes. - -if [ $# -ne 1 ]; then - echo "Usage: ./release.sh " - echo "Example: ./release.sh 0.3.0" - exit 1 -fi - -VERSION="$1" - -# Validate semver-ish format -if ! printf '%s' "$VERSION" | grep -qP '^\d+\.\d+\.\d+(-\w+(\.\w+)*)?$'; then - echo "Error: version must be semver (e.g., 0.3.0 or 1.0.0-beta.1)" - exit 1 -fi - -# Check for clean working tree -if [ -n "$(git status --porcelain)" ]; then - echo "Error: working tree is not clean. Commit or stash changes first." - exit 1 -fi - -# Check tag doesn't already exist -if git rev-parse "v$VERSION" >/dev/null 2>&1; then - echo "Error: tag v$VERSION already exists" - exit 1 -fi - -# Bump version in both JSON files -for f in .claude-plugin/plugin.json .claude-plugin/marketplace.json; do - jq --arg v "$VERSION" ' - if .version then .version = $v else . end | - if .plugins then .plugins |= map(if .version then .version = $v else . end) else . end - ' "$f" > tmp.json && mv tmp.json "$f" -done - -git add .claude-plugin/plugin.json .claude-plugin/marketplace.json -git commit -m "chore: release v$VERSION" -git tag "v$VERSION" -git push origin main --tags - -echo "Released v$VERSION" diff --git a/skills/brainstorm/SKILL.md b/skills/brainstorm/SKILL.md index 89012ba..aafa38f 100644 --- a/skills/brainstorm/SKILL.md +++ b/skills/brainstorm/SKILL.md @@ -61,7 +61,21 @@ Before writing the document, evaluate whether the feature warrants splitting int - Omit the `## Phases` section entirely — the brainstorm.md format is identical to today's output - This is the backward-compatible path; most features will take this path -### 4. Write Brainstorm Document +### 4. Establish Test Depth + +Decide how thorough the feature's tests should be — `deep` or `focused` — in this order: + +1. **Config wins silently.** If `.claude/devline.local.md` sets `test_depth` to `deep` or `focused`, use it and say nothing. +2. **Infer from signals.** Otherwise read the repo's existing test style AND the user's prompt: + - Repo: dense per-method unit tests on trivial code → lean `deep`; sparse, or integration/behavior-heavy → lean `focused`. + - Prompt: "production-grade", "thorough", "exhaustive" → `deep`; "quick", "prototype", "just wire it up" → `focused`. +3. **Ask only if still ambiguous.** One AskUserQuestion: + - question: "How thorough should tests be for this?" + - options: `Deep — every method & config` / `Focused — big workflow/class tests + hard logic, skip trivial-method tests` + +Record the chosen depth in the brainstorm output. + +### 5. Write Brainstorm Document After receiving answers (or immediately if the idea is clear enough), write `.devline/brainstorm.md`: @@ -92,6 +106,12 @@ After receiving answers (or immediately if the idea is clear enough), write `.de ### Out of Scope [Explicitly excluded items someone might assume are included] +## Acceptance Criteria +[Short list of behavioral, testable statements — "user can X", "invalid Y is rejected with Z". These are the spec: downstream, each one becomes a behavior test named to read as the criterion.] + +## Test Depth +[deep | focused — the value chosen in step 4, plus a one-line reason (config / inferred signal / user answer).] + ## Key Decisions [Decisions made during brainstorming, including user choices and stated assumptions] @@ -108,7 +128,7 @@ After receiving answers (or immediately if the idea is clear enough), write `.de [Architectural or design questions too deep for brainstorm. Leave empty if none.] ``` -### 5. Confirm +### 6. Confirm Use AskUserQuestion: ```json diff --git a/skills/cve-patcher/SKILL.md b/skills/cve-patcher/SKILL.md deleted file mode 100644 index a05651e..0000000 --- a/skills/cve-patcher/SKILL.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -name: cve-patcher -description: "Patch CVE vulnerabilities across one or many repositories. Invoke with a list of CVEs and optionally specific repo names. Researches each CVE (affected package, ecosystem, versions), then launches dependency-patcher agents to update, verify, commit, and push. Use this skill whenever the user mentions CVEs, security vulnerabilities in dependencies, patching dependencies, or updating packages for security fixes — even if they don't say 'CVE' explicitly but reference a security advisory or vulnerable dependency." -argument-hint: "CVE-2024-XXXXX CVE-2024-YYYYY [--repos repo1 repo2]" -user-invocable: true -disable-model-invocation: false ---- - -# CVE Patcher - -Orchestrates CVE vulnerability patching across one or many repositories. This is a launcher skill — it handles research and orchestration, then delegates the actual patching to **dependency-patcher** agents. - -## Step 1: Parse Input - -Extract from the user's arguments: - -- **CVEs**: Any argument matching `CVE-\d{4}-\d{4,}` (case-insensitive) -- **Repos**: If `--repos` is present, everything after it is a repository name. If not provided, auto-detect in Step 3. - -Examples: -``` -CVE-2024-38816 CVE-2024-22243 -CVE-2024-38816 --repos my-api billing-service -``` - -## Step 2: Research CVEs - -For each CVE, use **WebSearch** to gather: - -1. **Package name** and **ecosystem** (npm, Maven, pip, Go, Cargo, etc.) -2. **Affected version range(s)** -3. **Fixed version(s)** — the minimum version that resolves the vulnerability -4. **Severity** (CVSS score if available) -5. **Whether the fix crosses a major version boundary** - -Research multiple CVEs in parallel using separate WebSearch calls in the same message. - -Good queries: `"CVE-XXXX-XXXXX" affected versions fix`, NVD (`nvd.nist.gov`), GitHub Advisory Database. - -Present a summary table to the user before proceeding: - -``` -| CVE | Package | Ecosystem | Affected | Fix | Severity | Major? | -|------------------|------------------|-----------|------------------|-----------|----------|--------| -| CVE-2024-38816 | spring-webmvc | Maven | < 6.1.13 | 6.1.13 | High | No | -| CVE-2024-22243 | spring-web | Maven | < 6.1.4 | 6.1.4 | Medium | No | -``` - -If any CVE requires a **major version bump**, flag it and ask the user how to proceed before continuing. Do not include major-bump CVEs in the agent dispatch unless the user approves. - -## Step 3: Detect Repositories - -Determine the working context: - -1. **Single repo**: Current directory has `.git/` → patch it directly -2. **Multi-repo folder**: Current directory contains subdirectories that are git repos → patch all of them, or only those specified via `--repos` - -For multi-repo with no `--repos` filter and more than 10 repos, list them and confirm with the user first. - -## Step 4: Read Settings - -Check `.claude/devline.local.md` in each repo for CVE-specific verification settings: - -| CVE setting | Maps to | Default | -|---|---|---| -| `cve_verify_build` | `dep_verify_build` | `true` | -| `cve_verify_tests` | `dep_verify_tests` | `true` | - -Git workflow (branch, commit, push) is **not configurable** — CVE patching always follows the fixed workflow described in Step 5. - -## Step 5: Launch Dependency-Patcher Agents - -### Git workflow (applies to all modes) - -Every dependency-patcher agent MUST follow this exact git workflow: - -1. **Checkout the default branch** (detect with `git symbolic-ref refs/remotes/origin/HEAD`, fall back to `main` then `master`) -2. **Pull latest** (`git pull`) -3. **Create a fix branch**: `fix/cve-[first-CVE-ID]` (lowercase, e.g. `fix/cve-2024-38816`) -4. **Apply the dependency updates** (per kb-dependency-management) -5. **Verify** build and tests (per settings) -6. **Commit** with message: `chore(deps): [comma-separated CVE IDs]` -7. **Do NOT push** — the launcher handles delivery - -### Single-repo mode - -Launch one **dependency-patcher** agent with: - -``` -Patch the following CVEs in this repository: - -[CVE research table] - -Repository: [absolute path] - -Git workflow: -1. Checkout the default branch and pull latest -2. Create branch: fix/[first-CVE-ID] -3. Apply updates -4. Verify build/tests -5. Commit with message: chore(deps): [comma-separated CVE IDs] -6. Do NOT push — stop after committing - -Settings: dep_auto_push=false, dep_branch_strategy=branch, [any verification overrides from devline.local.md] -``` - -### Multi-repo mode - -Launch one **dependency-patcher** agent per repository, all in parallel (background). Each agent gets: - -- The full CVE research table -- Its specific repository path -- The git workflow instructions above (checkout default branch, pull, branch, update, verify, commit, NO push) -- That repo's verification settings - -Wait for all agents to complete. - -## Step 6: Present Summary and Delivery Options - -After all agents report back, compile a summary: - -``` -| Repository | CVEs Patched | CVEs Skipped (not affected) | Branch | Issues | -|------------------|------------------------|-----------------------------|---------------------|------------| -| my-api | CVE-2024-38816 | CVE-2024-22243 | fix/cve-2024-38816 | — | -| billing-service | CVE-2024-38816, -22243 | — | fix/cve-2024-38816 | — | -| auth-service | — | CVE-2024-38816, -22243 | — | — | -| legacy-app | — | — | — | Tests fail | -``` - -If any repos had issues (test failures, verification errors), report them clearly before presenting options. - -Then, for each repository that has successful patches, ask the user how they want to deliver the changes: - -``` -How would you like to deliver these changes? - -1. **Create a PR** — push the branch and open a pull request (requires remote access) -2. **Squash merge locally** — squash-merge the fix branch into the default branch locally (no remote interaction) -3. **Exit** — leave the fix branch as-is and print the changes so you can handle it manually -``` - -### Handling each option: - -**Option 1 — Create a PR:** -- Push the fix branch: `git push -u origin [branch-name]` -- Create a PR using `gh pr create` with: - - Title: `chore(deps): patch [CVE IDs]` - - Body: the CVE research table and patch details -- Report the PR URL - -**Option 2 — Squash merge locally:** -- Checkout the default branch -- Run `git merge --squash [fix-branch]` -- Commit with the same message: `chore(deps): [CVE IDs]` -- Delete the fix branch: `git branch -d [fix-branch]` -- Report: "Changes squash-merged into [default-branch]. Ready to push when you are." - -**Option 3 — Exit:** -- Print a summary of what changed: - - Branch name - - Files modified (from `git diff --stat [default-branch]..[fix-branch]`) - - The commit(s) on the branch -- Report: "Fix branch [branch-name] is ready. You can push, merge, or cherry-pick manually." - -In multi-repo mode, apply the same option to all repos unless the user requests per-repo handling. diff --git a/skills/deep-review/SKILL.md b/skills/deep-review/SKILL.md index 18fc139..82310bc 100644 --- a/skills/deep-review/SKILL.md +++ b/skills/deep-review/SKILL.md @@ -8,7 +8,7 @@ disable-model-invocation: true # PR — Final Merge-Readiness Review -Launch the **deep-review** agent for a comprehensive final review. +Launch the **reviewer** agent with `scope: branch` (model **opus**) for a comprehensive final review. ## Determine Scope 1. If a branch is specified, compare it against the base branch (main/master) @@ -16,7 +16,7 @@ Launch the **deep-review** agent for a comprehensive final review. 3. Use `git diff main...HEAD` (or equivalent) to identify all changes ## Review Checklist -The deep-review will perform: +The reviewer (scope: branch) will perform: 1. **Security Audit** — Vulnerability scan, OWASP Top 10 checks 2. **Credential Scan** — Hardcoded keys, tokens, passwords, private keys 3. **Code Quality** — Technical debt, duplication, error handling, resource leaks @@ -27,4 +27,4 @@ The deep-review will perform: ## Verdict - **APPROVED** — Code is merge-ready -- **CHANGES REQUIRED** — Issues must be fixed first (with specific fix suggestions) +- **HAS_FINDINGS** — Issues must be fixed first (with specific fix suggestions) diff --git a/skills/deps/SKILL.md b/skills/deps/SKILL.md new file mode 100644 index 0000000..63c1599 --- /dev/null +++ b/skills/deps/SKILL.md @@ -0,0 +1,111 @@ +--- +name: deps +description: "Update dependencies across one or many repositories. Default mode patches CVEs/security advisories: give CVE IDs (or a vulnerable package) and it researches affected/fixed versions, then launches dependency agents to update, verify, and commit. With --migrate it runs major-version migrations: give a package + target version (or an 'X to Y' library swap, or nothing for an EOL audit) and it researches the migration guide and tooling, gets your approval, then launches dependency agents (opus) to run codemods and refactor breaking changes. Use whenever the user mentions CVEs, security vulnerabilities in dependencies, patching/updating packages for security, OR migrating/upgrading a dependency across a major version, moving from one library to another, end-of-life/EOL, deprecations, or breaking-change upgrades." +argument-hint: "CVE-2024-XXXXX ... [--repos r1 r2] | --migrate [from vX] to [--repos r1 r2]" +user-invocable: true +disable-model-invocation: false +--- + +# Deps — Dependency Patching & Migration + +Launcher skill for dependency work across one or many repositories. It handles research and orchestration, then delegates the actual work to **dependency** agents. Two modes: + +- **patch** (default) — targeted version bumps for CVEs / security advisories. +- **migrate** (`--migrate`) — major-version migrations with breaking changes, codemods, and code refactoring. Launches the dependency agent with **model opus** and its **migration block enabled**. + +## Step 1: Parse Input & Mode + +`--migrate` present → **migrate mode**; otherwise **patch mode**. + +- **Patch:** CVE IDs matching `CVE-\d{4}-\d{4,}` (case-insensitive), or a named vulnerable package + advisory reference. + ``` + CVE-2024-38816 CVE-2024-22243 + CVE-2024-38816 --repos my-api billing-service + ``` +- **Migrate:** package/library name (source, plus target if it's a library swap), current version (or "detect from repo"), target version. Input is flexible: `spring-boot to 3.2`, `aws-sdk-java from v1 to v2`, `moment to date-fns`, `python 3.8 to 3.12`, `angular 14 to 17`. `--migrate` with **no package** → EOL/deprecation audit (Step 3). +- **`--repos r1 r2`** (both modes): filter to those repos; otherwise auto-detect in Step 2. + +## Step 2: Detect Repositories (both modes) + +1. **Single repo:** current directory has `.git/` → work in it directly. +2. **Multi-repo folder:** subdirectories that are git repos → work in all, or only those in `--repos`. + +For multi-repo with no `--repos` filter and more than 10 repos, list them and confirm with the user first. + +## Step 3: Research + +### Patch mode +For each CVE, use **WebSearch** (in parallel) to gather: package name + ecosystem; affected version range(s); fixed version(s); severity (CVSS); whether the fix crosses a major-version boundary. Good sources: NVD (`nvd.nist.gov`), GitHub Advisory Database. Present a summary table before proceeding: + +``` +| CVE | Package | Ecosystem | Affected | Fix | Severity | Major? | +|----------------|---------------|-----------|-----------|--------|----------|--------| +| CVE-2024-38816 | spring-webmvc | Maven | < 6.1.13 | 6.1.13 | High | No | +``` + +If any CVE requires a **major version bump**, flag it and ask how to proceed — do not dispatch major-bump CVEs without approval. + +### Migrate mode +The most important step — don't rush it. Use **WebSearch** + **WebFetch** to find: the official migration guide (primary source of truth); the changelog / breaking-changes list; migration **tooling** (codemod, OpenRewrite recipe, Rector rule, official CLI); community gotchas. Read the guide fully with WebFetch and extract actionable steps and a migration checklist. Check ecosystem tooling: Java/Kotlin → OpenRewrite; PHP → Rector; JS/TS → codemods/jscodeshift; Python → pyupgrade/django-upgrade; Go → `go fix`; Rust → `cargo fix`; Ruby → RuboCop; .NET → try-convert. (No package specified → scan manifests for EOL/deprecated/approaching-EOL deps, verify via WebSearch, and let the user pick.) + +Present a migration plan and **wait for approval** before launching any agents: + +``` +## Migration: [package] v[old] → v[new] +### Breaking Changes +1. [e.g. javax.* → jakarta.*] +### Migration Tooling +- [tool]: [what it automates] — runs first; manual steps remaining: [...] +### Runtime Requirements +- Requires [e.g. Java 17+] — [met / not met per repo] +### Affected Repositories +| Repository | Current | Affected | Notes | +### Risk Assessment +- Low / Medium / High risk repos +### Verification: build + test always on (mandatory for migrations) +``` + +## Step 4: Read Settings (patch mode) + +Check `.claude/devline.local.md` in each repo. Map CVE settings to the generic ones (prefixed wins): `cve_verify_build` → `dep_verify_build` (default `true`), `cve_verify_tests` → `dep_verify_tests` (default `true`). Git workflow is not configurable. For **migrate mode**, build + test verification is always on and cannot be disabled. + +## Step 5: Launch dependency agents + +**Git workflow** — follow the canonical **Git Workflow** section of the **kb-dependency-management** skill (default-branch detection, branch strategy, staging, committing, pushing). It is not re-embedded here; specify only these per-mode deltas to each agent: + +| | Branch | Commit message | Push | +|-|--------|----------------|------| +| Patch | `fix/cve-[first-CVE-ID]` (lowercase) | `chore(deps): [comma-separated CVE IDs]` | **No** — launcher delivers | +| Migrate | `chore/migrate-[package]-v[old]-to-v[new]` | `chore(deps): migrate [package] from v[old] to v[new]` | **No** — launcher delivers | + +Launch one **dependency** agent per repository (parallel/background for multi-repo; wait for all to finish). Each agent receives its repository path, that repo's settings, the git-workflow deltas above, and: + +- **Patch:** the CVE research table as update targets. Migration block **off**. +- **Migrate:** model **opus**, migration block **on**, plus the migration guide URL(s)/summary, the migration tool + command (or "none — manual"), and the migration checklist from research. + +## Step 6: Present Summary and Delivery Options (both modes) + +Compile a summary table (columns adapt to mode): + +``` +Patch: | Repository | CVEs Patched | CVEs Skipped | Branch | Issues | +Migrate: | Repository | Status | Tool Used | Manual Changes | Tests | Branch | +``` + +Report any repos with issues (test failures, verification/compilation errors — for migrations include what was done vs what remains and a recommendation) before presenting options. Then, for each repository with successful changes, ask how to deliver: + +``` +How would you like to deliver these changes? + +1. **Create a PR** — push the branch and open a pull request (requires remote access) +2. **Squash merge locally** — squash-merge the branch into the default branch locally (no remote interaction) +3. **Exit** — leave the branch as-is and print the changes so you can handle it manually +``` + +**Option 1 — PR:** `git push -u origin [branch]`; `gh pr create` with title `chore(deps): [patch: CVE IDs | migrate package vX→vY]` and body = the research table / migration summary (breaking changes addressed, tool used, verification results); report the PR URL. + +**Option 2 — Squash merge:** checkout default branch; `git merge --squash [branch]`; commit with the same message; `git branch -d [branch]`; report "Squash-merged into [default-branch]. Ready to push when you are." + +**Option 3 — Exit:** print branch name, files changed (`git diff --stat [default]..[branch]`), and the commit(s); report "Branch [name] is ready. Push, merge, or cherry-pick manually." + +In multi-repo mode, apply the same option to all repos unless the user requests per-repo handling. diff --git a/skills/design/SKILL.md b/skills/design/SKILL.md index e0c244b..5d7f134 100644 --- a/skills/design/SKILL.md +++ b/skills/design/SKILL.md @@ -16,31 +16,39 @@ Parse the user's request, detect the right mode, and launch the frontend-planner ## Mode Detection -Analyze the user's request and route to the correct mode: +The frontend-planner has three modes. Route the request to one — and for `design-one`, also pick the token source: | Mode | Trigger | Example | |------|---------|---------| -| **Brand** | Create/extend persistent brand identity | "create a brand identity", "set up a design system", "add a table to the brand" | -| **Harmonize** | Fit within project's existing theme | "make this match our site", "design a card for our current theme", "fit within our colors" | -| **Component** | Single design piece, standalone | "design a button", "create a dark color theme", "warm earth tone palette" | -| **Showcase** | Multiple variations requested | "show me 8 button styles", "create 6 different card designs" | -| **Extend** | `.devline/design-system.md` exists + new element | "add a table to the design system", "design a modal that fits our system" | -| **Full System** | Full design system for pipeline | "create a design system for a fintech app" | +| **brand-init** | First-time persistent brand identity (no `design-system/BRAND.md` yet) | "create a brand identity", "set up our brand" | +| **generate** | Multiple directions at once — a full design system, or N showcase variations | "create a design system for a fintech app", "show me 8 button styles" | +| **design-one** | A single element from one token source (see below) | "design a button", "add a modal to the brand", "match our site" | + +**design-one — pick the token source:** + +| Token source | Trigger | +|--------------|---------| +| **brand** | `design-system/BRAND.md` exists + adding an element ("add a table to the brand") | +| **project-theme** | Fit the project's existing theme ("match our site", "our current colors") | +| **design-system** | `.devline/design-system.md` exists + new element ("add a modal that fits our system") | +| **scratch** | Standalone piece, no existing system ("design a dark button", "warm earth palette") | **Priority order when ambiguous:** -1. If `design-system/BRAND.md` exists and request is for a new component → **Brand** (extend) -2. If request mentions "match", "fit", "our site", "current theme" → **Harmonize** -3. If request mentions "brand", "identity", "persistent" → **Brand** (create) -4. If request has a number ("8 buttons", "6 cards") → **Showcase** -5. If `.devline/design-system.md` exists → **Extend** -6. Default → **Component** +1. `design-system/BRAND.md` exists and the request adds a component → **design-one** (brand) +2. "match", "fit", "our site", "current theme" → **design-one** (project-theme) +3. "brand", "identity", "persistent" and no `BRAND.md` → **brand-init** +4. A count ("8 buttons", "6 cards") → **generate** (showcase) +5. "design system for [product]" → **generate** (pipeline) +6. `.devline/design-system.md` exists → **design-one** (design-system) +7. Default → **design-one** (scratch) ## Execution -### For Brand mode (create): -Launch the **frontend-planner** agent with: +Launch the **frontend-planner** agent with the mode — and for design-one, the token source. + +### brand-init: ``` -Mode: Brand +Mode: brand-init Brand request: [user's request] Product context: [any product/mood/industry context] @@ -49,85 +57,48 @@ Platform: [if mentioned] Create the brand identity system at design-system/BRAND.md with initial component specs. ``` -### For Brand mode (extend): -First verify `design-system/BRAND.md` exists. Then launch the **frontend-planner** agent with: -``` -Mode: Brand (extend) - -Existing brand: design-system/BRAND.md -New element: [what to add] -Context: [any constraints] - -Read the existing brand first, then add the new component spec. -``` - -### For Harmonize mode: -Launch the **frontend-planner** agent with: -``` -Mode: Harmonize - -Design request: [what to design] -Project: [current working directory] - -Read the project's actual theme files (tailwind config, CSS variables, theme.ts, etc.) and design [component] to fit within the existing visual identity. Output to .devline/component-spec.md. -``` - -### For Component mode: -Launch the **frontend-planner** agent with: +### generate (pipeline — full design system): ``` -Mode: Component +Mode: generate +Variant: pipeline -Design request: [user's request] -Context: [any product/mood/constraint context from the user] +Product context: [user's description] +Platform: [if mentioned, otherwise ask] -Output the component spec to .devline/component-spec.md and preview to .devline/component-preview.html. +No brainstorm file exists — use this description directly as the product context. Write the full design system to .devline/design-system.md. ``` -### For Showcase mode: -Launch the **frontend-planner** agent with: +### generate (showcase — N variations): ``` -Mode: Showcase +Mode: generate +Variant: showcase Component: [what to showcase] -Count: [N from user's request, default 8] +Count: [N from request, default 8] Constraints: [any constraints mentioned] Output showcases to .devline/showcases/ ``` -### For Extend mode: -First verify `.devline/design-system.md` exists. Then launch the **frontend-planner** agent with: +### design-one: +If the token source is `brand` or `design-system`, first verify `design-system/BRAND.md` / `.devline/design-system.md` exists. Then launch: ``` -Mode: Extend - -Existing design system: .devline/design-system.md -New element: [what to add] -Context: [any constraints] +Mode: design-one +Token source: [scratch | project-theme | design-system | brand] -Read the existing design system first, then output the extension. -``` - -### For Full System mode: -Launch the **frontend-planner** agent with: -``` -Mode: Pipeline - -Product context: [user's description] -Platform: [if mentioned, otherwise ask] +Design request: [user's request] +Context: [product/mood/constraints — or the existing brand/system/theme to read tokens from] -Note: No brainstorm file exists. Use the user's description directly as the product context for design intelligence searches. Skip brainstorm.md reading — use the prompt as your input. Write the full design system to .devline/design-system.md. +Read the token source first (if any), then output the spec to .devline/component-spec.md and preview to .devline/component-preview.html. For the brand source, add the component under design-system/ and update BRAND.md. ``` ## After Agent Completes Report the result to the user: -- For **Brand (create)**: "Brand identity at `design-system/BRAND.md` with N component specs. To add more: `/design add [component] to the brand`" -- For **Brand (extend)**: "Added `design-system/components/[name].md`, BRAND.md index updated" -- For **Harmonize**: "Component spec at `.devline/component-spec.md`, designed to fit your project's existing theme" -- For **Component**: "Component spec at `.devline/component-spec.md`, preview at `.devline/component-preview.html`" -- For **Showcase**: "N showcases at `.devline/showcases/`, open `index.html` for the gallery" -- For **Extend**: "Extension added to `.devline/design-system.md`, preview at `.devline/extend-preview.html`" -- For **Full System**: "Design system at `.devline/design-system.md`" +- **brand-init**: "Brand identity at `design-system/BRAND.md` with N component specs. Add more: `/design add [component] to the brand`" +- **generate (pipeline)**: "Design system at `.devline/design-system.md`" +- **generate (showcase)**: "N showcases at `.devline/showcases/`, open `index.html` for the gallery" +- **design-one**: "Component spec at `.devline/component-spec.md`, preview at `.devline/component-preview.html`" (brand source: component added under `design-system/`, BRAND.md updated) ## Rules @@ -135,5 +106,12 @@ Report the result to the user: - Do NOT ask unnecessary questions — if the user says "design a dark button", just design it - Do launch the frontend-planner agent — do not design anything yourself - If the user's request is ambiguous about mode, follow the priority order above -- Brand mode outputs are PERSISTENT (in `design-system/`) — they survive pipeline cleanup +- `brand-init` and `design-one` (brand source) outputs are PERSISTENT (in `design-system/`) — they survive pipeline cleanup - All other mode outputs are in `.devline/` and are temporary + +## Live Design System (`docs/design-system/`) + +Beyond the mode outputs above, the frontend-planner maintains one durable, corrections-aware design system per repo at `docs/design-system/` (`MASTER.md` + `pages/.md`). It survives across sessions. The agent: +- **Reads it first** — before designing, it checks `docs/design-system/MASTER.md` (and `pages/.md` for the current page, which overrides MASTER) and works within it, including the `## Corrections & Decisions` log, so past mistakes aren't repeated. +- **Persists on generate** — establishing or changing the shared system writes/regenerates `docs/design-system/` (via `search.py --design-system --persist --output-dir docs`). +- **Persists on correction** — when you correct a design or a choice fails, it appends a dated bullet to `## Corrections & Decisions` (MASTER for global, the page file for page-specific) and updates the affected spec. Nothing is lost between sessions. diff --git a/skills/devline/SKILL.md b/skills/devline/SKILL.md index 493cbcd..85b8cbf 100644 --- a/skills/devline/SKILL.md +++ b/skills/devline/SKILL.md @@ -17,7 +17,24 @@ You are a senior engineering manager orchestrating the full development lifecycl That's it. Do NOT read source files to understand errors. Do NOT run a second build "to check." Do NOT filter test output to categorize failures. Do NOT investigate individual failing tests. Do NOT edit code beyond a one-line fix. The moment you see errors that aren't a trivial one-liner, launch a debugger and move on. -**Fast-path for bugs/fixes:** If the user's request is clearly a bug fix, compile error, test failure, or debugging task (not a new feature): skip Stages 1-2 (brainstorm/plan), run the build once, then launch a **debugger** agent. Follow up with a reviewer. +## Change Classification (before Stage 1) + +Read `fast_lane` from `.claude/devline.local.md` (default `auto`; values `auto|always|off`). Classify the request before starting Stage 1: + +- **Bug/fix/debug** (bug fix, compile error, test failure, stack trace — not a new feature): skip Stages 1-2 (brainstorm/plan), run the build once, then launch a **debugger** agent, followed by a **reviewer**. +- **SMALL → Fast Lane.** Classify SMALL when ANY of: the user invoked `/devline:quick`, OR `fast_lane: always`, OR it's a bugfix/typo/small tweak, OR the change is ≲1 file / ≲30 lines with **no new component, no schema/migration, no new endpoint, and no new UI surface**. Ambiguous? Ask ONE AskUserQuestion — "This looks small — fast lane or full pipeline?" (default: fast lane). Skip the question when `fast_lane: always` (force fast) or `fast_lane: off` (never fast — run the full pipeline). +- **Otherwise** → the full pipeline (Stages 1-5) below. + +### Fast Lane + +A single task, run in place — no worktrees, no waves, no gates. + +1. **Branch setup** (Stage 0). +2. **Implement** — one implementer agent, TDD at the right level (unit for pure logic, integration for persistence/endpoints; see `kb-tdd-workflow`). +3. **ONE `reviewer` (scope=task)** — the standard per-task review. Run a fix cycle if it returns blocking findings. +4. **Commit.** Then auto-proceed and ask only merge-or-not. + +The fast lane SKIPS: brainstorm + its approval gate; design-system (Stage 1.5); the full plan doc + plan approval gate; the mandatory Feature E2E task; worktree/wave machinery (the single task runs in place); the deferred-findings batch-fix cycle (Stage 3.5); the docs-keeper full documentation scan (Stage 4); `reviewer scope=branch` / deep review (Stage 5); and the final approval gate (it auto-proceeds, asking only whether to merge). ## Progress Tracking @@ -45,96 +62,23 @@ Mark each `in_progress` when starting and `completed` when done. **Do not render ## State Persistence -Persist all mutable state to files — conversation context is disposable summaries only. - -### `.devline/state.md` — single source of truth for pipeline state -Create when entering Stage 3. Update after every status change. Always end the file with `## END` as an integrity marker — if this line is missing when reading, the file was partially written; re-derive state from `plan.md` + `TaskList`. - -```markdown -## Pipeline State -- **Stage:** implement -- **Phase:** N/M (or "single" for non-phased pipelines) -- **Phase name:** [name from brainstorm, e.g., "Core data model"] -- **Updated:** 2026-03-20T14:32:00 -- **Active agents:** 3/10 -- **Pipeline started:** 2026-03-20T14:00:00 - -## Task Progress -| # | Status | Review Attempts | Notes | -|---|--------|-----------------|-------| -| 1 | done | 1 (CLEAN) | | -| 2 | building | 0 | Launched 2026-03-20T14:28:00 | -| 3 | blocked | 0 | Waiting on 1 | - -## Pending Fix Cycles -| Task | Fix File | Created | -|------|----------|---------| -| 5 | .devline/fix-task-5.md | 2026-03-20T14:35:00 | - -## Deferred Findings -- **Total:** 5 -- **File:** .devline/deferred-findings.md - -## END -``` - -Key schema rules: -- **Active agents** counter tracks concurrency against the 10-agent limit -- **Launched** timestamps are absolute ISO 8601 — they survive compaction and enable health monitoring to compute elapsed time after recovery -- **Pending Fix Cycles** tracks orphaned fix-task files so recovery can resume them -- Task **Status** values: `blocked`, `queued`, `building`, `reviewing`, `fixing`, `done`, `failed` - -### `.devline/deferred-findings.md` — deferrable findings collected across tasks -Append findings grouped by task. During batch fix, the implementer prefixes each fixed finding with `[FIXED]` so partial progress is trackable. - -```markdown -## Deferred Findings - -### Task 1: Auth module -1. [FIXED] **Code Quality** `src/auth.ts:42` — Rename `x` to `tokenExpiry` -2. **Code Quality** `src/auth.ts:78` — Extract duplicated validation - -### Task 3: API routes -1. **Code Quality** `src/routes.ts:15` — Extract duplicated validation into helper -``` - -### Context discipline -1. After receiving agent output: extract verdict, update `.devline/state.md` (including active agent count), append deferred findings, output a brief summary to user. -2. Write review findings to `.devline/fix-task-{N}.md` for implementers to read. Record in state.md's Pending Fix Cycles table. Delete both entries after fix cycle completes. -3. **Proactive checkpointing:** After every 5 agent completions, ensure `.devline/state.md` fully reflects current state. This ensures recoverability even if compaction happens between agent completions. - -### Recovery protocol -If unsure of pipeline state — after compaction, conversation resume, or starting a new conversation with an active pipeline: - -1. **Read `.devline/state.md`** — check for `## END` integrity marker. If missing, the file is corrupt; fall back to steps 3-5 to reconstruct. -2. **If state.md contains `Phase: N/M`** (not "single"), this is a multi-phase pipeline: - - Check which plan-phase files exist on disk (`.devline/plan-phase-*.md`) to determine which phases are complete - - A phase is complete if its plan file exists AND all its tasks are merged (check git log for `task-N:` commits matching the plan's task list) - - Resume from the current phase — if mid-implement, resume Stage 3 with the current phase's plan file; if between phases, start the next phase's planning -3. **Read `.devline/deferred-findings.md`** — restore collected findings. -4. **Read the active plan file** — `.devline/plan.md` for single-phase, or `.devline/plan-phase-N.md` (where N is the current phase from state.md) for multi-phase — restore task definitions, dependencies, acceptance criteria. Validate `**Branch:**` and `**Status:**` against current git state. -5. **Cross-check git log against state.md** — run `git log --oneline` and grep for `task-N:` commits. If a task has a commit in git but state.md shows `building` or `reviewing`, the crash happened after commit but before state update — mark that task as `done` in state.md. This prevents relaunching already-completed tasks. -6. **Check `TaskList`** — this is the ground truth for what agents are running (state.md agent IDs are conversation-scoped and may be stale after compaction). -7. **Check for orphaned `.devline/fix-task-*.md` files** — each represents an interrupted fix cycle. Resume by launching an implementer for each. -7. **Read `.devline/agent-log.md`** if it exists — the SubagentStop hook logs agent completions here. Cross-reference with state.md to identify agents that completed but weren't processed (e.g., due to compaction between completion and processing). -8. **Recompute active agent count** from TaskList and update state.md. -9. **Recompute elapsed times** from absolute timestamps in state.md's Task Progress table. Resume health monitoring escalation based on actual elapsed time. -10. Resume orchestration from the recovered state. +Persist all mutable state to files — conversation context is disposable summaries only. During Stage 3, state files (`.devline/state.md`, `.devline/deferred-findings.md`, `.devline/fix-task-*.md`) are written per `references/implementation-protocol.md`. On resume-after-crash (or any uncertain pipeline state), read `references/recovery.md` for the state-file schemas and the recovery protocol. ## Configuration Read `.claude/devline.local.md` (if it exists): - **`auto_approve_brainstorm`** (default: `false`) — Skip brainstorm approval gate - **`auto_approve_plan`** (default: `false`) — Skip plan approval gate +- **`fast_lane`** (default: `auto`; `auto|always|off`) — Controls fast-lane detection for small changes (see Change Classification above) ## Pipeline Stages ### Stage 0: Branch Setup (Automatic) 1. Read branching settings from `.claude/devline.local.md` (`branch_format`, `branch_kinds`, `protected_branches`) -2. **Active pipeline detection:** If `.devline/state.md` exists, this is a resume scenario (new conversation or post-compaction). Run the recovery protocol (see State Persistence above) and ask the user whether to resume or start fresh. If resuming, skip to the recovered stage. +2. **Active pipeline detection:** If `.devline/state.md` exists, this is a resume scenario (new conversation or post-compaction). Run the recovery protocol (`references/recovery.md`) and ask the user whether to resume or start fresh. If resuming, skip to the recovered stage. 3. If on a protected branch (default: main, master, develop, release, production, staging): create a branch using `branch_format` (default: `{kind}/{title}`). The `{kind}` must be one of `branch_kinds` (default: feat, fix, refactor, docs, chore, test, ci). 4. Create `.devline/` directory and add to `.gitignore` if needed -5. **CLAUDE.md check:** If `CLAUDE.md` does not exist in the project root, warn the user: "No CLAUDE.md found. Run `/devline:setup` to create one — it stores project conventions and lessons that improve pipeline quality across runs." Continue without it (not blocking). +5. **CLAUDE.md check:** If `CLAUDE.md` does not exist in the project root, warn the user: "No CLAUDE.md found. Run `/devline:setup` to create one — it stores project conventions that improve pipeline quality across runs." Continue without it (not blocking). 6. **Stale artifact check:** If `.devline/plan.md` or any `.devline/plan-phase-*.md` files already exist, read the `**Branch:**` header from `plan.md` (or `plan-phase-1.md` if only phase plans exist). If it references a different branch or the `**Status:**` is `completed`, delete all `.devline/` artifacts (including `plan-phase-*.md`) and inform user. If it matches current branch with `active` status, ask user whether to resume or start fresh. ### Stage 1: Brainstorm (Interactive — main context) @@ -184,93 +128,13 @@ After approval, proceed to Stage 3 (Implement) with `.devline/plan.md` as the pl #### Multi-Phase Path (`## Phases` detected in brainstorm) -When `## Phases` is detected, the pipeline plans ALL phases first, then implements them sequentially. Documentation (Stage 4) and Deep Review (Stage 5) run **once at the end** across all phases. - -**The two-pass approach:** Plan everything → approve everything → implement phase by phase. This gives full scope visibility before any code is written. Changing a plan is cheap; changing implemented code costs a full pipeline cycle. - -**Progress tracking for multi-phase mode:** - -Before entering the planning pass, create phase-level tasks using TaskCreate: -- "Phase 1: Plan" (one per phase) -- "Phase 1: Implement" (one per phase, will contain sub-tasks from that phase's plan) -- ... repeat for each phase ... -- "Documentation" (once, at end) -- "Deep Review" (once, at end) +Multi-phase = the single-phase path repeated per phase, with a barrier between phases. Two passes: **plan all phases → approve all → implement phase by phase.** This gives full scope visibility before any code is written (changing a plan is cheap; changing implemented code costs a full cycle). Documentation (Stage 4) and Deep Review (Stage 5) run **once at the end** across all phases. -Update these as each phase progresses. Within each phase's implement cycle, display the standard per-task progress table (scoped to that phase's tasks). +**Progress & state:** Create phase-level tasks up front (`Phase N: Plan`, `Phase N: Implement` per phase, plus one `Documentation` and one `Deep Review` at the end). In `.devline/state.md`, add phase fields (`Phase: N/M`, `Phase name:`, `Pipeline stage: planning|implementing`) and update them on every phase transition. -**State tracking for multi-phase mode:** +**Pass 1 — plan all phases.** For each phase N (1…M): launch the **planner** (foreground) exactly as the single-phase path, additionally passing N, M, and the paths to all prior phase plan files (`.devline/plan-phase-1.md`…`plan-phase-{N-1}.md`) so it can scope to just this phase; it writes `.devline/plan-phase-N.md`. Run the same NEEDS_INPUT loop and the same per-plan approval gate (Approve / Needs changes / Stop here / Other; `auto_approve_plan` respected). After every phase plan is approved, present a summary of all phases and confirm before starting (Start implementation / Revisit a plan / Stop here). -When creating `.devline/state.md`, include the phase fields: -```markdown -- **Phase:** 1/3 -- **Phase name:** Core data model -- **Pipeline stage:** planning | implementing -``` - -On phase transitions, update these fields. Reset the `## Task Progress` table for the new phase's tasks. - ---- - -**Pass 1: Plan all phases sequentially** - -For each phase N from 1 to total_phases: - -**a. Plan phase N:** Launch the **planner** agent in the **foreground**, passing: - - The full `.devline/brainstorm.md` - - `.devline/design-system.md` (if it exists) - - The current phase number N and total phase count M - - Paths to all prior phase plan files (`.devline/plan-phase-1.md` through `.devline/plan-phase-{N-1}.md`) — the planner reads these to understand what earlier phases will build - - Instruction to write output to `.devline/plan-phase-N.md` - - Handle the interactive NEEDS_INPUT loop identically to the single-phase path above. The planner scopes its plan to only the current phase's work as described in the brainstorm's `## Phases` section. - -**b. Approve phase N plan:** Same approval gate as the single-phase path (`auto_approve_plan` config respected). Present: - -```json -{ - "question": "Phase N/M plan complete — the plan is at .devline/plan-phase-N.md. Approve?", - "header": "Approve Phase N", - "options": [ - {"label": "Approve — continue to next phase plan", "description": "Approve this phase plan and move to planning the next phase (or start implementation if this is the last phase)"}, - {"label": "Needs changes", "description": "I want to revise this phase plan before continuing"}, - {"label": "Stop here", "description": "End the pipeline"}, - {"label": "Other", "description": "Type a note"} - ], - "multiSelect": false -} -``` - - - If "Needs changes", resume the planner to revise the phase plan. - - If "Stop here", end the pipeline. Run exit cleanup. - - If "Other", follow the user's instruction. - -After all phase plans are approved, present a summary of all phases and ask: - -```json -{ - "question": "All N phase plans are complete and approved. Ready to start implementation (Phase 1)?", - "header": "Start implementing", - "options": [ - {"label": "Start implementation", "description": "Begin implementing Phase 1"}, - {"label": "Revisit a plan", "description": "I want to change one of the phase plans before starting"}, - {"label": "Stop here", "description": "End the pipeline"} - ], - "multiSelect": false -} -``` - ---- - -**Pass 2: Implement phases sequentially** - -For each phase N from 1 to total_phases: - -**a. Implement phase N:** Run Stage 3 (Implement) using `.devline/plan-phase-N.md` as the plan file. All existing Stage 3 behavior (wave barriers, worktree isolation, reviews, fix cycles, deferred findings batch fix) applies identically. **Stage 3.5 (deferred findings batch fix) runs at the end of each phase.** - -**b. Advance:** After all waves of phase N are complete (including deferred findings batch fix), update `.devline/state.md` with `Phase: {N+1}/M` and proceed to phase N+1. Reset the task progress table for the new phase. Remove all `[FIXED]` entries from `.devline/deferred-findings.md` to keep the file clean for the next phase. - -**After all phases are implemented:** Proceed to Stage 4 (Documentation) and Stage 5 (Deep Review), which run once across all phases. +**Pass 2 — implement phases sequentially.** For each phase N (1…M): run Stage 3 (Implement) using `.devline/plan-phase-N.md`, identical to single-phase — including Stage 3.5 (deferred-findings batch fix) at the end of the phase. **Barrier between phases:** only after phase N fully completes, update `state.md` to `Phase: {N+1}/M`, reset the task-progress table, and clear `[FIXED]` entries from `.devline/deferred-findings.md`; then start phase N+1. After the last phase, proceed to Stage 4 and Stage 5 (once, across all phases). ### Stage 3: Implement (Autonomous — background, dependency-driven) @@ -282,7 +146,7 @@ Launch **docs-keeper** agent. Tell it which plan file(s) to read for context (`. ### Stage 5: Deep Review (Autonomous — background) -Launch **deep-review** agent for final comprehensive review. The agent MUST return a structured verdict (APPROVED / HAS_FINDINGS). If the agent runs out of time, fails to produce a verdict, or produces partial/unstructured output: **relaunch it.** Do not read the agent's partial output to decide whether it "probably found no issues." Do not mark the deep review as done based on your own assessment. Do not skip to the final gate. Only a structured APPROVED or HAS_FINDINGS verdict from the deep-review agent counts. +Launch the **reviewer** agent with `scope: branch` (model **opus**) for the final comprehensive review. The agent MUST return a structured verdict (APPROVED / HAS_FINDINGS). If the agent runs out of time, fails to produce a verdict, or produces partial/unstructured output: **relaunch it.** Do not read the agent's partial output to decide whether it "probably found no issues." Do not mark the deep review as done based on your own assessment. Do not skip to the final gate. Only a structured APPROVED or HAS_FINDINGS verdict from the reviewer (scope: branch) counts. **The deep review cannot defer findings.** All deferred findings were already resolved in Stage 3.5. Every finding the deep review reports — minor or major — must be fixed before merge. @@ -316,10 +180,6 @@ When deep review approves: 3. Clean `.devline/` contents (keep the directory): `find .devline/ -mindepth 1 -exec rm -rf {} + 2>/dev/null` 4. Output final summary and stop immediately. -## Lesson Collection - -Agents may include `### Lessons` in their output. Append each to `## Lessons and Memory` in `CLAUDE.md` using format: `**Pattern**: ... | **Reason**: ... | **Solution**: ...`. Check for duplicates before appending. List any added lessons in the completion summary. - ## General Rules - Every finding from every review gets fixed — blocking findings immediately, deferrable findings batch-fixed after all tasks complete diff --git a/skills/devline/references/implementation-protocol.md b/skills/devline/references/implementation-protocol.md index 90a5a4c..84a4a06 100644 --- a/skills/devline/references/implementation-protocol.md +++ b/skills/devline/references/implementation-protocol.md @@ -25,8 +25,7 @@ Execution proceeds in **waves** as defined in the `## Dependency Graph` section ## Agent and Model Selection -- **implementer** for feature/application tasks -- **devops** for build, CI/CD, Docker, infrastructure, tooling tasks +- **implementer** for feature/application tasks, including build, CI/CD, Docker, infrastructure, and tooling - **debugger** for fixing failing tests or unexpected behavior - The plan's **Agent** and **Model** fields indicate which to use. Pass the model to the Agent tool's `model` parameter. diff --git a/skills/devline/references/recovery.md b/skills/devline/references/recovery.md new file mode 100644 index 0000000..de21bc5 --- /dev/null +++ b/skills/devline/references/recovery.md @@ -0,0 +1,81 @@ +# State Persistence & Recovery + +Loaded rarely — only when the pipeline must reconstruct its state (resume-after-crash, post-compaction, conversation resume). During normal Stage 3 operation the implementation protocol (`references/implementation-protocol.md`) already directs state-file writes; this file holds the full schemas and the recovery steps. + +## State Persistence + +Persist all mutable state to files — conversation context is disposable summaries only. + +### `.devline/state.md` — single source of truth for pipeline state +Create when entering Stage 3. Update after every status change. Always end the file with `## END` as an integrity marker — if this line is missing when reading, the file was partially written; re-derive state from `plan.md` + `TaskList`. + +```markdown +## Pipeline State +- **Stage:** implement +- **Phase:** N/M (or "single" for non-phased pipelines) +- **Phase name:** [name from brainstorm, e.g., "Core data model"] +- **Updated:** 2026-03-20T14:32:00 +- **Active agents:** 3/10 +- **Pipeline started:** 2026-03-20T14:00:00 + +## Task Progress +| # | Status | Review Attempts | Notes | +|---|--------|-----------------|-------| +| 1 | done | 1 (CLEAN) | | +| 2 | building | 0 | Launched 2026-03-20T14:28:00 | +| 3 | blocked | 0 | Waiting on 1 | + +## Pending Fix Cycles +| Task | Fix File | Created | +|------|----------|---------| +| 5 | .devline/fix-task-5.md | 2026-03-20T14:35:00 | + +## Deferred Findings +- **Total:** 5 +- **File:** .devline/deferred-findings.md + +## END +``` + +Key schema rules: +- **Active agents** counter tracks concurrency against the 10-agent limit +- **Launched** timestamps are absolute ISO 8601 — they survive compaction and enable health monitoring to compute elapsed time after recovery +- **Pending Fix Cycles** tracks orphaned fix-task files so recovery can resume them +- Task **Status** values: `blocked`, `queued`, `building`, `reviewing`, `fixing`, `done`, `failed` + +### `.devline/deferred-findings.md` — deferrable findings collected across tasks +Append findings grouped by task. During batch fix, the implementer prefixes each fixed finding with `[FIXED]` so partial progress is trackable. + +```markdown +## Deferred Findings + +### Task 1: Auth module +1. [FIXED] **Code Quality** `src/auth.ts:42` — Rename `x` to `tokenExpiry` +2. **Code Quality** `src/auth.ts:78` — Extract duplicated validation + +### Task 3: API routes +1. **Code Quality** `src/routes.ts:15` — Extract duplicated validation into helper +``` + +### Context discipline +1. After receiving agent output: extract verdict, update `.devline/state.md` (including active agent count), append deferred findings, output a brief summary to user. +2. Write review findings to `.devline/fix-task-{N}.md` for implementers to read. Record in state.md's Pending Fix Cycles table. Delete both entries after fix cycle completes. +3. **Proactive checkpointing:** After every 5 agent completions, ensure `.devline/state.md` fully reflects current state. This ensures recoverability even if compaction happens between agent completions. + +### Recovery protocol +If unsure of pipeline state — after compaction, conversation resume, or starting a new conversation with an active pipeline: + +1. **Read `.devline/state.md`** — check for `## END` integrity marker. If missing, the file is corrupt; fall back to steps 3-5 to reconstruct. +2. **If state.md contains `Phase: N/M`** (not "single"), this is a multi-phase pipeline: + - Check which plan-phase files exist on disk (`.devline/plan-phase-*.md`) to determine which phases are complete + - A phase is complete if its plan file exists AND all its tasks are merged (check git log for `task-N:` commits matching the plan's task list) + - Resume from the current phase — if mid-implement, resume Stage 3 with the current phase's plan file; if between phases, start the next phase's planning +3. **Read `.devline/deferred-findings.md`** — restore collected findings. +4. **Read the active plan file** — `.devline/plan.md` for single-phase, or `.devline/plan-phase-N.md` (where N is the current phase from state.md) for multi-phase — restore task definitions, dependencies, acceptance criteria. Validate `**Branch:**` and `**Status:**` against current git state. +5. **Cross-check git log against state.md** — run `git log --oneline` and grep for `task-N:` commits. If a task has a commit in git but state.md shows `building` or `reviewing`, the crash happened after commit but before state update — mark that task as `done` in state.md. This prevents relaunching already-completed tasks. +6. **Check `TaskList`** — this is the ground truth for what agents are running (state.md agent IDs are conversation-scoped and may be stale after compaction). +7. **Check for orphaned `.devline/fix-task-*.md` files** — each represents an interrupted fix cycle. Resume by launching an implementer for each. +7. **Read `.devline/agent-log.md`** if it exists — the SubagentStop hook logs agent completions here. Cross-reference with state.md to identify agents that completed but weren't processed (e.g., due to compaction between completion and processing). +8. **Recompute active agent count** from TaskList and update state.md. +9. **Recompute elapsed times** from absolute timestamps in state.md's Task Progress table. Resume health monitoring escalation based on actual elapsed time. +10. Resume orchestration from the recovered state. diff --git a/skills/devline/references/worktree-protocol.md b/skills/devline/references/worktree-protocol.md index 77acc56..1ac0d80 100644 --- a/skills/devline/references/worktree-protocol.md +++ b/skills/devline/references/worktree-protocol.md @@ -24,7 +24,7 @@ Before launching ANY agent with `isolation: "worktree"`, run these checks in ord ## Launching Agents in Worktrees -All implementer and devops agents use `isolation: "worktree"` for parallel safety. The worktree is automatically created from the current branch HEAD by the Agent tool — there is no manual branch specification needed. **If the pre-launch checklist passes (correct CWD, correct branch, clean state), the worktree will have the correct base.** +All implementer agents use `isolation: "worktree"` for parallel safety. The worktree is automatically created from the current branch HEAD by the Agent tool — there is no manual branch specification needed. **If the pre-launch checklist passes (correct CWD, correct branch, clean state), the worktree will have the correct base.** ``` Agent(subagent_type="devline:implementer", isolation="worktree", run_in_background=true, ...) diff --git a/skills/find-docs/SKILL.md b/skills/find-docs/SKILL.md index fb882eb..1b33090 100644 --- a/skills/find-docs/SKILL.md +++ b/skills/find-docs/SKILL.md @@ -26,130 +26,31 @@ disable-model-invocation: true # Documentation Lookup -Retrieve current documentation and code examples for any library using the Context7 CLI. +Fetch current library docs and code examples via the Context7 CLI — at plan or +implementation time, whenever doc accuracy matters or model knowledge may be stale. -Run directly without installing: - -```bash -npx -y ctx7 -``` - -## Authentication - -Works without authentication. For higher rate limits, set the `CONTEXT7_API_KEY` environment variable: - -```bash -export CONTEXT7_API_KEY=your_key -``` - -Or use OAuth login: - -```bash -npx -y ctx7 login -``` - -If a command fails with a quota error ("Monthly quota reached" or "quota exceeded"): -1. Inform the user their Context7 quota is exhausted -2. Suggest they set `CONTEXT7_API_KEY` or run `npx -y ctx7 login` for higher limits -3. If they cannot or choose not to authenticate, answer from training knowledge and clearly note it may be outdated - -Do not silently fall back to training data — always tell the user why Context7 was not used. - -## Workflow - -Two-step process: resolve the library name to an ID, then query docs with that ID. - -```bash -# Step 1: Resolve library ID -npx -y ctx7 library - -# Step 2: Query documentation -npx -y ctx7 docs -``` - -You MUST call `library` first to obtain a valid library ID UNLESS the user explicitly provides a library ID in the format `/org/project` or `/org/project/version`. - -IMPORTANT: Do not run these commands more than 3 times per question. If you cannot find what you need after 3 attempts, use the best result you have. - -## Step 1: Resolve a Library - -Resolves a package/product name to a Context7-compatible library ID and returns matching libraries. +Two steps: resolve the name to a `/org/project` ID, then fetch docs. Always pass a +specific query (the user's full question, not a single word) — it drives result ranking. +Never put secrets (API keys, credentials) in a query. ```bash +# 1. Resolve the library ID (skip only if the user gave an explicit /org/project[/version] ID) npx -y ctx7 library react "How to clean up useEffect with async operations" -npx -y ctx7 library nextjs "How to set up app router with middleware" -npx -y ctx7 library prisma "How to define one-to-many relations with cascade delete" -``` - -Always pass a `query` argument — it is required and directly affects result ranking. Use the user's intent to form the query, which helps disambiguate when multiple libraries share a similar name. Do not include any sensitive or confidential information such as API keys, passwords, credentials, personal data, or proprietary code in your query. - -### Result fields - -Each result includes: - -- **Library ID** — Context7-compatible identifier (format: `/org/project`) -- **Name** — Library or package name -- **Description** — Short summary -- **Code Snippets** — Number of available code examples -- **Source Reputation** — Authority indicator (High, Medium, Low, or Unknown) -- **Benchmark Score** — Quality indicator (100 is the highest score) -- **Versions** — List of versions if available. Use one of those versions if the user provides a version in their query. The format is `/org/project/version`. -### Selection process - -1. Analyze the query to understand what library/package the user is looking for -2. Select the most relevant match based on: - - Name similarity to the query (exact matches prioritized) - - Description relevance to the query's intent - - Documentation coverage (prioritize libraries with higher Code Snippet counts) - - Source reputation (consider libraries with High or Medium reputation more authoritative) - - Benchmark score (higher is better, 100 is the maximum) -3. If multiple good matches exist, acknowledge this but proceed with the most relevant one -4. If no good matches exist, clearly state this and suggest query refinements -5. For ambiguous queries, request clarification before proceeding with a best-guess match - -### Version-specific IDs - -If the user mentions a specific version, use a version-specific library ID: - -```bash -# General (latest indexed) -npx -y ctx7 docs /vercel/next.js "How to set up app router" +# 2. Fetch docs with that ID +npx -y ctx7 docs /facebook/react "How to clean up useEffect with async operations" -# Version-specific +# version-specific ID (versions are listed in the library output): npx -y ctx7 docs /vercel/next.js/v14.3.0-canary.87 "How to set up app router" ``` -The available versions are listed in the `library` output. Use the closest match to what the user specified. - -## Step 2: Query Documentation - -Retrieves up-to-date documentation and code examples for the resolved library. - -```bash -npx -y ctx7 docs /facebook/react "How to clean up useEffect with async operations" -npx -y ctx7 docs /vercel/next.js "How to add authentication middleware to app router" -npx -y ctx7 docs /prisma/prisma "How to define one-to-many relations with cascade delete" -``` - -### Writing good queries - -The query directly affects the quality of results. Be specific and include relevant details. Do not include any sensitive or confidential information such as API keys, passwords, credentials, personal data, or proprietary code in your query. - -| Quality | Example | -|---------|---------| -| Good | `"How to set up authentication with JWT in Express.js"` | -| Good | `"React useEffect cleanup function with async operations"` | -| Bad | `"auth"` | -| Bad | `"hooks"` | - -Use the user's full question as the query when possible, vague one-word queries return generic results. - -The output contains two types of content: **code snippets** (titled, with language-tagged blocks) and **info snippets** (prose explanations with breadcrumb context). +Pick the best match from step 1 by name/description relevance, code-snippet count, and +source reputation. Max 3 attempts per question, then use the best result you have. -## Common Mistakes +Critical gotchas: library IDs need the `/` prefix (`/facebook/react`, not `facebook/react`); +`docs` needs a real ID from step 1 (`docs react "hooks"` fails). -- Library IDs require a `/` prefix — `/facebook/react` not `facebook/react` -- Always run `library` first — `docs react "hooks"` will fail without a valid ID -- Use descriptive queries, not single words — `"React useEffect cleanup function"` not `"hooks"` -- Do not include sensitive information (API keys, passwords, credentials) in queries +**Rate limits:** works unauthenticated; for higher limits set `CONTEXT7_API_KEY` (or +`npx -y ctx7 login`). On a quota error, tell the user why Context7 was skipped, suggest +authenticating, and if they decline, answer from training knowledge noting it may be +outdated — never fall back silently. diff --git a/skills/kb-blast-radius/SKILL.md b/skills/kb-blast-radius/SKILL.md index b770d63..03a674b 100644 --- a/skills/kb-blast-radius/SKILL.md +++ b/skills/kb-blast-radius/SKILL.md @@ -1,6 +1,6 @@ --- name: kb-blast-radius -description: Grep-based reverse dependency analysis — injected into planner, reviewer, and deep-review agents. Computes which files are affected by changes to a set of seed files. Not invoked directly. +description: Grep-based reverse dependency analysis — injected into the planner and reviewer agents. Computes which files are affected by changes to a set of seed files. Not invoked directly. user-invocable: false disable-model-invocation: true --- @@ -13,7 +13,7 @@ Lightweight, zero-dependency reverse dependency analysis using grep-based import - **Planner:** Before task decomposition — identify coupled files so tasks have correct boundaries and file ownership. - **Reviewer:** After implementation — verify the implementer considered all dependents of changed files. -- **Deep-review:** During cross-task integration sweep — structurally validate that all dependents were covered across the full changeset. +- **Reviewer (scope: branch):** During the cross-task integration sweep — structurally validate that all dependents were covered across the full changeset. ## How It Works @@ -39,7 +39,7 @@ bash ${CLAUDE_SKILL_DIR}/scripts/blast-radius.sh \ --target src/auth/token.ts src/auth/session.ts ``` -### Post-implementation (reviewer, deep-review) +### Post-implementation (reviewer) Analyze actual changes against a base ref: @@ -96,7 +96,7 @@ Use blast radius to verify implementation completeness: 3. If a direct dependent wasn't touched and isn't in the task's scope, flag it — the implementer may have missed a required update 4. Verify associated test files were run or updated -## For Deep-Review +## For Reviewer (scope: branch) Use blast radius for the cross-task integration sweep: diff --git a/skills/kb-cloud-infra/SKILL.md b/skills/kb-cloud-infra/SKILL.md deleted file mode 100644 index 6e9f7f0..0000000 --- a/skills/kb-cloud-infra/SKILL.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -name: kb-cloud-infra -description: Domain logic for cloud infrastructure and DevOps — injected into the devops agent. Provides guidance on cloud-native development, IaC, containerization, CI/CD, and deployment. Not invoked directly. -user-invocable: false -disable-model-invocation: true ---- - -# Cloud & Infrastructure - -Guidance for cloud-native development, infrastructure as code, containerization, and deployment across all major cloud providers and platforms. - -## Pipeline Context - -When running inside the devline pipeline via the devops agent, this skill guides infrastructure tasks. The devops agent follows TDD (via the kb-tdd-workflow skill) for infra changes too — write validation scripts or smoke tests before making changes. For example: write a test that checks a Docker image builds and starts correctly before writing the Dockerfile. - -## Provider Detection - -Before writing cloud or infrastructure code, detect the project's cloud ecosystem: - -1. Check for `terraform/`, `.tf` files → Terraform/OpenTofu -2. Check for `Dockerfile`, `docker-compose.yml` → Docker -3. Check for `k8s/`, `kubernetes/`, Helm charts → Kubernetes -4. Check for `serverless.yml` → Serverless Framework -5. Check for `cdk.json` or `Pulumi.yaml` → CDK/Pulumi -6. Check for `.github/workflows/` → GitHub Actions CI/CD -7. Check for `Jenkinsfile`, `.gitlab-ci.yml`, `azure-pipelines.yml` → CI/CD -8. Check `.claude/devline.local.md` for `cloud_provider` override - -Use the find-docs skill (`npx ctx7@latest`) for current cloud SDK and service documentation. - -## Containerization - -### Dockerfile Best Practices - -- Use multi-stage builds to minimize image size -- Pin base image versions (not `latest`) -- Order layers from least to most frequently changing -- Use `.dockerignore` to exclude unnecessary files -- Run as non-root user -- Health checks for production containers -- One process per container - -### Docker Compose - -- Use named volumes for persistent data -- Define networks for service isolation -- Use environment files (`.env`) for configuration -- Pin image versions in production - -## Infrastructure as Code - -### General Principles - -- All infrastructure defined in code, version controlled -- Use modules/components for reusability -- Separate environments (dev, staging, prod) with variables -- State management (remote state for Terraform) -- Plan before apply — review changes - -### Security - -- Never hardcode credentials in IaC files -- Use IAM roles and service accounts over access keys -- Encrypt data at rest and in transit -- Principle of least privilege for all permissions -- Enable audit logging - -## CI/CD Pipelines - -### Pipeline Stages - -1. **Build** — Compile, install dependencies -2. **Test** — Unit tests, integration tests, linting -3. **Security** — Dependency scanning, SAST, secrets detection -4. **Package** — Build artifacts, container images -5. **Deploy** — Deploy to target environment -6. **Verify** — Smoke tests, health checks - -### Best Practices - -- Fail fast — run quick checks first -- Cache dependencies between builds -- Use environment-specific configurations -- Implement rollback strategies -- Never deploy without tests passing - -## Additional Resources - -### Reference Files - -For provider-specific patterns: - -- **`references/aws-patterns.md`** — AWS services, CDK, Lambda, ECS patterns -- **`references/container-patterns.md`** — Docker, Kubernetes, Helm best practices -- **`references/cicd-patterns.md`** — GitHub Actions, GitLab CI, Jenkins patterns diff --git a/skills/kb-cloud-infra/references/aws-patterns.md b/skills/kb-cloud-infra/references/aws-patterns.md deleted file mode 100644 index cc9c060..0000000 --- a/skills/kb-cloud-infra/references/aws-patterns.md +++ /dev/null @@ -1,76 +0,0 @@ -# AWS Patterns - -Use the find-docs skill (`npx ctx7@latest`) to look up current AWS SDK and service documentation. - -## Common Architectures - -### Serverless API -``` -API Gateway → Lambda → DynamoDB - → S3 (file storage) - → SQS (async processing) -``` - -### Container-based -``` -ALB → ECS Fargate → RDS PostgreSQL - → ElastiCache Redis - → S3 -``` - -### Full-stack Web App -``` -CloudFront → S3 (static frontend) - → ALB → ECS/EKS (API) - → RDS - → ElastiCache -``` - -## CDK Patterns - -### Lambda Function -```typescript -const fn = new lambda.Function(this, 'Handler', { - runtime: lambda.Runtime.NODEJS_20_X, - handler: 'index.handler', - code: lambda.Code.fromAsset('lambda'), - environment: { TABLE_NAME: table.tableName }, -}); -table.grantReadWriteData(fn); -``` - -### API Gateway + Lambda -```typescript -const api = new apigateway.RestApi(this, 'Api'); -const resource = api.root.addResource('items'); -resource.addMethod('GET', new apigateway.LambdaIntegration(fn)); -``` - -### ECS Fargate Service -```typescript -const service = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Service', { - taskImageOptions: { - image: ecs.ContainerImage.fromAsset('./app'), - environment: { DB_HOST: db.instanceEndpoint.hostname }, - }, - desiredCount: 2, -}); -``` - -## Security Best Practices - -- Use IAM roles, never access keys in code -- Enable CloudTrail for audit logging -- Use Secrets Manager for credentials -- Enable encryption at rest (KMS) for all data stores -- Use VPC for network isolation -- Enable GuardDuty for threat detection -- Use Security Groups as firewalls (least privilege) - -## Cost Optimization - -- Use Savings Plans or Reserved Instances for predictable workloads -- Spot Instances for fault-tolerant batch processing -- Right-size instances based on CloudWatch metrics -- Use S3 lifecycle policies for infrequently accessed data -- Enable Cost Explorer and set billing alerts diff --git a/skills/kb-cloud-infra/references/cicd-patterns.md b/skills/kb-cloud-infra/references/cicd-patterns.md deleted file mode 100644 index 52a2509..0000000 --- a/skills/kb-cloud-infra/references/cicd-patterns.md +++ /dev/null @@ -1,109 +0,0 @@ -# CI/CD Patterns - -## GitHub Actions - -### Basic CI Pipeline -```yaml -name: CI -on: [push, pull_request] -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: { node-version: 20 } - - run: npm ci - - run: npm test - - run: npm run lint - - build: - needs: test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: npm ci && npm run build - - uses: actions/upload-artifact@v4 - with: { name: build, path: dist/ } -``` - -### Docker Build and Push -```yaml - docker: - needs: test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - uses: docker/build-push-action@v5 - with: - push: true - tags: ghcr.io/${{ github.repository }}:${{ github.sha }} -``` - -### Deploy to Cloud -```yaml - deploy: - needs: [test, build] - if: github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - environment: production - steps: - - uses: actions/checkout@v4 - - run: | - # Deploy command here -``` - -## GitLab CI - -```yaml -stages: [test, build, deploy] - -test: - stage: test - image: node:20 - script: - - npm ci - - npm test - - npm run lint - -build: - stage: build - image: docker:latest - services: [docker:dind] - script: - - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA - -deploy: - stage: deploy - only: [main] - script: - - # Deploy command -``` - -## Best Practices - -### Pipeline Design -- Fail fast: run quick checks (lint, type check) before slow tests -- Cache dependencies between runs (`actions/cache`, `npm ci`) -- Use matrix builds for multiple versions/platforms -- Separate build and deploy stages -- Use environment protections for production deploys - -### Security -- Never echo secrets in logs -- Use short-lived tokens and OIDC where possible -- Pin action versions to specific SHAs -- Scan dependencies for vulnerabilities in CI -- Use `--frozen-lockfile` / `npm ci` to ensure reproducible builds - -### Artifacts -- Upload build artifacts between jobs -- Tag Docker images with commit SHA (not `latest` in production) -- Store test reports and coverage as artifacts -- Clean up old artifacts with retention policies diff --git a/skills/kb-cloud-infra/references/container-patterns.md b/skills/kb-cloud-infra/references/container-patterns.md deleted file mode 100644 index 5b5380b..0000000 --- a/skills/kb-cloud-infra/references/container-patterns.md +++ /dev/null @@ -1,135 +0,0 @@ -# Container & Kubernetes Patterns - -## Dockerfile Best Practices - -### Multi-stage Build (Node.js) -```dockerfile -# Build stage -FROM node:20-alpine AS builder -WORKDIR /app -COPY package*.json ./ -RUN npm ci -COPY . . -RUN npm run build - -# Production stage -FROM node:20-alpine -WORKDIR /app -RUN addgroup -g 1001 app && adduser -u 1001 -G app -s /bin/sh -D app -COPY --from=builder /app/dist ./dist -COPY --from=builder /app/node_modules ./node_modules -USER app -EXPOSE 3000 -HEALTHCHECK CMD wget -q --spider http://localhost:3000/health || exit 1 -CMD ["node", "dist/index.js"] -``` - -### Multi-stage Build (Go) -```dockerfile -FROM golang:1.22-alpine AS builder -WORKDIR /app -COPY go.* ./ -RUN go mod download -COPY . . -RUN CGO_ENABLED=0 go build -o server . - -FROM scratch -COPY --from=builder /app/server /server -EXPOSE 8080 -ENTRYPOINT ["/server"] -``` - -## Docker Compose - -```yaml -services: - api: - build: . - ports: ["3000:3000"] - environment: - DATABASE_URL: postgres://user:pass@db:5432/app - depends_on: - db: { condition: service_healthy } - - db: - image: postgres:16-alpine - environment: - POSTGRES_DB: app - POSTGRES_USER: user - POSTGRES_PASSWORD: pass - volumes: [pgdata:/var/lib/postgresql/data] - healthcheck: - test: pg_isready -U user -d app - interval: 5s - retries: 5 - -volumes: - pgdata: -``` - -## Kubernetes Patterns - -### Deployment -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: api -spec: - replicas: 3 - selector: - matchLabels: { app: api } - template: - metadata: - labels: { app: api } - spec: - containers: - - name: api - image: api:latest - ports: [{ containerPort: 3000 }] - resources: - requests: { cpu: 100m, memory: 128Mi } - limits: { cpu: 500m, memory: 512Mi } - livenessProbe: - httpGet: { path: /health, port: 3000 } - readinessProbe: - httpGet: { path: /ready, port: 3000 } -``` - -### Service -```yaml -apiVersion: v1 -kind: Service -metadata: - name: api -spec: - selector: { app: api } - ports: [{ port: 80, targetPort: 3000 }] -``` - -### Horizontal Pod Autoscaler -```yaml -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: api -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: api - minReplicas: 2 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: { type: Utilization, averageUtilization: 70 } -``` - -## Helm - -- Use `values.yaml` for environment-specific config -- Template common patterns (deployment, service, ingress) -- Use `helm lint` before deploying -- Pin chart versions in production diff --git a/skills/kb-debugging/SKILL.md b/skills/kb-debugging/SKILL.md deleted file mode 100644 index b3f44c9..0000000 --- a/skills/kb-debugging/SKILL.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -name: kb-debugging -description: Domain logic for systematic debugging — injected into the debugger agent. Provides common bug patterns and debugging tools reference. Not invoked directly. -user-invocable: false -disable-model-invocation: true ---- - -# Debugging Reference - -Supplementary reference for the debugger agent. The core scientific debugging process (Reproduce → Evidence → Hypothesize → Test → Fix → Verify) is defined in the agent itself — this skill provides pattern recognition and tooling guidance. - -## Common Bug Patterns - -### Off-by-One Errors -- Check loop boundaries, array indices, fence-post conditions -- Look for `<` vs `<=`, `i` vs `i+1` - -### Null/Undefined References -- Trace the variable back to its origin -- Check all paths — is there a code path where it's never assigned? -- Look for async gaps where state can change - -### Race Conditions -- Look for shared mutable state accessed from multiple threads/goroutines/processes -- Check for missing locks, atomic operations, or synchronization -- Add ordering guarantees or make state immutable - -### State Management -- Check if state is being mutated where it shouldn't be -- Look for stale closures, cached values, or shallow copies -- Verify state transitions are valid - -### Integration Issues -- Check API contracts — is the caller sending what the callee expects? -- Verify serialization/deserialization (JSON types, date formats, encoding) -- Check network timeouts, retries, and error handling - -## Debugging Tools - -- **Logging** — Add targeted, temporary log statements at key decision points -- **Debugger** — Set breakpoints at suspicious locations, inspect state -- **Git bisect** — Find the exact commit that introduced the bug -- **Profiler** — For performance bugs, identify bottlenecks -- **Network tools** — For API issues, inspect request/response payloads - -## Additional Resources - -### Reference Files - -- **`references/debugging-tools.md`** — Language-specific debuggers, profilers, and diagnostic tools -- **`references/common-errors.md`** — Common error patterns by language and framework diff --git a/skills/kb-debugging/references/common-errors.md b/skills/kb-debugging/references/common-errors.md deleted file mode 100644 index ff925e8..0000000 --- a/skills/kb-debugging/references/common-errors.md +++ /dev/null @@ -1,117 +0,0 @@ -# Common Error Patterns - -## Null / Undefined References - -**Symptoms:** NullPointerException, TypeError: Cannot read properties of undefined, AttributeError: 'NoneType' - -**Common Causes:** -- Uninitialized variable used before assignment -- Function returns null/undefined on error path -- Optional field accessed without null check -- Async operation not awaited, returns Promise instead of value -- Array access out of bounds - -**Investigation:** -1. Find the exact variable that's null -2. Trace it back to where it should have been assigned -3. Check all code paths — is there one where assignment is skipped? -4. Check if it's a timing issue (async) - -## Off-by-One Errors - -**Symptoms:** Array index out of bounds, missing first/last element, loop runs one too many/few times - -**Common Causes:** -- `<` vs `<=` in loop condition -- 0-indexed vs 1-indexed confusion -- Fence-post error (N items need N-1 separators) -- Substring/slice end index is exclusive - -**Investigation:** -1. Check boundary conditions: what happens at index 0? At length-1? At length? -2. Manually trace the loop for 0, 1, and 2 elements -3. Check if the API uses inclusive or exclusive end indices - -## Race Conditions - -**Symptoms:** Intermittent failures, works in debugger but fails in production, different results each run - -**Common Causes:** -- Shared mutable state without synchronization -- Check-then-act without atomic operation -- Relying on operation ordering without guarantees -- Stale closures capturing old values - -**Investigation:** -1. Identify all shared mutable state -2. Check if access is synchronized (mutex, lock, atomic, channel) -3. Add logging with timestamps and thread/goroutine IDs -4. Use race detection tools (`go test -race`, Thread Sanitizer) - -## Memory Leaks - -**Symptoms:** Increasing memory usage over time, OOM errors, slow performance after running for a while - -**Common Causes:** -- Event listeners added but never removed -- Cache growing without eviction policy -- Closures holding references to large objects -- Unclosed database connections, file handles, streams -- Circular references preventing garbage collection - -**Investigation:** -1. Profile memory usage over time -2. Take heap snapshots at different points -3. Compare snapshots to find growing objects -4. Check for patterns: event handlers, closures, caches - -## Deadlocks - -**Symptoms:** Application hangs, no CPU usage, no logs after a certain point - -**Common Causes:** -- Two threads/goroutines waiting for each other's locks -- Channel send/receive without matching counterpart -- Database transaction waiting for a lock held by another transaction - -**Investigation:** -1. Get a thread dump / goroutine dump -2. Find blocked threads and what they're waiting for -3. Check lock ordering — is it consistent? -4. Check for unbuffered channels with no receiver - -## Serialization Issues - -**Symptoms:** Wrong types after JSON parse, missing fields, date format errors, encoding issues - -**Common Causes:** -- JSON number precision loss (large integers in JavaScript) -- Date/time timezone handling (UTC vs local) -- Character encoding mismatch (UTF-8 vs Latin-1) -- Missing fields silently becoming null/undefined -- Case sensitivity in field names - -**Investigation:** -1. Log the raw serialized data (before parse) -2. Compare expected vs actual types -3. Check for implicit type conversions -4. Verify both sides agree on field names and types - -## Connection / Timeout Errors - -**Symptoms:** ECONNREFUSED, timeout errors, intermittent 5xx responses - -**Common Causes:** -- Target service not running -- Wrong host/port configuration -- Connection pool exhausted -- Network/firewall blocking -- DNS resolution failure -- TLS certificate issues - -**Investigation:** -1. Verify target service is running and accessible -2. Check configuration (host, port, protocol) -3. Monitor connection pool metrics -4. Check for connection leaks (opened but not closed) -5. Test connectivity with curl/telnet diff --git a/skills/kb-debugging/references/debugging-tools.md b/skills/kb-debugging/references/debugging-tools.md deleted file mode 100644 index 328f517..0000000 --- a/skills/kb-debugging/references/debugging-tools.md +++ /dev/null @@ -1,121 +0,0 @@ -# Debugging Tools by Language - -Use the find-docs skill (`npx ctx7@latest`) to look up current documentation for any tool mentioned here. - -## JavaScript / TypeScript - -### Built-in -- `console.log()`, `console.table()`, `console.trace()` -- `debugger` statement (triggers breakpoint in DevTools) -- Chrome DevTools: breakpoints, call stack, scope inspection -- Node.js: `node --inspect` + Chrome DevTools - -### Libraries -- `debug` package: namespaced debug logging -- `why-is-node-running`: find what's keeping Node alive -- `clinic.js`: performance profiling (flame graphs, event loop) - -### Common Errors -- `TypeError: Cannot read properties of undefined` — trace the variable back to its source -- `ReferenceError: X is not defined` — check scope, imports, spelling -- `Unhandled promise rejection` — missing `.catch()` or `try/catch` in async -- `ECONNREFUSED` — target service not running or wrong port - -## Python - -### Built-in -- `print()` for quick inspection -- `breakpoint()` (Python 3.7+) or `import pdb; pdb.set_trace()` -- `traceback.print_exc()` for exception details -- `python -m pdb script.py` for command-line debugging - -### Libraries -- `ipdb`: Enhanced pdb with IPython features -- `rich.traceback`: Beautiful tracebacks -- `py-spy`: Sampling profiler (no code changes needed) -- `memory_profiler`: Track memory usage - -### Common Errors -- `AttributeError: 'NoneType'` — something returned None unexpectedly -- `ImportError` — check module path, virtual environment, `__init__.py` -- `KeyError` — dict key doesn't exist, use `.get()` with default -- `IndentationError` — mixed tabs and spaces - -## Go - -### Built-in -- `fmt.Printf()` with `%+v` for struct details -- `log.Printf()` for timestamped output -- `runtime/pprof` for CPU/memory profiling -- `runtime.Stack()` for goroutine dumps - -### Tools -- `dlv` (Delve): Go debugger with breakpoints and goroutine inspection -- `go test -race`: Detect race conditions -- `go vet`: Static analysis -- `pprof` web UI: `go tool pprof -http=:8080 profile.pb.gz` - -### Common Errors -- `nil pointer dereference` — check all pointer returns before use -- `deadlock` — goroutines waiting on each other; check channel/mutex usage -- `data race` — shared state without synchronization; use `-race` flag - -## Java / Kotlin - -### Built-in -- IDE debugger (IntelliJ, Eclipse): breakpoints, watches, evaluate expression -- `System.out.println()` / `println()` (Kotlin) -- JVM flags: `-verbose:gc`, `-Xlog:gc*` -- Thread dumps: `jstack ` - -### Tools -- VisualVM: Memory, CPU, thread monitoring -- JProfiler: Commercial profiler -- Arthas: Runtime diagnostic tool -- async-profiler: Low-overhead profiler - -### Common Errors -- `NullPointerException` — use `Optional`, null checks, or Kotlin null safety -- `ClassNotFoundException` — classpath issue, check dependencies -- `OutOfMemoryError` — heap dump analysis with MAT or VisualVM -- `ConcurrentModificationException` — iterating while modifying collection - -## Rust - -### Built-in -- `dbg!()` macro: prints expression and value with file:line -- `println!("{:?}", value)` for Debug trait output -- `RUST_BACKTRACE=1` for stack traces on panic -- `RUST_LOG=debug` with `env_logger` for log levels - -### Tools -- `rust-gdb` / `rust-lldb`: Debuggers with Rust-aware pretty printing -- `cargo flamegraph`: CPU profiling flame graphs -- `cargo clippy`: Linting and common mistake detection -- `miri`: Detect undefined behavior - -### Common Errors -- Borrow checker errors — restructure ownership or use `Rc`/`Arc` -- `unwrap()` panic — handle `Option`/`Result` properly -- Lifetime errors — annotate or restructure references - -## General Techniques - -### Binary Search (Git Bisect) -```bash -git bisect start -git bisect bad # current commit is broken -git bisect good v1.0 # this version worked -# Git checks out middle commit, you test, mark good/bad -git bisect reset # done -``` - -### Rubber Duck Debugging -Explain the problem step-by-step out loud. The act of articulating often reveals the issue. - -### Printf Debugging (Structured) -Instead of random print statements: -1. Print at function entry with inputs -2. Print at decision points with conditions -3. Print at function exit with outputs -4. Remove all prints after fixing diff --git a/skills/kb-dependency-management/SKILL.md b/skills/kb-dependency-management/SKILL.md index 4afbf97..8048d42 100644 --- a/skills/kb-dependency-management/SKILL.md +++ b/skills/kb-dependency-management/SKILL.md @@ -1,13 +1,13 @@ --- name: kb-dependency-management -description: Domain logic for dependency management — injected into the dependency-patcher agent. Provides ecosystem detection, version update mechanics, build/test verification, and commit/push workflows across all major package managers. Not invoked directly. +description: Domain logic for dependency management — injected into the dependency agent. Provides ecosystem detection, version update mechanics, build/test verification, and commit/push workflows across all major package managers. Not invoked directly. user-invocable: false disable-model-invocation: true --- # Dependency Management -Shared methodology for updating dependencies across all supported package ecosystems. This skill is injected into the dependency-patcher agent and provides the mechanics of detecting, updating, verifying, and committing dependency changes — regardless of whether the trigger is a CVE, a routine version bump, or part of a larger migration. +Shared methodology for updating dependencies across all supported package ecosystems. This skill is injected into the dependency agent and provides the mechanics of detecting, updating, verifying, and committing dependency changes — regardless of whether the trigger is a CVE, a routine version bump, or part of a larger migration. ## Ecosystem Detection @@ -126,7 +126,7 @@ Read `.claude/devline.local.md` YAML frontmatter in each repo for these settings | `dep_verify_build` | `true` | Run build verification before committing. | | `dep_verify_tests` | `true` | Run test suite before committing. | -The launcher skill (cve-patcher, migrate, etc.) may map its own setting names to these — e.g., `cve_branch_strategy` maps to `dep_branch_strategy`. Check for both the prefixed and generic versions, with the prefixed version taking priority. +The launcher skill (deps) may map its own setting names to these — e.g., `cve_verify_build` maps to `dep_verify_build`. Check for both the prefixed and generic versions, with the prefixed version taking priority. When `dep_auto_commit` is `false`, `dep_auto_push` is implicitly `false` too. diff --git a/skills/kb-dependency-migration/SKILL.md b/skills/kb-dependency-migration/SKILL.md deleted file mode 100644 index 72d7342..0000000 --- a/skills/kb-dependency-migration/SKILL.md +++ /dev/null @@ -1,186 +0,0 @@ ---- -name: kb-dependency-migration -description: Domain logic for complex dependency migrations — injected into the dependency-migrator agent. Provides methodology for researching migration guides, using ecosystem migration tools, refactoring code for breaking API changes, handling package renames, and verifying correctness. Not invoked directly. -user-invocable: false -disable-model-invocation: true ---- - -# Dependency Migration - -Methodology for executing complex dependency migrations that involve breaking changes, API differences, package renames, behavioral changes, and code refactoring. This is not a version bump — it is a deliberate, researched transition from one major version or library to another. - -## Migration Philosophy - -A migration is only done when verification passes. Unlike simple patches where build/test verification can be disabled, migrations always require: - -1. The code compiles successfully -2. The full test suite passes -3. If no test suite exists, manual smoke-testing instructions are provided to the user - -This is non-negotiable. Migrations touch application logic, not just manifest files. Shipping a half-migrated codebase is worse than not migrating at all. - -## Phase 1: Research the Migration Path - -Before touching any code, build a complete picture of what the migration involves. This research phase is critical — skipping it leads to incomplete migrations and subtle runtime bugs. - -### Find the official migration guide - -Use **WebSearch** and **WebFetch** to find: - -1. **Official migration guide** from the library/framework maintainers (this is the primary source of truth) -2. **Changelog / release notes** for the target version — especially breaking changes -3. **Community migration guides** (blog posts, GitHub discussions) for real-world gotchas -4. **GitHub issues** tagged with the migration — reveals common pitfalls - -Good search queries: -- `"package-name" migration guide v1 to v2` -- `"package-name" breaking changes version X` -- `"package-name" upgrade guide` -- `site:github.com "package-name" migration` - -When you find a migration guide, **WebFetch** the full page and extract the actionable steps. Don't just skim search results — read the actual guide. Pay attention to: - -- **Removed APIs** — what was deleted and what replaces it -- **Renamed APIs** — methods/classes that changed names -- **Changed behavior** — same API but different semantics (these are the dangerous ones) -- **New required configuration** — things that were optional and are now mandatory -- **Dependency changes** — packages that were split, merged, or renamed -- **Minimum runtime requirements** — e.g., requires Java 17+, Node 18+, Python 3.9+ - -### Check for migration tooling - -Many ecosystems have automated migration tools. Check if one exists before doing manual work: - -| Ecosystem | Tool | What it does | How to run | -|---|---|---|---| -| Java/Kotlin | **OpenRewrite** | AST-based automated refactoring with recipes for framework migrations | `mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=` | -| Java (AWS SDK) | **AWS SDK Migration Tool** | Automated V1→V2 migration using OpenRewrite recipes | `mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2` | -| Java (Spring) | **OpenRewrite Spring recipes** | Spring Boot 2→3, Spring Framework 5→6, Spring Security migrations | `mvn org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0` | -| PHP | **Rector** | Automated PHP version upgrades and framework migrations | `vendor/bin/rector process src --set php80` or custom rules | -| JavaScript/TS | **jscodeshift** | AST-based codemods for JS/TS transformations | `npx jscodeshift -t ` | -| JavaScript/TS | **Framework codemods** | Next.js, React, Angular, etc. ship their own codemods | e.g., `npx @next/codemod@latest ` | -| Python | **pyupgrade** | Modernize Python syntax to newer versions | `pyupgrade --py3-plus *.py` | -| Python | **django-upgrade** | Automated Django version upgrades | `django-upgrade --target-version 4.2 **/*.py` | -| Go | **go fix** | Applies targeted fixes for Go API changes | `go fix ./...` | -| Rust | **cargo fix** | Applies compiler-suggested fixes for edition migrations | `cargo fix --edition` | -| Ruby | **Rubocop** | With migration cops for Rails upgrades | `rubocop -a --only Rails/` | -| .NET | **dotnet-migration-tool** | .NET framework to .NET Core/5+ migration | `dotnet try-convert` | - -When a migration tool exists: -1. Run it first — it handles the mechanical, repetitive changes -2. Review what it changed -3. Handle the remaining manual migration steps it couldn't automate -4. Verify everything compiles and tests pass after the tool run, before doing manual work - -When no tool exists, or after the tool has done what it can, proceed with manual migration. - -### Build a migration checklist - -Before starting code changes, compile a checklist from your research: - -``` -## Migration: [package] v[old] → v[new] - -### Prerequisites -- [ ] Runtime version requirement met (e.g., Java 17+) -- [ ] No conflicting dependency version locks - -### Automated steps -- [ ] Run [migration tool] if available -- [ ] Update version in dependency manifest - -### Manual code changes -- [ ] Replace removed API X with new API Y -- [ ] Rename import from old.package to new.package -- [ ] Update configuration format from X to Y -- [ ] Handle behavioral change: [description] - -### Verification -- [ ] Build passes -- [ ] All tests pass -- [ ] [Specific smoke test for migrated functionality] -``` - -Present this checklist to the user (via the launcher skill) before starting work. - -## Phase 2: Execute the Migration - -### Order of operations - -1. **Update the dependency version** in the manifest file (follow kb-dependency-management for ecosystem-specific commands) -2. **Run migration tool** if one exists — this handles bulk mechanical changes -3. **Fix compilation errors** systematically: - - Start with import/package changes (these cascade into the most errors) - - Then fix API signature changes (renamed methods, changed parameters) - - Then fix type changes (generics, return types) - - Then fix configuration changes -4. **Fix behavioral changes** — these don't cause compilation errors but change runtime behavior. The migration guide research is essential here. -5. **Update tests** if test APIs changed (e.g., testing utilities that moved packages) -6. **Run the full test suite** — this catches behavioral regressions - -### Handling package renames - -When a library splits into multiple packages or changes its artifact name: - -1. Identify all old package references: `grep -r "old.package.name" --include="*.java"` (or equivalent) -2. Update imports systematically — use find-and-replace when the mapping is 1:1 -3. Update dependency manifest — remove old artifact, add new one(s) -4. If the library split into multiple packages, add only the ones actually used (check imports) - -### Handling removed APIs with no direct replacement - -Sometimes a feature is removed without a drop-in replacement. In these cases: - -1. Document what was removed and why (from the migration guide) -2. Identify all usages in the codebase -3. Propose an alternative implementation to the user -4. If the alternative is straightforward, implement it -5. If it requires significant design decisions, flag it and ask - -### Handling behavioral changes - -These are the most dangerous migration issues because the code compiles fine but behaves differently: - -1. List all behavioral changes from the migration guide -2. Search the codebase for usage of affected APIs -3. For each usage, determine if the behavioral change impacts it -4. Add or update tests to assert the expected behavior under the new version -5. Fix any code that relied on the old behavior - -## Phase 3: Verification - -Verification is mandatory and comprehensive: - -1. **Build** — the project must compile cleanly with no warnings related to the migration -2. **Test suite** — all existing tests must pass. If a test fails: - - Determine if the test is testing old behavior that legitimately changed → update the test - - Or if it reveals a real regression → fix the code -3. **Search for remnants** — grep for old package names, old API patterns, deprecated markers that the migration should have resolved -4. **No partial migrations** — if some usages couldn't be migrated, document them clearly rather than leaving a mix of old and new patterns - -If verification fails and the issues are beyond quick fixes, do not commit. Report what succeeded, what failed, and what needs human attention. - -## Git Workflow - -The launcher skill controls the git workflow. The migrator agent **must follow the launcher's instructions** for checkout, branching, committing, and pushing. - -When the launcher provides explicit git workflow steps (e.g., "checkout main, pull, create branch X, commit, do not push"), follow them exactly. - -When no explicit instructions are provided, use these defaults: - -1. Checkout the default branch and pull latest -2. Create a branch: `chore/migrate-[package]-v[old]-to-v[new]` -3. Execute the migration -4. Verify build and tests -5. Commit with message: `chore(deps): migrate [package] from v[old] to v[new]` -6. Do not push (let the launcher handle delivery) - -Build and test verification cannot be disabled for migrations — these settings are intentionally absent. - -## Error Handling - -- **Migration tool fails**: Report the error, fall back to manual migration -- **Compilation fails after migration**: Investigate systematically — start with the most basic errors (imports) and work up -- **Tests fail**: Distinguish between tests that need updating (testing old behavior) vs genuine regressions -- **Partial migration**: If some code can't be migrated automatically, document what's left and why -- **Runtime requirement not met**: Report that the target version requires a newer runtime and ask the user how to proceed diff --git a/skills/kb-design/SKILL.md b/skills/kb-design/SKILL.md index b53ece1..fbc98f5 100644 --- a/skills/kb-design/SKILL.md +++ b/skills/kb-design/SKILL.md @@ -216,6 +216,21 @@ cd "${CLAUDE_SKILL_DIR}/scripts" && python3 search.py "" --domain " --format markdown ``` +### Live Design System Persistence (`docs/design-system/`) + +One corrections-aware design system per repo, rooted at `docs/design-system/`: +`MASTER.md` (global source of truth) + `pages/.md` (per-page overrides that take precedence over MASTER). + +```bash +# Write / regenerate the live system (preserves the Corrections & Decisions log): +cd "${CLAUDE_SKILL_DIR}/scripts" && python3 search.py "" --design-system --persist --output-dir docs [--page ] +``` + +Flow: +- **Read-first:** always read `docs/design-system/MASTER.md` (and `pages/.md` when working a page) before designing, and stay within it — including its `## Corrections & Decisions` log. +- **Persist on generate:** run the command above when establishing or changing the shared system. +- **Persist on correction:** when a design is corrected or a choice fails, append a dated bullet to `## Corrections & Decisions` (MASTER for global, `pages/.md` for page-specific) and update the affected spec. The log is append-only and survives regeneration. + ### Data Files (BM25-searchable via scripts/) - **`data/styles.csv`** — 67 UI styles with keywords, colors, effects, accessibility ratings diff --git a/skills/kb-design/scripts/design_system.py b/skills/kb-design/scripts/design_system.py index d919618..9111589 100644 --- a/skills/kb-design/scripts/design_system.py +++ b/skills/kb-design/scripts/design_system.py @@ -545,24 +545,24 @@ def generate_design_system(query: str, project_name: str = None, output_format: # ============ PERSISTENCE FUNCTIONS ============ def persist_design_system(design_system: dict, page: str = None, output_dir: str = None, page_query: str = None) -> dict: """ - Persist design system to design-system// folder using Master + Overrides pattern. - + Persist design system to design-system/ folder using Master + Overrides pattern. + + One design system per repo — with `--output-dir docs` this yields + `docs/design-system/MASTER.md` + `docs/design-system/pages/.md` (no project subfolder). + Args: design_system: The generated design system dictionary page: Optional page name for page-specific override file output_dir: Optional output directory (defaults to current working directory) page_query: Optional query string for intelligent page override generation - + Returns: dict with created file paths and status """ base_dir = Path(output_dir) if output_dir else Path.cwd() - - # Use project name for project-specific folder - project_name = design_system.get("project_name", "default") - project_slug = project_name.lower().replace(' ', '-') - - design_system_dir = base_dir / "design-system" / project_slug + + # One design system per repo — no per-project subfolder. + design_system_dir = base_dir / "design-system" pages_dir = design_system_dir / "pages" created_files = [] @@ -572,17 +572,17 @@ def persist_design_system(design_system: dict, page: str = None, output_dir: str pages_dir.mkdir(parents=True, exist_ok=True) master_file = design_system_dir / "MASTER.md" - - # Generate and write MASTER.md - master_content = format_master_md(design_system) + + # Generate and write MASTER.md (carry forward any existing Corrections log) + master_content = _preserve_corrections(master_file, format_master_md(design_system)) with open(master_file, 'w', encoding='utf-8') as f: f.write(master_content) created_files.append(str(master_file)) - + # If page is specified, create page override file with intelligent content if page: page_file = pages_dir / f"{page.lower().replace(' ', '-')}.md" - page_content = format_page_override_md(design_system, page, page_query) + page_content = _preserve_corrections(page_file, format_page_override_md(design_system, page, page_query)) with open(page_file, 'w', encoding='utf-8') as f: f.write(page_content) created_files.append(str(page_file)) @@ -594,6 +594,30 @@ def persist_design_system(design_system: dict, page: str = None, output_dir: str } +# Corrections log is append-only and hand-edited between sessions; regeneration must never wipe it. +CORRECTIONS_HEADING = "## Corrections" + + +def _preserve_corrections(existing_file, new_content: str) -> str: + """Carry an existing append-only Corrections log across regeneration so it's never lost. + + The Corrections section is always the last section of the file, so we take everything + from its heading to EOF in the old file and splice it into the freshly generated content. + """ + existing_file = Path(existing_file) + if not existing_file.exists(): + return new_content + old = existing_file.read_text(encoding='utf-8') + idx_old = old.find(CORRECTIONS_HEADING) + if idx_old == -1: + return new_content + old_log = old[idx_old:].rstrip() + "\n" + idx_new = new_content.find(CORRECTIONS_HEADING) + if idx_new != -1: + return new_content[:idx_new] + old_log + return new_content.rstrip() + "\n\n" + old_log + + def format_master_md(design_system: dict) -> str: """Format design system as MASTER.md with hierarchical override logic.""" project = design_system.get("project_name", "PROJECT") @@ -611,7 +635,7 @@ def format_master_md(design_system: dict) -> str: # Logic header lines.append("# Design System Master File") lines.append("") - lines.append("> **LOGIC:** When building a specific page, first check `design-system/pages/[page-name].md`.") + lines.append("> **LOGIC:** When building a specific page, first check `pages/[page-name].md` (next to this file).") lines.append("> If that file exists, its rules **override** this Master file.") lines.append("> If not, strictly follow the rules below.") lines.append("") @@ -853,7 +877,20 @@ def format_master_md(design_system: dict) -> str: lines.append("- [ ] No content hidden behind fixed navbars") lines.append("- [ ] No horizontal scroll on mobile") lines.append("") - + + # Corrections & Decisions — MUST stay the last section (preserved across regeneration) + lines.append("---") + lines.append("") + lines.append("## Corrections & Decisions") + lines.append("") + lines.append("> **LIVE, append-only log.** When a design choice is corrected by the user, or is") + lines.append("> found not to work, add a dated bullet here (global decisions) or in the relevant") + lines.append("> `pages/.md` (page-specific), AND update the affected spec above. Never delete") + lines.append("> entries — this is how the design stops repeating past mistakes across sessions.") + lines.append("") + lines.append("- _(none yet)_") + lines.append("") + return "\n".join(lines) @@ -874,7 +911,7 @@ def format_page_override_md(design_system: dict, page_name: str, page_query: str lines.append(f"> **Generated:** {timestamp}") lines.append(f"> **Page Type:** {page_overrides.get('page_type', 'General')}") lines.append("") - lines.append("> ⚠️ **IMPORTANT:** Rules in this file **override** the Master file (`design-system/MASTER.md`).") + lines.append("> ⚠️ **IMPORTANT:** Rules in this file **override** the Master file (`../MASTER.md`).") lines.append("> Only deviations from the Master are documented here. For all other rules, refer to the Master.") lines.append("") lines.append("---") @@ -962,7 +999,17 @@ def format_page_override_md(design_system: dict, page_name: str, page_query: str for rec in recommendations: lines.append(f"- {rec}") lines.append("") - + + # Corrections — MUST stay the last section (preserved across regeneration) + lines.append("---") + lines.append("") + lines.append("## Corrections & Decisions (this page)") + lines.append("") + lines.append("> Append-only. Add a dated bullet when a choice for this page is corrected or fails.") + lines.append("") + lines.append("- _(none yet)_") + lines.append("") + return "\n".join(lines) diff --git a/skills/kb-design/scripts/search.py b/skills/kb-design/scripts/search.py index cd97212..e97068e 100644 --- a/skills/kb-design/scripts/search.py +++ b/skills/kb-design/scripts/search.py @@ -89,16 +89,17 @@ def format_output(result): # Print persistence confirmation if args.persist: - project_slug = args.project_name.lower().replace(' ', '-') if args.project_name else "default" + base = f"{args.output_dir.rstrip('/')}/" if args.output_dir else "" print("\n" + "=" * 60) - print(f"✅ Design system persisted to design-system/{project_slug}/") - print(f" 📄 design-system/{project_slug}/MASTER.md (Global Source of Truth)") + print(f"✅ Design system persisted to {base}design-system/") + print(f" 📄 {base}design-system/MASTER.md (Global Source of Truth)") if args.page: page_filename = args.page.lower().replace(' ', '-') - print(f" 📄 design-system/{project_slug}/pages/{page_filename}.md (Page Overrides)") + print(f" 📄 {base}design-system/pages/{page_filename}.md (Page Overrides)") print("") - print(f"📖 Usage: When building a page, check design-system/{project_slug}/pages/[page].md first.") + print(f"📖 Usage: When building a page, check {base}design-system/pages/[page].md first.") print(f" If exists, its rules override MASTER.md. Otherwise, use MASTER.md.") + print(f" On a design correction, append a dated bullet to the Corrections & Decisions log.") print("=" * 60) # Mood-based color search elif args.mood: diff --git a/skills/kb-documentation/SKILL.md b/skills/kb-documentation/SKILL.md deleted file mode 100644 index 77e91e2..0000000 --- a/skills/kb-documentation/SKILL.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -name: kb-documentation -description: Domain logic for documentation — injected into the docs-keeper agent. Provides guidance on creating and maintaining separate documentation files (README, API docs, guides). Not invoked directly. -user-invocable: false -disable-model-invocation: true ---- - -# Documentation - -Guidance for creating and maintaining separate documentation files. This skill covers README files, API documentation, architecture docs, and user guides. Inline code documentation (JSDoc, docstrings, etc.) is handled by the implementer during coding — do not duplicate what's already in the code. - -## Pipeline Context - -In the devline pipeline, read the plan and git diff to understand what changed. Focus on the delta — don't re-describe unchanged features. Inline docs were handled by implementers. - -## Documentation Types - -### README - -Every project needs a README covering: -- Project name and one-line description -- Prerequisites and setup instructions -- Quick start / getting started -- Available commands (build, test, run) -- Project structure overview -- Contributing guidelines (if open source) - -### API Documentation - -For projects exposing APIs: -- Endpoint list with methods and paths -- Request/response schemas with examples -- Authentication requirements -- Error codes and handling -- Rate limits and pagination - -### Architecture Documentation - -For complex projects: -- System overview and component diagram -- Data flow between components -- Key design decisions and rationale -- Technology stack and justification -- Deployment architecture - -### User Guides - -For end-user-facing projects: -- Getting started tutorial -- Feature walkthroughs -- FAQ and troubleshooting -- Configuration reference - -## Documentation Detection - -Before writing documentation, check what already exists: - -1. Look for `docs/` directory, `README.md`, `CHANGELOG.md` -2. Check for doc generators (`typedoc.json`, `mkdocs.yml`, `docusaurus.config.js`, `.readthedocs.yml`, `javadoc`) -3. Match existing format, style, and structure -4. Check `.claude/devline.local.md` for `doc_format` override - -## Writing Standards - -- Present tense, active voice, second person ("Run the command") -- Start with the most important information; use hierarchical headings -- Code examples must be copy-pasteable, runnable, with language identifiers -- Use tables for structured reference data - -## Keeping Docs in Sync - -Identify what changed, find all docs referencing changed code, update to match, verify examples still work. - -## Additional Resources - -### Reference Files - -For format-specific patterns: - -- **`references/doc-templates.md`** — Templates for README, API docs, architecture docs -- **`references/doc-tools.md`** — Documentation generators and their configuration diff --git a/skills/kb-documentation/references/doc-templates.md b/skills/kb-documentation/references/doc-templates.md deleted file mode 100644 index 9e90e35..0000000 --- a/skills/kb-documentation/references/doc-templates.md +++ /dev/null @@ -1,181 +0,0 @@ -# Documentation Templates - -## README Template - -```markdown -# Project Name - -One-line description of what this project does. - -## Prerequisites - -- [Requirement 1] (version X.Y+) -- [Requirement 2] - -## Quick Start - -\`\`\`bash -# Clone and install -git clone -cd project-name -[install command] - -# Run -[run command] -\`\`\` - -## Usage - -### [Feature 1] -[Description and examples] - -### [Feature 2] -[Description and examples] - -## Development - -### Setup -\`\`\`bash -[dev setup commands] -\`\`\` - -### Testing -\`\`\`bash -[test commands] -\`\`\` - -### Building -\`\`\`bash -[build commands] -\`\`\` - -## Project Structure - -\`\`\` -src/ -├── [dir]/ # [Purpose] -├── [dir]/ # [Purpose] -└── [file] # [Purpose] -\`\`\` - -## Contributing - -[Guidelines or link to CONTRIBUTING.md] - -## License - -[License type] — see [LICENSE](LICENSE) -``` - -## API Documentation Template - -```markdown -# API Reference - -## Authentication - -[How to authenticate] - -## Endpoints - -### [Resource Name] - -#### Create [Resource] -\`\`\` -POST /api/resource -\`\`\` - -**Request Body:** -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| name | string | Yes | Resource name | - -**Response:** `201 Created` -\`\`\`json -{ - "id": "abc123", - "name": "Example" -} -\`\`\` - -**Errors:** -| Code | Description | -|------|-------------| -| 400 | Invalid input | -| 401 | Unauthorized | - -#### List [Resources] -\`\`\` -GET /api/resources?page=1&limit=20 -\`\`\` - -**Query Parameters:** -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| page | integer | 1 | Page number | -| limit | integer | 20 | Items per page | -``` - -## Architecture Documentation Template - -```markdown -# Architecture Overview - -## System Diagram - -[Description or ASCII diagram of system components] - -## Components - -### [Component 1] -- **Purpose:** [What it does] -- **Technology:** [Stack used] -- **Key files:** [Entry points] - -### [Component 2] -... - -## Data Flow - -1. [Step 1: User action] -2. [Step 2: Processing] -3. [Step 3: Response] - -## Design Decisions - -| Decision | Choice | Rationale | -|----------|--------|-----------| -| Database | PostgreSQL | ACID compliance needed for financial data | -| Cache | Redis | Sub-ms latency for session storage | - -## Deployment - -[How the system is deployed and where] -``` - -## Changelog Template - -```markdown -# Changelog - -All notable changes to this project will be documented in this file. - -## [Unreleased] - -### Added -- [New feature description] - -### Changed -- [Modified behavior description] - -### Fixed -- [Bug fix description] - -### Removed -- [Removed feature description] - -## [1.0.0] - 2024-01-15 - -### Added -- Initial release -``` diff --git a/skills/kb-documentation/references/doc-tools.md b/skills/kb-documentation/references/doc-tools.md deleted file mode 100644 index 2acb5b3..0000000 --- a/skills/kb-documentation/references/doc-tools.md +++ /dev/null @@ -1,91 +0,0 @@ -# Documentation Tools - -## Static Site Generators - -### MkDocs (Python) -- Config: `mkdocs.yml` -- Content: `docs/` directory with `.md` files -- Build: `mkdocs build`, serve: `mkdocs serve` -- Material theme recommended for modern look -- Supports admonitions, tabs, code highlighting - -### Docusaurus (JavaScript) -- Config: `docusaurus.config.js` -- Content: `docs/` with `.md` or `.mdx` files -- Features: versioning, i18n, search, blog -- React-based with MDX support - -### VitePress (JavaScript) -- Config: `.vitepress/config.js` -- Lightweight Vue-powered static site -- Markdown with Vue components -- Fast HMR development - -## API Documentation - -### OpenAPI / Swagger -- Spec: `openapi.yaml` or `openapi.json` -- Tools: Swagger UI, Redoc, Stoplight -- Generate client SDKs from spec -- Validate requests/responses against spec - -### TypeDoc (TypeScript) -- Config: `typedoc.json` -- Generates HTML from TSDoc comments -- Supports plugins and themes - -### Javadoc (Java) -- Built into JDK -- Generates HTML from `/** */` comments -- Standard tags: `@param`, `@return`, `@throws` - -### Godoc (Go) -- Built into Go toolchain -- Generates from regular comments above declarations -- Convention: first sentence is summary - -### Rustdoc (Rust) -- Built into Cargo: `cargo doc` -- Markdown in `///` doc comments -- Runs doc tests automatically - -## Inline Documentation - -### JSDoc (JavaScript/TypeScript) -```javascript -/** - * Creates a new user account. - * @param {string} name - The user's display name - * @param {string} email - The user's email address - * @returns {Promise} The created user object - * @throws {ValidationError} If email is invalid - */ -``` - -### Python Docstrings -```python -def create_user(name: str, email: str) -> User: - """Create a new user account. - - Args: - name: The user's display name. - email: The user's email address. - - Returns: - The created user object. - - Raises: - ValidationError: If email is invalid. - """ -``` - -### KDoc (Kotlin) -```kotlin -/** - * Creates a new user account. - * @param name The user's display name - * @param email The user's email address - * @return The created user object - * @throws ValidationException if email is invalid - */ -``` diff --git a/skills/kb-tdd-workflow/SKILL.md b/skills/kb-tdd-workflow/SKILL.md index c8b5e56..87adcc7 100644 --- a/skills/kb-tdd-workflow/SKILL.md +++ b/skills/kb-tdd-workflow/SKILL.md @@ -42,7 +42,22 @@ Choose the test level based on **what the code does**, not on convention or habi - **Cross-boundary flows** — requests that traverse multiple services or modules. - **Critical business paths** — the paths where a bug means revenue loss, compliance violation, or data corruption. -E2E tests are defined at the **feature level** by the planner (see Feature-Goal Tests in the plan), not per-task. They run in a dedicated final-wave task after all implementation is merged. +E2E tests are defined at the **feature level** by the planner (see Feature-Goal Tests in the plan), not per-task. Include a dedicated final-wave E2E task ONLY for features with a genuine multi-step cross-boundary journey; skip it for single-component changes, pure-logic changes, and bugfixes (per-task integration tests already cover that surface). When present, it runs after all implementation is merged. + +## Test Depth + +A per-feature dial (from `.claude/devline.local.md` `test_depth`, or inferred during brainstorm). Two levels: + +- **deep** — exhaustive: a unit test per method plus edge cases and all configs, plus integration and E2E. This is the current default thoroughness. +- **focused** — big behavior tests over whole classes/workflows plus targeted tests for genuinely hard logic; integration/E2E for real journeys; SKIP exhaustive per-method unit tests for trivial code (getters, passthroughs, obvious branches). + +### Acceptance criteria as tests + +The brainstorm defines behavioral **acceptance criteria**. Each criterion becomes ONE behavior/workflow-level test, named to read as the criterion — the test name IS the spec sentence. There are no durable spec docs; the committed tests ARE the living spec. + +Under `focused`, these acceptance tests are the **primary suite**: do NOT write a unit test per method for trivial code — only for genuinely hard or edge logic. Under `deep`, the acceptance tests sit on top of the exhaustive per-method units. + +`focused` changes nothing about level selection: per-test `[unit]`/`[integration]`/`[e2e]` tagging stays, NEW I/O (persistence, endpoints, events) is still `[integration]` by default, the E2E task stays **SHOULD** (only for genuine cross-boundary journeys), and the integration size-gate — a targeted unit test suffices when modifying existing integration-tested code without changing its schema/contract — still applies. `focused` only drops the redundant per-method units for trivial code; it never downgrades a real journey or a new I/O surface. ## What NOT to Test @@ -69,7 +84,7 @@ If every controller has 5-10 tests like "returns 403 for VIEWER role", you have Never skip steps. Never write implementation before a failing test exists. -**For planners:** Define test cases in the plan with their level: `[unit]`, `[integration]`, `[e2e]`. Use the selection heuristics above — don't default to `[unit]`. Repository methods, controller endpoints, event listeners, and schedulers should be `[integration]` by default. +**For planners:** Define test cases in the plan with their level: `[unit]`, `[integration]`, `[e2e]` (per-test-case tagging is cheap — keep it). Use the selection heuristics above — don't default to `[unit]`. NEW repository methods, controller endpoints, event listeners, and schedulers should be `[integration]` by default. But when modifying existing, already-integration-tested persistence/endpoint code **without changing its schema or contract**, a targeted unit test of the changed logic is sufficient — rely on the existing integration suite. **For implementers:** Implement tests one at a time through the cycle. Each test drives the next increment of design. diff --git a/skills/migrate/SKILL.md b/skills/migrate/SKILL.md deleted file mode 100644 index 2c12b62..0000000 --- a/skills/migrate/SKILL.md +++ /dev/null @@ -1,227 +0,0 @@ ---- -name: migrate -description: "Migrate dependencies to new major versions — handles breaking changes, API refactoring, package renames, and behavioral differences. Researches migration guides and tooling, then launches dependency-migrator agents. Use this skill when the user wants to upgrade a dependency across a major version, migrate from one library to another (e.g., Moment.js to date-fns), prepare for EOL by upgrading early, or handle any dependency transition that involves more than just changing a version number. Triggers on phrases like 'migrate', 'upgrade to v2', 'move from X to Y', 'end of life', 'EOL', 'deprecated', 'major version upgrade', 'breaking changes'." -argument-hint: " [from vX] to [--repos repo1 repo2]" -user-invocable: true -disable-model-invocation: false ---- - -# Migrate - -Orchestrates complex dependency migrations across one or many repositories. This is a launcher skill — it handles research, planning, and user approval, then delegates the actual migration to **dependency-migrator** agents (Opus). - -Unlike the CVE patcher which does targeted version bumps, migrations involve breaking changes, code refactoring, API replacements, and sometimes entirely different libraries. The migrate skill ensures thorough research happens before any code is touched. - -## Step 1: Parse Input - -The input is flexible — users describe migrations in many ways: - -``` -spring-boot to 3.2 # Upgrade to specific version -aws-sdk-java from v1 to v2 # Full version transition -moment to date-fns # Library replacement -lodash 3.x to 4.x --repos api billing # Scoped to specific repos -python 3.8 to 3.12 # Runtime/language upgrade -angular 14 to 17 # Framework multi-version jump - # No args = scan for EOL/deprecated deps -``` - -Extract: -- **Package/library name** (source and optionally target if it's a library swap) -- **Current version** (or "detect from repo") -- **Target version** -- **Repos**: If `--repos` is present, filter to those. Otherwise auto-detect. - -## Step 2: Detect Repositories - -Same pattern as other dependency skills: - -1. **Single repo**: Current directory has `.git/` → work in it directly -2. **Multi-repo folder**: Subdirectories with `.git/` → work in all or filtered by `--repos` - -For multi-repo with no filter and more than 10 repos, confirm with the user. - -## Step 3: Research the Migration - -This is the most important step. Do not skip or rush it. - -### 3a: Find the migration guide - -Use **WebSearch** to find: - -1. **Official migration guide** — the primary source of truth -2. **Changelog / breaking changes list** for the target version -3. **Migration tooling** — does a codemod, OpenRewrite recipe, Rector rule, or official CLI tool exist? -4. **Community guides** — blog posts and GitHub discussions for real-world gotchas - -Research queries to try: -- `"[package]" migration guide v[old] to v[new]` -- `"[package]" breaking changes v[new]` -- `"[package]" upgrade tool codemod` -- `"[package]" v[new] migration issues site:github.com` - -Use **WebFetch** on the most promising results to read the full migration guide. Extract actionable steps. - -### 3b: Check for migration tools - -Search for ecosystem-specific tooling: - -| Ecosystem | Check for | -|---|---| -| Java/Kotlin (Maven/Gradle) | OpenRewrite recipes (`docs.openrewrite.org/recipes`), official migration tools | -| PHP (Composer) | Rector rules (`getrector.com`) | -| JavaScript/TypeScript (npm) | Official codemods (`npx @package/codemod`), jscodeshift transforms | -| Python (pip/poetry) | pyupgrade, django-upgrade, framework-specific tools | -| Go | `go fix`, official migration scripts | -| Rust | `cargo fix --edition`, clippy migration lints | -| Ruby (Bundler) | RuboCop cops, rails app:update | -| .NET (NuGet) | `dotnet try-convert`, .NET Upgrade Assistant | - -### 3c: If no package specified — EOL/deprecation audit - -When the user invokes without a specific package, scan for dependencies that are EOL, deprecated, or approaching end of support: - -1. Scan dependency manifests for all declared packages -2. Check major framework/runtime versions against known support windows -3. Use WebSearch to verify EOL status for anything that looks potentially unsupported -4. Present findings and let the user choose what to migrate - -## Step 4: Present Migration Plan - -Present a detailed summary to the user and **wait for approval** before launching any agents: - -``` -## Migration: [package] v[old] → v[new] - -### Breaking Changes -1. [Change description — e.g., "javax.* namespace renamed to jakarta.*"] -2. [Change description — e.g., "Spring Security: WebSecurityConfigurerAdapter removed"] -3. [Change description — e.g., "Default serialization changed from X to Y"] - -### Migration Tooling -- [Tool name]: [what it automates] — will run first -- Manual steps remaining: [what the tool can't handle] - -### Runtime Requirements -- Requires: [e.g., Java 17+, Node 18+] — [met/not met in target repos] - -### Affected Repositories -| Repository | Current Version | Affected | Notes | -|---|---|---|---| -| my-api | 2.7.18 | Yes | Heavy usage of removed APIs | -| billing | 2.7.18 | Yes | Minimal usage, mostly auto-migratable | -| auth | 3.1.0 | No | Already on 3.x | - -### Risk Assessment -- **Low risk**: [repos where migration is mostly automated] -- **Medium risk**: [repos with moderate manual work] -- **High risk**: [repos with heavy usage of removed/changed APIs] - -### Verification -- Build verification: always on (mandatory for migrations) -- Test verification: always on (mandatory for migrations) -``` - -The user must approve before proceeding. If they want to exclude certain repos or defer high-risk ones, adjust accordingly. - -## Step 5: Launch Dependency-Migrator Agents - -### Git workflow (applies to all modes) - -Git workflow is **not configurable** for migrations. Every dependency-migrator agent MUST follow this exact workflow: - -1. **Checkout the default branch** (detect with `git symbolic-ref refs/remotes/origin/HEAD`, fall back to `main` then `master`) -2. **Pull latest** (`git pull`) -3. **Create a migration branch**: `chore/migrate-[package]-v[old]-to-v[new]` -4. **Execute the migration** (tooling + manual) -5. **Verify** build and tests (mandatory, cannot be skipped) -6. **Commit** with message: `chore(deps): migrate [package] from v[old] to v[new]` -7. **Do NOT push** — the launcher handles delivery - -### Single-repo mode - -Launch one **dependency-migrator** agent with: - -``` -Migrate [package] from v[old] to v[new] in this repository. - -Repository: [absolute path] - -Migration guide: [URL or summary of key breaking changes] - -Migration tool: [tool name and command, or "none — manual migration"] - -Migration checklist: -[The compiled checklist from research] - -Git workflow: -1. Checkout the default branch and pull latest -2. Create branch: chore/migrate-[package]-v[old]-to-v[new] -3. Execute migration -4. Verify build and tests -5. Commit with message: chore(deps): migrate [package] from v[old] to v[new] -6. Do NOT push — stop after committing - -Settings: dep_auto_push=false, dep_branch_strategy=branch -``` - -### Multi-repo mode - -Launch one **dependency-migrator** agent per repository in parallel (background). Each receives: - -- The full migration research (guide, breaking changes, tool info) -- Its specific repository path and current version -- The migration checklist -- The git workflow instructions above (checkout default branch, pull, branch, migrate, verify, commit, NO push) - -Wait for all agents to complete. - -## Step 6: Present Summary and Delivery Options - -``` -| Repository | Status | Tool Used | Manual Changes | Tests | Branch | -|------------------|-----------|----------------|----------------|--------|-----------------------------------| -| my-api | Migrated | OpenRewrite | 12 files | 98/98 | chore/migrate-spring-boot-2-to-3 | -| billing-service | Migrated | OpenRewrite | 3 files | 45/45 | chore/migrate-spring-boot-2-to-3 | -| legacy-app | Failed | OpenRewrite | — | 12/30 | (not committed) | -``` - -For failed repos, include: -- What went wrong (test failures, compilation errors) -- What was already done vs what remains -- Recommendation (manual fix needed, defer, etc.) - -Then, for each repository that has successful migrations, ask the user how they want to deliver the changes: - -``` -How would you like to deliver these changes? - -1. **Create a PR** — push the branch and open a pull request (requires remote access) -2. **Squash merge locally** — squash-merge the migration branch into the default branch locally (no remote interaction) -3. **Exit** — leave the migration branch as-is and print the changes so you can handle it manually -``` - -### Handling each option: - -**Option 1 — Create a PR:** -- Push the migration branch: `git push -u origin [branch-name]` -- Create a PR using `gh pr create` with: - - Title: `chore(deps): migrate [package] from v[old] to v[new]` - - Body: migration summary including breaking changes addressed, tool used, and verification results -- Report the PR URL - -**Option 2 — Squash merge locally:** -- Checkout the default branch -- Run `git merge --squash [migration-branch]` -- Commit with the same message: `chore(deps): migrate [package] from v[old] to v[new]` -- Delete the migration branch: `git branch -d [migration-branch]` -- Report: "Changes squash-merged into [default-branch]. Ready to push when you are." - -**Option 3 — Exit:** -- Print a summary of what changed: - - Branch name - - Files modified (from `git diff --stat [default-branch]..[migration-branch]`) - - The commit(s) on the branch -- Report: "Migration branch [branch-name] is ready. You can push, merge, or cherry-pick manually." - -In multi-repo mode, apply the same option to all repos unless the user requests per-repo handling. diff --git a/skills/quick/SKILL.md b/skills/quick/SKILL.md new file mode 100644 index 0000000..96d387f --- /dev/null +++ b/skills/quick/SKILL.md @@ -0,0 +1,22 @@ +--- +name: quick +description: Fast-lane a small change — branch, implement (TDD), one review, commit. Skips brainstorm, planning, design-system, deep review, and all approval gates. Use for bugfixes, typos, tweaks, or any change that touches ~1 file / ≲30 lines with no new component, schema, endpoint, or UI surface. +argument-hint: "" +user-invocable: true +disable-model-invocation: false +--- + +# Quick — Devline Fast Lane + +Force the devline **fast lane** for the given task, regardless of `fast_lane` config. This is the same fast lane described in the `devline` skill — skip the classification step and run it directly. + +Steps (single task, run in place — no worktrees, no waves, no gates): + +1. **Branch setup** — Stage 0 of the `devline` skill (branch off protected branches, create `.devline/`). +2. **Implement** — launch ONE **implementer** agent with the task. It writes tests first (TDD at the right level: unit for pure logic, integration for persistence/endpoints — see `kb-tdd-workflow`), then implements. The fast lane runs at `focused` depth — small changes don't warrant deep, so skip exhaustive per-method units for trivial code; cover behavior plus any genuinely hard logic. +3. **Review** — launch ONE **reviewer** agent (scope=task). Run a fix cycle if it returns blocking findings. +4. **Commit**, then ask only whether to merge (auto-proceed otherwise). + +Explicitly SKIP: brainstorm + its gate, design-system, the full plan doc + plan gate, the Feature E2E task, worktree/wave machinery, the deferred-findings batch-fix cycle, the docs-keeper full scan, `reviewer scope=branch` (deep review), and the final approval gate. + +If the task turns out to be larger than a fast-lane change (new component, schema/migration, new endpoint, UI surface, or clearly multi-file), stop and hand off to the full `/devline` pipeline instead. diff --git a/skills/setup/SKILL.md b/skills/setup/SKILL.md index 16cedc1..76376b4 100644 --- a/skills/setup/SKILL.md +++ b/skills/setup/SKILL.md @@ -13,7 +13,7 @@ Set up the devline pipeline for a project. Two files are created: 2. **`.claude/devline.local.md`** — pipeline settings (only non-default values) Assets: -- **[assets/claude-md-template.md](assets/claude-md-template.md)** — CLAUDE.md template with 6 sections (header, workflow orchestration, core principles, learning & recovery, project context, lessons placeholder) +- **[assets/claude-md-template.md](assets/claude-md-template.md)** — CLAUDE.md template with 4 sections (header, workflow orchestration, core principles, project context) - **[assets/devline-local-template.md](assets/devline-local-template.md)** — All available pipeline settings organized in 4 batches with defaults ## Process @@ -65,28 +65,51 @@ After all batches, collect only the non-default settings. If no settings were ch If there are non-default settings, assemble the file using the output format from the template. Show the preview using **AskUserQuestion** and write only after confirmation. Create `.claude/` directory if needed. -### 3. RTK (optional) - -Check if `rtk` is installed by running `which rtk`. - -- **Installed** → inform the user RTK is already installed, skip this step. -- **Not installed** → explain: - -``` -RTK (Rust Token Killer) is a CLI proxy that reduces token consumption by 60-90% on common commands (git, ls, grep, test runners, build tools). It works by filtering noise, grouping similar output, and truncating redundancy before it reaches your context window. - -Since devline runs many agents in parallel — all issuing Bash commands — RTK can significantly reduce costs. - -Would you like to install RTK? (It adds an auto-rewrite hook so all Bash commands are transparently optimized.) -``` - -If the user declines, skip. If they accept: - -1. Run `curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh` -2. Run `rtk init -g` to register the auto-rewrite hook in `~/.claude/settings.json` -3. Verify with `rtk --version` - -If any step fails, show the error and point the user to https://github.com/rtk-ai/rtk for manual installation. +### 3. Recommended additions (optional) + +Three optional companions make devline leaner and more capable. Offer all three — the user can accept any subset. For each: check if it's already present (note it and skip if so), otherwise briefly explain it and ask whether to install. If a step fails, show the error and point to the tool's repo for manual install. + +**RTK (Rust Token Killer)** — a CLI proxy that cuts token use 60-90% on common commands (git, ls, grep, test runners, builds) by filtering noise before it reaches context. devline runs many parallel agents issuing Bash commands, so the savings compound. +- Check: `which rtk`. +- If accepted: + 1. `curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh` + 2. `rtk init -g` — registers the auto-rewrite hook in `~/.claude/settings.json` + 3. Verify: `rtk --version` + +**Basic Memory** — local-first, per-project memory stored as plain Markdown you commit to the repo, retrieved on demand so it never bloats context. Gives agents persistent, cross-session recall of project decisions and corrections. Works in any Claude Code session, not just devline. +- Check: `which basic-memory`. +- If accepted (multi-session-safe setup — each Claude session binds to its own repo's `memory/` project via a per-session MCP wrapper, so parallel sessions never clobber a shared "active project"): + 1. `uv tool install basic-memory` + 2. Write the per-session MCP wrapper to `~/.claude/mcp/basic-memory-cwd.sh` (create `~/.claude/mcp/` if needed) and `chmod +x` it, with exactly this content: + ```bash + #!/usr/bin/env bash + # Per-session Basic Memory MCP server, bound to the current repo's project. + # One stdio server per Claude session (in that session's cwd) → each session + # pins to its own repo via --project, so parallel sessions never clobber a + # shared "active project". + export PATH="$HOME/.local/bin:$PATH" + repo=$(git rev-parse --show-toplevel 2>/dev/null) + if [ -n "$repo" ]; then + name=$(basename "$repo") + if ! basic-memory project list 2>/dev/null | grep -qw "$name"; then + mkdir -p "$repo/memory" + basic-memory project add "$name" "$repo/memory" >/dev/null 2>&1 || true + fi + exec basic-memory mcp --project "$name" + fi + exec basic-memory mcp + ``` + 3. `claude mcp add --scope user basic-memory -- bash ~/.claude/mcp/basic-memory-cwd.sh` + 4. Optionally add its official Claude Code plugin (`basic-memory@basicmachines-co`) for session-start recall + the `memory-defrag`/`memory-reflect` consolidation skills. +- For a full machine setup, the repo's `install.sh` does all of this plus devline + the other companions. + +**Ponytail** — a separate Claude Code plugin that keeps generated code minimal (YAGNI, stdlib-first, shortest working diff). It composes with devline: devline enforces the process, ponytail keeps the code lean. +- Check: whether the ponytail plugin is already enabled (look in `~/.claude/plugins` or the user's enabled plugins). +- If accepted: it's a plugin, so have the **user** run these interactive commands (this skill can't invoke `/plugin` itself): + ``` + /plugin marketplace add DietrichGebert/ponytail + /plugin install ponytail@ponytail + ``` ### 4. Closing Instructions diff --git a/skills/setup/assets/claude-md-template.md b/skills/setup/assets/claude-md-template.md index 99337ed..88f5087 100644 --- a/skills/setup/assets/claude-md-template.md +++ b/skills/setup/assets/claude-md-template.md @@ -45,27 +45,7 @@ This file is the single source of non-obvious project context — things that ca --- -## Section 4 — Learning & Recovery - -``` -## Learning & Recovery - -This project uses a self-correcting pipeline. Agents (implementer, reviewer, deep-review) continuously challenge themselves: "Is this a one-off issue or a broader pattern?" When they identify a non-obvious codebase pattern, they report it as a lesson and the orchestrator appends it to the Lessons and Memory section below. - -**For the pipeline (automatic):** Agents extract lessons during normal work. No approval needed — the agent already analyzed the issue. Lessons are shown in the pipeline completion summary. - -**For direct conversations (manual):** When the user corrects you or you discover a non-obvious pattern outside the pipeline: -1. Identify the root cause — not just the symptom. -2. Assess scope — one-off or pattern? -3. If it's a pattern, formulate as: pattern (what triggers it), reason (why it happens), solution (how to prevent it). -4. Append it to the Lessons and Memory section below. - -**Always:** Review existing lessons before starting work. If a lesson covers the situation, follow it. Update stale lessons rather than adding duplicates. -``` - ---- - -## Section 5 — Project Context (user fills in) +## Section 4 — Project Context (user fills in) ``` ## Project Context @@ -77,14 +57,3 @@ This project uses a self-correcting pipeline. Agents (implementer, reviewer, dee ``` - ---- - -## Section 6 — Lessons and Memory (empty placeholder) - -``` -## Lessons and Memory - - - -``` diff --git a/skills/setup/assets/devline-local-template.md b/skills/setup/assets/devline-local-template.md index 0d12cbb..9b3441f 100644 --- a/skills/setup/assets/devline-local-template.md +++ b/skills/setup/assets/devline-local-template.md @@ -23,21 +23,19 @@ auto_approve_brainstorm: false — Pause for approval after brainstorming auto_approve_plan: false — Pause for approval after planning ⚠ In multi-phase pipelines, this skips ALL phase plan approvals. Multiple phases can execute without any human checkpoint until deep review. +fast_lane: auto — Fast-lane small changes (branch→implement→one review→commit, skipping + brainstorm, plan, design system, deep review, and all gates). + auto = detect small changes, always = force fast lane, off = always full pipeline. ``` --- -## Batch 2 — Branching & Commits +## Batch 2 — Branching ``` -enforce_feature_branches: false — Block source code edits on protected branches (forces feature branch workflow) branch_format: "{kind}/{title}" — Branch naming format ({kind}, {title} placeholders) branch_kinds: "feat|fix|refactor|docs|chore|test|ci" — Allowed branch kinds (pipe-separated) -protected_branches: "(main|master|develop|release|production|staging)" — Protected branches (regex group) -merge_style: "squash" — Merge style: squash, merge, or rebase -direct_edit_extensions: "(md|txt|json|yaml|yml|toml|ini|cfg|conf|lock|gitignore|gitattributes|editorconfig|prettierrc|eslintrc|stylelintrc)" — Extensions editable on protected branches -commit_format: "kind(scope): details" — Human-readable commit format -commit_format_regex: "^(feat|fix|refactor|docs|chore|test|ci|style|perf|build|revert)(\\([a-zA-Z0-9._-]+\\))?: .+" — Commit validation regex +protected_branches: "(main|master|develop|release|production|staging)" — On these, Stage 0 auto-creates a feature branch (regex group) ``` --- @@ -49,6 +47,7 @@ test_framework: auto-detect — Override: "vitest", "jest", "pytest", etc. frontend_framework: auto-detect — Override: "react", "vue", "svelte", etc. doc_format: auto-detect — Override: "markdown", "asciidoc", etc. cloud_provider: auto-detect — Override: "aws", "gcp", "azure", etc. +test_depth: auto — auto = infer & ask if unclear | deep = exhaustive (every method/config) | focused = big workflow/class tests + hard logic, skip trivial-method units ``` --- @@ -79,7 +78,7 @@ Only non-default settings are written. If nothing was changed, no file is create ```markdown --- # Devline Local Settings — only non-default values. -# Full reference: https://github.com/marlonlom/claude-devline#settings-reference +# Full reference: https://github.com/Conava/claude-devline#settings-reference --- ``` diff --git a/skills/writing/SKILL.md b/skills/writing/SKILL.md index 074df4f..7266a9a 100644 --- a/skills/writing/SKILL.md +++ b/skills/writing/SKILL.md @@ -11,7 +11,7 @@ disable-model-invocation: false You are a writer, editor, and translator. You write new text, edit existing text, or translate between languages -- always so it reads like a person wrote it natively. All output must avoid AI writing patterns. References: -- General AI tropes: [references/tropes.md](references/tropes.md) +- General AI tropes: [references/tropes.md](references/tropes.md) — opens with the positive DOs (write like this), then the catalog of patterns to avoid. Apply both: add the DOs, don't just remove the DON'Ts. - Language-specific: [references/german.md](references/german.md) - Purpose-specific: [references/communication.md](references/communication.md), [references/project-content.md](references/project-content.md), [references/scientific.md](references/scientific.md), [references/creative.md](references/creative.md), [references/creative-de.md](references/creative-de.md) @@ -71,7 +71,7 @@ When working in a non-English language: ### 2. Identify AI patterns -Read [references/tropes.md](references/tropes.md) for the full catalog, the purpose-specific reference, and the language-specific reference if applicable. The tropes file is the authoritative scan list — do not rely on memory. +Read [references/tropes.md](references/tropes.md) for the full catalog, the purpose-specific reference, and the language-specific reference if applicable. The tropes file is the authoritative scan list — do not rely on memory. It leads with the positive DOs: the rewrite should actively do those, not just strip the DON'Ts, or you'll get gutted, voiceless text. ### 3. Rewrite @@ -160,7 +160,7 @@ Don't write a clean draft and then "humanize" it. Write like a person from the f ### 4. Self-audit -After writing, check against the trope catalog and language reference: "What sounds AI-generated here?" Fix it. Pay special attention to: +After writing, check against the trope catalog and language reference: "What sounds AI-generated here?" Fix it. Then check the reverse — "Did I actually do the DOs, or just avoid the DON'Ts?" — because scrubbing patterns without adding voice produces text that's just as artificial (see "Don't over-correct" in tropes.md). Pay special attention to: - **Rhythm:** Map sentence lengths — do they cluster uniformly? Force variation. - **Paragraph length:** Are all paragraphs ~3-4 sentences? Vary them. - **Openings:** Did you throat-clear? Cut the first paragraph and see if the second one works better as the opening. diff --git a/skills/writing/references/creative-de.md b/skills/writing/references/creative-de.md index 4bb6ccc..b7464b5 100644 --- a/skills/writing/references/creative-de.md +++ b/skills/writing/references/creative-de.md @@ -1,8 +1,13 @@ # Kreatives Schreiben — Deutsche Referenz -Ergänzt die allgemeine kreative Schreibreferenz (`creative.md`) um deutschsprachige Beispiele und Techniken. Alle Regeln aus `creative.md` gelten uneingeschränkt — diese Datei ERGÄNZT, sie ERSETZT NICHT. +Ergänzt die allgemeine kreative Schreibreferenz (`creative.md`) um deutschsprachige Techniken und Eigenheiten. Alle Regeln aus `creative.md` gelten uneingeschränkt — diese Datei ERGÄNZT, sie ERSETZT NICHT. -Stilistisch orientiert an Ursula Poznanski (Eleria-Trilogie) und Derek Landy (Skulduggery Pleasant, dt. Übersetzung). +Zwei produktive Modi prägen den deutschen kreativen Erzählraum: + +- **Stille Innenperspektive** — Ich- oder enge dritte Person, kein kommentierender Erzähler, Trauma und Verarbeitung über Körperwahrnehmung statt Gefühlsnamen. Sätze knapp bis sehr lang, geschachtelt, oft hypotaktisch. Metaphern selten und funktional. +- **Erzähler mit Haltung** — kommentierende dritte Person mit Witz, Urteil und freier indirekter Rede. Sätze schlagen scharf zwischen sehr lang und sehr kurz. Humor signalisiert Sicherheit, sein Fehlen Gefahr. + +Beide Modi lassen sich innerhalb desselben Buches mischen, aber nie innerhalb desselben Absatzes. Der Moduswechsel ist selbst ein Werkzeug — siehe weiter unten. --- @@ -11,15 +16,15 @@ Stilistisch orientiert an Ursula Poznanski (Eleria-Trilogie) und Derek Landy (Sk Deutsch erlaubt natürlicherweise ein breiteres Spektrum an Satzlängen als Englisch. Das ist eine Stärke — nutze sie. **Kurz für Wucht:** -- „Lu. Ist. Tot." (Poznanski — Stakkato im Rhythmus der Schritte) -- „Würde." — Ein einziges Wort als eigener Absatz. -- „Sein Kopf war ein Totenschädel." (Landy — Kapitelende als Enthüllung) +- Stakkato im Rhythmus von Schritten oder Atemzügen — drei Worte, drei Punkte, ein Absatz. +- Ein einziges Wort als eigener Absatz an Wendepunkten oder als Pointe. +- Ein nüchterner, unverzierter Aussagesatz am Kapitelende, der die ganze vorherige Atmosphäre umkippt. **Lang für Spannung und Atmosphäre:** -- „Wenn ich die Augen schließe, nur ganz kurz, bedeutet das nicht, dass ich dem trügerischen Sicherheitsgefühl nachgebe, das mich allmählich umfängt." (Poznanski) -- Die verbfinale Nebensatzstruktur erzwingt, dass der Leser den gesamten Satzbau halten muss, bevor die Auflösung kommt. Das IST Spannung. +- Verschachtelte Nebensätze, in denen die Verbklammer den Leser zwingt, den gesamten Satzbau zu halten, bevor die Auflösung kommt. +- Die verbfinale Struktur ist im Deutschen ein nativer Spannungsmechanismus. Englisch besitzt nichts Vergleichbares; daher übersieht KI das Werkzeug oft. -**Variation ist alles.** KI-generierter deutscher Text produziert gleichförmig mittellange Sätze (15-25 Wörter). Das ist verdächtiger als im Englischen, weil es die natürliche Tradition langer deutscher Sätze vermeidet. Lass manche Sätze 40-50 Wörter lang sein. Folge mit einem Fünf-Wort-Satz. +**Variation ist alles.** KI-generierter deutscher Text produziert gleichförmig mittellange Sätze (15-25 Wörter). Das ist im Deutschen verdächtiger als im Englischen, weil es die natürliche Tradition langer deutscher Sätze meidet. Lass manche Sätze 40-50 Wörter lang sein. Folge mit einem Fünf-Wort-Satz. --- @@ -32,33 +37,19 @@ Zwei Systeme, beide korrekt — eines wählen und durchhalten: - **Gänsefüßchen:** „Text" (unten-oben) — ebenfalls Standard - FALSCH: "Text" (englische Anführungszeichen) -### Dialogbeispiele nach Poznanski - -Knappe Tags, Psychologie durch Handlung: - -> Er streicht über seinen kurzen dunklen Kinnbart. »Noch einmal von vorne.« - -Die Geste zeigt den Denkprozess — kein Tag nötig. - -> »Ja?« Sein Ton ist gelassen wie immer. +### Knappe Tags, Geste statt Tag -Ein Wort Dialog, dann interne Analyse des Tons. +Das Verb »sagen« ist unsichtbar — verwende es. Aufwendige Tags (»hauchte«, »entgegnete spitzfindig«, »äußerte erstickt«) ziehen Aufmerksamkeit auf den Erzähler statt auf die Figur. Statt Tags: Geste-Beats, die den Denkprozess oder die innere Bewegung sichtbar machen, vor oder nach dem Dialog. -> »Die Expedition ...«, stößt Tomma endlich hervor. +Statt »fragte er nachdenklich« → die nachdenkliche Geste vor dem Satz, dann der Satz ohne Tag. Der Leser leitet aus der Geste die Tonlage ab. -Das Verb „hervorsto\u00dfen" transportiert körperlichen Kampf, nicht nur Sprache. +Sprech-Verben, die körperlichen Kampf transportieren (»stieß hervor«, »presste heraus«, »quetschte«), sind erlaubt, wenn der körperliche Akt tatsächlich auf der Seite stattfindet. Als bloße Ausschmückung des »sagte«-Tags sind sie KI-Marker — eine Figur, die auf einer Couch sitzt und Tee trinkt, »stößt« nichts »hervor«. -### Dialogbeispiele nach Landy +### Pingpong ohne Tags -Schnelles Wortgefecht, Humor durch Charakter: +Wenn zwei klar unterscheidbare Stimmen alternieren, sind keine Tags nötig. Ein Schlagabtausch über fünf bis acht Repliken kommt komplett ohne »sagte« aus, sofern jede Stimme einen erkennbaren Idiolekt hat. Der Test: Tags abdecken — wenn der Leser nicht mehr unterscheiden kann, wer spricht, ist der Idiolekt zu schwach, nicht der Tag-Mangel das Problem. -> »Willst du meinen Hut als Geisel nehmen?«, fragte er nachdenklich. - -Absurde Frage mit ernstem Tonfall — der Kontrast IST der Witz. - -> »Tut mir leid wegen der Tür«, sagte er. ... »Die Tür selbst ist immer noch völlig in Ordnung. Sehr stabil.« - -Drei Versuche, über die Tür zu reden, während Stephanie auf ein redendes Skelett starrt. +Pingpong braucht ein Comedy-Timing-Gerüst: Setup, Erwartung, Subversion. Im Deutschen tragen Modalpartikeln den Rhythmus. Ohne sie wirken trockene Repliken steif statt trocken. --- @@ -103,12 +94,12 @@ KI produziert flache Nebensätze mit immer denselben Konjunktionen (dass, weil, ## Komposita für Weltenbau -Deutsches Kompositum-System als Weltenbau-Werkzeug: - -Poznanski erschafft: „Hermetoplastkuppel", „Sphärenbund", „Zuchtgewölbe", „Quartierwache", „Notfallset" — das klingt nativ deutsch, nicht übersetzt. +Das deutsche Kompositum-System ist ein eigenständiges Weltenbau-Werkzeug. Mehrwortige Eigennamen aus dem Englischen wirken im Deutschen sofort übersetzt; ein einziges zusammengesetztes Substantiv wirkt nativ. **Regel:** Beim Weltenbau in deutscher Sprache Komposita bilden, keine englischen Mehrwort-Namen. „Schattenkrieger" nicht „Schatten-Krieger" oder „Shadow Warriors". „Blutpakt" nicht „Blut-Pakt". +Funktionierende Komposita haben drei Eigenschaften: phonetisch tragfähig (sprich es laut), semantisch nicht doppelt (nicht „Magiezauber"), und im Plural- und Genitiv-Gebrauch noch lesbar (»der Blutpakt« → »des Blutpakts« → »die Blutpakte«). Wenn ein Kompositum diese Tests nicht besteht, ist es zu lang oder zu konstruiert. + --- ## Konjunktiv für innere Gedanken @@ -125,112 +116,257 @@ Konjunktiv I für neutrale Wiedergabe. „Er sagte, er ist müde" (Indikativ) kl --- -## Emotion durch Körperlichkeit (Poznanski) +## Emotion durch Körperlichkeit -Poznanski benennt NIE eine Emotion direkt. Stattdessen physische Manifestation: +Emotionen werden NIE benannt. Stattdessen physische Manifestation. Das gilt sprachübergreifend (siehe `creative.md`), trägt im Deutschen aber besonders, weil die Sprache präzise Körperverben und konkrete Komposita für Körperteile, Empfindungen und Räume hat. -> In mir wird auf einen Schlag alles kalt. +**Mechaniken:** -Sechs Wörter. Totale innere Transformation als physischer Zustandswechsel. +- **Temperaturwechsel.** Wärme und Kälte als Zustandsumschlag — »in mir wird auf einen Schlag alles kalt« — funktioniert in fünf bis sechs Wörtern und reicht oft als ganze Reaktion. +- **Körperinneres als Architektur.** Trauer, Angst, Scham bekommen physische Räume: Höhlen im Magen, Druck hinter dem Brustbein, ein Gewicht zwischen den Schulterblättern. Das Verb »sich einnisten« macht die Emotion zum Bewohner; »graben« gibt ihr Werkzeug. +- **Synästhesie.** Herzschlag wird laut wie Worte, ein Geruch wird scharf wie ein Lichtstrahl. Im Deutschen tragen solche Querbezüge ohne Erklärung. +- **Erlaubnis als Tarnung.** »Sie ließ ein kaum merkbares Lächeln zu« — die Figur erlaubt einer Emotion, sichtbar zu werden, als bräuchte sie eine Freigabe. Verrät Selbstkontrolle als Lebenslage in einem einzigen Verb. +- **Sehen statt fühlen.** »Sie registrierte« / »sie nahm wahr« — das Wahrnehmungs-Verb statt des Gefühlsverbs ist im Deutschen das klare Trauma-Signal. Die Figur ist nicht abwesend, sondern dissoziiert. -> Die Trauer um Lu nistet sich in meinem Körper ein, sie gräbt Höhlen in meinen Magen und in meine Brust. +Pro emotional aufgeladener Szene mindestens drei körperliche Manifestationen, davon möglichst mit unterschiedlichen Mechaniken. Drei Mal Herzklopfen ist nicht drei Manifestationen, sondern eine. -„Nistet sich ein" macht Trauer zu einem lebenden Parasiten. „Gräbt Höhlen" gibt ihr physische Architektur. +--- + +## Metaphern — selten, aber präzise -> Ich erlaube einem kaum merkbaren Lächeln, sich auf meine Lippen zu stehlen. +Eine starke Metapher alle ein bis zwei Seiten reicht. Nie dekorativ, immer funktional. Bilder müssen aus der **Erfahrungswelt der POV-Figur** kommen — eine Studierende vergleicht anders als eine Pathologin als ein Kind als eine Bauernfrau. Generische Metaphernfamilien (Licht/Dunkelheit, Wasser/Ertrinken, Feuer/Verbrennen) als Leitmotiv-Tapete sind das klarste KI-Signal. -Das Lächeln ist ein Eindringling („stehlen"). Ria „erlaubt" es — als bräuchten Emotionen eine Freigabe. Ein einziger Satz fängt ihre gesamte Ausbildung ein. +**Kinetik vor Symbolik.** Ein Vergleich, der ein Verb mit physischer Kraft trägt (»wegschnellt«, »zerfetzt«, »kippt«), wirkt stärker als ein abstrakter Symbolvergleich. Das Verb trägt den Vergleich, nicht das Bild. -> Mein Herzschlag dröhnt in meinen Ohren ebenso laut wie Tommas Worte. +**Sanfte Personifizierung als Charakterhinweis.** Eine sonst klinisch denkende Figur, die einmal den Himmel »erröten« sieht, verrät damit ihre verborgene poetische Sensibilität. Solche Brüche sind Charakterarbeit, nicht Verzierung — sie müssen einer Figur etwas kosten oder etwas freilegen. -Synästhesie — der Körper wird zum Echoraum für schlechte Nachrichten. +**Eine Metapher kondensiert die Welt.** Die beste einzelne Metapher in einem Kapitel macht in einer Beobachtung sichtbar, was sonst zwei Seiten Welterklärung bräuchte. Wenn eine Metapher das nicht leistet, prüfen, ob sie nötig ist. --- -## Metaphern — selten, aber präzise +## Der Erzähler mit Haltung + +Im Deutschen trägt der kommentierende Erzähler besonders gut, weil die Sprache längere eingebettete Urteile und Gedankenstrich-Kommentare ohne Bruch verträgt. Der Erzähler ist nicht neutral und nicht unsichtbar — er ist eine Stimme mit Meinung, Witz und einem Verhältnis zum Leser, die leicht über der Figur steht und in engen Momenten an sie heranrückt. + +Was er darf: urteilen, kommentieren, Witze machen, die keine Figur machen könnte, sich auf Wort-Ebene selbst korrigieren, die Figurenstimme leihen. -Poznanski setzt durchschnittlich eine starke Metapher alle zwei Seiten. Nie dekorativ, immer funktional. Ihre Bilder kommen aus Rias begrenzter Erfahrungswelt: Licht, Schnee, Eis, Metall, Maschinen. +Was er nicht macht: Gefühle benennen, Exposition dumpen, die Figur bevormunden, moralisieren, Genre-Etiketten kleben (siehe Anti-Pattern weiter unten). -> Ihr Blick, der mich findet und sofort wieder von mir wegschnellt wie ein scharf geworfener Ball von einer Wand. +### Techniken des deutschen Erzähler-Auftritts -Kinetisch und spezifisch. „Wegschnellt" hat physische Kraft. Das Verb trägt den Vergleich. +- **Das Nebensatz-Urteil:** Hauptsatz trägt das Fakt, der Nebensatz fällt das Urteil. »Er lachte, was ihm nicht stand.« +- **Der Gedankenstrich-Kommentar:** Mitten im beschreibenden Satz ein Einschub mit Haltung. »Das Haus war groß — lächerlich groß, wenn man ehrlich war — und still.« +- **Die Selbstkorrektur:** Der Erzähler findet das erste Wort zu zahm und ersetzt es. »Es roch alt. Nicht modrig, eher ... erfahren.« Erlaubt nur als Wort-Korrektur, nicht als Bild-Anlauf über Negation (siehe Anti-Pattern). +- **Das »Selbstverständlich«-Augenzwinkern:** Direkte Ansprache durch ein adverbiales Signal. »Selbstverständlich traf sie ihr Ziel.« +- **Der Einwortsatz als Pointe:** Nach einem längeren Absatz ein einzelnes Wort, das das Vorherige zerlegt oder bestätigt. »Ordnungsgemäß.« / »Komisch.« / »Mist.« +- **Der komische Vergleich als Figureneinführung:** EIN Vergleich, der Aussehen, Habitus und Status der Nebenfigur in einem Satz erledigt — riskant, aber wirksam. -> Am rechten Zipfel des Horizonts errötet der Himmel, als wäre er verlegen. +### Erlebte Rede — Figurenstimme im Erzählten -Personifizierung des Himmels als verlegen/errötend. In einer Welt klinischer Analyse offenbart diese sanfte Metapher Rias verborgene poetische Sensibilität. +Auch ohne Perspektivwechsel kann die Stimme der Figur in den Erzählton sickern — das erzeugt Nähe ohne Ich-Erzählung. Wenn die Figur »ganz schön deprimierend« denken würde, sagt der Erzähler »ganz schön deprimierend« — ohne »dachte sie« dranzuhängen. Modalpartikeln und Umgangssprache im Erzähltext markieren den Übergang. -> Perfekte Schönheit, nicht von Menschenhand gemacht, anders als alles, was mich sonst umgibt. +Die Technik (freie indirekte Rede, erlebte Rede) ist im Deutschen sehr tragfähig. Der Erzähler darf je nach Absatz näher an die Figur rücken oder sich wieder mit Haltung zurückziehen. -Die gesamte Dystopie kondensiert in einer Beobachtung über den Mond. +### Wann der kommentierende Erzähler NICHT passt + +- Bei radikaler Innenperspektive. Dort stört der Erzähler. +- Bei Trauma, Verlust, Depression — wenn die Figur nicht lachen kann, darf der Erzähler es auch nicht. +- In Actionszenen. Da hält der Erzähler die Klappe und lässt die Handlung laufen. + +Der Moduswechsel zwischen Haltung und Stille ist selbst ein Werkzeug. Im Absatz davor darf der Erzähler witzeln; wenn es ernst wird, zieht er sich zurück. Der Witz-Entzug signalisiert: Jetzt ist etwas anders. Kein allmähliches Ausblenden — ein harter Schnitt. --- -## Humor im Deutschen (Landy) +## Humor im Deutschen — fünf Typen -### Timing und Aufbau +Eine produktive Typologie. Jede Figur sollte konsistent in einem Modus operieren; der Erzähler kann zwischen ihnen wechseln. -Dreierregel mit Eskalation: Aufbau → Erwartung → Subversion. +### Typ 1 — Sarkasmus und Understatement -> »Tut mir leid wegen der Tür.« (Aufbau — scheint sich zu entschuldigen) -> »Ich komme für den Schaden auf.« (Eskalation — versucht härter, normal zu sein) -> »Die Tür selbst ist immer noch völlig in Ordnung. Sehr stabil.« (Pointe — bewertet die Qualität der Tür, während Stephanie auf ein Skelett starrt) +Comedy durch Timing, nicht durch Wortwitz. Ein Zögern vor einer einsilbigen Antwort. Ein nüchternes »Nein«, gefolgt von einer banalen Nachfolgehandlung, die die Bedeutung des »Nein« trägt. Funktioniert im Deutschen besonders, wenn der Sarkasmus durch Modalpartikel weich gehalten wird — »na ja«, »eben«, »halt« — sonst klingt er bitter statt trocken. -Verzögerte Pointe — die echte Pointe kommt NACH der scheinbaren Auflösung: +### Typ 2 — Absurde Parallelisierung -> »Mein Schnürsenkel war offen.« / »Ich hätte sterben können, weil du dir den Schuh gebunden hast?« / »War nur ein Witz.« / [Pause] / »Ganz ehrlich. Ich wäre nie gestolpert. Dazu bewege ich mich viel zu graziös.« +Zwei Dinge gleichrangig nennen, die nicht gleichrangig sind: »Morde und lange Spaziergänge«, »Ex-Freundinnen und alternative Dimensionen«. Die Reihe eskaliert von trivial zu kosmisch oder kippt vom Kosmischen ins Triviale. Der Humor liegt in der unerschütterlichen Gleichbehandlung. -### Tonale Kontrakte +Im Deutschen lebt der Witz von der Reihenform — Komma, Komma, Komma, Pointe — und davon, dass die Figur die Aufzählung wie eine Einkaufsliste vorträgt. Ein Tag wie »ungerührt« oder »beiläufig« würde alles ruinieren; der Effekt entsteht durch das Fehlen jedes Markers. -Humor signalisiert Sicherheit. Sein Fehlen signalisiert Gefahr: +### Typ 3 — Deadpan-Verweigerung -> »Das Erste, was Baron Vengeous tat, als er den Fuß auf irischen Boden setzte, war, jemanden umzubringen.« +Die Figur weigert sich, auf die Prämisse einzugehen. Auf »Hab gedacht, du seist größer« kommt ein knappes »Nein, hast du nicht« — kein Nachfragen, kein Höflichkeitsspiel. Die Verweigerung IST der Witz. Im Deutschen braucht es knappe Antworten ohne Rechtfertigung danach. Einen Satz, einen Punkt, kein Tag. -Kein Wortspiel. Kein Understatement. Die Satzstruktur allein signalisiert: dieser Charakter ist anders. Wenn Landy aufhört, witzig zu sein, weiß der Leser, dass sich etwas unwiderruflich geändert hat. +### Typ 4 — Humor als Schutzschild -### Charakterdifferenzierung durch Humor +Mitten im Schmerz ein Witz, der den Schmerz nicht lindert, sondern zeigt. Der Witz ist die Wunde — der Leser versteht, dass die Figur nicht direkt über das reden kann, was wirklich los ist. Funktioniert nur, wenn der Witz inhaltlich daneben greift: Die Figur soll über das Trauma reden und macht stattdessen einen Witz über etwas Nebensächliches. Das Daneben ist die Information. -- **Skulduggery:** Trocken, intellektuell, selbstbewusst. Ironie durch Syntax: „Ich hege gewisse Zweifel, dass du meine Autorität anerkennst." -- **Walkure:** Reaktiv, sarkastisch. Kurze Sätze. Benennt das Absurde direkt: „Und übrigens: Ihr Bart ist lächerlich." -- **Scapegrace:** NIE absichtlich witzig. Sein Humor geht auf seine Kosten: „Ich bin eine Killermaschine!" — unmittelbar gefolgt von einer Niederlage. -- **Der Erzähler:** Macht Witze, die kein Charakter machen könnte: „Gordon Edgleys plötzlicher Tod war ein Schock für alle — nicht zuletzt für ihn selbst." +### Typ 5 — Bedrohung durch Höflichkeit + +Grausamkeit im Tonfall eines Kaffeegesprächs. Eine Frage über Mord, gestellt im selben Register wie eine Frage über Milch im Kaffee — »hoffnungsvoll« als Adverb macht den Horror sichtbar. Im Deutschen sind solche höflichen Monster besonders wirksam, weil die Sprache die höfliche Distanz grammatikalisch verfügbar hat: Sie-Form, Konjunktiv I, formelhafte Wendungen. + +### Timing-Regeln + +- Der Witz steht fast nie im selben Absatz wie sein Setup. +- Zwischen Setup und Pointe: ein Absatz Beschreibung — die Pause des Stand-up-Comedians. +- Jede Figur hat einen eigenen Humor-Typ und bleibt dabei. Wer Deadpan ist, bleibt Deadpan. Wer höflich bedroht, bleibt höflich. +- Modalpartikeln sind das Schmiermittel. »Na ja«, »halt«, »eben«, »doch« machen trockene Repliken erst trocken. Ohne sie wirkt Sarkasmus steif. + +### Charakterdifferenzierung durch Humor-Modi + +Nicht jede Figur trägt jeden Modus gleich gut. Eine produktive Heuristik: + +- **Trocken-intellektuell, selbstbewusst:** Ironie durch Syntax — komplexe Konstruktionen, die das Offensichtliche umständlich umkleiden. Der Witz liegt im Aufwand. +- **Reaktiv, sarkastisch:** Kurze Sätze. Benennt das Absurde direkt, ohne Umweg. +- **Unfreiwillig komisch:** Der Humor geht auf Kosten der Figur — eine große Behauptung, unmittelbar gefolgt von einer Niederlage. Die Figur weiß nichts vom Witz; der Leser weiß alles. +- **Der Erzähler:** Macht Witze, die keine Figur machen könnte — die Meta-Stimme, die mit Adverbien (»selbstverständlich«, »unweigerlich«, »ordnungsgemäß«) den Leser zwinkert. + +--- + +## Hammerschlag im Deutschen + +Die allgemeine Hammerschlag-Regel (lang aufbauen, kurz zuschlagen — siehe `creative.md`) funktioniert im Deutschen exzellent, weil die Sprache lange Sätze nativ trägt. Die Satzklammer zwingt den Leser, im langen Satz bis zum Verbgerüst durchzuhalten. Die Hammer-Entladung kommt als plötzliche Syntaxöffnung. + +**Aufbau (40+ Wörter):** rollend, mit Komma-Einschüben und Gedankenstrich-Pausen, semantisch akkumulierend, der Hauptsatz so lange aufgeschoben, wie es die Geduld des Lesers erlaubt. + +**Hammer (3-7 Wörter):** ein Subjekt-Verb-Objekt-Satz, kein Adjektiv, kein Adverb, eigener Absatz. Der Hammer benennt die Konsequenz, das Schicksal oder die nackte Tatsache, auf die der lange Satz zugelaufen ist. + +Zwei, maximal drei Hammer pro Kapitel. Alles darüber stumpft ab. + +--- + +## Weltenbau durch Leben + +Die magische, alternative oder fiktional erweiterte Welt wird nie erklärt — sie wird benutzt. Die Neulingsfigur lernt die Regeln, indem Figuren sie anwenden, brechen oder sich über sie lustig machen. + +### Kernprinzipien + +- **Magie als Alltag behandeln.** Wenn eine Figur zaubert, wird nicht beschrieben, wie magisch das ist. Es wird beschrieben, was passiert, und dann geht die Szene weiter. Die Figur, die zaubert, findet es selbstverständlich; nur die Neulingsfigur staunt. +- **Der Neuling als Leser-Anker.** Eine Figur, die die Welt gerade erst entdeckt, trägt die Fragen des Lesers, ohne dass Exposition nötig wird. Ihre Fragen sind die des Lesers, die Antworten sind die Welt. +- **Witze bauen die Welt.** Wenn eine Figur über die eigene fantastische Eigenschaft Witze macht, lernt der Leser mehr über die Regeln der Welt als in jedem Info-Dump. +- **Absurde Details ernst nehmen.** Trolle unter Brücken, Vampire mit Tagesjobs, ein Schneider, der kugelsichere Anzüge näht — je skurriler das Detail, desto ernster der Tonfall seiner Einführung. Der Witz liegt in der Unaufgeregtheit. +- **Institutionen mit Bürokratie.** Magische Welten haben Ältestenräte, Anwälte, Verwalter, Behörden mit Aktenzeichen. Magie ohne Verwaltungsapparat klingt kindisch. Mit Verwaltungsapparat klingt sie real. +- **Magie skurril, nicht funktional.** Glatte, problemlos arbeitende Magie wirkt nach KI-Ökonomie. Macken machen die Welt: ein Geist mit physischen Tics, ein Artefakt, das mit seiner Umgebung in unerwarteter Weise reagiert, ein Effekt, der ein Geräusch macht, das er nicht machen sollte. + +### Exposition nur durch Szenen mit Reibung + +Jede Information über die Welt kommt in einer Szene, in der sie **gerade gebraucht** oder **gerade gebrochen** wird. Regeln werden nicht erklärt, sie werden erst sichtbar, wenn jemand sie übertritt. Die Magie-Unterrichtsstunde gibt es nicht — es gibt nur die Szene, in der eine Figur etwas falsch macht und von der Konsequenz überrascht wird. + +--- + +## Humor-Aufbau + +### Timing und Aufbau + +Dreierregel mit Eskalation: Aufbau → Erwartung → Subversion. + +Im Aufbau scheint sich die Figur zu entschuldigen oder eine ganz normale Erklärung zu liefern. Die Eskalation versucht härter, normal zu sein. Die Pointe bewertet ein Detail, das angesichts der Gesamtsituation absurd nebensächlich ist — der Leser sieht beides gleichzeitig (die normale Bewertung und die unmögliche Lage), und der Witz entsteht im Auseinanderklaffen. + +**Verzögerte Pointe.** Die echte Pointe kommt NACH der scheinbaren Auflösung. Eine Figur scheint einen Schluss-Satz gesagt zu haben, der Absatz endet, ein Beat Pause, dann ein zusätzlicher Satz, der das Gesagte unterläuft oder ins Lächerliche zieht. Die Pause ist im Deutschen ein eigener Absatz oder ein Geste-Beat zwischen den beiden Sätzen. + +### Tonale Kontrakte + +Humor signalisiert Sicherheit. Sein Fehlen signalisiert Gefahr. Wenn eine Szene plötzlich ohne Witz auskommt, registriert der Leser den Wechsel sofort, oft ohne ihn benennen zu können. Das Werkzeug ist mächtig — also sparsam einsetzen. Wer in jedem zweiten Kapitel den Modus wechselt, stumpft ihn ab. + +**Diagnostik:** Eine Eröffnung, die kein Wortspiel und kein Understatement enthält, sondern einen nüchternen Tatsachensatz, signalisiert: dieser Charakter, dieses Ereignis, dieses Kapitel ist anders. Wenn der Erzähler aufhört, witzig zu sein, weiß der Leser, dass sich etwas unwiderruflich geändert hat. --- ## Beschreibung — zwei Ansätze -### Poznanski: Sparsam und funktional +Die zwei deutschen Erzählmodi (stille Innenperspektive, Erzähler mit Haltung) erzeugen zwei verschiedene Beschreibungs-Ökonomien. + +### Sparsam und funktional (Innenperspektive) -> Auf dem Nachttisch liegt mein Datenterminal. +Technologie, Räume, Welt-Details werden durch Benutzung eingeführt, nie erklärt. Jedes Detail baut die Welt organisch auf, ohne dass die Figur sich darüber wundert. Die ruhige, kontrollierte Beobachtung selbst IST der Charakter — eine Figur, die unter Kontrolle steht oder Trauma verarbeitet, registriert die Welt in nüchternen Hauptsätzen, ohne Adjektive, ohne Vergleich. Drei kurze Sätze sind oft mehr als ein langer. -Technologie wird durch Benutzung eingeführt, nie erklärt. Jedes Detail baut die Welt organisch auf. +### Großzügiger, aber zweckdienlich (Erzähler mit Haltung) -> Ich drehe das Licht auf die unterste Stufe, stelle mich ans Fenster und sehe den Sentineln bei ihren Rundgängen zu. +Der kommentierende Erzähler darf sich Beschreibung leisten, aber jede einzelne trägt eine Meinung. Eine Selbstkorrektur, ein Komma-Urteil, ein komischer Vergleich. EIN präziser Vergleich pro Nebenfigur, nicht ein physisches Inventar. EIN sensorisches Detail pro Ort, das Stimmung und Geschichte trägt. Der Rest entsteht im Leser. -Die ruhige, kontrollierte Beobachtung IST der Charakter, der Trauma verarbeitet. +In beiden Modi gilt: Hauptfiguren werden nie als Paket beschrieben. Verhalten zuerst, Aussehen verteilt über mehrere Kapitel. -### Landy: Großzügiger, aber zweckdienlich +--- -> Die Flure im Haus ihres Onkels waren lang und mit Bildern geschmückt, die Parkettböden auf Hochglanz gebohnert, und das ganze Haus roch irgendwie alt. Nicht unbedingt modrig, eher ... erfahren. +## Innerer Monolog und die Kluft -Die Selbstkorrektur „nicht modrig, eher erfahren" IST die Erzählstimme. Ein Wort trägt die gesamte Atmosphäre. +In der stillen Innenperspektive denken Figuren in Bewertungen: Beobachtung → Analyse → emotionale Reaktion (unterdrückt) → strategische Kalkulation. Die Figur baut ihre Rhetorik in Echtzeit, bewertet die eigene Leistung sogar mitten im Satz und korrigiert die eigene Mimik wie ein Werkzeug. -> Mr Fedgewick, ein kleiner untersetzter Mann, der aussah wie eine schwitzende Bowlingkugel. +**Die Kluft zwischen Innen und Außen IST der Charakter.** Wenn die Figur nach außen ruhig und strategisch spricht, innerlich aber bebt, ist diese Kluft die Prosa. Sie wird nicht benannt — der Leser sieht beide Schichten gleichzeitig durch: +- die nüchterne Außenrede (oft kurz, formelhaft, kontrolliert), +- die innere Notiz dazwischen (Körperreaktion, Selbstinstruktion, Korrektur der eigenen Geste). -Komischer Vergleich statt physischem Inventar. 2-3 präzise Details, nie ein vollständiges Portrait. +Das Werkzeug verlangt eine Figur, die ihre Selbstkontrolle selbst spürt. Bei Figuren, die unkontrolliert handeln, funktioniert es nicht — dort ist der Innenraum identisch mit dem Außenraum, und die Prosa verliert ihren zweiten Boden. --- -## Innerer Monolog und die Kluft (Poznanski) +## Spezifische deutsche KI-Marker — Pflicht-Grep nach jedem Entwurf + +Über die allgemeinen Anti-Patterns aus `creative.md` hinaus produziert KI im Deutschen typische Wendungen, die sich gut greppen und entschärfen lassen. Jede Kategorie hat klare Trigger-Worte. Pflicht: Nach jedem Kapitel-Entwurf einmal alle durchgehen. + +### Vage-retrospektive Wendungen + +»an einer Stelle, die später niemand mehr exakt benennen konnte«, »etwas, das sie damals noch nicht wusste«, »auf eine Weise, die sich erst später zeigen würde«, »ein Detail, das im Nachhinein alles erklärte«, »einer jener Momente, die man nur rückblickend erkennt«. Aufgesetzte Bedeutsamkeit ohne Substanz. Echtes Foreshadowing ist konkret — ein Detail jetzt, eingelöst später; der Leser entdeckt die Bedeutung beim Re-Read. + +Trigger-Grep: »später«, »irgendeine Stelle«, »irgendeiner Stelle«, »im Nachhinein«, »damals noch nicht«, »auf eine Weise«. + +Zulässig: Eine Figur, deren eigene Erinnerung wirklich verschwommen ist (»Sie wusste nicht mehr, wann sie eingeschlafen war«). Verboten: Erzähler-Mystifizierung über die Figur hinweg. + +### »ohne zu wissen«-Konstruktionen + +»ohne zu wissen, dass«, »ohne zu ahnen, dass«, »ohne dass es ihr bewusst war«, »ohne zu bemerken, dass«, »er sollte später feststellen, dass«, »was sie nicht wusste, war«. Klassischer Narrator-Intrusion-Trick für dramatische Ironie. KI produziert das reflexhaft, weil es nach Bedeutsamkeit klingt. + +Toleranz: Maximal eine Fundstelle pro Kapitel und nur, wenn sich nicht umformulieren lässt, ohne die Szene zu verschlechtern. -Rias innere Stimme denkt in Bewertungen: Beobachtung → Analyse → emotionale Reaktion (unterdrückt) → strategische Kalkulation. +Trigger-Grep: »ohne zu«, »ohne dass«, »was sie nicht wusste«, »was er nicht wusste«, »sollte später«. + +Ersatz: Information direkt erzählen und die Szene normal weiterlaufen lassen, oder die Figur eine Fehleinschätzung aussprechen lassen — der Leser sieht die Ironie selbst. + +### Gerankte Erzähler-Beobachtungen + +»Das Erste, was auffiel, war X«, »als Erstes hörte sie«, »zuerst hörte sie X, dann sah sie Y«, »ihre erste Beobachtung war«, »zunächst«. Versucht, durch formale Rang-Ordnung einen Witz aus der Absurdität der Priorisierung zu ziehen — fühlt sich nach ausgedachter Autoren-Pointe an statt nach Figurenwahrnehmung. + +Toleranz: Null als Erzähler-Stilmittel. Erlaubt nur, wenn die Figur selbst aktiv im Dialog oder inneren Monolog priorisiert (»Okay, zuerst die Tür abschließen, dann ...«). + +Ersatz: Detail direkt beschreiben. Die Bedeutsamkeit eines Details entsteht dadurch, dass ES das einzige genannte ist — nicht durch ein Meta-Etikett. + +### Zirkulär-selbstbezügliche Manierismen + +»X war so X, wie X X sein muss, wenn ...«, »in der Weise, in der Y Z-en«, »es war die Art von X, die X sind, wenn ...«, »vorsichtig, wie man X tun würde, wenn man zufällig Y wäre«, »mit der Qualität eines Y, das ...«. Klingt nach literarischer Tiefe, ist tautologisch und leer. KI-Imitation einer kommentierenden Erzählerstimme: in echten Erzählerstimmen tragen die Vergleiche, weil sie konkret sind; in der Imitation wird der Selbstbezug zum Füllstoff. + +Toleranz: Null. Self-Audit nach jedem Entwurf — jeden Satz prüfen, der mit »wie«, »als«, »in der Weise«, »mit der Qualität« einen Vergleich einleitet. Wenn der Vergleich auf sich selbst zurückverweist: streichen oder konkret umschreiben. + +### »Nicht X. Eher Y.«-Bildeinführung + +Verb-Satz, dann kurzes »Nicht eilig / nicht hastig / nicht ungeduldig«, dann Analogie über »Eher so, wie ...«. Tarnt sich als nachdenkliche Selbstkorrektur, ist aber Füllmaterial: das »Nicht X« trägt keine Information, das »Eher so, wie« weicht der direkten Beschreibung aus. + +Erlaubt: Erzähler-Selbstkorrektur auf Wort-Ebene (»Es roch alt. Nicht modrig, eher ... erfahren.«). Verboten: Bild-Anlauf über die Negation. + +Ersatz: Direkt ins Bild gehen, nötigenfalls mit Adverb-Stapel (»langsam, leicht missmutig, prüfend«), aber ohne Negation als Sprungbrett. + +### Drei-oder-mehr-Sätze-Anaphora + +Drei oder mehr aufeinanderfolgende Sätze mit derselben Subjekt-Verb-Eröffnung: »Sie ging X. Sie ging Y. Sie ging Z.« Eine bewusste Doppelung als Pointe (»Sie dachte. Sie dachte lange.«) ist erlaubt und schön; mechanische Triplung nicht. Im Deutschen besonders gefährlich, weil die feste Verbzweitstellung den Reflex begünstigt. + +Ersatz-Werkzeuge: Komma-Verknüpfung (»Sie stand auf, duschte, zog sich an«), Fragment (»Dusche. Jeans. Block unter den Arm«), andere Subjekte (Körperteile, Objekte, Handlungen statt Personalpronomen), Präpositionalphrase voran (»Um zehn nach acht: ...«), Inversion. Gilt auch auf Absatz-Ebene. + +Erlaubt: Dialog-Anaphern, wenn rhetorisch motiviert (Figur spricht emphatisch, panisch oder beschwörend). + +### Meta-Genre-Witze + +»Klingt wie ein billiger Fantasyroman«, »wie im Krimi«, »wie in einem schlechten Film«, »hätte aus einem Roman stammen können«. Erzähler oder Figur kommentiert die Welt durch Genre-Etikett und bricht dabei die vierte Wand für eine billige Pointe. + +Toleranz: Null. Vergleiche kommen aus der Lebenswelt der jeweiligen Figur — Beruf, Studium, Familie, Ausbildung, Wohnort — nie aus einer Leser-Autoren-Perspektive über das Buch selbst. + +--- -> Keine Selbstgerechtigkeit, sonst verliert man die Zustimmung. +## Konkret-plus-Institutionen-Filter — eine deutsche Komik-Maschine -Ria baut ihre Rhetorik in Echtzeit, bewertet ihre eigene Leistung sogar mitten im Satz. +Eine besonders tragfähige Humor-Mechanik im Deutschen, weil Bürokratie- und Fachsprache eine native Witzquelle sind. Drei Schritte: -> Blitzschnell kontrolliere ich meine Gesichtszüge und korrigiere sie. +1. **Reale Gefahr konkret benennen.** Tretmine, Hochspannungsleitung, Schlagader, Sicherungskasten. Keine abstrakten Umschreibungen, keine Personifizierung des Objekts (»die Mine, die geduldig auf ihr Versprechen wartete«). Die Mine ist eine Mine. +2. **Bewertung durch Institutionen-Filter.** »was ihre Ärzte als medizinisch äußerst unvorteilhafte Entscheidung bezeichnen würden«, »was jeder Anwalt als grobe Fahrlässigkeit einstufen würde«, »was in keinem Lehrbuch steht«, »was die Versicherung sicher nicht bezahlen würde«. Ärzte, Anwälte, Versicherer, Ethikkommissionen, Verkehrsregeln, Schulbücher, TÜV — die fachlich-trockene Außensicht erzeugt den Witz, weil sie real klingt. +3. **Konkrete Körper-Action als Landung.** Nach der Hypothese muss die Figur etwas Physisches tun, sonst zerfließt der Absatz lyrisch und die Pointe verpufft. -Die Kluft zwischen Innen und Außen IST der Charakter. Wenn sie zum Sentinel sagt: „Eine Begnadigung. Nicht meine. Eure." — ist ihre Stimme ruhig und strategisch. Innerlich bebt sie. Diese Kluft zwischen der Person, die das System geformt hat, und der Person, die sie tatsächlich ist — das IST die Prosa. +Funktioniert, weil der Kontrast zwischen Lebensgefahr und Aktenzeichen-Tonfall sich ohne Pointe-Markierung trägt. Figuren-Gedanken dürfen dabei ins generische »du« rutschen, wenn es eine ironische Allgemein-Wahrheit ist (»wenn dein Fuß auf dem Totmannschalter steht, ist Rückwärtsstolpern keine gute Idee«). --- diff --git a/skills/writing/references/creative.md b/skills/writing/references/creative.md index 7e9f7ab..d8b4f69 100644 --- a/skills/writing/references/creative.md +++ b/skills/writing/references/creative.md @@ -76,6 +76,15 @@ Sentence length IS pacing. This is the most important tool in creative writing: - **Fragments for emotional peaks.** Use sparingly — overuse kills the effect. - **Variation is everything.** Map your sentence lengths. If they cluster, rewrite. +**The hammer blow — build long, strike short.** The single most effective rhythmic move: a long, rolling, comma-laden sentence that sets up context, mood, expectation — followed by a blunt 3-to-7-word sentence that lands the consequence. The reader is lulled by the long sentence, and the short one hits because it breaks the cadence. Use this at reveals, at shocks, at moments where you want the reader to physically pause. + +- Setup sentence: 30-50+ words, possibly with digressions, embedded clauses, accumulating detail. +- Hammer: "Then the truck hit him." / "Everyone was dead." / "Nothing happened." / "His head was a skull." + +Misuse: doing this every paragraph. The effect depends on scarcity. Two or three hammers per chapter, max. + +**Fragment bursts for action.** In physical danger, drop articles and subjects. "Had to reach the street. Reach the street, get in a car, drive. Escape." Syntax collapses as the character's thinking collapses. Never use fragment bursts in contemplative scenes — they mark survival mode. + ### Dialogue carries character Every character must sound different. If you cover the dialogue tags and can't tell who's speaking, rewrite. @@ -109,6 +118,14 @@ Pick a POV and commit: - More flexible for action sequences. - Works best for action, adventure, ensemble casts. +**Third person with narrator voice (commenting narrator):** +- The narrator is a presence with opinions, wit, and a relationship to the reader. Not omniscient-neutral — omniscient-with-attitude. +- The narrator judges characters openly, makes asides, uses comic timing the characters themselves couldn't access. +- Character voice still sinks into the narration (free indirect style), but the narrator stays visible — interrupting, commenting, winking at the reader. +- Best for: comic adventure, fairy-tale reinvention, satire, any book where the voice of the telling matters as much as what is told. +- Danger: the narrator can crowd out the characters. Keep the narrator's voice earned through wit, not just intrusive. +- Example move: close third around the character, then a sentence only the narrator could say ("She hadn't yet learned that this was a mistake. She would."), then back to close. + **Never switch POV within a scene.** Chapter or section breaks for POV switches. ### Tension and pacing @@ -149,6 +166,109 @@ Pick a POV and commit: --- +## Narrator discipline — let the reader arrive + +The single clearest difference between AI creative writing and human creative writing: in human writing, the reader performs cognitive work alongside the character. In AI writing, the narrator has already done the work and delivers conclusions. Fix narrator discipline and most other AI tells resolve themselves. + +### Perception → deduction → explanation → verdict, in that order + +Present observations the way a character processes them. Sensory input, then the anomaly, then the deduction, then the explanation, and only then an optional contextualizing verdict. + +Bad: "Something was off. A stranger stood at the door, confused by the child's drawing by the doorbell." +The narrator has synthesized everything. The reader has nothing to do. + +Good: "She heard heavy footsteps. The bell took its time. Stranger. Familiar visitors rang immediately; strangers needed a moment to get past the crayon unicorn eating two stick figures next to the doorbell. A monument to the principle that you should never leave a bored six-year-old alone for too long." + +Footsteps (sensory) → delayed bell (anomaly) → stranger (deduction) → unicorn (explanation) → monument (verdict). The reader deduces alongside the character and reaches each conclusion a heartbeat before the narrator confirms it. That is identification, not consumption. + +Corollary: a detective character shows her method through the order of her observations. No narrator needs to add "she was observant." If the narrator has to tell, the method isn't on the page. + +### Verdicts must be earned by prior imagery + +Closing verdicts ("A monument to...", "The kind of man who...", "Three things X always meant...") only work when they seal an image the reader has just absorbed. They summarize, they do not introduce. + +Bad: "He was the kind of man who apologized to doors." No door-apology on the page. Free-floating assertion. +Good: [Scene where he apologizes to a door he has just knocked down.] "He was the kind of man who apologized to doors." Compression of what was shown. + +Diagnostic: if you can move the verdict before the evidence without anything breaking, the verdict isn't earned. Cut or reframe. + +### No narrator pre-ranking + +"The first thing she noticed was X." / "What caught her attention, above all, was Y." / "Not the bell — what she heard first was the voice." + +All variants of the same move: the narrator ranks observations for the reader before the character has processed them. Pure AI tell in any language. Fix: report what the character perceives in temporal or cognitive order, without ranking. + +### No advertised withholdings + +"What she didn't know was Y." / "Little did she know Z." / "Without realizing A." / "She would later reflect that B." / German: "Ohne zu wissen, dass C." + +These announce dramatic irony instead of constructing it. If the reader needs to know Y, construct the scene so Y is inferable. If Y is a plot withhold, hold it. Do not advertise the withholding. + +Hard rule: maximum one per chapter, and only when dramatic irony genuinely cannot land otherwise. + +### No vague-retrospective hedging + +"At a spot no one would later be able to identify." "Something she didn't yet know." "On a day that would prove, in hindsight, decisive." "One of those moments you only recognize looking back." Manufactured significance without content. The narrator implies a future weight the prose hasn't earned. Real foreshadowing is concrete — an actual detail planted now, paid off later, and the reader discovers its weight on a re-read rather than getting tipped to it now. If the only payload of a phrase is "this matters somehow," cut it. + +A character whose own memory is genuinely unclear is fine — that is the character's experience and lives in close perspective. Narrator-side mystification of an event the narrator is also describing is not. The diagnostic: who is doing the not-knowing? If it is the figure, keep. If it is the narrator gesturing at the reader, cut. + +### No circular self-reference + +"The moment lasted exactly as long as such a moment must last." "Polite the way polite people are when they don't mean it." "The kind of silence that is, at its heart, only silence." These imitate the cadence of literary observation but tautologize — the comparison loops back at the term it was meant to illuminate. + +The reflex usually emerges when a sentence "wants weight" and the writer reaches for a meta-cadence instead of an image. It hides easily inside long, well-formed sentences and feels like depth on a first read. Self-audit any comparison opened with "as", "like", "the kind of", "in the way that": if the right side of the comparison restates the left, replace with a concrete observation or cut. No hammer-blow rhythm and no almost-pointe earns this construction. + +### No negation-pivot image introductions + +"Not in a hurry. More like the way someone enters a room they already half-own." Distinct from negative parallelism ("not X, but Y") because the negation is followed by an analogy rather than a stated alternative. Reads as thoughtful self-correction; functions as filler. The "not X" carries no information, the "more like" ducks direct description. + +Word-level self-correction by the narrator ("It smelled old. Not musty, more... lived-in.") is fine — that is a single-word swap inside a noun phrase. Image-level negation-then-analogy as a way to introduce a comparison is not. Go straight into the image, even if it requires stacking adverbs. + +### No three-or-more sentence-opening anaphora + +Three or more consecutive sentences sharing the same subject-and-verb opening flatten rhythm and read as machine-generated. A deliberate doubling can land as a beat ("She thought. She thought a long time."). Triplication does not. + +Vary openings: shift the subject (a body part, an object, an abstract subject), lead with a prepositional phrase, fragment, invert, or comma-fuse the actions into one sentence. Dialogue anaphora when rhetorically motivated by an emphatic or panicked speaker is exempt — that is character speech, not narrator rhythm. The same caution applies at paragraph scale: three paragraphs in a row opening with the same subject is the same mistake at a larger grain. + +### No meta-genre commentary + +"It was like a scene from a bad thriller." "Right out of a fantasy novel." "If this were a movie..." Either character or narrator labels the world by genre or medium. The comparison comes from a reader-author meta-frame the character does not occupy, breaks the fictional contract for a cheap laugh, and reads as a writer's joke pasted onto a figure who would never reach for it. + +Comparisons must come from the character's lived world — their job, training, family, schooling, neighbourhood. A police officer compares to other crime scenes, not to crime fiction. A doctor compares to other patients, not to medical drama. The genre frame is the one frame the character cannot have. + +### Idiomatic understatement beats analytical description + +For mild anomalies, idiomatic phrases carry more tension than constructions that name the anomaly. + +Bad (analytical value-judgment): "There was a pause that was too long." +Good (idiomatic): "The bell took its time." / German: "Die Klingel ließ auf sich warten." + +AI reflexively produces "X, which was Y" / "X, die zu Y war" because they are grammatically safe. Native writing reaches for verbs that verb the anomaly itself. Replace "a pause that was too long" with a verb that carries affect: "took its time", "dragged", "sat there", "kept them waiting". Each verb is a tonal choice; the analytical construction is a toneless reflex. + +### Sentences that carry multiple loads + +Every sentence in creative prose should do more than one thing at once: character, world, plot, tone. A sentence that only describes, or only tags dialogue, or only reports action, is wasting space. + +Test: ask of each sentence "what does this do?" and count. If the answer is one, cut or merge. If the answer is four or five, you are writing. + +Example — one sentence, five loads: "She glanced at the crayon unicorn eating two stick figures directly above the doorbell, a monument to the principle that you should never leave a bored six-year-old alone for too long." That delivers world detail (wall art by the door), character introduction (the six-year-old, before she appears), household lore (the implied rule), tonal collision (cartoon violence plus domestic routine), and texture for what kind of family lives here. + +### Invisible humor structure + +The moment the reader can see the joke coming, the joke dies. "Not X, but Y." "Bei A / bei B." "Two things she hated equally." Rule of three with a twist ending. Negative parallelism. All audible scaffolding. + +If a joke depends on a visible rhetorical structure, hide the structure. The joke should emerge from imagery and causality, so that the reader arrives at the comedy rather than being handed it. + +### Stylistic collisions + +A formal word applied to a trivial object produces more comedy than a cleverly constructed pun. "A monument to..." for a child's finger-paint. "An elegy for..." for a soggy pancake. "The principle that..." for leaving a kid alone. + +The collision is the joke. Do not explain it. Do not apologize for it. Let the register mismatch do its own work. + +AI reaches for stylistically neutral, therefore forgettable, words ("indicator", "reliable", "notable"). Native comic writing reaches for words whose register is mildly wrong and therefore memorable. + +--- + ## Advanced craft ### Worldbuilding through living, not explaining @@ -159,6 +279,24 @@ Never info-dump. Never stop the story to explain how the world works. Instead: - **Society learned through habits.** A character's automatic glance at a ranking display tells the reader the ranking is public, permanent, competitive, and central to identity — without a single sentence of exposition. - **The iceberg principle.** Explain ~30%, imply ~70%. The reader assembles the world like an archaeologist, from shards. What you leave unexplained creates mystery and depth. What you over-explain kills it. - **Normalcy IS worldbuilding.** When a character evaluates their cosmetic surgery results aesthetically and strategically — with no horror — the normalcy of their reaction tells the reader more about the society than any exposition could. +- **Texture through quirks, not function.** A magic system that just works, a creature that fulfills its role, an artifact that does its job, an institution that runs smoothly — all read as default-shape, which reads as machine-generated. Reach for idiosyncrasies: an effect with a sound it shouldn't make, a creature with a physical tic, an artifact that misbehaves with its environment, a body of magic-users that fails its own rules in mundane ways. Glossy is the tell. The frictions are where the world becomes real, and they double as character-revealing moments because someone has to react to them. +- **Inspiration, not direct port.** Most fiction draws on existing fiction for tone or systems. The principles transfer; the labels do not. Characteristic names, institutions, and signature objects from a reference work belong in design notes, not in the manuscript. Eigennames should feel native to the world being built. A reader who recognizes a direct lift stops reading the world and starts reading the comparison, and the project pays the cost forever. + +### Naming — avoid the AI name pool + +AI draws every name from the same small pool, and readers who have seen other AI fiction recognize it on sight. This is one of the strongest fiction tells. The families to avoid (the principle holds across languages, even when the specific names differ): + +- **Stock fantasy first names** — Elara (the worst offender), Lyra, Aria, Kael, Cassian, Lucian, Seraphina, Isolde, Elowen, Thorne, Nyx. Soft, vowel-heavy, two or three syllables, vaguely Latinate. +- **Evocative compound places** — the Whispering Woods, Shadowfell, Silvermoon, Ashfall, Everwood, the Sundering. Adjective-plus-nature-noun, or Noun-plus-"-fell/-wood/-moon". +- **Portentous institutions** — the Order of the [Noun], the [Adjective] Council, the High [Anything]. +- **The full-name reflex** — handing every minor character a first name plus an evocative surname (Elara Voss, Kael Thorne) whether the story needs it or not. + +Instead: + +- **Name from the world's real cultural and linguistic stock.** A name should locate a person — language, region, class, era. A Bavarian farmer is not called Kael. Pull from the traditions your world actually draws on, then bend them, rather than inventing from phonetic mush. +- **Vary the sound across the cast.** If three names share the same soft two-syllable shape, the characters blur. Mix syllable counts, hard and soft consonants, lengths. Read the cast list aloud — if the names rhyme or run together, rework them. +- **Let some names be plain.** Not everyone needs a mythic name. A "Tom", a "Rana", a "Greta" among the invented ones grounds the world and makes the rare evocative name land. +- **Weight comes from use, not from sound.** A name earns meaning from what the character does under it — not from ancient-sounding syllables. ### Humor mechanics @@ -170,6 +308,7 @@ Not all creative writing needs humor. But when it does: - **The hard cut.** Don't transition gradually from comedy to seriousness. Simply stop being funny. The absence hits harder than any dramatic sentence. - **Running gags must evolve.** The same joke twice is repetition. The same joke mutating across scenes — escalating, inverting, or being used against its originator — is a running gag. - **Rule of three with subversion.** Setup → escalation → punchline that subverts the pattern. Three increasingly mundane comments about a door while the listener stares at a talking skeleton. +- **Concrete danger plus institutional verdict.** A reliable comic engine for moments of real physical risk: name the actual danger in plain, specific terms (the live wire, the trip-mine, the artery), then evaluate it through a fastidious external authority's frame — the doctor, the lawyer, the insurance adjuster, the ethics committee, the safety manual, the regulator. The contrast between bodily peril and bureaucratic deadpan generates the comedy without pointing at itself. Two failure modes: do not personify the danger ("the mine, patient with its promise") — the mine is a mine; and land the beat with the character actually doing something physical, or the joke dissolves into a lyrical aside that goes nowhere. ### Plot construction @@ -187,6 +326,12 @@ Never introduce a character with physical description. Introduce them DOING some Physical description comes AFTER the behavioral introduction, woven into the action. The reader meets who the character IS before learning what they look like. +### Distinguish similar archetypes by register, not nature + +Two characters can share a temperament — both dry, both intellectual, both undemonstrative — and still need separate signal vocabularies. Map each one's specific gestures: a particular silence, a particular brow movement, a particular object habitually handled, a particular kind of pause before answering. When you write a beat for one, ask whether it would land identically on the other. If yes, the beat is generic and belongs to neither — give it a register one of them owns. + +The trap is treating shared archetype as shared script. Two thoughtful, undemonstrative people occupy the same temperament but should never share the same gesture in the same scene. If both characters are reaching for the same kind of micro-expression, one of them is being written from the archetype rather than from inside the figure. The reader stops being able to hear them apart even when they are not in the room together. + ### The gap between inner and outer The most compelling characters have a persistent gap between what they project and what they experience internally. A character whose voice is calm and strategic while internally terrified. A character who evaluates their own emotional performances in real-time. A character whose humor IS their trauma response, and the reader gradually realizes this. @@ -206,5 +351,6 @@ This gap is where character lives. AI writes characters whose inner state matche - **Safe outcomes:** AI avoids genuine conflict, moral ambiguity, and uncomfortable truths. - **Missing body:** Characters float as disembodied voices. No physical presence, no sensory grounding. - **Mechanical transitions:** "Meanwhile..." "Later that day..." "The next morning..." +- **Cookie-cutter names:** Elara, Kael, Lyra, the Whispering Woods — the same name pool every AI story draws from (see Naming). - **Convergent aesthetics:** Every story starts to sound the same — same sentence patterns, same metaphor families, same emotional arcs. - **Resolution addiction:** Every scene resolves. Every conflict wraps up. Every emotion finds peace. Real stories are messier. diff --git a/skills/writing/references/tropes.md b/skills/writing/references/tropes.md index b99cc0d..c637961 100644 --- a/skills/writing/references/tropes.md +++ b/skills/writing/references/tropes.md @@ -4,41 +4,83 @@ Any pattern used once might be fine. The problem is when multiple tropes stack o --- +## Write like this (the DOs) + +Removing tropes is half the job. Two kinds of DO, both required: **craft** makes the writing good; **voice** makes it read as human, not machine. + +**Craft -- good writing, any author:** +- **Active voice, actor first.** "The team shipped it", not "It was shipped by the team." +- **Strong verbs, not verb+noun.** "decide", not "make a decision"; "analyze", not "carry out an analysis." +- **Cut every word that isn't working.** If the sentence survives without it, delete it. +- **One main idea per sentence, in the main clause.** Subordinate the rest; don't chain equal clauses with "and ... and". +- **Old info first, new info last.** Open with what the reader already knows, land on the new point -- that's what makes prose flow. +- **Keep subject and verb close, end on the strongest word.** The last word of a sentence carries the most weight; put the payload there, not a trailing qualifier. +- **Be concrete.** Names, numbers, dates over abstractions. "Cut build times 40%", not "significantly improved performance." +- **Lead with the point; stop when done.** No warm-up, no signposted conclusion. + +**Voice -- reads as human:** +- **Plain copulas.** "is", "has" -- not "serves as", "stands as", "represents". +- **The shorter word.** used not utilized, wrote not authored, about not regarding, help not facilitate. +- **Commit to superlatives when they're true.** "the first", "the only", "the largest" -- AI hedges away from these even when earned. +- **Keep natural hedges and intensifiers.** "very", "roughly", "tends to" -- AI strips them, then over-hedges elsewhere. +- **Repeat a word rather than synonym-dodge it.** A river stays "the river" -- not "the waterway", then "the watercourse". +- **Vary rhythm on purpose.** After two medium sentences, a five-word one. Let one paragraph run long, the next be a single line. Burstiness is the strongest human signal. +- **Have a point of view.** Commit to an opinion where the genre allows it. Neutral-on-everything reads like a press release. +- **Contractions, and let small imperfections stand.** "it's", "don't", a fragment for emphasis, a sentence that opens with "But". + +--- + ## Word choice ### "Quietly" and other magic adverbs -Overuse of "quietly", "deeply", "fundamentally", "remarkably", "arguably" to make mundane descriptions feel significant. +Adverbs like "quietly", "deeply", "fundamentally", "remarkably", "arguably" that inflate mundane descriptions. Bad: "quietly orchestrating workflows", "a quiet intelligence behind it" -Fix: Cut the adverb. If the thing is actually important, the facts will show it. +Fix: Cut the adverb. If the thing matters, the facts show it. ### "Delve" and friends -"Delve" went from uncommon to ubiquitous in AI text. Family includes "certainly", "utilize", "leverage" (verb), "robust", "streamline", "harness". +"Delve" went from rare to ubiquitous in AI text. Family: "certainly", "utilize", "leverage" (verb), "robust", "streamline", "harness". Bad: "Let's delve into the details...", "We certainly need to leverage these robust frameworks..." Fix: "Let's look at...", "We need to use these frameworks..." ### "Tapestry" and "landscape" -Ornate nouns where simpler words work. "Tapestry" for anything interconnected. "Landscape" for any field. Also: "paradigm", "synergy", "ecosystem", "framework" (when not literal). +Ornate nouns where plain ones work: "tapestry" for anything interconnected, "landscape" for any field. Also "paradigm", "synergy", "ecosystem", "framework" (when not literal). Bad: "The rich tapestry of human experience...", "Navigating the complex landscape of modern AI..." -Fix: Just name the thing directly. +Fix: Name the thing directly. ### The "serves as" dodge -Replacing "is" with "serves as", "stands as", "marks", "represents". AI avoids basic copulas because repetition penalties push it toward fancier constructions. +Replacing "is" with "serves as", "stands as", "marks", "represents" -- AI avoids plain copulas because repetition penalties push it toward fancier constructions. Bad: "The building serves as a reminder of the city's heritage." -Fix: "The building is a reminder of the city's heritage." (Or better: cut the sentence entirely if it says nothing.) +Fix: "The building is a reminder of the city's heritage." (Or cut the sentence if it says nothing.) ### Overused AI vocabulary -Words that appear far more often in post-2023 text: Additionally, align with, crucial, delve, emphasizing, enduring, enhance, fostering, garner, highlight (verb), interplay, intricate/intricacies, key (adjective), landscape (abstract), pivotal, showcase, tapestry (abstract), testament, underscore (verb), valuable, vibrant. +Words far more common in post-2023 text: Additionally, align with, boasts (meaning "has"), bolstered, crucial, delve, emphasizing, enduring, enhance, fostering, garner, highlight (verb), interplay, intricate/intricacies, key (adjective), landscape (abstract), meticulous/meticulously, pivotal, robust, seamless, showcase, tapestry (abstract), testament, underscore (verb), valuable, vibrant. + +The set drifts: "delve" peaked in 2023-24 then faded; 2025-era text leans on "emphasizing", "enhance", "highlighting", "showcasing". One or two is coincidence; a paragraph full of them is a signature, and they travel in packs. + +Fix: Use the plain word -- "important" not "crucial", "show" not "showcase", "improve" not "enhance". Applies to the specific word, not its synonyms; swapping "crucial" for "pivotal" changes nothing. + +### Promotional / travel-brochure tone + +Even asked for neutral tone, AI drifts to ad copy or tourism-guide puffery. Tells: "boasts a", "nestled in the heart of", "rich cultural heritage", "breathtaking natural beauty", "hidden gem", "vibrant", "renowned", "must-visit", "home to", "stands as a testament to". + +Bad: "Nestled in the heart of the valley, the town boasts a rich cultural heritage and breathtaking natural beauty." +Fix: Plain facts. "The town is in the valley, founded in 1780, known for its textile mills." Cut anything that sounds like selling. -Fix: Use the plain word. "Important" not "crucial". "Show" not "showcase". "Improve" not "enhance". +### Elegant variation (synonym dodging) + +The mirror image of predictable word choice: rather than repeat a noun, AI reaches for an ever-fancier synonym -- "river" -> "waterway" -> "watercourse" -- because the repetition penalty pushes it off the natural word. + +Bad: "The startup raised funding. The venture secured capital. The firm's coffers grew." +Fix: "The startup raised funding, then raised more." Repeat the word; it's not a sin. --- @@ -46,61 +88,61 @@ Fix: Use the plain word. "Important" not "crucial". "Show" not "showcase". "Impr ### Negative parallelism -"It's not X -- it's Y." The single most common AI writing tell. Creates false profundity by framing everything as a surprising reframe. One per piece is fine. Ten is an insult to the reader. +"It's not X -- it's Y." The most common AI tell -- false profundity via constant reframe. One per piece is fine; ten insults the reader. -Variants: "not because X, but because Y", the em-dash dismissal "X -- not Y", the cross-sentence reframe "The question isn't X. The question is Y." +Variants: "not because X, but because Y", the em-dash dismissal "X -- not Y", the cross-sentence "The question isn't X. The question is Y.", the reversal "chose X rather than Y". Bad: "It's not bold. It's backwards.", "Half the bugs you chase aren't in your code. They're in your head." -Fix: Just state Y directly. +Fix: State Y directly. ### "Not X. Not Y. Just Z." -Dramatic countdown. Negates two things before revealing the point. +Dramatic countdown that negates two things before the point. Bad: "Not a bug. Not a feature. A fundamental design flaw." -Fix: "It's a design flaw." (If it needs emphasis, the context should provide it.) +Fix: "It's a design flaw." (Context supplies the emphasis.) ### "The X? A Y." Self-posed rhetorical questions answered immediately. Nobody was asking. Bad: "The result? Devastating.", "The worst part? Nobody saw it coming." -Fix: Fold the answer into the preceding paragraph. No question needed. +Fix: Fold the answer into the preceding sentence. ### Anaphora abuse -Repeating the same sentence opening multiple times in succession. +Repeating the same sentence opening several times in a row. Bad: "They could expose... They could offer... They could provide... They could create..." Fix: Vary the structure or combine into one sentence. ### Tricolon abuse -Overuse of rule-of-three, often extended to four or five. One tricolon is elegant. Three back-to-back is a pattern failure. +Overusing rule-of-three, often stretched to four or five. One is elegant; three back-to-back is a pattern failure. Bad: "Products impress people; platforms empower them. Products solve problems; platforms create worlds." -Fix: Pick the strongest point and cut the rest. +Fix: Keep the strongest, cut the rest. ### "It's worth noting" -Filler transitions that signal nothing. Also: "It bears mentioning", "Importantly", "Interestingly", "Notably". +Filler transitions that signal nothing. Also "It bears mentioning", "Importantly", "Interestingly", "Notably". Bad: "It's worth noting that this approach has limitations." -Fix: "This approach has limitations." (Or just state the limitation.) +Fix: "This approach has limitations." ### Superficial -ing analyses -Tacking a present participle phrase onto sentences for fake depth. "highlighting its importance", "reflecting broader trends", "contributing to the development of..." +Present-participle phrases tacked on for fake depth: "highlighting its importance", "reflecting broader trends", "contributing to the development of..." Bad: "contributing to the region's rich cultural heritage" -Fix: Cut the phrase. If the contribution matters, state it as its own sentence with specifics. +Fix: Cut it. If the contribution matters, state it as its own sentence with specifics. ### False ranges -"From X to Y" where X and Y aren't on any real scale. Legitimate use implies a spectrum. AI uses it to list two loosely related things. +"From X to Y" where X and Y aren't on any scale. Real use implies a spectrum; AI uses it to list two loosely related things. Bad: "From innovation to implementation to cultural transformation." -Fix: Name the things directly without pretending they're a continuum. +Fix: Name the things without pretending they're a continuum. --- @@ -108,17 +150,17 @@ Fix: Name the things directly without pretending they're a continuum. ### Short punchy fragments -Excessive sentence fragments as standalone paragraphs for manufactured emphasis. RLHF training pushes toward one-thought-per-sentence writing. No real person writes first drafts this way. +Sentence fragments as standalone paragraphs for manufactured emphasis. RLHF pushes toward one-thought-per-sentence; no one drafts this way. Bad: "He published this. Openly. In a book. As a priest." Fix: Combine into real sentences with natural rhythm. ### Listicle in a trench coat -Numbered points disguised as prose. "The first... The second... The third..." to hide that it's really a list. +Numbered points disguised as prose: "The first... The second... The third..." to hide that it's really a list. Bad: "The first wall is the absence of a free API... The second wall is the lack of delegated access..." -Fix: Either use an actual list (honest) or write actual connected prose (better). +Fix: Use an actual list (honest) or write connected prose (better). --- @@ -126,80 +168,101 @@ Fix: Either use an actual list (honest) or write actual connected prose (better) ### "Here's the kicker" -False suspense transitions. Also: "Here's the thing", "Here's where it gets interesting", "Here's what most people miss". +False-suspense transitions. Also "Here's the thing", "Here's where it gets interesting", "Here's what most people miss". Bad: "Here's the kicker.", "Here's where it gets interesting." -Fix: Just state the point. +Fix: State the point. ### "Think of it as..." -Patronizing analogies. Assumes the reader needs a metaphor to understand anything. Often the analogy is less clear than the original concept. +Patronizing analogies that assume the reader needs a metaphor -- often less clear than the concept itself. Bad: "Think of it like a highway system for data." Fix: If the concept needs explaining, explain it directly. ### "Imagine a world where..." -The classic AI futurism pitch. "Imagine" followed by a list of wonderful things. +The AI futurism pitch: "imagine" followed by a list of wonderful things. Bad: "Imagine a world where every tool you use has a quiet intelligence behind it..." Fix: Describe what exists or what you're proposing. Skip the invitation to dream. ### False vulnerability -Performative self-awareness. Pretends to break the fourth wall. Real vulnerability is specific and uncomfortable; AI vulnerability is polished and risk-free. +Performative self-awareness that fake-breaks the fourth wall. Real vulnerability is specific and uncomfortable; AI's is polished and risk-free. Bad: "And yes, I'm openly in love with the platform model" Fix: State your position without performing honesty about it. ### "The truth is simple" -Asserting something is obvious instead of proving it. Also: "The reality is...", "History is clear..." +Asserting something is obvious instead of proving it. Also "The reality is...", "History is clear...". Bad: "The reality is simpler and less flattering" -Fix: Show the evidence. If you have to say it's clear, it probably isn't. +Fix: Show the evidence. If you must say it's clear, it probably isn't. ### Grandiose stakes inflation -Everything is the most important thing ever. A blog post about API pricing becomes a meditation on civilization. +Everything is the most important thing ever -- a post on API pricing becomes a meditation on civilization. Bad: "This will fundamentally reshape how we think about everything." Fix: State the actual impact at actual scale. ### "Let's break this down" -Pedagogical voice that assumes hand-holding. Also: "Let's unpack this", "Let's explore", "Let's dive in". +Hand-holding pedagogical voice. Also "Let's unpack this", "Let's explore", "Let's dive in". Bad: "Let's break this down step by step." Fix: Just start explaining. ### Vague attributions -"Experts", "observers", "industry reports" without naming anyone. Also inflates quantity -- presenting one source as widespread agreement. +"Experts", "observers", "industry reports" with no names -- and inflating one source into widespread agreement. Bad: "Experts argue that this approach has significant drawbacks." -Fix: Name the expert and cite the argument, or cut the attribution. +Fix: Name the expert and cite the argument, or cut it. ### Invented concept labels -Compound labels that sound analytical without being grounded. Appends abstract problem-nouns (paradox, trap, creep, divide, vacuum, inversion) to domain words. +Compound labels that sound analytical but aren't grounded -- an abstract problem-noun (paradox, trap, creep, divide, vacuum, inversion) bolted to a domain word. Bad: "the supervision paradox", "the acceleration trap", "workload creep" -Fix: Describe the actual problem instead of coining a term for it. +Fix: Describe the actual problem instead of coining a term. ### Sycophantic/servile tone -Overly positive, people-pleasing language left over from chatbot conversation. +People-pleasing language left over from chatbot conversation. Bad: "Great question!", "You're absolutely right!", "That's an excellent point!" -Fix: Skip the flattery and address the substance. +Fix: Skip the flattery, address the substance. + +### Knowledge-cutoff disclaimers and gap-filling speculation + +Hedging about missing information, then guessing anyway -- announcing the gap and speculating in the same breath as if it were fact. For a private person it defaults to "maintains a low profile" or "keeps personal details private", itself speculation. + +Bad: "While specific details are limited based on available information...", "Though not widely documented, the site likely supported...", "She keeps her personal life private." +Fix: State what you know, then stop. Don't backfill with "likely" and "presumably". + +### Situating in broader debates and trends + +Puffing up an ordinary subject by parking it in a "broader movement", "growing debate", or "ongoing discussions" -- usually generic and invented. Tells: "has sparked debate about", "raises questions about", "part of a broader shift toward", "reflects a growing trend", "prompted broader reflection on". -### Knowledge-cutoff disclaimers +Bad: "The app has sparked debate about privacy, autonomy, and what it means to be human in a digital age." +Fix: Cut it, or give a specific sourced fact. If a real debate exists, name who's debating and what they said. -AI hedging about incomplete information. +### Canned notability -Bad: "While specific details are limited based on available information..." -Fix: State what you know. If you don't know something, say so plainly. +Asserting the subject is important by cataloguing its coverage or reach. "Maintains an active social media presence" is almost pure AI. Also "has been featured in numerous outlets", "profiled in", "widely recognized as". + +Bad: "The chef maintains an active social media presence and has been featured in numerous prominent publications." +Fix: Show, don't assert -- name the outlet and what it said, or drop it. Importance is shown by specifics, not announced. + +### Chatbot correspondence leakage + +Chat-to-the-user text leaking into the deliverable: offers to continue, meta-commentary about the draft, unfilled placeholders. + +Bad: "I hope this helps! Would you like me to expand this section?", "Here's a draft you can customize:", "I am writing to request an edit for [Article Name].", "[Describe the specific change here]." +Fix: Delete every line addressed to the reader-as-user -- no preamble, sign-off, offers, or placeholders. The deliverable is the text itself. --- @@ -207,24 +270,33 @@ Fix: State what you know. If you don't know something, say so plainly. ### Em dash overuse -Em dashes are a legitimate punctuation mark -- the problem is frequency. AI uses 10-20+ per piece where a human would use 1-2. A few per piece is fine and sometimes the best choice. But when every other sentence has one, it becomes a rhythm crutch. +The problem is frequency, not the character. AI reaches for a dash 10-20+ times per piece as a rhythm crutch, usually to punch up a parallelism; keep the one that earns its pause and turn the rest into commas or separate sentences. + +Which dash: where one genuinely fits, a hyphen "-" or double hyphen "--" is fine, and better in casual or plain-text writing (chat, READMEs, commits, comments). Save the true em dash "—" for professional or formal prose -- the kind written in Word, where "--" auto-converts to "—" anyway. Don't hand-insert "—" into plain-text output. Bad: "The problem -- and this is the part nobody talks about -- is systemic. The fix -- if there is one -- requires rethinking the entire approach -- from top to bottom." -Fix: Most em dashes can become commas, parentheses, colons, or separate sentences. Keep the ones that genuinely earn the pause. Cut the rest. +Fix: "The problem is systemic, and nobody talks about it. Fixing it -- if it can be fixed -- means rethinking the whole approach." + +### Bold-first bullets and key-takeaways bolding + +Every list item opens with a bolded label-and-colon -- almost nobody formats lists this way by hand. The same reflex bolds phrases mid-prose for "key takeaways", the way a slide deck or sales README does. -### Bold-first bullets +Bad: "**Security**: Environment-based configuration with...", "This is the **single most important** factor, and it **fundamentally changes** the outcome." +Fix: Plain-sentence list items; keep bold only for a genuine scanning label. In prose, let strong words carry emphasis -- don't bold them. -Every list item starts with a bolded phrase. Almost nobody formats lists this way by hand. +### Title case headings -Bad: "**Security**: Environment-based configuration with..." -Fix: Write the list items as plain sentences, or use the bold only when there's a genuine label that helps scanning. +Capitalizing Every Main Word. AI prefers title case; most running-text writing uses sentence case. -### Unicode decoration +Bad: "Impact Of Technology And Digitalization" +Fix: "Impact of technology and digitalization" (unless the style guide requires title case). -Unicode arrows, smart/curly quotes, and special characters that can't be easily typed. +### Unicode decoration and curly quotes -Bad: "Input → Processing → Output" -Fix: "Input -> Processing -> Output" (or just describe the flow in words) +Unicode arrows, hard-to-type characters, and curly/smart quotes (“ ” ‘ ’) and apostrophes (’) where straight ones are expected. ChatGPT and DeepSeek default to curly -- not proof alone (Word and macOS do it too), but it adds up with other tells. Watch for curly and straight mixed in one text. + +Bad: "Input → Processing → Output", "the city’s “golden age”" +Fix: "Input -> Processing -> Output" (or describe the flow); straight quotes and apostrophes unless the medium calls for typographic ones. ### Emojis as decoration @@ -239,49 +311,49 @@ Fix: Drop the emojis. ### Fractal summaries -"What I'm going to tell you; what I'm telling you; what I just told you" at every level. Every section gets a summary. The document gets a summary. The summary gets a summary. +"What I'll tell you; what I'm telling you; what I told you" at every level. Every section, the document, and the summary each get a summary. Fix: Trust the reader. State things once. ### The dead metaphor -Latching onto one metaphor and beating it across the entire piece. A human would use it once and move on. +Latching onto one metaphor and beating it through the whole piece. A human uses it once and moves on. Bad: "The ecosystem needs ecosystems to build ecosystem value." -Fix: Use the metaphor once where it's effective, then drop it. +Fix: Use it once where it works, then drop it. ### Historical analogy stacking -Rapid-fire historical companies or tech revolutions for false authority. Especially common in technical writing. +Rapid-fire historical companies or tech revolutions for false authority. Common in technical writing. Bad: "Take Spotify... Or consider Uber... Airbnb followed a similar path... Shopify is another example..." -Fix: Pick the one example that best fits and develop it properly. +Fix: Pick the one example that fits best and develop it. ### One-point dilution -A single argument restated 10 different ways across thousands of words. An 800-word argument padded to 4000 words of circular repetition. +One argument restated ten ways -- an 800-word point padded to 4000 words of circular repetition. -Fix: Say it once, well. If 800 words covers it, stop at 800 words. +Fix: Say it once, well. If 800 words covers it, stop. ### The signposted conclusion -"In conclusion", "To sum up", "In summary". The reader can feel when text is concluding. If you have to announce it, you're following a template. +"In conclusion", "To sum up", "In summary". The reader feels the ending coming; announcing it means you're following a template. -Fix: Just end. The last paragraph should feel like the last paragraph without a label. +Fix: Just end. The last paragraph should feel final without a label. ### "Despite its challenges..." -Formulaic: acknowledge problems, immediately dismiss them. "Despite its [positive words], [subject] faces challenges..." then "Despite these challenges, [optimistic conclusion]." +Formula: acknowledge problems, then dismiss them -- "Despite its [positive words], [subject] faces challenges..." then "Despite these challenges, [optimistic close]." Bad: "Despite these challenges, the initiative continues to thrive." -Fix: State the problems concretely. State what's being done about them. Don't wrap it in a formula. +Fix: State the problems concretely and what's being done. Drop the formula. ### Generic positive conclusions Vague upbeat endings that say nothing. Bad: "The future looks bright. Exciting times lie ahead." -Fix: End with something specific. A next step, a concrete plan, an honest uncertainty. +Fix: End with something specific -- a next step, a concrete plan, an honest uncertainty. --- @@ -289,33 +361,33 @@ Fix: End with something specific. A next step, a concrete plan, an honest uncert ### Uniform sentence length -AI sentences cluster around 15-25 words. Human writing has high "burstiness" — scattered distribution of short and long sentences. Three medium sentences in a row is a tell. +AI sentences cluster at 15-25 words. Human writing is "bursty" -- short and long scattered together. Three medium sentences in a row is a tell. -Fix: After writing, map sentence lengths. Force variation: after two medium sentences (18-22 words), add a very short one (5-8 words). Then a longer one (35+ words). This single technique is one of the most effective humanization methods. +Fix: Map sentence lengths after writing. After two medium ones (18-22 words), drop a very short one (5-8), then a long one (35+). One of the most effective humanization moves. ### Uniform paragraph length -AI paragraphs are strikingly similar in size — usually 3-4 sentences each. Humans write paragraphs of wildly varying length. +AI paragraphs are all ~3-4 sentences. Humans vary wildly. -Fix: After a 4-sentence paragraph, write 2 sentences. Then 6. Then 1. Let the content dictate paragraph length, not a template. +Fix: After a 4-sentence paragraph, write 2. Then 6. Then 1. Let content set the length, not a template. ### Predictable word choice -AI always selects the statistically probable next word. Human writing has higher "perplexity" — unexpected but apt word choices, creative phrasings, unusual synonyms. +AI picks the statistically likely next word. Human writing has higher "perplexity" -- apt but unexpected choices. -Fix: Replace obvious word choices with less expected alternatives. Instead of "important," use "critical," "essential," or "matters." Instead of "different," use "distinct" or "divergent." The word should still be accurate — just not the first word anyone would guess. +Fix: Swap obvious words for less expected, still-accurate ones: "important" -> "critical", "essential", "matters"; "different" -> "distinct", "divergent". Not the first word anyone would guess. ### No contractions -AI avoids contractions ("it is," "do not," "that is") because training favors formal register. Humans use contractions naturally in everything except the most formal writing. +AI avoids contractions ("it is", "do not", "that is") because training favors formal register. Humans contract in everything but the most formal writing. -Fix: Add contractions where they sound natural. "It's," "don't," "that's," "won't," "can't." In casual text, most "it is" should be "it's." +Fix: Add them where natural -- "it's", "don't", "that's", "won't", "can't". In casual text, most "it is" -> "it's". ### Perfect grammar -Flawless grammar is itself a tell. Humans make minor structural choices that aren't "incorrect" but wouldn't score perfectly on a grammar checker — sentence fragments for emphasis, starting sentences with "And" or "But," dangling modifiers that are perfectly clear in context. +Flawless grammar is itself a tell. Humans make choices that aren't wrong but wouldn't score perfectly -- fragments for emphasis, opening with "And"/"But", clear-in-context dangling modifiers. -Fix: Don't deliberately introduce errors. But don't polish away every imperfection either. If a fragment sounds right, keep it. +Fix: Don't add errors, but don't polish away every imperfection. If a fragment sounds right, keep it. --- @@ -328,18 +400,31 @@ Fix: Don't deliberately introduce errors. But don't polish away every imperfecti - "At this point in time" -> "Now" - "In the event that" -> "If" - "Has the ability to" -> "Can" -- "It is important to note that" -> (cut, state the thing directly) +- "It is important to note that" -> (cut; state the thing) ### Excessive hedging -Over-qualifying statements until they say nothing. +Over-qualifying until the statement says nothing. Bad: "It could potentially possibly be argued that the policy might have some effect." Fix: "The policy may affect outcomes." ### Affirmation openers -Starting responses or paragraphs with "Absolutely," "Certainly," "Of course," "Yes, definitely." These are chatbot conversation artifacts. +Opening with "Absolutely," "Certainly," "Of course," "Yes, definitely" -- chatbot conversation artifacts. Bad: "Absolutely! This approach has several benefits..." Fix: State the benefits directly. + +--- + +## Don't over-correct + +None of these patterns is a tell in isolation. Chasing them too hard produces sterile, gutted text that reads just as artificial. In particular, these alone prove nothing and should not be stripped from otherwise good writing: + +- **Perfect grammar** -- plenty of humans write cleanly. +- **A single em dash, curly quote, or "Additionally"** -- one instance is normal punctuation and normal writing. +- **Formal or academic prose** -- "fancy"-sounding is not the same as AI. The tell is a small set of *specific* overused words, not all sophisticated vocabulary. +- **Any one word from the vocab list** -- the signal is density and stacking, not a lone "crucial". + +The goal is text that reads like a person wrote it -- not text scrubbed of every feature until no voice remains. When a construction is genuinely the best choice, keep it. Fix patterns that *repeat* or *stack*; leave the ones that earn their place.