tribunal-kit 6.0.0 → 7.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/.agent/.manifest.json +78 -0
- package/.agent/ARCHITECTURE.md +19 -241
- package/.agent/agents/accessibility-reviewer.md +23 -16
- package/.agent/agents/ai-code-reviewer.md +25 -21
- package/.agent/agents/anti-pattern-reviewer.md +12 -7
- package/.agent/agents/api-architect.md +1 -0
- package/.agent/agents/backend-specialist.md +23 -22
- package/.agent/agents/cloud-engineer.md +1 -0
- package/.agent/agents/code-archaeologist.md +1 -0
- package/.agent/agents/complexity-reviewer.md +10 -7
- package/.agent/agents/database-architect.md +3 -2
- package/.agent/agents/db-latency-auditor.md +6 -2
- package/.agent/agents/debugger.md +3 -2
- package/.agent/agents/dependency-reviewer.md +1 -0
- package/.agent/agents/devops-engineer.md +9 -8
- package/.agent/agents/documentation-writer.md +6 -5
- package/.agent/agents/explorer-agent.md +1 -0
- package/.agent/agents/frontend-reviewer.md +21 -17
- package/.agent/agents/frontend-specialist.md +23 -20
- package/.agent/agents/game-developer.md +1 -0
- package/.agent/agents/interaction-reviewer.md +10 -5
- package/.agent/agents/logic-reviewer.md +3 -0
- package/.agent/agents/minimalist-reviewer.md +6 -0
- package/.agent/agents/mobile-developer.md +7 -6
- package/.agent/agents/mobile-reviewer.md +14 -13
- package/.agent/agents/orchestrator.md +3 -0
- package/.agent/agents/penetration-tester.md +1 -0
- package/.agent/agents/performance-optimizer.md +6 -5
- package/.agent/agents/performance-reviewer.md +6 -6
- package/.agent/agents/pipeline-reviewer.md +144 -0
- package/.agent/agents/precedence-reviewer.md +1 -0
- package/.agent/agents/product-manager.md +1 -0
- package/.agent/agents/product-owner.md +1 -0
- package/.agent/agents/product-reviewer.md +12 -7
- package/.agent/agents/project-planner.md +3 -0
- package/.agent/agents/qa-automation-engineer.md +50 -43
- package/.agent/agents/resilience-reviewer.md +1 -0
- package/.agent/agents/schema-reviewer.md +1 -0
- package/.agent/agents/security-auditor.md +24 -24
- package/.agent/agents/seo-specialist.md +33 -23
- package/.agent/agents/sql-reviewer.md +5 -4
- package/.agent/agents/supervisor-agent.md +12 -2
- package/.agent/agents/swarm-worker-contracts.md +13 -13
- package/.agent/agents/swarm-worker-registry.md +51 -51
- package/.agent/agents/system-architect.md +1 -0
- package/.agent/agents/test-coverage-reviewer.md +25 -22
- package/.agent/agents/test-engineer.md +12 -11
- package/.agent/agents/throughput-optimizer.md +45 -40
- package/.agent/agents/type-safety-reviewer.md +5 -4
- package/.agent/agents/ui-ux-auditor.md +6 -4
- package/.agent/agents/ui-visual-auditor.md +3 -0
- package/.agent/agents/ux-reviewer.md +11 -6
- package/.agent/agents/visual-reviewer.md +11 -6
- package/.agent/agents/vitals-reviewer.md +5 -4
- package/.agent/history/memory/.memory.idx +3716 -1
- package/.agent/history/memory/MEMORY.md +246 -1
- package/.agent/mcp_config.json +1 -6
- package/.agent/routing_index.json +2034 -263
- package/.agent/rules/GEMINI.md +12 -10
- package/.agent/rules/GEMINI_PLANNER.md +19 -21
- package/.agent/scripts/_colors.js +52 -54
- package/.agent/scripts/_utils.js +52 -53
- package/.agent/scripts/auto_preview.js +39 -43
- package/.agent/scripts/bundle_analyzer.js +47 -60
- package/.agent/scripts/case_law_manager.js +200 -294
- package/.agent/scripts/checklist.js +73 -94
- package/.agent/scripts/cicd_validator.js +305 -0
- package/.agent/scripts/compile_router.py +4 -111
- package/.agent/scripts/context_broker.js +317 -412
- package/.agent/scripts/contract_engine.js +402 -0
- package/.agent/scripts/dependency_analyzer.js +112 -124
- package/.agent/scripts/graph_builder.js +75 -103
- package/.agent/scripts/graph_visualizer.js +10 -12
- package/.agent/scripts/graph_zoom.js +38 -55
- package/.agent/scripts/guardrail_engine.js +195 -145
- package/.agent/scripts/impact_classifier.js +55 -30
- package/.agent/scripts/inner_loop_validator.js +108 -159
- package/.agent/scripts/integrity_manifest.js +59 -67
- package/.agent/scripts/lint_runner.js +65 -75
- package/.agent/scripts/marathon_harness.js +131 -208
- package/.agent/scripts/migrate_skills_frontmatter.py +4 -63
- package/.agent/scripts/minify_context.js +29 -33
- package/.agent/scripts/minimal_change_engine.js +95 -87
- package/.agent/scripts/mutation_runner.js +46 -62
- package/.agent/scripts/pipeline_engine.js +320 -209
- package/.agent/scripts/prompt_compiler.js +118 -93
- package/.agent/scripts/schema_validator.js +73 -121
- package/.agent/scripts/security_scan.js +88 -117
- package/.agent/scripts/session_manager.js +52 -69
- package/.agent/scripts/signal_detector.js +24 -22
- package/.agent/scripts/skill_evolution.js +184 -245
- package/.agent/scripts/skill_integrator.js +35 -48
- package/.agent/scripts/socratic_gate_policy.js +15 -12
- package/.agent/scripts/strengthen_skills.js +29 -33
- package/.agent/scripts/swarm_dispatcher.js +120 -151
- package/.agent/scripts/test_runner.js +54 -56
- package/.agent/scripts/token_budget_broker.js +9 -7
- package/.agent/scripts/trace_engine.js +126 -0
- package/.agent/scripts/verify_all.js +76 -93
- package/.agent/scripts/visual_audit.js +16 -21
- package/.agent/skill_topic_map.json +237 -0
- package/.agent/skills/12-principles-of-animation/SKILL.md +7 -0
- package/.agent/skills/60fps-animation/SKILL.md +7 -0
- package/.agent/skills/accessible-animation/SKILL.md +5 -1
- package/.agent/skills/adapt/SKILL.md +7 -1
- package/.agent/skills/advanced-rag-pipelines/SKILL.md +1 -0
- package/.agent/skills/agent-organizer/SKILL.md +1 -0
- package/.agent/skills/agentic-patterns/SKILL.md +33 -25
- package/.agent/skills/agentic-workflows-2026/SKILL.md +80 -0
- package/.agent/skills/ai-app-hardening/SKILL.md +59 -0
- package/.agent/skills/ai-prompt-injection-defense/SKILL.md +7 -6
- package/.agent/skills/animation-on-scroll/SKILL.md +24 -15
- package/.agent/skills/animation-systems/SKILL.md +11 -10
- package/.agent/skills/antfu-conventions/SKILL.md +7 -2
- package/.agent/skills/api-patterns/SKILL.md +14 -10
- package/.agent/skills/api-security-auditor/SKILL.md +15 -14
- package/.agent/skills/app-builder/SKILL.md +1 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +2 -2
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +12 -12
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +3 -3
- package/.agent/skills/apple-design/SKILL.md +8 -7
- package/.agent/skills/architecture/SKILL.md +3 -2
- package/.agent/skills/audit-and-fix/SKILL.md +8 -5
- package/.agent/skills/authentication-best-practices/SKILL.md +9 -8
- package/.agent/skills/backend-security-expert/SKILL.md +1 -0
- package/.agent/skills/baseline-ui/SKILL.md +8 -7
- package/.agent/skills/bash-linux/SKILL.md +1 -0
- package/.agent/skills/behavioral-modes/SKILL.md +1 -0
- package/.agent/skills/better-colors/SKILL.md +11 -7
- package/.agent/skills/better-typography/SKILL.md +30 -16
- package/.agent/skills/better-ui/SKILL.md +17 -10
- package/.agent/skills/bolder/SKILL.md +6 -0
- package/.agent/skills/brainstorming/SKILL.md +6 -4
- package/.agent/skills/browser-native-ai/SKILL.md +5 -4
- package/.agent/skills/build-primitive/SKILL.md +5 -0
- package/.agent/skills/building-native-ui/SKILL.md +1 -0
- package/.agent/skills/cicd-pro/SKILL.md +2 -1
- package/.agent/skills/clarify/SKILL.md +19 -14
- package/.agent/skills/clean-code/SKILL.md +16 -15
- package/.agent/skills/cloud-architect/SKILL.md +1 -0
- package/.agent/skills/cobejs/SKILL.md +7 -9
- package/.agent/skills/code-review-checklist/SKILL.md +1 -0
- package/.agent/skills/codebase-design/SKILL.md +7 -2
- package/.agent/skills/colorize/SKILL.md +8 -3
- package/.agent/skills/compact-landing/SKILL.md +8 -3
- package/.agent/skills/company-logos/SKILL.md +6 -0
- package/.agent/skills/config-validator/SKILL.md +10 -9
- package/.agent/skills/containerization-pro/SKILL.md +6 -5
- package/.agent/skills/context-engineering-pro/SKILL.md +70 -0
- package/.agent/skills/create-design-md/SKILL.md +13 -5
- package/.agent/skills/critique/SKILL.md +10 -8
- package/.agent/skills/csharp-developer/SKILL.md +1 -0
- package/.agent/skills/data-validation-schemas/SKILL.md +28 -23
- package/.agent/skills/database-design/SKILL.md +2 -1
- package/.agent/skills/delight/SKILL.md +6 -0
- package/.agent/skills/deployment-procedures/SKILL.md +2 -1
- package/.agent/skills/design-lab/SKILL.md +5 -0
- package/.agent/skills/devops-engineer/SKILL.md +3 -2
- package/.agent/skills/devops-incident-responder/SKILL.md +2 -1
- package/.agent/skills/diagnosing-bugs/SKILL.md +12 -2
- package/.agent/skills/distill/SKILL.md +7 -2
- package/.agent/skills/documentation-templates/SKILL.md +3 -2
- package/.agent/skills/domain-modeling/SKILL.md +12 -4
- package/.agent/skills/duckdb-analytical-sql/SKILL.md +59 -0
- package/.agent/skills/edge-ai-mobile/SKILL.md +50 -0
- package/.agent/skills/edge-computing/SKILL.md +9 -8
- package/.agent/skills/emil-design-eng/SKILL.md +43 -27
- package/.agent/skills/error-resilience/SKILL.md +34 -16
- package/.agent/skills/expo-router-v4/SKILL.md +81 -0
- package/.agent/skills/extract-design-system/SKILL.md +12 -11
- package/.agent/skills/fabel-protocol/SKILL.md +24 -17
- package/.agent/skills/fixing-accessibility/SKILL.md +23 -16
- package/.agent/skills/fixing-metadata/SKILL.md +24 -13
- package/.agent/skills/fixing-motion-performance/SKILL.md +7 -5
- package/.agent/skills/framer-motion-expert/SKILL.md +29 -15
- package/.agent/skills/frontend-design/SKILL.md +21 -13
- package/.agent/skills/frontend-security-expert/SKILL.md +1 -0
- package/.agent/skills/game-design-expert/SKILL.md +1 -0
- package/.agent/skills/game-engineering-expert/SKILL.md +1 -0
- package/.agent/skills/generative-ui-expert/SKILL.md +3 -2
- package/.agent/skills/geo-fundamentals/SKILL.md +2 -1
- package/.agent/skills/git-pro/SKILL.md +10 -9
- package/.agent/skills/github-operations/SKILL.md +2 -1
- package/.agent/skills/gpt-taste/SKILL.md +7 -0
- package/.agent/skills/gsap-core/SKILL.md +26 -22
- package/.agent/skills/gsap-frameworks/SKILL.md +6 -5
- package/.agent/skills/gsap-performance/SKILL.md +4 -3
- package/.agent/skills/gsap-plugins/SKILL.md +34 -33
- package/.agent/skills/gsap-react/SKILL.md +9 -8
- package/.agent/skills/gsap-scrolltrigger/SKILL.md +34 -33
- package/.agent/skills/gsap-timeline/SKILL.md +18 -15
- package/.agent/skills/gsap-utils/SKILL.md +25 -24
- package/.agent/skills/harden/SKILL.md +9 -3
- package/.agent/skills/harness-protocol/SKILL.md +1 -0
- package/.agent/skills/i18n-localization/SKILL.md +10 -9
- package/.agent/skills/impeccable/SKILL.md +5 -0
- package/.agent/skills/improve-codebase-architecture/SKILL.md +10 -5
- package/.agent/skills/improve-ui/SKILL.md +12 -5
- package/.agent/skills/intelligent-routing/SKILL.md +7 -6
- package/.agent/skills/knowledge-graph/SKILL.md +1 -0
- package/.agent/skills/landing-page/SKILL.md +1 -0
- package/.agent/skills/lint-and-validate/SKILL.md +9 -4
- package/.agent/skills/llm-engineering/SKILL.md +55 -54
- package/.agent/skills/local-first/SKILL.md +20 -19
- package/.agent/skills/local-first-architecture/SKILL.md +6 -1
- package/.agent/skills/lottie-animation/SKILL.md +7 -3
- package/.agent/skills/marquee-loop/SKILL.md +1 -0
- package/.agent/skills/masked-reveal/SKILL.md +17 -4
- package/.agent/skills/mcp-builder/SKILL.md +13 -10
- package/.agent/skills/micro-interaction/SKILL.md +20 -5
- package/.agent/skills/mobile-design/SKILL.md +26 -15
- package/.agent/skills/monorepo-management/SKILL.md +3 -2
- package/.agent/skills/morphing-icons/SKILL.md +16 -6
- package/.agent/skills/motion-engineering/SKILL.md +19 -15
- package/.agent/skills/nextjs-react-expert/SKILL.md +26 -21
- package/.agent/skills/nodejs-best-practices/SKILL.md +89 -76
- package/.agent/skills/observability/SKILL.md +45 -44
- package/.agent/skills/opentelemetry-observability/SKILL.md +59 -0
- package/.agent/skills/page-transition-animation/SKILL.md +6 -3
- package/.agent/skills/parallel-agents/SKILL.md +7 -2
- package/.agent/skills/performance-profiling/SKILL.md +24 -13
- package/.agent/skills/plan-writing/SKILL.md +1 -0
- package/.agent/skills/platform-engineer/SKILL.md +3 -2
- package/.agent/skills/platform-engineering-opentofu/SKILL.md +68 -0
- package/.agent/skills/playwright-ai-e2e/SKILL.md +60 -0
- package/.agent/skills/playwright-best-practices/SKILL.md +29 -28
- package/.agent/skills/polish/SKILL.md +13 -12
- package/.agent/skills/powershell-windows/SKILL.md +1 -0
- package/.agent/skills/pricing-page/SKILL.md +8 -3
- package/.agent/skills/product-aware-heuristics/SKILL.md +122 -72
- package/.agent/skills/progressive-blur/SKILL.md +9 -4
- package/.agent/skills/project-idioms/SKILL.md +1 -0
- package/.agent/skills/property-based-testing/SKILL.md +58 -0
- package/.agent/skills/python-patterns/SKILL.md +1 -0
- package/.agent/skills/python-pro/SKILL.md +1 -0
- package/.agent/skills/quieter/SKILL.md +6 -0
- package/.agent/skills/react-doctor/SKILL.md +6 -0
- package/.agent/skills/react-specialist/SKILL.md +32 -28
- package/.agent/skills/readme-builder/SKILL.md +1 -0
- package/.agent/skills/realtime-patterns/SKILL.md +34 -33
- package/.agent/skills/red-team-tactics/SKILL.md +1 -0
- package/.agent/skills/redesign-skill/SKILL.md +6 -0
- package/.agent/skills/review-animations/SKILL.md +5 -2
- package/.agent/skills/review-animations/STANDARDS.md +37 -23
- package/.agent/skills/rust-pro/SKILL.md +1 -0
- package/.agent/skills/seo-fundamentals/SKILL.md +4 -3
- package/.agent/skills/server-management/SKILL.md +1 -0
- package/.agent/skills/shadcn-ui-expert/SKILL.md +28 -22
- package/.agent/skills/shape/SKILL.md +9 -2
- package/.agent/skills/skill-creator/SKILL.md +1 -0
- package/.agent/skills/soft-skill/SKILL.md +6 -0
- package/.agent/skills/sounds-on-the-web/SKILL.md +1 -0
- package/.agent/skills/sql-pro/SKILL.md +1 -0
- package/.agent/skills/supabase-postgres-best-practices/SKILL.md +1 -0
- package/.agent/skills/svg-animation/SKILL.md +16 -7
- package/.agent/skills/swiftui-expert/SKILL.md +1 -0
- package/.agent/skills/swiss-design/SKILL.md +5 -0
- package/.agent/skills/system-design-pro/SKILL.md +1 -0
- package/.agent/skills/systematic-debugging/SKILL.md +1 -0
- package/.agent/skills/tailwind-patterns/SKILL.md +25 -11
- package/.agent/skills/taste-skill/SKILL.md +6 -0
- package/.agent/skills/tdd-workflow/SKILL.md +5 -0
- package/.agent/skills/test-result-analyzer/SKILL.md +1 -0
- package/.agent/skills/testing-patterns/SKILL.md +123 -115
- package/.agent/skills/thermo-nuclear-code-quality-review/SKILL.md +5 -0
- package/.agent/skills/thinking-protocol/SKILL.md +3 -0
- package/.agent/skills/to-spring-or-not-to-spring/SKILL.md +9 -8
- package/.agent/skills/transitions-dev/SKILL.md +19 -6
- package/.agent/skills/trend-researcher/SKILL.md +1 -0
- package/.agent/skills/typescript-advanced/SKILL.md +23 -18
- package/.agent/skills/typeset/SKILL.md +10 -1
- package/.agent/skills/ui-reasoning-engine/SKILL.md +67 -48
- package/.agent/skills/ui-skill-packs/SKILL.md +6 -1
- package/.agent/skills/ui-skills-root/SKILL.md +39 -38
- package/.agent/skills/ui-ux-pro-max/SKILL.md +34 -26
- package/.agent/skills/ui-ux-researcher/SKILL.md +1 -0
- package/.agent/skills/vector-search-pgvector/SKILL.md +78 -0
- package/.agent/skills/vue-expert/SKILL.md +22 -19
- package/.agent/skills/vulnerability-scanner/SKILL.md +22 -21
- package/.agent/skills/web-accessibility-auditor/SKILL.md +2 -1
- package/.agent/skills/web-design-guidelines/SKILL.md +16 -10
- package/.agent/skills/web-quality-audit/SKILL.md +5 -0
- package/.agent/skills/webapp-testing/SKILL.md +14 -13
- package/.agent/skills/webgpu-performance/SKILL.md +1 -0
- package/.agent/skills/whimsy-injector/SKILL.md +9 -5
- package/.agent/skills/workflow-optimizer/SKILL.md +1 -0
- package/.agent/skills/zero-trust-passkeys/SKILL.md +90 -0
- package/.agent/templates/DESIGN.md +119 -110
- package/.agent/templates/design-tokens.json +9 -6
- package/.agent/workflows/acf.md +1 -0
- package/.agent/workflows/api-tester.md +1 -0
- package/.agent/workflows/audit.md +1 -0
- package/.agent/workflows/brainstorm.md +1 -0
- package/.agent/workflows/changelog.md +1 -0
- package/.agent/workflows/contract.md +60 -0
- package/.agent/workflows/create.md +1 -0
- package/.agent/workflows/debug.md +1 -0
- package/.agent/workflows/deploy.md +1 -0
- package/.agent/workflows/enhance.md +1 -0
- package/.agent/workflows/fix-ci.md +89 -0
- package/.agent/workflows/fix.md +1 -0
- package/.agent/workflows/generate.md +1 -0
- package/.agent/workflows/marathon.md +1 -0
- package/.agent/workflows/migrate.md +1 -0
- package/.agent/workflows/minimal.md +9 -7
- package/.agent/workflows/orchestrate.md +1 -0
- package/.agent/workflows/performance-benchmarker.md +1 -0
- package/.agent/workflows/pipeline.md +26 -21
- package/.agent/workflows/plan.md +1 -0
- package/.agent/workflows/preview.md +1 -0
- package/.agent/workflows/refactor.md +3 -2
- package/.agent/workflows/review-ai.md +4 -3
- package/.agent/workflows/review.md +1 -0
- package/.agent/workflows/session.md +1 -0
- package/.agent/workflows/status.md +1 -0
- package/.agent/workflows/strengthen-skills.md +1 -0
- package/.agent/workflows/super-prompt.md +1 -0
- package/.agent/workflows/swarm.md +15 -3
- package/.agent/workflows/test.md +8 -7
- package/.agent/workflows/tribunal-backend.md +3 -2
- package/.agent/workflows/tribunal-cicd.md +104 -0
- package/.agent/workflows/tribunal-database.md +1 -0
- package/.agent/workflows/tribunal-frontend.md +8 -6
- package/.agent/workflows/tribunal-full.md +15 -14
- package/.agent/workflows/tribunal-mobile.md +6 -5
- package/.agent/workflows/tribunal-performance.md +1 -0
- package/.agent/workflows/tribunal-speed.md +1 -0
- package/.agent/workflows/tribunal-ui.md +29 -21
- package/.agent/workflows/ui-ux-pro-max.md +19 -15
- package/CONTRIBUTING.md +3 -3
- package/README.md +160 -88
- package/SECURITY.md +11 -11
- package/bin/mcp-server.js +512 -233
- package/bin/tribunal-kit.js +29 -30
- package/bin/wrapper.js +45 -48
- package/dist/cli.js +26 -0
- package/dist/commands/case.js +2 -0
- package/dist/commands/contract.js +440 -0
- package/dist/commands/memory.js +3 -2
- package/dist/commands/native.js +36 -0
- package/dist/commands/status.js +6 -0
- package/dist/esm/index.mjs +32 -0
- package/dist/index.d.ts +58 -3
- package/package.json +20 -16
- package/scripts/benchmark.js +62 -86
- package/scripts/changelog.js +67 -73
- package/scripts/fix-vbc.js +13 -15
- package/scripts/fix-vbc.ps1 +2 -118
- package/scripts/stress_benchmark.js +358 -0
- package/scripts/sync-version.js +71 -41
- package/scripts/validate-payload.js +23 -30
- package/scripts/visual_audit.js +23 -13
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
* node .agent/scripts/security_scan.js . --files src/auth.ts src/db.ts
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
'use strict';
|
|
26
26
|
|
|
27
|
-
const fs = require(
|
|
28
|
-
const path = require(
|
|
27
|
+
const fs = require('fs');
|
|
28
|
+
const path = require('path');
|
|
29
29
|
|
|
30
30
|
const {
|
|
31
31
|
RED,
|
|
@@ -40,18 +40,12 @@ const {
|
|
|
40
40
|
banner,
|
|
41
41
|
timer,
|
|
42
42
|
formatMs,
|
|
43
|
-
} = require(
|
|
43
|
+
} = require('./_colors');
|
|
44
44
|
|
|
45
|
-
const { walkDir, SOURCE_EXTENSIONS } = require(
|
|
45
|
+
const { walkDir, SOURCE_EXTENSIONS, DEFAULT_SKIP_DIRS } = require('./_utils');
|
|
46
46
|
|
|
47
47
|
// ── Security-specific source extensions (broader than default) ──────────────
|
|
48
|
-
const SCAN_EXTENSIONS = new Set([
|
|
49
|
-
...SOURCE_EXTENSIONS,
|
|
50
|
-
".py",
|
|
51
|
-
".go",
|
|
52
|
-
".java",
|
|
53
|
-
".rb",
|
|
54
|
-
]);
|
|
48
|
+
const SCAN_EXTENSIONS = new Set([...SOURCE_EXTENSIONS, '.py', '.go', '.java', '.rb']);
|
|
55
49
|
|
|
56
50
|
const SEVERITY_COLORS = {
|
|
57
51
|
critical: RED + BOLD,
|
|
@@ -67,142 +61,117 @@ const PATTERNS = [
|
|
|
67
61
|
// Secrets
|
|
68
62
|
[
|
|
69
63
|
/(?:password|passwd|pwd)\s*=\s*["'][^"']+["']/i,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
'critical',
|
|
65
|
+
'Hardcoded Secret',
|
|
66
|
+
'Hardcoded password detected',
|
|
73
67
|
],
|
|
74
68
|
[
|
|
75
69
|
/(?:api_key|apikey|api_secret)\s*=\s*["'][^"']+["']/i,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
'critical',
|
|
71
|
+
'Hardcoded Secret',
|
|
72
|
+
'Hardcoded API key detected',
|
|
79
73
|
],
|
|
80
74
|
[
|
|
81
75
|
/(?:secret|token|auth_token)\s*=\s*["'][A-Za-z0-9+/=]{16,}["']/i,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
76
|
+
'critical',
|
|
77
|
+
'Hardcoded Secret',
|
|
78
|
+
'Hardcoded secret/token detected',
|
|
85
79
|
],
|
|
86
80
|
[
|
|
87
81
|
/(?:PRIVATE_KEY|private_key)\s*=\s*["']/i,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
'critical',
|
|
83
|
+
'Hardcoded Secret',
|
|
84
|
+
'Hardcoded private key detected',
|
|
91
85
|
],
|
|
92
86
|
|
|
93
87
|
// SQL Injection
|
|
94
88
|
[
|
|
95
89
|
/(?:query|execute|raw)\s*\(\s*[`"'].*\$\{/i,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
90
|
+
'high',
|
|
91
|
+
'SQL Injection',
|
|
92
|
+
'String interpolation in SQL query — use parameterized queries',
|
|
99
93
|
],
|
|
100
94
|
[
|
|
101
95
|
/(?:query|execute|raw)\s*\(\s*["'].*\+\s*(?:req|input|params|body)/i,
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
96
|
+
'high',
|
|
97
|
+
'SQL Injection',
|
|
98
|
+
'String concatenation with user input in SQL',
|
|
105
99
|
],
|
|
106
100
|
[
|
|
107
101
|
/\.raw\s*\(\s*`/,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
102
|
+
'medium',
|
|
103
|
+
'SQL Injection',
|
|
104
|
+
'Raw query with template literal — verify inputs are sanitized',
|
|
111
105
|
],
|
|
112
106
|
|
|
113
107
|
// XSS
|
|
114
108
|
[
|
|
115
109
|
/\.innerHTML\s*=/,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
'high',
|
|
111
|
+
'XSS',
|
|
112
|
+
'Direct innerHTML assignment — use textContent or a sanitizer',
|
|
119
113
|
],
|
|
120
114
|
[
|
|
121
115
|
/dangerouslySetInnerHTML/,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
116
|
+
'medium',
|
|
117
|
+
'XSS',
|
|
118
|
+
'dangerouslySetInnerHTML used — ensure input is sanitized',
|
|
125
119
|
],
|
|
126
|
-
[/document\.write\s*\(/,
|
|
120
|
+
[/document\.write\s*\(/, 'high', 'XSS', 'document.write() is an XSS vector'],
|
|
127
121
|
|
|
128
122
|
// Insecure Functions
|
|
129
|
-
[
|
|
130
|
-
|
|
131
|
-
"high",
|
|
132
|
-
"Code Injection",
|
|
133
|
-
"eval() is a code injection vector — avoid entirely",
|
|
134
|
-
],
|
|
135
|
-
[
|
|
136
|
-
/new\s+Function\s*\(/,
|
|
137
|
-
"high",
|
|
138
|
-
"Code Injection",
|
|
139
|
-
"new Function() is equivalent to eval()",
|
|
140
|
-
],
|
|
123
|
+
[/\beval\s*\(/, 'high', 'Code Injection', 'eval() is a code injection vector — avoid entirely'],
|
|
124
|
+
[/new\s+Function\s*\(/, 'high', 'Code Injection', 'new Function() is equivalent to eval()'],
|
|
141
125
|
[
|
|
142
126
|
/child_process\.exec\s*\(/,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
127
|
+
'medium',
|
|
128
|
+
'Command Injection',
|
|
129
|
+
'exec() with unsanitized input is a command injection vector',
|
|
146
130
|
],
|
|
147
131
|
[
|
|
148
132
|
/subprocess\.call\s*\(\s*[^,\]]*\bshell\s*=\s*True/,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
133
|
+
'high',
|
|
134
|
+
'Command Injection',
|
|
135
|
+
'subprocess with shell=True — use shell=False and pass args as list',
|
|
152
136
|
],
|
|
153
137
|
|
|
154
138
|
// Crypto
|
|
155
139
|
[
|
|
156
140
|
/createHash\s*\(\s*["']md5["']/,
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
],
|
|
161
|
-
[
|
|
162
|
-
/createHash\s*\(\s*["']sha1["']/,
|
|
163
|
-
"medium",
|
|
164
|
-
"Weak Crypto",
|
|
165
|
-
"SHA-1 is deprecated — use SHA-256+",
|
|
141
|
+
'medium',
|
|
142
|
+
'Weak Crypto',
|
|
143
|
+
'MD5 is cryptographically broken — use SHA-256+',
|
|
166
144
|
],
|
|
145
|
+
[/createHash\s*\(\s*["']sha1["']/, 'medium', 'Weak Crypto', 'SHA-1 is deprecated — use SHA-256+'],
|
|
167
146
|
[
|
|
168
147
|
/Math\.random\s*\(/,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
148
|
+
'low',
|
|
149
|
+
'Weak Randomness',
|
|
150
|
+
'Math.random() is not cryptographically secure — use crypto.randomBytes()',
|
|
172
151
|
],
|
|
173
152
|
|
|
174
153
|
// Auth Issues
|
|
175
154
|
[
|
|
176
155
|
/algorithms\s*:\s*\[\s*["']none["']/,
|
|
177
|
-
|
|
178
|
-
|
|
156
|
+
'critical',
|
|
157
|
+
'Auth Bypass',
|
|
179
158
|
"JWT 'none' algorithm allows auth bypass",
|
|
180
159
|
],
|
|
181
|
-
[
|
|
182
|
-
|
|
183
|
-
"high",
|
|
184
|
-
"Auth Bypass",
|
|
185
|
-
"SSL/TLS verification disabled",
|
|
186
|
-
],
|
|
187
|
-
[
|
|
188
|
-
/rejectUnauthorized\s*:\s*false/,
|
|
189
|
-
"high",
|
|
190
|
-
"Auth Bypass",
|
|
191
|
-
"TLS certificate validation disabled",
|
|
192
|
-
],
|
|
160
|
+
[/verify\s*:\s*false/, 'high', 'Auth Bypass', 'SSL/TLS verification disabled'],
|
|
161
|
+
[/rejectUnauthorized\s*:\s*false/, 'high', 'Auth Bypass', 'TLS certificate validation disabled'],
|
|
193
162
|
|
|
194
163
|
// Information Disclosure
|
|
195
164
|
[
|
|
196
165
|
/console\.log\s*\(.*(?:password|secret|token|key)/i,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
166
|
+
'medium',
|
|
167
|
+
'Info Disclosure',
|
|
168
|
+
'Sensitive data logged to console',
|
|
200
169
|
],
|
|
201
170
|
[
|
|
202
171
|
/\.env(?:\.local|\.production)/,
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
172
|
+
'low',
|
|
173
|
+
'Info Disclosure',
|
|
174
|
+
'Env file reference — ensure not committed to git',
|
|
206
175
|
],
|
|
207
176
|
];
|
|
208
177
|
|
|
@@ -218,20 +187,16 @@ function scanFile(filepath, projectRoot) {
|
|
|
218
187
|
|
|
219
188
|
let content;
|
|
220
189
|
try {
|
|
221
|
-
content = fs.readFileSync(filepath,
|
|
190
|
+
content = fs.readFileSync(filepath, 'utf8');
|
|
222
191
|
} catch {
|
|
223
192
|
return findings;
|
|
224
193
|
}
|
|
225
194
|
|
|
226
|
-
const lines = content.split(
|
|
195
|
+
const lines = content.split('\n');
|
|
227
196
|
for (let i = 0; i < lines.length; i++) {
|
|
228
197
|
const stripped = lines[i].trim();
|
|
229
198
|
// Skip comments
|
|
230
|
-
if (
|
|
231
|
-
stripped.startsWith("//") ||
|
|
232
|
-
stripped.startsWith("#") ||
|
|
233
|
-
stripped.startsWith("*")
|
|
234
|
-
) {
|
|
199
|
+
if (stripped.startsWith('//') || stripped.startsWith('#') || stripped.startsWith('*')) {
|
|
235
200
|
continue;
|
|
236
201
|
}
|
|
237
202
|
|
|
@@ -266,9 +231,7 @@ function scanDirectory(projectRoot, targetFiles) {
|
|
|
266
231
|
|
|
267
232
|
if (targetFiles && targetFiles.length > 0) {
|
|
268
233
|
for (const fpath of targetFiles) {
|
|
269
|
-
const absPath = path.isAbsolute(fpath)
|
|
270
|
-
? fpath
|
|
271
|
-
: path.join(projectRoot, fpath);
|
|
234
|
+
const absPath = path.isAbsolute(fpath) ? fpath : path.join(projectRoot, fpath);
|
|
272
235
|
if (fs.existsSync(absPath) && fs.statSync(absPath).isFile()) {
|
|
273
236
|
// FIX: Push individually instead of spread to avoid O(n²)
|
|
274
237
|
const fileFindings = scanFile(absPath, projectRoot);
|
|
@@ -278,7 +241,18 @@ function scanDirectory(projectRoot, targetFiles) {
|
|
|
278
241
|
return allFindings;
|
|
279
242
|
}
|
|
280
243
|
|
|
281
|
-
const files = walkDir(projectRoot, {
|
|
244
|
+
const files = walkDir(projectRoot, {
|
|
245
|
+
extensions: SCAN_EXTENSIONS,
|
|
246
|
+
skipDirs: new Set([
|
|
247
|
+
...DEFAULT_SKIP_DIRS,
|
|
248
|
+
'test',
|
|
249
|
+
'tests',
|
|
250
|
+
'__tests__',
|
|
251
|
+
'spec',
|
|
252
|
+
'specs',
|
|
253
|
+
'fixtures',
|
|
254
|
+
]),
|
|
255
|
+
});
|
|
282
256
|
|
|
283
257
|
for (const filepath of files) {
|
|
284
258
|
// FIX: Push individually instead of spread to avoid O(n²)
|
|
@@ -295,11 +269,8 @@ function scanDirectory(projectRoot, targetFiles) {
|
|
|
295
269
|
function printFindings(findings, minSeverity) {
|
|
296
270
|
const minRank = SEVERITY_RANK[minSeverity] ?? 3;
|
|
297
271
|
const filtered = findings
|
|
298
|
-
.filter(
|
|
299
|
-
.sort(
|
|
300
|
-
(a, b) =>
|
|
301
|
-
(SEVERITY_RANK[a.severity] ?? 3) - (SEVERITY_RANK[b.severity] ?? 3),
|
|
302
|
-
);
|
|
272
|
+
.filter(f => (SEVERITY_RANK[f.severity] ?? 3) <= minRank)
|
|
273
|
+
.sort((a, b) => (SEVERITY_RANK[a.severity] ?? 3) - (SEVERITY_RANK[b.severity] ?? 3));
|
|
303
274
|
|
|
304
275
|
if (filtered.length === 0) {
|
|
305
276
|
console.log(
|
|
@@ -308,13 +279,13 @@ function printFindings(findings, minSeverity) {
|
|
|
308
279
|
return 0;
|
|
309
280
|
}
|
|
310
281
|
|
|
311
|
-
let currentCategory =
|
|
282
|
+
let currentCategory = '';
|
|
312
283
|
for (const finding of filtered) {
|
|
313
284
|
if (finding.category !== currentCategory) {
|
|
314
285
|
currentCategory = finding.category;
|
|
315
286
|
console.log(`\n ${BOLD}${currentCategory}${RESET}`);
|
|
316
287
|
}
|
|
317
|
-
const color = SEVERITY_COLORS[finding.severity] ||
|
|
288
|
+
const color = SEVERITY_COLORS[finding.severity] || '';
|
|
318
289
|
console.log(
|
|
319
290
|
` ${color}[${finding.severity.toUpperCase()}]${RESET} ${finding.file}:${finding.line}`,
|
|
320
291
|
);
|
|
@@ -326,18 +297,18 @@ function printFindings(findings, minSeverity) {
|
|
|
326
297
|
}
|
|
327
298
|
|
|
328
299
|
function main() {
|
|
329
|
-
const args = { path: null, severity:
|
|
300
|
+
const args = { path: null, severity: 'low', files: null };
|
|
330
301
|
const raw = process.argv.slice(2);
|
|
331
302
|
|
|
332
303
|
for (let i = 0; i < raw.length; i++) {
|
|
333
|
-
if (raw[i] ===
|
|
304
|
+
if (raw[i] === '--severity' && raw[i + 1]) {
|
|
334
305
|
args.severity = raw[++i];
|
|
335
|
-
} else if (raw[i] ===
|
|
306
|
+
} else if (raw[i] === '--files') {
|
|
336
307
|
args.files = [];
|
|
337
|
-
while (i + 1 < raw.length && !raw[i + 1].startsWith(
|
|
308
|
+
while (i + 1 < raw.length && !raw[i + 1].startsWith('--')) {
|
|
338
309
|
args.files.push(raw[++i]);
|
|
339
310
|
}
|
|
340
|
-
} else if (!raw[i].startsWith(
|
|
311
|
+
} else if (!raw[i].startsWith('--') && !args.path) {
|
|
341
312
|
args.path = raw[i];
|
|
342
313
|
}
|
|
343
314
|
}
|
|
@@ -356,7 +327,7 @@ function main() {
|
|
|
356
327
|
}
|
|
357
328
|
|
|
358
329
|
console.log(
|
|
359
|
-
banner(
|
|
330
|
+
banner('security_scan.js', {
|
|
360
331
|
Project: projectRoot,
|
|
361
332
|
Severity: `${args.severity}+`,
|
|
362
333
|
}),
|
|
@@ -376,12 +347,12 @@ function main() {
|
|
|
376
347
|
bySeverity[f.severity] = (bySeverity[f.severity] || 0) + 1;
|
|
377
348
|
}
|
|
378
349
|
|
|
379
|
-
const uniqueFiles = new Set(findings.map(
|
|
350
|
+
const uniqueFiles = new Set(findings.map(f => f.file)).size;
|
|
380
351
|
|
|
381
|
-
for (const sev of [
|
|
352
|
+
for (const sev of ['critical', 'high', 'medium', 'low']) {
|
|
382
353
|
const c = bySeverity[sev] || 0;
|
|
383
354
|
if (c > 0) {
|
|
384
|
-
const color = SEVERITY_COLORS[sev] ||
|
|
355
|
+
const color = SEVERITY_COLORS[sev] || '';
|
|
385
356
|
console.log(` ${color}${sev.toUpperCase()}: ${c}${RESET}`);
|
|
386
357
|
}
|
|
387
358
|
}
|
|
@@ -13,31 +13,31 @@
|
|
|
13
13
|
* node .agent/scripts/session_manager.js export [--stdout]
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
'use strict';
|
|
17
17
|
|
|
18
|
-
const fs = require(
|
|
19
|
-
const path = require(
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
20
|
|
|
21
|
-
const STATE_FILE =
|
|
21
|
+
const STATE_FILE = '.agent_session.json';
|
|
22
22
|
|
|
23
|
-
const { GREEN, YELLOW, BLUE, CYAN, RED, BOLD, RESET } = require(
|
|
23
|
+
const { GREEN, YELLOW, BLUE, CYAN, RED, BOLD, RESET } = require('./_colors');
|
|
24
24
|
|
|
25
25
|
const VALID_COMMANDS = new Set([
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
'save',
|
|
27
|
+
'load',
|
|
28
|
+
'show',
|
|
29
|
+
'clear',
|
|
30
|
+
'status',
|
|
31
|
+
'tag',
|
|
32
|
+
'list',
|
|
33
|
+
'export',
|
|
34
34
|
]);
|
|
35
35
|
const LIST_PAGE_SIZE = 10;
|
|
36
36
|
|
|
37
37
|
function loadState() {
|
|
38
38
|
if (!fs.existsSync(STATE_FILE)) return {};
|
|
39
39
|
try {
|
|
40
|
-
const content = fs.readFileSync(STATE_FILE,
|
|
40
|
+
const content = fs.readFileSync(STATE_FILE, 'utf8');
|
|
41
41
|
return JSON.parse(content);
|
|
42
42
|
} catch {
|
|
43
43
|
return {};
|
|
@@ -45,7 +45,7 @@ function loadState() {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function saveState(state) {
|
|
48
|
-
fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2),
|
|
48
|
+
fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), 'utf8');
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
function cmdSave(note) {
|
|
@@ -73,7 +73,7 @@ function cmdLoad() {
|
|
|
73
73
|
console.log(`${YELLOW}No active session — use 'save' first.${RESET}`);
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
const tagsStr = (current.tags || []).join(
|
|
76
|
+
const tagsStr = (current.tags || []).join(', ') || 'none';
|
|
77
77
|
console.log(`${BOLD}Current session:${RESET}`);
|
|
78
78
|
console.log(` Session: #${current.session}`);
|
|
79
79
|
console.log(` Time: ${current.timestamp}`);
|
|
@@ -91,8 +91,8 @@ function cmdShow() {
|
|
|
91
91
|
console.log(`${BOLD}Session History (${history.length} total):${RESET}`);
|
|
92
92
|
const recent = history.slice(-10).reverse();
|
|
93
93
|
for (const entry of recent) {
|
|
94
|
-
const tagsStr = (entry.tags || []).join(
|
|
95
|
-
const tagsDisplay = tagsStr ? ` [${tagsStr}]` :
|
|
94
|
+
const tagsStr = (entry.tags || []).join(', ') || '';
|
|
95
|
+
const tagsDisplay = tagsStr ? ` [${tagsStr}]` : '';
|
|
96
96
|
console.log(
|
|
97
97
|
`\n ${BLUE}#${entry.session}${RESET} — ${entry.timestamp.slice(0, 16)}${tagsDisplay}`,
|
|
98
98
|
);
|
|
@@ -115,28 +115,22 @@ function cmdStatus() {
|
|
|
115
115
|
const current = state.current;
|
|
116
116
|
|
|
117
117
|
if (!history.length) {
|
|
118
|
-
console.log(
|
|
119
|
-
`${YELLOW}No session history — use 'save' to start tracking.${RESET}`,
|
|
120
|
-
);
|
|
118
|
+
console.log(`${YELLOW}No session history — use 'save' to start tracking.${RESET}`);
|
|
121
119
|
return;
|
|
122
120
|
}
|
|
123
121
|
|
|
124
122
|
const total = history.length;
|
|
125
123
|
const recent = history.slice(-3).reverse();
|
|
126
124
|
|
|
127
|
-
console.log(
|
|
128
|
-
`\n${BOLD}${CYAN}━━━ Session Status ━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`,
|
|
129
|
-
);
|
|
125
|
+
console.log(`\n${BOLD}${CYAN}━━━ Session Status ━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
|
|
130
126
|
console.log(` Total sessions: ${total}`);
|
|
131
127
|
if (current) {
|
|
132
|
-
console.log(
|
|
133
|
-
` Active: #${current.session} — ${current.note.slice(0, 60)}`,
|
|
134
|
-
);
|
|
128
|
+
console.log(` Active: #${current.session} — ${current.note.slice(0, 60)}`);
|
|
135
129
|
}
|
|
136
130
|
console.log(`\n${BOLD} Last 3 sessions:${RESET}`);
|
|
137
131
|
for (const entry of recent) {
|
|
138
|
-
const tagsStr = (entry.tags || []).join(
|
|
139
|
-
const tagsDisplay = tagsStr ? ` [${tagsStr}]` :
|
|
132
|
+
const tagsStr = (entry.tags || []).join(', ') || '';
|
|
133
|
+
const tagsDisplay = tagsStr ? ` [${tagsStr}]` : '';
|
|
140
134
|
const ts = entry.timestamp.slice(0, 16);
|
|
141
135
|
console.log(` ${BLUE}#${entry.session}${RESET} ${ts}${tagsDisplay}`);
|
|
142
136
|
console.log(` ${entry.note.slice(0, 70)}`);
|
|
@@ -154,16 +148,12 @@ function cmdTag(label) {
|
|
|
154
148
|
const state = loadState();
|
|
155
149
|
const current = state.current;
|
|
156
150
|
if (!current) {
|
|
157
|
-
console.log(
|
|
158
|
-
`${YELLOW}No active session — use 'save' first before tagging.${RESET}`,
|
|
159
|
-
);
|
|
151
|
+
console.log(`${YELLOW}No active session — use 'save' first before tagging.${RESET}`);
|
|
160
152
|
process.exit(1);
|
|
161
153
|
}
|
|
162
154
|
if (!current.tags) current.tags = [];
|
|
163
155
|
if (current.tags.includes(label)) {
|
|
164
|
-
console.log(
|
|
165
|
-
`${YELLOW}Tag '${label}' already exists on session #${current.session}.${RESET}`,
|
|
166
|
-
);
|
|
156
|
+
console.log(`${YELLOW}Tag '${label}' already exists on session #${current.session}.${RESET}`);
|
|
167
157
|
return;
|
|
168
158
|
}
|
|
169
159
|
|
|
@@ -183,9 +173,7 @@ function cmdTag(label) {
|
|
|
183
173
|
}
|
|
184
174
|
|
|
185
175
|
saveState(state);
|
|
186
|
-
console.log(
|
|
187
|
-
`${GREEN}✅ Tagged session #${current.session} with '${label}'.${RESET}`,
|
|
188
|
-
);
|
|
176
|
+
console.log(`${GREEN}✅ Tagged session #${current.session} with '${label}'.${RESET}`);
|
|
189
177
|
}
|
|
190
178
|
|
|
191
179
|
function cmdList(showAll) {
|
|
@@ -205,12 +193,10 @@ function cmdList(showAll) {
|
|
|
205
193
|
);
|
|
206
194
|
|
|
207
195
|
for (const entry of recent) {
|
|
208
|
-
const tagsStr = (entry.tags || []).join(
|
|
209
|
-
const tagsDisplay = tagsStr ? ` [${YELLOW}${tagsStr}${RESET}]` :
|
|
196
|
+
const tagsStr = (entry.tags || []).join(', ');
|
|
197
|
+
const tagsDisplay = tagsStr ? ` [${YELLOW}${tagsStr}${RESET}]` : '';
|
|
210
198
|
const ts = entry.timestamp.slice(0, 16);
|
|
211
|
-
console.log(
|
|
212
|
-
`\n ${BOLD}${BLUE}#${entry.session}${RESET} — ${ts}${tagsDisplay}`,
|
|
213
|
-
);
|
|
199
|
+
console.log(`\n ${BOLD}${BLUE}#${entry.session}${RESET} — ${ts}${tagsDisplay}`);
|
|
214
200
|
console.log(` ${entry.note}`);
|
|
215
201
|
}
|
|
216
202
|
|
|
@@ -231,31 +217,29 @@ function cmdExport(toStdout) {
|
|
|
231
217
|
return;
|
|
232
218
|
}
|
|
233
219
|
|
|
234
|
-
const lines = [
|
|
220
|
+
const lines = ['# Session Export\n'];
|
|
235
221
|
lines.push(`Generated: ${new Date().toISOString().slice(0, 16)}\n`);
|
|
236
222
|
lines.push(`Total sessions: ${history.length}\n\n---\n`);
|
|
237
223
|
|
|
238
224
|
const reversed = history.slice().reverse();
|
|
239
225
|
for (const entry of reversed) {
|
|
240
|
-
const sessionNum = entry.session ||
|
|
241
|
-
const ts = (entry.timestamp ||
|
|
242
|
-
const note = entry.note ||
|
|
226
|
+
const sessionNum = entry.session || '?';
|
|
227
|
+
const ts = (entry.timestamp || '').slice(0, 16);
|
|
228
|
+
const note = entry.note || '';
|
|
243
229
|
const tags = entry.tags || [];
|
|
244
|
-
const tagsStr = tags.length ? `\n**Tags:** ${tags.join(
|
|
230
|
+
const tagsStr = tags.length ? `\n**Tags:** ${tags.join(', ')}` : '';
|
|
245
231
|
|
|
246
232
|
lines.push(`## Session #${sessionNum} — ${ts}\n`);
|
|
247
233
|
lines.push(`${note}${tagsStr}\n\n---\n`);
|
|
248
234
|
}
|
|
249
235
|
|
|
250
|
-
const content = lines.join(
|
|
236
|
+
const content = lines.join('\n');
|
|
251
237
|
if (toStdout) {
|
|
252
238
|
console.log(content);
|
|
253
239
|
} else {
|
|
254
|
-
const exportPath = path.resolve(
|
|
255
|
-
fs.writeFileSync(exportPath, content,
|
|
256
|
-
console.log(
|
|
257
|
-
`${GREEN}✅ Exported ${history.length} sessions to${RESET} ${exportPath}`,
|
|
258
|
-
);
|
|
240
|
+
const exportPath = path.resolve('session_export.md');
|
|
241
|
+
fs.writeFileSync(exportPath, content, 'utf8');
|
|
242
|
+
console.log(`${GREEN}✅ Exported ${history.length} sessions to${RESET} ${exportPath}`);
|
|
259
243
|
}
|
|
260
244
|
}
|
|
261
245
|
|
|
@@ -272,31 +256,30 @@ function main() {
|
|
|
272
256
|
|
|
273
257
|
if (!VALID_COMMANDS.has(cmd)) {
|
|
274
258
|
console.log(`${RED}Unknown command: '${cmd}'${RESET}`);
|
|
275
|
-
console.log(`Valid commands: ${[...VALID_COMMANDS].sort().join(
|
|
259
|
+
console.log(`Valid commands: ${[...VALID_COMMANDS].sort().join(', ')}`);
|
|
276
260
|
process.exit(1);
|
|
277
261
|
}
|
|
278
262
|
|
|
279
|
-
if (cmd ===
|
|
280
|
-
let note = args.slice(1).join(
|
|
281
|
-
if (!note)
|
|
282
|
-
note = `session ${new Date().toISOString().slice(0, 16).replace("T", " ")}`;
|
|
263
|
+
if (cmd === 'save') {
|
|
264
|
+
let note = args.slice(1).join(' ').trim();
|
|
265
|
+
if (!note) note = `session ${new Date().toISOString().slice(0, 16).replace('T', ' ')}`;
|
|
283
266
|
cmdSave(note);
|
|
284
|
-
} else if (cmd ===
|
|
267
|
+
} else if (cmd === 'load') {
|
|
285
268
|
cmdLoad();
|
|
286
|
-
} else if (cmd ===
|
|
269
|
+
} else if (cmd === 'show') {
|
|
287
270
|
cmdShow();
|
|
288
|
-
} else if (cmd ===
|
|
271
|
+
} else if (cmd === 'clear') {
|
|
289
272
|
cmdClear();
|
|
290
|
-
} else if (cmd ===
|
|
273
|
+
} else if (cmd === 'status') {
|
|
291
274
|
cmdStatus();
|
|
292
|
-
} else if (cmd ===
|
|
293
|
-
const label = args.slice(1).join(
|
|
275
|
+
} else if (cmd === 'tag') {
|
|
276
|
+
const label = args.slice(1).join(' ').trim();
|
|
294
277
|
cmdTag(label);
|
|
295
|
-
} else if (cmd ===
|
|
296
|
-
const showAll = args.includes(
|
|
278
|
+
} else if (cmd === 'list') {
|
|
279
|
+
const showAll = args.includes('--all');
|
|
297
280
|
cmdList(showAll);
|
|
298
|
-
} else if (cmd ===
|
|
299
|
-
const toStdout = args.includes(
|
|
281
|
+
} else if (cmd === 'export') {
|
|
282
|
+
const toStdout = args.includes('--stdout');
|
|
300
283
|
cmdExport(toStdout);
|
|
301
284
|
}
|
|
302
285
|
}
|