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/06 08:20:54 UTC
(causeway) 02/39: CAUSEWAY-4012: adds proposal for safe finder command logging
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch CAUSEWAY-4012
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 0ff27c3cfb6b77536abbc7601a1d72e37e62f1b4
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jun 5 06:25:34 2026 +0100
CAUSEWAY-4012: adds proposal for safe finder command logging
---
.../log-safe-single-result-finders/.openspec.yaml | 2 +
.../log-safe-single-result-finders/design.md | 78 ++++++++++++++++++++++
.../log-safe-single-result-finders/proposal.md | 28 ++++++++
.../specs/command-export-yaml-result/spec.md | 19 ++++++
.../specs/command-replay-result-mapping/spec.md | 33 +++++++++
.../spec.md | 61 +++++++++++++++++
.../log-safe-single-result-finders/tasks.md | 44 ++++++++++++
7 files changed, 265 insertions(+)
diff --git a/openspec/changes/log-safe-single-result-finders/.openspec.yaml b/openspec/changes/log-safe-single-result-finders/.openspec.yaml
new file mode 100644
index 00000000000..c53ef21aaaf
--- /dev/null
+++ b/openspec/changes/log-safe-single-result-finders/.openspec.yaml
@@ -0,0 +1,2 @@
+schema: spec-driven
+created: 2026-06-05
diff --git a/openspec/changes/log-safe-single-result-finders/design.md b/openspec/changes/log-safe-single-result-finders/design.md
new file mode 100644
index 00000000000..e24f0f8890f
--- /dev/null
+++ b/openspec/changes/log-safe-single-result-finders/design.md
@@ -0,0 +1,78 @@
+## Context
+
+Command export and replay are used for regression testing by recording commands on a test instance and replaying them against both the current system version and a newer system version.
+Replay result mapping already lets applications map recorded returned object bookmarks to actual replay result bookmarks, and later replay steps can use that mapping when targets or reference parameters no longer have the same identifiers.
+The missing link is that safe finder actions are normally not command logged, so a recording can show a later command against an object without also recording the safe action that found that object.
+
+The change crosses command publishing, command logging, export, and replay because the framework must capture the finder invocation as a command log entry and then allow the existing export and replay mapping flows to process it.
+The behavior must be opt-in because safe actions can be frequent and many safe actions return lists, scalar values, or other results that are not useful for replay result remapping.
+
+## Goals / Non-Goals
+
+**Goals:**
+
+- Provide a configuration property that enables command logging for safe actions that return exactly one domain object.
+- Preserve the default behavior where safe finder actions are not logged unless explicitly configured.
+- Reuse the existing `CommandDto`, `CommandLogEntry#getResult()`, command export YAML, and replay result mapping SPI concepts.
+- Limit the added logging to safe action invocations whose result can be represented as a single returned object bookmark.
+- Ensure replay can execute the logged safe finder command and notify the mapping SPI with recorded and actual finder result bookmarks.
+
+**Non-Goals:**
+
+- Do not log all safe actions by default.
+- Do not add support for replay mapping list-valued finder results in this change.
+- Do not change command export file format beyond carrying safe finder entries through the existing command export shape.
+- Do not require applications to rewrite existing replay mapping listener implementations.
+
+## Decisions
+
+### Decision: Use an opt-in configuration property
+
+The new behavior will be guarded by a boolean configuration property in the Causeway command logging or command publishing configuration area.
+The default value will be `false` to avoid increasing command log volume or changing production behavior unexpectedly.
+
+Alternative considered: enable safe single-result finder logging automatically whenever command logging is enabled.
+That was rejected because many applications use safe actions heavily and may not want finder calls in the audit log outside regression recording contexts.
+
+### Decision: Classify eligibility by action semantics and bookmarkable result shape
+
+The framework will consider an invocation eligible only when the action has safe semantics and the completed result resolves to a single bookmarkable domain object.
+List, collection, array, optional-empty, scalar, void, and other non-single-object results will not be logged by this feature.
+
+Alternative considered: use naming conventions such as `find*` to identify finders.
+That was rejected because Causeway already models safe semantics and result cardinality more reliably than action names.
+
+### Decision: Reuse command log entries and returned object bookmarks
+
+Eligible safe finder invocations will be represented as normal command log entries with a command DTO and a returned object bookmark.
+This allows command export YAML and replay mapping notifications to use the existing returned object metadata pathway.
+
+Alternative considered: create a separate finder recording artifact outside command log entries.
+That was rejected because regression replay already consumes command log entries and the replay mapping SPI already understands recorded and actual returned object bookmarks.
+
+### Decision: Keep replay mapping listener contracts unchanged
+
+Replay of safe finder entries will use the existing result mapping notification when the recorded finder entry and replay result both have bookmarks.
+No new listener method is required.
+
+Alternative considered: add a finder-specific replay mapping callback.
+That was rejected because the existing callback already expresses the required mapping from recorded bookmark to actual bookmark.
+
+## Risks / Trade-offs
+
+- Increased command log volume when enabled → Keep the property disabled by default and document that it is intended for regression recording environments.
+- Ambiguous result shapes such as `Optional<T>` or framework wrappers → Define tests for accepted and rejected shapes, and only log when the framework can produce one returned object bookmark unambiguously.
+- Safe action replay might have side effects in poorly behaved applications → Limit the feature to opt-in regression recording and rely on the existing semantic contract that safe actions do not mutate state.
+- Duplicate logging if a safe action is explicitly command-published already → Prefer existing explicit command publishing behavior and avoid creating an additional entry for the same interaction.
+
+## Migration Plan
+
+No data migration is required.
+Existing applications keep current behavior because the new property defaults to disabled.
+Regression test applications can enable the property in their test configuration before recording command exports.
+Rollback consists of disabling the property and ignoring any previously recorded safe finder entries in newly generated recordings.
+
+## Open Questions
+
+- Confirm the final property namespace and name during implementation to match existing Causeway configuration conventions.
+- Confirm whether `Optional<T>` with a present bookmarkable object should be treated as a single-result finder or excluded from the first implementation for simplicity.
diff --git a/openspec/changes/log-safe-single-result-finders/proposal.md b/openspec/changes/log-safe-single-result-finders/proposal.md
new file mode 100644
index 00000000000..13592c8a9c9
--- /dev/null
+++ b/openspec/changes/log-safe-single-result-finders/proposal.md
@@ -0,0 +1,28 @@
+## Why
+
+Regression replay needs a complete dotted line through recorded workflows, including the safe finder actions that locate the domain objects later commands operate on.
+Today command logging normally captures only state-changing commands, so replay result remapping cannot learn how a found object in the recording corresponds to the object found during replay.
+
+## What Changes
+
+- Add an opt-in configuration property that enables command logging for safe actions that return a single domain object.
+- Treat enabled safe single-result finder invocations as command-log entries with command DTO and returned object bookmark metadata, so they can be exported and replayed alongside state-changing commands.
+- Keep existing default behavior unchanged when the property is disabled.
+- Exclude safe actions that return lists, collections, void, scalar values, or other non-single-domain-object results from this additional logging path.
+- Preserve existing command export and replay behavior so recorded finder results can feed the replay mapping SPI in the same way as other commands with returned object metadata.
+
+## Capabilities
+
+### New Capabilities
+- `safe-single-result-finder-command-logging`: Opt-in command logging for safe actions that return a single domain object, enabling exported regression recordings to include finder steps and their returned object bookmarks.
+
+### Modified Capabilities
+- `command-export-yaml-result`: Exported command YAML includes returned object metadata for safe single-result finder command log entries when the opt-in logging property is enabled.
+- `command-replay-result-mapping`: Replay result mapping notifications include replayed safe single-result finder entries when both recorded and actual result bookmarks are available.
+
+## Impact
+
+- Affects command creation, command publishing, and command log subscriber behavior for safe action invocations.
+- Adds framework configuration under the command logging or command publishing settings namespace.
+- Affects command log export and replay regression tests by allowing finder steps to appear in exported command streams.
+- Requires unit and integration tests covering disabled-by-default behavior, enabled finder logging, excluded safe result shapes, export metadata, and replay mapping notifications.
diff --git a/openspec/changes/log-safe-single-result-finders/specs/command-export-yaml-result/spec.md b/openspec/changes/log-safe-single-result-finders/specs/command-export-yaml-result/spec.md
new file mode 100644
index 00000000000..398d666ceb2
--- /dev/null
+++ b/openspec/changes/log-safe-single-result-finders/specs/command-export-yaml-result/spec.md
@@ -0,0 +1,19 @@
+## ADDED Requirements
+
+### Requirement: Exported command YAML includes logged safe finder returned object metadata
+The system SHALL export safe single-result finder command log entries using the existing command export YAML shape when safe finder logging created those entries.
+When a logged safe finder entry has a non-null returned object bookmark, the exported YAML SHALL include returned object metadata containing the bookmark logical type name and identifier.
+The system SHALL preserve compatibility with existing command replay import for exported safe finder entries.
+
+#### Scenario: Export logged safe finder command with returned object
+- **GIVEN** safe single-result finder command logging is enabled
+- **AND** a safe finder command log entry has result bookmark `demoCustomer:1`
+- **WHEN** the command is selected for export
+- **THEN** the generated YAML contains the embedded command DTO for the safe finder invocation
+- **AND** the generated YAML contains returned object metadata with logical type name `demoCustomer` and id `1`
+
+#### Scenario: Export command stream containing finder and state-changing commands
+- **GIVEN** a command export selection contains a logged safe finder command followed by a state-changing command that uses the found object
+- **WHEN** the commands are exported
+- **THEN** the generated YAML preserves both command entries in replay order
+- **AND** the safe finder entry includes its returned object metadata when available
diff --git a/openspec/changes/log-safe-single-result-finders/specs/command-replay-result-mapping/spec.md b/openspec/changes/log-safe-single-result-finders/specs/command-replay-result-mapping/spec.md
new file mode 100644
index 00000000000..138bcc75280
--- /dev/null
+++ b/openspec/changes/log-safe-single-result-finders/specs/command-replay-result-mapping/spec.md
@@ -0,0 +1,33 @@
+## ADDED Requirements
+
+### Requirement: Replay result mapping includes logged safe finder results
+The system SHALL replay imported safe single-result finder command log entries as replayable commands when they are present in the imported command stream.
+After a logged safe finder replay succeeds, the system SHALL notify the command replay mapping SPI when the imported command log entry has a recorded returned object bookmark and replay execution returns an actual result bookmark.
+The notification SHALL use the existing replay result mapping SPI contract and SHALL include the recorded finder result bookmark and the actual replay finder result bookmark.
+The system MUST NOT notify the SPI for a logged safe finder replay when either the recorded or actual result bookmark is unavailable.
+
+#### Scenario: Replayed safe finder maps recorded result to actual result
+- **GIVEN** an imported safe finder command log entry has recorded result bookmark `demoCustomer:1`
+- **WHEN** command replay executes that safe finder and obtains actual result bookmark `demoCustomer:2`
+- **THEN** the system notifies the command replay mapping SPI with recorded bookmark `demoCustomer:1` and actual bookmark `demoCustomer:2`
+
+#### Scenario: Replayed safe finder result is unavailable
+- **GIVEN** an imported safe finder command log entry has recorded result bookmark `demoCustomer:1`
+- **WHEN** command replay executes that safe finder and obtains no actual result bookmark
+- **THEN** the system does not notify the command replay mapping SPI for that finder result
+
+### Requirement: Safe finder result mappings can remap later replay inputs
+The system SHALL make replay result mappings produced by logged safe finder commands available to the same replay input remapping flow used by other replayed commands.
+When a later replayed command target or reference parameter uses a recorded bookmark that was mapped by an earlier safe finder replay, the system SHALL allow the command replay mapping SPI to replace that recorded bookmark with the actual replay bookmark.
+
+#### Scenario: Later replay command target is remapped from finder result
+- **GIVEN** replay of a safe finder command mapped recorded bookmark `demoCustomer:1` to actual bookmark `demoCustomer:2`
+- **WHEN** replay is about to execute a later command whose recorded target bookmark is `demoCustomer:1`
+- **AND** the command replay mapping SPI returns replacement bookmark `demoCustomer:2`
+- **THEN** the system executes the later replayed command against target bookmark `demoCustomer:2`
+
+#### Scenario: Later replay command reference parameter is remapped from finder result
+- **GIVEN** replay of a safe finder command mapped recorded bookmark `demoCustomer:1` to actual bookmark `demoCustomer:2`
+- **WHEN** replay is about to execute a later command whose reference parameter bookmark is `demoCustomer:1`
+- **AND** the command replay mapping SPI returns replacement bookmark `demoCustomer:2`
+- **THEN** the system executes the later replayed command with reference parameter bookmark `demoCustomer:2`
diff --git a/openspec/changes/log-safe-single-result-finders/specs/safe-single-result-finder-command-logging/spec.md b/openspec/changes/log-safe-single-result-finders/specs/safe-single-result-finder-command-logging/spec.md
new file mode 100644
index 00000000000..c68d4b953a6
--- /dev/null
+++ b/openspec/changes/log-safe-single-result-finders/specs/safe-single-result-finder-command-logging/spec.md
@@ -0,0 +1,61 @@
+## ADDED Requirements
+
+### Requirement: Safe single-result finder command logging is configurable
+The system SHALL provide a configuration property that enables command logging for safe action invocations that return a single domain object.
+The system SHALL leave this property disabled by default.
+When the property is disabled, safe action invocations MUST retain the existing behavior and MUST NOT be command logged solely because they return a single domain object.
+
+#### Scenario: Safe finder logging is disabled by default
+- **WHEN** an application does not configure safe single-result finder command logging
+- **AND** a user invokes a safe action that returns one domain object
+- **THEN** the system does not create a command log entry solely for that safe action invocation
+
+#### Scenario: Safe finder logging is enabled by property
+- **GIVEN** safe single-result finder command logging is configured as enabled
+- **WHEN** a user invokes a safe action that returns one domain object
+- **THEN** the system creates a command log entry for that safe action invocation
+
+### Requirement: Logged safe finder entries include command DTO and result bookmark
+When safe single-result finder command logging is enabled, the system SHALL store a command DTO for each eligible safe finder invocation.
+When the eligible safe finder returns a bookmarkable domain object, the system SHALL store that returned object's bookmark as the command log entry result.
+The command log entry SHALL be suitable for command export and command replay.
+
+#### Scenario: Safe finder returns one bookmarkable object
+- **GIVEN** safe single-result finder command logging is enabled
+- **WHEN** a user invokes a safe action with command target and parameters that returns bookmark `demoCustomer:1`
+- **THEN** the system creates a command log entry containing a command DTO for that invocation
+- **AND** the command log entry result is bookmark `demoCustomer:1`
+
+#### Scenario: Safe finder returns null
+- **GIVEN** safe single-result finder command logging is enabled
+- **WHEN** a user invokes a safe action that returns null
+- **THEN** the system creates no command log entry for that invocation under the safe single-result finder logging feature
+
+### Requirement: Safe finder logging excludes non-single-domain-object results
+When safe single-result finder command logging is enabled, the system MUST NOT create safe finder command log entries for safe actions whose result is a list, collection, array, void, scalar value, or otherwise not representable as exactly one returned object bookmark.
+The system MUST NOT log unsafe, idempotent, or non-idempotent actions through this safe finder logging path because those actions continue to use existing command publishing behavior.
+
+#### Scenario: Safe action returns a list
+- **GIVEN** safe single-result finder command logging is enabled
+- **WHEN** a user invokes a safe action that returns a list of domain objects
+- **THEN** the system creates no command log entry for that invocation under the safe single-result finder logging feature
+
+#### Scenario: Safe action returns a scalar value
+- **GIVEN** safe single-result finder command logging is enabled
+- **WHEN** a user invokes a safe action that returns a scalar value
+- **THEN** the system creates no command log entry for that invocation under the safe single-result finder logging feature
+
+#### Scenario: State-changing action is invoked
+- **GIVEN** safe single-result finder command logging is enabled
+- **WHEN** a user invokes an idempotent or non-idempotent action
+- **THEN** the safe finder logging path does not determine whether the action is command logged
+- **AND** the action continues to follow existing command publishing rules
+
+### Requirement: Explicit command publishing is not duplicated
+When an action invocation is already command logged through existing command publishing rules, the system MUST NOT create a duplicate command log entry for the same invocation through safe single-result finder command logging.
+
+#### Scenario: Safe action is explicitly command-published
+- **GIVEN** safe single-result finder command logging is enabled
+- **AND** a safe single-result action is explicitly configured for command publishing
+- **WHEN** a user invokes that action
+- **THEN** the system stores at most one command log entry for that invocation
diff --git a/openspec/changes/log-safe-single-result-finders/tasks.md b/openspec/changes/log-safe-single-result-finders/tasks.md
new file mode 100644
index 00000000000..a4ec266ce8b
--- /dev/null
+++ b/openspec/changes/log-safe-single-result-finders/tasks.md
@@ -0,0 +1,44 @@
+## 1. Discovery and Configuration
+
+- [ ] 1.1 Locate the existing command publishing, command DTO creation, and command log subscriber paths for action invocations.
+- [ ] 1.2 Identify the existing Causeway configuration namespace that should own the safe single-result finder logging property.
+- [ ] 1.3 Add the disabled-by-default boolean configuration property and bind it into the relevant runtime service or subscriber.
+- [ ] 1.4 Add documentation metadata or configuration property descriptors if this repository maintains generated config docs.
+
+## 2. Safe Finder Eligibility
+
+- [ ] 2.1 Implement eligibility detection for safe action invocations when the new property is enabled.
+- [ ] 2.2 Detect whether the completed result is exactly one bookmarkable domain object.
+- [ ] 2.3 Exclude null, list, collection, array, void, scalar, and otherwise non-single-bookmarkable results.
+- [ ] 2.4 Ensure idempotent and non-idempotent actions continue to follow existing command publishing behavior rather than the safe finder logging path.
+- [ ] 2.5 Prevent duplicate command log entries when a safe action is already explicitly command-published.
+
+## 3. Command Log Entry Creation
+
+- [ ] 3.1 Create or adapt the command DTO for eligible safe finder invocations so it can be persisted and replayed.
+- [ ] 3.2 Persist an eligible safe finder invocation as a command log entry when the property is enabled.
+- [ ] 3.3 Store the returned object's bookmark as the command log entry result.
+- [ ] 3.4 Keep disabled-by-default behavior unchanged for safe actions when the property is absent or false.
+
+## 4. Export and Replay Integration
+
+- [ ] 4.1 Verify command export includes logged safe finder entries in replay order.
+- [ ] 4.2 Verify exported safe finder entries include returned object metadata when a result bookmark is present.
+- [ ] 4.3 Verify replay executes imported safe finder command entries.
+- [ ] 4.4 Verify replay result mapping notifications are emitted for safe finder entries with recorded and actual result bookmarks.
+- [ ] 4.5 Verify later replay command targets and reference parameters can be remapped using mappings learned from safe finder replay results.
+
+## 5. Tests and Documentation
+
+- [ ] 5.1 Add unit tests for the new configuration property default and enabled values.
+- [ ] 5.2 Add unit tests for safe finder eligibility and excluded result shapes.
+- [ ] 5.3 Add tests ensuring explicitly command-published safe actions are not duplicated.
+- [ ] 5.4 Add export tests covering safe finder command entries and returned object metadata.
+- [ ] 5.5 Add replay tests covering finder result mapping notifications and subsequent input remapping.
+- [ ] 5.6 Update user-facing documentation for regression recording usage and the new configuration property.
+
+## 6. Validation
+
+- [ ] 6.1 Run the relevant commandlog applib unit tests.
+- [ ] 6.2 Run the relevant commandlog persistence integration tests for JDO and JPA if affected.
+- [ ] 6.3 Run OpenSpec validation for `log-safe-single-result-finders`.