Skip to content

Read only the projects of a solution that hold the application - #63

Merged
woksin merged 6 commits into
mainfrom
fix/screenplay-generation-defects
Aug 10, 2026
Merged

Read only the projects of a solution that hold the application#63
woksin merged 6 commits into
mainfrom
fix/screenplay-generation-defects

Conversation

@woksin

@woksin woksin commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes which projects of a solution take part in Screenplay generation, and updates the Cratis packages.

Added

  • --modules-from-namespace-roots on screenplay generate, taking each outermost namespace segment as a module rather than nesting everything under one
  • .slnf solution filters are accepted as a generation target

Changed

  • Cratis.Arc.Screenplay 20.68.0 to 21.0.1, Chronicle packages 16.11.0 to 16.19.1, Cratis.Fundamentals 7.16.6 to 7.17.1

Fixed

  • A multi-targeted project was read once per target framework, and its spec projects were not recognised as such, so spec code entered the generated document
  • Projects that cannot declare a command or an event are no longer read when generating from a solution, so test hosts and analyzer projects stop describing the application
  • Generating against a solution that has not been restored reported every consequence of the missing restore instead of the missing restore itself

woksin added 6 commits August 6, 2026 17:20
Cratis.Screenplay moves to 1.8.0 so that 'screenplay validate' compiles
documents with the same compiler the shipped Stage image runs — a document
the CLI gate accepted was not guaranteed to be one Stage accepts.

Cratis.Arc.Screenplay moves to 21.0.1, and Chronicle and Fundamentals to
their latest, none of which changes anything the CLI reads.
Cratis.Screenplay 1.7.0 added an optional 'Types' parameter to the
ApplicationSyntax primary constructor. Source compatible, binary breaking:
the published Cratis.Arc.Screenplay is compiled against 1.5.2, so its call
site names a constructor that no longer exists and every generation ends in

  Method not found: 'Void Cratis.Screenplay.Syntax.ApplicationSyntax..ctor(...)'

Verified against both 1.7.0 and 1.8.0. The compiler used by 'screenplay
validate' therefore stays a release behind the one the Stage image runs
until a Cratis.Arc.Screenplay built against 1.7.0 or later is published.
The generator can name the module of each feature after the outermost
segment of its namespace, and reaches that only when nothing named a module
and no single assembly names the application - so an application whose
namespaces already say what its modules are comes back as one module holding
every feature, with no way to ask for anything else.

--modules-from-namespace-roots asks for it. Where every slice shares a root
namespace, that outermost segment is the root, so it pairs with
--skip-segments to move the modules down to the segment that tells them
apart: Samples/Library then emits Authors, Inventory and Lending as modules
rather than as features of one module Library.
Three ways a document came to describe something other than the application
it names:

A workspace opens a multi-targeted project once per target framework and
tells the results apart by appending the framework to the name, so a project
arrived as Lib(net10.0) and Lib(netstandard2.0). The spec-name test was asked
of that decorated name and no longer recognized MyApp.Specs, and the dedupe
grouped by it and so could never group anything - both compilations of every
multi-targeted project were handed to the generator. Both questions are now
asked of the name with the framework removed, and one target framework is
picked deterministically.

Whether a project holds part of the application is now asked of what it can
see: every artifact is declared with an attribute the framework ships, so a
project resolving neither the Arc nor the Chronicle one is left out. A Roslyn
analyzer or a build-time tool beside the application no longer says something
about the solution that is not true. Pointing at a single project still reads
it whatever it can see.

The host integration specs start the application in is turned away with the
specs it serves, by name, because it references the same framework the
application does and nothing it can see tells it apart.

A solution filter is accepted and read as the solution it filters.
An unrestored project still opens and still yields a compilation - one with
no package reference resolved, in which every framework type the application
uses reads as missing. Generating against an unrestored solution therefore
produced eleven SP0024 errors saying 'Chronicle' does not exist in the
namespace 'Cratis', a 494-line document describing nobody's application, and
not one word about running a restore.

The assets file is asked for before anything is compiled, and its absence is
reported as CLI0005 naming the projects and the command to run. Nothing is
generated, because a document read from a half-resolved compilation can only
mislead. Where the intermediate output folder was moved - the artifacts
output layout of the SDK moves it out of the project folder - it is found
through the assembly the project compiles into it, and a project neither path
says anything about is taken for restored rather than failed.
@woksin woksin added the minor New features, non-breaking additions label Aug 6, 2026
@woksin

woksin commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

Reviewer context.

Gates. dotnet test Source/Cli.Specs 404 → 431 passing, 0 failed. dotnet build -c Release 0 errors, 0 warnings. Documentation/verify-markdown.sh clean.

Verified end to end on a repro solutionApp and App.Specs both multi-targeted, plus a netstandard2.0 analyzer project with no Cratis types:

projects read
before ["Analyzer","App(net10.0)","App(net9.0)","App.Specs(net10.0)","App.Specs(net9.0)"]
after ["App"]

The baseline document contained a whole feature Specs block built from the spec project. Roslyn names multi-TFM projects Name(tfm), so the spec-name test never matched and the dedupe by project name could not help.

On Studio, SP0038 moved from "The 17 projects of the application…" to "The 16 projects…" and the SP0024 that Specs.AppHost contributed is gone — that project passes the capability probe because it project-references the real ones, so it is the name rule that turns it away, matching Arc's own reference loader.

Cratis.Screenplay could not move and is still 1.6.4. Published Cratis.Arc.Screenplay 21.0.1 is compiled against Cratis.Screenplay 1.5.2, and 1.7.0 added a parameter to the ApplicationSyntax primary constructor — source-compatible, binary-breaking. Forcing 1.8.0 makes every generation die with Method not found: 'Void Cratis.Screenplay.Syntax.ApplicationSyntax..ctor(...)'. Verified against both 1.7.0 and 1.8.0. Cratis/Arc#2462 unblocks it. The reason is recorded in its own commit so the next attempt finds it.

A question for you on the new flag. I left --modules-from-namespace-roots off by default, because turning it on changes the shape of every existing document. But it does not on its own produce the intended result: where every slice shares a root namespace, the outermost segment is that shared root, so you get one module again. Samples/Library needs --modules-from-namespace-roots --skip-segments 1 to give module Authors / module Inventory / module Lending. If the intended default is really "modules from namespace roots, shared root skipped", that combination is arguably an Arc-side change — Cratis/Arc#2460 covers deriving modules from folders, which says it directly.

Not done: cratis render (#62), blocked on the same version constraint.

@woksin woksin closed this Aug 10, 2026
@woksin woksin reopened this Aug 10, 2026
@woksin
woksin merged commit d662575 into main Aug 10, 2026
7 checks passed
@woksin
woksin deleted the fix/screenplay-generation-defects branch August 10, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor New features, non-breaking additions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant