# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

---

## [0.10.2] - 2026-03-11

### Fixed

- Ruff B023 lint errors in Gmail and Outlook auth modules (unnecessary local
  variable shadowing `scopes` parameter)

## [0.10.1] - 2026-03-11

### Added

- GitHub Actions CI workflow (lint + unit tests on push/PR)
- GitHub Actions release workflow: build, publish to PyPI (trusted publishing),
  auto-create GitHub Release with changelog excerpt
- License changed from MIT to GPL-3.0-or-later

## [0.10.0] - 2026-03-11

### Added

- **CHANGELOG.md** backfilled with entries for all versions (0.1.0 through 0.9.0)
- **API Reference** (`docs/api_reference.md`): comprehensive method signatures,
  domain models, error types, and return types for both messaging and work tracking
- `Changelog` URL in `[project.urls]` -- PyPI sidebar now links to the changelog
- `CHANGELOG.md` included in sdist distribution

### Changed

- README now includes a Documentation section with links to the changelog,
  API reference, and adapter catalog

---

## [0.9.0] - 2026-03-07

### Changed

- **Slack adapter rewrite**: sync-first architecture with background listener
  - Connector rewritten for sync callers with optional background WebSocket
  - Identity-first design: `Identity` objects used consistently for sender/recipient
  - Auth module refactored for clearer bot-token vs user-token separation
  - Normalizer rewritten for the new sync message flow
  - CLI rewritten with identity-first commands
- Slack rate limiter: minor fix

## [0.8.2] - 2026-03-07

### Fixed

- Corrected `MessageEvent` attribute names in Slack CLI
- Added `APPIF_SLACK_USER_OAUTH_TOKEN` to `.env.example`

## [0.8.1] - 2026-03-07

### Fixed

- Ruff format compliance for Slack CLI

## [0.8.0] - 2026-03-07

### Added

- `users` CLI command for Slack adapter (list workspace users)
- `send` CLI command for Slack adapter (send messages from CLI)
- `join` CLI command for Slack adapter (join channels)
- User OAuth token support in Slack auth

## [0.7.1] - 2026-03-01

### Fixed

- Ruff format compliance on `models.py` (CI was failing on format check)

### Changed

- Pruned 12 low-value unit tests (framework mechanics, redundant boundaries, unrealistic inputs)
- Unit test count: 309 (net new tests retained, low-value tests removed)

## [0.7.0] - 2026-03-01

### Added

- `ProjectInfo` frozen dataclass: platform-agnostic project metadata (key, name, description, lead, project_type, url)
- `CreateProjectRequest` Pydantic BaseModel (frozen): project creation command with key validation (2-10 uppercase alphanumeric, starts with letter)
- `ProjectNotFound` error: domain exception for project-specific 404 responses
- `list_projects(instance?)` on WorkTracker protocol -- returns all accessible projects
- `get_project(key, instance?)` on WorkTracker protocol -- retrieves a single project by key
- `create_project(request, instance?)` on WorkTracker protocol -- creates a new project
- `delete_project(key, instance?)` on WorkTracker protocol -- deletes a project (irreversible)
- `normalize_project()` in Jira normalizer -- maps Jira project JSON to ProjectInfo (handles Cloud accountId and Server key fallback for lead)
- `_translate_project_error()` in Jira adapter -- maps HTTP errors to ProjectNotFound instead of ItemNotFound
- 24 unit tests: ProjectInfo construction/immutability, CreateProjectRequest validation/immutability, normalize_project (full, minimal, null description, lead fallback)
- 2 integration tests: list_projects, get_project
- Updated design.md, technical_design.md, readme.md with project operations documentation
- Unit test count: 298 -> 309

## [0.6.0] - 2026-03-01

### Added

- `ItemAttachment` dataclass: platform-agnostic attachment metadata (id, filename, mime_type, size_bytes, created, author) -- no platform URLs exposed
- `AttachmentContent` dataclass: download result containing metadata + complete file bytes, designed for future streaming variant via separate method
- `attachments: tuple[ItemAttachment, ...]` field on `WorkItem` -- always populated from platform data (no opt-in required)
- `download_attachment(attachment_id)` on `WorkTracker` protocol and `WorkTrackingService` -- fetches file content using the adapter's authenticated session
- `normalize_attachment()` in Jira normalizer
- `normalize_issue()` now extracts `fields.attachment` from Jira API responses
- 8 unit tests for attachment normalization and issue-level attachment extraction
- Unit test count: 290 -> 298

## [0.5.0] - 2026-03-01

### Breaking Changes

- `CreateItemRequest.item_type` is now `ItemCategory` (enum) instead of `str`. Callers must use `ItemCategory.TASK`, `ItemCategory.BUG`, etc. instead of raw strings like `"Task"` or `"Bug"`. Pydantic will coerce lowercase string values (e.g. `"task"`) but rejects arbitrary strings (e.g. `"Sub-task"`).
- `CreateItemRequest` is now a Pydantic `BaseModel` (frozen) instead of a `@dataclass(frozen=True)`. Construction syntax is identical but validation errors are now `pydantic.ValidationError` instead of `TypeError`.

### Added

- `ItemCategory` enum: TASK, SUBTASK, STORY, BUG, EPIC -- domain-level work item categories with rich docstrings for LLM and human consumers
- Cross-field validation: `parent_key` is required when `item_type` is `ItemCategory.SUBTASK`
- `JiraAdapter._resolve_issue_type()` -- maps `ItemCategory` to Jira-specific type strings using project createmeta
- Per-project issue type cache in `JiraAdapter` (instance lifetime, no TTL)
- Fallback strategies: STORY/BUG/EPIC fall back to Task when not available in the project; SUBTASK falls back to creating a Task with a CHILD_OF link when no subtask type exists
- `pydantic>=2.10` added to dependencies
- 24 unit tests for `ItemCategory` and `CreateItemRequest` Pydantic validation
- 15 unit tests for Jira type resolution, fallback behavior, and cache semantics
- ADR-001: Domain-Level Item Categories with Adapter-Resolved Issue Types

### Changed

- `CreateItemRequest` converted from frozen dataclass to Pydantic BaseModel (frozen=True)
- `JiraAdapter.create_item()` now resolves `ItemCategory` to platform type instead of passing raw string
- Integration tests updated to use `ItemCategory.TASK` instead of `"Task"` string
- Unit test count: 251 -> 290

### Migration from 0.4.x to 0.5.0

**`CreateItemRequest.item_type` type change:**
```python
# Before (0.4.x):
request = CreateItemRequest(project="PROJ", title="Fix bug", item_type="Task")

# After (0.5.0+):
from appif.domain.work_tracking.models import ItemCategory
request = CreateItemRequest(project="PROJ", title="Fix bug", item_type=ItemCategory.TASK)
```

## [0.4.0] - 2026-03-01

### Added

- Discovery APIs: `get_project_issue_types()` and `get_link_types()` on WorkTracker protocol
- `IssueTypeInfo` and `LinkTypeInfo` domain models
- Jira normalizers: `normalize_issue_type()` and `normalize_link_type_info()`
- 10 unit tests for discovery normalizers
- Integration tests for discovery APIs
- ADR-001 document (accepted)
- Updated design document with ItemCategory and discovery API sections

## [0.3.0] - 2026-02-28

### Added

- Work tracking domain: `WorkTracker` and `InstanceRegistry` protocols
- Jira adapter: full CRUD lifecycle (get, create, comment, transition, link, search)
- `WorkTrackingService` routing layer with multi-instance support
- YAML-based Jira configuration (`~/.config/appif/jira/config.yaml`)
- Domain models: `WorkItem`, `CreateItemRequest`, `SearchCriteria`, `LinkType`, etc.
- Domain errors: `ItemNotFound`, `InvalidTransition`, `PermissionDenied`, etc.
- Integration tests for Jira CRUD lifecycle
- Jira cleanup script (`scripts/jira_cleanup.py`)

## [0.2.0] - 2026-02-27

### Added

- Slack adapter with Socket Mode real-time messaging
- Slack CLI (`appif-slack`): channels, send, monitor commands
- User cache for Slack display name resolution

## [0.1.0] - 2026-02-26

### Added

- Initial release
- Gmail connector: OAuth 2.0, history polling, send/draft
- Outlook connector: Microsoft Graph, delta-query polling, send
- Messaging domain: `Connector` protocol, `MessageEvent`, `MessageContent`, `ConversationRef`
- Domain error hierarchy: `ConnectorError`, `NotAuthorized`, `TransientFailure`, etc.
- 241 unit tests across Gmail, Outlook, and messaging domain

[0.10.2]: https://github.com/dawsonlp/application_interfaces/compare/v0.10.1...v0.10.2
[0.10.1]: https://github.com/dawsonlp/application_interfaces/compare/v0.10.0...v0.10.1
[0.10.0]: https://github.com/dawsonlp/application_interfaces/compare/v0.9.0...v0.10.0
[0.9.0]: https://github.com/dawsonlp/application_interfaces/compare/v0.8.2...v0.9.0
[0.8.2]: https://github.com/dawsonlp/application_interfaces/compare/v0.8.1...v0.8.2
[0.8.1]: https://github.com/dawsonlp/application_interfaces/compare/v0.8.0...v0.8.1
[0.8.0]: https://github.com/dawsonlp/application_interfaces/compare/v0.7.1...v0.8.0
[0.7.1]: https://github.com/dawsonlp/application_interfaces/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/dawsonlp/application_interfaces/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/dawsonlp/application_interfaces/compare/v0.5.0...v0.6.0
[0.5.0]: https://github.com/dawsonlp/application_interfaces/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/dawsonlp/application_interfaces/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/dawsonlp/application_interfaces/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/dawsonlp/application_interfaces/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/dawsonlp/application_interfaces/releases/tag/v0.1.0