@astrasyncai/verification-gateway 3.11.0 → 3.11.1

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.
Files changed (73) hide show
  1. package/dist/adapter-interface/interface.d.mts +1 -1
  2. package/dist/adapter-interface/interface.d.ts +1 -1
  3. package/dist/adapters/express.js +1 -1
  4. package/dist/adapters/express.js.map +1 -1
  5. package/dist/adapters/express.mjs +1 -1
  6. package/dist/adapters/express.mjs.map +1 -1
  7. package/dist/adapters/mcp.js +1 -1
  8. package/dist/adapters/mcp.js.map +1 -1
  9. package/dist/adapters/mcp.mjs +1 -1
  10. package/dist/adapters/mcp.mjs.map +1 -1
  11. package/dist/adapters/nextjs.js +1 -1
  12. package/dist/adapters/nextjs.js.map +1 -1
  13. package/dist/adapters/nextjs.mjs +1 -1
  14. package/dist/adapters/nextjs.mjs.map +1 -1
  15. package/dist/adapters/sdk.js +1 -1
  16. package/dist/adapters/sdk.js.map +1 -1
  17. package/dist/adapters/sdk.mjs +1 -1
  18. package/dist/adapters/sdk.mjs.map +1 -1
  19. package/dist/bin/astrasync-claude-hook.js +63 -19
  20. package/dist/bin/astrasync-codex-hook.js +63 -19
  21. package/dist/bin/astrasync-guard.js +63 -19
  22. package/dist/bin/astrasync.js +63 -19
  23. package/dist/browser/background.js +63 -19
  24. package/dist/browser/background.js.map +1 -1
  25. package/dist/browser/background.mjs +63 -19
  26. package/dist/browser/background.mjs.map +1 -1
  27. package/dist/browser/browser-adapter.d.mts +1 -1
  28. package/dist/browser/browser-adapter.d.ts +1 -1
  29. package/dist/claude-code/claude-code-adapter.d.mts +1 -1
  30. package/dist/claude-code/claude-code-adapter.d.ts +1 -1
  31. package/dist/cli/index.d.mts +1 -1
  32. package/dist/cli/index.d.ts +1 -1
  33. package/dist/codex/index.d.mts +1 -1
  34. package/dist/codex/index.d.ts +1 -1
  35. package/dist/codex/index.js +63 -19
  36. package/dist/codex/index.js.map +1 -1
  37. package/dist/codex/index.mjs +63 -19
  38. package/dist/codex/index.mjs.map +1 -1
  39. package/dist/cursor/cursor-adapter.d.mts +1 -1
  40. package/dist/cursor/cursor-adapter.d.ts +1 -1
  41. package/dist/cursor/extension.d.mts +1 -1
  42. package/dist/cursor/extension.d.ts +1 -1
  43. package/dist/cursor/extension.js +63 -19
  44. package/dist/cursor/extension.js.map +1 -1
  45. package/dist/cursor/extension.mjs +63 -19
  46. package/dist/cursor/extension.mjs.map +1 -1
  47. package/dist/gateway/gateway.d.mts +1 -1
  48. package/dist/gateway/gateway.d.ts +1 -1
  49. package/dist/gateway/gateway.js +63 -19
  50. package/dist/gateway/gateway.js.map +1 -1
  51. package/dist/gateway/gateway.mjs +63 -19
  52. package/dist/gateway/gateway.mjs.map +1 -1
  53. package/dist/git-trigger/git-hooks.d.mts +1 -1
  54. package/dist/git-trigger/git-hooks.d.ts +1 -1
  55. package/dist/index.d.mts +1 -1
  56. package/dist/index.d.ts +1 -1
  57. package/dist/index.js +1 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/index.mjs +1 -1
  60. package/dist/index.mjs.map +1 -1
  61. package/dist/local-evaluator/evaluator.d.mts +10 -1
  62. package/dist/local-evaluator/evaluator.d.ts +10 -1
  63. package/dist/local-evaluator/evaluator.js +20 -9
  64. package/dist/local-evaluator/evaluator.js.map +1 -1
  65. package/dist/local-evaluator/evaluator.mjs +20 -9
  66. package/dist/local-evaluator/evaluator.mjs.map +1 -1
  67. package/dist/{types-C23_uaY8.d.ts → types-DhFPiZ3t.d.ts} +6 -1
  68. package/dist/{types-BV6abBnF.d.mts → types-cQVCMeNV.d.mts} +6 -1
  69. package/dist/verify.js +1 -1
  70. package/dist/verify.js.map +1 -1
  71. package/dist/verify.mjs +1 -1
  72. package/dist/verify.mjs.map +1 -1
  73. package/package.json +1 -1
