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:
ZJPex 2026-10-08 19:55:26 +08:00 committed by GitHub
parent 16b4fcd968
commit a02bfe2968
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 63 additions and 2 deletions

View File

@ -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

View File

@ -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"

View File

@ -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."""