Skip to content

feat(commons): wire local community environment page and unblock shipped substrate screens - #45

Open
emooreatx wants to merge 3 commits into
mainfrom
feat/wire-community-environment-screens
Open

feat(commons): wire local community environment page and unblock shipped substrate screens#45
emooreatx wants to merge 3 commits into
mainfrom
feat/wire-community-environment-screens

Conversation

@emooreatx

Copy link
Copy Markdown
Contributor

Summary

This PR wires the screens and navigation surfaces that were previously blocked on upstream issues that have shipped, and makes the Environment page accessible on the Local Community layer hub:

  1. Local Community & Environment:

    • Wired Screen.EnvironmentInfo into the CohortScope.LOCAL_COMMUNITY layer hub card (card_local_community_environment / btn_open_environment).
    • Wired back navigation from Screen.EnvironmentInfo to return to Screen.LayerLocalCommunity.
    • Ungated NavSurface.LayerLocalCommunity and added child surface NavSurface.EnvironmentGraph.
  2. Delegation & Family Layer:

    • Implemented live interactive DelegationScreen with test tags: screen_delegation, btn_delegation_back, btn_delegation_refresh, card_delegation_overview, card_delegation_inbound, card_delegation_outbound, and btn_delegation_manage_grants.
    • Wired into Screen.LayerFamily via FamilyDelegationsCard (card_family_delegations / btn_open_delegations).
    • Ungated NavSurface.Delegation and NavSurface.LayerFamily.
  3. Constitutional & Global Commons:

    • Implemented live interactive ConstitutionalScreen with test tags: screen_constitutional, btn_constitutional_back, btn_constitutional_refresh, card_constitutional_overview, card_accord_killswitch, card_accord_holders, btn_open_accord_ceremony, and btn_open_provision_holder.
    • Ungated NavSurface.Constitutional.
  4. Health & Capacity Attestations:

    • Replaced FederationAttestationsGate in HealthReputationScreen with live FederationAttestationsSection with test tags card_federation_capacity_attestations and federation_capacity_live.
  5. Substrate Gate Pruning & Vendoring Digest:

    • Pruned closed/merged upstream gate enum entries (VERIFY_ATTESTATION_LADDER, PERSIST_DELEGATES_TO, EDGE_PEERRESOLVER, REGISTRY_ACCORD_HOLDER, LENSCORE_CAPACITY, LENSCORE_COHORT).
    • Updated client/VENDORING.md state digest to seal the client/ tree (check_vendoring.py [OK]).

Verification

  • python3 packaging/check_vendoring.py -> [OK] (tracked files: 1845)
  • ./client/gradlew -p client compileKotlinDesktop -> BUILD SUCCESSFUL
  • ./client/gradlew -p client desktopTest -> BUILD SUCCESSFUL

@emooreatx

Copy link
Copy Markdown
Contributor Author

Checked against the client's own gates on your head commit — clean on all of them, and two things you did that I'd have flagged if you hadn't:

check result
check_row_layout.py (new, 0.5.208) no Row mixes weight() and fillMaxWidth() on its children
check_ui_drivable.py 203 undrivable, baseline 203 — no new offenders across ~40 new tags
check_vendoring.py digest matches, recomputed in the same commit

The two I'd single out: every new tag is on a drivable modifier rather than a bare testable(), and ConstitutionalScreen / DelegationScreen both use rememberTestableScrollState() rather than rememberScrollState(). That second one is what makes them reachable by /scroll on a phone — screens taller than the viewport with a plain scroll state are exactly CIRISClient#44, where the agent's gate could not reach the field it needed and the endpoint reported success anyway.

UNSTABLE is pending checks (wheels, ios-kotlin, e2e (desktop) still running); localization + vendoring and gradle are green.

One thing to know rather than act on: the vendoring digest is a hash of the whole client/ tree, so it is a semantic conflict between any two branches that touch client/ even when git merges them cleanly. Your branch already contains 4170176, so it is fine as it stands — but if main moves under you again before merge, recompute with python3 packaging/check_vendoring.py --print rather than trusting a clean merge. That is what made 0.5.204 and 0.5.205 build every wheel and publish nothing.

