@baselane/packs 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +191 -0
- package/NOTICE +6 -0
- package/README.md +15 -0
- package/dist/ai-merge.d.ts +26 -0
- package/dist/ai-merge.js +165 -0
- package/dist/aliases.d.ts +7 -0
- package/dist/aliases.js +9 -0
- package/dist/compose-draft.d.ts +19 -0
- package/dist/compose-draft.js +170 -0
- package/dist/drift-detect.d.ts +8 -0
- package/dist/drift-detect.js +21 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +21 -0
- package/dist/ingest.d.ts +25 -0
- package/dist/ingest.js +262 -0
- package/dist/load.d.ts +7 -0
- package/dist/load.js +29 -0
- package/dist/manifest.d.ts +71 -0
- package/dist/manifest.js +208 -0
- package/dist/materialize-harness.d.ts +15 -0
- package/dist/materialize-harness.js +48 -0
- package/dist/merge-region.d.ts +60 -0
- package/dist/merge-region.js +166 -0
- package/dist/overlap.d.ts +32 -0
- package/dist/overlap.js +49 -0
- package/dist/pack-from-fileset.d.ts +13 -0
- package/dist/pack-from-fileset.js +133 -0
- package/dist/render/adapters.d.ts +6 -0
- package/dist/render/adapters.js +43 -0
- package/dist/render/agents-md.d.ts +3 -0
- package/dist/render/agents-md.js +49 -0
- package/dist/render/bundle-union.d.ts +10 -0
- package/dist/render/bundle-union.js +87 -0
- package/dist/render/bundle.d.ts +3 -0
- package/dist/render/bundle.js +51 -0
- package/dist/render/capabilities.d.ts +19 -0
- package/dist/render/capabilities.js +86 -0
- package/dist/render/claude.d.ts +3 -0
- package/dist/render/claude.js +92 -0
- package/dist/render/design.d.ts +27 -0
- package/dist/render/design.js +443 -0
- package/dist/render/graph.d.ts +11 -0
- package/dist/render/graph.js +245 -0
- package/dist/render/memory.d.ts +35 -0
- package/dist/render/memory.js +353 -0
- package/dist/render/render-pack.d.ts +3 -0
- package/dist/render/render-pack.js +43 -0
- package/dist/render/repo-union.d.ts +14 -0
- package/dist/render/repo-union.js +94 -0
- package/dist/render/rollout-files.d.ts +18 -0
- package/dist/render/rollout-files.js +39 -0
- package/dist/render/system-map.d.ts +8 -0
- package/dist/render/system-map.js +73 -0
- package/dist/render/tasks.d.ts +32 -0
- package/dist/render/tasks.js +327 -0
- package/dist/render/wiki.d.ts +30 -0
- package/dist/render/wiki.js +288 -0
- package/dist/seed/graph-seed.d.ts +17 -0
- package/dist/seed/graph-seed.js +18 -0
- package/dist/seed/wiki-seed.d.ts +23 -0
- package/dist/seed/wiki-seed.js +133 -0
- package/dist/seed-skills.d.ts +18 -0
- package/dist/seed-skills.js +134 -0
- package/dist/types.d.ts +122 -0
- package/dist/types.js +1 -0
- package/dist/validate.d.ts +30 -0
- package/dist/validate.js +397 -0
- package/package.json +38 -0
- package/packs/database-review/pack.json +44 -0
- package/packs/database-review/rendered/.baselane/capabilities.json +10 -0
- package/packs/database-review/rendered/.baselane/system-map/README.md +18 -0
- package/packs/database-review/rendered/.claude/agents/database-reviewer.md +8 -0
- package/packs/database-review/rendered/.claude/commands/db-review.md +6 -0
- package/packs/database-review/rendered/.claude/commands/map.md +6 -0
- package/packs/database-review/rendered/.claude/settings.json +26 -0
- package/packs/database-review/rendered/.github/copilot-instructions.md +48 -0
- package/packs/database-review/rendered/AGENTS.md +66 -0
- package/packs/database-review/rendered/CLAUDE.md +9 -0
- package/packs/database-review/rendered/GEMINI.md +3 -0
- package/packs/disciplined-workflow/pack.json +63 -0
- package/packs/disciplined-workflow/rendered/.baselane/capabilities.json +10 -0
- package/packs/disciplined-workflow/rendered/.baselane/tasks/README.md +36 -0
- package/packs/disciplined-workflow/rendered/.claude/agents/plan-reviewer.md +8 -0
- package/packs/disciplined-workflow/rendered/.claude/agents/task-reviewer.md +8 -0
- package/packs/disciplined-workflow/rendered/.claude/commands/brainstorm.md +6 -0
- package/packs/disciplined-workflow/rendered/.claude/commands/execute-plan.md +6 -0
- package/packs/disciplined-workflow/rendered/.claude/commands/plan-work.md +6 -0
- package/packs/disciplined-workflow/rendered/.claude/commands/write-plan.md +6 -0
- package/packs/disciplined-workflow/rendered/.claude/settings.json +24 -0
- package/packs/disciplined-workflow/rendered/.github/copilot-instructions.md +24 -0
- package/packs/disciplined-workflow/rendered/AGENTS.md +43 -0
- package/packs/disciplined-workflow/rendered/CLAUDE.md +12 -0
- package/packs/disciplined-workflow/rendered/GEMINI.md +3 -0
- package/packs/frontend-design/pack.json +129 -0
- package/packs/frontend-design/rendered/.claude/skills/clone/SKILL.md +39 -0
- package/packs/frontend-design/rendered/.claude/skills/functional-ui/SKILL.md +78 -0
- package/packs/frontend-design/rendered/.claude/skills/gsap/SKILL.md +36 -0
- package/packs/frontend-design/rendered/.claude/skills/gsap/gsap-core.md +254 -0
- package/packs/frontend-design/rendered/.claude/skills/gsap/gsap-frameworks.md +266 -0
- package/packs/frontend-design/rendered/.claude/skills/gsap/gsap-performance.md +79 -0
- package/packs/frontend-design/rendered/.claude/skills/gsap/gsap-plugins.md +433 -0
- package/packs/frontend-design/rendered/.claude/skills/gsap/gsap-react.md +136 -0
- package/packs/frontend-design/rendered/.claude/skills/gsap/gsap-scrolltrigger.md +296 -0
- package/packs/frontend-design/rendered/.claude/skills/gsap/gsap-timeline.md +107 -0
- package/packs/frontend-design/rendered/.claude/skills/gsap/gsap-utils.md +284 -0
- package/packs/frontend-design/rendered/.claude/skills/marketing-ui/SKILL.md +36 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/SKILL.md +267 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/base-vs-radix.md +306 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/cli.md +290 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/composition.md +195 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/customization.md +209 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/forms.md +192 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/icons.md +101 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/mcp.md +105 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/registry.md +277 -0
- package/packs/frontend-design/rendered/.claude/skills/shadcn/styling.md +162 -0
- package/packs/frontend-design/rendered/.github/copilot-instructions.md +474 -0
- package/packs/frontend-design/rendered/AGENTS.md +33 -0
- package/packs/frontend-design/rendered/CLAUDE.md +10 -0
- package/packs/frontend-design/rendered/GEMINI.md +456 -0
- package/packs/frontend-taste/pack.json +43 -0
- package/packs/frontend-taste/rendered/.baselane/capabilities.json +16 -0
- package/packs/frontend-taste/rendered/.claude/agents/taste-reviewer.md +8 -0
- package/packs/frontend-taste/rendered/.claude/commands/design-review.md +6 -0
- package/packs/frontend-taste/rendered/.claude/settings.json +15 -0
- package/packs/frontend-taste/rendered/.github/copilot-instructions.md +51 -0
- package/packs/frontend-taste/rendered/AGENTS.md +68 -0
- package/packs/frontend-taste/rendered/CLAUDE.md +8 -0
- package/packs/frontend-taste/rendered/DESIGN.md +72 -0
- package/packs/frontend-taste/rendered/GEMINI.md +3 -0
- package/packs/go-rules/pack.json +38 -0
- package/packs/go-rules/rendered/.claude/agents/go-reviewer.md +8 -0
- package/packs/go-rules/rendered/.claude/commands/go-review.md +6 -0
- package/packs/go-rules/rendered/.claude/settings.json +15 -0
- package/packs/go-rules/rendered/.github/copilot-instructions.md +44 -0
- package/packs/go-rules/rendered/AGENTS.md +54 -0
- package/packs/go-rules/rendered/CLAUDE.md +8 -0
- package/packs/go-rules/rendered/GEMINI.md +3 -0
- package/packs/python-rules/pack.json +38 -0
- package/packs/python-rules/rendered/.claude/agents/python-reviewer.md +8 -0
- package/packs/python-rules/rendered/.claude/commands/python-review.md +6 -0
- package/packs/python-rules/rendered/.claude/settings.json +15 -0
- package/packs/python-rules/rendered/.github/copilot-instructions.md +43 -0
- package/packs/python-rules/rendered/AGENTS.md +53 -0
- package/packs/python-rules/rendered/CLAUDE.md +8 -0
- package/packs/python-rules/rendered/GEMINI.md +3 -0
- package/packs/second-brain/pack.json +36 -0
- package/packs/second-brain/rendered/.baselane/capabilities.json +25 -0
- package/packs/second-brain/rendered/.baselane/memory/README.md +34 -0
- package/packs/second-brain/rendered/.baselane/wiki/README.md +62 -0
- package/packs/second-brain/rendered/.claude/agents/librarian.md +14 -0
- package/packs/second-brain/rendered/.claude/commands/remember.md +6 -0
- package/packs/second-brain/rendered/.claude/commands/wiki.md +6 -0
- package/packs/second-brain/rendered/.claude/settings.json +35 -0
- package/packs/second-brain/rendered/.github/copilot-instructions.md +24 -0
- package/packs/second-brain/rendered/AGENTS.md +41 -0
- package/packs/second-brain/rendered/CLAUDE.md +9 -0
- package/packs/second-brain/rendered/GEMINI.md +3 -0
- package/packs/security-review/pack.json +72 -0
- package/packs/security-review/rendered/.claude/agents/security-reviewer.md +8 -0
- package/packs/security-review/rendered/.claude/commands/security-audit.md +6 -0
- package/packs/security-review/rendered/.claude/commands/security-scan.md +6 -0
- package/packs/security-review/rendered/.claude/settings.json +35 -0
- package/packs/security-review/rendered/.claude/skills/security-audit/SKILL.md +44 -0
- package/packs/security-review/rendered/.claude/skills/validate-at-boundaries/SKILL.md +41 -0
- package/packs/security-review/rendered/.github/copilot-instructions.md +137 -0
- package/packs/security-review/rendered/AGENTS.md +66 -0
- package/packs/security-review/rendered/CLAUDE.md +11 -0
- package/packs/security-review/rendered/GEMINI.md +90 -0
- package/packs/software-engineer-harness/pack.json +98 -0
- package/packs/software-engineer-harness/rendered/.baselane/capabilities.json +15 -0
- package/packs/software-engineer-harness/rendered/.baselane/system-map/README.md +18 -0
- package/packs/software-engineer-harness/rendered/.baselane/tasks/README.md +36 -0
- package/packs/software-engineer-harness/rendered/.claude/agents/architect.md +8 -0
- package/packs/software-engineer-harness/rendered/.claude/agents/checker.md +8 -0
- package/packs/software-engineer-harness/rendered/.claude/agents/code-reviewer.md +8 -0
- package/packs/software-engineer-harness/rendered/.claude/agents/code-simplifier.md +8 -0
- package/packs/software-engineer-harness/rendered/.claude/agents/planner.md +8 -0
- package/packs/software-engineer-harness/rendered/.claude/agents/reviewer.md +8 -0
- package/packs/software-engineer-harness/rendered/.claude/commands/build-and-check.md +6 -0
- package/packs/software-engineer-harness/rendered/.claude/commands/map.md +6 -0
- package/packs/software-engineer-harness/rendered/.claude/commands/plan-change.md +6 -0
- package/packs/software-engineer-harness/rendered/.claude/commands/plan-work.md +6 -0
- package/packs/software-engineer-harness/rendered/.claude/commands/review-change.md +6 -0
- package/packs/software-engineer-harness/rendered/.claude/commands/tdd-task.md +6 -0
- package/packs/software-engineer-harness/rendered/.claude/settings.json +35 -0
- package/packs/software-engineer-harness/rendered/.github/copilot-instructions.md +37 -0
- package/packs/software-engineer-harness/rendered/AGENTS.md +58 -0
- package/packs/software-engineer-harness/rendered/CLAUDE.md +18 -0
- package/packs/software-engineer-harness/rendered/GEMINI.md +3 -0
- package/packs/systematic-debugging/pack.json +44 -0
- package/packs/systematic-debugging/rendered/.claude/agents/debugger.md +8 -0
- package/packs/systematic-debugging/rendered/.claude/commands/debug.md +6 -0
- package/packs/systematic-debugging/rendered/.claude/commands/root-cause.md +6 -0
- package/packs/systematic-debugging/rendered/.claude/settings.json +15 -0
- package/packs/systematic-debugging/rendered/.github/copilot-instructions.md +20 -0
- package/packs/systematic-debugging/rendered/AGENTS.md +31 -0
- package/packs/systematic-debugging/rendered/CLAUDE.md +9 -0
- package/packs/systematic-debugging/rendered/GEMINI.md +3 -0
- package/packs/token-efficiency-harness/pack.json +49 -0
- package/packs/token-efficiency-harness/rendered/.baselane/capabilities.json +10 -0
- package/packs/token-efficiency-harness/rendered/.baselane/memory/README.md +34 -0
- package/packs/token-efficiency-harness/rendered/.claude/agents/scout.md +8 -0
- package/packs/token-efficiency-harness/rendered/.claude/commands/handoff.md +6 -0
- package/packs/token-efficiency-harness/rendered/.claude/commands/remember.md +6 -0
- package/packs/token-efficiency-harness/rendered/.claude/commands/usage-audit.md +6 -0
- package/packs/token-efficiency-harness/rendered/.claude/settings.json +26 -0
- package/packs/token-efficiency-harness/rendered/.github/copilot-instructions.md +26 -0
- package/packs/token-efficiency-harness/rendered/AGENTS.md +44 -0
- package/packs/token-efficiency-harness/rendered/CLAUDE.md +10 -0
- package/packs/token-efficiency-harness/rendered/GEMINI.md +3 -0
- package/packs/typescript-rules/pack.json +46 -0
- package/packs/typescript-rules/rendered/.claude/agents/typescript-reviewer.md +8 -0
- package/packs/typescript-rules/rendered/.claude/commands/typescript-review.md +6 -0
- package/packs/typescript-rules/rendered/.claude/settings.json +15 -0
- package/packs/typescript-rules/rendered/.claude/skills/immutable-updates/SKILL.md +46 -0
- package/packs/typescript-rules/rendered/.github/copilot-instructions.md +89 -0
- package/packs/typescript-rules/rendered/AGENTS.md +55 -0
- package/packs/typescript-rules/rendered/CLAUDE.md +9 -0
- package/packs/typescript-rules/rendered/GEMINI.md +51 -0
- package/skills/algorithmic-art/LICENSE +202 -0
- package/skills/algorithmic-art/LICENSE.txt +202 -0
- package/skills/algorithmic-art/SKILL.md +405 -0
- package/skills/algorithmic-art/templates/generator_template.js +223 -0
- package/skills/algorithmic-art/templates/viewer.html +599 -0
- package/skills/brainstorming/LICENSE +21 -0
- package/skills/brainstorming/SKILL.md +159 -0
- package/skills/brainstorming/scripts/frame-template.html +213 -0
- package/skills/brainstorming/scripts/helper.js +167 -0
- package/skills/brainstorming/scripts/server.cjs +723 -0
- package/skills/brainstorming/scripts/start-server.sh +209 -0
- package/skills/brainstorming/scripts/stop-server.sh +120 -0
- package/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/skills/brainstorming/visual-companion.md +291 -0
- package/skills/brand-guidelines/LICENSE +202 -0
- package/skills/brand-guidelines/LICENSE.txt +202 -0
- package/skills/brand-guidelines/SKILL.md +73 -0
- package/skills/canvas-design/LICENSE +202 -0
- package/skills/canvas-design/LICENSE.txt +202 -0
- package/skills/canvas-design/SKILL.md +130 -0
- package/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/skills/dispatching-parallel-agents/LICENSE +21 -0
- package/skills/dispatching-parallel-agents/SKILL.md +185 -0
- package/skills/executing-plans/LICENSE +21 -0
- package/skills/executing-plans/SKILL.md +70 -0
- package/skills/finishing-a-development-branch/LICENSE +21 -0
- package/skills/finishing-a-development-branch/SKILL.md +241 -0
- package/skills/first-party/README.md +32 -0
- package/skills/first-party/append-only-jsonl-stores/SKILL.md +50 -0
- package/skills/first-party/golden-snapshot-discipline/SKILL.md +45 -0
- package/skills/first-party/immutable-updates/SKILL.md +46 -0
- package/skills/first-party/manifest.json +10 -0
- package/skills/first-party/ts-extension-imports/SKILL.md +49 -0
- package/skills/first-party/validate-at-boundaries/SKILL.md +41 -0
- package/skills/first-party/zero-dependency-discipline/SKILL.md +41 -0
- package/skills/frontend-design/LICENSE +177 -0
- package/skills/frontend-design/LICENSE.txt +177 -0
- package/skills/frontend-design/SKILL.md +55 -0
- package/skills/internal-comms/LICENSE +202 -0
- package/skills/internal-comms/LICENSE.txt +202 -0
- package/skills/internal-comms/SKILL.md +32 -0
- package/skills/internal-comms/examples/3p-updates.md +47 -0
- package/skills/internal-comms/examples/company-newsletter.md +65 -0
- package/skills/internal-comms/examples/faq-answers.md +30 -0
- package/skills/internal-comms/examples/general-comms.md +16 -0
- package/skills/mcp-builder/LICENSE +202 -0
- package/skills/mcp-builder/LICENSE.txt +202 -0
- package/skills/mcp-builder/SKILL.md +236 -0
- package/skills/mcp-builder/reference/evaluation.md +602 -0
- package/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/skills/mcp-builder/reference/node_mcp_server.md +970 -0
- package/skills/mcp-builder/reference/python_mcp_server.md +719 -0
- package/skills/mcp-builder/scripts/connections.py +151 -0
- package/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/skills/receiving-code-review/LICENSE +21 -0
- package/skills/receiving-code-review/SKILL.md +213 -0
- package/skills/requesting-code-review/LICENSE +21 -0
- package/skills/requesting-code-review/SKILL.md +103 -0
- package/skills/requesting-code-review/code-reviewer.md +172 -0
- package/skills/seed-manifest.json +185 -0
- package/skills/skill-creator/LICENSE +202 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +485 -0
- package/skills/skill-creator/agents/analyzer.md +274 -0
- package/skills/skill-creator/agents/comparator.md +202 -0
- package/skills/skill-creator/agents/grader.md +223 -0
- package/skills/skill-creator/assets/eval_review.html +146 -0
- package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/skill-creator/references/schemas.md +430 -0
- package/skills/skill-creator/scripts/__init__.py +0 -0
- package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/skill-creator/scripts/generate_report.py +326 -0
- package/skills/skill-creator/scripts/improve_description.py +247 -0
- package/skills/skill-creator/scripts/package_skill.py +136 -0
- package/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/skills/skill-creator/scripts/run_eval.py +310 -0
- package/skills/skill-creator/scripts/run_loop.py +328 -0
- package/skills/skill-creator/scripts/utils.py +47 -0
- package/skills/slack-gif-creator/LICENSE +202 -0
- package/skills/slack-gif-creator/LICENSE.txt +202 -0
- package/skills/slack-gif-creator/SKILL.md +254 -0
- package/skills/slack-gif-creator/core/easing.py +234 -0
- package/skills/slack-gif-creator/core/frame_composer.py +176 -0
- package/skills/slack-gif-creator/core/gif_builder.py +269 -0
- package/skills/slack-gif-creator/core/validators.py +136 -0
- package/skills/slack-gif-creator/requirements.txt +4 -0
- package/skills/subagent-driven-development/LICENSE +21 -0
- package/skills/subagent-driven-development/SKILL.md +418 -0
- package/skills/subagent-driven-development/implementer-prompt.md +139 -0
- package/skills/subagent-driven-development/scripts/review-package +44 -0
- package/skills/subagent-driven-development/scripts/sdd-workspace +22 -0
- package/skills/subagent-driven-development/scripts/task-brief +40 -0
- package/skills/subagent-driven-development/task-reviewer-prompt.md +188 -0
- package/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/skills/systematic-debugging/LICENSE +21 -0
- package/skills/systematic-debugging/SKILL.md +296 -0
- package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/skills/systematic-debugging/find-polluter.sh +63 -0
- package/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/skills/systematic-debugging/test-academic.md +14 -0
- package/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/skills/test-driven-development/LICENSE +21 -0
- package/skills/test-driven-development/SKILL.md +371 -0
- package/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/skills/theme-factory/LICENSE +202 -0
- package/skills/theme-factory/LICENSE.txt +202 -0
- package/skills/theme-factory/SKILL.md +59 -0
- package/skills/theme-factory/theme-showcase.pdf +0 -0
- package/skills/theme-factory/themes/arctic-frost.md +19 -0
- package/skills/theme-factory/themes/botanical-garden.md +19 -0
- package/skills/theme-factory/themes/desert-rose.md +19 -0
- package/skills/theme-factory/themes/forest-canopy.md +19 -0
- package/skills/theme-factory/themes/golden-hour.md +19 -0
- package/skills/theme-factory/themes/midnight-galaxy.md +19 -0
- package/skills/theme-factory/themes/modern-minimalist.md +19 -0
- package/skills/theme-factory/themes/ocean-depths.md +19 -0
- package/skills/theme-factory/themes/sunset-boulevard.md +19 -0
- package/skills/theme-factory/themes/tech-innovation.md +19 -0
- package/skills/using-git-worktrees/LICENSE +21 -0
- package/skills/using-git-worktrees/SKILL.md +202 -0
- package/skills/using-superpowers/LICENSE +21 -0
- package/skills/using-superpowers/SKILL.md +62 -0
- package/skills/using-superpowers/references/antigravity-tools.md +23 -0
- package/skills/using-superpowers/references/codex-tools.md +39 -0
- package/skills/using-superpowers/references/pi-tools.md +16 -0
- package/skills/verification-before-completion/LICENSE +21 -0
- package/skills/verification-before-completion/SKILL.md +139 -0
- package/skills/web-artifacts-builder/LICENSE +202 -0
- package/skills/web-artifacts-builder/LICENSE.txt +202 -0
- package/skills/web-artifacts-builder/SKILL.md +74 -0
- package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/skills/web-artifacts-builder/scripts/init-artifact.sh +322 -0
- package/skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/skills/webapp-testing/LICENSE +202 -0
- package/skills/webapp-testing/LICENSE.txt +202 -0
- package/skills/webapp-testing/SKILL.md +96 -0
- package/skills/webapp-testing/examples/console_logging.py +35 -0
- package/skills/webapp-testing/examples/element_discovery.py +40 -0
- package/skills/webapp-testing/examples/static_html_automation.py +33 -0
- package/skills/webapp-testing/scripts/with_server.py +106 -0
- package/skills/writing-plans/LICENSE +21 -0
- package/skills/writing-plans/SKILL.md +174 -0
- package/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
package/dist/validate.js
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
function fail(field, want) {
|
|
2
|
+
throw new Error(`workflow-pack: ${field} must be ${want}`);
|
|
3
|
+
}
|
|
4
|
+
function str(obj, field, path = field) {
|
|
5
|
+
const v = obj[field];
|
|
6
|
+
if (typeof v !== "string" || v.length === 0)
|
|
7
|
+
fail(path, "a non-empty string");
|
|
8
|
+
return v;
|
|
9
|
+
}
|
|
10
|
+
function line(obj, field, path = field) {
|
|
11
|
+
const v = str(obj, field, path);
|
|
12
|
+
if (v.includes("\n"))
|
|
13
|
+
fail(path, "a single line (no newline characters)");
|
|
14
|
+
return v;
|
|
15
|
+
}
|
|
16
|
+
/** Like `line()` but allows the empty string — used for hook `matcher`, which is legitimately
|
|
17
|
+
* blank on events (e.g. "Stop") that have no tool to filter by. Render-time scaffolding
|
|
18
|
+
* constructs hooks with `matcher: ""` directly as typed `PackHook` object literals (see
|
|
19
|
+
* render/memory.ts, wiki.ts, tasks.ts, graph.ts, system-map.ts) — that's type-level intent
|
|
20
|
+
* only, never itself passed through this validator. But those same rendered packs DO get
|
|
21
|
+
* round-tripped through `validatePack` later (e.g. saved as a custom pack), so this must
|
|
22
|
+
* accept the empty-matcher shape rather than reject it. */
|
|
23
|
+
function lineOrEmpty(obj, field, path = field) {
|
|
24
|
+
const v = obj[field];
|
|
25
|
+
if (typeof v !== "string")
|
|
26
|
+
fail(path, "a string");
|
|
27
|
+
if (v.includes("\n"))
|
|
28
|
+
fail(path, "a single line (no newline characters)");
|
|
29
|
+
return v;
|
|
30
|
+
}
|
|
31
|
+
const SLUG = /^[a-z0-9][a-z0-9-]*$/;
|
|
32
|
+
// Capability methods may carry a `+`-joined modifier (e.g. system-map's "analyze+llm" — the
|
|
33
|
+
// analyze method with the optional LLM narration flag on), so `method` gets its own slightly
|
|
34
|
+
// wider pattern instead of loosening the shared `slug()` used for pack/agent/command ids.
|
|
35
|
+
const METHOD_SLUG = /^[a-z0-9][a-z0-9+-]*$/;
|
|
36
|
+
function slug(obj, field, path = field) {
|
|
37
|
+
const v = str(obj, field, path);
|
|
38
|
+
if (!SLUG.test(v))
|
|
39
|
+
fail(path, "a lowercase slug (letters, digits, dashes)");
|
|
40
|
+
return v;
|
|
41
|
+
}
|
|
42
|
+
function methodSlug(obj, field, path = field) {
|
|
43
|
+
const v = str(obj, field, path);
|
|
44
|
+
if (!METHOD_SLUG.test(v))
|
|
45
|
+
fail(path, "a lowercase slug (letters, digits, dashes, plus)");
|
|
46
|
+
return v;
|
|
47
|
+
}
|
|
48
|
+
function arr(obj, field) {
|
|
49
|
+
const v = obj[field];
|
|
50
|
+
if (!Array.isArray(v))
|
|
51
|
+
fail(field, "an array");
|
|
52
|
+
return v;
|
|
53
|
+
}
|
|
54
|
+
/** #23: an array of pack/skill names (slugs) — used by relatedTo/supersedes catalog cross-links. */
|
|
55
|
+
function slugArray(obj, field) {
|
|
56
|
+
return arr(obj, field).map((v, i) => {
|
|
57
|
+
if (typeof v !== "string" || !SLUG.test(v))
|
|
58
|
+
fail(`${field}[${i}]`, "a lowercase slug (a pack or skill name)");
|
|
59
|
+
return v;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function rec(v, path) {
|
|
63
|
+
if (typeof v !== "object" || v === null || Array.isArray(v))
|
|
64
|
+
fail(path, "an object");
|
|
65
|
+
return v;
|
|
66
|
+
}
|
|
67
|
+
function bool(obj, field, path = field) {
|
|
68
|
+
const v = obj[field];
|
|
69
|
+
if (typeof v !== "boolean")
|
|
70
|
+
fail(path, "a boolean");
|
|
71
|
+
return v;
|
|
72
|
+
}
|
|
73
|
+
function stringArray(obj, field, path = field) {
|
|
74
|
+
const v = obj[field];
|
|
75
|
+
if (!Array.isArray(v) || v.some((t) => typeof t !== "string" || t.length === 0)) {
|
|
76
|
+
fail(path, "an array of non-empty strings");
|
|
77
|
+
}
|
|
78
|
+
return v;
|
|
79
|
+
}
|
|
80
|
+
/** Like `stringArray()` but rejects a newline in any element — for arrays whose entries are
|
|
81
|
+
* joined raw into a single YAML frontmatter line (e.g. skill `allowed-tools`), where an embedded
|
|
82
|
+
* newline would inject extra frontmatter keys. */
|
|
83
|
+
function lineStringArray(obj, field, path = field) {
|
|
84
|
+
const v = obj[field];
|
|
85
|
+
if (!Array.isArray(v) || v.some((t) => typeof t !== "string" || t.length === 0 || t.includes("\n"))) {
|
|
86
|
+
fail(path, "an array of single-line non-empty strings");
|
|
87
|
+
}
|
|
88
|
+
return v;
|
|
89
|
+
}
|
|
90
|
+
/** Optional per-agent MCP servers (increment 30): a map of server name → { command, args? }.
|
|
91
|
+
* Preserved from harness bundles that scope tools per-agent; validated structurally like
|
|
92
|
+
* capability config so a stored agent can never encode a shape the render can't emit. */
|
|
93
|
+
function mcpServersMap(v, path) {
|
|
94
|
+
const o = rec(v, path);
|
|
95
|
+
const out = {};
|
|
96
|
+
for (const key of Object.keys(o)) {
|
|
97
|
+
// The server name is emitted raw as a YAML key (`${name}:`) and `command` as a raw
|
|
98
|
+
// `command: ${cfg.command}` line (render/claude.ts mcpServersYaml) — both must be
|
|
99
|
+
// single-line/slug-shaped or a crafted value could inject extra frontmatter keys.
|
|
100
|
+
if (!SLUG.test(key))
|
|
101
|
+
fail(`${path}.${key}`, "a lowercase slug (letters, digits, dashes)");
|
|
102
|
+
const s = rec(o[key], `${path}.${key}`);
|
|
103
|
+
const command = line(s, "command", `${path}.${key}.command`);
|
|
104
|
+
out[key] = {
|
|
105
|
+
command,
|
|
106
|
+
...(s.args !== undefined ? { args: stringArray(s, "args", `${path}.${key}.args`) } : {}),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
function agent(v, i) {
|
|
112
|
+
const o = rec(v, `agents[${i}]`);
|
|
113
|
+
const tools = o.tools;
|
|
114
|
+
if (!Array.isArray(tools) || tools.some((t) => typeof t !== "string")) {
|
|
115
|
+
fail(`agents[${i}].tools`, "an array of strings");
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
name: slug(o, "name", `agents[${i}].name`),
|
|
119
|
+
description: line(o, "description", `agents[${i}].description`),
|
|
120
|
+
tools: tools,
|
|
121
|
+
model: str(o, "model", `agents[${i}].model`),
|
|
122
|
+
prompt: str(o, "prompt", `agents[${i}].prompt`),
|
|
123
|
+
...(o.provenance !== undefined ? { provenance: blockProvenance(o.provenance, `agents[${i}].provenance`) } : {}),
|
|
124
|
+
...(o.mcpServers !== undefined ? { mcpServers: mcpServersMap(o.mcpServers, `agents[${i}].mcpServers`) } : {}),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function command(v, i) {
|
|
128
|
+
const o = rec(v, `commands[${i}]`);
|
|
129
|
+
return {
|
|
130
|
+
name: slug(o, "name", `commands[${i}].name`),
|
|
131
|
+
description: line(o, "description", `commands[${i}].description`),
|
|
132
|
+
argument_hint: line(o, "argument_hint", `commands[${i}].argument_hint`),
|
|
133
|
+
prompt: line(o, "prompt", `commands[${i}].prompt`),
|
|
134
|
+
...(o.provenance !== undefined ? { provenance: blockProvenance(o.provenance, `commands[${i}].provenance`) } : {}),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
// The fixed set of lifecycle events Claude Code actually fires hooks on. `line()` alone would
|
|
138
|
+
// accept any string, so a misspelled event (e.g. "PostToolUsee") would validate cleanly, render
|
|
139
|
+
// verbatim into settings.json, and then simply never fire — a silent no-op "guardrail" (bug #11).
|
|
140
|
+
// Exported (via index.ts) so the portal's pack-builder form can offer the same fixed list instead
|
|
141
|
+
// of a free-text field that only fails later, at validatePack time.
|
|
142
|
+
export const KNOWN_HOOK_EVENTS = [
|
|
143
|
+
"PreToolUse",
|
|
144
|
+
"PostToolUse",
|
|
145
|
+
"Notification",
|
|
146
|
+
"UserPromptSubmit",
|
|
147
|
+
"Stop",
|
|
148
|
+
"SubagentStop",
|
|
149
|
+
"PreCompact",
|
|
150
|
+
"SessionStart",
|
|
151
|
+
"SessionEnd",
|
|
152
|
+
];
|
|
153
|
+
const KNOWN_HOOK_EVENTS_SET = new Set(KNOWN_HOOK_EVENTS);
|
|
154
|
+
function hookEvent(obj, field, path = field) {
|
|
155
|
+
const v = line(obj, field, path);
|
|
156
|
+
if (!KNOWN_HOOK_EVENTS_SET.has(v)) {
|
|
157
|
+
fail(path, `a known Claude Code lifecycle event (${KNOWN_HOOK_EVENTS.join(", ")})`);
|
|
158
|
+
}
|
|
159
|
+
return v;
|
|
160
|
+
}
|
|
161
|
+
function hook(v, i) {
|
|
162
|
+
const o = rec(v, `hooks[${i}]`);
|
|
163
|
+
if (o.action !== "print-reminder" && o.action !== "run-command") {
|
|
164
|
+
fail(`hooks[${i}].action`, '"print-reminder" or "run-command"');
|
|
165
|
+
}
|
|
166
|
+
const base = {
|
|
167
|
+
event: hookEvent(o, "event", `hooks[${i}].event`),
|
|
168
|
+
matcher: lineOrEmpty(o, "matcher", `hooks[${i}].matcher`),
|
|
169
|
+
description: line(o, "description", `hooks[${i}].description`),
|
|
170
|
+
...(o.provenance !== undefined ? { provenance: blockProvenance(o.provenance, `hooks[${i}].provenance`) } : {}),
|
|
171
|
+
};
|
|
172
|
+
if (o.action === "run-command") {
|
|
173
|
+
return { ...base, action: "run-command", command: line(o, "command", `hooks[${i}].command`) };
|
|
174
|
+
}
|
|
175
|
+
return { ...base, action: "print-reminder", message: line(o, "message", `hooks[${i}].message`) };
|
|
176
|
+
}
|
|
177
|
+
/** Optional per-block provenance (increment 26): validated like attribution — reject wrong
|
|
178
|
+
* shapes, pass valid ones through; callers omit the key entirely when absent. */
|
|
179
|
+
function blockProvenance(v, path) {
|
|
180
|
+
const o = rec(v, path);
|
|
181
|
+
const componentId = line(o, "componentId", `${path}.componentId`);
|
|
182
|
+
const version = o.version;
|
|
183
|
+
if (typeof version !== "number" || !Number.isInteger(version) || version < 1) {
|
|
184
|
+
fail(`${path}.version`, "a positive integer");
|
|
185
|
+
}
|
|
186
|
+
return { componentId, version };
|
|
187
|
+
}
|
|
188
|
+
function capability(v, i) {
|
|
189
|
+
const o = rec(v, `capabilities[${i}]`);
|
|
190
|
+
const type = o.type;
|
|
191
|
+
if (type !== "memory" && type !== "tasks" && type !== "wiki" && type !== "graph" && type !== "design" && type !== "system-map") {
|
|
192
|
+
fail(`capabilities[${i}].type`, '"memory", "tasks", "wiki", "graph", "design", or "system-map"');
|
|
193
|
+
}
|
|
194
|
+
const store = o.store;
|
|
195
|
+
if (store !== "org" && store !== "repo") {
|
|
196
|
+
fail(`capabilities[${i}].store`, '"org" or "repo"');
|
|
197
|
+
}
|
|
198
|
+
const method = methodSlug(o, "method", `capabilities[${i}].method`);
|
|
199
|
+
const prov = o.provenance !== undefined ? { provenance: blockProvenance(o.provenance, `capabilities[${i}].provenance`) } : {};
|
|
200
|
+
if (o.config === undefined)
|
|
201
|
+
return { type, store, method, ...prov };
|
|
202
|
+
const rawConfig = rec(o.config, `capabilities[${i}].config`);
|
|
203
|
+
const config = {};
|
|
204
|
+
for (const key of Object.keys(rawConfig)) {
|
|
205
|
+
config[key] = line(rawConfig, key, `capabilities[${i}].config.${key}`);
|
|
206
|
+
}
|
|
207
|
+
return { type, store, method, config, ...prov };
|
|
208
|
+
}
|
|
209
|
+
/** Capabilities that render to the same output artifact collide silently if two are declared for
|
|
210
|
+
* one store — the render layer keys by a fixed path and the second write clobbers the first, while
|
|
211
|
+
* the capabilities manifest still prints both "provisioned". Reject the contradiction at the source:
|
|
212
|
+
* #21 memory "files" and "native" each own the `/remember` command + a fact store — at most one.
|
|
213
|
+
* (claude-mem/vector/letta only add Stop hooks, so they stack harmlessly and are unrestricted.)
|
|
214
|
+
* #20/#37 every design method (author/import/analyze) renders the single root DESIGN.md — at most
|
|
215
|
+
* one design capability per store; a second is dropped by render/design.ts's `.find()`. */
|
|
216
|
+
function assertNoCapabilityConflicts(capabilities) {
|
|
217
|
+
for (const store of ["org", "repo"]) {
|
|
218
|
+
const inStore = capabilities.filter((c) => c.store === store);
|
|
219
|
+
const memory = new Set(inStore.filter((c) => c.type === "memory").map((c) => c.method));
|
|
220
|
+
if (memory.has("files") && memory.has("native")) {
|
|
221
|
+
fail("capabilities", `at most one of memory "files" or "native" per store (both declared for "${store}" — they own conflicting /remember commands)`);
|
|
222
|
+
}
|
|
223
|
+
if (inStore.filter((c) => c.type === "design").length > 1) {
|
|
224
|
+
fail("capabilities", `at most one design capability per store (multiple declared for "${store}" — they all render the single DESIGN.md)`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function attribution(v) {
|
|
229
|
+
const o = rec(v, "attribution");
|
|
230
|
+
return {
|
|
231
|
+
source: line(o, "source", "attribution.source"),
|
|
232
|
+
url: line(o, "url", "attribution.url"),
|
|
233
|
+
license: line(o, "license", "attribution.license"),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function scope(v) {
|
|
237
|
+
if (v !== "repo" && v !== "developer" && v !== "both")
|
|
238
|
+
fail("scope", '"repo", "developer", or "both"');
|
|
239
|
+
return v;
|
|
240
|
+
}
|
|
241
|
+
function onboarding(v) {
|
|
242
|
+
if (!Array.isArray(v))
|
|
243
|
+
fail("onboarding", "an array");
|
|
244
|
+
const seen = new Set();
|
|
245
|
+
return v.map((raw, i) => {
|
|
246
|
+
const o = rec(raw, `onboarding[${i}]`);
|
|
247
|
+
const id = slug(o, "id", `onboarding[${i}].id`);
|
|
248
|
+
if (seen.has(id))
|
|
249
|
+
fail(`onboarding[${i}].id`, "unique within the pack");
|
|
250
|
+
seen.add(id);
|
|
251
|
+
return {
|
|
252
|
+
id,
|
|
253
|
+
title: line(o, "title", `onboarding[${i}].title`),
|
|
254
|
+
description: line(o, "description", `onboarding[${i}].description`),
|
|
255
|
+
...(o.command !== undefined ? { command: line(o, "command", `onboarding[${i}].command`) } : {}),
|
|
256
|
+
};
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
export const SKILL_NAME_MAX = 64;
|
|
260
|
+
export const SKILL_DESC_MAX = 1024;
|
|
261
|
+
export const SKILL_BODY_MAX_LINES = 500;
|
|
262
|
+
export const SKILL_BODY_WARN_LINES = 400;
|
|
263
|
+
const XML_TAG = /<\/?[a-zA-Z][^>]*>/;
|
|
264
|
+
/** name: slug, ≤64 chars. A name containing "anthropic"/"claude" is NOT rejected here — that
|
|
265
|
+
* restriction is agentskills.io's anti-impersonation rule for the *public upload* path, not a
|
|
266
|
+
* filesystem/catalog file-validity rule, so it must not hard-reject legitimate first-party
|
|
267
|
+
* content in baselane's own library (e.g. an imported `claude-api` skill). skillLints() below
|
|
268
|
+
* surfaces it as an amber advisory instead. */
|
|
269
|
+
function skillName(obj, path) {
|
|
270
|
+
const v = str(obj, "name", `${path}.name`);
|
|
271
|
+
if (!SLUG.test(v))
|
|
272
|
+
fail(`${path}.name`, "a lowercase slug (letters, digits, dashes)");
|
|
273
|
+
if (v.length > SKILL_NAME_MAX)
|
|
274
|
+
fail(`${path}.name`, `at most ${SKILL_NAME_MAX} characters`);
|
|
275
|
+
return v;
|
|
276
|
+
}
|
|
277
|
+
/** description: non-empty single line, ≤1024 chars, no XML tag (discovery field — kept clean). */
|
|
278
|
+
function skillDescription(obj, path) {
|
|
279
|
+
const v = line(obj, "description", `${path}.description`);
|
|
280
|
+
if (v.length > SKILL_DESC_MAX)
|
|
281
|
+
fail(`${path}.description`, `at most ${SKILL_DESC_MAX} characters`);
|
|
282
|
+
if (XML_TAG.test(v))
|
|
283
|
+
fail(`${path}.description`, "free of XML tags");
|
|
284
|
+
return v;
|
|
285
|
+
}
|
|
286
|
+
/** body: non-empty markdown, ≤500 lines (hard ceiling; the 400-line soft warning is a skillLint). */
|
|
287
|
+
function skillBody(obj, path) {
|
|
288
|
+
const v = str(obj, "body", `${path}.body`);
|
|
289
|
+
if (v.split("\n").length > SKILL_BODY_MAX_LINES) {
|
|
290
|
+
fail(`${path}.body`, `at most ${SKILL_BODY_MAX_LINES} lines`);
|
|
291
|
+
}
|
|
292
|
+
return v;
|
|
293
|
+
}
|
|
294
|
+
function skillReference(v, path) {
|
|
295
|
+
const o = rec(v, path);
|
|
296
|
+
return {
|
|
297
|
+
name: slug(o, "name", `${path}.name`),
|
|
298
|
+
body: str(o, "body", `${path}.body`),
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/** The single skill validator, path-parameterised so validatePack (`skills[i]`) and validateSkill
|
|
302
|
+
* (`skill`) share one code path. Reuses attribution()/blockProvenance() so a skill's optional
|
|
303
|
+
* licence notice and library link validate exactly like a pack's. */
|
|
304
|
+
function skillAt(v, path) {
|
|
305
|
+
const o = rec(v, path);
|
|
306
|
+
return {
|
|
307
|
+
name: skillName(o, path),
|
|
308
|
+
description: skillDescription(o, path),
|
|
309
|
+
body: skillBody(o, path),
|
|
310
|
+
category: slug(o, "category", `${path}.category`),
|
|
311
|
+
...(o.references !== undefined
|
|
312
|
+
? { references: arr(o, "references").map((r, i) => skillReference(r, `${path}.references[${i}]`)) }
|
|
313
|
+
: {}),
|
|
314
|
+
...(o.attribution !== undefined ? { attribution: attribution(o.attribution) } : {}),
|
|
315
|
+
...(o.provenance !== undefined ? { provenance: blockProvenance(o.provenance, `${path}.provenance`) } : {}),
|
|
316
|
+
// Governance frontmatter — validated with kebab-case error paths (matching the SKILL.md keys)
|
|
317
|
+
// so a lint points the author at the frontmatter line they wrote, not the internal camelCase.
|
|
318
|
+
...(o.userInvocable !== undefined ? { userInvocable: bool(o, "userInvocable", `${path}.user-invocable`) } : {}),
|
|
319
|
+
...(o.disableModelInvocation !== undefined ? { disableModelInvocation: bool(o, "disableModelInvocation", `${path}.disable-model-invocation`) } : {}),
|
|
320
|
+
...(o.allowedTools !== undefined ? { allowedTools: lineStringArray(o, "allowedTools", `${path}.allowed-tools`) } : {}),
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
/** The sole authority on a SkillBlock — mirrors validatePack for skills. Throws (like validatePack)
|
|
324
|
+
* on anything invalid; callers guard. */
|
|
325
|
+
export function validateSkill(raw) {
|
|
326
|
+
return skillAt(raw, "skill");
|
|
327
|
+
}
|
|
328
|
+
/** Non-throwing soft advisories surfaced when a skill is created or edited (portal's
|
|
329
|
+
* /app/skills/save, rendered as an amber notice by skillsPage — never blocks a save): warns when a
|
|
330
|
+
* body nears the 500-line ceiling, and when a name contains "anthropic"/"claude" (agentskills.io's
|
|
331
|
+
* public-upload anti-impersonation signal — worth an admin's attention here, but not a reject).
|
|
332
|
+
* Hard violations are rejected by validateSkill; this only surfaces amber. */
|
|
333
|
+
export function skillLints(block) {
|
|
334
|
+
const lints = [];
|
|
335
|
+
if (block.body.split("\n").length >= SKILL_BODY_WARN_LINES) {
|
|
336
|
+
lints.push({ field: "body", message: `body is approaching the ${SKILL_BODY_MAX_LINES}-line limit; split into references` });
|
|
337
|
+
}
|
|
338
|
+
if (block.name.includes("anthropic") || block.name.includes("claude")) {
|
|
339
|
+
lints.push({ field: "name", message: 'name contains the reserved word "anthropic" or "claude" — confirm this is legitimate first-party content, not impersonation' });
|
|
340
|
+
}
|
|
341
|
+
return lints;
|
|
342
|
+
}
|
|
343
|
+
export function validatePack(raw) {
|
|
344
|
+
const o = rec(raw, "root");
|
|
345
|
+
const context = rec(o.context, "context");
|
|
346
|
+
const capabilities = o.capabilities !== undefined ? arr(o, "capabilities").map(capability) : undefined;
|
|
347
|
+
if (capabilities)
|
|
348
|
+
assertNoCapabilityConflicts(capabilities);
|
|
349
|
+
return {
|
|
350
|
+
id: slug(o, "id"),
|
|
351
|
+
version: str(o, "version"),
|
|
352
|
+
title: line(o, "title"),
|
|
353
|
+
summary: line(o, "summary"),
|
|
354
|
+
context: { markdown: str(context, "markdown", "context.markdown") },
|
|
355
|
+
...(o.attribution !== undefined ? { attribution: attribution(o.attribution) } : {}),
|
|
356
|
+
...(o.scope !== undefined ? { scope: scope(o.scope) } : {}),
|
|
357
|
+
...(capabilities !== undefined ? { capabilities } : {}),
|
|
358
|
+
...(o.onboarding !== undefined ? { onboarding: onboarding(o.onboarding) } : {}),
|
|
359
|
+
...(o.skills !== undefined ? { skills: arr(o, "skills").map((v, i) => skillAt(v, `skills[${i}]`)) } : {}),
|
|
360
|
+
...(o.relatedTo !== undefined ? { relatedTo: slugArray(o, "relatedTo") } : {}),
|
|
361
|
+
...(o.supersedes !== undefined ? { supersedes: slugArray(o, "supersedes") } : {}),
|
|
362
|
+
agents: arr(o, "agents").map(agent),
|
|
363
|
+
commands: arr(o, "commands").map(command),
|
|
364
|
+
hooks: arr(o, "hooks").map(hook),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
/** Validates a single reusable library-component payload by reusing the EXACT block validators
|
|
368
|
+
* validatePack uses (`agent`/`command`/`hook`/`capability` above) — so a stored component can never
|
|
369
|
+
* encode a block validatePack would later reject. Returns the canonical, extra-field-stripped block
|
|
370
|
+
* (or the markdown string for "rules"). Throws (like validatePack) on anything invalid; callers guard. */
|
|
371
|
+
export function validateComponent(blockType, payload) {
|
|
372
|
+
switch (blockType) {
|
|
373
|
+
case "agent":
|
|
374
|
+
return agent(payload, 0);
|
|
375
|
+
case "command":
|
|
376
|
+
return command(payload, 0);
|
|
377
|
+
case "hook":
|
|
378
|
+
return hook(payload, 0);
|
|
379
|
+
case "capability":
|
|
380
|
+
return capability(payload, 0);
|
|
381
|
+
case "rules":
|
|
382
|
+
if (typeof payload !== "string" || payload.length === 0) {
|
|
383
|
+
fail("rules", "a non-empty markdown string");
|
|
384
|
+
}
|
|
385
|
+
return payload;
|
|
386
|
+
default: {
|
|
387
|
+
const exhaustive = blockType;
|
|
388
|
+
fail("blockType", `one of agent, command, hook, rules, capability (got ${String(exhaustive)})`);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/** The pack's target scope, defaulting an absent scope to "repo" so every pre-increment-28 pack
|
|
393
|
+
* (built-in or custom) keeps today's repo behavior. This is the ONLY place the default is applied —
|
|
394
|
+
* validatePack never injects `scope` into the object, so a pack's bytes round-trip unchanged. */
|
|
395
|
+
export function packScope(pack) {
|
|
396
|
+
return pack.scope ?? "repo";
|
|
397
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@baselane/packs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "WorkflowPack schema, validation, and render pipeline, plus the built-in packs shipped by the baselane CLI.",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"license": "Apache-2.0",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/mohammad0omar/baselane.sh.git",
|
|
11
|
+
"directory": "packages/packs"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://baselane.sh",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"packs/",
|
|
17
|
+
"skills/",
|
|
18
|
+
"NOTICE",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@baselane/analyze": "0.1.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^24.0.0",
|
|
29
|
+
"typescript": "^5.9.0",
|
|
30
|
+
"vitest": "^2.0.0"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"build": "tsc -p tsconfig.build.json"
|
|
36
|
+
},
|
|
37
|
+
"types": "./dist/index.d.ts"
|
|
38
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://baselane.dev/schema/workflow-pack-v1.json",
|
|
3
|
+
"id": "database-review",
|
|
4
|
+
"version": "1.2.0",
|
|
5
|
+
"title": "Database review",
|
|
6
|
+
"summary": "Query, schema, and migration review judgment a linter can't encode — index every foreign key, kill N+1s, keep queries parameterized, ship migrations that don't lock production — with a reviewer and a sqlfluff guard.",
|
|
7
|
+
"scope": "repo",
|
|
8
|
+
"attribution": { "source": "affaan-m/ECC", "url": "https://github.com/affaan-m/ECC", "license": "MIT" },
|
|
9
|
+
"context": {
|
|
10
|
+
"markdown": "## Database review discipline\n\n`sqlfluff` catches SQL style and obvious mistakes — this pack is the judgment it can't encode, applied in review of any query, schema, or migration before it reaches production.\n\n### Query performance\n\n- Every column in a `WHERE` or `JOIN` should be indexed — confirm with `EXPLAIN ANALYZE`, don't assume.\n- Watch for N+1: a query inside a loop over rows from a previous query. Batch or join it.\n- Composite indexes put equality columns before range columns.\n\n### Schema design\n\n- Use precise types: timestamp-with-timezone for times, decimal/numeric for money, `text` over an arbitrary varchar cap.\n- Every foreign key gets an index — no exceptions.\n- Put constraints (`NOT NULL`, `CHECK`, `ON DELETE`) in the schema, not only in application code.\n\n### Migration safety\n\n- Adding a `NOT NULL` column to a large table needs a backfill, not just a default — check in-flight writes during the migration.\n- Don't hold locks across an external call or a slow backfill; batch the backfill.\n- Every migration has a rollback path.\n\n### Data-layer security\n\n- Queries are parameterized, never string-concatenated with user input.\n- Multi-tenant tables enforce row-level access at the database, not only in application code.\n- Application database users get least-privilege grants, never blanket admin.\n\n### Flag in review\n\n- `SELECT *` in application code shipped to production.\n- Offset pagination on large, frequently-written tables — prefer cursor pagination.\n- `INSERT`s in a loop instead of a batch/multi-row insert.\n- Inconsistent lock ordering across transactions touching the same tables (deadlock risk).\n"
|
|
11
|
+
},
|
|
12
|
+
"agents": [
|
|
13
|
+
{
|
|
14
|
+
"name": "database-reviewer",
|
|
15
|
+
"description": "Reviews SQL, schema changes, and migrations for missing indexes, N+1 queries, unsafe migrations, and injection risk. Use when writing queries, schemas, or migrations, or troubleshooting database performance.",
|
|
16
|
+
"tools": ["Read", "Grep", "Glob", "Bash"],
|
|
17
|
+
"model": "sonnet",
|
|
18
|
+
"prompt": "You are a database reviewer. Before reviewing, consult ARCHITECTURE.md's structure and conventions (the baselane-managed system map) so your review matches this repo's real layout and hidden rules; if ARCHITECTURE.md does not exist yet, suggest running /map regenerate (or baselane map . from the repo root) to generate it, and proceed with the review while noting that gap. Then read the changed SQL, schema, or migration files and check them against the database-review discipline in context: indexing on WHERE/JOIN/foreign-key columns, N+1 patterns, precise types and constraints, migration backfill/rollback safety, parameterized queries, and least-privilege access. Cite exact file:line for each finding, name the concrete failure mode (e.g. \"this JOIN on orders.user_id has no index — table scan at N rows\"), and give severity. If the change is sound, say so."
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"commands": [
|
|
22
|
+
{
|
|
23
|
+
"name": "db-review",
|
|
24
|
+
"description": "Run the database-reviewer over the current query, schema, or migration changes.",
|
|
25
|
+
"argument_hint": "[optional: path or diff ref]",
|
|
26
|
+
"prompt": "Invoke the database-reviewer subagent over the current diff (or $ARGUMENTS if given). Report findings grouped by area (indexing, schema, migration safety, security) with file:line and fix for each. End with a clear verdict."
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"hooks": [
|
|
30
|
+
{
|
|
31
|
+
"event": "PostToolUse",
|
|
32
|
+
"matcher": "Edit|Write",
|
|
33
|
+
"description": "After an edit, lint SQL and migrations with sqlfluff when it is installed.",
|
|
34
|
+
"action": "run-command",
|
|
35
|
+
"command": "if command -v sqlfluff >/dev/null 2>&1; then sqlfluff lint --disable-progress-bar .; else echo \"sqlfluff not found — pip install sqlfluff to lint SQL/migrations (database-review)\"; fi"
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"onboarding": [
|
|
39
|
+
{ "id": "generate-system-map", "title": "Generate the system map", "description": "Analyze the repository's import graph into ARCHITECTURE.md.", "command": "baselane map ." }
|
|
40
|
+
],
|
|
41
|
+
"capabilities": [
|
|
42
|
+
{ "type": "system-map", "store": "repo", "method": "analyze" }
|
|
43
|
+
]
|
|
44
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# System map
|
|
2
|
+
|
|
3
|
+
`ARCHITECTURE.md` at the repo root carries a baselane-managed region generated from static
|
|
4
|
+
analysis: languages, layout, commands, import-graph hotspots, and measured conventions —
|
|
5
|
+
including **hidden rules** (conventions the code follows at >=90% consistency that no lint
|
|
6
|
+
config enforces). Human prose outside the managed region is never touched.
|
|
7
|
+
|
|
8
|
+
## Regenerating
|
|
9
|
+
|
|
10
|
+
Run `baselane map .` from the repo root after structural changes (modules added/moved,
|
|
11
|
+
commands changed, conventions shifted). Add `--llm` for an AI-narrated architecture section
|
|
12
|
+
(needs BASELANE_ANTHROPIC_KEY or ANTHROPIC_API_KEY). Commit the refreshed `ARCHITECTURE.md`
|
|
13
|
+
and `.baselane/system-map/report.json` together.
|
|
14
|
+
|
|
15
|
+
## Reading it
|
|
16
|
+
|
|
17
|
+
Consult ARCHITECTURE.md's conventions section before writing code — the hidden rules are the
|
|
18
|
+
ones nobody will tell you about in review until you break them.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: database-reviewer
|
|
3
|
+
description: Reviews SQL, schema changes, and migrations for missing indexes, N+1 queries, unsafe migrations, and injection risk. Use when writing queries, schemas, or migrations, or troubleshooting database performance.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a database reviewer. Before reviewing, consult ARCHITECTURE.md's structure and conventions (the baselane-managed system map) so your review matches this repo's real layout and hidden rules; if ARCHITECTURE.md does not exist yet, suggest running /map regenerate (or baselane map . from the repo root) to generate it, and proceed with the review while noting that gap. Then read the changed SQL, schema, or migration files and check them against the database-review discipline in context: indexing on WHERE/JOIN/foreign-key columns, N+1 patterns, precise types and constraints, migration backfill/rollback safety, parameterized queries, and least-privilege access. Cite exact file:line for each finding, name the concrete failure mode (e.g. "this JOIN on orders.user_id has no index — table scan at N rows"), and give severity. If the change is sound, say so.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run the database-reviewer over the current query, schema, or migration changes.
|
|
3
|
+
argument-hint: [optional: path or diff ref]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Invoke the database-reviewer subagent over the current diff (or $ARGUMENTS if given). Report findings grouped by area (indexing, schema, migration safety, security) with file:line and fix for each. End with a clear verdict.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Consult or regenerate the generated ARCHITECTURE.md system map.
|
|
3
|
+
argument-hint: <question about the architecture | "regenerate">
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Follow the protocol in `.baselane/system-map/README.md` for $ARGUMENTS. For a question, read `ARCHITECTURE.md` (the baselane-managed region) and answer from it — especially the Conventions & hidden rules section — before grepping. If $ARGUMENTS is "regenerate" (or modules/commands/conventions just changed), run `baselane map .` from the repo root and commit the refreshed ARCHITECTURE.md and .baselane/system-map/report.json.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"PostToolUse": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "Edit|Write",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "if command -v sqlfluff >/dev/null 2>&1; then sqlfluff lint --disable-progress-bar .; else echo \"sqlfluff not found — pip install sqlfluff to lint SQL/migrations (database-review)\"; fi"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"Stop": [
|
|
15
|
+
{
|
|
16
|
+
"matcher": "",
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "echo \"Before finishing, if you added/moved modules, changed commands, or shifted a convention, regenerate the system map (`baselane map .`) — see .baselane/system-map/README.md.\""
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copilot instructions
|
|
2
|
+
|
|
3
|
+
## Database review discipline
|
|
4
|
+
|
|
5
|
+
`sqlfluff` catches SQL style and obvious mistakes — this pack is the judgment it can't encode, applied in review of any query, schema, or migration before it reaches production.
|
|
6
|
+
|
|
7
|
+
### Query performance
|
|
8
|
+
|
|
9
|
+
- Every column in a `WHERE` or `JOIN` should be indexed — confirm with `EXPLAIN ANALYZE`, don't assume.
|
|
10
|
+
- Watch for N+1: a query inside a loop over rows from a previous query. Batch or join it.
|
|
11
|
+
- Composite indexes put equality columns before range columns.
|
|
12
|
+
|
|
13
|
+
### Schema design
|
|
14
|
+
|
|
15
|
+
- Use precise types: timestamp-with-timezone for times, decimal/numeric for money, `text` over an arbitrary varchar cap.
|
|
16
|
+
- Every foreign key gets an index — no exceptions.
|
|
17
|
+
- Put constraints (`NOT NULL`, `CHECK`, `ON DELETE`) in the schema, not only in application code.
|
|
18
|
+
|
|
19
|
+
### Migration safety
|
|
20
|
+
|
|
21
|
+
- Adding a `NOT NULL` column to a large table needs a backfill, not just a default — check in-flight writes during the migration.
|
|
22
|
+
- Don't hold locks across an external call or a slow backfill; batch the backfill.
|
|
23
|
+
- Every migration has a rollback path.
|
|
24
|
+
|
|
25
|
+
### Data-layer security
|
|
26
|
+
|
|
27
|
+
- Queries are parameterized, never string-concatenated with user input.
|
|
28
|
+
- Multi-tenant tables enforce row-level access at the database, not only in application code.
|
|
29
|
+
- Application database users get least-privilege grants, never blanket admin.
|
|
30
|
+
|
|
31
|
+
### Flag in review
|
|
32
|
+
|
|
33
|
+
- `SELECT *` in application code shipped to production.
|
|
34
|
+
- Offset pagination on large, frequently-written tables — prefer cursor pagination.
|
|
35
|
+
- `INSERT`s in a loop instead of a batch/multi-row insert.
|
|
36
|
+
- Inconsistent lock ordering across transactions touching the same tables (deadlock risk).
|
|
37
|
+
|
|
38
|
+
## Workflow pack: Database review
|
|
39
|
+
|
|
40
|
+
Query, schema, and migration review judgment a linter can't encode — index every foreign key, kill N+1s, keep queries parameterized, ship migrations that don't lock production — with a reviewer and a sqlfluff guard.
|
|
41
|
+
|
|
42
|
+
When acting as the database-reviewer role: You are a database reviewer. Before reviewing, consult ARCHITECTURE.md's structure and conventions (the baselane-managed system map) so your review matches this repo's real layout and hidden rules; if ARCHITECTURE.md does not exist yet, suggest running /map regenerate (or baselane map . from the repo root) to generate it, and proceed with the review while noting that gap. Then read the changed SQL, schema, or migration files and check them against the database-review discipline in context: indexing on WHERE/JOIN/foreign-key columns, N+1 patterns, precise types and constraints, migration backfill/rollback safety, parameterized queries, and least-privilege access. Cite exact file:line for each finding, name the concrete failure mode (e.g. "this JOIN on orders.user_id has no index — table scan at N rows"), and give severity. If the change is sound, say so.
|
|
43
|
+
|
|
44
|
+
Workflow steps:
|
|
45
|
+
|
|
46
|
+
- db-review: Invoke the database-reviewer subagent over the current diff (or $ARGUMENTS if given). Report findings grouped by area (indexing, schema, migration safety, security) with file:line and fix for each. End with a clear verdict.
|
|
47
|
+
|
|
48
|
+
- After an edit, lint SQL and migrations with sqlfluff when it is installed.
|