oh-my-claudecode 0.2.4 → 0.2.7

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.
Files changed (89) hide show
  1. package/README.md +103 -4
  2. package/commands/necronomicon-bind.md +45 -82
  3. package/dist/agents/builtin-agents.d.ts.map +1 -1
  4. package/dist/agents/builtin-agents.js +8 -0
  5. package/dist/agents/builtin-agents.js.map +1 -1
  6. package/dist/agents/cthulhu.d.ts.map +1 -1
  7. package/dist/agents/cthulhu.js +11 -0
  8. package/dist/agents/cthulhu.js.map +1 -1
  9. package/dist/agents/dagon.d.ts.map +1 -1
  10. package/dist/agents/dagon.js +13 -0
  11. package/dist/agents/dagon.js.map +1 -1
  12. package/dist/agents/nodens-advanced.d.ts +182 -0
  13. package/dist/agents/nodens-advanced.d.ts.map +1 -0
  14. package/dist/agents/nodens-advanced.js +297 -0
  15. package/dist/agents/nodens-advanced.js.map +1 -0
  16. package/dist/agents/nodens.d.ts +42 -0
  17. package/dist/agents/nodens.d.ts.map +1 -0
  18. package/dist/agents/nodens.js +147 -0
  19. package/dist/agents/nodens.js.map +1 -0
  20. package/dist/agents/shoggoth.d.ts.map +1 -1
  21. package/dist/agents/shoggoth.js +11 -1
  22. package/dist/agents/shoggoth.js.map +1 -1
  23. package/dist/cli/bind.d.ts +24 -0
  24. package/dist/cli/bind.d.ts.map +1 -1
  25. package/dist/cli/bind.js +92 -25
  26. package/dist/cli/bind.js.map +1 -1
  27. package/dist/cli/doctor.d.ts.map +1 -1
  28. package/dist/cli/doctor.js +7 -5
  29. package/dist/cli/doctor.js.map +1 -1
  30. package/dist/cli/index.js +54 -4
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/cli/version.d.ts +2 -0
  33. package/dist/cli/version.d.ts.map +1 -0
  34. package/dist/cli/version.js +28 -0
  35. package/dist/cli/version.js.map +1 -0
  36. package/dist/config/schema.d.ts +648 -17
  37. package/dist/config/schema.d.ts.map +1 -1
  38. package/dist/config/schema.js +21 -2
  39. package/dist/config/schema.js.map +1 -1
  40. package/dist/features/web-research-background/advanced-patterns.d.ts +44 -0
  41. package/dist/features/web-research-background/advanced-patterns.d.ts.map +1 -0
  42. package/dist/features/web-research-background/advanced-patterns.js +139 -0
  43. package/dist/features/web-research-background/advanced-patterns.js.map +1 -0
  44. package/dist/features/web-research-background/index.d.ts +73 -0
  45. package/dist/features/web-research-background/index.d.ts.map +1 -0
  46. package/dist/features/web-research-background/index.js +131 -0
  47. package/dist/features/web-research-background/index.js.map +1 -0
  48. package/dist/features/yith-archive/functions/opencode-import.d.ts.map +1 -1
  49. package/dist/features/yith-archive/functions/opencode-import.js +129 -90
  50. package/dist/features/yith-archive/functions/opencode-import.js.map +1 -1
  51. package/dist/features/yith-archive/index.d.ts +8 -0
  52. package/dist/features/yith-archive/index.d.ts.map +1 -1
  53. package/dist/features/yith-archive/index.js +1 -0
  54. package/dist/features/yith-archive/index.js.map +1 -1
  55. package/dist/features/yith-archive/types.d.ts +15 -0
  56. package/dist/features/yith-archive/types.d.ts.map +1 -1
  57. package/dist/hooks/design-detector-hook.d.ts +12 -0
  58. package/dist/hooks/design-detector-hook.d.ts.map +1 -0
  59. package/dist/hooks/design-detector-hook.js +42 -0
  60. package/dist/hooks/design-detector-hook.js.map +1 -0
  61. package/dist/hooks/design-detector.d.ts +47 -0
  62. package/dist/hooks/design-detector.d.ts.map +1 -0
  63. package/dist/hooks/design-detector.js +251 -0
  64. package/dist/hooks/design-detector.js.map +1 -0
  65. package/dist/hooks/index.d.ts +3 -0
  66. package/dist/hooks/index.d.ts.map +1 -1
  67. package/dist/hooks/index.js +27 -0
  68. package/dist/hooks/index.js.map +1 -1
  69. package/dist/hooks/web-research-detector.d.ts +58 -0
  70. package/dist/hooks/web-research-detector.d.ts.map +1 -0
  71. package/dist/hooks/web-research-detector.js +205 -0
  72. package/dist/hooks/web-research-detector.js.map +1 -0
  73. package/dist/hooks/web-research-hook.d.ts +12 -0
  74. package/dist/hooks/web-research-hook.d.ts.map +1 -0
  75. package/dist/hooks/web-research-hook.js +43 -0
  76. package/dist/hooks/web-research-hook.js.map +1 -0
  77. package/dist/hooks/yith-capture.d.ts +35 -0
  78. package/dist/hooks/yith-capture.d.ts.map +1 -0
  79. package/dist/hooks/yith-capture.js +113 -0
  80. package/dist/hooks/yith-capture.js.map +1 -0
  81. package/dist/linters/type-safety-ast.d.ts +108 -0
  82. package/dist/linters/type-safety-ast.d.ts.map +1 -0
  83. package/dist/linters/type-safety-ast.js +293 -0
  84. package/dist/linters/type-safety-ast.js.map +1 -0
  85. package/dist/linters/type-safety-linter.d.ts +66 -0
  86. package/dist/linters/type-safety-linter.d.ts.map +1 -0
  87. package/dist/linters/type-safety-linter.js +317 -0
  88. package/dist/linters/type-safety-linter.js.map +1 -0
  89. package/package.json +1 -1
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Web Research Detector Hook
3
+ *
4
+ * PreToolUse hook that detects when user messages indicate a need for web research.
5
+ * Injects system context reminding agents about enforcing current knowledge.
6
+ *
7
+ * When triggered, it warns the agent that web research may be needed and suggests
8
+ * searching for current information before providing answers.
9
+ */
10
+ export const WEB_RESEARCH_DETECTOR_HOOK_SCRIPT = `#!/usr/bin/env bash
11
+ # oh-my-claudecode: Web Research Detector PreToolUse Hook
12
+ # Fires on tool use to detect web research needs and inject enforcement context.
13
+
14
+ set -euo pipefail
15
+
16
+ CLAUDE_API_PROMPT="\${CLAUDE_API_PROMPT:-}"
17
+
18
+ # Extract a simple heuristic from the prompt: look for version patterns or date-sensitive keywords
19
+ # This is a bash-level heuristic that doesn't need the full TypeScript detector
20
+
21
+ # Check for version patterns: v1.0, 2024, latest, etc.
22
+ if echo "$CLAUDE_API_PROMPT" | grep -qiE '\\b(v[0-9]+\\.[0-9]+|20[0-9]{2}|latest\\s+(version|release|update)|breaking\\s+changes|what.?s\\s+new)\\b'; then
23
+ echo "[WEB RESEARCH ENFORCEMENT]"
24
+ echo "Detected request that may require current knowledge (version check, date-sensitive info)."
25
+ echo "If you don't have current information available, consider:"
26
+ echo " 1. Using WebSearch to find the latest information"
27
+ echo " 2. Checking official documentation for the most recent updates"
28
+ echo " 3. Being explicit about knowledge cutoff limitations"
29
+ echo ""
30
+ fi
31
+ `;
32
+ export function getWebResearchDetectorHookConfig() {
33
+ return {
34
+ matcher: "",
35
+ hooks: [
36
+ {
37
+ type: "command",
38
+ command: "~/.claude/hooks/web-research-detector.sh",
39
+ },
40
+ ],
41
+ };
42
+ }
43
+ //# sourceMappingURL=web-research-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-research-hook.js","sourceRoot":"","sources":["../../src/hooks/web-research-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,iCAAiC,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBhD,CAAA;AAED,MAAM,UAAU,gCAAgC;IAC9C,OAAO;QACL,OAAO,EAAE,EAAE;QACX,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,0CAA0C;aACpD;SACF;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * yith-capture Stop hook — the continuous-ingestion layer for Yith
3
+ * Archive. Fires after every assistant turn (Claude Code's `Stop`
4
+ * event), spawns a fast `oh-my-claudecode bind --resume --claude-only`
5
+ * in the background, and — when the pending-compression queue is big
6
+ * enough — spawns a `claude -p` compression tick too. All spawns are
7
+ * detached so the assistant response never waits on them.
8
+ *
9
+ * Architecture notes:
10
+ *
11
+ * - Capture debounce (`.last-captured`, 5 seconds): the Stop event
12
+ * can fire many times in quick succession (one per assistant
13
+ * response in a long flow), and each bind tick does disk I/O +
14
+ * a fresh node start. 5 seconds is short enough to feel "live"
15
+ * and long enough to keep CPU usage bounded.
16
+ *
17
+ * - Compression debounce (`.last-compressed`, 5 minutes): running
18
+ * `claude -p` with a compression-batch prompt takes ~30 seconds
19
+ * of background work and uses the user's subscription. Firing it
20
+ * every 5 seconds would burn credits; firing it every 5 minutes
21
+ * catches the queue opportunistically without being invasive.
22
+ *
23
+ * - Compression threshold (50 pending observations): below this, we
24
+ * let the user's manual `/necronomicon-bind` ritual handle
25
+ * compression. Above it, we assume the queue is growing faster
26
+ * than the user is running the ritual and nudge the cron-style
27
+ * spawn path into action automatically.
28
+ *
29
+ * - Fail-safe: the hook exits 0 on every branch. A broken Yith
30
+ * install can never block the user's Claude Code session — the
31
+ * hook is purely additive.
32
+ */
33
+ export declare const YITH_CAPTURE_HOOK_SCRIPT = "#!/usr/bin/env bash\n# oh-my-claudecode: Yith continuous-ingestion Stop hook\n# Runs after every assistant turn. Spawns background bind ticks to\n# keep raw observations flowing and (occasionally) to drain pending\n# compression via \\`claude -p\\`. Never blocks the session.\n\nset -euo pipefail\n\nYITH_DIR=\"${HOME}/.oh-my-claudecode/yith\"\nCAPTURE_SENTINEL=\"${YITH_DIR}/.last-captured\"\nCOMPRESS_SENTINEL=\"${YITH_DIR}/.last-compressed\"\nDEBOUNCE_CAPTURE_SEC=5\nDEBOUNCE_COMPRESS_SEC=300\nCOMPRESS_THRESHOLD=50\n\n# Bail early if Yith isn't installed yet (fresh machine, user hasn't\n# run \\`oh-my-claudecode bind\\` yet). The hook is strictly additive;\n# missing prerequisites are a silent no-op, not an error.\nif [ ! -d \"$YITH_DIR\" ]; then\n exit 0\nfi\n\n# Need the CLI on PATH to do anything useful.\nif ! command -v oh-my-claudecode >/dev/null 2>&1; then\n exit 0\nfi\n\nnow=$(date +%s)\n\n# \u2500\u2500 Capture tick (always tries to run) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nlast_capture=0\nif [ -f \"$CAPTURE_SENTINEL\" ]; then\n last_capture=$(cat \"$CAPTURE_SENTINEL\" 2>/dev/null || echo 0)\nfi\n\nif [ $((now - last_capture)) -ge $DEBOUNCE_CAPTURE_SEC ]; then\n echo \"$now\" > \"$CAPTURE_SENTINEL\"\n # Scope the scan to the current project when CLAUDE_PROJECT_DIR is\n # set by Claude Code \u2014 otherwise let bind scan everything.\n PROJECT_FLAG=\"\"\n if [ -n \"${CLAUDE_PROJECT_DIR:-}\" ]; then\n PROJECT_FLAG=\"--project ${CLAUDE_PROJECT_DIR}\"\n fi\n # Fork-detach: the CLI's \\`--background\\` flag spawns a grandchild\n # with detached stdio and exits the parent immediately, so the Stop\n # hook returns in ~10 ms regardless of how long the backfill takes.\n oh-my-claudecode bind --resume --claude-only --background $PROJECT_FLAG \\\n >/dev/null 2>&1 || true\nfi\n\n# \u2500\u2500 Compression tick (threshold-gated, less frequent) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nNECRONOMICON=\"${YITH_DIR}/necronomicon.json\"\nif [ -f \"$NECRONOMICON\" ] && command -v jq >/dev/null 2>&1; then\n PENDING=$(jq -r '.\"mem:pending-compression\".state.count // 0' \"$NECRONOMICON\" 2>/dev/null || echo 0)\n if [ \"$PENDING\" -ge \"$COMPRESS_THRESHOLD\" ]; then\n last_compress=0\n if [ -f \"$COMPRESS_SENTINEL\" ]; then\n last_compress=$(cat \"$COMPRESS_SENTINEL\" 2>/dev/null || echo 0)\n fi\n if [ $((now - last_compress)) -ge $DEBOUNCE_COMPRESS_SEC ]; then\n echo \"$now\" > \"$COMPRESS_SENTINEL\"\n oh-my-claudecode bind --resume --compress-only --background \\\n >/dev/null 2>&1 || true\n fi\n fi\nfi\n\nexit 0\n";
34
+ export declare function getYithCaptureHookConfig(): object;
35
+ //# sourceMappingURL=yith-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yith-capture.d.ts","sourceRoot":"","sources":["../../src/hooks/yith-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,eAAO,MAAM,wBAAwB,2wFAoEpC,CAAA;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAUjD"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * yith-capture Stop hook — the continuous-ingestion layer for Yith
3
+ * Archive. Fires after every assistant turn (Claude Code's `Stop`
4
+ * event), spawns a fast `oh-my-claudecode bind --resume --claude-only`
5
+ * in the background, and — when the pending-compression queue is big
6
+ * enough — spawns a `claude -p` compression tick too. All spawns are
7
+ * detached so the assistant response never waits on them.
8
+ *
9
+ * Architecture notes:
10
+ *
11
+ * - Capture debounce (`.last-captured`, 5 seconds): the Stop event
12
+ * can fire many times in quick succession (one per assistant
13
+ * response in a long flow), and each bind tick does disk I/O +
14
+ * a fresh node start. 5 seconds is short enough to feel "live"
15
+ * and long enough to keep CPU usage bounded.
16
+ *
17
+ * - Compression debounce (`.last-compressed`, 5 minutes): running
18
+ * `claude -p` with a compression-batch prompt takes ~30 seconds
19
+ * of background work and uses the user's subscription. Firing it
20
+ * every 5 seconds would burn credits; firing it every 5 minutes
21
+ * catches the queue opportunistically without being invasive.
22
+ *
23
+ * - Compression threshold (50 pending observations): below this, we
24
+ * let the user's manual `/necronomicon-bind` ritual handle
25
+ * compression. Above it, we assume the queue is growing faster
26
+ * than the user is running the ritual and nudge the cron-style
27
+ * spawn path into action automatically.
28
+ *
29
+ * - Fail-safe: the hook exits 0 on every branch. A broken Yith
30
+ * install can never block the user's Claude Code session — the
31
+ * hook is purely additive.
32
+ */
33
+ export const YITH_CAPTURE_HOOK_SCRIPT = `#!/usr/bin/env bash
34
+ # oh-my-claudecode: Yith continuous-ingestion Stop hook
35
+ # Runs after every assistant turn. Spawns background bind ticks to
36
+ # keep raw observations flowing and (occasionally) to drain pending
37
+ # compression via \\\`claude -p\\\`. Never blocks the session.
38
+
39
+ set -euo pipefail
40
+
41
+ YITH_DIR="\${HOME}/.oh-my-claudecode/yith"
42
+ CAPTURE_SENTINEL="\${YITH_DIR}/.last-captured"
43
+ COMPRESS_SENTINEL="\${YITH_DIR}/.last-compressed"
44
+ DEBOUNCE_CAPTURE_SEC=5
45
+ DEBOUNCE_COMPRESS_SEC=300
46
+ COMPRESS_THRESHOLD=50
47
+
48
+ # Bail early if Yith isn't installed yet (fresh machine, user hasn't
49
+ # run \\\`oh-my-claudecode bind\\\` yet). The hook is strictly additive;
50
+ # missing prerequisites are a silent no-op, not an error.
51
+ if [ ! -d "\$YITH_DIR" ]; then
52
+ exit 0
53
+ fi
54
+
55
+ # Need the CLI on PATH to do anything useful.
56
+ if ! command -v oh-my-claudecode >/dev/null 2>&1; then
57
+ exit 0
58
+ fi
59
+
60
+ now=\$(date +%s)
61
+
62
+ # ── Capture tick (always tries to run) ────────────────────────────────
63
+ last_capture=0
64
+ if [ -f "\$CAPTURE_SENTINEL" ]; then
65
+ last_capture=\$(cat "\$CAPTURE_SENTINEL" 2>/dev/null || echo 0)
66
+ fi
67
+
68
+ if [ \$((now - last_capture)) -ge \$DEBOUNCE_CAPTURE_SEC ]; then
69
+ echo "\$now" > "\$CAPTURE_SENTINEL"
70
+ # Scope the scan to the current project when CLAUDE_PROJECT_DIR is
71
+ # set by Claude Code — otherwise let bind scan everything.
72
+ PROJECT_FLAG=""
73
+ if [ -n "\${CLAUDE_PROJECT_DIR:-}" ]; then
74
+ PROJECT_FLAG="--project \${CLAUDE_PROJECT_DIR}"
75
+ fi
76
+ # Fork-detach: the CLI's \\\`--background\\\` flag spawns a grandchild
77
+ # with detached stdio and exits the parent immediately, so the Stop
78
+ # hook returns in ~10 ms regardless of how long the backfill takes.
79
+ oh-my-claudecode bind --resume --claude-only --background \$PROJECT_FLAG \\
80
+ >/dev/null 2>&1 || true
81
+ fi
82
+
83
+ # ── Compression tick (threshold-gated, less frequent) ─────────────────
84
+ NECRONOMICON="\${YITH_DIR}/necronomicon.json"
85
+ if [ -f "\$NECRONOMICON" ] && command -v jq >/dev/null 2>&1; then
86
+ PENDING=\$(jq -r '."mem:pending-compression".state.count // 0' "\$NECRONOMICON" 2>/dev/null || echo 0)
87
+ if [ "\$PENDING" -ge "\$COMPRESS_THRESHOLD" ]; then
88
+ last_compress=0
89
+ if [ -f "\$COMPRESS_SENTINEL" ]; then
90
+ last_compress=\$(cat "\$COMPRESS_SENTINEL" 2>/dev/null || echo 0)
91
+ fi
92
+ if [ \$((now - last_compress)) -ge \$DEBOUNCE_COMPRESS_SEC ]; then
93
+ echo "\$now" > "\$COMPRESS_SENTINEL"
94
+ oh-my-claudecode bind --resume --compress-only --background \\
95
+ >/dev/null 2>&1 || true
96
+ fi
97
+ fi
98
+ fi
99
+
100
+ exit 0
101
+ `;
102
+ export function getYithCaptureHookConfig() {
103
+ return {
104
+ matcher: "",
105
+ hooks: [
106
+ {
107
+ type: "command",
108
+ command: "~/.claude/hooks/yith-capture.sh",
109
+ },
110
+ ],
111
+ };
112
+ }
113
+ //# sourceMappingURL=yith-capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yith-capture.js","sourceRoot":"","sources":["../../src/hooks/yith-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoEvC,CAAA;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO;QACL,OAAO,EAAE,EAAE;QACX,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,iCAAiC;aAC3C;SACF;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * AST-Based TypeScript Type Safety Linter
3
+ *
4
+ * Uses TypeScript compiler API to perform accurate type safety analysis:
5
+ * - Detects 'any' types in all contexts with zero false positives
6
+ * - Identifies missing return type annotations
7
+ * - Finds unsafe casts with context awareness
8
+ * - Validates Promise type parameters
9
+ * - Provides auto-fix capabilities for common issues
10
+ * - Tracks type safety metrics over time
11
+ */
12
+ /**
13
+ * AST-based type safety issue
14
+ */
15
+ export interface ASTTypeSafetyIssue {
16
+ ruleId: string;
17
+ message: string;
18
+ line: number;
19
+ column: number;
20
+ severity: "error" | "warn" | "info";
21
+ fix?: string;
22
+ fixable?: boolean;
23
+ }
24
+ /**
25
+ * Auto-fix result
26
+ */
27
+ export interface AutoFixResult {
28
+ success: boolean;
29
+ message?: string;
30
+ originalCode?: string;
31
+ fixedCode?: string;
32
+ issuesFixed: number;
33
+ }
34
+ /**
35
+ * Type safety metrics
36
+ */
37
+ export interface TypeSafetyMetrics {
38
+ totalFiles: number;
39
+ filesWithIssues: number;
40
+ totalIssues: number;
41
+ issuesByRule: Record<string, number>;
42
+ errorCount: number;
43
+ warningCount: number;
44
+ scorePercentage: number;
45
+ timestamp: number;
46
+ }
47
+ /**
48
+ * Linter configuration for AST mode
49
+ */
50
+ export interface ASTLinterConfig {
51
+ enabled: boolean;
52
+ auto_fix?: boolean;
53
+ auto_fix_rules?: string[];
54
+ track_metrics?: boolean;
55
+ metrics_dir?: string;
56
+ }
57
+ /**
58
+ * Lint TypeScript file using AST analysis
59
+ *
60
+ * @param filePath - Path to the TypeScript file
61
+ * @param config - Linter configuration
62
+ * @returns Array of type safety issues found
63
+ */
64
+ export declare function lintFileAST(filePath: string, config?: ASTLinterConfig): ASTTypeSafetyIssue[];
65
+ /**
66
+ * Apply auto-fixes to a file
67
+ *
68
+ * @param filePath - Path to the TypeScript file
69
+ * @param issues - Issues to fix
70
+ * @param config - Configuration
71
+ * @returns Auto-fix result
72
+ */
73
+ export declare function fixIssuesInFile(filePath: string, issues: ASTTypeSafetyIssue[], config?: ASTLinterConfig): AutoFixResult;
74
+ /**
75
+ * Generate type safety metrics for files
76
+ *
77
+ * @param filePaths - Array of file paths to analyze
78
+ * @param config - Configuration
79
+ * @returns Type safety metrics
80
+ */
81
+ export declare function generateTypeMetrics(filePaths: string[], config?: ASTLinterConfig): TypeSafetyMetrics;
82
+ /**
83
+ * Export metrics to JSON file
84
+ *
85
+ * @param metrics - Metrics to export
86
+ * @param outputPath - Output file path
87
+ * @returns Success status
88
+ */
89
+ export declare function exportMetrics(metrics: TypeSafetyMetrics, outputPath: string): boolean;
90
+ /**
91
+ * Load historical metrics
92
+ *
93
+ * @param metricsDir - Directory containing metrics files
94
+ * @returns Array of metrics in chronological order
95
+ */
96
+ export declare function loadHistoricalMetrics(metricsDir: string): TypeSafetyMetrics[];
97
+ /**
98
+ * Calculate metrics trend
99
+ *
100
+ * @param metrics - Array of metrics in chronological order
101
+ * @returns Trend information
102
+ */
103
+ export declare function calculateMetricsTrend(metrics: TypeSafetyMetrics[]): {
104
+ improvement: boolean;
105
+ percentChange: number;
106
+ description: string;
107
+ };
108
+ //# sourceMappingURL=type-safety-ast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-safety-ast.d.ts","sourceRoot":"","sources":["../../src/linters/type-safety-ast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;IACnC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,kBAAkB,EAAE,CA+H5F;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,EAAE,EAC5B,MAAM,CAAC,EAAE,eAAe,GACvB,aAAa,CA6Df;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,CAAC,EAAE,eAAe,GACvB,iBAAiB,CAkCnB;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAYrF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAoB7E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG;IACnE,WAAW,EAAE,OAAO,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;CACpB,CAkBA"}
@@ -0,0 +1,293 @@
1
+ /**
2
+ * AST-Based TypeScript Type Safety Linter
3
+ *
4
+ * Uses TypeScript compiler API to perform accurate type safety analysis:
5
+ * - Detects 'any' types in all contexts with zero false positives
6
+ * - Identifies missing return type annotations
7
+ * - Finds unsafe casts with context awareness
8
+ * - Validates Promise type parameters
9
+ * - Provides auto-fix capabilities for common issues
10
+ * - Tracks type safety metrics over time
11
+ */
12
+ import * as fs from "fs";
13
+ import * as path from "path";
14
+ import * as ts from "typescript";
15
+ /**
16
+ * Lint TypeScript file using AST analysis
17
+ *
18
+ * @param filePath - Path to the TypeScript file
19
+ * @param config - Linter configuration
20
+ * @returns Array of type safety issues found
21
+ */
22
+ export function lintFileAST(filePath, config) {
23
+ if (!fs.existsSync(filePath)) {
24
+ return [];
25
+ }
26
+ const sourceCode = fs.readFileSync(filePath, "utf-8");
27
+ const sourceFile = ts.createSourceFile(filePath, sourceCode, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
28
+ const issues = [];
29
+ const lines = sourceCode.split("\n");
30
+ // Walk the AST and collect issues
31
+ const visit = (node) => {
32
+ // Check for 'any' type usage
33
+ if (ts.isTypeNode(node) && node.kind === ts.SyntaxKind.AnyKeyword) {
34
+ const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
35
+ issues.push({
36
+ ruleId: "TS_ANY_TYPE",
37
+ message: "Use of 'any' type is not allowed",
38
+ line: pos.line + 1,
39
+ column: pos.character + 1,
40
+ severity: "error",
41
+ fix: "Replace 'any' with specific type",
42
+ fixable: true,
43
+ });
44
+ }
45
+ // Check for unsafe type assertions
46
+ if (ts.isAsExpression(node)) {
47
+ const typeNode = node.type;
48
+ const typeText = typeNode.getText(sourceFile);
49
+ if (typeText === "any" ||
50
+ typeText === "unknown" ||
51
+ typeText.startsWith("Record<") ||
52
+ typeText === "{}") {
53
+ const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
54
+ issues.push({
55
+ ruleId: "TS_UNSAFE_CAST",
56
+ message: `Unsafe cast to '${typeText}'`,
57
+ line: pos.line + 1,
58
+ column: pos.character + 1,
59
+ severity: "error",
60
+ fix: `Use type guard or specific type instead of '${typeText}'`,
61
+ fixable: true,
62
+ });
63
+ }
64
+ }
65
+ // Check for missing return type annotations on functions
66
+ if ((ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) &&
67
+ !node.type &&
68
+ node.body) {
69
+ // Skip constructors and getters/setters
70
+ const isConstructor = ts.isFunctionDeclaration(node) && node.name?.text === "constructor";
71
+ const isGetterSetter = ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node);
72
+ if (!isConstructor && !isGetterSetter) {
73
+ const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
74
+ issues.push({
75
+ ruleId: "MISSING_RETURN_TYPE",
76
+ message: "Function missing explicit return type annotation",
77
+ line: pos.line + 1,
78
+ column: pos.character + 1,
79
+ severity: "warn",
80
+ fix: "Add return type annotation to function",
81
+ fixable: false, // Would require inference
82
+ });
83
+ }
84
+ }
85
+ // Check for Promise without type parameter
86
+ if (ts.isTypeReferenceNode(node)) {
87
+ const typeName = node.typeName;
88
+ if (ts.isIdentifier(typeName) && typeName.text === "Promise") {
89
+ if (!node.typeArguments || node.typeArguments.length === 0) {
90
+ const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
91
+ issues.push({
92
+ ruleId: "MISSING_PROMISE_TYPE",
93
+ message: "Promise must have type parameter",
94
+ line: pos.line + 1,
95
+ column: pos.character + 1,
96
+ severity: "warn",
97
+ fix: "Add type parameter: Promise<T>",
98
+ fixable: false,
99
+ });
100
+ }
101
+ }
102
+ }
103
+ // Check for @ts-ignore without reason
104
+ const precedingComments = ts.getLeadingCommentRanges(sourceCode, node.getFullStart());
105
+ if (precedingComments) {
106
+ for (const range of precedingComments) {
107
+ const comment = sourceCode.substring(range.pos, range.end);
108
+ if (comment.includes("@ts-ignore") && !comment.includes("@ts-ignore -")) {
109
+ const pos = sourceFile.getLineAndCharacterOfPosition(range.pos);
110
+ issues.push({
111
+ ruleId: "TS_IGNORE_WITHOUT_REASON",
112
+ message: "@ts-ignore must have a reason comment",
113
+ line: pos.line + 1,
114
+ column: pos.character + 1,
115
+ severity: "warn",
116
+ fix: "Add reason: @ts-ignore - <reason>",
117
+ fixable: true,
118
+ });
119
+ }
120
+ }
121
+ }
122
+ ts.forEachChild(node, visit);
123
+ };
124
+ visit(sourceFile);
125
+ return issues;
126
+ }
127
+ /**
128
+ * Apply auto-fixes to a file
129
+ *
130
+ * @param filePath - Path to the TypeScript file
131
+ * @param issues - Issues to fix
132
+ * @param config - Configuration
133
+ * @returns Auto-fix result
134
+ */
135
+ export function fixIssuesInFile(filePath, issues, config) {
136
+ if (!fs.existsSync(filePath)) {
137
+ return { success: false, message: "File not found", issuesFixed: 0 };
138
+ }
139
+ const originalCode = fs.readFileSync(filePath, "utf-8");
140
+ let fixedCode = originalCode;
141
+ let issuesFixed = 0;
142
+ const fixableRules = config?.auto_fix_rules || [
143
+ "TS_ANY_TYPE",
144
+ "TS_UNSAFE_CAST",
145
+ "TS_IGNORE_WITHOUT_REASON",
146
+ ];
147
+ const linesToFix = issues
148
+ .filter(issue => issue.fixable && fixableRules.includes(issue.ruleId))
149
+ .sort((a, b) => b.line - a.line); // Process from bottom to top to preserve positions
150
+ const lines = fixedCode.split("\n");
151
+ for (const issue of linesToFix) {
152
+ const lineIndex = issue.line - 1;
153
+ if (lineIndex >= 0 && lineIndex < lines.length) {
154
+ const line = lines[lineIndex];
155
+ // Apply fix based on rule
156
+ if (issue.ruleId === "TS_IGNORE_WITHOUT_REASON") {
157
+ if (line.includes("@ts-ignore") && !line.includes("@ts-ignore -")) {
158
+ lines[lineIndex] = line.replace(/@ts-ignore\b/, "@ts-ignore - complex type");
159
+ issuesFixed++;
160
+ }
161
+ }
162
+ else if (issue.ruleId === "TS_ANY_TYPE") {
163
+ // Replace simple 'any' with 'unknown'
164
+ if (line.includes(": any")) {
165
+ lines[lineIndex] = line.replace(/:\s*any\b/, ": unknown");
166
+ issuesFixed++;
167
+ }
168
+ }
169
+ else if (issue.ruleId === "TS_UNSAFE_CAST") {
170
+ // Replace unsafe casts with 'unknown'
171
+ if (line.includes("as any")) {
172
+ lines[lineIndex] = line.replace(/\bas\s+any\b/, "as unknown");
173
+ issuesFixed++;
174
+ }
175
+ }
176
+ }
177
+ }
178
+ fixedCode = lines.join("\n");
179
+ if (issuesFixed > 0) {
180
+ fs.writeFileSync(filePath, fixedCode, "utf-8");
181
+ }
182
+ return {
183
+ success: issuesFixed > 0,
184
+ message: `Fixed ${issuesFixed} issues`,
185
+ originalCode,
186
+ fixedCode,
187
+ issuesFixed,
188
+ };
189
+ }
190
+ /**
191
+ * Generate type safety metrics for files
192
+ *
193
+ * @param filePaths - Array of file paths to analyze
194
+ * @param config - Configuration
195
+ * @returns Type safety metrics
196
+ */
197
+ export function generateTypeMetrics(filePaths, config) {
198
+ const allIssues = [];
199
+ const filesWithIssues = new Set();
200
+ const issuesByRule = {};
201
+ for (const filePath of filePaths) {
202
+ const issues = lintFileAST(filePath, config);
203
+ if (issues.length > 0) {
204
+ filesWithIssues.add(filePath);
205
+ allIssues.push(...issues);
206
+ for (const issue of issues) {
207
+ issuesByRule[issue.ruleId] = (issuesByRule[issue.ruleId] || 0) + 1;
208
+ }
209
+ }
210
+ }
211
+ const errorCount = allIssues.filter(i => i.severity === "error").length;
212
+ const warningCount = allIssues.filter(i => i.severity === "warn").length;
213
+ // Calculate type safety score (0-100)
214
+ const maxIssues = filePaths.length * 10; // Arbitrary max issues per file
215
+ const scorePercentage = Math.max(0, 100 - (allIssues.length / maxIssues) * 100);
216
+ return {
217
+ totalFiles: filePaths.length,
218
+ filesWithIssues: filesWithIssues.size,
219
+ totalIssues: allIssues.length,
220
+ issuesByRule,
221
+ errorCount,
222
+ warningCount,
223
+ scorePercentage: Math.round(scorePercentage * 10) / 10,
224
+ timestamp: Date.now(),
225
+ };
226
+ }
227
+ /**
228
+ * Export metrics to JSON file
229
+ *
230
+ * @param metrics - Metrics to export
231
+ * @param outputPath - Output file path
232
+ * @returns Success status
233
+ */
234
+ export function exportMetrics(metrics, outputPath) {
235
+ try {
236
+ const dir = path.dirname(outputPath);
237
+ if (!fs.existsSync(dir)) {
238
+ fs.mkdirSync(dir, { recursive: true });
239
+ }
240
+ fs.writeFileSync(outputPath, JSON.stringify(metrics, null, 2), "utf-8");
241
+ return true;
242
+ }
243
+ catch (error) {
244
+ return false;
245
+ }
246
+ }
247
+ /**
248
+ * Load historical metrics
249
+ *
250
+ * @param metricsDir - Directory containing metrics files
251
+ * @returns Array of metrics in chronological order
252
+ */
253
+ export function loadHistoricalMetrics(metricsDir) {
254
+ const metrics = [];
255
+ if (!fs.existsSync(metricsDir)) {
256
+ return metrics;
257
+ }
258
+ const files = fs.readdirSync(metricsDir).filter(f => f.endsWith(".json")).sort();
259
+ for (const file of files) {
260
+ try {
261
+ const content = fs.readFileSync(path.join(metricsDir, file), "utf-8");
262
+ const data = JSON.parse(content);
263
+ metrics.push(data);
264
+ }
265
+ catch (error) {
266
+ // Skip invalid files
267
+ }
268
+ }
269
+ return metrics;
270
+ }
271
+ /**
272
+ * Calculate metrics trend
273
+ *
274
+ * @param metrics - Array of metrics in chronological order
275
+ * @returns Trend information
276
+ */
277
+ export function calculateMetricsTrend(metrics) {
278
+ if (metrics.length < 2) {
279
+ return { improvement: false, percentChange: 0, description: "Insufficient data for trend" };
280
+ }
281
+ const first = metrics[0];
282
+ const last = metrics[metrics.length - 1];
283
+ const percentChange = last.scorePercentage - first.scorePercentage;
284
+ const improvement = percentChange > 0;
285
+ return {
286
+ improvement,
287
+ percentChange: Math.round(percentChange * 10) / 10,
288
+ description: improvement
289
+ ? `Type safety improved by ${percentChange.toFixed(1)}%`
290
+ : `Type safety decreased by ${Math.abs(percentChange).toFixed(1)}%`,
291
+ };
292
+ }
293
+ //# sourceMappingURL=type-safety-ast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-safety-ast.js","sourceRoot":"","sources":["../../src/linters/type-safety-ast.ts"],"names":[],"mappings":"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"}