Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ an obligation to satisfy Stride v2. Replans retain their existing v2 contract.
An absent attachment preserves the current decision; an explicit `proxy: null`
chooses direct evaluation while historical profiles remain readable.

A current decision can reuse explicitly cited measurements from earlier
findings by the same agent on the linked question. Each profile keeps its own
input and evaluator revisions, and cross-profile comparison still requires the
same candidate pair. Findings with their own Yardstick decision retain their
original work and target scope.

### 5.3 Co-discovery: invest in a pair

The model compares the incumbent pair, direct evaluation and a small relevant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ M1 在既有 `explore_result_attachment_v0` 中添加可选 `work_yardstick_deci
replan 沿用既有 v2 契约。省略附件保留当前决策;显式 `proxy: null` 选择直接评测,
历史 profile 仍可读取。

当前决策可以复用同一 Agent 在关联问题中已记录、且本次明确引用的测量。
各 profile 保留自己的输入和 evaluator 版本,跨 profile 比较仍须对应同一候选对。
已附带 Yardstick 决策的 finding 继续遵循原工作与目标范围。

### 5.3 Co-discovery:投资于组合

模型比较当前组合、直接评测及少量相关替代方案,需要时才扩读有来源绑定的细节。它考虑:
Expand Down
4 changes: 2 additions & 2 deletions loopx/control_plane/capabilities/explore_measurements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function comparisonKey(node: string, metric: ExploreMeasurement): string {
*/
export function projectExploreMeasurementFeedback(
findings: readonly JsonObject[],
candidateRefs?: ReadonlySet<string>,
includeMeasurement?: (finding: JsonObject, measurement: ExploreMeasurement) => boolean,
): ExploreMeasurementFeedback[] {
const groups = new Map<string, ExploreMeasurementFeedback>();
const ordered = findings.filter(finding => finding.measurements !== undefined);
Expand All @@ -127,7 +127,7 @@ export function projectExploreMeasurementFeedback(
// source when its declared execution contradicts its measurements.
if (executionMeasurementError(measurements, finding.execution_observation) !== null) continue;
for (const measurement of measurements) {
if (candidateRefs && !candidateRefs.has(measurement.candidate_ref)) continue;
if (includeMeasurement && !includeMeasurement(finding, measurement)) continue;
const key = comparisonKey(node, measurement), prior = groups.get(key);
const previous = prior?.best ?? null;
const point = measurement.value === null ? null : {finding_id: id,
Expand Down
38 changes: 28 additions & 10 deletions loopx/control_plane/work_items/yardstick_decision.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,24 @@ function matchesProfile(row: ExploreMeasurementFeedback, profile: WorkYardstickP
return Object.entries(profile).every(([key, value]) => row[key as keyof WorkYardstickProfile] === value);
}

function measuredSearchComparison(scopedFindings: readonly JsonObject[], decision: WorkYardstickDecision) {
const pairFor = (profile: WorkYardstickProfile, candidates?: ReadonlySet<string>) =>
measuredPair(projectExploreMeasurementFeedback(scopedFindings, candidates).find(row => matchesProfile(row, profile)));
function measuredSearchComparison(
scopedFindings: readonly JsonObject[],
decision: WorkYardstickDecision,
cited: ReadonlySet<string>,
) {
const pairFor = (profile: WorkYardstickProfile, candidates?: ReadonlySet<string>) => {
const feedback = projectExploreMeasurementFeedback(scopedFindings, (row, measurement) =>
(row.work_yardstick !== undefined || cited.has(measurement.evidence_ref))
&& (!candidates || candidates.has(measurement.candidate_ref)));
return measuredPair(feedback.find(row => matchesProfile(row, profile)));
};
const goal = pairFor(decision.authoritative);
if (!goal) return null;
// Both comparisons have two distinct candidates. Scope the proxy lookup to
// the two goal candidates so a rejected sibling proxy false-positive or a
// later proxy-only screening row cannot displace their paired comparison.
const goalCandidates = new Set([goal.previous_best.candidate_ref, goal.latest.candidate_ref]);
const screen = decision.proxy && pairFor(decision.proxy, goalCandidates);
const proxy = screen && goalCandidates.has(screen.previous_best.candidate_ref)
&& goalCandidates.has(screen.latest.candidate_ref) ? screen : null;
const proxy = decision.proxy && pairFor(decision.proxy, goalCandidates);
const reversed = !!(goal.preferred_candidate_ref && proxy?.preferred_candidate_ref
&& goal.preferred_candidate_ref !== proxy.preferred_candidate_ref);
const opening = goal.preferred_candidate_ref === null
Expand Down Expand Up @@ -176,13 +182,25 @@ export function projectWorkYardstickCue(params: JsonObject): JsonObject | null {
row.node_id === source.node_id && profiles.some(p => matchesProfile(row, p)));
// An earlier target can share the same evaluator profile and work identity.
// Filter source findings before ranking so its best cannot displace a legal pair.
const cited = new Set(counter);
const sourceOrder = source.recorded_order;
const scopedFindings = findings.filter(row => {
if (row.node_id !== source.node_id) return false;
// A decision can cite the agent's earlier measurements on this linked
// question without changing their provenance or assigning earlier work.
if (row.work_yardstick === undefined) {
const order = row.recorded_order;
// A repeated reference appended later cannot change the decision's evidence.
return cited.size > 0 && typeof sourceOrder === "number" && Number.isSafeInteger(sourceOrder)
&& typeof order === "number" && Number.isSafeInteger(order) && order >= 0 && order < sourceOrder
&& row.agent_id === capture.binding.agent_id && Array.isArray(row.evidence_refs)
&& row.evidence_refs.some(ref => typeof ref === "string" && cited.has(ref));
}
const target = (row.work_yardstick as WorkYardstickCapture | undefined)?.decision?.target;
return row.node_id === source.node_id && belongsToWork(row, params) && target !== undefined
&& target.summary === decision.target.summary && target.scope === decision.target.scope
&& target.acceptance_ref === decision.target.acceptance_ref;
return belongsToWork(row, params) && target !== undefined && target.summary === decision.target.summary
&& target.scope === decision.target.scope && target.acceptance_ref === decision.target.acceptance_ref;
});
const searchComparison = measuredSearchComparison(scopedFindings, decision);
const searchComparison = measuredSearchComparison(scopedFindings, decision, cited);
return {source_finding_id: source.finding_id, node_id: source.node_id, binding: capture.binding, ...decision,
measurement_feedback: feedback,
...(searchComparison ? {search_comparison: searchComparison} : {}),
Expand Down
51 changes: 51 additions & 0 deletions tests/control_plane/test_work_yardstick_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,57 @@ def dictionary_encode(items):
assert "work_yardsticks" not in disabled and disabled["measurement_feedback"] == before


@pytest.mark.parametrize("provider", ["file", "sqlite"])
def test_later_plain_measurement_cannot_replace_cited_decision_evidence(tmp_path, provider, monkeypatch):
project, runtime, path = setup(tmp_path, active=True, provider=provider, write_scope=wide_write_scope())
refs = ["result:preview-a", "result:preview-b"]
plain = attachment()
chosen = plain.pop("work_yardstick_decision")
plain["evidence_refs"] = refs
plain["measurements"] = [
{**chosen["proxy"], "candidate_ref": f"candidate:{candidate}",
"evidence_ref": ref, "value": value}
for candidate, ref, value in zip(("a", "b"), refs, (8, 6))
]

def retain(turn_id, payload):
evidence = tmp_path / f"{turn_id}.json"
evidence.write_text(json.dumps(payload))
receipt = refresh(project, runtime, path, turn_id, evidence, "--delivery-boundary", "in_flight_continuation")
result = receipt["explore_result_delivery"]
assert result["ok"]
run(project, runtime, path, *_projected_cli_args(receipt["settlement_owed"]["command"],
turn_instance_id=turn_id))
return result

first = retain("previous-proxy", plain)
selected = attachment()
selected.update(node_id=first["node_id"], evidence_refs=[*refs, "result:outcome-a", "result:outcome-b"])
selected["work_yardstick_decision"]["counterevidence_refs"] = refs
selected["measurements"] = [
{**chosen["authoritative"], "candidate_ref": f"candidate:{candidate}",
"evidence_ref": f"result:outcome-{candidate}", "value": value}
for candidate, value in (("a", 20), ("b", 14))
]
result = retain("current-decision", selected)
before = context(runtime, path)["graph"]["work_yardsticks"][0]
assert before["search_comparison"]["proxy_order_reversed"] is False

late = {**plain, "node_id": first["node_id"], "evidence_refs": refs[1:],
"measurements": [{**plain["measurements"][1], "value": 99}]}
retain("later-duplicate-reference", late)
after = context(runtime, path)["graph"]["work_yardsticks"][0]
assert after["source_finding_id"] == result["finding_id"]
assert after["search_comparison"] == before["search_comparison"]
turn = binding("inspect-original-citation")
capture = tmp_path / "capture"
run(project, runtime, path, "quota", "should-run", "--codex-app", *turn,
"--decision-output-dir", str(capture), "--context-delivery", "on", "--delta-delivery", "off")
page = starting_page(project, runtime, path, turn, capture / "decision.json", monkeypatch)
assert "proxy reverses the observed goal order" not in page["content"]
assert "candidate:a" in page["content"]


def test_sqlite_current_work_to_ordinary_turn_to_concrete_action_and_readback(tmp_path):
project, runtime, path = setup(tmp_path)
source = tmp_path / "capture.json"
Expand Down
45 changes: 45 additions & 0 deletions tests/control_plane_ts/yardstick_decision.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,51 @@ test("goal and proxy join the same two candidates regardless of declared order a
}
});

test("a current decision can reuse explicitly cited measurements written before its separate outcome", () => {
const preview = {...proxy, input_revision: "preview-inputs-v2"};
const cited = ["result:preview-a", "result:preview-b", "result:preview-sibling"];
const declared = {...decision, proxy: preview, counterevidence_refs: cited};
const source = {...finding, recorded_order: 2, work_yardstick: {decision: declared, binding},
evidence_refs: [...cited, "result:goal-a", "result:goal-b"], measurements: [
{...authoritative, value: 20, candidate_ref: "candidate:a", evidence_ref: "result:goal-a"},
{...authoritative, value: 14, candidate_ref: "candidate:b", evidence_ref: "result:goal-b"},
]};
const recorded = {finding_id: "recorded-preview", node_id: source.node_id, agent_id: binding.agent_id,
recorded_order: 1, last_updated_at: "2026-01-01T00:00:00Z",
evidence_refs: [...cited, "result:preview-uncited"], measurements: [
{...preview, value: 6, candidate_ref: "candidate:a", evidence_ref: cited[0]!},
{...preview, value: 8, candidate_ref: "candidate:b", evidence_ref: cited[1]!},
{...preview, value: 98, candidate_ref: "candidate:sibling", evidence_ref: cited[2]!},
{...preview, value: 99, candidate_ref: "candidate:uncited", evidence_ref: "result:preview-uncited"},
]};
const project = (row = recorded, current = source) => projectWorkYardstickCue({...binding, enabled: true,
findings: [current, row], measurement_feedback: projectExploreMeasurementFeedback([current, row])})!.search_comparison;
const comparison = project();
assert.equal(comparison.goal.preferred_candidate_ref, "candidate:a");
assert.equal(comparison.proxy?.preferred_candidate_ref, "candidate:b");
assert.equal(comparison.proxy_order_reversed, true);

assert.equal(project({...recorded, agent_id: "peer"}).proxy, undefined);
assert.equal(project({...recorded, node_id: "different-question"}).proxy, undefined);
const differentInputs = recorded.measurements.map(row => ({...row, input_revision: "different-preview-inputs"}));
assert.equal(project({...recorded, measurements: differentInputs}).proxy, undefined);
const partial = {...source, work_yardstick: {binding, decision: {...declared, counterevidence_refs: [cited[0]!]}}};
assert.equal(project(recorded, partial).proxy, undefined);
const differentTarget = {...recorded, work_yardstick: {binding, decision: {...declared,
target: {...declared.target, acceptance_ref: "acceptance:another-target"}}}};
assert.equal(project(differentTarget).proxy, undefined);

const later = {...recorded, finding_id: "later-preview", recorded_order: 3,
// Claimed observation time is older. Only recorded order binds the citation.
last_updated_at: "2025-12-31T23:59:59Z", evidence_refs: [cited[1]!],
measurements: [{...recorded.measurements[1]!, value: 1}]};
const after = projectWorkYardstickCue({...binding, enabled: true, findings: [source, later, recorded]})!;
assert.deepEqual(after.search_comparison, comparison);
const unknown = projectWorkYardstickCue({...binding, enabled: true,
findings: [source, {...recorded, recorded_order: undefined}]})!;
assert.equal(unknown.search_comparison.proxy, undefined);
});

test("only strictly older committed replay preserves a stale predecessor as history", () => {
const params = {enabled: true, decision, binding, findings: [finding]};
assert.deepEqual(validateWorkYardstickContinuation({...params,
Expand Down
Loading