Skip to content

fix: resolve ProjectState import mismatches after #1500 decoupling refactor - #1504

Merged
colehurwitz merged 1 commit into
mainfrom
factory/run-c09a42c3
Sep 15, 2026
Merged

colehurwitz merged 1 commit into
mainfrom
factory/run-c09a42c3

Conversation

@colehurwitz

Copy link
Copy Markdown
Collaborator

Closes the mypy arg-type errors introduced by PR #1500's graph language decoupling.

Changes

  • Changed from factory.models import ProjectState to from factory.workflow.primitives import ProjectState in all 23 affected workflow/test files
  • 3 core workflow modules: research.py, deep_research.py, deep_qa.py
  • 11 contributed benchmark workflows: devopsgym, featurebench, legacybench, mini_swebench, outer_loop, programbench, salitrap, swebench, swebenchifyhard, terminalbench, tomswe
  • 9 contributed benchmark test files

Why

PR #1500 intentionally duplicated ProjectState into factory.workflow.primitives so the graph language has zero runtime deps on factory.models. The Workflow class and TriggerFn type alias reference primitives.ProjectState, but these 23 files still imported from factory.models, creating a type mismatch that produced 68 mypy arg-type errors.

This fix respects the decoupling design intent — the workflow subsystem should depend on primitives, not models.

Verification

  • uv run mypy factory/ | grep arg-type → 0 results (all 68 errors eliminated)
  • uv run pytest factory/workflow/contributed/ -x -q → 257 passed
  • uv run ruff check → all checks passed

🤖 Generated with Claude Code

…low.primitives

After PR #1500 decoupled the graph language from the runtime, Workflow.trigger's
type signature references primitives.ProjectState, but 23 workflow/test files
still imported from factory.models — creating 68 mypy arg-type errors.

This changes all 23 files to import ProjectState from factory.workflow.primitives,
which is the correct source for the workflow subsystem per the decoupling design.

Files changed:
- 3 core workflow modules (research, deep_research, deep_qa)
- 11 contributed benchmark workflows
- 9 contributed benchmark test files

Verification:
- mypy factory/ | grep arg-type → 0 results
- pytest factory/workflow/contributed/ → 257 passed
- ruff check → all passed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Sentrux Quality Report

Absolute

Scanning ....
[scan] git ls-files: 651 total, 637 kept, 14 dropped (ext:14, meta:0, big:0)
[build_project_map] 637 files, 108 unique dirs, 100 cache misses, 5.1ms
[resolve] 1270 resolved, 1680 unresolved (of 2950 total specs)
[resolve_imports] project_map 5.3ms, suffix_idx 1.6ms, suffix_resolve 23.1ms, total 30.0ms
[build_graphs] 637 files | maps 2.3ms, imports 30.2ms, calls+inherit 6.8ms, total 39.3ms | 1269 import, 10472 call, 4 inherit edges
sentrux check — 3 rules checked

Quality: 4404

✗ [Error] max_cc: 9 function(s) exceed max cyclomatic complexity of 30
    factory/workflow/executor.py:_execute_data (cc=53)
    factory/outer_loop/reflector.py:_extract_eval_patterns (cc=46)
    factory/cli/_ceo_helpers.py:_validate_ceo_flags (cc=43)
    factory/cli/_ceo_helpers.py:_execute_ceo (cc=43)
    factory/outer_loop/mutations.py:_try_mutation (cc=40)
    examples/chess_evolve.py:main (cc=33)
    factory/cli/_task_builder.py:_build_ceo_task (cc=32)
    factory/outer_loop/reflector.py:_llm_reflect (cc=32)
    factory/outer_loop/mutations.py:validate_and_repair (cc=31)

✗ 1 violation(s) found

Diff (vs base branch)

