agentic:sync-profiles iterates AgentProfile rows, calls GET {gateway}/v1/models
via Http::withToken, infers capability_tags from exposed model ids
(claude-opus → handoff/analysis/core; gpt-5.4-mini → dispatch/cheap;
embedding-* → embedding), leaves last_dispatched_at untouched.
agentic:dispatch-queue uses extended MantisClient->listOpen() (new
small wrapper), skips assigned tickets + 5min in-flight markers, runs
ProfileSelector::pickFor, adds suppression note via MantisClient->note,
queues DispatchMantisTicketJob up to --limit (default 3). Both
commands emit progress via Log.
Pest Feature tests use Http::fake + Queue::fake. Tests register the
new commands directly (Boot.php registration is a deferred follow-up
per #837 lane note).
Codex note: php -l clean; pest blocked by unrelated repo migration
infra (dedicated brain connection + SQLite-incompatible agent_sessions
rename).
Closes tasks.lthn.sh/view.php?id=829
Co-authored-by: Codex <noreply@openai.com>
Migration 2026_04_25_000002 adds nullable plugin_cc_name string column
to agent_profiles. AgentProfile::$fillable extended to allow it.
agentic:sync-plugins-cc artisan command:
- Scans ~/.claude/plugins via Storage::disk(...) local disk (Finder
fallback) for directories with plugin.json
- Maps to enabled AgentProfile by name first, plugin_cc_name second
- Upserts plugin_cc_name on matches; emits mapped/unmapped table
Pest Feature test fakes HOME, creates plugin dirs, verifies both
mapping paths + disabled/non-matching profiles stay null.
Codex note: php -l clean; pest skipped (no vendor/). Boot.php command
registration deferred — new test registers the command directly to
verify behaviour; Boot wiring belongs to a follow-up that touches
existing Boot file.
Closes tasks.lthn.sh/view.php?id=837
Co-authored-by: Codex <noreply@openai.com>
Foundation slice for Mantis #841 php/Mod/Agent RFC implementation:
* CompleteTask now wraps in DB::transaction with idempotent credit awards
and safe current_task_id clearing
* Credits/{Award,GetBalance,GetCreditHistory} updated for agent_id +
fleet_task_id ledger support and richer balance totals
* GenerateCommand canonical agentic:generate wiring; legacy duplicate
no longer registered
* Boot wires brain:clean / brain:prune / brain:reindex
* EmbedMemory exits early when memory already indexed
* 3 follow-on fleet migrations reconcile fleet_nodes pointer column,
fleet_tasks/credit_entries fk/index hygiene, fleet+credit constraints
* 4 foundation tests under php/tests/Feature/Mod/Agent/
php -l clean on all modified files. pest unrunnable in sandbox (no vendor/).
Foundation slice only: remaining model/action parity, full MCP tool/
service sweep, fleet controller auth-context, and 41-tool/45-action
surface left for follow-up tickets.
Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=841
Closes the 5 PARTIAL items flagged in docs/AUDIT-openbrain-20260424.md.
- Gap A (org scoping persisted on writes): new migration adds `org`
nullable+indexed column to brain_memories; BrainMemory fillable;
RememberKnowledge action forwards org; BrainService::remember
persists it.
- Gap B (supersede/forget Elastic cleanup): BrainService::forget
dispatches DeleteFromIndex (handles both Qdrant + Elastic); supersede
path dispatches cleanup for the old memory id before replacing it.
DeleteFromIndex itself untouched — already handled both indexes.
- Gap C (brain:reindex flags): --org, --project, --stale (null OR
>14d old), --dry-run (count+stop), --elastic-only added to the
artisan command.
- Gap D (MCP schemas expose org): brain_remember, brain_recall,
brain_list now accept `org` in input schema + forward into
action/service.
- Gap E (resilience uneven): brain_list now wrapped in
withCircuitBreaker('brain', ...) matching the pattern used by
BrainRemember/Recall/Forget. BrainService gains retryableHttp()
helper — 100/300/900ms exponential backoff, retries only on 5xx +
connection errors, not on 4xx. Qdrant calls route through it;
Ollama left alone (EmbedMemory job has its own retry).
Tests (Good/Bad/Ugly per gap):
- Feature/Brain/OrgScopingTest.php
- Feature/Brain/SupersedeForgetIndexCleanupTest.php
- Feature/Brain/ReindexFlagsTest.php
- Feature/Mcp/BrainSchemaOrgTest.php
- Feature/Brain/CircuitBreakerTest.php
php -l clean on all 13 files. Pest binary not in this checkout —
CI path validates the full suite.
Closes tasks.lthn.sh/view.php?id=107
Co-authored-by: Codex <noreply@openai.com>
Co-Authored-By: Virgil <virgil@lethean.io>
New artisan command brain:prune {--older-than=90} {--chunk=100} {--dry-run}
that completes the soft-delete → hard-delete lifecycle by:
1. selecting BrainMemory::onlyTrashed() where deleted_at < now - N days
2. dispatching DeleteFromIndex for each (Qdrant + ES cleanup)
3. forceDelete()'ing the rows
--dry-run counts without dispatching.
Complements brain:clean (which cleans recent soft-deletes) with a
retention-bounded terminal cleanup.
Pest coverage: Good (dispatch + forceDelete on aged trashed rows), Bad
(invalid chunk), Ugly (--dry-run skips both dispatch and delete).
Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=62
New artisan command brain:clean {--chunk=100} {--dry-run} that dispatches
the DeleteFromIndex job for soft-deleted BrainMemory rows (those in
onlyTrashed scope). Cleans up orphaned Qdrant + Elasticsearch index
entries that remain after a memory is soft-deleted.
--dry-run counts without dispatching.
php/tests/Feature/Console/BrainCleanCommandTest.php covers Good
(dispatches on trashed), Bad (invalid chunk), Ugly (--dry-run prevents
dispatch).
Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=61
New artisan command brain:reindex {--all} {--chunk=100} that dispatches
the EmbedMemory job for brain memories needing (re)indexing. Without
--all, only memories where indexed_at IS NULL are dispatched; --all
re-embeds every memory (useful after a Qdrant collection wipe or
embedding model change). Uses chunkById for memory-safe iteration at
scale.
php/tests/Feature/Console/BrainReindexCommandTest.php covers Good
(unindexed-only default), Bad (invalid chunk), Ugly (--all flag).
Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=60