Remove unconditional stateful-turn truncation
This commit is contained in:
@@ -219,11 +219,12 @@ Training use is tracked separately as `SFT_FULL`, `SFT_STEP_ONLY`,
|
|||||||
score.
|
score.
|
||||||
|
|
||||||
For a complete trajectory, the quality call also sees its final model patch. A
|
For a complete trajectory, the quality call also sees its final model patch. A
|
||||||
truncated prefix never receives that suffix-derived patch. Every non-success
|
truncated prefix never receives that suffix-derived patch. State-changing turns
|
||||||
trajectory (`resolved=0` or `-1`) is capped before its first statically detected
|
are recorded as audit telemetry but are not automatic boundaries: writing code
|
||||||
state-changing assistant turn. The effective boundary is the earlier of this
|
is not itself an error, and recovered experiments are useful process data. The
|
||||||
local cap and the GLM boundary. This intentionally prefers a shorter, safer
|
effective boundary is the earliest unrecovered major or critical behavior found
|
||||||
investigation trace.
|
by the boundary stage. The isolated quality stage rejects a retained prefix that
|
||||||
|
still contains an unrecovered severe problem.
|
||||||
|
|
||||||
Successful trajectories skip boundary selection and are scored as complete
|
Successful trajectories skip boundary selection and are scored as complete
|
||||||
trajectories. The command remains simple:
|
trajectories. The command remains simple:
|
||||||
|
|||||||
@@ -4,6 +4,19 @@ This file records strategy changes that materially affect dataset decisions or
|
|||||||
training-data semantics. Generated audit manifests are not treated as stable API
|
training-data semantics. Generated audit manifests are not treated as stable API
|
||||||
contracts.
|
contracts.
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Strategy correction
|
||||||
|
|
||||||
|
- Removed the unconditional cutoff before the first state-changing turn for
|
||||||
|
failed and unverified trajectories. A write or edit is not evidence of an
|
||||||
|
error by itself, and this cap discarded normal implementation, recovery, and
|
||||||
|
verification work.
|
||||||
|
- The semantic boundary now remains the earliest unrecovered major or critical
|
||||||
|
assistant behavior selected by the boundary stage. The isolated prefix-quality
|
||||||
|
stage remains the safety gate. The first stateful turn is retained as telemetry
|
||||||
|
for paired evaluation against the former policy.
|
||||||
|
|
||||||
## 2.0.0 - 2026-08-07
|
## 2.0.0 - 2026-08-07
|
||||||
|
|
||||||
### Strategy
|
### Strategy
|
||||||
|
|||||||
@@ -72,30 +72,23 @@ def materialize_prefix(
|
|||||||
def effective_boundary_policy(
|
def effective_boundary_policy(
|
||||||
record: dict[str, Any], model_result: dict[str, Any]
|
record: dict[str, Any], model_result: dict[str, Any]
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Choose a conservative effective boundary for one trajectory.
|
"""Use the semantic boundary while retaining the old cap as telemetry.
|
||||||
|
|
||||||
A failed or unverified record may not retain a statically detected
|
A state-changing turn is not evidence of an error by itself. Normal coding,
|
||||||
state-changing assistant turn. This deliberately favors a shorter
|
failed experiments, recovery, and verification are useful process data, so
|
||||||
investigation prefix over a late semantic boundary that could retain a bad
|
the first stateful turn must not become an unconditional cutoff. Prefix
|
||||||
implementation.
|
safety is enforced independently by the isolated quality stage.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
model_boundary = model_result["truncate_before_turn"]
|
model_boundary = model_result["truncate_before_turn"]
|
||||||
first_stateful = min(
|
first_stateful = min(
|
||||||
extract_static_signals(record)["stateful_turns"], default=None
|
extract_static_signals(record)["stateful_turns"], default=None
|
||||||
)
|
)
|
||||||
candidates = []
|
|
||||||
if model_result["decision"] == "TRUNCATE":
|
if model_result["decision"] == "TRUNCATE":
|
||||||
candidates.append((model_boundary, "MODEL_BOUNDARY"))
|
|
||||||
if int(record.get("resolved", -1)) != 1 and first_stateful is not None:
|
|
||||||
candidates.append((first_stateful, "NON_SUCCESS_FIRST_STATEFUL_CAP"))
|
|
||||||
|
|
||||||
if candidates:
|
|
||||||
boundary, source = min(candidates, key=lambda item: item[0])
|
|
||||||
return {
|
return {
|
||||||
"decision": "TRUNCATE",
|
"decision": "TRUNCATE",
|
||||||
"truncate_before_turn": boundary,
|
"truncate_before_turn": model_boundary,
|
||||||
"source": source,
|
"source": "MODEL_BOUNDARY",
|
||||||
"model_truncate_before_turn": model_boundary,
|
"model_truncate_before_turn": model_boundary,
|
||||||
"first_stateful_turn": first_stateful,
|
"first_stateful_turn": first_stateful,
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-3
@@ -140,7 +140,7 @@ def test_unrecovered_major_issue_is_locally_invalid() -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("resolved", [0, -1])
|
@pytest.mark.parametrize("resolved", [0, -1])
|
||||||
def test_non_success_outcome_is_capped_before_first_stateful_turn(resolved: int) -> None:
|
def test_non_success_outcome_is_not_capped_at_first_stateful_turn(resolved: int) -> None:
|
||||||
record = _record()
|
record = _record()
|
||||||
record["resolved"] = resolved
|
record["resolved"] = resolved
|
||||||
record["tools"] = [
|
record["tools"] = [
|
||||||
@@ -159,9 +159,34 @@ def test_non_success_outcome_is_capped_before_first_stateful_turn(resolved: int)
|
|||||||
result = _boundary()
|
result = _boundary()
|
||||||
result.update(decision="KEEP_FULL", truncate_before_turn=None)
|
result.update(decision="KEEP_FULL", truncate_before_turn=None)
|
||||||
policy = effective_boundary_policy(record, result)
|
policy = effective_boundary_policy(record, result)
|
||||||
|
assert policy["decision"] == "KEEP_FULL"
|
||||||
|
assert policy["truncate_before_turn"] is None
|
||||||
|
assert policy["source"] == "MODEL_DECISION"
|
||||||
|
assert policy["first_stateful_turn"] == 3
|
||||||
|
|
||||||
|
|
||||||
|
def test_semantic_boundary_is_not_replaced_by_earlier_stateful_turn() -> None:
|
||||||
|
record = _record()
|
||||||
|
record["resolved"] = 0
|
||||||
|
record["tools"] = [
|
||||||
|
{"type": "function", "function": {"name": "str_replace_editor"}}
|
||||||
|
]
|
||||||
|
record["trajectory"][2]["tool_calls"] = [
|
||||||
|
{
|
||||||
|
"id": "call-1",
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "str_replace_editor",
|
||||||
|
"arguments": '{"command":"str_replace","path":"src/a.py"}',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]
|
||||||
|
result = _boundary()
|
||||||
|
policy = effective_boundary_policy(record, result)
|
||||||
assert policy["decision"] == "TRUNCATE"
|
assert policy["decision"] == "TRUNCATE"
|
||||||
assert policy["truncate_before_turn"] == 3
|
assert policy["truncate_before_turn"] == 5
|
||||||
assert policy["source"] == "NON_SUCCESS_FIRST_STATEFUL_CAP"
|
assert policy["source"] == "MODEL_BOUNDARY"
|
||||||
|
assert policy["first_stateful_turn"] == 3
|
||||||
|
|
||||||
|
|
||||||
def test_boundary_payload_hides_outcome_and_patch_metadata() -> None:
|
def test_boundary_payload_hides_outcome_and_patch_metadata() -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user