You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2026/06/07 14:49:19 UTC

(causeway) 28/50: CAUSEWAY-4014: removes replayable command target cosmetics

This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch CAUSEWAY-4014
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit e5bf9694d91309bf67bcdb0dba93a1f82d6a8f95
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Sun Jun 7 11:50:08 2026 +0100

    CAUSEWAY-4014: removes replayable command target cosmetics
---
 .../applib/CausewayModuleExtCommandLogApplib.java  |  4 --
 ...ExportManager#exported.columnOrder.fallback.txt |  4 +-
 ...Manager#notYetExported.columnOrder.fallback.txt |  4 +-
 ...anager#pendingOrFailed.columnOrder.fallback.txt |  4 +-
 ...er#succeededOrExcluded.columnOrder.fallback.txt |  4 +-
 .../ReplayableCommand.columnOrder.fallback.txt     |  4 +-
 .../applib/dom/replay/ReplayableCommand.java       | 64 ++++-----------------
 .../replay/ReplayableCommand.layout.fallback.xml   |  7 +--
 .../dom/replay/ReplayableCommand_openTarget.java   | 65 ----------------------
 .../dom/replay/ReplayableCommand_openTargetTR.java | 62 ---------------------
 .../.openspec.yaml                                 |  0
 .../design.md                                      |  0
 .../proposal.md                                    |  0
 .../specs/replayable-command-remappings/spec.md    |  3 +-
 .../tasks.md                                       | 16 ++++++
 .../changes/replayable-command-cosmetics/tasks.md  | 16 ------
 .../specs/replayable-command-remappings/spec.md    | 12 +++-
 17 files changed, 46 insertions(+), 223 deletions(-)

diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/CausewayModuleExtCommandLogApplib.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/CausewayModuleExtCommandLogApplib.java
index 945ddddabb7..b17292d4e83 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/CausewayModuleExtCommandLogApplib.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/CausewayModuleExtCommandLogApplib.java
@@ -57,8 +57,6 @@
 import org.apache.causeway.extensions.commandlog.applib.dom.replay.ReplayableCommand_excludeFromReplay;
 import org.apache.causeway.extensions.commandlog.applib.dom.replay.ReplayableCommand_makeExportable;
 import org.apache.causeway.extensions.commandlog.applib.dom.replay.ReplayableCommand_openCommandLogEntry;
-import org.apache.causeway.extensions.commandlog.applib.dom.replay.ReplayableCommand_openTarget;
-import org.apache.causeway.extensions.commandlog.applib.dom.replay.ReplayableCommand_openTargetTR;
 import org.apache.causeway.extensions.commandlog.applib.dom.replay.ReplayableCommand_replayOrRetry;
 import org.apache.causeway.extensions.commandlog.applib.fakescheduler.FakeScheduler;
 import org.apache.causeway.extensions.commandlog.applib.job.BackgroundCommandsJobControl;
@@ -90,8 +88,6 @@
         CommandReplayResultMapping_delete.class,
         ReplayableCommand_makeExportable.class,
         ReplayableCommand_openCommandLogEntry.class,
-        ReplayableCommand_openTarget.class,
-        ReplayableCommand_openTargetTR.class,
         ReplayableCommand_replayOrRetry.class,
         ReplayableCommand_excludeFromReplay.class,
         ReplayableCommand_delete.class,
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandExportManager#exported.columnOrder.fallback.txt b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandExportManager#exported.columnOrder.fallback.txt
index bde91a6f91d..337130c7561 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandExportManager#exported.columnOrder.fallback.txt
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandExportManager#exported.columnOrder.fallback.txt
@@ -1,6 +1,4 @@
 #interactionId
 timestamp
-targetType
-targetId
 member
-replayState
\ No newline at end of file
+replayState
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandExportManager#notYetExported.columnOrder.fallback.txt b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandExportManager#notYetExported.columnOrder.fallback.txt
index bde91a6f91d..337130c7561 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandExportManager#notYetExported.columnOrder.fallback.txt
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandExportManager#notYetExported.columnOrder.fallback.txt
@@ -1,6 +1,4 @@
 #interactionId
 timestamp
-targetType
-targetId
 member
-replayState
\ No newline at end of file
+replayState
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandReplayManager#pendingOrFailed.columnOrder.fallback.txt b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandReplayManager#pendingOrFailed.columnOrder.fallback.txt
index bde91a6f91d..337130c7561 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandReplayManager#pendingOrFailed.columnOrder.fallback.txt
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandReplayManager#pendingOrFailed.columnOrder.fallback.txt
@@ -1,6 +1,4 @@
 #interactionId
 timestamp
