Complete local coordination view switching and record remaining blockers
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e3b8-9815-70f2-9ac5-37bcde2c5090
This commit is contained in:
parent
6923d4bfd0
commit
b47dd43b04
7 changed files with 227 additions and 55 deletions
|
|
@ -11,10 +11,10 @@
|
|||
| workplan | RAIL-FAB-WP-0025 | finished | — | workplans/RAIL-FAB-WP-0025-rail-rapp-reef-fabric-adaptation.md |
|
||||
| workplan | RAIL-FAB-WP-0026 | finished | — | workplans/RAIL-FAB-WP-0026-repo-family-relation-projection.md |
|
||||
| workplan | RAIL-FAB-WP-0027 | finished | — | workplans/RAIL-FAB-WP-0027-versioned-rail-readiness-projection.md |
|
||||
| workplan | RAIL-FAB-WP-0028 | proposed | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| workplan | RAIL-FAB-WP-0029 | proposed | — | workplans/RAIL-FAB-WP-0029-coordination-graph-perspective.md |
|
||||
| workplan | RAIL-FAB-WP-0028 | blocked | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| workplan | RAIL-FAB-WP-0029 | blocked | — | workplans/RAIL-FAB-WP-0029-coordination-graph-perspective.md |
|
||||
| workplan | RAIL-FAB-WP-0030 | finished | — | workplans/RAIL-FAB-WP-0030-flavor-and-depends-on-graph.md |
|
||||
| workplan | RAIL-FAB-WP-0031 | active | — | workplans/RAIL-FAB-WP-0031-flex-auth-access-engine-rename.md |
|
||||
| workplan | RAIL-FAB-WP-0031 | blocked | — | workplans/RAIL-FAB-WP-0031-flex-auth-access-engine-rename.md |
|
||||
| task | RAIL-FAB-WP-0025-T01 | done | — | workplans/RAIL-FAB-WP-0025-rail-rapp-reef-fabric-adaptation.md |
|
||||
| task | RAIL-FAB-WP-0025-T02 | done | — | workplans/RAIL-FAB-WP-0025-rail-rapp-reef-fabric-adaptation.md |
|
||||
| task | RAIL-FAB-WP-0025-T03 | done | — | workplans/RAIL-FAB-WP-0025-rail-rapp-reef-fabric-adaptation.md |
|
||||
|
|
@ -26,11 +26,11 @@
|
|||
| task | RAIL-FAB-WP-0027-T02 | done | — | workplans/RAIL-FAB-WP-0027-versioned-rail-readiness-projection.md |
|
||||
| task | RAIL-FAB-WP-0027-T03 | done | — | workplans/RAIL-FAB-WP-0027-versioned-rail-readiness-projection.md |
|
||||
| task | RAIL-FAB-WP-0027-T04 | done | — | workplans/RAIL-FAB-WP-0027-versioned-rail-readiness-projection.md |
|
||||
| task | RAIL-FAB-WP-0028-T01 | todo | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| task | RAIL-FAB-WP-0028-T02 | todo | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| task | RAIL-FAB-WP-0028-T03 | todo | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| task | RAIL-FAB-WP-0028-T04 | todo | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| task | RAIL-FAB-WP-0029-T01 | todo | — | workplans/RAIL-FAB-WP-0029-coordination-graph-perspective.md |
|
||||
| task | RAIL-FAB-WP-0028-T01 | wait | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| task | RAIL-FAB-WP-0028-T02 | wait | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| task | RAIL-FAB-WP-0028-T03 | wait | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| task | RAIL-FAB-WP-0028-T04 | wait | — | workplans/RAIL-FAB-WP-0028-hosted-financial-fabric-authority.md |
|
||||
| task | RAIL-FAB-WP-0029-T01 | wait | — | workplans/RAIL-FAB-WP-0029-coordination-graph-perspective.md |
|
||||
| task | RAIL-FAB-WP-0030-T01 | done | — | workplans/RAIL-FAB-WP-0030-flavor-and-depends-on-graph.md |
|
||||
| task | RAIL-FAB-WP-0030-T02 | done | — | workplans/RAIL-FAB-WP-0030-flavor-and-depends-on-graph.md |
|
||||
| task | RAIL-FAB-WP-0030-T03 | done | — | workplans/RAIL-FAB-WP-0030-flavor-and-depends-on-graph.md |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Coordination graph (workplans and waits)
|
||||
|
||||
State Hub owns workplans. Fabric does not author them. This view *projects*
|
||||
Repository files own workplans; State Hub indexes them. The Fabric explorer does not edit them. This view *projects*
|
||||
open workplans and open tasks into the existing graph explorer so chokepoints
|
||||
are inspectable.
|
||||
|
||||
|
|
@ -48,3 +48,15 @@ Chokepoint size is in-degree of **visible** (by default: non-residual)
|
|||
workplan nodes from `depends_on` and remaining `waits_on` edges.
|
||||
|
||||
Solid blue = indexed `depends_on`. Dashed amber = citation `waits_on`.
|
||||
|
||||
## Switching views
|
||||
|
||||
The mode selector switches between topology and coordination in the same page.
|
||||
Residual visibility refreshes the coordination payload and is retained in the
|
||||
shareable URL. A failed refresh leaves the prior graph visible and shows an
|
||||
error; an empty result can still be switched back to topology. Graph-specific
|
||||
rules, selection, and zone placement reset when replacing the dataset.
|
||||
|
||||
The registry route is available locally. Hosted acceptance remains blocked by
|
||||
RAIL-FAB-WP-0028's runtime, persistence, access, and deployment decisions; this
|
||||
UI change does not establish a production authority.
|
||||
|
|
|
|||
|
|
@ -568,8 +568,8 @@ def graph_explorer_page() -> str:
|
|||
(() => {
|
||||
const manifestUrl = "/exports/graph-explorer/manifest";
|
||||
const pageParams = new URLSearchParams(window.location.search);
|
||||
const graphMode = pageParams.get("mode");
|
||||
const includeResidualsParam = ["1", "true", "yes"].includes(
|
||||
let graphMode = pageParams.get("mode") === "coordination" ? "coordination" : "full";
|
||||
let includeResidualsParam = ["1", "true", "yes"].includes(
|
||||
(pageParams.get("include_residuals") || "").toLowerCase()
|
||||
);
|
||||
const graphUrl = graphMode === "coordination"
|
||||
|
|
@ -2141,6 +2141,7 @@ def graph_explorer_page() -> str:
|
|||
const state = currentViewState();
|
||||
if (state.search) params.set("search", state.search);
|
||||
if (state.mode && state.mode !== "full") params.set("mode", state.mode);
|
||||
if (state.mode === "coordination" && includeResidualsParam) params.set("include_residuals", "true");
|
||||
if (state.layout && state.layout !== "cose") params.set("layout", state.layout);
|
||||
if (state.labelMode && state.labelMode !== "auto") params.set("labelMode", state.labelMode);
|
||||
if (state.nodeTypes.length !== allNodeTypes.length) params.set("nodeTypes", state.nodeTypes.join(","));
|
||||
|
|
@ -2201,6 +2202,10 @@ def graph_explorer_page() -> str:
|
|||
};
|
||||
|
||||
const applyViewState = (state, options = {}) => {
|
||||
if (cy && "mode" in state && ((state.mode === "coordination") !== (graphMode === "coordination"))) {
|
||||
switchGraph(state.mode, includeResidualsParam, state);
|
||||
return;
|
||||
}
|
||||
if ("search" in state) searchInput.value = state.search || "";
|
||||
if ("mode" in state) modeSelect.value = optionExists(modeSelect, state.mode) ? state.mode : "full";
|
||||
if ("layout" in state) layoutSelect.value = optionExists(layoutSelect, state.layout) ? state.layout : "cose";
|
||||
|
|
@ -2828,11 +2833,7 @@ def graph_explorer_page() -> str:
|
|||
residualsWrap.style.display = coordinationActive ? "" : "none";
|
||||
residualsToggle.checked = includeResidualsParam;
|
||||
residualsToggle.addEventListener("change", () => {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("mode", "coordination");
|
||||
if (residualsToggle.checked) url.searchParams.set("include_residuals", "true");
|
||||
else url.searchParams.delete("include_residuals");
|
||||
window.location.search = url.search;
|
||||
switchGraph("coordination", residualsToggle.checked);
|
||||
});
|
||||
}
|
||||
profiles = loadProfiles();
|
||||
|
|
@ -2841,12 +2842,6 @@ def graph_explorer_page() -> str:
|
|||
...element,
|
||||
data: {...element.data, color: layerColors[element.data.layer] || "#667085"}
|
||||
}));
|
||||
if (elements.length === 0) {
|
||||
canvas.innerHTML = "<p class='canvas-notice'>No graph entities were returned by the registry.</p>";
|
||||
counts.textContent = "0 nodes / 0 edges";
|
||||
hiddenSummary.textContent = "Hidden 0";
|
||||
return;
|
||||
}
|
||||
canvas.innerHTML = "";
|
||||
cy = cytoscape({
|
||||
container: canvas,
|
||||
|
|
@ -2975,6 +2970,69 @@ def graph_explorer_page() -> str:
|
|||
applyViewState(urlState, {skipUrl: true});
|
||||
runLayout();
|
||||
updateUrlState();
|
||||
if (!elements.length) profileSummary.textContent = "No graph entities were returned by the registry.";
|
||||
};
|
||||
|
||||
let graphRequest = 0;
|
||||
const switchGraph = async (mode, includeResiduals = includeResidualsParam, viewState = null) => {
|
||||
const request = ++graphRequest;
|
||||
const coordination = mode === "coordination";
|
||||
const url = coordination
|
||||
? `/exports/graph-explorer?mode=coordination${includeResiduals ? "&include_residuals=true" : ""}`
|
||||
: "/exports/graph-explorer";
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
const payload = await response.json();
|
||||
if (!Array.isArray(payload.elements)) throw new Error("Invalid graph response");
|
||||
if (request !== graphRequest) return;
|
||||
const elements = payload.elements.map((element) => ({
|
||||
...element,
|
||||
data: {...element.data, color: layerColors[element.data.layer] || "#667085"}
|
||||
}));
|
||||
graphMode = coordination ? "coordination" : "full";
|
||||
includeResidualsParam = includeResiduals;
|
||||
activeMode = mode;
|
||||
modeSelect.value = mode;
|
||||
document.getElementById("include-residuals-wrap").style.display = coordination ? "" : "none";
|
||||
document.getElementById("include-residuals").checked = includeResiduals;
|
||||
selected = null;
|
||||
selectedAnchor = null;
|
||||
selectedZoneId = "";
|
||||
focusSet = null;
|
||||
manualOverrides = {};
|
||||
filterRules = [];
|
||||
editingRuleId = "";
|
||||
collapsedZoneSnapshots.clear();
|
||||
zoneContainerState.clear();
|
||||
zoneSummaries.clear();
|
||||
currentProfileId = "";
|
||||
profileSelect.value = "";
|
||||
allEdgeTypes = [...new Set(elements.map(({data}) => data.edgeType).filter(Boolean))].sort();
|
||||
renderChecklist(nodeTypeFilter, allNodeTypes, nodeTypeLabels, "node-type");
|
||||
renderChecklist(edgeTypeFilter, allEdgeTypes, {}, "edge-type");
|
||||
cy.elements().remove();
|
||||
cy.add(elements);
|
||||
popup.style.display = "none";
|
||||
refreshRuleBuilder();
|
||||
renderRules();
|
||||
syncFilterSummaries();
|
||||
if (viewState) applyViewState(viewState);
|
||||
else {
|
||||
applyFilters();
|
||||
runLayout();
|
||||
updateUrlState();
|
||||
}
|
||||
showDetails(null);
|
||||
updateProfileControls();
|
||||
updateProfileSummary();
|
||||
if (!elements.length) profileSummary.textContent = "No graph entities were returned by the registry.";
|
||||
} catch (error) {
|
||||
if (request !== graphRequest) return;
|
||||
modeSelect.value = activeMode;
|
||||
document.getElementById("include-residuals").checked = includeResidualsParam;
|
||||
profileSummary.textContent = `Could not load graph: ${error.message}`;
|
||||
}
|
||||
};
|
||||
|
||||
const handleFilterChange = () => {
|
||||
|
|
@ -2992,27 +3050,14 @@ def graph_explorer_page() -> str:
|
|||
nodeTypeFilter.addEventListener("change", handleFilterChange);
|
||||
edgeTypeFilter.addEventListener("change", handleFilterChange);
|
||||
modeSelect.addEventListener("input", () => {
|
||||
if (modeSelect.value === "coordination" && graphMode !== "coordination") {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("mode", "coordination");
|
||||
window.location.search = url.search;
|
||||
const mode = modeSelect.value || "full";
|
||||
if ((mode === "coordination") !== (graphMode === "coordination")) {
|
||||
switchGraph(mode);
|
||||
return;
|
||||
}
|
||||
if (graphMode === "coordination" && modeSelect.value !== "coordination") {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.delete("mode");
|
||||
url.searchParams.delete("include_residuals");
|
||||
window.location.search = url.search;
|
||||
return;
|
||||
}
|
||||
activeMode = modeSelect.value || "full";
|
||||
focusSet = null;
|
||||
currentProfileId = "";
|
||||
profileSelect.value = "";
|
||||
applyFilters();
|
||||
updateProfileControls();
|
||||
updateProfileSummary();
|
||||
updateUrlState();
|
||||
graphRequest += 1;
|
||||
activeMode = mode;
|
||||
handleFilterChange();
|
||||
});
|
||||
layoutSelect.addEventListener("input", () => {
|
||||
currentProfileId = "";
|
||||
|
|
@ -3179,8 +3224,8 @@ def graph_explorer_page() -> str:
|
|||
document.querySelector("[data-action='focus']").addEventListener("click", applyFocus);
|
||||
document.querySelector("[data-action='clear']").addEventListener("click", () => {
|
||||
searchInput.value = "";
|
||||
modeSelect.value = "full";
|
||||
activeMode = "full";
|
||||
modeSelect.value = graphMode;
|
||||
activeMode = graphMode;
|
||||
labelSelect.value = "auto";
|
||||
activeLabelMode = "auto";
|
||||
zoneBoundaryToggle.checked = true;
|
||||
|
|
|
|||
70
tests/test_graph_mode_switch.py
Normal file
70
tests/test_graph_mode_switch.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
"""Execute the browser transition against a small graph/DOM harness."""
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
import pytest
|
||||
|
||||
from railiance_fabric.graph_explorer_ui import graph_explorer_page
|
||||
|
||||
|
||||
def test_graph_switch_replaces_data_and_retains_previous_graph_on_failure(tmp_path):
|
||||
if not shutil.which("node"):
|
||||
pytest.skip("Node.js is required for the UI transition test")
|
||||
page = graph_explorer_page()
|
||||
transition = page.split(" let graphRequest = 0;", 1)[1].split(
|
||||
" const handleFilterChange", 1
|
||||
)[0]
|
||||
script = r'''
|
||||
const assert = require("node:assert/strict");
|
||||
let graphMode = "full", includeResidualsParam = false, activeMode = "full";
|
||||
let selected, selectedAnchor, selectedZoneId, focusSet, manualOverrides, filterRules;
|
||||
let editingRuleId, currentProfileId, allEdgeTypes;
|
||||
const layerColors = {}, allNodeTypes = [], nodeTypeLabels = {};
|
||||
const collapsedZoneSnapshots = new Map(), zoneContainerState = new Map(), zoneSummaries = new Map();
|
||||
const modeSelect = {}, profileSelect = {}, nodeTypeFilter = {}, edgeTypeFilter = {};
|
||||
const popup = {style: {}}, profileSummary = {};
|
||||
const controls = {};
|
||||
const document = {getElementById(id) {return controls[id] ||= {style: {}};}};
|
||||
let data = [{data: {id: "old"}}], urls = [], updated = 0;
|
||||
const cy = {elements: () => ({remove() {data = [];}}), add(elements) {data.push(...elements);}};
|
||||
const renderChecklist = () => {}, refreshRuleBuilder = () => {}, renderRules = () => {};
|
||||
const syncFilterSummaries = () => {}, applyFilters = () => {}, runLayout = () => {};
|
||||
const updateUrlState = () => {updated++;}, showDetails = () => {};
|
||||
const updateProfileControls = () => {}, updateProfileSummary = () => {};
|
||||
const applyViewState = () => {};
|
||||
let response = {ok: true, json: async () => ({elements: [{data: {id: "workplan:a"}}]})};
|
||||
let fetch = async (url) => {urls.push(url); return response;};
|
||||
let graphRequest = 0;
|
||||
'''
|
||||
script += transition + r'''
|
||||
(async () => {
|
||||
await switchGraph("coordination", true);
|
||||
assert.equal(data[0].data.id, "workplan:a");
|
||||
assert.equal(modeSelect.value, "coordination");
|
||||
assert.equal(controls["include-residuals-wrap"].style.display, "");
|
||||
assert.match(urls[0], /include_residuals=true/);
|
||||
response = {ok: false, status: 503};
|
||||
await switchGraph("full");
|
||||
assert.equal(data[0].data.id, "workplan:a");
|
||||
assert.equal(modeSelect.value, "coordination");
|
||||
assert.match(profileSummary.textContent, /503/);
|
||||
response = {ok: true, json: async () => ({elements: []})};
|
||||
await switchGraph("by-access-zone");
|
||||
assert.deepEqual(data, []);
|
||||
assert.equal(activeMode, "by-access-zone");
|
||||
assert.equal(graphMode, "full");
|
||||
assert.equal(controls["include-residuals-wrap"].style.display, "none");
|
||||
let resolveOld;
|
||||
fetch = () => new Promise(resolve => {resolveOld = resolve;});
|
||||
const oldRequest = switchGraph("coordination");
|
||||
fetch = async () => ({ok: true, json: async () => ({elements: [{data: {id: "latest"}}]})});
|
||||
await switchGraph("full");
|
||||
resolveOld({ok: true, json: async () => ({elements: [{data: {id: "stale"}}]})});
|
||||
await oldRequest;
|
||||
assert.equal(data[0].data.id, "latest");
|
||||
assert.equal(updated, 3);
|
||||
})().catch(error => {console.error(error); process.exitCode = 1;});
|
||||
'''
|
||||
path = tmp_path / "switch.cjs"
|
||||
path.write_text(script)
|
||||
subprocess.run(["node", str(path)], check=True, capture_output=True, text=True)
|
||||
|
|
@ -4,14 +4,14 @@ type: workplan
|
|||
title: "Host and operate the financial Fabric authority"
|
||||
domain: financials
|
||||
repo: railiance-fabric
|
||||
status: proposed
|
||||
status: blocked
|
||||
flavor: residual
|
||||
origin: residual
|
||||
origin_ref: STATE-WP-0079
|
||||
owner: codex
|
||||
topic_slug: railiance
|
||||
created: "2026-08-31"
|
||||
updated: "2026-09-22"
|
||||
updated: "2026-09-27"
|
||||
state_hub_workstream_id: "58a56363-3bda-50f7-8240-1e45131bc7d9"
|
||||
---
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ rollback rehearsal.
|
|||
|
||||
```task
|
||||
id: RAIL-FAB-WP-0028-T01
|
||||
status: todo
|
||||
status: wait
|
||||
flavor: residual
|
||||
priority: high
|
||||
state_hub_task_id: "65702f41-b87e-59e5-9396-cd1fda5e8ef4"
|
||||
|
|
@ -45,7 +45,7 @@ snapshot history and deterministic snapshot-set provenance.
|
|||
|
||||
```task
|
||||
id: RAIL-FAB-WP-0028-T02
|
||||
status: todo
|
||||
status: wait
|
||||
flavor: residual
|
||||
priority: high
|
||||
state_hub_task_id: "cad1af1d-177b-5a47-a9fa-d99c40bb2649"
|
||||
|
|
@ -59,7 +59,7 @@ Do not expose mutation endpoints without the authorization selected in T01.
|
|||
|
||||
```task
|
||||
id: RAIL-FAB-WP-0028-T03
|
||||
status: todo
|
||||
status: wait
|
||||
flavor: residual
|
||||
priority: high
|
||||
state_hub_task_id: "78a73d4e-46aa-53c7-911b-be5f79bc25e8"
|
||||
|
|
@ -73,7 +73,7 @@ accepted snapshot set.
|
|||
|
||||
```task
|
||||
id: RAIL-FAB-WP-0028-T04
|
||||
status: todo
|
||||
status: wait
|
||||
flavor: residual
|
||||
priority: high
|
||||
state_hub_task_id: "c66c3fa4-8856-5999-8c47-dbb2f6efc21e"
|
||||
|
|
@ -82,3 +82,19 @@ state_hub_task_id: "c66c3fa4-8856-5999-8c47-dbb2f6efc21e"
|
|||
Starts after T03. Run the fin-hub consumer gate against the hosted owner endpoint, inventory and
|
||||
switch any real callers, exercise rollback, and hand the receipts back to
|
||||
`STATE-WP-0079-T04` before State Hub's Fabric projection routes retire.
|
||||
|
||||
## Loose-end review — 2026-09-27
|
||||
|
||||
T01–T04 remain blocked. The fin-hub consumer contract selects Fabric as the
|
||||
specialized authority, but does not select or admit its production runtime,
|
||||
persistent volume, offsite backup ownership, authentication policy, or deployment
|
||||
repository. No hosted Fabric onboarding decision was found in this repository
|
||||
or railiance-platform's workplans. A workstation SQLite service does not satisfy
|
||||
this plan's durability gate.
|
||||
|
||||
T01 needs a runtime/persistence and access decision with railiance-platform and
|
||||
railiance-enablement, including named backup/recovery ownership and deployment
|
||||
admission. T02 waits for that decision; T03 waits for the deployed authority;
|
||||
T04 waits for freshness/recovery receipts and the fin-hub consumer gate. Keep
|
||||
State Hub projection routes available until those gates pass. Existing tasks
|
||||
retain all work; no new task or workplan was opened.
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@ type: workplan
|
|||
title: "Inspectable workplan and wait graph in the Fabric explorer"
|
||||
domain: financials
|
||||
repo: railiance-fabric
|
||||
status: proposed
|
||||
status: blocked
|
||||
flavor: planning
|
||||
owner: grok
|
||||
topic_slug: railiance
|
||||
created: "2026-09-14"
|
||||
updated: "2026-09-14"
|
||||
updated: "2026-09-27"
|
||||
related: [RAIL-FAB-WP-0028, CUST-WP-0071]
|
||||
state_hub_workstream_id: "1daac341-94dd-5f44-9907-91c611e7e3c1"
|
||||
---
|
||||
|
||||
State Hub remains the workplan authoring surface. Fabric already has a
|
||||
Repository files remain the workplan source; State Hub indexes them. Fabric already has a
|
||||
graph-explorer shell. This plan is a *perspective*: open workplans, open
|
||||
tasks, and wait/depends_on edges, so the 100+ loose ends are inspectable.
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ First slice (this file's companion commit):
|
|||
|
||||
```task
|
||||
id: RAIL-FAB-WP-0029-T01
|
||||
status: todo
|
||||
status: wait
|
||||
priority: medium
|
||||
state_hub_task_id: "f80a8b15-ea3d-5701-9707-0a6151f50b5c"
|
||||
```
|
||||
|
|
@ -35,3 +35,19 @@ Keep the projection a read of State Hub. Add mode switching without a full
|
|||
page reload, chokepoint sizing from in-degree, and a hosted registry path
|
||||
under RAIL-FAB-WP-0028 when that authority exists. Do not let Fabric become
|
||||
the place workplans are edited.
|
||||
|
||||
## Loose-end review — 2026-09-27
|
||||
|
||||
Completed the repo-local portion of T01: topology/coordination mode changes
|
||||
and residual visibility now fetch and replace the graph without page reload.
|
||||
The requested topology mode survives the switch back; empty payloads remain
|
||||
switchable, failed fetches retain the previous graph, and stale responses cannot
|
||||
overwrite a newer request. Shared URLs retain residual visibility. Existing
|
||||
in-degree sizing and indexed/citation edge precedence remain in place.
|
||||
|
||||
T01 stays `wait` and the workplan is `blocked` solely for hosted acceptance
|
||||
under RAIL-FAB-WP-0028. The read-only coordination export already has a registry
|
||||
route (`/exports/graph-explorer?mode=coordination`); it must be verified on the
|
||||
admitted hosted authority once available. No separate task was created for this
|
||||
remaining gate. Validation: JavaScript syntax check, executable transition
|
||||
regression, and the repository Python suite (see session progress receipt).
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ type: workplan
|
|||
title: "Follow the flex-auth to access-engine repository rename in Fabric"
|
||||
domain: financials
|
||||
repo: railiance-fabric
|
||||
status: active
|
||||
status: blocked
|
||||
flavor: residual
|
||||
origin: residual
|
||||
origin_ref: FLEX-WP-0020
|
||||
owner: codex
|
||||
topic_slug: railiance
|
||||
created: "2026-09-22"
|
||||
updated: "2026-09-22"
|
||||
updated: "2026-09-27"
|
||||
state_hub_workstream_id: "631e2974-55ba-58e3-b8ca-dc6c1c294111"
|
||||
---
|
||||
|
||||
|
|
@ -68,3 +68,16 @@ Re-run `scan-manifest` for the renamed entry and re-export the graph. Confirm
|
|||
that no `repo:flex-auth` repository node remains, that the `flex-auth.*`
|
||||
runtime nodes are unchanged, and that no edge endpoint is left unresolved.
|
||||
Then reply to flex-auth with the evidence.
|
||||
|
||||
## Loose-end review — 2026-09-27
|
||||
|
||||
T01–T03 remain `wait`; the workplan is now `blocked`. The local checkout remains
|
||||
`/home/worsch/flex-auth`; `/home/worsch/access-engine` is absent. The owner's
|
||||
FLEX-WP-0020 still records T05 (fresh preflight and exact human approval) and T06
|
||||
(Forgejo rename) as `wait`. There is no execution receipt satisfying T01.
|
||||
|
||||
Resume only after the owner reports the completed rename with unchanged
|
||||
repository UUID and Forge ID 42. Then update coordinates and re-ingest under
|
||||
T02/T03, preserving all `flex-auth.*` runtime identities. Preemptive manifest
|
||||
changes would point to a missing checkout; no declarations or historical
|
||||
snapshots were renamed during this review.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue