log-llm-config 1.4.10 → 1.4.11
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.
|
@@ -286,9 +286,16 @@ export async function runCompliancePromptGate() {
|
|
|
286
286
|
hookRunLog(`compliance_prompt_gate: ${ide} — autofix wrote JSON; recheck still flags same UUID(s) — proceeding (immediate apply)`);
|
|
287
287
|
}
|
|
288
288
|
if (deferredSqlitePending || recheckOk || claudeRecheckStaleAfterImmediateApply) {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
289
|
+
// Immediate-JSON agents (Claude / Claude Desktop, Copilot, OpenCode) write the config file to
|
|
290
|
+
// disk synchronously; a restart_command, if present, only reloads the already-compliant file
|
|
291
|
+
// into the running app — it is not the mechanism that makes the fix take effect. So report
|
|
292
|
+
// "verified" now instead of leaving the finding "pending" in the UI until the next prompt.
|
|
293
|
+
// Cursor's restart can carry a deferred state.vscdb write that only lands post-restart, so
|
|
294
|
+
// Cursor still verifies inline only when no restart is pending.
|
|
295
|
+
const immediateJsonAgent = ide === 'claude' || ide === 'copilot' || ide === 'opencode';
|
|
296
|
+
const immediateVerified = !deferredSqlitePending &&
|
|
297
|
+
(recheckOk || claudeRecheckStaleAfterImmediateApply) &&
|
|
298
|
+
(restartCommands.length === 0 || immediateJsonAgent);
|
|
292
299
|
if (immediateVerified) {
|
|
293
300
|
confirmAppliedAutofixVerified(appliedViolations, reportPromises);
|
|
294
301
|
await Promise.allSettled(reportPromises);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ItemTable key metadata from backend file_path_registry (vscdb_read_queries), cached in
|
|
3
|
+
* file_collection_vscdb_contract.json — no hardcoded Cursor paths in compliance/remediation.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileCollectionVscdbContract } from '../runtime/management_storage.js';
|
|
6
|
+
function sanitizeItemTableKey(raw) {
|
|
7
|
+
if (typeof raw !== 'string')
|
|
8
|
+
return undefined;
|
|
9
|
+
const trimmed = raw.trim();
|
|
10
|
+
if (!trimmed || trimmed.length > 512 || /['"\\]/.test(trimmed))
|
|
11
|
+
return undefined;
|
|
12
|
+
return trimmed;
|
|
13
|
+
}
|
|
14
|
+
function sanitizeStateKey(raw) {
|
|
15
|
+
if (typeof raw !== 'string')
|
|
16
|
+
return undefined;
|
|
17
|
+
const trimmed = raw.trim();
|
|
18
|
+
if (!trimmed || trimmed.length > 256)
|
|
19
|
+
return undefined;
|
|
20
|
+
return trimmed;
|
|
21
|
+
}
|
|
22
|
+
export function itemTableKeyToStateKeyFromReadQueries(queries) {
|
|
23
|
+
const out = {};
|
|
24
|
+
if (!queries?.length)
|
|
25
|
+
return out;
|
|
26
|
+
for (const step of queries) {
|
|
27
|
+
const stateKey = sanitizeStateKey(step.state_key);
|
|
28
|
+
if (!stateKey)
|
|
29
|
+
continue;
|
|
30
|
+
for (const rawKey of step.item_table_keys ?? []) {
|
|
31
|
+
const key = sanitizeItemTableKey(rawKey);
|
|
32
|
+
if (key)
|
|
33
|
+
out[key] = stateKey;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
/** Boolean ItemTable rows: field name under `${itemKey}.${field}` for compliance paths. */
|
|
39
|
+
export function scalarItemTableFieldByItemKeyFromReadQueries(queries) {
|
|
40
|
+
const out = {};
|
|
41
|
+
if (!queries?.length)
|
|
42
|
+
return out;
|
|
43
|
+
for (const step of queries) {
|
|
44
|
+
if (step.value_kind !== 'boolean')
|
|
45
|
+
continue;
|
|
46
|
+
const stateKey = sanitizeStateKey(step.state_key);
|
|
47
|
+
if (!stateKey)
|
|
48
|
+
continue;
|
|
49
|
+
for (const rawKey of step.item_table_keys ?? []) {
|
|
50
|
+
const key = sanitizeItemTableKey(rawKey);
|
|
51
|
+
if (key)
|
|
52
|
+
out[key] = stateKey;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
export function scalarItemTableFieldForKey(itemKey) {
|
|
58
|
+
const key = sanitizeItemTableKey(itemKey);
|
|
59
|
+
if (!key)
|
|
60
|
+
return undefined;
|
|
61
|
+
const contract = readFileCollectionVscdbContract();
|
|
62
|
+
const map = contract?.scalar_item_table_field_by_item_key;
|
|
63
|
+
const field = map?.[key];
|
|
64
|
+
if (typeof field === 'string' && field.trim())
|
|
65
|
+
return field.trim();
|
|
66
|
+
// Older cached contracts may omit scalar map; state_key from registry matches compliance field names.
|
|
67
|
+
const stateKey = contract?.item_table_key_to_state_key?.[key];
|
|
68
|
+
return typeof stateKey === 'string' && stateKey.trim() ? stateKey.trim() : undefined;
|
|
69
|
+
}
|
|
70
|
+
/** Separate registry rows (different state_key) — do not remap compliance paths onto manifest # key. */
|
|
71
|
+
export function itemTableKeysAreDistinctStateRows(applyKey, verifyKey) {
|
|
72
|
+
const a = sanitizeItemTableKey(applyKey);
|
|
73
|
+
const b = sanitizeItemTableKey(verifyKey);
|
|
74
|
+
if (!a || !b)
|
|
75
|
+
return false;
|
|
76
|
+
const map = readFileCollectionVscdbContract()?.item_table_key_to_state_key;
|
|
77
|
+
if (!map)
|
|
78
|
+
return false;
|
|
79
|
+
const stateA = map[a];
|
|
80
|
+
const stateB = map[b];
|
|
81
|
+
return typeof stateA === 'string' && typeof stateB === 'string' && stateA !== stateB;
|
|
82
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Runs after Cursor reopens: delayed compliance verify, then deferred config uploads if verified.
|
|
3
|
+
import { runPostApplyVerification } from './log_config_files/runtime/compliance_check.js';
|
|
4
|
+
import { hookRunLog } from './log_config_files/runtime/hook_logger.js';
|
|
5
|
+
import { clearDeferredPostApplyUploads, delayMs, POST_RESTART_VERIFY_DELAY_MS, runDeferredPostApplyUploadsFromSidecar, } from './log_config_files/runtime/remediation_sync.js';
|
|
6
|
+
import { finalizeAndUploadComplianceSessionLog, setActiveComplianceLogPath, } from './log_config_files/runtime/compliance_session_log.js';
|
|
7
|
+
import { isThisCliModule } from './cli_invocation_match.js';
|
|
8
|
+
const complianceLogPath = process.env.OPTIMUS_COMPLIANCE_LOG?.trim() || null;
|
|
9
|
+
if (complianceLogPath) {
|
|
10
|
+
setActiveComplianceLogPath(complianceLogPath);
|
|
11
|
+
}
|
|
12
|
+
export async function runPostRestartVerify() {
|
|
13
|
+
hookRunLog(`post_restart_verify: sleeping ${POST_RESTART_VERIFY_DELAY_MS}ms before verify`);
|
|
14
|
+
await delayMs(POST_RESTART_VERIFY_DELAY_MS);
|
|
15
|
+
const outcomes = await runPostApplyVerification();
|
|
16
|
+
if (outcomes.length > 0) {
|
|
17
|
+
hookRunLog(`post_restart_verify: outcomes count=${outcomes.length} verified=${outcomes.filter((o) => o.status === 'verified').length}`);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
hookRunLog('post_restart_verify: no pending post-restart verifications');
|
|
21
|
+
clearDeferredPostApplyUploads();
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
const allVerified = outcomes.every((o) => o.status === 'verified');
|
|
25
|
+
if (allVerified) {
|
|
26
|
+
await runDeferredPostApplyUploadsFromSidecar();
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
clearDeferredPostApplyUploads();
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (isThisCliModule(process.argv[1], import.meta.url)) {
|
|
33
|
+
runPostRestartVerify()
|
|
34
|
+
.then(async (ok) => {
|
|
35
|
+
if (complianceLogPath) {
|
|
36
|
+
await finalizeAndUploadComplianceSessionLog(complianceLogPath, ok ? 'success' : 'error');
|
|
37
|
+
}
|
|
38
|
+
process.exit(ok ? 0 : 1);
|
|
39
|
+
})
|
|
40
|
+
.catch(async (e) => {
|
|
41
|
+
hookRunLog(`post_restart_verify: error: ${e instanceof Error ? e.message : String(e)}`);
|
|
42
|
+
clearDeferredPostApplyUploads();
|
|
43
|
+
if (complianceLogPath) {
|
|
44
|
+
await finalizeAndUploadComplianceSessionLog(complianceLogPath, 'error');
|
|
45
|
+
}
|
|
46
|
+
process.exit(1);
|
|
47
|
+
});
|
|
48
|
+
}
|