Skip to content

Commit 9de822d

Browse files
committed
python: Add workflow
1 parent 382d5a2 commit 9de822d

32 files changed

Lines changed: 2485 additions & 145 deletions
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# This workflow runs Python tests for the build_tools module
2+
# Separate from the .NET tests to keep concerns isolated
3+
4+
name: Python Build Tools
5+
6+
on:
7+
push:
8+
branches: [ "mainline" ]
9+
paths:
10+
- 'build_tools/**'
11+
- '.github/workflows/python-build-tools.yml'
12+
pull_request:
13+
branches: [ "mainline" ]
14+
paths:
15+
- 'build_tools/**'
16+
- '.github/workflows/python-build-tools.yml'
17+
18+
jobs:
19+
test:
20+
runs-on: ubuntu-latest
21+
22+
permissions:
23+
contents: read
24+
25+
strategy:
26+
matrix:
27+
python-version: ["3.11", "3.12"]
28+
29+
steps:
30+
- uses: actions/checkout@v4
31+
32+
- name: Set up Python ${{ matrix.python-version }}
33+
uses: actions/setup-python@v5
34+
with:
35+
python-version: ${{ matrix.python-version }}
36+
37+
- name: Install dependencies
38+
run: |
39+
python -m pip install --upgrade pip
40+
# Install sharpy_auto_builder as editable package
41+
pip install -e "build_tools/sharpy_auto_builder[dev]"
42+
43+
- name: Run tests with pytest
44+
env:
45+
# Add repo root to PYTHONPATH to support 'from build_tools.' imports
46+
PYTHONPATH: ${{ github.workspace }}
47+
run: |
48+
python -m pytest build_tools/tests/ -v --tb=short

build_tools/sharpy_auto_builder/interrupt_handler.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ def _display_review_request(data: Dict[str, Any]) -> None:
7777
if task_desc:
7878
# Truncate description for display but show more than before
7979
desc_display = task_desc[:1500] if len(task_desc) > 1500 else task_desc
80-
console.print(Panel(Markdown(desc_display), title="Task Description", border_style="blue"))
80+
console.print(
81+
Panel(Markdown(desc_display), title="Task Description", border_style="blue")
82+
)
8183
console.print()
8284

8385
# Execution result
@@ -255,13 +257,16 @@ def _collect_review_response(data: Dict[str, Any]) -> Dict[str, Any]:
255257

256258
# Check if agent is asking a follow-up question
257259
agent_output = data.get("execution_result", {}).get("output", "")
258-
asking_followup = any(phrase in agent_output.lower() for phrase in [
259-
"would you like me to",
260-
"shall i",
261-
"do you want me to",
262-
"next steps:",
263-
"what would you like",
264-
])
260+
asking_followup = any(
261+
phrase in agent_output.lower()
262+
for phrase in [
263+
"would you like me to",
264+
"shall i",
265+
"do you want me to",
266+
"next steps:",
267+
"what would you like",
268+
]
269+
)
265270

266271
console.print("[bold yellow]What would you like to do?[/bold yellow]")
267272