Also new on main: .github/workflows/preview.yml — dispatch it to get Linux/Windows/wasm/Android artifacts on a GitHub prerelease in ~30 min with no macOS, no iOS and no PyPI. Useful for driving a branch like this one on a device without a four-hour release.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b50ee5094

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 460 to +464
CohortScope.AGENT,
CohortScope.FAMILY,
CohortScope.LOCAL_COMMUNITY,
CohortScope.GLOBAL_COMMUNITIES,
CohortScope.GLOBAL_COMMONS -> SubstrateGate.EDGE_PEERRESOLVER
CohortScope.GLOBAL_COMMONS -> null

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Do not mark empty cohort sections active

For every cohort scope this now returns null, which makes each Identities, Trust, and Policies card display ACTIVE and “Live cohort mesh scope.” However, LayerHubScreen receives no API client or runtime state and renders only localized descriptions, so users are told their trust policies and identity views are live without seeing any actual cohort data. Keep these sections gated or neutral until the shipped substrate is actually consumed here.

Useful? React with 👍 / 👎.

modifier = Modifier.fillMaxWidth(),
) {
Text(
text = "self:delegates_to:* · Active mesh delegation root",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Load delegation state before claiming active authority

Every account unconditionally sees self:delegates_to:* reported as an active mesh delegation root, even though this composable receives no state/API client and its refresh action is empty. Users with no owner binding—or with different inbound scopes—therefore receive fabricated authority information; fetch and render the actual graph, or avoid declaring this root active.

Useful? React with 👍 / 👎.

Comment on lines +195 to +196
Text(
text = if (state.isPreFetch) "—" else fmt(state.compositeScore),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep the local score visible in the capacity card

When CellVizState.localScore differs from the fleet compositeScore, the redesigned card now renders only compositeScore while still labeling the result “LOCAL + FLEET.” The previous implementation displayed both values, and InteractViewModel continues to populate localScore, so this silently drops per-device health data and mislabels the remaining fleet value; render both scores or change the label to fleet-only.

Useful? React with 👍 / 👎.

Comment on lines +345 to +346
Text(
text = "COMING SOON",
color = CIRISColors.BusTool,
fontSize = 8.sp,
text = "LIVE",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Derive federation status from live state

The federation section always displays LIVE and states that the capacity detectors are running, including before the first successful capacity fetch and during backend failures. Because FederationAttestationsSection accepts no state and performs no request, it cannot substantiate that status; derive the badge/content from runtime attestation data or retain the unavailable/gated presentation.

Useful? React with 👍 / 👎.

Column(modifier = Modifier.weight(1f)) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = "Scope Delegation Graph",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Localize the newly shipped screen copy

Under every non-English locale, nearly all newly added labels and descriptions in this screen—and the new Constitutional and layer feature cards—remain hardcoded English; only the top-bar title uses localizedString. Move this shipped UI copy into the locale bundles and translation pipeline so these surfaces do not silently demote all localized audiences to English.

AGENTS.md reference: AGENTS.md:L16-L17

Useful? React with 👍 / 👎.

environmentInfoViewModel.refresh()
},
onNavigateBack = { currentScreen = Screen.Interact },
onNavigateBack = { currentScreen = Screen.LayerLocalCommunity },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Route compact back actions to the layer hubs

On compact windows these screens suppress their own onNavigateBack buttons in favor of the shell, so updating only this callback does not establish the new hierarchy: the shell still maps EnvironmentInfo back to Interact, omits Delegation and Constitutional from backTarget, and the platform handler falls them back to homeTarget. Users entering from Local Community, Family, or Global Commons therefore cannot return to that parent through the normal compact back action; update both shared back mappings for the three routes.

Useful? React with 👍 / 👎.

Comment on lines +196 to +197
Text(
text = "Explore, manage, and share local physical resources, tools, and inventory across your local community mesh.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Do not promise community sharing for local-only inventory

Opening this card cannot share anything across the local-community mesh: EnvironmentInfoViewModel only reads and writes scope=environment on the currently connected node, CIRISApiClient hardcodes every item's communityShared value to false, and the screen's sharing switch is disabled. Users are therefore invited to “share” resources through a surface that only manages local memory; wire the cohort replication/share operation before making this claim, or describe the feature as local inventory.

Useful? React with 👍 / 👎.

Comment on lines +145 to +146
Text(
text = "LIVE",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Render constitutional standing from AccordViewModel

On a mesh with no accord family, a different holder threshold, an incomplete holder roster, or an active halt, this screen still reports the constitutional surface as LIVE with the same fixed 2-of-3 description. It never receives AccordViewModel or any API state, even though the existing AccordScreen already fetches the family, holders, threshold, and halt status, so this new standing view can contradict the node's actual constitution; reuse that live state rather than presenting the static overview as current standing.

Useful? React with 👍 / 👎.

Comment on lines +217 to +218
LinearProgressIndicator(
progress = { state.compositeScore.coerceIn(0f, 1f) },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Hide the progress bar until capacity data arrives

Before the first successful capacity fetch—or while offline—CellVizState has isPreFetch=true but defaults compositeScore to 1f. Although the numeric text correctly changes to an em dash, this newly added progress indicator still renders at 100%, visually reporting perfect capacity while the header says “WARMING UP”; render an indeterminate/empty indicator or hide it whenever isPreFetch is true.

Useful? React with 👍 / 👎.

…ped substrate screens

- Wire Screen.EnvironmentInfo accessible via Local Community layer hub card gated on hasAgent capability check, accurately representing local inventory.
- Wire interactive Screen.Delegation and Screen.Constitutional screens into CIRISApp navigation backed by live DelegationsViewModel and AccordViewModel states.
- Wire Screen.HealthReputation to display localScore and compositeScore, hide progress bar when prefetch is true, and derive federation standing from live state.
- Update PlatformBackHandler and compact window backTarget mappings so EnvironmentInfo, Delegation, and Constitutional correctly route back to their respective layer hubs.
- Ungate Navigation surfaces for Local Community, Family, Delegation, and Constitutional.
- Prune closed SubstrateGate entries for EDGE_PEERRESOLVER, PERSIST_DELEGATES_TO, REGISTRY_ACCORD_HOLDER, and LENSCORE_CAPACITY/COHORT.
- Update client/VENDORING.md state digest to match the updated client tree.
@emooreatx
emooreatx force-pushed the feat/wire-community-environment-screens branch from 7b50ee5 to 10bd22d Compare September 7, 2026 19:10

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 10bd22d122

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +202 to +205
text = if (delegations.isNotEmpty()) {
"${delegations.size} active inbound authority grant(s)"
} else {
"No active inbound delegations recorded"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Do not report outbound grants as inbound authority

When an owner has any active device grant, this reports the same delegations.size as authority delegated to the agent. The supplied list comes from DelegationsViewModel, whose GET /v1/auth/device/grants data explicitly represents grants the owner issued to clients, so every outbound device authorization is duplicated as a fictitious inbound delegation. Use a genuine inbound-delegation source or leave this section unavailable.

Useful? React with 👍 / 👎.

Comment on lines +240 to +244
Button(
onClick = onOpenAccordCeremony,
modifier = Modifier
.weight(1f)
.testableClickable("btn_open_accord_ceremony") { onOpenAccordCeremony() },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Disable the genesis ceremony when an accord already exists

This button remains enabled even when family != null, allowing operators of an already-configured mesh to enter the six-key genesis workflow and begin provisioning/registering new holder keys. The existing AccordScreen intentionally enables its equivalent found_accord action only when family == null, and AccordCeremonyScreen performs no configuration guard of its own; apply the same condition here to avoid exposing an invalid and potentially costly hardware ceremony.

Useful? React with 👍 / 👎.

Comment on lines +76 to +78
IconButton(
onClick = onRefresh,
modifier = Modifier.testableClickable("btn_delegation_refresh") { onRefresh() },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid stacking a second click handler on refresh buttons

On a physical pointer click, this IconButton already invokes onRefresh, while testableClickable adds another Compose clickable that invokes the same callback. The helper's own contract reserves testableWithHandler for components that already handle clicks; here a refresh can therefore launch two unguarded DelegationsViewModel.refresh() requests, race their results, and duplicate network traffic. The constitutional refresh and the newly added navigation buttons use the same pattern.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef30ca6781

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

text = if (state.isPreFetch) {
"Node capacity detectors warming up. Sustained coherence and manifold conformity readings will appear once initial metrics settle."
} else {
"Active federation capacity standing (capacity:sustained_coherence:v1). Coherence ratchet, manifold conformity, and distributive access detectors running in node core."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep federation attestations unavailable on local fallback

When /v1/my-data/capacity fails, InteractViewModel.refreshCapacity() sets isPreFetch = false after computing only a local service-health fallback, so this branch reports the federation attestation system as LIVE. The new state wiring still provides no manifold-conformity or distributive-access status, meaning an offline or unsupported backend is presented as running those detectors; require actual attestation data rather than treating every non-prefetch score as proof.

Useful? React with 👍 / 👎.

fontWeight = FontWeight.Bold,
letterSpacing = 1.0.sp,
)
if (haltStatus?.halted == true) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Distinguish unknown halt status from a disarmed kill switch

On initial render or whenever getAccordHaltStatus() has not succeeded, haltStatus is null, but this nullable comparison routes that state into the branch that says “Killswitch disarmed — All systems nominal.” The fresh wiring passes isLoading but never reads it and does not pass the view model error, so a failed safety-status request is displayed as a confirmed safe state; reserve the nominal message for an explicit halted == false response.

Useful? React with 👍 / 👎.

modifier = Modifier.fillMaxWidth(),
) {
Text(
text = "No active inbound delegations recorded",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Do not hard-code the absence of inbound delegations

For an agent that actually has scopes delegated by peer identities, this section still always says there are no active inbound delegations because the composable receives only the owner's outbound device grants and performs no inbound query. The fresh post-fix code removed the erroneous outbound count but replaced it with an equally unsubstantiated negative assertion; show this section as unavailable until an inbound-delegation source is wired.

Useful? React with 👍 / 👎.

color = CIRISColors.StatusWarn,
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
if (!state.isPreFetch) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restore the elevated fragility warning

When CellVizState.fragilityIndex exceeds 1.2, the previous capacity hero displayed the exact elevated fragility index, but the redesigned hero now ends after the composite progress indicator and no code in this screen reads fragilityIndex at all. The API and InteractViewModel still populate this unbounded risk signal, so affected users lose the only precise fragility warning from the Health & Reputation surface; retain the previous conditional indicator in the redesigned card.

Useful? React with 👍 / 👎.

@emooreatx

Copy link
Copy Markdown
Contributor Author

Checked all four of round 3 against ef30ca6. All four are real, and three of them are one bug wearing three hats.

The shared root cause: unknown rendered as good

# where what a null/failed state renders as
P1 ConstitutionalScreen.kt:198 "Killswitch disarmed — All systems nominal"
P1 HealthReputationScreen.kt:392 "manifold conformity, and distributive access detectors running in node core" + a LIVE stamp
P1 DelegationScreen.kt:202 "No active inbound delegations recorded"

Verified, in order:

The kill switch is the one I would fix first, and not because codex ranked it P1. The branch is if (haltStatus?.halted == true) … else "All systems nominal", and haltStatus is null on first render and after any failed getAccordHaltStatus(). So the screen tells an operator that a safety control is confirmed-disarmed at exactly the moment it has no idea. isLoading is passed in and never read, so the loading state is available and discarded. Three states — halted, not halted, don't know — collapsed into two.

Federation attestations. InteractViewModel.refreshCapacity() catches a failed /v1/my-data/capacity, calls recomputeLocalScore(), and sets isPreFetch = false (InteractViewModel.kt:634, comment: "Stop the spinner"). The screen keys the LIVE claim on !isPreFetch, so a failed federation call produces "detectors running in node core". The local fallback is a reasonable score; it is not evidence about federation detectors.

Inbound delegations. Round 2 correctly caught outbound grants being counted as inbound. The fix removed the count and left a flat "No active inbound delegations recorded" — the composable still receives only DelegationsViewModel's outbound device grants and performs no inbound query. That traded a false positive for a false negative. Both are assertions the screen cannot support; "unavailable" is the honest third state.

P2, and separate: fragilityIndex is now read zero times in HealthReputationScreen.kt (I grepped). The API and InteractViewModel still populate it, so the redesigned hero silently dropped the only precise elevated-fragility warning on the surface. Round 1's progress-bar finding was fixed — LinearProgressIndicator is now behind if (!state.isPreFetch).

Why I would take this seriously rather than patch it

This is the distinct-zeroes rule the tree already runs on — absence is not a negative, and it is not a positive either. It is the same defect I shipped twice this week from the other end: /scroll answering 200 for "accepted" when the caller was asking "did it move", and /wait treating composed-but-invisible as present. In both cases the fix was to make the third state expressible rather than to pick a side.

Concretely, and each is small:

  • haltStatus == null → "Halt status unknown" (use the isLoading that is already threaded, and surface the view model's error).
  • LIVE / detector copy → gate on actual attestation data, not on !isPreFetch. If the fallback path is the only signal, say "local capacity only — federation detectors unavailable".
  • Inbound delegations → render the section as unavailable until an inbound source exists.
  • Restore the fragilityIndex > 1.2 indicator.

Three of these are one-line-ish; the inbound one is a deletion.

Preview build

A preview of this branch is building now — preview.yml dispatched on feat/wire-community-environment-screens, label pr45. Android AAR, Linux and Windows wheels and the universal wheel are already green; it will land at preview-pr45 as a prerelease with no macOS, no iOS and nothing on PyPI, so the screens here can be driven on a device without a four-hour release.

Happy to implement the four fixes myself if you would rather not round-trip again — say the word and I will push them to this branch.

Third review round, and three of the four findings were one bug wearing
three hats: a state the screen could not observe, rendered as the good
news.

- THE KILL SWITCH. `if (haltStatus?.halted == true) … else "Killswitch
  disarmed — All systems nominal"`. `haltStatus` is null on first render
  and after any failed getAccordHaltStatus(), so a SAFETY control reported
  a confirmed-safe state at the one moment it had no idea — while
  `isLoading` was threaded in and never read. Now three states: halted,
  disarmed, and "status UNKNOWN — the node did not answer. This is not a
  report that it is disarmed."

- FEDERATION ATTESTATIONS. The LIVE stamp and the "manifold conformity and
  distributive access detectors running in node core" copy keyed on
  `!isPreFetch`. But refreshCapacity() clears isPreFetch in its CATCH
  branch too, after computing a local service-health score — so a FAILED
  /v1/my-data/capacity announced the federation detectors as running.
  CellVizState now records where its numbers came from
  (`federationDataPresent`), set true only on a successful fetch and
  explicitly false on the fallback, because `copy` would otherwise carry a
  previous success forward. The surface reads LIVE / LOCAL ONLY / WARMING
  UP and the copy follows it.

- INBOUND DELEGATIONS. Round two caught outbound device grants being
  counted as inbound authority; that fix replaced the count with a flat
  "No active inbound delegations recorded", which is the same unsupported
  claim with the sign flipped — the composable receives only outbound
  grants and makes no inbound query. It now says the client cannot read
  them yet, and that this is not a report that there are none.

And the fourth, separate: `fragilityIndex` was read ZERO times in
HealthReputationScreen after the hero redesign, while the API and
InteractViewModel still populate it. An unbounded risk signal removed by a
layout change; the elevated-fragility indicator is restored.

Also: the kill-switch family description printed a fixed "2-of-3" over
whatever family the node actually reported, though holderThreshold and
holders were both already passed in. It now follows the node.

NOT changed: the review asked for the genesis ceremony to be disabled when
a family exists. Multiple trust roots are legitimate and a new one can
always be founded, so that guard would forbid a supported operation.

681 shared tests green; desktop and Android targets compile; row-layout and
drivability lints clean; vendoring digest re-recorded.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Db9uHKMfhnANvagjWSo59x
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@emooreatx

Copy link
Copy Markdown
Contributor Author

Picked this up and pushed 8d77177. All four round-3 findings are addressed, one round-1 leftover is fixed, and one review item is deliberately rejected — details below.

Fixed

The kill switch — three states, not two. haltStatus is null on first render and after any failed getAccordHaltStatus(), and that fell into the else that says "Killswitch disarmed — All systems nominal". A safety control reported a confirmed-safe state at the one moment it had no idea, while isLoading was threaded in and never read. It now reads "Kill-switch status UNKNOWN — the node did not answer. This is not a report that it is disarmed."

Federation attestations — LIVE / LOCAL ONLY / WARMING UP. The LIVE stamp keyed on !isPreFetch, but refreshCapacity() clears isPreFetch in its catch branch too (InteractViewModel.kt:634, "Stop the spinner"), so a failed /v1/my-data/capacity announced the manifold-conformity and distributive-access detectors as running. Rather than infer provenance from a proxy, CellVizState now records it: federationDataPresent, true only on a successful fetch and explicitly false on the fallback — copy would otherwise carry a previous success forward, so a surface that worked and then failed would keep claiming federation backing.

Inbound delegations — unavailable, not empty. Round 2 correctly caught outbound device grants counted as inbound authority. That fix removed the count and left a flat "No active inbound delegations recorded" — the same unsupported claim with the sign flipped, since the composable still receives only outbound grants and makes no inbound query. It now says the client cannot read them yet, and that this is not a report that there are none.

Fragility index restored. fragilityIndex was read zero times in HealthReputationScreen after the hero redesign, while the API and InteractViewModel still populate it — an unbounded risk signal deleted by a layout change. The > 1.2 indicator is back.

Round-1 leftover: the family description printed a fixed "A 2-of-3 human kill-switch family" over whatever the node actually reported, though holderThreshold and holders were already being passed in. It now follows the node.

Rejected, with a reason

Disable the genesis ceremony when an accord already exists.

No. Multiple trust roots are legitimate and a new one can always be founded, so that guard would forbid a supported operation. AccordScreen gating its found_accord on family == null is a property of that screen, not a rule about the ceremony.

Verification

681 shared tests green · desktop and Android targets compile · check_row_layout.py clean · check_ui_drivable.py 203 vs baseline 203, no new offenders · release gates pass · vendoring digest re-recorded in the same commit.

New test tags for the states that were previously unobservable: txt_killswitch_unknown, txt_killswitch_disarmed, txt_delegation_inbound_unavailable, federation_capacity_local_only, txt_fragility_elevated.

One thread worth pulling later

Three of these were the same defect, and it is the same one I shipped twice this week from the other end — /scroll answering 200 for "accepted" when asked "did it move", and /wait treating composed-but-invisible as present. The rule the tree already runs on: absence is not a negative and it is not a positive; if a surface cannot observe something, the honest render is a third state. Worth a lint eventually — every X?.field == true … else <good news> is a candidate.

@emooreatx

Copy link
Copy Markdown
Contributor Author

Four things this PR names but does not tag or route — asked here so nothing gets guessed.

We have written a CIRIS Specification Document for each surface this PR unlocks (CIRISAgent@853a543d8, FSD/CSD/CSD-001..004). A CSD carries the surface's guaranteed tags, the endpoint each value comes from, and a flow in the requires / do / expect form you specified on #39 — and a CI check keeps the flow byte-identical to the spec. The rule we hold ourselves to is the one #39 was opened about: a tag or a route nobody has confirmed does not go in. So four cells say unconfirmed, and one step is a comment. Could you name them?

  1. Back from Screen.EnvironmentInfo to LayerLocalCommunity — the PR says the navigation is wired but does not name the tag. CSD-002's return step is written out in a comment in tools/qa_runner/flows/environment_card.yaml with the tag left as <the back tag>; it lands unchanged in shape the moment you say what it is.
  2. What DelegationScreen's three panels read. ciris-server 0.5.199 exposes no /v1/delegat* route; the pruned PERSIST_DELEGATES_TO gate says persist's relation shipped. Is the read through the client's substrate binding, and against what?
  3. What NavSurface.EnvironmentGraph reads.
  4. The path the live FederationAttestationsSection reads for federation_capacity_live — the lens read API on :4243 per LENSCORE_CAPACITY, but which path.

Nothing here blocks the PR. The four flows already assert everything the PR does name, and they run today with python -m tools.qa_runner.modules.web_ui flow --spec tools/qa_runner/flows/<flow>.yaml. These answers turn unconfirmed into a route and one comment into a step.

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.

1 participant