@aliou/pi-guardrails 0.13.0 → 0.13.2

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.
@@ -441,13 +441,15 @@ export function registerGuardrailsSettings(
441
441
 
442
442
  if (scope === "global") {
443
443
  featureItems.push({
444
- id: "onboarding.run",
444
+ id: "onboarding.completed",
445
445
  label: "Onboarding status",
446
- description: "Use /guardrails:onboarding to run onboarding",
446
+ description:
447
+ "Reset to pending to re-run onboarding (takes effect after reload)",
447
448
  currentValue:
448
449
  scopedConfig.onboarding?.completed === true
449
450
  ? "completed"
450
451
  : "pending",
452
+ values: ["completed", "pending"],
451
453
  });
452
454
  }
453
455
 
@@ -592,5 +594,43 @@ export function registerGuardrailsSettings(
592
594
  },
593
595
  ];
594
596
  },
597
+
598
+ onSettingChange: (id, newValue, config) => {
599
+ const updated = structuredClone(config);
600
+
601
+ if (id.startsWith("features.")) {
602
+ const featureKey = id.slice("features.".length);
603
+ updated.features = {
604
+ ...updated.features,
605
+ [featureKey]: newValue === "enabled",
606
+ };
607
+ return updated;
608
+ }
609
+
610
+ if (id === "permissionGate.requireConfirmation") {
611
+ updated.permissionGate = {
612
+ ...updated.permissionGate,
613
+ requireConfirmation: newValue === "on",
614
+ };
615
+ return updated;
616
+ }
617
+
618
+ if (id === "onboarding.completed") {
619
+ updated.onboarding = {
620
+ ...updated.onboarding,
621
+ completed: newValue === "completed",
622
+ completedAt:
623
+ newValue === "completed"
624
+ ? (updated.onboarding?.completedAt ?? new Date().toISOString())
625
+ : undefined,
626
+ version:
627
+ newValue === "completed" ? updated.onboarding?.version : undefined,
628
+ };
629
+ return updated;
630
+ }
631
+
632
+ // Fall through to default string storage for enums (pathAccess.mode, etc.)
633
+ return null;
634
+ },
595
635
  });
596
636
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliou/pi-guardrails",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "private": false,
@@ -39,8 +39,8 @@
39
39
  "@aliou/sh": "^0.1.0"
40
40
  },
41
41
  "peerDependencies": {
42
- "@earendil-works/pi-coding-agent": "0.74.0",
43
- "@earendil-works/pi-tui": "0.74.0"
42
+ "@earendil-works/pi-coding-agent": "*",
43
+ "@earendil-works/pi-tui": "*"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@aliou/biome-plugins": "^0.8.1",
@@ -0,0 +1,57 @@
1
+ import { addPendingWarning } from "../../warnings";
2
+ import type { GuardrailsConfig } from "../types";
3
+ import { CURRENT_VERSION } from "./version";
4
+
5
+ export function shouldRun(config: GuardrailsConfig): boolean {
6
+ const features = config.features as Record<string, unknown> | undefined;
7
+ if (features) {
8
+ for (const value of Object.values(features)) {
9
+ if (value === "enabled" || value === "disabled") return true;
10
+ }
11
+ }
12
+
13
+ const requiresConfirmation = config.permissionGate
14
+ ?.requireConfirmation as unknown;
15
+ if (requiresConfirmation === "on" || requiresConfirmation === "off") {
16
+ return true;
17
+ }
18
+
19
+ return false;
20
+ }
21
+
22
+ export function run(config: GuardrailsConfig): GuardrailsConfig {
23
+ const migrated = structuredClone(config) as Record<string, unknown>;
24
+ let changed = false;
25
+
26
+ const features = migrated.features as Record<string, unknown> | undefined;
27
+ if (features) {
28
+ for (const [key, value] of Object.entries(features)) {
29
+ if (value === "enabled" || value === "disabled") {
30
+ features[key] = value === "enabled";
31
+ changed = true;
32
+ }
33
+ }
34
+ }
35
+
36
+ const permissionGate = migrated.permissionGate as
37
+ | Record<string, unknown>
38
+ | undefined;
39
+ if (
40
+ permissionGate &&
41
+ (permissionGate.requireConfirmation === "on" ||
42
+ permissionGate.requireConfirmation === "off")
43
+ ) {
44
+ permissionGate.requireConfirmation =
45
+ permissionGate.requireConfirmation === "on";
46
+ changed = true;
47
+ }
48
+
49
+ if (changed) {
50
+ migrated.version = CURRENT_VERSION;
51
+ addPendingWarning(
52
+ "[guardrails] Config migrated: boolean settings stored as strings were converted to true/false.",
53
+ );
54
+ }
55
+
56
+ return migrated as GuardrailsConfig;
57
+ }
@@ -7,6 +7,7 @@ import * as envFilesToPolicies from "./004-env-files-to-policies";
7
7
  import * as normalizeAllowedPaths from "./005-normalize-allowed-paths";
8
8
  import * as applyBuiltinDefaults from "./006-apply-builtin-defaults";
9
9
  import * as markOnboardingDone from "./007-mark-onboarding-done";
10
+ import * as normalizeStringBooleans from "./008-normalize-string-booleans";
10
11
 
11
12
  export { CURRENT_VERSION } from "./version";
12
13
 
@@ -36,6 +37,11 @@ export const migrations: Migration<GuardrailsConfig>[] = [
36
37
  shouldRun: normalizeAllowedPaths.shouldRun,
37
38
  run: normalizeAllowedPaths.run,
38
39
  },
40
+ {
41
+ name: "normalize-string-booleans",
42
+ shouldRun: normalizeStringBooleans.shouldRun,
43
+ run: normalizeStringBooleans.run,
44
+ },
39
45
  ];
40
46
 
41
47
  export const globalConfigMigrations = [