valent-pipeline 0.19.24 → 0.19.25

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valent-pipeline",
3
- "version": "0.19.24",
3
+ "version": "0.19.25",
4
4
  "description": "v3 multi-agent AI pipeline for software development lifecycle",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,107 @@
1
+ // valent-pipeline — STANDARD hardened ESLint baseline.
2
+ // Seeded by `valent-pipeline init` into TypeScript projects that have NO ESLint config of their own;
3
+ // it never overwrites an existing one. This is the universal base — add project-specific guards in
4
+ // your own block.
5
+ //
6
+ // What it enforces (ONE `eslint .` pass, prod vs tests differentiated by file glob):
7
+ // • Strict TypeScript correctness — typescript-eslint `strict`, the hardest SYNTACTIC tier — on
8
+ // production code AND tests (a broken test is false confidence).
9
+ // • Maintainability caps (complexity / depth / length) on PRODUCTION code only — off for tests,
10
+ // where long/repetitive is fine.
11
+ //
12
+ // Requires (devDependencies — the standard uses NO others):
13
+ // eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
14
+ // Recommended package.json scripts:
15
+ // "lint": "eslint . --max-warnings 0" "typecheck": "tsc --noEmit"
16
+ // Make them a blocking gate by adding both to pipeline-config.yaml `pre_critic_gate.commands`.
17
+ //
18
+ // Project-specific guards (e.g. banning Math.random for deterministic sims, NodeNext import-extension
19
+ // rules, module-boundary guards) are intentionally NOT here — add them in your own config block.
20
+ // Type-aware rules (no-floating-promises, …) are the fast-follow — see the commented block at the bottom.
21
+
22
+ import tseslint from '@typescript-eslint/eslint-plugin';
23
+ import tsParser from '@typescript-eslint/parser';
24
+
25
+ // CORRECTNESS — applies to prod AND tests. STRICT = hardest syntactic tier (recommended spread first
26
+ // so the base set is present even if strict's `.rules` is delta-only).
27
+ const correctness = {
28
+ ...tseslint.configs.recommended.rules,
29
+ ...tseslint.configs.strict.rules,
30
+ '@typescript-eslint/no-explicit-any': 'error',
31
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
32
+ eqeqeq: ['error', 'smart'],
33
+ 'no-var': 'error',
34
+ 'prefer-const': 'error',
35
+ 'no-loop-func': 'error',
36
+ '@typescript-eslint/no-empty-function': 'error',
37
+ };
38
+
39
+ // MAINTAINABILITY — PRODUCTION code only (off for tests). Caps start strict; loosen per project if a
40
+ // codebase legitimately needs it, or tighten over time.
41
+ const maintainability = {
42
+ complexity: ['error', { max: 10 }],
43
+ 'max-depth': ['error', { max: 3 }],
44
+ 'max-lines-per-function': ['error', { max: 100, skipBlankLines: true, skipComments: true }],
45
+ 'max-lines': ['error', { max: 500, skipBlankLines: true, skipComments: true }],
46
+ 'no-console': ['error', { allow: ['warn', 'error'] }],
47
+ 'no-warning-comments': ['error', { terms: ['fixme', 'xxx', 'hack'], location: 'anywhere' }],
48
+ 'func-names': ['error', 'as-needed'],
49
+ };
50
+
51
+ // Lenient naming convention — enforces common casing without fighting external/snake_case APIs.
52
+ const naming = ['error',
53
+ { selector: 'default', format: ['camelCase'], leadingUnderscore: 'allow' },
54
+ { selector: 'variable', format: ['camelCase', 'PascalCase', 'UPPER_CASE'], leadingUnderscore: 'allow' },
55
+ { selector: 'typeLike', format: ['PascalCase'] },
56
+ { selector: 'enumMember', format: ['PascalCase', 'UPPER_CASE'] },
57
+ { selector: 'parameter', format: ['camelCase'], leadingUnderscore: 'allow' },
58
+ { selector: 'variable', modifiers: ['destructured'], format: null },
59
+ { selector: 'objectLiteralProperty', format: null },
60
+ ];
61
+
62
+ const tsLang = { parser: tsParser, parserOptions: { ecmaVersion: 2022, sourceType: 'module', ecmaFeatures: { jsx: true } } };
63
+
64
+ export default [
65
+ {
66
+ ignores: ['dist/**', 'build/**', 'node_modules/**', 'coverage/**', 'test-results/**',
67
+ '.valent-pipeline/**', 'stories/**', 'knowledge/**', '**/*.config.{js,cjs,mjs,ts}'],
68
+ },
69
+
70
+ // ── PRODUCTION code: strict correctness + maintainability + naming ──
71
+ {
72
+ files: ['**/*.ts', '**/*.tsx'],
73
+ languageOptions: tsLang,
74
+ plugins: { '@typescript-eslint': tseslint },
75
+ rules: {
76
+ ...correctness,
77
+ ...maintainability,
78
+ '@typescript-eslint/naming-convention': naming,
79
+ },
80
+ },
81
+
82
+ // ── TESTS (dedicated + colocated): correctness ONLY — size/cosmetics off. MUST stay last. ──
83
+ {
84
+ files: ['tests/**/*.ts', 'tests/**/*.tsx', '**/*.test.ts', '**/*.test.tsx', '**/*.spec.ts', '**/*.spec.tsx'],
85
+ languageOptions: tsLang,
86
+ plugins: { '@typescript-eslint': tseslint },
87
+ rules: {
88
+ ...correctness,
89
+ complexity: 'off',
90
+ 'max-depth': 'off',
91
+ 'max-lines': 'off',
92
+ 'max-lines-per-function': 'off',
93
+ 'no-console': 'off',
94
+ 'func-names': 'off',
95
+ 'no-warning-comments': 'off',
96
+ '@typescript-eslint/no-non-null-assertion': 'off', // `!` is idiomatic in test assertions
97
+ },
98
+ },
99
+ ];
100
+
101
+ /* ════ TYPE-AWARE FAST-FOLLOW — the eventual ceiling (strict-type-checked). Requires type info.
102
+ After `npm i -D typescript-eslint` (the unified pkg) and a tsconfig that includes your source:
103
+ • PRODUCTION block: parserOptions.projectService = true; spread ...strictTypeChecked (scoped) —
104
+ adds no-floating-promises, no-misused-promises, await-thenable, no-unnecessary-condition, …
105
+ • TESTS block: add '@typescript-eslint/no-floating-promises':'error' + no-misused-promises — the
106
+ highest-value test rules (they catch false-green un-awaited async assertions).
107
+ Needs a typescript-eslint release that supports your TypeScript major. ════ */
@@ -105,6 +105,27 @@ export async function init(options = {}) {
105
105
  console.log(' Created knowledge/correction-directives.yaml');
106
106
  }
