fix: bug of the prompts can't render in each other#1
Conversation
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="pyproject.toml">
<violation number="1" location="pyproject.toml:46">
P2: pytest is a test framework and should not be a runtime dependency. Remove it from `dependencies` — it is already listed under `[dependency-groups]` dev.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| @@ -43,6 +43,7 @@ dependencies = [ | |||
| "pyyaml>=6.0.0", | |||
| "tomli>=2.0.1; python_version < '3.11'", | |||
| "pydantic>=2.0.0", | |||
| "pytest>=8.4.2", | |||
There was a problem hiding this comment.
P2: pytest is a test framework and should not be a runtime dependency. Remove it from dependencies — it is already listed under [dependency-groups] dev.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At pyproject.toml, line 46:
<comment>pytest is a test framework and should not be a runtime dependency. Remove it from `dependencies` — it is already listed under `[dependency-groups]` dev.</comment>
<file context>
@@ -43,6 +43,7 @@ dependencies = [
"pyyaml>=6.0.0",
"tomli>=2.0.1; python_version < '3.11'",
"pydantic>=2.0.0",
+ "pytest>=8.4.2",
]
keywords = [
</file context>
There was a problem hiding this comment.
15 issues found
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="dynaprompt/engine/resolver.py">
<violation number="1" location="dynaprompt/engine/resolver.py:44">
P2: The `"dynaprompt"` exclusion is overly broad and may silently skip legitimate prompt files stored in a subdirectory named `dynaprompt`. This is the library's own name, not a standard system/environment directory like `__pycache__` or `venv`. Consider removing it from the exclusion list.</violation>
</file>
<file name="prompts/docs_api_reference_2_2.md">
<violation number="1" location="prompts/docs_api_reference_2_2.md:29">
P2: The `invoke` method does not exist on `PromptNode`. mkdocstrings will produce a warning or empty documentation for this non-existent member.</violation>
</file>
<file name="prompts/docs.advanced.debugging.md">
<violation number="1" location="prompts/docs.advanced.debugging.md:79">
P2: Replace deprecated `datetime.utcnow()` with `datetime.now(datetime.timezone.utc)` in the example code. `datetime.utcnow()` was deprecated in Python 3.12 and should not be used in documentation examples that users may copy.</violation>
</file>
<file name="prompts/docs.advanced.hooks.md">
<violation number="1" location="prompts/docs.advanced.hooks.md:122">
P2: Custom validator example and lifecycle diagram use `validate(node, rendered)` but the actual `PromptValidator.validate` signature is `validate(self, prompt_node, kwargs, current_env)`. The custom validator inheriting from `PromptValidator` will not work as shown — `rendered` will receive `kwargs` (a dict), so `rendered.text` would raise an AttributeError. Update the example and diagram to match the actual signature.</violation>
</file>
<file name="prompts/docs_advanced_async_2.md">
<violation number="1" location="prompts/docs_advanced_async_2.md:86">
P1: The `prompts.add_hook("before_render", "inject_context", async_inject_context)` call registers the hook under key `"before_render_inject_context"`, but the `async_hookable` dispatch for `async_render()` looks for `"before_async_render"`. The hook will silently never fire.</violation>
</file>
<file name="prompts/docs_advanced_environments_2.md">
<violation number="1" location="prompts/docs_advanced_environments_2.md:113">
P2: Debug trace output contradicts the TOML configuration: production sets `max_tokens = 4096`, but the debug trace shows `max_tokens = 1024 (from default)` while production is marked ACTIVE.</violation>
</file>
<file name="prompts/docs_advanced_environments_2_2_2.md">
<violation number="1" location="prompts/docs_advanced_environments_2_2_2.md:100">
P3: debug_trace() output shown in the documentation does not match the actual implementation output. Users following the docs will expect this format but will see a different visualization.</violation>
</file>
<file name="prompts/docs_advanced_hooks.md">
<violation number="1" location="prompts/docs_advanced_hooks.md:118">
P2: `TiktokenValidator.__init__` should call `super().__init__()` to properly initialize the `PromptValidator` base class. Without it, any setup that the base class performs (storing name patterns, validation rules, env gates, etc.) is skipped, which can cause runtime attribute errors or incorrect behavior.</violation>
</file>
<file name="prompts/docs_api_reference.md">
<violation number="1" location="prompts/docs_api_reference.md:29">
P1: The `invoke` member listed for `PromptNode` does not exist on the class. This will cause mkdocstrings to fail during documentation build.</violation>
</file>
<file name="prompts/docs_advanced_debugging_2.md">
<violation number="1" location="prompts/docs_advanced_debugging_2.md:72">
P2: The `prompt_hash` documentation is inaccurate: the hash is a 12-character truncation of the SHA-256 digest (not a full hash), and it is computed over `text`, `config`, and `schema_json` combined (not just `rendered.text`). Update the docs to match the actual implementation so users designing audit trails, test assertions, or version checks have correct expectations.</violation>
</file>
<file name="prompts/docs.schemas.md">
<violation number="1" location="prompts/docs.schemas.md:7">
P3: Document YAML schema loading here as well; the current text is incomplete and misleads users about supported schema files.</violation>
<violation number="2" location="prompts/docs.schemas.md:46">
P3: Remove the `register()` mention; this API does not exist in the repository.</violation>
</file>
<file name="prompts/docs_advanced_async.md">
<violation number="1" location="prompts/docs_advanced_async.md:70">
P2: Don't present `@async_hookable` as the way to attach async hooks, and don't show a before-render hook mutating kwargs here. As written, the example won't affect the render context.</violation>
<violation number="2" location="prompts/docs_advanced_async.md:106">
P2: Don't claim `render()` and `async_render()` are fully interchangeable. The sync path can't await async hooks, so they diverge as soon as a prompt uses coroutine hooks.</violation>
</file>
<file name="prompts/docs_advanced_hooks_2_2_2.md">
<violation number="1" location="prompts/docs_advanced_hooks_2_2_2.md:122">
P1: The `TiktokenValidator.validate` method signature `(self, node, rendered)` does not match the framework's actual `PromptValidator.validate` signature `(self, prompt_node, kwargs, current_env="default")`. The second argument is a `kwargs` dict (render variables), not a rendered result object, so `rendered.text` would raise an `AttributeError` at runtime.</violation>
</file>
Note: This PR contains a large number of files. cubic only reviews up to 100 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.
Re-trigger cubic
| kwargs["user_name"] = user_data["name"] | ||
| return kwargs | ||
|
|
||
| prompts.add_hook("before_render", "inject_context", async_inject_context) |
There was a problem hiding this comment.
P1: The prompts.add_hook("before_render", "inject_context", async_inject_context) call registers the hook under key "before_render_inject_context", but the async_hookable dispatch for async_render() looks for "before_async_render". The hook will silently never fire.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prompts/docs_advanced_async_2.md, line 86:
<comment>The `prompts.add_hook("before_render", "inject_context", async_inject_context)` call registers the hook under key `"before_render_inject_context"`, but the `async_hookable` dispatch for `async_render()` looks for `"before_async_render"`. The hook will silently never fire.</comment>
<file context>
@@ -0,0 +1,106 @@
+ kwargs["user_name"] = user_data["name"]
+ return kwargs
+
+prompts.add_hook("before_render", "inject_context", async_inject_context)
+
+rendered = await prompts.chat.async_render(user_id="123")
</file context>
| - async_render | ||
| - rerender | ||
| - async_rerender | ||
| - invoke |
There was a problem hiding this comment.
P1: The invoke member listed for PromptNode does not exist on the class. This will cause mkdocstrings to fail during documentation build.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prompts/docs_api_reference.md, line 29:
<comment>The `invoke` member listed for `PromptNode` does not exist on the class. This will cause mkdocstrings to fail during documentation build.</comment>
<file context>
@@ -0,0 +1,37 @@
+ - async_render
+ - rerender
+ - async_rerender
+ - invoke
+
+::: dynaprompt.nodes.RenderedPrompt
</file context>
| self.max_tokens = max_tokens | ||
| self.enc = tiktoken.encoding_for_model(model) | ||
|
|
||
| def validate(self, node, rendered) -> None: |
There was a problem hiding this comment.
P1: The TiktokenValidator.validate method signature (self, node, rendered) does not match the framework's actual PromptValidator.validate signature (self, prompt_node, kwargs, current_env="default"). The second argument is a kwargs dict (render variables), not a rendered result object, so rendered.text would raise an AttributeError at runtime.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prompts/docs_advanced_hooks_2_2_2.md, line 122:
<comment>The `TiktokenValidator.validate` method signature `(self, node, rendered)` does not match the framework's actual `PromptValidator.validate` signature `(self, prompt_node, kwargs, current_env="default")`. The second argument is a `kwargs` dict (render variables), not a rendered result object, so `rendered.text` would raise an `AttributeError` at runtime.</comment>
<file context>
@@ -0,0 +1,155 @@
+ self.max_tokens = max_tokens
+ self.enc = tiktoken.encoding_for_model(model)
+
+ def validate(self, node, rendered) -> None:
+ token_count = len(self.enc.encode(rendered.text))
+ if token_count > self.max_tokens:
</file context>
| rel_parts = child.relative_to(directory).parts | ||
| if any( | ||
| part.startswith(".") | ||
| or part in ("__pycache__", "venv", "env", "dynaprompt") |
There was a problem hiding this comment.
P2: The "dynaprompt" exclusion is overly broad and may silently skip legitimate prompt files stored in a subdirectory named dynaprompt. This is the library's own name, not a standard system/environment directory like __pycache__ or venv. Consider removing it from the exclusion list.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At dynaprompt/engine/resolver.py, line 44:
<comment>The `"dynaprompt"` exclusion is overly broad and may silently skip legitimate prompt files stored in a subdirectory named `dynaprompt`. This is the library's own name, not a standard system/environment directory like `__pycache__` or `venv`. Consider removing it from the exclusion list.</comment>
<file context>
@@ -37,6 +37,15 @@ def scan_directory(
+ rel_parts = child.relative_to(directory).parts
+ if any(
+ part.startswith(".")
+ or part in ("__pycache__", "venv", "env", "dynaprompt")
+ for part in rel_parts
+ ):
</file context>
| - async_render | ||
| - rerender | ||
| - async_rerender | ||
| - invoke |
There was a problem hiding this comment.
P2: The invoke method does not exist on PromptNode. mkdocstrings will produce a warning or empty documentation for this non-existent member.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prompts/docs_api_reference_2_2.md, line 29:
<comment>The `invoke` method does not exist on `PromptNode`. mkdocstrings will produce a warning or empty documentation for this non-existent member.</comment>
<file context>
@@ -0,0 +1,37 @@
+ - async_render
+ - rerender
+ - async_rerender
+ - invoke
+
+::: dynaprompt.nodes.RenderedPrompt
</file context>
|
|
||
| ## Async Hooks | ||
|
|
||
| You can also attach async hooks using `@async_hookable`. This is useful for: |
There was a problem hiding this comment.
P2: Don't present @async_hookable as the way to attach async hooks, and don't show a before-render hook mutating kwargs here. As written, the example won't affect the render context.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prompts/docs_advanced_async.md, line 70:
<comment>Don't present `@async_hookable` as the way to attach async hooks, and don't show a before-render hook mutating kwargs here. As written, the example won't affect the render context.</comment>
<file context>
@@ -0,0 +1,106 @@
+
+## Async Hooks
+
+You can also attach async hooks using `@async_hookable`. This is useful for:
+- Calling an async PII redaction service before rendering
+- Logging to an async audit trail after rendering
</file context>
| --- | ||
|
|
||
| !!! tip "Sync is still supported" | ||
| `async_render()` and `render()` are fully interchangeable. Use sync in scripts and tests, async in web servers and agents. |
There was a problem hiding this comment.
P2: Don't claim render() and async_render() are fully interchangeable. The sync path can't await async hooks, so they diverge as soon as a prompt uses coroutine hooks.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prompts/docs_advanced_async.md, line 106:
<comment>Don't claim `render()` and `async_render()` are fully interchangeable. The sync path can't await async hooks, so they diverge as soon as a prompt uses coroutine hooks.</comment>
<file context>
@@ -0,0 +1,106 @@
+---
+
+!!! tip "Sync is still supported"
+ `async_render()` and `render()` are fully interchangeable. Use sync in scripts and tests, async in web servers and agents.
</file context>
|
|
||
| **Output:** | ||
| ``` | ||
| 🔍 Debug Trace for: analyzer |
There was a problem hiding this comment.
P3: debug_trace() output shown in the documentation does not match the actual implementation output. Users following the docs will expect this format but will see a different visualization.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prompts/docs_advanced_environments_2_2_2.md, line 100:
<comment>debug_trace() output shown in the documentation does not match the actual implementation output. Users following the docs will expect this format but will see a different visualization.</comment>
<file context>
@@ -0,0 +1,120 @@
+
+**Output:**
+```
+🔍 Debug Trace for: analyzer
+──────────────────────────────────
+Layer: default
</file context>
|
|
||
| ## How it works | ||
|
|
||
| When you pass a list of files or a directory to `settings_files`, DynaPrompt scans for `.py` and `.json` files. |
There was a problem hiding this comment.
P3: Document YAML schema loading here as well; the current text is incomplete and misleads users about supported schema files.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prompts/docs.schemas.md, line 7:
<comment>Document YAML schema loading here as well; the current text is incomplete and misleads users about supported schema files.</comment>
<file context>
@@ -0,0 +1,57 @@
+
+## How it works
+
+When you pass a list of files or a directory to `settings_files`, DynaPrompt scans for `.py` and `.json` files.
+
+### 1. Python Schemas (.py)
</file context>
| When you pass a list of files or a directory to `settings_files`, DynaPrompt scans for `.py` and `.json` files. | |
| When you pass a list of files or a directory to `settings_files`, DynaPrompt scans for `.py`, `.json`, `.yaml`, and `.yml` files. |
|
|
||
| ## Referencing Schemas in Prompts | ||
|
|
||
| Once a schema is registered (either automatically or via `register()`), you can reference it by its string name in your prompt frontmatter. |
There was a problem hiding this comment.
P3: Remove the register() mention; this API does not exist in the repository.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At prompts/docs.schemas.md, line 46:
<comment>Remove the `register()` mention; this API does not exist in the repository.</comment>
<file context>
@@ -0,0 +1,57 @@
+
+## Referencing Schemas in Prompts
+
+Once a schema is registered (either automatically or via `register()`), you can reference it by its string name in your prompt frontmatter.
+
+**Example (`prompt.md`):**
</file context>
| Once a schema is registered (either automatically or via `register()`), you can reference it by its string name in your prompt frontmatter. | |
| Once a schema is loaded, you can reference it by its string name in your prompt frontmatter. |
Summary by cubic
Enable nested prompt rendering in Jinja so prompts can include other prompts by name or via a
prompts[...]proxy. Adds recursion protection, fixes synchronous rendering, and tightens directory scanning to make nested usage safe and reliable.New Features
{{ customer_service }}orprompts['child']using a newPromptsProxy.storeandparent_contextintoPromptNodeto enable lazy sub-prompt resolution.Bug Fixes
.render()so nested prompts resolve consistently (with or withoutauto_render), and skip hidden/env/cache folders during scan (.*,__pycache__,venv,env,dynaprompt).Additional updates: docs and examples demonstrating nested prompts;
debug_render.pyhelper for local testing.Written for commit aecaed2. Summary will update on new commits. Review in cubic