prompt_manager 0.5.8 → 1.0.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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.md +206 -516
  4. data/Rakefile +0 -8
  5. data/docs/api/configuration.md +31 -327
  6. data/docs/api/constants.md +60 -0
  7. data/docs/api/index.md +14 -0
  8. data/docs/api/metadata.md +99 -0
  9. data/docs/api/parsed.md +98 -0
  10. data/docs/api/pm-module.md +131 -0
  11. data/docs/api/render-context.md +51 -0
  12. data/docs/architecture/design-decisions.md +70 -0
  13. data/docs/architecture/index.md +6 -0
  14. data/docs/architecture/processing-pipeline.md +112 -0
  15. data/docs/assets/css/custom.css +1 -0
  16. data/docs/assets/images/prompt_manager.gif +0 -0
  17. data/docs/assets/images/prompt_manager.mp4 +0 -0
  18. data/docs/examples/ai-agent-prompts.md +173 -0
  19. data/docs/examples/code-review-prompt.md +107 -0
  20. data/docs/examples/index.md +7 -0
  21. data/docs/examples/multi-file-composition.md +123 -0
  22. data/docs/getting-started/configuration.md +106 -0
  23. data/docs/getting-started/index.md +7 -0
  24. data/docs/getting-started/installation.md +10 -73
  25. data/docs/getting-started/quick-start.md +50 -225
  26. data/docs/guides/comment-stripping.md +64 -0
  27. data/docs/guides/custom-directives.md +115 -0
  28. data/docs/guides/erb-rendering.md +102 -0
  29. data/docs/guides/includes.md +146 -0
  30. data/docs/guides/index.md +11 -0
  31. data/docs/guides/parameters.md +96 -0
  32. data/docs/guides/parsing.md +127 -0
  33. data/docs/guides/shell-expansion.md +108 -0
  34. data/docs/index.md +54 -214
  35. data/lib/pm/configuration.rb +17 -0
  36. data/lib/pm/directives.rb +61 -0
  37. data/lib/pm/metadata.rb +17 -0
  38. data/lib/pm/parsed.rb +59 -0
  39. data/lib/pm/shell.rb +57 -0
  40. data/lib/pm/version.rb +5 -0
  41. data/lib/pm.rb +121 -0
  42. data/lib/prompt_manager.rb +2 -27
  43. data/mkdocs.yml +101 -66
  44. metadata +42 -101
  45. data/docs/.keep +0 -0
  46. data/docs/advanced/custom-keywords.md +0 -421
  47. data/docs/advanced/dynamic-directives.md +0 -535
  48. data/docs/advanced/performance.md +0 -612
  49. data/docs/advanced/search-integration.md +0 -635
  50. data/docs/api/directive-processor.md +0 -431
  51. data/docs/api/prompt-class.md +0 -354
  52. data/docs/api/storage-adapters.md +0 -462
  53. data/docs/assets/favicon.ico +0 -1
  54. data/docs/assets/logo.svg +0 -24
  55. data/docs/core-features/comments.md +0 -48
  56. data/docs/core-features/directive-processing.md +0 -38
  57. data/docs/core-features/erb-integration.md +0 -68
  58. data/docs/core-features/error-handling.md +0 -197
  59. data/docs/core-features/parameter-history.md +0 -76
  60. data/docs/core-features/parameterized-prompts.md +0 -500
  61. data/docs/core-features/shell-integration.md +0 -79
  62. data/docs/development/architecture.md +0 -544
  63. data/docs/development/contributing.md +0 -425
  64. data/docs/development/roadmap.md +0 -234
  65. data/docs/development/testing.md +0 -822
  66. data/docs/examples/advanced.md +0 -523
  67. data/docs/examples/basic.md +0 -688
  68. data/docs/examples/real-world.md +0 -776
  69. data/docs/examples.md +0 -337
  70. data/docs/getting-started/basic-concepts.md +0 -318
  71. data/docs/migration/v0.9.0.md +0 -459
  72. data/docs/migration/v1.0.0.md +0 -591
  73. data/docs/storage/activerecord-adapter.md +0 -348
  74. data/docs/storage/custom-adapters.md +0 -176
  75. data/docs/storage/filesystem-adapter.md +0 -236
  76. data/docs/storage/overview.md +0 -427
  77. data/examples/advanced_integrations.rb +0 -52
  78. data/examples/directives.rb +0 -102
  79. data/examples/prompts_dir/advanced_demo.txt +0 -79
  80. data/examples/prompts_dir/directive_example.json +0 -1
  81. data/examples/prompts_dir/directive_example.txt +0 -8
  82. data/examples/prompts_dir/todo.json +0 -1
  83. data/examples/prompts_dir/todo.txt +0 -7
  84. data/examples/prompts_dir/toy/8-ball.txt +0 -4
  85. data/examples/rgfzf +0 -44
  86. data/examples/simple.rb +0 -160
  87. data/examples/using_search_proc.rb +0 -68
  88. data/improvement_plan.md +0 -996
  89. data/lib/prompt_manager/directive_processor.rb +0 -47
  90. data/lib/prompt_manager/prompt.rb +0 -195
  91. data/lib/prompt_manager/storage/active_record_adapter.rb +0 -157
  92. data/lib/prompt_manager/storage/file_system_adapter.rb +0 -339
  93. data/lib/prompt_manager/storage.rb +0 -34
  94. data/lib/prompt_manager/version.rb +0 -5
  95. data/prompt_manager_logo.png +0 -0
data/Rakefile CHANGED
@@ -1,13 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- begin
4
- require "tocer/rake/register"
5
- rescue LoadError => error
6
- puts error.message
7
- end
8
-
9
- Tocer::Rake::Register.call
10
-
11
3
  require "bundler/gem_tasks"
12
4
  require "rake/testtask"
13
5
 
@@ -1,355 +1,59 @@
1
- # Configuration API Reference
1
+ # PM::Configuration
2
2
 
3
- PromptManager provides comprehensive configuration options to customize behavior for your specific needs.
3
+ Global configuration for PM behavior. Accessed via `PM.config` or `PM.configure`.
4
4
 
5
- ## Basic Configuration
5
+ ## Source
6
6
 
7
- ```ruby
8
- PromptManager.configure do |config|
9
- # Storage adapter (default: FileSystemAdapter)
10
- config.storage = PromptManager::Storage::FileSystemAdapter.new
11
-
12
- # Default prompts directory (default: ~/prompts_dir/)
13
- config.prompts_dir = '/path/to/your/prompts'
14
-
15
- # Enable debug logging (default: false)
16
- config.debug = true
17
-
18
- # Custom logger (default: Rails.logger or Logger.new(STDOUT))
19
- config.logger = Logger.new('/var/log/prompt_manager.log')
20
- end
21
- ```
22
-
23
- ## Configuration Options
24
-
25
- ### Core Settings
26
-
27
- #### `storage`
28
- **Type:** `PromptManager::Storage::Base`
29
- **Default:** `FileSystemAdapter.new`
30
-
31
- The storage adapter to use for reading and writing prompts.
32
-
33
- ```ruby
34
- # FileSystem storage
35
- config.storage = PromptManager::Storage::FileSystemAdapter.new(
36
- prompts_dir: '/custom/prompts/path'
37
- )
38
-
39
- # ActiveRecord storage
40
- config.storage = PromptManager::Storage::ActiveRecordAdapter.new(
41
- model_class: Prompt
42
- )
43
-
44
- # Custom storage
45
- config.storage = MyCustomAdapter.new
46
- ```
47
-
48
- #### `prompts_dir`
49
- **Type:** `String` or `Array<String>`
50
- **Default:** `File.join(Dir.home, 'prompts_dir')`
51
-
52
- Directory path(s) to search for prompt files when using FileSystemAdapter.
53
-
54
- ```ruby
55
- # Single directory
56
- config.prompts_dir = '/app/prompts'
57
-
58
- # Multiple directories (search in order)
59
- config.prompts_dir = [
60
- '/app/prompts',
61
- '/shared/prompts',
62
- '/system/default_prompts'
63
- ]
64
- ```
65
-
66
- #### `debug`
67
- **Type:** `Boolean`
68
- **Default:** `false`
69
-
70
- Enable debug logging for troubleshooting.
71
-
72
- ```ruby
73
- config.debug = true
74
- ```
75
-
76
- #### `logger`
77
- **Type:** `Logger`
78
- **Default:** `Rails.logger` or `Logger.new(STDOUT)`
79
-
80
- Custom logger instance for PromptManager output.
81
-
82
- ```ruby
83
- config.logger = Logger.new('/var/log/prompt_manager.log')
84
- config.logger.level = Logger::DEBUG
85
- ```
86
-
87
- ### Parameter Processing
7
+ `lib/pm/configuration.rb`
88
8
 
89
- #### `save_parameter_history`
90
- **Type:** `Boolean`
91
- **Default:** `true`
9
+ ## Attributes
92
10
 
93
- Whether to save parameter values for reuse in future prompt renderings.
11
+ | Attribute | Type | Default | Description |
12
+ |-----------|------|---------|-------------|
13
+ | `prompts_dir` | String | `''` | Prepended to relative file paths in `PM.parse` |
14
+ | `shell` | Boolean | `true` | Default shell expansion setting for new parses |
15
+ | `erb` | Boolean | `true` | Default ERB rendering setting for new parses |
94
16
 
95
- ```ruby
96
- config.save_parameter_history = false
97
- ```
17
+ All attributes have both getter and setter methods (`attr_accessor`).
98
18
 
99
- #### `parameter_history_file`
100
- **Type:** `String`
101
- **Default:** `~/.prompt_manager/parameters_history.yaml`
19
+ ## Methods
102
20
 
103
- File path for storing parameter history.
21
+ ### initialize
104
22
 
105
- ```ruby
106
- config.parameter_history_file = '/app/data/prompt_history.yaml'
107
- ```
23
+ Creates a new Configuration with default values by calling `reset!`.
108
24
 
109
- #### `max_history_entries`
110
- **Type:** `Integer`
111
- **Default:** `10`
25
+ ### reset! → nil
112
26
 
113
- Maximum number of historical values to store per parameter.
27
+ Restores all attributes to their defaults:
114
28
 
115
29
  ```ruby
116
- config.max_history_entries = 5
117
- ```
118
-
119
- ### ERB Processing
120
-
121
- #### `erb_timeout`
122
- **Type:** `Numeric`
123
- **Default:** `30` (seconds)
124
-
125
- Timeout for ERB template processing to prevent infinite loops.
30
+ PM.config.reset!
126
31
 
127
- ```ruby
128
- config.erb_timeout = 60 # 1 minute
32
+ PM.config.prompts_dir #=> ''
33
+ PM.config.shell #=> true
34
+ PM.config.erb #=> true
129
35
  ```
130
36
 
131
- #### `erb_safe_level`
132
- **Type:** `Integer`
133
- **Default:** `0`
134
-
135
- Ruby safe level for ERB evaluation (0-4, higher = more restrictive).
136
-
137
- ```ruby
138
- config.erb_safe_level = 1 # Slightly more restrictive
139
- ```
140
-
141
- ### Directive Processing
142
-
143
- #### `max_include_depth`
144
- **Type:** `Integer`
145
- **Default:** `10`
37
+ ## Usage
146
38
 
147
- Maximum depth for nested `//include` directives to prevent circular includes.
39
+ ### Block Configuration
148
40
 
