@iamnishankhan/opencode-kit-grok 1.0.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/bin/cli.js +46 -0
- package/kit/.opencode/AGENTS.md +392 -0
- package/kit/.opencode/README.md +71 -0
- package/kit/.opencode/USAGE.md +405 -0
- package/kit/.opencode/agents/backend-specialist.md +278 -0
- package/kit/.opencode/agents/code-archaeologist.md +114 -0
- package/kit/.opencode/agents/database-architect.md +233 -0
- package/kit/.opencode/agents/debugger.md +234 -0
- package/kit/.opencode/agents/devops-engineer.md +252 -0
- package/kit/.opencode/agents/documentation-writer.md +111 -0
- package/kit/.opencode/agents/explorer-agent.md +83 -0
- package/kit/.opencode/agents/frontend-specialist.md +606 -0
- package/kit/.opencode/agents/game-developer.md +169 -0
- package/kit/.opencode/agents/mobile-developer.md +385 -0
- package/kit/.opencode/agents/orchestrator.md +213 -0
- package/kit/.opencode/agents/penetration-tester.md +197 -0
- package/kit/.opencode/agents/performance-optimizer.md +194 -0
- package/kit/.opencode/agents/product-manager.md +120 -0
- package/kit/.opencode/agents/product-owner.md +103 -0
- package/kit/.opencode/agents/project-planner.md +418 -0
- package/kit/.opencode/agents/qa-automation-engineer.md +113 -0
- package/kit/.opencode/agents/security-auditor.md +179 -0
- package/kit/.opencode/agents/seo-specialist.md +119 -0
- package/kit/.opencode/agents/test-engineer.md +169 -0
- package/kit/.opencode/commands/brainstorm.md +113 -0
- package/kit/.opencode/commands/coordinate.md +72 -0
- package/kit/.opencode/commands/create.md +63 -0
- package/kit/.opencode/commands/debug.md +102 -0
- package/kit/.opencode/commands/deploy.md +175 -0
- package/kit/.opencode/commands/enhance.md +62 -0
- package/kit/.opencode/commands/orchestrate.md +241 -0
- package/kit/.opencode/commands/plan.md +89 -0
- package/kit/.opencode/commands/preview.md +80 -0
- package/kit/.opencode/commands/remember.md +67 -0
- package/kit/.opencode/commands/status.md +86 -0
- package/kit/.opencode/commands/test.md +143 -0
- package/kit/.opencode/commands/verify.md +71 -0
- package/kit/.opencode/memory/MEMORY.md +6 -0
- package/kit/.opencode/memory/feedback-history.md +9 -0
- package/kit/.opencode/memory/project-conventions.md +16 -0
- package/kit/.opencode/memory/tech-decisions.md +10 -0
- package/kit/.opencode/memory/user-preferences.md +9 -0
- package/kit/.opencode/opencode.json +15 -0
- package/kit/.opencode/scripts/README.md +95 -0
- package/kit/.opencode/scripts/auto_preview.py +149 -0
- package/kit/.opencode/scripts/checklist.py +75 -0
- package/kit/.opencode/scripts/component_registry.py +238 -0
- package/kit/.opencode/scripts/dependency_graph.py +73 -0
- package/kit/.opencode/scripts/generate_manifest.py +44 -0
- package/kit/.opencode/scripts/session_manager.py +120 -0
- package/kit/.opencode/scripts/tests/test_toolkit.py +238 -0
- package/kit/.opencode/scripts/validate_kit.py +397 -0
- package/kit/.opencode/scripts/validation_runner.py +216 -0
- package/kit/.opencode/scripts/verify_all.py +85 -0
- package/kit/.opencode/skills/api-patterns/SKILL.md +83 -0
- package/kit/.opencode/skills/api-patterns/api-style.md +42 -0
- package/kit/.opencode/skills/api-patterns/auth.md +24 -0
- package/kit/.opencode/skills/api-patterns/documentation.md +26 -0
- package/kit/.opencode/skills/api-patterns/graphql.md +41 -0
- package/kit/.opencode/skills/api-patterns/rate-limiting.md +31 -0
- package/kit/.opencode/skills/api-patterns/response.md +37 -0
- package/kit/.opencode/skills/api-patterns/rest.md +40 -0
- package/kit/.opencode/skills/api-patterns/scripts/api_validator.py +211 -0
- package/kit/.opencode/skills/api-patterns/security-testing.md +122 -0
- package/kit/.opencode/skills/api-patterns/trpc.md +41 -0
- package/kit/.opencode/skills/api-patterns/versioning.md +22 -0
- package/kit/.opencode/skills/app-builder/SKILL.md +78 -0
- package/kit/.opencode/skills/app-builder/agent-coordination.md +71 -0
- package/kit/.opencode/skills/app-builder/feature-building.md +53 -0
- package/kit/.opencode/skills/app-builder/project-detection.md +45 -0
- package/kit/.opencode/skills/app-builder/scaffolding.md +110 -0
- package/kit/.opencode/skills/app-builder/tech-stack.md +41 -0
- package/kit/.opencode/skills/app-builder/templates/SKILL.md +39 -0
- package/kit/.opencode/skills/app-builder/templates/astro-static/TEMPLATE.md +78 -0
- package/kit/.opencode/skills/app-builder/templates/chrome-extension/TEMPLATE.md +96 -0
- package/kit/.opencode/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/kit/.opencode/skills/app-builder/templates/electron-desktop/TEMPLATE.md +97 -0
- package/kit/.opencode/skills/app-builder/templates/express-api/TEMPLATE.md +89 -0
- package/kit/.opencode/skills/app-builder/templates/flutter-app/TEMPLATE.md +93 -0
- package/kit/.opencode/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +97 -0
- package/kit/.opencode/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +126 -0
- package/kit/.opencode/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +125 -0
- package/kit/.opencode/skills/app-builder/templates/nextjs-static/TEMPLATE.md +174 -0
- package/kit/.opencode/skills/app-builder/templates/nuxt-app/TEMPLATE.md +127 -0
- package/kit/.opencode/skills/app-builder/templates/python-fastapi/TEMPLATE.md +94 -0
- package/kit/.opencode/skills/app-builder/templates/react-native-app/TEMPLATE.md +121 -0
- package/kit/.opencode/skills/architecture/SKILL.md +57 -0
- package/kit/.opencode/skills/architecture/context-discovery.md +43 -0
- package/kit/.opencode/skills/architecture/examples.md +94 -0
- package/kit/.opencode/skills/architecture/pattern-selection.md +68 -0
- package/kit/.opencode/skills/architecture/patterns-reference.md +50 -0
- package/kit/.opencode/skills/architecture/trade-off-analysis.md +77 -0
- package/kit/.opencode/skills/bash-linux/SKILL.md +201 -0
- package/kit/.opencode/skills/batch-operations/SKILL.md +105 -0
- package/kit/.opencode/skills/behavioral-modes/SKILL.md +253 -0
- package/kit/.opencode/skills/brainstorming/SKILL.md +178 -0
- package/kit/.opencode/skills/brainstorming/dynamic-questioning.md +350 -0
- package/kit/.opencode/skills/clean-code/SKILL.md +201 -0
- package/kit/.opencode/skills/code-review-checklist/SKILL.md +111 -0
- package/kit/.opencode/skills/code-review-graph/SKILL.md +305 -0
- package/kit/.opencode/skills/context-compression/SKILL.md +145 -0
- package/kit/.opencode/skills/coordinator-mode/SKILL.md +208 -0
- package/kit/.opencode/skills/database-design/SKILL.md +54 -0
- package/kit/.opencode/skills/database-design/database-selection.md +43 -0
- package/kit/.opencode/skills/database-design/indexing.md +39 -0
- package/kit/.opencode/skills/database-design/migrations.md +48 -0
- package/kit/.opencode/skills/database-design/optimization.md +36 -0
- package/kit/.opencode/skills/database-design/orm-selection.md +30 -0
- package/kit/.opencode/skills/database-design/schema-design.md +56 -0
- package/kit/.opencode/skills/database-design/scripts/schema_validator.py +172 -0
- package/kit/.opencode/skills/deployment-procedures/SKILL.md +243 -0
- package/kit/.opencode/skills/design-spec/SKILL.md +185 -0
- package/kit/.opencode/skills/design-spec/collection.md +106 -0
- package/kit/.opencode/skills/documentation-templates/SKILL.md +196 -0
- package/kit/.opencode/skills/frontend-architecture/SKILL.md +245 -0
- package/kit/.opencode/skills/frontend-design/SKILL.md +1222 -0
- package/kit/.opencode/skills/frontend-design/redesign.md +178 -0
- package/kit/.opencode/skills/frontend-design/scripts/accessibility_checker.py +145 -0
- package/kit/.opencode/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/kit/.opencode/skills/frontend-design/style-brutalist.md +92 -0
- package/kit/.opencode/skills/frontend-design/style-minimalist.md +85 -0
- package/kit/.opencode/skills/game-development/2d-games/SKILL.md +118 -0
- package/kit/.opencode/skills/game-development/3d-games/SKILL.md +134 -0
- package/kit/.opencode/skills/game-development/SKILL.md +169 -0
- package/kit/.opencode/skills/game-development/game-art/SKILL.md +184 -0
- package/kit/.opencode/skills/game-development/game-audio/SKILL.md +189 -0
- package/kit/.opencode/skills/game-development/game-design/SKILL.md +128 -0
- package/kit/.opencode/skills/game-development/mobile-games/SKILL.md +107 -0
- package/kit/.opencode/skills/game-development/multiplayer/SKILL.md +131 -0
- package/kit/.opencode/skills/game-development/pc-games/SKILL.md +143 -0
- package/kit/.opencode/skills/game-development/vr-ar/SKILL.md +122 -0
- package/kit/.opencode/skills/game-development/web-games/SKILL.md +149 -0
- package/kit/.opencode/skills/geo-fundamentals/SKILL.md +158 -0
- package/kit/.opencode/skills/geo-fundamentals/scripts/geo_checker.py +273 -0
- package/kit/.opencode/skills/i18n-localization/SKILL.md +156 -0
- package/kit/.opencode/skills/i18n-localization/scripts/i18n_checker.py +223 -0
- package/kit/.opencode/skills/intelligent-routing/SKILL.md +337 -0
- package/kit/.opencode/skills/lint-and-validate/SKILL.md +47 -0
- package/kit/.opencode/skills/lint-and-validate/scripts/lint_runner.py +184 -0
- package/kit/.opencode/skills/lint-and-validate/scripts/type_coverage.py +245 -0
- package/kit/.opencode/skills/mcp-builder/SKILL.md +205 -0
- package/kit/.opencode/skills/memory-system/SKILL.md +181 -0
- package/kit/.opencode/skills/mobile-design/SKILL.md +396 -0
- package/kit/.opencode/skills/mobile-design/decision-trees.md +516 -0
- package/kit/.opencode/skills/mobile-design/mobile-backend.md +491 -0
- package/kit/.opencode/skills/mobile-design/mobile-color-system.md +420 -0
- package/kit/.opencode/skills/mobile-design/mobile-debugging.md +122 -0
- package/kit/.opencode/skills/mobile-design/mobile-design-thinking.md +357 -0
- package/kit/.opencode/skills/mobile-design/mobile-navigation.md +458 -0
- package/kit/.opencode/skills/mobile-design/mobile-performance.md +767 -0
- package/kit/.opencode/skills/mobile-design/mobile-testing.md +356 -0
- package/kit/.opencode/skills/mobile-design/mobile-typography.md +433 -0
- package/kit/.opencode/skills/mobile-design/platform-android.md +666 -0
- package/kit/.opencode/skills/mobile-design/platform-ios.md +561 -0
- package/kit/.opencode/skills/mobile-design/scripts/mobile_audit.py +670 -0
- package/kit/.opencode/skills/mobile-design/touch-psychology.md +537 -0
- package/kit/.opencode/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +351 -0
- package/kit/.opencode/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +240 -0
- package/kit/.opencode/skills/nextjs-react-expert/3-server-server-side-performance.md +490 -0
- package/kit/.opencode/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +264 -0
- package/kit/.opencode/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +581 -0
- package/kit/.opencode/skills/nextjs-react-expert/6-rendering-rendering-performance.md +432 -0
- package/kit/.opencode/skills/nextjs-react-expert/7-js-javascript-performance.md +684 -0
- package/kit/.opencode/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +150 -0
- package/kit/.opencode/skills/nextjs-react-expert/9-cache-components.md +103 -0
- package/kit/.opencode/skills/nextjs-react-expert/SKILL.md +293 -0
- package/kit/.opencode/skills/nextjs-react-expert/scripts/convert_rules.py +222 -0
- package/kit/.opencode/skills/nextjs-react-expert/scripts/react_performance_checker.py +281 -0
- package/kit/.opencode/skills/nodejs-best-practices/SKILL.md +336 -0
- package/kit/.opencode/skills/parallel-agents/SKILL.md +192 -0
- package/kit/.opencode/skills/performance-profiling/SKILL.md +145 -0
- package/kit/.opencode/skills/performance-profiling/scripts/bundle_analyzer.py +120 -0
- package/kit/.opencode/skills/performance-profiling/scripts/lighthouse_audit.py +108 -0
- package/kit/.opencode/skills/plan-writing/SKILL.md +153 -0
- package/kit/.opencode/skills/powershell-windows/SKILL.md +169 -0
- package/kit/.opencode/skills/python-patterns/SKILL.md +443 -0
- package/kit/.opencode/skills/red-team-tactics/SKILL.md +201 -0
- package/kit/.opencode/skills/rust-pro/SKILL.md +177 -0
- package/kit/.opencode/skills/seo-fundamentals/SKILL.md +131 -0
- package/kit/.opencode/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/kit/.opencode/skills/server-management/SKILL.md +163 -0
- package/kit/.opencode/skills/simplify-code/SKILL.md +131 -0
- package/kit/.opencode/skills/skillify/SKILL.md +115 -0
- package/kit/.opencode/skills/systematic-debugging/SKILL.md +111 -0
- package/kit/.opencode/skills/tailwind-patterns/SKILL.md +271 -0
- package/kit/.opencode/skills/tdd-workflow/SKILL.md +151 -0
- package/kit/.opencode/skills/testing-patterns/SKILL.md +180 -0
- package/kit/.opencode/skills/testing-patterns/scripts/test_runner.py +219 -0
- package/kit/.opencode/skills/verify-changes/SKILL.md +127 -0
- package/kit/.opencode/skills/vulnerability-scanner/SKILL.md +278 -0
- package/kit/.opencode/skills/vulnerability-scanner/checklists.md +124 -0
- package/kit/.opencode/skills/vulnerability-scanner/scripts/dependency_analyzer.py +144 -0
- package/kit/.opencode/skills/vulnerability-scanner/scripts/security_scan.py +410 -0
- package/kit/.opencode/skills/web-design-guidelines/SKILL.md +56 -0
- package/kit/.opencode/skills/webapp-testing/SKILL.md +189 -0
- package/kit/.opencode/skills/webapp-testing/scripts/playwright_runner.py +123 -0
- package/lib/init.js +61 -0
- package/package.json +21 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Session Manager - OpenCode kit
|
|
4
|
+
=================================
|
|
5
|
+
Analyzes project state, detects tech stack, tracks file statistics, and provides
|
|
6
|
+
a summary of the current session.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python .opencode/scripts/session_manager.py status [path]
|
|
10
|
+
python .opencode/scripts/session_manager.py info [path]
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import json
|
|
15
|
+
import argparse
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Dict, Any, List
|
|
18
|
+
|
|
19
|
+
def get_project_root(path: str) -> Path:
|
|
20
|
+
return Path(path).resolve()
|
|
21
|
+
|
|
22
|
+
def analyze_package_json(root: Path) -> Dict[str, Any]:
|
|
23
|
+
pkg_file = root / "package.json"
|
|
24
|
+
if not pkg_file.exists():
|
|
25
|
+
return {"type": "unknown", "dependencies": {}}
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
with open(pkg_file, 'r', encoding='utf-8') as f:
|
|
29
|
+
data = json.load(f)
|
|
30
|
+
|
|
31
|
+
deps = data.get("dependencies", {})
|
|
32
|
+
dev_deps = data.get("devDependencies", {})
|
|
33
|
+
all_deps = {**deps, **dev_deps}
|
|
34
|
+
|
|
35
|
+
stack = []
|
|
36
|
+
if "next" in all_deps: stack.append("Next.js")
|
|
37
|
+
elif "react" in all_deps: stack.append("React")
|
|
38
|
+
elif "vue" in all_deps: stack.append("Vue")
|
|
39
|
+
elif "svelte" in all_deps: stack.append("Svelte")
|
|
40
|
+
elif "express" in all_deps: stack.append("Express")
|
|
41
|
+
elif "nestjs" in all_deps or "@nestjs/core" in all_deps: stack.append("NestJS")
|
|
42
|
+
|
|
43
|
+
if "tailwindcss" in all_deps: stack.append("Tailwind CSS")
|
|
44
|
+
if "prisma" in all_deps: stack.append("Prisma")
|
|
45
|
+
if "typescript" in all_deps: stack.append("TypeScript")
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
"name": data.get("name", "unnamed"),
|
|
49
|
+
"version": data.get("version", "0.0.0"),
|
|
50
|
+
"stack": stack,
|
|
51
|
+
"scripts": list(data.get("scripts", {}).keys())
|
|
52
|
+
}
|
|
53
|
+
except Exception as e:
|
|
54
|
+
return {"error": str(e)}
|
|
55
|
+
|
|
56
|
+
def count_files(root: Path) -> Dict[str, int]:
|
|
57
|
+
stats = {"created": 0, "modified": 0, "total": 0}
|
|
58
|
+
# Simple count for now, comprehensive tracking would require git diff or extensive history
|
|
59
|
+
exclude = {".git", "node_modules", ".next", "dist", "build", ".agents", ".agents", ".gemini", "__pycache__"}
|
|
60
|
+
|
|
61
|
+
for root_dir, dirs, files in os.walk(root):
|
|
62
|
+
dirs[:] = [d for d in dirs if d not in exclude]
|
|
63
|
+
stats["total"] += len(files)
|
|
64
|
+
|
|
65
|
+
return stats
|
|
66
|
+
|
|
67
|
+
def detect_features(root: Path) -> List[str]:
|
|
68
|
+
# Heuristic: look at folder names in src/
|
|
69
|
+
features = []
|
|
70
|
+
src = root / "src"
|
|
71
|
+
if src.exists():
|
|
72
|
+
possible_dirs = ["components", "modules", "features", "app", "pages", "services"]
|
|
73
|
+
for d in possible_dirs:
|
|
74
|
+
p = src / d
|
|
75
|
+
if p.exists() and p.is_dir():
|
|
76
|
+
# List subdirectories as likely features
|
|
77
|
+
for child in p.iterdir():
|
|
78
|
+
if child.is_dir():
|
|
79
|
+
features.append(child.name)
|
|
80
|
+
return features[:10] # Limit to top 10
|
|
81
|
+
|
|
82
|
+
def print_status(root: Path):
|
|
83
|
+
info = analyze_package_json(root)
|
|
84
|
+
stats = count_files(root)
|
|
85
|
+
features = detect_features(root)
|
|
86
|
+
|
|
87
|
+
print("\n=== Project Status ===")
|
|
88
|
+
print(f"\n📁 Project: {info.get('name', root.name)}")
|
|
89
|
+
print(f"📂 Path: {root}")
|
|
90
|
+
print(f"🏷️ Type: {', '.join(info.get('stack', ['Generic']))}")
|
|
91
|
+
print(f"📊 Status: Active")
|
|
92
|
+
|
|
93
|
+
print("\n🔧 Tech Stack:")
|
|
94
|
+
for tech in info.get('stack', []):
|
|
95
|
+
print(f" • {tech}")
|
|
96
|
+
|
|
97
|
+
print(f"\n✅ Detected Modules/Features ({len(features)}):")
|
|
98
|
+
for feat in features:
|
|
99
|
+
print(f" • {feat}")
|
|
100
|
+
if not features:
|
|
101
|
+
print(" (No distinct feature modules detected)")
|
|
102
|
+
|
|
103
|
+
print(f"\n📄 Files: {stats['total']} total files tracked")
|
|
104
|
+
print("\n====================\n")
|
|
105
|
+
|
|
106
|
+
def main():
|
|
107
|
+
parser = argparse.ArgumentParser(description="Session Manager")
|
|
108
|
+
parser.add_argument("command", choices=["status", "info"], help="Command to run")
|
|
109
|
+
parser.add_argument("path", nargs="?", default=".", help="Project path")
|
|
110
|
+
|
|
111
|
+
args = parser.parse_args()
|
|
112
|
+
root = get_project_root(args.path)
|
|
113
|
+
|
|
114
|
+
if args.command == "status":
|
|
115
|
+
print_status(root)
|
|
116
|
+
elif args.command == "info":
|
|
117
|
+
print(json.dumps(analyze_package_json(root), indent=2))
|
|
118
|
+
|
|
119
|
+
if __name__ == "__main__":
|
|
120
|
+
main()
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import importlib.util
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
import tempfile
|
|
7
|
+
import unittest
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
TOOLKIT = Path(__file__).resolve().parents[2]
|
|
11
|
+
SCRIPTS = TOOLKIT / "scripts"
|
|
12
|
+
sys.path.insert(0, str(SCRIPTS))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def load_module(name: str, path: Path):
|
|
16
|
+
spec = importlib.util.spec_from_file_location(name, path)
|
|
17
|
+
assert spec and spec.loader
|
|
18
|
+
module = importlib.util.module_from_spec(spec)
|
|
19
|
+
sys.modules[name] = module
|
|
20
|
+
spec.loader.exec_module(module)
|
|
21
|
+
return module
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
validate_kit = load_module("agkit_validate_kit", SCRIPTS / "validate_kit.py")
|
|
25
|
+
component_registry = sys.modules["component_registry"]
|
|
26
|
+
dependency_graph = sys.modules["dependency_graph"]
|
|
27
|
+
security_scan = load_module("agkit_security_scan", TOOLKIT / "skills/vulnerability-scanner/scripts/security_scan.py")
|
|
28
|
+
dependency_analyzer = load_module("agkit_dependency_analyzer", TOOLKIT / "skills/vulnerability-scanner/scripts/dependency_analyzer.py")
|
|
29
|
+
bundle_analyzer = load_module("agkit_bundle_analyzer", TOOLKIT / "skills/performance-profiling/scripts/bundle_analyzer.py")
|
|
30
|
+
validation_runner = load_module("agkit_validation_runner", SCRIPTS / "validation_runner.py")
|
|
31
|
+
geo_checker = load_module("agkit_geo_checker", TOOLKIT / "skills/geo-fundamentals/scripts/geo_checker.py")
|
|
32
|
+
react_performance = load_module(
|
|
33
|
+
"agkit_react_performance",
|
|
34
|
+
TOOLKIT / "skills/nextjs-react-expert/scripts/react_performance_checker.py",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ToolkitRegressionTests(unittest.TestCase):
|
|
39
|
+
def test_toolkit_self_validation_passes(self):
|
|
40
|
+
findings = validate_kit.validate(TOOLKIT)
|
|
41
|
+
errors = [item for item in findings if item.severity == "error"]
|
|
42
|
+
self.assertEqual([], errors)
|
|
43
|
+
|
|
44
|
+
def test_mcp_config_is_valid_json(self):
|
|
45
|
+
data = json.loads((TOOLKIT / "mcp_config.json").read_text("utf-8"))
|
|
46
|
+
self.assertIn("mcpServers", data)
|
|
47
|
+
|
|
48
|
+
def test_security_scanner_ignores_patterns_inside_strings(self):
|
|
49
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
50
|
+
root = Path(tmp)
|
|
51
|
+
(root / "sample.py").write_text(
|
|
52
|
+
"""PATTERN = r'eval\\s*\\('
|
|
53
|
+
TOKEN = 'YOUR_API_KEY'
|
|
54
|
+
""",
|
|
55
|
+
"utf-8",
|
|
56
|
+
)
|
|
57
|
+
report = security_scan.run_full_scan(str(root), "all")
|
|
58
|
+
self.assertEqual(0, report["summary"]["critical"])
|
|
59
|
+
self.assertEqual(0, report["summary"]["high"])
|
|
60
|
+
|
|
61
|
+
def test_security_scanner_detects_executable_eval_and_secret(self):
|
|
62
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
63
|
+
root = Path(tmp)
|
|
64
|
+
(root / "bad.py").write_text(
|
|
65
|
+
"""api_key = 'sk_live_12345678901234567890'
|
|
66
|
+
eval(user_input)
|
|
67
|
+
""",
|
|
68
|
+
"utf-8",
|
|
69
|
+
) # agkit: allow-secret
|
|
70
|
+
report = security_scan.run_full_scan(str(root), "all")
|
|
71
|
+
self.assertGreaterEqual(report["summary"]["critical"], 1)
|
|
72
|
+
self.assertGreaterEqual(report["summary"]["high"], 1)
|
|
73
|
+
self.assertTrue(security_scan._should_fail(report, "high"))
|
|
74
|
+
|
|
75
|
+
def test_security_scanner_detects_nested_nextjs_header_configuration(self):
|
|
76
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
77
|
+
root = Path(tmp)
|
|
78
|
+
(root / "package.json").write_text('{"private":true}', "utf-8")
|
|
79
|
+
web = root / "web"
|
|
80
|
+
web.mkdir()
|
|
81
|
+
(web / "next.config.ts").write_text(
|
|
82
|
+
'const headers = [{ key: "Content-Security-Policy", value: "frame-ancestors \'none\'" }];',
|
|
83
|
+
"utf-8",
|
|
84
|
+
)
|
|
85
|
+
report = security_scan.run_full_scan(str(root), "config")
|
|
86
|
+
config = report["scans"]["configuration"]
|
|
87
|
+
self.assertTrue(config["checks"]["security_headers_config"])
|
|
88
|
+
self.assertFalse(any("security-header" in item.get("issue", "") for item in config["findings"]))
|
|
89
|
+
|
|
90
|
+
def test_dependency_analyzer_flags_missing_lock(self):
|
|
91
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
92
|
+
root = Path(tmp)
|
|
93
|
+
(root / "package.json").write_text('{"dependencies":{"demo":"latest"}}', "utf-8")
|
|
94
|
+
report = dependency_analyzer.analyze(root)
|
|
95
|
+
issues = {item["issue"] for item in report["findings"]}
|
|
96
|
+
self.assertIn("Missing JavaScript lock file", issues)
|
|
97
|
+
self.assertIn("Unbounded dependency version", issues)
|
|
98
|
+
|
|
99
|
+
def test_bundle_analyzer_flags_oversized_asset(self):
|
|
100
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
101
|
+
root = Path(tmp)
|
|
102
|
+
asset = root / "dist" / "app.js"
|
|
103
|
+
asset.parent.mkdir(parents=True)
|
|
104
|
+
asset.write_bytes(b"x" * 2048)
|
|
105
|
+
report = bundle_analyzer.analyze(root, file_warn_kib=1, file_fail_kib=2, total_fail_kib=100)
|
|
106
|
+
self.assertTrue(report["findings"])
|
|
107
|
+
self.assertEqual("high", report["findings"][0]["severity"])
|
|
108
|
+
|
|
109
|
+
def test_geo_checker_follows_localized_mdx_and_skips_layouts(self):
|
|
110
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
111
|
+
root = Path(tmp)
|
|
112
|
+
route = root / "web" / "src" / "app" / "docs" / "demo"
|
|
113
|
+
route.mkdir(parents=True)
|
|
114
|
+
(route / "page.tsx").write_text(
|
|
115
|
+
'import En from "./content.en.mdx";\n'
|
|
116
|
+
'import Vi from "./content.vi.mdx";\n'
|
|
117
|
+
'export default function Page(){ return <En />; }\n',
|
|
118
|
+
"utf-8",
|
|
119
|
+
)
|
|
120
|
+
(route / "content.en.mdx").write_text(
|
|
121
|
+
"# Demo\n\n## Overview\nText.\n\n## Usage\nText.\n",
|
|
122
|
+
"utf-8",
|
|
123
|
+
)
|
|
124
|
+
(route / "content.vi.mdx").write_text(
|
|
125
|
+
"# Trình diễn\n\n## Tổng quan\nNội dung.\n\n## Sử dụng\nNội dung.\n",
|
|
126
|
+
"utf-8",
|
|
127
|
+
)
|
|
128
|
+
(route.parent / "layout.tsx").write_text(
|
|
129
|
+
"export default function Layout({children}){return <div>{children}</div>}\n",
|
|
130
|
+
"utf-8",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
pages = geo_checker.find_web_pages(root)
|
|
134
|
+
self.assertEqual([route / "page.tsx"], pages)
|
|
135
|
+
result = geo_checker.check_page(route / "page.tsx", root)
|
|
136
|
+
self.assertGreaterEqual(result["score"], 60)
|
|
137
|
+
self.assertFalse(any("Multiple H1" in issue for issue in result["issues"]))
|
|
138
|
+
|
|
139
|
+
def test_react_checker_ignores_generated_next_output(self):
|
|
140
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
141
|
+
root = Path(tmp)
|
|
142
|
+
web = root / "web"
|
|
143
|
+
source = web / "src" / "app"
|
|
144
|
+
generated = web / ".next" / "types"
|
|
145
|
+
source.mkdir(parents=True)
|
|
146
|
+
generated.mkdir(parents=True)
|
|
147
|
+
(web / "package.json").write_text(
|
|
148
|
+
'{"dependencies":{"next":"16.2.10","react":"19.2.3"}}',
|
|
149
|
+
"utf-8",
|
|
150
|
+
)
|
|
151
|
+
(source / "page.tsx").write_text(
|
|
152
|
+
"export default function Page(){return <main><h1>Safe</h1></main>}\n",
|
|
153
|
+
"utf-8",
|
|
154
|
+
)
|
|
155
|
+
(generated / "page.ts").write_text(
|
|
156
|
+
"async function generated(){await one();\nawait two();}\n",
|
|
157
|
+
"utf-8",
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
checker = react_performance.PerformanceChecker(str(root))
|
|
161
|
+
# Resolve paths: macOS temp dirs use /var -> /private/var symlinks.
|
|
162
|
+
scanned = {path.resolve() for path in checker._iter_files(["ts", "tsx"])}
|
|
163
|
+
self.assertIn((source / "page.tsx").resolve(), scanned)
|
|
164
|
+
self.assertNotIn((generated / "page.ts").resolve(), scanned)
|
|
165
|
+
self.assertTrue(checker.run())
|
|
166
|
+
self.assertEqual([], checker.issues)
|
|
167
|
+
|
|
168
|
+
def test_runner_finds_embedded_toolkit_for_external_project(self):
|
|
169
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
170
|
+
project = Path(tmp)
|
|
171
|
+
located = validation_runner.locate_toolkit_root(project, str(SCRIPTS / "checklist.py"))
|
|
172
|
+
self.assertEqual(TOOLKIT, located)
|
|
173
|
+
|
|
174
|
+
def test_all_components_use_strict_semver(self):
|
|
175
|
+
manifest = component_registry.build_manifest(TOOLKIT)
|
|
176
|
+
for group in ("agents", "skills", "workflows", "rules"):
|
|
177
|
+
with self.subTest(group=group):
|
|
178
|
+
invalid = {
|
|
179
|
+
name: data["version"]
|
|
180
|
+
for name, data in manifest[group].items()
|
|
181
|
+
if not component_registry.is_semver(data["version"])
|
|
182
|
+
}
|
|
183
|
+
self.assertEqual({}, invalid)
|
|
184
|
+
|
|
185
|
+
def test_component_registry_and_lock_are_synchronized(self):
|
|
186
|
+
manifest = component_registry.build_manifest(TOOLKIT)
|
|
187
|
+
lock = component_registry.build_lock(TOOLKIT, manifest)
|
|
188
|
+
self.assertEqual(manifest, json.loads((TOOLKIT / "manifest.json").read_text("utf-8")))
|
|
189
|
+
self.assertEqual(lock, json.loads((TOOLKIT / "manifest.lock.json").read_text("utf-8")))
|
|
190
|
+
|
|
191
|
+
def test_dependency_graph_is_synchronized(self):
|
|
192
|
+
expected = dependency_graph.render(TOOLKIT)
|
|
193
|
+
self.assertEqual(expected, (TOOLKIT / "DEPENDENCY_GRAPH.md").read_text("utf-8"))
|
|
194
|
+
|
|
195
|
+
def test_workflow_dependencies_resolve(self):
|
|
196
|
+
manifest = component_registry.build_manifest(TOOLKIT)
|
|
197
|
+
agents = set(manifest["agents"])
|
|
198
|
+
skills = set(manifest["skills"])
|
|
199
|
+
for name, workflow in manifest["workflows"].items():
|
|
200
|
+
with self.subTest(workflow=name):
|
|
201
|
+
self.assertLessEqual(set(workflow["requires"]["agents"]), agents)
|
|
202
|
+
self.assertLessEqual(set(workflow["requires"]["skills"]), skills)
|
|
203
|
+
self.assertTrue(workflow["artifactOutputs"])
|
|
204
|
+
|
|
205
|
+
def test_orchestration_guidance_is_antigravity_first_and_bounded(self):
|
|
206
|
+
orchestrator = (TOOLKIT / "agent/orchestrator.md").read_text("utf-8")
|
|
207
|
+
parallel = (TOOLKIT / "skills/parallel-agents/SKILL.md").read_text("utf-8")
|
|
208
|
+
combined = orchestrator + "\n" + parallel
|
|
209
|
+
|
|
210
|
+
self.assertNotIn("Claude Code's native Agent Tool", combined)
|
|
211
|
+
self.assertNotIn("Claude orchestrates autonomously", combined)
|
|
212
|
+
self.assertNotIn("**Explore** | Haiku", combined)
|
|
213
|
+
self.assertNotIn("**Plan** | Sonnet", combined)
|
|
214
|
+
self.assertIn("Google Antigravity is the primary production runtime", combined)
|
|
215
|
+
self.assertIn("max_delegation_depth", combined)
|
|
216
|
+
self.assertIn("Never allow an open-ended ReAct", combined)
|
|
217
|
+
self.assertIn("isolated worktree", combined)
|
|
218
|
+
self.assertIn("untrusted data", combined)
|
|
219
|
+
|
|
220
|
+
def test_caret_semver_resolution(self):
|
|
221
|
+
self.assertTrue(component_registry.version_satisfies("1.4.2", "^1.2.0"))
|
|
222
|
+
self.assertFalse(component_registry.version_satisfies("2.0.0", "^1.2.0"))
|
|
223
|
+
self.assertTrue(component_registry.version_satisfies("0.3.5", "^0.3.1"))
|
|
224
|
+
self.assertFalse(component_registry.version_satisfies("0.4.0", "^0.3.1"))
|
|
225
|
+
|
|
226
|
+
def test_memory_topics_are_present(self):
|
|
227
|
+
topics = {
|
|
228
|
+
"project-conventions.md",
|
|
229
|
+
"user-preferences.md",
|
|
230
|
+
"tech-decisions.md",
|
|
231
|
+
"feedback-history.md",
|
|
232
|
+
}
|
|
233
|
+
self.assertLessEqual(topics, {path.name for path in (TOOLKIT / "memory").glob("*.md")})
|
|
234
|
+
self.assertLessEqual(len((TOOLKIT / ".opencode/memory/MEMORY.md").read_text("utf-8").splitlines()), 200)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
if __name__ == "__main__":
|
|
238
|
+
unittest.main()
|