octocode-cli 1.5.1 → 1.5.3

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 (112) hide show
  1. package/README.md +28 -9
  2. package/out/chunks/chunk-375ZNU3A.js +317 -0
  3. package/out/chunks/{chunk-V64AXUWB.js → chunk-AYILFPX4.js} +1 -1
  4. package/out/chunks/chunk-BRHVQB64.js +10 -0
  5. package/out/chunks/{command-help-specs-JZXVSLZ5.js → chunk-KWJUBVXJ.js} +1 -1
  6. package/out/chunks/chunk-OMXWZJBJ.js +100 -0
  7. package/out/chunks/command-help-specs-RVJK6V6M.js +8 -0
  8. package/out/chunks/commands-JFDCC4Q7.js +8 -0
  9. package/out/chunks/{help-P7TCOYAJ.js → help-H3WGUJO7.js} +1 -1
  10. package/out/chunks/main-help-BUTDD4IR.js +10 -0
  11. package/out/chunks/{spinner-URV2OX6O.js → spinner-DXD4JQIU.js} +1 -1
  12. package/out/chunks/tool-command-L6PVHUNS.js +8 -0
  13. package/out/octocode-cli.js +1 -1
  14. package/package.json +2 -2
  15. package/skills/octocode-brainstorming/scripts/tavily-search.mjs +1 -10
  16. package/skills/octocode-chrome-devtools/scripts/cdp-runner.mjs +0 -2
  17. package/skills/octocode-chrome-devtools/scripts/cdp-sandbox.mjs +1 -5
  18. package/skills/octocode-chrome-devtools/scripts/cdp-template.mjs +1 -10
  19. package/skills/octocode-chrome-devtools/scripts/open-browser.mjs +0 -3
  20. package/skills/octocode-chrome-devtools/scripts/sourcemap-resolver.mjs +1 -4
  21. package/skills/octocode-chrome-devtools/scripts/undercover.mjs +0 -2
  22. package/skills/octocode-engineer/SKILL.md +7 -33
  23. package/skills/octocode-engineer/references/cli-reference.md +5 -11
  24. package/skills/octocode-engineer/references/externals.md +0 -4
  25. package/skills/octocode-engineer/references/quality-indicators.md +10 -50
  26. package/skills/octocode-engineer/references/tool-workflows.md +10 -13
  27. package/skills/octocode-engineer/src/analysis/dependency-summary.test.ts +2 -2
  28. package/skills/octocode-engineer/src/ast/metrics.test.ts +2 -2
  29. package/skills/octocode-engineer/src/ast/search-main.ts +2 -15
  30. package/skills/octocode-engineer/src/ast/search.ts +1 -7
  31. package/skills/octocode-engineer/src/ast/tree-sitter.test.ts +4 -4
  32. package/skills/octocode-engineer/src/ast/tree-sitter.ts +2 -2
  33. package/skills/octocode-engineer/src/collectors/chains.ts +3 -10
  34. package/skills/octocode-engineer/src/collectors/prototype-pollution.ts +3 -3
  35. package/skills/octocode-engineer/src/collectors/security.ts +3 -3
  36. package/skills/octocode-engineer/src/common/ensure-deps.ts +3 -20
  37. package/skills/octocode-engineer/src/detectors/code-quality.ts +0 -1
  38. package/skills/octocode-engineer/src/index.test.ts +1 -1
  39. package/skills/octocode-engineer/src/index.ts +1 -11
  40. package/skills/octocode-engineer/src/pipeline/affected.ts +2 -7
  41. package/skills/octocode-engineer/src/pipeline/baseline.ts +2 -8
  42. package/skills/octocode-engineer/src/pipeline/cache.ts +2 -2
  43. package/skills/octocode-engineer/src/pipeline/config-loader.test.ts +1 -2
  44. package/skills/octocode-engineer/src/pipeline/config-loader.ts +0 -9
  45. package/skills/octocode-engineer/src/pipeline/create-options.ts +2 -15
  46. package/skills/octocode-engineer/src/pipeline/reporters.ts +2 -12
  47. package/skills/octocode-engineer/src/reporting/summary-md.test.ts +2 -2
  48. package/skills/octocode-engineer/src/run.ts +1 -7
  49. package/skills/octocode-engineer/src/types/constants.ts +0 -5
  50. package/skills/octocode-engineer/src/types/core.ts +0 -5
  51. package/skills/octocode-news/eslint.config.mjs +1 -6
  52. package/skills/octocode-news/src/rss-core.ts +2 -4
  53. package/skills/octocode-research/ecosystem.config.cjs +0 -31
  54. package/skills/octocode-research/package.json +1 -1
  55. package/skills/octocode-research/scripts/server.js +272 -230
  56. package/skills/octocode-research/src/__tests__/integration/circuitBreaker.test.ts +0 -24
  57. package/skills/octocode-research/src/__tests__/integration/routes.test.ts +0 -10
  58. package/skills/octocode-research/src/__tests__/integration/serverLifecycle.test.ts +5 -22
  59. package/skills/octocode-research/src/__tests__/integration/toolsRoutes.test.ts +0 -27
  60. package/skills/octocode-research/src/__tests__/unit/circuitBreaker.test.ts +0 -29
  61. package/skills/octocode-research/src/__tests__/unit/errorHandler.test.ts +1 -12
  62. package/skills/octocode-research/src/__tests__/unit/httpPreprocess.test.ts +1 -9
  63. package/skills/octocode-research/src/__tests__/unit/logger.test.ts +0 -7
  64. package/skills/octocode-research/src/__tests__/unit/queryParser.test.ts +1 -7
  65. package/skills/octocode-research/src/__tests__/unit/responseBuilder.test.ts +0 -11
  66. package/skills/octocode-research/src/__tests__/unit/retry.test.ts +1 -18
  67. package/skills/octocode-research/src/__tests__/unit/schemas.test.ts +2 -25
  68. package/skills/octocode-research/src/index.ts +0 -27
  69. package/skills/octocode-research/src/mcpCache.ts +3 -18
  70. package/skills/octocode-research/src/middleware/errorHandler.ts +1 -4
  71. package/skills/octocode-research/src/middleware/logger.ts +1 -6
  72. package/skills/octocode-research/src/middleware/queryParser.ts +3 -22
  73. package/skills/octocode-research/src/routes/github.ts +0 -11
  74. package/skills/octocode-research/src/routes/local.ts +0 -12
  75. package/skills/octocode-research/src/routes/lsp.ts +1 -10
  76. package/skills/octocode-research/src/routes/package.ts +0 -2
  77. package/skills/octocode-research/src/routes/prompts.ts +2 -32
  78. package/skills/octocode-research/src/routes/tools.ts +12 -177
  79. package/skills/octocode-research/src/server-init.ts +0 -32
  80. package/skills/octocode-research/src/server.ts +8 -37
  81. package/skills/octocode-research/src/types/errorGuards.ts +0 -15
  82. package/skills/octocode-research/src/types/guards.ts +6 -27
  83. package/skills/octocode-research/src/types/mcp.ts +1 -8
  84. package/skills/octocode-research/src/types/responses.ts +0 -15
  85. package/skills/octocode-research/src/utils/asyncTimeout.ts +1 -63
  86. package/skills/octocode-research/src/utils/circuitBreaker.ts +43 -166
  87. package/skills/octocode-research/src/utils/colors.ts +3 -17
  88. package/skills/octocode-research/src/utils/errorQueue.ts +6 -28
  89. package/skills/octocode-research/src/utils/logger.ts +11 -93
  90. package/skills/octocode-research/src/utils/resilience.ts +22 -77
  91. package/skills/octocode-research/src/utils/responseBuilder.ts +26 -78
  92. package/skills/octocode-research/src/utils/responseFactory.ts +0 -7
  93. package/skills/octocode-research/src/utils/responseParser.ts +11 -59
  94. package/skills/octocode-research/src/utils/retry.ts +12 -75
  95. package/skills/octocode-research/src/utils/routeFactory.ts +10 -61
  96. package/skills/octocode-research/src/utils/url.ts +0 -5
  97. package/skills/octocode-research/src/validation/httpPreprocess.ts +15 -61
  98. package/skills/octocode-research/src/validation/schemas.ts +14 -101
  99. package/skills/octocode-research/src/validation/toolCallSchema.ts +5 -65
  100. package/skills/octocode-research/tsdown.config.ts +2 -7
  101. package/skills/octocode-search-skill/SKILL.md +9 -2
  102. package/skills/octocode-search-skill/references/discovery-surfaces.md +2 -1
  103. package/skills/octocode-slides/scripts/navbridge.js +1 -14
  104. package/skills/octocode-slides/scripts/presenter.js +2 -61
  105. package/skills/octocode-stats/scripts/build_dashboard.mjs +1 -19
  106. package/out/chunks/chunk-7476PETK.js +0 -309
  107. package/out/chunks/chunk-OQBJTZWK.js +0 -60
  108. package/out/chunks/chunk-UCZCF3BQ.js +0 -9
  109. package/out/chunks/commands-XBFPLHSQ.js +0 -8
  110. package/out/chunks/main-help-ULF5PAQY.js +0 -10
  111. package/out/chunks/tool-command-M6VA7P2F.js +0 -8
  112. package/skills/octocode-research/AGENTS.md +0 -349
