From f89c034be6890a476a3504e4283862fe15cb664b Mon Sep 17 00:00:00 2001 From: Luke Maj Date: Wed, 14 Oct 2026 14:42:09 +0200 Subject: [PATCH 1/4] Accept a delegated negative only after one failed challenge (#226) A result that says the work cannot be done must list attempts and primary sources. The coordinator tries once, or assigns one challenger, before that result reaches the user or an Issue. --- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- .grok-plugin/plugin.json | 2 +- CHANGELOG.md | 6 + VERSION | 2 +- evals/negative-result-gate.json | 104 ++++++++++++++++++ .../references/bounded-delegation.md | 8 ++ skills/operations/references/orchestration.md | 8 +- tests/test_negative_result_gate.py | 82 ++++++++++++++ tools/versionctl/pyproject.toml | 2 +- 10 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 evals/negative-result-gate.json create mode 100644 tests/test_negative_result_gate.py diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index f1f51792..f8d99cfc 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agentsmd", - "version": "17.1.1", + "version": "17.2.0", "description": "Portable agent rules, Project Direction, Delivery System profiles, owned workflow Skills, and deterministic version control.", "author": { "name": "lukaszmaj" diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 5e420f5f..36aef2c3 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agentsmd", - "version": "17.1.1", + "version": "17.2.0", "description": "Portable agent rules, Project Direction, Delivery System profiles, owned workflow Skills, and deterministic version control.", "author": { "name": "lukaszmaj", diff --git a/.grok-plugin/plugin.json b/.grok-plugin/plugin.json index 7ee9d1b0..9368fcd4 100644 --- a/.grok-plugin/plugin.json +++ b/.grok-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agentsmd", - "version": "17.1.1", + "version": "17.2.0", "description": "Portable agent rules, Project Direction, Delivery System profiles, owned workflow Skills, and deterministic version control.", "author": { "name": "lukaszmaj" diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a24f10b..b3164f3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ All completed repository versions are recorded here. Release entries follow SemVer and identify one user-consumable repository state. +## [17.2.0] - 2026-10-14 + +### Added + +- A delegated negative result reaches the user or an Issue only after it lists attempts and primary sources and one challenge fails to make the work succeed (#226) + ## [17.1.1] - 2026-10-13 ### Changed diff --git a/VERSION b/VERSION index 6f9c209b..290a3f36 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -17.1.1 +17.2.0 diff --git a/evals/negative-result-gate.json b/evals/negative-result-gate.json new file mode 100644 index 00000000..13156f1b --- /dev/null +++ b/evals/negative-result-gate.json @@ -0,0 +1,104 @@ +{ + "fixture_kind": "negative-result-gate", + "issue": "https://github.com/toolboxmd/agentsmd/issues/226", + "incident_date": "2026-10-14", + "primary_sources": ["docs", "readme", "help", "env", "config"], + "cases": [ + { + "id": "grok-cannot-strip-relayed", + "incident": true, + "summary": "A worker said Grok cannot be stripped of global rules and skills. The report listed no attempts and no primary sources. Nobody tried to make removal work. The planner relayed the negative to the user.", + "polarity": "negative", + "attempts_listed": false, + "primary_sources": [], + "coordinator_tried": false, + "challenger_assigned": false, + "attempt_failed": false, + "reaches_user_or_issue": false + }, + { + "id": "opencode-no-recipe-filed", + "incident": true, + "summary": "A worker said OpenCode had no verified subscription recipe. The report listed no attempts and no primary sources. Nobody tried to make a recipe work. The planner filed a to-do from that negative.", + "polarity": "negative", + "attempts_listed": false, + "primary_sources": [], + "coordinator_tried": false, + "challenger_assigned": false, + "attempt_failed": false, + "reaches_user_or_issue": false + }, + { + "id": "grok-disproved-by-own-readme", + "incident": true, + "summary": "The same Grok negative was checked against the tool's own README and environment. GROK_HOME plus an empty HOME removed the user instructions. The negative did not survive.", + "polarity": "negative", + "attempts_listed": true, + "primary_sources": ["docs", "readme", "help", "env", "config"], + "coordinator_tried": true, + "challenger_assigned": false, + "attempt_failed": false, + "reaches_user_or_issue": false + }, + { + "id": "opencode-disproved-by-auth-list", + "incident": true, + "summary": "The same OpenCode negative was checked against the live credential store. OpenCode already held an OpenCode Go credential. The negative did not survive.", + "polarity": "negative", + "attempts_listed": true, + "primary_sources": ["docs", "readme", "help", "env", "config"], + "coordinator_tried": true, + "challenger_assigned": false, + "attempt_failed": false, + "reaches_user_or_issue": false + }, + { + "id": "listed-sources-without-a-challenge", + "incident": false, + "summary": "The report lists attempts and every primary source class, and still says the work cannot be done. Neither the coordinator nor a challenger has tried to make it work.", + "polarity": "negative", + "attempts_listed": true, + "primary_sources": ["docs", "readme", "help", "env", "config"], + "coordinator_tried": false, + "challenger_assigned": false, + "attempt_failed": false, + "reaches_user_or_issue": false + }, + { + "id": "missing-config-keys", + "incident": false, + "summary": "Attempts are listed and a challenger failed, but config keys were never checked.", + "polarity": "negative", + "attempts_listed": true, + "primary_sources": ["docs", "readme", "help", "env"], + "coordinator_tried": false, + "challenger_assigned": true, + "attempt_failed": true, + "reaches_user_or_issue": false + }, + { + "id": "survives-coordinator-attempt", + "incident": false, + "summary": "Attempts and every primary source class are listed. The coordinator tried once to make the work succeed and it still failed.", + "polarity": "negative", + "attempts_listed": true, + "primary_sources": ["docs", "readme", "help", "env", "config"], + "coordinator_tried": true, + "challenger_assigned": false, + "attempt_failed": true, + "reaches_user_or_issue": true + }, + { + "id": "survives-one-challenger", + "incident": false, + "summary": "Attempts and every primary source class are listed. One challenger whose only job was to make the work succeed still failed.", + "polarity": "negative", + "attempts_listed": true, + "primary_sources": ["docs", "readme", "help", "env", "config", "man-page"], + "coordinator_tried": false, + "challenger_assigned": true, + "attempt_failed": true, + "reaches_user_or_issue": true + } + ] +} diff --git a/skills/operations/references/bounded-delegation.md b/skills/operations/references/bounded-delegation.md index e941ed5f..6cdb9ce0 100644 --- a/skills/operations/references/bounded-delegation.md +++ b/skills/operations/references/bounded-delegation.md @@ -37,6 +37,14 @@ at safe boundaries and before reporting. User stops, revoked authority, unsafe writes, and shared-state failures interrupt immediately. The host's existing message tools usually suffice; do not build a queue service by default. +A negative result says the work cannot be done: not possible, cannot remove, +blocked, no recipe, or failed. Accept it only when it lists what was tried and +which primary sources were checked: the tool's own docs and bundled README, its +`--help`, its environment variables, and its config keys. Before you relay that +result to the user or file anything from it, try the work once yourself or +assign one challenger whose only job is to make the work succeed. Report only a +negative result that survives that attempt, and include the attempts. + Integrate reviewed components as they become ready under the one-final-approval- PR contract. Preserve accepted outputs promptly in their authorized durable owner. A disposable worker's confident transcript is not durable delivery evidence. diff --git a/skills/operations/references/orchestration.md b/skills/operations/references/orchestration.md index d8d51c0c..7416393d 100644 --- a/skills/operations/references/orchestration.md +++ b/skills/operations/references/orchestration.md @@ -66,8 +66,12 @@ when sufficient. Include the unit's outcome, allowed and forbidden writes, shared-resource limits, acceptance, proof seam, known gotchas, report shape, and bounded escalation -condition. Do not dispatch unresolved ownership or acceptance. Do not dispatch -implementation of a new component or system until the brief cites a Spec Issue +condition. The report shape for a negative result (not possible, cannot remove, +blocked, no recipe, or failed) lists what was tried and which primary sources +were checked: the tool's own docs and bundled README, its `--help`, its +environment variables, and its config keys. Do not dispatch unresolved +ownership or acceptance. Do not dispatch implementation of a new component or +system until the brief cites a Spec Issue ([to-spec](../procedures/to-spec/index.md)) whose Design review names the reviewer, the verdict, and the user's decisions; acceptance criteria in a brief are not a design. A microfix or a change inside an existing component says so in diff --git a/tests/test_negative_result_gate.py b/tests/test_negative_result_gate.py new file mode 100644 index 00000000..2060b5c8 --- /dev/null +++ b/tests/test_negative_result_gate.py @@ -0,0 +1,82 @@ +"""Regression for accepting a delegated negative result (toolboxmd/agentsmd#226).""" + +from __future__ import annotations + +import json +from pathlib import Path +import unittest + +ROOT = Path(__file__).resolve().parents[1] +FIXTURE = ROOT / "evals" / "negative-result-gate.json" +DELEGATION = ROOT / "skills/operations/references/bounded-delegation.md" +ORCHESTRATION = ROOT / "skills/operations/references/orchestration.md" + + +def words(path: Path) -> str: + return " ".join(path.read_text(encoding="utf-8").split()) + + +def negative_may_reach_user_or_issue(case: dict, primary_sources: set[str]) -> bool: + """The acceptance gate. A negative reaches the user or an Issue only when it survives.""" + if case["polarity"] != "negative": + raise AssertionError("this gate does not grade positive findings") + listed = case["attempts_listed"] and primary_sources <= set(case["primary_sources"]) + challenged = case["coordinator_tried"] or case["challenger_assigned"] + return listed and challenged and case["attempt_failed"] + + +class NegativeResultGateTests(unittest.TestCase): + def setUp(self) -> None: + self.fixture = json.loads(FIXTURE.read_text(encoding="utf-8")) + + def test_incident_fixture_grades_every_case(self) -> None: + self.assertEqual(self.fixture["fixture_kind"], "negative-result-gate") + self.assertIn("226", self.fixture["issue"]) + primary = set(self.fixture["primary_sources"]) + self.assertEqual(primary, {"docs", "readme", "help", "env", "config"}) + cases = self.fixture["cases"] + self.assertEqual(len(cases), len({case["id"] for case in cases})) + incident = [case["id"] for case in cases if case["incident"]] + self.assertEqual( + incident, + [ + "grok-cannot-strip-relayed", + "opencode-no-recipe-filed", + "grok-disproved-by-own-readme", + "opencode-disproved-by-auth-list", + ], + ) + for case in cases: + with self.subTest(case=case["id"]): + self.assertEqual(case["polarity"], "negative") + self.assertEqual( + negative_may_reach_user_or_issue(case, primary), + case["reaches_user_or_issue"], + ) + + def test_delegation_reference_owns_the_acceptance_gate(self) -> None: + text = words(DELEGATION) + for clause in ( + "A negative result says the work cannot be done: not possible, cannot remove, blocked, no recipe, or failed.", + "Accept it only when it lists what was tried and which primary sources were checked: the tool's own docs and bundled README, its `--help`, its environment variables, and its config keys.", + "Before you relay that result to the user or file anything from it, try the work once yourself or assign one challenger whose only job is to make the work succeed.", + "Report only a negative result that survives that attempt, and include the attempts.", + "Validate at safe boundaries and before reporting.", + ): + with self.subTest(clause=clause): + self.assertIn(clause, text) + self.assertEqual(text.count("Validate at safe boundaries and before reporting."), 1) + self.assertNotIn("try harder", text.lower()) + + def test_worker_brief_requires_attempts_and_primary_sources(self) -> None: + text = words(ORCHESTRATION) + self.assertIn( + "The report shape for a negative result (not possible, cannot remove, blocked, no recipe, or failed) " + "lists what was tried and which primary sources were checked: the tool's own docs and bundled README, " + "its `--help`, its environment variables, and its config keys.", + text, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/versionctl/pyproject.toml b/tools/versionctl/pyproject.toml index 59765e99..12b16744 100644 --- a/tools/versionctl/pyproject.toml +++ b/tools/versionctl/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "toolboxmd-versionctl" -version = "17.1.1" +version = "17.2.0" description = "Deterministic repository version mechanics for coding agents" readme = "README.md" requires-python = ">=3.11" From caf7e158774650ad172be169fd358a6dcb344afc Mon Sep 17 00:00:00 2001 From: Luke Maj Date: Wed, 14 Oct 2026 14:55:25 +0200 Subject: [PATCH 2/4] Load the negative-result gate before relaying a result (#226) Accepting one delegated result never opened bounded-delegation. The acceptance path now requires that gate. An ordinary failed slice is still recorded at once. --- evals/negative-result-gate.json | 2 +- skills/operations/references/bounded-delegation.md | 10 ++++++---- skills/operations/references/orchestration.md | 4 +++- tests/test_negative_result_gate.py | 6 ++++++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/evals/negative-result-gate.json b/evals/negative-result-gate.json index 13156f1b..cd02401a 100644 --- a/evals/negative-result-gate.json +++ b/evals/negative-result-gate.json @@ -61,7 +61,7 @@ "primary_sources": ["docs", "readme", "help", "env", "config"], "coordinator_tried": false, "challenger_assigned": false, - "attempt_failed": false, + "attempt_failed": true, "reaches_user_or_issue": false }, { diff --git a/skills/operations/references/bounded-delegation.md b/skills/operations/references/bounded-delegation.md index 6cdb9ce0..faaa8d7e 100644 --- a/skills/operations/references/bounded-delegation.md +++ b/skills/operations/references/bounded-delegation.md @@ -38,10 +38,12 @@ writes, and shared-state failures interrupt immediately. The host's existing message tools usually suffice; do not build a queue service by default. A negative result says the work cannot be done: not possible, cannot remove, -blocked, no recipe, or failed. Accept it only when it lists what was tried and -which primary sources were checked: the tool's own docs and bundled README, its -`--help`, its environment variables, and its config keys. Before you relay that -result to the user or file anything from it, try the work once yourself or +blocked, no recipe, or failed. An ordinary failed slice, one that does not say +the work cannot be done, is still recorded at once. Accept it only when it +lists what was tried and which primary sources were checked: the tool's own docs +and bundled README, its `--help`, its environment variables, and its config +keys. Before you relay that result to the user or file anything from it, try +the work once yourself or assign one challenger whose only job is to make the work succeed. Report only a negative result that survives that attempt, and include the attempts. diff --git a/skills/operations/references/orchestration.md b/skills/operations/references/orchestration.md index 7416393d..2456c342 100644 --- a/skills/operations/references/orchestration.md +++ b/skills/operations/references/orchestration.md @@ -106,7 +106,9 @@ relevant fields in the final response. The coordinator independently verifies Git/GitHub state and reuses valid exact-candidate proof under [verification](verification.md); transcripts and duplicate -checks are unnecessary. Start the next unblocked substantive Issue with its own +checks are unnecessary. Before you relay a negative result or file anything from +it, read [bounded delegation](bounded-delegation.md) in full and apply its +negative-result gate. Start the next unblocked substantive Issue with its own packet. Resume the same Issue when context remains useful; recover current state from Git, GitHub, instructions, and handoff. Never recreate completed work or request completed approvals again. diff --git a/tests/test_negative_result_gate.py b/tests/test_negative_result_gate.py index 2060b5c8..3974b0e8 100644 --- a/tests/test_negative_result_gate.py +++ b/tests/test_negative_result_gate.py @@ -61,6 +61,7 @@ def test_delegation_reference_owns_the_acceptance_gate(self) -> None: "Accept it only when it lists what was tried and which primary sources were checked: the tool's own docs and bundled README, its `--help`, its environment variables, and its config keys.", "Before you relay that result to the user or file anything from it, try the work once yourself or assign one challenger whose only job is to make the work succeed.", "Report only a negative result that survives that attempt, and include the attempts.", + "An ordinary failed slice, one that does not say the work cannot be done, is still recorded at once.", "Validate at safe boundaries and before reporting.", ): with self.subTest(clause=clause): @@ -76,6 +77,11 @@ def test_worker_brief_requires_attempts_and_primary_sources(self) -> None: "its `--help`, its environment variables, and its config keys.", text, ) + self.assertIn( + "Before you relay a negative result or file anything from it, read [bounded delegation](bounded-delegation.md) " + "in full and apply its negative-result gate.", + text, + ) if __name__ == "__main__": From b8c6b890bab7438c94e598e194cadb9696a44508 Mon Sep 17 00:00:00 2001 From: Luke Maj Date: Wed, 14 Oct 2026 14:58:42 +0200 Subject: [PATCH 3/4] Leave filed work with a named owner (#226) Filing an Issue for work the user wants done is not the job. The turn ends with a running worker or an accepted handoff, and the report names that owner. --- CHANGELOG.md | 1 + evals/issue-owner.json | 84 +++++++++++++++++++ skills/operations/references/orchestration.md | 8 +- tests/test_negative_result_gate.py | 33 ++++++++ 4 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 evals/issue-owner.json diff --git a/CHANGELOG.md b/CHANGELOG.md index b3164f3d..386c651f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ SemVer and identify one user-consumable repository state. ### Added - A delegated negative result reaches the user or an Issue only after it lists attempts and primary sources and one challenge fails to make the work succeed (#226) +- An Issue filed or found for work the user wants done leaves that turn with a running worker or a named agent that accepted the handoff, and the report names that owner (#226) ## [17.1.1] - 2026-10-13 diff --git a/evals/issue-owner.json b/evals/issue-owner.json new file mode 100644 index 00000000..86628dd6 --- /dev/null +++ b/evals/issue-owner.json @@ -0,0 +1,84 @@ +{ + "fixture_kind": "issue-owner", + "issue": "https://github.com/toolboxmd/agentsmd/issues/226", + "incident_date": "2026-10-14", + "cases": [ + { + "id": "agent-observer-85-86-unstaffed", + "incident": true, + "summary": "The planner filed toolboxmd/agent-observer#85 and #86 for work the user had asked for, wrote that the planner would staff the build, and sent no handoff. No worker was running. Nobody worked on them until the user asked.", + "running_worker_started": false, + "within_authority": false, + "handoff_sent": false, + "handoff_acknowledged": false, + "report_names_owner": false, + "leaves_with_owner": false + }, + { + "id": "promise-without-handoff", + "incident": false, + "summary": "The report says a named planner will pick the Issue up. No message was sent and no worker is running.", + "running_worker_started": false, + "within_authority": true, + "handoff_sent": false, + "handoff_acknowledged": false, + "report_names_owner": true, + "leaves_with_owner": false + }, + { + "id": "handoff-sent-not-acknowledged", + "incident": false, + "summary": "A handoff message was sent to a named agent. That agent has not acknowledged it. The report names them.", + "running_worker_started": false, + "within_authority": true, + "handoff_sent": true, + "handoff_acknowledged": false, + "report_names_owner": true, + "leaves_with_owner": false + }, + { + "id": "worker-outside-authority", + "incident": false, + "summary": "A worker is running, but starting it was outside the agent's authority. No accepted handoff exists. The report names the worker.", + "running_worker_started": true, + "within_authority": false, + "handoff_sent": false, + "handoff_acknowledged": false, + "report_names_owner": true, + "leaves_with_owner": false + }, + { + "id": "worker-started-report-omits-name", + "incident": false, + "summary": "A worker was started within authority and is running. The report to the user does not name that owner.", + "running_worker_started": true, + "within_authority": true, + "handoff_sent": false, + "handoff_acknowledged": false, + "report_names_owner": false, + "leaves_with_owner": false + }, + { + "id": "running-worker-named", + "incident": false, + "summary": "A worker was started within authority and is running. The report names that worker.", + "running_worker_started": true, + "within_authority": true, + "handoff_sent": false, + "handoff_acknowledged": false, + "report_names_owner": true, + "leaves_with_owner": true + }, + { + "id": "named-agent-accepted", + "incident": false, + "summary": "The handoff was sent to a named agent and that agent acknowledged it. The report names that agent.", + "running_worker_started": false, + "within_authority": true, + "handoff_sent": true, + "handoff_acknowledged": true, + "report_names_owner": true, + "leaves_with_owner": true + } + ] +} diff --git a/skills/operations/references/orchestration.md b/skills/operations/references/orchestration.md index 2456c342..13a879ee 100644 --- a/skills/operations/references/orchestration.md +++ b/skills/operations/references/orchestration.md @@ -108,8 +108,12 @@ The coordinator independently verifies Git/GitHub state and reuses valid exact-candidate proof under [verification](verification.md); transcripts and duplicate checks are unnecessary. Before you relay a negative result or file anything from it, read [bounded delegation](bounded-delegation.md) in full and apply its -negative-result gate. Start the next unblocked substantive Issue with its own -packet. Resume the same Issue when context remains useful; recover current state +negative-result gate. When you file or find an Issue for work the user wants +done, leave that turn with a real owner: a running worker you started within +your authority, or a named agent that has accepted the handoff, message sent +and acknowledged. "X will pick it up", with no handoff, is not an owner. Name +the owner in the report to the user. Start the next unblocked substantive +Issue with its own packet. Resume the same Issue when context remains useful; recover current state from Git, GitHub, instructions, and handoff. Never recreate completed work or request completed approvals again. diff --git a/tests/test_negative_result_gate.py b/tests/test_negative_result_gate.py index 3974b0e8..b6fd3ce5 100644 --- a/tests/test_negative_result_gate.py +++ b/tests/test_negative_result_gate.py @@ -10,12 +10,20 @@ FIXTURE = ROOT / "evals" / "negative-result-gate.json" DELEGATION = ROOT / "skills/operations/references/bounded-delegation.md" ORCHESTRATION = ROOT / "skills/operations/references/orchestration.md" +OWNER_FIXTURE = ROOT / "evals" / "issue-owner.json" def words(path: Path) -> str: return " ".join(path.read_text(encoding="utf-8").split()) +def leaves_with_owner(case: dict) -> bool: + """A filed or found Issue leaves the turn with an owner only when one of these holds.""" + running = case["running_worker_started"] and case["within_authority"] + accepted = case["handoff_sent"] and case["handoff_acknowledged"] + return (running or accepted) and case["report_names_owner"] + + def negative_may_reach_user_or_issue(case: dict, primary_sources: set[str]) -> bool: """The acceptance gate. A negative reaches the user or an Issue only when it survives.""" if case["polarity"] != "negative": @@ -82,6 +90,31 @@ def test_worker_brief_requires_attempts_and_primary_sources(self) -> None: "in full and apply its negative-result gate.", text, ) + self.assertIn( + "When you file or find an Issue for work the user wants done, leave that turn with a real owner: " + "a running worker you started within your authority, or a named agent that has accepted the handoff, " + "message sent and acknowledged.", + text, + ) + self.assertIn('"X will pick it up", with no handoff, is not an owner.', text) + self.assertIn("Name the owner in the report to the user.", text) + self.assertNotIn("Pursue necessary in-scope work", text) + + +class IssueOwnerTests(unittest.TestCase): + def setUp(self) -> None: + self.fixture = json.loads(OWNER_FIXTURE.read_text(encoding="utf-8")) + + def test_incident_fixture_grades_every_case(self) -> None: + self.assertEqual(self.fixture["fixture_kind"], "issue-owner") + self.assertIn("226", self.fixture["issue"]) + cases = self.fixture["cases"] + self.assertEqual(len(cases), len({case["id"] for case in cases})) + incident = [case["id"] for case in cases if case["incident"]] + self.assertEqual(incident, ["agent-observer-85-86-unstaffed"]) + for case in cases: + with self.subTest(case=case["id"]): + self.assertEqual(leaves_with_owner(case), case["leaves_with_owner"]) if __name__ == "__main__": From 9672e94656a71aeae6d8c1f12e81eb4677072481 Mon Sep 17 00:00:00 2001 From: Luke Maj Date: Wed, 14 Oct 2026 15:07:56 +0200 Subject: [PATCH 4/4] Name the negative result the source list applies to (#226) "Accept it" followed the ordinary-slice sentence, so the list could be read as applying to that slice. --- skills/operations/references/bounded-delegation.md | 12 ++++++------ tests/test_negative_result_gate.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/skills/operations/references/bounded-delegation.md b/skills/operations/references/bounded-delegation.md index faaa8d7e..12eb4d08 100644 --- a/skills/operations/references/bounded-delegation.md +++ b/skills/operations/references/bounded-delegation.md @@ -39,12 +39,12 @@ message tools usually suffice; do not build a queue service by default. A negative result says the work cannot be done: not possible, cannot remove, blocked, no recipe, or failed. An ordinary failed slice, one that does not say -the work cannot be done, is still recorded at once. Accept it only when it -lists what was tried and which primary sources were checked: the tool's own docs -and bundled README, its `--help`, its environment variables, and its config -keys. Before you relay that result to the user or file anything from it, try -the work once yourself or -assign one challenger whose only job is to make the work succeed. Report only a +the work cannot be done, is still recorded at once. Accept a negative result +only when it lists what was tried and which primary sources were checked: the +tool's own docs and bundled README, its `--help`, its environment variables, +and its config keys. Before you relay that result to the user or file anything +from it, try the work once yourself or assign one challenger whose only job is +to make the work succeed. Report only a negative result that survives that attempt, and include the attempts. Integrate reviewed components as they become ready under the one-final-approval- diff --git a/tests/test_negative_result_gate.py b/tests/test_negative_result_gate.py index b6fd3ce5..67fad17d 100644 --- a/tests/test_negative_result_gate.py +++ b/tests/test_negative_result_gate.py @@ -66,7 +66,7 @@ def test_delegation_reference_owns_the_acceptance_gate(self) -> None: text = words(DELEGATION) for clause in ( "A negative result says the work cannot be done: not possible, cannot remove, blocked, no recipe, or failed.", - "Accept it only when it lists what was tried and which primary sources were checked: the tool's own docs and bundled README, its `--help`, its environment variables, and its config keys.", + "Accept a negative result only when it lists what was tried and which primary sources were checked: the tool's own docs and bundled README, its `--help`, its environment variables, and its config keys.", "Before you relay that result to the user or file anything from it, try the work once yourself or assign one challenger whose only job is to make the work succeed.", "Report only a negative result that survives that attempt, and include the attempts.", "An ordinary failed slice, one that does not say the work cannot be done, is still recorded at once.",