Skip to content

feat(core): first-class tasks + task_events entity and relay API - #6425

Open
mfethe1 wants to merge 4 commits into
block:mainfrom
mfethe1:feat/task-system
Open

feat(core): first-class tasks + task_events entity and relay API#6425
mfethe1 wants to merge 4 commits into
block:mainfrom
mfethe1:feat/task-system

Conversation

@mfethe1

@mfethe1 mfethe1 commented Aug 20, 2026

Copy link
Copy Markdown

Summary

Adds the first two phases of Buzz's community-scoped task system: the durable task/task-event backend and mobile quick actions for creating tasks and summarizing threads into tasks.

Phase 1 — task entity and relay API

  • Added additive migration 0032_task_system.sql and schema/schema.sql parity for tasks and task_events.
  • Added tenant-scoped task status, priority, parent, assignee, source, and completion invariants.
  • Added the task lifecycle event log with a single-summary constraint.
  • Added authenticated task create/list/get/update and task-event endpoints with host-derived community scoping and channel access filtering.
  • Restricted event writes to the supported lifecycle actions; transition events are derived by the API rather than accepted as forged input.

Phase 2 — mobile quick actions

  • Added a + Task composer action that opens the New task sheet with channel/thread source context.
  • Added mobile task models/API and the New task sheet, including scope selection, optional assignee mention, due-date presets, priority, validation, and relay error handling.
  • Added a thread-header Summarize thread action.
  • Added a deterministic extractive Markdown digest that excludes system/blank rows, preserves thread order, highlights decisions and open questions, and extracts links.
  • Added copy-to-clipboard and save-to-task flows for a new or existing task; summaries persist through the supported summary_persisted task event.

Verification

All commands were run from this worktree with the repository Hermit toolchain.

  • dart format --output=none --set-exit-if-changed . — exit 0; 442 files checked, 0 changed.
  • flutter analyze --no-fatal-infos — exit 0; no issues found.
  • flutter test — exit 0; all 1,638 tests passed.
  • just fmt-check — exit 0.
  • just clippy — exit 0; workspace/all-targets clippy passed. Local Linux OpenSSL was supplied through PKG_CONFIG_PATH because the environment did not expose openssl.pc by default.
  • just test-unit — exit 0; unit-test recipe passed.
  • Focused Phase 2 tests — exit 0; 83 tests passed.
  • DCO Check — pass.

Scope note

The mobile tests use mocked HTTP clients for the task flows. A live relay/HTTP integration run was not performed in this verification pass.

@mfethe1
mfethe1 requested a review from a team as a code owner August 20, 2026 18:02
Adds a durable, community-scoped task entity so harness agents (Claude Code, Codex, ACP mesh) and humans can create/update/close work items inside Buzz. Includes:\n- migration 0032: tasks + task_events (additive, tenant-scoped, write-fenced, cross-tenant-unreferenceable)\n- schema.sql parity\n- REST API: list/create/get/patch + append-event, NIP-98 auth, channel access filtering, transition events un-forgeable\n- verification: migration-lint test + core unit tests + DB behavioral probes pass

Signed-off-by: Michael Feth <michael@jira-flow.com>
Signed-off-by: Michael Feth <michael@jira-flow.com>
mfethe1 added a commit to mfethe1/buzz that referenced this pull request Aug 22, 2026
Applied as the PR's net effect via 3-way merge. The one conflict was in
thread_detail_page.dart: main rebuilt the app bar (iOS glass back button,
padded title), while this PR only changed the title line -- main's version
subsumes it, so ours was kept.

Cherry-picked-from: PR block#6425
Signed-off-by: Michael Feth <mfethe1@gmail.com>
mfethe1 added a commit to mfethe1/buzz that referenced this pull request Aug 22, 2026
…the 1000-line gate

The mobile file-size ratchet flagged thread_detail_page.dart growing 994 -> 1004
lines when PR block#6425's quick actions landed. Moved the landing-highlight and
tail-correction constants into thread_detail_page/constants.dart as a part file,
matching the existing part-file layout. Back to 994 lines; ratchet green.

Signed-off-by: Michael Feth <mfethe1@gmail.com>
Resolves the app bar conflict in thread_detail_page.dart. Upstream replaced
the FrostedAppBar with an iOS glass back button, iconColor, and a padded
title carrying a ValueKey; this branch had only made the title Text const.
Upstream's version supersedes it and is kept whole. This branch's actual
contribution to that widget -- the actions: [_SummarizeThreadButton(...)]
block -- merged cleanly outside the conflict and is unaffected.

