[ 
https://issues.apache.org/jira/browse/GROOVY-12468?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18128996#comment-18128996
 ] 

ASF GitHub Bot commented on GROOVY-12468:
-----------------------------------------

codecov-commenter commented on PR #2992:
URL: https://github.com/apache/groovy/pull/2992#issuecomment-6285612189

   ## 
[Codecov](https://app.codecov.io/gh/apache/groovy/pull/2992?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 Report
   :x: Patch coverage is `82.81250%` with `11 lines` in your changes missing 
coverage. Please review.
   :white_check_mark: Project coverage is 72.4360%. Comparing base 
([`c227066`](https://app.codecov.io/gh/apache/groovy/commit/c227066191b1a0c95b12c3672cc5f333fc4f27d7?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache))
 to head 
([`21fe917`](https://app.codecov.io/gh/apache/groovy/commit/21fe917740578fe26386293b840061cc034c0e31?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
   :warning: Report is 4 commits behind head on master.
   
   | [Files with missing 
lines](https://app.codecov.io/gh/apache/groovy/pull/2992?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 | Patch % | Lines |
   |---|---|---|
   | 
[...he/groovy/contracts/ast/SpecASTTransformation.java](https://app.codecov.io/gh/apache/groovy/pull/2992?src=pr&el=tree&filepath=subprojects%2Fgroovy-contracts%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fgroovy%2Fcontracts%2Fast%2FSpecASTTransformation.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3VicHJvamVjdHMvZ3Jvb3Z5LWNvbnRyYWN0cy9zcmMvbWFpbi9qYXZhL29yZy9hcGFjaGUvZ3Jvb3Z5L2NvbnRyYWN0cy9hc3QvU3BlY0FTVFRyYW5zZm9ybWF0aW9uLmphdmE=)
 | 82.8125% | [2 Missing and 9 partials :warning: 
](https://app.codecov.io/gh/apache/groovy/pull/2992?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 |
   
   <details><summary>Additional details and impacted files</summary>
   
   
   
   [![Impacted file tree 
graph](https://app.codecov.io/gh/apache/groovy/pull/2992/graphs/tree.svg?width=650&height=150&src=pr&token=1r45138NfQ&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)](https://app.codecov.io/gh/apache/groovy/pull/2992?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   
   ```diff
   @@                Coverage Diff                 @@
   ##               master      #2992        +/-   ##
   ==================================================
   + Coverage     72.4271%   72.4360%   +0.0089%     
   - Complexity      40610      40633        +23     
   ==================================================
     Files            1643       1644         +1     
     Lines          142669     142733        +64     
     Branches        26793      26812        +19     
   ==================================================
   + Hits           103331     103390        +59     
   + Misses          29832      29830         -2     
   - Partials         9506       9513         +7     
   ```
   
   | [Files with missing 
lines](https://app.codecov.io/gh/apache/groovy/pull/2992?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 | Coverage Δ | |
   |---|---|---|
   | 
[...he/groovy/contracts/ast/SpecASTTransformation.java](https://app.codecov.io/gh/apache/groovy/pull/2992?src=pr&el=tree&filepath=subprojects%2Fgroovy-contracts%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fgroovy%2Fcontracts%2Fast%2FSpecASTTransformation.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3VicHJvamVjdHMvZ3Jvb3Z5LWNvbnRyYWN0cy9zcmMvbWFpbi9qYXZhL29yZy9hcGFjaGUvZ3Jvb3Z5L2NvbnRyYWN0cy9hc3QvU3BlY0FTVFRyYW5zZm9ybWF0aW9uLmphdmE=)
 | `82.8125% <82.8125%> (ø)` | |
   
   ... and [9 files with indirect coverage 
changes](https://app.codecov.io/gh/apache/groovy/pull/2992/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   </details>
   <details><summary> :rocket: New features to boost your workflow: </summary>
   
   - :snowflake: [Test 
Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, 
report on failures, and find test suite problems.
   - :package: [JS Bundle 
Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save 
yourself from yourself by tracking and limiting bundle sizes in JS merges.
   </details>




> @Spec spike
> -----------
>
>                 Key: GROOVY-12468
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12468
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>
> _This is a spike of a feature several other languages are experimenting 
> with/supporting. It is essentially an annotation that records a comment (not 
> unlike @Groovydoc) but can have special meaning for tooling - allowing 
> "hole-driven" development._
> h2. Summary
> Add a {{@Spec}} annotation that marks a method (and optionally a loop or 
> local declaration) as having a prose specification intended as an LLM prompt, 
> alongside the method's typed signature and any {{@Requires}}/{{@Ensures}} 
> contracts. A method carrying {{@Spec}} with an empty body is an unfilled 
> "hole". A tool (outside the compiler) fills the hole ahead of time by writing 
> a generated body into the source under the spec, and the spec stays in place 
> as documentation and as the input for later regeneration.
> The annotation is essentially a structured comment: unlike a plain comment, 
> tools can find it, and the compiler can tell a filled body from an unfilled 
> one.
> h2. Motivation
> Martin Odersky's Scala Days 2026 keynote showed program holes filled ahead of 
> time: a method with a typed signature, a prose spec string and {{???}}, and a 
> "sync" step where an agent writes the body under the spec. Groovy can offer 
> the same workflow with a stronger guarantee, because a fill can be checked 
> against contracts, not just against types.
> * The spec is written for both people and models, and it lives next to the 
> code it describes.
> * Contracts make the spec checkable. For example, the keynote's own generated 
> date parser accepts 31 February; a one-line {{@Ensures}} catches it.
> * No runtime evaluation, in-process compilation or typed binding is needed: 
> the generated body sits in real source and the compiler sees its real scope.
> * Writing contracts for this example already found GROOVY-12463 (contracts 
> skipped on a trailing implicit return after an early {{return}}).
> h2. Example
> {code:groovy}
> import groovy.contracts.Ensures
> import groovy.contracts.Requires
> class Dates {
>     @Spec('''
>         Parse an ISO-8601 calendar date (yyyy-MM-dd) into its year, month
>         and day. Reject dates that do not exist, such as 2026-02-31.
>     ''')
>     @Requires({ text != null })
>     @Ensures({ result.month in 1..12 && result.day <= 
> YearMonth.of(result.year, result.month).lengthOfMonth() })
>     static DateParts parse(String text) { }   // unfilled: throws until synced
> }
> {code}
> After a sync, the body is filled in and the {{@Spec}} remains, with a 
> {{fill}} member recording what was generated (see below).
> h2. Proposal
> h3. 1. The annotation
> * {{@Spec(String value)}}: the prose specification.
> * Target: methods; also {{@ExtendedTarget(ExtendedElementType.LOOP)}} and 
> local variable declarations for smaller holes. Probes on 6.0.0 confirm the 
> annotation can be placed on {{for}}, {{while}} and {{do-while}} loops and on 
> local declarations.
> * {{fill}} member (optional, written by tooling): a hash of the spec text and 
> of the generated body, so a tool can tell whether the spec or the body has 
> changed since the last fill.
> * Source/class retention to be decided. Loop and local annotations are not 
> written to the class file in any case, so those specs exist only in source.
> h3. 2. A small local transform
> * A method carrying {{@Spec}} with an empty body is compiled to throw (for 
> example {{UnsupportedOperationException("unfilled @Spec: Dates.parse")}}) 
> instead of returning {{null}}. An unfilled loop can be made to throw 
> similarly.
> * The transform never calls a model. Compiling still runs nothing beyond what 
> it runs today.
> h3. 3. The sync tool (outside core)
> Not part of this ticket's compiler change, but it defines the contract the 
> annotation must support. A library with a command line (and possibly an MCP 
> tool) that IDE plugins and CI call rather than reimplement:
> * Find unfilled specs; prompt the model with the prose, contracts, signature 
> and types in scope.
> * Compile each candidate with the configured type checkers, check contracts 
> (by proof via groovy-verify where possible, otherwise by tests), and retry on 
> diagnostics or counterexamples. Only a candidate that passes is written back.
> * Use the {{fill}} hash to classify each spec:
> ** *in sync*: nothing to do
> ** *stale*: spec changed, body untouched; regenerate
> ** *hand-edited*: body changed by a person; never overwrite. Offer to update 
> the spec (as a diff for a person to approve, and only if the edited body 
> still satisfies the contracts), drop {{@Spec}}, or report the drift
> ** *conflict*: both changed; a person resolves it
> ** *unfilled*: no body yet
> * Confirmation scales with how well a fill was checked: proved fills apply 
> without asking; fills whose contracts or tests pass apply and are shown for 
> review; compile-only fills ask; failures leave the hole unfilled with the 
> last diagnostics. Updating a spec from code always asks.
> * A non-interactive mode for CI fails the build when any spec is stale, 
> hand-edited or unfilled.
> h2. Open questions
> * *Home*: should the annotation and transform start in core 
> ({{groovy.transform.Spec}}), in groovy-contracts next to 
> {{@Requires}}/{{@Ensures}}, or outside the project until the convention has 
> proved itself?
> * *Retention*: source only, or class retention so method-level specs are 
> visible to reflection and to tools reading compiled libraries?
> * *Hash format*: what exactly goes into {{fill}}, and should 
> whitespace/formatting changes to the body count as a hand edit?
> * *Static scope*: should a {{@Spec}} method be compiled statically by 
> default, so checkers see every call in generated code? Probes on 6.0.0 show 
> per-method static compilation works, including closures and anonymous inner 
> classes in the method; a loop-level spec would require compiling the whole 
> enclosing method statically.
> h2. Out of scope
> * Calling a model from the compiler or from an AST transform.
> * Runtime (LACUNA-style) holes filled while the program runs; those need a 
> typed binding (GROOVY-12462) and a restricted compiler profile (GEP pending), 
> and can build on this later.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to