Plan: Extract Commercial Features → Apache 2.0 Only
Context
SpecLeft is currently dual-licensed (Apache 2.0 for the open core, a commercial license for enforcement/signing). The goal is to make the project fully Apache 2.0 by moving the three commercial modules (enforcement/, license/, specleft_signing/) and their two CLI commands (enforce, license) out of the main source tree and into .future_features/. All cross-cutting references to these modules must also be cleaned up.
Step 1 — Create .future_features/ skeleton
Create the directory structure and a brief README.md explaining its purpose:
.future_features/
├── README.md
├── LICENSE-COMMERCIAL
├── src/
│ ├── specleft_signing/
│ ├── license/
│ ├── enforcement/
│ └── commands/
├── tests/
│ ├── license/
│ ├── commands/
│ └── acceptance/
│ └── fixtures/
└── features/
Step 2 — Move commercial source modules
| From |
To |
| src/specleft/specleft_signing/ |
.future_features/src/specleft_signing/ |
| src/specleft/license/ |
.future_features/src/license/ |
| src/specleft/enforcement/ |
.future_features/src/enforcement/ |
| src/specleft/commands/enforce.py |
.future_features/src/commands/enforce.py |
| src/specleft/commands/license.py |
.future_features/src/commands/license.py |
Step 5 — Update src/specleft/commands/__init__.py
Remove:
from specleft.commands.enforce import enforce (line 11)
from specleft.commands.license import license_group (line 15)
"enforce" and "license_group" from __all__ (lines 27, 31)
Step 6 — Update src/specleft/cli/main.py
Remove:
enforce and license_group from the import block (lines 14, 18)
cli.add_command(enforce) (line 53)
cli.add_command(license_group) (line 54)
Step 7 — Update src/specleft/commands/plan.py
Remove:
- Line 18:
from specleft.license.status import resolve_license
- Lines 725–732: The entire license notice block at the end of the command (
resolve_license() call + the click.echo() lines prompting users to buy a license)
Step 8 — Update src/specleft/pytest_plugin.py
Line 463 contains a print statement referencing https://specleft.dev/enforce. Remove it or replace with the GitHub docs URL since the commercial product page no longer applies.
Step 9 — Update LICENSE
Replace LICENSE (currently a dual-license pointer) with the full Apache 2.0 text from LICENSE-OPEN. pyproject.toml already uses { file = "LICENSE" }, so the build config stays valid without further changes.
Step 10 — Update NOTICE.md
Rewrite to reflect a single Apache 2.0 license only. Remove all references to the commercial license tier and LICENSE-COMMERCIAL.
Step 11 — Update pyproject.toml
- Remove
cryptography>=41.0.0 from [project] dependencies — no longer needed once signing code is gone.
- Remove the mypy override block for
specleft_signing.* (lines 171–173).
- Add the OSI classifier:
"License :: OSI Approved :: Apache Software License",
Step 12 — Update README.md
Remove the commercial feature section (lines ~130–154) that documents specleft enforce and the licensing tier.
Step 13 — Update docs/cli-reference.md
Remove the specleft enforce section (lines 241–296) and the specleft license section (lines 349–365).
Verification
After all changes, verify in order:
# 1. No broken imports
python -c "from specleft.cli.main import cli"
2. enforce and license must be absent from CLI
specleft --help
3. Full test suite passes
pytest tests/ -x
4. Agent contract still healthy
specleft contract --format json
specleft doctor --format json
5. No remaining references to commercial modules in src/
grep -r "specleft_signing|from specleft.license|from specleft.enforcement" src/
Must return zero matches
Plan: Extract Commercial Features → Apache 2.0 Only
Context
SpecLeft is currently dual-licensed (Apache 2.0 for the open core, a commercial license for enforcement/signing). The goal is to make the project fully Apache 2.0 by moving the three commercial modules (
enforcement/,license/,specleft_signing/) and their two CLI commands (enforce,license) out of the main source tree and into.future_features/. All cross-cutting references to these modules must also be cleaned up.Step 1 — Create
.future_features/skeletonCreate the directory structure and a brief
README.mdexplaining its purpose:Step 2 — Move commercial source modules
Step 5 — Update
src/specleft/commands/__init__.pyRemove:
from specleft.commands.enforce import enforce(line 11)from specleft.commands.license import license_group(line 15)"enforce"and"license_group"from__all__(lines 27, 31)Step 6 — Update
src/specleft/cli/main.pyRemove:
enforceandlicense_groupfrom the import block (lines 14, 18)cli.add_command(enforce)(line 53)cli.add_command(license_group)(line 54)Step 7 — Update
src/specleft/commands/plan.pyRemove:
from specleft.license.status import resolve_licenseresolve_license()call + theclick.echo()lines prompting users to buy a license)Step 8 — Update
src/specleft/pytest_plugin.pyLine 463 contains a print statement referencing
https://specleft.dev/enforce. Remove it or replace with the GitHub docs URL since the commercial product page no longer applies.Step 9 — Update
LICENSEReplace
LICENSE(currently a dual-license pointer) with the full Apache 2.0 text fromLICENSE-OPEN.pyproject.tomlalready uses{ file = "LICENSE" }, so the build config stays valid without further changes.Step 10 — Update
NOTICE.mdRewrite to reflect a single Apache 2.0 license only. Remove all references to the commercial license tier and
LICENSE-COMMERCIAL.Step 11 — Update
pyproject.tomlcryptography>=41.0.0from[project] dependencies— no longer needed once signing code is gone.specleft_signing.*(lines 171–173).Step 12 — Update
README.mdRemove the commercial feature section (lines ~130–154) that documents
specleft enforceand the licensing tier.Step 13 — Update
docs/cli-reference.mdRemove the
specleft enforcesection (lines 241–296) and thespecleft licensesection (lines 349–365).Verification
After all changes, verify in order: