mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-26 13:16:24 +00:00
fix(subagents): scope Go zero-test summaries to individual packages (#6492)
* fix(subagents): scope Go zero-test summaries to packages * docs(subagents): fold Go zero-test guidance into checklist
This commit is contained in:
parent
16b4fcd968
commit
a02bfe2968
@ -1877,6 +1877,8 @@ The lead agent can spawn sub-agents on the fly — each with its own scoped cont
|
||||
|
||||
Cancelled or timed-out background sub-agent executions retain provider-reported token usage from completed model calls, including responses received before their next progress update. Final usage delivery to the parent run does not count earlier progress snapshots twice.
|
||||
|
||||
For `tests_passed:go test ./...`, packages marked `[no test files]` or `[no tests to run]` do not veto a passing summary from another package. Runs with only zero-test package summaries remain `UNVERIFIED`; failures still take precedence. This checks recorded execution evidence, not claim correctness.
|
||||
|
||||
For file acceptance criteria, an empty regular file in the shared workspace can satisfy `file:<path> exists` and `file_written:<path>`, including on remote sandboxes. It fails `file:<path> non-empty` with a deterministic empty-file result.
|
||||
|
||||
To request JSON syntax validation, explicitly set a `task` or `batch_task` item's
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -121,6 +121,8 @@ _TEST_PASS_SHAPE_RE = re.compile(
|
||||
#: cannot see: "0 passed", go's no-test markers, unittest "Ran 0 tests".
|
||||
_TEST_ZERO_SHAPE_RE = re.compile(r"\b0\s+passed\b|\[no test files\]|\[no tests to run\]|\bRan 0 tests\b", re.IGNORECASE)
|
||||
|
||||
_GO_ZERO_TEST_LINE_RE = re.compile(r"^(?:ok|\?)[ \t]+\S+[^\r\n]*\[(?:no test files|no tests to run)\][ \t]*\r?$", re.MULTILINE)
|
||||
|
||||
_TEST_FAIL_SHAPE_RE = re.compile(
|
||||
r"\b[1-9]\d*\s+failed\b" # pytest / jest: "1 failed"
|
||||
r"|\b[1-9]\d*\s+errors?\b" # pytest: "1 error" — an errored collection means part of the selection never ran
|
||||
@ -1826,7 +1828,9 @@ def _check_tests_passed_leaf(command: str, bash_executions: list[dict[str, Any]]
|
||||
base["checked"] = True
|
||||
base["detail"] = "recorded output carries a failing test summary"
|
||||
return base
|
||||
if _TEST_PASS_SHAPE_RE.search(output_tail) and not _TEST_ZERO_SHAPE_RE.search(output_tail):
|
||||
# Go zero-test markers describe one package; exclude the whole line from pass evidence.
|
||||
summary_tail = _GO_ZERO_TEST_LINE_RE.sub("", output_tail)
|
||||
if _TEST_PASS_SHAPE_RE.search(summary_tail) and not _TEST_ZERO_SHAPE_RE.search(summary_tail):
|
||||
base["checked"] = True
|
||||
base["holds"] = True
|
||||
base["detail"] = "recorded output carries a passing test summary"
|
||||
|
||||
@ -2281,6 +2281,60 @@ class TestTestsPassedLeaf:
|
||||
assert leaf["holds"] is False, output
|
||||
assert leaf["checked"] is False, output
|
||||
|
||||
@pytest.mark.parametrize("passed", ["ok example/a 0.01s", "ok\texample/a\t(cached)"])
|
||||
@pytest.mark.parametrize("empty", ["? example/b [no test files]", "ok example/b 0.01s [no tests to run]"])
|
||||
@pytest.mark.parametrize("reverse", [False, True])
|
||||
def test_go_package_without_tests_does_not_veto_tested_package(self, passed, empty, reverse):
|
||||
lines = [passed, empty]
|
||||
if reverse:
|
||||
lines.reverse()
|
||||
verdict = check_acceptance_criteria(
|
||||
["tests_passed:go test ./..."],
|
||||
bash_executions=[_bash_execution("go test ./...", output_tail="\r\n".join(lines))],
|
||||
)
|
||||
assert verdict["leaves"][0]["checked"] is True
|
||||
assert verdict["leaves"][0]["holds"] is True
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"output",
|
||||
[
|
||||
"? example/a [no test files]\n? example/b [no test files]",
|
||||
"ok example/a 0.01s [no tests to run]\n? example/b [no test files]",
|
||||
"ok example/a (cached) [no tests to run]",
|
||||
"? example/b [no test files]",
|
||||
"ok example/a 0.01s\n0 passed",
|
||||
"ok example/a 0.01s\nRan 0 tests\nOK",
|
||||
"ok example/a 0.01s\n[no tests to run]",
|
||||
],
|
||||
)
|
||||
def test_go_zero_tests_still_need_positive_evidence(self, output):
|
||||
verdict = check_acceptance_criteria(["tests_passed:go test ./..."], bash_executions=[_bash_execution("go test ./...", output_tail=output)])
|
||||
assert verdict["leaves"][0]["checked"] is False
|
||||
assert verdict["leaves"][0]["holds"] is False
|
||||
|
||||
@pytest.mark.parametrize("failure", ["FAIL example/c 0.01s", "FAIL example/c [no test files]", "1 failed"])
|
||||
def test_go_mixed_package_failure_wins(self, failure):
|
||||
output = "ok example/a 0.01s\n? example/b [no test files]\n" + failure
|
||||
verdict = check_acceptance_criteria(["tests_passed:go test ./..."], bash_executions=[_bash_execution("go test ./...", output_tail=output)])
|
||||
assert verdict["leaves"][0]["checked"] is True
|
||||
assert verdict["leaves"][0]["holds"] is False
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"command,status,shell_persistent",
|
||||
[
|
||||
("go test ./...", "error", False),
|
||||
("go test ./...", "success", True),
|
||||
("go test ./...", "success", None),
|
||||
("go test ./other", "success", False),
|
||||
("echo 'ok example/a 0.01s'; go test ./...", "success", False),
|
||||
("go test ./... > result.log", "success", False),
|
||||
],
|
||||
)
|
||||
def test_go_mixed_packages_preserve_evidence_boundaries(self, command, status, shell_persistent):
|
||||
execution = _bash_execution(command, status=status, shell_persistent=shell_persistent, output_tail="ok example/a 0.01s\n? example/b [no test files]")
|
||||
verdict = check_acceptance_criteria(["tests_passed:go test ./..."], bash_executions=[execution])
|
||||
assert verdict["leaves"][0]["holds"] is False
|
||||
|
||||
def test_negated_option_value_is_not_execution_evidence(self):
|
||||
"""PR review: ``pytest --ignore tests/security tests`` never ran the
|
||||
security tests — the criterion must not match the negated token."""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user