@promptbook/cli 0.112.0-41 → 0.112.0-42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. package/esm/apps/agents-server/src/database/acquireMigrationExecutionLock.d.ts +12 -1
  2. package/esm/apps/agents-server/src/database/runDatabaseMigrations.d.ts +9 -0
  3. package/esm/index.es.js +189 -29
  4. package/esm/index.es.js.map +1 -1
  5. package/esm/scripts/verify-prompts/verify-prompts.d.ts +23 -2
  6. package/esm/src/cli/cli-commands/coder/verify.test.d.ts +1 -0
  7. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +2 -14
  8. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/createAgentPersistenceRecords.d.ts +40 -0
  9. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/createAgentPersistenceRecords.test.d.ts +1 -0
  10. package/esm/src/version.d.ts +1 -1
  11. package/package.json +1 -1
  12. package/umd/apps/agents-server/src/database/acquireMigrationExecutionLock.d.ts +12 -1
  13. package/umd/apps/agents-server/src/database/runDatabaseMigrations.d.ts +9 -0
  14. package/umd/index.umd.js +189 -29
  15. package/umd/index.umd.js.map +1 -1
  16. package/umd/scripts/verify-prompts/verify-prompts.d.ts +23 -2
  17. package/umd/src/cli/cli-commands/coder/verify.test.d.ts +1 -0
  18. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +2 -14
  19. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/createAgentPersistenceRecords.d.ts +40 -0
  20. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/createAgentPersistenceRecords.test.d.ts +1 -0
  21. package/umd/src/version.d.ts +1 -1
@@ -1,8 +1,29 @@
1
+ import type { PromptFile } from '../run-codex-prompts/prompts/types/PromptFile';
2
+ /**
3
+ * Options supported by the prompt verification helper.
4
+ */
5
+ export type VerifyPromptsOptions = {
6
+ /**
7
+ * Process prompt files in reverse order.
8
+ */
9
+ readonly reverse?: boolean;
10
+ /**
11
+ * Ignore prompt files whose filename or first prompt line contains one of the provided values.
12
+ */
13
+ readonly ignore?: ReadonlyArray<string>;
14
+ };
1
15
  /**
2
16
  * Starts the verification loop and exits when no `[ ]` prompts remain.
3
17
  *
4
- * @param reverse - Process files in reverse order
18
+ * @public exported from `@promptbook/cli`
19
+ */
20
+ export declare function verifyPrompts(options?: VerifyPromptsOptions): Promise<void>;
21
+ /**
22
+ * Splits prompt files into files that should be verified now and files ignored for this run.
5
23
  *
6
24
  * @public exported from `@promptbook/cli`
7
25
  */
8
- export declare function verifyPrompts(reverse?: boolean): Promise<void>;
26
+ export declare function partitionPromptFilesByIgnore(promptFiles: ReadonlyArray<PromptFile>, ignoreValues: ReadonlyArray<string>): {
27
+ promptFiles: PromptFile[];
28
+ ignoredPromptFiles: PromptFile[];
29
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -4,23 +4,11 @@ import type { string_book } from '../../../../book-2.0/agent-source/string_book'
4
4
  import type { string_agent_name, string_agent_permanent_id } from '../../../../types/typeAliases';
5
5
  import { AgentCollectionInSupabaseOptions } from './AgentCollectionInSupabaseOptions';
6
6
  import type { AgentsDatabaseSchema } from './AgentsDatabaseSchema';
7
+ import { type CreateAgentPersistenceRecordsOptions } from './createAgentPersistenceRecords';
7
8
  /**
8
9
  * Options for creating a new agent entry.
9
10
  */
10
- type CreateAgentOptions = {
11
- /**
12
- * Visibility for the new agent.
13
- */
14
- readonly visibility?: 'PRIVATE' | 'UNLISTED' | 'PUBLIC';
15
- /**
16
- * Folder identifier to assign the new agent to.
17
- */
18
- readonly folderId?: number | null;
19
- /**
20
- * Sort order for the agent within its parent folder.
21
- */
22
- readonly sortOrder?: number;
23
- };
11
+ type CreateAgentOptions = CreateAgentPersistenceRecordsOptions;
24
12
  /**
25
13
  * Optional controls for persisting one source update.
26
14
  */
@@ -0,0 +1,40 @@
1
+ import type { AgentBasicInformation } from '../../../../book-2.0/agent-source/AgentBasicInformation';
2
+ import type { string_book } from '../../../../book-2.0/agent-source/string_book';
3
+ import type { CreateAgentInput } from '../../CreateAgentInput';
4
+ import type { AgentsDatabaseSchema } from './AgentsDatabaseSchema';
5
+ /**
6
+ * Optional persistence overrides for one new agent row.
7
+ *
8
+ * @private shared persistence helper for `AgentCollectionInSupabase`
9
+ */
10
+ export type CreateAgentPersistenceRecordsOptions = Omit<CreateAgentInput, 'source'>;
11
+ /**
12
+ * Prepared insert rows and returned profile for one newly persisted agent.
13
+ *
14
+ * @private shared persistence helper for `AgentCollectionInSupabase`
15
+ */
16
+ export type CreateAgentPersistenceRecordsResult = {
17
+ /**
18
+ * Parsed created agent profile including the resolved permanent id.
19
+ */
20
+ readonly createdAgent: AgentBasicInformation & Required<Pick<AgentBasicInformation, 'permanentId'>>;
21
+ /**
22
+ * Insert row for the `Agent` table.
23
+ */
24
+ readonly agentInsertRecord: AgentsDatabaseSchema['public']['Tables']['Agent']['Insert'];
25
+ /**
26
+ * Insert row for the `AgentHistory` table.
27
+ */
28
+ readonly agentHistoryInsertRecord: AgentsDatabaseSchema['public']['Tables']['AgentHistory']['Insert'];
29
+ };
30
+ /**
31
+ * Builds normalized insert rows for a newly created persisted agent.
32
+ *
33
+ * @param agentSource - Source content of the agent.
34
+ * @param options - Optional folder placement, ordering, and visibility overrides.
35
+ * @param createdAt - Shared creation timestamp used across all persisted rows.
36
+ * @returns Insert rows and the created agent profile.
37
+ *
38
+ * @private shared persistence helper for `AgentCollectionInSupabase`
39
+ */
40
+ export declare function createAgentPersistenceRecords(agentSource: string_book, options?: CreateAgentPersistenceRecordsOptions, createdAt?: string): CreateAgentPersistenceRecordsResult;
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
15
15
  export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
16
16
  /**
17
17
  * Represents the version string of the Promptbook engine.
18
- * It follows semantic versioning (e.g., `0.112.0-40`).
18
+ * It follows semantic versioning (e.g., `0.112.0-41`).
19
19
  *
20
20
  * @generated
21
21
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptbook/cli",
3
- "version": "0.112.0-41",
3
+ "version": "0.112.0-42",
4
4
  "description": "Promptbook: Turn your company's scattered knowledge into AI ready books",
5
5
  "private": false,
6
6
  "sideEffects": false,
@@ -1,14 +1,25 @@
1
1
  import type { Client } from 'pg';
2
2
  import type { DatabaseMigrationLogger } from './runDatabaseMigrations';
3
+ /**
4
+ * Lock-acquisition strategies used by the migration runner.
5
+ *
6
+ * `wait` is appropriate for explicit/manual migration flows where the caller expects one serialized run.
7
+ * `skip` is appropriate for background startup checks where waiting would block request handling.
8
+ *
9
+ * @private function of runDatabaseMigrations
10
+ */
11
+ export type DatabaseMigrationExecutionLockMode = 'wait' | 'skip';
3
12
  /**
4
13
  * Acquires advisory lock preventing concurrent migration execution across processes.
5
14
  *
6
15
  * @param client Connected PostgreSQL client.
7
16
  * @param logger Logger used for progress output.
17
+ * @param mode Whether the caller should block for the lock or skip when it is already held.
18
+ * @returns `true` when the lock was acquired and migrations may proceed.
8
19
  *
9
20
  * @private function of runDatabaseMigrations
10
21
  */
11
- export declare function acquireMigrationExecutionLock(client: Client, logger: DatabaseMigrationLogger): Promise<void>;
22
+ export declare function acquireMigrationExecutionLock(client: Client, logger: DatabaseMigrationLogger, mode?: DatabaseMigrationExecutionLockMode): Promise<boolean>;
12
23
  /**
13
24
  * Releases advisory lock used for migration execution.
14
25
  *
@@ -1,4 +1,5 @@
1
1
  import { type ServerRecord } from '../utils/serverRegistry';
2
+ import { type DatabaseMigrationExecutionLockMode } from './acquireMigrationExecutionLock';
2
3
  /**
3
4
  * Allowed values describing who applied a migration record.
4
5
  */
@@ -67,6 +68,10 @@ export type RunDatabaseMigrationsOptions = {
67
68
  * If true, prints every SQL migration body before execution.
68
69
  */
69
70
  readonly logSqlStatements?: boolean;
71
+ /**
72
+ * Whether migration execution should wait for the advisory lock or skip when another process already owns it.
73
+ */
74
+ readonly executionLockMode?: DatabaseMigrationExecutionLockMode;
70
75
  };
71
76
  /**
72
77
  * Result of one prefix migration run.
@@ -97,6 +102,10 @@ export type RunDatabaseMigrationsResult = {
97
102
  * Per-prefix summary.
98
103
  */
99
104
  readonly perPrefix: ReadonlyArray<DatabaseMigrationPrefixResult>;
105
+ /**
106
+ * Whether migration execution was skipped because another process already held the advisory lock.
107
+ */
108
+ readonly isSkippedDueToActiveMigrationLock: boolean;
100
109
  };
101
110
  /**
102
111
  * Reads migration runtime configuration from environment variables and `_Server`.
package/umd/index.umd.js CHANGED
@@ -60,7 +60,7 @@
60
60
  * @generated
61
61
  * @see https://github.com/webgptorg/promptbook
62
62
  */
63
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-41';
63
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-42';
64
64
  /**
65
65
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
66
66
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -3094,14 +3094,16 @@
3094
3094
  - Archives verified prompt files to prompts/done/ directory
3095
3095
  - Auto-appends repair prompts for incomplete work
3096
3096
  - Processes files with all-done prompts first
3097
+ - Supports ignoring matching prompt candidates for one verification run
3097
3098
  `));
3098
3099
  command.option('--reverse', 'Process prompt files in reverse order', false);
3100
+ command.option('--ignore <candidate-text>', 'Ignore prompt files whose filename or first prompt line contains the given text (repeatable)', collectStringOption, []);
3099
3101
  command.action(handleActionErrors(async (cliOptions) => {
3100
- const { reverse } = cliOptions;
3102
+ const { reverse, ignore } = cliOptions;
3101
3103
  // Note: Import the main function dynamically to avoid loading heavy dependencies until needed
3102
3104
  const { verifyPrompts } = await Promise.resolve().then(function () { return verifyPrompts$1; });
3103
3105
  try {
3104
- await verifyPrompts(reverse);
3106
+ await verifyPrompts({ reverse, ignore });
3105
3107
  }
3106
3108
  catch (error) {
3107
3109
  console.error(colors__default["default"].bgRed('Prompt verification failed:'), error);
@@ -3110,6 +3112,14 @@
3110
3112
  return process.exit(0);
3111
3113
  }));
3112
3114
  }
3115
+ /**
3116
+ * Collects repeatable string options from Commander.
3117
+ *
3118
+ * @private internal utility of `coder verify` command
3119
+ */
3120
+ function collectStringOption(value, previousValues) {
3121
+ return [...previousValues, value];
3122
+ }
3113
3123
  // Note: [🟡] Code for CLI command [verify](src/cli/cli-commands/coder/verify.ts) should never be published outside of `@promptbook/cli`
3114
3124
  // Note: [💞] Ignore a discrepancy between file name and entity name
3115
3125
 
@@ -45392,6 +45402,7 @@
45392
45402
  return value.split('\\').join('/');
45393
45403
  }
45394
45404
 
45405
+ // cspell:ignore hashtext
45395
45406
  /**
45396
45407
  * Cross-process advisory lock key guarding migration execution.
45397
45408
  *
@@ -45403,13 +45414,27 @@
45403
45414
  *
45404
45415
  * @param client Connected PostgreSQL client.
45405
45416
  * @param logger Logger used for progress output.
45417
+ * @param mode Whether the caller should block for the lock or skip when it is already held.
45418
+ * @returns `true` when the lock was acquired and migrations may proceed.
45406
45419
  *
45407
45420
  * @private function of runDatabaseMigrations
45408
45421
  */
45409
- async function acquireMigrationExecutionLock(client, logger) {
45422
+ async function acquireMigrationExecutionLock(client, logger, mode = 'wait') {
45423
+ var _a;
45424
+ if (mode === 'skip') {
45425
+ logger.info('🔒 Checking migration lock without waiting');
45426
+ const { rows } = await client.query('SELECT pg_try_advisory_lock(hashtext($1)) AS "isMigrationLockAcquired";', [DATABASE_MIGRATION_LOCK_KEY]);
45427
+ if (!((_a = rows[0]) === null || _a === void 0 ? void 0 : _a.isMigrationLockAcquired)) {
45428
+ logger.info('⏭️ Migration lock is already held by another process. Skipping this migration attempt.');
45429
+ return false;
45430
+ }
45431
+ logger.info('🔒 Migration lock acquired');
45432
+ return true;
45433
+ }
45410
45434
  logger.info('🔒 Waiting for migration lock');
45411
45435
  await client.query('SELECT pg_advisory_lock(hashtext($1));', [DATABASE_MIGRATION_LOCK_KEY]);
45412
45436
  logger.info('🔒 Migration lock acquired');
45437
+ return true;
45413
45438
  }
45414
45439
  /**
45415
45440
  * Releases advisory lock used for migration execution.
@@ -45933,23 +45958,33 @@
45933
45958
  * @returns Aggregated migration summary.
45934
45959
  */
45935
45960
  async function runDatabaseMigrations(options) {
45936
- var _a, _b, _c, _d;
45961
+ var _a, _b, _c, _d, _e;
45937
45962
  const logger = (_a = options.logger) !== null && _a !== void 0 ? _a : console;
45938
45963
  const selectedPrefixes = selectPrefixesForMigration(options.prefixes, (_b = options.registeredServers) !== null && _b !== void 0 ? _b : [], options.onlyTargets);
45939
45964
  const migrationsDirectory = (_c = options.migrationsDirectory) !== null && _c !== void 0 ? _c : (await resolveMigrationsDirectory());
45940
45965
  const migrationFiles = await readMigrationFiles(migrationsDirectory);
45966
+ const totalMigrationFiles = migrationFiles.length;
45941
45967
  const perPrefix = [];
45942
- logger.info(`📂 Found ${migrationFiles.length} migration files`);
45968
+ logger.info(`📂 Found ${totalMigrationFiles} migration files`);
45943
45969
  logger.info(`📋 Found ${selectedPrefixes.length} prefixes to migrate: ${selectedPrefixes
45944
45970
  .map((prefix) => prefix || '<default>')
45945
45971
  .join(', ')}`);
45946
45972
  const client = await createPostgresClient(options.connectionString);
45947
45973
  let hasExecutionLock = false;
45974
+ let isSkippedDueToActiveMigrationLock = false;
45948
45975
  try {
45949
45976
  await client.connect();
45950
45977
  logger.info('🔌 Connected to database');
45951
- await acquireMigrationExecutionLock(client, logger);
45952
- hasExecutionLock = true;
45978
+ hasExecutionLock = await acquireMigrationExecutionLock(client, logger, (_d = options.executionLockMode) !== null && _d !== void 0 ? _d : 'wait');
45979
+ if (!hasExecutionLock) {
45980
+ isSkippedDueToActiveMigrationLock = true;
45981
+ return {
45982
+ processedPrefixes: [],
45983
+ totalMigrationFiles,
45984
+ perPrefix,
45985
+ isSkippedDueToActiveMigrationLock,
45986
+ };
45987
+ }
45953
45988
  for (const prefix of selectedPrefixes) {
45954
45989
  logger.info(`\n🏗️ Migrating prefix: "${prefix}"`);
45955
45990
  const appliedCount = await migratePrefix({
@@ -45960,7 +45995,7 @@
45960
45995
  logger,
45961
45996
  migrationFiles,
45962
45997
  migrationsDirectory,
45963
- logSqlStatements: (_d = options.logSqlStatements) !== null && _d !== void 0 ? _d : false,
45998
+ logSqlStatements: (_e = options.logSqlStatements) !== null && _e !== void 0 ? _e : false,
45964
45999
  });
45965
46000
  perPrefix.push({ prefix, appliedCount });
45966
46001
  }
@@ -45973,8 +46008,9 @@
45973
46008
  }
45974
46009
  return {
45975
46010
  processedPrefixes: selectedPrefixes,
45976
- totalMigrationFiles: migrationFiles.length,
46011
+ totalMigrationFiles,
45977
46012
  perPrefix,
46013
+ isSkippedDueToActiveMigrationLock,
45978
46014
  };
45979
46015
  }
45980
46016
  /**
@@ -48162,24 +48198,26 @@
48162
48198
  */
48163
48199
  const MAX_PENDING_FILE_NAMES = 8;
48164
48200
  /**
48165
- * Parse command-line arguments
48201
+ * Default verification options parsed from the current process arguments.
48166
48202
  */
48167
- const REVERSE_ORDER = process.argv.includes('--reverse');
48203
+ const DEFAULT_VERIFY_PROMPTS_OPTIONS = normalizeVerifyPromptsOptions(parseVerifyPromptsCliOptions(process.argv.slice(2)));
48168
48204
  /**
48169
48205
  * Starts the verification loop and exits when no `[ ]` prompts remain.
48170
48206
  *
48171
- * @param reverse - Process files in reverse order
48172
- *
48173
48207
  * @public exported from `@promptbook/cli`
48174
48208
  */
48175
- async function verifyPrompts(reverse = REVERSE_ORDER) {
48209
+ async function verifyPrompts(options = DEFAULT_VERIFY_PROMPTS_OPTIONS) {
48210
+ const normalizedOptions = normalizeVerifyPromptsOptions(options);
48176
48211
  console.info(colors__default["default"].cyan.bold('📋 Prompt verification helper'));
48177
- if (reverse) {
48212
+ if (normalizedOptions.reverse) {
48178
48213
  console.info(colors__default["default"].gray('Processing files in reverse order'));
48179
48214
  }
48180
- const initialFiles = await loadPromptFiles(PROMPTS_DIR);
48181
- if (reverse) {
48182
- initialFiles.reverse();
48215
+ if (normalizedOptions.ignore.length > 0) {
48216
+ console.info(colors__default["default"].gray(`Ignoring candidates matching: ${normalizedOptions.ignore.join(', ')}`));
48217
+ }
48218
+ const { promptFiles: initialFiles, ignoredPromptFiles } = await loadPromptFilesForVerification(normalizedOptions);
48219
+ if (ignoredPromptFiles.length > 0) {
48220
+ console.info(colors__default["default"].gray(`Ignored ${ignoredPromptFiles.length} prompt file(s) for this run.`));
48183
48221
  }
48184
48222
  displayTopLevelFileList(initialFiles);
48185
48223
  await prepareArchiveDirectory();
@@ -48194,10 +48232,7 @@
48194
48232
  if (wasSkipped) {
48195
48233
  skippedFiles.add(fileWithAllDone.path);
48196
48234
  }
48197
- promptFiles = await loadPromptFiles(PROMPTS_DIR);
48198
- if (REVERSE_ORDER) {
48199
- promptFiles.reverse();
48200
- }
48235
+ promptFiles = (await loadPromptFilesForVerification(normalizedOptions)).promptFiles;
48201
48236
  continue;
48202
48237
  }
48203
48238
  // Second priority: process todo prompts
@@ -48207,11 +48242,56 @@
48207
48242
  break;
48208
48243
  }
48209
48244
  await resolvePrompt(nextPrompt);
48210
- promptFiles = await loadPromptFiles(PROMPTS_DIR);
48211
- if (REVERSE_ORDER) {
48212
- promptFiles.reverse();
48245
+ promptFiles = (await loadPromptFilesForVerification(normalizedOptions)).promptFiles;
48246
+ }
48247
+ }
48248
+ /**
48249
+ * Parses supported command-line arguments for the standalone verification script.
48250
+ */
48251
+ function parseVerifyPromptsCliOptions(args) {
48252
+ return {
48253
+ reverse: args.includes('--reverse'),
48254
+ ignore: readRepeatableStringOption(args, '--ignore'),
48255
+ };
48256
+ }
48257
+ /**
48258
+ * Loads prompt files and applies ordering plus ignore filters for one verification pass.
48259
+ */
48260
+ async function loadPromptFilesForVerification(options) {
48261
+ const loadedPromptFiles = await loadPromptFiles(PROMPTS_DIR);
48262
+ const { promptFiles, ignoredPromptFiles } = partitionPromptFilesByIgnore(loadedPromptFiles, options.ignore);
48263
+ if (options.reverse) {
48264
+ promptFiles.reverse();
48265
+ }
48266
+ return { promptFiles, ignoredPromptFiles };
48267
+ }
48268
+ /**
48269
+ * Splits prompt files into files that should be verified now and files ignored for this run.
48270
+ *
48271
+ * @public exported from `@promptbook/cli`
48272
+ */
48273
+ function partitionPromptFilesByIgnore(promptFiles, ignoreValues) {
48274
+ const normalizedIgnoreValues = normalizeIgnoreValues(ignoreValues);
48275
+ if (normalizedIgnoreValues.length === 0) {
48276
+ return {
48277
+ promptFiles: [...promptFiles],
48278
+ ignoredPromptFiles: [],
48279
+ };
48280
+ }
48281
+ const promptFilesToVerify = [];
48282
+ const ignoredPromptFiles = [];
48283
+ for (const promptFile of promptFiles) {
48284
+ if (matchesIgnoredPromptFile(promptFile, normalizedIgnoreValues)) {
48285
+ ignoredPromptFiles.push(promptFile);
48286
+ }
48287
+ else {
48288
+ promptFilesToVerify.push(promptFile);
48213
48289
  }
48214
48290
  }
48291
+ return {
48292
+ promptFiles: promptFilesToVerify,
48293
+ ignoredPromptFiles,
48294
+ };
48215
48295
  }
48216
48296
  /**
48217
48297
  * Ensures the destination directory for completed prompts exists.
@@ -48219,13 +48299,92 @@
48219
48299
  async function prepareArchiveDirectory() {
48220
48300
  await promises.mkdir(DONE_PROMPTS_DIR, { recursive: true });
48221
48301
  }
48302
+ /**
48303
+ * Normalizes verification options so the rest of the flow can assume stable defaults.
48304
+ */
48305
+ function normalizeVerifyPromptsOptions(options) {
48306
+ var _a, _b;
48307
+ return {
48308
+ reverse: (_a = options.reverse) !== null && _a !== void 0 ? _a : false,
48309
+ ignore: normalizeIgnoreValues((_b = options.ignore) !== null && _b !== void 0 ? _b : []),
48310
+ };
48311
+ }
48312
+ /**
48313
+ * Normalizes ignore values and removes empty or duplicate entries case-insensitively.
48314
+ */
48315
+ function normalizeIgnoreValues(ignoreValues) {
48316
+ const normalizedIgnoreValues = [];
48317
+ const seenIgnoreValues = new Set();
48318
+ for (const ignoreValue of ignoreValues) {
48319
+ const trimmedIgnoreValue = ignoreValue.trim();
48320
+ if (!trimmedIgnoreValue) {
48321
+ continue;
48322
+ }
48323
+ const lowerCasedIgnoreValue = trimmedIgnoreValue.toLowerCase();
48324
+ if (seenIgnoreValues.has(lowerCasedIgnoreValue)) {
48325
+ continue;
48326
+ }
48327
+ seenIgnoreValues.add(lowerCasedIgnoreValue);
48328
+ normalizedIgnoreValues.push(trimmedIgnoreValue);
48329
+ }
48330
+ return normalizedIgnoreValues;
48331
+ }
48332
+ /**
48333
+ * Reads one repeatable string option from raw CLI arguments.
48334
+ */
48335
+ function readRepeatableStringOption(args, flag) {
48336
+ const values = [];
48337
+ for (let index = 0; index < args.length; index += 1) {
48338
+ const argument = args[index];
48339
+ if (!argument) {
48340
+ continue;
48341
+ }
48342
+ if (argument === flag) {
48343
+ const nextValue = args[index + 1];
48344
+ if (nextValue !== undefined && !nextValue.startsWith('--')) {
48345
+ values.push(nextValue);
48346
+ index += 1;
48347
+ }
48348
+ continue;
48349
+ }
48350
+ if (argument.startsWith(`${flag}=`)) {
48351
+ values.push(argument.slice(flag.length + 1));
48352
+ }
48353
+ }
48354
+ return values;
48355
+ }
48356
+ /**
48357
+ * Resolves whether a prompt file should be ignored for this verification run.
48358
+ */
48359
+ function matchesIgnoredPromptFile(promptFile, ignoreValues) {
48360
+ const searchableValues = [promptFile.name, getPromptFileFirstLine(promptFile)].map((value) => value.toLowerCase());
48361
+ return ignoreValues.some((ignoreValue) => {
48362
+ const lowerCasedIgnoreValue = ignoreValue.toLowerCase();
48363
+ return searchableValues.some((searchableValue) => searchableValue.includes(lowerCasedIgnoreValue));
48364
+ });
48365
+ }
48366
+ /**
48367
+ * Returns the first meaningful line of the prompt file after the status line.
48368
+ */
48369
+ function getPromptFileFirstLine(promptFile) {
48370
+ var _a;
48371
+ const firstSection = promptFile.sections[0];
48372
+ const startLineIndex = (firstSection === null || firstSection === void 0 ? void 0 : firstSection.statusLineIndex) !== undefined ? firstSection.statusLineIndex + 1 : ((_a = firstSection === null || firstSection === void 0 ? void 0 : firstSection.startLine) !== null && _a !== void 0 ? _a : 0);
48373
+ for (let index = startLineIndex; index < promptFile.lines.length; index += 1) {
48374
+ const line = promptFile.lines[index];
48375
+ if (line !== undefined && line.trim() !== '') {
48376
+ return line.trim();
48377
+ }
48378
+ }
48379
+ return '';
48380
+ }
48222
48381
  /**
48223
48382
  * Displays the list of files that currently live in the prompts root.
48224
48383
  */
48225
48384
  function displayTopLevelFileList(promptFiles) {
48226
48385
  console.info(colors__default["default"].cyan('\nTop-level prompt files:'));
48227
48386
  if (!promptFiles.length) {
48228
- console.info(colors__default["default"].gray(' (no markdown files found in prompts/)'));
48387
+ console.info(colors__default["default"].gray(' (no prompt markdown files found for this run in prompts/)'));
48229
48388
  return;
48230
48389
  }
48231
48390
  for (const file of promptFiles) {
@@ -48542,7 +48701,7 @@
48542
48701
  }
48543
48702
  // Note: When run as a standalone script, call the exported function
48544
48703
  if (require.main === module) {
48545
- verifyPrompts(REVERSE_ORDER).catch((error) => {
48704
+ verifyPrompts(DEFAULT_VERIFY_PROMPTS_OPTIONS).catch((error) => {
48546
48705
  console.error(colors__default["default"].bgRed('Prompt verification failed:'), error);
48547
48706
  process.exit(1);
48548
48707
  });
@@ -48550,7 +48709,8 @@
48550
48709
 
48551
48710
  var verifyPrompts$1 = /*#__PURE__*/Object.freeze({
48552
48711
  __proto__: null,
48553
- verifyPrompts: verifyPrompts
48712
+ verifyPrompts: verifyPrompts,
48713
+ partitionPromptFilesByIgnore: partitionPromptFilesByIgnore
48554
48714
  });
48555
48715
 
48556
48716
  /**