feat: rename to issue-core and add task ingestion endpoint

Renames the package, distribution, CLI alias, Makefile targets, and
working directory from issue-facade to issue-core, signalling its
role as the authoritative task lifecycle manager for the Coulomb org
(peer to activity-core, rules-core, project-core).

Adds POST /issues/ ingestion endpoint for activity-core's IssueSink,
under a new optional [api] extra. The endpoint is served by `issue
serve`, authenticates via the ISSUE_CORE_API_KEY env var (Bearer or
X-API-Key header), and routes the TaskSpec payload to the configured
default backend with full traceability metadata embedded in
sync_metadata.

- T01: Python package issue_tracker -> issue_core, dir rename
- T02: registered in state hub under custodian domain
- T03: INTENT.md (what it is, what it isn't, how it fits)
- T04: SCOPE.md (in/out-of-scope, integration boundaries)
- T05: POST /issues/ via FastAPI + Uvicorn, 9 unit tests
- T06: docs/nats-task-ingestion.md design stub

Closes ISSC-WP-0001.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-17 05:16:27 +02:00
parent 99ea1fbc45
commit b605d970e3
38 changed files with 1324 additions and 361 deletions

View File

@@ -1,4 +1,4 @@
# Issue Facade Roadmap
# Issue Core Roadmap
**Long-term vision and implementation plan for agent-driven software development coordination.**
@@ -29,7 +29,7 @@
**Implementation:**
```python
# issue_tracker/core/detection.py
# issue_core/core/detection.py
def detect_git_remote() -> Optional[Dict[str, str]]:
"""
@@ -64,7 +64,7 @@ def parse_remote_url(url: str) -> Optional[Dict[str, str]]:
**Implementation:**
```python
# issue_tracker/core/env_config.py
# issue_core/core/env_config.py
def load_backend_from_env() -> Optional[Dict[str, Any]]:
"""
@@ -95,7 +95,7 @@ issue config auto
**Implementation:**
```
.issue-facade/
.issue-core/
├── config.json # Repository-specific settings
├── issues.db # Local cache/backup
└── credentials.json # Optional encrypted credentials
@@ -126,10 +126,10 @@ issue config auto
**Functions:**
```python
def load_repo_config(path: Path = Path.cwd()) -> Optional[Dict]:
"""Load .issue-facade/config.json from repo root."""
"""Load .issue-core/config.json from repo root."""
def save_repo_config(config: Dict, path: Path = Path.cwd()):
"""Save config to .issue-facade/config.json."""
"""Save config to .issue-core/config.json."""
def find_repo_root() -> Optional[Path]:
"""Walk up directory tree to find git root."""
@@ -141,14 +141,14 @@ def find_repo_root() -> Optional[Path]:
**Implementation:**
```python
# issue_tracker/core/auto_config.py
# issue_core/core/auto_config.py
def auto_configure_backend() -> IssueBackend:
"""
Auto-configure backend with fallback priority:
1. Check .issue-facade/config.json
1. Check .issue-core/config.json
2. Detect from git remote + environment token
3. Check global config (~/.config/issue-facade/)
3. Check global config (~/.config/issue-core/)
4. Prompt user for manual configuration
"""
```
@@ -196,7 +196,7 @@ if issue backend show "$backend_name" &>/dev/null; then
if [ "$replace" = "y" ] || [ "$replace" = "Y" ]; then
# Create timestamped backup
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
CONFIG_FILE="$HOME/.config/issue-facade/backends.json"
CONFIG_FILE="$HOME/.config/issue-core/backends.json"
if [ -f "$CONFIG_FILE" ]; then
BACKUP_FILE="$CONFIG_FILE.backup.$TIMESTAMP"
cp "$CONFIG_FILE" "$BACKUP_FILE"
@@ -255,7 +255,7 @@ fi
**Implementation:**
```python
# issue_tracker/core/agent.py
# issue_core/core/agent.py
@dataclass
class AgentContext:
@@ -269,7 +269,7 @@ def get_agent_context() -> AgentContext:
"""
Get agent context from:
1. Environment (ISSUE_AGENT_ID, ISSUE_AGENT_TYPE)
2. Config file (.issue-facade/config.json)
2. Config file (.issue-core/config.json)
3. Default to system username
"""
@@ -310,7 +310,7 @@ issue config agent show
**Implementation:**
```python
# issue_tracker/core/locking.py
# issue_core/core/locking.py
class IssueClaim:
issue_id: str
@@ -423,7 +423,7 @@ def get_agent_state(issue: Issue) -> Dict[str, Any]:
**Implementation:**
```python
# issue_tracker/core/webhooks.py
# issue_core/core/webhooks.py
class WebhookManager:
"""Manage webhooks for real-time notifications."""
@@ -525,7 +525,7 @@ issue depends ready # List issues ready to start
**Implementation:**
```python
# issue_tracker/core/query_dsl.py
# issue_core/core/query_dsl.py
class QueryParser:
"""
@@ -559,7 +559,7 @@ issue list --query="is:in-progress created:>7d"
**Implementation:**
```python
# issue_tracker/core/activity.py
# issue_core/core/activity.py
@dataclass
class ActivityEvent:
@@ -596,7 +596,7 @@ class ActivityStream:
**Implementation:**
```python
# issue_tracker/core/distributed_lock.py
# issue_core/core/distributed_lock.py
class DistributedLockManager:
"""Distributed locking using Redis/database."""
@@ -638,7 +638,7 @@ with distributed_lock(f"issue:{issue_id}", agent_id):
**Implementation:**
```python
# issue_tracker/core/sync_strategies.py
# issue_core/core/sync_strategies.py
class ConflictResolutionStrategy(ABC):
def resolve(self, local: Issue, remote: Issue) -> Issue: