Why: cursor 3/3 exhausted; PI direct dispatched as host integration work.
Scope: 8 test files (7 modified + 1 new), 255 insertions, 29 new vitest tests covering 11 U4 frontend-auto-discover scenarios end-to-end:
- AutoDiscover (3 new in store.test.ts)
- CapabilityGroup (3 new in rolePermissions.test.ts + 6 new in panels)
- CreatorOwnerMemberDuties (4 new across adminRdmSections/projectmeta/AccountUsersPanel)
- MemberManagementEntryHidden (3 new in adminRdmSections/projectmeta)
- EmptyListNoCreate (4 new in projectmeta/TaskSidebar)
- DefaultProjectDisabled (1 new in store.test.ts/projectmeta)
- RefreshBackoff + RefreshSingleFlight + RefreshHiddenPause + RefreshReconnectCompensate
- ProjectLifecycleConversation (5 new in test/conversation-work.test.ts)
Verification: npm run build ok (5.35s); ./node_modules/.bin/vitest run 656/656 (was 627, +29 new); new 29 tests across all 11 patterns all pass; no production files touched.
Refs: plan revision 3 U5-Frontend; /tmp/iam-link-u5-frontend-pi-verify-20261019.json exit=0.
Why: PR #106 is behind main by 15 commits (password login, regulation
citations, RDM member search) and conflicted in RdmAuditWorkspace.tsx and
rdmManagement.ts; the user authorized merging the renderer line on 2026-10-18.
Evidence: content is the agent-exec transport ec5012fe (cursor worker, unit
frontend-task11-sync-main-50ec836-r2, receipt
/tmp/cleanup-20261018/render/frontend-sync-run2.json, SELF): tsc -b, vitest
541/541 and vite build passed; host reviewed both conflict resolutions as unions.
Impact: no behaviour removed from either side; regulation tab and document
open flow coexist in the materials tab.
Refs: PR #106, Frontend main 50ec836
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: TimelineTab's history effect read the shared events genRef without
incrementing it, so two overlapping history requests both passed the
check and a stale response could overwrite a fresher one, violating the
single-async-owner / drop-stale-events rule. Tree row buttons also hid
their expand state from assistive tech and announced the decorative caret.
Evidence: new src/components/RdmAuditWorkspace.test.tsx (7 cases) covers
out-of-order resolve, stale rejection, cleanup invalidation, ref isolation
and aria attributes; reverting to the non-incrementing read fails 3 cases.
npm test 43 files / 503 tests pass; npm run build ok;
node scripts/check-knip.mjs 50 <= 51; test/design-guard.test.ts 7/7.
Impact: history state now owned by historyGenRef via startLatestFetch
(incremented per fetch, checked on resolve, invalidated on cleanup); the
events-list seq is untouched. Expandable tree buttons expose
aria-expanded, non-expandable rows omit it, caret is aria-hidden.
Refs: review findings on RdmAuditWorkspace (TimelineTab history seq,
tree row a11y); AGENTS.md async-state rule; DESIGN.md
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: Owner decision merge_whole requires the parent "two trees" initiative's
Frontend work (local-only 95e1948, feature/rdm-two-trees-readable-audit:
814643f..95e1948) to ship together with the unified document render
workspace branch.
Evidence:
- Conflict src/components/RdmAuditWorkspace.tsx (TreeList render): HEAD added
a per-document "阅读与交付" open button inside the old two-level doc/section
list; 95e1948 replaced that list with the recursive TreeNodeRow. Kept the
recursive TreeNodeRow and moved the open button into it (wrapped in
.rdm-audit-tree-row, onOpenDoc threaded through recursion, shown for
kind === 'doc' at any depth; aria-label keeps "阅读与交付:<title>").
MaterialsTab/DocumentRenderWorkspace, saveBase64File and key={pid} from
HEAD and readable presentation, paging, detail seq-guard, trace relation
and timeline changes from 95e1948 merged cleanly.
- Conflict src/styles.css (both appended at end of file): kept HEAD's
render workspace / cockpit rules followed by 95e1948's 760px media query.
- Semantic fix e2e/rdm-audit.playwright.ts: tree kind is now shown in
business language, so the section filter matches '章节' instead of
'section'.
- npm test: 42 files, 496 tests passed (incl. design-guard,
rdmAuditPresentation, rdmAuditTree); npm run build: ok;
node scripts/check-knip.mjs: 50 <= 51; npx playwright test --list: 78 tests
in 17 files.
Impact: RDM audit materials tab renders both project trees recursively with
readable names and still opens any document in the render workspace; audit
timeline and trace show readable records and retired/stale relations.
Refs: 95e1948 (814643f, b52f965, c9b55eb, b921bef, 505aba3, 1ef68ab,
ad503c9, 987be74, 95e1948); HEAD 50d12ce
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: RDM now anchors annotations on nodeId + textStart + textEnd + textHash
(spec 06 §2) and acceptance 10 §5 requires accurate comment ranges. The
workspace only sent whole-node annotations and ignored quote/needsReanchor.
- Selecting text inside one node's title in the reader view records a
code-point range (Array.from indices; surrogate pairs and ZWJ emoji are
counted as runes, half-pair endpoints widen) and sends textStart/textEnd
plus quote, so RDM rejects rather than misplaces a drifted range.
- No selection keeps whole-node behavior; replies never carry range params;
textHash/range are never sent; a range is dropped if it belongs to another
node.
- Selections spanning several nodes or containing no node text record no
range and show a notice that the whole node will be annotated; the composer
always shows the scope with a "whole node" escape.
- Annotation items show the server quote and a visible needs-reanchor state;
review_anchor_invalid: errors map to readable Chinese text.
- Reader titles become role=button spans because browsers do not allow text
selection inside <button>.
Evidence: npm test 40 files / 486 tests pass (30 new in
test/review-annotation-anchor.test.ts); npm run build exit 0;
node scripts/check-knip.mjs "50 <= 51"; design-guard 7/7; playwright
--list compiles 13 tests; headless Chromium check of the selection reader
(single, multi-node, triple-click clamp, emoji offsets).
Impact: document review UI only; base-gate decision source anchoring is
unchanged. Offsets are computed on the displayed node title (no frozen-text
read endpoint exists), guarded by quote equality on the server.
Refs: unified renderer plan Task 13; phase1 F2; spec 06 §2
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: RDM be80ad4 (docs/design/render-node-id-contract.md) accepts workspace tree
node ids (dn-/sec-/legacy-) for review annotate/revise, adds treeNodeId to receipts,
rdm.render.review.view items and trace entries while nodeId stays canonical, points
anchored-to at the tree node id, and marks audit-reader trace entries with
contentMasked=true. Grouping review items by the canonical nodeId left them all
unlocated, and the workspace showed no render trace at all.
Evidence: npx tsc --noEmit exit 0; npx vitest run 39 files / 456 tests passed (12 new
in test/document-render-workspace.test.ts: treeNodeId grouping with nodeId fallback
and orphan rules for annotations and revisions, data-locate targets, annotate/revise
payload carrying the selected tree node id, layer=render filtering, anchored-to
against tree nodes without canonical fallback, masked entries never reading body
fields, empty state); npm run build ok; node scripts/check-knip.mjs 51 <= 51;
e2e/document-renderer.playwright.ts type-checks (tsc exit 0) and
npx playwright test --list loads 13 tests.
Impact: locateNodeId (treeNodeId first, nodeId fallback, otherwise unlocated) is
shared by diagnostics, review grouping and trace. Clicking an annotation or revision
group, a reply, or a trace node locates and re-scrolls like diagnostics. Annotate and
revise send the selected tree node id as nodeId. A 渲染链条 panel reads
rdm.inspect.relations (kind=doc) through the single guarded resource owner (stale
responses dropped) and reloads after preview, submit, export, review and decision
actions. Masked entries show metadata only with a 内容已遮蔽 marker and a panel
notice. The e2e spec is unchanged: §11-5b already asserts that the group title is the
selected tree node, and the leak scan is untouched. Not run against a live backend
or browser here.
Refs: RDM be80ad4 docs/design/render-node-id-contract.md; unified renderer spec 10
§11 items 4, 5 and 7; DESIGN.md §8, §9.2, §11.
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: Browser acceptance (/tmp/renderer-browser-acceptance/20261017T061021Z) found
§11-4 showed 25/25 diagnostics as 未定位节点 because the renderer nodeId is the
canonical mapping id (pp.cover.document-number.value) while the workspace tree uses
dn-… ids; RDM now adds treeNodeId to every diagnostic. §11-3 failed only because
the e2e spec still expected 已验证/未发布 although all 44 DHF profiles are published.
Evidence: npx tsc --noEmit exit 0; npx vitest run 39 files / 445 tests passed (4 new
in test/document-render-workspace.test.ts covering treeNodeId, nodeId fallback,
unknown ids and per-node counts); npm run build ok; node scripts/check-knip.mjs
unused exports 51 <= 51; e2e/document-renderer.playwright.ts type-checks (tsc exit 0)
and playwright test --list loads 13 tests. Real rdm.render.profiles payload in
evidence/network/item3-author.jsonl: template rule state=published,
publicationAllowed=true, no blockedReason, refusal controlled_requires_exact_profile.
Impact: normalizeDiagnostics keeps treeNodeId; locateDiagnostic resolves treeNodeId
first and falls back to nodeId, otherwise the diagnostic stays explicitly unlocated.
Badges and the 有诊断问题 filter count by the located tree node. Clicking a located
diagnostic selects the node and scrolls it into view in canvas or reader, also on a
repeated click. Diagnostics loading keeps its single request guard. §11-3 now asserts
已发布, 可正式交付, an enabled option and no reason, and still asserts source, version,
the no-fallback notice and refusal. Not run against a live backend or browser here.
Refs: unified renderer plan Task 13 §11 items 3 and 4; spec 10 §11 item 3;
summary.md root causes §A and §B.
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: the cockpit refresh reloaded overview and tree but left the node
detail at its old snapshot, so the 刷新对齐 banner persisted after
refreshing (DV-R05 wants every projection to advance). PanoramaNode now
refetches when the overview snapshotRevision advances. Scenario 4 also
scoped its tree clicks to the 验证主体报告 branch — the unscoped first
caret expanded an unrelated rdm-self doc.
Evidence: tsc clean, vitest green, build green (SELF); seven-scenario
rerun to be recorded on the Dev I4 card.
Impact: cockpit panorama + e2e spec.
Refs: rollout I4
Why: the I4 scenarios assert the version collapsible for a selected
section in the panorama (not only the reader); the panorama node view
had no version block, so .cockpit-versions-toggle never existed there.
Also normalize null list projections in the panorama node detail fetch
(same Go nil-slice issue fixed for the panel earlier).
Evidence: tsc clean, vitest green, build green (SELF); seven-scenario
rerun to be recorded on the Dev I4 card.
Impact: cockpit panorama only.
Refs: rollout I4
Why: rdm.cockpit.node projects empty conflicts as items:null (Go nil
slice) while sources arrive as []; the panel read items.length on null
and crashed, so the conflicts empty state never rendered (I4 e2e
scenario 3).
Evidence: tsc clean, vitest green, build green (SELF); seven-scenario
rerun to be recorded on the Dev I4 card.
Impact: cockpit panel only.
Refs: rollout I4
Why: The base gate (cmdbus.RequiresProjectWorkDecision) refuses rdm.review.doc.approve/reject/final unless the request carries a committed conversation source as top-level conversationId and anchorMessageId. The workspace sent bare params, so the decision buttons were refused in the real product.
Evidence: vitest 39 files / 441 tests passed (22 new in test/document-decision.test.ts); npx tsc --noEmit clean; npm run build ok; check-knip unused exports 51 <= 51; e2e/document-renderer.playwright.ts type-checks and lists 13 tests. Request shape from pins/agent-system-backend: internal/server/server.go:1276-1304 (body decode), internal/cmdbus/cmdbus.go:109-134 and 385, internal/app/app.go:646-665 (preflight), server.go:1010-1150 (message POST returns the committed message).
Impact: approve/reject/final first post a Chinese decision message to the host project's 文档审签记录 conversation (reused, or created), then dispatch with its id as the anchor (entrance button). Identity is never sent. Any failing step shows a readable refusal and nothing is dispatched. Double-click is ignored while an action is in flight, and retries reuse the operation id so the server returns the same source message. rdmCommand takes an optional source; rdm.render.* is unchanged. The e2e spec drives §11-5c through the workspace only and asserts the anchored, committed receipt. Not run against a live backend or browser here.
Refs: unified renderer plan Task 11; RDM cmdbus gate (pins/agent-system-backend internal/cmdbus/cmdbus.go:109-134); live-verify sequence /tmp/live-verify/run.sh lines 56-70 and 140-146.
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: the local ProjectView interface invented 'id'; rdm.project.list
returns projectId. Every option value was undefined, so auto-select set
pid to undefined and the overview request was never issued — cockpit
showed 加载概览… forever after the project list loaded (I4 e2e scenario 1).
Evidence: tsc clean, vitest green, build green (SELF); network probe shows
rdm.cockpit.overview 200 and .cockpit-stats rendered; seven-scenario rerun
to be recorded on the Dev I4 card.
Impact: cockpit entry only.
Refs: rollout I4
Why: the cockpit rendered the project dropdown with no project selected
and an empty main area — the design's 首屏 default (first visible project
drives the overview) was never implemented; caught by I4 e2e scenario 1
which got past the project list but never saw .cockpit-stats.
Evidence: tsc clean, vitest green, build green (SELF); seven-scenario
rerun to be recorded on the Dev I4 card.
Impact: cockpit entry only.
Refs: rollout I4
Why: Task 11 requires the document render workspace to offer approve, reject and final decisions, rule bind/unbind for document, document type and project default, and the full delivery package, so reviewers and settings holders no longer need other screens.
Evidence: vitest 38 files / 419 tests passed (new test/document-render-actions.test.ts covers decision entries from frozen duties, decision payloads without identity fields, package availability, refusal codes, binding candidates and payloads, perm gating and SSR visibility); tsc --noEmit clean; knip unused exports 51 <= baseline 51.
Impact: decision entries show only when the command is enabled and the frozen submission lists the session user; binding needs rdm.perm.check project.settings allowed=true; package appears only for ready deliveries; organization-default binding is not offered from the workspace (domain admin only).
Refs: unified renderer plan Task 11, 05 section 9, 06 section 6, 07 sections 1 and 5; RDM plugins/rdm/plugin.go review.doc.* and render.profile.* schemas (7169944, 4b7ac2a, 75ba50c).
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: #102 rewrote the bare-array fallback into a multi-line callback and
turned 'if (!c) setProjects(...)' into an early 'if (!c) return', which
skips setProjects on the normal (non-cancelled) path — the cockpit then
hangs on 加载中 forever, caught by I4 e2e scenario 1.
Evidence: tsc clean, vitest 324/324, build green (SELF); seven-scenario
browser suite rerun recorded on the Dev I4 card.
Impact: cockpit entry only.
Refs: rollout I4
Why: origin/main carries the cockpit, account and duty-settings work; the render workspace branch needs its rdmRender capability state kept beside the new rdmCockpitAvailable flag.
Evidence: store.ts conflicts resolved by keeping both sides in the identity reset and capability refresh paths; tsc --noEmit clean; vitest run 37 files / 394 tests passed; npm run build passed; knip unused exports 51 <= baseline 51.
Impact: refresh failure and identity reset now clear rdmCockpitAvailable and rdmRender together; no behavior removed from either side.
Refs: unified renderer plan Task 11 (09-implementation-plan.md); Dev precheck verdict SHARED_WORKSPACE_BUSY recorded in the task report.
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: rdm.project.list returns { projects: [...] }; the cockpit component
assumed a bare array and always rendered 暂无可见研发项目, caught by I4 e2e
scenario 1.
Evidence: tsc/vitest/build green (SELF); browser e2e rerun recorded on the
Dev I4 card.
Impact: cockpit entry only.
Refs: rollout I4
Why: TaskSidebar builds its own workspace entry list without the cockpit
flag, so the 文档驾驶舱 entry never appeared in the sidebar even when the
command probe passed (caught by I4 e2e scenario 1).
Evidence: tsc/vitest/vite build green (SELF); cockpit e2e suite re-run via
Dev scripts/e2e.sh follows on the Dev I4 card.
Impact: sidebar entry visibility only; no behavior change elsewhere.
Refs: rollout I4
Why: implement the reviewed I3 increment - continuous body reading with
per-section status lines, version summary with collapsed line-diff (backend
versions projection from RDM PR #420), right evidence panel with
sources/history/impacts/conflicts tabs, panorama-reader positioning on the
shared selection, per user+project view preferences (panorama/reader,
density, panel tab), strict-seq history merging and honest restricted states.
Evidence: 10 new pure-logic tests (prefs validation, version summary and
diff marks, strict history merge drops, reader assembly three-state); vitest
324/324 green; tsc and vite build green; tokens-only styles.
Impact: cockpit-only; no fourth column, no standalone graph (relations stay
in the right panel); reader entry is explicit (panorama button / view toggle).
Refs: rollout I3
Why: implement the reviewed I2 increment - statistics band, structure tree
with lazy section pages, panorama center (project overview + node summary),
shared selection/filter, snapshot-consistency banner and honest states, per
the frozen contract (Dev docs/superpowers 2026-10-16, rollout section 7).
Evidence: vitest 314/314 green (14 new pure-logic tests covering capability
gate, true-zero vs unavailable stats, filter toggle, snapshot equality and
update notice, context key, selection survival, honest badges); tsc -b and
vite production build green.
Impact: new workspace entry (rdm-cockpit, gated on the seven cockpit
commands); no changes to existing surfaces; reader view and right panel
land in I3.
Refs: rollout I2
Why: the forced password gate still submitted an empty current password
after the backend began requiring it (current_required), locking every
account seeded with an initial password out of the workbench, and the
admin user panel had no client for the owner-confirmed recovery
proposal contract that replaced one-time key issuing (HTTP 410).
Evidence: npm test 300 passed; tsc -b && vite build ok; knip issues
54 <= baseline 55 (SELF).
Impact: mode-aware ChangePasswordGate with current-password input,
admin recovery proposal panel, owner-side account settings section,
recovery proposal client methods; no backend changes.
Refs: backend 8dfc223, b9c0a34; frontend #94
Why: independent review flagged the issue client still targeting the 410
endpoint and a hint sentence ending with a period.
Evidence: npm run build + npm test re-run on the fix (SELF).
Impact: api client surface only.
Refs: review brief /tmp/review-brief-admin-user-contract.md
Why: Running §11 against RDM d63f1db showed three Frontend defects. A
validated template rule with a server blockedReason was disabled for
preview, although the server only restricts formal delivery. A reviewer
opening the document in another session could not find the author's
submission until an export existed. Template-instance blocks without a
title (cover, sign-off table, fields) rendered as blank canvas nodes and
reader headings.
Evidence: npx vitest run (35 files, 363 tests passed); npm run build ok;
node scripts/check-knip.mjs (43 <= 43); browser run under
/tmp/renderer-browser-acceptance/20261016T064052Z (item1 172 nodes,
preview generated with the validated template rule).
Impact: Preview is offered for validated/draft rules while formal submit
stays blocked; the current submission comes from rdm.review.doc.status;
untitled nodes show "<kind>(<templateBlockId>)".
Refs: unified renderer plan Task 13 §11
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: backend 8dfc223 replaced POST /api/admin/users with strict
{owner, profile} decoding and returned 410 for login-key issuing, so the
UI create form failed with 400 unknown field name. Creation now sends
{owner, profile:{name}} only; password input, admin checkbox and the
login-key issue entry are removed; notice points to the local CLI
initialize-account flow. passwords.ts lost its only consumer.
Evidence: npm run build + npm test (34 files/293 passed) + knip identical
to baseline on the task worktree (SELF).
Impact: UsersPanel and api client only; no style/token changes.
Refs: backend 8dfc223, b9c0a34
Why: S9 acceptance finding 3 — the project settings modal exposed the
host override settings (including the model/key group, masked) to plain
project members; the duties data plane was already permission-enforced,
but the host settings surface had no gate.
Evidence: vitest 34 files / 293 tests pass with the change; tsc reports
no errors in the modified file. Ruling per the acceptance plan P1-B:
the modal entry stays (granted duty managers need the RDM tabs), while
the host override settings group renders only for the project owner or
a system admin; RDM tabs keep their own fail-closed gating.
Impact: ProjectSettingsModal project tab renders an explanatory empty
state for non-privileged viewers; members/duties/matrix tabs unchanged.
Refs: S9 acceptance report P1-B
Why: Independent review of a81e94a..85428b4 found five contract mismatches
against the RDM server: profile sources document-type/project-default were
dropped, the refusal object {code,message} was ignored, submit receipts were
read as `id` instead of `submissionId`, diagnostics were expected inside
preview/export receipts (they live in a separate diagnostics delivery blob),
and rdm.inspect.tree was treated as recursive although it returns one level.
Evidence: New tests use the server JSON shapes (RenderProfileOptions,
RenderDeliveryReceipt, DocSubmissionRec, rdmRenderDownload, InspectTree); 26
of them fail against the previous implementation. npx vitest run: 35 files,
359 tests passed; npm run build: ok; scripts/check-knip.mjs: unused exports
43 <= 43; git diff --cached --check: clean.
Impact: Rules panel lists all five sources with Chinese labels and keeps the
server's selected default; refusals render readably; a new submission is
auto-selected; diagnostics are fetched via rdm.render.download kind=diagnostics
under a sequence/epoch guard with readable failures and a Chinese receipt
state label; the document tree is walked breadth-first (depth 12, 2000 nodes,
concurrency 4) with a truncation notice. Playwright spec asserts per-node
diagnostic anchors after preview (authored, not run).
Refs: unified renderer plan Task 11 review findings
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: unified renderer Task 11 needs a reader/delivery UI over the RDM
document tree: four-level rule selection with controlled-document
no-fallback explanation, preview with node-linked diagnostics, a
structure canvas and a linear reader sharing one selection and filter,
review annotations/revisions, and per-delivery downloads.
Evidence: npx vitest run -> 35 files, 338 tests passed (45 new in
test/document-render-workspace.test.ts, design-guard green);
npm run build -> tsc -b + vite build ok; npx knip -> findings identical
to the pre-existing baseline (check-knip 43 <= 43); git diff --check
clean. e2e/document-renderer.playwright.ts authored, not executed.
Impact: new src/documentRenderPresentation.ts (pure helpers) and
src/components/DocumentRenderWorkspace.tsx, opened from a per-document
"阅读与交付" action in the audit materials tree; store gains an
rdmRender capability probe (fail-closed); audit export reuses the shared
base64 file saver; token-only styles appended to styles.css. Async
state is owned per hook with request guards plus identity epoch, and
the workspace remounts per identity/project/document scope.
Refs: unified renderer plan Task 11
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: Approving an extra package, rebuilding the base layer, reclaiming unused layers, and uploading a wheel need an admin surface that uses the existing admin controls.
Evidence: SELF tsc of the new panel reported no errors in frontend sources. UI package type errors come from missing node_modules in this worktree, not from this panel.
Impact: Administrators get a Python 环境 section. Other admin sections are unchanged.
Refs: .task/feature-layered-python-env.md
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: a lost write response was keeping the old duty version, so the next save replayed it, and a busy save could stay locked if another request advanced the sequence.
Evidence: SELF vitest duty-draft 6 passed, tsc passed, knip 43, Playwright duty flows 3 passed.
Impact: an unknown save reloads server roles, confirmation resets, and busy clears even if a later read is discarded.
Refs: docs/proposals/2026-10-15-rdm-duty-matrix-rework.md
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: project settings must keep the shared duty draft and must not regain template document creation from main.
Evidence: SELF vitest 292 passed, tsc --noEmit passed, knip unused exports 43.
Impact: the duties tab stays assignment-only while conversation ordering from main is included.
Refs: docs/proposals/2026-10-15-rdm-duty-matrix-rework.md
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: Completion or progress from an earlier task could appear in the process of an unrelated newer answer.
Evidence: The new ownership regression fails before the guard and passes afterward; the frontend suite, TypeScript and unchanged export gate pass.
Impact: Project child progress only into its originating live turn while still reconciling background results.
Refs: feature/workbench-flow-completion chronological display requirement