Until this window, Project Hub existed primarily as architectural planning notes and database schemas. Over the third week of July, the hub stood up as something an operator can actually run: an API backend managing work breakdown and dispatch, paired with an interactive frontend to visualize work progression.
The core responsibility of the Project Hub is turning monolithic project
deliverables into parallelizable execution waves. In project-hub-api, PR #13
implemented the phase decomposition service (IP-HUB-3.1). The implementation
deliberately kept graph mathematics isolated: DecompositionService was built
as a stateless singleton that takes raw work items and dependencies, calculates
topological orderings into discrete waves, and returns clean plan models before
any database transactions occur.
Directly following planning was the dispatch loop (#12, IP-HUB-3.2). Once
waves are committed, the dispatch engine monitors task completions, advances
the active wave index, and broadcasts status changes over an SSE change-event
stream.
On the frontend (project-hub-ui), PR #4 brought these capabilities to the
screen. Consuming the newly separated @adp/ui components and @adp/client
transport libraries, the UI implemented the Planner view (IP-HUB-3.3), wave
sequence cards showing pending vs. running tasks, and telemetry scoping panels
(IP-HUB-2.3).
Getting the project deployed on self-hosted runners hit a roadblock with CI.
In Gitea Actions 1.27.0, using if: ${{ needs.<job>.result == 'success' }}
caused workflows to lock up silently because the expression parser failed to
evaluate job dependency context. PR #11 unblocked the pipeline by dropping the
fragile expression syntax in favor of direct workflow job dependencies.
Additionally, PR #8 introduced explicit retention rules for v* release tags
in the local container registry, ensuring that production deployment images
would not be pruned as ephemeral test builds.
By July 25, the initial epics closed and project-hub-api tagged v0.1.5,
giving the platform a dedicated control plane for agent task orchestration.
Lessons learned
- Avoid needs. property evaluation in Gitea Actions if: conditions.*
Gitea Actions runner expressions can fail silently when parsing
needs.<job>properties in top-levelif:clauses, deadlocking downstream deployment jobs. Rely on explicitneeds: [job]dependency lists and step-level status gates instead. - Isolate algorithmic decomposition services as pure stateless singletons. Separating topological dependency sorting and wave generation into a stateless service with strict argument validation makes complex graph logic easy to unit test without needing mocked database contexts.
- Protect tagged container images from automated retention pruning.
Container registries configured to clean up untagged or old CI artifacts can
accidentally prune active deployment images unless explicit retention rules
are created to protect semantic version tags (
v*).