@@ -149,8 +149,9 @@ function extractBacktickSubstitutions(text, collect) {
149
149
  return kept.join(" ");
150
150
  }
151
151
  function basename(token) {
152
- const slash = token.lastIndexOf("/");
153
- return slash === -1 ? token : token.slice(slash + 1);
152
+ const slash = Math.max(token.lastIndexOf("/"), token.lastIndexOf("\\"));
153
+ const name = slash === -1 ? token : token.slice(slash + 1);
154
+ return name.replace(/\.(exe|cmd|bat|ps1)$/i, "");
154
155
  }
155
156
  function matchSegment(segment, list) {
156
157
  const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
@@ -283,7 +284,9 @@ var LocalEvaluator = class {
283
284
  }
284
285
  return {
285
286
  recommendation: "ALLOW",
286
- reason: "All PDLSS checks passed",
287
+ // "evaluated": dimensions absent from the policy are skipped, not
288
+ // failed — evaluatedDimensions below records which ones ran.
289
+ reason: "All evaluated PDLSS checks passed",
287
290
  evaluatedDimensions: {
288
291
  purpose: true,
289
292
  scope: !!this.policy.scope,
@@ -382,7 +385,7 @@ var LocalEvaluator = class {
382
385
  }
383
386
  }
384
387
  if ((context.purpose === "file.read" || context.purpose === "file.write" || context.purpose === "file.delete") && context.target) {
385
- const targetLower = context.target.toLowerCase();
388
+ const targetLower = context.target.toLowerCase().replace(/\\/g, "/");
386
389
  for (const sensitivePath of SENSITIVE_PATHS) {
387
390
  if (targetLower.includes(sensitivePath.toLowerCase())) {
388
391
  score = Math.max(score, 50);
@@ -411,12 +414,20 @@ var LocalEvaluator = class {
411
414
  matchesAnyPattern(value, patterns) {
412
415
  return patterns.some((pattern) => this.matchGlob(value, pattern));
413
416
  }
414
- /**
415
- * Simple glob pattern matching.
416
- * Supports * (matches any characters including / and spaces) and ? (single char).
417
- * Uses the same approach as the backend's matchGlobPattern.
418
- */
417
+ homePrefix() {
418
+ if (this.cachedHomePrefix !== void 0) return this.cachedHomePrefix;
419
+ const env = typeof process !== "undefined" ? process.env : void 0;
420
+ const home = env?.HOME || env?.USERPROFILE;
421
+ this.cachedHomePrefix = home ? home.replace(/\\/g, "/") : null;
422
+ return this.cachedHomePrefix;
423
+ }
419
424
  matchGlob(value, pattern) {
425
+ value = value.replace(/\\/g, "/");
426
+ pattern = pattern.replace(/\\/g, "/");
427
+ if (pattern === "~" || pattern.startsWith("~/")) {
428
+ const home = this.homePrefix();
429
+ if (home) pattern = home + pattern.slice(1);
430
+ }
420
431
  if (pattern === value) return true;
421
432
  const starCount = (pattern.match(/\*/g) ?? []).length;
422
433
  if (starCount > 8) {
@@ -3689,7 +3700,7 @@ function getTrustLevel(score) {
3689
3700
  }
3690
3701
 
3691
3702
  // src/version.ts
3692
- var SDK_VERSION = "3.11.0";
3703
+ var SDK_VERSION = "3.11.1";
3693
3704
 
3694
3705
  // src/well-known.ts
3695
3706
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -4453,13 +4464,29 @@ var TraceLogger = class {
4453
4464
  */
4454
4465
  logEvaluation(context, decision) {
4455
4466
  if (!this.enabled) return;
4456
- this.write({
4457
- id: this.generateId(),
4458
- timestamp: /* @__PURE__ */ new Date(),
4459
- type: "evaluation",
4460
- context: redactDeep(context),
4461
- decision: redactDeep(decision)
4462
- });
4467
+ let event;
4468
+ try {
4469
+ event = {
4470
+ id: this.generateId(),
4471
+ timestamp: /* @__PURE__ */ new Date(),
4472
+ type: "evaluation",
4473
+ context: redactDeep(context),
4474
+ decision: redactDeep(decision)
4475
+ };
4476
+ } catch (err) {
4477
+ event = {
4478
+ id: this.generateId(),
4479
+ timestamp: /* @__PURE__ */ new Date(),
4480
+ type: "error",
4481
+ metadata: {
4482
+ error: `trace redaction failed: ${err instanceof Error ? err.message : String(err)}`,
4483
+ recommendation: decision.recommendation,
4484
+ purpose: context.purpose,
4485
+ action: context.action
4486
+ }
4487
+ };
4488
+ }
4489
+ this.write(event);
4463
4490
  }
4464
4491
  /**
4465
4492
  * Log a tool call the guard saw but did not govern. One line per skip
@@ -4501,17 +4528,34 @@ var TraceLogger = class {
4501
4528
  });
4502
4529
  }
4503
4530
  write(event) {
4531
+ let line;
4532
+ try {
4533
+ line = JSON.stringify(event) + "\n";
4534
+ } catch {
4535
+ return;
4536
+ }
4504
4537
  try {
4505
4538
  const filePath = this.getCurrentFilePath();
4506
- const line = JSON.stringify(event) + "\n";
4507
4539
  if ((0, import_fs3.existsSync)(filePath)) {
4508
4540
  const stats = (0, import_fs3.statSync)(filePath);
4509
4541
  if (stats.size > MAX_FILE_SIZE) {
4510
4542
  this.rotate();
4511
4543
  }
4512
4544
  }
4513
- (0, import_fs3.appendFileSync)(filePath, line);
4545
+ for (let attempt = 0; attempt < 3; attempt++) {
4546
+ try {
4547
+ (0, import_fs3.appendFileSync)(filePath, line);
4548
+ return;
4549
+ } catch {
4550
+ }
4551
+ }
4552
+ const fallbackPath = filePath.replace(/\.jsonl$/, `-r${process.pid}.jsonl`);
4553
+ (0, import_fs3.appendFileSync)(fallbackPath, line);
4514
4554
  } catch {
4555
+ try {
4556
+ console.error(`[AstraSync TraceLogger] failed to persist trace line: ${line.trim()}`);
4557
+ } catch {
4558
+ }
4515
4559
  }
4516
4560
  }
4517
4561
  getCurrentFilePath() {
@@ -4288,8 +4288,9 @@ function extractBacktickSubstitutions(text, collect) {
4288
4288
  return kept.join(" ");
4289
4289
  }
4290
4290
  function basename(token) {
4291
- const slash = token.lastIndexOf("/");
4292
- return slash === -1 ? token : token.slice(slash + 1);
4291
+ const slash = Math.max(token.lastIndexOf("/"), token.lastIndexOf("\\"));
4292
+ const name = slash === -1 ? token : token.slice(slash + 1);
4293
+ return name.replace(/\.(exe|cmd|bat|ps1)$/i, "");
4293
4294
  }
4294
4295
  function matchSegment(segment, list) {
4295
4296
  const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
@@ -4422,7 +4423,9 @@ var LocalEvaluator = class {
4422
4423
  }
4423
4424
  return {
4424
4425
  recommendation: "ALLOW",
4425
- reason: "All PDLSS checks passed",
4426
+ // "evaluated": dimensions absent from the policy are skipped, not
4427
+ // failed — evaluatedDimensions below records which ones ran.
4428
+ reason: "All evaluated PDLSS checks passed",
4426
4429
  evaluatedDimensions: {
4427
4430
  purpose: true,
4428
4431
  scope: !!this.policy.scope,
@@ -4521,7 +4524,7 @@ var LocalEvaluator = class {
4521
4524
  }
4522
4525
  }
4523
4526
  if ((context.purpose === "file.read" || context.purpose === "file.write" || context.purpose === "file.delete") && context.target) {
4524
- const targetLower = context.target.toLowerCase();
4527
+ const targetLower = context.target.toLowerCase().replace(/\\/g, "/");
4525
4528
  for (const sensitivePath of SENSITIVE_PATHS) {
4526
4529
  if (targetLower.includes(sensitivePath.toLowerCase())) {
4527
4530
  score = Math.max(score, 50);
@@ -4550,12 +4553,20 @@ var LocalEvaluator = class {
4550
4553
  matchesAnyPattern(value, patterns) {
4551
4554
  return patterns.some((pattern) => this.matchGlob(value, pattern));
4552
4555
  }
4553
- /**
4554
- * Simple glob pattern matching.
4555
- * Supports * (matches any characters including / and spaces) and ? (single char).
4556
- * Uses the same approach as the backend's matchGlobPattern.
4557
- */
4556
+ homePrefix() {
4557
+ if (this.cachedHomePrefix !== void 0) return this.cachedHomePrefix;
4558
+ const env = typeof process !== "undefined" ? process.env : void 0;
4559
+ const home = env?.HOME || env?.USERPROFILE;
4560
+ this.cachedHomePrefix = home ? home.replace(/\\/g, "/") : null;
4561
+ return this.cachedHomePrefix;
4562
+ }
4558
4563
  matchGlob(value, pattern) {
4564
+ value = value.replace(/\\/g, "/");
4565
+ pattern = pattern.replace(/\\/g, "/");
4566
+ if (pattern === "~" || pattern.startsWith("~/")) {
4567
+ const home = this.homePrefix();
4568
+ if (home) pattern = home + pattern.slice(1);
4569
+ }
4559
4570
  if (pattern === value) return true;
4560
4571
  const starCount = (pattern.match(/\*/g) ?? []).length;
4561
4572
  if (starCount > 8) {
@@ -4598,7 +4609,7 @@ function getTrustLevel(score) {
4598
4609
  }
4599
4610
 
4600
4611
  // src/version.ts
4601
- var SDK_VERSION = "3.11.0";
4612
+ var SDK_VERSION = "3.11.1";
4602
4613
 
4603
4614
  // src/well-known.ts
4604
4615
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -5362,13 +5373,29 @@ var TraceLogger = class {
5362
5373
  */
5363
5374
  logEvaluation(context, decision) {
5364
5375
  if (!this.enabled) return;
5365
- this.write({
5366
- id: this.generateId(),
5367
- timestamp: /* @__PURE__ */ new Date(),
5368
- type: "evaluation",
5369
- context: redactDeep(context),
5370
- decision: redactDeep(decision)
5371
- });
5376
+ let event;
5377
+ try {
5378
+ event = {
5379
+ id: this.generateId(),
5380
+ timestamp: /* @__PURE__ */ new Date(),
5381
+ type: "evaluation",
5382
+ context: redactDeep(context),
5383
+ decision: redactDeep(decision)
5384
+ };
5385
+ } catch (err) {
5386
+ event = {
5387
+ id: this.generateId(),
5388
+ timestamp: /* @__PURE__ */ new Date(),
5389
+ type: "error",
5390
+ metadata: {
5391
+ error: `trace redaction failed: ${err instanceof Error ? err.message : String(err)}`,
5392
+ recommendation: decision.recommendation,
5393
+ purpose: context.purpose,
5394
+ action: context.action
5395
+ }
5396
+ };
5397
+ }
5398
+ this.write(event);
5372
5399
  }
5373
5400
  /**
5374
5401
  * Log a tool call the guard saw but did not govern. One line per skip
@@ -5410,17 +5437,34 @@ var TraceLogger = class {
5410
5437
  });
5411
5438
  }
5412
5439
  write(event) {
5440
+ let line;
5441
+ try {
5442
+ line = JSON.stringify(event) + "\n";
5443
+ } catch {
5444
+ return;
5445
+ }
5413
5446
  try {
5414
5447
  const filePath = this.getCurrentFilePath();
5415
- const line = JSON.stringify(event) + "\n";
5416
5448
  if ((0, import_fs3.existsSync)(filePath)) {
5417
5449
  const stats = (0, import_fs3.statSync)(filePath);
5418
5450
  if (stats.size > MAX_FILE_SIZE) {
5419
5451
  this.rotate();
5420
5452
  }
5421
5453
  }
5422
- (0, import_fs3.appendFileSync)(filePath, line);
5454
+ for (let attempt = 0; attempt < 3; attempt++) {
5455
+ try {
5456
+ (0, import_fs3.appendFileSync)(filePath, line);
5457
+ return;
5458
+ } catch {
5459
+ }
5460
+ }
5461
+ const fallbackPath = filePath.replace(/\.jsonl$/, `-r${process.pid}.jsonl`);
5462
+ (0, import_fs3.appendFileSync)(fallbackPath, line);
5423
5463
  } catch {
5464
+ try {
5465
+ console.error(`[AstraSync TraceLogger] failed to persist trace line: ${line.trim()}`);
5466
+ } catch {
5467
+ }
5424
5468
  }
5425
5469
  }
5426
5470
  getCurrentFilePath() {
@@ -4628,8 +4628,9 @@ function extractBacktickSubstitutions(text, collect) {
4628
4628
  return kept.join(" ");
4629
4629
  }
4630
4630
  function basename(token) {
4631
- const slash = token.lastIndexOf("/");
4632
- return slash === -1 ? token : token.slice(slash + 1);
4631
+ const slash = Math.max(token.lastIndexOf("/"), token.lastIndexOf("\\"));
4632
+ const name = slash === -1 ? token : token.slice(slash + 1);
4633
+ return name.replace(/\.(exe|cmd|bat|ps1)$/i, "");
4633
4634
  }
4634
4635
  function matchSegment(segment, list) {
4635
4636
  const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
@@ -4795,7 +4796,9 @@ var init_evaluator = __esm({
4795
4796
  }
4796
4797
  return {
4797
4798
  recommendation: "ALLOW",
4798
- reason: "All PDLSS checks passed",
4799
+ // "evaluated": dimensions absent from the policy are skipped, not
4800
+ // failed — evaluatedDimensions below records which ones ran.
4801
+ reason: "All evaluated PDLSS checks passed",
4799
4802
  evaluatedDimensions: {
4800
4803
  purpose: true,
4801
4804
  scope: !!this.policy.scope,
@@ -4894,7 +4897,7 @@ var init_evaluator = __esm({
4894
4897
  }
4895
4898
  }
4896
4899
  if ((context.purpose === "file.read" || context.purpose === "file.write" || context.purpose === "file.delete") && context.target) {
4897
- const targetLower = context.target.toLowerCase();
4900
+ const targetLower = context.target.toLowerCase().replace(/\\/g, "/");
4898
4901
  for (const sensitivePath of SENSITIVE_PATHS) {
4899
4902
  if (targetLower.includes(sensitivePath.toLowerCase())) {
4900
4903
  score = Math.max(score, 50);
@@ -4923,12 +4926,20 @@ var init_evaluator = __esm({
4923
4926
  matchesAnyPattern(value, patterns) {
4924
4927
  return patterns.some((pattern) => this.matchGlob(value, pattern));
4925
4928
  }
4926
- /**
4927
- * Simple glob pattern matching.
4928
- * Supports * (matches any characters including / and spaces) and ? (single char).
4929
- * Uses the same approach as the backend's matchGlobPattern.
4930
- */
4929
+ homePrefix() {
4930
+ if (this.cachedHomePrefix !== void 0) return this.cachedHomePrefix;
4931
+ const env = typeof process !== "undefined" ? process.env : void 0;
4932
+ const home = env?.HOME || env?.USERPROFILE;
4933
+ this.cachedHomePrefix = home ? home.replace(/\\/g, "/") : null;
4934
+ return this.cachedHomePrefix;
4935
+ }
4931
4936
  matchGlob(value, pattern) {
4937
+ value = value.replace(/\\/g, "/");
4938
+ pattern = pattern.replace(/\\/g, "/");
4939
+ if (pattern === "~" || pattern.startsWith("~/")) {
4940
+ const home = this.homePrefix();
4941
+ if (home) pattern = home + pattern.slice(1);
4942
+ }
4932
4943
  if (pattern === value) return true;
4933
4944
  const starCount = (pattern.match(/\*/g) ?? []).length;
4934
4945
  if (starCount > 8) {
@@ -4989,7 +5000,7 @@ var SDK_VERSION;
4989
5000
  var init_version = __esm({
4990
5001
  "src/version.ts"() {
4991
5002
  "use strict";
4992
- SDK_VERSION = "3.11.0";
5003
+ SDK_VERSION = "3.11.1";
4993
5004
  }
4994
5005
  });
4995
5006
 
@@ -6231,13 +6242,29 @@ var init_trace_logger = __esm({
6231
6242
  */
6232
6243
  logEvaluation(context, decision) {
6233
6244
  if (!this.enabled) return;
6234
- this.write({
6235
- id: this.generateId(),
6236
- timestamp: /* @__PURE__ */ new Date(),
6237
- type: "evaluation",
6238
- context: redactDeep(context),
6239
- decision: redactDeep(decision)
6240
- });
6245
+ let event;
6246
+ try {
6247
+ event = {
6248
+ id: this.generateId(),
6249
+ timestamp: /* @__PURE__ */ new Date(),
6250
+ type: "evaluation",
6251
+ context: redactDeep(context),
6252
+ decision: redactDeep(decision)
6253
+ };
6254
+ } catch (err) {
6255
+ event = {
6256
+ id: this.generateId(),
6257
+ timestamp: /* @__PURE__ */ new Date(),
6258
+ type: "error",
6259
+ metadata: {
6260
+ error: `trace redaction failed: ${err instanceof Error ? err.message : String(err)}`,
6261
+ recommendation: decision.recommendation,
6262
+ purpose: context.purpose,
6263
+ action: context.action
6264
+ }
6265
+ };
6266
+ }
6267
+ this.write(event);
6241
6268
  }
6242
6269
  /**
6243
6270
  * Log a tool call the guard saw but did not govern. One line per skip
@@ -6279,17 +6306,34 @@ var init_trace_logger = __esm({
6279
6306
  });
6280
6307
  }
6281
6308
  write(event) {
6309
+ let line;
6310
+ try {
6311
+ line = JSON.stringify(event) + "\n";
6312
+ } catch {
6313
+ return;
6314
+ }
6282
6315
  try {
6283
6316
  const filePath = this.getCurrentFilePath();
6284
- const line = JSON.stringify(event) + "\n";
6285
6317
  if ((0, import_fs3.existsSync)(filePath)) {
6286
6318
  const stats = (0, import_fs3.statSync)(filePath);
6287
6319
  if (stats.size > MAX_FILE_SIZE) {
6288
6320
  this.rotate();
6289
6321
  }
6290
6322
  }
6291
- (0, import_fs3.appendFileSync)(filePath, line);
6323
+ for (let attempt = 0; attempt < 3; attempt++) {
6324
+ try {
6325
+ (0, import_fs3.appendFileSync)(filePath, line);
6326
+ return;
6327
+ } catch {
6328
+ }
6329
+ }
6330
+ const fallbackPath = filePath.replace(/\.jsonl$/, `-r${process.pid}.jsonl`);
6331
+ (0, import_fs3.appendFileSync)(fallbackPath, line);
6292
6332
  } catch {
6333
+ try {
6334
+ console.error(`[AstraSync TraceLogger] failed to persist trace line: ${line.trim()}`);
6335
+ } catch {
6336
+ }
6293
6337
  }
6294
6338
  }
6295
6339
  getCurrentFilePath() {
@@ -387,8 +387,9 @@ function extractBacktickSubstitutions(text, collect) {
387
387
  return kept.join(" ");
388
388
  }
389
389
  function basename(token) {
390
- const slash = token.lastIndexOf("/");
391
- return slash === -1 ? token : token.slice(slash + 1);
390
+ const slash = Math.max(token.lastIndexOf("/"), token.lastIndexOf("\\"));
391
+ const name = slash === -1 ? token : token.slice(slash + 1);
392
+ return name.replace(/\.(exe|cmd|bat|ps1)$/i, "");
392
393
  }
393
394
  function matchSegment(segment, list) {
394
395
  const tokens = segment.split(/\s+/).filter((t) => /[a-z0-9]/.test(t));
@@ -521,7 +522,9 @@ var LocalEvaluator = class {
521
522
  }
522
523
  return {
523
524
  recommendation: "ALLOW",
524
- reason: "All PDLSS checks passed",
525
+ // "evaluated": dimensions absent from the policy are skipped, not
526
+ // failed — evaluatedDimensions below records which ones ran.
527
+ reason: "All evaluated PDLSS checks passed",
525
528
  evaluatedDimensions: {
526
529
  purpose: true,
527
530
  scope: !!this.policy.scope,
@@ -620,7 +623,7 @@ var LocalEvaluator = class {
620
623
  }
621
624
  }
622
625
  if ((context.purpose === "file.read" || context.purpose === "file.write" || context.purpose === "file.delete") && context.target) {
623
- const targetLower = context.target.toLowerCase();
626
+ const targetLower = context.target.toLowerCase().replace(/\\/g, "/");
624
627
  for (const sensitivePath of SENSITIVE_PATHS) {
625
628
  if (targetLower.includes(sensitivePath.toLowerCase())) {
626
629
  score = Math.max(score, 50);
@@ -649,12 +652,20 @@ var LocalEvaluator = class {
649
652
  matchesAnyPattern(value, patterns) {
650
653
  return patterns.some((pattern) => this.matchGlob(value, pattern));
651
654
  }
652
- /**
653
- * Simple glob pattern matching.
654
- * Supports * (matches any characters including / and spaces) and ? (single char).
655
- * Uses the same approach as the backend's matchGlobPattern.
656
- */
655
+ homePrefix() {
656
+ if (this.cachedHomePrefix !== void 0) return this.cachedHomePrefix;
657
+ const env = typeof process !== "undefined" ? process.env : void 0;
658
+ const home = env?.HOME || env?.USERPROFILE;
659
+ this.cachedHomePrefix = home ? home.replace(/\\/g, "/") : null;
660
+ return this.cachedHomePrefix;
661
+ }
657
662
  matchGlob(value, pattern) {
663
+ value = value.replace(/\\/g, "/");
664
+ pattern = pattern.replace(/\\/g, "/");
665
+ if (pattern === "~" || pattern.startsWith("~/")) {
666
+ const home = this.homePrefix();
667
+ if (home) pattern = home + pattern.slice(1);
668
+ }
658
669
  if (pattern === value) return true;
659
670
  const starCount = (pattern.match(/\*/g) ?? []).length;
660
671
  if (starCount > 8) {
@@ -3927,7 +3938,7 @@ function getTrustLevel(score) {
3927
3938
  }
3928
3939
 
3929
3940
  // src/version.ts
3930
- var SDK_VERSION = "3.11.0";
3941
+ var SDK_VERSION = "3.11.1";
3931
3942
 
3932
3943
  // src/well-known.ts
3933
3944
  var CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -4691,13 +4702,29 @@ var TraceLogger = class {
4691
4702
  */
4692
4703
  logEvaluation(context, decision) {
4693
4704
  if (!this.enabled) return;
4694
- this.write({
4695
- id: this.generateId(),
4696
- timestamp: /* @__PURE__ */ new Date(),
4697
- type: "evaluation",
4698
- context: redactDeep(context),
4699
- decision: redactDeep(decision)
4700
- });
4705
+ let event;
4706
+ try {
4707
+ event = {
4708
+ id: this.generateId(),
4709
+ timestamp: /* @__PURE__ */ new Date(),
4710
+ type: "evaluation",
4711
+ context: redactDeep(context),
4712
+ decision: redactDeep(decision)
4713
+ };
4714
+ } catch (err) {
4715
+ event = {
4716
+ id: this.generateId(),
4717
+ timestamp: /* @__PURE__ */ new Date(),
4718
+ type: "error",
4719
+ metadata: {
4720
+ error: `trace redaction failed: ${err instanceof Error ? err.message : String(err)}`,
4721
+ recommendation: decision.recommendation,
4722
+ purpose: context.purpose,
4723
+ action: context.action
4724
+ }
4725
+ };
4726
+ }
4727
+ this.write(event);
4701
4728
  }
4702
4729
  /**
4703
4730
  * Log a tool call the guard saw but did not govern. One line per skip
@@ -4739,17 +4766,34 @@ var TraceLogger = class {
4739
4766
  });
4740
4767
  }
4741
4768
  write(event) {
4769
+ let line;
4770
+ try {
4771
+ line = JSON.stringify(event) + "\n";
4772
+ } catch {
4773
+ return;
4774
+ }
4742
4775
  try {
4743
4776
  const filePath = this.getCurrentFilePath();
4744
- const line = JSON.stringify(event) + "\n";
4745
4777
  if ((0, import_fs3.existsSync)(filePath)) {
4746
4778
  const stats = (0, import_fs3.statSync)(filePath);
4747
4779
  if (stats.size > MAX_FILE_SIZE) {
4748
4780
  this.rotate();
4749
4781
  }
4750
4782
  }
4751
- (0, import_fs3.appendFileSync)(filePath, line);
4783
+ for (let attempt = 0; attempt < 3; attempt++) {
4784
+ try {
4785
+ (0, import_fs3.appendFileSync)(filePath, line);
4786
+ return;
4787
+ } catch {
4788
+ }
4789
+ }
4790
+ const fallbackPath = filePath.replace(/\.jsonl$/, `-r${process.pid}.jsonl`);
4791
+ (0, import_fs3.appendFileSync)(fallbackPath, line);
4752
4792
  } catch {
4793
+ try {
4794
+ console.error(`[AstraSync TraceLogger] failed to persist trace line: ${line.trim()}`);
4795
+ } catch {
4796
+ }
4753
4797
  }
4754
4798
  }
4755
4799
  getCurrentFilePath() {