@boyingliu01/xp-gate 0.20.1 → 0.20.2
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/adapters/java.sh +373 -27
- package/gate-3.sh +51 -3
- package/gate-4.sh +32 -1
- package/hooks/gate-3.sh +51 -3
- package/hooks/gate-4.sh +32 -1
- package/hooks/pre-commit +275 -36
- package/lib/__tests__/doctor-spawn-capability.test.js +116 -0
- package/lib/__tests__/doctor-tui-skill-freshness.test.js +49 -10
- package/lib/doctor-tui.js +21 -3
- package/lib/doctor.js +111 -8
- package/lib/gate-audit.ts +3 -0
- package/lib/mattpocock-license-verdict.json +1 -1
- package/mock-policy/AGENTS.md +2 -2
- package/mutation/AGENTS.md +2 -2
- package/package.json +1 -1
- package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-code/skills/admin-template-guidelines/SKILL.md +1 -0
- package/plugins/claude-code/skills/batch-grill-me/SKILL.md +1 -0
- package/plugins/claude-code/skills/clipboard-vision/SKILL.md +1 -0
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +2 -2
- package/plugins/claude-code/skills/domain-modeling/SKILL.md +1 -0
- package/plugins/claude-code/skills/grill-with-docs/SKILL.md +1 -0
- package/plugins/claude-code/skills/grilling/SKILL.md +1 -0
- package/plugins/claude-code/skills/improve-codebase-architecture/SKILL.md +1 -0
- package/plugins/claude-code/skills/ralph-loop/SKILL.md +1 -0
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +2 -2
- package/plugins/claude-code/skills/test-driven-development/SKILL.md +1 -0
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +2 -2
- package/plugins/claude-code/skills/test-specification-alignment/SKILL.md +1 -0
- package/plugins/claude-code/skills/to-issues/SKILL.md +1 -0
- package/plugins/dsh/package.json +1 -1
- package/plugins/dsh/skills/admin-template-guidelines/SKILL.md +1 -0
- package/plugins/dsh/skills/batch-grill-me/SKILL.md +1 -0
- package/plugins/dsh/skills/clipboard-vision/SKILL.md +1 -0
- package/plugins/dsh/skills/delphi-review/AGENTS.md +2 -2
- package/plugins/dsh/skills/domain-modeling/SKILL.md +1 -0
- package/plugins/dsh/skills/grill-with-docs/SKILL.md +1 -0
- package/plugins/dsh/skills/grilling/SKILL.md +1 -0
- package/plugins/dsh/skills/improve-codebase-architecture/SKILL.md +1 -0
- package/plugins/dsh/skills/ralph-loop/SKILL.md +1 -0
- package/plugins/dsh/skills/sprint-flow/AGENTS.md +2 -2
- package/plugins/dsh/skills/test-driven-development/SKILL.md +1 -0
- package/plugins/dsh/skills/test-specification-alignment/AGENTS.md +2 -2
- package/plugins/dsh/skills/test-specification-alignment/SKILL.md +1 -0
- package/plugins/dsh/skills/to-issues/SKILL.md +1 -0
- package/plugins/opencode/package.json +1 -1
- package/plugins/opencode/skills/admin-template-guidelines/SKILL.md +1 -0
- package/plugins/opencode/skills/batch-grill-me/SKILL.md +1 -0
- package/plugins/opencode/skills/clipboard-vision/SKILL.md +1 -0
- package/plugins/opencode/skills/delphi-review/AGENTS.md +2 -2
- package/plugins/opencode/skills/domain-modeling/SKILL.md +1 -0
- package/plugins/opencode/skills/grill-with-docs/SKILL.md +1 -0
- package/plugins/opencode/skills/grilling/SKILL.md +1 -0
- package/plugins/opencode/skills/improve-codebase-architecture/SKILL.md +1 -0
- package/plugins/opencode/skills/ralph-loop/SKILL.md +1 -0
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +2 -2
- package/plugins/opencode/skills/test-driven-development/SKILL.md +1 -0
- package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +2 -2
- package/plugins/opencode/skills/test-specification-alignment/SKILL.md +1 -0
- package/plugins/opencode/skills/to-issues/SKILL.md +1 -0
- package/plugins/qoder/plugin.json +1 -1
- package/plugins/qoder/skills/delphi-review/AGENTS.md +2 -2
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +2 -2
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +2 -2
- package/principles/AGENTS.md +2 -2
- package/principles/adapters/__tests__/java.test.ts +317 -0
- package/principles/adapters/java.ts +325 -13
- package/skills/admin-template-guidelines/SKILL.md +1 -0
- package/skills/batch-grill-me/SKILL.md +1 -0
- package/skills/clipboard-vision/SKILL.md +1 -0
- package/skills/delphi-review/AGENTS.md +2 -2
- package/skills/domain-modeling/SKILL.md +1 -0
- package/skills/grill-with-docs/SKILL.md +1 -0
- package/skills/grilling/SKILL.md +1 -0
- package/skills/improve-codebase-architecture/SKILL.md +1 -0
- package/skills/ralph-loop/SKILL.md +1 -0
- package/skills/sprint-flow/AGENTS.md +2 -2
- package/skills/test-driven-development/SKILL.md +1 -0
- package/skills/test-specification-alignment/AGENTS.md +2 -2
- package/skills/test-specification-alignment/SKILL.md +1 -0
- package/skills/to-issues/SKILL.md +1 -0
|
@@ -1,6 +1,191 @@
|
|
|
1
1
|
import { BaseAdapter } from './base';
|
|
2
2
|
import { Adapter } from '../types';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Structural fields the clean-code rules consume (mirror of the TypeScript
|
|
6
|
+
* adapter's function shape). Before #507 this adapter returned only
|
|
7
|
+
* `{ name, type, modifiers, line, code }`, so every rule reading
|
|
8
|
+
* `startLine`/`length`/`paramCount`/`nestingDepth`/`hasTryCatch`/`ioOperations`
|
|
9
|
+
* silently saw `undefined` and skipped the file -- G4 reported a run over Java
|
|
10
|
+
* with zero effective coverage (#507 S4 audit).
|
|
11
|
+
*/
|
|
12
|
+
interface JavaFunctionInfo {
|
|
13
|
+
name: string;
|
|
14
|
+
type: string;
|
|
15
|
+
modifiers: string[];
|
|
16
|
+
line: number;
|
|
17
|
+
startLine: number;
|
|
18
|
+
/** Body line span, matching the `length` field long-function reads. */
|
|
19
|
+
length: number;
|
|
20
|
+
paramCount: number;
|
|
21
|
+
nestingDepth: number;
|
|
22
|
+
hasTryCatch: boolean;
|
|
23
|
+
ioOperations: string[];
|
|
24
|
+
code: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface JavaImportInfo {
|
|
28
|
+
name: string;
|
|
29
|
+
line: number;
|
|
30
|
+
used: boolean;
|
|
31
|
+
type: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Java-side I/O markers for the missing-error-handling rule. */
|
|
35
|
+
const JAVA_IO_OPERATIONS = [
|
|
36
|
+
'executeQuery',
|
|
37
|
+
'executeUpdate',
|
|
38
|
+
'executeBatch',
|
|
39
|
+
'getConnection',
|
|
40
|
+
'FileInputStream',
|
|
41
|
+
'FileOutputStream',
|
|
42
|
+
'FileReader',
|
|
43
|
+
'FileWriter',
|
|
44
|
+
'BufferedReader',
|
|
45
|
+
'BufferedWriter',
|
|
46
|
+
'Files.',
|
|
47
|
+
'HttpClient',
|
|
48
|
+
'RestTemplate',
|
|
49
|
+
'Socket',
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Numeric literal scan for the magic-numbers rule. Lookahead mirrors the
|
|
54
|
+
* TypeScript adapter (`(?![\w$])`): digits as call arguments (`foo(2)`) are
|
|
55
|
+
* the most common magic-number site and must be reported, so `)` is NOT
|
|
56
|
+
* excluded. A per-call regex comes from `javaParse.magicNumberRegex()`;
|
|
57
|
+
* `String.prototype.match` with the global flag returns all matches per line
|
|
58
|
+
* and ignores lastIndex, so there is no shared-state bug to worry about.
|
|
59
|
+
* Known gaps (documented in docs/java-principles-coverage.md): hex
|
|
60
|
+
* (0xFF), underscore separators (1_000) and literal suffixes (1000L) are
|
|
61
|
+
* not matched.
|
|
62
|
+
*/
|
|
63
|
+
const MAGIC_NUMBER_SOURCE = '(?<![\\w$.])(-?\\d+(?:\\.\\d+)?)(?![\\w$])';
|
|
64
|
+
|
|
65
|
+
const MEMBER_KEYWORDS = new Set([
|
|
66
|
+
'if', 'for', 'while', 'switch', 'catch', 'return', 'synchronized', 'new',
|
|
67
|
+
'super', 'this', 'throw', 'assert', 'try'
|
|
68
|
+
]);
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Pure parse helpers, kept OUTSIDE the adapter class and called through this
|
|
72
|
+
* namespace object. Two reasons, both from the gate dogfooding itself (#507
|
|
73
|
+
* S4): the srp heuristic counts every bare `word(` inside a class body as a
|
|
74
|
+
* method, and dip flags every bare `new X(` as direct instantiation -- dotted
|
|
75
|
+
* namespace calls keep both scanners blind to implementation helpers.
|
|
76
|
+
*/
|
|
77
|
+
export const javaParse = {
|
|
78
|
+
/** Top-level brace depth of a method body (deep-nesting rule). */
|
|
79
|
+
braceDepth(body: string): number {
|
|
80
|
+
let depth = 0;
|
|
81
|
+
let max = 0;
|
|
82
|
+
for (const ch of body) {
|
|
83
|
+
if (ch === '{') {
|
|
84
|
+
depth += 1;
|
|
85
|
+
if (depth > max) max = depth;
|
|
86
|
+
} else if (ch === '}') {
|
|
87
|
+
depth -= 1;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return max;
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
/** Parameter count of a raw parameter list, comma-aware at depth zero. */
|
|
94
|
+
countParams(paramList: string): number {
|
|
95
|
+
const trimmed = paramList.trim();
|
|
96
|
+
if (!trimmed) return 0;
|
|
97
|
+
let depth = 0;
|
|
98
|
+
let count = 1;
|
|
99
|
+
for (const ch of trimmed) {
|
|
100
|
+
if (ch === '(' || ch === '<' || ch === '[') depth += 1;
|
|
101
|
+
else if (ch === ')' || ch === '>' || ch === ']') depth -= 1;
|
|
102
|
+
else if (ch === ',' && depth === 0) count += 1;
|
|
103
|
+
}
|
|
104
|
+
return count;
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Method-like members inside a class/interface body: `name(` occurrences
|
|
109
|
+
* minus control keywords and constructor calls. Mirrors the TypeScript
|
|
110
|
+
* adapter's member heuristic so SRP/god-class see the same signal shape.
|
|
111
|
+
*/
|
|
112
|
+
countMembers(body: string): string[] {
|
|
113
|
+
const memberRe = /(?<![\w$.])(\w+)\s*\(/g;
|
|
114
|
+
const methods: string[] = [];
|
|
115
|
+
let m: RegExpExecArray | null;
|
|
116
|
+
while ((m = memberRe.exec(body)) !== null) {
|
|
117
|
+
const name = m[1];
|
|
118
|
+
if (!MEMBER_KEYWORDS.has(name) && !methods.includes(name)) methods.push(name);
|
|
119
|
+
}
|
|
120
|
+
return methods;
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
magicNumberRegex(): RegExp {
|
|
124
|
+
return new RegExp(MAGIC_NUMBER_SOURCE, 'g');
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Strip string/char literals and comments (line + block, multi-line)
|
|
129
|
+
* before any brace/call-site analysis. Contents become empty/space so the
|
|
130
|
+
* LINE structure (and thus line numbers) is preserved -- column positions
|
|
131
|
+
* shift, so callers must use lineOf() instead of getLineNumber() on masked
|
|
132
|
+
* content. This is what keeps a `"{` inside a format string or a javadoc
|
|
133
|
+
* code example from corrupting nestingDepth/hasTryCatch/methodCount
|
|
134
|
+
* (#507 blind review M3/M4).
|
|
135
|
+
*
|
|
136
|
+
* String/char patterns exclude newlines (#507 Delphi round-1 B-MAJOR-3):
|
|
137
|
+
* a cross-line pairing let one unbalanced quote inside a comment swallow
|
|
138
|
+
* every line up to the NEXT real string, deleting whole control blocks
|
|
139
|
+
* from the analysis. Damage is now bounded to the offending line.
|
|
140
|
+
*/
|
|
141
|
+
maskCode(body: string): string {
|
|
142
|
+
return body
|
|
143
|
+
.replace(/"(?:[^"\\\n]|\\[^\n])*"/g, '""')
|
|
144
|
+
.replace(/'(?:[^'\\\n]|\\[^\n])'/g, "''")
|
|
145
|
+
.replace(/\/\*[\s\S]*?\*\//g, (m) => m.replace(/[^\n]/g, ' '))
|
|
146
|
+
.replace(/\/\/.*$/gm, '');
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Line number of `position` within `content`. maskCode preserves line
|
|
151
|
+
* structure (contents shrink but never add/remove lines), so a line
|
|
152
|
+
* computed on masked content is exact for the original file.
|
|
153
|
+
*/
|
|
154
|
+
lineOf(content: string, position: number): number {
|
|
155
|
+
return content.substring(0, position).split('\n').length;
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Brace-balanced block starting at the first `{` at/after `startPos`.
|
|
160
|
+
* Runs on MASKED content only -- on raw text a string-embedded `{`
|
|
161
|
+
* desynchronizes the depth tracker. Returns null when unbalanced
|
|
162
|
+
* (callers decide the fallback; base.extractCodeBlock's 100-char
|
|
163
|
+
* truncation fallback would silently hand back garbage structure).
|
|
164
|
+
*/
|
|
165
|
+
extractBracedBlock(content: string, startPos: number): string | null {
|
|
166
|
+
let inBlock = false;
|
|
167
|
+
let depth = 0;
|
|
168
|
+
for (let i = startPos; i < content.length; i += 1) {
|
|
169
|
+
const ch = content[i];
|
|
170
|
+
if (ch === '{') {
|
|
171
|
+
inBlock = true;
|
|
172
|
+
depth += 1;
|
|
173
|
+
} else if (ch === '}' && inBlock) {
|
|
174
|
+
depth -= 1;
|
|
175
|
+
if (depth === 0) {
|
|
176
|
+
return content.substring(startPos, i + 1);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
/** Usage detector for an imported simple name (word-boundary, $-escaped). */
|
|
184
|
+
importUsage(simpleName: string): RegExp {
|
|
185
|
+
return new RegExp(`\\b${simpleName.replace(/\$/g, '\\$')}\\b`);
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
|
|
4
189
|
export class JavaAdapter extends BaseAdapter implements Adapter {
|
|
5
190
|
detectLanguage(): string {
|
|
6
191
|
const ext = this.filePath.toLowerCase();
|
|
@@ -19,38 +204,165 @@ export class JavaAdapter extends BaseAdapter implements Adapter {
|
|
|
19
204
|
}
|
|
20
205
|
|
|
21
206
|
extractFunctions(): unknown[] {
|
|
22
|
-
const
|
|
23
|
-
const methodRegex = /(public|private|protected|static|final|synchronized|native)\s+[\w<>[\]]
|
|
207
|
+
const results: JavaFunctionInfo[] = [];
|
|
208
|
+
const methodRegex = /(public|private|protected|static|final|synchronized|native)\s+[\w<>[\],\s]+?\s+(\w+)\s*\(([^)]*)\)\s*(throws\s+[\w,\s.]+)?\s*\{/g;
|
|
209
|
+
// Signature scan AND block extraction run on the MASKED content
|
|
210
|
+
// (#507 Delphi round-1 B-MAJOR-6 / A-minor-1): a javadoc example like
|
|
211
|
+
// `public int foo(int x) {` on raw text produced a ghost function whose
|
|
212
|
+
// length/nestingDepth fed long-function/deep-nesting, and an unbalanced
|
|
213
|
+
// string brace stretched the extracted block past the real method end.
|
|
214
|
+
// Masked content keeps line structure, so lineOf() is exact.
|
|
215
|
+
const maskedContent = javaParse.maskCode(this.fileContent);
|
|
24
216
|
let match;
|
|
25
217
|
|
|
26
|
-
while ((match = methodRegex.exec(
|
|
27
|
-
|
|
218
|
+
while ((match = methodRegex.exec(maskedContent)) !== null) {
|
|
219
|
+
const code = javaParse.extractBracedBlock(maskedContent, match.index) ?? '';
|
|
220
|
+
const line = javaParse.lineOf(maskedContent, match.index);
|
|
221
|
+
const masked = code; // already masked (extracted from maskedContent)
|
|
222
|
+
results.push({
|
|
28
223
|
name: match[2],
|
|
29
224
|
type: 'method',
|
|
30
|
-
modifiers: match[1].split(
|
|
31
|
-
line
|
|
32
|
-
|
|
225
|
+
modifiers: match[1].split(/\s+/).filter(m => m.trim()),
|
|
226
|
+
line,
|
|
227
|
+
startLine: line,
|
|
228
|
+
length: code ? code.split('\n').length : 0,
|
|
229
|
+
paramCount: javaParse.countParams(match[3] ?? ''),
|
|
230
|
+
nestingDepth: javaParse.braceDepth(masked),
|
|
231
|
+
hasTryCatch: /catch\s*\(/.test(masked),
|
|
232
|
+
ioOperations: JAVA_IO_OPERATIONS.filter(op => masked.includes(op)),
|
|
233
|
+
code
|
|
33
234
|
});
|
|
34
235
|
}
|
|
35
236
|
|
|
36
|
-
return
|
|
237
|
+
return results;
|
|
37
238
|
}
|
|
38
239
|
|
|
39
240
|
extractClasses(): unknown[] {
|
|
40
241
|
const classMatches = [];
|
|
41
|
-
|
|
242
|
+
// Generic type parameters -- `class Box<T>`, `class Foo<T> extends Bar<T>` --
|
|
243
|
+
// are the norm in modern Java; without the optional `<...>` slot the
|
|
244
|
+
// whole class vanished from extractClasses and srp/god-class/dip went
|
|
245
|
+
// blind on generic code -- #507 blind review M1.
|
|
246
|
+
const classRegex = /(public|private|protected)?\s*(abstract|final|static)?\s*class\s+(\w+)\s*(?:<[^<>]*>)?\s*(extends\s+[\w.]+(?:<[^<>]*>)?)?\s*(implements\s+[\w,\s.]+(?:<[^<>]*>)?)?\s*\{/g;
|
|
42
247
|
let match;
|
|
43
248
|
|
|
44
|
-
|
|
249
|
+
// Class scan also runs on masked content: a javadoc mention of `class
|
|
250
|
+
// Foo` no longer yields a ghost class, and string-embedded braces cannot
|
|
251
|
+
// stretch the extracted body (#507 Delphi round-1 B-MAJOR-6).
|
|
252
|
+
const maskedContent = javaParse.maskCode(this.fileContent);
|
|
253
|
+
while ((match = classRegex.exec(maskedContent)) !== null) {
|
|
254
|
+
const code = javaParse.extractBracedBlock(maskedContent, match.index) ?? '';
|
|
255
|
+
// srp reads `cls.methodCount` directly, with no code re-scan fallback,
|
|
256
|
+
// so an adapter omitting it makes SRP structurally dead on Java -- #507 S4.
|
|
257
|
+
const methods = javaParse.countMembers(code);
|
|
45
258
|
classMatches.push({
|
|
46
259
|
name: match[3],
|
|
47
260
|
type: 'class',
|
|
48
261
|
modifiers: [match[1], match[2]].filter(m => m && m.trim()),
|
|
49
|
-
line:
|
|
50
|
-
|
|
262
|
+
line: javaParse.lineOf(maskedContent, match.index),
|
|
263
|
+
methodCount: methods.length,
|
|
264
|
+
methods,
|
|
265
|
+
code
|
|
51
266
|
});
|
|
52
267
|
}
|
|
53
268
|
|
|
54
269
|
return classMatches;
|
|
55
270
|
}
|
|
56
|
-
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Interfaces for the ISP rule, which reads `adapter.extractInterfaces()`.
|
|
274
|
+
* Java interface methods are bare signature lines, counted with the same
|
|
275
|
+
* member heuristic as classes minus constructors.
|
|
276
|
+
*/
|
|
277
|
+
extractInterfaces(): Array<{ name: string; line: number; methods: string[]; methodCount: number; code: string }> {
|
|
278
|
+
const results: Array<{ name: string; line: number; methods: string[]; methodCount: number; code: string }> = [];
|
|
279
|
+
const ifaceRegex = /(?:public|private|protected)?\s*interface\s+(\w+)\s*(?:<[^<>]*>)?\s*\{/g;
|
|
280
|
+
let match;
|
|
281
|
+
|
|
282
|
+
// Masked scan, same rationale as extractClasses (#507 Delphi round-1
|
|
283
|
+
// B-MAJOR-6): no ghost interfaces from javadoc, no string-brace bleed.
|
|
284
|
+
const maskedContent = javaParse.maskCode(this.fileContent);
|
|
285
|
+
while ((match = ifaceRegex.exec(maskedContent)) !== null) {
|
|
286
|
+
const code = javaParse.extractBracedBlock(maskedContent, match.index) ?? '';
|
|
287
|
+
const methods = javaParse.countMembers(code);
|
|
288
|
+
results.push({
|
|
289
|
+
name: match[1],
|
|
290
|
+
line: javaParse.lineOf(maskedContent, match.index),
|
|
291
|
+
methods,
|
|
292
|
+
methodCount: methods.length,
|
|
293
|
+
code
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return results;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Numeric literal scan for the magic-numbers rule. Constant declarations
|
|
302
|
+
* (`static final ... = <n>`) are skipped: naming a constant is exactly the
|
|
303
|
+
* remedy the rule asks for. Masking ORDER matters -- #507 blind review M3:
|
|
304
|
+
* string/char literals first, so `"http://x"` cannot swallow the rest of
|
|
305
|
+
* the line as a comment), then line comments, then block comments with
|
|
306
|
+
* cross-line state -- a commented-out code block must not resurrect its
|
|
307
|
+
* numbers as findings.
|
|
308
|
+
*/
|
|
309
|
+
extract(): Array<{ value: number; line: number }> {
|
|
310
|
+
const out: Array<{ value: number; line: number }> = [];
|
|
311
|
+
const lines = this.fileContent.split('\n');
|
|
312
|
+
const numRegex = javaParse.magicNumberRegex();
|
|
313
|
+
let inBlockComment = false;
|
|
314
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
315
|
+
let line = lines[i];
|
|
316
|
+
if (inBlockComment) {
|
|
317
|
+
const end = line.indexOf('*/');
|
|
318
|
+
if (end === -1) continue;
|
|
319
|
+
line = line.slice(end + 2);
|
|
320
|
+
inBlockComment = false;
|
|
321
|
+
}
|
|
322
|
+
line = line
|
|
323
|
+
.replace(/"(?:[^"\\]|\\.)*"/g, '""')
|
|
324
|
+
.replace(/'(?:[^'\\]|\\.)'/g, "''")
|
|
325
|
+
.replace(/\/\/.*$/, '');
|
|
326
|
+
while (line.includes('/*')) {
|
|
327
|
+
const start = line.indexOf('/*');
|
|
328
|
+
const end = line.indexOf('*/', start + 2);
|
|
329
|
+
if (end === -1) {
|
|
330
|
+
line = line.slice(0, start);
|
|
331
|
+
inBlockComment = true;
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
line = line.slice(0, start) + ' ' + line.slice(end + 2);
|
|
335
|
+
}
|
|
336
|
+
if (/^\s*(?:public|private|protected)?\s*static\s+final\s/.test(line)) continue;
|
|
337
|
+
const matches = line.match(numRegex) ?? [];
|
|
338
|
+
for (const value of matches) out.push({ value: Number(value), line: i + 1 });
|
|
339
|
+
}
|
|
340
|
+
return out;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Import statements with a usage signal for the unused-imports rule. Usage
|
|
345
|
+
* is a conservative check: the imported simple name must appear somewhere
|
|
346
|
+
* outside the import block itself.
|
|
347
|
+
*/
|
|
348
|
+
get imports(): JavaImportInfo[] {
|
|
349
|
+
const lines = this.fileContent.split('\n');
|
|
350
|
+
const imports: JavaImportInfo[] = [];
|
|
351
|
+
const importRegex = /^\s*import\s+(?:static\s+)?([\w.]+)\s*;\s*$/;
|
|
352
|
+
const importLines = new Set<number>();
|
|
353
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
354
|
+
const m = importRegex.exec(lines[i]);
|
|
355
|
+
if (m) {
|
|
356
|
+
imports.push({ name: m[1], line: i + 1, used: false, type: 'import' });
|
|
357
|
+
importLines.add(i);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (imports.length === 0) return imports;
|
|
361
|
+
const body = lines.filter((_, idx) => !importLines.has(idx)).join('\n');
|
|
362
|
+
for (const imp of imports) {
|
|
363
|
+
const simpleName = imp.name.split('.').pop() ?? imp.name;
|
|
364
|
+
imp.used = javaParse.importUsage(simpleName).test(body);
|
|
365
|
+
}
|
|
366
|
+
return imports;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: admin-template-guidelines
|
|
3
|
+
version: 1.0.0
|
|
3
4
|
description: "6 maintainability rules for AI-generated admin interfaces (Fastify + Nunjucks + HTMX + Alpine.js). Prevents route bloat, test inconsistency, Nunjucks traps, repeated data logic, auth blind spots, and HTMX/Alpine confusion."
|
|
4
5
|
maturity: alpha
|
|
5
6
|
---
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/DELPHI-REVIEW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
3
|
+
**Generated:** 2026-10-12
|
|
4
4
|
**Commit:** unknown
|
|
5
5
|
**Branch:** unknown
|
|
6
|
-
**Version:** 0.20.
|
|
6
|
+
**Version:** 0.20.2.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Delphi Consensus Review — multi-round anonymous expert review (≥90% threshold, exactly 3 experts with distinct executable model IDs). Supports design, requirements, and code-walkthrough modes.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: domain-modeling
|
|
3
|
+
version: 1.0.0
|
|
3
4
|
description: Build and sharpen a project's domain model. Use when the user wants to pin down domain terminology or a ubiquitous language, record an architectural decision, or when another skill needs to maintain the domain model.
|
|
4
5
|
---
|
|
5
6
|
|
package/skills/grilling/SKILL.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: improve-codebase-architecture
|
|
3
|
+
version: 1.0.0
|
|
3
4
|
description: Find deepening opportunities in a codebase, informed by domain language in CONTEXT.md and decisions in ADRs. Use when user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make a codebase more AI-navigable. Run periodically (weekly or after surges of development).
|
|
4
5
|
---
|
|
5
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/SPRINT-FLOW KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
3
|
+
**Generated:** 2026-10-12
|
|
4
4
|
**Commit:** unknown
|
|
5
5
|
**Branch:** unknown
|
|
6
|
-
**Version:** 0.20.
|
|
6
|
+
**Version:** 0.20.2.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
**6-phase** development pipeline (v2.0 compact redesign, Issue #290): PREP → DESIGN → BUILD → VERIFY → SHIP → CLOSE. Phase 3/6 BUILD default build mode is **ralph-loop** (REQ-level iteration, 40-67% token savings vs parallel). HARD-GATE between DESIGN (2/6) and BUILD (3/6): design must pass Delphi review (≥90% consensus) before any coding.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# SKILLS/TEST-SPECIFICATION-ALIGNMENT KNOWLEDGE BASE
|
|
2
2
|
|
|
3
|
-
**Generated:** 2026-10-
|
|
3
|
+
**Generated:** 2026-10-12
|
|
4
4
|
**Commit:** unknown
|
|
5
5
|
**Branch:** unknown
|
|
6
|
-
**Version:** 0.20.
|
|
6
|
+
**Version:** 0.20.2.0
|
|
7
7
|
|
|
8
8
|
## OVERVIEW
|
|
9
9
|
Test-Specification Alignment Engine — two-stage validation ensuring tests accurately reflect requirements and design specs.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: to-issues
|
|
3
|
+
version: 1.0.0
|
|
3
4
|
description: Break a plan, spec, or PRD into independently-grabbable issues using tracer-bullet vertical slices. Use when user wants to convert a plan into issues, create implementation tickets, or break down work into vertical slices. Integrates with XP-Gate sprint-flow Phase 1.
|
|
4
5
|
---
|
|
5
6
|
|