@@ -1,11 +1,5 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Entry point for `scripts/ast/search.js`. Verifies the @ast-grep native
4
- * addons and other runtime deps are installed before loading the main
5
- * search logic. If missing, the bootstrap detects the user's package
6
- * manager and installs into the skill directory, or prints an actionable
7
- * manual command.
8
- */
2
+
9
3
  import { ensureNativeDependencies } from '../common/ensure-deps.js';
10
4
 
11
5
  ensureNativeDependencies(import.meta.url, { tag: '[octocode-ast-search]' });
@@ -405,10 +405,10 @@ function f() {
405
405
 
406
406
  it('computes cognitiveComplexity > 0 for nested control flow', () => {
407
407
  const code = `function complexFn(x: number, y: boolean) {
408
- if (x > 0) { // +1
409
- if (y) { // +2 (1 + nesting=1)
410
- for (let i = 0; i < x; i++) { // +3 (1 + nesting=2)
411
- if (i % 2 === 0) { // +4 (1 + nesting=3)
408
+ if (x > 0) {
409
+ if (y) {
410
+ for (let i = 0; i < x; i++) {
411
+ if (i % 2 === 0) {
412
412
  console.log(i);
413
413
  }
414
414
  }
@@ -473,8 +473,8 @@ export async function resolveTreeSitter(): Promise<TreeSitterRuntime> {
473
473
  parserPy.setLanguage(pyLang as Parameters<Parser['setLanguage']>[0]);
474
474
  }
475
475
  } catch {
476
- // tree-sitter-python not installed — Python analysis via tree-sitter disabled
477
- }
476
+ void 0;
477
+ }
478
478
 
479
479
  treeSitterRuntime = {
480
480
  available: true,
@@ -4,15 +4,10 @@ import { getLineAndCharacter } from '../common/utils.js';
4
4
 
5
5
  import type { FileEntry, MessageChainEntry } from '../types/index.js';
6
6
 
7
- /** Minimum property-access depth to flag as a message chain (Law of Demeter). */
7
+
8
8
  const MIN_CHAIN_DEPTH = 4;
9
9
 
10
- /**
11
- * Walk a property-access or element-access expression to its root and return
12
- * the full chain text and depth (number of dot-steps).
13
- *
14
- * Handles: a.b.c.d a?.b?.c?.d a['b']['c']['d']
15
- */
10
+
16
11
  function measureChain(node: ts.Node, sourceFile: ts.SourceFile): { text: string; depth: number } | null {
17
12
  let depth = 0;
18
13
  let current: ts.Node = node;
@@ -27,14 +22,12 @@ function measureChain(node: ts.Node, sourceFile: ts.SourceFile): { text: string;
27
22
 
28
23
  if (depth < MIN_CHAIN_DEPTH) return null;
29
24
 
30
- // Avoid reporting intermediate nodes — only report the outermost chain.
31
- // (The outermost node is the one whose parent is NOT itself a property/element access)
32
25
  const parent = node.parent;
33
26
  if (
34
27
  ts.isPropertyAccessExpression(parent) ||
35
28
  ts.isElementAccessExpression(parent)
36
29
  ) {
37
- return null; // This is an intermediate node; the outermost will be visited.
30
+ return null;
38
31
  }
39
32
 
40
33
  return { text: node.getText(sourceFile), depth };
@@ -16,7 +16,7 @@ const DEEP_MERGE_NAMES = new Set([
16
16
  'mixin',
17
17
  ]);
18
18
 
19
- /** Check if a computed-property-write key comes from a for..of/for..in loop over known internal iteration */
19
+
20
20
  function isKeyFromInternalIteration(
21
21
  node: ts.ElementAccessExpression,
22
22
  sourceFile: ts.SourceFile
@@ -49,7 +49,7 @@ function isKeyFromInternalIteration(
49
49
  return false;
50
50
  }
51
51
 
52
- /** Check if the containing block has a __proto__/constructor/prototype key guard */
52
+
53
53
  function hasProtoKeyGuard(node: ts.Node, sourceFile: ts.SourceFile): boolean {
54
54
  const block = findParentBlock(node);
55
55
  if (!block) return false;
@@ -63,7 +63,7 @@ function hasProtoKeyGuard(node: ts.Node, sourceFile: ts.SourceFile): boolean {
63
63
  );
64
64
  }
65
65
 
66
- /** Check if the target object was created with Object.create(null) or is Map/Set */
66
+
67
67
  function isTargetSafeObject(
68
68
  node: ts.ElementAccessExpression,
69
69
  sourceFile: ts.SourceFile
@@ -50,9 +50,9 @@ const SECRET_PATTERNS = [
50
50
  const SQL_KEYWORDS =
51
51
  /\b(SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|TRUNCATE)\b/i;
52
52
 
53
- /** Strings that look like placeholders, not real secrets */
53
+
54
54
  const PLACEHOLDER_PATTERN = /^(YOUR_|REPLACE_ME|<[a-z_-]+>|\$\{|{{)/i;
55
- /** UUID pattern: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx */
55
+
56
56
  const UUID_PATTERN =
57
57
  /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
58
58
 
@@ -74,7 +74,7 @@ function isPlaceholderOrUuid(value: string): boolean {
74
74
  return PLACEHOLDER_PATTERN.test(value) || UUID_PATTERN.test(value);
75
75
  }
76
76
 
77
- /** Skip strings inside finding metadata fields (suggestedFix, reason, impact, etc.) */
77
+
78
78
  const METADATA_PROP_NAMES = new Set([
79
79
  'suggestedFix',
80
80
  'strategy',
@@ -1,13 +1,3 @@
1
- /**
2
- * Ensures native and pure-JS dependencies required at runtime are installed.
3
- *
4
- * The skill's bundle cannot inline native addons (@ast-grep/napi, tree-sitter
5
- * variants) — they must exist in the skill's node_modules at runtime. When the
6
- * skill ships standalone (outside the monorepo's hoisted node_modules), the
7
- * first run needs to install them. This module detects the user's package
8
- * manager from lockfiles, runs install against the skill directory, and exits
9
- * with an actionable message if install fails.
10
- */
11
1
  import { spawnSync } from 'node:child_process';
12
2
  import { existsSync } from 'node:fs';
13
3
  import { createRequire } from 'node:module';
@@ -75,7 +65,6 @@ function planInstall(skillDir: string): InstallPlan {
75
65
  }
76
66
 
77
67
  function findSkillDir(entryUrl: string): string {
78
- // Walk up from the entry file until we find a package.json — that's the skill root.
79
68
  let dir = dirname(fileURLToPath(entryUrl));
80
69
  for (let i = 0; i < MAX_SKILL_DIR_HOPS; i++) {
81
70
  if (existsSync(join(dir, 'package.json'))) return dir;
@@ -83,7 +72,6 @@ function findSkillDir(entryUrl: string): string {
83
72
  if (parent === dir) break;
84
73
  dir = parent;
85
74
  }
86
- // Fallback: assume scripts/<file>.js → skill root is one level up.
87
75
  return dirname(dirname(fileURLToPath(entryUrl)));
88
76
  }
89
77
 
@@ -102,18 +90,13 @@ function missingPackagesFrom(skillDir: string, entryUrl: string): string[] {
102
90
  }
103
91
 
104
92
  export interface EnsureDepsOptions {
105
- /** If false, print instructions and exit; do not run the installer. */
93
+
106
94
  autoInstall?: boolean;
107
- /** Log prefix for user-facing messages. */
95
+
108
96
  tag?: string;
109
97
  }
110
98
 
111
- /**
112
- * Verify the skill's runtime dependencies are resolvable. If not:
113
- * - Detect the user's package manager from the skill directory's lockfile.
114
- * - If autoInstall is true (default), run the installer in the skill dir.
115
- * - Otherwise, print the exact command for the user and exit 1.
116
- */
99
+
117
100
  export function ensureNativeDependencies(
118
101
  entryUrl: string,
119
102
  options: EnsureDepsOptions = {},
@@ -921,7 +921,6 @@ export function detectMessageChains(fileSummaries: FileEntry[]): FindingDraft[]
921
921
  const findings: FindingDraft[] = [];
922
922
  for (const entry of fileSummaries) {
923
923
  if (!entry.messageChains || entry.messageChains.length === 0) continue;
924
- // Group by line start — take the deepest chain at each location
925
924
  const byLine = new Map<number, typeof entry.messageChains[0]>();
926
925
  for (const chain of entry.messageChains) {
927
926
  const existing = byLine.get(chain.lineStart);
@@ -1234,7 +1234,7 @@ describe('diversifyFindings', () => {
1234
1234
 
1235
1235
  it('returns all findings when limit >= length', () => {
1236
1236
  const input = [makeDraft('high', 'a', 1), makeDraft('high', 'b', 1)];
1237
- expect(diversifyFindings(input, 10)).toBe(input); // same reference
1237
+ expect(diversifyFindings(input, 10)).toBe(input);
1238
1238
  expect(diversifyFindings(input, 2)).toBe(input);
1239
1239
  });
1240
1240
 
@@ -433,17 +433,7 @@ export function assignFindingIds(
433
433
  return { findings, byFile };
434
434
  }
435
435
 
436
- /**
437
- * Programmatic scan API — the equivalent of dependency-cruiser's `cruise()`
438
- * or madge's constructor. Runs the full analysis pipeline without CLI I/O.
439
- *
440
- * Usage:
441
- * ```ts
442
- * import { scan, DEFAULT_OPTS } from './index.js';
443
- * const result = await scan({ root: '/path/to/project', graph: true });
444
- * console.log(result.exitCode); // 0=clean, 1=findings, 2=error
445
- * ```
446
- */
436
+
447
437
  export async function scan(
448
438
  overrides: Partial<AnalysisOptions> = {}
449
439
  ): Promise<ScanResult> {
@@ -6,10 +6,7 @@ import { ALLOWED_EXTS } from '../types/index.js';
6
6
 
7
7
  import type { DependencyState } from '../types/index.js';
8
8
 
9
- /**
10
- * Resolves --affected: git changed files + transitive dependents.
11
- * Inspired by dependency-cruiser's --affected (uses watskeburt internally).
12
- */
9
+
13
10
  export function resolveAffectedFiles(
14
11
  root: string,
15
12
  revision: string,
@@ -45,9 +42,7 @@ function getGitChangedFiles(root: string, revision: string): string[] {
45
42
  }
46
43
  }
47
44
 
48
- /**
49
- * BFS: walk incoming edges to collect all transitive dependents of changed files.
50
- */
45
+
51
46
  function collectTransitiveDependents(
52
47
  seeds: Set<string>,
53
48
  state: DependencyState,
@@ -9,10 +9,7 @@ export interface BaselineEntry {
9
9
  title: string;
10
10
  }
11
11
 
12
- /**
13
- * Saves current findings as a baseline for future --ignore-known runs.
14
- * Inspired by dependency-cruiser's --ignore-known baseline file.
15
- */
12
+
16
13
  export function saveBaseline(
17
14
  root: string,
18
15
  findings: Finding[]
@@ -37,10 +34,7 @@ export function saveBaseline(
37
34
  return baselinePath;
38
35
  }
39
36
 
40
- /**
41
- * Loads a baseline file and filters out known findings.
42
- * Match key: (category, file) — title changes don't break the match.
43
- */
37
+
44
38
  export function filterKnownFindings<T extends Pick<Finding, 'category' | 'file'>>(
45
39
  findings: T[],
46
40
  baselinePath: string,
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
 
4
- export const ANALYSIS_SCHEMA_VERSION = '1.1.0'; // Keep in sync with REPORT_SCHEMA_VERSION in index.ts
4
+ export const ANALYSIS_SCHEMA_VERSION = '1.1.0';
5
5
 
6
6
  interface CacheEntry {
7
7
  mtimeMs: number;
@@ -18,7 +18,7 @@ interface AnalysisCache {
18
18
  }
19
19
 
20
20
  const CACHE_VERSION = 1;
21
- const DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
21
+ const DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
22
22
 
23
23
  export function loadCache(root: string): AnalysisCache | null {
24
24
  const cachePath = path.join(
@@ -167,9 +167,8 @@ describe('config-loader', () => {
167
167
  fs.writeFileSync(
168
168
  path.join(root, '.octocode-scan.json'),
169
169
  `{
170
- // Enable graph
171
170
  "graph": true,
172
- "flow": false // Not yet
171
+ "flow": false
173
172
  }`
174
173
  );
175
174
  const config = loadConfigFile(root, null);
@@ -7,11 +7,6 @@ type ConfigOverrides = Partial<Omit<AnalysisOptions, 'root' | 'packageRoot' | 'c
7
7
 
8
8
  const CONFIG_NAMES = ['.octocode-scan.json', '.octocode-scan.jsonc'];
9
9
 
10
- /**
11
- * Loads config from file, auto-discovered config, or package.json#octocode.
12
- * CLI flags always win over config file values.
13
- * Inspired by knip's .knip.json and eslint's flat config.
14
- */
15
10
  export function loadConfigFile(
16
11
  root: string,
17
12
  explicitPath: string | null
@@ -75,10 +70,6 @@ function normalizeConfig(obj: Record<string, unknown>): ConfigOverrides {
75
70
  return result as ConfigOverrides;
76
71
  }
77
72
 
78
- /**
79
- * Merges config file overrides into defaults, then CLI overrides on top.
80
- * CLI args that differ from defaults always win.
81
- */
82
73
  export function mergeConfigIntoDefaults(
83
74
  defaults: AnalysisOptions,
84
75
  config: ConfigOverrides,
@@ -8,17 +8,7 @@ export interface CreateOptionsInput {
8
8
  args: AnalysisOptions;
9
9
  }
10
10
 
11
- /**
12
- * Transforms raw parsed CLI args into validated, normalized runtime options.
13
- * This is Layer 2 in the 3-layer CLI pattern (args → options → engine).
14
- *
15
- * Responsible for:
16
- * - Deriving computed fields (packageRoot)
17
- * - Auto-enabling flags based on feature selection (test-quality → includeTests)
18
- *
19
- * Inspired by knip's create-options.ts, eslint's translate-cli-options.js,
20
- * and dependency-cruiser's normalize-cli-options.mjs.
21
- */
11
+
22
12
  export function createOptions({ args }: CreateOptionsInput): AnalysisOptions {
23
13
  const opts = { ...args };
24
14
 
@@ -37,10 +27,7 @@ function autoEnableTestQuality(opts: AnalysisOptions): void {
37
27
  }
38
28
  }
39
29
 
40
- /**
41
- * Resolves `--exclude` into a features set by subtracting from ALL_CATEGORIES.
42
- * Called during CLI arg parsing when --exclude is used.
43
- */
30
+
44
31
  export function resolveExcludeToFeatures(
45
32
  excludeSet: Set<string>
46
33
  ): Set<string> {
@@ -1,9 +1,5 @@
1
1
  import type { Finding, ReporterFormat } from '../types/index.js';
2
2
 
3
- /**
4
- * Formats findings for alternative output targets.
5
- * Inspired by eslint's --format flag and dependency-cruiser's reporter plugins.
6
- */
7
3
 
8
4
  export function formatFindings(
9
5
  findings: Finding[],
@@ -34,10 +30,7 @@ function severityToLevel(severity: string): string {
34
30
  }
35
31
  }
36
32
 
37
- /**
38
- * Compact: one-line per finding for terminal/CI logs.
39
- * Format: severity:file:line - [category] title
40
- */
33
+
41
34
  function formatCompact(findings: Finding[], root: string): string {
42
35
  return findings
43
36
  .map(f => {
@@ -48,10 +41,7 @@ function formatCompact(findings: Finding[], root: string): string {
48
41
  .join('\n');
49
42
  }
50
43
 
51
- /**
52
- * GitHub Actions: ::warning / ::error annotations.
53
- * These appear inline on PR diffs.
54
- */
44
+
55
45
  function formatGitHubActions(findings: Finding[], root: string): string {
56
46
  return findings
57
47
  .map(f => {
@@ -173,13 +173,13 @@ describe('computeHealthScore', () => {
173
173
  it('penalizes medium findings (weight 3)', () => {
174
174
  const findings = [makeFinding({ severity: 'medium' })];
175
175
  const score = computeHealthScore(findings, 10);
176
- expect(score).toBe(97); // 100 - (3/10)*10 = 97
176
+ expect(score).toBe(97);
177
177
  });
178
178
 
179
179
  it('penalizes low findings (weight 1)', () => {
180
180
  const findings = [makeFinding({ severity: 'low' })];
181
181
  const score = computeHealthScore(findings, 10);
182
- expect(score).toBe(99); // 100 - (1/10)*10 = 99
182
+ expect(score).toBe(99);
183
183
  });
184
184
 
185
185
  it('info severity has weight 0', () => {
@@ -1,11 +1,5 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Entry point for the octocode-engineer scanner. Verifies runtime
4
- * dependencies (native addons that cannot be bundled + the TypeScript
5
- * compiler) are installed before loading the pipeline. If missing, the
6
- * bootstrap detects the user's package manager from lockfiles and installs
7
- * into the skill's own node_modules, or prints an actionable manual command.
8
- */
2
+
9
3
  import { ensureNativeDependencies } from './common/ensure-deps.js';
10
4
 
11
5
  ensureNativeDependencies(import.meta.url, { tag: '[octocode-scan]' });
@@ -6,7 +6,6 @@ import type { AnalysisOptions, Thresholds } from './core.js';
6
6
  import type { DependencyProfile } from './dependency.js';
7
7
 
8
8
  export const DEFAULT_THRESHOLDS: Thresholds = {
9
- // Architecture
10
9
  couplingThreshold: 15,
11
10
  fanInThreshold: 20,
12
11
  fanOutThreshold: 15,
@@ -17,7 +16,6 @@ export const DEFAULT_THRESHOLDS: Thresholds = {
17
16
  sdpMaxSourceInstability: 0.6,
18
17
  layerOrder: [],
19
18
 
20
- // Code quality
21
19
  minFunctionStatements: 6,
22
20
  minFlowStatements: 6,
23
21
  criticalComplexityThreshold: 30,
@@ -35,15 +33,12 @@ export const DEFAULT_THRESHOLDS: Thresholds = {
35
33
  magicStringMinOccurrences: 3,
36
34
  booleanParamThreshold: 3,
37
35
 
38
- // Semantic
39
36
  overrideChainThreshold: 3,
40
37
  shotgunThreshold: 8,
41
38
 
42
- // Security
43
39
  secretEntropyThreshold: 4.5,
44
40
  secretMinLength: 20,
45
41
 
46
- // Test quality
47
42
  mockThreshold: 10,
48
43
  };
49
44
 
@@ -123,7 +123,6 @@ export interface ControlMapEntry extends FlowEntry {
123
123
  }
124
124
 
125
125
  export interface Thresholds {
126
- // Architecture
127
126
  couplingThreshold: number;
128
127
  fanInThreshold: number;
129
128
  fanOutThreshold: number;
@@ -134,7 +133,6 @@ export interface Thresholds {
134
133
  sdpMaxSourceInstability: number;
135
134
  layerOrder: string[];
136
135
 
137
- // Code quality
138
136
  minFunctionStatements: number;
139
137
  minFlowStatements: number;
140
138
  criticalComplexityThreshold: number;
@@ -152,15 +150,12 @@ export interface Thresholds {
152
150
  magicStringMinOccurrences: number;
153
151
  booleanParamThreshold: number;
154
152
 
155
- // Semantic
156
153
  overrideChainThreshold: number;
157
154
  shotgunThreshold: number;
158
155
 
159
- // Security
160
156
  secretEntropyThreshold: number;
161
157
  secretMinLength: number;
162
158
 
163
- // Test quality
164
159
  mockThreshold: number;
165
160
  }
166
161
 
@@ -5,12 +5,7 @@ import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"
5
5
 
6
6
  export default tseslint.config(
7
7
  {
8
- ignores: ["node_modules/**", "scripts/**"]
9
- },
10
- js.configs.recommended,
11
- ...tseslint.configs.recommended,
12
- {
13
- files: ["src/**/*.ts", "*.mjs"],
8
+ ignores: ["node_modules*.ts", "*.mjs"],
14
9
  languageOptions: {
15
10
  ecmaVersion: "latest",
16
11
  sourceType: "module",
@@ -82,7 +82,6 @@ export function parseFeedCatalog(markdown) {
82
82
  pastSeparator = false;
83
83
  }
84
84
 
85
- // Fenced-block parsing (legacy ### RSS Feeds format)
86
85
  if (/^### RSS Feeds/.test(trimmed)) {
87
86
  awaitingFence = true;
88
87
  insideFeedBlock = false;
@@ -107,7 +106,6 @@ export function parseFeedCatalog(markdown) {
107
106
  return;
108
107
  }
109
108
 
110
- // Table parsing: extract from RSS column
111
109
  if (trimmed.startsWith("|")) {
112
110
  const cells = trimmed
113
111
  .replace(/^\|/, "")
@@ -326,8 +324,8 @@ export async function readResponseBody(response, maxBytes = 1024 * 1024) {
326
324
  try {
327
325
  await reader.cancel();
328
326
  } catch {
329
- // Ignore cancellation errors once we have the bytes we need.
330
- }
327
+ void 0;
328
+ }
331
329
  }
332
330
 
333
331
  text += decoder.decode();
@@ -11,76 +11,45 @@
11
11
  * @see docs/SERVER_FLOWS.md for detailed flow documentation
12
12
  */
13
13
 
14
- // PM2 logs disabled - app handles all logging with rotation
15
14
 
16
15
  module.exports = {
17
16
  apps: [{
18
17
  name: 'octocode-research',
19
18
  script: './scripts/server.js',
20
19
 
21
- // ============================================
22
- // RESTART STRATEGIES
23
- // ============================================
24
20
 
25
- // ❌ REMOVED: cron_restart: '0 * * * *'
26
- // Replaced by idle-based restart in server.ts (30 min idle → restart)
27
21
 
28
- // ✅ Memory guard (PM2 safety net)
29
22
  max_memory_restart: '500M',
30
23
 
31
- // ============================================
32
- // GRACEFUL SHUTDOWN
33
- // ============================================
34
24
 
35
- // Allow 2 minutes for connection draining during shutdown
36
- // This gives long-running requests time to complete
37
25
  kill_timeout: 120000,
38
26
 
39
- // Wait for process.send('ready') before marking as online
40
27
  wait_ready: true,
41
28
 
42
- // Timeout for ready signal (15s for MCP initialization)
43
29
  listen_timeout: 15000,
44
30
 
45
- // ============================================
46
- // RESTART BEHAVIOR
47
- // ============================================
48
31
 
49
- // Auto-restart on crash
50
32
  autorestart: true,
51
33
 
52
- // Max consecutive restarts before stopping
53
34
  max_restarts: 10,
54
35
 
55
- // Delay between restarts
56
36
  restart_delay: 1000,
57
37
 
58
- // Exponential backoff on repeated crashes
59
38
  exp_backoff_restart_delay: 100,
60
39
 
61
- // Minimum uptime to consider app started successfully
62
40
  min_uptime: 5000,
63
41
 
64
- // ============================================
65
- // LOGGING
66
- // ============================================
67
42
 
68
- // PM2 logs disabled - app handles logging in ~/.octocode/logs/
69
43
  out_file: '/dev/null',
70
44
  error_file: '/dev/null',
71
45
  merge_logs: true,
72
46
  combine_logs: true,
73
47
 
74
- // ============================================
75
- // ENVIRONMENT
76
- // ============================================
77
48
 
78
- // Node.js environment
79
49
  env: {
80
50
  NODE_ENV: 'production',
81
51
  },
82
52
 
83
- // Development environment (pm2 start --env development)
84
53
  env_development: {
85
54
  NODE_ENV: 'development',
86
55
  },
@@ -52,7 +52,7 @@
52
52
  "js-yaml": "^4.1.1",
53
53
  "octocode-mcp": "workspace:^",
54
54
  "octocode-shared": "workspace:^",
55
- "zod": "^3.25.0"
55
+ "zod": "^4.0.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@eslint/js": "^9.27.0",