terminal-smart-cli 0.97.47 → 0.97.48
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/lib/content-quality.js +45 -0
- package/lib/verify.js +8 -1
- package/package.json +1 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs=require('fs');
|
|
3
|
+
const path=require('path');
|
|
4
|
+
|
|
5
|
+
const TEXT_EXT=new Set(['.html','.htm','.css','.js','.mjs','.cjs','.ts','.tsx','.jsx','.json','.md','.txt','.svg','.xml','.yml','.yaml']);
|
|
6
|
+
const SKIP=new Set(['node_modules','.git','.cache','.idea','.vscode','coverage']);
|
|
7
|
+
const MOJIBAKE=[
|
|
8
|
+
{ regex:/\uFFFD/g, label:'caractere de substituição Unicode (�)' },
|
|
9
|
+
{ regex:/Ã[\u0080-\u00BF]/g, label:'UTF-8 interpretado como Latin-1 (Ã…)' },
|
|
10
|
+
{ regex:/Â[\u0080-\u00BF\u00A0]/g, label:'UTF-8 interpretado como Latin-1 (Â…)' },
|
|
11
|
+
{ regex:/â(?:€|€™|€œ|€|€“|€”|€¦)/g, label:'pontuação UTF-8 corrompida (â…)' },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
function inspectText(value,{html=false}={}) {
|
|
15
|
+
const source=String(value || ''); const defects=[];
|
|
16
|
+
for(const item of MOJIBAKE){ const hits=source.match(item.regex); if(hits?.length) defects.push(`${item.label}: ${hits.length} ocorrência(s)`); }
|
|
17
|
+
if(html && /<!doctype html|<html[\s>]/i.test(source)
|
|
18
|
+
&& !/<meta\s+[^>]*charset\s*=\s*["']?utf-8\b/i.test(source)
|
|
19
|
+
&& !/<meta\s+[^>]*http-equiv\s*=\s*["']content-type["'][^>]*charset\s*=\s*["']?utf-8\b/i.test(source)) defects.push('HTML completo sem <meta charset="utf-8">');
|
|
20
|
+
return {ok:defects.length===0,defects};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function scanProject(root,{maxFiles=1500,maxBytes=2*1024*1024}={}) {
|
|
24
|
+
const defects=[]; let scanned=0;
|
|
25
|
+
const walk=dir=>{
|
|
26
|
+
if(scanned>=maxFiles) return;
|
|
27
|
+
let entries=[]; try{entries=fs.readdirSync(dir,{withFileTypes:true});}catch(_){return;}
|
|
28
|
+
for(const entry of entries){
|
|
29
|
+
if(scanned>=maxFiles) break;
|
|
30
|
+
if(entry.isDirectory()){ if(!SKIP.has(entry.name)) walk(path.join(dir,entry.name)); continue; }
|
|
31
|
+
const file=path.join(dir,entry.name); const ext=path.extname(entry.name).toLowerCase();
|
|
32
|
+
if(!TEXT_EXT.has(ext)) continue;
|
|
33
|
+
let stat; try{stat=fs.statSync(file);}catch(_){continue;}
|
|
34
|
+
if(stat.size>maxBytes) continue;
|
|
35
|
+
let source; try{source=fs.readFileSync(file,'utf8');}catch(_){continue;}
|
|
36
|
+
scanned++;
|
|
37
|
+
const result=inspectText(source,{html:ext==='.html'||ext==='.htm'});
|
|
38
|
+
for(const defect of result.defects) defects.push(`${path.relative(root,file)}: ${defect}`);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
walk(path.resolve(root));
|
|
42
|
+
return {ok:defects.length===0,defects,scanned,truncated:scanned>=maxFiles};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports={inspectText,scanProject};
|
package/lib/verify.js
CHANGED
|
@@ -73,6 +73,10 @@ function vPort(c) {
|
|
|
73
73
|
sock.connect(port, host);
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
|
+
function vProjectTextQuality(c,cwd) {
|
|
77
|
+
const result=require('./content-quality').scanProject(cwd,{maxFiles:c.max_files||1500});
|
|
78
|
+
return {ok:result.ok,detail:result.ok ? `${result.scanned} arquivo(s) de texto com UTF-8 íntegro` : `${result.defects.length} problema(s) de codificação`,evidence:result.defects.slice(0,8).join(' | ')};
|
|
79
|
+
}
|
|
76
80
|
|
|
77
81
|
// Analisa a saída de `ldd`: quais libs NÃO resolvem. Separado pra ser testável sem ldd real.
|
|
78
82
|
// "arquivo está no lugar" ≠ "roda": foi o buraco do deploy que só checou `file` (arquitetura).
|
|
@@ -111,6 +115,7 @@ const VERIFIERS = {
|
|
|
111
115
|
http: (c) => vHttp(c),
|
|
112
116
|
port: (c) => vPort(c),
|
|
113
117
|
ldd: (c, cwd, opts) => vLdd(c, cwd, opts),
|
|
118
|
+
project_text_quality: (c,cwd) => vProjectTextQuality(c,cwd),
|
|
114
119
|
};
|
|
115
120
|
const VERIFIER_TYPES = Object.keys(VERIFIERS);
|
|
116
121
|
|
|
@@ -132,6 +137,7 @@ function _labelFor(c) {
|
|
|
132
137
|
case 'http': return (c.method || 'GET') + ' ' + c.url + ' → ' + (c.status || 200);
|
|
133
138
|
case 'port': return 'porta ' + c.port + ' escutando';
|
|
134
139
|
case 'ldd': return 'libs de ' + c.path + ' resolvem' + (c.remote ? ' (VPS)' : '');
|
|
140
|
+
case 'project_text_quality': return 'textos e HTML sem caracteres corrompidos';
|
|
135
141
|
default: return c.type || '?';
|
|
136
142
|
}
|
|
137
143
|
}
|
|
@@ -148,7 +154,7 @@ async function runAll(criteria, opts = {}) {
|
|
|
148
154
|
// ── COMPILADOR de critérios (TaskSpec): o LLM/usuário PROPÕE, o harness VALIDA ────
|
|
149
155
|
// Aceita só tipos conhecidos com os campos obrigatórios preenchidos; descarta o resto
|
|
150
156
|
// (o modelo não impõe critério malformado). Determinístico. Retorna { criteria, dropped }.
|
|
151
|
-
const _REQUIRED = { command: ['cmd'], file_exists: ['path'], file_absent: ['path'], file_contains: ['path', 'text'], http: ['url'], port: ['port'], ldd: ['path'] };
|
|
157
|
+
const _REQUIRED = { command: ['cmd'], file_exists: ['path'], file_absent: ['path'], file_contains: ['path', 'text'], http: ['url'], port: ['port'], ldd: ['path'], project_text_quality:[] };
|
|
152
158
|
function compileCriteria(raw) {
|
|
153
159
|
const list = Array.isArray(raw) ? raw : (raw && Array.isArray(raw.criteria) ? raw.criteria : []);
|
|
154
160
|
const criteria = [], dropped = [];
|
|
@@ -168,6 +174,7 @@ function compileCriteria(raw) {
|
|
|
168
174
|
function deriveFromStack(cwd) {
|
|
169
175
|
let st; try { st = require('./stack').detectStack(cwd); } catch (_) { return []; }
|
|
170
176
|
const out = [];
|
|
177
|
+
out.push({type:'project_text_quality',label:'textos e HTML preservam UTF-8'});
|
|
171
178
|
for (const t of (st.test || [])) { if (/test/i.test(t)) out.push({ type: 'command', cmd: t, exit: 0, label: 'testes passam (' + t + ')' }); }
|
|
172
179
|
return out;
|
|
173
180
|
}
|