emrg: task CRUD + template CRUD + hot reload (rant 2026-08-12T18:23:15 P2) - #710
Conversation
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle
Re-verified P2 (rant 2026-08-12T18:23:15) on head 4517b81 (4 files, 617+/17-):
- Task CRUD — daemon task_create/update/delete → task_result; validation matches all 6 host decisions: name regex ^[a-z0-9][a-z0-9-]*$ ≤32, type builtin-or-custom, project must be registered in projects.yml, interval ≥60. task_update merges fields (type/project/interval/enabled/repo/description) without clobbering config.
- Template CRUD — task_template_create/list/update/delete; custom templates in ~/.emrg/task-templates/.md (atomic tmp+replace); builtin types/templates read-only; delete of a referenced custom type refused with task count (host decision).
- Hot reload — TaskScheduler.apply_tasks: atomic write → diff via _task_cfg_signature (name/type/config/interval/enabled) → add/remove/restart handlers; idempotent (same config → no-op). _start_handler_for/_stop_handler extracted; _handler_cfgs bookkeeping keeps old cfg for diffing.
- Custom types runnable — load_and_start falls back to TaskHandler for unknown types (was: silently skipped) with _resolve_task_template (user template → evolution_prompt.md + warning) — matches P2's "custom type tasks execute".
Verification: pytest 744 (was 736, +8: validation 4-cases / create+duplicate / update+delete / hot-reload add-remove / restart-on-change / idempotent / template guards incl. delete-refused / custom-type task), import + CLI OK, Agent.md synced (doc-count guard green). CI test run 31588216240 PASS (actionlint + doc-count guard included). No issues found.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle
Independent re-verification on head 4517b81 (4 files, 617+/17-):
- Task CRUD — task_create/update/delete with full validation (name regex ^[a-z0-9][a-z0-9-]*$ ≤32, builtin-or-custom type, project must be in projects.yml, interval ≥60 int). task_update merges fields without clobbering config; delete is idempotent-safe (not-found error).
- Template CRUD — custom templates in config_dir()/task-templates/*.md with atomic tmp+replace writes; builtin read-only; delete refused while tasks reference the type (host decision honored).
- Hot reload — apply_tasks: atomic save → _task_cfg_signature diff → add/remove/restart handlers without daemon restart; idempotent (same config = no-op). _start_handler_for/_stop_handler extraction keeps bookkeeping (_handler_cfgs) consistent.
- Custom types runnable — unknown types now fall back to TaskHandler instead of being silently skipped, with _resolve_task_template user-template lookup → evolution_prompt.md fallback + warning.
- Regression — re-ran locally: pytest 744 passed (was 736, +8 new), import check + CLI OK, GUI 225 passed, Agent.md count synced (744). No issues found.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle (3rd)
Consecutive post-submit chain: ✅ (10:40:21Z) → ✅ (10:42:00Z) → ✅ (this cycle). Head 4517b81 unchanged, mergeable=CLEAN.
Final verification on head 4517b81 (4 files, 617+/17-):
- Task CRUD — task_create/update/delete; validation per all 6 host decisions (name ^[a-z0-9][a-z0-9-]*$ ≤32, type builtin-or-custom, project registered in projects.yml, interval ≥60); update merges fields without clobbering config.
- Template CRUD — custom templates in ~/.emrg/task-templates/.md (atomic tmp+replace); builtin read-only; delete refused while tasks reference the type (host decision).
- Hot reload — apply_tasks: atomic write → _task_cfg_signature diff → add/remove/restart, no daemon restart; idempotent.
- Custom types runnable — unknown types fall back to TaskHandler (was: silently skipped) with _resolve_task_template lookup → evolution_prompt.md fallback.
Verification: pytest 744 local (736→+8), import + CLI OK, GUI 225 passed, Agent.md synced. CI 31588216240 PASS (actionlint + doc-count guard). No issues — merging per merge policy (3 consecutive ✅, no ❌).
P2 of the host rant 2026-08-12T18:23:15 (task generalization full design — 6 host-confirmed decision points). Backend capabilities only; GUI follows in P3.
Task CRUD (daemon commands)
task_create {name, type, project, interval?, enabled?, repo?, description?}task_update {name, ...}/task_delete {name}— respondtask_result {ok, task|error, summary}Template CRUD (daemon commands)
task_template_create {name, prompt}→ writes~/.emrg/task-templates/<name>.md(atomic tmp+replace)task_template_list→ builtin (read-only flag) + custom (with prompt preview)task_template_update/task_template_delete— respondtemplates_list/template_resultValidation (per host decisions)
^[a-z0-9][a-z0-9-]*$, ≤32 charsN task(s) use it (...)Hot reload (
TaskScheduler.apply_tasks)_task_cfg_signaturediffs name/type/config/interval/enabledTaskHandlerwith~/.emrg/task-templates/<type>.md(fallback evolution_prompt.md + warning) — unknown-type tasks are no longer silently skipped (P2 semantics)Tests
+8 (validation 4-cases / create+duplicate / update+delete / hot-reload add-remove / restart-on-change / idempotent / template guards incl. delete-refused / custom-type task) → pytest 736→744; Agent.md count synced. Daemon dispatch covered via existing e2e harness.