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/08/04 18:47:42 UTC
(causeway) 11/22: CAUSEWAY-3910: plan recording-aware command publishing reconciliation
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit fc74666a15e5e365ce59ba95599f56a59668502c
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Aug 4 13:55:00 2026 +0100
CAUSEWAY-3910: plan recording-aware command publishing reconciliation
---
.../.openspec.yaml | 2 +
.../reconcile-recording-aware-publishing/design.md | 96 ++++++++++++++++++
.../proposal.md | 30 ++++++
.../recording-aware-command-publishing/spec.md | 111 +++++++++++++++++++++
.../reconcile-recording-aware-publishing/tasks.md | 23 +++++
5 files changed, 262 insertions(+)
diff --git a/openspec/changes/reconcile-recording-aware-publishing/.openspec.yaml b/openspec/changes/reconcile-recording-aware-publishing/.openspec.yaml
new file mode 100644
index 00000000000..1b062d3a7c7
--- /dev/null
+++ b/openspec/changes/reconcile-recording-aware-publishing/.openspec.yaml
@@ -0,0 +1,2 @@
+schema: spec-driven
+created: 2026-08-04
diff --git a/openspec/changes/reconcile-recording-aware-publishing/design.md b/openspec/changes/reconcile-recording-aware-publishing/design.md
new file mode 100644
index 00000000000..38771c87e25
--- /dev/null
+++ b/openspec/changes/reconcile-recording-aware-publishing/design.md
@@ -0,0 +1,96 @@
+## Context
+
+C1 introduced immutable `causeway.extensions.command-log.recording-support` configuration, the `CommandRecordingSuppressed` marker, and runtime suppression at `MemberExecutorServiceDefault.prepareCommandForPublishing(...)`.
+C4a/D1 then added portable result metadata and broader bookmark capture without changing which interactions become commands.
+Causeway 4 still applies its normal action and property command-publishing policies when constructing `CommandPublishingFacet` instances, so enabled recording support does not yet include ordinary safe actions or property edits.
+
+Maintenance implements this capability in the metamodel facet factories rather than in the commandlog subscriber or runtime executor.
+The Causeway 4 implementation must preserve that semantic boundary while adapting to current facet-holder APIs, immutable configuration, and existing C1 suppression.
+
+## Goals / Non-Goals
+
+**Goals:**
+
+- Make enabled recording support sufficient to publish unannotated safe actions through the normal action command-publishing facet model.
+- Make enabled recording support sufficient to publish ordinary property edits, including properties explicitly configured with disabled command publishing, so recorded mutation sequences remain complete.
+- Preserve explicit `@Action(commandPublishing = DISABLED)` as a safe-action opt-out.
+- Preserve existing action and property policies when recording support is disabled.
+- Keep C1 target and owner suppression authoritative after facet eligibility is established.
+- Ensure already-published actions and properties still produce one normal command publication rather than a second recording-specific publication.
+
+**Non-Goals:**
+
+- Do not synthesize parented-collection selector or scalar-reference navigation actions; those belong to C3/C4b.
+- Do not change command result capture, DTOs, YAML, replay mapping, export/import, manager workflows, or background-completion policy.
+- Do not introduce a safe-action-specific configuration property or alter the C1 recording-support configuration shape.
+- Do not make result shape, bookmark availability, or later export reachability part of publishing eligibility.
+- Do not change commandlog persistence schemas or add a subscriber-side fallback publisher.
+
+## Decisions
+
+### Use command-publishing facet selection as the only eligibility seam
+
+Action and property facet creation will consult `CausewayConfiguration.Extensions.CommandLog.recordingSupport()` and install an appropriate `CommandPublishingFacet` when recording support is enabled.
+The runtime executor and commandlog subscriber will continue to consume `CommandPublishingFacet.isPublishingEnabled()` through their existing publication flow.
+
+This follows maintenance semantics and keeps command preparation, lifecycle notifications, DTO creation, and persistence on one path.
+A runtime-executor override or commandlog-subscriber fallback was rejected because either would duplicate metamodel policy and risk incomplete or duplicate lifecycle publication.
+
+### Add a recording-backed safe-action facet without changing state-changing action policy
+
+An unannotated or `AS_CONFIGURED` action with safe semantics will receive a configuration-backed facet that reports enabled only while recording support is `ENABLED`, even when the ordinary global action policy is `NONE` or ignores safe actions.
+An explicitly disabled safe action will retain its disabled annotation facet.
+An explicitly enabled action or an action with a command DTO processor will retain the existing enabled facet.
+Idempotent and non-idempotent actions will continue to follow existing annotation and global action publishing policies.
+
+This preserves maintenance’s safe-action opt-out and avoids treating all action semantics as recording candidates.
+Changing the global action command-publishing policy was rejected because that would broaden unrelated policy consumers and state-changing action behavior.
+
+### Install one recording-support property facet before ordinary property policy selection
+
+When recording support is enabled, property facet creation will select one property-specific recording facet before evaluating property annotation or global property publishing policy.
+That facet reports publishing enabled for unannotated, `AS_CONFIGURED`, explicitly enabled, and explicitly disabled properties.
+When recording support is disabled, existing annotation and global property publishing policy remain unchanged.
+
+The explicit-disabled override is intentionally stronger for properties than for safe actions because replay recording must not silently omit state mutations.
+Installing one facet rather than layering a fallback preserves one publication for properties already configured as published.
+Changing the global property policy to `ALL` was rejected because it would blur configuration semantics and affect consumers beyond recording support.
+
+### Keep C1 suppression downstream of metamodel eligibility
+
+Recording-aware facets determine whether an interaction is eligible for normal command publication, but `MemberExecutorServiceDefault.prepareCommandForPublishing(...)` will remain the authoritative suppression boundary for marked targets and owners.
+The facet factories will not attempt to inspect domain target types during metamodel construction.
+
+This preserves contributed and mixin member behavior and avoids duplicating suppression rules across metamodel paths.
+Focused tests will verify that enabled recording support does not bypass C1 suppression.
+
+### Port observable maintenance scenarios onto Causeway 4 test seams
+
+Metamodel tests will cover facet selection for action semantics, action annotations, property annotations, global policies, and enabled or disabled recording support.
+Runtime or commandlog tests will cover suppressed interactions and the absence of duplicate publication where the existing test infrastructure can verify those boundaries without introducing persistence-adapter-specific behavior.
+
+JPA and JDO persistence-matrix tests are not required unless implementation reveals adapter-specific commandlog behavior, because this change does not alter persistence and both interaction types remain on the existing subscriber path.
+
+## Risks / Trade-offs
+
+- [Risk] Recording support can substantially increase command volume by including safe queries and property edits.
+ → Mitigation: keep recording support disabled by default and preserve explicit safe-action opt-outs plus C1 suppression.
+- [Risk] Overriding explicit property publishing disablement is surprising.
+ → Mitigation: make the replay-completeness rule normative, document the asymmetry with safe actions, and test it directly.
+- [Risk] A fallback facet could coexist with an annotation facet and publish twice.
+ → Mitigation: select exactly one facet in each action or property creation branch and add explicit non-duplication coverage.
+- [Risk] Maintenance code differs structurally from Causeway 4 facet APIs.
+ → Mitigation: port the policy into current `FacetHolder`, semantic-facet, and immutable-configuration conventions rather than copying source mechanically.
+- [Risk] Suppression tests might pass at the metamodel level while runtime command preparation still publishes.
+ → Mitigation: retain and extend runtime coverage around `prepareCommandForPublishing(...)` with recording-aware eligible members.
+
+## Migration Plan
+
+The change is opt-in through the existing recording-support setting, so applications that leave it disabled require no migration.
+Applications enabling recording support will see additional safe-action and property-edit commands and can use explicit safe-action disablement or `CommandRecordingSuppressed` for intentional exclusions.
+Rollback consists of disabling recording support or reverting the facet-selection changes; no stored schema migration is required.
+
+## Open Questions
+
+None.
+Maintenance semantics resolve the deliberate difference between safe-action explicit opt-out and authoritative property-edit recording.
diff --git a/openspec/changes/reconcile-recording-aware-publishing/proposal.md b/openspec/changes/reconcile-recording-aware-publishing/proposal.md
new file mode 100644
index 00000000000..5c13f5b6aa1
--- /dev/null
+++ b/openspec/changes/reconcile-recording-aware-publishing/proposal.md
@@ -0,0 +1,30 @@
+## Why
+
+Causeway 4 now has the recording-support configuration and suppression foundation, but enabling it still does not make ordinary safe-action invocations or property edits available to the normal command-publishing pipeline.
+Without those interactions, recorded command sequences can omit finder steps and state changes needed for faithful replay.
+
+## What Changes
+
+- Make `causeway.extensions.command-log.recording-support=ENABLED` enable normal command publishing for safe actions.
+- Make enabled recording support install property command-publishing metadata for ordinary property edits, including properties that would otherwise resolve to disabled publishing.
+- Keep safe-action explicit opt-outs, C1 recording suppression, and the existing single command-publishing/subscriber path authoritative.
+- Preserve current action and property command-publishing behavior when recording support is disabled.
+- Add focused metamodel and runtime or commandlog tests for enabled, disabled, suppressed, explicitly configured, and non-duplicated interactions.
+- Defer synthetic navigation actions, replay mapping, export/import workflows, unified command management, and background-completion behavior to their later capability changes.
+
+## Capabilities
+
+### New Capabilities
+
+- `recording-aware-command-publishing`: Defines how recording support broadens safe-action and property-edit command-publishing eligibility while preserving normal publishing flow, suppression, opt-outs, and disabled-mode compatibility.
+
+### Modified Capabilities
+
+None.
+
+## Impact
+
+- Affects action and property command-publishing facet selection in `core/metamodel`.
+- Uses the existing immutable recording-support configuration in `core/config` without adding a new configuration property.
+- Exercises the existing runtime command publication and commandlog subscriber path without changing command DTO or persistence schemas.
+- Adds metamodel-level coverage and focused runtime or commandlog compatibility coverage.
diff --git a/openspec/changes/reconcile-recording-aware-publishing/specs/recording-aware-command-publishing/spec.md b/openspec/changes/reconcile-recording-aware-publishing/specs/recording-aware-command-publishing/spec.md
new file mode 100644
index 00000000000..f323339d2b7
--- /dev/null
+++ b/openspec/changes/reconcile-recording-aware-publishing/specs/recording-aware-command-publishing/spec.md
@@ -0,0 +1,111 @@
+## ADDED Requirements
+
+### Requirement: Recording support enables safe-action command publishing
+When `causeway.extensions.command-log.recording-support` is `ENABLED`, the system SHALL enable command publishing for action invocations with safe semantics through the normal action command-publishing facet model.
+The system SHALL apply this recording-aware eligibility to unannotated safe actions and safe actions configured as `AS_CONFIGURED`, including when the ordinary global action policy is `NONE` or ignores safe actions.
+The system MUST NOT use action result shape or bookmark availability to decide publishing eligibility.
+When recording support is `DISABLED`, safe actions MUST retain existing command-publishing behavior.
+
+#### Scenario: Unannotated safe action is eligible during recording
+- **GIVEN** recording support is `ENABLED`
+- **AND** a safe action has no explicit command-publishing setting
+- **WHEN** the metamodel evaluates command-publishing metadata for the action
+- **THEN** the action reports command publishing enabled
+
+#### Scenario: Global action policy does not exclude a recorded safe action
+- **GIVEN** recording support is `ENABLED`
+- **AND** the global action command-publishing policy is `NONE` or ignores safe actions
+- **AND** a safe action is unannotated or configured as `AS_CONFIGURED`
+- **WHEN** the metamodel evaluates command-publishing metadata for the action
+- **THEN** the action reports command publishing enabled
+
+#### Scenario: Safe action remains unchanged when recording is disabled
+- **GIVEN** recording support is `DISABLED`
+- **AND** a safe action is not otherwise command-published
+- **WHEN** a user invokes the action
+- **THEN** the invocation is not command-published solely because it has safe semantics
+
+#### Scenario: Result shape does not determine safe-action eligibility
+- **GIVEN** recording support is `ENABLED`
+- **AND** two otherwise equivalent safe actions return different result shapes or bookmark availability
+- **WHEN** the metamodel evaluates command-publishing metadata for both actions
+- **THEN** both actions have the same recording-aware publishing eligibility
+
+### Requirement: Safe-action opt-outs and state-changing policy remain authoritative
+An explicit `@Action(commandPublishing = Publishing.DISABLED)` setting SHALL remain a local opt-out for a safe action while recording support is enabled.
+Recording-aware safe-action publishing MUST NOT alter command-publishing eligibility for idempotent or non-idempotent actions.
+Existing explicit enablement and command DTO processor behavior SHALL remain authoritative and MUST NOT create a second publication path.
+
+#### Scenario: Explicitly disabled safe action remains disabled
+- **GIVEN** recording support is `ENABLED`
+- **AND** a safe action is explicitly configured with command publishing `DISABLED`
+- **WHEN** the metamodel evaluates command-publishing metadata for the action
+- **THEN** the action reports command publishing disabled
+
+#### Scenario: State-changing action retains existing policy
+- **GIVEN** recording support is `ENABLED`
+- **AND** an idempotent or non-idempotent action is not otherwise command-published
+- **WHEN** the metamodel evaluates command-publishing metadata for the action
+- **THEN** recording support does not make that action command-published solely because recording is enabled
+
+#### Scenario: Explicitly published safe action is not duplicated
+- **GIVEN** recording support is `ENABLED`
+- **AND** a safe action is already explicitly command-published or uses a command DTO processor
+- **WHEN** a user invokes the action once
+- **THEN** the normal command-publishing flow publishes at most one command for that invocation
+
+### Requirement: Recording support enables property-edit command publishing
+When recording support is `ENABLED`, the system SHALL enable command publishing for ordinary property edits through the normal property command-publishing facet model.
+Recording-aware property publishing SHALL apply to unannotated, `AS_CONFIGURED`, explicitly enabled, and explicitly disabled properties regardless of the ordinary global property publishing policy.
+When recording support is `DISABLED`, properties MUST retain their existing annotation and global-policy behavior.
+The system MUST install one authoritative property command-publishing facet and MUST NOT add a second property-edit publication path.
+
+#### Scenario: Unannotated property edit is eligible during recording
+- **GIVEN** recording support is `ENABLED`
+- **AND** a property has no explicit command-publishing setting
+- **WHEN** the metamodel evaluates command-publishing metadata for the property
+- **THEN** the property reports command publishing enabled
+
+#### Scenario: Explicitly disabled property is eligible during recording
+- **GIVEN** recording support is `ENABLED`
+- **AND** a property is explicitly configured with command publishing `DISABLED`
+- **WHEN** the metamodel evaluates command-publishing metadata for the property
+- **THEN** the property reports command publishing enabled for replay completeness
+
+#### Scenario: Property policy remains unchanged when recording is disabled
+- **GIVEN** recording support is `DISABLED`
+- **AND** a property is not otherwise command-published
+- **WHEN** a user edits the property
+- **THEN** the edit is not command-published solely because it is a property edit
+
+#### Scenario: Already-published property edit is not duplicated
+- **GIVEN** recording support is `ENABLED`
+- **AND** a property is already explicitly or globally command-published
+- **WHEN** a user edits the property once
+- **THEN** the normal command-publishing flow publishes at most one command for that edit
+
+### Requirement: Recording-aware publication preserves command-recording suppression
+Recording-aware action and property facets SHALL use the existing command preparation and publication lifecycle.
+An interaction whose target or member owner implements `CommandRecordingSuppressed` MUST remain excluded by the C1 suppression boundary even when recording-aware facet metadata reports publishing enabled.
+The system MUST NOT persist recording-aware interactions through a commandlog-specific fallback when normal command preparation suppresses them.
+
+#### Scenario: Marked safe-action target remains suppressed
+- **GIVEN** recording support is `ENABLED`
+- **AND** a safe action is recording-aware eligible
+- **AND** the interaction target or action owner implements `CommandRecordingSuppressed`
+- **WHEN** the action is invoked
+- **THEN** command preparation does not publish the invocation
+
+#### Scenario: Marked property target remains suppressed
+- **GIVEN** recording support is `ENABLED`
+- **AND** a property edit is recording-aware eligible
+- **AND** the interaction target or property owner implements `CommandRecordingSuppressed`
+- **WHEN** the property is edited
+- **THEN** command preparation does not publish the edit
+
+#### Scenario: Eligible unmarked interaction uses normal lifecycle
+- **GIVEN** recording support is `ENABLED`
+- **AND** an unmarked safe action or property edit is recording-aware eligible
+- **WHEN** the interaction executes
+- **THEN** command readiness, start, and completion use the existing command-publishing lifecycle
+- **AND** no recording-specific publication lifecycle is created
diff --git a/openspec/changes/reconcile-recording-aware-publishing/tasks.md b/openspec/changes/reconcile-recording-aware-publishing/tasks.md
new file mode 100644
index 00000000000..fa479b91b44
--- /dev/null
+++ b/openspec/changes/reconcile-recording-aware-publishing/tasks.md
@@ -0,0 +1,23 @@
+## 1. Recording-aware safe-action facets
+
+- [ ] 1.1 Add a configuration-backed action command-publishing facet that reports enabled for safe semantics only when command-log recording support is `ENABLED`.
+- [ ] 1.2 Update action facet selection so unannotated and `AS_CONFIGURED` safe actions use recording-aware eligibility while explicit disablement, explicit enablement, DTO processors, and state-changing actions preserve their existing branches.
+- [ ] 1.3 Add focused metamodel tests for enabled and disabled recording support, global `NONE` and ignore-safe policies, explicit safe-action opt-out, explicit publication, and non-safe action compatibility.
+
+## 2. Recording-aware property facets
+
+- [ ] 2.1 Add a property command-publishing facet selected when recording support is enabled and reporting publishing enabled through the normal facet contract.
+- [ ] 2.2 Update property facet selection so the recording-support facet is the single authoritative choice before annotation and global-policy branches, including for explicitly disabled and already-published properties.
+- [ ] 2.3 Add focused metamodel tests for unannotated, `AS_CONFIGURED`, explicitly disabled, explicitly enabled, globally configured, contributed, and mixin properties with recording support enabled and disabled.
+
+## 3. Runtime compatibility and documentation
+
+- [ ] 3.1 Extend runtime or commandlog coverage to prove recording-aware eligible safe actions and property edits use normal command publication while C1 target and owner suppression remains authoritative.
+- [ ] 3.2 Add regression coverage proving explicitly published safe actions and property edits do not create duplicate command publication.
+- [ ] 3.3 Update recording-support documentation to describe safe-action inclusion, safe-action explicit opt-out, authoritative property-edit inclusion, disabled-mode compatibility, and suppression.
+
+## 4. Verification
+
+- [ ] 4.1 Run focused metamodel, runtime-service, and commandlog tests for recording-aware command publishing with JDK 21.
+- [ ] 4.2 Run the affected aggregate Maven build with JDK 21 and confirm existing command-recording and result-metadata tests remain green.
+- [ ] 4.3 Run IDE compilation and inspections plus strict OpenSpec and repository checks, confirming the implementation introduces no C3/C4b synthetic actions or later replay, export, manager, reachability, or background-gate behavior.