Signed-off-by: Michael Feth <michael@jira-flow.com>

# Conflicts:
#	mobile/lib/features/channels/thread_detail_page.dart
Upstream landed 0032_channel_roster_snapshot_fence (block#6251) while this
branch carried 0032_task_system. Different filenames, so git merged the
two cleanly and produced a duplicate migration version -- the failure
class a textual merge cannot see.

Renumbers ours to 0033 (upstream owns 0032) and repoints the assertions
that this branch itself introduced:

- task_system_tables_are_additive_tenant_scoped_and_fenced now reads
  migrations[32]/version 33 instead of migrations[31]/version 32, which
  had silently begun asserting against upstream's roster fence.
- embedded_migrator_contains_consolidated_initial_schema expects 33
  migrations; this branch had bumped it 31->32 and upstream's addition
  makes 33 correct.
- Comments in task.rs and schema.sql renumbered to match.

No migration SQL changed; the file was renamed, not rewritten.

Verified: buzz-db 109 passed 0 failed, buzz-core 269 passed,
buzz-relay tasks 8 passed, workflow_sink 17 passed. buzz-relay --lib
full is 906 passed / 9 failed, and those 9 are byte-identical to
upstream main's own 9 failures (api::media, api::admin, telemetry --
pre-existing, unrelated to this branch).

Signed-off-by: Michael Feth <michael@jira-flow.com>
@mfethe1

mfethe1 commented Aug 22, 2026

Copy link
Copy Markdown
Author

Rebased onto main (040b203f7) and pushed as a2bd15f8e. This PR was mergeable=false / dirty; it is now mergeable=true. Two things needed resolving, and the second was not visible to git.

1. App bar conflict in mobile/lib/features/channels/thread_detail_page.dart

main rewrote this FrostedAppBarIosGlassNavigationButton leading, iconColor, and a padded title carrying ValueKey('thread-app-bar-title'). This branch had only made the title Text const, which upstream's rewrite supersedes, so upstream's version is kept whole and the const-title line is dropped.

This branch's actual contribution to that widget — the actions: [_SummarizeThreadButton(...)] block and the thread_summary imports — merged cleanly outside the conflict region and is unchanged. Verified post-merge that both the glass back button and _SummarizeThreadButton are present.

2. A duplicate migration version that merged cleanly

