Skip to content

Commit cd6925e

Browse files
Release 2026.4.1 (#643) (#38)
# 🎈 Minor Updates - Made `ideas.translate` resumable by re-reading the translation cache. - Added environment variables `HYBRID_BUILD` and `STATIC_TRANSLATIONS` for controlling translation strategy and disabling bleeding edge features. - Improved `ideas.agents.testgen` prompt and workflow. --------- Co-authored-by: Cory Cornelius <cory.cornelius@intel.com>
1 parent b43d7a0 commit cd6925e

15 files changed

Lines changed: 438 additions & 476 deletions

AGENTS.mk

Lines changed: 27 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,113 +6,80 @@
66

77
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
88
MAKEFILE_DIR := $(realpath $(dir $(MAKEFILE_PATH)))
9-
EXTRACT_INFO_CMAKE := ${MAKEFILE_DIR}/extract_info.cmake
10-
IDEAS_MAKEFILE := $(MAKEFILE_DIR)/IDEAS.mk
11-
12-
ANTHROPIC_AUTH_TOKEN ?= $(OPENROUTER_API_KEY)
13-
ANTHROPIC_BASE_URL ?= https://openrouter.ai/api
14-
ANTHROPIC_API_KEY ?= ""
159

1610
AGENT_PROVIDER ?= openrouter
1711
AGENT_MODEL ?= anthropic/claude-sonnet-4.6
18-
BASE_URL ?= "https://openrouter.ai/api/v1"
19-
TRANSLATION_DIR ?= translation.$(shell git --git-dir=${MAKEFILE_DIR}/.git rev-parse HEAD)
20-
21-
export EXTRACT_INFO_CMAKE
22-
23-
TARGETS ?= $(shell [ -d build-ninja ] && find build-ninja -maxdepth 1 -type f -executable -exec basename {} \; | cut -d. -f1 | sed -e "s/^lib//gi")
24-
ifeq (${TARGETS},)
25-
ifeq ($(filter cmake clean,$(MAKECMDGOALS)),)
26-
$(error No TARGETS found! You need to run cmake!)
27-
endif
28-
endif
12+
AGENT_BASE_URL ?= "https://openrouter.ai/api/v1"
2913

3014
# Docker configuration
31-
DOCKER_DIR := ${MAKEFILE_DIR}/docker
15+
DOCKER_HOSTDIR := ${MAKEFILE_DIR}/docker
3216
DOCKER_WORKDIR := /home/user/IDEAS
33-
# Relative path to the current working directory
34-
DOCKER_REL_CWD := $(patsubst $(MAKEFILE_DIR)/%,%,$(CURDIR))
3517
DOCKER_RUN ?= docker run --rm \
3618
--init \
3719
-it \
3820
-v $(MAKEFILE_DIR):$(DOCKER_WORKDIR) \
39-
-v $(DOCKER_DIR)/.venv:$(DOCKER_WORKDIR)/.venv \
21+
-w $(DOCKER_WORKDIR)/$(patsubst $(MAKEFILE_DIR)/%,%,$(CURDIR)) \
4022
-e OPENROUTER_API_KEY \
4123
-e TRANSLATION_DIR \
4224
-e AGENT_PROVIDER \
4325
-e AGENT_MODEL \
44-
-e BASE_URL \
26+
-e AGENT_BASE_URL \
4527
-e RUSTFLAGS \
46-
-e VERBOSE \
4728
ideas-$(shell id -u)
4829

4930
ifdef DOCKER_RUN
50-
# Touch directory for correct permissions when mounted
51-
VENV_SETUP = mkdir -p $(DOCKER_DIR)/.venv
52-
# Run inside Docker container with exit-on-error
53-
RUN_CMD = $(DOCKER_RUN) /bin/sh -c 'set -e; cd $(DOCKER_WORKDIR)/$(DOCKER_REL_CWD); $(1)'
31+
RUN_PREFIX = \
32+
mkdir -p $(DOCKER_HOSTDIR)/.venv && \
33+
$(DOCKER_RUN) \
34+
/bin/sh -c 'set -e;
35+
RUN_SUFFIX = '
5436
else
55-
VENV_SETUP = @true
56-
RUN_CMD = $(1)
37+
RUN_PREFIX =
38+
RUN_SUFFIX =
5739
endif
5840

59-
# cmake
60-
.PHONY: cmake
61-
cmake: build-ninja/cmake.log
62-
63-
build-ninja/cmake.log: test_case/CMakeLists.txt ${EXTRACT_INFO_CMAKE}
64-
uv run python -m ideas.cmake source_dir=test_case build_dir=build-ninja
65-
@touch $@
66-
67-
build-ninja/CMakeCache.txt: build-ninja/cmake.log
68-
build-ninja/compile_commands.json: build-ninja/cmake.log
69-
build-ninja/build.log: build-ninja/cmake.log
7041

7142
# test generation from project
7243
.PHONY: testgen
7344
testgen: test_crate/tests/test_assert.rs ;
7445

7546
.PRECIOUS: test_crate/tests/test_assert.rs
7647
test_crate/tests/test_assert.rs:
77-
$(VENV_SETUP)
78-
$(call RUN_CMD,\
48+
$(RUN_PREFIX) \
7949
uv run python -m ideas.agents.testgen model=$(if $(AGENT_PROVIDER),${AGENT_PROVIDER}/,)${AGENT_MODEL} \
8050
c_code=test_case \
8151
project_name=$(notdir $(CURDIR)) \
8252
test_vectors_out=test_vectors/agent \
8353
test_crate_out=test_crate \
8454
hydra.output_subdir=.testgen \
8555
hydra.job.name=testgen \
86-
hydra.run.dir=test_vectors; \
87-
)
56+
hydra.run.dir=test_vectors \
57+
$(RUN_SUFFIX)
58+
# Agent is not guaranteed to write file
59+
[ -f test_crate/tests/test_assert.rs ] || { echo "ERROR: Agent failed to generate test_crate/tests/test_assert.rs"; exit 1; }
8860

8961

9062
# library targets: generate tests from the consolidated lib.c
9163
.PRECIOUS: test_crates/%/tests/test_assert.rs
9264
test_crates/%/tests/test_assert.rs: ${TRANSLATION_DIR}/%/src/lib.c | build-ninja/lib%.so.type
93-
# Copy lib.c into test_targets/<target>/src/ so
94-
# build.rs can use ../../test_targets/<target>/src/lib.c
65+
# Copy lib.c into test_crates/<target>/src/ so
66+
# build.rs can use ../../test_crates/<target>/src/lib.c
9567
# both in Docker /tmp and on disk
96-
mkdir -p test_targets/$*/src
97-
cp ${TRANSLATION_DIR}/$*/src/lib.c test_targets/$*/src/lib.c
98-
$(VENV_SETUP)
99-
$(call RUN_CMD,\
68+
mkdir -p test_crates/$*/src
69+
cp ${TRANSLATION_DIR}/$*/src/lib.c test_crates/$*/src/lib.c
70+
$(RUN_PREFIX) \
10071
uv run python -m ideas.agents.testgen model=$(if $(AGENT_PROVIDER),${AGENT_PROVIDER}/,)${AGENT_MODEL} \
101-
c_code=test_targets/$*/src/lib.c \
72+
c_code=test_crates/$*/src/lib.c \
10273
project_name=$* \
10374
test_vectors_out=test_vectors/$*/agent \
10475
test_crate_out=test_crates/$* \
10576
hydra.output_subdir=.testgen \
10677
hydra.job.name=testgen \
107-
hydra.run.dir=test_vectors/$*; \
108-
)
78+
hydra.run.dir=test_vectors/$* \
79+
$(RUN_SUFFIX)
80+
# Agent is not guaranteed to write file
81+
[ -f test_crates/$*/tests/test_assert.rs ] || { echo "ERROR: Agent failed to generate test_crates/$*/tests/test_assert.rs"; exit 1; }
10982

11083
# executable targets: do nothing
11184
test_crates/%/tests/test_assert.rs: ${TRANSLATION_DIR}/%/src/main.c | build-ninja/%.type
112-
mkdir -p test_crates/$*/tests
113-
touch test_crates/$*/tests/test_assert.rs
114-
115-
# fallback
116-
test_crates/%/tests/test_assert.rs:
117-
mkdir -p test_crates/$*/tests
118-
touch test_crates/$*/tests/test_assert.rs
85+
$(error Agent cannot generate tests for binary targets yet!)

IDEAS.mk

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ build-ninja/build.log: build-ninja/cmake.log
5555
# init
5656
.PHONY: init
5757
init: $(patsubst %,${TRANSLATION_DIR}/%/init,${TARGETS}) ;
58-
${TRANSLATION_DIR}/%/init: ${TRANSLATION_DIR}/%/src/lib.c | build-ninja/lib%.so.type ;
59-
${TRANSLATION_DIR}/%/init: ${TRANSLATION_DIR}/%/src/main.c | build-ninja/%.type ;
58+
${TRANSLATION_DIR}/%/init: ${TRANSLATION_DIR}/%/src/lib.c | build-ninja/lib%.so.type
59+
touch ${TRANSLATION_DIR}/$*/src/lib.c
60+
${TRANSLATION_DIR}/%/init: ${TRANSLATION_DIR}/%/src/main.c | build-ninja/%.type
61+
touch ${TRANSLATION_DIR}/$*/src/main.c
6062

6163
# initialize workspace
6264
.PRECIOUS: ${TRANSLATION_DIR}/Cargo.toml
@@ -103,7 +105,7 @@ ${TRANSLATION_DIR}/%/translate: ${TRANSLATION_DIR}/%/src/lib.rs | build-ninja/li
103105
${TRANSLATION_DIR}/%/translate: ${TRANSLATION_DIR}/%/src/main.rs | build-ninja/%.type ;
104106

105107
.PRECIOUS: ${TRANSLATION_DIR}/%/src/lib.rs
106-
${TRANSLATION_DIR}/%/src/lib.rs: ${TRANSLATION_DIR}/%/src/lib.c ${TRANSLATION_DIR}/%/tests/test_cases.rs | ${TRANSLATION_DIR}/%/Cargo.toml
108+
${TRANSLATION_DIR}/%/src/lib.rs: ${TRANSLATION_DIR}/%/src/lib.c | ${TRANSLATION_DIR}/%/Cargo.toml ${TRANSLATION_DIR}/%/tests/test_assert.rs
107109
-uv run python -m ideas.translate model.name=${PROVIDER}/${MODEL} \
108110
filename=${TRANSLATION_DIR}/$*/src/lib.c \
109111
cargo_toml=${TRANSLATION_DIR}/$*/Cargo.toml \
@@ -210,35 +212,24 @@ test_vectors/%/%.json:
210212
$(error $@ not found)
211213

212214

213-
# testgen
214-
.PHONY: testgen_argless
215-
testgen_argless: $(patsubst %,test_vectors/%/testgen_argless,${TARGETS})
216-
test_vectors/%/testgen_argless: | build-ninja/lib%.so.type ;
217-
test_vectors/%/testgen_argless: test_vectors/%/argless.json | build-ninja/%.type ;
218-
219-
.PRECIOUS: test_vectors/%/argless.json
220-
test_vectors/%/argless.json: | build-ninja/%.type
221-
-uv run python -m ideas.testgen artifact=build-ninja/$* \
222-
test_vector=$@ \
223-
hydra.output_subdir=.testgen \
224-
hydra.job.name=testgen \
225-
hydra.run.dir=test_vectors/$*
226-
227215
# testgen for each C target
228216
.PHONY: testgen_target
229-
testgen_target: $(patsubst %,${TRANSLATION_DIR}/%/tests/test_assert.rs,${TARGETS}) ;
217+
testgen_target: $(patsubst %,test_crates/%/tests/test_assert.rs,${TARGETS}) ;
230218

231-
${TRANSLATION_DIR}/%/tests/test_assert.rs: test_crates/%/tests/test_assert.rs build-ninja/lib%.so.type
232-
mkdir -p $(dir $@)
233-
cp test_crates/$*/tests/test_assert.rs $@
219+
.PRECIOUS: test_crates/%/tests/test_assert.rs
220+
test_crates/%/tests/test_assert.rs: | ${TRANSLATION_DIR}/%/src/lib.c build-ninja/lib%.so.type
221+
-@$(MAKE) -j1 -f $(AGENTS_MAKEFILE) test_crates/$*/tests/test_assert.rs
234222

235223
.PRECIOUS: test_crates/%/tests/test_assert.rs
236-
test_crates/%/tests/test_assert.rs:
224+
test_crates/%/tests/test_assert.rs: | ${TRANSLATION_DIR}/%/src/main.c | build-ninja/%.type
237225
-@$(MAKE) -j1 -f $(AGENTS_MAKEFILE) test_crates/$*/tests/test_assert.rs
238226

239-
${TRANSLATION_DIR}/%/tests/test_assert.rs: build-ninja/%.type
227+
${TRANSLATION_DIR}/%/tests/test_assert.rs: test_crates/%/tests/test_assert.rs | build-ninja/lib%.so.type
240228
mkdir -p $(dir $@)
241-
touch $@
229+
cp test_crates/$*/tests/test_assert.rs $@
230+
231+
${TRANSLATION_DIR}/%/tests/test_assert.rs: | build-ninja/%.type
232+
$(error Agent cannot generate tests for binary targets yet!)
242233

243234

244235
# clean

Makefile

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ kill:## Kill all vLLM servers
9999
.PHONY: FORCE
100100
FORCE:
101101

102+
.PHONY: examples
103+
examples:## Print out examples
104+
examples: $(addsuffix /print,${EXAMPLES}) ;
105+
examples/%/print: FORCE
106+
@if [ -d "$(@D)" ]; then echo "$(@D)"; fi
107+
102108
.PHONY: examples/init
103109
examples/init:## Initialize all examples
104110
examples/init: $(addsuffix /init,${EXAMPLES}) ;
@@ -122,15 +128,6 @@ examples/%/cmake: FORCE
122128
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) cmake
123129

