From 5d885102744fc4f45b6037e13d1408bdc53326f3 Mon Sep 17 00:00:00 2001 From: "ci[bot]" Date: Mon, 24 Aug 2026 09:30:03 +0800 Subject: [PATCH] :package: deps(thirdparty): update snapshots --- brooks-lint/.claude-plugin/marketplace.json | 2 +- brooks-lint/.claude-plugin/plugin.json | 2 +- brooks-lint/.codex-plugin/plugin.json | 2 +- .../.github/actions/brooks-lint/action.yml | 10 + .../.github/workflows/star-history.yml | 40 + brooks-lint/CHANGELOG.md | 22 + brooks-lint/CLAUDE.md | 2 + brooks-lint/README.es.md | 38 +- brooks-lint/README.ja.md | 36 +- brooks-lint/README.ko.md | 36 +- brooks-lint/README.md | 36 +- brooks-lint/README.zh-CN.md | 36 +- brooks-lint/README.zh-TW.md | 36 +- brooks-lint/SOURCE.md | 4 +- brooks-lint/assets/star-history.json | 1398 +++++++++++++++++ brooks-lint/assets/star-history.svg | 45 + brooks-lint/docs/dsh-setup.md | 60 + brooks-lint/docs/getting-started.md | 11 +- brooks-lint/docs/github-action-example.yml | 1 + brooks-lint/docs/index.html | 2 +- brooks-lint/gemini-extension.json | 2 +- brooks-lint/package.json | 2 +- brooks-lint/scripts/ci-review.mjs | 4 +- brooks-lint/scripts/gen-star-history.mjs | 241 +++ brooks-lint/scripts/install.sh | 10 +- brooks-lint/scripts/platforms.mjs | 64 + brooks-lint/scripts/run-evals-live.mjs | 2 +- brooks-lint/scripts/validate-repo.mjs | 48 + brooks-lint/scripts/validate-repo.test.mjs | 65 + cangjie-skill/README.en.md | 6 + cangjie-skill/README.ja.md | 6 + cangjie-skill/README.md | 29 + cangjie-skill/SOURCE.md | 4 +- .../assets/wecom-cangjie-group-qr.png | Bin 4700 -> 4731 bytes darwin-skill/README.md | 2 +- darwin-skill/SOURCE.md | 4 +- ...etup-pointer-only-for-hard-dependencies.md | 6 +- .../adr/0002-ship-as-a-claude-code-plugin.md | 20 +- matt-pocock-skills/.agents/install-block.md | 12 +- matt-pocock-skills/.agents/invocation.md | 18 +- matt-pocock-skills/.agents/writing-docs.md | 54 +- .../.changeset/add-implement-spec-skill.md | 5 + .../domain-modeling-trigger-context-adr.md | 2 +- .../.changeset/fix-yaml-frontmatter-colons.md | 5 + .../grilling-add-hr-between-questions.md | 5 + .../.changeset/grilling-remove-em-dashes.md | 5 + .../.changeset/remove-em-dashes-repo-wide.md | 5 + .../skill-tool-invocation-terminology.md | 9 + .../user-invoked-skill-invocation.md | 11 + .../.changeset/wait-what-context-map.md | 5 + .../.claude-plugin/marketplace.json | 2 +- matt-pocock-skills/.claude-plugin/plugin.json | 2 +- matt-pocock-skills/.gitignore | 1 + .../mainstream-issue-trackers-only.md | 6 +- .../.out-of-scope/question-limits.md | 6 +- .../.out-of-scope/setup-skill-verify-mode.md | 4 +- matt-pocock-skills/CLAUDE.md | 18 +- matt-pocock-skills/CONTEXT.md | 12 +- matt-pocock-skills/README.md | 60 +- matt-pocock-skills/SOURCE.md | 4 +- .../docs/engineering/ask-matt.md | 18 +- .../docs/engineering/code-review.md | 22 +- .../docs/engineering/codebase-design.md | 38 +- .../docs/engineering/diagnosing-bugs.md | 34 +- .../docs/engineering/domain-modeling.md | 34 +- .../docs/engineering/grill-with-docs.md | 34 +- .../docs/engineering/implement.md | 2 +- .../improve-codebase-architecture.md | 30 +- .../docs/engineering/prototype.md | 32 +- .../docs/engineering/research.md | 28 +- .../engineering/resolving-merge-conflicts.md | 12 +- .../engineering/setup-matt-pocock-skills.md | 22 +- matt-pocock-skills/docs/engineering/tdd.md | 30 +- .../docs/engineering/to-spec.md | 32 +- .../docs/engineering/to-tickets.md | 46 +- matt-pocock-skills/docs/engineering/triage.md | 36 +- .../docs/engineering/wayfinder.md | 56 +- matt-pocock-skills/docs/engineering/wizard.md | 30 +- .../docs/productivity/grill-me.md | 24 +- .../docs/productivity/grilling.md | 30 +- .../docs/productivity/handoff.md | 30 +- matt-pocock-skills/docs/productivity/teach.md | 36 +- .../docs/productivity/to-questionnaire.md | 32 +- .../docs/productivity/wait-what.md | 2 +- .../docs/productivity/writing-for-agents.md | 40 +- matt-pocock-skills/scripts/link-skills.sh | 8 +- .../scripts/sync-plugin-version.mjs | 2 +- .../skills/deprecated/README.md | 2 +- .../skills/engineering/README.md | 36 +- .../engineering/ask-matt/PHASE-BOUNDARIES.md | 14 +- .../skills/engineering/ask-matt/SKILL.md | 68 +- .../skills/engineering/code-review/SKILL.md | 54 +- .../engineering/codebase-design/DEEPENING.md | 8 +- .../codebase-design/DESIGN-IT-TWICE.md | 18 +- .../engineering/codebase-design/SKILL.md | 26 +- .../engineering/diagnosing-bugs/SKILL.md | 58 +- .../scripts/hitl-loop.template.sh | 4 +- .../engineering/domain-modeling/ADR-FORMAT.md | 22 +- .../domain-modeling/CONTEXT-FORMAT.md | 6 +- .../engineering/domain-modeling/SKILL.md | 18 +- .../engineering/grill-with-docs/SKILL.md | 2 +- .../HTML-REPORT.md | 38 +- .../improve-codebase-architecture/SKILL.md | 42 +- .../skills/engineering/prototype/LOGIC.md | 34 +- .../skills/engineering/prototype/SKILL.md | 14 +- .../skills/engineering/prototype/UI.md | 46 +- .../skills/engineering/research/SKILL.md | 2 +- .../resolving-merge-conflicts/SKILL.md | 2 +- .../setup-matt-pocock-skills/SKILL.md | 60 +- .../setup-matt-pocock-skills/domain.md | 8 +- .../issue-tracker-github.md | 8 +- .../issue-tracker-gitlab.md | 10 +- .../issue-tracker-local.md | 4 +- .../skills/engineering/tdd/SKILL.md | 16 +- .../skills/engineering/to-spec/SKILL.md | 8 +- .../skills/engineering/to-tickets/SKILL.md | 32 +- .../skills/engineering/triage/AGENT-BRIEF.md | 18 +- .../skills/engineering/triage/OUT-OF-SCOPE.md | 30 +- .../skills/engineering/triage/SKILL.md | 58 +- .../skills/engineering/wayfinder/SKILL.md | 74 +- .../skills/engineering/wizard/SKILL.md | 18 +- .../skills/engineering/wizard/template.sh | 48 +- .../skills/in-progress/README.md | 15 +- .../in-progress/claude-handoff/SKILL.md | 6 +- .../in-progress/implement-spec/SKILL.md | 35 + .../implement-spec/agents/openai.yaml | 5 + .../skills/in-progress/loop-me/SKILL.md | 20 +- .../setup-ts-deep-modules/SKILL.md | 48 +- .../dependency-cruiser.config.cjs | 16 +- .../skills/in-progress/writing-beats/SKILL.md | 30 +- .../in-progress/writing-fragments/SKILL.md | 16 +- .../skills/in-progress/writing-shape/SKILL.md | 26 +- matt-pocock-skills/skills/misc/README.md | 10 +- .../misc/git-guardrails-claude-code/SKILL.md | 2 +- .../skills/misc/setup-pre-commit/SKILL.md | 2 +- .../skills/productivity/README.md | 14 +- .../skills/productivity/grill-me/SKILL.md | 2 +- .../skills/productivity/grilling/SKILL.md | 14 +- .../skills/productivity/handoff/SKILL.md | 2 +- .../productivity/teach/GLOSSARY-FORMAT.md | 6 +- .../teach/LEARNING-RECORD-FORMAT.md | 20 +- .../productivity/teach/MISSION-FORMAT.md | 8 +- .../productivity/teach/RESOURCES-FORMAT.md | 4 +- .../skills/productivity/teach/SKILL.md | 8 +- .../productivity/to-questionnaire/SKILL.md | 11 +- .../skills/productivity/wait-what/SKILL.md | 4 +- .../productivity/wait-what/agents/openai.yaml | 2 +- .../writing-for-agents/SKILL-MECHANICS.md | 10 +- .../productivity/writing-for-agents/SKILL.md | 50 +- ui-ux-pro-max/CONTRIBUTING.md | 6 +- ui-ux-pro-max/README.md | 2 +- ui-ux-pro-max/README.zh.md | 2 +- ui-ux-pro-max/SOURCE.md | 4 +- 153 files changed, 3428 insertions(+), 1203 deletions(-) create mode 100644 brooks-lint/.github/workflows/star-history.yml create mode 100644 brooks-lint/assets/star-history.json create mode 100644 brooks-lint/assets/star-history.svg create mode 100644 brooks-lint/docs/dsh-setup.md create mode 100644 brooks-lint/scripts/gen-star-history.mjs create mode 100644 brooks-lint/scripts/platforms.mjs create mode 100644 matt-pocock-skills/.changeset/add-implement-spec-skill.md create mode 100644 matt-pocock-skills/.changeset/fix-yaml-frontmatter-colons.md create mode 100644 matt-pocock-skills/.changeset/grilling-add-hr-between-questions.md create mode 100644 matt-pocock-skills/.changeset/grilling-remove-em-dashes.md create mode 100644 matt-pocock-skills/.changeset/remove-em-dashes-repo-wide.md create mode 100644 matt-pocock-skills/.changeset/skill-tool-invocation-terminology.md create mode 100644 matt-pocock-skills/.changeset/user-invoked-skill-invocation.md create mode 100644 matt-pocock-skills/.changeset/wait-what-context-map.md create mode 100644 matt-pocock-skills/skills/in-progress/implement-spec/SKILL.md create mode 100644 matt-pocock-skills/skills/in-progress/implement-spec/agents/openai.yaml diff --git a/brooks-lint/.claude-plugin/marketplace.json b/brooks-lint/.claude-plugin/marketplace.json index fb7242c5..2365bdf0 100644 --- a/brooks-lint/.claude-plugin/marketplace.json +++ b/brooks-lint/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ { "name": "brooks-lint", "description": "AI code reviews grounded in twelve classic engineering books — decay risk diagnostics with book citations, severity labels, and six analysis modes (PR review, architecture audit, tech debt, test quality, health dashboard, full-sweep auto-fix)", - "version": "1.4.3", + "version": "1.5.0", "source": "./", "author": { "name": "hyhmrright", diff --git a/brooks-lint/.claude-plugin/plugin.json b/brooks-lint/.claude-plugin/plugin.json index 91840c4c..f5f12a18 100644 --- a/brooks-lint/.claude-plugin/plugin.json +++ b/brooks-lint/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "brooks-lint", "description": "AI code reviews grounded in twelve classic engineering books — decay risk diagnostics with book citations, severity labels, and six analysis modes (PR review, architecture audit, tech debt, test quality, health dashboard, full-sweep auto-fix)", - "version": "1.4.3", + "version": "1.5.0", "author": { "name": "hyhmrright", "email": "hyhmrright@gmail.com" diff --git a/brooks-lint/.codex-plugin/plugin.json b/brooks-lint/.codex-plugin/plugin.json index 75d6b288..a6d64025 100644 --- a/brooks-lint/.codex-plugin/plugin.json +++ b/brooks-lint/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "brooks-lint", - "version": "1.4.3", + "version": "1.5.0", "description": "AI code reviews grounded in twelve classic engineering books — decay risk diagnostics with book citations, severity labels, and six analysis modes (PR review, architecture audit, tech debt, test quality, health dashboard, full-sweep auto-fix)", "author": { "name": "hyhmrright", diff --git a/brooks-lint/.github/actions/brooks-lint/action.yml b/brooks-lint/.github/actions/brooks-lint/action.yml index 73977da3..8bee998f 100644 --- a/brooks-lint/.github/actions/brooks-lint/action.yml +++ b/brooks-lint/.github/actions/brooks-lint/action.yml @@ -24,6 +24,9 @@ inputs: model: description: "Claude model to use" default: "claude-sonnet-4-6" + api-base-url: + description: "Anthropic-compatible /v1/messages endpoint to call instead of api.anthropic.com (empty = Anthropic)" + default: "" outputs: score: @@ -71,10 +74,17 @@ runs: shell: bash env: ANTHROPIC_API_KEY: ${{ inputs.anthropic-api-key }} + API_BASE_URL: ${{ inputs.api-base-url }} SARIF_FILE: ${{ inputs.sarif-file }} MODE: ${{ inputs.mode }} MODEL: ${{ inputs.model }} run: | + # Exported only when the input is set: naming ANTHROPIC_BASE_URL in the + # env block above would blank out one inherited from the job env. The + # SDK reads the variable itself, so nothing downstream needs a flag. + if [ -n "$API_BASE_URL" ]; then + export ANTHROPIC_BASE_URL="$API_BASE_URL" + fi sarif_arg=() if [ -n "$SARIF_FILE" ]; then sarif_arg=(--sarif-out "$SARIF_FILE") diff --git a/brooks-lint/.github/workflows/star-history.yml b/brooks-lint/.github/workflows/star-history.yml new file mode 100644 index 00000000..13d705de --- /dev/null +++ b/brooks-lint/.github/workflows/star-history.yml @@ -0,0 +1,40 @@ +name: Star history + +# GitHub restricted the stargazers API to a repo's own admins and collaborators, +# so no third-party service can chart this repo any more. GITHUB_TOKEN can read +# it, so we regenerate the committed SVG here instead. +on: + schedule: + - cron: "17 3 * * 1" # Mondays, 03:17 UTC + workflow_dispatch: + +concurrency: + group: star-history + cancel-in-progress: true + +jobs: + refresh: + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: write + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - name: Set up Node.js + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 + with: + node-version: 22 + - name: Regenerate the chart + run: node scripts/gen-star-history.mjs + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Commit when the chart moved + run: | + if git diff --quiet -- assets/star-history.svg assets/star-history.json; then + echo "No change." + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git commit -m "chore: refresh the star history chart" -- assets/star-history.svg assets/star-history.json + git push diff --git a/brooks-lint/CHANGELOG.md b/brooks-lint/CHANGELOG.md index 44e27723..6c9250e2 100644 --- a/brooks-lint/CHANGELOG.md +++ b/brooks-lint/CHANGELOG.md @@ -2,6 +2,28 @@ All notable changes to brooks-lint are documented here. +## [1.5.0] - 2026-08-14 + +### Added + +- **DeepSeek Harness (`dsh`) support** — DeepSeek AI's open-source agent harness + loads standard Agent Skills through `packages/skill/skill-filesystem`, so all + six modes run with no conversion. `./scripts/install.sh dsh` installs into + `$DSH_HOME/skills` (default `~/.dsh/skills`); `--project` targets + `./.dsh/skills`. dsh also scans `~/.agents/skills`, so the existing + vendor-neutral `install.sh agents` install already covered it. New guide at + [`docs/dsh-setup.md`](docs/dsh-setup.md), with the platform added to the README + install table in all six languages and to `docs/getting-started.md`. + + Three details of dsh's loader matter and are documented in the guide: discovery + is one level deep (`//SKILL.md`), which the installer's flat layout + already satisfies so `../_shared/` resolves; skill names must be kebab-case, + which `brooks-*` already is; and dsh recognises a whitespace-bounded `/name` + token anywhere in a message, so `/brooks-review` and the other five work from + its `/` menu or typed inline. dsh also reads `AGENTS.md` — `$DSH_HOME/AGENTS.md` + plus every file from the project root down to the working directory — so the + repo's Iron Law and Health Score rules load the same way they do elsewhere. + ## [1.4.3] - 2026-08-04 ### Fixed diff --git a/brooks-lint/CLAUDE.md b/brooks-lint/CLAUDE.md index 837ec53e..e53bef14 100644 --- a/brooks-lint/CLAUDE.md +++ b/brooks-lint/CLAUDE.md @@ -36,6 +36,8 @@ Guidance for Claude Code when modifying this repository. For repo layout, instal - `` field `commands` is not accepted `` — `"commands": []` is what stops the CLI from migrating `commands/*.md` into duplicate `source-command-brooks-*` skills (issue #22). Confirmed by installing both ways under an isolated `CODEX_HOME`: drop the field and Codex regenerates `.codex-plugin/migrated-command-skills/`. The CLI's `RawPluginManifest` accepts `commands`; only the ingestion schema rejects it. - `` skill `_shared` is missing `SKILL.md` `` — the validator only skips dot-prefixed dirs, and `_shared/` is a shared-framework dir by design (see above). Renaming it to `.shared/` would also require changing `install.sh`'s `cp -R "$SRC"/*`, whose glob does not match dot-dirs. - **GitHub Action cache:** `.github/actions/brooks-lint/action.yml` uses `actions/cache@v4` with built-in cache-hit guard — do NOT add a manual directory check. +- **Adding a platform is derived, not hardcoded:** create `docs/-setup.md`, add the platform to `install.sh`'s `PLATFORMS` **and** both `global_dir()` / `project_dir()` case tables, then link the new guide from every `README*.md` and `docs/getting-started.md`. `npm run validate` derives both sides (`scripts/platforms.mjs`) and fails on any gap — a guide missing from one translation, or a `PLATFORMS` entry with no directory mapping. Do not add a hand-maintained platform list anywhere. +- **Star history is data-first, never hand-drawn:** `assets/star-history.json` (raw `starred_at` timestamps, no usernames) is the source of truth; `assets/star-history.svg` is a pure function of it. Never hand-edit the SVG — `npm run validate` re-renders and fails on any mismatch. `node scripts/gen-star-history.mjs` refetches (needs `GITHUB_TOKEN` or `gh auth`, since GitHub restricted the stargazers API to admins/collaborators on 2026-06-30); `--render-only` redraws offline from the committed data. The render must stay deterministic — anchoring the time axis to the clock would make the weekly workflow commit noise on every run. - **Custom risks:** Teams add project-specific risk codes via `custom-risks-guide.md` in their project root. Template lives at `skills/_shared/custom-risks-guide.md`. ## How the Skills Work diff --git a/brooks-lint/README.es.md b/brooks-lint/README.es.md index 45e523b5..1c183477 100644 --- a/brooks-lint/README.es.md +++ b/brooks-lint/README.es.md @@ -27,7 +27,7 @@

- Version + Version MIT License Claude Code Plugin Codex CLI Skill @@ -78,7 +78,7 @@ Luego solo pide ("revisa este PR", "audita la arquitectura"), o ejecuta uno de l ([qué hace cada uno](#comandos-de-barra)). Cada hallazgo se devuelve como **Síntoma → Origen → Consecuencia → Remedio** con una cita de libro y -una puntuación de salud de 0 a 100. Las opciones completas de instalación (8 plataformas más) y la +una puntuación de salud de 0 a 100. Las opciones completas de instalación (9 plataformas más) y la configuración de CI/CD están [más abajo](#instalación). ## Los doce libros @@ -273,7 +273,7 @@ Install the brooks-lint skill from hyhmrright/brooks-lint # pídelo dentro O usa el instalador de abajo: `./scripts/install.sh gemini` / `./scripts/install.sh codex`. -### Cualquier otra plataforma — OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid +### Cualquier otra plataforma — OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid · DeepSeek Harness brooks-lint se distribuye como [Agent Skills](https://agentskills.io) estándar. **Cualquier agente que cargue Agent Skills ejecuta los seis modos sin conversión alguna** — un solo comando los instala: @@ -281,7 +281,7 @@ Skills ejecuta los seis modos sin conversión alguna** — un solo comando los i ```bash # elige tu plataforma; --project instala en el repositorio actual en lugar de en tu configuración global curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts/install.sh | bash -s -- -# = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · gemini · codex · agents +# = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · dsh · gemini · codex · agents ``` El instalador copia los skills **de forma plana** en la carpeta correcta, de modo que el framework compartido @@ -298,11 +298,12 @@ El instalador copia los skills **de forma plana** en la carpeta correcta, de mod | GitHub Copilot | `.github/skills` (`--project`) | `.claude/skills`, `AGENTS.md` | [configuración](docs/copilot-setup.md) | | Kiro (AWS) | `~/.kiro/skills` | `AGENTS.md` | [configuración](docs/kiro-setup.md) | | Factory Droid | `~/.factory/skills` | `AGENTS.md` | [configuración](docs/factory-droid-setup.md) | +| DeepSeek Harness (`dsh`) | `~/.dsh/skills` | `~/.agents/skills`, `AGENTS.md` | [configuración](docs/dsh-setup.md) | -Kiro y Factory Droid también registran `/brooks-review` automáticamente. ¿Nuevo en los skills, o usas un -agente que no aparece aquí? Consulta **[docs/getting-started.md](docs/getting-started.md)**. +Kiro, Factory Droid y DeepSeek Harness también registran `/brooks-review` automáticamente. ¿Nuevo en los +skills, o usas un agente que no aparece aquí? Consulta **[docs/getting-started.md](docs/getting-started.md)**. -> **🧪 Estado de verificación.** Claude Code, Gemini CLI y Codex CLI están verificados por el mantenedor. Las ocho +> **🧪 Estado de verificación.** Claude Code, Gemini CLI y Codex CLI están verificados por el mantenedor. Las nueve > plataformas anteriores están documentadas a partir de la especificación oficial de skills de cada herramienta y verificadas a nivel > de diseño de archivos (el instalador está probado), pero el mantenedor aún no las ha ejecutado de extremo a extremo en cada plataforma. ¿Probaste > alguna — funciona **o** está rota? [Abre un issue](https://github.com/hyhmrright/brooks-lint/issues/new) con @@ -322,10 +323,11 @@ agente que no aparece aquí? Consulta **[docs/getting-started.md](docs/getting-s **Sintaxis por plataforma.** Claude Code también acepta la forma con espacio de nombres `/brooks-lint:brooks-review` — las formas cortas las instala el hook session-start al iniciar la primera -sesión. Codex CLI usa `$brooks-review`. Gemini CLI usa la tabla tal cual. OpenCode, Cursor, Antigravity y pi -invocan los Agent Skills desde la `description` de cada skill, así que basta con pedirlo ("revisa este PR", -"¿dónde está nuestra peor deuda técnica?"); para invocarlos explícitamente usa la sintaxis propia de cada -plataforma (pi registra cada skill como `/skill:brooks-review`). En todas las plataformas los skills también +sesión. Codex CLI usa `$brooks-review`. Gemini CLI usa la tabla tal cual. OpenCode, Cursor, Antigravity, pi y +DeepSeek Harness invocan los Agent Skills desde la `description` de cada skill, así que basta con pedirlo +("revisa este PR", "¿dónde está nuestra peor deuda técnica?"); para invocarlos explícitamente usa la sintaxis +propia de cada plataforma (pi registra cada skill como `/skill:brooks-review`; dsh usa la tabla tal cual, desde +su menú `/` o escrito a mano). En todas las plataformas los skills también se activan solos cuando hablas de calidad de código, arquitectura o salud de las pruebas. > Las revisiones de PR incluyen automáticamente una comprobación rápida de pruebas (Step 7, ligera; se omite @@ -448,6 +450,18 @@ La action publica la revisión como un comentario del PR y, opcionalmente, hace `fail-on-regression` lee `.brooks-lint-history.json`, así que confirma ese archivo para imponer "sin nuevas regresiones". Definir `sarif-file` hace que los hallazgos aparezcan en línea en la pestaña **Files changed** del PR y requiere el permiso `security-events: write` en el job. +**Endpoint de API personalizado.** `api-base-url` apunta la action a cualquier endpoint `/v1/messages` compatible con Anthropic —un proxy autoalojado, una pasarela de LLM, un espejo regional— en lugar de `api.anthropic.com`. Pasa la clave de ese endpoint como `anthropic-api-key` y el id de modelo que espera como `model`: + +```yaml + with: + mode: review + api-base-url: https://your-gateway.example.com + anthropic-api-key: ${{ secrets.GATEWAY_API_KEY }} + model: gateway-model-id +``` + +brooks-lint envía tu diff al host que indiques aquí, así que apúntalo solo a uno en el que confíes con tu código fuente. Ejecutar `scripts/ci-review.mjs` por tu cuenta no necesita ninguna opción: el SDK de Anthropic lee `ANTHROPIC_BASE_URL` directamente. + **Coste:** ~$0,05–0,15 por ejecución de PR, según el tamaño del diff y el modelo. Se recomienda ejecutar solo en eventos `pull_request`. ## Hoja de ruta @@ -486,7 +500,7 @@ síntesis de sus ideas, aplicada a la evaluación moderna de la calidad del cód ## Historial de estrellas -[![Star History Chart](https://api.star-history.com/svg?repos=hyhmrright/brooks-lint&type=Date)](https://star-history.com/#hyhmrright/brooks-lint&Date) +[![Star History](assets/star-history.svg)](https://github.com/hyhmrright/brooks-lint/stargazers) --- diff --git a/brooks-lint/README.ja.md b/brooks-lint/README.ja.md index 83fe5bc0..7209819c 100644 --- a/brooks-lint/README.ja.md +++ b/brooks-lint/README.ja.md @@ -27,7 +27,7 @@

- Version + Version MIT License Claude Code Plugin Codex CLI Skill @@ -78,7 +78,7 @@ curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts `/brooks-health`、`/brooks-sweep`([それぞれの機能](#スラッシュコマンド))。 すべての指摘は **症状 → 根源 → 結果 → 対策** の形式で、書籍の出典と 0〜100 の健全性スコアとともに -返されます。完全なインストール方法(さらに 8 つのプラットフォーム)と CI/CD のセットアップは +返されます。完全なインストール方法(さらに 9 つのプラットフォーム)と CI/CD のセットアップは [以下](#インストール)を参照してください。 ## 十二冊の書籍 @@ -273,7 +273,7 @@ Install the brooks-lint skill from hyhmrright/brooks-lint # Codex セッ または下記のインストーラーを使用:`./scripts/install.sh gemini` / `./scripts/install.sh codex`。 -### その他すべてのプラットフォーム — OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid +### その他すべてのプラットフォーム — OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid · DeepSeek Harness brooks-lint は標準的な [Agent Skills](https://agentskills.io) として配布されています。**Agent Skills を読み込むエージェントなら、どれも変換なしで六つすべてのモードを実行できます**——1 つのコマンドでインストールできます: @@ -281,7 +281,7 @@ Skills を読み込むエージェントなら、どれも変換なしで六つ ```bash # プラットフォームを選択;--project はグローバル設定ではなく現在のリポジトリにインストール curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts/install.sh | bash -s -- -# = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · gemini · codex · agents +# = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · dsh · gemini · codex · agents ``` インストーラーはスキルをあなたのプラットフォームに適したフォルダへ**フラット**にコピーするため、共有フレームワーク @@ -299,11 +299,12 @@ curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts | GitHub Copilot | `.github/skills`(`--project`) | `.claude/skills`、`AGENTS.md` | [設定](docs/copilot-setup.md) | | Kiro(AWS) | `~/.kiro/skills` | `AGENTS.md` | [設定](docs/kiro-setup.md) | | Factory Droid | `~/.factory/skills` | `AGENTS.md` | [設定](docs/factory-droid-setup.md) | +| DeepSeek Harness(`dsh`) | `~/.dsh/skills` | `~/.agents/skills`、`AGENTS.md` | [設定](docs/dsh-setup.md) | -Kiro と Factory Droid は `/brooks-review` も自動登録します。スキルが初めて、または上記にないエージェントを -お使いですか? **[docs/getting-started.md](docs/getting-started.md)** を参照してください。 +Kiro、Factory Droid、DeepSeek Harness は `/brooks-review` も自動登録します。スキルが初めて、または +上記にないエージェントをお使いですか? **[docs/getting-started.md](docs/getting-started.md)** を参照してください。 -> **🧪 検証状況。** Claude Code、Gemini CLI、Codex CLI はメンテナーによって検証済みです。上記の八つの +> **🧪 検証状況。** Claude Code、Gemini CLI、Codex CLI はメンテナーによって検証済みです。上記の九つの > プラットフォームは各ツールの公式スキル仕様から文書化され、ファイルレイアウトのレベルで検証されています > (インストーラーはテスト済み)が、メンテナーがすべてのプラットフォームでエンドツーエンドに実行したわけ > ではまだありません。どれかを試した——動いた **または** 壊れた? プラットフォーム、バージョン、見たこと @@ -323,10 +324,11 @@ Kiro と Factory Droid は `/brooks-review` も自動登録します。スキル **プラットフォーム別の構文。** Claude Code は名前空間付きの完全形 `/brooks-lint:brooks-review` も受け付けます ——短縮形は session-start フックが最初のセッション開始時に自動インストールします。Codex CLI は -`$brooks-review`。Gemini CLI は上の表のとおり。OpenCode、Cursor、Antigravity、pi は各スキルの -`description` から Agent Skills を呼び出すので、話しかけるだけで十分です(「この PR をレビューして」 +`$brooks-review`。Gemini CLI は上の表のとおり。OpenCode、Cursor、Antigravity、pi、DeepSeek Harness は +各スキルの `description` から Agent Skills を呼び出すので、話しかけるだけで十分です(「この PR をレビューして」 「最悪の技術的負債はどこ?」)。明示的に呼び出す場合は各プラットフォームの構文を使います(pi は各スキルを -`/skill:brooks-review` として登録)。どのプラットフォームでも、コード品質・アーキテクチャ・テストの健全性に +`/skill:brooks-review` として登録。dsh は上の表のとおりで、`/` メニューから選ぶか直接入力)。どの +プラットフォームでも、コード品質・アーキテクチャ・テストの健全性に ついて話すと、スキルは自動的にトリガーされます。 > PR レビューには軽量な Step 7 クイックテストチェックが自動的に含まれます(ドキュメントのみの diff では @@ -448,6 +450,18 @@ jobs: `fail-on-regression` は `.brooks-lint-history.json` を読み取るため、そのファイルをコミットすれば「新たな回帰なし」を強制できます。`sarif-file` を設定すると、指摘が PR の **Files changed** タブにインラインで表示されるようになり、ジョブに `security-events: write` 権限が必要になります。 +**カスタム API エンドポイント。** `api-base-url` を指定すると、action は `api.anthropic.com` ではなく Anthropic 互換の `/v1/messages` エンドポイント(自前のプロキシ、LLM ゲートウェイ、リージョンミラーなど)を呼び出します。そのエンドポイントのキーを `anthropic-api-key` に、期待されるモデル id を `model` に渡してください: + +```yaml + with: + mode: review + api-base-url: https://your-gateway.example.com + anthropic-api-key: ${{ secrets.GATEWAY_API_KEY }} + model: gateway-model-id +``` + +brooks-lint はここで指定したホストに diff を送信するため、ソースコードを預けられる相手だけを指定してください。`scripts/ci-review.mjs` を自分で実行する場合はフラグは不要です — Anthropic SDK が `ANTHROPIC_BASE_URL` を直接読み取ります。 + **コスト:** PR 実行ごとにおよそ $0.05〜0.15、diff のサイズとモデルによります。`pull_request` イベントのみで実行することを推奨します。 ## ロードマップ @@ -486,7 +500,7 @@ MIT License — 詳細は [LICENSE](LICENSE) を参照してください。 ## スター履歴 -[![Star History Chart](https://api.star-history.com/svg?repos=hyhmrright/brooks-lint&type=Date)](https://star-history.com/#hyhmrright/brooks-lint&Date) +[![Star History](assets/star-history.svg)](https://github.com/hyhmrright/brooks-lint/stargazers) --- diff --git a/brooks-lint/README.ko.md b/brooks-lint/README.ko.md index 3a29399f..10341590 100644 --- a/brooks-lint/README.ko.md +++ b/brooks-lint/README.ko.md @@ -27,7 +27,7 @@

- Version + Version MIT License Claude Code Plugin Codex CLI Skill @@ -78,7 +78,7 @@ curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts `/brooks-sweep`([각각 하는 일](#슬래시-명령)). 모든 진단은 도서 출처와 0–100 건강 점수와 함께 **증상 → 근원 → 결과 → 처방** 형태로 돌아옵니다. 전체 -설치 옵션(추가 8개 플랫폼)과 CI/CD 설정은 [아래](#설치)를 참고하세요. +설치 옵션(추가 9개 플랫폼)과 CI/CD 설정은 [아래](#설치)를 참고하세요. ## 열두 권의 책 @@ -272,7 +272,7 @@ Install the brooks-lint skill from hyhmrright/brooks-lint # Codex 세션 또는 아래 설치기를 사용하세요: `./scripts/install.sh gemini` / `./scripts/install.sh codex`. -### 그 밖의 모든 플랫폼 — OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid +### 그 밖의 모든 플랫폼 — OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid · DeepSeek Harness brooks-lint는 표준 [Agent Skills](https://agentskills.io) 형태로 배포됩니다. **Agent Skills를 로드하는 모든 에이전트는 변환 없이 여섯 가지 모드를 모두 실행합니다** — 한 줄의 명령으로 설치됩니다: @@ -280,7 +280,7 @@ Skills를 로드하는 모든 에이전트는 변환 없이 여섯 가지 모드 ```bash # 플랫폼을 고르세요; --project는 전역 설정 대신 현재 저장소에 설치합니다 curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts/install.sh | bash -s -- -# = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · gemini · codex · agents +# = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · dsh · gemini · codex · agents ``` 설치기는 스킬을 당신의 플랫폼에 맞는 폴더로 **평평하게** 복사하므로, 공유 프레임워크(`../_shared/`)가 @@ -297,12 +297,13 @@ curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts | GitHub Copilot | `.github/skills`(`--project`) | `.claude/skills`, `AGENTS.md` | [설정](docs/copilot-setup.md) | | Kiro (AWS) | `~/.kiro/skills` | `AGENTS.md` | [설정](docs/kiro-setup.md) | | Factory Droid | `~/.factory/skills` | `AGENTS.md` | [설정](docs/factory-droid-setup.md) | +| DeepSeek Harness (`dsh`) | `~/.dsh/skills` | `~/.agents/skills`, `AGENTS.md` | [설정](docs/dsh-setup.md) | -Kiro와 Factory Droid는 `/brooks-review`도 자동 등록합니다. 스킬이 처음이거나 위 목록에 없는 에이전트를 -쓰시나요? **[docs/getting-started.md](docs/getting-started.md)**를 참고하세요. +Kiro, Factory Droid, DeepSeek Harness는 `/brooks-review`도 자동 등록합니다. 스킬이 처음이거나 위 +목록에 없는 에이전트를 쓰시나요? **[docs/getting-started.md](docs/getting-started.md)**를 참고하세요. > **🧪 검증 상태.** Claude Code, Gemini CLI, Codex CLI는 메인테이너가 검증했습니다. 위 -> 여덟 개 플랫폼은 각 도구의 공식 스킬 명세를 토대로 문서화되었고 파일 레이아웃 +> 아홉 개 플랫폼은 각 도구의 공식 스킬 명세를 토대로 문서화되었고 파일 레이아웃 > 수준에서 검증되었으나(설치기는 테스트되었음), 메인테이너가 모든 플랫폼에서 end-to-end로 직접 실행해 보지는 > 못했습니다. 어떤 것을 시도해 보셨나요 — 잘 되든 **안 되든**? 플랫폼, 버전, 본 결과를 담아 > [이슈를 열어 주세요](https://github.com/hyhmrright/brooks-lint/issues/new). @@ -322,9 +323,10 @@ Kiro와 Factory Droid는 `/brooks-review`도 자동 등록합니다. 스킬이 **플랫폼별 문법.** Claude Code는 네임스페이스가 붙은 전체 형식 `/brooks-lint:brooks-review`도 받습니다 — 짧은 형식은 session-start 훅이 첫 세션 시작 시 자동 설치합니다. Codex CLI는 `$brooks-review`를 씁니다. -Gemini CLI는 위 표 그대로입니다. OpenCode, Cursor, Antigravity, pi는 각 스킬의 `description`에서 Agent -Skills를 호출하므로 그냥 요청하면 됩니다("이 PR을 리뷰해줘", "우리 최악의 기술 부채는 어디야?"). 명시적 -호출이 필요하면 각 플랫폼의 문법을 쓰세요(pi는 각 스킬을 `/skill:brooks-review`로 등록). 모든 +Gemini CLI는 위 표 그대로입니다. OpenCode, Cursor, Antigravity, pi, DeepSeek Harness는 각 스킬의 +`description`에서 Agent Skills를 호출하므로 그냥 요청하면 됩니다("이 PR을 리뷰해줘", "우리 최악의 기술 +부채는 어디야?"). 명시적 호출이 필요하면 각 플랫폼의 문법을 쓰세요(pi는 각 스킬을 +`/skill:brooks-review`로 등록; dsh는 위 표 그대로이며 `/` 메뉴에서 고르거나 직접 입력). 모든 플랫폼에서 코드 품질, 아키텍처, 테스트 건강을 이야기하면 스킬이 자동으로 트리거됩니다. > PR 리뷰에는 가벼운 Step 7 빠른 테스트 점검이 자동으로 포함됩니다(문서만 바뀐 diff에서는 건너뜀). @@ -446,6 +448,18 @@ jobs: `fail-on-regression`은 `.brooks-lint-history.json`을 읽으므로, "새로운 회귀 없음"을 강제하려면 그 파일을 커밋하세요. `sarif-file`을 설정하면 진단이 PR의 **Files changed** 탭에 인라인으로 나타나며, job에 `security-events: write` 권한이 필요합니다. +**사용자 지정 API 엔드포인트.** `api-base-url`을 지정하면 action이 `api.anthropic.com` 대신 Anthropic 호환 `/v1/messages` 엔드포인트(자체 호스팅 프록시, LLM 게이트웨이, 리전 미러)를 호출합니다. 해당 엔드포인트의 키를 `anthropic-api-key`로, 기대하는 모델 id를 `model`로 전달하세요: + +```yaml + with: + mode: review + api-base-url: https://your-gateway.example.com + anthropic-api-key: ${{ secrets.GATEWAY_API_KEY }} + model: gateway-model-id +``` + +brooks-lint는 여기에 지정한 호스트로 diff를 전송하므로, 소스 코드를 맡겨도 되는 곳만 지정하세요. `scripts/ci-review.mjs`를 직접 실행할 때는 플래그가 필요 없습니다 — Anthropic SDK가 `ANTHROPIC_BASE_URL`을 직접 읽습니다. + **비용:** PR 실행당 약 $0.05–0.15로, diff 크기와 모델에 따라 다릅니다. `pull_request` 이벤트에서만 실행할 것을 권장합니다. ## 로드맵 @@ -484,7 +498,7 @@ MIT License — 자세한 내용은 [LICENSE](LICENSE)를 참고하세요. ## Star 히스토리 -[![Star History Chart](https://api.star-history.com/svg?repos=hyhmrright/brooks-lint&type=Date)](https://star-history.com/#hyhmrright/brooks-lint&Date) +[![Star History](assets/star-history.svg)](https://github.com/hyhmrright/brooks-lint/stargazers) --- diff --git a/brooks-lint/README.md b/brooks-lint/README.md index d17c28d9..f83c4271 100644 --- a/brooks-lint/README.md +++ b/brooks-lint/README.md @@ -27,7 +27,7 @@

- Version + Version MIT License Claude Code Plugin Codex CLI Skill @@ -78,7 +78,7 @@ Then just ask ("review this PR", "audit the architecture"), or run one of the si ([what each one does](#slash-commands)). Every finding comes back as **Symptom → Source → Consequence → Remedy** with a book citation and a -0–100 Health Score. Full install options (8 more platforms) and CI/CD setup are [below](#installation). +0–100 Health Score. Full install options (9 more platforms) and CI/CD setup are [below](#installation). ## The Twelve Books @@ -272,7 +272,7 @@ Install the brooks-lint skill from hyhmrright/brooks-lint # ask inside a C Or use the installer below: `./scripts/install.sh gemini` / `./scripts/install.sh codex`. -### Every other platform — OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid +### Every other platform — OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid · DeepSeek Harness brooks-lint ships as standard [Agent Skills](https://agentskills.io). **Any agent that loads Agent Skills runs all six modes with no conversion** — one command installs them: @@ -280,7 +280,7 @@ Skills runs all six modes with no conversion** — one command installs them: ```bash # pick your platform; --project installs into the current repo instead of your global config curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts/install.sh | bash -s -- -# = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · gemini · codex · agents +# = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · dsh · gemini · codex · agents ``` The installer copies the skills **flat** into the right folder, so the shared framework @@ -297,12 +297,13 @@ The installer copies the skills **flat** into the right folder, so the shared fr | GitHub Copilot | `.github/skills` (`--project`) | `.claude/skills`, `AGENTS.md` | [setup](docs/copilot-setup.md) | | Kiro (AWS) | `~/.kiro/skills` | `AGENTS.md` | [setup](docs/kiro-setup.md) | | Factory Droid | `~/.factory/skills` | `AGENTS.md` | [setup](docs/factory-droid-setup.md) | +| DeepSeek Harness (`dsh`) | `~/.dsh/skills` | `~/.agents/skills`, `AGENTS.md` | [setup](docs/dsh-setup.md) | -Kiro and Factory Droid also auto-register `/brooks-review`. New to skills, or using an agent not -listed? See **[docs/getting-started.md](docs/getting-started.md)**. +Kiro, Factory Droid, and DeepSeek Harness also auto-register `/brooks-review`. New to skills, or +using an agent not listed? See **[docs/getting-started.md](docs/getting-started.md)**. > **🧪 Verification status.** Claude Code, Gemini CLI, and Codex CLI are maintainer-verified. The -> eight platforms above are documented from each tool's official skill spec and verified at the +> nine platforms above are documented from each tool's official skill spec and verified at the > file-layout level (the installer is tested), but not yet run end-to-end by the maintainer on every > platform. Tried one — working **or** broken? > [Open an issue](https://github.com/hyhmrright/brooks-lint/issues/new) with the platform, version, @@ -323,9 +324,10 @@ listed? See **[docs/getting-started.md](docs/getting-started.md)**. **Syntax by platform.** Claude Code also accepts the namespaced form `/brooks-lint:brooks-review` — short forms are auto-installed on first session start by the session-start hook. Codex CLI uses `$brooks-review`. Gemini CLI uses the table as written. -OpenCode, Cursor, Antigravity, and pi invoke Agent Skills from each skill's `description`, so -just ask ("review this PR", "where's our worst tech debt?"); for explicit invocation use the -platform's own syntax (pi registers each skill as `/skill:brooks-review`). On every platform the +OpenCode, Cursor, Antigravity, pi, and DeepSeek Harness invoke Agent Skills from each skill's +`description`, so just ask ("review this PR", "where's our worst tech debt?"); for explicit +invocation use the platform's own syntax (pi registers each skill as `/skill:brooks-review`; dsh +takes the table as written, from its `/` menu or typed inline). On every platform the skills also trigger automatically when you discuss code quality, architecture, or test health. > PR reviews include a lightweight Step 7 Quick Test Check automatically (skipped for docs-only @@ -448,6 +450,18 @@ The action posts the review as a PR comment and optionally fails the check if th `fail-on-regression` reads `.brooks-lint-history.json`, so commit that file to enforce "no new regressions". Setting `sarif-file` makes findings appear inline on the PR's **Files changed** tab and requires `security-events: write` permission on the job. +**Custom API endpoint.** `api-base-url` points the action at any Anthropic-compatible `/v1/messages` endpoint — a self-hosted proxy, an LLM gateway, a regional mirror — instead of `api.anthropic.com`. Pass that endpoint's key as `anthropic-api-key` and the model id it expects as `model`: + +```yaml + with: + mode: review + api-base-url: https://your-gateway.example.com + anthropic-api-key: ${{ secrets.GATEWAY_API_KEY }} + model: gateway-model-id +``` + +brooks-lint sends your diff to whatever host you name here, so only point it at one you trust with your source. Running `scripts/ci-review.mjs` yourself needs no flag at all — the Anthropic SDK reads `ANTHROPIC_BASE_URL` directly. + **Cost:** ~$0.05–0.15 per PR run depending on diff size and model. Recommend running on `pull_request` events only. ## Roadmap @@ -486,7 +500,7 @@ their ideas, applied to modern code quality assessment. ## Star History -[![Star History Chart](https://api.star-history.com/svg?repos=hyhmrright/brooks-lint&type=Date)](https://star-history.com/#hyhmrright/brooks-lint&Date) +[![Star History](assets/star-history.svg)](https://github.com/hyhmrright/brooks-lint/stargazers) --- diff --git a/brooks-lint/README.zh-CN.md b/brooks-lint/README.zh-CN.md index 35f406e4..c6a4e0d4 100644 --- a/brooks-lint/README.zh-CN.md +++ b/brooks-lint/README.zh-CN.md @@ -27,7 +27,7 @@

- Version + Version MIT License Claude Code Plugin Codex CLI Skill @@ -76,7 +76,7 @@ curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts 装好后直接开口("审查这个 PR""审计架构"),或运行六个命令之一——`/brooks-review`、`/brooks-audit`、 `/brooks-debt`、`/brooks-test`、`/brooks-health`、`/brooks-sweep`([各自的作用](#斜杠命令))。 -每条诊断都以 **症状 → 根源 → 后果 → 对策** 返回,附书目出处和 0–100 健康分。完整安装方式(另外 8 个 +每条诊断都以 **症状 → 根源 → 后果 → 对策** 返回,附书目出处和 0–100 健康分。完整安装方式(另外 9 个 平台)和 CI/CD 配置见[下文](#安装)。 ## 十二本书 @@ -270,7 +270,7 @@ Install the brooks-lint skill from hyhmrright/brooks-lint # 在 Codex 会 或使用下面的安装器:`./scripts/install.sh gemini` / `./scripts/install.sh codex`。 -### 其它所有平台——OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid +### 其它所有平台——OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid · DeepSeek Harness brooks-lint 以标准 [Agent Skills](https://agentskills.io) 形式分发。**任何加载 Agent Skills 的 agent 都能无需任何转换运行全部六种模式**——一条命令即可安装: @@ -278,7 +278,7 @@ brooks-lint 以标准 [Agent Skills](https://agentskills.io) 形式分发。** ```bash # 选择你的平台;加 --project 装进当前仓库而非全局配置 curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts/install.sh | bash -s -- <平台> -# <平台> = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · gemini · codex · agents +# <平台> = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · dsh · gemini · codex · agents ``` 安装器会把技能**扁平**拷进该平台对应的文件夹,让共享框架(`../_shared/`)始终正确解析——你不可能装错布局。 @@ -294,11 +294,12 @@ curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts | GitHub Copilot | `.github/skills`(`--project`) | `.claude/skills`、`AGENTS.md` | [配置](docs/copilot-setup.md) | | Kiro(AWS) | `~/.kiro/skills` | `AGENTS.md` | [配置](docs/kiro-setup.md) | | Factory Droid | `~/.factory/skills` | `AGENTS.md` | [配置](docs/factory-droid-setup.md) | +| DeepSeek Harness(`dsh`) | `~/.dsh/skills` | `~/.agents/skills`、`AGENTS.md` | [配置](docs/dsh-setup.md) | -Kiro 与 Factory Droid 还会自动注册 `/brooks-review`。不熟悉 skills、或用的是上面没列出的 agent? -见 **[docs/getting-started.md](docs/getting-started.md)**。 +Kiro、Factory Droid 与 DeepSeek Harness 还会自动注册 `/brooks-review`。不熟悉 skills、或用的是上面 +没列出的 agent?见 **[docs/getting-started.md](docs/getting-started.md)**。 -> **🧪 验证状态。** Claude Code、Gemini CLI、Codex CLI 已由维护者验证。上面八个平台依据各工具官方技能规范编写, +> **🧪 验证状态。** Claude Code、Gemini CLI、Codex CLI 已由维护者验证。上面九个平台依据各工具官方技能规范编写, > 并已在文件布局层面验证(安装器经过测试),但维护者尚未在每个平台端到端实跑。在某平台试过了——无论成功**还是**失败? > 请[提一个 issue](https://github.com/hyhmrright/brooks-lint/issues/new),附上平台、版本和你看到的结果。 > 用的是其它兼容 Agent Skills 的 agent?它几乎肯定以同样方式工作——告诉我们,我们会补上。 @@ -316,9 +317,10 @@ Kiro 与 Factory Droid 还会自动注册 `/brooks-review`。不熟悉 skills、 **各平台语法。** Claude Code 也接受带命名空间的完整形式 `/brooks-lint:brooks-review`——短命令由 session-start 钩子在首次会话启动时自动安装。Codex CLI 用 `$brooks-review`。Gemini CLI 直接用上表。 -OpenCode、Cursor、Antigravity、pi 依据每个技能的 `description` 自动调用 Agent Skills,直接提问即可 -("审查这个 PR"、"我们最糟的技术债在哪");需要显式调用时用各平台自己的语法(pi 把每个技能注册为 -`/skill:brooks-review`)。在所有平台上,当你讨论代码质量、架构或测试健康时,这些技能也会自动触发。 +OpenCode、Cursor、Antigravity、pi、DeepSeek Harness 依据每个技能的 `description` 自动调用 Agent +Skills,直接提问即可("审查这个 PR"、"我们最糟的技术债在哪");需要显式调用时用各平台自己的语法 +(pi 把每个技能注册为 `/skill:brooks-review`;dsh 直接用上表,可从 `/` 菜单选或手打)。在所有平台上, +当你讨论代码质量、架构或测试健康时,这些技能也会自动触发。 > PR 审查会自动包含一个轻量的第 7 步快速测试检查(对纯文档 diff 会跳过)。需要完整的测试审查请用 > `/brooks-test`;需要某个维度的深度诊断时,请用该维度的专项技能,而不是 `/brooks-health`。 @@ -437,6 +439,18 @@ jobs: `fail-on-regression` 读取 `.brooks-lint-history.json`,因此提交该文件即可强制"无新增回归"。设置 `sarif-file` 会让诊断直接显示在 PR 的 **Files changed** 标签页,并需要 job 具备 `security-events: write` 权限。 +**自定义 API 端点。** `api-base-url` 让 action 改为调用任意 Anthropic 兼容的 `/v1/messages` 端点 —— 自建代理、LLM 网关或区域镜像 —— 而不是 `api.anthropic.com`。把该端点的密钥作为 `anthropic-api-key` 传入,把它期望的模型 id 作为 `model` 传入: + +```yaml + with: + mode: review + api-base-url: https://your-gateway.example.com + anthropic-api-key: ${{ secrets.GATEWAY_API_KEY }} + model: gateway-model-id +``` + +brooks-lint 会把你的 diff 发送到这里填写的主机,因此只应指向你信任其接触源码的一方。自己运行 `scripts/ci-review.mjs` 完全不需要参数 —— Anthropic SDK 会直接读取 `ANTHROPIC_BASE_URL`。 + **成本:** 每次 PR 运行约 $0.05–0.15,取决于 diff 大小和模型。建议仅在 `pull_request` 事件上运行。 ## 路线图 @@ -472,7 +486,7 @@ MIT License——详见 [LICENSE](LICENSE)。 ## Star 历史 -[![Star History Chart](https://api.star-history.com/svg?repos=hyhmrright/brooks-lint&type=Date)](https://star-history.com/#hyhmrright/brooks-lint&Date) +[![Star History](assets/star-history.svg)](https://github.com/hyhmrright/brooks-lint/stargazers) --- diff --git a/brooks-lint/README.zh-TW.md b/brooks-lint/README.zh-TW.md index 123a0d4e..a18df48c 100644 --- a/brooks-lint/README.zh-TW.md +++ b/brooks-lint/README.zh-TW.md @@ -27,7 +27,7 @@

- Version + Version MIT License Claude Code Plugin Codex CLI Skill @@ -76,7 +76,7 @@ curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts 裝好後直接開口(「審查這個 PR」「稽核架構」),或執行六個命令之一——`/brooks-review`、`/brooks-audit`、 `/brooks-debt`、`/brooks-test`、`/brooks-health`、`/brooks-sweep`([各自的作用](#斜線命令))。 -每條診斷都以 **症狀 → 根源 → 後果 → 對策** 回傳,附書目出處和 0–100 健康分。完整安裝方式(另外 8 個 +每條診斷都以 **症狀 → 根源 → 後果 → 對策** 回傳,附書目出處和 0–100 健康分。完整安裝方式(另外 9 個 平台)和 CI/CD 設定見[下文](#安裝)。 ## 十二本書 @@ -270,7 +270,7 @@ Install the brooks-lint skill from hyhmrright/brooks-lint # 在 Codex 工 或使用下面的安裝器:`./scripts/install.sh gemini` / `./scripts/install.sh codex`。 -### 其他所有平台——OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid +### 其他所有平台——OpenCode · Cursor · Windsurf · Antigravity · pi · Copilot · Kiro · Factory Droid · DeepSeek Harness brooks-lint 以標準 [Agent Skills](https://agentskills.io) 形式散布。**任何載入 Agent Skills 的 agent 都能無需任何轉換執行全部六種模式**——一條命令即可安裝: @@ -278,7 +278,7 @@ brooks-lint 以標準 [Agent Skills](https://agentskills.io) 形式散布。** ```bash # 選擇你的平台;加 --project 裝進當前儲存庫而非全域設定 curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts/install.sh | bash -s -- <平台> -# <平台> = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · gemini · codex · agents +# <平台> = opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · dsh · gemini · codex · agents ``` 安裝器會把技能**扁平**複製進該平台對應的資料夾,讓共享框架(`../_shared/`)始終正確解析——你不可能裝錯佈局。 @@ -294,11 +294,12 @@ curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts | GitHub Copilot | `.github/skills`(`--project`) | `.claude/skills`、`AGENTS.md` | [設定](docs/copilot-setup.md) | | Kiro(AWS) | `~/.kiro/skills` | `AGENTS.md` | [設定](docs/kiro-setup.md) | | Factory Droid | `~/.factory/skills` | `AGENTS.md` | [設定](docs/factory-droid-setup.md) | +| DeepSeek Harness(`dsh`) | `~/.dsh/skills` | `~/.agents/skills`、`AGENTS.md` | [設定](docs/dsh-setup.md) | -Kiro 與 Factory Droid 還會自動註冊 `/brooks-review`。不熟悉 skills、或用的是上面沒列出的 agent? -見 **[docs/getting-started.md](docs/getting-started.md)**。 +Kiro、Factory Droid 與 DeepSeek Harness 還會自動註冊 `/brooks-review`。不熟悉 skills、或用的是上面 +沒列出的 agent?見 **[docs/getting-started.md](docs/getting-started.md)**。 -> **🧪 驗證狀態。** Claude Code、Gemini CLI、Codex CLI 已由維護者驗證。上面八個平台依據各工具官方技能規範撰寫, +> **🧪 驗證狀態。** Claude Code、Gemini CLI、Codex CLI 已由維護者驗證。上面九個平台依據各工具官方技能規範撰寫, > 並已在檔案佈局層面驗證(安裝器經過測試),但維護者尚未在每個平台端到端實跑。在某平台試過了——無論成功**還是**失敗? > 請[提一個 issue](https://github.com/hyhmrright/brooks-lint/issues/new),附上平台、版本和你看到的結果。 > 用的是其他相容 Agent Skills 的 agent?它幾乎肯定以同樣方式運作——告訴我們,我們會補上。 @@ -316,9 +317,10 @@ Kiro 與 Factory Droid 還會自動註冊 `/brooks-review`。不熟悉 skills、 **各平台語法。** Claude Code 也接受帶命名空間的完整形式 `/brooks-lint:brooks-review`——短命令由 session-start 鉤子在首次工作階段啟動時自動安裝。Codex CLI 用 `$brooks-review`。Gemini CLI 直接用上表。 -OpenCode、Cursor、Antigravity、pi 依據每個技能的 `description` 自動呼叫 Agent Skills,直接提問即可 -(「審查這個 PR」、「我們最糟的技術債在哪」);需要顯式呼叫時用各平台自己的語法(pi 把每個技能註冊為 -`/skill:brooks-review`)。在所有平台上,當你討論程式碼品質、架構或測試健康時,這些技能也會自動觸發。 +OpenCode、Cursor、Antigravity、pi、DeepSeek Harness 依據每個技能的 `description` 自動呼叫 Agent +Skills,直接提問即可(「審查這個 PR」、「我們最糟的技術債在哪」);需要顯式呼叫時用各平台自己的語法 +(pi 把每個技能註冊為 `/skill:brooks-review`;dsh 直接用上表,可從 `/` 選單挑或手打)。在所有平台上, +當你討論程式碼品質、架構或測試健康時,這些技能也會自動觸發。 > PR 審查會自動包含一個輕量的第 7 步快速測試檢查(對純文件 diff 會跳過)。需要完整的測試稽核請用 > `/brooks-test`;需要某個維度的深度診斷時,請用該維度的專項技能,而不是 `/brooks-health`。 @@ -437,6 +439,18 @@ jobs: `fail-on-regression` 讀取 `.brooks-lint-history.json`,因此提交該檔案即可強制「無新增回歸」。設定 `sarif-file` 會讓診斷直接顯示在 PR 的 **Files changed** 分頁,並需要 job 具備 `security-events: write` 權限。 +**自訂 API 端點。** `api-base-url` 讓 action 改為呼叫任意 Anthropic 相容的 `/v1/messages` 端點 —— 自建代理、LLM 閘道或區域鏡像 —— 而不是 `api.anthropic.com`。把該端點的金鑰作為 `anthropic-api-key` 傳入,把它預期的模型 id 作為 `model` 傳入: + +```yaml + with: + mode: review + api-base-url: https://your-gateway.example.com + anthropic-api-key: ${{ secrets.GATEWAY_API_KEY }} + model: gateway-model-id +``` + +brooks-lint 會把你的 diff 傳送到這裡填寫的主機,因此只應指向你信任其接觸原始碼的一方。自己執行 `scripts/ci-review.mjs` 完全不需要參數 —— Anthropic SDK 會直接讀取 `ANTHROPIC_BASE_URL`。 + **成本:** 每次 PR 執行約 $0.05–0.15,取決於 diff 大小和模型。建議僅在 `pull_request` 事件上執行。 ## 路線圖 @@ -472,7 +486,7 @@ MIT License——詳見 [LICENSE](LICENSE)。 ## Star 歷史 -[![Star History Chart](https://api.star-history.com/svg?repos=hyhmrright/brooks-lint&type=Date)](https://star-history.com/#hyhmrright/brooks-lint&Date) +[![Star History](assets/star-history.svg)](https://github.com/hyhmrright/brooks-lint/stargazers) --- diff --git a/brooks-lint/SOURCE.md b/brooks-lint/SOURCE.md index cf23c268..ab5ece00 100644 --- a/brooks-lint/SOURCE.md +++ b/brooks-lint/SOURCE.md @@ -1,8 +1,8 @@ # Source - Repo: https://github.com/hyhmrright/brooks-lint -- Ref: 814174cd5b340bc0d8b0161b6d8288980428a44d +- Ref: e9acf5c6100d2d786ed58f0fb7b9566a6218926a - Remove-Paths: -- Snapshot: 2026-08-12 +- Snapshot: 2026-08-24 - Sync-Mode: copy_skill_dirs - Notes: vendored into playbook branch thirdparty/skill diff --git a/brooks-lint/assets/star-history.json b/brooks-lint/assets/star-history.json new file mode 100644 index 00000000..6fd8c553 --- /dev/null +++ b/brooks-lint/assets/star-history.json @@ -0,0 +1,1398 @@ +{ + "repo": "hyhmrright/brooks-lint", + "starredAt": [ + "2026-03-27T13:19:06Z", + "2026-03-28T01:08:24Z", + "2026-03-28T13:27:36Z", + "2026-03-28T15:36:18Z", + "2026-03-29T02:57:00Z", + "2026-03-31T09:52:26Z", + "2026-03-31T13:37:15Z", + "2026-04-01T01:49:10Z", + "2026-04-01T02:55:57Z", + "2026-04-02T01:43:43Z", + "2026-04-02T09:41:26Z", + "2026-04-02T15:14:20Z", + "2026-04-03T09:27:23Z", + "2026-04-03T09:36:36Z", + "2026-04-03T11:50:57Z", + "2026-04-03T18:20:42Z", + "2026-04-05T18:44:36Z", + "2026-04-06T05:43:40Z", + "2026-04-06T07:25:08Z", + "2026-04-07T05:45:43Z", + "2026-04-07T06:42:39Z", + "2026-04-08T06:35:35Z", + "2026-04-08T13:33:05Z", + "2026-04-08T16:58:05Z", + "2026-04-09T02:31:24Z", + "2026-04-09T03:03:07Z", + "2026-04-10T07:25:09Z", + "2026-04-10T10:18:53Z", + "2026-04-13T03:14:44Z", + "2026-04-13T13:02:36Z", + "2026-04-15T12:09:04Z", + "2026-04-16T03:50:11Z", + "2026-04-16T07:35:33Z", + "2026-04-16T08:35:56Z", + "2026-04-16T16:28:37Z", + "2026-04-18T01:07:28Z", + "2026-04-18T09:33:08Z", + "2026-04-18T13:43:17Z", + "2026-04-18T17:18:03Z", + "2026-04-19T12:20:11Z", + "2026-04-19T22:49:33Z", + "2026-04-20T03:01:30Z", + "2026-04-20T11:58:02Z", + "2026-04-21T03:28:54Z", + "2026-04-21T14:28:20Z", + "2026-04-21T16:32:36Z", + "2026-04-22T04:09:22Z", + "2026-04-22T07:37:08Z", + "2026-04-22T08:54:11Z", + "2026-04-23T04:33:43Z", + "2026-04-23T08:54:47Z", + "2026-04-23T10:35:24Z", + "2026-04-23T12:38:05Z", + "2026-04-23T14:21:25Z", + "2026-04-24T00:46:23Z", + "2026-04-24T01:16:57Z", + "2026-04-24T01:35:47Z", + "2026-04-24T12:06:40Z", + "2026-04-25T10:37:12Z", + "2026-04-25T15:43:58Z", + "2026-04-25T15:49:44Z", + "2026-04-26T00:51:24Z", + "2026-04-26T05:23:02Z", + "2026-04-26T12:19:16Z", + "2026-04-26T21:37:01Z", + "2026-04-26T22:21:08Z", + "2026-04-26T23:40:11Z", + "2026-04-27T01:39:05Z", + "2026-04-27T12:30:27Z", + "2026-04-27T14:30:12Z", + "2026-04-27T17:06:30Z", + "2026-04-27T17:57:45Z", + "2026-04-27T21:36:52Z", + "2026-04-27T22:38:49Z", + "2026-04-28T02:29:38Z", + "2026-04-28T05:19:11Z", + "2026-04-28T08:21:36Z", + "2026-04-28T14:22:52Z", + "2026-04-28T15:13:02Z", + "2026-04-28T20:39:42Z", + "2026-04-29T01:18:16Z", + "2026-04-29T03:08:10Z", + "2026-04-29T12:36:16Z", + "2026-04-29T20:32:59Z", + "2026-04-29T21:02:22Z", + "2026-04-29T23:32:38Z", + "2026-04-30T02:32:27Z", + "2026-04-30T05:56:21Z", + "2026-04-30T06:18:27Z", + "2026-04-30T08:14:10Z", + "2026-04-30T09:17:56Z", + "2026-04-30T13:48:50Z", + "2026-04-30T14:46:42Z", + "2026-05-01T01:06:56Z", + "2026-05-01T10:39:07Z", + "2026-05-02T14:45:26Z", + "2026-05-03T17:20:22Z", + "2026-05-03T18:37:50Z", + "2026-05-03T18:57:17Z", + "2026-05-03T19:58:38Z", + "2026-05-03T22:32:52Z", + "2026-05-04T13:53:56Z", + "2026-05-05T04:36:46Z", + "2026-05-05T05:43:17Z", + "2026-05-06T01:09:41Z", + "2026-05-06T04:36:44Z", + "2026-05-06T05:24:10Z", + "2026-05-06T07:14:44Z", + "2026-05-06T10:58:06Z", + "2026-05-06T12:09:13Z", + "2026-05-06T13:34:29Z", + "2026-05-07T01:57:16Z", + "2026-05-07T07:06:16Z", + "2026-05-07T13:46:52Z", + "2026-05-08T00:20:27Z", + "2026-05-08T09:44:44Z", + "2026-05-09T10:19:01Z", + "2026-05-09T15:14:28Z", + "2026-05-09T15:38:18Z", + "2026-05-10T01:48:03Z", + "2026-05-10T19:20:12Z", + "2026-05-11T06:48:27Z", + "2026-05-11T11:56:29Z", + "2026-05-12T15:13:51Z", + "2026-05-13T00:50:56Z", + "2026-05-13T01:13:57Z", + "2026-05-13T04:22:39Z", + "2026-05-13T11:56:48Z", + "2026-05-13T21:16:47Z", + "2026-05-14T04:04:04Z", + "2026-05-14T04:46:40Z", + "2026-05-14T09:23:49Z", + "2026-05-14T10:02:26Z", + "2026-05-14T23:30:30Z", + "2026-05-15T10:07:56Z", + "2026-05-15T16:59:59Z", + "2026-05-16T01:16:11Z", + "2026-05-16T06:30:16Z", + "2026-05-16T08:47:10Z", + "2026-05-16T14:09:22Z", + "2026-05-17T10:42:11Z", + "2026-05-17T17:29:47Z", + "2026-05-18T00:50:19Z", + "2026-05-18T11:57:24Z", + "2026-05-18T18:05:59Z", + "2026-05-18T18:34:27Z", + "2026-05-19T02:55:00Z", + "2026-05-19T03:23:28Z", + "2026-05-19T14:18:07Z", + "2026-05-19T14:49:30Z", + "2026-05-19T14:56:51Z", + "2026-05-20T14:55:37Z", + "2026-05-20T19:12:17Z", + "2026-05-21T02:51:05Z", + "2026-05-21T04:02:05Z", + "2026-05-21T06:40:26Z", + "2026-05-21T20:11:23Z", + "2026-05-21T23:01:41Z", + "2026-05-22T01:43:51Z", + "2026-05-22T07:31:27Z", + "2026-05-24T03:36:07Z", + "2026-05-24T10:24:49Z", + "2026-05-24T12:15:55Z", + "2026-05-25T00:23:19Z", + "2026-05-25T00:23:46Z", + "2026-05-25T04:34:44Z", + "2026-05-25T05:07:12Z", + "2026-05-25T20:42:56Z", + "2026-05-26T01:41:04Z", + "2026-05-26T06:37:12Z", + "2026-05-26T07:49:22Z", + "2026-05-26T13:39:23Z", + "2026-05-26T19:31:06Z", + "2026-05-27T01:52:43Z", + "2026-05-27T03:03:26Z", + "2026-05-27T07:01:14Z", + "2026-05-28T02:59:49Z", + "2026-05-28T09:01:19Z", + "2026-05-28T13:01:35Z", + "2026-05-29T14:18:24Z", + "2026-05-29T20:19:44Z", + "2026-05-30T09:14:29Z", + "2026-05-31T03:19:55Z", + "2026-06-01T12:47:11Z", + "2026-06-01T16:06:44Z", + "2026-06-01T18:13:01Z", + "2026-06-01T18:40:49Z", + "2026-06-02T01:38:32Z", + "2026-06-02T18:10:46Z", + "2026-06-03T03:51:49Z", + "2026-06-05T08:58:54Z", + "2026-06-06T03:11:07Z", + "2026-06-06T04:02:50Z", + "2026-06-06T14:53:20Z", + "2026-06-06T20:26:36Z", + "2026-06-07T05:31:32Z", + "2026-06-07T05:40:38Z", + "2026-06-07T05:47:48Z", + "2026-06-07T05:59:54Z", + "2026-06-07T06:06:27Z", + "2026-06-07T06:13:44Z", + "2026-06-07T06:14:09Z", + "2026-06-07T06:17:51Z", + "2026-06-07T06:22:14Z", + "2026-06-07T06:26:15Z", + "2026-06-07T06:29:27Z", + "2026-06-07T06:31:46Z", + "2026-06-07T06:33:03Z", + "2026-06-07T06:34:34Z", + "2026-06-07T06:34:40Z", + "2026-06-07T06:46:33Z", + "2026-06-07T06:47:50Z", + "2026-06-07T06:48:44Z", + "2026-06-07T06:49:53Z", + "2026-06-07T06:54:33Z", + "2026-06-07T06:57:01Z", + "2026-06-07T06:57:54Z", + "2026-06-07T06:58:28Z", + "2026-06-07T06:59:23Z", + "2026-06-07T06:59:35Z", + "2026-06-07T07:03:16Z", + "2026-06-07T07:04:45Z", + "2026-06-07T07:05:06Z", + "2026-06-07T07:09:54Z", + "2026-06-07T07:10:11Z", + "2026-06-07T07:11:58Z", + "2026-06-07T07:12:08Z", + "2026-06-07T07:13:56Z", + "2026-06-07T07:15:10Z", + "2026-06-07T07:15:51Z", + "2026-06-07T07:18:51Z", + "2026-06-07T07:19:23Z", + "2026-06-07T07:24:08Z", + "2026-06-07T07:25:51Z", + "2026-06-07T07:26:56Z", + "2026-06-07T07:28:31Z", + "2026-06-07T07:28:32Z", + "2026-06-07T07:28:48Z", + "2026-06-07T07:30:29Z", + "2026-06-07T07:31:28Z", + "2026-06-07T07:33:45Z", + "2026-06-07T07:36:11Z", + "2026-06-07T07:36:45Z", + "2026-06-07T07:37:48Z", + "2026-06-07T07:40:56Z", + "2026-06-07T07:44:05Z", + "2026-06-07T07:44:07Z", + "2026-06-07T07:45:28Z", + "2026-06-07T07:46:08Z", + "2026-06-07T07:46:12Z", + "2026-06-07T07:48:28Z", + "2026-06-07T07:48:36Z", + "2026-06-07T07:51:58Z", + "2026-06-07T07:52:21Z", + "2026-06-07T07:53:47Z", + "2026-06-07T07:58:01Z", + "2026-06-07T08:00:21Z", + "2026-06-07T08:02:31Z", + "2026-06-07T08:02:35Z", + "2026-06-07T08:03:51Z", + "2026-06-07T08:08:09Z", + "2026-06-07T08:09:32Z", + "2026-06-07T08:14:01Z", + "2026-06-07T08:17:09Z", + "2026-06-07T08:22:58Z", + "2026-06-07T08:24:12Z", + "2026-06-07T08:26:15Z", + "2026-06-07T08:27:33Z", + "2026-06-07T08:27:40Z", + "2026-06-07T08:30:16Z", + "2026-06-07T08:31:50Z", + "2026-06-07T08:33:33Z", + "2026-06-07T08:37:54Z", + "2026-06-07T08:40:59Z", + "2026-06-07T08:41:24Z", + "2026-06-07T08:42:09Z", + "2026-06-07T08:42:20Z", + "2026-06-07T08:42:57Z", + "2026-06-07T08:45:17Z", + "2026-06-07T08:45:48Z", + "2026-06-07T08:47:24Z", + "2026-06-07T08:48:06Z", + "2026-06-07T08:48:57Z", + "2026-06-07T08:49:16Z", + "2026-06-07T08:49:49Z", + "2026-06-07T08:50:48Z", + "2026-06-07T08:52:48Z", + "2026-06-07T08:56:37Z", + "2026-06-07T08:57:38Z", + "2026-06-07T08:59:16Z", + "2026-06-07T09:03:52Z", + "2026-06-07T09:05:57Z", + "2026-06-07T09:07:06Z", + "2026-06-07T09:09:42Z", + "2026-06-07T09:11:21Z", + "2026-06-07T09:16:07Z", + "2026-06-07T09:22:32Z", + "2026-06-07T09:25:39Z", + "2026-06-07T09:28:19Z", + "2026-06-07T09:28:27Z", + "2026-06-07T09:28:44Z", + "2026-06-07T09:31:00Z", + "2026-06-07T09:45:22Z", + "2026-06-07T09:47:55Z", + "2026-06-07T09:50:31Z", + "2026-06-07T09:52:36Z", + "2026-06-07T09:58:31Z", + "2026-06-07T09:59:21Z", + "2026-06-07T10:06:45Z", + "2026-06-07T10:08:43Z", + "2026-06-07T10:08:44Z", + "2026-06-07T10:13:47Z", + "2026-06-07T10:13:58Z", + "2026-06-07T10:18:48Z", + "2026-06-07T10:20:54Z", + "2026-06-07T10:22:24Z", + "2026-06-07T10:26:41Z", + "2026-06-07T10:26:57Z", + "2026-06-07T10:28:20Z", + "2026-06-07T10:31:46Z", + "2026-06-07T10:36:06Z", + "2026-06-07T10:36:34Z", + "2026-06-07T10:37:18Z", + "2026-06-07T10:37:22Z", + "2026-06-07T10:39:35Z", + "2026-06-07T10:41:00Z", + "2026-06-07T10:43:07Z", + "2026-06-07T10:44:16Z", + "2026-06-07T10:47:52Z", + "2026-06-07T10:48:25Z", + "2026-06-07T10:49:09Z", + "2026-06-07T10:50:11Z", + "2026-06-07T10:52:34Z", + "2026-06-07T10:52:36Z", + "2026-06-07T10:52:36Z", + "2026-06-07T10:56:08Z", + "2026-06-07T10:57:56Z", + "2026-06-07T10:59:51Z", + "2026-06-07T11:04:31Z", + "2026-06-07T11:08:08Z", + "2026-06-07T11:09:40Z", + "2026-06-07T11:10:18Z", + "2026-06-07T11:14:20Z", + "2026-06-07T11:15:45Z", + "2026-06-07T11:17:33Z", + "2026-06-07T11:19:38Z", + "2026-06-07T11:19:55Z", + "2026-06-07T11:20:48Z", + "2026-06-07T11:25:07Z", + "2026-06-07T11:26:12Z", + "2026-06-07T11:28:55Z", + "2026-06-07T11:30:47Z", + "2026-06-07T11:32:51Z", + "2026-06-07T11:32:51Z", + "2026-06-07T11:33:02Z", + "2026-06-07T11:33:27Z", + "2026-06-07T11:34:38Z", + "2026-06-07T11:40:32Z", + "2026-06-07T11:40:49Z", + "2026-06-07T11:42:27Z", + "2026-06-07T11:44:44Z", + "2026-06-07T11:44:53Z", + "2026-06-07T11:47:45Z", + "2026-06-07T11:51:38Z", + "2026-06-07T11:54:25Z", + "2026-06-07T11:55:47Z", + "2026-06-07T11:55:49Z", + "2026-06-07T11:57:42Z", + "2026-06-07T11:58:07Z", + "2026-06-07T11:58:37Z", + "2026-06-07T11:59:12Z", + "2026-06-07T11:59:57Z", + "2026-06-07T12:05:01Z", + "2026-06-07T12:06:34Z", + "2026-06-07T12:07:08Z", + "2026-06-07T12:08:44Z", + "2026-06-07T12:10:07Z", + "2026-06-07T12:10:12Z", + "2026-06-07T12:10:20Z", + "2026-06-07T12:11:45Z", + "2026-06-07T12:12:47Z", + "2026-06-07T12:14:03Z", + "2026-06-07T12:14:11Z", + "2026-06-07T12:15:24Z", + "2026-06-07T12:15:48Z", + "2026-06-07T12:17:11Z", + "2026-06-07T12:17:20Z", + "2026-06-07T12:17:36Z", + "2026-06-07T12:18:37Z", + "2026-06-07T12:19:13Z", + "2026-06-07T12:20:49Z", + "2026-06-07T12:22:30Z", + "2026-06-07T12:22:58Z", + "2026-06-07T12:24:38Z", + "2026-06-07T12:25:30Z", + "2026-06-07T12:25:59Z", + "2026-06-07T12:26:37Z", + "2026-06-07T12:27:10Z", + "2026-06-07T12:27:23Z", + "2026-06-07T12:28:10Z", + "2026-06-07T12:28:19Z", + "2026-06-07T12:30:50Z", + "2026-06-07T12:32:03Z", + "2026-06-07T12:32:15Z", + "2026-06-07T12:33:22Z", + "2026-06-07T12:33:32Z", + "2026-06-07T12:34:43Z", + "2026-06-07T12:35:37Z", + "2026-06-07T12:36:40Z", + "2026-06-07T12:44:25Z", + "2026-06-07T12:45:39Z", + "2026-06-07T12:45:53Z", + "2026-06-07T12:46:45Z", + "2026-06-07T12:47:00Z", + "2026-06-07T12:47:23Z", + "2026-06-07T12:49:01Z", + "2026-06-07T12:50:13Z", + "2026-06-07T12:51:40Z", + "2026-06-07T12:52:38Z", + "2026-06-07T12:54:26Z", + "2026-06-07T12:56:34Z", + "2026-06-07T12:56:45Z", + "2026-06-07T13:00:43Z", + "2026-06-07T13:02:25Z", + "2026-06-07T13:02:51Z", + "2026-06-07T13:07:13Z", + "2026-06-07T13:08:53Z", + "2026-06-07T13:11:51Z", + "2026-06-07T13:11:55Z", + "2026-06-07T13:12:19Z", + "2026-06-07T13:13:00Z", + "2026-06-07T13:14:41Z", + "2026-06-07T13:18:26Z", + "2026-06-07T13:20:41Z", + "2026-06-07T13:21:17Z", + "2026-06-07T13:21:23Z", + "2026-06-07T13:23:47Z", + "2026-06-07T13:25:19Z", + "2026-06-07T13:26:10Z", + "2026-06-07T13:26:19Z", + "2026-06-07T13:28:05Z", + "2026-06-07T13:31:41Z", + "2026-06-07T13:34:54Z", + "2026-06-07T13:35:01Z", + "2026-06-07T13:35:01Z", + "2026-06-07T13:43:10Z", + "2026-06-07T13:52:36Z", + "2026-06-07T13:53:16Z", + "2026-06-07T13:54:02Z", + "2026-06-07T13:54:48Z", + "2026-06-07T13:54:58Z", + "2026-06-07T13:57:23Z", + "2026-06-07T14:04:02Z", + "2026-06-07T14:09:23Z", + "2026-06-07T14:09:53Z", + "2026-06-07T14:12:20Z", + "2026-06-07T14:15:35Z", + "2026-06-07T14:15:39Z", + "2026-06-07T14:17:13Z", + "2026-06-07T14:17:33Z", + "2026-06-07T14:18:30Z", + "2026-06-07T14:19:12Z", + "2026-06-07T14:20:30Z", + "2026-06-07T14:20:41Z", + "2026-06-07T14:21:46Z", + "2026-06-07T14:22:36Z", + "2026-06-07T14:24:17Z", + "2026-06-07T14:24:28Z", + "2026-06-07T14:24:51Z", + "2026-06-07T14:27:16Z", + "2026-06-07T14:27:34Z", + "2026-06-07T14:30:21Z", + "2026-06-07T14:30:44Z", + "2026-06-07T14:34:37Z", + "2026-06-07T14:38:16Z", + "2026-06-07T14:38:24Z", + "2026-06-07T14:38:52Z", + "2026-06-07T14:41:34Z", + "2026-06-07T14:41:53Z", + "2026-06-07T14:42:01Z", + "2026-06-07T14:44:10Z", + "2026-06-07T14:47:27Z", + "2026-06-07T14:50:13Z", + "2026-06-07T14:50:40Z", + "2026-06-07T14:52:47Z", + "2026-06-07T14:53:41Z", + "2026-06-07T14:57:30Z", + "2026-06-07T14:58:06Z", + "2026-06-07T15:00:50Z", + "2026-06-07T15:04:49Z", + "2026-06-07T15:06:55Z", + "2026-06-07T15:07:04Z", + "2026-06-07T15:08:54Z", + "2026-06-07T15:09:19Z", + "2026-06-07T15:11:40Z", + "2026-06-07T15:11:41Z", + "2026-06-07T15:12:02Z", + "2026-06-07T15:17:34Z", + "2026-06-07T15:18:52Z", + "2026-06-07T15:23:45Z", + "2026-06-07T15:26:39Z", + "2026-06-07T15:29:40Z", + "2026-06-07T15:29:53Z", + "2026-06-07T15:30:04Z", + "2026-06-07T15:32:56Z", + "2026-06-07T15:33:48Z", + "2026-06-07T15:36:58Z", + "2026-06-07T15:37:39Z", + "2026-06-07T15:41:25Z", + "2026-06-07T15:41:25Z", + "2026-06-07T15:41:27Z", + "2026-06-07T15:41:51Z", + "2026-06-07T15:43:08Z", + "2026-06-07T15:44:17Z", + "2026-06-07T15:46:40Z", + "2026-06-07T15:50:56Z", + "2026-06-07T15:51:21Z", + "2026-06-07T15:53:05Z", + "2026-06-07T15:54:30Z", + "2026-06-07T15:55:49Z", + "2026-06-07T15:57:26Z", + "2026-06-07T15:58:39Z", + "2026-06-07T16:00:05Z", + "2026-06-07T16:03:03Z", + "2026-06-07T16:04:48Z", + "2026-06-07T16:05:04Z", + "2026-06-07T16:08:02Z", + "2026-06-07T16:08:15Z", + "2026-06-07T16:08:35Z", + "2026-06-07T16:10:04Z", + "2026-06-07T16:10:05Z", + "2026-06-07T16:11:59Z", + "2026-06-07T16:12:16Z", + "2026-06-07T16:13:09Z", + "2026-06-07T16:14:20Z", + "2026-06-07T16:14:47Z", + "2026-06-07T16:17:28Z", + "2026-06-07T16:17:29Z", + "2026-06-07T16:19:53Z", + "2026-06-07T16:20:53Z", + "2026-06-07T16:20:53Z", + "2026-06-07T16:21:56Z", + "2026-06-07T16:23:16Z", + "2026-06-07T16:25:34Z", + "2026-06-07T16:26:49Z", + "2026-06-07T16:26:52Z", + "2026-06-07T16:28:46Z", + "2026-06-07T16:29:35Z", + "2026-06-07T16:31:13Z", + "2026-06-07T16:32:26Z", + "2026-06-07T16:32:43Z", + "2026-06-07T16:33:40Z", + "2026-06-07T16:33:43Z", + "2026-06-07T16:37:35Z", + "2026-06-07T16:38:31Z", + "2026-06-07T16:39:45Z", + "2026-06-07T16:39:49Z", + "2026-06-07T16:39:52Z", + "2026-06-07T16:41:09Z", + "2026-06-07T16:42:59Z", + "2026-06-07T16:45:04Z", + "2026-06-07T16:46:08Z", + "2026-06-07T16:46:16Z", + "2026-06-07T16:48:51Z", + "2026-06-07T16:51:32Z", + "2026-06-07T16:52:42Z", + "2026-06-07T16:52:42Z", + "2026-06-07T16:57:08Z", + "2026-06-07T16:58:08Z", + "2026-06-07T16:58:20Z", + "2026-06-07T16:58:20Z", + "2026-06-07T17:00:40Z", + "2026-06-07T17:01:27Z", + "2026-06-07T17:01:46Z", + "2026-06-07T17:04:09Z", + "2026-06-07T17:04:37Z", + "2026-06-07T17:05:49Z", + "2026-06-07T17:08:46Z", + "2026-06-07T17:12:24Z", + "2026-06-07T17:16:18Z", + "2026-06-07T17:17:37Z", + "2026-06-07T17:18:20Z", + "2026-06-07T17:19:55Z", + "2026-06-07T17:21:33Z", + "2026-06-07T17:21:45Z", + "2026-06-07T17:23:53Z", + "2026-06-07T17:24:24Z", + "2026-06-07T17:26:51Z", + "2026-06-07T17:32:47Z", + "2026-06-07T17:32:49Z", + "2026-06-07T17:33:43Z", + "2026-06-07T17:36:32Z", + "2026-06-07T17:47:46Z", + "2026-06-07T17:48:35Z", + "2026-06-07T17:50:54Z", + "2026-06-07T17:52:31Z", + "2026-06-07T17:52:42Z", + "2026-06-07T17:53:30Z", + "2026-06-07T17:58:42Z", + "2026-06-07T18:00:00Z", + "2026-06-07T18:00:13Z", + "2026-06-07T18:06:29Z", + "2026-06-07T18:10:37Z", + "2026-06-07T18:10:44Z", + "2026-06-07T18:11:02Z", + "2026-06-07T18:33:55Z", + "2026-06-07T18:36:59Z", + "2026-06-07T18:42:41Z", + "2026-06-07T18:43:14Z", + "2026-06-07T18:44:12Z", + "2026-06-07T18:44:41Z", + "2026-06-07T18:46:37Z", + "2026-06-07T18:47:05Z", + "2026-06-07T18:52:25Z", + "2026-06-07T18:52:26Z", + "2026-06-07T18:56:44Z", + "2026-06-07T19:03:33Z", + "2026-06-07T19:05:45Z", + "2026-06-07T19:07:43Z", + "2026-06-07T19:23:49Z", + "2026-06-07T19:24:04Z", + "2026-06-07T19:32:27Z", + "2026-06-07T19:35:55Z", + "2026-06-07T19:46:14Z", + "2026-06-07T19:49:43Z", + "2026-06-07T19:59:43Z", + "2026-06-07T20:03:16Z", + "2026-06-07T20:14:50Z", + "2026-06-07T20:36:33Z", + "2026-06-07T20:39:56Z", + "2026-06-07T20:43:36Z", + "2026-06-07T20:48:10Z", + "2026-06-07T20:59:06Z", + "2026-06-07T21:29:21Z", + "2026-06-07T21:30:18Z", + "2026-06-07T21:37:37Z", + "2026-06-07T21:44:36Z", + "2026-06-07T21:45:21Z", + "2026-06-07T21:45:26Z", + "2026-06-07T22:03:01Z", + "2026-06-07T22:16:42Z", + "2026-06-07T22:25:34Z", + "2026-06-07T22:30:55Z", + "2026-06-07T22:32:19Z", + "2026-06-07T22:37:02Z", + "2026-06-07T22:40:38Z", + "2026-06-07T22:48:13Z", + "2026-06-07T22:52:27Z", + "2026-06-07T22:53:25Z", + "2026-06-07T23:08:32Z", + "2026-06-07T23:09:33Z", + "2026-06-07T23:20:14Z", + "2026-06-07T23:20:47Z", + "2026-06-07T23:23:39Z", + "2026-06-07T23:24:39Z", + "2026-06-07T23:28:35Z", + "2026-06-07T23:30:34Z", + "2026-06-07T23:40:37Z", + "2026-06-07T23:42:10Z", + "2026-06-07T23:44:11Z", + "2026-06-07T23:45:33Z", + "2026-06-07T23:47:17Z", + "2026-06-07T23:52:40Z", + "2026-06-07T23:53:10Z", + "2026-06-07T23:53:31Z", + "2026-06-08T00:05:06Z", + "2026-06-08T00:09:28Z", + "2026-06-08T00:14:11Z", + "2026-06-08T00:23:59Z", + "2026-06-08T00:25:40Z", + "2026-06-08T00:33:32Z", + "2026-06-08T00:33:42Z", + "2026-06-08T00:37:25Z", + "2026-06-08T00:37:46Z", + "2026-06-08T00:42:42Z", + "2026-06-08T00:44:27Z", + "2026-06-08T00:51:40Z", + "2026-06-08T00:52:43Z", + "2026-06-08T00:54:12Z", + "2026-06-08T00:59:27Z", + "2026-06-08T01:00:32Z", + "2026-06-08T01:01:18Z", + "2026-06-08T01:03:43Z", + "2026-06-08T01:08:20Z", + "2026-06-08T01:10:18Z", + "2026-06-08T01:12:26Z", + "2026-06-08T01:24:48Z", + "2026-06-08T01:29:34Z", + "2026-06-08T01:33:45Z", + "2026-06-08T01:35:32Z", + "2026-06-08T01:40:10Z", + "2026-06-08T01:44:17Z", + "2026-06-08T01:46:06Z", + "2026-06-08T01:50:34Z", + "2026-06-08T02:02:03Z", + "2026-06-08T02:07:10Z", + "2026-06-08T02:10:49Z", + "2026-06-08T02:20:01Z", + "2026-06-08T02:20:11Z", + "2026-06-08T02:22:26Z", + "2026-06-08T02:23:40Z", + "2026-06-08T02:28:34Z", + "2026-06-08T02:30:56Z", + "2026-06-08T02:31:02Z", + "2026-06-08T02:39:13Z", + "2026-06-08T02:39:42Z", + "2026-06-08T02:40:27Z", + "2026-06-08T02:46:08Z", + "2026-06-08T02:46:18Z", + "2026-06-08T03:09:40Z", + "2026-06-08T03:11:22Z", + "2026-06-08T03:12:11Z", + "2026-06-08T03:13:30Z", + "2026-06-08T03:14:02Z", + "2026-06-08T03:17:07Z", + "2026-06-08T03:21:56Z", + "2026-06-08T03:30:10Z", + "2026-06-08T03:30:38Z", + "2026-06-08T03:33:49Z", + "2026-06-08T03:39:09Z", + "2026-06-08T03:47:08Z", + "2026-06-08T03:53:29Z", + "2026-06-08T04:04:28Z", + "2026-06-08T04:09:42Z", + "2026-06-08T04:11:28Z", + "2026-06-08T04:14:41Z", + "2026-06-08T04:18:10Z", + "2026-06-08T04:25:36Z", + "2026-06-08T04:25:54Z", + "2026-06-08T04:26:12Z", + "2026-06-08T04:29:47Z", + "2026-06-08T05:01:35Z", + "2026-06-08T05:03:23Z", + "2026-06-08T05:03:28Z", + "2026-06-08T05:18:08Z", + "2026-06-08T05:18:55Z", + "2026-06-08T05:19:38Z", + "2026-06-08T05:29:07Z", + "2026-06-08T05:34:46Z", + "2026-06-08T05:41:20Z", + "2026-06-08T05:42:48Z", + "2026-06-08T05:52:33Z", + "2026-06-08T05:55:26Z", + "2026-06-08T05:57:02Z", + "2026-06-08T06:15:52Z", + "2026-06-08T06:30:58Z", + "2026-06-08T06:36:30Z", + "2026-06-08T06:37:26Z", + "2026-06-08T06:45:11Z", + "2026-06-08T06:59:58Z", + "2026-06-08T07:03:50Z", + "2026-06-08T07:04:26Z", + "2026-06-08T07:05:11Z", + "2026-06-08T07:13:42Z", + "2026-06-08T07:16:52Z", + "2026-06-08T07:26:04Z", + "2026-06-08T07:40:52Z", + "2026-06-08T07:45:56Z", + "2026-06-08T07:49:53Z", + "2026-06-08T07:50:00Z", + "2026-06-08T07:55:24Z", + "2026-06-08T07:59:38Z", + "2026-06-08T08:11:53Z", + "2026-06-08T08:14:44Z", + "2026-06-08T08:17:48Z", + "2026-06-08T08:30:35Z", + "2026-06-08T08:39:50Z", + "2026-06-08T08:40:19Z", + "2026-06-08T08:45:21Z", + "2026-06-08T09:01:54Z", + "2026-06-08T09:05:30Z", + "2026-06-08T09:14:11Z", + "2026-06-08T09:18:18Z", + "2026-06-08T09:19:29Z", + "2026-06-08T09:33:57Z", + "2026-06-08T09:36:05Z", + "2026-06-08T09:46:26Z", + "2026-06-08T09:47:01Z", + "2026-06-08T09:59:59Z", + "2026-06-08T10:13:31Z", + "2026-06-08T10:20:49Z", + "2026-06-08T10:42:58Z", + "2026-06-08T10:46:38Z", + "2026-06-08T10:49:18Z", + "2026-06-08T10:50:19Z", + "2026-06-08T10:50:30Z", + "2026-06-08T10:51:08Z", + "2026-06-08T10:53:09Z", + "2026-06-08T10:58:10Z", + "2026-06-08T11:01:40Z", + "2026-06-08T11:16:54Z", + "2026-06-08T11:26:54Z", + "2026-06-08T11:27:09Z", + "2026-06-08T11:31:03Z", + "2026-06-08T11:37:24Z", + "2026-06-08T11:40:17Z", + "2026-06-08T11:41:15Z", + "2026-06-08T11:48:23Z", + "2026-06-08T11:54:41Z", + "2026-06-08T11:54:51Z", + "2026-06-08T12:05:46Z", + "2026-06-08T12:16:11Z", + "2026-06-08T12:16:59Z", + "2026-06-08T12:30:52Z", + "2026-06-08T12:35:29Z", + "2026-06-08T12:42:07Z", + "2026-06-08T12:45:09Z", + "2026-06-08T13:24:36Z", + "2026-06-08T13:25:16Z", + "2026-06-08T13:39:44Z", + "2026-06-08T13:40:22Z", + "2026-06-08T13:41:51Z", + "2026-06-08T14:01:20Z", + "2026-06-08T14:02:23Z", + "2026-06-08T14:04:35Z", + "2026-06-08T14:07:32Z", + "2026-06-08T14:07:55Z", + "2026-06-08T14:12:19Z", + "2026-06-08T14:16:49Z", + "2026-06-08T14:29:20Z", + "2026-06-08T14:31:16Z", + "2026-06-08T14:31:38Z", + "2026-06-08T14:41:39Z", + "2026-06-08T14:50:03Z", + "2026-06-08T15:01:27Z", + "2026-06-08T15:06:40Z", + "2026-06-08T15:07:07Z", + "2026-06-08T15:13:24Z", + "2026-06-08T15:23:52Z", + "2026-06-08T15:28:13Z", + "2026-06-08T15:30:53Z", + "2026-06-08T15:30:55Z", + "2026-06-08T15:37:50Z", + "2026-06-08T15:41:09Z", + "2026-06-08T15:43:19Z", + "2026-06-08T15:48:06Z", + "2026-06-08T15:49:17Z", + "2026-06-08T15:56:36Z", + "2026-06-08T15:58:14Z", + "2026-06-08T16:21:02Z", + "2026-06-08T16:27:27Z", + "2026-06-08T16:33:25Z", + "2026-06-08T16:48:05Z", + "2026-06-08T17:04:31Z", + "2026-06-08T17:23:06Z", + "2026-06-08T17:24:19Z", + "2026-06-08T17:30:42Z", + "2026-06-08T18:00:42Z", + "2026-06-08T18:15:34Z", + "2026-06-08T18:35:34Z", + "2026-06-08T19:28:02Z", + "2026-06-08T20:32:42Z", + "2026-06-08T21:52:36Z", + "2026-06-08T22:49:21Z", + "2026-06-08T22:51:40Z", + "2026-06-08T22:53:31Z", + "2026-06-09T00:24:21Z", + "2026-06-09T01:50:46Z", + "2026-06-09T02:03:11Z", + "2026-06-09T02:07:50Z", + "2026-06-09T02:16:47Z", + "2026-06-09T02:44:35Z", + "2026-06-09T03:35:04Z", + "2026-06-09T03:54:08Z", + "2026-06-09T05:05:53Z", + "2026-06-09T06:11:04Z", + "2026-06-09T06:23:43Z", + "2026-06-09T06:31:29Z", + "2026-06-09T06:46:59Z", + "2026-06-09T07:11:53Z", + "2026-06-09T07:19:10Z", + "2026-06-09T08:34:03Z", + "2026-06-09T08:35:26Z", + "2026-06-09T08:38:07Z", + "2026-06-09T08:49:32Z", + "2026-06-09T09:33:37Z", + "2026-06-09T09:45:09Z", + "2026-06-09T09:54:56Z", + "2026-06-09T12:46:42Z", + "2026-06-09T17:24:16Z", + "2026-06-09T18:26:44Z", + "2026-06-09T18:47:06Z", + "2026-06-09T21:05:21Z", + "2026-06-10T00:39:33Z", + "2026-06-10T01:34:02Z", + "2026-06-10T01:52:39Z", + "2026-06-10T02:28:45Z", + "2026-06-10T02:31:32Z", + "2026-06-10T05:45:36Z", + "2026-06-10T08:06:41Z", + "2026-06-10T08:42:16Z", + "2026-06-10T09:48:55Z", + "2026-06-10T09:53:10Z", + "2026-06-10T12:50:50Z", + "2026-06-10T13:44:03Z", + "2026-06-10T17:01:17Z", + "2026-06-11T02:18:38Z", + "2026-06-11T02:59:53Z", + "2026-06-11T07:34:36Z", + "2026-06-11T09:47:19Z", + "2026-06-11T10:51:55Z", + "2026-06-11T16:39:17Z", + "2026-06-11T16:48:25Z", + "2026-06-11T20:37:32Z", + "2026-06-12T01:17:33Z", + "2026-06-12T01:55:07Z", + "2026-06-12T02:07:37Z", + "2026-06-12T03:47:56Z", + "2026-06-12T05:11:26Z", + "2026-06-12T05:47:08Z", + "2026-06-12T07:40:46Z", + "2026-06-12T08:51:56Z", + "2026-06-12T09:26:25Z", + "2026-06-12T10:08:45Z", + "2026-06-12T10:40:05Z", + "2026-06-12T12:59:01Z", + "2026-06-12T14:15:21Z", + "2026-06-12T15:29:28Z", + "2026-06-13T01:45:44Z", + "2026-06-13T02:12:17Z", + "2026-06-13T02:27:44Z", + "2026-06-13T02:31:22Z", + "2026-06-13T02:36:07Z", + "2026-06-13T02:38:08Z", + "2026-06-13T02:39:21Z", + "2026-06-13T02:40:20Z", + "2026-06-13T03:04:59Z", + "2026-06-13T03:05:30Z", + "2026-06-13T03:10:30Z", + "2026-06-13T03:11:09Z", + "2026-06-13T03:16:42Z", + "2026-06-13T03:18:06Z", + "2026-06-13T03:20:09Z", + "2026-06-13T03:25:12Z", + "2026-06-13T03:29:35Z", + "2026-06-13T03:33:28Z", + "2026-06-13T03:47:34Z", + "2026-06-13T03:51:56Z", + "2026-06-13T04:30:43Z", + "2026-06-13T04:34:14Z", + "2026-06-13T04:38:49Z", + "2026-06-13T04:43:13Z", + "2026-06-13T04:43:30Z", + "2026-06-13T04:52:14Z", + "2026-06-13T05:01:55Z", + "2026-06-13T05:07:15Z", + "2026-06-13T05:27:06Z", + "2026-06-13T05:35:55Z", + "2026-06-13T05:48:50Z", + "2026-06-13T05:57:51Z", + "2026-06-13T05:57:55Z", + "2026-06-13T06:00:15Z", + "2026-06-13T06:10:01Z", + "2026-06-13T06:21:45Z", + "2026-06-13T06:33:54Z", + "2026-06-13T06:49:21Z", + "2026-06-13T06:49:30Z", + "2026-06-13T06:51:18Z", + "2026-06-13T06:57:22Z", + "2026-06-13T07:23:25Z", + "2026-06-13T07:38:41Z", + "2026-06-13T07:39:47Z", + "2026-06-13T07:52:57Z", + "2026-06-13T08:14:57Z", + "2026-06-13T08:34:48Z", + "2026-06-13T09:29:45Z", + "2026-06-13T09:31:31Z", + "2026-06-13T09:41:20Z", + "2026-06-13T09:56:49Z", + "2026-06-13T10:09:53Z", + "2026-06-13T10:17:29Z", + "2026-06-13T10:19:39Z", + "2026-06-13T10:21:03Z", + "2026-06-13T10:25:14Z", + "2026-06-13T10:49:24Z", + "2026-06-13T10:51:43Z", + "2026-06-13T11:18:26Z", + "2026-06-13T11:27:47Z", + "2026-06-13T11:32:48Z", + "2026-06-13T11:57:20Z", + "2026-06-13T12:04:19Z", + "2026-06-13T12:19:06Z", + "2026-06-13T13:02:04Z", + "2026-06-13T13:03:28Z", + "2026-06-13T13:15:50Z", + "2026-06-13T13:19:17Z", + "2026-06-13T13:31:16Z", + "2026-06-13T13:37:41Z", + "2026-06-13T13:51:52Z", + "2026-06-13T13:57:16Z", + "2026-06-13T13:58:15Z", + "2026-06-13T14:24:26Z", + "2026-06-13T14:30:34Z", + "2026-06-13T14:38:15Z", + "2026-06-13T14:39:35Z", + "2026-06-13T14:40:13Z", + "2026-06-13T14:40:56Z", + "2026-06-13T14:46:04Z", + "2026-06-13T14:52:16Z", + "2026-06-13T14:56:36Z", + "2026-06-13T15:18:58Z", + "2026-06-13T15:28:32Z", + "2026-06-13T15:30:23Z", + "2026-06-13T15:36:08Z", + "2026-06-13T15:39:02Z", + "2026-06-13T15:39:42Z", + "2026-06-13T15:50:35Z", + "2026-06-13T15:51:20Z", + "2026-06-13T15:55:31Z", + "2026-06-13T15:55:55Z", + "2026-06-13T15:56:46Z", + "2026-06-13T16:03:45Z", + "2026-06-13T16:04:51Z", + "2026-06-13T16:08:45Z", + "2026-06-13T16:11:43Z", + "2026-06-13T16:12:06Z", + "2026-06-13T16:26:41Z", + "2026-06-13T16:47:11Z", + "2026-06-13T17:21:07Z", + "2026-06-13T17:39:43Z", + "2026-06-13T17:53:06Z", + "2026-06-13T18:00:19Z", + "2026-06-13T18:23:22Z", + "2026-06-13T19:20:52Z", + "2026-06-13T19:36:57Z", + "2026-06-13T20:55:17Z", + "2026-06-13T21:14:53Z", + "2026-06-13T21:56:04Z", + "2026-06-13T22:31:25Z", + "2026-06-13T23:43:29Z", + "2026-06-13T23:58:44Z", + "2026-06-14T00:31:52Z", + "2026-06-14T00:33:12Z", + "2026-06-14T00:39:49Z", + "2026-06-14T00:45:36Z", + "2026-06-14T01:09:53Z", + "2026-06-14T02:06:33Z", + "2026-06-14T02:07:16Z", + "2026-06-14T02:53:08Z", + "2026-06-14T02:55:13Z", + "2026-06-14T03:22:57Z", + "2026-06-14T03:29:03Z", + "2026-06-14T03:32:31Z", + "2026-06-14T04:14:15Z", + "2026-06-14T04:16:51Z", + "2026-06-14T05:39:27Z", + "2026-06-14T05:42:10Z", + "2026-06-14T06:14:23Z", + "2026-06-14T07:11:14Z", + "2026-06-14T08:56:54Z", + "2026-06-14T09:19:43Z", + "2026-06-14T15:24:45Z", + "2026-06-15T00:30:28Z", + "2026-06-15T03:15:21Z", + "2026-06-15T03:19:25Z", + "2026-06-15T03:28:22Z", + "2026-06-15T03:44:56Z", + "2026-06-15T04:18:28Z", + "2026-06-15T04:24:25Z", + "2026-06-15T05:41:40Z", + "2026-06-15T06:27:31Z", + "2026-06-15T06:44:13Z", + "2026-06-15T07:16:54Z", + "2026-06-15T07:36:24Z", + "2026-06-15T08:19:19Z", + "2026-06-15T09:14:56Z", + "2026-06-15T09:53:58Z", + "2026-06-15T11:13:27Z", + "2026-06-15T12:11:39Z", + "2026-06-15T12:40:32Z", + "2026-06-15T14:58:51Z", + "2026-06-15T16:22:45Z", + "2026-06-15T17:54:34Z", + "2026-06-16T02:04:28Z", + "2026-06-16T03:47:06Z", + "2026-06-16T06:42:16Z", + "2026-06-16T08:17:43Z", + "2026-06-16T12:05:36Z", + "2026-06-16T12:27:07Z", + "2026-06-16T15:27:22Z", + "2026-06-16T18:35:30Z", + "2026-06-16T21:17:32Z", + "2026-06-17T07:06:41Z", + "2026-06-17T07:26:58Z", + "2026-06-17T07:51:50Z", + "2026-06-17T08:42:10Z", + "2026-06-17T09:06:42Z", + "2026-06-17T09:44:16Z", + "2026-06-17T10:43:41Z", + "2026-06-17T11:41:48Z", + "2026-06-17T13:04:47Z", + "2026-06-17T14:44:08Z", + "2026-06-17T14:53:06Z", + "2026-06-17T23:48:48Z", + "2026-06-18T04:09:53Z", + "2026-06-18T10:12:26Z", + "2026-06-18T14:04:37Z", + "2026-06-18T20:11:33Z", + "2026-06-19T09:20:58Z", + "2026-06-19T11:10:56Z", + "2026-06-19T11:34:37Z", + "2026-06-20T05:07:46Z", + "2026-06-20T06:06:04Z", + "2026-06-20T10:01:29Z", + "2026-06-20T11:13:29Z", + "2026-06-20T15:31:51Z", + "2026-06-20T16:38:29Z", + "2026-06-20T17:29:45Z", + "2026-06-21T00:34:28Z", + "2026-06-21T01:50:46Z", + "2026-06-21T06:29:34Z", + "2026-06-21T08:18:34Z", + "2026-06-21T08:55:15Z", + "2026-06-21T10:10:45Z", + "2026-06-21T17:48:33Z", + "2026-06-22T01:47:25Z", + "2026-06-22T05:54:02Z", + "2026-06-22T07:12:14Z", + "2026-06-23T06:46:48Z", + "2026-06-23T07:40:50Z", + "2026-06-23T09:53:00Z", + "2026-06-23T10:34:24Z", + "2026-06-23T12:26:46Z", + "2026-06-23T12:43:37Z", + "2026-06-23T14:45:55Z", + "2026-06-23T15:30:33Z", + "2026-06-24T02:03:52Z", + "2026-06-24T02:36:19Z", + "2026-06-24T04:46:05Z", + "2026-06-24T09:34:45Z", + "2026-06-25T05:42:06Z", + "2026-06-25T06:06:21Z", + "2026-06-25T07:06:07Z", + "2026-06-25T15:40:15Z", + "2026-06-25T21:33:08Z", + "2026-06-26T01:38:16Z", + "2026-06-26T05:30:29Z", + "2026-06-26T07:50:32Z", + "2026-06-26T11:17:55Z", + "2026-06-26T13:49:41Z", + "2026-06-26T16:49:13Z", + "2026-06-26T19:03:03Z", + "2026-06-27T17:11:00Z", + "2026-06-28T06:06:14Z", + "2026-06-28T11:20:48Z", + "2026-06-28T14:48:43Z", + "2026-06-28T19:43:49Z", + "2026-06-28T21:40:12Z", + "2026-06-29T02:03:05Z", + "2026-06-29T02:42:01Z", + "2026-06-29T02:57:56Z", + "2026-06-29T03:18:47Z", + "2026-06-29T03:51:48Z", + "2026-06-29T05:53:52Z", + "2026-06-29T08:18:52Z", + "2026-06-29T20:05:49Z", + "2026-06-29T22:22:41Z", + "2026-06-30T01:18:04Z", + "2026-06-30T05:30:02Z", + "2026-06-30T10:06:06Z", + "2026-06-30T14:26:38Z", + "2026-06-30T17:18:01Z", + "2026-06-30T20:05:48Z", + "2026-07-01T02:09:58Z", + "2026-07-01T03:26:56Z", + "2026-07-01T12:01:36Z", + "2026-07-01T12:26:28Z", + "2026-07-02T02:53:34Z", + "2026-07-02T03:45:33Z", + "2026-07-02T05:23:11Z", + "2026-07-02T05:56:30Z", + "2026-07-02T08:14:27Z", + "2026-07-03T13:26:02Z", + "2026-07-03T13:54:41Z", + "2026-07-03T14:44:07Z", + "2026-07-03T17:35:07Z", + "2026-07-04T06:01:01Z", + "2026-07-04T15:11:29Z", + "2026-07-04T18:23:14Z", + "2026-07-05T10:28:34Z", + "2026-07-05T14:03:23Z", + "2026-07-06T05:16:32Z", + "2026-07-06T08:24:25Z", + "2026-07-06T09:29:02Z", + "2026-07-06T18:58:31Z", + "2026-07-07T03:41:04Z", + "2026-07-07T03:55:02Z", + "2026-07-07T06:37:28Z", + "2026-07-07T06:50:54Z", + "2026-07-07T07:47:33Z", + "2026-07-07T13:00:09Z", + "2026-07-07T14:07:34Z", + "2026-07-08T05:21:07Z", + "2026-07-08T07:28:29Z", + "2026-07-08T08:33:55Z", + "2026-07-08T10:33:58Z", + "2026-07-09T01:43:12Z", + "2026-07-09T02:22:14Z", + "2026-07-09T09:36:30Z", + "2026-07-09T13:46:47Z", + "2026-07-10T09:00:05Z", + "2026-07-10T14:07:24Z", + "2026-07-10T14:40:20Z", + "2026-07-10T15:19:20Z", + "2026-07-10T15:38:21Z", + "2026-07-11T01:34:03Z", + "2026-07-12T00:24:51Z", + "2026-07-12T13:11:52Z", + "2026-07-12T13:15:06Z", + "2026-07-12T19:08:35Z", + "2026-07-13T00:00:11Z", + "2026-07-13T03:46:59Z", + "2026-07-13T04:12:17Z", + "2026-07-13T06:04:08Z", + "2026-07-13T07:07:30Z", + "2026-07-13T07:54:20Z", + "2026-07-13T10:33:38Z", + "2026-07-13T15:09:18Z", + "2026-07-13T17:48:28Z", + "2026-07-14T03:44:33Z", + "2026-07-14T03:56:41Z", + "2026-07-14T05:58:32Z", + "2026-07-14T14:44:44Z", + "2026-07-15T02:57:54Z", + "2026-07-16T01:40:29Z", + "2026-07-16T07:23:36Z", + "2026-07-16T12:25:14Z", + "2026-07-17T16:14:08Z", + "2026-07-18T03:33:19Z", + "2026-07-18T05:35:40Z", + "2026-07-19T17:53:29Z", + "2026-07-20T06:23:01Z", + "2026-07-20T08:43:21Z", + "2026-07-21T00:27:17Z", + "2026-07-21T02:28:14Z", + "2026-07-21T21:16:33Z", + "2026-07-22T03:24:23Z", + "2026-07-22T03:30:40Z", + "2026-07-22T06:48:17Z", + "2026-07-22T07:49:01Z", + "2026-07-22T15:11:10Z", + "2026-07-23T01:20:19Z", + "2026-07-24T02:42:53Z", + "2026-07-24T05:48:23Z", + "2026-07-24T20:07:12Z", + "2026-07-27T01:20:17Z", + "2026-07-27T02:30:38Z", + "2026-07-27T03:35:12Z", + "2026-07-27T06:09:57Z", + "2026-07-27T07:13:03Z", + "2026-07-27T09:35:58Z", + "2026-07-27T14:33:25Z", + "2026-07-27T16:16:25Z", + "2026-07-27T16:54:04Z", + "2026-07-28T01:20:43Z", + "2026-07-28T08:59:41Z", + "2026-07-28T10:35:52Z", + "2026-07-28T11:44:30Z", + "2026-07-28T17:58:30Z", + "2026-07-30T00:47:50Z", + "2026-07-30T02:46:24Z", + "2026-07-30T02:48:38Z", + "2026-07-30T02:55:36Z", + "2026-07-30T03:25:07Z", + "2026-07-30T06:42:41Z", + "2026-07-30T07:18:39Z", + "2026-07-30T07:28:42Z", + "2026-07-30T08:15:33Z", + "2026-07-30T10:14:52Z", + "2026-07-30T22:34:40Z", + "2026-07-31T00:25:54Z", + "2026-07-31T01:56:20Z", + "2026-08-01T09:41:00Z", + "2026-08-01T15:00:51Z", + "2026-08-02T09:59:55Z", + "2026-08-02T10:37:17Z", + "2026-08-03T03:22:57Z", + "2026-08-03T12:02:26Z", + "2026-08-03T13:53:59Z", + "2026-08-04T03:53:09Z", + "2026-08-04T14:29:53Z", + "2026-08-05T14:47:27Z", + "2026-08-06T11:51:40Z", + "2026-08-06T12:54:13Z", + "2026-08-07T11:40:11Z", + "2026-08-08T14:03:01Z", + "2026-08-08T23:48:13Z", + "2026-08-09T03:27:26Z", + "2026-08-09T11:16:59Z", + "2026-08-09T20:24:28Z", + "2026-08-10T04:15:26Z", + "2026-08-10T05:01:57Z", + "2026-08-10T14:16:07Z", + "2026-08-11T01:23:41Z", + "2026-08-11T05:17:49Z", + "2026-08-11T14:22:58Z", + "2026-08-12T07:03:08Z", + "2026-08-12T20:30:14Z", + "2026-08-14T15:13:42Z", + "2026-08-14T15:36:43Z", + "2026-08-14T15:41:37Z", + "2026-08-14T16:16:06Z", + "2026-08-14T16:22:33Z", + "2026-08-14T16:46:47Z", + "2026-08-14T17:25:03Z", + "2026-08-14T17:48:10Z", + "2026-08-14T18:10:19Z", + "2026-08-14T18:28:43Z", + "2026-08-14T19:14:43Z", + "2026-08-14T20:52:18Z", + "2026-08-14T21:34:47Z", + "2026-08-14T21:44:12Z", + "2026-08-15T00:20:05Z", + "2026-08-15T00:20:28Z", + "2026-08-15T00:37:22Z", + "2026-08-15T00:53:48Z", + "2026-08-15T01:37:39Z", + "2026-08-15T01:42:43Z", + "2026-08-15T02:38:58Z", + "2026-08-15T02:53:51Z", + "2026-08-15T03:17:09Z", + "2026-08-15T03:26:20Z", + "2026-08-15T03:56:00Z", + "2026-08-15T04:44:16Z", + "2026-08-15T06:00:32Z", + "2026-08-15T06:50:30Z", + "2026-08-15T07:42:17Z", + "2026-08-15T07:58:46Z", + "2026-08-15T08:56:35Z", + "2026-08-15T09:18:41Z", + "2026-08-15T09:46:42Z", + "2026-08-15T09:49:39Z", + "2026-08-15T10:36:36Z", + "2026-08-15T10:37:02Z", + "2026-08-15T10:57:44Z", + "2026-08-15T11:13:50Z", + "2026-08-15T12:01:53Z", + "2026-08-15T13:15:36Z", + "2026-08-15T13:17:28Z", + "2026-08-15T14:36:12Z", + "2026-08-15T14:39:05Z", + "2026-08-15T15:22:31Z", + "2026-08-15T16:31:51Z", + "2026-08-15T16:36:24Z", + "2026-08-15T17:58:25Z", + "2026-08-15T18:43:29Z", + "2026-08-15T20:37:03Z", + "2026-08-15T20:38:04Z", + "2026-08-15T21:07:46Z", + "2026-08-16T01:41:39Z", + "2026-08-16T03:15:41Z", + "2026-08-16T03:50:45Z", + "2026-08-16T05:05:29Z", + "2026-08-16T05:36:56Z", + "2026-08-16T06:03:00Z", + "2026-08-16T07:39:40Z", + "2026-08-16T08:09:44Z", + "2026-08-16T09:22:52Z", + "2026-08-16T12:03:01Z", + "2026-08-16T12:09:48Z", + "2026-08-16T15:19:06Z", + "2026-08-17T02:23:23Z", + "2026-08-17T03:11:50Z", + "2026-08-17T03:12:53Z", + "2026-08-17T07:21:56Z", + "2026-08-17T07:37:46Z", + "2026-08-17T08:17:35Z", + "2026-08-17T09:35:14Z", + "2026-08-17T14:21:48Z", + "2026-08-17T16:39:04Z", + "2026-08-17T18:33:30Z", + "2026-08-17T22:04:03Z", + "2026-08-17T23:28:37Z", + "2026-08-18T01:06:59Z", + "2026-08-18T03:08:36Z", + "2026-08-18T07:41:29Z", + "2026-08-18T07:49:14Z", + "2026-08-18T09:19:24Z", + "2026-08-18T12:46:57Z", + "2026-08-18T21:04:03Z", + "2026-08-19T05:48:10Z", + "2026-08-19T05:55:15Z", + "2026-08-19T06:35:34Z", + "2026-08-19T07:44:16Z", + "2026-08-19T07:58:58Z", + "2026-08-19T11:50:06Z", + "2026-08-19T19:30:18Z", + "2026-08-19T21:42:56Z", + "2026-08-20T03:08:13Z", + "2026-08-20T03:45:56Z", + "2026-08-20T07:57:30Z", + "2026-08-20T09:08:40Z", + "2026-08-20T13:43:15Z" + ] +} diff --git a/brooks-lint/assets/star-history.svg b/brooks-lint/assets/star-history.svg new file mode 100644 index 00000000..ce337dbd --- /dev/null +++ b/brooks-lint/assets/star-history.svg @@ -0,0 +1,45 @@ + + + + + + + + + + Star History + hyhmrright/brooks-lint + + 0 + 500 + 1,000 + 1,500 + + + + + + 1,393 + + Apr 2026 + May + Jun + Jul + Aug + + diff --git a/brooks-lint/docs/dsh-setup.md b/brooks-lint/docs/dsh-setup.md new file mode 100644 index 00000000..5e4ad66d --- /dev/null +++ b/brooks-lint/docs/dsh-setup.md @@ -0,0 +1,60 @@ +# DeepSeek Harness (dsh) Setup + +[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`) is DeepSeek AI's +open-source agent harness — an "everything is a plugin" architecture with a Web UI, started with +`npx @deepseek-ai/dsh web`. It natively loads [Agent Skills](https://agentskills.io) and reads +`AGENTS.md`, so all six brooks-lint modes run with no conversion. + +## Install + +```bash +# simplest — one command (global) +curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts/install.sh | bash -s -- dsh + +# from a clone +./scripts/install.sh dsh # global: ~/.dsh/skills (or $DSH_HOME/skills) +./scripts/install.sh dsh --project # this repo: ./.dsh/skills +``` + +Prefer a manual copy? Clone the repo and `cp -r skills/* ~/.dsh/skills/` — the contents, not the +`skills/` folder itself, so `_shared/` lands as a sibling of the `brooks-*` folders. + +dsh scans these skill roots, highest priority first, so an existing vendor-neutral install is picked +up automatically: + +| Root | Notes | +|---|---| +| `/.dsh/skills` | what `--project` writes | +| `/.agents/skills` | shared with Cursor, Copilot, pi | +| `$DSH_HOME/skills` (default `~/.dsh/skills`) | what the global install writes | +| `$DSH_AGENTS_HOME/skills` (default `~/.agents/skills`) | `./scripts/install.sh agents` also covers dsh | + +The project root is the nearest ancestor containing `.git`; without one, dsh uses the current +directory. When the same skill name appears in two roots, the higher one wins. + +## Invoke + +Just ask — dsh routes to a skill from its `description`: + +- "review this PR" → `brooks-review` +- "audit the architecture" → `brooks-audit` +- "where's our worst tech debt?" → `brooks-debt` + +For explicit invocation, type `/` in the Web UI prompt and pick the skill, or type the token by hand: +`/brooks-review`, `/brooks-audit`, `/brooks-debt`, `/brooks-test`, `/brooks-health`, `/brooks-sweep`. +dsh recognises a whitespace-bounded `/name` anywhere in a message and injects that skill's body +deterministically. The repo's `AGENTS.md` carries the Iron Law (Symptom → Source → Consequence → +Remedy) and the Health Score rules; dsh also loads `$DSH_HOME/AGENTS.md` plus every `AGENTS.md` from +the project root down to your working directory. + +## Notes + +- **Flat layout** is mandatory (the installer guarantees it): discovery is one level deep + (`//SKILL.md`), never recursive, and the skills read `../_shared/`, which only resolves + when `_shared/` sits beside the `brooks-*` folders. `_shared/` itself has no `SKILL.md`, so dsh + ignores it as a skill and the modes read it as ordinary files. +- dsh is in developer preview and warns of compatibility-breaking changes; the skill discovery + contract above reflects `packages/skill/skill-filesystem` as of August 2026. +- 🧪 Documented per the official [skills subsystem](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/skills.md) + docs; community end-to-end verification welcome — + [open an issue](https://github.com/hyhmrright/brooks-lint/issues/new). diff --git a/brooks-lint/docs/getting-started.md b/brooks-lint/docs/getting-started.md index 2cd393a7..665f91f5 100644 --- a/brooks-lint/docs/getting-started.md +++ b/brooks-lint/docs/getting-started.md @@ -33,10 +33,10 @@ layout wrong: curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts/install.sh | bash -s -- ``` -`` ∈ `opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · gemini · -codex · claude · agents`. Add `--project` to install into the current repo instead of your global -config. `agents` targets the vendor-neutral `~/.agents/skills` folder that Cursor, Copilot, pi, Gemini, -and Codex all read. +`` ∈ `opencode · cursor · windsurf · antigravity · pi · kiro · copilot · droid · dsh · +gemini · codex · claude · agents`. Add `--project` to install into the current repo instead of your +global config. `agents` targets the vendor-neutral `~/.agents/skills` folder that Cursor, Copilot, pi, +Gemini, Codex, and DeepSeek Harness all read. ## Per-platform guides @@ -50,6 +50,7 @@ and Codex all read. | GitHub Copilot | [copilot-setup.md](copilot-setup.md) | `.github/skills`, `.claude/skills`, `~/.copilot/skills` | ✅ | | Kiro | [kiro-setup.md](kiro-setup.md) | `.kiro/skills`, `~/.kiro/skills` | ✅ | | Factory Droid | [factory-droid-setup.md](factory-droid-setup.md) | `~/.factory/skills`, `.factory/skills`, `.agent/skills` | ✅ | +| DeepSeek Harness | [dsh-setup.md](dsh-setup.md) | `.dsh/skills`, `.agents/skills`, `~/.dsh/skills`, `~/.agents/skills` | ✅ | For Claude Code, Gemini CLI, and Codex CLI, see the [README install section](../README.md#installation). `./scripts/install.sh gemini` and `./scripts/install.sh codex` also work and use the flat layout these @@ -68,7 +69,7 @@ If your agent accepts a skills folder or an instruction file, brooks-lint works: ## Verification status The marketplace-installed platforms (Claude Code, Gemini CLI, Codex CLI) are maintainer-verified. The -eight Agent-Skills platforms above are documented from each tool's official skill spec and verified at +nine Agent-Skills platforms above are documented from each tool's official skill spec and verified at the file-layout level (the installer is tested), but not yet end-to-end run by the maintainer on every platform. **Tried one? Tell us** — [open an issue](https://github.com/hyhmrright/brooks-lint/issues/new) with the platform, version, and what you saw, working or broken. diff --git a/brooks-lint/docs/github-action-example.yml b/brooks-lint/docs/github-action-example.yml index 127f6b29..7120851e 100644 --- a/brooks-lint/docs/github-action-example.yml +++ b/brooks-lint/docs/github-action-example.yml @@ -28,3 +28,4 @@ jobs: # fail-on: critical # fail on any Critical finding (none | warning | critical) # fail-on-regression: true # fail if the Health Score dropped vs the last run # sarif-file: brooks-lint.sarif # also upload findings to GitHub Code Scanning + # api-base-url: https://your-gateway.example.com # any Anthropic-compatible /v1/messages endpoint diff --git a/brooks-lint/docs/index.html b/brooks-lint/docs/index.html index adf682e9..bc2f27c0 100644 --- a/brooks-lint/docs/index.html +++ b/brooks-lint/docs/index.html @@ -28,7 +28,7 @@ "description": "AI code reviews grounded in twelve classic software engineering books. Decay-risk diagnostics with book citations, severity labels, and six analysis modes including full-sweep auto-fix.", "url": "https://hyhmrright.github.io/brooks-lint/", "image": "https://hyhmrright.github.io/brooks-lint/hero.png", - "softwareVersion": "1.4.3", + "softwareVersion": "1.5.0", "license": "https://github.com/hyhmrright/brooks-lint/blob/main/LICENSE", "codeRepository": "https://github.com/hyhmrright/brooks-lint", "keywords": "AI code review, code quality, tech debt, architecture audit, test quality, Claude Code plugin, refactoring, clean architecture", diff --git a/brooks-lint/gemini-extension.json b/brooks-lint/gemini-extension.json index 3be6049f..7950a650 100644 --- a/brooks-lint/gemini-extension.json +++ b/brooks-lint/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "brooks-lint", - "version": "1.4.3", + "version": "1.5.0", "description": "AI code reviews grounded in twelve classic engineering books — decay risk diagnostics with book citations, severity labels, and six analysis modes (PR review, architecture audit, tech debt, test quality, health dashboard, full-sweep auto-fix)", "author": "hyhmrright", "license": "MIT", diff --git a/brooks-lint/package.json b/brooks-lint/package.json index feece015..fd6f98fd 100644 --- a/brooks-lint/package.json +++ b/brooks-lint/package.json @@ -1,6 +1,6 @@ { "name": "brooks-lint", - "version": "1.4.3", + "version": "1.5.0", "type": "module", "scripts": { "bump": "node scripts/bump-version.mjs", diff --git a/brooks-lint/scripts/ci-review.mjs b/brooks-lint/scripts/ci-review.mjs index 61d67a7f..f722697e 100644 --- a/brooks-lint/scripts/ci-review.mjs +++ b/brooks-lint/scripts/ci-review.mjs @@ -101,7 +101,9 @@ try { process.exit(1); } -const report = message.content[0]?.text ?? ""; +// The first block is not always the text one — an endpoint that returns a +// thinking block first would otherwise yield undefined. +const report = message.content.find((block) => block.type === "text")?.text ?? ""; const scoreMatch = report.match(/Health\s+Score[:\s]+(\d+)/i); const score = scoreMatch ? parseInt(scoreMatch[1], 10) : null; diff --git a/brooks-lint/scripts/gen-star-history.mjs b/brooks-lint/scripts/gen-star-history.mjs new file mode 100644 index 00000000..071de3ea --- /dev/null +++ b/brooks-lint/scripts/gen-star-history.mjs @@ -0,0 +1,241 @@ +// Generates the README star-history chart from first-party GitHub data. +// +// GitHub restricted the public stargazers API to a repository's own admins and +// collaborators (announced 2026-06-30), which broke every third-party chart +// service — api.star-history.com now serves an error card instead of a chart. +// We own this repo, so we read the star data ourselves and commit the result, +// keeping the README free of any third-party image host. +// +// The committed dataset, not the drawing, is the source of truth: the SVG is a +// pure function of assets/star-history.json. That keeps the chart re-renderable +// with no credentials if the endpoint tightens further, keeps the weekly diff +// readable (dates, not shifted path coordinates), and lets `npm run validate` +// prove the two files agree. +// +// Run: node scripts/gen-star-history.mjs → refetch, rewrite both files +// node scripts/gen-star-history.mjs --render-only → redraw the SVG offline +import { execFileSync } from "node:child_process"; +import { readFileSync, writeFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); +// README-only assets, so they live in assets/ alone — unlike the banners, the +// GitHub Pages site under docs/ does not render them. +const OUT = join(ROOT, "assets", "star-history.svg"); +const DATA = join(ROOT, "assets", "star-history.json"); + +const REPO = process.env.GITHUB_REPOSITORY ?? "hyhmrright/brooks-lint"; + +const W = 800, H = 400; +const PAD = { top: 44, right: 24, bottom: 48, left: 64 }; +const PLOT_W = W - PAD.left - PAD.right; +const PLOT_H = H - PAD.top - PAD.bottom; +const ACCENT = "#3b82f6"; // matches the logo palette used by gen-banner.mjs +const FONT = `-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif`; + +const esc = (s) => String(s).replace(/&/g, "&").replace(//g, ">"); + +// The stargazers endpoint is no longer public: it needs credentials that can +// read this repo. CI supplies GITHUB_TOKEN; locally we borrow the gh CLI's. +function resolveToken() { + if (process.env.GITHUB_TOKEN) return process.env.GITHUB_TOKEN; + try { + return execFileSync("gh", ["auth", "token"], { encoding: "utf8" }).trim(); + } catch { + throw new Error( + "No GITHUB_TOKEN set and `gh auth token` failed. Since GitHub restricted " + + "the stargazers API, this script needs credentials for a repo admin or collaborator.", + ); + } +} + +// Returns the raw starred_at strings, oldest first — exactly what we commit. +async function fetchStarTimestamps(token) { + const stamps = []; + for (let page = 1; ; page++) { + const url = `https://api.github.com/repos/${REPO}/stargazers?per_page=100&page=${page}`; + const res = await fetch(url, { + headers: { + // The star+json media type is what adds starred_at to each entry. + Accept: "application/vnd.github.star+json", + Authorization: `Bearer ${token}`, + "X-GitHub-Api-Version": "2022-11-28", + "User-Agent": "brooks-lint-gen-star-history", + }, + }); + // Past 400 pages GitHub answers 422 rather than paginating, so a repo above + // 40,000 stars can no longer be read in full — the committed dataset is what + // preserves the history when that day comes. + if (!res.ok) { + throw new Error(`GitHub API ${res.status} on page ${page}: ${(await res.text()).slice(0, 200)}`); + } + const batch = await res.json(); + for (const entry of batch) { + // A missing starred_at means the star+json media type stopped being + // honoured. Fail loudly rather than plot NaN coordinates. + if (Number.isNaN(Date.parse(entry.starred_at))) { + throw new Error(`Stargazer without a usable starred_at on page ${page}.`); + } + stamps.push(entry.starred_at); + } + if (batch.length < 100) return stamps.sort((a, b) => Date.parse(a) - Date.parse(b)); + } +} + +export function readStamps() { + return JSON.parse(readFileSync(DATA, "utf8")).starredAt; +} + +function writeStamps(stamps) { + // Deliberately no generated-at field: the file has to stay byte-identical when + // no star was added, or the workflow's "commit only when it moved" guard would + // fire every single run. Git already records when it last changed. + writeFileSync(DATA, `${JSON.stringify({ repo: REPO, starredAt: stamps }, null, 2)}\n`); +} + +// Round the axis maximum up to a 1/2/5 × 10ⁿ step so tick labels stay readable. +function niceStep(max, targetTicks) { + const raw = max / targetTicks; + const mag = 10 ** Math.floor(Math.log10(raw)); + for (const m of [1, 2, 5]) if (raw <= m * mag) return m * mag; + return 10 * mag; +} + +// One tick per month, thinned out so labels never collide on a long history. +function monthTicks(from, to) { + const all = []; + const cursor = new Date(from); + cursor.setUTCDate(1); + cursor.setUTCHours(0, 0, 0, 0); + if (cursor.getTime() < from) cursor.setUTCMonth(cursor.getUTCMonth() + 1); + while (cursor.getTime() <= to) { + all.push(cursor.getTime()); + cursor.setUTCMonth(cursor.getUTCMonth() + 1); + } + const stride = Math.ceil(all.length / 8) || 1; + return all.filter((_, i) => i % stride === 0); +} + +const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + +function monthLabel(ms, showYear) { + const d = new Date(ms); + const month = MONTHS[d.getUTCMonth()]; + return showYear ? `${month} ${d.getUTCFullYear()}` : month; +} + +// 1,392 points would bloat the committed SVG for no visible gain. Keep every +// nth sample plus the exact final point, so the headline count stays truthful. +function downsample(points, limit) { + if (points.length <= limit) return points; + const stride = Math.ceil(points.length / limit); + const kept = points.filter((_, i) => i % stride === 0); + if (kept.at(-1) !== points.at(-1)) kept.push(points.at(-1)); + return kept; +} + +export function render(stamps) { + const times = stamps.map((iso) => Date.parse(iso)); + const total = times.length; + const t0 = times[0]; + // The axis ends at the newest star rather than at "now". Anchoring it to the + // clock would shift every x coordinate on every run, so the workflow could + // never tell a real change from a redraw and would commit noise weekly. + const t1 = times.at(-1); + // Stars are whole numbers, so never let a tiny repo produce fractional ticks. + const step = Math.max(1, niceStep(total, 5)); + const yMax = Math.ceil(total / step) * step; + + const x = (ms) => PAD.left + ((ms - t0) / (t1 - t0)) * PLOT_W; + const y = (n) => PAD.top + PLOT_H - (n / yMax) * PLOT_H; + + const points = downsample( + times.map((ms, i) => [ms, i + 1]), + 300, + ); + const line = points.map(([ms, n], i) => `${i === 0 ? "M" : "L"}${x(ms).toFixed(1)} ${y(n).toFixed(1)}`).join(""); + const area = `${line}L${x(t1).toFixed(1)} ${y(0).toFixed(1)}L${x(t0).toFixed(1)} ${y(0).toFixed(1)}Z`; + + const yTicks = []; + for (let n = 0; n <= yMax; n += step) yTicks.push(n); + + const xTicks = monthTicks(t0, t1); + const spansYears = new Date(t0).getUTCFullYear() !== new Date(t1).getUTCFullYear(); + + const gridLines = yTicks + .map( + (n) => + `` + + `${n.toLocaleString("en-US")}`, + ) + .join("\n "); + + const xLabels = xTicks + .map( + (ms, i) => + `` + + `${monthLabel(ms, spansYears || i === 0)}`, + ) + .join("\n "); + + // Anchoring the axis to the newest star puts the final point exactly on the + // right edge, so the callout always hangs back inside the plot. + const lastX = PAD.left + PLOT_W; + const lastY = y(total); + + return ` + + + + + + + + + Star History + ${esc(REPO)} + + ${gridLines} + + + + + + ${total.toLocaleString("en-US")} + + ${xLabels} + + +`; +} + +async function main() { + const renderOnly = process.argv.includes("--render-only"); + const stamps = renderOnly ? readStamps() : await fetchStarTimestamps(resolveToken()); + // Two points are the minimum a time axis can span; one would divide by zero + // and silently write a chart full of NaN coordinates. + if (stamps.length < 2) throw new Error(`Only ${stamps.length} stargazer(s) for ${REPO} — refusing to write a chart.`); + if (!renderOnly) writeStamps(stamps); + writeFileSync(OUT, render(stamps)); + console.log(`Wrote ${OUT} — ${stamps.length} stars through ${stamps.at(-1).slice(0, 10)}`); +} + +// Importable so `npm run validate` can re-render from the committed data and +// prove the SVG is in sync; only a direct run touches the network or disk. +if (process.argv[1] === fileURLToPath(import.meta.url)) await main(); diff --git a/brooks-lint/scripts/install.sh b/brooks-lint/scripts/install.sh index b6e939c2..90270ef0 100755 --- a/brooks-lint/scripts/install.sh +++ b/brooks-lint/scripts/install.sh @@ -13,8 +13,9 @@ # ./scripts/install.sh [--project] # curl -fsSL https://raw.githubusercontent.com/hyhmrright/brooks-lint/main/scripts/install.sh | bash -s -- # -# Platforms: opencode cursor windsurf antigravity pi kiro copilot droid gemini codex claude agents -# agents = the vendor-neutral ~/.agents/skills folder (read by Cursor, Copilot, pi, Gemini, Codex) +# Platforms: opencode cursor windsurf antigravity pi kiro copilot droid dsh gemini codex claude agents +# agents = the vendor-neutral ~/.agents/skills folder (read by Cursor, Copilot, pi, Gemini, +# Codex, and DeepSeek Harness) # # Flags: # --project install into the current repo (././skills) instead of the global folder @@ -24,7 +25,7 @@ set -euo pipefail REPO_URL="https://github.com/hyhmrright/brooks-lint.git" -PLATFORMS="opencode cursor windsurf antigravity pi kiro copilot droid gemini codex claude agents" +PLATFORMS="opencode cursor windsurf antigravity pi kiro copilot droid dsh gemini codex claude agents" err() { printf '\033[31merror:\033[0m %s\n' "$*" >&2; } info() { printf '\033[36m›\033[0m %s\n' "$*"; } @@ -59,6 +60,8 @@ global_dir() { kiro) printf '%s' "$HOME/.kiro/skills" ;; copilot) printf '%s' "$HOME/.copilot/skills" ;; droid) printf '%s' "$HOME/.factory/skills" ;; + # DeepSeek Harness resolves its config root from $DSH_HOME, falling back to ~/.dsh. + dsh) printf '%s' "${DSH_HOME:-$HOME/.dsh}/skills" ;; gemini) printf '%s' "$HOME/.gemini/skills" ;; codex) printf '%s' "$HOME/.codex/skills" ;; claude) printf '%s' "$HOME/.claude/skills" ;; @@ -77,6 +80,7 @@ project_dir() { kiro) printf '%s' "$PWD/.kiro/skills" ;; copilot) printf '%s' "$PWD/.github/skills" ;; droid) printf '%s' "$PWD/.factory/skills" ;; + dsh) printf '%s' "$PWD/.dsh/skills" ;; gemini) printf '%s' "$PWD/.gemini/skills" ;; codex) printf '%s' "$PWD/.codex/skills" ;; claude) printf '%s' "$PWD/.claude/skills" ;; diff --git a/brooks-lint/scripts/platforms.mjs b/brooks-lint/scripts/platforms.mjs new file mode 100644 index 00000000..12aa4329 --- /dev/null +++ b/brooks-lint/scripts/platforms.mjs @@ -0,0 +1,64 @@ +/** + * Platform-inventory helpers shared by validate-repo.mjs and its tests. + * + * Nothing here hardcodes a platform or a translation. The platforms carrying an + * install-table row are discovered from the docs/-setup.md files on disk, + * the documents that must show that table are discovered from README*.md, and + * the installer's own list is parsed out of scripts/install.sh — so a new + * platform, or a seventh language, is covered on arrival. Keeping a separate + * hand-maintained list is what let the localized README badges go stale before + * (see version-refs.mjs). + */ + +import { readdirSync } from "node:fs"; +import path from "node:path"; + +/** + * Every document that carries the per-platform install table: all README + * translations, plus the getting-started guide, which is the one non-README + * page with a platform table of its own. + */ +export function platformDocs(root) { + const readmes = readdirSync(root) + .filter((file) => file.startsWith("README") && file.endsWith(".md")) + .sort(); + return [...readmes, path.join("docs", "getting-started.md")]; +} + +/** Every per-platform setup guide, as bare filenames. */ +export function setupGuides(root) { + return readdirSync(path.join(root, "docs")) + .filter((file) => file.endsWith("-setup.md")) + .sort(); +} + +/** + * Setup-guide filenames linked from one document, normalized so a README's + * `docs/kiro-setup.md` and getting-started's sibling `kiro-setup.md` compare + * equal. Returns a sorted, de-duplicated array. + */ +export function linkedSetupGuides(text) { + const links = text.matchAll(/\((?:docs\/)?([a-z0-9-]+-setup\.md)\)/g); + return [...new Set([...links].map((match) => match[1]))].sort(); +} + +/** + * The installer's platform list plus the platforms each directory-mapping + * function actually handles. A platform in PLATFORMS with no case arm fails + * `install.sh ` with "unknown platform"; a case arm missing from + * PLATFORMS is invisible in --list and the help text. + */ +export function parseInstallerPlatforms(text) { + const declared = text.match(/^PLATFORMS="([^"]*)"/m)?.[1].trim(); + return { + declared: declared ? declared.split(/\s+/) : [], + global: caseArms(text, "global_dir"), + project: caseArms(text, "project_dir"), + }; +} + +/** Platform names matched by the `case` arms of one shell function. */ +function caseArms(text, fnName) { + const body = text.match(new RegExp(`^${fnName}\\(\\) \\{$([\\s\\S]*?)^\\}$`, "m"))?.[1] ?? ""; + return [...body.matchAll(/^\s+([a-z][a-z0-9-]*)\)/gm)].map((match) => match[1]); +} diff --git a/brooks-lint/scripts/run-evals-live.mjs b/brooks-lint/scripts/run-evals-live.mjs index cfdda01f..bdc850cc 100644 --- a/brooks-lint/scripts/run-evals-live.mjs +++ b/brooks-lint/scripts/run-evals-live.mjs @@ -81,7 +81,7 @@ for (const scenario of scenarios) { system: systemPrompt, messages: [{ role: "user", content: userMessage }], }); - aiText = message.content[0]?.text ?? ""; + aiText = message.content.find((block) => block.type === "text")?.text ?? ""; verdict = classify(scenario, aiText); } catch (err) { error = err.message; diff --git a/brooks-lint/scripts/validate-repo.mjs b/brooks-lint/scripts/validate-repo.mjs index 3839f1a5..32131cb8 100644 --- a/brooks-lint/scripts/validate-repo.mjs +++ b/brooks-lint/scripts/validate-repo.mjs @@ -15,6 +15,8 @@ import { } from "./frontmatter.mjs"; import { GUIDE_BY_MODE, VALID_MODES } from "./assemble-prompt.mjs"; import { versionRefs } from "./version-refs.mjs"; +import { platformDocs, setupGuides, linkedSetupGuides, parseInstallerPlatforms } from "./platforms.mjs"; +import { render as renderStarHistory, readStamps as readStarStamps } from "./gen-star-history.mjs"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const root = path.resolve(__dirname, ".."); @@ -325,6 +327,49 @@ function checkAgentsDocs() { } } +// Every docs/-setup.md must be linked from all six READMEs and the +// getting-started table. A platform added to one language and forgotten in the +// others was previously caught only by hand. +function checkPlatformDocs() { + const guides = setupGuides(root); + check(guides.length > 0, "docs/ should contain at least one -setup.md guide"); + + for (const file of platformDocs(root)) { + const linked = linkedSetupGuides(readText(file)); + for (const guide of guides) { + check(linked.includes(guide), `${file} is missing an install-table link to docs/${guide}`); + } + for (const link of linked) { + check(guides.includes(link), `${file} links to docs/${link}, which does not exist`); + } + } +} + +function checkInstallerPlatforms() { + const { declared, global: globalArms, project } = parseInstallerPlatforms(readText("scripts/install.sh")); + check(declared.length > 0, "scripts/install.sh should declare a PLATFORMS list"); + + for (const [arms, fn] of [[globalArms, "global_dir"], [project, "project_dir"]]) { + for (const platform of declared) { + check(arms.includes(platform), `scripts/install.sh ${fn}() has no path for PLATFORMS entry '${platform}'`); + } + for (const platform of arms) { + check(declared.includes(platform), `scripts/install.sh ${fn}() maps '${platform}', which PLATFORMS omits`); + } + } +} + +// assets/star-history.svg is a pure function of assets/star-history.json, so a +// mismatch means the chart was hand-edited or the data moved without a redraw. +// Re-rendering here needs no credentials, which is the point of committing the +// data rather than the drawing alone. +function checkStarHistory() { + check( + renderStarHistory(readStarStamps()) === readText("assets/star-history.svg"), + "assets/star-history.svg does not match assets/star-history.json — rerun `node scripts/gen-star-history.mjs --render-only`", + ); +} + function checkSecurity() { const security = readText("SECURITY.md"); check(!security.includes(" + -- [](link) — +- [](link): ## Not yet specified @@ -62,67 +62,67 @@ Each ticket is a **child issue** of the map; the tracker's issue id is its ident ``` -Each ticket carries a `wayfinder:` label — one of `research`, `prototype`, `grilling`, `task` (see [Ticket Types](#ticket-types)). +Each ticket carries a `wayfinder:` label, one of `research`, `prototype`, `grilling`, `task` (see [Ticket Types](#ticket-types)). A session **claims** a ticket by assigning it to the dev driving the map, **first**, before any work, so concurrent sessions skip it. That assignee _is_ the claim: an open, unassigned ticket is unclaimed. -Blocking uses the tracker's **native** dependency relationship — essential because it renders the frontier _visually_ in the tracker's own UI, so the human sees what's takeable without opening the map. Only a tracker that lacks native blocking falls back to a body convention. A ticket is **unblocked** when every ticket blocking it is closed; the **frontier** is the open, unblocked, unclaimed children — the edge of the known. +Blocking uses the tracker's **native** dependency relationship: essential because it renders the frontier _visually_ in the tracker's own UI, so the human sees what's takeable without opening the map. Only a tracker that lacks native blocking falls back to a body convention. A ticket is **unblocked** when every ticket blocking it is closed; the **frontier** is the open, unblocked, unclaimed children, the edge of the known. -The answer isn't part of the body — it's recorded on resolution (see [Work through the map](#work-through-the-map)). Assets created while resolving a ticket are linked from the issue, not pasted in. +The answer isn't part of the body; it's recorded on resolution (see [Work through the map](#work-through-the-map)). Assets created while resolving a ticket are linked from the issue, not pasted in. ## Ticket Types -Every ticket is either **HITL** — human in the loop, worked _with_ a human who speaks for themselves — or **AFK**, driven by the agent alone. A HITL ticket only resolves through that live exchange; the agent never stands in for the human's side of it (a grilling agent that answers its own questions has broken this). +Every ticket is either **HITL** (human in the loop, worked _with_ a human who speaks for themselves) or **AFK**, driven by the agent alone. A HITL ticket only resolves through that live exchange; the agent never stands in for the human's side of it (a grilling agent that answers its own questions has broken this). -- **Research** (AFK): Reading documentation, third-party APIs, or local resources like knowledge bases to surface a fact a decision waits on. Resolved by a `/research` **subagent**. Use when knowledge outside the current working directory is required. -- **Prototype** (HITL): Raise the fidelity of the discussion by making a cheap, rough, concrete artifact to react to — an outline, a rough take, a stub, or UI/logic code via the /prototype skill. Links the prototype as an asset. Use when "how should it look" or "how should it behave" is the key question. -- **Grilling** (HITL): Conversation. The default case. Always invoke the /grilling and /domain-modeling skills. -- **Task** (HITL or AFK): Manual work that must happen before a _decision_ can be made — nothing to decide, prototype, or research, but the discussion is blocked until it's done. Signing up for a service so its API can be judged, provisioning access, moving data so its shape can be seen. This is the one type that _does_ rather than decides — and it earns its place by unblocking a decision, not by delivering the destination. The agent drives it alone where it can (AFK); otherwise it hands the human a precise checklist (HITL). Resolved when the work is done; the answer records what was done and any resulting facts (credentials location, new URLs, row counts) later tickets depend on. +- **Research** (AFK): Reading documentation, third-party APIs, or local resources like knowledge bases to surface a fact a decision waits on. Resolved by a subagent that calls the Skill tool with "research". Use when knowledge outside the current working directory is required. +- **Prototype** (HITL): Raise the fidelity of the discussion by making a cheap, rough, concrete artifact to react to (an outline, a rough take, a stub, or UI/logic code) by calling the Skill tool with "prototype". Links the prototype as an asset. Use when "how should it look" or "how should it behave" is the key question. +- **Grilling** (HITL): Conversation. The default case. Always call the Skill tool twice, for "grilling" and "domain-modeling". +- **Task** (HITL or AFK): Manual work that must happen before a _decision_ can be made: nothing to decide, prototype, or research, but the discussion is blocked until it's done. Signing up for a service so its API can be judged, provisioning access, moving data so its shape can be seen. This is the one type that _does_ rather than decides, and it earns its place by unblocking a decision, not by delivering the destination. The agent drives it alone where it can (AFK); otherwise it hands the human a precise checklist (HITL). Resolved when the work is done; the answer records what was done and any resulting facts (credentials location, new URLs, row counts) later tickets depend on. ## Fog of war -The map is _deliberately_ incomplete: don't chart what you can't yet see. Beyond the live tickets lies the **fog of war** — the dim view of decisions and investigations you can tell are coming but can't yet pin down, because they hang on questions still open. Resolving a ticket clears the fog ahead of it, graduating whatever's now specifiable into fresh tickets — one at a time, until the way to the destination is clear and no tickets remain. +The map is _deliberately_ incomplete: don't chart what you can't yet see. Beyond the live tickets lies the **fog of war**: the dim view of decisions and investigations you can tell are coming but can't yet pin down, because they hang on questions still open. Resolving a ticket clears the fog ahead of it, graduating whatever's now specifiable into fresh tickets, one at a time, until the way to the destination is clear and no tickets remain. -The map's **Not yet specified** section is where that dim view is written down: the suspected question, the area to revisit later. It's the undiscovered frontier _toward_ the destination — everything here is in scope, just not sharp enough to ticket. Write as loosely or as fully as the view allows; it doubles as a signpost for collaborators reading where the effort is headed. +The map's **Not yet specified** section is where that dim view is written down: the suspected question, the area to revisit later. It's the undiscovered frontier _toward_ the destination: everything here is in scope, just not sharp enough to ticket. Write as loosely or as fully as the view allows; it doubles as a signpost for collaborators reading where the effort is headed. -**Fog or ticket?** The test is whether you can state the question precisely now — _not_ whether you can answer it now. +**Fog or ticket?** The test is whether you can state the question precisely now, _not_ whether you can answer it now. -- **Ticket when** the question is already sharp — even if it's blocked and you can't act on it yet. +- **Ticket when** the question is already sharp, even if it's blocked and you can't act on it yet. - **Not yet specified when** you can't yet phrase it that sharply. Don't pre-slice the fog into ticket-sized pieces: it's coarser than a ticket, and one patch may graduate into several tickets, or none, once the frontier reaches it. **Not yet specified** excludes what's already decided (Decisions so far), what's already a live ticket, and what's out of scope (the next section). ## Out of scope -Fog only ever gathers _toward_ the destination. The destination fixes the scope, so work beyond it is **out of scope** — it isn't fog, and it doesn't belong in **Not yet specified**. It gets its own **Out of scope** section on the map: work you've consciously ruled out of _this_ effort. Scope, not sharpness, lands it here. +Fog only ever gathers _toward_ the destination. The destination fixes the scope, so work beyond it is **out of scope**: it isn't fog, and it doesn't belong in **Not yet specified**. It gets its own **Out of scope** section on the map: work you've consciously ruled out of _this_ effort. Scope, not sharpness, lands it here. -Out-of-scope work never graduates — the frontier stops at the destination — so it returns only if the destination is redrawn, and then as a fresh effort, not a resumption. +Out-of-scope work never graduates (the frontier stops at the destination), so it returns only if the destination is redrawn, and then as a fresh effort, not a resumption. -Ruling something out of scope is a scoping act, not a step on the route. When a ticket that already exists turns out to sit past the destination — mis-scoped in while charting, or exposed by a resolution — **close it** (a closed ticket is unambiguously off the frontier) and leave one line in the **Out of scope** section: the gist plus why it's out of scope, linking the closed ticket. It stays out of **Decisions so far**, which records the route actually walked — a scope boundary isn't a step on it. +Ruling something out of scope is a scoping act, not a step on the route. When a ticket that already exists turns out to sit past the destination (mis-scoped in while charting, or exposed by a resolution), **close it** (a closed ticket is unambiguously off the frontier) and leave one line in the **Out of scope** section: the gist plus why it's out of scope, linking the closed ticket. It stays out of **Decisions so far**, which records the route actually walked; a scope boundary isn't a step on it. ## Invocation -Two modes. Either way, **never resolve more than one ticket per session** — with the exception of research tickets. +Two modes. Either way, **never resolve more than one ticket per session**, with the exception of research tickets. ### Chart the map User invokes with a loose idea. -1. **Name the destination.** Run a `/grilling` and `/domain-modeling` session to pin down what this map is finding its way to — the spec, decision, or change. The destination fixes the scope, so it's settled first. -2. **Map the frontier.** Grill again, **breadth-first** this time: fan out across the whole space rather than deep on any one thread, surfacing the open decisions and the first steps takeable now. **If this surfaces no fog** — the way to the destination is already clear, the whole journey small enough for one session — you don't need a map. Stop and ask the user how they'd like to proceed. +1. **Name the destination.** Call the Skill tool twice, for "grilling" and "domain-modeling", to pin down what this map is finding its way to: the spec, decision, or change. The destination fixes the scope, so it's settled first. +2. **Map the frontier.** Grill again, **breadth-first** this time: fan out across the whole space rather than deep on any one thread, surfacing the open decisions and the first steps takeable now. **If this surfaces no fog** (the way to the destination is already clear, the whole journey small enough for one session), you don't need a map. Stop and ask the user how they'd like to proceed. 3. **Create the map** (label `wayfinder:map`): Destination and Notes filled in, Decisions-so-far empty, the fog sketched into **Not yet specified**. -4. **Create the tickets you can specify now** as child issues of the map — then wire blocking edges in a **second pass** (issues need ids before they can reference each other). Wiring sorts them into the frontier and the blocked; everything you can't yet specify stays in the fog — the **Not yet specified** section. -5. **Fire the research subagents.** For each `research` ticket you just created, spin up a `/research` subagent to resolve it in parallel, capturing its findings on a throwaway `research/` branch with a context pointer from the ticket. -6. Stop — charting is one session's work; it hand-resolves nothing. +4. **Create the tickets you can specify now** as child issues of the map, then wire blocking edges in a **second pass** (issues need ids before they can reference each other). Wiring sorts them into the frontier and the blocked; everything you can't yet specify stays in the fog: the **Not yet specified** section. +5. **Fire the research subagents.** For each `research` ticket you just created, spin up a subagent that calls the Skill tool with "research" to resolve it in parallel, capturing its findings on a throwaway `research/` branch with a context pointer from the ticket. +6. Stop: charting is one session's work; it hand-resolves nothing. ### Work through the map -User invokes with a map (URL or number). A ticket is **optional** — without one, you pick the next decision, not the user. +User invokes with a map (URL or number). A ticket is **optional**: without one, you pick the next decision, not the user. -1. Load the **map** — the low-res view, not every ticket body. +1. Load the **map**: the low-res view, not every ticket body. 2. Choose the ticket. If the user named one, use it. Otherwise take the first frontier ticket in order. **Claim it**: assign it to yourself before any work. -3. Resolve it — **zoom as needed**: fetch the full body of any related or closed ticket on demand; invoke the skills the `## Notes` block names. If in doubt, use `/grilling` and `/domain-modeling`. +3. Resolve it. **Zoom as needed**: fetch the full body of any related or closed ticket on demand; call the Skill tool for whichever skills the `## Notes` block names. If in doubt, call the Skill tool twice, for "grilling" and "domain-modeling". 4. Record the resolution: post the answer as a **resolution comment**, **close** the issue, and **append a context pointer** to the map's Decisions-so-far. -5. Add newly-surfaced tickets (create-then-wire); graduate any fog the answer has made specifiable, clearing each graduated patch from **Not yet specified** so it lives only as its new ticket. If the answer reveals a ticket — this one or another — sits beyond the destination, **rule it out of scope** rather than resolving it on the route. If the decision invalidates other parts of the map, update or delete those tickets. +5. Add newly-surfaced tickets (create-then-wire); graduate any fog the answer has made specifiable, clearing each graduated patch from **Not yet specified** so it lives only as its new ticket. If the answer reveals that a ticket (this one or another) sits beyond the destination, **rule it out of scope** rather than resolving it on the route. If the decision invalidates other parts of the map, update or delete those tickets. The user may run unblocked tickets in parallel, so expect other sessions to be editing the tracker concurrently. diff --git a/matt-pocock-skills/skills/engineering/wizard/SKILL.md b/matt-pocock-skills/skills/engineering/wizard/SKILL.md index fdc2a721..c4294ad8 100644 --- a/matt-pocock-skills/skills/engineering/wizard/SKILL.md +++ b/matt-pocock-skills/skills/engineering/wizard/SKILL.md @@ -7,38 +7,38 @@ description: Generate an interactive bash wizard that walks a human through step A **wizard** is a bash script that walks a human, step by step, through a manual procedure that's tedious to do by hand and tedious to re-explain to an AI every time. It opens each URL, says exactly what to click and copy, captures the values, writes them where they belong (`.env`, GitHub secrets), confirms at every stage, and shows how many stages are left. It might configure third-party services, run a one-off migration, or move the project from one state to another. -The delightful UX is already solved by [template.sh](template.sh) — stage-by-stage progress, confirmation gates, cross-platform URL opening (including WSL), hidden secret entry, idempotent `.env` upserts, `gh secret`/`gh variable` writes, and a closing summary. **Your job is only to scope the procedure and author its stages.** The library above the `STAGES` marker is identical in every wizard; that consistency is the point — never hand-edit it. +The delightful UX is already solved by [template.sh](template.sh): stage-by-stage progress, confirmation gates, cross-platform URL opening (including WSL), hidden secret entry, idempotent `.env` upserts, `gh secret`/`gh variable` writes, and a closing summary. **Your job is only to scope the procedure and author its stages.** The library above the `STAGES` marker is identical in every wizard; that consistency is the point: never hand-edit it. -A wizard is ephemeral by default — built for one run, saved to a scratch or `scripts/` path, deleted when the job's done. Commit it only when the user wants a repeatable setup path that should live in the repo. +A wizard is ephemeral by default: built for one run, saved to a scratch or `scripts/` path, deleted when the job's done. Commit it only when the user wants a repeatable setup path that should live in the repo. ## Process ### 1. Scope the procedure -Work out every manual step the human must take and every value that gets captured along the way. Read the repo first — don't ask cold: +Work out every manual step the human must take and every value that gets captured along the way. Read the repo first, don't ask cold: - For setup: `.env`, `.env.example`, `.env.*`, `README`, `docker-compose*`, framework config, and `.github/workflows/*` (every `secrets.*` / `vars.*` reference is a value the wizard must produce). - For a migration or transition: the current state, the target state, and the irreversible actions between them. -Then show the user the ordered list of stages and the values each produces, and confirm — they may add, drop, or reorder. +Then show the user the ordered list of stages and the values each produces, and confirm: they may add, drop, or reorder. -**Done when:** every stage is named in order, and for each captured value you know (a) where the human gets it, (b) where it's written (`.env`, a GitHub secret, both, or nowhere — some stages are pure actions), and (c) whether it's secret (hidden entry) or public. +**Done when:** every stage is named in order, and for each captured value you know (a) where the human gets it, (b) where it's written (`.env`, a GitHub secret, both, or nowhere; some stages are pure actions), and (c) whether it's secret (hidden entry) or public. ### 2. Map each stage's journey -For each stage, write the precise path a human follows: which URL to open, what to do there, where a value is shown, which variable it fills — e.g. "Dashboard → Developers → API keys → Reveal test key → copy". Where you don't actually know the current UI or the exact command, say so and ask the user or check the docs — never invent steps that may not exist. +For each stage, write the precise path a human follows: which URL to open, what to do there, where a value is shown, which variable it fills: e.g. "Dashboard → Developers → API keys → Reveal test key → copy". Where you don't actually know the current UI or the exact command, say so and ask the user or check the docs: never invent steps that may not exist. **Done when:** every stage traces to concrete instructions a stranger could follow. ### 3. Author the wizard -Copy `template.sh` to the target path. Replace the example stage with one `stage` per step, in dependency order. Use the library helpers — `stage`, `say`/`step`, `open_url`, `ask`/`ask_secret`, `write_env`, `set_secret`/`set_var`, `pause`/`confirm` — and set `TOTAL_STAGES` to the number of stages you wrote. +Copy `template.sh` to the target path. Replace the example stage with one `stage` per step, in dependency order. Use the library helpers: `stage`, `say`/`step`, `open_url`, `ask`/`ask_secret`, `write_env`, `set_secret`/`set_var`, `pause`/`confirm`. Set `TOTAL_STAGES` to the number of stages you wrote. -Hold the bar the template sets: open the URL before asking for its value, use `ask_secret` for anything secret, `write_env` every persisted value, `set_secret` only the values CI actually needs, and `confirm` before any irreversible action. Each `stage` clears the screen so only the current step is visible — keep a stage to one focused task so nothing the human needs scrolls away. Don't touch the library above the marker. +Hold the bar the template sets: open the URL before asking for its value, use `ask_secret` for anything secret, `write_env` every persisted value, `set_secret` only the values CI actually needs, and `confirm` before any irreversible action. Each `stage` clears the screen so only the current step is visible: keep a stage to one focused task so nothing the human needs scrolls away. Don't touch the library above the marker. ### 4. Verify and hand off - `bash -n