Document each PROVIDER_PATTERNS entry with real User-Agent examples,
add inline comments to BROWSER_INDICATORS and NON_AGENT_BOTS with
categorised UA examples, document MCP_TOKEN_HEADER with token format
details, and add class-level usage examples and detection priority
ordering.
Closes#31
Refs: DOC-001
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Log a warning for each AI provider registered without an API key so
that misconfiguration is surfaced at boot time (not silently on the
first API call). Each message names the environment variable to set:
ANTHROPIC_API_KEY – Claude
GOOGLE_AI_API_KEY – Gemini
OPENAI_API_KEY – OpenAI
Providers without a key remain registered but are marked unavailable
via isAvailable(), preserving backward compatibility.
- Add Log::warning() calls in registerProviders() for empty keys
- Extend AgenticManagerTest with a dedicated 'API key validation
warnings' describe block (7 new test cases)
- Update DX-002 in TODO.md as resolved
Closes#29
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Updated workspace_id error messages in all MCP tools to include
actionable guidance and a documentation link. Affected tools:
PlanCreate, PlanGet, PlanList, StateSet, StateGet, StateList,
SessionStart.
Resolves DX-001 from TODO.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Track progress in a per-batch JSON state file after each article so
a mid-run crash leaves a recoverable checkpoint
- Add `maxRetries` parameter to generateBatch() with per-article retry
loop (default: 1 extra attempt)
- Add `resumeBatch()` to re-process only failed/pending articles,
skipping those already successfully generated in a prior run
- Add `loadBatchProgress()` public method for inspecting state
- State stores per-article status, attempt counts, error messages,
and timestamps for full observability
Tests: 6 new scenarios covering state persistence, resume capability,
retry logic, and the no-state error case
Closes#27
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Verify agent_sessions.session_id: unique() constraint creates an
implicit unique index (agent_sessions_session_id_unique) which is
sufficient for string lookups; no additional index required
- Drop redundant agent_plans_slug_index: the unique() constraint on
slug already provides agent_plans_slug_unique covering all lookups
- Add compound (workspace_id, slug) index on agent_plans for the
common routing pattern WHERE workspace_id = ? AND slug = ?
- Verify agent_workspace_states.key: already indexed via ->index('key')
in migration 000003; no additional index required
- Mark DB-002 as resolved in TODO.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace hardcoded cache key in ForAgentsController with a config-based
key (`mcp.cache.for_agents_key`) and configurable TTL
(`mcp.cache.for_agents_ttl`). This prevents collisions with other modules
or packages that might use the same flat cache key.
- Add `cacheKey()` method on ForAgentsController, reads from config
- Add `cache` section to config.php with default key and TTL
- Dynamic Cache-Control max-age now follows the configured TTL
- Add ForAgentsControllerTest covering key customisation,
cache storage, invalidation, TTL, and response structure
Refs: TODO.md CQ-003
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch View/Modal/Admin/ApiKeyManager.php from Core\Api\Models\ApiKey
to Core\Mod\Agentic\Models\AgentApiKey and AgentApiKeyService, bringing
the workspace-owner admin UI into consistency with all other services.
Changes:
- Replace Core\Api\Models\ApiKey import with AgentApiKey + AgentApiKeyService
- Use AgentApiKeyService::create() for key generation
- Use AgentApiKey::forWorkspace() scoping in revokeKey() and render()
- Rename newKeyScopes → newKeyPermissions, toggleScope → togglePermission
- Expose availablePermissions() from AgentApiKey for the create form
- Update blade template: permissions field, getMaskedKey(), togglePermission,
dynamic permission checkboxes from AgentApiKey::availablePermissions()
- Add tests/Feature/ApiKeyManagerTest.php with integration coverage
- Mark CQ-002 resolved in TODO.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Convert PHPUnit class-based tests to Pest functional syntax with:
- 47 test cases organised into 9 describe blocks
- Proper beforeEach/afterEach hooks for test setup/teardown
- Covers: template listing, retrieval, preview, variable substitution,
plan creation, validation, categories, context generation, edge cases
- Uses expect() assertions and method chaining for clarity
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Convert AgentApiKeyTest from PHPUnit class-based syntax to Pest functional syntax
- Add tests/Pest.php configuration with helper functions (createWorkspace, createApiKey)
- Organise tests using describe() blocks for better structure
- Add additional test coverage for key rotation and security edge cases
- Update TODO.md to reflect Pest syntax usage
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
P2 Items Completed (P2-062 to P2-068):
- Switch AgentApiKey from SHA-256 to Argon2id hashing
- Add 200+ tests for models, services, and AI providers
- Create agent_plans migration with phases and workspace states
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>