@chemx/starter-kit 26.10.4-1258 → 26.10.4-235
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.
|
@@ -73,38 +73,10 @@ const normalizeWords = (text) => {
|
|
|
73
73
|
.filter((w) => w.length > 1 && !STOP_WORDS.has(w));
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
// A line-based scan cannot tell a comment from a string that quotes one. Walk the line
|
|
77
|
-
// up to the match and track quote state: if a quote is still open at that offset, the
|
|
78
|
-
// match sits inside a string literal and is describing the pattern, not committing it.
|
|
79
|
-
// Lines that are wholly a comment short-circuit, so apostrophes in prose cannot open a
|
|
80
|
-
// phantom string and suppress a real finding.
|
|
81
|
-
const COMMENT_LINE_START = /^\s*(?:\/\/|#|\*|--)/;
|
|
82
|
-
|
|
83
|
-
const isInsideStringLiteral = (lineText, matchIndex) => {
|
|
84
|
-
if (matchIndex <= 0) return false;
|
|
85
|
-
if (COMMENT_LINE_START.test(lineText)) return false;
|
|
86
|
-
|
|
87
|
-
let quote = null;
|
|
88
|
-
for (let i = 0; i < matchIndex; i += 1) {
|
|
89
|
-
const ch = lineText[i];
|
|
90
|
-
if (ch === '\\') {
|
|
91
|
-
i += 1;
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
if (quote) {
|
|
95
|
-
if (ch === quote) quote = null;
|
|
96
|
-
} else if (ch === '"' || ch === "'" || ch === '`') {
|
|
97
|
-
quote = ch;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return quote !== null;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
76
|
export const checkSlopTextPatterns = (content, lines, relativePath, violations) => {
|
|
104
77
|
lines.forEach((lineText, idx) => {
|
|
105
78
|
for (const pat of CONVERSATIONAL_PATTERNS) {
|
|
106
|
-
|
|
107
|
-
if (hit && !isInsideStringLiteral(lineText, hit.index)) {
|
|
79
|
+
if (pat.regex.test(lineText)) {
|
|
108
80
|
const meta = RULE_REGISTRY[pat.rule];
|
|
109
81
|
violations.push({
|
|
110
82
|
filePath: relativePath,
|
package/cli/reader.js
CHANGED
|
@@ -4,8 +4,6 @@ import { parse } from '@babel/parser';
|
|
|
4
4
|
import traverseModule from '@babel/traverse';
|
|
5
5
|
import { ANSI } from './theme.js';
|
|
6
6
|
import { resolveSafePath } from './path-scope.js';
|
|
7
|
-
import { isBabelParsable } from './languages.js';
|
|
8
|
-
import { extractAstMetadata } from './search-ast.js';
|
|
9
7
|
|
|
10
8
|
import {
|
|
11
9
|
stripCodeComments,
|
|
@@ -36,12 +34,6 @@ const traverse = traverseModule.default || traverseModule;
|
|
|
36
34
|
* @param {string} filePath File path for parser context.
|
|
37
35
|
* @returns {string} Compressed structural outline.
|
|
38
36
|
*/
|
|
39
|
-
const OUTLINE_KIND_LABELS = {
|
|
40
|
-
class: 'class',
|
|
41
|
-
function: 'function',
|
|
42
|
-
symbol: 'symbol'
|
|
43
|
-
};
|
|
44
|
-
|
|
45
37
|
export const generateAstOutline = (code, filePath) => {
|
|
46
38
|
const isVue = filePath.endsWith('.vue');
|
|
47
39
|
const isSvelte = filePath.endsWith('.svelte');
|
|
@@ -60,21 +52,6 @@ export const generateAstOutline = (code, filePath) => {
|
|
|
60
52
|
const lines = [];
|
|
61
53
|
lines.push(`// Outline: ${filePath}`);
|
|
62
54
|
|
|
63
|
-
// Babel cannot parse C/C++, Python, Go, Rust, Java, C# or Kotlin. It also does not
|
|
64
|
-
// throw on them, because errorRecovery swallows the failure and yields an empty AST,
|
|
65
|
-
// so the catch-block fallback below never fires for these files. Route them to the
|
|
66
|
-
// polyglot extractor instead.
|
|
67
|
-
if (!isBabelParsable(filePath)) {
|
|
68
|
-
const meta = extractAstMetadata(scriptContent, filePath);
|
|
69
|
-
const seen = new Set();
|
|
70
|
-
for (const sym of meta.symbols) {
|
|
71
|
-
if (!sym?.name || seen.has(sym.name)) continue;
|
|
72
|
-
seen.add(sym.name);
|
|
73
|
-
lines.push(`${OUTLINE_KIND_LABELS[sym.kind] || 'symbol'} ${sym.name}`);
|
|
74
|
-
}
|
|
75
|
-
return lines.join('\n');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
55
|
try {
|
|
79
56
|
const ast = parse(scriptContent, {
|
|
80
57
|
sourceType: 'module',
|
package/package.json
CHANGED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import test from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { auditCode } from './rules.js';
|
|
4
|
-
|
|
5
|
-
const fired = (code, file = 'src/thing.js') =>
|
|
6
|
-
auditCode(code, file, file).some((v) => v.rule === 'AI_SLOP_LAZY_PLACEHOLDER');
|
|
7
|
-
|
|
8
|
-
test('slop: real truncation placeholder in a comment still fires', () => {
|
|
9
|
-
assert.equal(fired('function a() {\n // ... rest of code\n}\n'), true);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
test('slop: trailing truncation comment after code still fires', () => {
|
|
13
|
-
assert.equal(fired('doThing(); // ... remaining implementation\n'), true);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('slop: placeholder text inside a double-quoted string does not fire', () => {
|
|
17
|
-
const code = 'const copy = "Blocks lazy \'// ...rest of code\' truncation placeholders";\n';
|
|
18
|
-
assert.equal(fired(code), false, 'marketing copy describing the pattern must not be flagged');
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('slop: placeholder text inside a single-quoted string does not fire', () => {
|
|
22
|
-
const code = "const copy = 'we detect // ... existing code markers';\n";
|
|
23
|
-
assert.equal(fired(code), false);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('slop: placeholder inside a template literal does not fire', () => {
|
|
27
|
-
const code = 'const copy = `catches // ... remaining logic in your diff`;\n';
|
|
28
|
-
assert.equal(fired(code), false);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('slop: string-literal guard applies to non-JS languages too', () => {
|
|
32
|
-
const py = 'DESCRIPTION = "flags // ... rest of code placeholders"\n';
|
|
33
|
-
assert.equal(fired(py, 'services/detect.py'), false);
|
|
34
|
-
});
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import test from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { generateAstOutline } from './reader.js';
|
|
4
|
-
|
|
5
|
-
const CPP = `
|
|
6
|
-
#include <memory>
|
|
7
|
-
namespace audio {
|
|
8
|
-
struct FrameHeader { uint32_t size; };
|
|
9
|
-
class StreamDecoder : public IDecoder {
|
|
10
|
-
public:
|
|
11
|
-
bool DecodeFrame(const FrameHeader& header);
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
`;
|
|
15
|
-
|
|
16
|
-
const PY = `
|
|
17
|
-
import os
|
|
18
|
-
|
|
19
|
-
class ConsentService:
|
|
20
|
-
def revoke(self, user_id):
|
|
21
|
-
return True
|
|
22
|
-
|
|
23
|
-
def helper(x):
|
|
24
|
-
return x
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
test('outline: renders C++ declarations instead of an empty header', () => {
|
|
28
|
-
const out = generateAstOutline(CPP, 'src/audio/StreamDecoder.cpp');
|
|
29
|
-
const body = out.split('\n').filter((l) => !l.startsWith('// Outline:'));
|
|
30
|
-
assert.ok(body.length > 0, `expected symbols, got only the header:\n${out}`);
|
|
31
|
-
assert.ok(out.includes('StreamDecoder'), `expected StreamDecoder in:\n${out}`);
|
|
32
|
-
assert.ok(out.includes('FrameHeader'), `expected FrameHeader in:\n${out}`);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test('outline: renders Python declarations instead of an empty header', () => {
|
|
36
|
-
const out = generateAstOutline(PY, 'services/consent.py');
|
|
37
|
-
const body = out.split('\n').filter((l) => !l.startsWith('// Outline:'));
|
|
38
|
-
assert.ok(body.length > 0, `expected symbols, got only the header:\n${out}`);
|
|
39
|
-
assert.ok(out.includes('ConsentService'), `expected ConsentService in:\n${out}`);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test('outline: still renders JavaScript exports unchanged', () => {
|
|
43
|
-
const js = `export const FOO = 1;\nexport function bar(a) { return a; }\n`;
|
|
44
|
-
const out = generateAstOutline(js, 'cli/thing.js');
|
|
45
|
-
assert.ok(out.includes('FOO'), out);
|
|
46
|
-
assert.ok(out.includes('bar'), out);
|
|
47
|
-
});
|