fix: resolve ProjectState import mismatches after #1500 decoupling refactor - #1504
Conversation
…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>
Sentrux Quality ReportAbsoluteDiff (vs base branch) |
Codecov Report✅ All modified and coverable lines are covered by tests. 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. 🚀 New features to boost your workflow:
|
|
@ceo-review |
There was a problem hiding this comment.
✅ 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 ProjectState → from factory.workflow.primitives import ProjectState across 23 files in factory/workflow/. Testing verifies:
- The new import path works
- Cross-module compatibility is maintained
- No circular imports introduced
- All contributed workflows still import cleanly
- No stale imports remain in
factory/workflow/ - All contributed tests pass
- 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
Closes the mypy arg-type errors introduced by PR #1500's graph language decoupling.
Changes
from factory.models import ProjectStatetofrom factory.workflow.primitives import ProjectStatein all 23 affected workflow/test filesresearch.py,deep_research.py,deep_qa.pyWhy
PR #1500 intentionally duplicated
ProjectStateintofactory.workflow.primitivesso the graph language has zero runtime deps onfactory.models. TheWorkflowclass andTriggerFntype alias referenceprimitives.ProjectState, but these 23 files still imported fromfactory.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, notmodels.Verification
uv run mypy factory/ | grep arg-type→ 0 results (all 68 errors eliminated)uv run pytest factory/workflow/contributed/ -x -q→ 257 passeduv run ruff check→ all checks passed🤖 Generated with Claude Code