diff --git a/assets/__init__.py b/assets/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/automation/__init__.py b/automation/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pyproject.toml b/pyproject.toml
index 815999d..7b44812 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -21,4 +21,4 @@ packages = ["cascadingdev"]
version = { file = "VERSION" }
[tool.pytest.ini_options]
-pythonpath = ["src"]
+pythonpath = ["src", ".", "assets"]
diff --git a/tests/test_template_meta.py b/tests/test_template_meta.py
index dfb877c..c312b5d 100644
--- a/tests/test_template_meta.py
+++ b/tests/test_template_meta.py
@@ -1,10 +1,81 @@
# tests/test_template_meta.py
import pytest
+from assets.runtime.create_feature import find_template_fields, render_request_from_template
-def test_load_template_with_meta():
- # Test META parsing
- assert True
+def test_find_template_fields():
+ template_content = """
+# Feature Request
+
+**Title**:
+**Intent**:
+**Motivation / Problem**:
+**Feature ID**:
+**Meta**:
+**Author**:
+"""
+ fields = find_template_fields(template_content)
+ expected_fields = [
+ ("Title", ""),
+ ("Intent", ""),
+ ("Motivation / Problem", ""),
+ ("Author", "")
+ ]
+ assert fields == expected_fields
+
+def test_render_request_from_template():
+ template_content = """
+# Feature Request:
+
+**Intent**:
+**Author**:
+"""
+ fields = {
+ "Title": "My Awesome Feature",
+ "Intent": "This feature will do amazing things.",
+ "Author": "Test User"
+ }
+ fid = "FR_2023-10-27_my-awesome-feature"
+ created = "2023-10-27"
+
+ rendered_content = render_request_from_template(template_content, fields, fid, created)
+ expected_content = """
+# Feature Request: My Awesome Feature
+
+**Intent**: This feature will do amazing things.
+**Author**: Test User
+
+**Feature ID**: FR_2023-10-27_my-awesome-feature
+**Meta**: Created: 2023-10-27 • Author: Test User
+"""
+ assert rendered_content.strip() == expected_content.strip()
+
+def test_render_request_from_template_with_existing_meta():
+ template_content = """
+# Feature Request:
+
+**Intent**:
+**Author**:
+
+**Feature ID**: EXISTING_FID
+**Meta**: Existing Meta Info
+"""
+ fields = {
+ "Title": "Another Feature",
+ "Intent": "This is another feature.",
+ "Author": "Another User"
+ }
+ fid = "FR_2023-10-28_another-feature"
+ created = "2023-10-28"
+
+ rendered_content = render_request_from_template(template_content, fields, fid, created)
+ expected_content = """
+# Feature Request: Another Feature
+
+**Intent**: This is another feature.
+**Author**: Another User
+
+**Feature ID**: EXISTING_FID
+**Meta**: Existing Meta Info
+"""
+ assert rendered_content.strip() == expected_content.strip()
-def test_render_placeholders():
- # Test token replacement
- assert True
diff --git a/tests/test_workflow.py b/tests/test_workflow.py
new file mode 100644
index 0000000..4a66420
--- /dev/null
+++ b/tests/test_workflow.py
@@ -0,0 +1,82 @@
+import pytest
+from pathlib import Path
+from automation.workflow import parse_votes, _extract_vote_value
+
+def test_extract_vote_value():
+ assert _extract_vote_value("READY") == "READY"
+ assert _extract_vote_value("CHANGES ") == "CHANGES"
+ assert _extract_vote_value(" REJECT") == "REJECT"
+ assert _extract_vote_value("INVALID") is None
+ assert _extract_vote_value("Some text READY") is None
+ assert _extract_vote_value("READY ") == "READY"
+ assert _extract_vote_value("No vote here") is None
+
+def test_parse_votes_single_participant_single_vote(tmp_path):
+ discussion_content = """
+- Participant A: Initial comment.
+- Participant A: VOTE: READY
+"""
+ discussion_file = tmp_path / "discussion.md"
+ discussion_file.write_text(discussion_content)
+
+ votes = parse_votes(discussion_file)
+ assert votes == {"Participant A": "READY"}
+
+def test_parse_votes_single_participant_multiple_votes(tmp_path):
+ discussion_content = """
+- Participant B: First comment. VOTE: CHANGES
+- Participant B: Second comment.
+- Participant B: VOTE: READY
+"""
+ discussion_file = tmp_path / "discussion.md"
+ discussion_file.write_text(discussion_content)
+
+ votes = parse_votes(discussion_file)
+ assert votes == {"Participant B": "READY"}
+
+def test_parse_votes_multiple_participants(tmp_path):
+ discussion_content = """
+- Participant C: Comment one. VOTE: READY
+- Participant D: Comment two. VOTE: CHANGES
+- Participant C: Another comment.
+- Participant D: Final thoughts. VOTE: READY
+"""
+ discussion_file = tmp_path / "discussion.md"
+ discussion_file.write_text(discussion_content)
+
+ votes = parse_votes(discussion_file)
+ assert votes == {"Participant C": "READY", "Participant D": "READY"}
+
+def test_parse_votes_malformed_lines(tmp_path):
+ discussion_content = """
+- Participant E: VOTE: READY
+- Participant F: VOTE: INVALID_VOTE
+- Participant E: Another comment. VOTE: CHANGES
+- Participant F: Just a comment.
+"""
+ discussion_file = tmp_path / "discussion.md"
+ discussion_file.write_text(discussion_content)
+
+ votes = parse_votes(discussion_file)
+ assert votes == {"Participant E": "CHANGES"} # Participant F's vote is invalid and ignored
+
+def test_parse_votes_mixed_content(tmp_path):
+ discussion_content = """
+# Discussion Title
+
+Some introductory text.
+
+- Participant G: First point.
+- Participant G: Second point. VOTE: READY
+
+- Participant H: Question?
+- Participant H: VOTE: CHANGES
+
+- Participant G: Response to H. VOTE: REJECT
+
+"""
+ discussion_file = tmp_path / "discussion.md"
+ discussion_file.write_text(discussion_content)
+
+ votes = parse_votes(discussion_file)
+ assert votes == {"Participant G": "REJECT", "Participant H": "CHANGES"}