build_tools/sharpy_auto_builder/orchestrator/nodes/task_execution.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,10 @@ async def _execute_implementation_node(
174174
# Truncate if very long but keep enough context
175175
max_prev_output = 4000
176176
if len(prev_output) > max_prev_output:
177-
prev_output = prev_output[-max_prev_output:] + "\n... [earlier output truncated]"
177+
prev_output = (
178+
prev_output[-max_prev_output:]
179+
+ "\n... [earlier output truncated]"
180+
)
178181
prompt += f"\n\n## Your Previous Response\n{prev_output}"
179182

180183
prompt += f"\n\n## Human Reviewer Feedback (MUST ADDRESS)\nThe human reviewer requested a retry with the following feedback:\n{human_response['feedback']}\n\nPlease carefully address these concerns in this implementation attempt."
@@ -593,13 +596,21 @@ async def _fix_test_failures_node(
593596

594597
def _get_test_component(self: "Orchestrator", task_data: dict) -> str:
595598
"""Determine which test component to filter by based on task."""
596-
if "lexer" in task_data["id"].lower() or "0.1.0" in task_data["phase"]:
599+
phase = task_data["phase"]
600+
task_id_lower = task_data["id"].lower()
601+
602+
# Use exact phase prefix matching to avoid substring bugs
603+
# (e.g., "0.1.1" in "0.1.10" incorrectly matches)
604+
def phase_matches(prefix: str) -> bool:
605+
return phase == prefix or phase.startswith(prefix + ".")
606+
607+
if "lexer" in task_id_lower or phase_matches("0.1.0"):
597608
return "Lexer"
598-
elif "parser" in task_data["id"].lower() or "0.1.1" in task_data["phase"]:
609+
elif "parser" in task_id_lower or phase_matches("0.1.1"):
599610
return "Parser"
600-
elif "codegen" in task_data["id"].lower() or "0.1.2" in task_data["phase"]:
611+
elif "codegen" in task_id_lower or phase_matches("0.1.2"):
601612
return "CodeGen"
602-
elif "semantic" in task_data["id"].lower():
613+
elif "semantic" in task_id_lower:
603614
return "Semantic"
604615
return ""
605616

build_tools/sharpy_auto_builder/state/answers/.gitkeep

Whitespace-only changes.

build_tools/sharpy_auto_builder/state/execution_log.jsonl

Lines changed: 65 additions & 0 deletions
Large diffs are not rendered by default.

build_tools/sharpy_auto_builder/state/ground_truth.json

Lines changed: 129 additions & 15 deletions
Large diffs are not rendered by default.

build_tools/sharpy_auto_builder/state/human_review/.gitkeep

Whitespace-only changes.

build_tools/sharpy_auto_builder/state/questions/.gitkeep

Whitespace-only changes.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"id": "q_20260115_014822_f426ffb1",
3+
"task_id": "0.1.6.8",
4+
"question": "Agent is asking for guidance on task 0.1.6.8: Verify Name Mangling Implementation",
5+
"context": "## Summary\n\nI have completed the **Name Mangling Implementation Verification** for the Sharpy compiler. Here's what I found:\n\n### \u2705 **Implementation Status: 95% Complete**\n\n**Strengths:**\n- **74/74 NameMangler unit tests passing** \u2705\n- **320/320 CodeGen integration tests passing** \u2705\n- Comprehensive name mangling rules implemented\n- Excellent C# keyword escaping\n- Dunder method mapping works correctly\n- Context-aware transforms properly defined\n\n### \u26a0\ufe0f **One Discrepancy Identified**\n\n**Issue:** Field name mangling in `RoslynEmitter.cs:1195` bypasses the context-aware transform\n\n**Current Behavior:**\n- ALL fields use `ToPascalCase`\n- `user_count` \u2192 `UserCount` \u2705\n- `_user_count` \u2192 `_UserCount` \u274c (should be `_userCount`)\n\n**Root Cause:**\n```csharp\n// RoslynEmitter.cs:1195\nvar fieldName = NameMangler.ToPascalCase(varDecl.Name); // \u26a0\ufe0f Direct call\n\n// Should be:\nvar fieldName = NameMangler.Transform(varDecl.Name, NameContext.Field);\n```\n\n**Requirement:** \nPer `task_list_0_1_6_classes_v2.md:15`: \n> Name mangling: `snake_case` \u2192 `PascalCase` for public, `_snake_case` \u2192 `_camelCase` for private\n\n### \ud83d\udccb **Recommendation**\n\nYou have two options:\n\n1. **Fix the code** - Update `RoslynEmitter.cs:1195` to use `Transform(name, NameContext.Field)` \n2. **Update the spec** - Document that all fields use PascalCase (current behavior)\n\nThe `NameMangler` class itself is well-architected and ready to support either choice. Would you like me to implement Option 1 (fix the code to match the spec)?\n",
6+
"priority": "high",
7+
"options": [
8+
"1. **Fix the code** - Update `RoslynEmitter.cs:1195` to use `Transform(name, NameContext.Field)`",
9+
"2. **Update the spec** - Document that all fields use PascalCase (current behavior)"
10+
],
11+
"created_at": "2026-01-15T01:48:22.757237",
12+
"status": "pending",
13+
"answer": null,
14+
"answered_at": null,
15+
"answer_source": null
16+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Question: q_20260115_014822_f426ffb1
2+
3+
**Task:** 0.1.6.8
4+
**Priority:** high
5+
**Created:** 2026-01-15T01:48:22.757237
6+
**Status:** pending
7+
8+
## Question
9+
10+
Agent is asking for guidance on task 0.1.6.8: Verify Name Mangling Implementation
11+
12+
## Context
13+
14+
## Summary
15+
16+
I have completed the **Name Mangling Implementation Verification** for the Sharpy compiler. Here's what I found:
17+
18+
### **Implementation Status: 95% Complete**
19+
20+
**Strengths:**
21+
- **74/74 NameMangler unit tests passing**
22+
- **320/320 CodeGen integration tests passing**
23+
- Comprehensive name mangling rules implemented
24+
- Excellent C# keyword escaping
25+
- Dunder method mapping works correctly
26+
- Context-aware transforms properly defined
27+
28+
### ⚠️ **One Discrepancy Identified**
29+
30+
**Issue:** Field name mangling in `RoslynEmitter.cs:1195` bypasses the context-aware transform
31+
32+
**Current Behavior:**
33+
- ALL fields use `ToPascalCase`
34+
- `user_count``UserCount`
35+
- `_user_count``_UserCount` ❌ (should be `_userCount`)
36+
37+
**Root Cause:**
38+
```csharp
39+
// RoslynEmitter.cs:1195
40+
var fieldName = NameMangler.ToPascalCase(varDecl.Name); // ⚠️ Direct call
41+
42+
// Should be:
43+
var fieldName = NameMangler.Transform(varDecl.Name, NameContext.Field);
44+
```
45+
46+
**Requirement:**
47+
Per `task_list_0_1_6_classes_v2.md:15`:
48+
> Name mangling: `snake_case``PascalCase` for public, `_snake_case``_camelCase` for private
49+
50+
### 📋 **Recommendation**
51+
52+
You have two options:
53+
54+
1. **Fix the code** - Update `RoslynEmitter.cs:1195` to use `Transform(name, NameContext.Field)`
55+
2. **Update the spec** - Document that all fields use PascalCase (current behavior)
56+
57+
The `NameMangler` class itself is well-architected and ready to support either choice. Would you like me to implement Option 1 (fix the code to match the spec)?
58+
59+
60+
## Options
61+
62+
1. 1. **Fix the code** - Update `RoslynEmitter.cs:1195` to use `Transform(name, NameContext.Field)`
63+
2. 2. **Update the spec** - Document that all fields use PascalCase (current behavior)
64+
65+
## How to Answer
66+
67+
Create a file in the answers directory with the same ID:
68+
`/Users/anton/Documents/github/sharpy/build_tools/sharpy_auto_builder/state/answers/q_20260115_014822_f426ffb1.json`
69+
70+
With content:
71+
```json
72+
{
73+
"answer": "Your answer here",
74+
"notes": "Optional explanation"
75+
}
76+
```
77+
78+
Or for option selection:
79+
```json
80+
{
81+
"answer": "1",
82+
"notes": "Selected option 1 because..."
83+
}
84+
```

0 commit comments

Comments
 (0)