pi-usereq 0.10.0 → 0.12.0

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 (52) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +6 -6
  3. package/package.json +1 -1
  4. package/pi-usereq/docs/REFERENCES.md +861 -704
  5. package/pi-usereq/docs/REQUIREMENTS.md +152 -95
  6. package/pi-usereq/docs/WORKFLOW.md +228 -65
  7. package/scripts/lib/extension-debug-harness.ts +2 -2
  8. package/scripts/tool-args-to-params.ts +2 -2
  9. package/src/cli.ts +12 -12
  10. package/src/core/debug-runtime.ts +2 -2
  11. package/src/core/extension-status.ts +98 -36
  12. package/src/core/pi-notify.ts +5 -5
  13. package/src/core/pi-usereq-tools.ts +4 -2
  14. package/src/core/prompt-command-catalog.ts +4 -5
  15. package/src/core/prompt-command-runtime.ts +347 -42
  16. package/src/core/prompts.ts +0 -2
  17. package/src/core/req-references-command.ts +175 -0
  18. package/src/core/req-reset-command.ts +323 -0
  19. package/src/core/resources.ts +6 -23
  20. package/src/core/runtime-project-paths.ts +21 -1
  21. package/src/core/settings-menu.ts +85 -28
  22. package/src/core/tool-runner.ts +26 -6
  23. package/src/index.ts +530 -104
  24. package/tests/attended-results-scenarios.ts +5 -5
  25. package/tests/cli-command-option-parity.test.ts +25 -25
  26. package/tests/debug-extension-harness.test.ts +8 -2
  27. package/tests/extension-registration.test.ts +1109 -76
  28. package/tests/oracle-project.test.ts +4 -4
  29. package/tests/oracle-standalone.test.ts +5 -5
  30. package/src/core/reference-payload.ts +0 -752
  31. package/src/resources/prompts/references.md +0 -64
  32. /package/tests/fixtures_attended_results/project/{references.json → summarize.json} +0 -0
  33. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_c.c.json +0 -0
  34. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_cpp.cpp.json +0 -0
  35. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_csharp.cs.json +0 -0
  36. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_elixir.ex.json +0 -0
  37. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_go.go.json +0 -0
  38. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_haskell.hs.json +0 -0
  39. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_java.java.json +0 -0
  40. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_javascript.js.json +0 -0
  41. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_kotlin.kt.json +0 -0
  42. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_lua.lua.json +0 -0
  43. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_perl.pl.json +0 -0
  44. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_php.php.json +0 -0
  45. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_python.py.json +0 -0
  46. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_ruby.rb.json +0 -0
  47. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_rust.rs.json +0 -0
  48. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_scala.scala.json +0 -0
  49. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_shell.sh.json +0 -0
  50. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_swift.swift.json +0 -0
  51. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_typescript.ts.json +0 -0
  52. /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_zig.zig.json +0 -0
