@lhi/tdd-audit 1.1.0 → 1.1.1

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/index.js CHANGED
@@ -16,7 +16,6 @@ const projectDir = process.cwd();
16
16
 
17
17
  const targetSkillDir = path.join(agentBaseDir, agentDirName, 'skills', 'tdd-remediation');
18
18
  const targetWorkflowDir = path.join(agentBaseDir, agentDirName, 'workflows');
19
- const targetTestDir = path.join(projectDir, '__tests__', 'security');
20
19
 
21
20
  // ─── 1. Framework Detection ──────────────────────────────────────────────────
22
21
 
@@ -43,7 +42,24 @@ function detectFramework() {
43
42
 
44
43
  const framework = detectFramework();
45
44
 
46
- // ─── 2. Quick Scan ───────────────────────────────────────────────────────────
45
+ // ─── 2. Test Directory Detection ─────────────────────────────────────────────
46
+
47
+ function detectTestBaseDir() {
48
+ // Respect an existing convention before inventing one
49
+ const candidates = ['__tests__', 'tests', 'test', 'spec'];
50
+ for (const dir of candidates) {
51
+ if (fs.existsSync(path.join(projectDir, dir))) return dir;
52
+ }
53
+ // Framework-informed defaults when no directory exists yet
54
+ if (framework === 'pytest') return 'tests';
55
+ if (framework === 'go') return 'test';
56
+ return '__tests__';
57
+ }
58
+
59
+ const testBaseDir = detectTestBaseDir();
60
+ const targetTestDir = path.join(projectDir, testBaseDir, 'security');
61
+
62
+ // ─── 3. Quick Scan ───────────────────────────────────────────────────────────
47
63
 
48
64
  const VULN_PATTERNS = [
49
65
  { name: 'SQL Injection', severity: 'CRITICAL', pattern: /(`SELECT[^`]*\$\{|"SELECT[^"]*"\s*\+|execute\(f"|cursor\.execute\(.*%s|\.query\(`[^`]*\$\{)/i },
@@ -111,9 +127,9 @@ function printFindings(findings) {
111
127
  console.log('\n Run /tdd-audit in your agent to remediate.\n');
112
128
  }
113
129
 
114
- // ─── 3. Install Skill Files ───────────────────────────────────────────────────
130
+ // ─── 4. Install Skill Files ───────────────────────────────────────────────────
115
131
 
116
- console.log(`\nInstalling TDD Remediation Skill (${isLocal ? 'local' : 'global'}, framework: ${framework})...\n`);
132
+ console.log(`\nInstalling TDD Remediation Skill (${isLocal ? 'local' : 'global'}, framework: ${framework}, test dir: ${testBaseDir}/)...\n`);
117
133
 
118
134
  if (!fs.existsSync(targetSkillDir)) fs.mkdirSync(targetSkillDir, { recursive: true });
119
135
 
@@ -123,7 +139,7 @@ for (const item of ['SKILL.md', 'prompts', 'templates']) {
123
139
  if (fs.existsSync(src)) fs.cpSync(src, dest, { recursive: true });
124
140
  }
125
141
 
126
- // ─── 4. Scaffold Security Test Boilerplate ────────────────────────────────────
142
+ // ─── 5. Scaffold Security Test Boilerplate ────────────────────────────────────
127
143
 
128
144
  if (!fs.existsSync(targetTestDir)) {
129
145
  fs.mkdirSync(targetTestDir, { recursive: true });
@@ -147,7 +163,7 @@ if (!fs.existsSync(destTest) && fs.existsSync(srcTest)) {
147
163
  console.log(`✅ Scaffolded ${path.relative(projectDir, destTest)}`);
148
164
  }
149
165
 
150
- // ─── 5. Install Workflow Shortcode ────────────────────────────────────────────
166
+ // ─── 6. Install Workflow Shortcode ────────────────────────────────────────────
151
167
 
152
168
  if (!fs.existsSync(targetWorkflowDir)) fs.mkdirSync(targetWorkflowDir, { recursive: true });
153
169
  const srcWorkflow = path.join(__dirname, 'workflows', 'tdd-audit.md');
@@ -157,7 +173,7 @@ if (fs.existsSync(srcWorkflow)) {
157
173
  console.log(`✅ Installed /tdd-audit workflow shortcode`);
158
174
  }
159
175
 
160
- // ─── 6. Inject test:security into package.json ────────────────────────────────
176
+ // ─── 7. Inject test:security into package.json ────────────────────────────────
161
177
 
162
178
  const pkgPath = path.join(projectDir, 'package.json');
163
179
  if (framework !== 'pytest' && framework !== 'go' && fs.existsSync(pkgPath)) {
@@ -165,11 +181,12 @@ if (framework !== 'pytest' && framework !== 'go' && fs.existsSync(pkgPath)) {
165
181
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
166
182
  if (!pkg.scripts?.['test:security']) {
167
183
  pkg.scripts = pkg.scripts || {};
184
+ const secDir = `${testBaseDir}/security`;
168
185
  pkg.scripts['test:security'] = {
169
- jest: 'jest --testPathPattern=__tests__/security --forceExit',
170
- vitest: 'vitest run __tests__/security',
171
- mocha: "mocha '__tests__/security/**/*.spec.js'",
172
- }[framework] || 'jest --testPathPattern=__tests__/security --forceExit';
186
+ jest: `jest --testPathPattern=${secDir} --forceExit`,
187
+ vitest: `vitest run ${secDir}`,
188
+ mocha: `mocha '${secDir}/**/*.spec.js'`,
189
+ }[framework] || `jest --testPathPattern=${secDir} --forceExit`;
173
190
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
174
191
  console.log(`✅ Added "test:security" script to package.json`);
175
192
  } else {
@@ -180,7 +197,7 @@ if (framework !== 'pytest' && framework !== 'go' && fs.existsSync(pkgPath)) {
180
197
  }
181
198
  }
182
199
 
183
- // ─── 7. Scaffold CI Workflow ─────────────────────────────────────────────────
200
+ // ─── 8. Scaffold CI Workflow ─────────────────────────────────────────────────
184
201
 
185
202
  const ciWorkflowDir = path.join(projectDir, '.github', 'workflows');
186
203
  const ciWorkflowPath = path.join(ciWorkflowDir, 'security-tests.yml');
@@ -203,7 +220,7 @@ if (!fs.existsSync(ciWorkflowPath)) {
203
220
  console.log(` .github/workflows/security-tests.yml already exists — skipped`);
204
221
  }
205
222
 
206
- // ─── 8. Pre-commit Hook (opt-in) ─────────────────────────────────────────────
223
+ // ─── 9. Pre-commit Hook (opt-in) ─────────────────────────────────────────────
207
224
 
208
225
  if (withHooks) {
209
226
  const gitDir = path.join(projectDir, '.git');
@@ -241,7 +258,7 @@ if (withHooks) {
241
258
  }
242
259
  }
243
260
 
244
- // ─── 9. Quick Scan ───────────────────────────────────────────────────────────
261
+ // ─── 10. Quick Scan ──────────────────────────────────────────────────────────
245
262
 
246
263
  if (!skipScan) {
247
264
  process.stdout.write('\n🔍 Scanning for vulnerability patterns...');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lhi/tdd-audit",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Anti-Gravity Skill for TDD Remediation. Patches security vulnerabilities using a Red-Green-Refactor protocol with automated exploit tests.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -101,7 +101,7 @@ Ask the user to confirm the list before beginning remediation. If they say "fix
101
101
 
102
102
  For **each** confirmed vulnerability, rigorously apply the RED-GREEN-REFACTOR protocol in order:
103
103
 
104
- 1. **[RED](./red-phase.md)**: Write the exploit test in `__tests__/security/` and run it to prove the vulnerability exists (test must fail).
104
+ 1. **[RED](./red-phase.md)**: Write the exploit test in the project's security test directory (e.g., `tests/security/`, `__tests__/security/`, `test/security/` — wherever the installer scaffolded the boilerplate) and run it to prove the vulnerability exists (test must fail).
105
105
  2. **[GREEN](./green-phase.md)**: Apply the targeted patch. Run the exploit test — it must now pass.
106
106
  3. **[REFACTOR](./refactor-phase.md)**: Run the full test suite. All tests must be green before moving on.
107
107