pi-usereq 0.63.0 → 0.65.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 +1 -1
- package/package.json +1 -1
- package/scripts/pi-cli-update-src-docs.sh +370 -0
- package/scripts/pi-prompts-update.sh +338 -0
- package/src/core/context-file-size.ts +204 -7
- package/src/core/extension-status.ts +16 -0
- package/src/core/prompt-command-runtime.ts +7 -3
- package/src/core/prompts.ts +12 -5
- package/src/core/token-counter.ts +26 -6
- package/src/index.ts +41 -18
- package/src/resources/pi-prompts-version.txt +1 -0
- package/src/resources/prompts/analyze.md +12 -3
- package/src/resources/prompts/readme.md +6 -3
package/src/core/prompts.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
comparePiUsereqStartupToolNames,
|
|
18
18
|
type PiUsereqStartupToolName,
|
|
19
19
|
} from "./pi-usereq-tools.js";
|
|
20
|
-
import { formatContextFileSize, type ContextFileSizeFacts } from "./context-file-size.js";
|
|
20
|
+
import { computeContextOccupancyFacts, formatContextFileSize, sumEnabledContextFileTokens, type ContextFileSizeFacts } from "./context-file-size.js";
|
|
21
21
|
import { formatRuntimePathForDisplay, normalizeRelativeDirContract } from "./path-context.js";
|
|
22
22
|
import type {
|
|
23
23
|
PromptCommandExecutionPlan,
|
|
@@ -387,28 +387,35 @@ export const PROMPT_COMMAND_SUMMARY_CUSTOM_TYPE = "pi-usereq-prompt-command";
|
|
|
387
387
|
|
|
388
388
|
/**
|
|
389
389
|
* @brief Builds the on-screen command invocation summary for one bundled prompt-backed `req-<prompt>` command.
|
|
390
|
-
* @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. When measured context-file size facts are supplied, every enabled existing context file in the `context files` field is rendered as `name(<chars>c/<tokens>t)`; without facts, or for enabled missing files, the plain `name` form is rendered. 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. Sections are emitted in the order `Command:`, `Configuration:` with its bullet list, then `User's Request:`, each separated by one blank line. Runtime is O(l + t log t) where l is language count and t is enabled-tool count. No external state is mutated.
|
|
390
|
+
* @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. When measured context-file size facts are supplied, every enabled existing context file in the `context files` field is rendered as `name(<chars>c/<tokens>t)`; when the enabled existing token total contributes tokens, the field additionally appends the `[<percent>% context]` occupancy suffix against the selected model max input context (or `[<percent>%/1.0M* context]` with the documented fallback); without facts, or for enabled missing files, the plain `name` form is rendered. 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. Sections are emitted in the order `Command:`, `Configuration:` with its bullet list, then `User's Request:`, each separated by one blank line. Runtime is O(l + t log t) where l is language count and t is enabled-tool count. No external state is mutated.
|
|
391
391
|
* @param[in] promptName {string} Bundled prompt name without the `req-` prefix.
|
|
392
392
|
* @param[in] args {string} User request arguments passed to the slash command.
|
|
393
393
|
* @param[in] config {UseReqConfig} Effective project configuration supplying directory, git, static-check, and tool fields.
|
|
394
394
|
* @param[in] contextFileSizes {Record<string, ContextFileSizeFacts> | undefined} Optional measured context-file size facts keyed by canonical file name, consumed for `context files` size suffixes.
|
|
395
|
+
* @param[in] maxContextTokens {number | undefined} Selected model max input context tokens consumed by the occupancy suffix; undefined selects the documented 1,000,000-token fallback.
|
|
395
396
|
* @return {string} Multi-line command invocation summary text.
|
|
396
|
-
* @satisfies REQ-335, REQ-336, REQ-337, REQ-338, REQ-353, REQ-377
|
|
397
|
+
* @satisfies REQ-335, REQ-336, REQ-337, REQ-338, REQ-353, REQ-377, REQ-402, REQ-403, REQ-404, REQ-407
|
|
397
398
|
*/
|
|
398
399
|
export function renderPromptCommandSummary(
|
|
399
400
|
promptName: string,
|
|
400
401
|
args: string,
|
|
401
402
|
config: UseReqConfig,
|
|
402
403
|
contextFileSizes?: Record<string, ContextFileSizeFacts>,
|
|
404
|
+
maxContextTokens?: number | undefined,
|
|
403
405
|
): string {
|
|
404
|
-
const
|
|
406
|
+
const contextSegments = CONTEXT_FILE_DESCRIPTORS
|
|
405
407
|
.filter((descriptor) => config[descriptor.flagKey])
|
|
406
408
|
.map((descriptor) => {
|
|
407
409
|
const baseName = descriptor.fileName.replace(/\.md$/, "").toLowerCase();
|
|
408
410
|
const facts = contextFileSizes?.[descriptor.fileName];
|
|
409
411
|
return facts?.exists ? `${baseName}(${formatContextFileSize(facts)})` : baseName;
|
|
410
412
|
})
|
|
411
|
-
.join(", ")
|
|
413
|
+
.join(", ");
|
|
414
|
+
const totalContextTokens = contextFileSizes ? sumEnabledContextFileTokens(config, contextFileSizes) : 0;
|
|
415
|
+
const contextFiles = (contextSegments || "none")
|
|
416
|
+
+ (contextSegments && totalContextTokens > 0
|
|
417
|
+
? ` ${computeContextOccupancyFacts(totalContextTokens, maxContextTokens).suffix}`
|
|
418
|
+
: "");
|
|
412
419
|
const enabledLanguages = DEFAULT_STATIC_CHECK_LANGUAGES
|
|
413
420
|
.filter((language) => config["static-check"][language]?.enabled === "enable")
|
|
414
421
|
.join(", ") || "none";
|
|
@@ -196,14 +196,34 @@ function defaultJsTiktokenModuleLoader(): JsTiktokenModule {
|
|
|
196
196
|
|
|
197
197
|
let jsTiktokenModuleLoader: () => JsTiktokenModule = defaultJsTiktokenModuleLoader;
|
|
198
198
|
|
|
199
|
+
const cachedTokenCounterEncodings = new Map<string, TokenCounterEncoding>();
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @brief Resolves one shared tokenizer encoding for a `TokenCounter` construction.
|
|
203
|
+
* @details Checks the process-scoped per-encoding cache first and constructs the `js-tiktoken` encoding only on the first request per encoding name, so repeated `TokenCounter` construction across the `files-tokens` runner, canonical-doc counting, and context-file measurement reuses one parsed encoder instead of re-parsing the bundled BPE ranks each time. Runtime is O(1) after the first construction for the encoding and dominated by the single deferred `getEncoding` construction otherwise. Side effect: mutates the module-local encoding cache on first resolution per encoding name.
|
|
204
|
+
* @param[in] encodingName {string} `js-tiktoken` encoding identifier.
|
|
205
|
+
* @return {TokenCounterEncoding} Cached or newly constructed tokenizer encoding.
|
|
206
|
+
* @throws {ReqError} Propagates the deterministic unavailable-dependency failure when `js-tiktoken` cannot be loaded.
|
|
207
|
+
*/
|
|
208
|
+
function resolveTokenCounterEncoding(encodingName: string): TokenCounterEncoding {
|
|
209
|
+
const cachedEncoding = cachedTokenCounterEncodings.get(encodingName);
|
|
210
|
+
if (cachedEncoding) {
|
|
211
|
+
return cachedEncoding;
|
|
212
|
+
}
|
|
213
|
+
const encoding = loadJsTiktokenModule().getEncoding(encodingName);
|
|
214
|
+
cachedTokenCounterEncodings.set(encodingName, encoding);
|
|
215
|
+
return encoding;
|
|
216
|
+
}
|
|
217
|
+
|
|
199
218
|
/**
|
|
200
219
|
* @brief Overrides the `js-tiktoken` loader for tests.
|
|
201
|
-
* @details Enables deterministic dependency-failure tests without mutating repository dependencies on disk. Runtime is O(
|
|
220
|
+
* @details Enables deterministic dependency-failure tests without mutating repository dependencies on disk. Clears the process-scoped encoding cache so every loader swap observes fresh module behavior instead of encoders constructed by the previous loader. Runtime is O(e) in cached encoding count. Side effects are limited to module-local test state and cache reset.
|
|
202
221
|
* @param[in] loader {(() => JsTiktokenModule) | undefined} Replacement loader, or `undefined` to restore the default loader.
|
|
203
222
|
* @return {void} No return value.
|
|
204
223
|
*/
|
|
205
224
|
export function setJsTiktokenModuleLoaderForTests(loader?: () => JsTiktokenModule): void {
|
|
206
225
|
jsTiktokenModuleLoader = loader ?? defaultJsTiktokenModuleLoader;
|
|
226
|
+
cachedTokenCounterEncodings.clear();
|
|
207
227
|
}
|
|
208
228
|
|
|
209
229
|
/**
|
|
@@ -233,23 +253,23 @@ function loadJsTiktokenModule(): JsTiktokenModule {
|
|
|
233
253
|
|
|
234
254
|
/**
|
|
235
255
|
* @brief Encapsulates one tokenizer instance for repeated token counting.
|
|
236
|
-
* @details
|
|
256
|
+
* @details Resolves the process-scoped shared encoder for the requested encoding so multiple documents and multiple counter instances are counted without repeated encoding construction; the first construction per encoding name parses the BPE ranks once and every later `TokenCounter` reuses it through the module-local cache. Counting cost is O(n) in content length. The class mutates only instance state during construction.
|
|
237
257
|
*/
|
|
238
258
|
export class TokenCounter {
|
|
239
259
|
/**
|
|
240
260
|
* @brief Stores the tokenizer implementation used for subsequent counts.
|
|
241
|
-
* @details
|
|
261
|
+
* @details Holds the cached encoder resolved through the per-encoding process cache. Access complexity is O(1); construction is O(1) after the first resolution for the encoding name.
|
|
242
262
|
*/
|
|
243
263
|
private encoding: TokenCounterEncoding;
|
|
244
264
|
|
|
245
265
|
/**
|
|
246
266
|
* @brief Initializes a token counter for one encoding family.
|
|
247
|
-
* @details Resolves the
|
|
267
|
+
* @details Resolves the shared cached tokenizer for the encoding name, constructing the underlying `js-tiktoken` encoding at most once per encoding name per process so repeated constructions from token tools and context-file measurement are constant-time cache hits. Side effects are limited to instance initialization plus the optional first-time encoding cache mutation.
|
|
248
268
|
* @param[in] encodingName {string} `js-tiktoken` encoding identifier. Defaults to `cl100k_base`.
|
|
249
269
|
* @return {TokenCounter} New token counter instance.
|
|
250
270
|
*/
|
|
251
271
|
constructor(encodingName = TOKEN_COUNTER_ENCODING) {
|
|
252
|
-
this.encoding =
|
|
272
|
+
this.encoding = resolveTokenCounterEncoding(encodingName);
|
|
253
273
|
}
|
|
254
274
|
|
|
255
275
|
/**
|
|
@@ -427,7 +447,7 @@ function buildCountFileMetricsResult(filePath: string, content: string, counter:
|
|
|
427
447
|
|
|
428
448
|
/**
|
|
429
449
|
* @brief Counts tokens, characters, bytes, and lines for one in-memory content string.
|
|
430
|
-
* @details
|
|
450
|
+
* @details Resolves the process-cached shared `TokenCounter` encoder for the encoding, tokenizes the supplied text once, and pairs the result with raw character length, UTF-8 byte size, and logical line count. Runtime is O(n) after the one-time per-encoding encoder construction. No filesystem I/O occurs.
|
|
431
451
|
* @param[in] content {string} Text payload to measure.
|
|
432
452
|
* @param[in] encodingName {string} Tokenizer identifier. Defaults to `cl100k_base`.
|
|
433
453
|
* @return {{ tokens: number; chars: number; bytes: number; lines: number }} Aggregate metrics for the supplied content.
|
package/src/index.ts
CHANGED
|
@@ -84,8 +84,10 @@ import {
|
|
|
84
84
|
type PiUsereqStartupToolName,
|
|
85
85
|
} from "./core/pi-usereq-tools.js";
|
|
86
86
|
import {
|
|
87
|
+
computeContextOccupancyFacts,
|
|
87
88
|
formatContextFileSize,
|
|
88
89
|
measureContextFileSizes,
|
|
90
|
+
sumEnabledContextFileTokens,
|
|
89
91
|
type ContextFileName,
|
|
90
92
|
type ContextFileSizeFacts,
|
|
91
93
|
} from "./core/context-file-size.js";
|
|
@@ -160,6 +162,7 @@ import {
|
|
|
160
162
|
getPiUsereqRuntimeSoundLevel,
|
|
161
163
|
isStaleExtensionContextError,
|
|
162
164
|
renderPiUsereqStatus,
|
|
165
|
+
resolveModelContextWindowTokens,
|
|
163
166
|
setPiUsereqRuntimeSoundLevel,
|
|
164
167
|
setPiUsereqStatusConfig,
|
|
165
168
|
setPiUsereqWorkflowState,
|
|
@@ -3397,6 +3400,7 @@ function registerPromptCommands(
|
|
|
3397
3400
|
});
|
|
3398
3401
|
const projectBase = getProjectBase(commandCwd);
|
|
3399
3402
|
const config = loadProjectConfig(commandCwd);
|
|
3403
|
+
const maxContextTokens = resolveModelContextWindowTokens(statusController.state.contextUsage);
|
|
3400
3404
|
transitionPromptWorkflowState(
|
|
3401
3405
|
statusController,
|
|
3402
3406
|
ctx,
|
|
@@ -3427,6 +3431,7 @@ function registerPromptCommands(
|
|
|
3427
3431
|
},
|
|
3428
3432
|
originalModel,
|
|
3429
3433
|
originalThinkingLevel,
|
|
3434
|
+
maxContextTokens,
|
|
3430
3435
|
);
|
|
3431
3436
|
const content = renderPrompt(
|
|
3432
3437
|
promptName,
|
|
@@ -3470,6 +3475,7 @@ function registerPromptCommands(
|
|
|
3470
3475
|
args,
|
|
3471
3476
|
config,
|
|
3472
3477
|
measureContextFileSizes(projectBase, config),
|
|
3478
|
+
maxContextTokens,
|
|
3473
3479
|
);
|
|
3474
3480
|
const promptDelivery = deliverPromptCommand(pi, content, commandSummary, promptContext);
|
|
3475
3481
|
transitionPromptWorkflowState(
|
|
@@ -4545,44 +4551,56 @@ async function configureStaticCheckMenu(
|
|
|
4545
4551
|
}
|
|
4546
4552
|
|
|
4547
4553
|
/**
|
|
4548
|
-
* @brief Summarizes the `Context Files` flag state with measured sizes for the top-level menu value column.
|
|
4549
|
-
* @details Renders the three context-file flags as compact `name:on|off` segments in the documented order, appending `(<chars>c/<tokens>t)` measured size facts to every enabled segment
|
|
4554
|
+
* @brief Summarizes the `Context Files` flag state with measured sizes and context occupancy for the top-level menu value column.
|
|
4555
|
+
* @details Renders the three context-file flags as compact `name:on|off` segments in the documented order, appending `(<chars>c/<tokens>t)` measured size facts to every enabled segment, then appends the occupancy suffix computed from the enabled existing token total against the selected model max input context (`[<percent>% context]`, or `[<percent>%/1.0M* context]` with the documented fallback) whenever that total contributes tokens, while disabled segments stay plain `name:off`. Runtime is O(1) in segment count. No external state is mutated.
|
|
4550
4556
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
4551
4557
|
* @param[in] sizes {Record<ContextFileName, ContextFileSizeFacts>} Measured context-file size facts keyed by canonical file name.
|
|
4552
|
-
* @
|
|
4553
|
-
* @
|
|
4558
|
+
* @param[in] maxContextTokens {number | undefined} Selected model max input context tokens; undefined selects the documented 1,000,000-token fallback.
|
|
4559
|
+
* @return {string} Compact `Context Files` summary string with the occupancy suffix.
|
|
4560
|
+
* @satisfies REQ-327, REQ-376, REQ-402, REQ-403, REQ-404, REQ-405
|
|
4554
4561
|
*/
|
|
4555
4562
|
function formatContextFilesSummary(
|
|
4556
4563
|
config: UseReqConfig,
|
|
4557
4564
|
sizes: Record<ContextFileName, ContextFileSizeFacts>,
|
|
4565
|
+
maxContextTokens?: number | undefined,
|
|
4558
4566
|
): string {
|
|
4559
4567
|
const segments = [
|
|
4560
4568
|
`requirements:${config["context-files-requirements"] ? `on(${formatContextFileSize(sizes["REQUIREMENTS.md"])})` : "off"}`,
|
|
4561
4569
|
`references:${config["context-files-references"] ? `on(${formatContextFileSize(sizes["REFERENCES.md"])})` : "off"}`,
|
|
4562
4570
|
`workflow:${config["context-files-workflow"] ? `on(${formatContextFileSize(sizes["WORKFLOW.md"])})` : "off"}`,
|
|
4563
4571
|
];
|
|
4564
|
-
|
|
4572
|
+
const summary = segments.join(" \u2022 ");
|
|
4573
|
+
const totalTokens = sumEnabledContextFileTokens(config, sizes);
|
|
4574
|
+
return totalTokens > 0
|
|
4575
|
+
? `${summary} ${computeContextOccupancyFacts(totalTokens, maxContextTokens).suffix}`
|
|
4576
|
+
: summary;
|
|
4565
4577
|
}
|
|
4566
4578
|
|
|
4567
4579
|
/**
|
|
4568
4580
|
* @brief Builds the shared settings-menu choices for the `Context Files` submenu.
|
|
4569
|
-
* @details Exposes one inline toggle row per context file in the documented `REQUIREMENTS.md`, `REFERENCES.md`, `WORKFLOW.md` order whose value renders `on|off • <chars>c/<tokens>t` measured size facts plus a value-less subtree-local `Reset defaults` row. Cycle values embed the same measured facts so inline toggling keeps the size estimate visible while persisting the on|off state. Runtime is O(1) in row count. No external state is mutated.
|
|
4581
|
+
* @details Exposes one inline toggle row per context file in the documented `REQUIREMENTS.md`, `REFERENCES.md`, `WORKFLOW.md` order whose value renders `on|off • <chars>c/<tokens>t` measured size facts plus the context-occupancy suffix computed from the enabled existing token total against the selected model max input context, followed by a value-less subtree-local `Reset defaults` row. Cycle values embed the same measured facts and occupancy suffix so inline toggling keeps the size estimate visible while persisting the on|off state. Runtime is O(1) in row count. No external state is mutated.
|
|
4570
4582
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
4571
4583
|
* @param[in] sizes {Record<ContextFileName, ContextFileSizeFacts>} Measured context-file size facts keyed by canonical file name.
|
|
4584
|
+
* @param[in] maxContextTokens {number | undefined} Selected model max input context tokens; undefined selects the documented 1,000,000-token fallback.
|
|
4572
4585
|
* @return {PiUsereqSettingsMenuChoice[]} Ordered `Context Files` submenu choices.
|
|
4573
|
-
* @satisfies REQ-327, REQ-328, REQ-333, REQ-375
|
|
4586
|
+
* @satisfies REQ-327, REQ-328, REQ-333, REQ-375, REQ-403, REQ-404, REQ-406
|
|
4574
4587
|
*/
|
|
4575
4588
|
function buildContextFilesMenuChoices(
|
|
4576
4589
|
config: UseReqConfig,
|
|
4577
4590
|
sizes: Record<ContextFileName, ContextFileSizeFacts>,
|
|
4591
|
+
maxContextTokens?: number | undefined,
|
|
4578
4592
|
): PiUsereqSettingsMenuChoice[] {
|
|
4593
|
+
const totalTokens = sumEnabledContextFileTokens(config, sizes);
|
|
4594
|
+
const occupancySuffix = totalTokens > 0
|
|
4595
|
+
? ` ${computeContextOccupancyFacts(totalTokens, maxContextTokens).suffix}`
|
|
4596
|
+
: "";
|
|
4579
4597
|
const buildRow = (
|
|
4580
4598
|
id: "context-files-requirements" | "context-files-references" | "context-files-workflow",
|
|
4581
4599
|
fileName: ContextFileName,
|
|
4582
4600
|
description: string,
|
|
4583
4601
|
): PiUsereqSettingsMenuChoice => {
|
|
4584
|
-
const sizedOn = `on \u2022 ${formatContextFileSize(sizes[fileName])}`;
|
|
4585
|
-
const sizedOff = `off \u2022 ${formatContextFileSize(sizes[fileName])}`;
|
|
4602
|
+
const sizedOn = `on \u2022 ${formatContextFileSize(sizes[fileName])}${occupancySuffix}`;
|
|
4603
|
+
const sizedOff = `off \u2022 ${formatContextFileSize(sizes[fileName])}${occupancySuffix}`;
|
|
4586
4604
|
return {
|
|
4587
4605
|
id,
|
|
4588
4606
|
label: fileName,
|
|
@@ -4619,13 +4637,15 @@ function buildContextFilesMenuChoices(
|
|
|
4619
4637
|
* @param[in] ctx {ExtensionCommandContext} Active command context.
|
|
4620
4638
|
* @param[in,out] config {UseReqConfig} Mutable effective project configuration.
|
|
4621
4639
|
* @param[in] onConfigChange {() => void} Shared persistence-plus-status callback.
|
|
4640
|
+
* @param[in] maxContextTokens {number | undefined} Selected model max input context tokens used by the submenu occupancy suffix; undefined selects the documented 1,000,000-token fallback.
|
|
4622
4641
|
* @return {Promise<void>} Promise resolved when the submenu closes.
|
|
4623
|
-
* @satisfies REQ-327, REQ-328, REQ-333
|
|
4642
|
+
* @satisfies REQ-327, REQ-328, REQ-333, REQ-406
|
|
4624
4643
|
*/
|
|
4625
4644
|
async function configureContextFilesMenu(
|
|
4626
4645
|
ctx: ExtensionCommandContext,
|
|
4627
4646
|
config: UseReqConfig,
|
|
4628
4647
|
onConfigChange: () => void,
|
|
4648
|
+
maxContextTokens?: number | undefined,
|
|
4629
4649
|
): Promise<void> {
|
|
4630
4650
|
const contextFileSizes = measureContextFileSizes(getProjectBase(ctx.cwd), config);
|
|
4631
4651
|
const setFlag = (flagKey: "context-files-requirements" | "context-files-references" | "context-files-workflow", enabled: boolean): void => {
|
|
@@ -4635,9 +4655,9 @@ async function configureContextFilesMenu(
|
|
|
4635
4655
|
};
|
|
4636
4656
|
let focusedChoiceId: string | undefined;
|
|
4637
4657
|
while (true) {
|
|
4638
|
-
const choice = await showPiUsereqSettingsMenu(ctx, "Context Files", buildContextFilesMenuChoices(config, contextFileSizes), {
|
|
4658
|
+
const choice = await showPiUsereqSettingsMenu(ctx, "Context Files", buildContextFilesMenuChoices(config, contextFileSizes, maxContextTokens), {
|
|
4639
4659
|
initialSelectedId: focusedChoiceId,
|
|
4640
|
-
getChoices: () => buildContextFilesMenuChoices(config, contextFileSizes),
|
|
4660
|
+
getChoices: () => buildContextFilesMenuChoices(config, contextFileSizes, maxContextTokens),
|
|
4641
4661
|
onChange: (choiceId, newValue) => {
|
|
4642
4662
|
if (choiceId === "context-files-requirements") {
|
|
4643
4663
|
setFlag("context-files-requirements", newValue.startsWith("on"));
|
|
@@ -4688,12 +4708,14 @@ async function configureContextFilesMenu(
|
|
|
4688
4708
|
* @details Serializes primary configuration actions into right-valued menu rows consumed by the shared settings-menu renderer, including the `Context Files` injection toggles, automatic git-commit mode, effective prompt-command worktree state, notification summary, debug summary, locked worktree rows when automatic git commit is disabled, and display-only local plus global config paths. Runtime is O(s) in source-directory count. No external state is mutated.
|
|
4689
4709
|
* @param[in] cwd {string} Current working directory.
|
|
4690
4710
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
4711
|
+
* @param[in] maxContextTokens {number | undefined} Selected model max input context tokens used by the `Context Files` occupancy suffix; undefined selects the documented 1,000,000-token fallback.
|
|
4691
4712
|
* @return {PiUsereqSettingsMenuChoice[]} Ordered top-level menu choices.
|
|
4692
|
-
* @satisfies REQ-006, REQ-031, REQ-137, REQ-150, REQ-151, REQ-152, REQ-162, REQ-190, REQ-191, REQ-197, REQ-204, REQ-205, REQ-212, REQ-215, REQ-216, REQ-236, REQ-237, REQ-238, REQ-239, REQ-240, REQ-314, REQ-318, REQ-319, REQ-320, REQ-326, REQ-376
|
|
4713
|
+
* @satisfies REQ-006, REQ-031, REQ-137, REQ-150, REQ-151, REQ-152, REQ-162, REQ-190, REQ-191, REQ-197, REQ-204, REQ-205, REQ-212, REQ-215, REQ-216, REQ-236, REQ-237, REQ-238, REQ-239, REQ-240, REQ-314, REQ-318, REQ-319, REQ-320, REQ-326, REQ-376, REQ-405
|
|
4693
4714
|
*/
|
|
4694
4715
|
function buildPiUsereqMenuChoices(
|
|
4695
4716
|
cwd: string,
|
|
4696
4717
|
config: UseReqConfig,
|
|
4718
|
+
maxContextTokens?: number | undefined,
|
|
4697
4719
|
): PiUsereqSettingsMenuChoice[] {
|
|
4698
4720
|
const autoGitCommitDisabled = config.AUTO_GIT_COMMIT === "disable";
|
|
4699
4721
|
const effectiveGitWorktreeEnabled = resolveEffectiveGitWorktreeEnabled(
|
|
@@ -4722,7 +4744,7 @@ function buildPiUsereqMenuChoices(
|
|
|
4722
4744
|
{
|
|
4723
4745
|
id: "context-files",
|
|
4724
4746
|
label: "Context Files",
|
|
4725
|
-
value: formatContextFilesSummary(config, measureContextFileSizes(cwd, config)),
|
|
4747
|
+
value: formatContextFilesSummary(config, measureContextFileSizes(cwd, config), maxContextTokens),
|
|
4726
4748
|
description: "Toggle injection of REQUIREMENTS.md, REFERENCES.md, and WORKFLOW.md into prompt context through `%%CONTEXT_FILES%%`.",
|
|
4727
4749
|
},
|
|
4728
4750
|
{
|
|
@@ -4865,6 +4887,7 @@ async function configurePiUsereq(
|
|
|
4865
4887
|
});
|
|
4866
4888
|
let config = loadProjectConfig(ctx.cwd);
|
|
4867
4889
|
const projectBase = getProjectBase(ctx.cwd);
|
|
4890
|
+
const maxContextTokens = resolveModelContextWindowTokens(statusController.state.contextUsage);
|
|
4868
4891
|
const initialShortcut = config["notify-sound-toggle-shortcut"];
|
|
4869
4892
|
const persistConfigChange = () => {
|
|
4870
4893
|
Object.assign(config, normalizeConfigPaths(projectBase, config));
|
|
@@ -4878,10 +4901,10 @@ async function configurePiUsereq(
|
|
|
4878
4901
|
const choice = await showPiUsereqSettingsMenu(
|
|
4879
4902
|
ctx,
|
|
4880
4903
|
"pi-usereq",
|
|
4881
|
-
buildPiUsereqMenuChoices(ctx.cwd, config),
|
|
4904
|
+
buildPiUsereqMenuChoices(ctx.cwd, config, maxContextTokens),
|
|
4882
4905
|
{
|
|
4883
4906
|
initialSelectedId: focusedChoiceId,
|
|
4884
|
-
getChoices: () => buildPiUsereqMenuChoices(ctx.cwd, config),
|
|
4907
|
+
getChoices: () => buildPiUsereqMenuChoices(ctx.cwd, config, maxContextTokens),
|
|
4885
4908
|
onChange: (choiceId, newValue) => {
|
|
4886
4909
|
if (choiceId === "auto-git-commit") {
|
|
4887
4910
|
config.AUTO_GIT_COMMIT = newValue === "enable" ? "enable" : "disable";
|
|
@@ -4934,7 +4957,7 @@ async function configurePiUsereq(
|
|
|
4934
4957
|
continue;
|
|
4935
4958
|
}
|
|
4936
4959
|
if (choice === "context-files") {
|
|
4937
|
-
await configureContextFilesMenu(ctx, config, persistConfigChange);
|
|
4960
|
+
await configureContextFilesMenu(ctx, config, persistConfigChange, maxContextTokens);
|
|
4938
4961
|
continue;
|
|
4939
4962
|
}
|
|
4940
4963
|
if (choice === "auto-git-commit") {
|
|
@@ -5079,7 +5102,7 @@ async function configurePiUsereq(
|
|
|
5079
5102
|
{ label: "Document directory", previousValue: config["docs-dir"], nextValue: defaultConfig["docs-dir"] },
|
|
5080
5103
|
{ label: "Source-code directories", previousValue: config["src-dir"].join(", "), nextValue: defaultConfig["src-dir"].join(", ") },
|
|
5081
5104
|
{ label: "Unit tests directory", previousValue: config["tests-dir"], nextValue: defaultConfig["tests-dir"] },
|
|
5082
|
-
{ label: "Context Files", previousValue: formatContextFilesSummary(config, measureContextFileSizes(ctx.cwd, config)), nextValue: formatContextFilesSummary(defaultConfig, measureContextFileSizes(ctx.cwd, defaultConfig)) },
|
|
5105
|
+
{ label: "Context Files", previousValue: formatContextFilesSummary(config, measureContextFileSizes(ctx.cwd, config), maxContextTokens), nextValue: formatContextFilesSummary(defaultConfig, measureContextFileSizes(ctx.cwd, defaultConfig), maxContextTokens) },
|
|
5083
5106
|
{ label: "Auto git commit", previousValue: config.AUTO_GIT_COMMIT, nextValue: defaultConfig.AUTO_GIT_COMMIT },
|
|
5084
5107
|
{ label: "Git worktree", previousValue: config.GIT_WORKTREE_ENABLED, nextValue: defaultConfig.GIT_WORKTREE_ENABLED },
|
|
5085
5108
|
{ label: "Worktree prefix", previousValue: config.GIT_WORKTREE_PREFIX, nextValue: defaultConfig.GIT_WORKTREE_PREFIX },
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v0.8.0
|
|
@@ -102,7 +102,7 @@ Use for: string/pattern searches inside code bodies, cross-file references, conf
|
|
|
102
102
|
## Execution Protocol (Global vs Local)
|
|
103
103
|
You must manage the execution flow using two distinct methods:
|
|
104
104
|
- **Global Roadmap** (*check-list*):
|
|
105
|
-
- You MUST maintain a *check-list* internally with `
|
|
105
|
+
- You MUST maintain a *check-list* internally with `3` Steps (one item per Step).
|
|
106
106
|
- **Do NOT** use the *task-list tool* for this high-level roadmap.
|
|
107
107
|
- **Local Sub-tasks** (Tool Usage):
|
|
108
108
|
- If a *task-list tool* is available, use it **exclusively** to manage granular sub-tasks *within* a specific step (e.g., in Step X: "1. Edit file A", "2. Edit file B"; or in Step Y: "1. Fix test K", "2. Fix test L").
|
|
@@ -123,13 +123,22 @@ During the execution flow you MUST follow these directives:
|
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
## Steps
|
|
126
|
-
Create internally a *check-list* for the **Global Roadmap** including all the numbered steps below: `1..
|
|
126
|
+
Create internally a *check-list* for the **Global Roadmap** including all the numbered steps below: `1..3`, and start following the roadmap at the same time, executing the instructions of Step 1. If a tool call is required in Step 1, invoke it immediately; otherwise proceed to Step 1 without additional commentary. Do not add extra intent-adjustment checks unless explicitly listed in the Steps section.
|
|
127
127
|
1. Analyze the [User Request](#users-request)
|
|
128
128
|
- Using [User Request](#users-request) as a unified semantic framework, extract all directly and tangentially related information from `%%DOC_PATH%%/REQUIREMENTS.md`, `%%DOC_PATH%%/WORKFLOW.md` and `%%DOC_PATH%%/REFERENCES.md`, prioritizing high recall to capture every borderline connection across both sources, to identify the most likely related files and functions based on explicit evidence, and treat any uncertain links as candidates without claiming completeness, then analyze the involved source code from %%SRC_PATHS%% to answer the [User Request](#users-request), ensuring compliance with %%GUIDELINES_FILES%% documents if present.
|
|
129
129
|
- Do NOT create or modify tests in this workflow. If you cite tests as evidence, treat them as read-only artifacts.
|
|
130
130
|
- Read %%GUIDELINES_FILES%% files and ensure any suggested follow-up changes would conform to those **guidelines**. Do not check unrelated **guidelines**.
|
|
131
|
-
2.
|
|
131
|
+
2. Generate the follow-up prompt text from the analysis outcome
|
|
132
|
+
- Using the Step 1 analysis outcome, classify the result against `%%DOC_PATH%%/REQUIREMENTS.md` into exactly one branch:
|
|
133
|
+
- IF the analysis identified an implementation behavior that conflicts with requirements (the source code must change while `%%DOC_PATH%%/REQUIREMENTS.md` stays unchanged), GENERATE the exact prompt text to pass to the LLM Agent with the `/req-fix` command, including the defect summary, the affected requirement IDs, and concrete evidence (file paths with line numbers).
|
|
134
|
+
- ELSE IF the analysis identified changes needed to BOTH the source code and `%%DOC_PATH%%/REQUIREMENTS.md`, GENERATE the exact prompt text to pass to the LLM Agent with the `/req-change` command, including the requested change description, the affected requirement IDs, and concrete evidence (file paths with line numbers).
|
|
135
|
+
- ELSE IF the analysis identified source-code modifications with the intent of improving or adjusting the sources (internals, structure, maintainability, or performance) while `%%DOC_PATH%%/REQUIREMENTS.md` stays unchanged and NO implementation behavior conflicting with requirements was identified, GENERATE the exact prompt text to pass to the LLM Agent with the `/req-refactor` command, including the improvement objective, the affected source paths/symbols, the requirement IDs constraining the behavior to preserve, and concrete evidence (file paths with line numbers).
|
|
136
|
+
- ELSE (no source-code or requirements modifications are required), do NOT generate any follow-up prompt text.
|
|
137
|
+
- Each generated follow-up prompt text (`/req-fix`, `/req-change`, or `/req-refactor`) MUST be printed ONLY when the analysis identified its corresponding trigger in the classification above, and MUST NOT be printed in any other case; when generated, carry it into Step 3 for printing under the `## **Next Workflow**` report section.
|
|
138
|
+
- Do NOT execute the generated follow-up prompt and do NOT apply any fix or repository modification in this workflow; this workflow remains read-only.
|
|
139
|
+
3. Present results
|
|
132
140
|
- PRINT, in the response, the final analysis report for a human reader using clear, easily understandable sentences and readable Markdown formatting that highlight key findings, file paths, and concise evidence. Use the fixed report schema: ## **Outcome**, ## **Requirement Delta**, ## **Design Delta**, ## **Implementation Delta**, ## **Verification Delta**, ## **Evidence**, ## **Assumptions**, ## **Next Workflow**. Final line MUST be exactly: STATUS: OK or STATUS: ERROR.
|
|
141
|
+
- Include the Step 2 generated follow-up prompt text under `## **Next Workflow**` ONLY when Step 2 generated it; omit the follow-up prompt text entirely in all other cases.
|
|
133
142
|
|
|
134
143
|
<h2 id="users-request">User's Request</h2>
|
|
135
144
|
%%ARGS%%
|
|
@@ -39,7 +39,7 @@ In scope: static analysis of user-visible behavior from %%SRC_PATHS%% and relate
|
|
|
39
39
|
- Write root `README.md` in English.
|
|
40
40
|
- Do not perform unrelated edits.
|
|
41
41
|
- Analyze user-visible implementation changes, including new features, CLI parameters/options, GUI interactions, distributed APIs, and configuration-file schema updates when present.
|
|
42
|
-
- Validate
|
|
42
|
+
- Validate the current root `README.md` exhaustively against implementation evidence: enumerate every section, validate each sentence, and record a per-sentence conformance outcome before editing; then update only missing, outdated, or incorrect user-facing content.
|
|
43
43
|
- Parse [User Request](#users-request) (`%%ARGS%%`) as explicit additional-edit directives, using the same anchor-based reference model used by `write.md`, and execute those directives in the same scoped README update pass.
|
|
44
44
|
- Keep non-analysis documentary sections unchanged, including document headers, versioning metadata, context/scope descriptions, personal motivations, related projects, and high-level conceptual or graphical descriptions that do not alter interface usage.
|
|
45
45
|
- Preserve existing README structure and formatting patterns (section order, heading hierarchy, bullet/list style, table style) whenever possible.
|
|
@@ -136,9 +136,12 @@ Create internally a *check-list* for the **Global Roadmap** including all the nu
|
|
|
136
136
|
- Use repository evidence only; for each finding, collect file paths and line ranges.
|
|
137
137
|
- Derive a compact "README coverage list" of user-visible behavior that MUST appear in root `README.md`.
|
|
138
138
|
2. Validate and update root `README.md`
|
|
139
|
-
- Read the current root `README.md` and
|
|
140
|
-
-
|
|
139
|
+
- Read the current root `README.md` and enumerate ALL its sections and headings in document order to fix the complete validation surface.
|
|
140
|
+
- Validate `README.md` sentence by sentence, section by section, in document order: for every sentence, verify its content against repository implementation evidence and record exactly one outcome: `CONFORMING`, `OUTDATED`, or `UNSUPPORTED`.
|
|
141
|
+
- Classify non-analysis documentary sections (headers, versioning, motivations, related projects, high-level graphics) as `NOT-ANALYZED-BY-DESIGN` instead of sentence-level validation; never skip any other part or section.
|
|
142
|
+
- Identify and list the exact `README.md` sections impacted by the detected user-visible implementation changes, the recorded validation outcomes, and explicit additional edits from [User Request](#users-request) before editing.
|
|
141
143
|
- Update only the identified sections so `README.md` reflects the current externally visible behavior and usage flows.
|
|
144
|
+
- Completeness gate: do NOT proceed to Step 3 until every enumerated section and every sentence has a recorded outcome and every `OUTDATED` or `UNSUPPORTED` sentence in analysis sections is corrected or removed.
|
|
142
145
|
- Keep all non-analysis documentary sections unchanged (e.g., headers, versioning, context/scope narratives, motivations, related projects, high-level graphics/descriptions not tied to interface behavior).
|
|
143
146
|
- Keep content focused on user interaction, setup, commands, interfaces, and observable outputs.
|
|
144
147
|
- Do NOT add internal implementation details, internal architecture, private symbol names, or algorithm internals.
|