107
107
 
108
+ // 6b. Seed the standard hardened ESLint config for TypeScript projects — inherited ONLY when the
109
+ // project has no ESLint config of its own (never clobbers an existing setup). The standard uses
110
+ // just @typescript-eslint/{parser,eslint-plugin}; see the config header for the lint/typecheck
111
+ // scripts to wire into pre_critic_gate.commands.
112
+ const projectLanguage = (config.tech_stack?.language || 'TypeScript').toLowerCase();
113
+ const isTsProject = projectLanguage.includes('typescript') || /\bts\b/.test(projectLanguage);
114
+ if (isTsProject) {
115
+ const eslintConfigNames = [
116
+ 'eslint.config.js', 'eslint.config.mjs', 'eslint.config.cjs', 'eslint.config.ts',
117
+ '.eslintrc', '.eslintrc.js', '.eslintrc.cjs', '.eslintrc.json', '.eslintrc.yml', '.eslintrc.yaml',
118
+ ];
119
+ const hasEslintConfig = eslintConfigNames.some((n) => fileExists(join(projectRoot, n)));
120
+ const stdEslintSrc = join(PACKAGE_ROOT, 'pipeline', 'templates', 'eslint.config.standard.mjs');
121
+ if (hasEslintConfig) {
122
+ console.log(' ESLint config already present — kept the project\'s own (standard not seeded)');
123
+ } else if (existsSync(stdEslintSrc)) {
124
+ writeFileSafe(join(projectRoot, 'eslint.config.mjs'), readFileSync(stdEslintSrc, 'utf-8'));
125
+ console.log(' Seeded standard hardened ESLint config -> eslint.config.mjs');
126
+ }
127
+ }
128
+
108
129
  // 7. Write the vendored CLI's runtime package.json and install its deps. The CLI needs
109
130
  // commander/yaml/ajv to run AT ALL (resolve-graph, validate-handoff, sprint-pack, …);
110
131
  // sqlite knowledge mode additionally needs better-sqlite3 (FTS5 is compiled in — the whole