-targetType
-targetId
 member
-replayState
\ No newline at end of file
+replayState
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandReplayManager#succeededOrExcluded.columnOrder.fallback.txt b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandReplayManager#succeededOrExcluded.columnOrder.fallback.txt
index bde91a6f91d..337130c7561 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandReplayManager#succeededOrExcluded.columnOrder.fallback.txt
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/CommandReplayManager#succeededOrExcluded.columnOrder.fallback.txt
@@ -1,6 +1,4 @@
 #interactionId
 timestamp
-targetType
-targetId
 member
-replayState
\ No newline at end of file
+replayState
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.columnOrder.fallback.txt b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.columnOrder.fallback.txt
index bde91a6f91d..337130c7561 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.columnOrder.fallback.txt
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.columnOrder.fallback.txt
@@ -1,6 +1,4 @@
 #interactionId
 timestamp
-targetType
-targetId
 member
-replayState
\ No newline at end of file
+replayState
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.java
index ae2213a0e8a..24f9bac1f49 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.java
@@ -31,20 +31,16 @@
 import javax.inject.Named;
 
 import org.apache.causeway.applib.ViewModel;
-import org.apache.causeway.applib.annotation.Action;
-import org.apache.causeway.applib.annotation.ActionLayout;
 import org.apache.causeway.applib.annotation.Collection;
 import org.apache.causeway.applib.annotation.CollectionLayout;
 import org.apache.causeway.applib.annotation.DomainObject;
 import org.apache.causeway.applib.annotation.DomainObjectLayout;
 import org.apache.causeway.applib.annotation.Introspection;
 import org.apache.causeway.applib.annotation.LabelPosition;
-import org.apache.causeway.applib.annotation.MemberSupport;
 import org.apache.causeway.applib.annotation.ObjectSupport;
 import org.apache.causeway.applib.annotation.Programmatic;
 import org.apache.causeway.applib.annotation.Property;
 import org.apache.causeway.applib.annotation.PropertyLayout;
-import org.apache.causeway.applib.annotation.SemanticsOf;
 import org.apache.causeway.applib.annotation.Where;
 import org.apache.causeway.applib.jaxb.JavaTimeXMLGregorianCalendarMarshalling;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
@@ -54,7 +50,6 @@
 import org.apache.causeway.commons.functional.Try;
 import org.apache.causeway.commons.internal.base._NullSafe;
 import org.apache.causeway.commons.internal.base._Refs.ObjectReference;
-import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.io.JsonUtils;
 import org.apache.causeway.commons.io.TextUtils;
 import org.apache.causeway.commons.io.YamlUtils;
