LearnNewsExamplesServices
Frontmatter
id18406
titleShare bounded predicate waits across dock consumers
stateClosed
labels
enhancementairefactoringcore
assigneesneo-gpt-emmy
createdAtSep 7, 2026, 12:47 AM
updatedAtSep 7, 2026, 1:15 AM
githubUrlhttps://github.com/neomjs/neo/issues/18406
authorneo-gpt-emmy
commentsCount0
parentIssue18304
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 7, 2026, 1:15 AM

Share bounded predicate waits across dock consumers

Closed Backlog/active-chunk-21 enhancementairefactoringcore
neo-gpt-emmy
neo-gpt-emmy commented on Sep 7, 2026, 12:47 AM

Context

The bounded loop audit found eight matching Boolean wait bodies across Workstation and DemoB. The other seven matching loop headers contain gesture actuation, receipt returns or readiness snapshots and are excluded. This is one small implementation cut under the existing workspace-decomposition epic.

The Problem

Each consumer repeats attempt bounds, delay scheduling, early success and final predicate sampling. Those mechanics depend only on the instance lifecycle, while the predicates depend on the consumer. Copying the mechanics makes their destruction and retry behavior independently editable.

The Architectural Reality

src/core/Base.mjs already owns timeout() and trap(). Its timeout registers a rejection which destroy() settles with Neo.isDestroyed. Both consumer classes inherit Base through their ordinary families; no dock-specific collaborator or configuration bridge is needed.

A live import probe reports Base.prototype.waitFor === undefined, with timeout and trap both functions. Source searches across src, apps and examples found no conflicting waitFor method.

The Fix

Add Base#waitFor(predicate, {attempts=120, delay=16}={}) for a synchronous Boolean predicate. Reuse this.timeout(delay); retain the existing loop's immediate sample, bounded waits, early success, and final predicate read. Propagate predicate exceptions and timeout rejection.

Replace only the eight simple Boolean wait bodies in apps/workstation/view/Workspace.mjs and examples/dashboard/crossWindow/DemoBWorkspace.mjs. Keep their predicates, caller defaults and public methods. Extend the existing core timeout unit spec and regenerate the tracked size baseline.

Contract Ledger

Surface Authority Behavior Fallback Docs Evidence
New Base.waitFor Existing Base timeout/trap lifecycle Synchronous predicate sampled immediately; at most attempts waits; true exits early; one final sample after exhaustion Boolean false on exhaustion; exceptions and destruction rejection propagate Method JSDoc Immediate/delayed success, exhaustion/final sample, throwing predicate, actual destroy
Eight consumer waits Existing consumer predicates and signatures Delegate repeated polling mechanics through inherited Base method Preserve current attempts/delay and return values Existing consumer intent retained Focused consumer suites and full unit suite

Acceptance Criteria

  • Base owns one documented predicate-wait implementation using its existing timeout lifecycle, with no dock-specific state.
  • Eight matching Boolean loop copies are removed; their predicates and caller defaults remain in the two consumers.
  • Controls verify immediate success, bounded delays, final sampling, predicate failure and Neo.isDestroyed rejection during a pending wait.
  • Existing consumer behavior remains green; focused and full unit suites pass, and the size baseline records the consumer reduction.

Out of Scope

The seven gesture/snapshot/receipt loops; async predicates; event subscription machinery; native park/admission/recovery changes; other factory conversions; modifying existing approved PRs; Brain/tooling work.

Avoided Traps

A new helper class or controller with consumer callbacks/configs; putting consumer predicates into Base; treating all matching loop headers as equivalent; converting destruction rejection into false; changing retry semantics while extracting them.

Decision Record impact: aligned-with ADR 0029; no docking or native authority changes. Decision Record: no new ADR required for this additive lifecycle utility.

Related

Parent: #18304

Live latest-open sweep: latest20 open issues checked at2026-09-06T22:45Z; no equivalent found. Latest30 all-status A2A checked in the same window; Vega owns remaining triage but explicitly has no implementation claim on this cut. Exact all-state waitFor search found the parent and unrelated old test tickets. MC problem/rationale searches returned off-topic results, no applicable prior decision. Own-assignment sweep: existing VesselPark, guide, film and launch obligations do not own this polling cut. Labels verified. Structure-map command exits1 without output; placement rests on the existing Base timeout/trap methods. Vega received the concrete Base placement and exclusions in MESSAGE:bb9b5401-1fd5-4703-800f-ba2d65e18a0a.

Origin Session ID: 10c286a7-65e7-4f15-be8e-8dace71af32d Retrieval Hint: bounded Boolean predicate loops Base timeout destroy rejection Workstation DemoB