Skip to content

MP-09: studio-aware displays (monitors, task wall) - #14

Open
aurablacklight wants to merge 14 commits into
mainfrom
mp/MP-09-displays
Open

aurablacklight wants to merge 14 commits into
mainfrom
mp/MP-09-displays

Conversation

@aurablacklight

Copy link
Copy Markdown

In another player's studio the monitors and the task wall draw from that studio's public state. In the player's own studio they draw as before.

Stacked on Wave 0. This branch starts from the four open Wave 0 pull requests (#1, #2, #4, #5) merged together, so until they are on main this diff also shows their changes. The packet's own change is 2 commits: compare from the Wave 0 base.

What is in it

  • A remote monitor shows the agent's public name and state word and "activity hidden", or the activity when the owner shares it.
  • A remote task wall shows the counts per lane (blocked tasks counted in Todo, as on the own wall) and no cards, or the titles when the owner shares them.
  • Each panel's cached agent resolution records the layout it was resolved against, so two studios in view do not clear each other's cache.

Review history

Reviewed by the coordinator (4 findings) and, after one fix round, by a second model (5 small findings, corrected by the coordinator). The worknote (docs/multiplayer/worknotes/MP-09.md on this branch) has the details.

Verification

  • Tests on this branch: gradlew test --rerun --no-build-cache and gradlew build: 60 JUnit tests and 2 game tests, all passing.
  • All fourteen Wave 1 branches together (mp/integration): 238 JUnit tests and 102 game tests pass, and the singleplayer QA compare (ten shots against a reference on the same display) moved no shot; the singleplayer client logged no agentcraft.mp line.
  • Seen in a game window: In a singleplayer client with the dev.mp.fake overlay: every monitor reports a remote source, the monitor and wall looks with the policy off and on, and the own wall back after clear. The singleplayer QA compare moved no shot.

Still owed, and not run by anyone:

  • The two-client look (a real remote studio instead of the overlay).
  • Every check that needs a dedicated server with a real player or two clients belongs to MP-I; none was run for this packet.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NLkzPTC3pm16WCmLm9dqyp

aurablacklight and others added 11 commits October 3, 2026 23:23
The packet worker could not run the live checks in its sandbox. Add what the
coordinator observed when running them outside it, including what failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UTWx6KTPBs4koTLg8uZMHX
…r review

- A client whose DevBridge cannot bind its port is detected from its log,
  and relaunched once after the TIME_WAIT window, bounded by --timeout.
- Server and client telemetry is read from logs/debug.log, so debug-level
  agentcraft.mp events are visible to harness tests.
- Gradle preparation is bounded by --timeout, the launch export ensures
  client assets, and the process identity no longer depends on the
  caller's time zone or locale.
- Fall back to the checkout's .gradle-home and check for Java 25, like the
  other launchers. Document and pin the --json summary shape.
- Windows: portable test fixture paths, -ExecutionPolicy Bypass, and the
  wrapper started through Start-Bg. None of this was run on Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnFLfHG1rVtWmS9c6mAQP
main gained the CI workflow (.github/workflows/ci.yml). Nothing else changes
on this branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnFLfHG1rVtWmS9c6mAQP
Local integration branch for Wave 1 (not pushed, not for main).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnFLfHG1rVtWmS9c6mAQP
Local integration branch for Wave 1 (not pushed, not for main).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnFLfHG1rVtWmS9c6mAQP
Local integration branch for Wave 1 (not pushed, not for main).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnFLfHG1rVtWmS9c6mAQP
Local integration branch for Wave 1 (not pushed, not for main).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnFLfHG1rVtWmS9c6mAQP
…wed)

In another player's studio the monitors and the task wall draw from that
studio's public state. In the player's own studio they draw as before.

Written by a sandboxed worker and not yet reviewed. The coordinator re-ran
the tests outside the sandbox; they pass. The review, and the live checks
the worknote lists, are still owed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnFLfHG1rVtWmS9c6mAQP
… review)

With two studios in view the monitor's agent-resolution cache was cleared on
every extract, because one layout key guarded the whole map. Each panel's entry
now records the layout it was resolved against and only that entry is resolved
again when its layout changes.

A remote Task Wall's Todo lane counts its blocked tasks, as the own wall does.

The studio-per-panel cache is also cleared once a second, because the registry
can change what a position resolves to without telling its listeners. The task
board's outline hook checks the block before it asks for the studio.

Two tests that could not fail are removed, and the worknote records the review
and the runs.

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

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Remote display caches can retain stale geometry/style data, and task walls ignore the public Foreman-offline signal.

Review effort: Balanced
Findings: 3 Medium severity

Open (3)
What changed in this PR

Adds studio-aware monitors and task walls while retaining the local Foreman rendering path. The PR is stacked on the Wave 0 multiplayer foundation, test infrastructure, Node baseline, and harness.

Changes:

  • Renders remote displays exclusively from public studio state.
  • Adds per-studio and per-panel display caches plus remote view-model tests.
  • Includes prerequisite multiplayer contracts, game tests, and tooling.
File Description
README.md Updates Node prerequisite.
docs/​multiplayer/​README.md Updates campaign status.
docs/​multiplayer/​handoffs/​session-resume.md Updates coordinator handoff.
docs/​multiplayer/​work-packets.md Defines multiplayer packet contracts.
docs/​multiplayer/​worknotes/​MP-09.md Records display implementation and verification.
docs/​multiplayer/​worknotes/​MP-B.md Documents Node baseline work.
docs/​multiplayer/​worknotes/​MP-F.md Documents foundation contracts.
docs/​multiplayer/​worknotes/​MP-H.md Documents harness work.
docs/​multiplayer/​worknotes/​MP-T.md Documents game-test infrastructure.
foreman/​package.json Requires Node 22.18+.
foreman/​src/​repos.ts Parses Node 24 test output.
foreman/​test/​repos.test.ts Tests test-output parsing.
mod/​build.gradle Adds JUnit and game-test configuration.
mod/​src/​client/​java/​dev/​agentcraft/​client/​ClientFeatures.java Wires multiplayer client features.
mod/​src/​client/​java/​dev/​agentcraft/​client/​monitor/​AgentResolutionCache.java Caches monitor binding resolution.
mod/​src/​client/​java/​dev/​agentcraft/​client/​monitor/​DisplayText.java Adds remote-display labels.
mod/​src/​client/​java/​dev/​agentcraft/​client/​monitor/​MonitorFeature.java Resolves bindings against studio layouts.
mod/​src/​client/​java/​dev/​agentcraft/​client/​monitor/​MonitorRenderer.java Selects local or remote monitor data.
mod/​src/​client/​java/​dev/​agentcraft/​client/​monitor/​MonitorScreen.java Lays out remote monitor content.
mod/​src/​client/​java/​dev/​agentcraft/​client/​monitor/​RemoteMonitorView.java Models public remote monitor data.
mod/​src/​client/​java/​dev/​agentcraft/​client/​monitor/​StudioDisplays.java Caches panel-to-studio resolution.
mod/​src/​client/​java/​dev/​agentcraft/​client/​mp/​MpMode.java Tracks multiplayer client mode.
mod/​src/​client/​java/​dev/​agentcraft/​client/​mp/​RemoteAgentClicks.java Adds remote-agent click seam.
mod/​src/​client/​java/​dev/​agentcraft/​client/​mp/​StudioView.java Defines client studio snapshots.
mod/​src/​client/​java/​dev/​agentcraft/​client/​mp/​Studios.java Implements the studio registry.
mod/​src/​client/​java/​dev/​agentcraft/​client/​mp/​dev/​MpDevFake.java Adds remote-studio development overlay.
mod/​src/​client/​java/​dev/​agentcraft/​client/​mp/​layout/​LayoutSyncClient.java Adds layout-sync feature seam.
mod/​src/​client/​java/​dev/​agentcraft/​client/​mp/​publish/​PublishFeature.java Adds publisher feature seam.
mod/​src/​client/​java/​dev/​agentcraft/​client/​mp/​remote/​RemoteStudiosFeature.java Adds remote-studio feature seam.
mod/​src/​client/​java/​dev/​agentcraft/​client/​mp/​visitor/​VisitorFeature.java Adds visitor feature seam.
mod/​src/​client/​java/​dev/​agentcraft/​client/​taskwall/​RemoteBoard.java Lays out remote task walls.
mod/​src/​client/​java/​dev/​agentcraft/​client/​taskwall/​RemoteBoardView.java Models public task-wall data.
mod/​src/​client/​java/​dev/​agentcraft/​client/​taskwall/​TaskBoardRenderer.java Renders local or remote task walls.
mod/​src/​client/​java/​dev/​agentcraft/​client/​taskwall/​TaskWallFeature.java Adds remote board caching and guards.
mod/​src/​gametest/​java/​dev/​agentcraft/​gametest/​HqSmokeGameTest.java Adds HQ smoke game test.
mod/​src/​gametest/​resources/​fabric.mod.json Registers generated game-test entrypoints.
mod/​src/​main/​java/​dev/​agentcraft/​AgentCraft.java Wires multiplayer server features.
mod/​src/​main/​java/​dev/​agentcraft/​hq/​HqBuilder.java Adds studio-aware build options.
mod/​src/​main/​java/​dev/​agentcraft/​layout/​Anchors.java Stores layouts per studio.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​MpEvents.java Defines multiplayer telemetry events.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​MpLog.java Emits sanitized multiplayer telemetry.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​MpReasons.java Defines rejection reasons.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​MpServerConfig.java Loads multiplayer server configuration.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​Plot.java Defines studio plot bounds.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​PlotDirectory.java Defines plot lookup API.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​PlotGrid.java Maps plot indexes and origins.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​Plots.java Provides active plot directory.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​RateBucket.java Adds shared rate limiting.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​StudioId.java Defines studio identity.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​HelloC2S.java Defines client handshake payload.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​HelloS2C.java Defines server handshake payload.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​LayoutRemoveS2C.java Defines layout removal payload.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​LayoutS2C.java Defines layout synchronization payload.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​MpCodecs.java Adds bounded multiplayer codecs.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​MpPayloads.java Registers payloads and handshake.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​MpProtocol.java Defines protocol version.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​PresenceS2C.java Defines presence payload.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​PublicStateC2S.java Defines public-state payload.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​ServerInfo.java Defines advertised server settings.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​StudioEventC2S.java Defines outbound studio events.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​StudioEventS2C.java Defines relayed studio events.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​StudioStateS2C.java Defines relayed studio state.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​net/​WorldIntentC2S.java Defines world-intent payload.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​server/​StudioRange.java Calculates visible studios.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​server/​intent/​WorldIntentFeature.java Adds world-intent seam.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​server/​layout/​LayoutSyncFeature.java Adds server layout-sync seam.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​server/​plot/​PlotFeature.java Adds plot feature seam.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​server/​protect/​PlotProtectionFeature.java Adds plot-protection seam.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​server/​relay/​RelayFeature.java Adds relay feature seam.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​server/​world/​ServerWorldFeature.java Adds server-world seam.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​AgentStateWire.java Defines public agent states.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​CiSlot.java Defines public CI slots.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​CiStatusWire.java Defines public CI states.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​Counts.java Defines public summary counts.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​GoalStatusWire.java Defines public goal states.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​GoalSummary.java Defines public goal summaries.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​LampStatusWire.java Defines lamp states.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​MpText.java Sanitizes public text.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​PublicAgent.java Defines public agent data.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​PublicEvent.java Defines public events.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​PublicJson.java Encodes public-state JSON.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​PublicPolicy.java Defines text-sharing policy.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​PublicStudioState.java Defines the public-state allowlist.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​PublicTask.java Defines public task data.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​StationWire.java Defines public station values.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​TaskStatusWire.java Defines public task states.
mod/​src/​main/​java/​dev/​agentcraft/​mp/​state/​WorldIntent.java Defines desired world state.
mod/​src/​test/​java/​dev/​agentcraft/​client/​foreman/​ForemanStates.java Provides state fixtures.
mod/​src/​test/​java/​dev/​agentcraft/​client/​foreman/​ForemanStatesTest.java Tests state fixtures.
mod/​src/​test/​java/​dev/​agentcraft/​client/​monitor/​AgentResolutionCacheTest.java Tests per-layout monitor caching.
mod/​src/​test/​java/​dev/​agentcraft/​client/​monitor/​RemoteMonitorViewTest.java Tests remote monitor models.
mod/​src/​test/​java/​dev/​agentcraft/​client/​taskwall/​RemoteBoardViewTest.java Tests remote board models.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​AnchorsTest.java Tests per-studio anchors.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​CodecTest.java Tests payload round trips.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​DevFakeTest.java Tests development overlay.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​FoundationTest.java Tests foundation contracts.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​RateBucketTest.java Tests rate limiting.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​RemoteAgentClicksTest.java Tests click delegation.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​StudioRangeTest.java Tests studio visibility.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​StudiosTest.java Tests studio registry and mode.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​WireBoundaryTest.java Tests wire validation boundaries.
mod/​src/​test/​java/​dev/​agentcraft/​mp/​WiringTest.java Tests feature wiring.
mod/​src/​test/​resources/​dev/​agentcraft/​fixtures/​showcase-late.json Adds late-state fixture.
mod/​src/​test/​resources/​dev/​agentcraft/​fixtures/​showcase.json Adds showcase-state fixture.
tools/​README.md Documents harness operation.
tools/​launch.ps1 Enforces Node baseline on Windows.
tools/​lib/​mp/​config.mjs Parses harness configuration.
tools/​lib/​mp/​export-launch.gradle Exports Loom launch metadata.
tools/​lib/​mp/​harness.mjs Implements harness lifecycle.
tools/​lib/​mp/​index.mjs Exposes readiness and telemetry helpers.
tools/​lib/​mp/​launch.mjs Builds isolated JVM launches.
tools/​lib/​mp/​processes.mjs Tracks process ownership and recovery.
tools/​mac.mjs Enforces Node baseline on macOS.
tools/​mp.mjs Adds multiplayer harness CLI.
tools/​package.json Requires Node 22.18+.
tools/​test/​mp-config.test.mjs Tests harness configuration.
tools/​test/​mp-library.test.mjs Tests harness helper APIs.
tools/​test/​mp-processes.test.mjs Tests process ownership.
tools/​test/​mp-review.test.mjs Tests reviewed harness behavior.
tools/​test/​mp-shutdown.test.mjs Tests cleanup and recovery.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +31 to +50
/** A resolved panel: the binding and the layout identity it was resolved against. */
private record Entry(String agent, String layoutName, long layoutRevision) {
}

private final Map<BlockPos, Entry> entries = new HashMap<>();

/**
* The binding for the panel at {@code pos}, cached until the layout it resolved against changes
* name or revision. Only a miss runs {@code resolver}.
*/
String resolve(BlockPos pos, Direction facing, int width, int height, Anchors.Layout layout, Resolver resolver) {
BlockPos key = pos.immutable();
Entry entry = entries.get(key);
if (entry != null && entry.layoutRevision() == layout.revision() && entry.layoutName().equals(layout.name())) {
return entry.agent();
}
String agent = resolver.resolve(layout, key, facing, width, height);
entries.put(key, new Entry(agent, layout.name(), layout.revision()));
return agent;
}
Comment on lines +184 to +187
boolean syncRemoteSource(StudioView v, String binding, ScreenStyle st, int ppb, int panelW, int panelH) {
if (v == remoteSource && binding.equals(remoteBinding)) {
return false;
}
Comment thread mod/src/client/java/dev/agentcraft/client/taskwall/RemoteBoardView.java Outdated
aurablacklight and others added 2 commits October 4, 2026 10:29
…a remote wall offline (MP-09)

The monitor's agent-resolution cache and the remote monitor's fast path
ignored the panel's facing and size (and the look), so a resized or re-faced
panel, or a look switch, kept the old binding or layout until the studio's next
state. Both now compare those inputs too.

A remote task wall showed as live while its owner's Foreman was offline: it
used the presence flag alone. It now needs both, as the remote monitor does.

Found by the pull-request review, which also noted worknote statements that
were out of date. 65 JUnit tests and both game tests pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NLkzPTC3pm16WCmLm9dqyp
Every studio event cleared the whole position-to-studio cache, so with several
studios publishing a few states a second it was rebuilt almost every frame.
The cache now holds which studio covers a position and reads the studio's
current view on each use, and it is cleared only when a studio appears, goes,
or changes its layout or plot.

One dev-only effect: switching the overlay flag of an existing fake studio
takes effect at the once-a-second backstop instead of at once.

Found by the pull-request review. 67 JUnit tests and both game tests pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NLkzPTC3pm16WCmLm9dqyp
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NLkzPTC3pm16WCmLm9dqyp
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.

2 participants