pi-usereq 0.75.0 → 0.77.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.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # PI-useReq/pi-usereq (0.75.0)
1
+ # PI-useReq/pi-usereq (0.77.0)
2
2
 
3
3
  <p align="center">
4
4
  <img src="https://img.shields.io/badge/python-3.11%2B-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python 3.11+">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-usereq",
3
- "version": "0.75.0",
3
+ "version": "0.77.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Ogekuri/PI-useReq.git"
@@ -32,7 +32,6 @@ import {
32
32
  normalizePiNotifyTemplateValue,
33
33
  } from "./pi-notify.js";
34
34
  import {
35
- DEFAULT_DEBUG_ENABLED,
36
35
  DEFAULT_DEBUG_LOG_FILE,
37
36
  DEFAULT_DEBUG_LOG_ON_STATUS,
38
37
  DEFAULT_DEBUG_PROMPTS_ENABLED,
@@ -40,7 +39,7 @@ import {
40
39
  DEFAULT_DEBUG_STATUS_CHANGES,
41
40
  DEFAULT_DEBUG_TOOL_COMMANDS_ENABLED,
42
41
  DEFAULT_DEBUG_WORKFLOW_EVENTS,
43
- normalizeDebugEnabled,
42
+ getRuntimeDebugEnabled,
44
43
  normalizeDebugEnabledPrompts,
45
44
  normalizeDebugEnabledTools,
46
45
  normalizeDebugLogFile,
@@ -149,7 +148,8 @@ interface GlobalStaticCheckLanguageConfig {
149
148
 
150
149
  /**
151
150
  * @brief Defines the persisted local pi-usereq configuration schema.
152
- * @details Captures project-scoped directory, debug, and static-check enablement fields written to `<base-path>/.pi-usereq.json` while excluding global notification, tool, git, and checker-command settings. The interface is compile-time only and introduces no runtime side effects.
151
+ * @details Captures project-scoped directory, debug, and static-check enablement fields written to `<base-path>/.pi-usereq.json` while excluding the runtime-only `DEBUG_ENABLED` flag and global notification, tool, git, and checker-command settings. The interface is compile-time only and introduces no runtime side effects.
152
+ * @satisfies REQ-426
153
153
  */
154
154
  interface UseReqLocalConfig {
155
155
  "docs-dir": string;
@@ -159,7 +159,6 @@ interface UseReqLocalConfig {
159
159
  "context-files-references": boolean;
160
160
  "context-files-workflow": boolean;
161
161
  "static-check": Record<string, LocalStaticCheckLanguageConfig>;
162
- DEBUG_ENABLED: "enable" | "disable";
163
162
  DEBUG_LOG_FILE: string;
164
163
  DEBUG_PROMPTS_ENABLED: DebugPromptsEnabled;
165
164
  DEBUG_PROMPTS_LOG_PATH: string;
@@ -587,7 +586,7 @@ export function getGlobalConfigPath(): string {
587
586
  * @details Populates canonical docs/test/source directories, derives local static-check enable defaults from the supplied global checker definitions, and seeds documented debug defaults including tool-wrapper command registration without any cross-project fields. Runtime is O(l). No filesystem side effects occur.
588
587
  * @param[in] globalStaticCheckConfig {Record<string, GlobalStaticCheckLanguageConfig>} Global checker definitions used to derive local enable defaults.
589
588
  * @return {UseReqLocalConfig} Fresh default local configuration object.
590
- * @satisfies CTN-019, REQ-328, REQ-413, REQ-414
589
+ * @satisfies CTN-013, CTN-019, REQ-328, REQ-413, REQ-414, REQ-426
591
590
  */
592
591
  function getDefaultLocalConfig(
593
592
  globalStaticCheckConfig: Record<string, GlobalStaticCheckLanguageConfig>,
@@ -600,7 +599,6 @@ function getDefaultLocalConfig(
600
599
  "context-files-references": DEFAULT_CONTEXT_FILES_FLAG,
601
600
  "context-files-workflow": DEFAULT_CONTEXT_FILES_FLAG,
602
601
  "static-check": getDefaultLocalStaticCheckConfig(globalStaticCheckConfig),
603
- DEBUG_ENABLED: DEFAULT_DEBUG_ENABLED,
604
602
  DEBUG_LOG_FILE: DEFAULT_DEBUG_LOG_FILE,
605
603
  DEBUG_PROMPTS_ENABLED: DEFAULT_DEBUG_PROMPTS_ENABLED,
606
604
  DEBUG_PROMPTS_LOG_PATH: DEFAULT_DEBUG_PROMPTS_LOG_PATH,
@@ -652,11 +650,11 @@ function getDefaultGlobalConfig(): UseReqGlobalConfig {
652
650
 
653
651
  /**
654
652
  * @brief Merges persisted local and global configuration scopes into the effective runtime config.
655
- * @details Normalizes local directories, combines local static-check enable flags with global checker arrays, resolves effective worktree disablement when automatic git commit is off, normalizes debug and notification fields including tool-wrapper command registration, and disables Pushover until both credentials are populated. Runtime is O(l + c + p). No external state is mutated.
653
+ * @details Normalizes local directories, combines local static-check enable flags with global checker arrays, resolves effective worktree disablement when automatic git commit is off, normalizes debug and notification fields including tool-wrapper command registration, sources the runtime-only `DEBUG_ENABLED` flag from the process-scoped debug store, and disables Pushover until both credentials are populated. Runtime is O(l + c + p). No external state is mutated.
656
654
  * @param[in] localConfig {UseReqLocalConfig} Persisted local configuration.
657
655
  * @param[in] globalConfig {UseReqGlobalConfig} Persisted global configuration.
658
656
  * @return {UseReqConfig} Effective merged configuration.
659
- * @satisfies REQ-328, REQ-413, REQ-414
657
+ * @satisfies REQ-236, REQ-328, REQ-413, REQ-414, REQ-426
660
658
  */
661
659
  function mergeConfigScopes(
662
660
  localConfig: UseReqLocalConfig,
@@ -691,7 +689,7 @@ function mergeConfigScopes(
691
689
  AUTO_GIT_COMMIT: autoGitCommit,
692
690
  GIT_WORKTREE_ENABLED: gitWorktreeEnabled,
693
691
  GIT_WORKTREE_PREFIX: normalizeGitWorktreePrefix(globalConfig.GIT_WORKTREE_PREFIX),
694
- DEBUG_ENABLED: normalizeDebugEnabled(localConfig.DEBUG_ENABLED),
692
+ DEBUG_ENABLED: getRuntimeDebugEnabled(),
695
693
  DEBUG_LOG_FILE: normalizeDebugLogFile(localConfig.DEBUG_LOG_FILE),
696
694
  DEBUG_PROMPTS_ENABLED: normalizeDebugPromptsEnabled(localConfig.DEBUG_PROMPTS_ENABLED),
697
695
  DEBUG_PROMPTS_LOG_PATH: normalizeDebugPromptsLogPath(localConfig.DEBUG_PROMPTS_LOG_PATH),
@@ -862,11 +860,11 @@ function normalizeGlobalStaticCheckConfig(
862
860
 
863
861
  /**
864
862
  * @brief Loads and sanitizes the persisted local configuration.
865
- * @details Returns defaults when `<base-path>/.pi-usereq.json` is absent. Otherwise parses the local JSON payload, normalizes project-scoped directory, debug, tool-wrapper command registration, and static-check enable fields, and ignores misplaced global keys without migration. Runtime is O(n) in file size. Side effects are limited to filesystem reads.
863
+ * @details Returns defaults when `<base-path>/.pi-usereq.json` is absent. Otherwise parses the local JSON payload, normalizes project-scoped directory, debug, tool-wrapper command registration, and static-check enable fields, ignores any persisted `DEBUG_ENABLED` payload, and ignores misplaced global keys without migration. Runtime is O(n) in file size. Side effects are limited to filesystem reads.
866
864
  * @param[in] projectBase {string} Absolute project root path.
867
865
  * @param[in] defaultStaticCheckConfig {Record<string, LocalStaticCheckLanguageConfig>} Local static-check enable defaults derived from the current global checker map.
868
866
  * @return {UseReqLocalConfig} Sanitized local configuration.
869
- * @satisfies CTN-019, REQ-328, REQ-413, REQ-414
867
+ * @satisfies CTN-019, REQ-328, REQ-413, REQ-414, REQ-426
870
868
  */
871
869
  function loadLocalConfig(
872
870
  projectBase: string,
@@ -883,7 +881,6 @@ function loadLocalConfig(
883
881
  "context-files-references": DEFAULT_CONTEXT_FILES_FLAG,
884
882
  "context-files-workflow": DEFAULT_CONTEXT_FILES_FLAG,
885
883
  "static-check": normalizeLocalStaticCheckConfig(undefined, defaultStaticCheckConfig),
886
- DEBUG_ENABLED: DEFAULT_DEBUG_ENABLED,
887
884
  DEBUG_LOG_FILE: DEFAULT_DEBUG_LOG_FILE,
888
885
  DEBUG_PROMPTS_ENABLED: DEFAULT_DEBUG_PROMPTS_ENABLED,
889
886
  DEBUG_PROMPTS_LOG_PATH: DEFAULT_DEBUG_PROMPTS_LOG_PATH,
@@ -915,7 +912,6 @@ function loadLocalConfig(
915
912
  "context-files-references": normalizeContextFilesFlag(data["context-files-references"]),
916
913
  "context-files-workflow": normalizeContextFilesFlag(data["context-files-workflow"]),
917
914
  "static-check": normalizeLocalStaticCheckConfig(data["static-check"], defaultStaticCheckConfig),
918
- DEBUG_ENABLED: normalizeDebugEnabled(data.DEBUG_ENABLED),
919
915
  DEBUG_LOG_FILE: normalizeDebugLogFile(data.DEBUG_LOG_FILE),
920
916
  DEBUG_PROMPTS_ENABLED: normalizeDebugPromptsEnabled(data.DEBUG_PROMPTS_ENABLED),
921
917
  DEBUG_PROMPTS_LOG_PATH: normalizeDebugPromptsLogPath(data.DEBUG_PROMPTS_LOG_PATH),
@@ -995,10 +991,10 @@ export function loadConfig(projectBase: string): UseReqConfig {
995
991
 
996
992
  /**
997
993
  * @brief Builds the persisted local configuration payload.
998
- * @details Copies only project-scoped keys into a fresh object so runtime-derived metadata plus global checker, tool, git, and notification fields never reach `.pi-usereq.json`, while preserving the debug tool-wrapper command flag beside other local debug settings. Runtime is O(n) in config size. No external state is mutated.
994
+ * @details Copies only project-scoped keys into a fresh object so runtime-derived metadata, the runtime-only `DEBUG_ENABLED` flag, and global checker, tool, git, and notification fields never reach `.pi-usereq.json`, while preserving the debug tool-wrapper command flag beside other persisted local debug settings. Runtime is O(n) in config size. No external state is mutated.
999
995
  * @param[in] config {UseReqConfig} Effective configuration object.
1000
996
  * @return {UseReqLocalConfig} Persistable local configuration payload.
1001
- * @satisfies CTN-012, CTN-013, CTN-019, REQ-104, REQ-146, REQ-249, REQ-316, REQ-277, REQ-328, REQ-413, REQ-414
997
+ * @satisfies CTN-012, CTN-013, CTN-019, REQ-104, REQ-146, REQ-249, REQ-316, REQ-277, REQ-328, REQ-413, REQ-414, REQ-426
1002
998
  */
1003
999
  function buildPersistedLocalConfig(config: UseReqConfig): UseReqLocalConfig {
1004
1000
  const normalizedSrcDir = config["src-dir"]
@@ -1022,7 +1018,6 @@ function buildPersistedLocalConfig(config: UseReqConfig): UseReqLocalConfig {
1022
1018
  ),
1023
1019
  ]),
1024
1020
  ),
1025
- DEBUG_ENABLED: normalizeDebugEnabled(config.DEBUG_ENABLED),
1026
1021
  DEBUG_LOG_FILE: normalizeDebugLogFile(config.DEBUG_LOG_FILE),
1027
1022
  DEBUG_PROMPTS_ENABLED: normalizeDebugPromptsEnabled(config.DEBUG_PROMPTS_ENABLED),
1028
1023
  DEBUG_PROMPTS_LOG_PATH: normalizeDebugPromptsLogPath(config.DEBUG_PROMPTS_LOG_PATH),
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file
3
3
  * @brief Declares debug inventories, normalizers, and JSON log persistence helpers.
4
- * @details Centralizes debug-menu selector inventories, config-field normalization, workflow-status gating, and append-only JSON log writing for tool, prompt, and dedicated workflow debug events. Runtime is dominated by JSON serialization plus filesystem I/O during log writes. Side effects include directory creation and file overwrite when debug entries are appended.
4
+ * @details Centralizes debug-menu selector inventories, config-field normalization, the process-scoped runtime debug-enable state, workflow-status gating, append-only JSON log writing for tool, prompt, and dedicated workflow debug events, process-scoped capture of the exact `before_provider_request` provider payload for active prompt runs, and error-stage provider payload dumps gated by `after_provider_response` error statuses. Runtime is dominated by JSON serialization plus filesystem I/O during log writes. Side effects include directory creation and file overwrite when debug entries are appended.
5
5
  */
6
6
 
7
7
  import fs from "node:fs";
@@ -24,6 +24,49 @@ import {
24
24
  */
25
25
  export const DEFAULT_DEBUG_ENABLED = "disable" as const;
26
26
 
27
+ /**
28
+ * @brief Describes the process-scoped runtime debug-enable state persisted across session rebinds.
29
+ * @details Stores the user-toggled runtime `Debug` flag on `globalThis` because pi rebinds extension modules for `/new`, `/resume`, `/fork`, and `/reload` while the hosting process persists across those operations; the flag therefore survives ctrl+N session forks and `req-reset` but resets to `disable` when a fresh pi CLI process starts. The interface is compile-time only and introduces no runtime cost.
30
+ * @satisfies REQ-236, REQ-426
31
+ */
32
+ interface ProcessScopedDebugEnabledStore {
33
+ runtimeDebugEnabled: "enable" | "disable" | undefined;
34
+ }
35
+
36
+ /**
37
+ * @brief Returns the process-scoped runtime debug-enable store.
38
+ * @details Lazily initializes one `globalThis` record so session rebinds reuse the toggled runtime debug mode instead of resetting it to the persisted default. Runtime is O(1). Side effect: initializes process-scoped state on first access.
39
+ * @return {ProcessScopedDebugEnabledStore} Mutable process-scoped runtime debug store.
40
+ */
41
+ function getProcessScopedDebugEnabledStore(): ProcessScopedDebugEnabledStore {
42
+ const globalScope = globalThis as typeof globalThis & { __piUsereqDebugEnabledStore?: ProcessScopedDebugEnabledStore };
43
+ if (!globalScope.__piUsereqDebugEnabledStore) {
44
+ globalScope.__piUsereqDebugEnabledStore = { runtimeDebugEnabled: undefined };
45
+ }
46
+ return globalScope.__piUsereqDebugEnabledStore;
47
+ }
48
+
49
+ /**
50
+ * @brief Resolves the runtime debug-enable mode for the current pi host process.
51
+ * @details Returns the process-scoped toggled value when present and the documented `disable` default otherwise, so every fresh pi CLI process starts with debug logging disabled regardless of any stale persisted payload. Runtime is O(1). No external state is mutated.
52
+ * @return {"enable" | "disable"} Effective runtime debug-enable mode.
53
+ * @satisfies REQ-236
54
+ */
55
+ export function getRuntimeDebugEnabled(): "enable" | "disable" {
56
+ return getProcessScopedDebugEnabledStore().runtimeDebugEnabled ?? DEFAULT_DEBUG_ENABLED;
57
+ }
58
+
59
+ /**
60
+ * @brief Stores one user-toggled runtime debug-enable mode for the current pi host process.
61
+ * @details Mutates only the process-scoped runtime store so `Debug` menu toggles survive session rebinds without reaching persisted local or global configuration files. Runtime is O(1). Side effect: mutates process-scoped runtime state.
62
+ * @param[in] runtimeDebugEnabled {"enable" | "disable"} Next runtime debug-enable mode.
63
+ * @return {void} No return value.
64
+ * @satisfies REQ-236, REQ-426
65
+ */
66
+ export function setRuntimeDebugEnabled(runtimeDebugEnabled: "enable" | "disable"): void {
67
+ getProcessScopedDebugEnabledStore().runtimeDebugEnabled = runtimeDebugEnabled;
68
+ }
69
+
27
70
  /**
28
71
  * @brief Defines the default debug log file value.
29
72
  * @details New configurations write debug JSON entries to `/tmp/PI-useReq.json` unless the user overrides the path. Access complexity is O(1).
@@ -442,10 +485,10 @@ export function shouldLogDebugPromptWorkflowEvent(
442
485
 
443
486
  /**
444
487
  * @brief Tests whether one dispatched prompt content file should be written.
445
- * @details Requires global debug enablement, explicit prompt-content debug enablement, and a matching workflow-state filter before any filesystem work occurs; prompt-content logging is therefore fully subordinate to the global `Debug` flag. Runtime is O(1). No external state is mutated.
488
+ * @details Requires global debug enablement plus explicit prompt-content debug enablement before any filesystem work occurs; prompt-content logging is fully subordinate to the global `Debug` flag and exempt from the `DEBUG_LOG_ON_STATUS` workflow-state filter so enabled runs always save their debug files. Runtime is O(1). No external state is mutated.
446
489
  * @param[in] config {UseReqConfig} Effective project configuration.
447
- * @param[in] workflowState {DebugWorkflowState} Current workflow state.
448
- * @param[in] promptName {PromptCommandName} Bundled prompt name.
490
+ * @param[in] workflowState {DebugWorkflowState} Current workflow state; retained for signature compatibility and excluded from gating per REQ-416.
491
+ * @param[in] promptName {PromptCommandName} Bundled prompt name; retained for signature compatibility.
449
492
  * @return {boolean} `true` when the prompt content file should be written.
450
493
  * @satisfies REQ-413, REQ-416
451
494
  */
@@ -455,8 +498,7 @@ export function shouldLogDebugPromptContent(
455
498
  promptName: PromptCommandName,
456
499
  ): boolean {
457
500
  return normalizeDebugEnabled(config.DEBUG_ENABLED) === "enable"
458
- && normalizeDebugPromptsEnabled(config.DEBUG_PROMPTS_ENABLED) === "enable"
459
- && matchesDebugWorkflowState(normalizeDebugLogOnStatus(config.DEBUG_LOG_ON_STATUS), workflowState);
501
+ && normalizeDebugPromptsEnabled(config.DEBUG_PROMPTS_ENABLED) === "enable";
460
502
  }
461
503
 
462
504
  /**
@@ -680,16 +722,107 @@ export function formatPromptDebugFileName(
680
722
  return `${formatPromptDebugTimestamp(date)}-${getDebugPromptName(promptName)}`;
681
723
  }
682
724
 
725
+ /**
726
+ * @brief Builds one command-invocation summary debug filename for one bundled prompt.
727
+ * @details Appends the `-request` suffix to the shared `<timestamp>-<req-command>` base so every saved command invocation summary stays attributable to the originating `/req-*` prompt. Runtime is O(1). No external state is mutated.
728
+ * @param[in] promptName {PromptCommandName} Bundled prompt name.
729
+ * @param[in] date {Date} Write-time timestamp. Defaults to the current wall-clock time.
730
+ * @return {string} Prompt debug filename in the `<timestamp>-<req-command>-request` shape.
731
+ * @satisfies REQ-417, REQ-427
732
+ */
733
+ export function formatPromptDebugRequestFileName(
734
+ promptName: PromptCommandName,
735
+ date = new Date(),
736
+ ): string {
737
+ return `${formatPromptDebugFileName(promptName, date)}-request`;
738
+ }
739
+
740
+ /**
741
+ * @brief Builds one dispatched-prompt content debug filename for one bundled prompt.
742
+ * @details Appends the `-prompt` suffix to the shared `<timestamp>-<req-command>` base so every saved initial LLM prompt stays attributable to the originating `/req-*` prompt. Runtime is O(1). No external state is mutated.
743
+ * @param[in] promptName {PromptCommandName} Bundled prompt name.
744
+ * @param[in] date {Date} Write-time timestamp. Defaults to the current wall-clock time.
745
+ * @return {string} Prompt debug filename in the `<timestamp>-<req-command>-prompt` shape.
746
+ * @satisfies REQ-417, REQ-418
747
+ */
748
+ export function formatPromptDebugPromptFileName(
749
+ promptName: PromptCommandName,
750
+ date = new Date(),
751
+ ): string {
752
+ return `${formatPromptDebugFileName(promptName, date)}-prompt`;
753
+ }
754
+
755
+ /**
756
+ * @brief Writes one gated prompt debug file under the configured prompt log directory.
757
+ * @details Applies the global-debug plus prompt-debug gating, creates the configured prompt log directory, and writes the supplied text into the requested filename so dispatched-prompt artifacts can be replayed from the pi CLI without pi-usereq installed. Runtime is dominated by one directory creation plus one file write when enabled and O(1) otherwise. Side effects include directory creation and file creation only for enabled matching entries.
758
+ * @param[in] projectBase {string} Absolute original project base path.
759
+ * @param[in] config {UseReqConfig} Effective project configuration.
760
+ * @param[in] workflowState {DebugWorkflowState} Current workflow state; excluded from gating per REQ-416.
761
+ * @param[in] promptName {PromptCommandName} Bundled prompt name.
762
+ * @param[in] fileName {string} Target filename under the resolved prompt log directory.
763
+ * @param[in] content {string} Exact text to persist.
764
+ * @return {boolean} `true` when the file is written; otherwise `false`.
765
+ * @satisfies REQ-416
766
+ */
767
+ function writePromptDebugFile(
768
+ projectBase: string,
769
+ config: UseReqConfig,
770
+ workflowState: DebugWorkflowState,
771
+ promptName: PromptCommandName,
772
+ fileName: string,
773
+ content: string,
774
+ ): boolean {
775
+ if (!shouldLogDebugPromptContent(config, workflowState, promptName)) {
776
+ return false;
777
+ }
778
+ const logDirectory = resolveDebugPromptsLogPath(projectBase, config);
779
+ try {
780
+ fs.mkdirSync(logDirectory, { recursive: true });
781
+ fs.writeFileSync(path.join(logDirectory, fileName), content, "utf8");
782
+ return true;
783
+ } catch {
784
+ return false;
785
+ }
786
+ }
787
+
788
+ /**
789
+ * @brief Writes one command invocation summary debug file when prompt debug logging is enabled.
790
+ * @details Persists the exact summary text displayed on screen into one `<timestamp>-<req-command>-request` file so the `/req-*` invocation headers survive beside the dispatched prompt. Runtime is dominated by one directory creation plus one file write when enabled and O(1) otherwise. Side effects include directory creation and file creation only for enabled matching entries.
791
+ * @param[in] projectBase {string} Absolute original project base path.
792
+ * @param[in] config {UseReqConfig} Effective project configuration.
793
+ * @param[in] workflowState {DebugWorkflowState} Current workflow state; excluded from gating per REQ-416.
794
+ * @param[in] promptName {PromptCommandName} Bundled prompt name.
795
+ * @param[in] requestText {string} Exact command invocation summary text displayed on screen.
796
+ * @return {boolean} `true` when the request file is written; otherwise `false`.
797
+ * @satisfies REQ-416, REQ-417, REQ-427, REQ-428
798
+ */
799
+ export function logDebugPromptRequest(
800
+ projectBase: string,
801
+ config: UseReqConfig,
802
+ workflowState: DebugWorkflowState,
803
+ promptName: PromptCommandName,
804
+ requestText: string,
805
+ ): boolean {
806
+ return writePromptDebugFile(
807
+ projectBase,
808
+ config,
809
+ workflowState,
810
+ promptName,
811
+ formatPromptDebugRequestFileName(promptName),
812
+ requestText,
813
+ );
814
+ }
815
+
683
816
  /**
684
817
  * @brief Writes one dispatched prompt content file when prompt debug logging is enabled.
685
- * @details Applies global-debug, prompt-debug, and workflow-state gating before creating the configured prompt log directory and writing the exact delivered prompt content into one `<timestamp>-<req-command>` file so the send can be replayed from the pi CLI without pi-usereq installed. Runtime is dominated by one directory creation plus one file write when enabled and O(1) otherwise. Side effects include directory creation and file creation only for enabled matching entries.
818
+ * @details Persists the exact rendered prompt content delivered through `sendMessage` or `sendUserMessage` into one `<timestamp>-<req-command>-prompt` file so the send can be replayed from the pi CLI without pi-usereq installed. Runtime is dominated by one directory creation plus one file write when enabled and O(1) otherwise. Side effects include directory creation and file creation only for enabled matching entries.
686
819
  * @param[in] projectBase {string} Absolute original project base path.
687
820
  * @param[in] config {UseReqConfig} Effective project configuration.
688
- * @param[in] workflowState {DebugWorkflowState} Current workflow state.
821
+ * @param[in] workflowState {DebugWorkflowState} Current workflow state; excluded from gating per REQ-416.
689
822
  * @param[in] promptName {PromptCommandName} Bundled prompt name.
690
823
  * @param[in] content {string} Exact rendered prompt content delivered through `sendMessage` or `sendUserMessage`.
691
824
  * @return {boolean} `true` when the prompt content file is written; otherwise `false`.
692
- * @satisfies REQ-416, REQ-417, REQ-418
825
+ * @satisfies REQ-416, REQ-417, REQ-418, REQ-428
693
826
  */
694
827
  export function logDebugPromptContent(
695
828
  projectBase: string,
@@ -698,15 +831,152 @@ export function logDebugPromptContent(
698
831
  promptName: PromptCommandName,
699
832
  content: string,
700
833
  ): boolean {
701
- if (!shouldLogDebugPromptContent(config, workflowState, promptName)) {
834
+ return writePromptDebugFile(
835
+ projectBase,
836
+ config,
837
+ workflowState,
838
+ promptName,
839
+ formatPromptDebugPromptFileName(promptName),
840
+ content,
841
+ );
842
+ }
843
+
844
+ /**
845
+ * @brief Describes one process-scoped captured provider request payload bound to an active prompt run.
846
+ * @details Pairs the bundled prompt name, the serialization of the exact `before_provider_request` payload, the original project base, and the resolved prompt log directory so a later `after_provider_response` error status can dump the failing request verbatim without live controller state, cached configuration, or live provider objects. The interface is compile-time only and introduces no runtime cost.
847
+ * @satisfies REQ-421
848
+ */
849
+ interface CapturedPromptErrorPayload {
850
+ promptName: PromptCommandName;
851
+ payloadText: string;
852
+ projectBase: string;
853
+ logDirectory: string;
854
+ }
855
+
856
+ /**
857
+ * @brief Describes the process-scoped provider error payload capture state persisted across extension rebinds.
858
+ * @details Stores the latest captured prompt error payload on `globalThis` because pi rebinds extension modules for `/new`, `/resume`, `/fork`, and `/reload` between prompt dispatch and provider execution, while the hosting process persists across those operations, so the capture survives the forked execution-session switch. The interface is compile-time only and introduces no runtime cost.
859
+ */
860
+ interface ProcessScopedPromptErrorCaptureStore {
861
+ capturedPromptErrorPayload: CapturedPromptErrorPayload | undefined;
862
+ }
863
+
864
+ /**
865
+ * @brief Returns the process-scoped provider error payload capture store.
866
+ * @details Lazily initializes one `globalThis` record so session rebinds never discard an already captured failing provider request. Runtime is O(1). Side effect: initializes process-scoped state on first access.
867
+ * @return {ProcessScopedPromptErrorCaptureStore} Mutable process-scoped capture store.
868
+ */
869
+ function getProcessScopedPromptErrorCaptureStore(): ProcessScopedPromptErrorCaptureStore {
870
+ const globalScope = globalThis as typeof globalThis & { __piUsereqPromptErrorCaptureStore?: ProcessScopedPromptErrorCaptureStore };
871
+ if (!globalScope.__piUsereqPromptErrorCaptureStore) {
872
+ globalScope.__piUsereqPromptErrorCaptureStore = { capturedPromptErrorPayload: undefined };
873
+ }
874
+ return globalScope.__piUsereqPromptErrorCaptureStore;
875
+ }
876
+
877
+ /**
878
+ * @brief Builds one provider error payload debug filename for one bundled prompt.
879
+ * @details Combines the write-time `YYYYMMDDHHMMSSmmm` timestamp, the invokable `req-*` command name, and the failing provider response status into the `<timestamp>-<req-command>-error-<status>` shape so every saved error-stage prompt payload stays attributable to the originating `/req-*` prompt and its session error code. Runtime is O(1). No external state is mutated.
880
+ * @param[in] promptName {PromptCommandName} Bundled prompt name.
881
+ * @param[in] errorCode {number} Failing provider response status, such as `400`.
882
+ * @param[in] date {Date} Write-time timestamp. Defaults to the current wall-clock time.
883
+ * @return {string} Provider error payload filename in the `<timestamp>-<req-command>-error-<status>` shape.
884
+ * @satisfies REQ-423
885
+ */
886
+ export function formatPromptDebugErrorFileName(
887
+ promptName: PromptCommandName,
888
+ errorCode: number,
889
+ date = new Date(),
890
+ ): string {
891
+ return `${formatPromptDebugTimestamp(date)}-${getDebugPromptName(promptName)}-error-${errorCode}`;
892
+ }
893
+
894
+ /**
895
+ * @brief Serializes one provider request payload into deterministic text.
896
+ * @details Pretty-prints the payload as JSON while degrading circular references into one `[Circular]` token and bigint values into decimal strings so serialization failures never discard the capture. Runtime is O(n) in serialized payload size. No external state is mutated.
897
+ * @param[in] payload {unknown} Exact `before_provider_request` provider request payload.
898
+ * @return {string} Serialized payload text; the empty string when the payload serializes to nothing.
899
+ */
900
+ function serializePromptProviderPayload(payload: unknown): string {
901
+ const seenObjects = new WeakSet<object>();
902
+ return JSON.stringify(
903
+ payload,
904
+ (_key: string, value: unknown) => {
905
+ if (typeof value === "bigint") {
906
+ return value.toString();
907
+ }
908
+ if (typeof value === "object" && value !== null) {
909
+ if (seenObjects.has(value)) {
910
+ return "[Circular]";
911
+ }
912
+ seenObjects.add(value);
913
+ }
914
+ return value;
915
+ },
916
+ 2,
917
+ ) ?? "";
918
+ }
919
+
920
+ /**
921
+ * @brief Captures one exact provider request payload for the active prompt run when prompt debug logging is enabled.
922
+ * @details Applies the global-debug plus prompt-debug gating, serializes the exact `before_provider_request` payload through the cycle-safe serializer, and stores the prompt name, payload text, original project base, and resolved prompt log directory in the process-scoped capture store so the payload survives session replacement and later error-stage writes require no live workflow state or cached configuration. Runtime is O(n) in serialized payload size when enabled and O(1) otherwise. Side effect: mutates the process-scoped capture store for enabled matching requests.
923
+ * @param[in] config {UseReqConfig} Effective project configuration.
924
+ * @param[in] promptName {PromptCommandName} Active bundled prompt name.
925
+ * @param[in] projectBase {string} Absolute original project base path used to resolve the prompt log directory.
926
+ * @param[in] payload {unknown} Exact `before_provider_request` provider request payload.
927
+ * @return {void} No return value.
928
+ * @satisfies REQ-416, REQ-421
929
+ */
930
+ export function capturePromptProviderRequestForDebug(
931
+ config: UseReqConfig,
932
+ promptName: PromptCommandName,
933
+ projectBase: string,
934
+ payload: unknown,
935
+ ): void {
936
+ if (!shouldLogDebugPromptContent(config, "unknown", promptName)) {
937
+ return;
938
+ }
939
+ getProcessScopedPromptErrorCaptureStore().capturedPromptErrorPayload = {
940
+ promptName,
941
+ payloadText: serializePromptProviderPayload(payload),
942
+ projectBase,
943
+ logDirectory: resolveDebugPromptsLogPath(projectBase, config),
944
+ };
945
+ }
946
+
947
+ /**
948
+ * @brief Writes the captured provider request payload as one error-stage prompt debug file for the failing prompt.
949
+ * @details Consumes the process-scoped capture, discards it after every write attempt so stale payloads never reach later runs, rejects failing statuses below 400, and writes the exact captured payload into one `<timestamp>-<req-command>-error-<status>` file inside the captured log directory beside the initial dispatched prompt artifacts. All write inputs come from the capture itself, so the flush requires no live workflow state, cached configuration, or active controller prompt request. Runtime is dominated by one directory creation plus one file write when a capture exists and O(1) otherwise. Side effects include directory creation and file creation only when a capture exists and the status is an error status.
950
+ * @param[in] errorCode {number} Failing provider response status, such as `400`.
951
+ * @return {boolean} `true` when the provider error payload file is written; otherwise `false`.
952
+ * @satisfies REQ-422, REQ-423, REQ-424, REQ-425
953
+ */
954
+ export function flushCapturedPromptErrorPayload(errorCode: number): boolean {
955
+ const captureStore = getProcessScopedPromptErrorCaptureStore();
956
+ const captured = captureStore.capturedPromptErrorPayload;
957
+ captureStore.capturedPromptErrorPayload = undefined;
958
+ if (!captured || !Number.isFinite(errorCode) || errorCode < 400) {
702
959
  return false;
703
960
  }
704
- const logDirectory = resolveDebugPromptsLogPath(projectBase, config);
705
961
  try {
706
- fs.mkdirSync(logDirectory, { recursive: true });
707
- fs.writeFileSync(path.join(logDirectory, formatPromptDebugFileName(promptName)), content, "utf8");
962
+ fs.mkdirSync(captured.logDirectory, { recursive: true });
963
+ fs.writeFileSync(
964
+ path.join(captured.logDirectory, formatPromptDebugErrorFileName(captured.promptName, errorCode)),
965
+ captured.payloadText,
966
+ "utf8",
967
+ );
708
968
  return true;
709
969
  } catch {
710
970
  return false;
711
971
  }
712
972
  }
973
+
974
+ /**
975
+ * @brief Discards any captured provider request payload for the ended prompt run.
976
+ * @details Clears the process-scoped capture unconditionally so leftover payloads from a finished `req-*` prompt run never flush into later provider errors raised outside extension-owned prompt orchestration. Runtime is O(1). Side effect: mutates the process-scoped capture store.
977
+ * @return {void} No return value.
978
+ * @satisfies REQ-421, REQ-425
979
+ */
980
+ export function discardCapturedPromptErrorPayload(): void {
981
+ getProcessScopedPromptErrorCaptureStore().capturedPromptErrorPayload = undefined;
982
+ }
@@ -74,6 +74,7 @@ export const PI_USEREQ_STATUS_HOOK_NAMES = [
74
74
  "session_tree",
75
75
  "context",
76
76
  "before_provider_request",
77
+ "after_provider_response",
77
78
  "before_agent_start",
78
79
  "agent_start",
79
80
  "agent_end",
package/src/index.ts CHANGED
@@ -133,8 +133,12 @@ import {
133
133
  DEFAULT_DEBUG_STATUS_CHANGES,
134
134
  DEFAULT_DEBUG_TOOL_COMMANDS_ENABLED,
135
135
  DEFAULT_DEBUG_WORKFLOW_EVENTS,
136
+ capturePromptProviderRequestForDebug,
137
+ discardCapturedPromptErrorPayload,
138
+ flushCapturedPromptErrorPayload,
136
139
  logDebugPromptContent,
137
140
  logDebugPromptEvent,
141
+ logDebugPromptRequest,
138
142
  logDebugPromptWorkflowEvent,
139
143
  logDebugToolExecution,
140
144
  normalizeDebugEnabledPrompts,
@@ -146,6 +150,7 @@ import {
146
150
  normalizeDebugStatusChanges,
147
151
  normalizeDebugToolCommandsEnabled,
148
152
  normalizeDebugWorkflowEvents,
153
+ setRuntimeDebugEnabled,
149
154
  shouldLogDebugPromptWorkflowState,
150
155
  type DebugLogOnStatus,
151
156
  type DebugWorkflowState,
@@ -1443,14 +1448,14 @@ async function finalizeMatchedPromptSuccess(
1443
1448
 
1444
1449
  /**
1445
1450
  * @brief Handles one intercepted pi lifecycle hook for pi-usereq status updates.
1446
- * @details Applies session-start-specific resource validation, project-config refresh, idle-time shared-tokenizer and context-file measurement pre-warm, startup-tool enablement, and selected debug-tool logging before forwarding the originating hook name and payload into the shared `updateExtensionStatus(...)` pipeline. Before `agent_start`, re-verifies any prepared prompt execution session switch. On `agent_end`, dispatches configured command-notify, sound, and prompt-specific Pushover effects, logs dedicated workflow-closure diagnostics, classifies the prompt outcome, and for every matched successful worktree-backed completion defers the restore switch, stash-assisted merge, and worktree deletion to `agent_settled` when the running pi host supports that 0.80.4+ event (because its `switchSession` awaits the active agent run to become idle and would deadlock inside `agent_end`), or executes the finalization directly at `agent_end` when the host does not emit `agent_settled`. On `agent_settled`, reuses persisted replacement-session command contexts when event contexts omit `switchSession()`, executes the deferred stash-assisted merge-and-delete finalization path, emits a warning-only notification when restored `base-path` changes are reapplied after merge, tolerates stale replacement-session notification contexts after session replacement, retains the worktree plus notifies closure failure for interrupted or failed outcomes, logs selected prompt workflow transitions, and transitions workflow state through `merging`, `error`, and `idle` as required. On `session_shutdown`, captures pre-update prompt snapshots so workflow-shutdown diagnostics and same-runtime command continuation preserve the active prompt workflow state across switch-triggered rebinding, then disposes the shared controller. Runtime is dominated by configuration loading during `session_start` and git finalization during matched successful closure handling; all other hooks are O(1). Side effects include resource checks, active-tool mutation, active-session replacement, status updates, live-ticker disposal on shutdown, optional child-process spawning, outbound HTTPS requests, branch merges, worktree deletion, and optional debug-log writes.
1451
+ * @details Applies session-start-specific resource validation, project-config refresh, idle-time shared-tokenizer and context-file measurement pre-warm, startup-tool enablement, and selected debug-tool logging before forwarding the originating hook name and payload into the shared `updateExtensionStatus(...)` pipeline. After the status update, captures the exact `before_provider_request` provider payload for the live active or pending prompt run with a fresh config fallback when the controller has no cached config, flushes the process-scoped captured payload as one `<timestamp>-<req-command>-error-<status>` file whenever `after_provider_response` reports a status >= 400 without requiring live workflow state, and discards the capture at prompt-run end so stale payloads never reach later runs. Before `agent_start`, re-verifies any prepared prompt execution session switch. On `agent_end`, dispatches configured command-notify, sound, and prompt-specific Pushover effects, logs dedicated workflow-closure diagnostics, classifies the prompt outcome, and for every matched successful worktree-backed completion defers the restore switch, stash-assisted merge, and worktree deletion to `agent_settled` when the running pi host supports that 0.80.4+ event (because its `switchSession` awaits the active agent run to become idle and would deadlock inside `agent_end`), or executes the finalization directly at `agent_end` when the host does not emit `agent_settled`. On `agent_settled`, reuses persisted replacement-session command contexts when event contexts omit `switchSession()`, executes the deferred stash-assisted merge-and-delete finalization path, emits a warning-only notification when restored `base-path` changes are reapplied after merge, tolerates stale replacement-session notification contexts after session replacement, retains the worktree plus notifies closure failure for interrupted or failed outcomes, logs selected prompt workflow transitions, and transitions workflow state through `merging`, `error`, and `idle` as required. On `session_shutdown`, captures pre-update prompt snapshots so workflow-shutdown diagnostics and same-runtime command continuation preserve the active prompt workflow state across switch-triggered rebinding, then disposes the shared controller. Runtime is dominated by configuration loading during `session_start` and git finalization during matched successful closure handling; all other hooks are O(1). Side effects include resource checks, active-tool mutation, active-session replacement, status updates, live-ticker disposal on shutdown, optional child-process spawning, outbound HTTPS requests, branch merges, worktree deletion, and optional debug-log writes.
1447
1452
  * @param[in] pi {ExtensionAPI} Active extension API instance.
1448
1453
  * @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
1449
1454
  * @param[in] hookName {PiUsereqStatusHookName} Intercepted hook name.
1450
1455
  * @param[in] event {unknown} Hook payload forwarded by pi.
1451
1456
  * @param[in] ctx {ExtensionContext} Active extension context.
1452
1457
  * @return {Promise<void>} Promise resolved when hook processing completes.
1453
- * @satisfies REQ-117, REQ-118, REQ-119, REQ-131, REQ-132, REQ-133, REQ-166, REQ-167, REQ-168, REQ-169, REQ-172, REQ-176, REQ-178, REQ-184, REQ-185, REQ-186, REQ-187, REQ-208, REQ-209, REQ-221, REQ-228, REQ-229, REQ-230, REQ-244, REQ-245, REQ-246, REQ-247, REQ-276, REQ-277, REQ-278, REQ-279, REQ-280, REQ-291, REQ-292
1458
+ * @satisfies REQ-117, REQ-118, REQ-119, REQ-131, REQ-132, REQ-133, REQ-166, REQ-167, REQ-168, REQ-169, REQ-172, REQ-176, REQ-178, REQ-184, REQ-185, REQ-186, REQ-187, REQ-208, REQ-209, REQ-221, REQ-228, REQ-229, REQ-230, REQ-244, REQ-245, REQ-246, REQ-247, REQ-276, REQ-277, REQ-278, REQ-279, REQ-280, REQ-291, REQ-292, REQ-421, REQ-422, REQ-425
1454
1459
  */
1455
1460
  async function handleExtensionStatusEvent(
1456
1461
  pi: ExtensionAPI,
@@ -1509,6 +1514,31 @@ async function handleExtensionStatusEvent(
1509
1514
  }
1510
1515
  : undefined;
1511
1516
  updateExtensionStatus(statusController, hookName, event, ctx);
1517
+ // Provider payload capture and error flush read the LIVE post-update controller state and fall
1518
+ // back to a fresh config load: after switchSession rebinds the extension, the entry-read
1519
+ // `activePromptRequest` snapshot can be stale, `agent_start` promotion may lag one hook, and the
1520
+ // replacement-session instance may not have cached config yet. The process-scoped capture store
1521
+ // carries everything the error-stage write needs, so the flush itself is state-independent.
1522
+ const livePromptRequest = statusController.state.activePromptRequest
1523
+ ?? statusController.state.pendingPromptRequest;
1524
+ if (hookName === "before_provider_request" && livePromptRequest !== undefined) {
1525
+ const providerRequestEvent = event as { payload?: unknown };
1526
+ capturePromptProviderRequestForDebug(
1527
+ statusController.config ?? loadProjectConfig(resolveLiveBootstrapCwd(ctx.cwd)),
1528
+ livePromptRequest.promptName,
1529
+ livePromptRequest.basePath,
1530
+ providerRequestEvent.payload,
1531
+ );
1532
+ }
1533
+ if (hookName === "after_provider_response") {
1534
+ const providerResponseEvent = event as { status?: unknown };
1535
+ if (typeof providerResponseEvent.status === "number" && providerResponseEvent.status >= 400) {
1536
+ flushCapturedPromptErrorPayload(providerResponseEvent.status);
1537
+ }
1538
+ }
1539
+ if (hookName === "agent_end" || hookName === "agent_settled") {
1540
+ discardCapturedPromptErrorPayload();
1541
+ }
1512
1542
  if (hookName === "tool_result" && statusController.config) {
1513
1543
  const toolEvent = event as {
1514
1544
  toolName?: string;
@@ -1783,13 +1813,14 @@ function getDebugToolToggleNames(): PiUsereqStartupToolName[] {
1783
1813
 
1784
1814
  /**
1785
1815
  * @brief Restores the debug configuration subtree to its documented defaults.
1786
- * @details Resets global debug enablement, log path, prompt-content debug enablement plus prompt log path, tool-wrapper command registration, workflow-state filter, dedicated workflow-event logging, and selected tool plus prompt debug toggles without mutating unrelated settings. Runtime is O(1). Side effect: mutates `config`.
1816
+ * @details Resets runtime debug enablement in both the effective config object and the process-scoped runtime debug store, then resets log path, prompt-content debug enablement plus prompt log path, tool-wrapper command registration, workflow-state filter, dedicated workflow-event logging, and selected tool plus prompt debug toggles without mutating unrelated settings. Runtime is O(1). Side effect: mutates `config` and process-scoped runtime debug state.
1787
1817
  * @param[in,out] config {UseReqConfig} Mutable configuration object.
1788
1818
  * @return {void} No return value.
1789
- * @satisfies REQ-236, REQ-237, REQ-238, REQ-239, REQ-195, REQ-277, REQ-322, REQ-413, REQ-414, REQ-420
1819
+ * @satisfies REQ-236, REQ-237, REQ-238, REQ-239, REQ-195, REQ-277, REQ-322, REQ-413, REQ-414, REQ-420, REQ-426
1790
1820
  */
1791
1821
  function resetDebugConfigToDefaults(config: UseReqConfig): void {
1792
1822
  config.DEBUG_ENABLED = "disable";
1823
+ setRuntimeDebugEnabled("disable");
1793
1824
  config.DEBUG_LOG_FILE = DEFAULT_DEBUG_LOG_FILE;
1794
1825
  config.DEBUG_PROMPTS_ENABLED = DEFAULT_DEBUG_PROMPTS_ENABLED;
1795
1826
  config.DEBUG_PROMPTS_LOG_PATH = DEFAULT_DEBUG_PROMPTS_LOG_PATH;
@@ -1991,12 +2022,12 @@ function buildDebugMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice
1991
2022
 
1992
2023
  /**
1993
2024
  * @brief Runs the interactive Debug submenu.
1994
- * @details Lets the user toggle global debug enablement, prompt-content debug enablement plus prompt log path, tool-wrapper command registration, debug file and workflow filters, dedicated workflow-event logging, per-tool selectors, and per-prompt selectors while preserving row focus across re-renders. Runtime depends on user interaction count. Side effects include UI updates, config mutation, and optional debug command registration.
2025
+ * @details Lets the user toggle runtime global debug enablement (stored only in the process-scoped runtime debug store and never persisted), prompt-content debug enablement plus prompt log path, tool-wrapper command registration, debug file and workflow filters, dedicated workflow-event logging, per-tool selectors, and per-prompt selectors while preserving row focus across re-renders. Runtime depends on user interaction count. Side effects include UI updates, config mutation, process-scoped runtime debug state mutation, and optional debug command registration.
1995
2026
  * @param[in] pi {ExtensionAPI} Active extension API instance.
1996
2027
  * @param[in] ctx {ExtensionCommandContext} Active command context.
1997
2028
  * @param[in,out] config {UseReqConfig} Mutable configuration object.
1998
2029
  * @return {Promise<void>} Promise resolved when the submenu closes.
1999
- * @satisfies REQ-236, REQ-237, REQ-238, REQ-239, REQ-240, REQ-241, REQ-242, REQ-243, REQ-192, REQ-193, REQ-195, REQ-277, REQ-321, REQ-322, REQ-323, REQ-413, REQ-414, REQ-415, REQ-420
2030
+ * @satisfies REQ-236, REQ-237, REQ-238, REQ-239, REQ-240, REQ-241, REQ-242, REQ-243, REQ-192, REQ-193, REQ-195, REQ-277, REQ-321, REQ-322, REQ-323, REQ-413, REQ-414, REQ-415, REQ-420, REQ-426
2000
2031
  */
2001
2032
  async function configureDebugMenu(
2002
2033
  pi: ExtensionAPI,
@@ -2021,6 +2052,7 @@ async function configureDebugMenu(
2021
2052
  onChange: (choiceId, newValue) => {
2022
2053
  if (choiceId === "debug-enabled") {
2023
2054
  config.DEBUG_ENABLED = newValue === "enable" ? "enable" : "disable";
2055
+ setRuntimeDebugEnabled(config.DEBUG_ENABLED);
2024
2056
  onConfigChange();
2025
2057
  ctx.ui.notify(`Debug ${config.DEBUG_ENABLED}`, "info");
2026
2058
  return;
@@ -2087,6 +2119,7 @@ async function configureDebugMenu(
2087
2119
 
2088
2120
  if (choice === "debug-enabled") {
2089
2121
  config.DEBUG_ENABLED = config.DEBUG_ENABLED === "enable" ? "disable" : "enable";
2122
+ setRuntimeDebugEnabled(config.DEBUG_ENABLED);
2090
2123
  onConfigChange();
2091
2124
  ctx.ui.notify(`Debug ${config.DEBUG_ENABLED}`, "info");
2092
2125
  continue;
@@ -3430,11 +3463,11 @@ function registerReqReferencesCommand(
3430
3463
 
3431
3464
  /**
3432
3465
  * @brief Registers bundled prompt-backed commands with the extension.
3433
- * @details Creates one prompt-template-backed `req-<prompt>` command per bundled prompt name. Each handler rejects non-`idle` workflow state by transitioning the shared workflow state to `error` before command-side preflight, otherwise transitions the shared workflow state through `checking`, `error`, and `running`, runs dedicated prompt-command git and required-doc preflight checks, optionally prepares a dedicated worktree execution plan using the active session directory, persists the prompt metadata needed for switch-triggered rebinding, switches the active session to the verified execution cwd before prompt handoff, logs dedicated workflow-activation diagnostics, renders the prompt, starts prompt delivery into the forked active session, records `running` immediately after delivery handoff begins, saves the exact delivered prompt content into the debug prompt log path when prompt debug logging is enabled, and then awaits the wrapped prompt-delivery promise whose stale post-restore rejections are suppressed. Runtime is O(p) for registration; handler cost depends on prompt preflight, worktree preparation, session switching, prompt rendering, prompt dispatch, and optional debug logging. Side effects include command registration, status-controller mutation, worktree creation, active-session replacement, optional worktree rollback, optional prompt-content debug file creation, user-message delivery during execution, and optional debug-log writes.
3466
+ * @details Creates one prompt-template-backed `req-<prompt>` command per bundled prompt name. Each handler rejects non-`idle` workflow state by transitioning the shared workflow state to `error` before command-side preflight, otherwise transitions the shared workflow state through `checking`, `error`, and `running`, runs dedicated prompt-command git and required-doc preflight checks, optionally prepares a dedicated worktree execution plan using the active session directory, persists the prompt metadata needed for switch-triggered rebinding, switches the active session to the verified execution cwd before prompt handoff, logs dedicated workflow-activation diagnostics, renders the prompt, starts prompt delivery into the forked active session, records `running` immediately after delivery handoff begins, saves the exact command invocation summary plus the delivered prompt content into the debug prompt log path as separate `-request` and `-prompt` files when prompt debug logging is enabled, and then awaits the wrapped prompt-delivery promise whose stale post-restore rejections are suppressed. Runtime is O(p) for registration; handler cost depends on prompt preflight, worktree preparation, session switching, prompt rendering, prompt dispatch, and optional debug logging. Side effects include command registration, status-controller mutation, worktree creation, active-session replacement, optional worktree rollback, optional prompt-debug file creation, user-message delivery during execution, and optional debug-log writes.
3434
3467
  * @param[in] pi {ExtensionAPI} Active extension API instance.
3435
3468
  * @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
3436
3469
  * @return {void} No return value.
3437
- * @satisfies REQ-004, REQ-067, REQ-068, REQ-169, REQ-200, REQ-201, REQ-202, REQ-203, REQ-206, REQ-207, REQ-219, REQ-220, REQ-221, REQ-224, REQ-225, REQ-226, REQ-227, REQ-245, REQ-246, REQ-247, REQ-277, REQ-281, REQ-377, REQ-416, REQ-417, REQ-418
3470
+ * @satisfies REQ-004, REQ-067, REQ-068, REQ-169, REQ-200, REQ-201, REQ-202, REQ-203, REQ-206, REQ-207, REQ-219, REQ-220, REQ-221, REQ-224, REQ-225, REQ-226, REQ-227, REQ-245, REQ-246, REQ-247, REQ-277, REQ-281, REQ-377, REQ-416, REQ-417, REQ-418, REQ-427, REQ-428
3438
3471
  */
3439
3472
  function registerPromptCommands(
3440
3473
  pi: ExtensionAPI,
@@ -3540,6 +3573,13 @@ function registerPromptCommands(
3540
3573
  promptName,
3541
3574
  "running",
3542
3575
  );
3576
+ logDebugPromptRequest(
3577
+ projectBase,
3578
+ config,
3579
+ statusController.state.workflowState,
3580
+ promptName,
3581
+ commandSummary,
3582
+ );
3543
3583
  logDebugPromptContent(
3544
3584
  projectBase,
3545
3585
  config,