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>
Implements the async-embedding pipeline's worker side:
- php/Jobs/EmbedMemory.php — Laravel Job that calls BrainService::embed()
+ qdrantUpsert() and sets indexed_at on success
- php/Migrations/…_add_indexed_at_to_brain_memories.php — nullable
timestamp + index, portable across pgsql/mariadb (hasColumn guard)
- BrainMemory: +indexed_at fillable + datetime cast + PHPDoc
- BrainService: qdrantUpsert() private→public so the Job can use it;
elasticIndex() stub added (to be implemented by the ES ticket)
- php/tests/Feature/Jobs/EmbedMemoryTest.php — Pest tests for success
path and Qdrant-failure path
Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=56
Three related fixes so the brain DB works on Postgres, not just MariaDB:
1. config.php — brain charset/collation was hardcoded to utf8mb4 which
Postgres rejects as client_encoding. Now driver-aware: utf8 for
pgsql, utf8mb4 otherwise. Override via BRAIN_DB_CHARSET env var.
2. Migration 000008 (create_brain_memories) — self-referential FK on
supersedes_id was declared inside Schema::create{}, causing Postgres
to evaluate it before the PK index existed ('no unique constraint
matching given keys'). Split into Schema::create + separate
Schema::table to guarantee PK is in place when FK is added.
3. Migration 000009 (drop workspace FK) — try/catch inside the Blueprint
closure couldn't catch deferred SQL failures. Replaced with a
constraint-exists pre-query against information_schema, supporting
both pgsql and mariadb/mysql drivers. Fresh installs no longer fail
trying to drop a constraint that was never created.
Co-Authored-By: Virgil <virgil@lethean.io>