Skip to content

feat(dev-team): add licensing skill and command#329

Open
gandalf-at-lerian wants to merge 1 commit intomainfrom
feat/license-step-dev-cycle
Open

feat(dev-team): add licensing skill and command#329
gandalf-at-lerian wants to merge 1 commit intomainfrom
feat/license-step-dev-cycle

Conversation

@gandalf-at-lerian
Copy link
Copy Markdown
Contributor

Summary

Adds ring:dev-licensing skill and /ring:dev-license command 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-licensing

  • 4-gate workflow: detect → confirm → apply → validate
  • Replaces/creates LICENSE file with full license text
  • Updates all source file headers (.go, .ts) to match
  • Updates SPDX identifiers in go.mod/package.json
  • Updates README license badge/section
  • Validates consistency across codebase
  • Supports dry-run mode

New command: /ring:dev-license [apache|elv2|proprietary]

  • Standalone command to apply/switch license
  • Interactive detection when no type specified
  • --dry-run, --year, --holder options

Reference license texts:

  • references/apache-2.0.txt — full Apache 2.0
  • references/elastic-v2.txt — full Elastic License v2
  • references/proprietary.txt — Lerian Studio General License

Updated core.md License Headers section:

  • Replaced hardcoded Elasticsearch B.V. headers with Lerian-specific templates
  • Added header templates for all three license types
  • Updated Header Components table

Updated dev-cycle SKILL.md:

  • Added advisory license detection at Gate 0 (pre-implementation)
  • Non-blocking: prompts user if no LICENSE found, proceeds if skipped

License types

Type SPDX Use case
apache Apache-2.0 Open source (e.g., Midaz core)
elv2 Elastic-2.0 Source-available Lerian products
proprietary LicenseRef-Lerian-Proprietary Internal/closed repos

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)
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

Walkthrough

This 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

Cohort / File(s) Summary
Licensing Standards Update
dev-team/docs/standards/golang/core.md
Replaced fixed Elastic License 2.0 header requirement with repository-scoped multi-license support (Apache 2.0, Elastic License v2, Proprietary); updated required header format templates, SPDX identifiers, and header component guidance to match the repository's LICENSE file.
Command Definition
dev-team/commands/dev-license.md
New command definition for /ring:dev-license workflow specifying metadata, usage syntax, supported license types with SPDX identifiers, optional flags (--dry-run, --year, --holder), runnable examples, and skill integration with ring:dev-licensing.
Licensing Skill & Reference Texts
dev-team/skills/dev-licensing/SKILL.md, dev-team/skills/dev-licensing/references/*
New ring:dev-licensing skill (v1.0.0) implementing a multi-gate licensing orchestrator with detection, confirmation, application, and validation workflows; includes canonical license reference texts for Apache 2.0, Elastic License v2, and Proprietary licenses.
Dev Cycle Integration
dev-team/skills/dev-cycle/SKILL.md
Added license detection advisory step at cycle start that infers license type from repository LICENSE file or prompts user selection; stored in state and linked to licensing skill invocation; non-blocking for Gate 0.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0c3fe5a and 5f6f2ce.

📒 Files selected for processing (7)
  • dev-team/commands/dev-license.md
  • dev-team/docs/standards/golang/core.md
  • dev-team/skills/dev-cycle/SKILL.md
  • 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

Comment on lines +903 to 905
| 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 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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.

Suggested change
| 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.

Comment on lines +1851 to +1856
→ 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}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Suggested change
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.

Comment on lines +34 to +38
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)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant