feat(okf): one bundle-id rule, reconciled against the mount and origin-marked
[skip-docs] — the invariant row for this plan lands in Step 13, where the mutations that force it have been measured. Documenting a seam before its measurement is the claim-without-evidence class this repo writes rows against. Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
parent
60e51ab76c
commit
842c51401d
5 changed files with 388 additions and 4 deletions
|
|
@ -859,7 +859,12 @@ def navigator_tools(bundle_dirs: Sequence[str]) -> list[FunctionTool]:
|
|||
description="Open ONE knowledge base by id and read its navigated context.",
|
||||
)
|
||||
def read_bundle(bundle_id: str) -> str:
|
||||
return okf.bundle_context(okf.navigate_bundle(_resolve_bundle(index, bundle_id)))
|
||||
bundle_dir = _resolve_bundle(index, bundle_id)
|
||||
# The base is OPENED here, so this is where it is reconciled against its mount (Step 10).
|
||||
# ``_bundle_index`` above stays PURE — it does no file I/O, and must not: two of its own
|
||||
# arms configure directories that do not exist and expect an id error, not an I/O one.
|
||||
okf.reconcile_bundle_id(bundle_dir)
|
||||
return okf.bundle_context(okf.navigate_bundle(bundle_dir))
|
||||
|
||||
@tool(
|
||||
name="read_file",
|
||||
|
|
|
|||
|
|
@ -51,8 +51,9 @@ class Approach(BaseModel):
|
|||
id: str = Field(min_length=1)
|
||||
label: str = Field(min_length=1)
|
||||
description: str = ""
|
||||
#: Which knowledge base this approach belongs to (§ C.7), by the base's id — the directory's
|
||||
#: BASENAME, exactly as ``explore._bundle_index`` names it. DEFAULTS to empty, meaning "no base
|
||||
#: Which knowledge base this approach belongs to (§ C.7), by the base's id — exactly as
|
||||
#: ``okf.reconcile_bundle_id`` resolves it (the base's own declaration where it makes one, the
|
||||
#: mount's basename otherwise). DEFAULTS to empty, meaning "no base
|
||||
#: named": a legitimate statement when the run has only one base to name, and what keeps every
|
||||
#: mandate written before multi-base existed valid and dispatchable unchanged.
|
||||
#:
|
||||
|
|
|
|||
|
|
@ -846,6 +846,101 @@ def navigate_bundle(bundle_dir: str) -> Bundle:
|
|||
return Bundle(dir=bundle_dir, files=tuple(files), skipped=tuple(skipped))
|
||||
|
||||
|
||||
class BundleIdMismatch(ValueError):
|
||||
"""A base declares a ``bundle_id`` its mount does not carry.
|
||||
|
||||
A ``ValueError`` DELIBERATELY: it must land on ``run.main``'s refusal tuple and on hosting's
|
||||
400 arm rather than on the crash channel. ``ExplorationError`` is a ``RuntimeError`` and would
|
||||
give an operator a traceback and an automated caller a 500 — a configuration mistake dressed
|
||||
as a server fault.
|
||||
"""
|
||||
|
||||
|
||||
#: Which source answered. THREE values, not a boolean (operator decision B1): a caller that cannot
|
||||
#: tell "the concept said so" from "we fell back twice" has been handed a stamp it cannot audit.
|
||||
BundleIdOrigin = Literal["declared-concept", "declared-index", "mount-derived"]
|
||||
|
||||
_BUNDLE_ID_KEY = "bundle_id"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ResolvedBundleId:
|
||||
"""A base's id together with WHERE it came from.
|
||||
|
||||
``origin`` is REQUIRED WITHOUT DEFAULT, for the reason ``ProvenanceStamp.cost_baseline_anchored``
|
||||
is: both defaults would lie about an event. Defaulting to ``"mount-derived"`` would let a
|
||||
resolver that never read the base claim it had; defaulting to a declared value would claim a
|
||||
declaration that never happened.
|
||||
"""
|
||||
|
||||
id: str
|
||||
origin: BundleIdOrigin
|
||||
|
||||
|
||||
def _declared_bundle_id(frontmatter: dict[str, str]) -> str:
|
||||
"""The declared id, de-quoted through ``unquote_scalar`` — this repo's ONE de-quoting rule."""
|
||||
return unquote_scalar(frontmatter.get(_BUNDLE_ID_KEY, "")).strip()
|
||||
|
||||
|
||||
def _reconciled(
|
||||
declared: str, mount: str, origin: BundleIdOrigin, bundle_dir: str
|
||||
) -> ResolvedBundleId:
|
||||
if declared != mount:
|
||||
raise BundleIdMismatch(
|
||||
f"knowledge base {bundle_dir!r} declares bundle_id {declared!r} but is mounted as "
|
||||
f"{mount!r}; an approach names a base by that id, so a run would evaluate against one "
|
||||
f"and report the other (source: {origin})"
|
||||
)
|
||||
return ResolvedBundleId(id=declared, origin=origin)
|
||||
|
||||
|
||||
def reconcile_bundle_id(
|
||||
bundle_dir: str | Path, *, concept_name: str | None = None
|
||||
) -> ResolvedBundleId:
|
||||
"""Resolve a base's ``bundle_id`` against the mount it was opened from — the ONE rule.
|
||||
|
||||
``bundle_id`` denotes the corpus **as a mounted artefact**, never the production event that made
|
||||
it (operator decision D6). That denotation cannot be changed once artefacts bear the stamp,
|
||||
which is why it is written down here rather than left to each call site.
|
||||
|
||||
Resolution order is operator decision B1 — identity is the pair ``(bundle_id, concept_id)``, and
|
||||
the CONCEPT's own frontmatter is consulted first:
|
||||
|
||||
1. ``concept_name``'s frontmatter, when a concept is named and declares the key →
|
||||
``"declared-concept"``;
|
||||
2. the root ``index.md``'s frontmatter → ``"declared-index"``;
|
||||
3. the mount's basename → ``"mount-derived"``.
|
||||
|
||||
A declared id that DISAGREES with the mount raises ``BundleIdMismatch`` at whichever source
|
||||
declared it. A base whose root ``index.md`` cannot be read is **unknown, not undeclared**:
|
||||
``navigate_bundle``'s fail-fast propagates unchanged, because reading an unreadable base as
|
||||
"it declares nothing" would widen the answer on missing evidence.
|
||||
|
||||
MEASURED 2026-09-02: no file under ``shared/`` declares the key (zero ``^bundle_id`` hits
|
||||
against a known-positive control of 31 files carrying ``^type:``), so every base in this repo
|
||||
resolves ``mount-derived`` today and both declared branches are DEFENSIVE.
|
||||
|
||||
:raises BundleIdMismatch: a declared id the mount does not carry.
|
||||
:raises ValueError: the root ``index.md`` is missing or unreadable.
|
||||
"""
|
||||
root = str(bundle_dir)
|
||||
mount = Path(root).name
|
||||
if concept_name is not None:
|
||||
concept = _load_file(root, concept_name)
|
||||
if concept is None:
|
||||
raise ValueError(f"OKF bundle has no readable concept {concept_name!r}: {root!r}")
|
||||
declared = _declared_bundle_id(concept.frontmatter)
|
||||
if declared:
|
||||
return _reconciled(declared, mount, "declared-concept", root)
|
||||
index = _load_file(root, _INDEX_NAME)
|
||||
if index is None:
|
||||
raise ValueError(f"OKF bundle has no readable {_INDEX_NAME}: {root!r}")
|
||||
declared = _declared_bundle_id(index.frontmatter)
|
||||
if declared:
|
||||
return _reconciled(declared, mount, "declared-index", root)
|
||||
return ResolvedBundleId(id=mount, origin="mount-derived")
|
||||
|
||||
|
||||
def bundle_context(bundle: Bundle, *, dimension: str | None = None) -> str:
|
||||
"""Render a navigated bundle as agent read-context via progressive disclosure: the ``index.md``
|
||||
summary, then each concept file as ``## {type}: {title}\\n{body}``. ``type: verdict`` files are
|
||||
|
|
|
|||
|
|
@ -658,6 +658,10 @@ async def run_project(
|
|||
# before the amendment (every commons-owned golden) is legitimately un-anchored -> None =
|
||||
# pre-S4.0 behaviour. A baseline that exists but is malformed still raises (fail-closed).
|
||||
if bundle_dir is not None:
|
||||
# ONE bundle-id rule (Step 10): the base is reconciled against the mount it was opened
|
||||
# from, HERE rather than in ``explore._bundle_index``, which stays pure and does no I/O.
|
||||
# A base that declares an id its mount does not carry is refused before anything is spent.
|
||||
okf.reconcile_bundle_id(bundle_dir)
|
||||
bundle = okf.navigate_bundle(bundle_dir)
|
||||
project = _project_from_bundle(bundle_dir, project_id, bundle=bundle)
|
||||
baseline = okf.load_optional_cost_baseline(bundle_dir)
|
||||
|
|
@ -1511,7 +1515,11 @@ async def run_mandate_across_bundles(
|
|||
"""
|
||||
by_id: dict[str, str] = {}
|
||||
for raw in bundle_dirs:
|
||||
bundle_id = Path(raw).name
|
||||
# The ONE derivation rule (Step 10) — this used to be a second private copy of
|
||||
# ``Path(raw).name``, free to drift from ``explore``'s. The REFUSAL below stays local:
|
||||
# ``MandateRoutingError`` is this door's class, ``ExplorationError`` is explore's, and
|
||||
# unifying the derivation is not the same as unifying the two doors' error vocabularies.
|
||||
bundle_id = okf.reconcile_bundle_id(raw).id
|
||||
if bundle_id in by_id:
|
||||
# The same refusal ``explore._bundle_index`` makes, for the same reason: the id is how
|
||||
# the mandate names a base, so two bases answering to one name would let an approach be
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue