Skip to content

Bound PowerFactory contingency element scans - #88

Merged
qian-harvard merged 2 commits into
Power-Agent:mainfrom
aswinkrishnapoyil:fix/powerfactory-contingency-element-scan
Sep 23, 2026
Merged

qian-harvard merged 2 commits into
Power-Agent:mainfrom
aswinkrishnapoyil:fix/powerfactory-contingency-element-scan

Conversation

@aswinkrishnapoyil

Copy link
Copy Markdown
Contributor

Summary

  • Add a termination ceiling to the affected-element walk in get_contingency_summary.
  • Raise a clear error if PowerFactory does not return None within 10,000 elements.
  • Preserve the existing bounded output and truncation metadata.
  • Add regression coverage for a GetObject() implementation that never signals the end.

This prevents the single PowerFactory worker from becoming stuck in an unbounded loop.

Validation

  • PowerFactory suite: 40 passed, including 7 subtests.
  • git diff --check passed.

Closes #87

aswinkrishnapoyil and others added 2 commits September 23, 2026 18:36
The bounded walk looped over range(cap) with a for/else, so it never
probed index cap. A contingency listing exactly cap elements exhausted
the loop without seeing PowerFactory's terminating None and was
rejected as having "exceeded the safe limit" -- a false error, where
main accepts it.

The walk now probes one index past the cap: None there means the list
is complete, anything else raises. Behaviour at the real cap of 10,000:

  n=10000     ok, total=10000, 10001 probes
  n=10001     "exceeded the safe limit", 10001 probes
  never None  "exceeded the safe limit", 10001 probes

The tests pin the boundary with the cap patched to the fixture's two
elements, and assert the cap stays above max_affected_elements' clamp
of 1000 so truncation remains reachable. The never-None fake now counts
its probes and raises after ten, so reverting to an unbounded walk fails
the test in milliseconds instead of hanging CI, which sets no pytest
timeout -- checked by mutation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@qian-harvard

Copy link
Copy Markdown
Contributor

This does what #87 asked for: the walk now always terminates, a runaway GetObject surfaces as a structured {success: false} with Release() still running, and total_affected_elements can never be a capped number because every path that reaches the cap raises. Reviewed from four angles, with each finding independently reproduced; nothing blocking.

I pushed one fix as c4ef140 (maintainer edit): an off-by-one at the boundary. for index in range(cap) with a for/else never probes index cap, so a contingency listing exactly 10,000 elements exhausted the loop without seeing the terminating None and was rejected as "exceeded" — a false error, where main accepts it. The walk now probes one index past the cap:

n=10000     ok, total=10000, 10001 probes
n=10001     "exceeded the safe limit", 10001 probes
never None  "exceeded the safe limit", 10001 probes

Tests: the boundary is pinned with the cap patched to the fixture's two elements, and there's an assertion that the cap stays above max_affected_elements' clamp of 1000 so truncation stays reachable. One change to your test: the never-None fake now counts its probes and raises after ten. Before, reverting to while True made the test hang rather than fail, and CI sets no pytest timeout — I checked by mutation that it now fails in milliseconds.

Merging. Thanks for turning #87 around within the hour.

@qian-harvard
qian-harvard merged commit 861a1cf into Power-Agent:main Sep 23, 2026
4 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.

get_contingency_summary: element walk has no termination bound

2 participants