Fix/docker version badge - #11
Merged
Merged
Conversation
added 8 commits
September 21, 2026 16:02
Two things made the GUI's version badge lie. `src/asaree/_version.py` is gitignored but was not in .dockerignore, so a host-side `uv sync` left one behind that `COPY src/` baked into the image -- and since _app_version() prefers it over the distribution metadata, the badge froze at whatever commit that checkout last built. Separately, /app is a partial checkout (no frontend/, tests/, docs/, or root files), so everything missing reads as deleted against the mounted index and `git describe --dirty` returns -dirty. setuptools_scm treats dirty like distance, so building the v0.6.0 tag produced 0.6.1.dev0: every release announced itself as a prerelease of the next one. Marking the absent paths assume-unchanged before `uv sync` restores the clean describe the tag names. Verified: a build of the v0.6.0 commit now installs asaree==0.6.0 and _app_version() returns 0.6.0, so the badge reads v0.6.0.
A Reason+Act run that hits max_iterations does not fail: Motoro's loop falls through its for...else, keeps the last tool result as the output, and still marks the run completed. Downstream that is indistinguishable from a finished run -- the Output Parser reads a tool dump instead of a report, and every contracted field the dump does not happen to state comes back null. That is what the "Extracted fields: null" reports were. The cap is a safety stop, not a budget: the agent exits the moment it answers, so a cap above what a run needs costs nothing while one below it silently truncates. Raise the new-node default from 15 to 30 and, in the inspector, offer the number the driven agent's wiring implies -- measured from the run that failed, where one tool call costs one iteration and a Script costs several (run it, then write throwaway Python to read the JSON it left on disk).
Motoro reports a Reason+Act run that exhausts max_iterations as `completed`, keeping whatever the last Act returned as its output. Two things downstream then lie: the node run shows a green "Done", and a wired Output Parser handed a tool dump instead of a written answer produces a payload whose every field is null -- rendered as a tidy list of results whose answer happens to be "null". Read the truncation off agent_runs.pattern_overrides, which the ReasonAct pattern already persists (reason_act_state.max_iterations_hit); the step rows cannot answer it, since the stored Act step carries the pre-hook should_continue and is false on every run. Carry it as a `truncation` flag on the completed node run rather than a new status: ~20 sites read that vocabulary to mean "did this node produce usable output", and for a truncated run the answer is still yes. The badge goes amber, and the output panel says what happened and which number to raise. Separately, flag an all-null payload with a caveat. The extractor types every contracted field `T | None` and may not infer, so "found nothing" and "the answer genuinely had none of these" are the same object; one null among real values is a real partial reading and stays silent.
The wiring-derived `max_iterations` suggestion only existed inside the Reason + Act inspector, where you had to already be looking at the field to see it. It now drives the node's own warning triangle and the pre-run "run anyway?" scan, so an undersized cap is visible on the canvas and interrupts a Run before it burns tokens on a loop that will be cut off. The suggestion moves to a single `suggestedIterationsByPattern` memo on the canvas so the node card and the inspector can't disagree about the number. A replicate whose agent hit the ceiling no longer counts as scored: the metrics it produced are real measurements of an unfinished run, and letting them project would make a cell read "3/3 scored" when all three agents stopped mid-work. "Scored" is `metric_values` being set, so withholding the projection excludes it from the cell accents, the design-history counts and the factorial analysis at once. The numbers survive on the attempt and in `artifacts["measurement"]`, and `artifacts["truncation"]` is what lets a "completed but unscored" replicate explain itself in the Runs tab.
Node progress listed one row per node in the graph keyed by node id, and only the agents had a name to fall back on -- so a dataset, an output parser or a script showed a bare uuid that matches nothing the user can point at on the canvas. lib/nodeNames.ts is the shared answer: a node's own label when the user set one, otherwise the placeholder its card already shows for that type, with same-named nodes numbered in canvas order so three unlabelled Scripts don't read as three identical rows.
The agent node already badges "Hit iteration limit" after a truncated run, but the number that caused it is configured on the Reason + Act node driving that agent, which showed nothing -- so the finding pointed at a node with no fix on it. The truncation now crosses that edge and raises the pattern node's own warning triangle. Deliberately not a findNodeConfigIssues entry: that scan is static pre-flight state, and a past run's outcome would keep blocking the pre-run dialog after the cap was already raised, until the next run happened to replace it. The card warning clears as soon as the cap is above what died. An observed truncation also outranks the wiring heuristic when suggesting a number -- a run that died at 40 is the loop itself saying 40 was short, where suggestedMaxIterations is only guessing from what's connected.
A Test Run reports itself only through its own results panel -- it never seeds runQuery, since list_protocol_runs excludes test runs -- so the pattern node's new warning could only ever come from a production run. That is backwards for the one finding it carries: a Test Run is how you iterate on the canvas, so a cap that truncated one has to reach the node you would fix. The node badges keep reading runQuery alone (that is the run the canvas is watching); only the truncation finding takes whichever run is newer, so raising the cap and running for real clears what a Test Run left behind.
Every Run button routes through RunConfirmDialog, which is the last point where raising the cap is cheaper than paying for the run -- and the most expensive case, "Run all cells", is exactly the one that repeats a truncation across every replicate. The canvas can name the node: findNodeConfigIssues takes the caps its agents actually died at and reports them in place of the wiring estimate, evidence instead of a guess. A run outcome is admissible in that static scan only because it is gated on the cap still being at or below what failed -- raise it and the finding is gone, without waiting for another run to prove it. The Runs tab's dialogs have the stored graph and a trial list but no run, so they can't tell which node's cap did it; they report the same thing per replicate instead, in the same amber the node badge and the Runs tab badges already use.
jay-m-dev
force-pushed
the
fix/docker-version-badge
branch
from
September 22, 2026 20:25
1e1a860 to
549c991
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces improvements to how Reason+Act agent iteration limits are handled and communicated in both the backend Docker build process and the frontend UI. The main goals are to ensure the reported app version is accurate, prevent accidental "dirty" builds, and provide better feedback and suggestions to users when an agent run is truncated due to hitting its iteration cap. The UI now offers actionable hints and clearer messaging around iteration limits, and the Docker build process avoids freezing version information.
Docker build process improvements:
.dockerignore: Addedsrc/asaree/_version.pyto prevent copying a stale, build-generated version file into the image, which could otherwise freeze the reported app version.Dockerfile: Updated build steps to mark all missing files as "assume-unchanged" in the mounted git index, preventing "dirty" version tags due to partial checkouts and ensuring accurate version reporting in both application and test images. [1] [2]Frontend: Reason+Act node iteration cap feedback:
frontend/src/components/protocol/NodeRunOutputPanel.tsx: Added aTruncationNotecomponent to inform users when an agent was stopped by its iteration limit, explaining the implications and how to fix it. Also updated badge logic to reflect truncation status. [1] [2] [3]Frontend: Iteration cap suggestions and wiring analysis:
frontend/src/components/protocol/ProtocolCanvas.tsx:Frontend: Inspector actionable hints:
frontend/src/components/protocol/ReasonActPatternNodeInspector.tsx: