Skip to content

fix: preserve sparse fan-out roster rows - #518

Merged
pedronauck merged 2 commits into
mainfrom
issue-506
Sep 1, 2026
Merged

pedronauck merged 2 commits into
mainfrom
issue-506

Conversation

@pedronauck

@pedronauck pedronauck commented Sep 1, 2026 •

Copy link
Copy Markdown
Member

What & why

Fixes #506.

Fan-out roster projection treated the highest persisted item index as a contiguous range. When only item 2, or items 2 and 5, existed, CompozyOS invented rows for the missing indexes and left them pending. This change projects only the exact persisted item indexes, so roster rows, rollups, and run progress describe the workers that actually exist.

The change also documents sparse-index behavior in the Loop running guide and the official Compozy skill, and corrects the stale Web source comment about not_taken.

After rebasing onto the current main, exact-head CI exposed a base regression: scripts/sync-emojibase.mjs resolves its data through web/package.json, but the required Web development dependency had been removed. This PR restores the pinned dependency so clean installs can execute the repository's codegen contract.

How you verified it

  • make gate passed on the rebased diff with fresh Go lint, Go race-test, and all-workspace JS records.
  • go test -race -cover ./internal/loop -count=1 passed all 1,086 tests. Changed functions have 89.2%-100% coverage.
  • The canonical internal/loop.TestRosterContract regression first reproduced the bug ([0 1 2 3 4 5] instead of [2 5]) and now passes for both lone and non-contiguous sparse indexes.
  • Isolated real-scenario QA passed across CLI, HTTP, UDS, compozy__loop_runs, and the headed Web UI. The observed worker indexes were exactly 2 and 2,4; rollup was 2/2; run-list progress was 3/3; Web refresh preserved the result.
  • The strict QA evidence audit passed, and teardown finished with clean: true and no surviving processes.
  • A fresh clone of base main reproduced the Emojibase resolution error. A fresh clone of this branch passed bun install --frozen-lockfile followed by make codegen-check.

OpenAI Codex co-wrote this change. I reviewed the diff and verified the result locally.

Impact

  • CLI/HTTP/UDS: response shapes and routes are unchanged. Existing roster and progress reads now return correct sparse fan-out results.
  • Web: no component contract changed; the UI consumes the corrected server rollup. The stale not_taken source comment was updated, and the pinned codegen data dependency was restored.
  • Docs: updated packages/site/content/docs/loops/running.mdx and skills/compozy/references/loops.md.
  • Config: no config.toml key, default, or lifecycle changed.
  • Native tools: no tool IDs, toolsets, descriptors, schemas, digests, risk flags, availability diagnostics, or capability gates changed. compozy__loop_runs inherits the corrected shared roster projection.
  • Extensibility and hooks: no extensions, hooks, capabilities, registries, bridge SDKs, MCP sidecars, or resource contracts changed.
  • Workspace data isolation: no datum ownership or workspace_id propagation changed. Loop outputs remain workspace-scoped through CLI, HTTP, UDS, core, store, Web, events, and cache reads.
  • Official Compozy skill: updated the Loop reference with sparse-index semantics and clarified that not_taken requires durable route evidence.
  • QA tracker: the affected Loop scenarios were re-walked and recorded as passing. Restoring the build-only dependency has no user-visible QA scenario impact.

  • make gate passes locally; this PR is delivered only after its required CI checks are green
  • New or changed behavior is covered by tests, or I explained above why not
  • If an agent wrote or co-wrote this, I named it above and verified the result myself

Summary by CodeRabbit

  • Bug Fixes

    • Preserved exact fan-out item indexes in roster projections, including sparse indexes without filling gaps.
    • Improved fan-out rollups and progress totals for more accurate loop status reporting.
  • Documentation

    • Clarified that unselected route branches represent durable, visually neutral evidence of unresolved work.

@vercel

vercel Bot commented Sep 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
compozy-site Ready Ready Preview Sep 1, 2026 2:34pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: 6cfb93e7-a0e8-4603-b33f-6f646d92bfc5

📥 Commits

Reviewing files that changed from the base of the PR and between ed2561c and d18a163.

⛔ Files ignored due to path filters (8)
  • docs/qa/bugs/BUG-20260901-filtered-fanout-phantom-rows.md is excluded by !**/*.md
  • docs/qa/reports/2026-09-01-issue-506-filtered-fanout.md is excluded by !**/*.md
  • docs/qa/scenarios/LP-fan-out-filtering.md is excluded by !**/*.md
  • docs/qa/scenarios/LP-run-read-agent-journey.md is excluded by !**/*.md
  • docs/qa/scenarios/LP-runs-roster-server-ordering.md is excluded by !**/*.md
  • docs/qa/scenarios/LP-web-run-operator-register.md is excluded by !**/*.md
  • packages/site/content/docs/loops/running.mdx is excluded by !**/*.mdx
  • skills/compozy/references/loops.md is excluded by !**/*.md
