@nklisch/pi-enhanced 0.1.6 → 0.1.7

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.1.7
4
+
5
+ ### Changed
6
+
7
+ - Rebundle `@nklisch/pi-clearance` v0.2.3 so confirmed mode and settings changes update the active-session footer immediately instead of waiting for another tool call or restart.
8
+ - Rebundle `@nklisch/pi-model-modes` v0.3.2 so global mode persistence is visible in autocomplete and the bare `/mode` panel.
9
+
3
10
  ## v0.1.6
4
11
 
5
12
  ### Changed
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nklisch/pi-clearance",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Configurable auto-reviewer Pi extension for parsed, structural command policy",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -131,6 +131,7 @@ const piAutoApprove: ExtensionFactory = (pi: ExtensionAPI) => {
131
131
  recentDecisionSource,
132
132
  analyzerRegistry,
133
133
  toolMetadata: () => toolMetadata(pi),
134
+ refreshOperatorStatus: (ctx, policy) => operatorStatus.refresh(ctx, policy),
134
135
  });
135
136
  registerProposalTools(
136
137
  pi,
@@ -138,6 +139,7 @@ const piAutoApprove: ExtensionFactory = (pi: ExtensionAPI) => {
138
139
  policyResolver,
139
140
  packageRegistration: packageRegistration.snapshot,
140
141
  audit,
142
+ refreshOperatorStatus: (ctx, policy) => operatorStatus.refresh(ctx, policy),
141
143
  },
142
144
  proposalBatchCache,
143
145
  );
@@ -147,6 +149,7 @@ const piAutoApprove: ExtensionFactory = (pi: ExtensionAPI) => {
147
149
  policyResolver,
148
150
  packageRegistration: packageRegistration.snapshot,
149
151
  audit,
152
+ refreshOperatorStatus: (ctx, policy) => operatorStatus.refresh(ctx, policy),
150
153
  },
151
154
  proposalBatchCache,
152
155
  );
@@ -42,6 +42,7 @@ import {
42
42
  completion,
43
43
  filterCompletions,
44
44
  resolvePolicyReport,
45
+ refreshOperatorStatus,
45
46
  stableUnique,
46
47
  usageReport,
47
48
  } from "./types.ts";