This is the part worth flagging. main landed 0032_channel_roster_snapshot_fence.sql (#6251) while this branch carried 0032_task_system.sql. Different filenames, so git merged them without a conflict and produced two migration version 32s. git merge-tree reported zero conflicts against a tree that was semantically broken.

The symptom was a test on this branch silently asserting against the wrong migration: assert_eq!(migrations[31].version, 32) had begun reading upstream's roster fence rather than the task system, and failed on sql.contains("CREATE TABLE tasks").

Fixed by renumbering ours, since upstream owns 0032:

  • migrations/0032_task_system.sqlmigrations/0033_task_system.sqlrenamed, not rewritten. No migration SQL changed, so brownfield checksums are untouched and the additive-migration invariant holds.
  • task_system_tables_are_additive_tenant_scoped_and_fenced now reads migrations[32] / version 33.
  • embedded_migrator_contains_consolidated_initial_schema now expects 33 migrations. git blame confirms that line is this branch's own (40f39053de bumped it 31→32); upstream's addition makes 33 correct. On-disk count verified: 33 here, 32 on main.
  • Renumbered the stale 0032 comments in crates/buzz-db/src/task.rs and schema/schema.sql.

No assertion was weakened to make anything pass. Every line changed was introduced by this branch.

Verification

suite result
cargo test -p buzz-db --lib 109 passed, 0 failed
cargo test -p buzz-core --lib 269 passed, 0 failed
cargo test -p buzz-relay --lib tasks 8 passed, 0 failed
cargo test -p buzz-relay --lib workflow_sink 17 passed, 0 failed
duplicate migration versions none

cargo test -p buzz-relay --lib (full) is 906 passed / 8 failed. Those 8 are not from this branch — I ran the same suite in a worktree on untouched main (040b203f7) and diffed the failure name sets:

ours:     906 passed, 8 failed
baseline: 898 passed, 9 failed   (main, untouched)
ours minus baseline:  empty      (zero regressions)

All 8 (api::media x6, api::admin x2) fail identically on main and reproduce under --test-threads=1, so they are pre-existing and environmental rather than order-dependent. The +8 pass delta is exactly this branch's new task tests.

Baseline additionally fails telemetry::tests::trace_context_lookup_does_not_enable_callsites. That one is genuinely order-dependent global tracing state — on this branch it failed 1 of 3 identical full-suite runs. I'm noting it as flaky rather than claiming this branch fixed it.

Not verified locally

dart/flutter are not installed on this machine, so the Dart edit above is not locally compiled or analyzed. It is structurally sound and marker-free, but "it builds" is not something I have evidence for — mobile CI is the first real check. Flagging that explicitly rather than implying a green mobile gate.

Since this touches migrations/ and schema/schema.sql, I'm treating it as review-required regardless of gate colour and am not self-merging.

mfethe1 added a commit to mfethe1/buzz that referenced this pull request Aug 22, 2026
mfethe1 added a commit to mfethe1/buzz that referenced this pull request Aug 23, 2026
Fork-only integration. The task system does not exist on block/buzz origin/main
(crates/buzz-db/src/task.rs, crates/buzz-relay/src/api/tasks.rs,
mobile/lib/shared/tasks/, migrations/0033 all absent; upstream migrations stop
at 0032), so HW-001 cannot be upstreamed until PR block#6425 merges.

Gates re-run independently by Loop 4:
  cargo buzz-db 109 / buzz-core 269 / buzz-acp 819 / buzz-relay 933, 0 failed
  desktop pnpm typecheck + 5 check:* guards, all exit 0
  flutter analyze 6 issues (equals baseline, no increase)
  flutter test: 14 failures, name set IDENTICAL to product/main baseline
  comm -23 ours baseline = empty (0 regressions)

Signed-off-by: Michael Feth <michael@jira-flow.com>
mfethe1 added a commit to mfethe1/buzz that referenced this pull request Aug 23, 2026
Read-only backlink chip on the mobile thread view, surfacing the
source_ref reverse lookup that HW-001 shipped but left invisible.

Validated independently by Loop 4 (not trusting Loop 3's self-report):
- integrity: no conflict markers on either branch or the merged tree;
  git diff --check clean; duplicate migration prefix scan empty
  (0 migration files touched); DCO present; no AI attribution trailers.
- scope: git diff product/main...feat/HW-004 -- ':!mobile' is EMPTY.
  Rust and desktop trees are byte-identical, so those gates are
  structurally unaffected rather than merely assumed green.
- flutter analyze: 6 issues on feat, 6 on product/main @93b9bdcb9,
  identical diagnostic signature sets, none in the new files.
- flutter test --reporter json, NAME SETS diffed both directions:
  base 1760 pass / 14 fail, feat 1771 pass / 14 fail.
  ONLY-IN-FEAT empty, ONLY-IN-BASE empty = IDENTICAL.
  The 14 are CONTROL.yaml's known upstream baseline failures.

Fork-only, re-confirmed by evidence rather than inherited claim:
git cat-file -e origin/main:<path> shows mobile/lib/shared/tasks/
{tasks_api,task}.dart, thread_detail_page/summarize_action.dart and
migrations/0033_task_system.sql are ABSENT upstream (upstream
migrations stop at 0032). No block/buzz PR is opened for HW-004; it
cannot be upstreamed until block#6425 merges.

Signed-off-by: Michael Feth <michael@jira-flow.com>
mfethe1 added a commit to mfethe1/buzz that referenced this pull request Aug 23, 2026
Read-only task detail sheet reached by tapping the HW-004 thread chip.
One GET per open, 404/500 render the identical error row (no existence
oracle), unknown actions/statuses render verbatim, untrusted text
rune-clamped. Zero Rust/desktop/migration changes.

Gates re-run by Loop 4 (independent of Loop 3's self-report):
- integrity: conflict markers empty, diff --check clean, no dup
  migration prefixes, DCO present, no AI attribution trailers
- cargo: buzz-db 109/0, buzz-core 269/0, buzz-acp 819/0, buzz-relay 933/0
- desktop: pnpm typecheck + 5 check:* guards all EXIT:0
- flutter analyze: signature set IDENTICAL to product/main base
  (6 vs 6, comm empty both directions; 6th diagnostic is pre-existing
  product drift in huddle_call_avatar.dart, not introduced here)
- flutter test --reporter json: feat 1790 pass/14 fail vs untouched
  origin/main@e23632941 1647 pass/14 fail; failure NAME SETS identical
  both directions (comm -23 empty); the 14 are known upstream failures
- combined tree: merged tree SHA == feat tree SHA (identity); zero
  duplicate test names introduced
- visual evidence regenerated byte-identical (5/5 PNGs, sha256 match)

fork-only: task system absent from origin/main (block#6425 still OPEN).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant