Files
Tabish Bidiwale 4f4af5708d feat: add change creation utilities (#408)
* proposal: add change manager - extract + new functionality

Slice 2 of the artifact tracker POC. Creates ChangeManager module that:

**Extracts existing functionality:**
- `listChanges()` from ListCommand + ChangeCommand.getActiveChanges()
- `changeExists()` from inline fs.access() checks
- `getChangePath()` from inline path.join() calls
- `isInitialized()` from ListCommand directory check

**Adds new functionality:**
- `createChange(name, description?)` - create change directory + README
- `validateName(name)` - enforce kebab-case naming

**Refactors CLI commands to be thin wrappers:**
- ListCommand delegates to ChangeManager
- ChangeCommand delegates to ChangeManager

Also updates docs/artifact_poc.md to reflect XDG decisions from Slice 1.

* proposal: simplify to utility functions only

Remove extraction/refactor scope. Just add:
- createChange(projectRoot, name, description?)
- validateChangeName(name)

Simple utility functions in src/utils/change-utils.ts.
No class, no abstraction layer.

* docs: update artifact_poc.md for simplified Slice 2

- Rename ChangeManager to change-utils (simple utility functions)
- Remove extracted methods (listChanges, getChangePath, etc.)
- Keep only new functionality: createChange(), validateChangeName()
- Update component diagram and summary table

* docs: clarify existing vs new functionality in artifact_poc.md

Audit artifact_poc.md against existing codebase to mark what already
exists vs what's genuinely new:

- Slice 4 CLI table: Added Status column (NEW/EXISTS)
- Added "Existing CLI commands" section listing what's not in scope
- Updated Implementation Order Slice 4 with explicit new vs existing
- Summary table: Updated status + added "What already exists" section

Key finding: The document was already well-simplified. Only truly new
functionality (createChange, validateChangeName, InstructionLoader,
artifact graph CLI commands) is proposed.

* rename: change-manager -> change-creation capability

The capability name "change-manager" implied a manager class abstraction,
but the simplified proposal uses only utility functions. Renamed to
"change-creation" to accurately reflect what the capability provides.

* feat: implement change creation utilities

Add createChange() and validateChangeName() functions for programmatic
change directory creation with kebab-case validation.

- createChange(projectRoot, name) creates openspec/changes/<name>/
- validateChangeName() enforces kebab-case naming conventions
- Comprehensive test coverage (21 tests)

* chore: archive add-change-manager change

Move change to archive and create change-creation spec with
requirements for createChange() and validateChangeName().

* docs: update change-creation spec purpose
2025-12-26 22:14:56 +11:00

2.7 KiB

change-creation Specification

Purpose

Provide programmatic utilities for creating and validating OpenSpec change directories.

Requirements

Requirement: Change Creation

The system SHALL provide a function to create new change directories programmatically.

Scenario: Create change

  • WHEN createChange(projectRoot, 'add-auth') is called
  • THEN the system creates openspec/changes/add-auth/ directory

Scenario: Duplicate change rejected

  • WHEN createChange(projectRoot, 'add-auth') is called and openspec/changes/add-auth/ already exists
  • THEN the system throws an error indicating the change already exists

Scenario: Creates parent directories if needed

  • WHEN createChange(projectRoot, 'add-auth') is called and openspec/changes/ does not exist
  • THEN the system creates the full path including parent directories

Scenario: Invalid change name rejected

  • WHEN createChange(projectRoot, 'Add Auth') is called with an invalid name
  • THEN the system throws a validation error

Requirement: Change Name Validation

The system SHALL validate change names follow kebab-case conventions.

Scenario: Valid kebab-case name accepted

  • WHEN a change name like add-user-auth is validated
  • THEN validation returns { valid: true }

Scenario: Numeric suffixes accepted

  • WHEN a change name like add-feature-2 is validated
  • THEN validation returns { valid: true }

Scenario: Single word accepted

  • WHEN a change name like refactor is validated
  • THEN validation returns { valid: true }

Scenario: Uppercase characters rejected

  • WHEN a change name like Add-Auth is validated
  • THEN validation returns { valid: false, error: "..." }

Scenario: Spaces rejected

  • WHEN a change name like add auth is validated
  • THEN validation returns { valid: false, error: "..." }

Scenario: Underscores rejected

  • WHEN a change name like add_auth is validated
  • THEN validation returns { valid: false, error: "..." }

Scenario: Special characters rejected

  • WHEN a change name like add-auth! is validated
  • THEN validation returns { valid: false, error: "..." }

Scenario: Leading hyphen rejected

  • WHEN a change name like -add-auth is validated
  • THEN validation returns { valid: false, error: "..." }

Scenario: Trailing hyphen rejected

  • WHEN a change name like add-auth- is validated
  • THEN validation returns { valid: false, error: "..." }

Scenario: Consecutive hyphens rejected

  • WHEN a change name like add--auth is validated
  • THEN validation returns { valid: false, error: "..." }