log-llm-config 1.4.10 → 1.4.12

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
- const immediateVerified = restartCommands.length === 0 &&
290
- !deferredSqlitePending &&
291
- (recheckOk || claudeRecheckStaleAfterImmediateApply);
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);
@@ -101,7 +101,15 @@ function collectDirectoryMetadata(t) {
101
101
  try {
102
102
  const dirStat = statSync(t.path);
103
103
  const glob = t.dir_glob ?? '*';
104
- const newest = findNewestMatchingFile(t.path, glob, 0, METADATA_DIR_SCAN_MAX_DEPTH);
104
+ // A "|"-delimited dir_glob is an ordered priority list: use the newest match of the FIRST
105
+ // glob that matches anything, so e.g. "**/*.jsonl|**/*" prefers a session transcript
106
+ // (events.jsonl) over any other session-state file — even when a non-jsonl file is newer.
107
+ let newest = null;
108
+ for (const g of glob.split('|')) {
109
+ newest = findNewestMatchingFile(t.path, g, 0, METADATA_DIR_SCAN_MAX_DEPTH);
110
+ if (newest)
111
+ break;
112
+ }
105
113
  const bestPath = newest?.path ?? t.path;
106
114
  const bestMtime = newest?.mtime ?? dirStat.mtime;
107
115
  return {
@@ -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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "log-llm-config",
3
- "version": "1.4.10",
3
+ "version": "1.4.12",
4
4
  "description": "CLI helpers for logging hardware UUIDs and posting startup payloads to Optimus Security.",
5
5
  "type": "module",
6
6
  "bin": {