Describe an application split across several projects as one document - #2410
Describe an application split across several projects as one document#2410woksin wants to merge 6 commits into
Conversation
An application written as several projects has one source root per project and a single directory to write all of their paths relative to, worked out from the roots together. Saying a project's root as a directory rather than only as the paths made from it is what lets that be asked at all. The comparing of directories moves out with it. The same three questions - normalize, share a prefix, is this a file system root - are asked of one project's directories and of the roots of all of them, so they belong beside neither. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A command handing its work to an aggregate root reads the behavior's body, and that body is the one an analysis reads that need not belong to the project the command does. A workspace loads a project reference as a compilation, so the sibling project's source is right there - and asking the wrong compilation for a semantic model is not a wrong answer but an ArgumentException. An aggregate root in a domain project called from the project above it therefore crashed generation rather than describing the layered application it is. A tree belonging to no project handed over is one that cannot be read at all, and that is now said rather than leaving the command stated as producing nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A layered application is not described by any one of its projects. The generator took a single compilation, so pointing it at one project of a solution described that project and referred to the events of the rest as things it never introduces - the difference between describing the project you pointed at and describing the application, which is the stated goal of the tool. Generate now also takes a list. Each compilation contributes what its own assembly declares, and what the projects hold together becomes one document: a namespace two of them declare into is one slice, a concept three of them refer to is declared once, a policy the host registers is found by the artifact naming it, an aggregate root in the project below is one a command hands its work to, and an event a sibling project declares is one the application has rather than one it imports. An event a package declares is still imported, because a package really is outside the application. Nothing of this reaches the document through the order the list arrives in. Nothing decides what order a host enumerates the projects of a solution in, so they are put into assembly name order before anything is read. Paths stay relative and now say which project a file belongs to: they are written relative to the directory the projects are all under. Projects that share no directory keep their own roots, because a path relative to the root of a file system is the machine's own layout wearing a relative path's clothes, and that is reported (SP0038). What two projects declare under one name in one slice cannot both be described, so the first is kept and the second is reported (SP0037). The single-compilation overload is unchanged and now runs through the same path as a list of one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two projects built from source strings, one referencing the other the way a workspace loads a project reference, is the whole shape of a layered application - and every one of these fails against a generator that reads one compilation, most of them by describing half of what the projects hold. Each is a claim that can fail on its own: the slice two projects write, the name only one of them can be described under, the concept declared once however many refer to it, the policy the host registers for an artifact elsewhere, the aggregate root a project above hands its work to, the event a sibling declares against the event a package does, the directory the paths are relative to when the projects share one and when they do not, and the same projects handed over the other way round printing the same bytes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The end to end check exists to get behind the seam every specification is built from strings on, and a compilation built from strings cannot have a sibling project loaded as a compilation reference - which is exactly where an application of several projects lives. Handing the harness a solution rather than a project is what puts a real layered application through the same gate: every project of it that is not a specification project, generated into one document, read back by the Screenplay compiler. Handing it a single project does exactly what it did. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Reviewer context — deliberately kept out of the description. This is agent-authored code that no human has read yet. Green CI is not sign-off. Do not merge without explicit review. Stacked on #2408; it must merge after. APIScreenplayGenerationResult Generate(IReadOnlyList<Compilation> compilations, ScreenplayOptions options);
ApplicationModelAnalysis Analyze(IReadOnlyList<Compilation> compilations, ScreenplayOptions options);The single- Ordering. Compilations are sorted by assembly name, tie-broken by the ordinally-first source file path, before anything is read — caller order never reaches the model. What projects genuinely share is unified (one type registry, one aggregate-root catalogue, one cross-slice query set, one diagnostics sequence); everything reading symbols of a single compilation stays per project. The four judgment calls
A latent bug found on the wayA command handing work to an aggregate root in another project crashed with Verification
Two honest caveatsThe single-project regression check is parent-vs-mine under identical environment, not against the published baseline. The first run reproduced the stated 5530 lines / 1100 diagnostics exactly; every run afterwards — including runs of the unmodified parent code, confirmed by stashing — gives 5527 / 1108, because that application's design-time build mutated its own gitignored
|
|
Independent verification of the multi-project result, run separately from the work itself. Generated from the reference application's full solution (
Line count differs slightly from the figure in the report above (5,641 vs 5,639) because that application's working tree is being edited concurrently; it is drift in the source, not in the generator. CI on this PR is fully green: 43 passing, 0 failing, 45 checks. |
|
Superseded by #2413, which now targets Nothing is lost — every commit here is an ancestor of that branch, and the branch is kept. Reviewer context for all of it is consolidated into a single comment there. Closing so there is one PR to review and one set of release notes rather than four that have to be merged in order. |
Added
Fixed