chore: update vendored skills and record provenance
humanizer 2.2.0 -> 2.9.1 (blader/humanizer, MIT): adds a Voice Calibration section and a passive-voice pattern, reworks negative parallelisms and em dashes. Version moved to metadata.version upstream. impeccable 3.6.0 -> 4.0.4 (pbakaus/impeccable, Apache-2.0): the repo tags the skill and the npm CLI separately, so 3.6.0 was a real release and npm's 3.5.0 was never the comparison. Adds native-platform reference briefs. Each now carries an UPSTREAM file; bin/check-vendored.sh reports drift.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
import {
|
||||
@@ -18,14 +19,20 @@ import {
|
||||
EDIT_COUNT_THRESHOLD,
|
||||
GENERATED_PATH,
|
||||
SENSITIVE_PATH,
|
||||
appendDesignSystemNote,
|
||||
designSystemOptions,
|
||||
filterFindings,
|
||||
isNativePlatform,
|
||||
loadDetector,
|
||||
matchConfiguredExtension,
|
||||
matchesAnyGlob,
|
||||
persistCache,
|
||||
readCache,
|
||||
readConfig,
|
||||
renderTemplate,
|
||||
resolveCacheCwd,
|
||||
resolveProjectCwd,
|
||||
resolveProjectPlatform,
|
||||
truthy,
|
||||
writeAuditLog,
|
||||
} from './hook-lib.mjs';
|
||||
@@ -330,6 +337,22 @@ function isInsideProject(filePath, cwd) {
|
||||
}
|
||||
}
|
||||
|
||||
// The static HTML engine reads its input from disk, but preToolUse only has
|
||||
// the proposed content. Stage it in a temp file so html-engine targets get the
|
||||
// same DOM-structural rules pre-write that runHook applies post-edit.
|
||||
async function detectProposedHtml(detector, content, filePath, scanOptions) {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'impeccable-pre-'));
|
||||
const tmpFile = path.join(dir, path.basename(filePath));
|
||||
try {
|
||||
fs.writeFileSync(tmpFile, content);
|
||||
const findings = await detector.detectHtml(tmpFile, scanOptions);
|
||||
// Findings carry the temp path; remap so file-scoped ignores still match.
|
||||
return (findings || []).map((f) => (f && typeof f === 'object' ? { ...f, file: filePath } : f));
|
||||
} finally {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
function cursorBlockMessage(findings, filePath, config, cwd) {
|
||||
const rendered = renderTemplate(findings, filePath, config, { cwd });
|
||||
const blocked = rendered.replace(
|
||||
@@ -377,9 +400,12 @@ async function main() {
|
||||
return allow({ skipped: 'stdin-empty' });
|
||||
}
|
||||
|
||||
const cwd = resolveProjectCwd(event);
|
||||
const sessionCwd = resolveProjectCwd(event);
|
||||
const started = Date.now();
|
||||
const filePath = proposedFilePath(event, cwd);
|
||||
const filePath = proposedFilePath(event, sessionCwd);
|
||||
// Re-key config/cache to the edited file's project root when the session
|
||||
// was launched from a non-project umbrella directory (issue #305).
|
||||
const cwd = resolveCacheCwd(filePath, sessionCwd);
|
||||
const audit = {
|
||||
harness: 'cursor',
|
||||
cwd,
|
||||
@@ -392,9 +418,13 @@ async function main() {
|
||||
if (SENSITIVE_PATH.test(filePath)) return allow({ ...audit, skipped: 'sensitive', durationMs: Date.now() - started });
|
||||
if (GENERATED_PATH.test(filePath)) return allow({ ...audit, skipped: 'generated', durationMs: Date.now() - started });
|
||||
|
||||
// Config is read before the extension gate so `detector.extensions` entries
|
||||
// (e.g. `.blade.php` template files, issue #316) can widen it.
|
||||
const config = readConfig(cwd);
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
audit.ext = ext;
|
||||
if (!ALLOWED_EXTS.has(ext)) return allow({ ...audit, skipped: 'extension', durationMs: Date.now() - started });
|
||||
const configuredExt = matchConfiguredExtension(filePath, config.extensions);
|
||||
audit.ext = configuredExt ? configuredExt.ext : ext;
|
||||
if (!ALLOWED_EXTS.has(ext) && !configuredExt) return allow({ ...audit, skipped: 'extension', durationMs: Date.now() - started });
|
||||
|
||||
const contentResult = proposedContent(event, cwd, filePath);
|
||||
if (contentResult && typeof contentResult === 'object' && contentResult.skipped) {
|
||||
@@ -403,9 +433,14 @@ async function main() {
|
||||
const content = typeof contentResult === 'string' ? contentResult : '';
|
||||
if (!content) return allow({ ...audit, skipped: 'no-proposed-content', durationMs: Date.now() - started });
|
||||
|
||||
const config = readConfig(cwd);
|
||||
if (config.enabled === false) return allow({ ...audit, skipped: 'config-disabled', durationMs: Date.now() - started });
|
||||
|
||||
// Web rule engine, native project: stand aside (see resolveProjectPlatform).
|
||||
const platform = resolveProjectPlatform(cwd);
|
||||
if (isNativePlatform(platform)) {
|
||||
return allow({ ...audit, skipped: 'native-platform', platform, durationMs: Date.now() - started });
|
||||
}
|
||||
|
||||
const rel = relativePath(filePath, cwd);
|
||||
if (matchesAnyGlob(rel, config.ignoreFiles) || matchesAnyGlob(filePath, config.ignoreFiles)) {
|
||||
return allow({ ...audit, skipped: 'config-ignore-file', durationMs: Date.now() - started });
|
||||
@@ -415,10 +450,18 @@ async function main() {
|
||||
if (!detector || typeof detector.detectText !== 'function') {
|
||||
return allow({ ...audit, skipped: 'detector-missing', durationMs: Date.now() - started });
|
||||
}
|
||||
const scanOptions = designSystemOptions(config, detector, cwd);
|
||||
|
||||
// Mirror runHook's engine routing so template issues the HTML engine catches
|
||||
// post-edit cannot slip past the pre-write gate.
|
||||
const useHtmlEngine = configuredExt
|
||||
? configuredExt.engine === 'html'
|
||||
: (ext === '.html' || ext === '.htm');
|
||||
let findings = [];
|
||||
try {
|
||||
findings = await detector.detectText(content, filePath);
|
||||
findings = useHtmlEngine && typeof detector.detectHtml === 'function'
|
||||
? await detectProposedHtml(detector, content, filePath, scanOptions)
|
||||
: await detector.detectText(content, filePath, scanOptions);
|
||||
} catch {
|
||||
return allow({ ...audit, error: 'detector-threw', durationMs: Date.now() - started });
|
||||
}
|
||||
@@ -433,7 +476,7 @@ async function main() {
|
||||
});
|
||||
}
|
||||
|
||||
const message = cursorBlockMessage(filtered, filePath, config, cwd);
|
||||
const message = appendDesignSystemNote(cursorBlockMessage(filtered, filePath, config, cwd), scanOptions);
|
||||
const sessionId = event.session_id || event.conversation_id || 'unknown';
|
||||
const cache = readCache(cwd);
|
||||
const denial = bumpCursorDenial(cache, sessionId, filePath, filtered);
|
||||
|
||||
Reference in New Issue
Block a user