Scanning ....
[scan] git ls-files: 651 total, 637 kept, 14 dropped (ext:14, meta:0, big:0)
[build_project_map] 637 files, 108 unique dirs, 100 cache misses, 5.1ms
[resolve] 1270 resolved, 1680 unresolved (of 2950 total specs)
[resolve_imports] project_map 5.2ms, suffix_idx 1.1ms, suffix_resolve 20.1ms, total 26.4ms
[build_graphs] 637 files | maps 2.2ms, imports 26.5ms, calls+inherit 6.7ms, total 35.4ms | 1269 import, 10472 call, 4 inherit edges
sentrux gate — structural regression check

Quality:      4400 -> 4404
Coupling:     0.81 → 0.80
Cycles:       4 → 4
God files:    3 → 3

Distance from Main Sequence: 0.33

✓ No degradation detected

@codecov

codecov Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.74%. Comparing base (4262d36) to head (025eebb).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1504      +/-   ##
==========================================
- Coverage   83.76%   83.74%   -0.02%     
==========================================
  Files         225      225              
  Lines       25760    25737      -23     
  Branches     4209     4209              
==========================================
- Hits        21577    21554      -23     
+ Misses       3202     3200       -2     
- Partials      981      983       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@colehurwitz
colehurwitz marked this pull request as ready for review September 15, 2026 17:26
@colehurwitz

Copy link
Copy Markdown
Collaborator Author

@ceo-review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Factory Review: KEEP

Verdict: KEEP
Reason: QA: CLEAN — 601 tests pass, 0 mypy errors (68 resolved), 0 lint issues, composite 0.9631. Code review 7/7 PASS. Adversarial QA 7/7 PASS with evidence.

QA Analysis

Adversarial QA Report — PR #1504

PR: fix: resolve ProjectState import mismatches after #1500 decoupling refactor
Detected project type: Library (multi-agent orchestration framework)
Date: 2026-09-15
Strategist plan: No .factory/strategy/current.md found — this is a targeted fix PR, not a hypothesis experiment.


Smoke Test

Status: PASS (via contributed test suite — 257 tests in 0.85s)


Test Plan

The PR changes from factory.models import ProjectStatefrom factory.workflow.primitives import ProjectState across 23 files in factory/workflow/. Testing verifies:

  1. The new import path works
  2. Cross-module compatibility is maintained
  3. No circular imports introduced
  4. All contributed workflows still import cleanly
  5. No stale imports remain in factory/workflow/
  6. All contributed tests pass
  7. Zero mypy arg-type errors

Feature Tests

Test 1: Import Smoke Test

Status: ✅ VERIFIED

$ uv run python -c 'from factory.workflow.primitives import ProjectState; print(ProjectState.__members__)'
{'NO_REPO': <ProjectState.NO_REPO: 'no_repo'>, 'REPO_INCOMPLETE': <ProjectState.REPO_INCOMPLETE: 'incomplete'>, 'NO_FACTORY': <ProjectState.NO_FACTORY: 'no_factory'>, 'EVALS_PENDING_REVIEW': <ProjectState.EVALS_PENDING_REVIEW: 'evals_pending_review'>, 'HAS_FACTORY': <ProjectState.HAS_FACTORY: 'has_factory'>}

All 5 enum members present and accessible.


Test 2: Cross-Module Identity Test

Status: ✅ VERIFIED (with note)

$ uv run python -c 'from factory.models import ProjectState as A; from factory.workflow.primitives import ProjectState as B; print("identity:", A is B); print("HAS_FACTORY equal:", A.HAS_FACTORY == B.HAS_FACTORY); print("HAS_FACTORY value equal:", A.HAS_FACTORY.value == B.HAS_FACTORY.value); print("type A:", type(A.HAS_FACTORY)); print("type B:", type(B.HAS_FACTORY))'
identity: False
HAS_FACTORY equal: True
HAS_FACTORY value equal: True
type A: <enum 'ProjectState'>
type B: <enum 'ProjectState'>

Note: identity: False is expected by design. The comment in primitives.py says: "inlined so the graph language has zero runtime deps". Since both are str, Enum subclasses with identical values, == comparison works correctly. Additional verification confirmed all 5 members match and string interop is clean. No isinstance(..., ProjectState) checks exist in factory/workflow/, so identity difference causes no runtime issues.


