@lucasi/vibes 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/AGENTS.md +162 -0
- package/MIGRATION.md +368 -0
- package/README.md +44 -0
- package/bin/setup.js +127 -0
- package/commands/build-fix.md +56 -0
- package/commands/checkpoint.md +67 -0
- package/commands/code-review.md +68 -0
- package/commands/e2e.md +105 -0
- package/commands/eval.md +88 -0
- package/commands/evolve.md +36 -0
- package/commands/go-build.md +87 -0
- package/commands/go-review.md +71 -0
- package/commands/go-test.md +131 -0
- package/commands/harness-audit.md +73 -0
- package/commands/instinct-export.md +93 -0
- package/commands/instinct-import.md +88 -0
- package/commands/instinct-status.md +29 -0
- package/commands/learn.md +61 -0
- package/commands/loop-start.md +32 -0
- package/commands/loop-status.md +24 -0
- package/commands/model-route.md +26 -0
- package/commands/orchestrate.md +88 -0
- package/commands/plan.md +25 -0
- package/commands/projects.md +23 -0
- package/commands/promote.md +23 -0
- package/commands/quality-gate.md +29 -0
- package/commands/refactor-clean.md +102 -0
- package/commands/rust-build.md +78 -0
- package/commands/rust-review.md +65 -0
- package/commands/rust-test.md +104 -0
- package/commands/security.md +89 -0
- package/commands/setup-pm.md +67 -0
- package/commands/skill-create.md +117 -0
- package/commands/tdd.md +67 -0
- package/commands/test-coverage.md +80 -0
- package/commands/update-codemaps.md +81 -0
- package/commands/update-docs.md +67 -0
- package/commands/verify.md +67 -0
- package/instructions/INSTRUCTIONS.md +337 -0
- package/opencode.json +466 -0
- package/package.json +27 -0
- package/prompts/agents/architect.txt +175 -0
- package/prompts/agents/build-error-resolver.txt +233 -0
- package/prompts/agents/code-reviewer.txt +103 -0
- package/prompts/agents/cpp-build-resolver.txt +81 -0
- package/prompts/agents/cpp-reviewer.txt +65 -0
- package/prompts/agents/database-reviewer.txt +247 -0
- package/prompts/agents/doc-updater.txt +192 -0
- package/prompts/agents/docs-lookup.txt +57 -0
- package/prompts/agents/e2e-runner.txt +305 -0
- package/prompts/agents/go-build-resolver.txt +325 -0
- package/prompts/agents/go-reviewer.txt +241 -0
- package/prompts/agents/harness-optimizer.txt +27 -0
- package/prompts/agents/java-build-resolver.txt +123 -0
- package/prompts/agents/java-reviewer.txt +97 -0
- package/prompts/agents/kotlin-build-resolver.txt +120 -0
- package/prompts/agents/kotlin-reviewer.txt +127 -0
- package/prompts/agents/loop-operator.txt +39 -0
- package/prompts/agents/planner.txt +113 -0
- package/prompts/agents/python-reviewer.txt +85 -0
- package/prompts/agents/refactor-cleaner.txt +241 -0
- package/prompts/agents/rust-build-resolver.txt +93 -0
- package/prompts/agents/rust-reviewer.txt +61 -0
- package/prompts/agents/security-reviewer.txt +207 -0
- package/prompts/agents/tdd-guide.txt +216 -0
- package/skills/agent-eval/SKILL.md +145 -0
- package/skills/agent-harness-construction/SKILL.md +73 -0
- package/skills/agent-introspection-debugging/SKILL.md +153 -0
- package/skills/agent-payment-x402/SKILL.md +178 -0
- package/skills/agent-sort/SKILL.md +215 -0
- package/skills/agentic-engineering/SKILL.md +63 -0
- package/skills/ai-first-engineering/SKILL.md +51 -0
- package/skills/ai-regression-testing/SKILL.md +385 -0
- package/skills/android-clean-architecture/SKILL.md +339 -0
- package/skills/api-connector-builder/SKILL.md +120 -0
- package/skills/api-design/SKILL.md +523 -0
- package/skills/architecture-decision-records/SKILL.md +179 -0
- package/skills/article-writing/SKILL.md +79 -0
- package/skills/automation-audit-ops/SKILL.md +142 -0
- package/skills/autonomous-agent-harness/SKILL.md +267 -0
- package/skills/autonomous-loops/SKILL.md +610 -0
- package/skills/backend-patterns/SKILL.md +598 -0
- package/skills/benchmark/SKILL.md +93 -0
- package/skills/blueprint/SKILL.md +105 -0
- package/skills/brand-voice/SKILL.md +97 -0
- package/skills/brand-voice/references/voice-profile-schema.md +55 -0
- package/skills/browser-qa/SKILL.md +87 -0
- package/skills/bun-runtime/SKILL.md +84 -0
- package/skills/canary-watch/SKILL.md +99 -0
- package/skills/carrier-relationship-management/SKILL.md +212 -0
- package/skills/ck/SKILL.md +147 -0
- package/skills/ck/commands/forget.mjs +44 -0
- package/skills/ck/commands/info.mjs +24 -0
- package/skills/ck/commands/init.mjs +143 -0
- package/skills/ck/commands/list.mjs +40 -0
- package/skills/ck/commands/migrate.mjs +202 -0
- package/skills/ck/commands/resume.mjs +36 -0
- package/skills/ck/commands/save.mjs +210 -0
- package/skills/ck/commands/shared.mjs +387 -0
- package/skills/ck/hooks/session-start.mjs +224 -0
- package/skills/claude-api/SKILL.md +337 -0
- package/skills/claude-devfleet/SKILL.md +103 -0
- package/skills/click-path-audit/SKILL.md +244 -0
- package/skills/clickhouse-io/SKILL.md +439 -0
- package/skills/code-tour/SKILL.md +236 -0
- package/skills/codebase-onboarding/SKILL.md +233 -0
- package/skills/coding-standards/SKILL.md +549 -0
- package/skills/compose-multiplatform-patterns/SKILL.md +299 -0
- package/skills/configure-ecc/SKILL.md +367 -0
- package/skills/connections-optimizer/SKILL.md +189 -0
- package/skills/content-engine/SKILL.md +131 -0
- package/skills/content-hash-cache-pattern/SKILL.md +161 -0
- package/skills/context-budget/SKILL.md +135 -0
- package/skills/continuous-agent-loop/SKILL.md +45 -0
- package/skills/continuous-learning/SKILL.md +123 -0
- package/skills/continuous-learning/config.json +18 -0
- package/skills/continuous-learning/evaluate-session.sh +69 -0
- package/skills/continuous-learning-v2/SKILL.md +365 -0
- package/skills/continuous-learning-v2/agents/observer-loop.sh +282 -0
- package/skills/continuous-learning-v2/agents/observer.md +198 -0
- package/skills/continuous-learning-v2/agents/session-guardian.sh +150 -0
- package/skills/continuous-learning-v2/agents/start-observer.sh +244 -0
- package/skills/continuous-learning-v2/config.json +8 -0
- package/skills/continuous-learning-v2/hooks/observe.sh +428 -0
- package/skills/continuous-learning-v2/scripts/detect-project.sh +228 -0
- package/skills/continuous-learning-v2/scripts/instinct-cli.py +1426 -0
- package/skills/continuous-learning-v2/scripts/test_parse_instinct.py +984 -0
- package/skills/cost-aware-llm-pipeline/SKILL.md +183 -0
- package/skills/council/SKILL.md +203 -0
- package/skills/cpp-coding-standards/SKILL.md +723 -0
- package/skills/cpp-testing/SKILL.md +324 -0
- package/skills/crosspost/SKILL.md +111 -0
- package/skills/csharp-testing/SKILL.md +321 -0
- package/skills/customer-billing-ops/SKILL.md +140 -0
- package/skills/customs-trade-compliance/SKILL.md +263 -0
- package/skills/dart-flutter-patterns/SKILL.md +563 -0
- package/skills/dashboard-builder/SKILL.md +108 -0
- package/skills/data-scraper-agent/SKILL.md +764 -0
- package/skills/database-migrations/SKILL.md +429 -0
- package/skills/deep-research/SKILL.md +155 -0
- package/skills/defi-amm-security/SKILL.md +160 -0
- package/skills/deployment-patterns/SKILL.md +427 -0
- package/skills/design-system/SKILL.md +82 -0
- package/skills/django-patterns/SKILL.md +734 -0
- package/skills/django-security/SKILL.md +593 -0
- package/skills/django-tdd/SKILL.md +729 -0
- package/skills/django-verification/SKILL.md +469 -0
- package/skills/dmux-workflows/SKILL.md +191 -0
- package/skills/docker-patterns/SKILL.md +364 -0
- package/skills/documentation-lookup/SKILL.md +90 -0
- package/skills/dotnet-patterns/SKILL.md +321 -0
- package/skills/e2e-testing/SKILL.md +326 -0
- package/skills/ecc-tools-cost-audit/SKILL.md +160 -0
- package/skills/email-ops/SKILL.md +121 -0
- package/skills/energy-procurement/SKILL.md +228 -0
- package/skills/enterprise-agent-ops/SKILL.md +50 -0
- package/skills/eval-harness/SKILL.md +270 -0
- package/skills/evm-token-decimals/SKILL.md +130 -0
- package/skills/exa-search/SKILL.md +103 -0
- package/skills/fal-ai-media/SKILL.md +284 -0
- package/skills/finance-billing-ops/SKILL.md +127 -0
- package/skills/flutter-dart-code-review/SKILL.md +435 -0
- package/skills/foundation-models-on-device/SKILL.md +243 -0
- package/skills/frontend-design/SKILL.md +145 -0
- package/skills/frontend-patterns/SKILL.md +642 -0
- package/skills/frontend-slides/SKILL.md +184 -0
- package/skills/frontend-slides/STYLE_PRESETS.md +330 -0
- package/skills/gan-style-harness/SKILL.md +278 -0
- package/skills/git-workflow/SKILL.md +715 -0
- package/skills/github-ops/SKILL.md +144 -0
- package/skills/golang-patterns/SKILL.md +674 -0
- package/skills/golang-testing/SKILL.md +720 -0
- package/skills/google-workspace-ops/SKILL.md +95 -0
- package/skills/healthcare-cdss-patterns/SKILL.md +245 -0
- package/skills/healthcare-emr-patterns/SKILL.md +159 -0
- package/skills/healthcare-eval-harness/SKILL.md +207 -0
- package/skills/healthcare-phi-compliance/SKILL.md +145 -0
- package/skills/hexagonal-architecture/SKILL.md +276 -0
- package/skills/hipaa-compliance/SKILL.md +78 -0
- package/skills/hookify-rules/SKILL.md +128 -0
- package/skills/inventory-demand-planning/SKILL.md +247 -0
- package/skills/investor-materials/SKILL.md +96 -0
- package/skills/investor-outreach/SKILL.md +91 -0
- package/skills/iterative-retrieval/SKILL.md +211 -0
- package/skills/java-coding-standards/SKILL.md +147 -0
- package/skills/jira-integration/SKILL.md +293 -0
- package/skills/jpa-patterns/SKILL.md +151 -0
- package/skills/knowledge-ops/SKILL.md +154 -0
- package/skills/kotlin-coroutines-flows/SKILL.md +284 -0
- package/skills/kotlin-exposed-patterns/SKILL.md +719 -0
- package/skills/kotlin-ktor-patterns/SKILL.md +689 -0
- package/skills/kotlin-patterns/SKILL.md +711 -0
- package/skills/kotlin-testing/SKILL.md +824 -0
- package/skills/laravel-patterns/SKILL.md +415 -0
- package/skills/laravel-plugin-discovery/SKILL.md +229 -0
- package/skills/laravel-security/SKILL.md +285 -0
- package/skills/laravel-tdd/SKILL.md +283 -0
- package/skills/laravel-verification/SKILL.md +179 -0
- package/skills/lead-intelligence/SKILL.md +321 -0
- package/skills/lead-intelligence/agents/enrichment-agent.md +85 -0
- package/skills/lead-intelligence/agents/mutual-mapper.md +75 -0
- package/skills/lead-intelligence/agents/outreach-drafter.md +98 -0
- package/skills/lead-intelligence/agents/signal-scorer.md +60 -0
- package/skills/liquid-glass-design/SKILL.md +279 -0
- package/skills/llm-trading-agent-security/SKILL.md +146 -0
- package/skills/logistics-exception-management/SKILL.md +222 -0
- package/skills/manim-video/SKILL.md +89 -0
- package/skills/manim-video/assets/network_graph_scene.py +52 -0
- package/skills/market-research/SKILL.md +75 -0
- package/skills/mcp-server-patterns/SKILL.md +69 -0
- package/skills/messages-ops/SKILL.md +104 -0
- package/skills/nanoclaw-repl/SKILL.md +33 -0
- package/skills/nestjs-patterns/SKILL.md +230 -0
- package/skills/nextjs-turbopack/SKILL.md +44 -0
- package/skills/nodejs-keccak256/SKILL.md +102 -0
- package/skills/nutrient-document-processing/SKILL.md +167 -0
- package/skills/nuxt4-patterns/SKILL.md +100 -0
- package/skills/openclaw-persona-forge/SKILL.md +296 -0
- package/skills/openclaw-persona-forge/gacha.py +224 -0
- package/skills/openclaw-persona-forge/gacha.sh +5 -0
- package/skills/openclaw-persona-forge/references/avatar-style.md +124 -0
- package/skills/openclaw-persona-forge/references/boundary-rules.md +53 -0
- package/skills/openclaw-persona-forge/references/error-handling.md +53 -0
- package/skills/openclaw-persona-forge/references/identity-tension.md +48 -0
- package/skills/openclaw-persona-forge/references/naming-system.md +39 -0
- package/skills/openclaw-persona-forge/references/output-template.md +166 -0
- package/skills/opensource-pipeline/SKILL.md +255 -0
- package/skills/pencil-design/SKILL.md +175 -0
- package/skills/perl-patterns/SKILL.md +504 -0
- package/skills/perl-security/SKILL.md +503 -0
- package/skills/perl-testing/SKILL.md +475 -0
- package/skills/plankton-code-quality/SKILL.md +236 -0
- package/skills/postgres-patterns/SKILL.md +147 -0
- package/skills/product-capability/SKILL.md +141 -0
- package/skills/product-lens/SKILL.md +92 -0
- package/skills/production-scheduling/SKILL.md +238 -0
- package/skills/project-flow-ops/SKILL.md +111 -0
- package/skills/prompt-optimizer/SKILL.md +397 -0
- package/skills/python-patterns/SKILL.md +750 -0
- package/skills/python-testing/SKILL.md +816 -0
- package/skills/pytorch-patterns/SKILL.md +396 -0
- package/skills/quality-nonconformance/SKILL.md +260 -0
- package/skills/ralphinho-rfc-pipeline/SKILL.md +67 -0
- package/skills/regex-vs-llm-structured-text/SKILL.md +220 -0
- package/skills/remotion-video-creation/SKILL.md +43 -0
- package/skills/remotion-video-creation/rules/3d.md +86 -0
- package/skills/remotion-video-creation/rules/animations.md +29 -0
- package/skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx +173 -0
- package/skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx +100 -0
- package/skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/skills/remotion-video-creation/rules/assets.md +78 -0
- package/skills/remotion-video-creation/rules/audio.md +172 -0
- package/skills/remotion-video-creation/rules/calculate-metadata.md +104 -0
- package/skills/remotion-video-creation/rules/can-decode.md +75 -0
- package/skills/remotion-video-creation/rules/charts.md +58 -0
- package/skills/remotion-video-creation/rules/compositions.md +146 -0
- package/skills/remotion-video-creation/rules/display-captions.md +126 -0
- package/skills/remotion-video-creation/rules/extract-frames.md +229 -0
- package/skills/remotion-video-creation/rules/fonts.md +152 -0
- package/skills/remotion-video-creation/rules/get-audio-duration.md +58 -0
- package/skills/remotion-video-creation/rules/get-video-dimensions.md +68 -0
- package/skills/remotion-video-creation/rules/get-video-duration.md +58 -0
- package/skills/remotion-video-creation/rules/gifs.md +138 -0
- package/skills/remotion-video-creation/rules/images.md +130 -0
- package/skills/remotion-video-creation/rules/import-srt-captions.md +67 -0
- package/skills/remotion-video-creation/rules/lottie.md +67 -0
- package/skills/remotion-video-creation/rules/measuring-dom-nodes.md +34 -0
- package/skills/remotion-video-creation/rules/measuring-text.md +143 -0
- package/skills/remotion-video-creation/rules/sequencing.md +106 -0
- package/skills/remotion-video-creation/rules/tailwind.md +11 -0
- package/skills/remotion-video-creation/rules/text-animations.md +20 -0
- package/skills/remotion-video-creation/rules/timing.md +179 -0
- package/skills/remotion-video-creation/rules/transcribe-captions.md +19 -0
- package/skills/remotion-video-creation/rules/transitions.md +122 -0
- package/skills/remotion-video-creation/rules/trimming.md +52 -0
- package/skills/remotion-video-creation/rules/videos.md +171 -0
- package/skills/repo-scan/SKILL.md +78 -0
- package/skills/research-ops/SKILL.md +112 -0
- package/skills/returns-reverse-logistics/SKILL.md +240 -0
- package/skills/rules-distill/SKILL.md +264 -0
- package/skills/rules-distill/scripts/scan-rules.sh +58 -0
- package/skills/rules-distill/scripts/scan-skills.sh +129 -0
- package/skills/rust-patterns/SKILL.md +499 -0
- package/skills/rust-testing/SKILL.md +500 -0
- package/skills/safety-guard/SKILL.md +75 -0
- package/skills/santa-method/SKILL.md +306 -0
- package/skills/search-first/SKILL.md +161 -0
- package/skills/security-bounty-hunter/SKILL.md +99 -0
- package/skills/security-review/SKILL.md +495 -0
- package/skills/security-review/cloud-infrastructure-security.md +361 -0
- package/skills/security-scan/SKILL.md +165 -0
- package/skills/seo/SKILL.md +154 -0
- package/skills/skill-comply/SKILL.md +58 -0
- package/skills/skill-comply/fixtures/compliant_trace.jsonl +5 -0
- package/skills/skill-comply/fixtures/noncompliant_trace.jsonl +3 -0
- package/skills/skill-comply/fixtures/tdd_spec.yaml +44 -0
- package/skills/skill-comply/prompts/classifier.md +24 -0
- package/skills/skill-comply/prompts/scenario_generator.md +62 -0
- package/skills/skill-comply/prompts/spec_generator.md +42 -0
- package/skills/skill-comply/pyproject.toml +15 -0
- package/skills/skill-comply/scripts/__init__.py +0 -0
- package/skills/skill-comply/scripts/classifier.py +85 -0
- package/skills/skill-comply/scripts/grader.py +122 -0
- package/skills/skill-comply/scripts/parser.py +107 -0
- package/skills/skill-comply/scripts/report.py +170 -0
- package/skills/skill-comply/scripts/run.py +127 -0
- package/skills/skill-comply/scripts/runner.py +161 -0
- package/skills/skill-comply/scripts/scenario_generator.py +70 -0
- package/skills/skill-comply/scripts/spec_generator.py +72 -0
- package/skills/skill-comply/scripts/utils.py +13 -0
- package/skills/skill-comply/tests/test_grader.py +137 -0
- package/skills/skill-comply/tests/test_parser.py +90 -0
- package/skills/skill-stocktake/SKILL.md +193 -0
- package/skills/skill-stocktake/scripts/quick-diff.sh +87 -0
- package/skills/skill-stocktake/scripts/save-results.sh +56 -0
- package/skills/skill-stocktake/scripts/scan.sh +170 -0
- package/skills/social-graph-ranker/SKILL.md +154 -0
- package/skills/springboot-patterns/SKILL.md +314 -0
- package/skills/springboot-security/SKILL.md +272 -0
- package/skills/springboot-tdd/SKILL.md +158 -0
- package/skills/springboot-verification/SKILL.md +231 -0
- package/skills/strategic-compact/SKILL.md +131 -0
- package/skills/strategic-compact/suggest-compact.sh +54 -0
- package/skills/swift-actor-persistence/SKILL.md +143 -0
- package/skills/swift-concurrency-6-2/SKILL.md +216 -0
- package/skills/swift-protocol-di-testing/SKILL.md +190 -0
- package/skills/swiftui-patterns/SKILL.md +259 -0
- package/skills/tdd-workflow/SKILL.md +463 -0
- package/skills/team-builder/SKILL.md +168 -0
- package/skills/terminal-ops/SKILL.md +109 -0
- package/skills/token-budget-advisor/SKILL.md +133 -0
- package/skills/ui-demo/SKILL.md +465 -0
- package/skills/unified-notifications-ops/SKILL.md +187 -0
- package/skills/verification-loop/SKILL.md +126 -0
- package/skills/video-editing/SKILL.md +310 -0
- package/skills/videodb/SKILL.md +374 -0
- package/skills/videodb/reference/api-reference.md +550 -0
- package/skills/videodb/reference/capture-reference.md +407 -0
- package/skills/videodb/reference/capture.md +101 -0
- package/skills/videodb/reference/editor.md +443 -0
- package/skills/videodb/reference/generative.md +331 -0
- package/skills/videodb/reference/rtstream-reference.md +564 -0
- package/skills/videodb/reference/rtstream.md +65 -0
- package/skills/videodb/reference/search.md +230 -0
- package/skills/videodb/reference/streaming.md +406 -0
- package/skills/videodb/reference/use-cases.md +118 -0
- package/skills/videodb/scripts/ws_listener.py +282 -0
- package/skills/visa-doc-translate/README.md +86 -0
- package/skills/visa-doc-translate/SKILL.md +117 -0
- package/skills/workspace-surface-audit/SKILL.md +125 -0
- package/skills/x-api/SKILL.md +230 -0
- package/tools/changed-files.ts +83 -0
- package/tools/check-coverage.ts +172 -0
- package/tools/format-code.ts +70 -0
- package/tools/git-summary.ts +56 -0
- package/tools/index.ts +14 -0
- package/tools/lint-check.ts +87 -0
- package/tools/run-tests.ts +141 -0
- package/tools/security-audit.ts +279 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ECC Custom Tool: Git Summary
|
|
3
|
+
*
|
|
4
|
+
* Returns branch/status/log/diff details for the active repository.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
|
|
8
|
+
import { execSync } from "child_process"
|
|
9
|
+
|
|
10
|
+
const gitSummaryTool: ToolDefinition = tool({
|
|
11
|
+
description:
|
|
12
|
+
"Generate git summary with branch, status, recent commits, and optional diff stats.",
|
|
13
|
+
args: {
|
|
14
|
+
depth: tool.schema
|
|
15
|
+
.number()
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Number of recent commits to include (default: 5)"),
|
|
18
|
+
includeDiff: tool.schema
|
|
19
|
+
.boolean()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Include diff stats against base branch (default: true)"),
|
|
22
|
+
baseBranch: tool.schema
|
|
23
|
+
.string()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("Base branch for diff comparison (default: main)"),
|
|
26
|
+
},
|
|
27
|
+
async execute(args, context) {
|
|
28
|
+
const cwd = context.worktree || context.directory
|
|
29
|
+
const depth = args.depth ?? 5
|
|
30
|
+
const includeDiff = args.includeDiff ?? true
|
|
31
|
+
const baseBranch = args.baseBranch ?? "main"
|
|
32
|
+
|
|
33
|
+
const result: Record<string, string> = {
|
|
34
|
+
branch: run("git branch --show-current", cwd) || "unknown",
|
|
35
|
+
status: run("git status --short", cwd) || "clean",
|
|
36
|
+
log: run(`git log --oneline -${depth}`, cwd) || "no commits found",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (includeDiff) {
|
|
40
|
+
result.stagedDiff = run("git diff --cached --stat", cwd) || ""
|
|
41
|
+
result.branchDiff = run(`git diff ${baseBranch}...HEAD --stat`, cwd) || `unable to diff against ${baseBranch}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return JSON.stringify(result)
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
export default gitSummaryTool
|
|
49
|
+
|
|
50
|
+
function run(command: string, cwd: string): string {
|
|
51
|
+
try {
|
|
52
|
+
return execSync(command, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).trim()
|
|
53
|
+
} catch {
|
|
54
|
+
return ""
|
|
55
|
+
}
|
|
56
|
+
}
|
package/tools/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ECC Custom Tools for OpenCode
|
|
3
|
+
*
|
|
4
|
+
* These tools extend OpenCode with additional capabilities.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Re-export all tools
|
|
8
|
+
export { default as runTests } from "./run-tests.js"
|
|
9
|
+
export { default as checkCoverage } from "./check-coverage.js"
|
|
10
|
+
export { default as securityAudit } from "./security-audit.js"
|
|
11
|
+
export { default as formatCode } from "./format-code.js"
|
|
12
|
+
export { default as lintCheck } from "./lint-check.js"
|
|
13
|
+
export { default as gitSummary } from "./git-summary.js"
|
|
14
|
+
export { default as changedFiles } from "./changed-files.js"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ECC Custom Tool: Lint Check
|
|
3
|
+
*
|
|
4
|
+
* Detects the appropriate linter and returns a runnable lint command.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
|
|
8
|
+
import * as path from "path"
|
|
9
|
+
import * as fs from "fs"
|
|
10
|
+
|
|
11
|
+
type Linter = "biome" | "eslint" | "ruff" | "pylint" | "golangci-lint"
|
|
12
|
+
|
|
13
|
+
const lintCheckTool: ToolDefinition = tool({
|
|
14
|
+
description:
|
|
15
|
+
"Detect linter for a target path and return command for check/fix runs.",
|
|
16
|
+
args: {
|
|
17
|
+
target: tool.schema
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("File or directory to lint (default: current directory)"),
|
|
21
|
+
fix: tool.schema
|
|
22
|
+
.boolean()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Enable auto-fix mode"),
|
|
25
|
+
linter: tool.schema
|
|
26
|
+
.enum(["biome", "eslint", "ruff", "pylint", "golangci-lint"])
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("Optional linter override"),
|
|
29
|
+
},
|
|
30
|
+
async execute(args, context) {
|
|
31
|
+
const cwd = context.worktree || context.directory
|
|
32
|
+
const target = args.target || "."
|
|
33
|
+
const fix = args.fix ?? false
|
|
34
|
+
const detected = args.linter || detectLinter(cwd)
|
|
35
|
+
|
|
36
|
+
const command = buildLintCommand(detected, target, fix)
|
|
37
|
+
return JSON.stringify({
|
|
38
|
+
success: true,
|
|
39
|
+
linter: detected,
|
|
40
|
+
command,
|
|
41
|
+
instructions: `Run this command:\n\n${command}`,
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
export default lintCheckTool
|
|
47
|
+
|
|
48
|
+
function detectLinter(cwd: string): Linter {
|
|
49
|
+
if (fs.existsSync(path.join(cwd, "biome.json")) || fs.existsSync(path.join(cwd, "biome.jsonc"))) {
|
|
50
|
+
return "biome"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const eslintConfigs = [
|
|
54
|
+
".eslintrc.json",
|
|
55
|
+
".eslintrc.js",
|
|
56
|
+
".eslintrc.cjs",
|
|
57
|
+
"eslint.config.js",
|
|
58
|
+
"eslint.config.mjs",
|
|
59
|
+
]
|
|
60
|
+
if (eslintConfigs.some((name) => fs.existsSync(path.join(cwd, name)))) {
|
|
61
|
+
return "eslint"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const pyprojectPath = path.join(cwd, "pyproject.toml")
|
|
65
|
+
if (fs.existsSync(pyprojectPath)) {
|
|
66
|
+
try {
|
|
67
|
+
const content = fs.readFileSync(pyprojectPath, "utf-8")
|
|
68
|
+
if (content.includes("ruff")) return "ruff"
|
|
69
|
+
} catch {
|
|
70
|
+
// ignore read errors and keep fallback logic
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (fs.existsSync(path.join(cwd, ".golangci.yml")) || fs.existsSync(path.join(cwd, ".golangci.yaml"))) {
|
|
75
|
+
return "golangci-lint"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return "eslint"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function buildLintCommand(linter: Linter, target: string, fix: boolean): string {
|
|
82
|
+
if (linter === "biome") return `npx @biomejs/biome lint${fix ? " --write" : ""} ${target}`
|
|
83
|
+
if (linter === "eslint") return `npx eslint${fix ? " --fix" : ""} ${target}`
|
|
84
|
+
if (linter === "ruff") return `ruff check${fix ? " --fix" : ""} ${target}`
|
|
85
|
+
if (linter === "pylint") return `pylint ${target}`
|
|
86
|
+
return `golangci-lint run ${target}`
|
|
87
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Tests Tool
|
|
3
|
+
*
|
|
4
|
+
* Custom OpenCode tool to run test suites with various options.
|
|
5
|
+
* Automatically detects the package manager and test framework.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
|
|
9
|
+
import * as path from "path"
|
|
10
|
+
import * as fs from "fs"
|
|
11
|
+
|
|
12
|
+
const runTestsTool: ToolDefinition = tool({
|
|
13
|
+
description:
|
|
14
|
+
"Run the test suite with optional coverage, watch mode, or specific test patterns. Automatically detects package manager (npm, pnpm, yarn, bun) and test framework.",
|
|
15
|
+
args: {
|
|
16
|
+
pattern: tool.schema
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Test file pattern or specific test name to run"),
|
|
20
|
+
coverage: tool.schema
|
|
21
|
+
.boolean()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Run with coverage reporting (default: false)"),
|
|
24
|
+
watch: tool.schema
|
|
25
|
+
.boolean()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Run in watch mode for continuous testing (default: false)"),
|
|
28
|
+
updateSnapshots: tool.schema
|
|
29
|
+
.boolean()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Update Jest/Vitest snapshots (default: false)"),
|
|
32
|
+
},
|
|
33
|
+
async execute(args, context) {
|
|
34
|
+
const { pattern, coverage, watch, updateSnapshots } = args
|
|
35
|
+
const cwd = context.worktree || context.directory
|
|
36
|
+
|
|
37
|
+
// Detect package manager
|
|
38
|
+
const packageManager = await detectPackageManager(cwd)
|
|
39
|
+
|
|
40
|
+
// Detect test framework
|
|
41
|
+
const testFramework = await detectTestFramework(cwd)
|
|
42
|
+
|
|
43
|
+
// Build command
|
|
44
|
+
let cmd: string[] = [packageManager]
|
|
45
|
+
|
|
46
|
+
if (packageManager === "npm") {
|
|
47
|
+
cmd.push("run", "test")
|
|
48
|
+
} else {
|
|
49
|
+
cmd.push("test")
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Add options based on framework
|
|
53
|
+
const testArgs: string[] = []
|
|
54
|
+
|
|
55
|
+
if (coverage) {
|
|
56
|
+
testArgs.push("--coverage")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (watch) {
|
|
60
|
+
testArgs.push("--watch")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (updateSnapshots) {
|
|
64
|
+
testArgs.push("-u")
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (pattern) {
|
|
68
|
+
if (testFramework === "jest" || testFramework === "vitest") {
|
|
69
|
+
testArgs.push("--testPathPattern", pattern)
|
|
70
|
+
} else {
|
|
71
|
+
testArgs.push(pattern)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Add -- separator for npm
|
|
76
|
+
if (testArgs.length > 0) {
|
|
77
|
+
if (packageManager === "npm") {
|
|
78
|
+
cmd.push("--")
|
|
79
|
+
}
|
|
80
|
+
cmd.push(...testArgs)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const command = cmd.join(" ")
|
|
84
|
+
|
|
85
|
+
return JSON.stringify({
|
|
86
|
+
command,
|
|
87
|
+
packageManager,
|
|
88
|
+
testFramework,
|
|
89
|
+
options: {
|
|
90
|
+
pattern: pattern || "all tests",
|
|
91
|
+
coverage: coverage || false,
|
|
92
|
+
watch: watch || false,
|
|
93
|
+
updateSnapshots: updateSnapshots || false,
|
|
94
|
+
},
|
|
95
|
+
instructions: `Run this command to execute tests:\n\n${command}`,
|
|
96
|
+
})
|
|
97
|
+
},
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
export default runTestsTool
|
|
101
|
+
|
|
102
|
+
async function detectPackageManager(cwd: string): Promise<string> {
|
|
103
|
+
const lockFiles: Record<string, string> = {
|
|
104
|
+
"bun.lockb": "bun",
|
|
105
|
+
"pnpm-lock.yaml": "pnpm",
|
|
106
|
+
"yarn.lock": "yarn",
|
|
107
|
+
"package-lock.json": "npm",
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
for (const [lockFile, pm] of Object.entries(lockFiles)) {
|
|
111
|
+
if (fs.existsSync(path.join(cwd, lockFile))) {
|
|
112
|
+
return pm
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return "npm"
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function detectTestFramework(cwd: string): Promise<string> {
|
|
120
|
+
const packageJsonPath = path.join(cwd, "package.json")
|
|
121
|
+
|
|
122
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
123
|
+
try {
|
|
124
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"))
|
|
125
|
+
const deps = {
|
|
126
|
+
...packageJson.dependencies,
|
|
127
|
+
...packageJson.devDependencies,
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (deps.vitest) return "vitest"
|
|
131
|
+
if (deps.jest) return "jest"
|
|
132
|
+
if (deps.mocha) return "mocha"
|
|
133
|
+
if (deps.ava) return "ava"
|
|
134
|
+
if (deps.tap) return "tap"
|
|
135
|
+
} catch {
|
|
136
|
+
// Ignore parse errors
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return "unknown"
|
|
141
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Audit Tool
|
|
3
|
+
*
|
|
4
|
+
* Custom OpenCode tool to run security audits on dependencies and code.
|
|
5
|
+
* Combines npm audit, secret scanning, and OWASP checks.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: This tool SCANS for security anti-patterns - it does not introduce them.
|
|
8
|
+
* The regex patterns below are used to DETECT potential issues in user code.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
|
|
12
|
+
import * as path from "path"
|
|
13
|
+
import * as fs from "fs"
|
|
14
|
+
|
|
15
|
+
const securityAuditTool: ToolDefinition = tool({
|
|
16
|
+
description:
|
|
17
|
+
"Run a comprehensive security audit including dependency vulnerabilities, secret scanning, and common security issues.",
|
|
18
|
+
args: {
|
|
19
|
+
type: tool.schema
|
|
20
|
+
.enum(["all", "dependencies", "secrets", "code"])
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Type of audit to run (default: all)"),
|
|
23
|
+
fix: tool.schema
|
|
24
|
+
.boolean()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Attempt to auto-fix dependency vulnerabilities (default: false)"),
|
|
27
|
+
severity: tool.schema
|
|
28
|
+
.enum(["low", "moderate", "high", "critical"])
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Minimum severity level to report (default: moderate)"),
|
|
31
|
+
},
|
|
32
|
+
async execute(args, context) {
|
|
33
|
+
const auditType = args.type ?? "all"
|
|
34
|
+
const fix = args.fix ?? false
|
|
35
|
+
const severity = args.severity ?? "moderate"
|
|
36
|
+
const cwd = context.worktree || context.directory
|
|
37
|
+
|
|
38
|
+
const results: AuditResults = {
|
|
39
|
+
timestamp: new Date().toISOString(),
|
|
40
|
+
directory: cwd,
|
|
41
|
+
checks: [],
|
|
42
|
+
summary: {
|
|
43
|
+
passed: 0,
|
|
44
|
+
failed: 0,
|
|
45
|
+
warnings: 0,
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Check for dependencies audit
|
|
50
|
+
if (auditType === "all" || auditType === "dependencies") {
|
|
51
|
+
results.checks.push({
|
|
52
|
+
name: "Dependency Vulnerabilities",
|
|
53
|
+
description: "Check for known vulnerabilities in dependencies",
|
|
54
|
+
command: fix ? "npm audit fix" : "npm audit",
|
|
55
|
+
severityFilter: severity,
|
|
56
|
+
status: "pending",
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check for secrets
|
|
61
|
+
if (auditType === "all" || auditType === "secrets") {
|
|
62
|
+
const secretPatterns = await scanForSecrets(cwd)
|
|
63
|
+
if (secretPatterns.length > 0) {
|
|
64
|
+
results.checks.push({
|
|
65
|
+
name: "Secret Detection",
|
|
66
|
+
description: "Scan for hardcoded secrets and API keys",
|
|
67
|
+
status: "failed",
|
|
68
|
+
findings: secretPatterns,
|
|
69
|
+
})
|
|
70
|
+
results.summary.failed++
|
|
71
|
+
} else {
|
|
72
|
+
results.checks.push({
|
|
73
|
+
name: "Secret Detection",
|
|
74
|
+
description: "Scan for hardcoded secrets and API keys",
|
|
75
|
+
status: "passed",
|
|
76
|
+
})
|
|
77
|
+
results.summary.passed++
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Check for common code security issues
|
|
82
|
+
if (auditType === "all" || auditType === "code") {
|
|
83
|
+
const codeIssues = await scanCodeSecurity(cwd)
|
|
84
|
+
if (codeIssues.length > 0) {
|
|
85
|
+
results.checks.push({
|
|
86
|
+
name: "Code Security",
|
|
87
|
+
description: "Check for common security anti-patterns",
|
|
88
|
+
status: "warning",
|
|
89
|
+
findings: codeIssues,
|
|
90
|
+
})
|
|
91
|
+
results.summary.warnings++
|
|
92
|
+
} else {
|
|
93
|
+
results.checks.push({
|
|
94
|
+
name: "Code Security",
|
|
95
|
+
description: "Check for common security anti-patterns",
|
|
96
|
+
status: "passed",
|
|
97
|
+
})
|
|
98
|
+
results.summary.passed++
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Generate recommendations
|
|
103
|
+
results.recommendations = generateRecommendations(results)
|
|
104
|
+
|
|
105
|
+
return JSON.stringify(results)
|
|
106
|
+
},
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
export default securityAuditTool
|
|
110
|
+
|
|
111
|
+
interface AuditCheck {
|
|
112
|
+
name: string
|
|
113
|
+
description: string
|
|
114
|
+
command?: string
|
|
115
|
+
severityFilter?: string
|
|
116
|
+
status: "pending" | "passed" | "failed" | "warning"
|
|
117
|
+
findings?: Array<{ file: string; issue: string; line?: number }>
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface AuditResults {
|
|
121
|
+
timestamp: string
|
|
122
|
+
directory: string
|
|
123
|
+
checks: AuditCheck[]
|
|
124
|
+
summary: {
|
|
125
|
+
passed: number
|
|
126
|
+
failed: number
|
|
127
|
+
warnings: number
|
|
128
|
+
}
|
|
129
|
+
recommendations?: string[]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function scanForSecrets(
|
|
133
|
+
cwd: string
|
|
134
|
+
): Promise<Array<{ file: string; issue: string; line?: number }>> {
|
|
135
|
+
const findings: Array<{ file: string; issue: string; line?: number }> = []
|
|
136
|
+
|
|
137
|
+
// Patterns to DETECT potential secrets (security scanning)
|
|
138
|
+
const secretPatterns = [
|
|
139
|
+
{ pattern: /api[_-]?key\s*[:=]\s*['"][^'"]{20,}['"]/gi, name: "API Key" },
|
|
140
|
+
{ pattern: /password\s*[:=]\s*['"][^'"]+['"]/gi, name: "Password" },
|
|
141
|
+
{ pattern: /secret\s*[:=]\s*['"][^'"]{10,}['"]/gi, name: "Secret" },
|
|
142
|
+
{ pattern: /Bearer\s+[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+/g, name: "JWT Token" },
|
|
143
|
+
{ pattern: /sk-[a-zA-Z0-9]{32,}/g, name: "OpenAI API Key" },
|
|
144
|
+
{ pattern: /ghp_[a-zA-Z0-9]{36}/g, name: "GitHub Token" },
|
|
145
|
+
{ pattern: /aws[_-]?secret[_-]?access[_-]?key/gi, name: "AWS Secret" },
|
|
146
|
+
]
|
|
147
|
+
|
|
148
|
+
const ignorePatterns = [
|
|
149
|
+
"node_modules",
|
|
150
|
+
".git",
|
|
151
|
+
"dist",
|
|
152
|
+
"build",
|
|
153
|
+
".env.example",
|
|
154
|
+
".env.template",
|
|
155
|
+
]
|
|
156
|
+
|
|
157
|
+
const srcDir = path.join(cwd, "src")
|
|
158
|
+
if (fs.existsSync(srcDir)) {
|
|
159
|
+
await scanDirectory(srcDir, secretPatterns, ignorePatterns, findings)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Also check root config files
|
|
163
|
+
const configFiles = ["config.js", "config.ts", "settings.js", "settings.ts"]
|
|
164
|
+
for (const configFile of configFiles) {
|
|
165
|
+
const filePath = path.join(cwd, configFile)
|
|
166
|
+
if (fs.existsSync(filePath)) {
|
|
167
|
+
await scanFile(filePath, secretPatterns, findings)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return findings
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function scanDirectory(
|
|
175
|
+
dir: string,
|
|
176
|
+
patterns: Array<{ pattern: RegExp; name: string }>,
|
|
177
|
+
ignorePatterns: string[],
|
|
178
|
+
findings: Array<{ file: string; issue: string; line?: number }>
|
|
179
|
+
): Promise<void> {
|
|
180
|
+
if (!fs.existsSync(dir)) return
|
|
181
|
+
|
|
182
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true })
|
|
183
|
+
|
|
184
|
+
for (const entry of entries) {
|
|
185
|
+
const fullPath = path.join(dir, entry.name)
|
|
186
|
+
|
|
187
|
+
if (ignorePatterns.some((p) => fullPath.includes(p))) continue
|
|
188
|
+
|
|
189
|
+
if (entry.isDirectory()) {
|
|
190
|
+
await scanDirectory(fullPath, patterns, ignorePatterns, findings)
|
|
191
|
+
} else if (entry.isFile() && entry.name.match(/\.(ts|tsx|js|jsx|json)$/)) {
|
|
192
|
+
await scanFile(fullPath, patterns, findings)
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async function scanFile(
|
|
198
|
+
filePath: string,
|
|
199
|
+
patterns: Array<{ pattern: RegExp; name: string }>,
|
|
200
|
+
findings: Array<{ file: string; issue: string; line?: number }>
|
|
201
|
+
): Promise<void> {
|
|
202
|
+
try {
|
|
203
|
+
const content = fs.readFileSync(filePath, "utf-8")
|
|
204
|
+
const lines = content.split("\n")
|
|
205
|
+
|
|
206
|
+
for (let i = 0; i < lines.length; i++) {
|
|
207
|
+
const line = lines[i]
|
|
208
|
+
for (const { pattern, name } of patterns) {
|
|
209
|
+
// Reset regex state
|
|
210
|
+
pattern.lastIndex = 0
|
|
211
|
+
if (pattern.test(line)) {
|
|
212
|
+
findings.push({
|
|
213
|
+
file: filePath,
|
|
214
|
+
issue: `Potential ${name} found`,
|
|
215
|
+
line: i + 1,
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
} catch {
|
|
221
|
+
// Ignore read errors
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function scanCodeSecurity(
|
|
226
|
+
cwd: string
|
|
227
|
+
): Promise<Array<{ file: string; issue: string; line?: number }>> {
|
|
228
|
+
const findings: Array<{ file: string; issue: string; line?: number }> = []
|
|
229
|
+
|
|
230
|
+
// Patterns to DETECT security anti-patterns (this tool scans for issues)
|
|
231
|
+
// These are detection patterns, not code that uses these anti-patterns
|
|
232
|
+
const securityPatterns = [
|
|
233
|
+
{ pattern: /\beval\s*\(/g, name: "eval() usage - potential code injection" },
|
|
234
|
+
{ pattern: /innerHTML\s*=/g, name: "innerHTML assignment - potential XSS" },
|
|
235
|
+
{ pattern: /dangerouslySetInnerHTML/g, name: "dangerouslySetInnerHTML - potential XSS" },
|
|
236
|
+
{ pattern: /document\.write/g, name: "document.write - potential XSS" },
|
|
237
|
+
{ pattern: /\$\{.*\}.*sql/gi, name: "Potential SQL injection" },
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
const srcDir = path.join(cwd, "src")
|
|
241
|
+
if (fs.existsSync(srcDir)) {
|
|
242
|
+
await scanDirectory(srcDir, securityPatterns, ["node_modules", ".git", "dist"], findings)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return findings
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function generateRecommendations(results: AuditResults): string[] {
|
|
249
|
+
const recommendations: string[] = []
|
|
250
|
+
|
|
251
|
+
for (const check of results.checks) {
|
|
252
|
+
if (check.status === "failed" && check.name === "Secret Detection") {
|
|
253
|
+
recommendations.push(
|
|
254
|
+
"CRITICAL: Remove hardcoded secrets and use environment variables instead"
|
|
255
|
+
)
|
|
256
|
+
recommendations.push("Add a .env file (gitignored) for local development")
|
|
257
|
+
recommendations.push("Use a secrets manager for production deployments")
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (check.status === "warning" && check.name === "Code Security") {
|
|
261
|
+
recommendations.push(
|
|
262
|
+
"Review flagged code patterns for potential security vulnerabilities"
|
|
263
|
+
)
|
|
264
|
+
recommendations.push("Consider using DOMPurify for HTML sanitization")
|
|
265
|
+
recommendations.push("Use parameterized queries for database operations")
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (check.status === "pending" && check.name === "Dependency Vulnerabilities") {
|
|
269
|
+
recommendations.push("Run 'npm audit' to check for dependency vulnerabilities")
|
|
270
|
+
recommendations.push("Consider using 'npm audit fix' to auto-fix issues")
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (recommendations.length === 0) {
|
|
275
|
+
recommendations.push("No critical security issues found. Continue following security best practices.")
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return recommendations
|
|
279
|
+
}
|