@@ -319,6 +320,7 @@ export async function handlePackMutationCommand(input: {
319
320
  }
320
321
 
321
322
  const refreshed = await resolvePolicyReport(ctx, deps);
323
+ if (refreshed.ok) refreshOperatorStatus(ctx, deps, refreshed.policy);
322
324
  const effectivePack = refreshed.ok
323
325
  ? getAutoReviewerPack(refreshed.policy, packId)?.pack
324
326
  : undefined;
@@ -31,6 +31,7 @@ import {
31
31
  completion,
32
32
  filterCompletions,
33
33
  resolvePolicyReport,
34
+ refreshOperatorStatus,
34
35
  stableUnique,
35
36
  usageReport,
36
37
  } from "./types.ts";
@@ -212,6 +213,7 @@ export async function handleScopeCommand(
212
213
  }
213
214
 
214
215
  const refreshed = await resolvePolicyReport(ctx, deps);
216
+ if (refreshed.ok) refreshOperatorStatus(ctx, deps, refreshed.policy);
215
217
  const status = refreshed.ok
216
218
  ? scopeStatusFromConfig(refreshed.policy.config)
217
219
  : undefined;
@@ -37,6 +37,7 @@ import {
37
37
  type AutoReviewerCommandDependencies,
38
38
  type CommandReport,
39
39
  resolvePolicyReport,
40
+ refreshOperatorStatus,
40
41
  stableUnique,
41
42
  } from "../types.ts";
42
43
  import {
@@ -219,6 +220,12 @@ export async function dispatchSettingsAction(
219
220
  }
220
221
 
221
222
  const refreshed = await resolvePolicyReport(ctx, deps);
223
+ if (refreshed.ok) {
224
+ // Config writes and policy-cache invalidation are complete at this point;
225
+ // publish the same resolved policy immediately instead of waiting for the
226
+ // next tool call or session restart to refresh the footer projection.
227
+ refreshOperatorStatus(ctx, deps, refreshed.policy);
228
+ }
222
229
  const warnings = stableUnique([
223
230
  ...planned.plan.warnings.map((warning) => warning.message),
224
231
  ...apply.warnings,
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  ExtensionAPI,
3
3
  ExtensionCommandContext,
4
+ ExtensionContext,
4
5
  } from "@earendil-works/pi-coding-agent";
5
6
 
6
7
  import type { AuditLogger } from "../../audit/logger.ts";
@@ -33,6 +34,11 @@ export interface AutoReviewerCommandDependencies {
33
34
  readonly recentDecisionSource: RecentDecisionSource;
34
35
  /** Structural analyzer used only to summarize the recent command for the agent. */
35
36
  readonly analyzerRegistry: ToolAnalyzerRegistry;
37
+ /** Refresh the active-session footer after a confirmed config write resolves. */
38
+ readonly refreshOperatorStatus?: (
39
+ ctx: ExtensionContext,
40
+ policy: ResolvedPolicy,
41
+ ) => void;
36
42
  }
37
43
 
38
44
  export interface CommandReport<TDetails = unknown> {
@@ -78,6 +84,19 @@ export const USAGE_MARKDOWN = [
78
84
  "Reviewer prompt posture and model pinning are available as confirm-backed settings selectors; context mode, token budget, escalation, and other advanced fields are edited in user-owned global config.",
79
85
  ].join("\n");
80
86
 
87
+ export function refreshOperatorStatus(
88
+ ctx: ExtensionContext,
89
+ deps: Pick<AutoReviewerCommandDependencies, "refreshOperatorStatus">,
90
+ policy: ResolvedPolicy,
91
+ ): void {
92
+ try {
93
+ deps.refreshOperatorStatus?.(ctx, policy);
94
+ } catch {
95
+ // Footer visibility is advisory and must never turn an applied config write
96
+ // into a reported failure or trigger rollback after durable validation.
97
+ }
98
+ }
99
+
81
100
  export async function resolvePolicyForCommand(
82
101
  ctx: ExtensionCommandContext,
83
102
  deps: Pick<AutoReviewerCommandDependencies, "policyResolver">,
@@ -31,6 +31,7 @@ import {
31
31
  type RatchetProposalWritePlanResult,
32
32
  } from "../../replay/proposal-write-plan.ts";
33
33
  import { checkAgainstFloor } from "../../replay/proposals.ts";
34
+ import { refreshOperatorStatus } from "../config-commands/types.ts";
34
35
  import {
35
36
  composeConfigCommandPostWritePolicy,
36
37
  createExtensionContextConfigCommandWriterDependencies,
@@ -558,6 +559,15 @@ export async function applyAcceptedWritableProposal(input: {
558
559
  ? {}
559
560
  : { transactionReplay: replayRecorder.result }),
560
561
  });
562
+ if (apply.status === "applied" && apply.changed === true) {
563
+ try {
564
+ const refreshed = await resolveRatchetPolicy(input.ctx, input.deps);
565
+ refreshOperatorStatus(input.ctx, input.deps, refreshed);
566
+ } catch {
567
+ // The durable writer and post-write validation have already settled.
568
+ // Footer refresh remains advisory and cannot change the apply result.
569
+ }
570
+ }
561
571
  return {
562
572
  apply: applyWithPostWriteReplay(apply, postWriteReplay),
563
573
  postWriteReplay,
@@ -2,12 +2,17 @@ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
 
3
3
  import type { AuditLogger } from "../../audit/logger.ts";
4
4
  import type { PackageRegistrationSnapshot } from "../../packs/package-registration.ts";
5
- import type { PolicyResolver } from "../policy-cache.ts";
5
+ import type { PolicyResolver, ResolvedPolicy } from "../policy-cache.ts";
6
6
 
7
7
  export interface RatchetToolDependencies {
8
8
  readonly policyResolver: PolicyResolver;
9
9
  readonly packageRegistration: () => PackageRegistrationSnapshot;
10
10
  readonly audit: AuditLogger;
11
+ /** Refresh the active-session footer after an approved proposal writes config. */
12
+ readonly refreshOperatorStatus?: (
13
+ ctx: ExtensionContext,
14
+ policy: ResolvedPolicy,
15
+ ) => void;
11
16
  }
12
17
 
13
18
  export interface RatchetToolContext {
@@ -107,6 +107,11 @@ The command surface mirrors that merge model:
107
107
  /mode default off --global # clear global default
108
108
  ```
109
109
 
110
+ Autocomplete surfaces `--global` as the first choice after `/mode default ` and
111
+ continues with preset completion after `/mode default --global `. The bare `/mode`
112
+ panel also prints both durable forms so persistence is discoverable without reading
113
+ documentation.
114
+
110
115
  Writes preserve sibling keys such as `cycleKeybinding`, format JSON with two-space
111
116
  indentation, and refuse to overwrite malformed/non-object JSON files. An invalid
112
117
  `defaultMode` (unknown preset / missing fragment) warns and is skipped during
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nklisch/pi-model-modes",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "A pi extension that adapts the system prompt per model/mode.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -25,11 +25,14 @@ export const MODE_DEFAULT_GLOBAL_FLAG = "--global";
25
25
  const OFF_DESCRIPTION = "clear override — fall back to default";
26
26
  const NONE_DESCRIPTION = "explicit no-mode override — wins over default";
27
27
  const DEFAULT_DESCRIPTION = "manage the durable default — writes pi-model-modes.json";
28
- const GLOBAL_FLAG_DESCRIPTION = "target the global (~/.pi/agent) config file";
28
+ const GLOBAL_FLAG_DESCRIPTION = "persist globally in ~/.pi/agent (instead of this project)";
29
29
 
30
30
  const MODE_ARG_TRIGGER = /^\/mode[ \t]+([^\s]*)$/;
31
31
  /** Stage 2: `<action>` token after `/mode default ` (no further tokens). */
32
32
  const MODE_DEFAULT_ACTION_TRIGGER = /^\/mode[ \t]+default[ \t]+([^\s]*)$/;
33
+ /** Stage 2b: action after the discoverable leading `--global` form. */
34
+ const MODE_DEFAULT_GLOBAL_ACTION_TRIGGER =
35
+ /^\/mode[ \t]+default[ \t]+--global[ \t]+([^\s]*)$/;
33
36
  /** Stage 3: a leading-dash token after `/mode default <action> `. */
34
37
  const MODE_DEFAULT_FLAG_TRIGGER = /^\/mode[ \t]+default[ \t]+[^\s]+[ \t]+(--?[^\s]*)$/;
35
38
 
@@ -69,7 +72,7 @@ export function buildModeTopLevelItems(
69
72
  ];
70
73
  }
71
74
 
72
- /** PURE: build the single-item `--global` suggestion list for stage 3. */
75
+ /** PURE: build the single-item `--global` suggestion list. */
73
76
  export function buildDefaultGlobalFlagItems(): AutocompleteItem[] {
74
77
  return [
75
78
  {
@@ -93,8 +96,9 @@ export function filterModeArgItems(
93
96
  * should delegate. Three-stage dispatch for the `/mode default` subcommand:
94
97
  *
95
98
  * - Stage 3: `/mode default <action> <--flag>` → `[--global]`
96
- * - Stage 2: `/mode default <action>` → presets + `off` (NO `default` —
97
- * `default default` is meaningless)
99
+ * - Stage 2b: `/mode default --global <action>` → presets + `off`
100
+ * - Stage 2: `/mode default <action>` → `--global` + presets + `off` (NO
101
+ * `default` — `default default` is meaningless)
98
102
  * - Stage 1: `/mode <partial>` → presets + `off` + `default` (top level)
99
103
  *
100
104
  * The three triggers are structurally mutually exclusive (trailing-space gates
@@ -115,12 +119,26 @@ export function getModeArgSuggestions(
115
119
  };
116
120
  }
117
121
 
118
- // Stage 2: action after `/mode default `.
122
+ // Stage 2b: action after the leading, discoverable global flag form.
123
+ const globalActionToken = beforeCursor.match(
124
+ MODE_DEFAULT_GLOBAL_ACTION_TRIGGER,
125
+ )?.[1];
126
+ if (globalActionToken !== undefined) {
127
+ return {
128
+ prefix: globalActionToken,
129
+ items: filterModeArgItems(buildModeArgItems(registry), globalActionToken),
130
+ };
131
+ }
132
+
133
+ // Stage 2: action or global scope after `/mode default `.
119
134
  const actionToken = beforeCursor.match(MODE_DEFAULT_ACTION_TRIGGER)?.[1];
120
135
  if (actionToken !== undefined) {
121
136
  return {
122
137
  prefix: actionToken,
123
- items: filterModeArgItems(buildModeArgItems(registry), actionToken),
138
+ items: filterModeArgItems(
139
+ [...buildDefaultGlobalFlagItems(), ...buildModeArgItems(registry)],
140
+ actionToken,
141
+ ),
124
142
  };
125
143
  }
126
144
 
@@ -241,6 +241,9 @@ export function formatModeListing(
241
241
  ` ${summary}`,
242
242
  "Available presets:",
243
243
  presetList,
244
+ "Durable defaults:",
245
+ " /mode default <preset> — persist for this project",
246
+ " /mode default --global <preset> — persist globally",
244
247
  ].join("\n");
245
248
  }
246
249
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nklisch/pi-enhanced",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Pi, enhanced — one install for nklisch's full harness: policy-gated command review, plugin marketplace, subagents, background tasks, research tools, search, model modes, and a curated UX set.",
5
5
  "author": {
6
6
  "name": "nklisch"