@groeponline/pi-wishcraft 1.3.0 → 1.3.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.3.1] - 2026-08-25
6
+
7
+ ### Fixed
8
+ - Make protected-main releases promote only an exact bot-generated candidate SHA after its own canonical `Verify` check succeeds.
9
+ - Keep `package-lock.json` version metadata synchronized with release commits and resolve the dev-only `nanoid` advisory at 3.3.18.
10
+
5
11
  ## [1.3.0] - 2026-08-25
6
12
 
7
13
  ## [1.2.0] - 2026-08-24
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groeponline/pi-wishcraft",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Operator cockpit for Pi: live powerline status, searchable skills, idea queue, sticky Bash, hooks, policy controls, and session UX.",
5
5
  "type": "module",
6
6
  "files": [
@@ -59,6 +59,7 @@ export function createDeckNavState(
59
59
  assignEvent: "streaming",
60
60
  skillCreate: false,
61
61
  skillCreateName: "",
62
+ navMode: false,
62
63
  };
63
64
  }
64
65
 
@@ -155,7 +156,7 @@ export function createDeckComponent(
155
156
 
156
157
  if (state.pendingJump === "g" && data.length === 1 && isOverlayPrintable(data)) {
157
158
  const route = deckRouteByJump(data);
158
- state = { ...state, pendingJump: null };
159
+ state = { ...state, pendingJump: null, navMode: false };
159
160
  if (route) setRoute(route);
160
161
  return;
161
162
  }
@@ -167,8 +168,27 @@ export function createDeckComponent(
167
168
  return;
168
169
  }
169
170
 
171
+ // ←/tab returns focus to the NAVIGATION column in one press; from there
172
+ // ↑↓ moves the nav selection and any other key drops back into the list.
173
+ if (
174
+ !state.composerOpen &&
175
+ !state.skillCreate &&
176
+ (matchesKey(data, "left") || matchesKey(data, "tab"))
177
+ ) {
178
+ state = { ...state, navMode: true };
179
+ return;
180
+ }
181
+ if (state.navMode) {
182
+ if (matchesKey(data, "up") || matchesKey(data, "down")) {
183
+ // fall through to the nav handlers at the bottom
184
+ } else {
185
+ state = { ...state, navMode: false };
186
+ return;
187
+ }
188
+ }
189
+
170
190
  if (state.route === "appearance") {
171
- if (handleList(data, "selectedAppearance", STRUCTURAL_PRESET_NAMES.length)) return;
191
+ if (!state.navMode && handleList(data, "selectedAppearance", STRUCTURAL_PRESET_NAMES.length)) return;
172
192
  if (matchesKey(data, "enter")) {
173
193
  const name = STRUCTURAL_PRESET_NAMES[state.selectedAppearance];
174
194
  if (name) {
@@ -182,7 +202,7 @@ export function createDeckComponent(
182
202
 
183
203
  if (state.route === "motion") {
184
204
  const count = filterMotions(state.searchQuery).length;
185
- if (handleList(data, "selectedMotion", count)) return;
205
+ if (!state.navMode && handleList(data, "selectedMotion", count)) return;
186
206
  if (data === "t") {
187
207
  state = { ...state, assignEvent: cycleAssignEvent(state.assignEvent) };
188
208
  return;
@@ -248,7 +268,7 @@ export function createDeckComponent(
248
268
  }
249
269
  const snapshot = liveSnapshot();
250
270
  const rows = filterSkillRows(snapshot.skills, state.searchQuery);
251
- if (handleList(data, "selectedSkill", rows.length)) return;
271
+ if (!state.navMode && handleList(data, "selectedSkill", rows.length)) return;
252
272
  if (matchesKey(data, "enter")) {
253
273
  const selected = rows[state.selectedSkill];
254
274
  if (!selected) return;
@@ -266,7 +286,7 @@ export function createDeckComponent(
266
286
  }
267
287
 
268
288
  if (state.route === "ideas") {
269
- if (handleList(data, "selectedIdea", liveSnapshot().ideas.length)) return;
289
+ if (!state.navMode && handleList(data, "selectedIdea", liveSnapshot().ideas.length)) return;
270
290
  }
271
291
 
272
292
  if (matchesKey(data, "up")) {
@@ -311,7 +331,7 @@ export function createDeckComponent(
311
331
  if (state.route !== "motion" && state.route !== "skills") {
312
332
  const matches = filterDeckRoutes(next);
313
333
  if (matches.length === 1) {
314
- state = { ...state, searchOpen: false, searchQuery: "" };
334
+ state = { ...state, searchOpen: false, searchQuery: "", navMode: false };
315
335
  setRoute(matches[0]!);
316
336
  }
317
337
  }
@@ -324,7 +344,7 @@ export function createDeckComponent(
324
344
  }
325
345
  const matches = filterDeckRoutes(state.searchQuery);
326
346
  if (matches[0]) {
327
- state = { ...state, searchOpen: false, searchQuery: "" };
347
+ state = { ...state, searchOpen: false, searchQuery: "", navMode: false };
328
348
  setRoute(matches[0]);
329
349
  }
330
350
  }
@@ -31,13 +31,13 @@ export function deckFooter(state: DeckNavState): string {
31
31
  if (state.skillCreate) return "type a name · enter create · esc cancel";
32
32
  switch (state.route) {
33
33
  case "appearance":
34
- return "↑↓ select base · enter apply · / Search · g h Home · Esc Close";
34
+ return "↑↓ select base · enter apply · ←/tab nav · / Search · g h Home · Esc Close";
35
35
  case "motion":
36
- return "↑↓ motion · t event · e composer · enter apply · Esc Close";
36
+ return "↑↓ motion · t event · e composer · enter apply · ←/tab nav · Esc Close";
37
37
  case "skills":
38
- return "↑↓ skill · enter insert · n new · / filter · Esc Close";
38
+ return "↑↓ skill · enter insert · n new · / filter · ←/tab nav · Esc Close";
39
39
  case "ideas":
40
- return "↑↓ idea · / Search · g h Home · Esc Close";
40
+ return "↑↓ idea · / Search · ←/tab nav · g h Home · Esc Close";
41
41
  default:
42
42
  return "/ Search g h Home g s Signal g i Ideas ? Help Esc Close";
43
43
  }
@@ -94,4 +94,6 @@ export interface DeckNavState {
94
94
  assignEvent: import("../../../motion/types.ts").MotionEvent;
95
95
  skillCreate: boolean;
96
96
  skillCreateName: string;
97
+ /** True when ↑↓ moves the NAVIGATION column instead of the route list. */
98
+ navMode: boolean;
97
99
  }