Skip to content

fix(rpc): source the shell error catalogue from dig-rpc-protocol so -32004 carries one name - #494

Merged
MichaelTaylor3d merged 6 commits into
mainfrom
loop/478-error-name-drift
Sep 2, 2026
Merged

fix(rpc): source the shell error catalogue from dig-rpc-protocol so -32004 carries one name#494
MichaelTaylor3d merged 6 commits into
mainfrom
loop/478-error-name-drift

Conversation

@MichaelTaylor3d

@MichaelTaylor3d MichaelTaylor3d commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Closes #478

What changed

dig-node-service's ErrorCode now SOURCES its number and machine string from
dig_rpc_protocol::ErrorCode for every code the two share, instead of restating them. This
extends the pattern already used in the same file for three wallet codes.

  • -32004 is RESOURCE_UNAVAILABLE everywhere: the enum variant is renamed to
    ResourceUnavailable and the hand-written arms in code() / name() are gone.
  • Its catalogued origin becomes node, not upstream — see below.
  • The same sourcing covers -32700, -32600, -32601, -32602, -32010, -32030, -32031,
    -32032.
  • -32060 PEER_PING_REFUSED untouched, per the issue.

The issue's premise, re-measured — and why this needs no cascade

The issue expected a released-wire-name collision requiring an alias in dig-rpc-protocol.
Measured on origin/main, that is not the situation:

  • RESOURCE_NOT_AVAILABLE_AT_ROOT has zero producers and zero consumers. Every -32004 frame
    dig-node emits is minted in dig-node-core and framed by seams/dig_rpc/errors.rs::error_object,
    which derives data.code from dig_rpc_protocol::ErrorCode — so it has always carried
    RESOURCE_UNAVAILABLE. The long name existed only in meta.rs and in a test that pinned it.
  • Consumers match numerically or on RESOURCE_UNAVAILABLE (dig-dns, dig-sdk); docs.dig.net already
    publishes RESOURCE_UNAVAILABLE.

So this was a discovery-document lie, not a wire break: a client generated from rpc.discover
would match "RESOURCE_NOT_AVAILABLE_AT_ROOT" and never match anything. Real under §6.2 — the
catalogue is a contract — but no live client is affected, and no dig-rpc-protocol release and no
release-first cascade is required
. The two names denote the same condition (the crate's own
description for ResourceUnavailable is literally "Resource not available at the requested root"),
and the layer distinction is already carried by the separate data.origin field.

No alias and no compatibility period: an alias would add public surface for a name with no producers
and no consumers, institutionalising the drift. SYSTEM.md's 0.9.0-yank precedent governs names that
actually shipped on the wire; this one never did.

The origin fix

The catalogue claimed -32004 has origin: "upstream", but the node library mints -32004 locally
on an ordinary miss (dig.fetchRange "resource not held", dig.getManifest "capsule not held
locally"), and SPEC.md already admitted both. Unlike the name, data.origin IS on the wire and IS
derived per-frame by the minter — so the catalogue value is the default a client should expect from
this node, and it may not say upstream for a code this node mints itself. Set to node; the
per-frame value stays authoritative, and the SPEC row now says so.

DispatchFailed / -32000 — EXCLUDED, and filed rather than renamed

Judged fresh rather than swept in, and it is the opposite case to -32004:

  • DISPATCH_FAILED is on the wire — rpc.rs:67-77 puts code.name() into error.data.code, and
    server.rs mints ErrorCode::DispatchFailed at two sites.
  • dig-node-core mints no -32000 under ServerError (grep returns nothing), so unlike -32004
    there is no second name reaching the same client. The shell's catalogue and the shell's frames agree.

Renaming it to the crate's generic SERVER_ERROR would therefore be a genuine released-wire-name
change of exactly the class the dig-rpc-protocol 0.9.0 yank records. Left alone, excluded from the
sourcing with a comment at both code() and name() explaining why, and split out as #496.

Blast radius

gitnexus's dig-node index is ~301 commits stale and returns a false-safe impactedCount: 0, so this
was measured with ripgrep + direct reads, stated per §2.0's fallback clause.

ResourceNotAvailableAtRoot occurred in exactly two files — crates/dig-node-service/src/meta.rs
(6 sites) and tests/openrpc_drift_guard.rs — plus one doc comment in dig-node-core/src/lib.rs:240
and four SPEC.md passages. All are in this diff; a repo-wide grep for the old name now returns only
the two deliberate mentions in the inverted test's own prose. Nothing outside dig-node referenced it.

Tests

crates/dig-node-service/tests/openrpc_drift_guard.rs:

  • shell_error_names_match_the_shared_catalogue — the INVARIANT, not a list: for every variant in
    meta::ErrorCode::all() whose number dig_rpc_protocol::ErrorCode::ALL also declares, the shell's
    .name() must equal the crate's machine_code(). It also asserts it checked at least 7 codes, so a
    future change that empties the intersection cannot make it pass vacuously. DispatchFailed is the
    one documented exclusion.
  • the_catalogued_name_for_32004_is_the_name_the_node_emits — the EMITTED FRAME, not the
    catalogue: drives a real -32004 out of handle_rpc on an empty ephemeral node (hermetic, no
    network) and asserts error.data.code == "RESOURCE_UNAVAILABLE", then asserts the catalogue entry
    for -32004 carries that same string. Comparing the two artefacts is what makes it a decision test
    rather than a presence test.
  • reconciled_error_codes_are_catalogued_with_correct_origin was inverted — it pinned the defect.

Recorded pre-fix failure (tests written and run BEFORE the meta.rs change):

test shell_error_names_match_the_shared_catalogue ... FAILED
test the_catalogued_name_for_32004_is_the_name_the_node_emits ... FAILED
  left: String("RESOURCE_NOT_AVAILABLE_AT_ROOT")
 right: String("RESOURCE_UNAVAILABLE")
test result: FAILED. 8 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out

Both failed on the real defect, and the second one is the measurement that establishes the frame
carries RESOURCE_UNAVAILABLE today.

After:

cargo test -p dig-node-service --test openrpc_drift_guard
  test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
cargo test -p dig-node-service --lib
  test result: ok. 747 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

0 filtered out in each — the assertions ran rather than being filtered away.

A full cargo test -p dig-node-service (all integration targets) could not be completed on this host:
it fails during LINKING with link.exe … 0xc000012d and a run of rustc ICEs, on a 19 GB target tree
with several sibling lanes building concurrently. That is a host-resource failure, not a compile error
in this diff — the same tree builds and passes when targets are built individually. CI is the honest
measurement of the remaining targets.

Docs / SPEC

Version

0.235.0 → 0.237.0. Minor: the published discovery document changes a machine name and an origin
value, which is a compatible extension for a name nothing emitted, but not a silent patch. 0.236.0 is
claimed by a sibling lane.

…32004 carries one name

The shell published `RESOURCE_NOT_AVAILABLE_AT_ROOT` for -32004 while every frame the
node emits carries `RESOURCE_UNAVAILABLE` — a generated client would match a name no
frame has ever had. The long name had zero producers, so this is a discovery-document
lie rather than a wire break, and no dig-rpc-protocol change is needed.

Every code the shell shares with the contract crate now takes its number and machine
string from `dig_rpc_protocol::ErrorCode` instead of restating it. -32000 is excluded
and tracked on #496: the shell mints DISPATCH_FAILED itself, so that name IS on the wire.

The catalogued origin for -32004 becomes `node`: the node library mints it on an
ordinary local miss, so claiming `upstream` was a second untruth in the same row.

Closes #478
@MichaelTaylor3d

Copy link
Copy Markdown
Contributor Author

docs.dig.net sweep, full-tree denominator (the body cites the docs/+i18n/ scoped figure of 14):

  • RESOURCE_NOT_AVAILABLE_AT_ROOTzero files, whole repo, not just docs/+i18n/.
  • RESOURCE_UNAVAILABLE — 119 files whole-repo (14 under docs/+i18n/; the rest are build output and translation artifacts).

Both numbers agree on the load-bearing claim: nothing in docs.dig.net publishes the name this PR removes, so §4.3 needs no docs change.

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor Author

loop-reviewer — IN PROGRESS, not the verdict

Head audited: 375cf44. gitnexus dig-node index is ~300 commits stale (false-safe zeros), so blast
radius was measured with ripgrep + direct reads per §2.0's fallback clause.

Confirmed so far:

  • Sourcing is real. crates/dig-node-service/src/meta.rs:790-806 (code()) and :831-849
    (name()) delegate to dig_rpc_protocol::ErrorCode for all nine shared codes; -32000 is
    excluded with the reason stated at both arms.
  • No surviving rival. Repo-wide grep for RESOURCE_NOT_AVAILABLE_AT_ROOT /
    ResourceNotAvailableAtRoot returns only the two deliberate mentions inside the inverted test's
    own prose and its negative assertion (openrpc_drift_guard.rs:149, :172). Nothing in production
    code. dig-node-core's LOCAL_WIRE_CODES (lib.rs:5203) is a pre-existing test-only table that
    already maps both -32004 consts to RESOURCE_UNAVAILABLE — it agrees and is out of scope.
  • §2.4b spot-check clean. dig-rpc-protocol latest published is 0.10.2; the new dev-dep
    (crates/dig-node-service/Cargo.toml:305) is "0.10", the same line the shell compiles against
    at :161, so the guard cannot compare against a different catalogue.
  • SPEC.md :96-101, :971-976, :1184, :3197 all updated in this PR; the #477 hedges are
    gone and the table row reads RESOURCE_UNAVAILABLE / node. The PR body records the docs.dig.net
    sweep by name (14 files carry RESOURCE_UNAVAILABLE, zero carry the old name).

One finding is forming on meta.rs:914 (a literal \n + 17 spaces inside a published catalogue
description). Verdict follows once the suite result is in.

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor Author

loop-security: IN PROGRESS — not the verdict

Audited head: 375cf44f085fcd585f5a4551b87f6eb8ccac8411 (resolved from gh pr view 494 --json headRefOid).
Note: gitnexus + socraticode MCP both failed to connect this session (CONNECT_TIMEOUT), so blast radius
is by grep + direct read against my own worktree, not by impact.

Cleared so far

1. No numeric re-mapping. No auth code silently re-coded. The primary risk of sourcing code() from a
shared crate is that a sourced discriminant differs from the value it replaced, silently re-coding a
refusal. It does not. Every discriminant in dig-rpc-protocol 0.10.2 src/error.rs equals the constant
it replaced, checked one by one:

variant old hardcoded (meta.rs) dig-rpc-protocol 0.10.2
ParseError -32700 error.rs:101 -32700
InvalidRequest -32600 error.rs:103 -32600
MethodNotFound -32601 error.rs:105 -32601
InvalidParams -32602 error.rs:107 -32602
ResourceUnavailable -32004 error.rs:124 -32004
UpstreamError -32010 error.rs:151 -32010
Unauthorized -32030 error.rs:230 -32030
NotSupported -32031 error.rs:232 -32031
ControlError -32032 error.rs:234 -32032

Unauthorized is the one that would matter most and it is unchanged in both code and name — a
control-plane auth refusal still renders -32030 / UNAUTHORIZED, not a retryable
RESOURCE_UNAVAILABLE. -32000 DISPATCH_FAILED is deliberately left hardcoded rather than taking the
crate's SERVER_ERROR name, which is the right call: sourcing it would have been an unannounced
shipped-name change on the wire.

2. Machine names are byte-identical except the intended rename. error.rs:262-288 yields
PARSE_ERROR, INVALID_REQUEST, METHOD_NOT_FOUND, INVALID_PARAMS, UPSTREAM_ERROR, UNAUTHORIZED,
NOT_SUPPORTED, CONTROL_ERROR — identical to the strings deleted from meta.rs. Only -32004 changes
name, which is the point of the PR.

3. Dependency is clean. dig-rpc-protocol resolves to exactly ONE line — Cargo.lock:3187-3190,
version 0.10.2, source = "registry+https://github.com/rust-lang/crates.io-index" with a checksum. Not a
git = dep. The new [dev-dependencies] entry (crates/dig-node-service/Cargo.toml:305) is "0.10",
caret-compatible with dig-node-core's "0.10.2", and the single lock entry confirms both resolve to the
same crate — so the drift guard cannot compare against a different catalogue than the shell compiles
against, which is what that pin was for. Cargo.lock gained no other entries.

Still open: whether origin() changing -32004 from "upstream" to "node" alters real minted frames
(it is called at mint time in rpc.rs:74, control.rs:758, meta.rs:1202, :1218, not only in the
catalogue), the drift guard's own strength, and one string-literal defect I am still confirming.

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor Author

loop-security: PASS

Audited head: 375cf44f085fcd585f5a4551b87f6eb8ccac8411 — resolved from
gh pr view 494 --json headRefOid at both the start and the end of this audit; it did not move.
Checks on that head: 15 SUCCESS, 1 SKIPPED. PR still draft; I have not merged or undrafted.

No security defect in this diff. It is a pure name/number re-sourcing with no new logic, no new
branch, and no new I/O. Detail per area, with the one non-gating quality defect at the bottom.

Cleared

1. No numeric re-mapping — the main risk, and it is absent. Sourcing code() from a shared crate
could silently re-code a refusal. It does not: every discriminant in dig-rpc-protocol 0.10.2
src/error.rs equals the constant it replaced (-32700/-32600/-32601/-32602/-32004/-32010/
-32030/-32031/-32032, table in my earlier interim comment). Unauthorized is unchanged in both
number and name
(error.rs:230 = -32030, error.rs:286 = UNAUTHORIZED), so a control-plane auth
refusal still renders -32030 UNAUTHORIZED and cannot present as a retryable RESOURCE_UNAVAILABLE a
client would loop on. No code is derived from untrusted input — meta.rs code()/name()/origin()
are pure const/match over a closed enum with no argument.

2. The rename fails closed, and breaks no known consumer. git grep for the wire string
RESOURCE_NOT_AVAILABLE_AT_ROOT across dig-app, digs, dig-chrome-extension, dig-rpc, dig-download and
dig-sdk returns zero hits; the only occurrences were in dig-node itself and are gone from shipped
src at this head. A hypothetical client that did match the old name loses its match arm but the
numeric -32004 is unchanged, so it degrades to generic error handling — an error stays an error.

3. No new leakage. data.origin is a coarse three-value label (node/upstream/shell) — no
paths, addresses, peer ids or wallet state, before or after. The only rendered text that changed is the
-32004 description. The origin flip from upstream to node is document-only:
ErrorCode::ResourceUnavailable appears solely inside meta.rs's catalogue functions
(:798,:840,:900,:914,:973) and is never passed to rpc_error() (rpc.rs:74) or control_error()
(control.rs:758), so no live frame's data.origin changes. SPEC.md:3197 states the relayed case
still carries origin: upstream, which matches the code.

4. Dependency is clean. Exactly ONE dig-rpc-protocol line — Cargo.lock:3187-3190, 0.10.2,
source = "registry+…crates.io-index" with a checksum, not git =. The new dev-dep
(crates/dig-node-service/Cargo.toml:305, "0.10") is caret-compatible with dig-node-core's "0.10.2"
and resolves to that same single entry, so the guard cannot compare against a different catalogue than
the shell compiles against. Cargo.lock gained no entries at all — the only changed line is the
dig-node-service version — so no second line of any dig-*/chia-* family is dragged in.

5. No new panics on a peer-reachable path. Zero unwrap/expect/panic! added to shipped src; the
only .expect() calls are in tests/openrpc_drift_guard.rs, which is dev-only. control_cli.rs is not
touched, so no cleartext-logging surface changed.

6. The guard is not vacuous. shell_error_names_match_the_shared_catalogue carries a checked >= 7
floor, and the_catalogued_name_for_32004_is_the_name_the_node_emits drives a REAL -32004 out of an
ephemeral node and asserts the emitted data.code equals the catalogue entry — comparing two artefacts
rather than letting the catalogue agree with itself.

7. -32000 left unsourced is the right call. Taking the crate's SERVER_ERROR would have been an
unannounced shipped-name change on the wire. It is excluded from the guard deliberately and documented
in both meta.rs and SPEC.md.

Non-gating — LOW, quality, hand to the correctness gate

crates/dig-node-service/src/meta.rs:915 — the new -32004 description embeds a literal \n escape
followed by 17 spaces inside a single-line Rust string literal. Verified byte-level with cat -A:

...at the requested root M-bM-^@M-^T a genuine \n                 content miss, whether...

In Rust that is an actual newline character plus the spaces, not a line continuation (a continuation
is a trailing backslash at end-of-line, which strips both the newline and the leading whitespace). So
the machine-readable catalogue published at /.well-known/dig-node.json, /openrpc.json and
rpc.discover carries a message with an embedded newline and a run of spaces in it.

Not a security finding and I am not gating on it: serde_json escapes the newline, so there is no
injection or frame-splitting vector — it is malformed prose in a machine-consumable document. Fix is
one line (collapse to a single space, or use a real trailing-backslash continuation).

Scope I did not cover

I did not compile or run the suite — the diff introduces no logic and CI is green on this exact head.
gitnexus and socraticode MCP both failed to connect this session (CONNECT_TIMEOUT), so blast radius is
by git grep + direct read rather than impact; given the changed surface is a closed enum with all
call sites inside one file, I consider that adequate coverage here. Work was done in my own detached
worktree at C:/tmp/worktrees/gate494s, now removed; no shared checkout was touched and I made no
commits.

@MichaelTaylor3d MichaelTaylor3d left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

loop-reviewer correctness gate on head 375cf44 — one GATING finding, inline. Everything else in the diff checks out; see the interim comment for per-item evidence.

Comment thread crates/dig-node-service/src/meta.rs Outdated
@MichaelTaylor3d

Copy link
Copy Markdown
Contributor Author

loop-reviewer — VERDICT: CHANGES-REQUIRED

Audited head: 375cf44f085fcd585f5a4551b87f6eb8ccac8411 (resolved from the remote, not from the
dispatch brief). Correctness gate only; a loop-security gate runs separately on the same head.

One gating finding, posted inline on crates/dig-node-service/src/meta.rs:915: the -32004
description() literal contains a \n escape plus 17 spaces on a single source line, and
description() is published as the discovery document's message (meta.rs:1052, :1201, :1217).
Confirmed with cat -A. Cheap to fix; everything else in the PR is sound.

Per-item evidence:

  1. fix(rpc): -32004 carries two different machine names across the shell/engine boundary #478 acceptance — met. meta.rs:790-806 / :831-849 source number and machine name from
    dig_rpc_protocol::ErrorCode for all nine shared codes; the variant is ResourceUnavailable;
    -32060 PEER_PING_REFUSED untouched as the issue required. The issue floated an alias in
    dig-rpc-protocol; the PR instead measures that the old name had zero producers and zero
    consumers and reconciles directly. That is better evidence than the issue's premise, and it
    matches decide: -32000 is DISPATCH_FAILED in the shell and SERVER_ERROR in the contract crate #496's RESOURCE_UNAVAILABLE decision. -32000 correctly excluded with the reason stated
    at both arms and split out as decide: -32000 is DISPATCH_FAILED in the shell and SERVER_ERROR in the contract crate #496 (which is open and still a decision).
  2. No rival copy. Repo-wide grep for the old name/variant returns only the inverted test's prose
    and its negative assertion (openrpc_drift_guard.rs:149, :172). dig-node-core's
    LOCAL_WIRE_CODES (lib.rs:5203-5212) is a pre-existing TEST-only table that already maps both
    -32004 consts to RESOURCE_UNAVAILABLE — it agrees and is out of scope. Non-gating, noted for a
    follow-up: fix(rpc): -32004 carries two different machine names across the shell/engine boundary #478's context also named dig-node-core's control_err (-32030/31/32) as a fourth
    undelegated copy; it is not in this diff and not in the issue's Scope paragraph.
  3. Tests not vacuous. shell_error_names_match_the_shared_catalogue asserts an INVARIANT over the
    intersection with a checked >= 7 floor, so it cannot pass on an emptied set; reverting the
    name() sourcing puts "RESOURCE_NOT_AVAILABLE_AT_ROOT" back against the crate's
    machine_code() and the assertion fails. the_catalogued_name_for_32004_is_the_name_the_node_emits
    compares the EMITTED frame against the catalogue rather than the catalogue against itself, so it
    fails under the same revert from the other side. The PR's recorded pre-fix run shows both red on
    the real defect.
    Local run blocked, stated rather than claimed: cargo test -p dig-node-service --test openrpc_drift_guard in this worktree dies at LINK : fatal error LNK1102: out of memory — a host
    resource failure, not this diff. Test + coverage is green on 375cf44 (run 33571041278) and is
    the honest measurement.
  4. SPEC/docs — done in the same unit. SPEC.md:96-101, :971-976, :1184, :3197; the fix(rpc): mint error frames from the taxonomy so data.code and data.origin are present #477
    hedges are gone and the table row reads RESOURCE_UNAVAILABLE / node. The docs.dig.net sweep is
    stated by name in the PR body (14 files carry the new name, zero carry the old) — §4.3 satisfied.
    The origin: upstream → node change is argued correctly: the per-frame value stays authoritative
    and the catalogue may not claim upstream for a code this node mints locally.
  5. §2.4b spot-check clean. dig-rpc-protocol latest published is 0.10.2; the new dev-dep
    (Cargo.toml:305) is "0.10", the same line the shell already compiles against at :161, so the
    guard cannot compare against a different catalogue than the code under test.

Blast radius measured with ripgrep + direct reads — the gitnexus dig-node index is ~300 commits stale
and returns false-safe zeros (§2.0 fallback).

Re-gate scope when the finding lands: the one-line literal only. No other leg needs re-running.

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor Author

Scoped re-gate IN PROGRESS — not the verdict

head read: afa6ae7916c076b43e3320e1c5f4a9f163c2f348 (resolved from gh pr view 494 --json headRefOid).

Confirmed so far:

  1. Branch-only delta is scoped. git diff --stat $(git merge-base origin/main afa6ae7) afa6ae7 touches 7 files: Cargo.toml, Cargo.lock, SPEC.md, crates/dig-node-core/src/lib.rs (1 line), crates/dig-node-service/Cargo.toml (+5, the dig-rpc-protocol dep), crates/dig-node-service/src/meta.rs, crates/dig-node-service/tests/openrpc_drift_guard.rs. Everything else in 375cf44..afa6ae7 arrives via three origin/main merges. git merge-base --is-ancestor origin/main afa6ae7 → branch contains main.
  2. The gating \n is gone. meta.rs:914-920 now renders the message via concat! of three fragments; a repo-wide grep for a literal escape in a meta.rs string returns only doc-comment hits.
  3. A test exercises it, twice. meta.rs:1243 pins the exact rendered text, and meta.rs:1259 closes the class over ErrorCode::all() (which includes ResourceUnavailable, meta.rs:977), refusing any control character or run of two spaces in any catalogued description(). The prior defect — literal newline plus source indentation — fails both.
  4. Version gate. Cargo.toml 0.246.0 at head, Cargo.lock dig-node-service 0.246.0, origin/main 0.245.0.

Note on provenance, non-gating: the fix and the bump were applied inside merge-commit conflict resolutions (b539dc45 and 29fed3f8), not as their own commits, so git log --no-merges on the delta shows nothing. Content is correct; recording it because it makes the fix invisible to a log-only read.

Remaining: confirming the two new tests actually run green locally. Verdict follows.

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor Author

VERDICT: PASS (scoped re-gate)

head read: afa6ae7916c076b43e3320e1c5f4a9f163c2f348 — resolved from gh pr view 494 --json headRefOid, not from the dispatch brief.

Scope of this pass, per §1.10: the round-1 gating finding, the delta since 375cf44, and the version gate. The rest of the diff was cleared at 375cf44 (loop-security PASS) and was not re-audited.

1. The delta is only the fix, the merges, and the bump

git diff --stat $(git merge-base origin/main afa6ae7) afa6ae7 — 7 files, all in scope:

file change
crates/dig-node-service/src/meta.rs the catalogue sourcing + the fix + 2 new tests
crates/dig-node-service/tests/openrpc_drift_guard.rs catalogue/frame guards
crates/dig-node-service/Cargo.toml dig-rpc-protocol = "0.10" added to [dev-dependencies], pinned to the same line as the normal dep
crates/dig-node-core/src/lib.rs one doc line, RESOURCE_NOT_AVAILABLE_AT_ROOT -> RESOURCE_UNAVAILABLE
SPEC.md error-table rename
Cargo.toml / Cargo.lock 0.245.0 -> 0.246.0

Everything else in 375cf44..afa6ae7 comes in through three origin/main merges (b539dc45, 29fed3f8, afa6ae79). git merge-base --is-ancestor origin/main afa6ae7 succeeds, so the branch is not behind.

2. The gating finding is genuinely fixed, and a test discriminates

crates/dig-node-service/src/meta.rs:914-920 renders the message as a concat! of three fragments — no backslash continuation, so nothing for a re-wrap to rejoin into a control character.

Two tests, and both would fail under the defect (a literal \n followed by source indentation):

  • meta.rs:1243 resource_unavailable_description_is_one_line_of_exact_published_text — pins the RENDERED bytes, using \u{2014} for the em dash rather than the raw character.
  • meta.rs:1259 no_catalogued_description_carries_a_control_character_or_run_of_spaces — iterates ErrorCode::all() (which contains ResourceUnavailable, meta.rs:977) and refuses both a control character and a run of two spaces. This closes the CLASS, not the instance, which is the right shape: the next re-wrap of any other message fails too.

Ran locally in a detached worktree at this head: cargo test -p dig-node-service --lib meta::tests -> 18 passed, 0 failed, 758 filtered out, both new tests present by name in the output. The count is non-zero, so the assertions actually executed.

Not done, and stated rather than implied: I did not perform a revert-proof (restoring the old literal and watching it go red) — that is an 11-minute rebuild for a property readable from the assertions themselves, since a literal newline is char::is_control and the following indentation is a run of spaces.

3. Version gate

Cargo.toml [workspace.package] version = "0.246.0" (:35), Cargo.lock dig-node-service version = "0.246.0" (:3034), origin/main at 0.245.0. Consistent and incrementing.

Non-gating note

The fix and the bump were applied inside merge-commit conflict resolutions (b539dc45 for the string, 29fed3f8 for the version), not as their own commits — so git log --no-merges 375cf44..afa6ae7 shows nothing and a log-only read of this PR would conclude nothing changed. The content is correct; recording it so the next reader does not mistake the empty log for an unfixed finding. No action required.

Merge remains the orchestrator's, and this PR is still a draft.

@MichaelTaylor3d
MichaelTaylor3d marked this pull request as ready for review September 2, 2026 10:44
@MichaelTaylor3d
MichaelTaylor3d merged commit b9979d8 into main Sep 2, 2026
15 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the loop/478-error-name-drift branch September 2, 2026 10:44
MichaelTaylor3d added a commit that referenced this pull request Sep 2, 2026
origin/main advanced to b9979d8 (#494, the shell error catalogue). Only the
workspace version and Cargo.lock conflicted; #494 touches no file this branch
does. The pre-assigned 0.248.0 is kept and the lock re-resolved from main's.

Subject is `chore:` and not `merge:` deliberately: `merge` is not in this repo's
commitlint type-enum, and the three earlier merge commits on this branch were
rewritten for the same reason.

Co-Authored-By: Claude <noreply@anthropic.com>
MichaelTaylor3d added a commit that referenced this pull request Sep 2, 2026
…0.250.0

Main moved to 0.246.0 while this branch was being fixed. Same two conflicts as
the previous merge and the same resolution: Cargo.toml keeps only the assigned
0.250.0 (every other hunk of main verbatim), Cargo.lock taken from origin/main
then `cargo update -w --offline`, which relocked one package. No source
conflicts; SPEC.md auto-merged.

Co-Authored-By: Claude <noreply@anthropic.com>
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.

fix(rpc): -32004 carries two different machine names across the shell/engine boundary

1 participant