pi-usereq 0.39.0 → 0.41.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/CHANGELOG.md +52 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/pi-usereq/docs/REFERENCES.md +286 -274
- package/pi-usereq/docs/REQUIREMENTS.md +12 -4
- package/pi-usereq/docs/WORKFLOW.md +7 -5
- package/src/core/config.ts +3 -3
- package/src/core/prompt-command-runtime.ts +6 -6
- package/src/core/prompts.ts +69 -1
- package/src/core/req-references-command.ts +3 -3
- package/src/core/req-reset-command.ts +3 -3
- package/src/core/runtime-project-paths.ts +3 -3
- package/src/index.ts +62 -6
- package/tests/extension-registration.test.ts +290 -0
- package/tests/prompt-command-summary.test.ts +36 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "PI-useReq Requirements"
|
|
3
3
|
description: Software requirements specification
|
|
4
|
-
version: "0.0.
|
|
5
|
-
date: "2026-07-
|
|
4
|
+
version: "0.0.73"
|
|
5
|
+
date: "2026-07-10"
|
|
6
6
|
author: "OpenAI Codex"
|
|
7
7
|
scope:
|
|
8
8
|
paths:
|
|
@@ -89,6 +89,7 @@ PI-useReq is a TypeScript pi extension plus companion Node CLI and standalone ex
|
|
|
89
89
|
- **DES-010**: MUST centralize event-driven context snapshots, run-timing state, prompt-orchestration workflow state, and status-bar rendering through shared extension-status helpers.
|
|
90
90
|
- **DES-011**: MUST implement `.github/workflows/release-npm.yml` as a two-job GitHub Actions pipeline where `check-branch` gates `build-release`, preserving changelog-driven GitHub Release creation while adding npm publication.
|
|
91
91
|
- **DES-015**: MUST implement config-gated `debug-compress`, `debug-references`, `debug-static-check`, and `debug-tokens` slash-command wrappers in `src/index.ts` that reuse existing tool-runner execution paths.
|
|
92
|
+
- **DES-016**: MUST deliver rendered bundled-prompt content to the LLM through `sendMessage` as a `display:false` custom message with `triggerTurn:true` and MUST NOT use `sendUserMessage` when `sendMessage` is available.
|
|
92
93
|
|
|
93
94
|
### 3.2 Functions
|
|
94
95
|
- **REQ-001**: MUST access bundled prompts, git execution instructions, templates, and guidelines from `<installation-path>/resources` without requiring user-home resource copies before prompt or tool execution.
|
|
@@ -157,6 +158,11 @@ PI-useReq is a TypeScript pi extension plus companion Node CLI and standalone ex
|
|
|
157
158
|
- **REQ-066**: MUST omit `reset-context` and `context-reset` fields from persisted local and global configuration.
|
|
158
159
|
- **REQ-067**: MUST send every bundled prompt-backed `req-<prompt>` payload into the current active session.
|
|
159
160
|
- **REQ-068**: MUST use one prompt-delivery path that sends bundled prompt-backed `req-<prompt>` payloads through the forked execution session by using only the replacement-session context for post-switch session-bound operations.
|
|
161
|
+
- **REQ-334**: MUST NOT display rendered prompt content on screen when delivering bundled prompt-backed `req-<prompt>` commands and MUST deliver the full rendered content only to the LLM agent.
|
|
162
|
+
- **REQ-335**: MUST display a command invocation summary on screen for every bundled prompt-backed `req-<prompt>` command containing the command name, passed arguments, and active configuration.
|
|
163
|
+
- **REQ-336**: MUST render the command invocation summary with the command name without the `req-` prefix in uppercase and the user request arguments.
|
|
164
|
+
- **REQ-337**: MUST include `docs-dir`, `src-dir`, `tests-dir`, enabled context files, `AUTO_GIT_COMMIT`, effective `GIT_WORKTREE_ENABLED`, `GIT_WORKTREE_PREFIX`, enabled static-check languages, and `enabled-tools` in the command invocation summary.
|
|
165
|
+
- **REQ-338**: MUST render `none` for the command invocation summary `context files`, `static code checks`, and `enabled tools` fields whenever their respective enabled-item list is empty.
|
|
160
166
|
- **REQ-008**: MUST provide a `Language static code checkers` submenu that adds global Command entries by guided language flow, removes configured global checker entries, toggles local per-language enablement, and resets static-check configuration.
|
|
161
167
|
- **REQ-160**: MUST hardcode `Command` as the only user-configurable static-check module and omit module-selection UI from static-check configuration menus.
|
|
162
168
|
- **REQ-161**: MUST hide `Dummy` from user-configurable static-check menus while preserving existing-config parsing and debug-driver support for `Dummy` entries.
|
|
@@ -390,12 +396,12 @@ PI-useReq is a TypeScript pi extension plus companion Node CLI and standalone ex
|
|
|
390
396
|
- **REQ-325**: MUST reject `debug-compress`, `debug-references`, `debug-static-check`, `debug-summarize`, and `debug-tokens` execution when `DEBUG_TOOL_COMMANDS_ENABLED=disable`.
|
|
391
397
|
- **REQ-326**: MUST add a top-level `Context Files` row to the `pi-usereq` menu between `Unit tests directory` and `Auto git commit`.
|
|
392
398
|
- **REQ-327**: MUST expose a `Context Files` submenu with separate enable toggles for `REQUIREMENTS.md`, `REFERENCES.md`, and `WORKFLOW.md` in that order.
|
|
393
|
-
- **REQ-328**: MUST persist `context-files-requirements`, `context-files-references`, and `context-files-workflow` as boolean flags in local configuration, each defaulting to
|
|
399
|
+
- **REQ-328**: MUST persist `context-files-requirements`, `context-files-references`, and `context-files-workflow` as boolean flags in local configuration, each defaulting to disabled.
|
|
394
400
|
- **REQ-329**: MUST replace the `%%CONTEXT_FILES%%` prompt token with one markdown section per enabled context file in the order `REQUIREMENTS.md`, `REFERENCES.md`, `WORKFLOW.md`.
|
|
395
401
|
- **REQ-330**: MUST render each `%%CONTEXT_FILES%%` section as the file-name heading, an HTML `<file name="<docs-dir>/<filename>">` reference with `%%DOC_PATH%%` pre-substituted, and the raw file content inside four-backtick `markdown` fences.
|
|
396
402
|
- **REQ-331**: MUST omit the `%%CONTEXT_FILES%%` section for any disabled flag or missing context file without surfacing an error.
|
|
397
403
|
- **REQ-332**: MUST inject `%%CONTEXT_FILES%%` content verbatim after every other prompt replacement so literal `%%...%%` tokens inside context files are not substituted.
|
|
398
|
-
- **REQ-333**: MUST restore all three `Context Files` flags to
|
|
404
|
+
- **REQ-333**: MUST restore all three `Context Files` flags to disabled when the `Context Files` subtree `Reset defaults` is approved.
|
|
399
405
|
|
|
400
406
|
## 4. Test Requirements
|
|
401
407
|
- **TST-001**: MUST verify extension activation registers every documented prompt command, agent tool, and configuration command while omitting tool-name slash commands, `test-static-check`, and the removed standalone config-viewer command.
|
|
@@ -506,6 +512,7 @@ PI-useReq is a TypeScript pi extension plus companion Node CLI and standalone ex
|
|
|
506
512
|
- **TST-065**: MUST verify default startup-tool enablement matches the documented enabled and disabled tool matrix.
|
|
507
513
|
- **TST-110**: MUST verify `Enable tools` toggles, enable-all, disable-all, and reset-defaults persist only in global configuration.
|
|
508
514
|
- **TST-066**: MUST verify `req-<prompt>` commands keep working when extension custom-tool registrations are removed from the runtime inventory.
|
|
515
|
+
- **TST-121**: MUST verify bundled prompt-backed `req-<prompt>` commands deliver the full rendered prompt content through the fallback `sendUserMessage` channel when the runtime does not expose `sendMessage`.
|
|
509
516
|
- **TST-059**: MUST verify every agent-tool registration defines custom `renderResult` and that compact rendering shows essential invocation parameters while expanded rendering avoids fallback raw-content display.
|
|
510
517
|
- **TST-086**: MUST verify bundled prompt-backed `req-<prompt>` commands abort before prompt dispatch when the persisted execution-session header cwd or `process.cwd()` differs from the expected execution path, and abort before merge when persisted execution-session header metadata or verified worktree artifacts diverge, while stale pre-switch context probes alone do not abort.
|
|
511
518
|
- **TST-113**: MUST verify default local configuration persists `DEBUG_TOOL_COMMANDS_ENABLED=disable`, and the `Debug` submenu renders `Enable debug commands for tools` before `Log file`.
|
|
@@ -516,6 +523,7 @@ PI-useReq is a TypeScript pi extension plus companion Node CLI and standalone ex
|
|
|
516
523
|
- **TST-118**: MUST verify the `Context Files` submenu persists the three context-file flags in local configuration with immediate-save, reset, and focus-preserving re-render behavior.
|
|
517
524
|
- **TST-119**: MUST verify `%%CONTEXT_FILES%%` replacement emits one section per enabled existing file in the documented order and omits disabled or missing files.
|
|
518
525
|
- **TST-120**: MUST verify `%%CONTEXT_FILES%%` sections use the file-name heading, the pre-substituted HTML file reference, and four-backtick `markdown` fences around raw content.
|
|
526
|
+
- **TST-122**: MUST verify the command invocation summary renders `none` for `context files`, `static code checks`, and `enabled tools` when no items are enabled in each respective category.
|
|
519
527
|
|
|
520
528
|
## 5. Observed Component Model
|
|
521
529
|
|
|
@@ -575,8 +575,9 @@
|
|
|
575
575
|
- `buildIgnoredGitStatusPaths(...)`: ignore extension-owned debug-log artifacts during cleanliness verification [`src/core/req-references-command.ts`]
|
|
576
576
|
- `renderPrompt(...)`: render prompt-command payloads with bundled commit-instruction expansion, conditional pi.dev governance guidance, and `%%CONTEXT_FILES%%` context-file injection [`src/core/prompts.ts`]
|
|
577
577
|
- `buildContextFilesBlock(...)`: build the markdown block injected at `%%CONTEXT_FILES%%` from enabled context files in documented order with pre-substituted `%%DOC_PATH%%` file references and four-backtick fences [`src/core/prompts.ts`]
|
|
578
|
-
- `
|
|
579
|
-
|
|
578
|
+
- `renderPromptCommandSummary(...)`: render the on-screen command invocation summary with command name, user request arguments, and active configuration fields, rendering `none` for empty context-file, static-check-language, and enabled-tool lists [`src/core/prompts.ts`]
|
|
579
|
+
- `deliverPromptCommand(...)`: dispatch the rendered prompt as a hidden `display:false` custom message plus a `display:true` summary into the current recorded session, awaiting and suppressing summary delivery failures before the hidden prompt turn, falling back to `sendUserMessage(...)` when `sendMessage(...)` is unavailable [`src/index.ts`]
|
|
580
|
+
- External boundaries: `RecordingExtensionAPI.sendMessage(...)` or fallback `RecordingExtensionAPI.sendUserMessage(...)` records the delivered prompt payload plus summary.
|
|
580
581
|
- `configurePiUsereq(...)`: execute the interactive configuration menu [`src/index.ts`]
|
|
581
582
|
- `buildPiUsereqMenuChoices(...)`: serialize top-level settings actions including the `Context Files` injection toggle row, effective worktree locking, plus display-only local and global config-path rows [`src/index.ts`]
|
|
582
583
|
- `formatLocalConfigPathForMenu(...)`: format the current local config path with the shared `~`-relative path formatter for menu display [`src/index.ts`]
|
|
@@ -879,10 +880,11 @@
|
|
|
879
880
|
- `writePersistedPromptCommandSessionContext(...)`: store the reusable command-capable replacement-session context for later closure handling [`src/core/prompt-command-state.ts`]
|
|
880
881
|
- `clearPersistedPromptCommandSessionContext(...)`: drop reusable command-context persistence when worktree routing is inactive [`src/core/prompt-command-state.ts`]
|
|
881
882
|
- `logPromptWorkflowEvent(...)`: append selected workflow-activation debug entries [`src/index.ts`]
|
|
882
|
-
- `
|
|
883
|
+
- `renderPromptCommandSummary(...)`: render the on-screen command invocation summary with command name without the `req-` prefix in uppercase, user request arguments, and active configuration fields, rendering `none` for empty context-file, static-check-language, and enabled-tool lists [`src/core/prompts.ts`]
|
|
884
|
+
- `deliverPromptCommand(...)`: start dispatch of the rendered prompt as a hidden `display:false` custom message with `triggerTurn:true` plus a `display:true` command invocation summary into the current active session after execution-session activation is verified, preferring replacement-session `sendMessage(...)` when available, falling back to `sendUserMessage(...)` when `sendMessage(...)` is unavailable, awaiting and suppressing the non-critical summary delivery before the authoritative hidden prompt turn so a rejecting summary never surfaces as an unhandled rejection that could terminate the process before prompt-end closure runs the worktree merge, returning the delivery promise so the final `running` transition is recorded immediately after handoff begins instead of after the full prompt run completes, and suppressing the documented stale post-restore rejection once the prompt was already accepted [`src/index.ts`]
|
|
883
885
|
- `writePersistedPromptCommandRuntimeState(...)`: mirror the prepared prompt execution plan into process-scoped persistence before the worktree session switch returns control [`src/core/prompt-command-state.ts`]
|
|
884
|
-
- `isStaleExtensionContextError(...)`: classify stale post-restore delivery rejections from replacement-session `
|
|
885
|
-
- External boundaries: replacement-session `
|
|
886
|
+
- `isStaleExtensionContextError(...)`: classify stale post-restore delivery rejections from replacement-session `sendMessage(...)` [`src/core/extension-status.ts`]
|
|
887
|
+
- External boundaries: replacement-session `sendMessage(...)` or `pi.sendMessage(...)` delivers the hidden rendered prompt payload plus the displayed summary into the active `AgentSession`; fallback replacement-session `sendUserMessage(...)` or `pi.sendUserMessage(...)` delivers the rendered prompt payload when `sendMessage(...)` is unavailable.
|
|
886
888
|
- `abortPromptCommandExecution(...)`: restore the original session-backed base path and delete created worktree resources when command-side preflight or prompt handoff fails [`src/core/prompt-command-runtime.ts`]
|
|
887
889
|
- `restorePromptCommandExecution(...)`: switch back to the original session through replacement-session-aware `ctx.switchSession(sessionPath, { withSession })` handling, reuse the persisted replacement-session context when lifecycle hooks omit `switchSession()`, carry forward the returned replacement-session context for later session-bound work, re-align `process.cwd()` to `base-path`, confirm `process.cwd()` plus the persisted original-session file header cwd when the file is already persisted, append optional workflow-restore debug entries, clear active worktree path facts, and best-effort realign the live `ctx.cwd` mirror when worktree routing was active without failing on stale or getter-only context mirrors [`src/core/prompt-command-runtime.ts`]
|
|
888
890
|
- `resolvePromptCommandSwitchContext(...)`: prefer the live command context or fall back to the persisted replacement-session context keyed by the execution-session file [`src/core/prompt-command-runtime.ts`]
|
package/src/core/config.ts
CHANGED
|
@@ -214,14 +214,14 @@ export const DEFAULT_TESTS_DIR = "tests";
|
|
|
214
214
|
export const DEFAULT_SRC_DIRS = ["src"];
|
|
215
215
|
/**
|
|
216
216
|
* @brief Defines the default value for every persisted context-file injection flag.
|
|
217
|
-
* @details Each `%%CONTEXT_FILES%%` injection toggle defaults to
|
|
217
|
+
* @details Each `%%CONTEXT_FILES%%` injection toggle defaults to disabled so the bundled canonical documents are excluded from the prompt context unless the user explicitly enables one. Lookup complexity is O(1).
|
|
218
218
|
* @satisfies REQ-328
|
|
219
219
|
*/
|
|
220
|
-
export const DEFAULT_CONTEXT_FILES_FLAG =
|
|
220
|
+
export const DEFAULT_CONTEXT_FILES_FLAG = false;
|
|
221
221
|
|
|
222
222
|
/**
|
|
223
223
|
* @brief Normalizes one persisted context-file injection flag.
|
|
224
|
-
* @details Returns the documented default (`
|
|
224
|
+
* @details Returns the documented default (`false`) for missing or non-boolean values and preserves only explicit boolean input, so any malformed persisted entry keeps context-file injection disabled. Runtime is O(1). No external state is mutated.
|
|
225
225
|
* @param[in] value {unknown} Candidate persisted context-file flag.
|
|
226
226
|
* @return {boolean} Normalized context-file injection flag.
|
|
227
227
|
* @satisfies REQ-328
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import fs from "node:fs";
|
|
8
8
|
import path from "node:path";
|
|
9
|
-
import { spawnSync } from "node:child_process";
|
|
9
|
+
import { spawnSync, type SpawnSyncReturns } from "node:child_process";
|
|
10
10
|
import { ReqError } from "./errors.js";
|
|
11
11
|
import { classifyPiNotifyOutcome, type PiNotifyOutcome } from "./pi-notify.js";
|
|
12
12
|
import {
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
type DebugWorkflowState,
|
|
21
21
|
} from "./debug-runtime.js";
|
|
22
22
|
import { type PromptCommandName } from "./prompt-command-catalog.js";
|
|
23
|
+
export { type PromptCommandName } from "./prompt-command-catalog.js";
|
|
23
24
|
import {
|
|
24
25
|
isSameOrAncestorPath,
|
|
25
26
|
normalizeRelativeDirContract,
|
|
@@ -119,14 +120,13 @@ interface PromptCommandActiveContext extends PromptCommandSessionContext {
|
|
|
119
120
|
|
|
120
121
|
/**
|
|
121
122
|
* @brief Describes one serializable session entry copied into a materialized execution-session file.
|
|
122
|
-
* @details Captures the stable tree-entry fields needed to write a JSONL session snapshot for cross-cwd session replacement when the origin session file has not been flushed yet. The interface is compile-time only and introduces no runtime cost.
|
|
123
|
+
* @details Captures the stable tree-entry fields needed to write a JSONL session snapshot for cross-cwd session replacement when the origin session file has not been flushed yet. Mirrors the SDK `SessionEntryBase` shape without an index signature so the SDK `SessionEntry` union remains structurally assignable for passthrough serialization. The interface is compile-time only and introduces no runtime cost.
|
|
123
124
|
*/
|
|
124
125
|
interface PromptCommandSessionEntry {
|
|
125
126
|
type: string;
|
|
126
127
|
id: string;
|
|
127
128
|
parentId: string | null;
|
|
128
129
|
timestamp: string;
|
|
129
|
-
[key: string]: unknown;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
/**
|
|
@@ -705,7 +705,7 @@ async function switchPromptCommandSession(
|
|
|
705
705
|
throw new ReqError(`ERROR: Prompt orchestration requires ctx.switchSession() for ${sessionFile}.`, 1);
|
|
706
706
|
}
|
|
707
707
|
let replacementContext: PromptCommandActiveContext | undefined;
|
|
708
|
-
let switchResult: { cancelled?: boolean } | void;
|
|
708
|
+
let switchResult: { cancelled?: boolean } | void = undefined;
|
|
709
709
|
try {
|
|
710
710
|
switchResult = await ctx.switchSession(sessionFile, {
|
|
711
711
|
withSession: async (activeContext) => {
|
|
@@ -840,9 +840,9 @@ const PROMPT_REQUIRED_DOCS: Record<PromptCommandName, readonly PromptRequiredDoc
|
|
|
840
840
|
* @details Delegates to `spawnSync`, preserves the supplied working directory, and returns the raw subprocess result used by prompt-command orchestration. Runtime is dominated by external process execution. Side effects include process spawning.
|
|
841
841
|
* @param[in] command {string[]} Executable plus argument vector.
|
|
842
842
|
* @param[in] cwd {string} Working directory for the subprocess.
|
|
843
|
-
* @return {
|
|
843
|
+
* @return {SpawnSyncReturns<string>} Captured subprocess result with UTF-8 decoded stdout and stderr.
|
|
844
844
|
*/
|
|
845
|
-
function runCapture(command: string[], cwd: string):
|
|
845
|
+
function runCapture(command: string[], cwd: string): SpawnSyncReturns<string> {
|
|
846
846
|
return spawnSync(command[0]!, command.slice(1), {
|
|
847
847
|
cwd,
|
|
848
848
|
encoding: "utf8",
|
package/src/core/prompts.ts
CHANGED
|
@@ -6,7 +6,17 @@
|
|
|
6
6
|
|
|
7
7
|
import fs from "node:fs";
|
|
8
8
|
import path from "node:path";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
buildPromptReplacementPaths,
|
|
11
|
+
DEFAULT_DOCS_DIR,
|
|
12
|
+
DEFAULT_STATIC_CHECK_LANGUAGES,
|
|
13
|
+
resolveEffectiveGitWorktreeEnabled,
|
|
14
|
+
type UseReqConfig,
|
|
15
|
+
} from "./config.js";
|
|
16
|
+
import {
|
|
17
|
+
comparePiUsereqStartupToolNames,
|
|
18
|
+
type PiUsereqStartupToolName,
|
|
19
|
+
} from "./pi-usereq-tools.js";
|
|
10
20
|
import { formatRuntimePathForDisplay, normalizeRelativeDirContract } from "./path-context.js";
|
|
11
21
|
import type {
|
|
12
22
|
PromptCommandExecutionPlan,
|
|
@@ -355,3 +365,61 @@ export function renderPrompt(
|
|
|
355
365
|
}
|
|
356
366
|
return adapted.split("%%CONTEXT_FILES%%").join("");
|
|
357
367
|
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* @brief Defines the custom-message type used for pi-usereq prompt-command screen summaries and hidden LLM prompt delivery.
|
|
371
|
+
* @details The constant is reused as the `customType` for both the `display:true` command invocation summary and the `display:false` hidden rendered prompt so the TUI renders only the summary while the full prompt reaches the LLM agent through the same custom-message channel. Access complexity is O(1).
|
|
372
|
+
* @satisfies DES-016, REQ-334
|
|
373
|
+
*/
|
|
374
|
+
export const PROMPT_COMMAND_SUMMARY_CUSTOM_TYPE = "pi-usereq-prompt-command";
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* @brief Builds the on-screen command invocation summary for one bundled prompt-backed `req-<prompt>` command.
|
|
378
|
+
* @details Renders the command name without the `req-` prefix in uppercase, the user request arguments, and the active configuration fields (`docs-dir`, `src-dir`, `tests-dir`, enabled context files, `AUTO_GIT_COMMIT`, effective `GIT_WORKTREE_ENABLED`, `GIT_WORKTREE_PREFIX`, enabled static-check languages, and `enabled-tools`) so the TUI shows only a compact summary while the full rendered prompt is delivered hidden to the LLM agent. Static-check languages are emitted in canonical `DEFAULT_STATIC_CHECK_LANGUAGES` order; enabled tools are emitted in documented menu order via `comparePiUsereqStartupToolNames`. The `context files`, `static code checks`, and `enabled tools` fields render the literal `none` placeholder whenever their respective enabled-item list is empty so the summary never shows a blank value. Runtime is O(l + t log t) where l is language count and t is enabled-tool count. No external state is mutated.
|
|
379
|
+
* @param[in] promptName {string} Bundled prompt name without the `req-` prefix.
|
|
380
|
+
* @param[in] args {string} User request arguments passed to the slash command.
|
|
381
|
+
* @param[in] config {UseReqConfig} Effective project configuration supplying directory, git, static-check, and tool fields.
|
|
382
|
+
* @return {string} Multi-line command invocation summary text.
|
|
383
|
+
* @satisfies REQ-335, REQ-336, REQ-337, REQ-338
|
|
384
|
+
*/
|
|
385
|
+
export function renderPromptCommandSummary(
|
|
386
|
+
promptName: string,
|
|
387
|
+
args: string,
|
|
388
|
+
config: UseReqConfig,
|
|
389
|
+
): string {
|
|
390
|
+
const contextFiles = CONTEXT_FILE_DESCRIPTORS
|
|
391
|
+
.filter((descriptor) => config[descriptor.flagKey])
|
|
392
|
+
.map((descriptor) => descriptor.fileName.replace(/\.md$/, "").toLowerCase())
|
|
393
|
+
.join(", ") || "none";
|
|
394
|
+
const enabledLanguages = DEFAULT_STATIC_CHECK_LANGUAGES
|
|
395
|
+
.filter((language) => config["static-check"][language]?.enabled === "enable")
|
|
396
|
+
.join(", ") || "none";
|
|
397
|
+
const enabledTools = ([...config["enabled-tools"]]
|
|
398
|
+
.sort((left, right) =>
|
|
399
|
+
comparePiUsereqStartupToolNames(
|
|
400
|
+
left as PiUsereqStartupToolName,
|
|
401
|
+
right as PiUsereqStartupToolName,
|
|
402
|
+
))
|
|
403
|
+
.join(", ") || "none");
|
|
404
|
+
const effectiveWorktree = resolveEffectiveGitWorktreeEnabled(
|
|
405
|
+
config.AUTO_GIT_COMMIT,
|
|
406
|
+
config.GIT_WORKTREE_ENABLED,
|
|
407
|
+
);
|
|
408
|
+
const lines: string[] = [
|
|
409
|
+
`Command: ${promptName.toUpperCase()}`,
|
|
410
|
+
"",
|
|
411
|
+
`User's Request: ${args}`,
|
|
412
|
+
"",
|
|
413
|
+
"Configuration:",
|
|
414
|
+
`- document dir: ${config["docs-dir"]}`,
|
|
415
|
+
`- source-code dirs: ${config["src-dir"].join(", ")}`,
|
|
416
|
+
`- unit tests dir: ${config["tests-dir"]}`,
|
|
417
|
+
`- context files: ${contextFiles}`,
|
|
418
|
+
`- auto git commit: ${config.AUTO_GIT_COMMIT}`,
|
|
419
|
+
`- git worktree: ${effectiveWorktree}`,
|
|
420
|
+
`- worktree prefix: ${config.GIT_WORKTREE_PREFIX}`,
|
|
421
|
+
`- static code checks: ${enabledLanguages}`,
|
|
422
|
+
`- enabled tools: ${enabledTools}`,
|
|
423
|
+
];
|
|
424
|
+
return lines.join("\n");
|
|
425
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @details Performs slash-command-owned git validation reuse, reference-file generation, targeted staging, fixed-message commit creation, and post-commit cleanliness verification without creating a worktree or starting an LLM session. Runtime is dominated by git subprocess execution plus source-summary generation and one documentation write. Side effects include filesystem writes and git index/history mutation.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { spawnSync } from "node:child_process";
|
|
7
|
+
import { spawnSync, type SpawnSyncReturns } from "node:child_process";
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import type { UseReqConfig } from "./config.js";
|
|
10
10
|
import { ReqError } from "./errors.js";
|
|
@@ -39,9 +39,9 @@ export interface ReqReferencesCommandPlan {
|
|
|
39
39
|
* @details Delegates to `spawnSync(...)`, preserves the supplied working directory, and returns the raw result so callers can interpret git exit status plus diagnostics deterministically. Runtime is dominated by external process execution. Side effects include subprocess creation.
|
|
40
40
|
* @param[in] command {string[]} Executable plus argument vector.
|
|
41
41
|
* @param[in] cwd {string} Working directory for the subprocess.
|
|
42
|
-
* @return {
|
|
42
|
+
* @return {SpawnSyncReturns<string>} Captured subprocess result with UTF-8 stdout and stderr.
|
|
43
43
|
*/
|
|
44
|
-
function runCapture(command: string[], cwd: string):
|
|
44
|
+
function runCapture(command: string[], cwd: string): SpawnSyncReturns<string> {
|
|
45
45
|
return spawnSync(command[0]!, command.slice(1), {
|
|
46
46
|
cwd,
|
|
47
47
|
encoding: "utf8",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import fs from "node:fs";
|
|
8
8
|
import path from "node:path";
|
|
9
|
-
import { spawnSync } from "node:child_process";
|
|
9
|
+
import { spawnSync, type SpawnSyncReturns } from "node:child_process";
|
|
10
10
|
import {
|
|
11
11
|
normalizeGitWorktreePrefix,
|
|
12
12
|
type UseReqConfig,
|
|
@@ -63,9 +63,9 @@ type ReqResetCommandContext = Parameters<typeof restorePromptCommandExecution>[1
|
|
|
63
63
|
* @details Delegates to `spawnSync(...)`, preserves the supplied working directory, and returns the raw result so callers can interpret git exit status plus diagnostics deterministically. Runtime is dominated by external process execution. Side effects include subprocess creation.
|
|
64
64
|
* @param[in] command {string[]} Executable plus argument vector.
|
|
65
65
|
* @param[in] cwd {string} Working directory for the subprocess.
|
|
66
|
-
* @return {
|
|
66
|
+
* @return {SpawnSyncReturns<string>} Captured subprocess result with UTF-8 stdout and stderr.
|
|
67
67
|
*/
|
|
68
|
-
function runCapture(command: string[], cwd: string):
|
|
68
|
+
function runCapture(command: string[], cwd: string): SpawnSyncReturns<string> {
|
|
69
69
|
return spawnSync(command[0]!, command.slice(1), {
|
|
70
70
|
cwd,
|
|
71
71
|
encoding: "utf8",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import path from "node:path";
|
|
8
|
-
import { spawnSync } from "node:child_process";
|
|
8
|
+
import { spawnSync, type SpawnSyncReturns } from "node:child_process";
|
|
9
9
|
import { ReqError } from "./errors.js";
|
|
10
10
|
import { isSameOrAncestorPath } from "./path-context.js";
|
|
11
11
|
|
|
@@ -14,9 +14,9 @@ import { isSameOrAncestorPath } from "./path-context.js";
|
|
|
14
14
|
* @details Delegates to `spawnSync`, keeps execution synchronous for deterministic command flows, and supports an optional working directory. Runtime is dominated by the spawned git process. Side effects include subprocess creation.
|
|
15
15
|
* @param[in] command {string[]} Git executable plus argument vector.
|
|
16
16
|
* @param[in] cwd {string | undefined} Optional working directory.
|
|
17
|
-
* @return {
|
|
17
|
+
* @return {SpawnSyncReturns<string>} Captured subprocess result with UTF-8 stdout and stderr.
|
|
18
18
|
*/
|
|
19
|
-
function runGitCapture(command: string[], cwd?: string):
|
|
19
|
+
function runGitCapture(command: string[], cwd?: string): SpawnSyncReturns<string> {
|
|
20
20
|
return spawnSync(command[0]!, command.slice(1), {
|
|
21
21
|
cwd,
|
|
22
22
|
encoding: "utf8",
|
package/src/index.ts
CHANGED
|
@@ -83,7 +83,11 @@ import {
|
|
|
83
83
|
normalizeEnabledPiUsereqTools,
|
|
84
84
|
type PiUsereqStartupToolName,
|
|
85
85
|
} from "./core/pi-usereq-tools.js";
|
|
86
|
-
import {
|
|
86
|
+
import {
|
|
87
|
+
PROMPT_COMMAND_SUMMARY_CUSTOM_TYPE,
|
|
88
|
+
renderPrompt,
|
|
89
|
+
renderPromptCommandSummary,
|
|
90
|
+
} from "./core/prompts.js";
|
|
87
91
|
import {
|
|
88
92
|
abortPromptCommandExecution,
|
|
89
93
|
activatePromptCommandExecution,
|
|
@@ -906,21 +910,68 @@ function executeStatusTool(operation: () => ToolResult): ReturnType<typeof build
|
|
|
906
910
|
|
|
907
911
|
/**
|
|
908
912
|
* @brief Starts delivery of one rendered prompt into the current active session.
|
|
909
|
-
* @details Prefers the replacement-session `
|
|
913
|
+
* @details Prefers the replacement-session `sendMessage(...)` helper exposed by `withSession(...)` callbacks after session replacement so post-switch prompt delivery never reuses stale pre-switch session-bound extension objects. Delivers the rendered prompt as a `display:false` custom message with `triggerTurn:true` so the full content reaches the LLM agent without appearing on screen, and emits a `display:true` command invocation summary so the TUI shows only the compact summary. Awaits the non-critical summary delivery and suppresses its failures before dispatching the authoritative hidden prompt turn so a rejecting summary never surfaces as an unhandled rejection that could terminate the process before prompt-end closure runs the worktree merge. Returns the underlying hidden-delivery promise without awaiting the full agent turn so callers can record the `running` workflow transition as soon as prompt handoff is accepted; the returned promise resolves after the hidden prompt message is accepted, which on runtimes whose async replacement-session helpers resolve only after `agent_end` lets prompt-end closure finalize the worktree merge during the awaited delivery. When pi later invalidates that replacement-session context during successful prompt-end restoration, the helper suppresses the documented stale-extension-context rejection because the prompt was already accepted and late rethrow would surface a false orchestration failure. Falls back to `sendUserMessage(...)` only for non-replacement flows or runtimes that do not expose `sendMessage`. Runtime is O(n) in prompt length. Side effects are limited to hidden prompt delivery plus on-screen summary display.
|
|
910
914
|
* @param[in] pi {ExtensionAPI} Handler-scoped extension API instance retained as the fallback dispatcher.
|
|
911
915
|
* @param[in] content {string} Rendered prompt markdown.
|
|
916
|
+
* @param[in] summary {string} Command invocation summary text displayed on screen.
|
|
912
917
|
* @param[in] context {unknown} Optional replacement-session helper context.
|
|
913
918
|
* @return {Promise<void>} Promise representing eventual prompt-delivery completion.
|
|
914
|
-
* @satisfies REQ-004, REQ-067, REQ-068, REQ-227, REQ-281
|
|
919
|
+
* @satisfies REQ-004, REQ-067, REQ-068, REQ-227, REQ-281, REQ-334, REQ-335, DES-016
|
|
915
920
|
*/
|
|
916
921
|
function deliverPromptCommand(
|
|
917
922
|
pi: ExtensionAPI,
|
|
918
923
|
content: string,
|
|
924
|
+
summary: string,
|
|
919
925
|
context?: unknown,
|
|
920
926
|
): Promise<void> {
|
|
921
927
|
const replacementContext = context as {
|
|
928
|
+
sendMessage?: (
|
|
929
|
+
message: { customType: string; content: string; display: boolean },
|
|
930
|
+
options?: { triggerTurn?: boolean; deliverAs?: "steer" | "followUp" | "nextTurn" },
|
|
931
|
+
) => Promise<void> | void;
|
|
922
932
|
sendUserMessage?: (message: string) => Promise<void> | void;
|
|
923
933
|
} | undefined;
|
|
934
|
+
const summaryMessage = {
|
|
935
|
+
customType: PROMPT_COMMAND_SUMMARY_CUSTOM_TYPE,
|
|
936
|
+
content: summary,
|
|
937
|
+
display: true,
|
|
938
|
+
};
|
|
939
|
+
const hiddenPromptMessage = {
|
|
940
|
+
customType: PROMPT_COMMAND_SUMMARY_CUSTOM_TYPE,
|
|
941
|
+
content,
|
|
942
|
+
display: false,
|
|
943
|
+
};
|
|
944
|
+
if (typeof replacementContext?.sendMessage === "function") {
|
|
945
|
+
// The on-screen summary is non-critical; await it and suppress its delivery failures so a
|
|
946
|
+
// rejecting summary never surfaces as an unhandled rejection that could terminate the
|
|
947
|
+
// process before the authoritative hidden prompt turn drives prompt-end closure.
|
|
948
|
+
const summaryDelivery = Promise.resolve(
|
|
949
|
+
replacementContext.sendMessage(summaryMessage),
|
|
950
|
+
).catch(() => {
|
|
951
|
+
// Intentionally suppressed: the hidden prompt message below is the authoritative turn trigger.
|
|
952
|
+
});
|
|
953
|
+
return summaryDelivery.then(() =>
|
|
954
|
+
replacementContext!.sendMessage!(hiddenPromptMessage, { triggerTurn: true }),
|
|
955
|
+
).catch((error) => {
|
|
956
|
+
if (isStaleExtensionContextError(error)) {
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
throw error;
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
if (typeof pi.sendMessage === "function") {
|
|
963
|
+
// `pi.sendMessage` is a fire-and-forget dispatcher in the pi runtime; chain both deliveries
|
|
964
|
+
// through one suppressed summary promise so a rejecting summary cannot terminate the process
|
|
965
|
+
// before the hidden prompt turn drives prompt-end closure.
|
|
966
|
+
const fallbackSummary = Promise.resolve(
|
|
967
|
+
pi.sendMessage(summaryMessage),
|
|
968
|
+
).catch(() => {
|
|
969
|
+
// Intentionally suppressed: the hidden prompt message below is the authoritative turn trigger.
|
|
970
|
+
});
|
|
971
|
+
return fallbackSummary.then(() => {
|
|
972
|
+
pi.sendMessage(hiddenPromptMessage, { triggerTurn: true });
|
|
973
|
+
});
|
|
974
|
+
}
|
|
924
975
|
if (typeof replacementContext?.sendUserMessage === "function") {
|
|
925
976
|
return Promise.resolve(replacementContext.sendUserMessage(content)).catch((error) => {
|
|
926
977
|
if (isStaleExtensionContextError(error)) {
|
|
@@ -1036,7 +1087,7 @@ function logPromptWorkflowEvent(
|
|
|
1036
1087
|
* @param[in] projectBase {string} Absolute original project base path.
|
|
1037
1088
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
1038
1089
|
* @param[in] promptName {import("./core/prompt-command-catalog.js").PromptCommandName} Bundled prompt name.
|
|
1039
|
-
* @param[in] nextState {
|
|
1090
|
+
* @param[in] nextState {import("./core/extension-status.js").PiUsereqWorkflowState} Next workflow state.
|
|
1040
1091
|
* @return {void} No return value.
|
|
1041
1092
|
*/
|
|
1042
1093
|
function transitionPromptWorkflowState(
|
|
@@ -1045,7 +1096,7 @@ function transitionPromptWorkflowState(
|
|
|
1045
1096
|
projectBase: string,
|
|
1046
1097
|
config: UseReqConfig,
|
|
1047
1098
|
promptName: import("./core/prompt-command-catalog.js").PromptCommandName,
|
|
1048
|
-
nextState:
|
|
1099
|
+
nextState: import("./core/extension-status.js").PiUsereqWorkflowState,
|
|
1049
1100
|
): void {
|
|
1050
1101
|
const previousState = statusController.state.workflowState;
|
|
1051
1102
|
setPiUsereqWorkflowState(statusController, nextState, ctx);
|
|
@@ -3073,7 +3124,12 @@ function registerPromptCommands(
|
|
|
3073
3124
|
},
|
|
3074
3125
|
);
|
|
3075
3126
|
renderPiUsereqStatus(statusController, promptContext);
|
|
3076
|
-
const
|
|
3127
|
+
const commandSummary = renderPromptCommandSummary(
|
|
3128
|
+
promptName,
|
|
3129
|
+
args,
|
|
3130
|
+
config,
|
|
3131
|
+
);
|
|
3132
|
+
const promptDelivery = deliverPromptCommand(pi, content, commandSummary, promptContext);
|
|
3077
3133
|
transitionPromptWorkflowState(
|
|
3078
3134
|
statusController,
|
|
3079
3135
|
promptContext,
|