feat(row6): a proposal whose approach declared no requirement is unsupported
Stress round 6 validated three falsification arms, and every validated approach rested only on run-level declarations nobody can attribute to one approach. declare_requirement now takes a required approach_id (a mandate id or own-proposal; an unknown id is refused naming the valid ones), and a ValidatedProposal whose approach has neither a mandate requirement nor a declaration under its own id becomes validator.Unsupported - a Rejection subclass carrying the validator's own ruling, reported as `unsupported` in coverage, the outcome artefact, the settlement and the judge, and never counted or summed. The rule is active whenever the debate held the declaration tool, the micro base included; the road and pre-pass paths are untouched. Declaration quality is not judged, so the rule can be satisfied by declaring any document the run read. The v1 gate's row 6 probes pass; its artefact half reads IKKE MÅLT because stress round 6 predates approach-addressed declarations, and IKKE MÅLT is never green - it fails the exit code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9847e014e7
commit
938a1ca30e
23 changed files with 718 additions and 115 deletions
|
|
@ -215,7 +215,8 @@ _INSTRUCTIONS: Final = {
|
|||
"BINDS it: pass read_dir a 'filter' word taken from the approach's own label — "
|
||||
"filter='rundkjoring' finds the level's requirements about roundabouts, and one of them is "
|
||||
"the 'Krav 4.1.2-1' you are looking for — read it with read_file, then call "
|
||||
"declare_requirement with the base id, that path and the requirement's own number. The "
|
||||
"declare_requirement with the base id, that path, the requirement's own number and the "
|
||||
"short label of the direction as approach_id. The "
|
||||
"reply gives back the document's own title and number: if they are not about your measure, "
|
||||
"you declared the wrong requirement and should filter again. A direction with no "
|
||||
"requirement behind it is a guess. "
|
||||
|
|
@ -371,6 +372,21 @@ class DeclaredRequirement:
|
|||
bundle_id: str
|
||||
path: str
|
||||
ref: str
|
||||
#: WHICH approach the declaration is for (row 6). A requirement bound at run level cannot be
|
||||
#: attributed to one approach — the judge labelled such a declaration ``run`` — so the rule that
|
||||
#: a validated proposal must rest on its own approach's declaration needs the address on the
|
||||
#: record itself. In a commissioned run it is one of the mandate's ids or ``own-proposal``; the
|
||||
#: exploration, which mints its directions after declaring, records the label verbatim.
|
||||
approach_id: str
|
||||
|
||||
|
||||
class UnknownApproach(ValueError):
|
||||
"""A declaration named an approach this run was not commissioned with (row 6).
|
||||
|
||||
Returned as a refused TURN, never raised out of the run (the ``RequirementNotRead`` rule): the
|
||||
refusal NAMES the valid ids, and naming them is the correction — a declaration filed under an
|
||||
id no approach carries would be recorded against nothing and could never satisfy the rule.
|
||||
"""
|
||||
|
||||
|
||||
class RequirementNotRead(ValueError):
|
||||
|
|
@ -1068,6 +1084,7 @@ def _index_excerpt(body: str) -> tuple[str, bool]:
|
|||
_RETURNABLE_REFUSALS: Final = (
|
||||
ExplorationError,
|
||||
RequirementNotRead,
|
||||
UnknownApproach,
|
||||
okf.BundleIdMismatch,
|
||||
okf.BundlePathNotFound,
|
||||
okf.DocumentPathRefused,
|
||||
|
|
@ -1186,6 +1203,7 @@ def navigator_tools(
|
|||
opened: list[ToolCall] | None = None,
|
||||
requirements: list[DeclaredRequirement] | None = None,
|
||||
labels: Sequence[str] = (),
|
||||
approach_ids: Sequence[str] | None = None,
|
||||
) -> list[FunctionTool]:
|
||||
"""The navigator's tools: survey the catalogue, open one base, read one document — and, when
|
||||
the caller offers the two sinks, DECLARE the requirement that binds a direction.
|
||||
|
|
@ -1241,6 +1259,11 @@ def navigator_tools(
|
|||
the run's own read trace and a second record of it would be free to disagree with the first.
|
||||
Passing one without the other is refused at construction: a log that cannot see what was opened
|
||||
would accept every declaration, which is the vacuous-gate class.
|
||||
|
||||
**Every declaration names the approach it is for** (row 6). ``approach_ids`` is the set a
|
||||
commissioned run can file under — the mandate's ids plus ``own-proposal`` — and an id outside it
|
||||
is refused with the valid ones named. ``None`` (the exploration, which has no ids until it mints
|
||||
them) records any non-empty id verbatim.
|
||||
"""
|
||||
if (opened is None) != (requirements is None):
|
||||
raise ExplorationError(
|
||||
|
|
@ -1462,20 +1485,36 @@ def navigator_tools(
|
|||
"'Krav 4.1.2-1'), read_file to read it, then declare it. The reply gives back the "
|
||||
"document's own "
|
||||
"title and number, so you can see whether you declared the requirement you meant: a "
|
||||
"declaration of a requirement that is not about the measure is worth nothing."
|
||||
"declaration of a requirement that is not about the measure is worth nothing. "
|
||||
"approach_id names the approach the requirement binds: declare once for EACH approach "
|
||||
"you propose for (the run's own proposal is 'own-proposal'). A proposal whose approach "
|
||||
"declared no requirement is not validated, however good its numbers are."
|
||||
),
|
||||
)
|
||||
def declare_requirement(bundle_id: str, path: str, ref: str) -> dict[str, Any]:
|
||||
def declare_requirement(
|
||||
bundle_id: str, path: str, ref: str, approach_id: str
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return _declare_requirement(bundle_id, path, ref)
|
||||
return _declare_requirement(bundle_id, path, ref, approach_id)
|
||||
except _RETURNABLE_REFUSALS as exc:
|
||||
return _refused_mapping(exc)
|
||||
|
||||
def _declare_requirement(bundle_id: str, path: str, ref: str) -> dict[str, Any]:
|
||||
def _declare_requirement(
|
||||
bundle_id: str, path: str, ref: str, approach_id: str
|
||||
) -> dict[str, Any]:
|
||||
assert opened is not None and requirements is not None # the constructor guard above
|
||||
# The base is resolved by the SAME index every read rung uses, so an unknown base is
|
||||
# refused here exactly as it is there rather than being accepted into the record.
|
||||
resolved_dir = _resolve_bundle(index, bundle_id)
|
||||
# Row 6: the address is checked before anything is read, so a declaration filed under no
|
||||
# approach is refused whatever else is right about it.
|
||||
if approach_ids is not None and approach_id not in approach_ids:
|
||||
raise UnknownApproach(
|
||||
f"{approach_id!r}; this run's approaches are {', '.join(map(repr, approach_ids))}. "
|
||||
"Declare the requirement under the id of the approach it binds"
|
||||
)
|
||||
if not approach_id.strip():
|
||||
raise UnknownApproach("an empty approach_id; name the approach this requirement binds")
|
||||
read_paths = [call.path for call in opened if call.name == "read_file" and call.path]
|
||||
if path not in read_paths:
|
||||
raise RequirementNotRead(
|
||||
|
|
@ -1518,7 +1557,9 @@ def navigator_tools(
|
|||
"Use read_dir with a 'filter' word from the approach's own label to find the "
|
||||
"candidates, then read_file the ones that could bind it"
|
||||
)
|
||||
requirements.append(DeclaredRequirement(bundle_id=bundle_id, path=path, ref=ref))
|
||||
requirements.append(
|
||||
DeclaredRequirement(bundle_id=bundle_id, path=path, ref=ref, approach_id=approach_id)
|
||||
)
|
||||
# P20/A1: give back the DOCUMENT's own title and number, read off the base rather than
|
||||
# echoed from the arguments. MEASURED (P19 round 3, P17b): 13 declarations over 5 runs and
|
||||
# NOT ONE named a fasit concept — the tool answered ``{"declared": true, ...}`` to every
|
||||
|
|
@ -1532,6 +1573,7 @@ def navigator_tools(
|
|||
"bundle_id": bundle_id,
|
||||
"path": path,
|
||||
"ref": ref,
|
||||
"approach_id": approach_id,
|
||||
"title": declared[0],
|
||||
"req_number": declared[1],
|
||||
"binds": (
|
||||
|
|
@ -1577,7 +1619,10 @@ def requirement_payload(declared: Sequence[DeclaredRequirement]) -> list[dict[st
|
|||
copies of "what a declaration looks like" would drift into two answers about one run, which is
|
||||
the kø-(p) defect landing in exactly the files an operator reads after a paid run.
|
||||
"""
|
||||
return [{"bundle_id": d.bundle_id, "path": d.path, "ref": d.ref} for d in declared]
|
||||
return [
|
||||
{"bundle_id": d.bundle_id, "path": d.path, "ref": d.ref, "approach_id": d.approach_id}
|
||||
for d in declared
|
||||
]
|
||||
|
||||
|
||||
def _refused(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue