Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
24eb234
fixed naming error for batch norm block
devgunnu Feb 8, 2026
5fc8c83
removed the background square
devgunnu Feb 9, 2026
e341440
fixed custom block ui
devgunnu Feb 9, 2026
30009a4
Fix indentation in validation checks for node types
RETR0-OS Feb 14, 2026
d834f29
Fix validation check for node types
RETR0-OS Feb 14, 2026
8537a60
Merge pull request #52 from ForgeOpus/resnet_update
RETR0-OS Feb 14, 2026
12ca169
Implement loss function node for explicit loss selection
claude Feb 14, 2026
fcb959c
Add code quality enhancements and robustness improvements
claude Feb 14, 2026
7f6cd0b
Fix Loss node UI layout and port positioning
claude Feb 15, 2026
ecd1d8f
Fix Loss node UI with internal port labels
claude Feb 15, 2026
8e7d478
Align Loss node handles with label rows
claude Feb 15, 2026
6307356
Add Ground Truth node and remove CSV upload
claude Feb 15, 2026
b941284
Fix shape propagation for DataLoader and Ground Truth nodes
claude Feb 15, 2026
22b18db
Immediately recalculate output shapes on input/config changes
claude Feb 15, 2026
d345da9
Fix Input node to be passthrough when connected to DataLoader
claude Feb 15, 2026
b74f16e
Fix Loss and GroundTruth port semantics and output handles
claude Feb 15, 2026
ec26436
Fix validation to exclude source and terminal nodes from connection w…
claude Feb 15, 2026
1233e66
Add missing codegen support for GroundTruth and fix MaxPool type mism…
claude Feb 15, 2026
7cb00e6
Add get_pytorch_code_spec to GroundTruth and exclude from layer gener…
claude Feb 15, 2026
b17d1a8
Complete frontend-backend compatibility audit fixes
claude Feb 15, 2026
f58f1d7
fix model name
RETR0-OS Feb 16, 2026
fd11de6
Fix generated scripts.
RETR0-OS Feb 16, 2026
d08f3b0
feat: Add metrics node support for PyTorch and TensorFlow
RETR0-OS Feb 16, 2026
9665aaf
feat: Enhance support for metrics nodes in PyTorch and TensorFlow orc…
RETR0-OS Feb 16, 2026
f6ce214
Add Product Hunt badge to README
RETR0-OS Feb 17, 2026
2908718
Add Product Hunt badge to README
RETR0-OS Feb 17, 2026
b8968c0
Update README with Product Hunt badge
RETR0-OS Feb 17, 2026
720f77a
Apply suggestion from @Copilot
RETR0-OS Feb 17, 2026
e7f1f85
"Claude PR Assistant workflow"
RETR0-OS Feb 17, 2026
ab8351b
"Claude Code Review workflow"
RETR0-OS Feb 17, 2026
c4844d3
Merge pull request #54 from ForgeOpus/add-claude-github-actions-17713…
RETR0-OS Feb 17, 2026
545283a
Bump the npm_and_yarn group across 1 directory with 4 updates
dependabot[bot] Feb 17, 2026
7328ff8
fix: Address PR review comments on code generation pipeline
github-actions[bot] Feb 17, 2026
09c8711
Change triggers to include workflow_dispatch
RETR0-OS Feb 17, 2026
6dc44fa
Merge pull request #53 from ForgeOpus/claude/audit-code-generation-tWPbv
RETR0-OS Feb 17, 2026
181fc30
update lock file
RETR0-OS Feb 17, 2026
067bc1d
Merge remote-tracking branch 'origin/main' into dependabot/npm_and_ya…
RETR0-OS Feb 17, 2026
37dd46e
Merge pull request #56 from ForgeOpus/dependabot/npm_and_yarn/project…
RETR0-OS Feb 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Claude Code Review

on:
workflow_dispatch:

jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
plugins: 'code-review@claude-code-plugins'
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
Comment on lines +3 to +35
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workflow_dispatch runs don’t have a github.event.pull_request payload, so ${{ github.event.pull_request.number }} will be empty and the prompt will be wrong. Add an explicit input for PR number (or use pull_request-based triggers) and build the prompt from that input.

Copilot uses AI. Check for mistakes.
# or https://code.claude.com/docs/en/cli-reference for available options

50 changes: 50 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read

# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'

# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)'

12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@

</div>

<p align="center">
<a href="https://www.producthunt.com/products/forgeopus?embed=true&utm_source=badge-featured&utm_medium=badge&utm_campaign=badge-forgeopus" target="_blank" rel="noopener noreferrer">
<img
alt="ForgeOpus - Where AI masterpieces are forged. Your work, your opus. | Product Hunt"
width="250"
height="54"
src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1080450&theme=light&t=1771311433851"
/>
</a>
</p>


<br />

## ✨ What is VisionForge?
Expand Down
10 changes: 10 additions & 0 deletions project/block_manager/services/codegen/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ def topological_sort(nodes: List[Dict], edges: List[Dict]) -> List[Dict]:
if in_degree[neighbor] == 0:
queue.append(neighbor)

# Cycle detection: if not all nodes were sorted, there's a cycle
if len(sorted_ids) != len(nodes):
# Find nodes that are still in the cycle (have non-zero in-degree)
cycle_nodes = [node_id for node_id, degree in in_degree.items() if degree > 0]
raise ValueError(
f"Graph contains a cycle. Neural networks must be acyclic (feedforward). "
f"Nodes involved in cycle: {', '.join(cycle_nodes[:5])}"
Comment on lines +49 to +53
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cycle error message says “Nodes involved in cycle”, but the remaining non-zero in-degree set can include nodes downstream of a cycle (not necessarily in the cycle). Consider rewording to something like “nodes that could not be topologically sorted (cycle candidates)” or compute a real cycle for accuracy.

Suggested change
# Find nodes that are still in the cycle (have non-zero in-degree)
cycle_nodes = [node_id for node_id, degree in in_degree.items() if degree > 0]
raise ValueError(
f"Graph contains a cycle. Neural networks must be acyclic (feedforward). "
f"Nodes involved in cycle: {', '.join(cycle_nodes[:5])}"
# Find nodes that could not be topologically sorted (cycle candidates, may include downstream nodes)
cycle_nodes = [node_id for node_id, degree in in_degree.items() if degree > 0]
raise ValueError(
f"Graph contains a cycle or unsortable component. Neural networks must be acyclic (feedforward). "
f"Nodes that could not be topologically sorted (cycle candidates): {', '.join(cycle_nodes[:5])}"

Copilot uses AI. Check for mistakes.
+ (" and more..." if len(cycle_nodes) > 5 else "")
)

# Return nodes in sorted order
return [node_map[node_id] for node_id in sorted_ids if node_id in node_map]

Expand Down
6 changes: 3 additions & 3 deletions project/block_manager/services/codegen/base_orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def _generate_code_specs(

processable_nodes = [
n for n in sorted_nodes
if get_node_type(n) not in ('input', 'dataloader', 'output')
if get_node_type(n) not in ('input', 'dataloader', 'output', 'loss', 'metrics', 'groundtruth')
]

for node in processable_nodes:
Expand Down Expand Up @@ -193,7 +193,7 @@ def _generate_forward_pass(

processable_nodes = [
n for n in sorted_nodes
if get_node_type(n) not in ('output',)
if get_node_type(n) not in ('output', 'loss', 'metrics', 'groundtruth')
]

for node in processable_nodes:
Expand Down Expand Up @@ -273,7 +273,7 @@ def _generate_config_file(self, nodes: List[Dict[str, Any]]) -> str:
input_shape = self._extract_input_shape(nodes)
layer_count = sum(
1 for n in nodes
if get_node_type(n) not in ('input', 'output', 'dataloader')
if get_node_type(n) not in ('input', 'output', 'dataloader', 'loss', 'metrics', 'groundtruth')
)

if layer_count > 20:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def _generate_internal_node_specs(
node_type = get_node_type(node)

# Skip special nodes
if node_type in ('input', 'output', 'dataloader'):
if node_type in ('input', 'output', 'dataloader', 'loss'):
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Group codegen only skips loss as a special node. If metrics or groundtruth appear inside a group, they’ll be treated like layers and could produce invalid code/specs. Extend the skip list to match the orchestrators’ special-node exclusions.

Suggested change
if node_type in ('input', 'output', 'dataloader', 'loss'):
if node_type in ('input', 'output', 'dataloader', 'loss', 'metrics', 'groundtruth'):

Copilot uses AI. Check for mistakes.
continue

node_id = node['id']
Expand Down Expand Up @@ -273,8 +273,8 @@ def _generate_forward_pass(
var_map[node_id] = var_name
continue

# Skip output and dataloader nodes (they don't produce code)
if node_type in ('output', 'dataloader'):
# Skip output, dataloader, and loss nodes (they don't produce code)
if node_type in ('output', 'dataloader', 'loss'):
continue

# Get the spec for this node
Expand Down
Loading