@@ -164,7 +159,17 @@ public ReplayableCommand(
 
     @ObjectSupport public String title() {
         final var timestamp = getTimestampIfAny().map(ChronoZonedDateTime::toInstant).map(Instant::toString).map(x -> " @ " + x).orElse("");
-        return getTargetType() + ":" + getTargetId() + " #" + getMember() + timestamp;
+        return targetTitlePrefix() + " #" + getMember() + timestamp;
+    }
+
+    private String targetTitlePrefix() {
+        return commandRecord()
+            .map(CommandRecord::commandDto)
+            .map(CommandDto::getTargets)
+            .filter(targets -> !targets.getOid().isEmpty())
+            .map(targets -> targets.getOid().get(0))
+            .map(target -> target.getType() + ":" + target.getId())
+            .orElse("");
     }
 
 //requires v4
@@ -208,53 +213,6 @@ public Optional<ZonedDateTime> getTimestampIfAny() {
                 .map(JavaTimeXMLGregorianCalendarMarshalling::toZonedDateTime);
     }
 
-    @Property
-    @PropertyLayout(
-            sequence = "2.1",
-            fieldSetId = "details",
-            describedAs = "Target Type of the original (replayable) Command")
-    public String getTargetType() {
-        return commandRecord()
-            .map(CommandRecord::commandDto)
-            .map(commandDto->commandDto.getTargets().getOid().get(0))
-            .map(OidDto::getType)
-            .orElse(null);
-    }
-
-    @Property
-    @PropertyLayout(
-            sequence = "2.2",
-            fieldSetId = "details",
-            describedAs = "Target ID of the original (replayable) Command")
-    public String getTargetId() {
-        return commandRecord()
-            .map(CommandRecord::commandDto)
-            .map(commandDto->commandDto.getTargets().getOid().get(0))
-            .map(OidDto::getId)
-            .map(id->_Strings.ellipsifyAtEnd(id, 10, "..."))
-            .orElse(null);
-    }
-
-    @Action(semantics = SemanticsOf.SAFE)
-    @ActionLayout(
-            cssClassFa = "fa-bullseye"
-    )
-    public class openTarget {
-
-        @MemberSupport public Object act() {
-            return commandLogEntry()
-                    .map(CommandLogEntry::getTarget)
-                    .flatMap(bookmark -> bookmarkService.lookup(bookmark))
-                    .orElse(null);
-        }
-        @MemberSupport public String disableAct() {
-            return commandLogEntry().isPresent() ? null : "Unknown target";
-        }
-
-        @Inject BookmarkService bookmarkService;
-    }
-
-
     @Property
     @PropertyLayout(
             sequence = "3.1",
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.layout.fallback.xml b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.layout.fallback.xml
index 9abeeb06dc2..cebdcf14f12 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.layout.fallback.xml
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.layout.fallback.xml
@@ -37,7 +37,7 @@
                     </bs:row>
                 </bs:tab>
             </bs:tabGroup>
-            <cpt:collection id="participants"/>
+            <cpt:collection defaultView="table" paged="15" id="participants"/>
             <cpt:fieldSet name="Control" id="control">
                 <cpt:action id="replayOrRetry" position="PANEL"/>
                 <cpt:property id="replayState"/>
@@ -50,11 +50,6 @@
             </cpt:fieldSet>
         </bs:col>
     </bs:row>
-    <bs:row>
-        <bs:col span="12">
-            <cpt:collection defaultView="table" paged="15" id="participants"/>
-        </bs:col>
-    </bs:row>
     <bs:row>
         <bs:col span="12">
             <bs:tabGroup unreferencedCollections="true"/>
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand_openTarget.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand_openTarget.java
deleted file mode 100644
index c26fa2068c0..00000000000
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand_openTarget.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.causeway.extensions.commandlog.applib.dom.replay;
-
-import javax.inject.Inject;
-
-import org.apache.causeway.applib.annotation.Action;
-import org.apache.causeway.applib.annotation.ActionLayout;
-import org.apache.causeway.applib.annotation.MemberSupport;
-import org.apache.causeway.applib.annotation.Publishing;
-import org.apache.causeway.applib.annotation.SemanticsOf;
-import org.apache.causeway.applib.services.bookmark.BookmarkService;
-import org.apache.causeway.extensions.commandlog.applib.dom.CommandLogEntry;
-
-import lombok.RequiredArgsConstructor;
-
-@Action(
-        semantics = SemanticsOf.SAFE,
-        commandPublishing = Publishing.DISABLED,
-        domainEvent = ReplayableCommand_openTarget.DomainEvent.class,
-        executionPublishing = Publishing.DISABLED
-)
-@ActionLayout(
-        sequence = "0.3", associateWith = "target",
-        describedAs = "Opens the underlying Target"
-)
-@RequiredArgsConstructor
-public class ReplayableCommand_openTarget {
-
-    public static class DomainEvent extends ReplayableCommand.ActionDomainEvent<ReplayableCommand_openTarget> {
-    }
-
-    private final ReplayableCommand replayableCommand;
-
-    @MemberSupport
-    public Object act() {
-        return replayableCommand.commandLogEntry()
-                .map(CommandLogEntry::getTarget)
-                .flatMap(bookmark -> bookmarkService.lookup(bookmark))
-                .orElse(null);
-    }
-
-    @MemberSupport
-    public String disableAct() {
-        return replayableCommand.commandLogEntry().isEmpty() ? "No corresponding CommandLogEntry" : null;
-    }
-
-    @Inject private BookmarkService bookmarkService;
-}
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand_openTargetTR.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand_openTargetTR.java
deleted file mode 100644
index ae9fad85db4..00000000000
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand_openTargetTR.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.causeway.extensions.commandlog.applib.dom.replay;
-
-import lombok.RequiredArgsConstructor;
-
-import javax.inject.Inject;
-
-import org.apache.causeway.applib.annotation.*;
-import org.apache.causeway.applib.services.bookmark.BookmarkService;
-import org.apache.causeway.extensions.commandlog.applib.dom.CommandLogEntry;
-
-@Action(
-        semantics = SemanticsOf.SAFE,
-        commandPublishing = Publishing.DISABLED,
-        domainEvent = ReplayableCommand_openTargetTR.DomainEvent.class,
-        executionPublishing = Publishing.DISABLED
-)
-@ActionLayout(
-        named = "Open Target",
-        describedAs = "Opens the underlying Target",
-        hidden = Where.OBJECT_FORMS // table row action.
-)
-@RequiredArgsConstructor
-public class ReplayableCommand_openTargetTR {
-
-    public static class DomainEvent extends ReplayableCommand.ActionDomainEvent<ReplayableCommand_openTargetTR> {
-    }
-
-    private final ReplayableCommand replayableCommand;
-
-    @MemberSupport
-    public Object act() {
-        return replayableCommand.commandLogEntry()
-                .map(CommandLogEntry::getTarget)
-                .flatMap(bookmark -> bookmarkService.lookup(bookmark))
-                .orElse(null);
-    }
-
-    @MemberSupport
-    public String disableAct() {
-        return replayableCommand.commandLogEntry().isEmpty() ? "No corresponding CommandLogEntry" : null;
-    }
-
-    @Inject private BookmarkService bookmarkService;
-}
diff --git a/openspec/changes/replayable-command-cosmetics/.openspec.yaml b/openspec/changes/archive/2026-06-07-replayable-command-cosmetics/.openspec.yaml
similarity index 100%
rename from openspec/changes/replayable-command-cosmetics/.openspec.yaml
rename to openspec/changes/archive/2026-06-07-replayable-command-cosmetics/.openspec.yaml
diff --git a/openspec/changes/replayable-command-cosmetics/design.md b/openspec/changes/archive/2026-06-07-replayable-command-cosmetics/design.md
similarity index 100%
rename from openspec/changes/replayable-command-cosmetics/design.md
rename to openspec/changes/archive/2026-06-07-replayable-command-cosmetics/design.md
diff --git a/openspec/changes/replayable-command-cosmetics/proposal.md b/openspec/changes/archive/2026-06-07-replayable-command-cosmetics/proposal.md
similarity index 100%
rename from openspec/changes/replayable-command-cosmetics/proposal.md
rename to openspec/changes/archive/2026-06-07-replayable-command-cosmetics/proposal.md
diff --git a/openspec/changes/replayable-command-cosmetics/specs/replayable-command-remappings/spec.md b/openspec/changes/archive/2026-06-07-replayable-command-cosmetics/specs/replayable-command-remappings/spec.md
similarity index 91%
rename from openspec/changes/replayable-command-cosmetics/specs/replayable-command-remappings/spec.md
rename to openspec/changes/archive/2026-06-07-replayable-command-cosmetics/specs/replayable-command-remappings/spec.md
index d75a9e7f117..0906e5e7ad1 100644
--- a/openspec/changes/replayable-command-cosmetics/specs/replayable-command-remappings/spec.md
+++ b/openspec/changes/archive/2026-06-07-replayable-command-cosmetics/specs/replayable-command-remappings/spec.md
@@ -3,7 +3,7 @@
 ### Requirement: Replayable participant layouts expose participant data
 The system SHALL provide fallback layout metadata for `ReplayableCommandParticipant`.
 The participant layout SHALL expose role, parameter name, recorded bookmark, target, parameter, result, and actual bookmark in that order.
-The `ReplayableCommand` fallback layout SHALL include the participants collection as a table named `Participants`.
+The `ReplayableCommand` fallback layout SHALL include the participants collection as a table named `Participants` before the control field set.
 The `ReplayableCommand` object view MUST NOT expose separate target summary properties for target type or target identifier.
 The `ReplayableCommand` object view MUST NOT expose a separate open target action.
 Target inspection and navigation SHALL be available through target rows in the participants collection.
@@ -11,6 +11,7 @@ Target inspection and navigation SHALL be available through target rows in the p
 #### Scenario: User views participants table on a replayable command
 - **WHEN** a user views a replayable command using fallback layout metadata
 - **THEN** the layout includes the participants collection as a table named `Participants`
+- **AND** the participants table appears before the control field set
 
 #### Scenario: User views participant fields
 - **WHEN** a user views a replayable command participant using fallback layout metadata
diff --git a/openspec/changes/archive/2026-06-07-replayable-command-cosmetics/tasks.md b/openspec/changes/archive/2026-06-07-replayable-command-cosmetics/tasks.md
new file mode 100644
index 00000000000..c1d840ba0a1
--- /dev/null
+++ b/openspec/changes/archive/2026-06-07-replayable-command-cosmetics/tasks.md
@@ -0,0 +1,16 @@
+## 1. ReplayableCommand Cleanup
+
+- [x] 1.1 Remove the `openTarget` action and its `BookmarkService` dependency from `ReplayableCommand`.
+- [x] 1.2 Remove exposed `targetType` and `targetId` properties from `ReplayableCommand`.
+- [x] 1.3 Preserve any needed title logic using non-exposed helpers if required.
+
+## 2. Layout Metadata
+
+- [x] 2.1 Remove `openTarget`, `targetType`, and `targetId` references from `ReplayableCommand.layout.fallback.xml`.
+- [x] 2.2 Keep the `member`, replay state, DTO, and participants table layout unchanged except for removed target members.
+
+## 3. Tests and Validation
+
+- [x] 3.1 Update focused command log applib tests for the removed target members if needed.
+- [x] 3.2 Run focused command log applib tests for replayable command mapping and participant behaviour.
+- [x] 3.3 Run `openspec validate replayable-command-cosmetics --strict`.
diff --git a/openspec/changes/replayable-command-cosmetics/tasks.md b/openspec/changes/replayable-command-cosmetics/tasks.md
deleted file mode 100644
index ac9f017427f..00000000000
--- a/openspec/changes/replayable-command-cosmetics/tasks.md
+++ /dev/null
@@ -1,16 +0,0 @@
-## 1. ReplayableCommand Cleanup
-
-- [ ] 1.1 Remove the `openTarget` action and its `BookmarkService` dependency from `ReplayableCommand`.
-- [ ] 1.2 Remove exposed `targetType` and `targetId` properties from `ReplayableCommand`.
-- [ ] 1.3 Preserve any needed title logic using non-exposed helpers if required.
-
-## 2. Layout Metadata
-
-- [ ] 2.1 Remove `openTarget`, `targetType`, and `targetId` references from `ReplayableCommand.layout.fallback.xml`.
-- [ ] 2.2 Keep the `member`, replay state, DTO, and participants table layout unchanged except for removed target members.
-
-## 3. Tests and Validation
-
-- [ ] 3.1 Update focused command log applib tests for the removed target members if needed.
-- [ ] 3.2 Run focused command log applib tests for replayable command mapping and participant behaviour.
-- [ ] 3.3 Run `openspec validate replayable-command-cosmetics --strict`.
diff --git a/openspec/specs/replayable-command-remappings/spec.md b/openspec/specs/replayable-command-remappings/spec.md
index 4b947796e80..d5d42543fcf 100644
--- a/openspec/specs/replayable-command-remappings/spec.md
+++ b/openspec/specs/replayable-command-remappings/spec.md
@@ -96,12 +96,22 @@ The system MUST NOT resolve or display a result object for commands that have no
 ### Requirement: Replayable participant layouts expose participant data
 The system SHALL provide fallback layout metadata for `ReplayableCommandParticipant`.
 The participant layout SHALL expose role, parameter name, recorded bookmark, target, parameter, result, and actual bookmark in that order.
-The `ReplayableCommand` fallback layout SHALL include the participants collection as a table named `Participants`.
+The `ReplayableCommand` fallback layout SHALL include the participants collection as a table named `Participants` before the control field set.
+The `ReplayableCommand` object view MUST NOT expose separate target summary properties for target type or target identifier.
+The `ReplayableCommand` object view MUST NOT expose a separate open target action.
+Target inspection and navigation SHALL be available through target rows in the participants collection.
 
 #### Scenario: User views participants table on a replayable command
 - **WHEN** a user views a replayable command using fallback layout metadata
 - **THEN** the layout includes the participants collection as a table named `Participants`
+- **AND** the participants table appears before the control field set
 
 #### Scenario: User views participant fields
 - **WHEN** a user views a replayable command participant using fallback layout metadata
 - **THEN** the layout displays the participant role, parameter name, recorded bookmark, target, parameter, result, and actual bookmark in order
+
+#### Scenario: User inspects target through participants
+- **WHEN** a user views a replayable command using fallback layout metadata
+- **THEN** the layout does not display separate `targetType` or `targetId` properties
+- **AND** the layout does not display a separate `openTarget` action
+- **AND** target information is available through the participants table