📒 Files selected for processing (5)
  • internal/loop/roster.go
  • internal/loop/roster_helpers.go
  • internal/loop/roster_projection.go
  • internal/loop/roster_test.go
  • web/src/systems/loops/lib/loop-run-fanout-band.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 3 remain after this review.


Walkthrough

The roster projection now indexes each materialized output item and projects only those indexes. This preserves nonzero and sparse fan-out indexes. Tests cover roster items, rollups, and progress totals. A frontend comment clarifies the never progress segment.

Changes

Fan-out roster projection

Layer / File(s) Summary
Index materialized output items
internal/loop/roster_helpers.go, internal/loop/roster.go
indexOutputs records sorted item indexes per roster node key. rosterItems receives the index map instead of a maximum item count.
Project exact roster items
internal/loop/roster_projection.go, internal/loop/roster_test.go, web/src/systems/loops/lib/loop-run-fanout-band.ts
rosterItems projects only recorded indexes. Tests cover sparse indexes, fan-out rollups, and progress totals. The never segment comment describes durable evidence that a route branch was not taken.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to d18a1

The PR corrects sparse fan-out roster and progress reporting and restores a pinned build dependency needed for clean code generation. The changes are covered by passing tests and validation, with no actionable merge-blocking risk remaining.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #506 by indexing exact persisted fan-out item indexes, preventing fabricated pending rows and incorrect rollups. Regression tests cover sparse indexes, sorting, rollups, and …
Out of Scope Changes check ✅ Passed The reviewed changes support the stated objectives. The roster fix, regression tests, and related comment update are relevant to sparse fan-out reporting. Excluded documentation files cannot be assess…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preserving sparse fan-out roster rows.
Full details: Linked Issues check

Explanation

The changes address issue #506 by indexing exact persisted fan-out item indexes, preventing fabricated pending rows and incorrect rollups. Regression tests cover sparse indexes, sorting, rollups, and progress totals.

Full details: Out of Scope Changes check

Explanation

The reviewed changes support the stated objectives. The roster fix, regression tests, and related comment update are relevant to sparse fan-out reporting. Excluded documentation files cannot be assessed, but they are not required to validate the coding objectives.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-506

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit d18a163.

@pedronauck
pedronauck marked this pull request as ready for review September 1, 2026 14:31
@pedronauck
pedronauck marked this pull request as draft September 1, 2026 14:32
@pedronauck
pedronauck marked this pull request as ready for review September 1, 2026 14:32
@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown

Greptile Summary

The PR changes roster projection to preserve only exact persisted fan-out item indexes instead of filling gaps, and adds regression coverage for lone and non-contiguous sparse workers.

  • Sorts persisted worker indexes while retaining their sparse identities.
  • Keeps roster progress and multi-worker fan-out rollups based only on materialized rows.
  • Updates Loop documentation, the official skill reference, Web source commentary, and QA records to describe the corrected behavior.

Confidence Score: 5/5

The PR appears safe to merge because the changed projection follows persisted worker identities and no actionable regression was identified.

Storage uniqueness and atomic snapshot writes support the new exact-index projection, while the added tests cover sparse ordering, roster progress, and rollup behavior.

Important Files Changed

Filename Overview
internal/loop/roster_helpers.go Replaces maximum-index tracking with sorted lists of exact persisted item indexes.
internal/loop/roster_projection.go Projects fan-out rows only for persisted indexes, preventing synthetic pending rows in sparse ranges.
internal/loop/roster.go Wires exact output-index projection into the roster read path without changing its public shape.
internal/loop/roster_test.go Adds canonical coverage for lone and non-contiguous sparse fan-out workers, rollups, and progress.
packages/site/content/docs/loops/running.mdx Documents that fan-out source indexes may be sparse and that absent indexes do not count as workers.
skills/compozy/references/loops.md Aligns the official agent guidance with sparse roster semantics and durable not-taken evidence.
web/src/systems/loops/lib/loop-run-fanout-band.ts Corrects the comment describing not-taken segments without changing runtime behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Persisted generation outputs] --> B[Group exact item indexes by generation and node]
    B --> C[Sort sparse indexes]
    C --> D[Project one roster row per persisted index]
    D --> E[Compute progress and fan-out rollups]
    C -. Missing indexes are not projected .-> D
Loading

Reviews (1): Last reviewed commit: "test: verify sparse fan-out roster repor..." | Re-trigger Greptile

@pedronauck

Copy link
Copy Markdown
Member Author

@CodeRabbit full review

@coderabbitai

coderabbitai Bot commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@pedronauck
pedronauck merged commit b233aea into main Sep 1, 2026
39 checks passed
@pedronauck
pedronauck deleted the issue-506 branch September 1, 2026 14:54
This was referenced Sep 27, 2026
This was referenced Oct 6, 2026
This was referenced Oct 9, 2026

This branch was successfully deployed

1 active deployment
Preview — d18a1633 Deployed Sep 1, 2026 by vercel[bot]
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.

Fan-out filter: roster invents pending rows for rejected items, so a successful run reports an unclosable fraction

1 participant