124130

125-
.PHONE: examples/testgen_argless
126-
examples/testgen_argless:## Generate argless tests for executable targets in all C examples
127-
examples/testgen_argless: $(addsuffix /testgen_argless,${EXAMPLES})
128-
examples/%/testgen_argless:## Generate argless tests for executable targets in a specific C example
129-
examples/%/testgen_argless: FORCE
130-
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) cmake
131-
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) testgen_argless
132-
133-
134131
.PHONY: examples/testgen_agent
135132
examples/testgen_agent:## Generate test vectors for all C examples with an agent
136133
examples/testgen_agent: $(addsuffix /testgen_agent,${EXAMPLES})
@@ -145,22 +142,9 @@ examples/testgen_agent_target: $(addsuffix /testgen_agent_target,${EXAMPLES})
145142
examples/%/testgen_agent_target:## Generate test vectors for all targets in a specific C example with an agent
146143
examples/%/testgen_agent_target: FORCE
147144
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) cmake
148-
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) init
149145
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) testgen_target
150146

151147

152-
.PHONY: examples/testgen_and_translate
153-
examples/testgen_and_translate:## Generate tests and translate all examples
154-
examples/testgen_and_translate: $(addsuffix /testgen_and_translate,${EXAMPLES})
155-
examples/%/testgen_and_translate:## Generate tests and translate specific example
156-
examples/%/testgen_and_translate: FORCE
157-
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) cmake
158-
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) testgen_argless
159-
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) init
160-
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) testgen_target
161-
-@$(MAKE) -j1 -f $(IDEAS_MAKEFILE) -C $(@D) translate
162-
163-
164148
.PHONY: examples/translate
165149
examples/translate:## Translate all examples
166150
examples/translate: $(addsuffix /translate,${EXAMPLES})

src/ideas/agents/testgen.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ class TestgenInstructions:
125125
Write a `{rs_crate_path}/build.rs` that:
126126
1. Uses `cc::Build::new()` with `.compiler("clang")` to compile **all** C source files discovered in Step 1.
127127
2. Adds the correct include directories so the C headers are found.
128-
3. Links any extra system libraries the C project requires (e.g. `println!("cargo::rustc-link-lib=m");`).
129-
4. Passes `-w` (suppress warnings) and `-std=c99`.
128+
3. Uses `.warnings(false)` to suppress warnings.
129+
4. Uses `.std("c99")` to specify the C standard.
130+
5. Links any extra system libraries the C project requires (e.g. `println!("cargo::rustc-link-lib=m");`).
130131
"""
131132
)
132133

@@ -351,7 +352,7 @@ class TestgenInstructions:
351352
JSON file.
352353
- For floating-point fields use an epsilon comparison:
353354
```rust
354-
assert!((actual - expected).abs() < 1e-4,
355+
assert!((actual - expected).abs() / expected.abs() < 1e-3,
355356
"field `<name>`: expected {{expected}}, got {{actual}}");
356357
```
357358
- For integer / bool fields use `assert_eq!`.
@@ -442,9 +443,7 @@ def _main(cfg: TestgenConfig) -> None:
442443
logger_trajectory.addHandler(fh)
443444
# Simultaneous print and log to file
444445
printer = LoggingConsolePrinter(logger=logger_trajectory)
445-
446-
name = "C library test vector generator"
447-
agent = RelentlessAgent(name=name)
446+
agent = RelentlessAgent(name="C library test vector generator")
448447

449448
project_name = cfg.project_name
450449
work_dir = Path(tempfile.mkdtemp()) / project_name

0 commit comments

Comments
 (0)