Buttons: one definition, aligned to the design system — plus local prior-art recall #94

Merged
bvandeusen merged 12 commits from dev into main 2026-08-02 18:50:04 -04:00
Showing only changes of commit 6d01788326 - Show all commits
+56 -1
View File
@@ -181,13 +181,25 @@ def check_shellcheck() -> None:
# pinning: the bug and the healthy no-results case look identical from outside. # pinning: the bug and the healthy no-results case look identical from outside.
# Pinning it does NOT make the failure visible; it makes sure the fail-open # Pinning it does NOT make the failure visible; it makes sure the fail-open
# behaviour is deliberate rather than accidental. # behaviour is deliberate rather than accidental.
# A symbol that exists nowhere, ASSEMBLED rather than written literally.
# The prior-art hook's local arm (#2280) fires with no credentials, so the
# silence assertion below needs a name the repo genuinely lacks. Two traps,
# both hit while writing this:
# - `def f` matched real code, so the hook spoke and "silent" was asserting
# the wrong thing;
# - spelling the replacement out in full put `def <name>(` INTO this file,
# so the smoke event defined the very symbol it claimed was absent.
# Concatenating keeps the contiguous string out of the source.
_ABSENT_SYM = "zz" + "_absent_" + "9f3a2b"
SMOKE_EVENTS: dict[str, str] = { SMOKE_EVENTS: dict[str, str] = {
"scribe_autoinject.sh": json.dumps( "scribe_autoinject.sh": json.dumps(
{"session_id": "smoke", "cwd": ".", "prompt": "a multi-line\nprompt\nhere"} {"session_id": "smoke", "cwd": ".", "prompt": "a multi-line\nprompt\nhere"}
), ),
"scribe_prior_art.sh": json.dumps( "scribe_prior_art.sh": json.dumps(
{"session_id": "smoke", "cwd": ".", "tool_name": "Edit", {"session_id": "smoke", "cwd": ".", "tool_name": "Edit",
"tool_input": {"file_path": "src/x.py", "new_string": "def f():\n pass\n"}} "tool_input": {"file_path": "src/x.py",
"new_string": f"def {_ABSENT_SYM}():\n pass\n"}}
), ),
"scribe_sync_processes.sh": json.dumps({"source": "startup"}), "scribe_sync_processes.sh": json.dumps({"source": "startup"}),
"scribe_session_context.sh": json.dumps({"source": "startup"}), "scribe_session_context.sh": json.dumps({"source": "startup"}),
@@ -253,6 +265,48 @@ def check_fail_open() -> None:
ok(f"{rel} [{label}]: exit 0, silent") ok(f"{rel} [{label}]: exit 0, silent")
def check_local_prior_art_needs_no_instance() -> None:
"""The prior-art hook's local arm must answer with no credentials (#2280).
The other arms ask Scribe what was RECORDED. This one asks the repo what
EXISTS, which needs no instance — and that is the whole reason it catches
the case the recorded arms structurally cannot: a helper nobody thought to
record. If it ever silently starts depending on configuration, it stops
covering that case and nothing else would notice.
Paired with the silence assertion in check_fail_open, which uses a symbol
that cannot exist. Together they pin both halves: silent when there is
nothing to say, and speaking when there is — both with no instance at all.
"""
script = HOOKS_DIR / "scribe_prior_art.sh"
if not script.is_file() or not shutil.which("jq"):
skip("prior-art local arm: hook or jq missing")
return
# A definition this repo really does contain, written into a DIFFERENT file
# so the self-match exclusion doesn't suppress it.
event = json.dumps({
"session_id": "smoke", "cwd": ".", "tool_name": "Write",
"tool_input": {
"file_path": "scripts/_probe_not_real.py",
"content": "def check_local_prior_art_needs_no_instance():\n pass\n",
},
})
try:
proc = _run_hook(script, event, {}) # NO credentials, on purpose
except subprocess.TimeoutExpired:
fail("prior-art local arm: hung")
return
if proc.returncode != 0:
fail(f"prior-art local arm: exited {proc.returncode}, must be 0")
elif "already defined" not in proc.stdout:
fail("prior-art local arm: found nothing for a symbol this repo "
"defines, with no credentials — the arm that needs no instance "
"has stopped working, and the recorded arms cannot cover for it")
else:
ok("prior-art local arm: answers with no instance configured")
def _git(*args: str) -> tuple[int, str]: def _git(*args: str) -> tuple[int, str]:
proc = subprocess.run( proc = subprocess.run(
["git", *args], capture_output=True, text=True, cwd=ROOT ["git", *args], capture_output=True, text=True, cwd=ROOT
@@ -344,6 +398,7 @@ def main() -> int:
check_patterns() check_patterns()
check_shellcheck() check_shellcheck()
check_fail_open() check_fail_open()
check_local_prior_art_needs_no_instance()
if not args.no_version: if not args.no_version:
check_version_bump(args.base) check_version_bump(args.base)