Recover the specifications a slice carries into the document - #2411
Recover the specifications a slice carries into the document#2411woksin wants to merge 5 commits into
Conversation
Screenplay has a specification construct - given, when, then - and nothing in the model to fill it from, so the generator has never written one. This introduces the shape a scenario is recovered into and the names the source of one is recognized by, ahead of the reading and the writing that follow. A given, a when and a then are the same shape - a name and a list of values - so one model covers all three and the step it sits in says which it is. A rejection carries the reason the source names for it, and an empty one where the source names none: the scenario is named after the words the source uses for it, so what it was about is already said there and inventing a sentence to repeat it would describe an application nobody wrote. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A Cratis application carries its integration specifications beside the slice they are about, in a shape rigid enough to read: what had happened is stated against a scenario or appended to the event log, one command is issued, and each assertion says one thing about what followed. That is the specification construct exactly, so the scenarios were there all along and the document simply never carried them. Both shapes Arc documents are read - the pipeline driven in process and a running host driven over HTTP - matched on the names of the testing types alone, so neither testing package has to be referenced. A specification about a collaborator is passed over rather than reported, because what is read is decided by what a specification touches rather than by where it sits. Values are recovered the way a produces mapping is, one source shorter: a scenario refers to nothing outside itself, so a constant is the only source of a value there is. A value that is code is left out and the rest of the scenario stands. A step that is code, or one that only happens under a condition, takes the scenario with it - an example missing the state it started from is a different example from the one the source states, and stating it would be the one failure mode a reader cannot catch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A document stating what a slice does and carrying none of the scenarios proving it loses half the story, so every scenario recovered is written into the slice it belongs to, ordered by name like everything else in a slice. Nothing a step states is left out over its name. Every other block decides what a line is from its first word, so a property named after a directive collides with it; the values of a step are written one level deeper than the step itself and the step takes every line beneath it as a value, whatever its first word says. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both shapes Arc documents are specified against - the pipeline driven in process and a running host driven over HTTP - along with a rejection named and unnamed, a value that is code, and each of the three ways a scenario is left out whole. The testing surface is declared as source rather than referenced, which asks the recognition the only question worth asking of it: whether the names alone are enough. The end to end specification carries a scenario from source through the printed text and back through the Screenplay compiler, because a scenario is the one construct where the value of a property and the name of a step sit one indentation apart - and a document nobody reads back is a document that compiles by luck. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two lines of work built from the same base are stacked here: reading an application written as several projects, and recovering the scenarios a slice is specified by. Both branches had independently claimed SP0037 and SP0038 for different meanings. A code is never reused and never renumbered, because consumers suppress and group on it, so one number cannot carry two meanings. The multiproject codes are already published on an open pull request whose reviewer notes cite them, so those keep the numbers - SP0037 stays RepeatedDeclarationAcrossProjects and SP0038 stays ProjectsWithoutASharedRoot - and the specification codes move on: UnreadableSpecification to SP0039 and UnreadableSpecificationValue to SP0040. ApplicationModelAnalyzer had to place specification recovery in the flow that now reads several compilations. A scenario reads the symbols of the project it is written in, so it is recovered per project exactly as an artifact is. Which slice it belongs to is a different question: it names no slice, it is placed by the nearest namespace above it that declares one, and nothing says that slice is declared by the project the scenario sits in - a bounded context handling its commands beside the contracts project publishing its events is specified from the project holding the handlers. So each project is asked for its scenarios only once the slices of every project have been joined, and placement is decided against the slices of the whole application. The scenarios landing in one slice are then joined by the rule the union already applies to everything else within a slice: one of a name, the first kept. 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 #2410, which is stacked on #2408; this merges last of the three. What is recognizedA class is treated as a Chronicle integration specification when it is a non-abstract top-level class with a
The issue's evidence was out of date about its own reference application. #2404 describes Two judgement calls
A conditional step takes the whole scenario with it. A real correctness bug was found and fixed mid-implementation: Placement, which the merge changedSpecifications are read per project (all semantic work on one compilation), but placed after Volume, which was the open question+3,460 lines for 507 scenarios — about 7 lines each, 62% growth, not the multiple I expected. Most values are runtime identities and get dropped, so a scenario averages 2.4 value lines. No option to disable was added, and I agree with that: if a larger application does make a document unwieldy, the right lever is a per-slice or per-module filter driven by a real complaint, not a global off switch added on speculation. Verification
Two corrections the agent made to its own work, worth readingA "zero specifications recovered" result was not the merge. That application's A "nondeterminism" finding was a broken guard, not a real defect. Five distinct hashes across six runs looked like nondeterminism in the multi-project path. The cause was the application being edited concurrently, while the guard — Known limits
|
|
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
specificationblocks, so a document states what the application is specified to do rather than only what it declares; a scenario with a step that cannot be read statically is reported rather than guessed at (Screenplay generation: recover 'specification' blocks from Chronicle integration specs #2404)