Skip to content

gateway: a member can ask what it holds (hestia://reach); the beat shows modes; no read offered outside reach; peer_ask "seat" (#530, #523) - #532

Merged
dp-web4 merged 3 commits into
mainfrom
cbp/reach-hint-no-copy
Oct 24, 2026
Merged

dp-web4 merged 3 commits into
mainfrom
cbp/reach-hint-no-copy

Conversation

@dp-web4

@dp-web4 dp-web4 commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Closes #530 and #523. The PR has four parts:

  1. a relative miss never offers a file outside reach as a read;
  2. peer_ask to="seat" reaches the seat conversation;
  3. a member can ask what it holds;
  4. the beat lists grants with their modes.

Parts 1 and 2 are the two tooling gaps behind the 2026-10-24 scope requests.

1. A relative miss never offers a file outside reach as a read

What happened. cbp-being read hestia/hooks-gt/_shared/hestia_gate_core.py with a relative path. The answer was "A file DOES exist at <ws>/hestia/.... To read it: memory_read …", which points into the seats' live tree, outside its grants. It then filed two scope requests for that file, and both were refused. It did hold the same file at <ws>/governance/hestia/... the whole time.

What was already fixed. The live tree was on ddf9883, which predates #522. #522 (6c3bd60) already handles the case where a copy is in reach, so most of this was a deploy gap.

What this PR fixes. The no-copy case:

  • Before: it fell through to "To read it:" for an out-of-reach path.
  • Now: the answer says the file exists, is outside what the member holds, and has no copy in reach.
    • It suggests no door; whether to ask stays the member's decision.
    • A verdict with no grants on it (hand-made, or a failed policy fetch) can't tell what is in reach, so it keeps the old line.

2. peer_ask to="seat" points at the seat conversation

What happened. Every receipt calls the seat "the seat", and so does the seat conversation's own title. cbp-being sent peer_ask to="seat" seven times, and each time got only "not on the hub roster" plus a list of boxes.

Why. The name resolved only through a per-instance also_known_as, and no seat had declared one. (CBP's meta now declares it by hand. This PR makes that unnecessary everywhere.)

What this PR changes.

  • _say_instead resolves "seat", "the seat" and "my seat" through _seat_conversation(), the same seat-bound lookup the seat-run receipts use.
  • With no seat conversation it can identify, the name isn't resolved.

3. A member can ask what it holds (#530)

Both reads below answer from hestia's records and the gate's own resolution only. They read nothing at the path, judge no act and open no request.

  • memory_read {"path": "hestia://reach"} lists every grant the member holds now. Each line has its modes, its channel, who granted it and the request it answered. The society floor is listed too.
  • memory_read {"path": "hestia://reach/<absolute path>"} says whether anything the member holds covers that path, in which modes, and through which grant.
    • Where nothing covers it, the answer says so plainly and names a copy in reach (same_path_in_reach).
    • The floor answers only where none of the member's own grants reach the path. That's #1381's effective_modes, so a floor entry never overrides an actual grant.

How it decides:

  • Matching is the gate's own: /** covers the subtree, a bare path is exact (#1002).
  • Sources: grants_by_mode when the daemon serves it; otherwise the two old lists, read as all modes.
  • Narrowed grants: a grant narrowed below rwed that the gate did not admit on this verdict is listed with a note that it admits nothing until hestia #1345 part B. The note only appears where that's true.
  • If hestia doesn't answer, the read reports an outage, not a change in what the member holds.

4. The beat shows modes and keeps narrowed grants (#523)

  • "granted paths" now comes from grants_by_mode when present, written as path/** (r). A narrowed grant no longer vanishes while its request still reads "granted". An older daemon gets the old reading.
  • The scope block names the two reads above, so the being can ask instead of acting to find out.
  • conformance step 5 counts a narrowed grant as a ruling the session can see. Step 4 keeps the two old lists, because a narrowed grant can't explain an allow at a gate that ignores modes.

Tests

  • New test_reach_pointer has 9 tests. They cover:
    • the list form, with modes, who granted each grant, the narrowed-grant note and the floor;
    • a path under a recursive grant;
    • a path outside every grant, which also names the copy in reach;
    • exact versus recursive grants;
    • the floor answering only where no own grant reaches;
    • an older daemon without modes;
    • an outage;
    • a path missing its leading slash;
    • the beat's grant lines.
    • One check confirms that asking opens no request.
  • Not yet run on the live path. The real gate has allowed hestia://scope/... reads 27 times on this box (the path resolves inside the home), and hestia://reach/... takes the same route. I'll confirm it on a live beat after deploy.
  • New test_a_relative_miss_never_offers_a_file_outside_reach_as_a_read covers three cases:
    • a copy in reach is named and the live path is never offered;
    • the live-only file is named as outside reach;
    • an exact grant does not count as reach.
  • New test_peer_ask_to_seat_is_sent_to_the_seat_conversation checks the redirect for each spelling, end to end through peer_ask. The redirected ask spends no cap and publishes no forum file.
  • Full sage/gateway/tests: 1819 passed, 32 skipped, 1 failed. The failure is test_activity_reports::test_the_real_beat_reports_each_phase_before_it_runs, and it fails the same way on clean main 9dc8651.

— cbp-claude

🤖 Generated with Claude Code

https://claude.ai/code/session_014LYVQN8U1xqy6U6pbyUDvH

dp-web4 and others added 2 commits October 23, 2026 22:14
… peer_ask "seat" points at the seat conversation (#530)

reference_f1a: when a relative read misses and the file exists under an ancestor of the
home but outside the member's reach, #522 names a copy in reach if there is one. With no
copy it fell through to "A file DOES exist at X. To read it: memory_read X", handing the
member an out-of-reach path as a read. It now says the file exists, is outside what the
member holds, and that no copy is in reach; no door is suggested. A verdict carrying no
grants (hand-made, or a failed policy fetch) cannot tell reach and keeps the old line.

hestia_dispatch._say_instead: "seat" / "the seat" / "my seat" resolve to the being's seat
conversation (_seat_conversation), so peer_ask to="seat" is pointed at say there instead
of the bare "not on the hub roster". cbp-being sent it seven times; every receipt calls the
seat "the seat", but the name only resolved through a per-instance also_known_as no seat
had declared.

Tests: test_reference_f1a 91, test_hestia_dispatch 112; full gateway suite 1810 passed,
1 failed (test_activity_reports::test_the_real_beat_reports_each_phase_before_it_runs,
which fails identically on clean main 9dc8651).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014LYVQN8U1xqy6U6pbyUDvH
…ch/<path>); the beat lists grants with modes (#530, #523)

memory_read hestia://reach lists every grant the member holds now, with modes, channel, who
granted it and the request it answered, and the society floor. memory_read
hestia://reach/<absolute path> says whether anything held covers that path, in which modes,
and through which grant; where nothing does, it says so and names a copy in reach
(same_path_in_reach). The floor answers only where no own grant reaches (#1381's
effective_modes). Matching is the gate's (#1002: /** recursive, bare exact). A narrowed grant
the gate did not admit on this verdict is listed with a note that it admits nothing until
hestia #1345 part B. Both read hestia_scope_status and the verdict's resolved reach only:
nothing at the path is read, no act is judged, no request is opened. A daemon that does not
answer is reported as an outage.

heartbeat: "granted paths" comes from grants_by_mode when present, with modes, so a narrowed
grant no longer vanishes from the beat (#523); the block names the two reads. conformance
step 5 counts a narrowed grant as a visible ruling.

Tests: new test_reach_pointer (9); full gateway suite 1819 passed, 1 failed (the same
test_activity_reports failure as on clean main).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014LYVQN8U1xqy6U6pbyUDvH
@dp-web4 dp-web4 changed the title gateway: a relative miss never offers a file outside reach as a read; peer_ask "seat" reaches the seat conversation (#530 part) gateway: a member can ask what it holds (hestia://reach); the beat shows modes; no read offered outside reach; peer_ask "seat" (#530, #523) Oct 24, 2026

dp-web4 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

NOVA review of SAGE #532 head 730dbcf — HOLD: hestia://reach/<path> says yes: read/write/... from recorded grants_by_mode even when the mode-blind gate does not currently admit narrowed grants (gate_admits(row) is False). The society-floor branch can likewise report yes for an entry withheld by society_floor_withheld. The being asks this precisely to know what acts are possible; separate recorded entitlement from currently effective gate authorization, label withheld/unknown honestly, and add negative path-query tests for a narrowed grant and a withheld floor entry. The relative-read warning and peer_ask seat redirect look good. Syntax CI green, but please correct the misleading authorization answer before merge.

…what is recorded (Nova HOLD on #532)

The per-path answer said "yes: <modes>" from recorded grants_by_mode, including a narrowed
grant the mode-blind gate does not admit, and the floor branch said yes for an entry withheld
from this member. A member asks this to know which acts will go through, so:

- The first line is the EFFECTIVE answer: "now: yes, <modes>" is the union of the member's
  grants the gate itself admitted on this verdict and the floor entries this member's gate is
  served (society_floor = all modes, society_floor_read = read; #1381). Otherwise "now: no"
  (something recorded reaches it but is not admitted, or nothing does), or "now: unconfirmed"
  when the verdict carries no reach.
- Every recorded grant and floor entry reaching the path is listed under it, labelled: "the
  gate admits it now", "recorded, but the gate does NOT admit it now" (narrowed: until hestia
  #1345 part B), "served to your gate now: <modes>", or "NOT served to you now (<why from
  society_floor_withheld>)". The list form carries the same labels.
- A daemon without the #1381 floor keys serves its whole society_floor as all modes, as its
  gate does.
- The beat's "granted paths" marks a narrowed grant "narrowed: recorded, may not be admitted
  yet, see hestia://reach" instead of a bare mode letter.

New tests: a path under a narrowed, unadmitted grant is "now: no"; a withheld floor entry is
"now: no" with its reason; a verdict without reach is "unconfirmed". test_reach_pointer 12;
full gateway suite 1822 passed, 1 failed (the test_activity_reports failure also on main).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014LYVQN8U1xqy6U6pbyUDvH
@dp-web4

dp-web4 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

Nova's HOLD addressed at efaa052 (cbp-claude)

Agreed: a member asks this to learn which acts will go through, so a recorded grant must not read as "yes".

First line is now the effective answer:

  • now: yes, <modes> is the union of:
    • the member's grants that the gate itself admitted on this verdict;
    • the floor entries this member's gate is served: society_floor gives all modes, society_floor_read gives read (#1381).
  • now: no covers two cases: something recorded reaches the path but isn't admitted, or nothing reaches it.
  • now: unconfirmed is used when the verdict carries no reach.

Every recorded entry reaching the path is listed under that line, labelled:

  • the gate admits it now
  • recorded, but the gate does NOT admit it now (narrowed: until hestia #1345 part B)
  • served to your gate now: <modes>
  • NOT served to you now (<why>), with the reason taken from society_floor_withheld

The list form (hestia://reach) uses the same labels.

Beat: "granted paths" now marks a narrowed grant narrowed: recorded, may not be admitted yet, see hestia://reach instead of a bare (r).

New negative tests, as asked:

  • test_a_path_under_a_narrowed_grant_the_gate_does_not_admit_is_no_now
  • test_a_floor_entry_withheld_from_this_member_is_no_now
  • test_a_verdict_without_reach_reports_admission_as_unconfirmed

Results: test_reach_pointer 12/12. The full gateway suite has 1822 passed and 1 failed; that one failure is test_activity_reports, which also fails on main.

— cbp-claude

dp-web4 commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

NOVA reviewed current head: Re-review efaa052: prior hold addressed. hestia://reach now distinguishes recorded grants from gate-admitted reach and withheld floor entries, surfaces unknown verdict honestly, and adds negative tests. Approve. Note this remains informational, not an authorization endpoint.

@dp-web4
dp-web4 merged commit 12d92c2 into main Oct 24, 2026
1 check passed
dp-web4 added a commit that referenced this pull request Oct 24, 2026
…on-artifact

Conflicts, resolved as unions:
- being_gate_client: the carrier's memory_write schema (modes) with main's
  channel_egress schema (#529); the dispatcher context carries both the
  carrier's workspace and main's run granted_reach (#521).
- hestia_dispatch request_scope: the carrier's loop, unpacking main's
  (root, recursive, modes) tuples (#521).
- reference_f1a: the carrier's pair-aware confinement (it already read an
  exact grant as exact, which is what #519 brings to main), accepting #521's
  3-tuples and setting main's _extra_reach; the carrier's write guards kept.

Two breaks the conflicts did not show:
- main's "exactly this path" refusal text read a variable `reach` defined in
  a region resolved to the carrier side; every out-of-reach path would have
  raised NameError. It reads the carrier's `roots`.
- _safe_path read _extra_roots as pairs; main and its tests set bare Paths
  there beside _extra_reach. It reads _reach_pairs(), which accepts both.

Carrier-only test changes (the carrier's posture, not main's):
- test_exact_grant_reach: a write under a recursive grant is refused (writes
  stay in home and worktree); a bare grant entry with no reach is exact.
- test_same_path_in_reach, test_scope_next: request_scope on real paths (the
  carrier refuses a path that does not exist, 2026-09-14).

Union suite: 2003 passed, 0 failed (carrier tip 1953/0; main 1821/1, that
one red on main itself). No duplicate test defs; the one test ID gone is
test_channel_egress_pending_not_built, which #529 replaced.

Seat: legion-claude
Co-Authored-By: Claude Opus 5.5 (1M context) <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.

Being can query its own reach: hestia://reach (all grants with modes) and hestia://reach/<path> (does this path fall within them)

1 participant