Skip to content

fix: support prompt map dependencies - #974

Open
mldangelo-oai wants to merge 104 commits into
mainfrom
mdangelo/codex/sec-prompt-map-dependencies
Open

fix: support prompt map dependencies#974
mldangelo-oai wants to merge 104 commits into
mainfrom
mdangelo/codex/sec-prompt-map-dependencies

Conversation

@mldangelo-oai

Copy link
Copy Markdown
Contributor

Summary

  • model Promptfoo's supported mapping-form prompts
  • inspect map keys through the same containment-aware file visitor as array prompts
  • fail dependency extraction closed instead of translating exceptions into an empty inventory
  • regenerate the shipped dist/ bundle

Security impact

Fixes Codex Security finding csf_f464f43c8d24989b741c6cb1 / occurrence occ_9e5db0cfa90fdd59bfc02eb2.

Previously, a valid prompt map caused the array-only walker to throw after provider extraction. The outer catch returned [], erased the provider dependency, and allowed a provider-only pull request to take the normal successful no-change path.

Scope

This PR addresses mapping-form prompts and the fail-open exception boundary. Scalar prompts/providers and external tests/defaults remain separately tracked findings.

Validation

  • both map regressions failed before the patch
  • Promptfoo 0.121.14's real UnifiedConfigSchema accepts the original fixture
  • bundled patched helper retains providers/provider.py
  • file-backed map keys are extracted
  • unreadable/malformed config extraction now raises and causes the action to fail
  • npm run all passes: 9 test files, 239 tests, 100% coverage
  • post-commit npm run package leaves the tree clean

Copy link
Copy Markdown
Contributor Author

@codex review

Please review the exact current head: ddec68dcc27bd0ef80e1f12af00a2de48647bdd4, focusing on Promptfoo schema parity and fail-closed change detection.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the GitHub Action’s config dependency extraction to correctly handle Promptfoo’s mapping-form prompts and to fail closed (raise) on dependency-extraction errors, preventing provider-only changes from being incorrectly skipped.

Changes:

  • Support Promptfoo prompts as either an array or a mapping, and extract file://... dependencies from mapping keys.
  • Change dependency extraction error handling from “warn + return []” to “throw”, so the action fails closed.
  • Update tests and regenerate the bundled dist/ output.

Reviewed changes

Copilot reviewed 3 out of 5 changed files in this pull request and generated no comments.

File Description
src/utils/config.ts Adds mapping-form prompt dependency extraction and changes extraction failures to throw.
tests/utils/config.test.ts Adds regression tests for prompt maps and verifies fail-closed behavior on invalid YAML/read failures.
tests/main.test.ts Ensures the action fails (and does not execute promptfoo) when dependency extraction throws.
dist/index.js Regenerated bundle reflecting the updated dependency extraction logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ddec68dcc2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
Comment thread src/utils/config.ts Outdated
mldangelo and others added 2 commits July 8, 2026 08:58
…ompt-map-dependencies

# Conflicts:
#	dist/index.js.map
Both the array and mapping forms feed the same `extractPromptFile` visitor,
so select the iterable once (entries vs keys) instead of duplicating the
for-loop across an if/else. Behavior unchanged; regenerate dist.

Merges origin/main (js-yaml v5 config loading) and regenerates dist to clear
the merge conflict.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff1413db79

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
Comment thread src/utils/config.ts Outdated

Copy link
Copy Markdown
Contributor Author

@codex review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 6 changed files in this pull request and generated 2 comments.

Comment thread src/utils/config.ts Outdated
Comment thread src/utils/config.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8a8a1c046d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
@mldangelo-oai
mldangelo-oai requested a review from Copilot July 15, 2026 01:04
@mldangelo-oai

Copy link
Copy Markdown
Contributor Author

@codex review

Two missed-re-eval bugs in the dependencyChanged matcher:
- A directory dependency without a trailing slash (e.g. 'data') was only
  prefix-matched when isDirectory(dep) was true, so a PR that *deletes* the
  directory (isDirectory false) skipped the eval even though a watched child
  changed. Always test the directory-prefix form; a file dependency has no
  children so it never false-matches.
- config.ts classifies a bracket character class (file[1].txt) as a glob via
  hasGlobCharacterClass, but main.ts gated Minimatch behind glob.hasMagic,
  which reports no magic for single-char classes -> a deleted match like
  file1.txt was missed. Mirror config.ts's classification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 41ade6d4dc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
Comment on lines +1665 to +1667
processFileUrl(
`file://${renderedFilterPath}`,
true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve file URLs for Nunjucks filters

When a configured filter uses the supported file://filters/normalize.js form, this prepends a second scheme and passes file://file://filters/normalize.js to processFileUrl. That resolves as a literal file:/... path rather than the real filter script, so a PR changing only the filter can miss dependencyChanged and skip the evaluation; only add file:// when the configured value does not already have it.

Useful? React with 👍 / 👎.

@mldangelo

Copy link
Copy Markdown
Member

Two more correctness fixes pushed (41ade6d) — dependency matching side

An extended adversarial pass over the main.ts dependency-matching logic (the earlier passes only covered config.ts extraction) found two more real missed-re-eval bugs — the dangerous, under-inclusive direction — now fixed. npm run all passes (634 tests, 100% coverage, CI green).

  1. Deleted directory dependency (P3). A directory dep without a trailing slash (e.g. data) was only prefix-matched when isDirectory(dep) was true. In a PR that deletes the directory, isDirectory returns false, so the whole dep.endsWith('/') || isDirectory(dep) block was skipped and a changed child (data/context.json) didn't trigger the eval. Fixed by always testing the directory-prefix form (a file dep has no children, so it never false-matches).

  2. Bracket-class glob dependency (P2). config.ts classifies a bracket character class (file[1].txt) as a glob via hasGlobCharacterClass, but main.ts gated Minimatch behind glob.hasMagic, which reports no magic for single-char classes. So config.ts emitted file[1].txt as a raw glob dependency, but main.ts treated it as a literal and never matched a changed file1.txt → missed eval. Fixed by mirroring config.ts's classification (OR-in the same character-class check). Verified with the repo's glob 13.0.6 / minimatch 10.2.5.

Note: I checked the other config PRs — the bracket-class inconsistency is unique to this PR (the others' config.ts don't use hasGlobCharacterClass), while the directory bug also affected #979/#982/#983 (fixed there too).

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-24T08:52:04.431848Z f2923ed New commits
🔒 Security Review Completed 2026-08-24T08:56:29.996986Z f2923ed New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dddfda4793

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
if (absolutePath) {
dependencies.add(absolutePath);
}
if (Array.isArray(config.prompts)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Regenerate the shipped action bundle

For every installed GitHub Action run, action.yml executes dist/index.js, but this commit changes only src/utils/config.ts; the committed bundle still performs for (const prompt of config.prompts) and therefore retains the mapping-form failure this patch is intended to fix. Regenerate and commit dist/ so consumers execute this new array/map branch.

AGENTS.md reference: AGENTS.md:L96-L98

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +261 to +263
} catch (error) {
core.warning(
`Failed to extract dependencies from config: ${error instanceof Error ? error.message : String(error)}`,
);
return [];
const message = error instanceof Error ? error.message : String(error);
throw new Error(`Failed to extract dependencies from config: ${message}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve JavaScript and TypeScript config support

When the action is given a supported .js/.ts Promptfoo config and the event supplies any changed-file list, dependency extraction attempts to parse the module source as YAML; typical export default { ... } syntax throws, and this new rethrow propagates to run() and marks the action failed before Promptfoo can load the config. Detect executable config extensions and conservatively run/watch all changes rather than treating their non-YAML syntax as an extraction failure.

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +155 to +157
const extractPromptFile = (prompt: PromptEntry): void => {
if (typeof prompt === 'string' && prompt.startsWith('file://')) {
processFileUrl(prompt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Track non-file-URL mapped prompt references

When a mapping-form prompt uses another Promptfoo-supported reference form, such as prompts/main.txt: main prompt or exec:./prompts/generate.sh: generated prompt, each key reaches this helper but is discarded because it does not start with file://. With changed-file filtering enabled, changing only that prompt or generator can therefore leave dependencyChanged false and cause the action to skip the evaluation; mapped keys need the same bare-path and executable-reference handling as Promptfoo.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dddfda4793

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
Comment on lines +180 to +181
for (const prompt of Object.keys(config.prompts)) {
extractPromptFile(prompt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Rebuild the distributed action bundle

action.yml executes dist/index.js, but this commit leaves that blob byte-for-byte unchanged; the bundled extractor still iterates config.prompts directly and catches extraction failures by returning []. Consumers therefore receive none of the new prompt-map or fail-closed behavior even though the source tests pass. Regenerate and commit dist/ with the source changes.

AGENTS.md reference: AGENTS.md:L94-L99

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +180 to +181
for (const prompt of Object.keys(config.prompts)) {
extractPromptFile(prompt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recognize bare and exec-backed mapped prompts

When a prompt map key uses a supported bare path or command form, such as prompts/main.txt: main or 'exec:./prompts/generate.sh': generated, extractPromptFile ignores it because string entries are accepted only when they begin with file://. A PR changing only the referenced prompt or generator can therefore leave dependencyChanged false and skip the evaluation; handle the same bare-path and executable forms that Promptfoo loads at runtime.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +155 to +157
const extractPromptFile = (prompt: PromptEntry): void => {
if (typeof prompt === 'string' && prompt.startsWith('file://')) {
processFileUrl(prompt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve absolute file URLs in mapped prompts

When a map key is an absolute URL such as file:///workspace/repo/prompts/main.txt, the new branch sends it to processFileUrl, where removing the scheme leaves an absolute-looking path that is passed through path.join(configDir, filePath). Node joins that under the config directory, producing a nonexistent path such as evals/workspace/repo/prompts/main.txt instead of the real in-workspace file, so an edit to the actual prompt is not detected. Resolve contained absolute paths directly before recording the dependency.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +155 to +157
const extractPromptFile = (prompt: PromptEntry): void => {
if (typeof prompt === 'string' && prompt.startsWith('file://')) {
processFileUrl(prompt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve zero-match mapped prompt glob roots

When a mapped prompt glob has no matches in the post-change checkout—most notably when a PR deletes its last matched file—this path can return no usable dependency. For file://prompts/*.txt, the helper records prompts without a directory marker, so after the directory disappears isDirectory is false and the deleted prompts/old.txt does not match; a root-level file://*.txt records no base at all. Preserve a directory sentinel for zero-match globs so deletions still trigger evaluation.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 97f0bb7663

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
Comment on lines 159 to 160
if (prompt.startsWith('file://')) {
processFileUrl(prompt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip function selectors from mapped file prompts

When a prompt-map key uses Promptfoo's supported function-backed form, such as file://prompts/build.py:create_prompt, this passes the selector through as part of the filename and records prompts/build.py:create_prompt instead of prompts/build.py. A change to the actual script therefore does not match the dependency, allowing the action to take the no-change path; strip the function selector before processing the file URL.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +163 to +166
} else if (
!/\s/.test(prompt) &&
/\.(?:txt|md|json|ya?ml|py|[cm]?[jt]s|njk)$/i.test(prompt)
) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept whitespace in bare mapped prompt paths

When a quoted prompt-map key is a valid bare path containing spaces, such as 'prompt assets/my generator.py': generated, this whitespace check discards it even though Promptfoo loads that path. If only that generator changes, no dependency matches and the evaluation can be skipped; classify path-like keys without rejecting all embedded whitespace.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines 159 to 160
if (prompt.startsWith('file://')) {
processFileUrl(prompt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Inspect dependencies inside mapped structured prompts

When a mapped prompt such as file://prompts/chat.yaml contains a message referencing file://partials/system.txt, Promptfoo loads both files, but this branch records only the outer YAML path and never inspects its structured contents. A PR that changes only the partial can therefore miss every dependency match and skip the evaluation; traverse file references inside mapped YAML and JSON prompts as well.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e9dac6e637

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
: promptPath;
processFileUrl(`file://${filePath}`);
} else if (prompt.startsWith('exec:')) {
processFileUrl(`file://${prompt.slice('exec:'.length)}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse executable prompt commands before recording dependencies

When a mapped executable prompt includes normal command arguments, such as 'exec:./prompts/generate.sh --tone formal': generated, this branch records prompts/generate.sh --tone formal as one filename rather than the script path. Consequently, a PR changing only prompts/generate.sh does not match the extracted dependency and the evaluation can be skipped. The fresh evidence after the earlier executable-prompt comment is that the new branch still passes the entire command tail directly to processFileUrl; parse the command and track its file-backed arguments instead.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +171 to +172
(!/\s/.test(prompt) || /[\\/]/.test(prompt)) &&
/\.(?:txt|md|json|ya?ml|py|[cm]?[jt]s|njk)$/i.test(prompt)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip selectors from bare function prompt keys

For a supported bare mapped function prompt such as 'prompts/build.py:create_prompt': generated, the key reaches this extension check with the selector still attached, so it no longer ends in .py and no dependency is recorded. A change to prompts/build.py can therefore be treated as unrelated. The fresh evidence after the prior selector fix is that selector stripping is performed only in the file:// branch; apply it before classifying bare prompt paths as well.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f3934009a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
Comment on lines +152 to +155
const absolutePath = resolveConfigDependency(
filePath,
'structured prompt dependency',
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Inspect each structured prompt matched by a glob

Although direct structured paths are now walked, a mapped glob such as file://prompts/*.yaml is resolved here as one literal wildcard path, so the subsequent existence check returns without inspecting any matched YAML. If a matched prompt references file://shared/system.txt outside the glob's base directory and only that shared file changes, it is absent from the dependency set and changed-file filtering skips an evaluation that would load the changed content; pass every expanded structured match through the walker.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4ee825fa19

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
Comment on lines +207 to +208
if (typeof value === 'string' && value.startsWith('file://')) {
processPromptFile(value);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip selectors from nested prompt references

When a mapped YAML or JSON prompt contains a function-backed reference such as file://prompts/build.py:create_prompt, this recursive branch passes the selector through to processPromptFile, which records prompts/build.py:create_prompt rather than the actual script. A change to prompts/build.py therefore does not match the extracted dependency and the action can incorrectly skip evaluation. Fresh evidence after the earlier top-level selector fix is that nested structured values still bypass the stripping performed in extractPromptFile.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +256 to +258
} else if (
(!/\s/.test(prompt) || /[\\/]/.test(prompt)) &&
/\.(?:txt|md|json|ya?ml|py|[cm]?[jt]s|njk)$/i.test(prompt)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include .j2 in bare mapped prompt detection

When a prompt map uses a bare Jinja template path such as prompts/main.j2, this extension allowlist ignores the key even though the newly added visitor explicitly recognizes .j2 as a text-template file. If only that template changes, no dependency matches and the action can skip the evaluation. Fresh evidence after the earlier bare-path fix is that .j2 remains omitted here while .njk and the other supported template extensions are accepted.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +191 to +195
if (isTextTemplate) {
for (const match of contents.matchAll(
/\{%-?\s*(?:include|extends|import|from)\s+(['"])(.*?)\1/g,
)) {
processPromptFile(`file://${match[2]}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail closed on dynamic template imports

When a mapped text template uses a Nunjucks expression such as {% include partialTemplate %} or an array of fallback templates, this regex recognizes only directly quoted filenames and silently records no dependency. In a changed-file-filtered run where the resolved partial is outside the monitored prompt glob, editing only that partial can therefore skip an evaluation even though Promptfoo loads the changed content at render time; unsupported dynamic file-loading tags need to trigger conservative dependency handling rather than being ignored.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +147 to +151
const filePath = fileUrl.slice('file://'.length);
const isStructuredPrompt = /\.(?:json|ya?ml)$/i.test(filePath);
const isTextTemplate = /\.(?:txt|md|j2|njk)$/i.test(filePath);
if (!isStructuredPrompt && !isTextTemplate) {
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recurse into imported templates regardless of extension

When a mapped .j2 or .njk prompt statically imports a template with another conventional suffix, for example base.html, the import itself is recorded but this extension gate prevents that file from being inspected. If base.html then includes partials/header.html, the header never enters the dependency set, so changing only it can skip evaluation even though Nunjucks loads it transitively; files reached through a template-loading tag should continue through the template visitor regardless of their suffix.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b614fa9de8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts Outdated
Comment on lines +145 to +146
for (const match of contents.matchAll(
/\{%-?\s*(?:include|extends|import|from)\s+([\s\S]+?)-?%\}/g,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore template tags inside comments and raw blocks

When a mapped template contains an inert dynamic tag inside a Nunjucks comment or {% raw %} block—for example {# {% include partialTemplate %} #}—this regex still matches it and adds the repository-root sentinel. Any unrelated changed file then sets dependencyChanged, causing the action to evaluate every prompt and potentially spend model quota even though Nunjucks never loads that dependency; exclude comments and raw blocks before scanning import tags.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Comment thread src/utils/config.ts Outdated
Comment on lines +171 to +173
const isTextTemplate =
importedTemplate || /\.(?:txt|md|j2|njk)$/i.test(filePath);
if (!isStructuredPrompt && !isTextTemplate) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Inspect all file-backed text prompt extensions

When a mapped text prompt uses another valid suffix, such as file://prompts/main.html, the outer file is recorded but this allowlist returns before scanning its Nunjucks content. If main.html includes shared/header.html, changing only that partial leaves it out of the dependency set and can incorrectly skip the evaluation; treat non-structured file-backed prompts as text templates rather than limiting top-level inspection to these four extensions.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 347e0759ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts
Comment on lines +181 to +183
!/\.(?:cjs|cts|j2|js|jsonl?|md|mjs|mts|py|ts|txt|ya?ml)(?::[A-Za-z_]\w*)?$/i.test(
prompt,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include .njk in bare prompt path detection

When a prompt map or scalar prompt uses a bare Nunjucks path such as prompts/main.njk, this extension allowlist rejects it, so changing only that template can leave dependencyChanged false and skip the evaluation. Unlike the previously reported .j2 case, this revision accepts .j2 but still omits the equally supported .njk extension.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 751def08d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/utils/config.ts
Comment on lines +72 to +74
const absolutePath = path.isAbsolute(filePath)
? path.normalize(filePath)
: path.resolve(path.join(configDir, filePath));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize Windows drive-letter file URLs before resolving

On Windows runners, a canonical mapped glob such as file:///D:/a/repo/prompts/*.txt reaches this code as /D:/a/repo/prompts/*.txt; path.normalize treats that as a current-drive-root path (\D:\a\...) rather than the drive-absolute path D:\a\.... Glob expansion and the fallback watcher root therefore use malformed paths, so changing or deleting the matched prompt can leave dependencyChanged false and skip evaluation. Fresh evidence beyond the prior absolute-path report is that this revision handles POSIX roots but still does not normalize the /D:/... Windows file-URL form.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants