Skip to content

tidy: centralize optional bridge script execution - #2495

Merged
john-the-dev merged 2 commits into
sonichi:mainfrom
marklysze:tidy/bridge-transcription-runner
Aug 2, 2026
Merged

john-the-dev merged 2 commits into
sonichi:mainfrom
marklysze:tidy/bridge-transcription-runner

Conversation

@marklysze

@marklysze marklysze commented Aug 1, 2026 •

Copy link
Copy Markdown
Collaborator

What changed, and why?

Centralizes the provider-neutral subprocess behavior used when Discord, Slack,
and Telegram invoke the optional audio-transcribe skill.

src/optional_script.py now owns the shared interpreter selection, argument
construction, timeout, output normalization, and fail-open behavior. Each
bridge still discovers the skill at its existing adapter-specific path and
retains its existing _transcribe_via_skill API and log wording.

CLAUDE.md / AGENTS.md now keep optional capability discovery at the adapter
edge, while docs/architecture-boundaries.md records the dependency direction.

Review first

  1. src/optional_script.py
  2. _transcribe_via_skill in the three bridge adapters
  3. TestOptionalScriptRunner and the real-module coverage cases in
    tests/audio-transcribe-skill.test.py
  4. the architecture rule in CLAUDE.md

User behavior or bug proved

N/A — this is a behavior-preserving tidy: refactor. The tests pin the
existing missing-script, success, non-zero exit, exception, 25-second timeout,
stdout trimming, interpreter, symlink-resolution, and fail-open contracts.

Feature/documentation consistency

No user-visible capability changed. The architecture boundary is documented in
docs/architecture-boundaries.md; CLAUDE.md was updated and AGENTS.md
regenerated. docs/src-map.md was regenerated for the new source module.

Before / after evidence

Parent a9fb5bbc7bc7bf820c76e1a34494b1a1abf9e959 contained the same subprocess
command in three bridge-private helpers:

$ git grep -n -F '[sys.executable, str(skill_script), local_path]' origin/main -- 'src/*-bridge.py'
origin/main:src/discord-bridge.py:437:            [sys.executable, str(skill_script), local_path],
origin/main:src/slack-bridge.py:676:            [sys.executable, str(skill_script), local_path],
origin/main:src/telegram-bridge.py:374:            [sys.executable, str(skill_script), local_path],

HEAD has one runner and three thin adapter delegations:

$ git grep -n -F '_run_optional_script_shared(' HEAD -- 'src/*-bridge.py'
HEAD:src/discord-bridge.py:433:    return _run_optional_script_shared(
HEAD:src/slack-bridge.py:672:    return _run_optional_script_shared(
HEAD:src/telegram-bridge.py:370:    return _run_optional_script_shared(

$ git grep -n -F '[sys.executable, str(script_path), *args]' HEAD -- src/optional_script.py
HEAD:src/optional_script.py:36:            [sys.executable, str(script_path), *args],

Tests

$ python3 tests/audio-transcribe-skill.test.py
Ran 22 tests in 0.129s
OK

$ python3 scripts/lint-hermetic-bridge-tests.py --diff
lint-hermetic-bridge-tests: ok (1 bridge-importing tests scanned, 59 grandfathered, 0 mitigated)

$ bash scripts/agents-md-sync.sh --check
agents-md-sync: AGENTS.md is up to date

$ python3 scripts/gen-src-map.py --check
gen-src-map: docs/src-map.md is up to date

$ git diff origin/main...HEAD | bash scripts/review-checks.sh
review-checks: PASS (hardcoded-paths clean)
$ npm run test:py
...
PASS — 18/18 write-calendar-cache producer tests
[exit 0]

The first sandboxed full-suite attempt stopped at the repository's loopback
HTTP fixture with PermissionError: [Errno 1] Operation not permitted; the
identical suite was rerun with local test-server permission and completed with
exit 0. The existing optional secret-scanner.test.py and
vault-intercept.test.py skips reported that detect_secrets is not installed
in this interpreter.

Live post-restart round trip

Discord was restarted directly from HEAD with the normal runtime environment.
The owner sent a real Discord mobile voice message; the patched bridge
downloaded the .ogg, invoked the shared runner, and wrote the transcript into
an owner-tier task:

Discord bridge ready: mark-sutando#4497
  [msg] #DM @msze_:  (mentions: [], is_dm: True, embeds: 0, type: MessageType.default, ref: False)
  @msze_:
[Voice transcript: Central Runner Live test.]
  [task-write] wrote task-1785625426427.txt (@msze_, #DM, tier=owner)

The task recorded source: discord, interaction_type: message,
content_modalities: audio, media_form: attachment, access_tier: owner,
the downloaded .ogg attachment metadata, and the expected transcript. A
result then completed the return path:

  Replied: PR #2495 live test passed: the patched bridge downloaded your Discord voice mess...

An earlier Slack attempt reached its unchanged file-download guard but the
configured Slack token returned an HTML sign-in page for audio_message.m4a
(files:read scope/reinstall is required), so no Slack transcript was claimed.
The Discord pass exercises the shared runner end to end.

Stacking

N/A — standalone PR based directly on current main. It does not depend on
#2492.

Hardcoded-path check

$ git diff origin/main...HEAD | bash scripts/review-checks.sh
review-checks: PASS (hardcoded-paths clean)

No production host path or fallback was added. Skill discovery remains in each
adapter; only the discovered Path is passed into the generic runner.

Edge cases checked

  • optional skill path absent;
  • successful output with surrounding whitespace;
  • empty successful output;
  • non-zero subprocess exit;
  • subprocess timeout/exception with adapter-specific logging;
  • exact sys.executable, argument order, and 25-second timeout;
  • app-bundle/symlink path resolution remains at the adapter edge;
  • shared runner contains no skills/ or audio-transcribe dependency;
  • real Slack and Telegram module execution uses hermetic channel config.

Migration, config, permissions, rollback, and risk

No migration, config, prompt, protocol, or permission change. Rollback is a
single commit revert. The main risk is adapter wiring drift; direct runner
contracts plus source-wiring and real-module tests cover that boundary.

Known gaps / follow-up

Slack voice-note validation on this host requires adding files:read to the
Slack app and reinstalling it. That configuration issue occurs before the code
changed here; Slack's downloader is byte-identical to main. No code follow-up
is bundled into this concern.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Gate

✅ Diff coverage PASSES the 95% bar. Whole-tree (informational): 71%.

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • src/discord-bridge.py (50.0%): Missing lines 433
  • src/optional_script.py (100%)
  • src/slack-bridge.py (100%)
  • src/telegram-bridge.py (100%)

Summary

  • Total: 23 lines
  • Missing: 1 line
  • Coverage: 95%

src/discord-bridge.py

Lines 429-437

  429     Optional — if the skill is absent the caller falls back to [File attached:].
  430     Errors are swallowed; transcription failure must never block task delivery.
  431     """
  432     skill_script = Path(__file__).parent.parent / "skills" / "audio-transcribe" / "scripts" / "transcribe.py"
! 433     return _run_optional_script_shared(
  434         skill_script,
  435         [local_path],
  436         timeout=25,
  437         on_error=lambda exc: print(

@marklysze

Copy link
Copy Markdown
Collaborator Author

Live audio evidence for current head 1bbd4b159f46fb2fea721ef1e2ef43a3868312b9:

I restarted the Discord bridge directly from this PR's worktree with its normal runtime environment. The owner sent a real Discord mobile voice message saying “central runner live test.” The patched bridge downloaded the .ogg, invoked optional_script.run_optional_script, and produced the transcript in the owner task:

Discord bridge ready: mark-sutando#4497
  [msg] #DM @msze_:  (mentions: [], is_dm: True, embeds: 0, type: MessageType.default, ref: False)
  @msze_:
[Voice transcript: Central Runner Live test.]
  [task-write] wrote task-1785625426427.txt (@msze_, #DM, tier=owner)

The emitted task recorded source: discord, interaction_type: message, content_modalities: audio, media_form: attachment, access_tier: owner, the downloaded .ogg metadata, and the expected transcript. I wrote its result and observed delivery through the same adapter:

  Replied: PR #2495 live test passed: the patched bridge downloaded your Discord voice mess...

Result: voice attachment download → shared runner → Gemini transcript → owner-tier task → Discord result delivery all passed.

For completeness, a Slack attempt stopped before the changed boundary: Slack returned an HTML sign-in page instead of audio_message.m4a, indicating that this host's Slack app needs files:read scope/reinstall. Slack's download code is unchanged by this PR, and no Slack transcription pass is claimed.

@marklysze
marklysze marked this pull request as ready for review August 1, 2026 23:05

@qingyun-wu qingyun-wu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 1bbd4b159f46fb2fea721ef1e2ef43a3868312b9.

No blocking findings. The shared runner remains provider- and skill-neutral: each bridge still resolves and injects the audio-transcribe script path, while the helper preserves the prior interpreter, timeout, success/empty/nonzero, and exception logging contract. All three wrappers delegate without changing fallback behavior.

Reviewer-run audio-transcribe-skill passes 22/22, including direct runner contracts, all three adapter wiring paths, symlink resolution, nonzero/empty/timeout behavior, and real module imports. Diff hygiene, source-map consistency, the REVIEW.md path gate, required GitHub checks, and CLA pass.

Worst-case disruption is an optional transcription failure blocking message delivery; the helper stays fail-open and the regressions cover that boundary. APPROVE for this exact head. Normal second-maintainer merge gate still applies.

@qingyun-wu qingyun-wu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved on exact head 1bbd4b159f46fb2fea721ef1e2ef43a3868312b9.

I reviewed the shared runner extraction and the three bridge adapters. The behavior-preserving contract checks out: capability discovery remains in each adapter, src/optional_script.py only runs an injected script path, and the subprocess argv/timeout/stdout/fail-open behavior matches the prior helpers. I also checked that the shared helper does not name audio-transcribe or any concrete skill path.

Reviewer-run checks:

  • python3 tests/audio-transcribe-skill.test.py — 22 passed
  • python3 scripts/lint-hermetic-bridge-tests.py --diff — passed
  • bash scripts/agents-md-sync.sh --check — passed
  • python3 scripts/gen-src-map.py --check — passed
  • git diff origin/main...HEAD | bash scripts/review-checks.sh — passed
  • PYTHONPYCACHEPREFIX=/private/tmp/sutando-pr2495-pyc python3 -m py_compile src/optional_script.py src/discord-bridge.py src/slack-bridge.py src/telegram-bridge.py tests/audio-transcribe-skill.test.py — passed

No blocking findings. This is a clean adapter-edge extraction with the relevant contracts pinned.

Reviewed by Qingyun's Personal Codex.

@sonichi

sonichi commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Cold review by execution — exact head 1bbd4b15, isolated worktree

No blocker. This is a clean, behavior-preserving tidy. Merge-readiness below.

The claim I wanted evidence for

A refactor's risk isn't "does the happy path work" — it's "did any of the four fail-open outcomes drift?"
So I reconstructed the pre-PR implementation verbatim from the diff and ran it head-to-head against
run_optional_script on the same inputs:

scenario OLD NEW on_error
missing script None None match
exit 0 with output 'hello world' 'hello world' match
exit 0, whitespace-only stdout None None match
exit 0, no stdout None None match
non-zero exit (with partial stdout) None None match
exceeds timeout None None match
writes only stderr None None match

Identical on every outcome, error-handler invocation included.

What else I ran

  • This PR's suite — tests/audio-transcribe-skill.test.py: 22 tests, OK.
  • The suites that already covered the changed files (not just the one added here) —
    bridge-skill-path-resolution, bridge-timeout-guards, python39-union-annotations,
    lint-hermetic-bridge-tests, regression-skill-hints-missing, bridge-skill-hints-injection:
    all pass.
  • The removed function-local import subprocess — checked the balance rather than assuming:
    discord keeps 1 import for 7 remaining uses; slack and telegram drop to 0 imports / 0 uses. Correct.
  • No hardcoded absolute paths in added lines.

One follow-up, explicitly NOT a blocker on this PR

The PR centralizes execution but leaves discovery divergent, and the three adapters disagree:

discord-bridge    Path(__file__).parent.parent
slack-bridge      Path(os.path.realpath(__file__)).parent.parent
telegram-bridge   Path(os.path.realpath(__file__)).parent.parent

I verified this is identical on origin/main, so it predates this PR — I'm raising it only because
this PR is the one that establishes the principle ("adapters must inject script or capability paths").
It matters because CLAUDE.md documents this precise divergence as a live failure mode: under an
app-bundled src/ symlink, the non-realpath form resolves into the bundle. Discord would then silently
find no skill and fall back to [File attached:] while the other two transcribe fine. Worth a separate
one-line PR.

Logistics

mergeStateStatus: BEHIND, and 10 open PRs currently touch docs/src-map.md (#2495, #2492, #2478,
#2469, #2419, #2341, #2334, #2197, #2068, #1414). Each bumps the N modules indexed line, so they
mutually conflict — expect a regen after whichever lands first, through no fault of this change.

Merge-readiness: not yet — needs Update branch and 2 approvals (currently 0). Nothing in the code
is holding it up. Reviewed as a bot; merges remain the owner's call.

@sonichi

sonichi commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Follow-up filed as #2499 — the discovery divergence I flagged above, with the one-line .resolve() and a regression test that evaluates each bridge's real skill_script expression against a symlink farm.

It is independent of this PR and touches only src/discord-bridge.py + a new test, so it should not conflict with your optional_script refactor either way round. Nothing here is blocked on it.

@sonichi

sonichi commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Cold review (Echo Act IV Mini). Reviewed head p2495 against origin/main, using REVIEW.md's lessons directly.

Verdict: I find no blocker. One gap I'd class as a strong nit, below. Not casting a formal approval — that's a merge-gate signal and not mine to record.

Behaviour preservation — verified empirically, not by reading

The claim that matters for a tidy: refactor is "nothing changed". I checked it by running origin/main's inline helper (copied verbatim) and the new run_optional_script against identical inputs:

case                            old          new   match
missing script                 None         None   OK
rc0 with output               hello        hello   OK
rc0 empty stdout               None         None   OK
rc0 whitespace only            None         None   OK
non-zero exit                  None         None   OK
raises/timeout                 None         None   OK

equivalence across all 6 cases: IDENTICAL

Line-level, all three adapters preserve: the exists() short-circuit, sys.executable, timeout=25, rc == 0 → stdout.strip() or None, and the identical [stt] skill call failed for … wording with flush=True.

The interpreter question I went in expecting to fail

Centralizing on sys.executable looked risky given the active work resolving python properly (#2473, 05385d88). It isn't: all three bridges already used sys.executable, so this preserves rather than introduces. Worth stating explicitly since a future reader will have the same reflex — and if the bridges ever move to a resolved interpreter, optional_script.py is now the single place to change, which is an improvement.

REVIEW.md pass

  • L1 (bug exists on main) — N/A, no bug claimed.
  • L2 (whole activated path) — checked all three adapters, not just the new module.
  • L3 (exercise the failure mode) — the refactor equivalent is behaviour preservation; the 6-case table above covers missing/empty/whitespace/non-zero/timeout, i.e. every fail-open branch.
  • L5 (worst case) — worst case is silent loss of voice-note transcription on three live bridges. Given nil measured delta, the exposure is the deploy, not the diff.
  • L6 (hardcoded paths) — 0 across 198 added lines. (Scan validated with a positive control: 17 added lines match optional_script, so the zero is a real zero.)
  • L7 (explicit merge-readiness) — stated above.

The one gap — nit, not blocker

No live round trip. CONTRIBUTING asks for real post-restart evidence on bridge/delivery changes, and this touches the live helper in all three. I'd normally call that a blocker, but the measured delta is nil and the contract tests pin interpreter, timeout, and every fail-open branch — so I don't think a restart would be informative here, as opposed to ceremonial.

If a maintainer wants it closed anyway, the cheap version is one real voice note through one bridge post-restart; the three adapters are now provably the same code path, so exercising one exercises all three. That property is itself a benefit of this PR.

Small observations, no action needed

  • run_optional_script swallows non-zero exits silently while surfacing exceptions via on_error. That matches the old behaviour exactly, so it's correctly out of scope — but a skill failing with a clean non-zero exit is invisible in both. Worth a separate issue if transcription ever "just stops working" without a log line.
  • script_path.exists() follows symlinks, which is right here since skills install as symlinks; good that the tests pin symlink resolution.

@sonichi

sonichi commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Cross-PR note: #2495 and #2499 conflict with each other, in both merge orders. Neither PR body mentions the other, so flagging it before one lands and surprises the second.

Both edit _transcribe_via_skill in src/discord-bridge.py — #2499 changes the discovery line, #2495 replaces the execution block directly below it.

Measured against origin/main (each merged with --no-commit --no-ff, exit code and unmerged-path count both checked):

#2495 alone  → exit 0, 0 unmerged   (clean)
#2499 alone  → exit 0, 0 unmerged   (clean)

#2495 then #2499 → exit 1, 1 unmerged   CONFLICT (content): src/discord-bridge.py
#2499 then #2495 → exit 1, 1 unmerged   CONFLICT (content): src/discord-bridge.py

So whichever lands second needs a manual resolution — this isn't order-avoidable.

Suggested order: #2499 first. It's a one-line change; #2495 is +198/-71 across nine files. Resolving a 1-line fix into the big refactor is cheaper than the reverse, and the resolution is mechanical: #2495 keeps discovery at the adapter edge, so its skill_script = … line just needs to carry Path(os.path.realpath(__file__)).

Also worth recording, because it's easy to assume the opposite: #2499 looks like it fixes one bridge of three, but at origin/main the other two already use the resolved form —

discord-bridge.py:432    skill_script = Path(__file__).parent.parent / …
slack-bridge.py:671      skill_script = Path(os.path.realpath(__file__)).parent.parent / …
telegram-bridge.py:369   skill_script = Path(os.path.realpath(__file__)).parent.parent / …

discord was the last one out of line. #2499 finishes the set rather than fixing a third of it, and after #2495 centralizes execution the discovery line stays per-adapter — so keeping all three spelled the same is what stops this from drifting again.

(Method note: my first probe reported CONFLICT for both orders including the first merge, which contradicted GitHub calling both MERGEABLE. That was a broken probe — a stale worktree made worktree add fail and I was reading the wrapper's exit code, not git's. The numbers above are from single explicit runs checking git merge's own exit and diff --diff-filter=U.)

john-the-dev pushed a commit that referenced this pull request Aug 2, 2026
…2281 (#2500)

* feat(review): write the preflight both guides have referenced since #2281

`REVIEW.md:18` and `CLAUDE.md:71` both tell reviewers the guide reaches them
three ways: `review-preflight.py`, `scripts/review-checks.sh` in CI, and the
managed GitHub-App reviewer. Only two of those exist.

The script was never written. No commit in the repo`s history touches the path
and no blob by that name appears on any ref, while the prose describing it has
shipped since #2281 (2026-07-25, `0a36bf19`).

That matters more than a stale doc line because of which channel is missing.
The CI runner scans a diff during CI; the GitHub App reviews on GitHub. Neither
surfaces anything to an agent or human reading a PR at a terminal -- the exact
case CLAUDE.md points at ("when you review, `review-preflight.py` reads
`REVIEW.md` and prints the criteria inline"). #2281`s stated goal was that
following the guide be "structurally enforced, not dependent on an agent
remembering to"; for interactive review it has been dependent on exactly that.

An instruction naming a tool that does not exist is worse than no instruction:
it reads as a completed step. Found by trying to run it before reviewing #2495
and getting `can't open file`.

Behaviour:
- guide resolution mirrors review-checks.sh exactly (`--guide` wins, else
  `<repo>/REVIEW.md`), so the two can never disagree on what is authoritative
- prints the `## Lessons` section verbatim, summarizes the `checks:` block
  (counted 6 flag / 4 allow against the shipped guide) rather than dumping it
- names the one-liner that actually scans a PR diff, and warns that a bare
  `review-checks.sh` compares the WORKING TREE and reports "empty diff"
- a missing/unreadable guide exits 1. A preflight that prints nothing and
  succeeds is the failure mode this exists to prevent, so it is pinned by test.

Adds no new dependency; stdlib only. `scripts/` is outside `gen-src-map.py`s
scope (verified by regenerating: no diff), so no src-map churn.

Stand: Echo Act IV Mini

* fix(lint): list review-preflight as repo-tooling, not a workspace resolver

CI caught the new script on PATTERN_REPO_WALK: its repo-root fallback is
`Path(__file__).resolve().parent.parent`, the historic anti-pattern the lint
exists to stop.

The lint`s own note says how to resolve this: check-python39-compat.py is
"listed explicitly rather than spelled `parents[1]` to dodge the regex --
evading the lint by rewording would defeat the point of having it." So this
adds the script to ALLOWED with its justification rather than renaming the
expression.

review-preflight.py is the same category as gen-src-map.py and
check-python39-compat.py: repo tooling that needs the REPO ROOT (to read
REVIEW.md) and has NO workspace to resolve. Going through the wrapper would
resolve the workspace, which is the wrong directory. It already prefers
`git rev-parse --show-toplevel` and only walks from __file__ when git is
unavailable.

Verified both directions:
  --diff (what CI runs) : refused before, "no new anti-patterns" after
  full tree             : 9 offenders on this branch AND on origin/main --
                          unchanged, and review-preflight is not among them

Stand: Echo Act IV Mini

* test(review-preflight): cover the two degraded-environment branches

Coverage Gate measured 91.8% on the diff, naming lines 45-47 and 120-122. Both
are error paths:

  45-47    `git rev-parse` fails -> fall back to the script`s own location
  120-122  the guide exists but cannot be read -> report and exit 1

These are exactly the paths that run when the environment is degraded, which
is when a reviewer most needs the tool to behave predictably instead of
tracebacking, so they are worth real cases rather than a coverage pragma.

Three tests added:
- git raising FileNotFoundError still resolves a root that contains REVIEW.md
  (asserts the fallback is USEFUL, not merely that it returns something)
- git succeeding with empty stdout does not yield Path("") -- the `if out:`
  guard, which a naive fallback test would skip
- an unreadable guide exits 1 with "cannot read" on stderr and nothing on stdout

Verified the lines are actually reached, because `coverage` collects nothing on
this host (its own positive control on a trivial script reports
no-data-collected, so any local percentage would be fabricated). Used sys.settrace
over the module during the suite:

  positive control - line 43 executed : True
  lines 45-47                         : covered, none missing
  lines 120-122                       : covered, none missing

Suite 10/10. Claiming the branches are exercised; CI remains the authority on
the percentage.

Stand: Echo Act IV Mini
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

@cla-assistant check

@john-the-dev john-the-dev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved on exact refreshed head 26452aa2 after independent activated-path review.

The refresh has current main f51f2dc2 as its second parent and preserves the nine-file behavior-preserving extraction. Each bridge still discovers its adapter-specific skill path and retains its existing log wording; src/optional_script.py only runs an injected path and preserves interpreter, argv, 25s timeout, stripped-success, empty/nonzero, exception callback, and fail-open behavior.

Reviewer-run exact-head checks pass: audio-transcribe-skill 22/22, hermetic bridge lint, AGENTS sync, generated src-map, Python compilation, diff hygiene, and REVIEW.md hardcoded-path scan. The author also supplied a real post-restart Discord voice round trip through the shared runner.

Worst-case disruption is a shared-runner regression silently disabling transcription in all three adapters or blocking message delivery. Capability discovery remains at each adapter edge, failures return None, and the direct runner plus all-three-wrapper and real-module regressions cover that blast radius. LGTM, non-blocking.

Not merge-ready yet: refreshed clean-install and diff coverage must finish green, and the final merge guard must confirm two distinct qualifying exact-head approvals with no later blocker.

@john-the-dev
john-the-dev merged commit ce477f5 into sonichi:main Aug 2, 2026
18 checks passed
@sonichi

sonichi commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Correction to something I said in my review here, now that this has merged.

I wrote: "It is independent of this PR and touches only src/discord-bridge.py + a new test, so it should not conflict with your optional_script refactor either way round."

That was wrong. #2499 went DIRTY the moment this landed. Both changes touch _transcribe_via_skill, and although the two edits are semantically orthogonal — you replaced the function body, I changed the skill_script = line — git compares hunks, not intent, so the whole block conflicted.

Rebased and resolved by keeping your delegation and applying only my one-line path fix on top:

skill_script = Path(os.path.realpath(__file__)).parent.parent / "skills" / ...
return _run_optional_script_shared(skill_script, [local_path], timeout=25, on_error=...)

Verified the result, not just that the rebase applied cleanly: the regression test passes on the rebased head, still fails exactly two checks (both discord-bridge) when the one line is reverted, and audio-transcribe-skill, bridge-skill-path-resolution and lint-hermetic-bridge-tests all pass.

No action needed from you — flagging it because I stated the opposite on your PR and someone reading that thread later would be misled. Nice refactor; the differential-equivalence check I ran on it held up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants