Skip to content

adds a doc explaining how complex multi-agency setups work in OBA#471

Merged
aaronbrethorst merged 1 commit into
mainfrom
docs
Jul 11, 2026
Merged

adds a doc explaining how complex multi-agency setups work in OBA#471
aaronbrethorst merged 1 commit into
mainfrom
docs

Conversation

@aaronbrethorst

@aaronbrethorst aaronbrethorst commented Jul 11, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Documentation
    • Added comprehensive guidance for creating multi-agency GTFS bundles.
    • Documented optional stop consolidation and validation workflows.
    • Added configuration examples for federation builds, audit logging, and verification.
    • Included a multi-agency bundle build script and consolidation file template.
    • Described pipeline workflows, smoke testing, edge cases, and troubleshooting guidance.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a comprehensive technical specification for building OBA multi-agency GTFS bundles, including per-agency loading, optional stop consolidation, Spring configuration, build scripts, CI verification, smoke tests, edge cases, and implementation references.

Changes

Multi-agency bundle specification

Layer / File(s) Summary
Loading and stop consolidation
docs/oba-multi-agency-bundle-spec.md
Defines per-agency GtfsBundle loading, agency ID mappings, load ordering, consolidation mappings, and entity replacement semantics.
Builder configuration and execution
docs/oba-multi-agency-bundle-spec.md
Documents Spring XML configuration, invocation rules, container requirements, and a multi-agency build script.
Pipeline workflow and validation
docs/oba-multi-agency-bundle-spec.md
Documents consolidation authoring, CI verification, smoke tests, edge cases, failure modes, examples, and source references.

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

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the new documentation about complex multi-agency setups in OBA.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/oba-multi-agency-bundle-spec.md`:
- Line 344: Update the three fenced code blocks in the documentation, including
the locations near lines 344, 749, and 930, to specify appropriate language
identifiers such as text or tsv immediately after each opening fence.
- Around line 845-850: Revise the numerical assertion for `stops-for-agency`
counts so it does not subtract every configured absorbed token; calculate the
reduction only from absorbed IDs present in the loaded feeds, or replace the
exact-count check with direct validation that required canonical IDs are loaded.
Update the assertion text near “Numerical assertions to bake into CI”
accordingly.
- Around line 348-359: Correct the worked load sequence to reflect
GtfsMultiReaderImpl’s entity-class-first iteration: load agencies from all feeds
before stops, then continue with subsequent entity classes. Remove claims that
mts.zip is processed first, that its stops load immediately, or that feeds load
in parallel, while preserving the replacement mapping and rejected-stop
behavior.
- Around line 596-630: Create /bundle/logs before the verification command
writes to it. Update the setup near mkdir -p /bundle/feeds to also create the
logs directory, ensuring tee can write consolidation-verification.txt
successfully.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5976b3b8-ae56-4698-8eb8-3a148924c771

📥 Commits

Reviewing files that changed from the base of the PR and between 9bd105b and 23b5d5b.

📒 Files selected for processing (1)
  • docs/oba-multi-agency-bundle-spec.md


Consolidation file entry:

```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add language identifiers to fenced code blocks.

markdownlint reports missing fence languages at all three locations. Use appropriate identifiers such as text or tsv.

Also applies to: 749-749, 930-930

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 344-344: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/oba-multi-agency-bundle-spec.md` at line 344, Update the three fenced
code blocks in the documentation, including the locations near lines 344, 749,
and 930, to specify appropriate language identifiers such as text or tsv
immediately after each opening fence.

Source: Linters/SAST tools

Comment on lines +348 to +359
Build sequence:

1. `mts.zip` reads first (or in parallel with the others). MTS Agency is
stored. MTS Stop 60123 is stored. Nothing unusual.
2. `ucsd.zip` reads. UCSD Agency is stored. UCSD Stop `gtsg-1` tries to
save → `StoreImpl.saveEntity` sees it has a replacement → entity is
shunted into `_rejectionStore`. **It never reaches the main store.**
3. Routes, Trips load normally. UCSD route still belongs to UCSD agency.
4. `stop_times.txt` rows from `ucsd.zip` parse. Each row referencing
`gtsg-1` triggers `getEntityForId(Stop.class, "UCSD_gtsg-1")`, which
sees the mapping and returns the `MTS_60123` Stop entity instead.
The resulting `StopTime` is bolted onto `MTS_60123`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the worked load sequence.

GtfsMultiReaderImpl iterates entity classes outermost and feeds innermost, so it loads all agencies across feeds before any stops. It does not read mts.zip and then immediately read its stops, and the supplied implementation provides no parallel loading. Rewrite this example to avoid implying feed ordering or parallelism is required.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/oba-multi-agency-bundle-spec.md` around lines 348 - 359, Correct the
worked load sequence to reflect GtfsMultiReaderImpl’s entity-class-first
iteration: load agencies from all feeds before stops, then continue with
subsequent entity classes. Remove claims that mts.zip is processed first, that
its stops load immediately, or that feeds load in parallel, while preserving the
replacement mapping and rejected-stop behavior.

Comment on lines +596 to +630
mkdir -p /bundle/feeds
cd /bundle

for AGENCY in "${!FEEDS[@]}"; do
URL="${FEEDS[$AGENCY]}"
PRISTINE="/bundle/feeds/${AGENCY}_pristine.zip"
TIDY_DIR="/bundle/feeds/${AGENCY}_tidy"
FINAL="/bundle/feeds/$(echo "$AGENCY" | tr '[:upper:]' '[:lower:]').zip"

echo "=== ${AGENCY}: downloading ==="
wget -O "$PRISTINE" "$URL"

echo "=== ${AGENCY}: tidying ==="
rm -rf "$TIDY_DIR"
mkdir -p "$TIDY_DIR"
(cd "$TIDY_DIR" && gtfstidy -OscRCSmeD -o . "$PRISTINE")

echo "=== ${AGENCY}: repacking ==="
rm -f "$FINAL"
(cd "$TIDY_DIR" && zip -q "$FINAL" *)
done

# Verify the consolidation file before building, so a stale canonical id
# fails the build loudly rather than silently dropping consolidations.
# COPY /oba/config/sdmts-stop-consolidation.txt and bundle-config.xml
# into the image at Dockerfile build time.
echo "=== verifying stop-consolidation file ==="
java -cp /oba/builder.jar \
org.onebusaway.transit_data_federation.bundle.utilities.GtfsStopReplacementVerificationMain \
/oba/config/sdmts-stop-consolidation.txt \
/bundle/feeds/mts.zip:MTS \
/bundle/feeds/nctd.zip:NCTD \
/bundle/feeds/san.zip:SAN \
/bundle/feeds/ucsd.zip:UCSD \
| tee /bundle/logs/consolidation-verification.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Create /bundle/logs before using tee.

The script creates /bundle/feeds but never creates /bundle/logs. Unless that directory already exists in the image, tee /bundle/logs/consolidation-verification.txt fails; with set -o pipefail, the build exits before the bundle build starts.

Proposed fix
 mkdir -p /bundle/feeds
+mkdir -p /bundle/logs
 cd /bundle
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
mkdir -p /bundle/feeds
cd /bundle
for AGENCY in "${!FEEDS[@]}"; do
URL="${FEEDS[$AGENCY]}"
PRISTINE="/bundle/feeds/${AGENCY}_pristine.zip"
TIDY_DIR="/bundle/feeds/${AGENCY}_tidy"
FINAL="/bundle/feeds/$(echo "$AGENCY" | tr '[:upper:]' '[:lower:]').zip"
echo "=== ${AGENCY}: downloading ==="
wget -O "$PRISTINE" "$URL"
echo "=== ${AGENCY}: tidying ==="
rm -rf "$TIDY_DIR"
mkdir -p "$TIDY_DIR"
(cd "$TIDY_DIR" && gtfstidy -OscRCSmeD -o . "$PRISTINE")
echo "=== ${AGENCY}: repacking ==="
rm -f "$FINAL"
(cd "$TIDY_DIR" && zip -q "$FINAL" *)
done
# Verify the consolidation file before building, so a stale canonical id
# fails the build loudly rather than silently dropping consolidations.
# COPY /oba/config/sdmts-stop-consolidation.txt and bundle-config.xml
# into the image at Dockerfile build time.
echo "=== verifying stop-consolidation file ==="
java -cp /oba/builder.jar \
org.onebusaway.transit_data_federation.bundle.utilities.GtfsStopReplacementVerificationMain \
/oba/config/sdmts-stop-consolidation.txt \
/bundle/feeds/mts.zip:MTS \
/bundle/feeds/nctd.zip:NCTD \
/bundle/feeds/san.zip:SAN \
/bundle/feeds/ucsd.zip:UCSD \
| tee /bundle/logs/consolidation-verification.txt
mkdir -p /bundle/feeds
mkdir -p /bundle/logs
cd /bundle
for AGENCY in "${!FEEDS[@]}"; do
URL="${FEEDS[$AGENCY]}"
PRISTINE="/bundle/feeds/${AGENCY}_pristine.zip"
TIDY_DIR="/bundle/feeds/${AGENCY}_tidy"
FINAL="/bundle/feeds/$(echo "$AGENCY" | tr '[:upper:]' '[:lower:]').zip"
echo "=== ${AGENCY}: downloading ==="
wget -O "$PRISTINE" "$URL"
echo "=== ${AGENCY}: tidying ==="
rm -rf "$TIDY_DIR"
mkdir -p "$TIDY_DIR"
(cd "$TIDY_DIR" && gtfstidy -OscRCSmeD -o . "$PRISTINE")
echo "=== ${AGENCY}: repacking ==="
rm -f "$FINAL"
(cd "$TIDY_DIR" && zip -q "$FINAL" *)
done
# Verify the consolidation file before building, so a stale canonical id
# fails the build loudly rather than silently dropping consolidations.
# COPY /oba/config/sdmts-stop-consolidation.txt and bundle-config.xml
# into the image at Dockerfile build time.
echo "=== verifying stop-consolidation file ==="
java -cp /oba/builder.jar \
org.onebusaway.transit_data_federation.bundle.utilities.GtfsStopReplacementVerificationMain \
/oba/config/sdmts-stop-consolidation.txt \
/bundle/feeds/mts.zip:MTS \
/bundle/feeds/nctd.zip:NCTD \
/bundle/feeds/san.zip:SAN \
/bundle/feeds/ucsd.zip:UCSD \
| tee /bundle/logs/consolidation-verification.txt
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/oba-multi-agency-bundle-spec.md` around lines 596 - 630, Create
/bundle/logs before the verification command writes to it. Update the setup near
mkdir -p /bundle/feeds to also create the logs directory, ensuring tee can write
consolidation-verification.txt successfully.

Comment on lines +845 to +850
Numerical assertions to bake into CI:

- **Sum of `stops-for-agency` counts** = (sum of input `stops.txt` row
counts) − (count of non-blank, non-comment, non-`{{{`/`}}}` lines in
the consolidation file, multiplied by absorbed-tokens-per-line). A
single mismatch means a consolidation silently failed to apply.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Do not subtract every configured absorbed token from the expected count.

The verification utility only requires canonical IDs to exist, and the document explicitly allows absorbed stops to disappear. Therefore, subtracting all absorbed tokens will reject valid builds whenever an absorbed stop is absent upstream. Compute the expected reduction from absorbed IDs actually present in the loaded feeds, or remove this exact-count assertion and validate loaded IDs directly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/oba-multi-agency-bundle-spec.md` around lines 845 - 850, Revise the
numerical assertion for `stops-for-agency` counts so it does not subtract every
configured absorbed token; calculate the reduction only from absorbed IDs
present in the loaded feeds, or replace the exact-count check with direct
validation that required canonical IDs are loaded. Update the assertion text
near “Numerical assertions to bake into CI” accordingly.

@aaronbrethorst aaronbrethorst merged commit c967410 into main Jul 11, 2026
3 checks passed
@aaronbrethorst aaronbrethorst deleted the docs branch July 11, 2026 02:18
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