@@ -211,10 +211,10 @@ const PROMPT_COMMAND_EXAMPLES: Record<string, string> = {
211
211
  */
212
212
  const TOOL_EXAMPLES: Record<string, string> = {
213
213
  "files-tokens": `npm run debug:ext:tool -- --name files-tokens --params '{"files":["pi-usereq/docs/REQUIREMENTS.md","pi-usereq/docs/WORKFLOW.md"]}' --cwd . --format json`,
214
- "files-references": `npm run debug:ext:tool -- --name files-references --params '{"files":["src/index.ts","src/core/tool-runner.ts"]}' --cwd . --format pretty`,
214
+ "files-summarize": `npm run debug:ext:tool -- --name files-summarize --params '{"files":["src/index.ts","src/core/tool-runner.ts"]}' --cwd . --format pretty`,
215
215
  "files-compress": `npm run debug:ext:tool -- --name files-compress --params '{"files":["src/index.ts"],"enableLineNumbers":true}' --cwd . --format json`,
216
216
  "files-search": `npm run debug:ext:tool -- --name files-search --params '{"tag":"FUNCTION|METHOD","pattern":"^run","files":["src/core/tool-runner.ts"],"enableLineNumbers":true}' --cwd . --format pretty`,
217
- references: "npm run debug:ext:tool -- --name references --cwd . --format pretty",
217
+ summarize: "npm run debug:ext:tool -- --name summarize --cwd . --format pretty",
218
218
  compress: `npm run debug:ext:tool -- --name compress --params '{"enableLineNumbers":true}' --cwd . --format json`,
219
219
  search: `npm run debug:ext:tool -- --name search --params '{"tag":"FUNCTION","pattern":"^run","enableLineNumbers":true}' --cwd . --format pretty`,
220
220
  tokens: "npm run debug:ext:tool -- --name tokens --cwd . --format json",
@@ -97,7 +97,7 @@ function takeBooleanFlag(tokens: string[], flag: string): { tokens: string[]; pr
97
97
  export function buildToolParamsFromArgsText(toolName: string, argsText: string): Record<string, unknown> {
98
98
  const tokens = shellSplit(argsText);
99
99
  switch (toolName) {
100
- case "references":
100
+ case "summarize":
101
101
  case "tokens":
102
102
  case "static-check":
103
103
  if (tokens.length !== 0) {
@@ -105,7 +105,7 @@ export function buildToolParamsFromArgsText(toolName: string, argsText: string):
105
105
  }
106
106
  return {};
107
107
  case "files-tokens":
108
- case "files-references":
108
+ case "files-summarize":
109
109
  case "files-static-check":
110
110
  return { files: tokens };
111
111
  case "files-compress": {
package/src/cli.ts CHANGED
@@ -20,12 +20,12 @@ import {
20
20
  runCompress,
21
21
  runFilesCompress,
22
22
  runFilesSearch,
23
- runFilesReferences,
23
+ runFilesSummarize,
24
24
  runFilesStaticCheck,
25
25
  runFilesTokens,
26
26
  runSearch,
27
27
  runProjectStaticCheck,
28
- runReferences,
28
+ runSummarize,
29
29
  runTokens,
30
30
  } from "./core/tool-runner.js";
31
31
  import {
@@ -46,10 +46,10 @@ interface ParsedArgs {
46
46
  enableLineNumbers?: boolean;
47
47
  enableStaticCheck?: string[];
48
48
  filesTokens?: string[];
49
- filesReferences?: string[];
49
+ filesSummarize?: string[];
50
50
  filesCompress?: string[];
51
51
  filesSearch?: string[];
52
- references?: boolean;
52
+ summarize?: boolean;
53
53
  compress?: boolean;
54
54
  search?: [string, string];
55
55
  tokens?: boolean;
@@ -106,9 +106,9 @@ function parseArgs(argv: string[]): ParsedArgs {
106
106
  index = next;
107
107
  break;
108
108
  }
109
- case "--files-references": {
109
+ case "--files-summarize": {
110
110
  const [values, next] = takeUntilOption(index + 1);
111
- parsed.filesReferences = values;
111
+ parsed.filesSummarize = values;
112
112
  index = next;
113
113
  break;
114
114
  }
@@ -124,8 +124,8 @@ function parseArgs(argv: string[]): ParsedArgs {
124
124
  index = next;
125
125
  break;
126
126
  }
127
- case "--references":
128
- parsed.references = true;
127
+ case "--summarize":
128
+ parsed.summarize = true;
129
129
  index += 1;
130
130
  break;
131
131
  case "--compress":
@@ -256,12 +256,12 @@ export function main(argv = process.argv.slice(2)): number {
256
256
  }
257
257
  const args = parseArgs(argv);
258
258
  const hereOnlyProjectCommand = !!(
259
- args.references || args.compress || args.tokens || args.search || args.staticCheck
259
+ args.summarize || args.compress || args.tokens || args.search || args.staticCheck
260
260
  );
261
261
  if (hereOnlyProjectCommand) {
262
262
  if (args.base) {
263
263
  throw new ReqError(
264
- "Error: --references, --compress, --tokens, --find, and --static-check do not allow --base; use --here.",
264
+ "Error: --summarize, --compress, --tokens, --find, and --static-check do not allow --base; use --here.",
265
265
  1,
266
266
  );
267
267
  }
@@ -281,12 +281,12 @@ export function main(argv = process.argv.slice(2)): number {
281
281
  }
282
282
 
283
283
  if (args.filesTokens) return writeResult(runFilesTokens(args.filesTokens));
284
- if (args.filesReferences) return writeResult(runFilesReferences(args.filesReferences, process.cwd(), args.verbose));
284
+ if (args.filesSummarize) return writeResult(runFilesSummarize(args.filesSummarize, process.cwd(), args.verbose));
285
285
  if (args.filesCompress) return writeResult(runFilesCompress(args.filesCompress, process.cwd(), args.enableLineNumbers, args.verbose));
286
286
  if (args.filesSearch) return writeResult(runFilesSearch(args.filesSearch, args.enableLineNumbers, args.verbose));
287
287
  if (args.testStaticCheck) return runStaticCheck(args.testStaticCheck);
288
288
  if (args.filesStaticCheck) return writeResult(runFilesStaticCheck(args.filesStaticCheck, projectBase, config));
289
- if (args.references) return writeResult(runReferences(projectBase, config, args.verbose));
289
+ if (args.summarize) return writeResult(runSummarize(projectBase, config, args.verbose));
290
290
  if (args.compress) return writeResult(runCompress(projectBase, config, args.enableLineNumbers, args.verbose));
291
291
  if (args.search) return writeResult(runSearch(projectBase, args.search[0], args.search[1], config, args.enableLineNumbers, args.verbose));
292
292
  if (args.tokens) return writeResult(runTokens(projectBase, config));
@@ -26,10 +26,10 @@ export const DEFAULT_DEBUG_ENABLED = "disable" as const;
26
26
 
27
27
  /**
28
28
  * @brief Defines the default debug log file value.
29
- * @details Relative values resolve against the original project base when entries are written. Access complexity is O(1).
29
+ * @details New configurations write debug JSON entries to `/tmp/PI-useReq.json` unless the user overrides the path. Access complexity is O(1).
30
30
  * @satisfies CTN-013, REQ-237
31
31
  */
32
- export const DEFAULT_DEBUG_LOG_FILE = "debug.json";
32
+ export const DEFAULT_DEBUG_LOG_FILE = "/tmp/PI-useReq.json";
33
33
 
34
34
  /**
35
35
  * @brief Defines the default workflow-transition logging mode.
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * @file
3
3
  * @brief Tracks pi-usereq extension status state and renders status-bar telemetry.
4
- * @details Centralizes hook interception, context-usage snapshots, run timing,
5
- * and deterministic status-bar formatting for the pi-usereq extension. Runtime
6
- * is O(1) per event plus O(s) in configured source-path count during status
7
- * rendering. Side effects are limited to in-memory state mutation and interval
4
+ * @details Centralizes hook interception, context-usage snapshots, active-branch lookup, run timing, and deterministic status-bar formatting for the pi-usereq extension. Runtime
5
+ * is O(1) per event plus interval-driven re-renders while a prompt remains
6
+ * active. Side effects are limited to in-memory state mutation and interval
8
7
  * scheduling through exported controller helpers.
9
8
  */
10
9
 
@@ -15,15 +14,13 @@ import type {
15
14
  ThemeColor,
16
15
  } from "@mariozechner/pi-coding-agent";
17
16
  import type { UseReqConfig } from "./config.js";
17
+ import type { PiNotifySoundLevel } from "./pi-notify.js";
18
18
  import type { PromptCommandExecutionPlan } from "./prompt-command-runtime.js";
19
- import {
20
- formatRuntimePathForDisplay,
21
- getRuntimeContextPath,
22
- } from "./path-context.js";
23
19
  import {
24
20
  restorePersistedPromptCommandRuntimeStateForSession,
25
21
  writePersistedPromptCommandRuntimeState,
26
22
  } from "./prompt-command-state.js";
23
+ import { resolveRuntimeGitBranchName } from "./runtime-project-paths.js";
27
24
 
28
25
  /**
29
26
  * @brief Enumerates the CLI-supported theme tokens consumed by status rendering.
@@ -115,7 +112,7 @@ export type PiUsereqWorkflowState = "idle" | "checking" | "running" | "merging"
115
112
 
116
113
  /**
117
114
  * @brief Stores the mutable runtime facts displayed by the status bar.
118
- * @details Persists the prompt-orchestration workflow state, the latest context-usage snapshot, the active run start timestamp, the most recent normally completed run duration, the accumulated duration of all normally completed runs, and prompt-request metadata carried from command dispatch into the next runtime execution. Runtime state is mutated in-place by controller helpers. Compile-time only and introduces no runtime cost.
115
+ * @details Persists the prompt-orchestration workflow state, the latest context-usage snapshot, the active run start timestamp, the most recent normally completed run duration, the accumulated duration of all normally completed runs, the in-memory runtime sound level, and prompt-request metadata carried from command dispatch into the next runtime execution. Runtime state is mutated in-place by controller helpers. Compile-time only and introduces no runtime cost.
119
116
  */
120
117
  export interface PiUsereqStatusState {
121
118
  workflowState: PiUsereqWorkflowState;
@@ -123,6 +120,7 @@ export interface PiUsereqStatusState {
123
120
  runStartTimeMs: number | undefined;
124
121
  lastRunDurationMs: number | undefined;
125
122
  totalRunDurationMs: number | undefined;
123
+ runtimeSoundLevel: PiNotifySoundLevel | undefined;
126
124
  pendingPromptRequest: PiUsereqPromptRequest | undefined;
127
125
  activePromptRequest: PiUsereqPromptRequest | undefined;
128
126
  }
@@ -323,6 +321,17 @@ function createStatusThemeAdapter(theme: RawStatusTheme): StatusThemeAdapter {
323
321
  };
324
322
  }
325
323
 
324
+ /**
325
+ * @brief Resolves the active git branch value rendered in the status bar.
326
+ * @details Reads the current branch from the active context working directory on every status render so worktree switches and restored base-session renders expose the latest branch immediately. Runtime is dominated by git execution when the working directory belongs to a repository. Side effects include subprocess creation.
327
+ * @param[in] ctx {ExtensionContext} Active extension context.
328
+ * @return {string} Active branch name or `unknown` when unavailable.
329
+ * @satisfies REQ-121, REQ-283
330
+ */
331
+ function resolveStatusBranchValue(ctx: ExtensionContext): string {
332
+ return resolveRuntimeGitBranchName(ctx.cwd);
333
+ }
334
+
326
335
  /**
327
336
  * @brief Normalizes one raw context-usage snapshot.
328
337
  * @details Preserves the runtime token and context-window counts, derives a
@@ -370,12 +379,10 @@ function refreshContextUsage(
370
379
 
371
380
  /**
372
381
  * @brief Resolves the icon text for one normalized context-usage snapshot.
373
- * @details Maps context usage to one fixed-width icon band so footer rendering
374
- * remains compact and deterministic. Unavailable usage degrades to the `0%`
375
- * icon. Runtime is O(1). No external state is mutated.
382
+ * @details Maps context usage to one fixed-width icon band so footer rendering remains compact and deterministic across the documented `0`, `>0-<25`, `>=25-<50`, `>=50-<75`, and `>=75` percent bands. Unavailable usage degrades to the `0%` icon. Runtime is O(1). No external state is mutated.
376
383
  * @param[in] contextUsage {ContextUsage | undefined} Normalized context snapshot.
377
384
  * @return {string} Fixed-width gauge icon text.
378
- * @satisfies REQ-121, REQ-122
385
+ * @satisfies REQ-122, REQ-284
379
386
  */
380
387
  function resolveContextUsageIconText(
381
388
  contextUsage: ContextUsage | undefined,
@@ -384,13 +391,13 @@ function resolveContextUsageIconText(
384
391
  if (percent === undefined || percent === null || percent <= 0) {
385
392
  return "▕_▏";
386
393
  }
387
- if (percent <= 25) {
394
+ if (percent < 25) {
388
395
  return "▕▂▏";
389
396
  }
390
- if (percent <= 50) {
397
+ if (percent < 50) {
391
398
  return "▕▄▏";
392
399
  }
393
- if (percent <= 90) {
400
+ if (percent < 75) {
394
401
  return "▕▆▏";
395
402
  }
396
403
  return "▕█▏";
@@ -398,22 +405,22 @@ function resolveContextUsageIconText(
398
405
 
399
406
  /**
400
407
  * @brief Formats one icon-based context-usage gauge.
401
- * @details Renders the documented `warning`-colored icon bands for `0-90%`, applies terminal blink control to the `warning`-colored `>90-100%` icon, and applies terminal blink control to the `error`-colored overflow icon so unsupported terminals degrade to non-blinking colored text automatically. Runtime is O(1). No external state is mutated.
408
+ * @details Renders the documented gauge icon with the same non-error status-value theme token used by `status` below `90%`, switches to theme `error` for `>=90%`, and enables terminal blink only for `>=100%`. Runtime is O(1). No external state is mutated.
402
409
  * @param[in] theme {StatusThemeAdapter} Normalized status theme.
403
410
  * @param[in] contextUsage {ContextUsage | undefined} Normalized context snapshot.
404
411
  * @return {string} Rendered fixed-width gauge icon.
405
- * @satisfies REQ-121, REQ-122, REQ-126, REQ-127, REQ-128, REQ-233
412
+ * @satisfies REQ-122, REQ-126, REQ-127, REQ-128, REQ-233, REQ-284
406
413
  */
407
414
  function formatContextUsageBar(
408
415
  theme: StatusThemeAdapter,
409
416
  contextUsage: ContextUsage | undefined,
410
417
  ): string {
411
418
  const percent = contextUsage?.percent ?? 0;
412
- if (percent > 100) {
419
+ if (percent >= 100) {
413
420
  return theme.colorize("error", "\u001b[5m▕█▏\u001b[25m");
414
421
  }
415
- if (percent > 90) {
416
- return theme.colorize("warning", "\u001b[5m▕█▏\u001b[25m");
422
+ if (percent >= 90) {
423
+ return theme.colorize("error", "▕█▏");
417
424
  }
418
425
  return theme.value(resolveContextUsageIconText(contextUsage));
419
426
  }
@@ -543,34 +550,48 @@ function didAgentEndAbort(messages: AgentEndEvent["messages"]): boolean {
543
550
  );
544
551
  }
545
552
 
553
+ /**
554
+ * @brief Resolves the active runtime sound level used by status and notify flows.
555
+ * @details Prefers the mutable runtime sound state, then falls back to the cached persisted boot value, and finally defaults to `none` before `session_start` loads configuration. Runtime is O(1). No external state is mutated.
556
+ * @param[in] state {PiUsereqStatusState} Mutable status state snapshot.
557
+ * @param[in] config {UseReqConfig | undefined} Cached project configuration.
558
+ * @return {PiNotifySoundLevel} Active runtime sound level.
559
+ * @satisfies REQ-180, REQ-285
560
+ */
561
+ function resolvePiUsereqRuntimeSoundLevel(
562
+ state: PiUsereqStatusState,
563
+ config: UseReqConfig | undefined,
564
+ ): PiNotifySoundLevel {
565
+ return state.runtimeSoundLevel ?? config?.["notify-sound"] ?? "none";
566
+ }
567
+
546
568
  /**
547
569
  * @brief Builds the full single-line pi-usereq status-bar payload.
548
- * @details Renders status, current-path, context, elapsed, and sound fields in the canonical order with dim bullet separators, workflow-state highlighting, and the documented icon-based context gauge. Runtime is O(1). No external state is mutated.
549
- * @param[in] cwd {string} Runtime working directory used for context-path derivation.
570
+ * @details Renders status, branch, context, elapsed, and sound fields in the canonical order with dim bullet separators, workflow-state highlighting, the documented icon-based context gauge, and the active runtime sound level instead of the persisted boot value. Runtime is O(1). No external state is mutated.
550
571
  * @param[in] config {UseReqConfig} Effective project configuration.
551
572
  * @param[in] theme {StatusThemeAdapter} Normalized status theme.
552
573
  * @param[in] state {PiUsereqStatusState} Mutable status state snapshot.
574
+ * @param[in] branchName {string} Active git branch name shown in the footer.
553
575
  * @param[in] nowMs {number} Current wall-clock time in milliseconds.
554
576
  * @return {string} Single-line status-bar text.
555
- * @satisfies REQ-109, REQ-112, REQ-120, REQ-121, REQ-123, REQ-124, REQ-125, REQ-126, REQ-127, REQ-128, REQ-148, REQ-156, REQ-159, REQ-180, REQ-222, REQ-223
577
+ * @satisfies REQ-109, REQ-112, REQ-120, REQ-121, REQ-123, REQ-124, REQ-125, REQ-126, REQ-127, REQ-128, REQ-156, REQ-159, REQ-180, REQ-222, REQ-223, REQ-233, REQ-283, REQ-284
556
578
  */
557
579
  function buildPiUsereqStatusText(
558
- cwd: string,
559
580
  config: UseReqConfig,
560
581
  theme: StatusThemeAdapter,
561
582
  state: PiUsereqStatusState,
583
+ branchName: string,
562
584
  nowMs: number,
563
585
  ): string {
564
- const currentPathText = formatRuntimePathForDisplay(getRuntimeContextPath(cwd));
565
586
  const elapsedText = formatElapsedStatusValue(state, nowMs);
566
- const soundText = config["notify-sound"];
587
+ const soundText = resolvePiUsereqRuntimeSoundLevel(state, config);
567
588
  return [
568
589
  formatRenderedStatusField(
569
590
  theme,
570
591
  "status",
571
592
  formatWorkflowStateValue(theme, state.workflowState),
572
593
  ),
573
- formatStatusField(theme, "current-path", currentPathText),
594
+ formatStatusField(theme, "branch", branchName),
574
595
  formatRenderedStatusField(
575
596
  theme,
576
597
  "context",
@@ -626,7 +647,7 @@ function syncPiUsereqStatusTicker(
626
647
 
627
648
  /**
628
649
  * @brief Creates an empty pi-usereq status controller.
629
- * @details Initializes the mutable status snapshot, including empty prompt-request tracking, and starts with no config, no context, and no live ticker. Runtime is O(1). No external state is mutated.
650
+ * @details Initializes the mutable status snapshot, including empty prompt-request tracking and an unset runtime sound level that later loads from persisted config during `session_start`, and starts with no config, no context, and no live ticker. Runtime is O(1). No external state is mutated.
630
651
  * @return {PiUsereqStatusController} New status controller.
631
652
  * @satisfies DES-010
632
653
  */
@@ -640,6 +661,7 @@ export function createPiUsereqStatusController(): PiUsereqStatusController {
640
661
  runStartTimeMs: undefined,
641
662
  lastRunDurationMs: undefined,
642
663
  totalRunDurationMs: undefined,
664
+ runtimeSoundLevel: undefined,
643
665
  pendingPromptRequest: undefined,
644
666
  activePromptRequest: undefined,
645
667
  },
@@ -650,8 +672,9 @@ export function createPiUsereqStatusController(): PiUsereqStatusController {
650
672
  /**
651
673
  * @brief Stores the effective project configuration used by status rendering.
652
674
  * @details Replaces the controller's cached configuration so later status
653
- * renders reuse the latest docs, tests, source-path, and pi-notify values
654
- * without reading from disk on every event. Runtime is O(1). Side effect:
675
+ * renders reuse the latest docs, tests, source-path, and persisted pi-notify
676
+ * values without reading from disk on every event, while leaving the active
677
+ * runtime sound level in `controller.state`. Runtime is O(1). Side effect:
655
678
  * mutates `controller.config`.
656
679
  * @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
657
680
  * @param[in] config {UseReqConfig} Effective project configuration.
@@ -664,13 +687,47 @@ export function setPiUsereqStatusConfig(
664
687
  controller.config = config;
665
688
  }
666
689
 
690
+ /**
691
+ * @brief Returns the active runtime sound level tracked by the status controller.
692
+ * @details Exposes the in-memory runtime sound state so shortcut handlers and prompt-end notification dispatch can stay decoupled from the persisted boot value stored in `.pi-usereq.json`. Runtime is O(1). No external state is mutated.
693
+ * @param[in] controller {PiUsereqStatusController} Mutable status controller.
694
+ * @return {PiNotifySoundLevel} Active runtime sound level.
695
+ * @satisfies REQ-180, REQ-285
696
+ */
697
+ export function getPiUsereqRuntimeSoundLevel(
698
+ controller: PiUsereqStatusController,
699
+ ): PiNotifySoundLevel {
700
+ return resolvePiUsereqRuntimeSoundLevel(controller.state, controller.config);
701
+ }
702
+
703
+ /**
704
+ * @brief Stores one new runtime sound level and refreshes the status bar.
705
+ * @details Mutates only the in-memory runtime sound state so shortcut-driven sound changes do not update `.pi-usereq.json`, then re-renders the footer when an active extension context is available. Runtime is O(1). Side effect: mutates `controller.state.runtimeSoundLevel` and may update `ctx.ui` status.
706
+ * @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
707
+ * @param[in] runtimeSoundLevel {PiNotifySoundLevel} Next active runtime sound level.
708
+ * @param[in] ctx {ExtensionContext | undefined} Optional active extension context.
709
+ * @return {void} No return value.
710
+ * @satisfies REQ-180, REQ-286, REQ-287
711
+ */
712
+ export function setPiUsereqRuntimeSoundLevel(
713
+ controller: PiUsereqStatusController,
714
+ runtimeSoundLevel: PiNotifySoundLevel,
715
+ ctx?: ExtensionContext,
716
+ ): void {
717
+ controller.state.runtimeSoundLevel = runtimeSoundLevel;
718
+ const renderContext = ctx ?? controller.latestContext;
719
+ if (renderContext) {
720
+ renderPiUsereqStatus(controller, renderContext);
721
+ }
722
+ }
723
+
667
724
  /**
668
725
  * @brief Renders the current pi-usereq status bar into the active UI context.
669
- * @details Updates the controller's latest context pointer and writes the single-line status text only when configuration is available, deriving `current-path` from the active runtime context path aligned to `ctx.cwd` and including the documented icon-based context gauge. When pi has already invalidated the supplied context after session replacement or reload, the helper clears the stale cached context and returns without surfacing the stale-instance exception. Runtime is O(s) in configured source-path count. Side effect: mutates `ctx.ui` status when the context is still active.
726
+ * @details Updates the controller's latest context pointer, refreshes the live `getContextUsage()` snapshot for direct render call sites that do not pass through `updateExtensionStatus(...)`, and writes the single-line status text only when configuration is available, including the active branch field, documented icon-based context gauge, and active runtime sound level. When pi has already invalidated the supplied context after session replacement or reload, the helper clears the stale cached context and returns without surfacing the stale-instance exception. Runtime is O(1) plus git execution for branch refresh. Side effect: mutates `controller.state.contextUsage` and `ctx.ui` status when the context is still active.
670
727
  * @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
671
728
  * @param[in] ctx {ExtensionContext} Active extension context.
672
729
  * @return {void} No return value.
673
- * @satisfies REQ-120, REQ-121, REQ-123, REQ-124, REQ-125, REQ-126, REQ-127, REQ-128, REQ-148, REQ-159, REQ-180, REQ-280
730
+ * @satisfies REQ-118, REQ-119, REQ-120, REQ-121, REQ-123, REQ-124, REQ-125, REQ-126, REQ-127, REQ-128, REQ-159, REQ-180, REQ-233, REQ-280, REQ-283, REQ-284
674
731
  */
675
732
  export function renderPiUsereqStatus(
676
733
  controller: PiUsereqStatusController,
@@ -681,14 +738,16 @@ export function renderPiUsereqStatus(
681
738
  return;
682
739
  }
683
740
  try {
741
+ refreshContextUsage(controller.state, ctx);
684
742
  const theme = createStatusThemeAdapter(ctx.ui.theme as RawStatusTheme);
743
+ const branchName = resolveStatusBranchValue(ctx);
685
744
  ctx.ui.setStatus(
686
745
  "pi-usereq",
687
746
  buildPiUsereqStatusText(
688
- ctx.cwd,
689
747
  controller.config,
690
748
  theme,
691
749
  controller.state,
750
+ branchName,
692
751
  Date.now(),
693
752
  ),
694
753
  );
@@ -727,13 +786,13 @@ export function setPiUsereqWorkflowState(
727
786
 
728
787
  /**
729
788
  * @brief Updates mutable status state for one intercepted lifecycle hook.
730
- * @details Refreshes stored context usage on every hook, resets or restores persisted elapsed counters during `session_start`, restores persisted prompt-command metadata when the active session matches a forked execution session, resynchronizes that metadata on later lifecycle hooks so post-switch workflow transitions performed by the initiating command handler become visible to the replacement-session runtime, resets workflow state to `idle` for documented session-start reasons, starts run timing on `agent_start`, promotes pending prompt-request metadata into the active run, captures non-aborted run duration on `agent_end`, accumulates successful runtime into `Σ`, preserves in-memory prompt-command state plus process-scoped persistence across switch-triggered `session_shutdown`, tolerates stale post-replacement render contexts, synchronizes the live ticker, and re-renders the status bar when configuration is available. Runtime is O(n) in `agent_end` message count and otherwise O(1). Side effects include in-memory state mutation, interval scheduling, process-scoped persistence mutation, and footer-status updates.
789
+ * @details Refreshes stored context usage on every hook, resets or restores persisted elapsed counters during `session_start`, loads the active runtime sound level from persisted config during `session_start`, restores persisted prompt-command metadata when the active session matches a forked execution session, resynchronizes that metadata on later lifecycle hooks so post-switch workflow transitions performed by the initiating command handler become visible to the replacement-session runtime, resets workflow state to `idle` for documented session-start reasons, starts run timing on `agent_start`, promotes pending prompt-request metadata into the active run, captures non-aborted run duration on `agent_end`, accumulates successful runtime into `Σ`, preserves in-memory prompt-command state plus process-scoped persistence across switch-triggered `session_shutdown`, tolerates stale post-replacement render contexts, synchronizes the live ticker, and re-renders the status bar when configuration is available. Runtime is O(n) in `agent_end` message count and otherwise O(1). Side effects include in-memory state mutation, interval scheduling, process-scoped persistence mutation, and footer-status updates.
731
790
  * @param[in,out] controller {PiUsereqStatusController} Mutable status controller.
732
791
  * @param[in] hookName {PiUsereqStatusHookName} Intercepted hook name.
733
792
  * @param[in] event {unknown} Hook payload forwarded from the wrapper.
734
793
  * @param[in] ctx {ExtensionContext} Active extension context.
735
794
  * @return {void} No return value.
736
- * @satisfies REQ-009, REQ-117, REQ-118, REQ-119, REQ-123, REQ-124, REQ-125, REQ-159, REQ-169, REQ-217, REQ-221, REQ-278, REQ-279, REQ-280
795
+ * @satisfies REQ-009, REQ-117, REQ-118, REQ-119, REQ-123, REQ-124, REQ-125, REQ-159, REQ-169, REQ-217, REQ-221, REQ-278, REQ-279, REQ-280, REQ-285
737
796
  */
738
797
  export function updateExtensionStatus(
739
798
  controller: PiUsereqStatusController,
@@ -752,6 +811,9 @@ export function updateExtensionStatus(
752
811
  } else {
753
812
  restorePersistedElapsedState(controller.state);
754
813
  }
814
+ controller.state.runtimeSoundLevel = controller.config?.["notify-sound"]
815
+ ?? controller.state.runtimeSoundLevel
816
+ ?? "none";
755
817
  const shouldResetWorkflowState = shouldResetWorkflowStateOnSessionStart(event);
756
818
  if (shouldResetWorkflowState) {
757
819
  controller.state.workflowState = "idle";
@@ -110,7 +110,7 @@ export interface PiNotifyEventRequest {
110
110
 
111
111
  /**
112
112
  * @brief Describes the configuration fields consumed by pi-notify helpers.
113
- * @details Narrows the full project config to the persisted notify, sound, and Pushover fields used by status rendering, prompt-end routing, and shortcut toggles. Compile-time only and introduces no runtime cost.
113
+ * @details Narrows the full project config to the notify, sound, and Pushover fields used by status rendering and prompt-end routing. Callers may override `notify-sound` with the active runtime sound level before dispatch. Compile-time only and introduces no runtime cost.
114
114
  */
115
115
  export type PiNotifyConfigFields = Pick<
116
116
  UseReqConfig,
@@ -363,10 +363,10 @@ export function formatPiNotifyPushoverStatus(config: Pick<UseReqConfig, "notify-
363
363
 
364
364
  /**
365
365
  * @brief Cycles one sound level through the canonical shortcut order.
366
- * @details Advances persisted sound state in the exact order `none -> low -> mid -> high -> none`, enabling deterministic shortcut toggling and menu reuse. Runtime is O(1). No external state is mutated.
367
- * @param[in] currentLevel {PiNotifySoundLevel} Current persisted sound level.
368
- * @return {PiNotifySoundLevel} Next sound level in the cycle.
369
- * @satisfies REQ-134
366
+ * @details Advances the active runtime sound state in the exact order `none -> low -> mid -> high -> none`, enabling deterministic shortcut toggling without mutating persisted boot configuration. Runtime is O(1). No external state is mutated.
367
+ * @param[in] currentLevel {PiNotifySoundLevel} Current active runtime sound level.
368
+ * @return {PiNotifySoundLevel} Next runtime sound level in the cycle.
369
+ * @satisfies REQ-286
370
370
  */
371
371
  export function cyclePiNotifySoundLevel(currentLevel: PiNotifySoundLevel): PiNotifySoundLevel {
372
372
  const currentIndex = PI_NOTIFY_SOUND_LEVELS.indexOf(currentLevel);
@@ -10,9 +10,10 @@
10
10
  */
11
11
  export const PI_USEREQ_CUSTOM_TOOL_NAMES = [
12
12
  "files-tokens",
13
- "files-references",
13
+ "files-summarize",
14
14
  "files-compress",
15
15
  "files-search",
16
+ "summarize",
16
17
  "references",
17
18
  "compress",
18
19
  "search",
@@ -51,9 +52,10 @@ export const PI_USEREQ_STARTUP_TOOL_NAMES = [
51
52
  */
52
53
  export const PI_USEREQ_DEFAULT_ENABLED_TOOL_NAMES = [
53
54
  "files-tokens",
54
- "files-references",
55
+ "files-summarize",
55
56
  "files-compress",
56
57
  "files-search",
58
+ "summarize",
57
59
  "references",
58
60
  "compress",
59
61
  "search",
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * @file
3
- * @brief Declares the canonical bundled `req-*` prompt-command inventory.
4
- * @details Centralizes prompt-command names shared by extension registration, configuration normalization, debug-menu rendering, and prompt-runtime orchestration. The module is side-effect free. Lookup cost is O(1) per exported constant access.
3
+ * @brief Declares the canonical bundled prompt-backed `req-*` command inventory.
4
+ * @details Centralizes only prompt-template-backed command names shared by extension registration, configuration normalization, debug-menu rendering, and prompt-runtime orchestration. Specialized slash commands such as `req-references` and `req-reset` are registered outside this inventory. The module is side-effect free. Lookup cost is O(1) per exported constant access.
5
5
  */
6
6
 
7
7
  /**
8
- * @brief Lists bundled prompt-command names handled by the extension.
9
- * @details Provides the single source of truth for `req-*` prompt registration, required-document routing, debug-prompt inventory derivation, and prompt-command worktree orchestration. Access complexity is O(1).
8
+ * @brief Lists bundled prompt-backed command names handled by the extension.
9
+ * @details Provides the single source of truth for prompt-template-backed `req-*` registration, required-document routing, debug-prompt inventory derivation, and prompt-command worktree orchestration. Access complexity is O(1).
10
10
  */
11
11
  export const PROMPT_COMMAND_NAMES = [
12
12
  "analyze",
@@ -21,7 +21,6 @@ export const PROMPT_COMMAND_NAMES = [
21
21
  "readme",
22
22
  "recreate",
23
23
  "refactor",
24
- "references",
25
24
  "renumber",
26
25
  "workflow",
27
26
  "write",