149
41
  ```ruby
150
- config.max_include_depth = 5
151
- ```
152
-
153
- #### `directive_timeout`
154
- **Type:** `Numeric`
155
- **Default:** `30` (seconds)
156
-
157
- Timeout for directive processing.
158
-
159
- ```ruby
160
- config.directive_timeout = 60
161
- ```
162
-
163
- ### Caching
164
-
165
- #### `cache_prompts`
166
- **Type:** `Boolean`
167
- **Default:** `false`
168
-
169
- Enable in-memory caching of prompt content.
170
-
171
- ```ruby
172
- config.cache_prompts = true
173
- ```
174
-
175
- #### `cache_ttl`
176
- **Type:** `Numeric`
177
- **Default:** `300` (5 minutes)
178
-
179
- Time-to-live for cached prompt content in seconds.
180
-
181
- ```ruby
182
- config.cache_ttl = 600 # 10 minutes
183
- ```
184
-
185
- #### `cache_store`
186
- **Type:** `ActiveSupport::Cache::Store`
187
- **Default:** `ActiveSupport::Cache::MemoryStore.new`
188
-
189
- Custom cache store for prompt content.
190
-
191
- ```ruby
192
- config.cache_store = ActiveSupport::Cache::RedisStore.new(
193
- url: ENV['REDIS_URL']
194
- )
195
- ```
196
-
197
- ### Error Handling
198
-
199
- #### `error_handler`
200
- **Type:** `Proc`
201
- **Default:** `nil`
202
-
203
- Custom error handler for prompt processing errors.
204
-
205
- ```ruby
206
- config.error_handler = ->(error, context) {
207
- Rails.logger.error "Prompt error: #{error.message}"
208
- ErrorReporter.notify(error, context: context)
209
-
210
- # Return fallback content
211
- "Service temporarily unavailable"
212
- }
213
- ```
214
-
215
- #### `raise_on_missing_prompts`
216
- **Type:** `Boolean`
217
- **Default:** `true`
218
-
219
- Whether to raise exceptions for missing prompts or return nil.
220
-
221
- ```ruby
222
- config.raise_on_missing_prompts = false
223
- ```
224
-
225
- #### `raise_on_missing_parameters`
226
- **Type:** `Boolean`
227
- **Default:** `true`
228
-
229
- Whether to raise exceptions for missing parameters or substitute with placeholders.
230
-
231
- ```ruby
232
- config.raise_on_missing_parameters = false
233
- ```
234
-
235
- ## Environment-based Configuration
236
-
237
- ### Rails Configuration
238
-
239
- ```ruby
240
- # config/environments/development.rb
241
- Rails.application.configure do
242
- config.prompt_manager.debug = true
243
- config.prompt_manager.prompts_dir = Rails.root.join('app', 'prompts')
244
- config.prompt_manager.save_parameter_history = true
245
- end
246
-
247
- # config/environments/production.rb
248
- Rails.application.configure do
249
- config.prompt_manager.debug = false
250
- config.prompt_manager.cache_prompts = true
251
- config.prompt_manager.cache_ttl = 3600 # 1 hour
252
-
253
- config.prompt_manager.error_handler = ->(error, context) {
254
- Rollbar.error(error, context)
255
- "Service temporarily unavailable"
256
- }
257
- end
258
- ```
259
-
260
- ### Environment Variables
261
-
262
- PromptManager respects these environment variables:
263
-
264
- ```bash
265
- # Storage configuration
266
- PROMPT_MANAGER_PROMPTS_DIR="/app/prompts"
267
- PROMPT_MANAGER_DEBUG="true"
268
-
269
- # Cache configuration
270
- PROMPT_MANAGER_CACHE_PROMPTS="true"
271
- PROMPT_MANAGER_CACHE_TTL="600"
272
-
273
- # Database URL for ActiveRecord adapter
274
- DATABASE_URL="postgres://user:pass@localhost/prompts_db"
275
- ```
276
-
277
- ## Configuration Validation
278
-
279
- Validate your configuration:
280
-
281
- ```ruby
282
- PromptManager.configure do |config|
283
- config.storage = MyAdapter.new
284
- config.debug = true
285
- end
286
-
287
- # Validate configuration
288
- begin
289
- PromptManager.validate_configuration!
290
- puts "Configuration valid"
291
- rescue PromptManager::ConfigurationError => e
292
- puts "Configuration error: #{e.message}"
42
+ PM.configure do |config|
43
+ config.prompts_dir = '~/.prompts'
44
+ config.shell = false
293
45
  end
294
46
  ```