Test 3: Circular Import Test

Status: ✅ VERIFIED

$ uv run python -c 'import factory.workflow.research; import factory.workflow.deep_qa; import factory.workflow.deep_research; print("All core workflow modules import successfully")'
All core workflow modules import successfully

No circular imports — all 3 core workflow modules import cleanly.


Test 4: Contributed Workflow Import Test

Status: ✅ VERIFIED

$ uv run python -c 'import factory.workflow.contributed.devopsgym.workflow; import factory.workflow.contributed.featurebench.workflow; import factory.workflow.contributed.swebench.workflow; print("Contributed workflows import OK")'
OK: factory.workflow.contributed.devopsgym.workflow
OK: factory.workflow.contributed.featurebench.workflow
OK: factory.workflow.contributed.swebench.workflow
Contributed workflows import check complete

All 3 contributed workflow packages import without errors.


Test 5: Grep Verification — No Stale Imports

Status: ✅ VERIFIED

$ grep -rn 'from factory.models import ProjectState' factory/workflow/
(no output)

Zero stale imports found in factory/workflow/.

Bonus check — broader search found 2 remaining uses outside scope:

$ grep -rn 'from factory.models import ProjectState' factory/
factory/state.py:9:from factory.models import ProjectState
factory/cli/_mode_handlers.py:69:    from factory.models import ProjectState

These are in factory/state.py and factory/cli/_mode_handlers.py — outside factory/workflow/ and thus correctly out of scope for this PR.

AST-level verification also confirmed all contributed workflow .py files use the correct import:

$ uv run python -c "<AST check script>"
All contributed workflow files use factory.workflow.primitives

Test 6: Contributed Workflow Test Suite

Status: ✅ VERIFIED

$ uv run pytest factory/workflow/contributed/ -x -q
........................................................................ [ 28%]
........................................................................ [ 56%]
........................................................................ [ 84%]
.........................................                                [100%]
257 passed in 0.85s

All 257 contributed workflow tests pass with zero failures.


Test 7: mypy Verification

Status: ✅ VERIFIED

$ uv run mypy factory/ 2>&1 | grep 'arg-type' | head -20
(no output)

$ uv run mypy factory/ 2>&1 | tail -5
Success: no issues found in 244 source files

Zero arg-type errors. Zero mypy errors of any kind across all 244 source files.


Edge Case Tests

Edge Case: Value Interoperability

Status: ✅ VERIFIED

$ uv run python -c "<full interop check>"
All 5 members match between modules
String interop verified

All enum member names, values, and string representations are identical across both modules.

Edge Case: No isinstance Boundary Crossings

Status: ✅ VERIFIED

$ grep -rn 'isinstance.*ProjectState' factory/workflow/
(no output)

No isinstance checks on ProjectState in factory/workflow/, so the dual-class design cannot cause type mismatch bugs.


Acceptance Criteria Verification

# Criterion Status Evidence
1 ProjectState importable from factory.workflow.primitives ✅ VERIFIED 5 members printed correctly
2 Cross-module value compatibility ✅ VERIFIED == returns True, values match
3 No circular imports in core workflows ✅ VERIFIED 3 modules import cleanly
4 Contributed workflows import correctly ✅ VERIFIED 3/3 packages import OK
5 No stale imports in factory/workflow/ ✅ VERIFIED grep returns empty
6 All contributed tests pass ✅ VERIFIED 257/257 pass
7 Zero mypy arg-type errors ✅ VERIFIED 0 errors in 244 files

Adversarial Verdict: PASS

All 7 required tests pass with concrete evidence. The import migration is complete and correct within its declared scope (factory/workflow/). The dual ProjectState definition is an intentional architectural choice for zero-dependency graph primitives, and value interop is confirmed. No regressions detected.


Posted by Factory CEO

@colehurwitz
colehurwitz merged commit d282f83 into main Sep 15, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant