Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f23afb4
Add verified fix preparation engine
yoni-at-strix Sep 25, 2026
49eca20
Harden fix preparation against review findings
yoni-at-strix Sep 25, 2026
2b413da
Keep prepared candidates and staleness consistent across revisions
yoni-at-strix Sep 25, 2026
be1c2e4
Withhold automatic fixes when repairs exceed the recorded draft
yoni-at-strix Sep 25, 2026
9d525ad
Add bounded fix verification feedback loop
yoni-at-strix Sep 25, 2026
d02b74c
Preserve explicit blocked repair outcomes
yoni-at-strix Sep 25, 2026
a41000d
Retry unchanged repairs when verification changes
yoni-at-strix Sep 25, 2026
c510f58
fix: retry transient verifier inconclusive results
yoni-at-strix Sep 28, 2026
df313c1
refactor fix preparation gates
yoni-at-strix Sep 28, 2026
00fcb4c
fix: classify distinct check failures correctly
yoni-at-strix Sep 28, 2026
f213a7d
Require functional fix evidence and preserve partial preparation work
Sep 29, 2026
198a254
Make preparation history factory explicit for strict type checking
Sep 29, 2026
791ef91
fix: let independent evidence resolve repair timeout
yoni-at-strix Sep 29, 2026
85b3030
Preserve partial fixes and require consistent execution evidence
Sep 29, 2026
f03fd72
Simplify fix preparation around native tests and independent review
Sep 29, 2026
0faa7b7
Make fix handoffs actionable and require customer unit tests
Sep 29, 2026
43391eb
Let repair and review agents own the fix workflow
Sep 29, 2026
d184142
Let fix reviewer own validation and completion
Sep 29, 2026
348fbf2
Support native fix-agent assignments and final reviewed patches
Sep 30, 2026
5badb2d
Remove retired fix execution and proof machinery
Sep 30, 2026
d35197b
Move complete fix workflow into OSS and add strix fix CLI
Sep 30, 2026
acf262f
Keep fix outputs private and outside the source checkout
Sep 30, 2026
1c1a899
Focus fix agents and preserve completion evidence
Sep 30, 2026
77bd5da
Require an explicit fix handoff for source-backed findings
yoni-at-strix Sep 30, 2026
868ba53
Scope fix validation and warn on repeated commands
yoni-at-strix Sep 30, 2026
e4f1fe6
Merge remote-tracking branch 'origin/main' into devin/1790308365-veri…
yoni-at-strix Sep 30, 2026
ba6bbaf
Include repair follow-ups in the readable review
yoni-at-strix Sep 30, 2026
1789400
Keep an approved fix when only the PR text changes
yoni-at-strix Sep 30, 2026
8317665
Run confirmed finding fixes as native agents in the scan sandbox
yoni-at-strix Sep 30, 2026
b71ed13
Use native child delegation for finding fixes and strengthen completi…
yoni-at-strix Sep 30, 2026
1f8295c
Launch native fixes after persistence and bound completion failures
yoni-at-strix Sep 30, 2026
f75fb5f
fix: harden fix dispatch and verification (STR-815)
yoni-at-strix Oct 1, 2026
bba4aa2
fix: require reviewed current patches and enforce fix network isolation
Oct 1, 2026
60d4ce1
feat: allow scans to skip automatic fixes
yoni-at-strix Oct 1, 2026
3763a67
fix: finalize cancelled fix agents
yoni-at-strix Oct 1, 2026
1fa7d21
feat: publish verified fixes as local branches
yoni-at-strix Oct 1, 2026
f144685
fix: complete interactive autofix scans before cleanup
yoni-at-strix Oct 1, 2026
098fa36
fix: guard resumed assessments and ignore withdrawn fix records
yoni-at-strix Oct 1, 2026
9edb2ae
fix: disable automatic fix agents for PR review scans
yoni-at-strix Oct 1, 2026
8bd7f4c
refactor: use one auto-fix setting and infer fix delivery
yoni-at-strix Oct 2, 2026
818d583
Accept stray characters in validation status and hide auto-fix guidan…
yoni-at-strix Oct 2, 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
Prev Previous commit
Next Next commit
Withhold automatic fixes when repairs exceed the recorded draft
Repair can change files beyond the candidate's draft edits while the
manifest still verifies. Comparing the applied draft hashes against the
final manifest now demotes the result to ready_with_gaps, so SARIF and
other auto-apply consumers never offer a fix that omits verified
changes.
  • Loading branch information
yoni-at-strix committed Sep 25, 2026
commit be1c2e4767a8e6661cd826396115e82efd85290d
26 changes: 26 additions & 0 deletions strix/fix/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,29 @@ async def build_git_manifest(
return entries, summary.decode(errors="replace").strip(), None


def _applied_hashes(workspace: Path, candidate: FixCandidateV1) -> dict[Path, str]:
"""Content hashes of each edited file, captured right after the draft is applied."""
applied: dict[Path, str] = {}
for edit in candidate.draft_edits:
path = (workspace / edit.file).resolve()
applied[path] = hashlib.sha256(path.read_bytes()).hexdigest()
return applied


def _change_extends_draft(
workspace: Path,
applied_sha256: dict[Path, str],
manifest: list[FileManifestEntry],
) -> bool:
"""Whether the verified change set differs from the applied draft edits."""
final_changes = {
(workspace / entry.path).resolve(): entry.resulting_sha256 for entry in manifest
}
return set(final_changes) != set(applied_sha256) or any(
resulting != applied_sha256[resolved] for resolved, resulting in final_changes.items()
)


async def _verify_source(context: PreparationContext) -> bool:
identity = context.candidate.source_identity
if identity is None:
Expand Down Expand Up @@ -429,6 +452,7 @@ async def execute() -> FixPreparationResultV1: # noqa: PLR0911, PLR0912
)
context.candidate = anchored
_apply_edits(workspace, context.candidate)
applied_sha256 = _applied_hashes(workspace, context.candidate)

checks: list[CheckResult] = []
reproduction: CheckResult | None = None
Expand Down Expand Up @@ -474,6 +498,8 @@ async def execute() -> FixPreparationResultV1: # noqa: PLR0911, PLR0912
for result in checks
if not result.required and result.status is not CheckStatus.PASSED
)
if _change_extends_draft(workspace, applied_sha256, manifest):
gaps.append("The verified change extends beyond the recorded draft edits.")
if reproduction is None and not verifier.reproduction_executed:
gaps.append("No executable security reproduction was available.")
elif reproduction is not None and reproduction.status is CheckStatus.UNAVAILABLE:
Expand Down
24 changes: 24 additions & 0 deletions tests/test_fix_preparation.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,30 @@ async def test_prepare_fix_returns_ready_with_manifest(tmp_path: Path) -> None:
assert (workspace / "app.py").read_text(encoding="utf-8").endswith("return 'safe'\n")


@pytest.mark.asyncio
async def test_prepare_fix_demotes_ready_when_repair_exceeds_draft(
tmp_path: Path,
) -> None:
workspace, commit = _workspace(tmp_path)

async def widening_repair(
_context: PreparationContext,
_checks: list[CheckResult],
) -> None:
(workspace / "hardening.py").write_text("HELPER = True\n", encoding="utf-8")

result = await prepare_fix(
_request(_candidate(commit)),
workspace,
repair=widening_repair,
verify=_verified,
)

assert result.state is PreparationState.READY_WITH_GAPS
assert any("beyond the recorded draft edits" in gap for gap in result.gaps)
assert result.candidate.digest() == result.candidate_digest


@pytest.mark.asyncio
async def test_prepare_fix_retries_failed_checks(tmp_path: Path) -> None:
workspace, commit = _workspace(tmp_path)
Expand Down