295
47
 
296
- ## Runtime Configuration
297
-
298
- Access current configuration:
48
+ ### Direct Access
299
49
 
300
50
  ```ruby
301
- # Get current storage adapter
302
- storage = PromptManager.configuration.storage
303
-
304
- # Check debug mode
305
- if PromptManager.configuration.debug
306
- puts "Debug mode enabled"
307
- end
308
-
309
- # Access logger
310
- PromptManager.configuration.logger.info("Processing prompt...")
51
+ PM.config.prompts_dir = '/usr/share/prompts'
52
+ PM.config.erb = false
311
53
  ```
312
54
 
313
- ## Configuration Best Practices
314
-
315
- ### Development
316
- ```ruby
317
- PromptManager.configure do |config|
318
- config.debug = true
319
- config.prompts_dir = './prompts'
320
- config.save_parameter_history = true
321
- config.cache_prompts = false # Always reload for development
322
- end
323
- ```
55
+ ## Override Behavior
324
56
 
325
- ### Production
326
- ```ruby
327
- PromptManager.configure do |config|
328
- config.debug = false
329
- config.cache_prompts = true
330
- config.cache_ttl = 3600
331
-
332
- config.error_handler = ->(error, context) {
333
- ErrorService.notify(error, context)
334
- "Service temporarily unavailable"
335
- }
336
-
337
- # Use database storage for high availability
338
- config.storage = PromptManager::Storage::ActiveRecordAdapter.new
339
- end
340
- ```
57
+ Per-file YAML metadata always overrides the global setting. If a file has `shell: true` in its front-matter, shell expansion runs even when `PM.config.shell` is `false`.
341
58
 
342
- ### Testing
343
- ```ruby
344
- # spec/spec_helper.rb
345
- RSpec.configure do |config|
346
- config.before(:each) do
347
- PromptManager.configure do |config|
348
- config.prompts_dir = Rails.root.join('spec', 'fixtures', 'prompts')
349
- config.save_parameter_history = false
350
- config.cache_prompts = false
351
- config.raise_on_missing_prompts = true
352
- end
353
- end
354
- end
355
- ```
59
+ The global setting acts as the default when a file does not specify the value.
@@ -0,0 +1,60 @@
1
+ # Constants
2
+
3
+ Regular expressions and markers defined in the `PM` module.
4
+
5
+ ## Source
6
+
7
+ `lib/pm.rb` and `lib/pm/shell.rb`
8
+
9
+ ## Reference
10
+
11
+ ### PM::VERSION
12
+
13
+ ```ruby
14
+ PM::VERSION #=> "1.0.0"
15
+ ```
16
+
17
+ Current version of the PM library. Defined in `lib/pm/version.rb`.
18
+
19
+ ### PM::METADATA_REGEXP
20
+
21
+ ```ruby
22
+ PM::METADATA_REGEXP
23
+ ```
24
+
25
+ Matches YAML front-matter delimited by `---` fences. Captures the YAML content between the fences and the remaining body.
26
+
27
+ Used internally by `PM.parse` to separate metadata from content.
28
+
29
+ ### PM::HTML_COMMENT_REGEXP
30
+
31
+ ```ruby
32
+ PM::HTML_COMMENT_REGEXP
33
+ ```
34
+
35
+ Matches HTML comments (`<!-- ... -->`), including multiline comments. Uses the `m` (multiline) flag for dot-matches-newline behavior.
36
+
37
+ Used by `PM.strip_comments`.
38
+
39
+ ### PM::ENV_VAR_REGEXP
40
+
41
+ ```ruby
42
+ PM::ENV_VAR_REGEXP
43
+ ```
44
+
45
+ Matches environment variable references in two forms:
46
+
47
+ - `${VAR}` -- braced form (captured in group 1)
48
+ - `$VAR` -- bare form (captured in group 2)
49
+
50
+ Only matches UPPERCASE variable names (`[A-Z_][A-Z0-9_]*`). Lowercase names are intentionally ignored to avoid conflicts with ERB and other syntax.
51
+
52
+ Used by `PM.expand_shell` during the environment variable expansion phase.
53
+
54
+ ### PM::COMMAND_START
55
+
56
+ ```ruby
57
+ PM::COMMAND_START #=> "$("
58
+ ```
59
+
60
+ String marker that identifies the start of a command substitution. Used by the shell expansion parser to find `$(command)` sequences with proper handling of nested parentheses.
data/docs/api/index.md ADDED
@@ -0,0 +1,14 @@
1
+ # API Reference
2
+
3
+ Complete reference for all PM classes, modules, and methods.
4
+
5
+ ## Classes and Modules
6
+
7
+ | Name | Description |
8
+ |------|-------------|
9
+ | [PM Module](pm-module.md) | Top-level module with all public class methods |
10
+ | [PM::Configuration](configuration.md) | Global settings (prompts_dir, shell, erb) |
11
+ | [PM::Metadata](metadata.md) | OpenStruct-based metadata container |
12
+ | [PM::Parsed](parsed.md) | Result object from `PM.parse` |
13
+ | [PM::RenderContext](render-context.md) | Context passed to directive blocks |
14
+ | [Constants](constants.md) | Regular expressions and markers |
@@ -0,0 +1,99 @@
1
+ # PM::Metadata
2
+
3
+ OpenStruct-based metadata container with automatic predicate methods for boolean values.
4
+
5
+ ## Source
6
+
7
+ `lib/pm/metadata.rb`
8
+
9
+ ## Inheritance
10
+
11
+ ```
12
+ OpenStruct
13
+ └── PM::Metadata
14
+ ```
15
+
16
+ ## Constructor
17
+
18
+ ### Metadata.new(hash = {}) → Metadata
19
+
20
+ Creates a new metadata object. All hash keys become accessible via dot notation. Boolean values also get predicate methods.
21
+
22
+ ```ruby
23
+ meta = PM::Metadata.new(title: 'Hello', shell: true, erb: false)
24
+
25
+ meta.title #=> "Hello"
26
+ meta.shell #=> true
27
+ meta.shell? #=> true
28
+ meta.erb #=> false
29
+ meta.erb? #=> false
30
+ ```
31
+
32
+ ## Dot Notation Access
33
+
34
+ All YAML keys from the front-matter are accessible as methods:
35
+
36
+ ```ruby
37
+ parsed = PM.parse("---\ntitle: Test\nprovider: openai\nmodel: gpt-4\n---\nContent")
38
+
39
+ parsed.metadata.title #=> "Test"
40
+ parsed.metadata.provider #=> "openai"
41
+ parsed.metadata.model #=> "gpt-4"
42
+ ```
43
+
44
+ ## Predicate Methods
45
+
46
+ Boolean keys (`true` or `false` values) automatically get a `?`-suffixed predicate method:
47
+
48
+ ```ruby
49
+ meta = PM::Metadata.new(shell: true, verbose: false)
50
+
51
+ meta.shell? #=> true
52
+ meta.verbose? #=> false
53
+ ```
54
+
55
+ Non-boolean keys do not get predicate methods:
56
+
57
+ ```ruby
58
+ meta = PM::Metadata.new(title: 'Test')
59
+ meta.respond_to?(:title?) #=> false
60
+ ```
61
+
62
+ ## File-Specific Keys
63
+
64
+ When `PM.parse` reads from a file, these keys are added automatically:
65
+
66
+ | Key | Type | Description |
67
+ |-----|------|-------------|
68
+ | `directory` | String | Absolute path to the parent directory |
69
+ | `name` | String | Filename (e.g., `review.md`) |
70
+ | `created_at` | Time | File creation timestamp |
71
+ | `modified_at` | Time | Last modification timestamp |
72
+
73
+ ## Special Keys
74
+
75
+ ### parameters
76
+
77
+ The `parameters` hash from YAML front-matter:
78
+
79
+ ```ruby
80
+ parsed.metadata.parameters
81
+ #=> {"language" => "ruby", "code" => nil}
82
+ ```
83
+
84
+ Keys with `nil` values are required parameters. Keys with any other value are defaults.
85
+
86
+ ### includes
87
+
88
+ Populated after `to_s` is called. Contains a tree of included files:
89
+
90
+ ```ruby
91
+ parsed.metadata.includes
92
+ #=> [{ path: "/path/to/header.md", depth: 1, metadata: {...}, includes: [] }]
93
+ ```
94
+
95
+ This is `nil` before `to_s` and is reset on each `to_s` call.
96
+
97
+ ### shell and erb
98
+
99
+ Control processing behavior. Default to `true` when not specified in the YAML. The global configuration default is applied during metadata construction.
@@ -0,0 +1,98 @@
1
+ # PM::Parsed
2
+
3
+ The result object returned by `PM.parse`. A Struct with two fields: `metadata` and `content`.
4
+
5
+ ## Source
6
+
7
+ `lib/pm/parsed.rb`
8
+
9
+ ## Structure
10
+
11
+ ```ruby
12
+ PM::Parsed = Struct.new(:metadata, :content)
13
+ ```
14
+
15
+ ## Fields
16
+
17
+ | Field | Type | Description |
18
+ |-------|------|-------------|
19
+ | `metadata` | PM::Metadata | Parsed YAML front-matter |
20
+ | `content` | String | Markdown content after metadata extraction and shell expansion |
21
+
22
+ ## Methods
23
+
24
+ ### `[](key)` → Object
25
+
26
+ Bracket accessor that delegates to `metadata`:
27
+
28
+ ```ruby
29
+ parsed = PM.parse("---\ntitle: Hello\n---\nContent")
30
+
31
+ parsed[:title] #=> "Hello"
32
+ parsed['title'] #=> "Hello"
33
+ ```
34
+
35
+ ### to_s(values = {}) → String
36
+
37
+ Render the prompt content with ERB template evaluation.
38
+
39
+ **Parameters:**
40
+
41
+ | Name | Type | Description |
42
+ |------|------|-------------|
43
+ | `values` | Hash | Parameter values to merge with defaults |
44
+
45
+ **Returns:** Rendered prompt as String.
46
+
47
+ **Raises:** `ArgumentError` if required parameters (those with `nil` defaults) are not provided.
48
+
49
+ **Behavior:**
50
+
51
+ 1. Merges provided values with parameter defaults from metadata
52
+ 2. Validates all required parameters are present
53
+ 3. If `erb: true`, evaluates ERB with parameters and registered directives
54
+ 4. If `erb: false`, returns content as-is
55
+ 5. Populates `metadata.includes` with the include tree
56
+
57
+ ```ruby
58
+ parsed = PM.parse('review.md')
59
+
60
+ # With required params
61
+ result = parsed.to_s('code' => File.read('app.rb'))
62
+
63
+ # Override defaults
64
+ result = parsed.to_s('code' => source, 'language' => 'python')
65
+
66
+ # Symbol keys work
67
+ result = parsed.to_s(code: source)
68
+ ```
69
+
70
+ ### render_with(values, included, depth) → String
71
+
72
+ Internal method used by `to_s` and the `include` directive. Handles the ERB rendering pipeline with include tracking.
73
+
74
+ **Parameters:**
75
+
76
+ | Name | Type | Description |
77
+ |------|------|-------------|
78
+ | `values` | Hash | Merged parameter values |
79
+ | `included` | Set | File paths already in the include chain |
80
+ | `depth` | Integer | Current include nesting depth |
81
+
82
+ This method is not typically called directly.
83
+
84
+ ## Typical Usage
85
+
86
+ ```ruby
87
+ parsed = PM.parse('prompt.md')
88
+
89
+ # Access metadata
90
+ parsed.metadata.title
91
+ parsed.metadata.parameters
92
+
93
+ # Render
94
+ output = parsed.to_s('key' => 'value')
95
+
96
+ # Check includes after render
97
+ parsed.metadata.includes
98
+ ```