fix(prompts): fix three infrastructure bugs in prompt dependency resolution

- ContentMacro: add __post_init__ to auto-derive raw_text when built
  programmatically, preventing str.replace("", X) corruption
- MacroParser: add @{target} shorthand syntax support mapped to REQUIRED kind,
  updating parse, has_macros, count_macros, and find_macro_positions
- Artifact: store content in model and SQLite DB, replace resolver placeholder
  with actual artifact content, add migration for existing databases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-11 20:53:02 +01:00
parent 01b9596ce6
commit 706981c39f
9 changed files with 191 additions and 10 deletions

View File

@@ -177,3 +177,66 @@ class TestMacroParser:
content = "{{generate:test| key = value }}"
macros = self.parser.parse(content)
assert macros[0].parameters == {"key": "value"}
# --- Shorthand @{target} syntax tests ---
def test_parse_shorthand_macro(self):
"""Test parsing @{target} shorthand syntax."""
content = "Some text @{glossary} more text"
macros = self.parser.parse(content)
assert len(macros) == 1
assert macros[0].kind == MacroKind.REQUIRED
assert macros[0].target == "glossary"
assert macros[0].raw_text == "@{glossary}"
assert macros[0].parameters == {}
def test_parse_shorthand_with_line_numbers(self):
"""Test shorthand macros record line numbers."""
content = "Line 1\n@{dep1}\nLine 3\n@{dep2}"
macros = self.parser.parse(content)
assert len(macros) == 2
assert macros[0].line_number == 2
assert macros[1].line_number == 4
def test_parse_mixed_syntax(self):
"""Test parsing both {{kind:target}} and @{target} in same content."""
content = "{{require:dep1}} and @{dep2} and {{optional:dep3}}"
macros = self.parser.parse(content)
assert len(macros) == 3
assert macros[0].kind == MacroKind.REQUIRED
assert macros[0].target == "dep1"
assert macros[1].kind == MacroKind.OPTIONAL
assert macros[1].target == "dep3"
assert macros[2].kind == MacroKind.REQUIRED
assert macros[2].target == "dep2"
def test_shorthand_has_macros(self):
"""Test has_macros returns True for shorthand syntax."""
assert self.parser.has_macros("@{target}") is True
assert self.parser.has_macros("no macros here") is False
def test_shorthand_count_macros(self):
"""Test count_macros includes shorthand macros."""
content = "@{dep1} @{dep2} {{optional:dep3}}"
counts = self.parser.count_macros(content)
assert counts['required'] == 2
assert counts['optional'] == 1
def test_shorthand_find_macro_positions(self):
"""Test find_macro_positions includes shorthand macros."""
content = "Start @{dep1} middle {{require:dep2}} end"
positions = self.parser.find_macro_positions(content)
assert len(positions) == 2
# Should be sorted by position
assert positions[0][2] == "@{dep1}"
assert positions[1][2] == "{{require:dep2}}"
def test_shorthand_target_trimmed(self):
"""Test shorthand target with spaces is trimmed."""
content = "@{ my-artifact }"
macros = self.parser.parse(content)
assert macros[0].target == "my-artifact"