My first machine was a 386 with Windows 3.1. Thirty years later I am Head of IT at the Ministry of Preschool Education of Uzbekistan, responsible for EMIS infrastructure at national scale — and still writing the migration files, the service classes, and the Angular components that keep it running.
— Dr Khindol Madraimov, Tashkent
Short-form writing — mostly about AI tooling, agentic workflows, and things I figure out while running EMIS at the ministry. Follow on LinkedIn →
/advisor in public beta — an Opus advisor paired with a Sonnet executor. Same pattern, now official.
/lm-studio skill that wires local LM Studio models (Qwen 3.5 9B on an M1) into Claude's agentic workflow alongside cloud Opus, Sonnet, and Haiku. A Sonnet agent dispatches tasks to cloud Haiku and local Qwen in parallel — no proxy layer.I write the migration, the service class, the Angular component, the feature tests, and the release note — then defend the scope in the ticket thread.
z_{ticket}_ backup-table pattern — reversible, auditable
DatabaseTransactions feature tests
ControllerActionTable + shared Traits for cross-cutting logic
Alert queues, webhook processors, scheduled workers. Things that used to block the UI now run on their own clock, with retries, structured logging, and supervisor-managed workers.
Security role functions, homeroom vs teacher hierarchy, excluded-roles bypass, per-module visibility. Rules expressed in data, not scattered across templates.
Log-file ownership races between cron and Apache users. Swagger regeneration steps forgotten on deploy. The recurring bugs that masquerade as code — fixed with documentation and process, not more code.
If a one-day ticket turns into a week of cross-cutting work, I say so clearly and break down why. Unflagged scope creep always becomes somebody else's problem later.
My instinct is to teach the agent-assisted workflow — read the Swagger, write a reference file, ask the assistant for the function with debounced search — rather than hand down finished code. Goal: the junior ships the next feature without me.
Four habits that have survived thirty years of changing stacks.
Before writing any fix I read the Table class, the Trait, the migration, and the last three commits on the file. Most bugs are already described somewhere in the code — in a comment, a TODO, or a test.
If a one-day ticket has grown into a week of cross-cutting work, I re-estimate in the ticket with a line-by-line breakdown. Dev subtotal. QA allowance. Full cycle. Scope creep flagged out loud becomes tomorrow's resource, not tomorrow's crisis.
One branch covers migration (with backup tables), API, frontend, feature tests, and release doc. Nothing is thrown over a fence. The tester gets a "what to click" section in plain language.
Cron user vs Apache user. Swagger regeneration step. Permissions on storage/logs/. Migration order on remote. The tedious things that always come back if nobody writes them down — I write them down.
A public trail of code, writing, and technical arguments going back years. Including one phrase I still defend: "Crash and Quit Driven Development."
Crash and Quit Driven Development: if the feature can survive an unexpected kill -9 and a restart, it's a feature. If it needs a clean shutdown to preserve state, it's a liability. Written in about it on the blog since I first ran OpenEMIS in production.
Tooling I've extracted from the day job and published: openemis-ai-assistant · openemis_docker_dev · claude-code-agents · playwright-record-mp4. When a solution turns out to be useful outside the domain, I rewrite it for a general audience and push it up.
Personal projects that belong here too: edusys (this very site you are reading), caffecito (a small café ordering tool), gws-sheets (a Claude Code skill), soulmate, namozimbot. Not everything I build is enterprise-scale. Some of it is just for me and my family.
Migrated the alert system from synchronous CakePHP sends — which were blocking the UI during attendance marking — to an asynchronous Laravel queue. Shipped alert_queue table, polling worker, Email and SMS senders with Twilio credentials in the database, a reusable QueueableAlerts Eloquent trait, and a deployment guide covering cron, nohup, and supervisor.
Two new institution-level features designed and delivered across the full stack: database tables with the backup-tables migration pattern, Laravel v5 API with Swagger regeneration, three feature test files, two new CakePHP ControllerActionTable classes, security-role seed data, and a mini client that writes to the v5 endpoints for ministry-of-education sync flows.
Built StaleProfileBannerTrait — a shared Trait integrated across four profile index tables (Student, Staff, Institution, Classes). Unified date-math, threshold colours, hover tooltips, and banner copy into one place. Three lines of integration per table, zero duplicated logic.
Before and alongside the EMIS work, I've been an editor and translator with Издательство Диля in Saint Petersburg — roughly a decade of books on Islamic studies, plus one I wrote myself. Nobody expects a published Arabic-language workbook from an EMIS engineer. That is rather the point.
