Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
ID: ISSUE-LOCAL-01M3NH23E78PEXCJF4HW1XHQQ3
Title: frozen-evidence byte equality and record link resolution cannot both hold
Row: POLICY-ISSUE-INTAKE
State: OPEN
Kind: bug
GitHub: -
Mirror: PENDING
Availability: FULL
Created: 2026-09-28
Updated: 2026-09-28
Closed: -

## Problem

An _intake record's Problem must quote the frozen archive line byte for byte, but check-agent-record's check_links requires every link in a record to resolve from the record's own directory. The archive lives at .agents/completed/issue-index.md, one level under .agents, so a link to a spec is spelled ../specs/x.md there; the record that QUOTES the row lives at .agents/issues/<owner>/, two levels down, so the same link must be spelled ../../specs/x.md from there. One string cannot satisfy both. Commit e3539d994 re-pointed the ISSUE-GH-1033 quote to the record-relative spelling to fix the dangling link, which broke the byte comparison: first divergence at column 2191 of archive line 350, archive 2237 chars against evidence 2240. Measured over all 831 records that carry a Frozen archive evidence block, 350 are byte-equal, 438 differ from the cited line ONLY by a relative link rebase, and 43 cite a line the archive no longer has (24 past its 886 lines after the delete and re-add, 19 naming a row that moved). Restoring the archive spelling makes check-links red instead. Fix: compare the quote against the cited line with each side's relative link targets resolved to the file they denote, so the check asks whether the quote IS the archived row rather than which directory holds the quote.

## Resolution

-
101 changes: 94 additions & 7 deletions scripts/issue_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from dataclasses import dataclass
from datetime import date
from pathlib import Path
import posixpath
import re
from typing import TypeAlias

Expand All @@ -38,11 +39,21 @@
_LOCAL_ID = re.compile(r"ISSUE-LOCAL-([0-7][0-9A-HJKMNP-TV-Z]{25})\Z")
_ROW_ID = re.compile(r"[A-Z0-9][A-Za-z0-9_.-]*\Z")
_GITHUB_NUMBER = re.compile(r"[1-9][0-9]*\Z")
# The one frozen archive an intake record's Problem must quote, in
# repository-relative form. The record that HOLDS a quote lives deeper than
# the file the quote was cut from, which is why the comparison below
# resolves relative link targets instead of comparing their spelling: the
# same row is `../specs/x.md` in the archive and `../../specs/x.md` in the
# record, and both gates (this one and check-links) must be satisfiable at
# once.
FROZEN_ARCHIVE_RELPATH = ".agents/completed/issue-index.md"
_INTAKE_PROBLEM = re.compile(
r"Archive: `\.agents/completed/issue-index\.md:([1-9][0-9]*)`\n\n"
r"Archive: `" + re.escape(FROZEN_ARCHIVE_RELPATH) + r":([1-9][0-9]*)`\n\n"
r"### Frozen archive evidence\n\n"
r"> ([^\n]+)\Z"
)
_LINK_TARGET = re.compile(r"(\[[^\]]*\]\()([^)]+)(\))")
_REMOTE_TARGET = re.compile(r"[A-Za-z][A-Za-z0-9+.-]*:")


class IssueRecordError(ValueError):
Expand Down Expand Up @@ -303,19 +314,80 @@ def intake_archive_evidence(record: IssueRecord) -> tuple[int, str] | None:
return int(match.group(1)), match.group(2)


def _resolve_relative_links(line: str, base: str) -> str:
"""Rewrite every relative Markdown link target to the file it denotes.

A relative link resolves against the file that QUOTES it, so one frozen
row cannot keep one spelling in the archive (`.agents/completed/`) and in
the record that quotes it (`.agents/issues/<owner>/`). Resolving both
sides to the repository-relative path they point at is what lets the
evidence comparison ask the question it means to ask -- is this the
archived row? -- instead of which directory holds the quote.

Remote (`https:`, `mailto:`, ...) and root-absolute (`/...`) targets are
left exactly as written: only a rebase of a relative target is
comparable, so a swapped remote URL, a truncated link, or any other
difference still fails the comparison byte for byte.
"""

def rewrite(match: re.Match[str]) -> str:
raw = match.group(2)
lead = raw[: len(raw) - len(raw.lstrip())]
trail = raw[len(raw.rstrip()) :]
target = raw.strip()
angled = target.startswith("<") and target.endswith(">")
if angled:
target = target[1:-1]
path, separator, fragment = target.partition("#")
if (
not path
or path.startswith(("/", "?"))
or _REMOTE_TARGET.match(path) is not None
):
return match.group(0)
resolved = posixpath.normpath(posixpath.join(base, path))
rendered = f"{resolved}{separator}{fragment}"
if angled:
rendered = f"<{rendered}>"
return f"{match.group(1)}{lead}{rendered}{trail}{match.group(3)}"

return _LINK_TARGET.sub(rewrite, line)


def _archive_evidence_matches_source(
evidence: tuple[int, str],
frozen_archive: bytes | None,
record_base: str = "",
) -> bool:
"""Require exact UTF-8 evidence bytes at the declared one-based source line."""
"""Require the declared line to be the quote, modulo relative link rebase.

Byte equality is tried first and answers almost every record: an archive
that has not moved and a record that copied the line verbatim need
nothing resolved. Only when the bytes differ is the quote compared with
each side's relative link targets resolved, which admits exactly the
spelling a MOVE forces (`../specs/x.md` vs `../../specs/x.md`) and
nothing else. `record_base` is the record's repository-relative
directory; with no base to resolve against, only byte equality passes.
"""

if frozen_archive is None:
return False
line_number, archived_line = evidence
source_lines = frozen_archive.split(b"\n")
if line_number > len(source_lines):
return False
return source_lines[line_number - 1] == archived_line.encode("utf-8")
source_line = source_lines[line_number - 1]
if source_line == archived_line.encode("utf-8"):
return True
if not record_base:
return False
try:
decoded = source_line.decode("utf-8")
except UnicodeDecodeError:
return False
return _resolve_relative_links(
decoded, posixpath.dirname(FROZEN_ARCHIVE_RELPATH)
) == _resolve_relative_links(archived_line, record_base)


def _archive_row_owner(line: str, github: int | None) -> str | None:
Expand All @@ -342,13 +414,20 @@ def _archive_row_owner(line: str, github: int | None) -> str | None:
def valid_intake_archive_evidence(
record: IssueRecord,
frozen_archive: bytes | None = None,
record_base: str = "",
) -> tuple[int, str] | None:
"""Return evidence only when exact source bytes identify ownerless self."""
"""Return evidence only when the source line identifies ownerless self.

`record_base` is the record's repository-relative directory, so a quote
whose links were re-pointed to resolve from there still matches the line
it was cut from; see `_resolve_relative_links`.
"""

evidence = intake_archive_evidence(record)
if evidence is None or not _archive_evidence_matches_source(
evidence,
frozen_archive,
record_base,
):
return None
_, line = evidence
Expand Down Expand Up @@ -455,7 +534,7 @@ def validate_issue_record(
errors.append(f"{name} must be UNKNOWN for Availability METADATA_ONLY")
if normalize_body(record.resolution).strip() != "-":
errors.append("Resolution must be - for Availability METADATA_ONLY")
archive = ".agents/completed/issue-index.md"
archive = FROZEN_ARCHIVE_RELPATH
exact_number = (
record.github is not None
and re.search(rf"(?<![0-9])#{record.github}(?![0-9])", record.problem)
Expand All @@ -470,6 +549,11 @@ def validate_issue_record(
)

owner = path.parent.name
# The record's own directory, repository-relative, so the frozen-evidence
# comparison can resolve a re-pointed relative link against where the
# quote lives instead of where the quote was cut from. Two levels under
# .agents/, against the archive's one.
record_base = f".agents/issues/{owner}"
owed_count = _owed_count(owed, record.id)
if owner == "_intake":
intake_shape = (
Expand Down Expand Up @@ -498,10 +582,13 @@ def validate_issue_record(
archived_owner = _archive_row_owner(archived_line, record.github)
if archived_owner not in {"", "-", "—"}:
errors.append("_intake frozen evidence must contain archived Row -")
if not _archive_evidence_matches_source(evidence, frozen_archive):
if not _archive_evidence_matches_source(
evidence, frozen_archive, record_base
):
errors.append(
"_intake Frozen archive evidence must equal the declared line "
"in the frozen archive source"
"in the frozen archive source (a relative link may differ only "
"by spelling, and must resolve to the same file)"
)
if owed_count:
errors.append("_intake must not have an owning spec reference")
Expand Down
113 changes: 113 additions & 0 deletions tests/scripts/test_issue_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,42 @@ def frozen_archive_source(
).encode()


def linked_intake_problem(
number: int = 77,
line: int = 6,
spec: str = "../specs/example.md",
) -> str:
"""An intake Problem whose quote carries a relative link, archive-spelled.

The archive lives at `.agents/completed/issue-index.md`, so a link to a
spec is `../specs/...` there. The record that QUOTES the row lives two
levels down, and the same link is `../../specs/...` from there -- the
spelling #3348 is about.
"""
archived = (
f"| [#{number}](https://github.com/mudler/vllm.cpp/issues/{number}) "
f"| — | Spec [example]({spec}) | bug |"
)
return (
f"Archive: `.agents/completed/issue-index.md:{line}`\n\n"
"### Frozen archive evidence\n\n"
f"> {archived}"
)


def linked_frozen_archive_source(number: int = 77, spec: str = "../specs/example.md") -> bytes:
archived = (
f"| [#{number}](https://github.com/mudler/vllm.cpp/issues/{number}) "
f"| — | Spec [example]({spec}) | bug |"
)
return (
"# Issue index\n\nFrozen archive\n"
"| Issue | Row | Title | Kind |\n"
"|---:|---|---|---|\n"
f"{archived}\n"
).encode()


def parse(text: str | None = None) -> records.IssueRecord:
return records.parse_issue_text(text if text is not None else issue_text())

Expand Down Expand Up @@ -543,6 +579,83 @@ def test_intake_evidence_must_equal_the_declared_frozen_source_line(
frozen_archive=frozen_archive,
)

def test_intake_quote_may_rebase_a_relative_link_to_resolve_from_the_record(
self, tmp_path: Path
) -> None:
"""The record-relative spelling of a link is the SAME link (#3348).

`check-links` requires every link in a record to resolve from the
record's own directory; the frozen-evidence comparison required the
quote to be byte-identical to the archive line it was cut from. One
string could not satisfy both, because the archive is one level under
`.agents/` and the record two. A quote whose ONLY difference is a
relative link resolving to the same file is accepted.
"""
record = self.intake(problem=linked_intake_problem(spec="../../specs/example.md"))
validate(
tmp_path,
record,
owner="_intake",
rows={"ROW-A"},
owed=(),
frozen_archive=linked_frozen_archive_source(),
)

@pytest.mark.parametrize(
("spec", "archive_spec"),
[
# a rebase to a DIFFERENT file is still drift
("../../specs/other.md", "../specs/example.md"),
("../../specs/example.md#frag", "../specs/example.md"),
# a remote target is never rebased, so a swap must fail byte for byte
("https://example.com/example.md", "../specs/example.md"),
# a root-absolute target is never rebased either
("/specs/example.md", "../specs/example.md"),
],
)
def test_intake_quote_may_rebase_nothing_but_a_relative_link(
self, tmp_path: Path, spec: str, archive_spec: str
) -> None:
record = self.intake(problem=linked_intake_problem(spec=spec))
with pytest.raises(records.IssueRecordError, match="frozen archive source"):
validate(
tmp_path,
record,
owner="_intake",
rows={"ROW-A"},
owed=(),
frozen_archive=linked_frozen_archive_source(spec=archive_spec),
)

def test_a_rebased_quote_needs_a_record_base_to_be_compared(self) -> None:
"""Without the record's directory, only byte equality may pass.

The public helper keeps the old strict behaviour for a caller that
cannot say where the quote lives, rather than guessing a base and
admitting a drift it cannot see.
"""
record = records.IssueRecord(
id="ISSUE-GH-77",
title="Archived 77",
row=None,
state="UNKNOWN",
kind="bug",
github=77,
mirror="MISSING",
availability="METADATA_ONLY",
created="UNKNOWN",
updated="UNKNOWN",
closed="UNKNOWN",
problem=linked_intake_problem(spec="../../specs/example.md"),
resolution="-",
)
assert records.valid_intake_archive_evidence(
record, linked_frozen_archive_source()
) is None
assert records.valid_intake_archive_evidence(
record, linked_frozen_archive_source(), ".agents/issues/_intake"
) is not None

def test_full_and_local_records_cannot_use_intake(self, tmp_path: Path) -> None:
for record in (
parse(),
Expand Down
Loading