feat(dev-team): add licensing skill and command#329
feat(dev-team): add licensing skill and command#329gandalf-at-lerian wants to merge 1 commit intomainfrom
Conversation
Add ring:dev-licensing skill and /ring:dev-license command for applying or switching licenses across Lerian repositories. Three license types supported: - Apache 2.0 (open source, e.g. Midaz core) - Elastic License v2 (source-available Lerian products) - Proprietary (Lerian Studio General License) The skill handles LICENSE file replacement, source file header updates, SPDX identifier updates, and consistency validation. Also updates core.md License Headers section to replace hardcoded Elasticsearch B.V. headers with Lerian-specific templates for all three license types, and integrates license detection into dev-cycle Gate 0 as an advisory check. New files: - dev-team/skills/dev-licensing/SKILL.md - dev-team/skills/dev-licensing/references/apache-2.0.txt - dev-team/skills/dev-licensing/references/elastic-v2.txt - dev-team/skills/dev-licensing/references/proprietary.txt - dev-team/commands/dev-license.md Modified: - dev-team/docs/standards/golang/core.md (License Headers section) - dev-team/skills/dev-cycle/SKILL.md (license detection at Gate 0)
WalkthroughThis pull request introduces a comprehensive multi-license framework for service repositories, replacing the fixed Elastic License 2.0 header standard with a flexible system supporting Apache 2.0, Elastic License v2, and Proprietary licenses. The changes include updated coding standards, a new licensing command definition, a licensing orchestrator skill with multi-gate validation flow, and canonical license reference texts. Changes
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@dev-team/docs/standards/golang/core.md`:
- Around line 903-905: The table entry "LICENSE location | Inline in header"
conflicts with the "ELv2 required header template" described earlier; update the
header guidance so the header component includes an explicit LICENSE file
reference to match ELv2 requirements. Concretely, modify the table row for
"LICENSE location" and the "Header component" guidance to state that the header
must include a "LICENSE: <repository LICENSE>" reference (or point to the
LICENSE file in the repo root) and ensure the "License reference" row remains
"MUST match the LICENSE file in the repo root"; update the documentation text
near the "ELv2 required header template" and the table entries ("License
reference" and "LICENSE location") so they are consistent.
In `@dev-team/skills/dev-cycle/SKILL.md`:
- Around line 1851-1856: The code assigns state.license_type from license_type
which remains "unknown" because the selected value isn't persisted after the
prompt flow; update the flow so that when the user selects a license (the branch
that invokes Skill("ring:dev-licensing") with the chosen type) you set
state.license_type = <chosen value> immediately before logging "License
detected: {license_type}" (and ensure the "skip" branch still sets
state.license_type appropriately if desired), so that state.license_type
reflects the user selection rather than the initial "unknown".
In `@dev-team/skills/dev-licensing/references/proprietary.txt`:
- Line 3: The file contains a hardcoded year "2025" which prevents the
workflow's --year override and Gate 2 proprietary year substitution from
propagating to LICENSE; update the content in proprietary.txt to use the
project's year substitution token (e.g., replace the literal "2025" with the
same placeholder the workflow expects such as a {{YEAR}}/YEAR variable or the
repository's substitution syntax) so the --year flag and Gate 2 processor can
inject the correct year at build time, and verify the substitution step reads
this file during the licensing generation step.
In `@dev-team/skills/dev-licensing/SKILL.md`:
- Around line 34-38: The schema currently marks license_type as required which
blocks the interactive detection flow and causes /ring:dev-license to fail with
no args; remove license_type from the schema's required array (make it optional)
and adjust the /ring:dev-license handler to detect and prompt for license_type
when it's missing (i.e., only enforce a provided license_type if the caller
supplies it), ensuring the detection flow runs when license_type is absent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: bb2920db-d6fb-46db-a9a2-53e95a5c1f4a
📒 Files selected for processing (7)
dev-team/commands/dev-license.mddev-team/docs/standards/golang/core.mddev-team/skills/dev-cycle/SKILL.mddev-team/skills/dev-licensing/SKILL.mddev-team/skills/dev-licensing/references/apache-2.0.txtdev-team/skills/dev-licensing/references/elastic-v2.txtdev-team/skills/dev-licensing/references/proprietary.txt
| | License reference | Depends on repository LICENSE | MUST match the LICENSE file in the repo root | | ||
| | LICENSE location | Inline in header | No separate LICENSE file reference needed | | ||
|
|
There was a problem hiding this comment.
Header component guidance conflicts with ELv2 required template
Line 904-Line 905 says no LICENSE-file reference is needed, but the ELv2 required header template (Line 879-Line 883) explicitly requires LICENSE reference. This contradiction can produce non-compliant headers.
🔧 Proposed fix
-| LICENSE location | Inline in header | No separate LICENSE file reference needed |
+| LICENSE location | Repository root (`LICENSE`) | Header text MUST align with repository LICENSE; ELv2 header explicitly references LICENSE |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | License reference | Depends on repository LICENSE | MUST match the LICENSE file in the repo root | | |
| | LICENSE location | Inline in header | No separate LICENSE file reference needed | | |
| | License reference | Depends on repository LICENSE | MUST match the LICENSE file in the repo root | | |
| | LICENSE location | Repository root (`LICENSE`) | Header text MUST align with repository LICENSE; ELv2 header explicitly references LICENSE | | |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@dev-team/docs/standards/golang/core.md` around lines 903 - 905, The table
entry "LICENSE location | Inline in header" conflicts with the "ELv2 required
header template" described earlier; update the header guidance so the header
component includes an explicit LICENSE file reference to match ELv2
requirements. Concretely, modify the table row for "LICENSE location" and the
"Header component" guidance to state that the header must include a "LICENSE:
<repository LICENSE>" reference (or point to the LICENSE file in the repo root)
and ensure the "License reference" row remains "MUST match the LICENSE file in
the repo root"; update the documentation text near the "ELv2 required header
template" and the table entries ("License reference" and "LICENSE location") so
they are consistent.
| → Ask user: "No LICENSE file detected. Which license should this repository use? [apache|elv2|proprietary|skip]" | ||
| → If user selects a license: invoke Skill("ring:dev-licensing") with chosen type | ||
| → If user selects "skip": log "⚠️ WARNING: No LICENSE file. License headers may be inconsistent." | ||
|
|
||
| Store: state.license_type = license_type | ||
| Log: "License detected: {license_type}" |
There was a problem hiding this comment.
Persist the selected license value before writing state
After the prompt flow (Line 1851-Line 1853), state.license_type is still assigned from license_type, which starts as "unknown". If the user selects a license, that selected value must be assigned before Line 1855.
🔧 Proposed fix
-7. Detect repository license:
- license_type = "unknown"
+7. Detect repository license:
+ license_type = "unknown"
+ selected_license = ""
@@
- - If not found (no LICENSE file):
+ - If not found (no LICENSE file):
→ Ask user: "No LICENSE file detected. Which license should this repository use? [apache|elv2|proprietary|skip]"
- → If user selects a license: invoke Skill("ring:dev-licensing") with chosen type
+ → If user selects a license:
+ - selected_license = {user_selection}
+ - license_type = selected_license
+ - invoke Skill("ring:dev-licensing") with chosen type
→ If user selects "skip": log "⚠️ WARNING: No LICENSE file. License headers may be inconsistent."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@dev-team/skills/dev-cycle/SKILL.md` around lines 1851 - 1856, The code
assigns state.license_type from license_type which remains "unknown" because the
selected value isn't persisted after the prompt flow; update the flow so that
when the user selects a license (the branch that invokes
Skill("ring:dev-licensing") with the chosen type) you set state.license_type =
<chosen value> immediately before logging "License detected: {license_type}"
(and ensure the "skip" branch still sets state.license_type appropriately if
desired), so that state.license_type reflects the user selection rather than the
initial "unknown".
| @@ -0,0 +1,24 @@ | |||
| Lerian Studio General License | |||
|
|
|||
| Copyright (c) 2025 Lerian Studio Ltd. All rights reserved. | |||
There was a problem hiding this comment.
Year substitution cannot work with a hardcoded year
Line 3 hardcodes 2025, but the workflow/docs support --year and Gate 2 describes proprietary year substitution. With this reference, overrides won’t propagate to LICENSE.
🔧 Proposed fix
-Copyright (c) 2025 Lerian Studio Ltd. All rights reserved.
+Copyright (c) {YEAR} Lerian Studio Ltd. All rights reserved.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Copyright (c) 2025 Lerian Studio Ltd. All rights reserved. | |
| Copyright (c) {YEAR} Lerian Studio Ltd. All rights reserved. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@dev-team/skills/dev-licensing/references/proprietary.txt` at line 3, The file
contains a hardcoded year "2025" which prevents the workflow's --year override
and Gate 2 proprietary year substitution from propagating to LICENSE; update the
content in proprietary.txt to use the project's year substitution token (e.g.,
replace the literal "2025" with the same placeholder the workflow expects such
as a {{YEAR}}/YEAR variable or the repository's substitution syntax) so the
--year flag and Gate 2 processor can inject the correct year at build time, and
verify the substitution step reads this file during the licensing generation
step.
| required: | ||
| - name: license_type | ||
| type: string | ||
| enum: [apache, elv2, proprietary] | ||
| description: "The license to apply: apache (Apache 2.0), elv2 (Elastic License v2), proprietary (Lerian Studio General License)" |
There was a problem hiding this comment.
license_type cannot be required if interactive detection is supported
The schema currently requires license_type, but the intended flow supports running without it and asking the user during detection. This creates an entrypoint failure for /ring:dev-license with no args.
🔧 Proposed fix
input_schema:
- required:
- - name: license_type
- type: string
- enum: [apache, elv2, proprietary]
- description: "The license to apply: apache (Apache 2.0), elv2 (Elastic License v2), proprietary (Lerian Studio General License)"
- optional:
+ required: []
+ optional:
+ - name: license_type
+ type: string
+ enum: [apache, elv2, proprietary]
+ description: "Optional upfront choice. If omitted, Gate 0 detects current state and asks user which license to apply."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@dev-team/skills/dev-licensing/SKILL.md` around lines 34 - 38, The schema
currently marks license_type as required which blocks the interactive detection
flow and causes /ring:dev-license to fail with no args; remove license_type from
the schema's required array (make it optional) and adjust the /ring:dev-license
handler to detect and prompt for license_type when it's missing (i.e., only
enforce a provided license_type if the caller supplies it), ensuring the
detection flow runs when license_type is absent.
Summary
Adds
ring:dev-licensingskill and/ring:dev-licensecommand for applying or switching licenses across Lerian repositories.Context
From #tech-team discussion: the boilerplate had a generic proprietary license. Fred confirmed licensing is per-app — each repo gets the appropriate license (Apache 2.0, ELv2, or proprietary) case by case. Rather than a standalone agent, this is integrated as a step in the scaffolding flow.
What's included
New skill:
ring:dev-licensingNew command:
/ring:dev-license [apache|elv2|proprietary]--dry-run,--year,--holderoptionsReference license texts:
references/apache-2.0.txt— full Apache 2.0references/elastic-v2.txt— full Elastic License v2references/proprietary.txt— Lerian Studio General LicenseUpdated
core.mdLicense Headers section:Updated
dev-cycleSKILL.md:License types
apacheelv2proprietary