Skip to content

feat: Phase 3 leftovers — Saga kind, catalog smoke, Cycle card#4

Merged
Cervator merged 7 commits into
mainfrom
feat/phase3-leftovers
Jul 8, 2026
Merged

feat: Phase 3 leftovers — Saga kind, catalog smoke, Cycle card#4
Cervator merged 7 commits into
mainfrom
feat/phase3-leftovers

Conversation

@agent-refr

Copy link
Copy Markdown

AI-assisted change proposal. Filed by agent driven by @Cervator via GDD.

Summary

Completes the Phase 3 leftovers (on top of the merged Cycle kind + MTL seed):

  • Saga custom kind — the narrated half of the two-family model. A thin,
    Git-backed index entity for an authored After-Action-Report: SagaProcessor
    validates spec.skald (author), spec.timeframe, non-empty spec.touches[],
    optional spec.owner, and the required siliconsaga.org/saga-doc annotation;
    emits built-in relations (skald/owner → ownedBy, touches[] → dependsOn). Seed
    saga-soccer-2026-spring with its narrative body in examples/sagas/. ADR 0008.
    Authoring UI / blog-render remain deferred (Phase 4+).
  • make smoke-catalog — a committed, real end-to-end catalog-ingestion test
    (boots the backend headless in stub mode, asserts Cycle + Saga ingest with
    their relations via the catalog API, tears down). The idiomatic realization of
    the "real startTestBackend catalog test" leftover; supersedes the source-assertion
    smokes for runtime coverage.
  • Curated Cycle overview card — a new-frontend-system EntityCardBlueprint
    extension gated to kind: cycle, showing type / timeframe / part-of / happens-at
    in place of the generic default page.

Test plan

  • make ci green — config-check, lint, envelope BDD 23/23, app+backend units
    16/16 (incl. the new SagaProcessor suite and the app render with the Cycle
    module registered).
  • tsc clean (backend module + frontend extension).
  • make smoke-catalog PASS — Cycle + Saga ingest at runtime with all relations,
    no catalog errors.
  • Manual UI check (author): the curated Cycle card renders on soccer-2026-spring.

Related

Cervator added 3 commits July 6, 2026 22:08
…DR 0008

The narrated half of the two-family model (Phase 3 leftover). Adds a custom
`Saga` kind — a thin, Git-backed index entity for an authored After-Action-Report:

- `SagaProcessor` (new-backend-system catalog module) validates `spec.skald`
  (author, a User ref), `spec.timeframe`, non-empty `spec.touches[]` (entity refs
  it narrates), optional `spec.owner`, and the required `siliconsaga.org/saga-doc`
  annotation (path to the narrative). Emits built-in relations: skald/owner →
  ownedBy/ownerOf, touches[] → dependsOn/dependencyOf.
- Seed: a `saga-soccer-2026-spring` example over the MTL season, with its narrative
  body at `examples/sagas/soccer-2026-spring.md` (Git-backed — Backstage indexes it,
  the DB never holds unique data). Allowed the `Saga` kind on the mtl.yaml location.
- ADR 0008 records the decision.

Deferred (Phase 4+): the authoring UX (catalog-backed touches pickers) and
blog/TechDocs rendering of the narrative — this is the catalog kind only.

Verified: unit tests 7/7, `make ci` green (units 16/16, envelope 23/23), and a
headless boot-smoke confirms the Saga ingests at runtime with all relations.

Co-Authored-By: Cervator <cervator@gmail.com>
The committed, real end-to-end ingestion test for the custom kinds — the piece the
design tracked as "a real startTestBackend catalog test" to supersede the
source-assertion BDD smokes.

Realized as a headless smoke script (the idiomatic pattern here — the committed
counterpart to smoke-gitea, and what the design called startTestBackend's "live
cousin"). A pure jest startTestBackend for catalog *location processing* is
awkward and flaky: the catalog ingests locations asynchronously on a scheduler, so
a test polls the API anyway — which is exactly what this script does, without the
in-process-backend fragility.

`make smoke-catalog` boots the backend headlessly in stub mode (no cluster, no
secrets), waits for the MTL seed to process, and asserts via the catalog API that
`Cycle` and `Saga` ingest WITH their emitted relations (partOf/ownedBy/dependsOn),
then tears the backend down. Safe to run anywhere, including CI. Verified PASS.

Co-Authored-By: Cervator <cervator@gmail.com>
…nsion)

The last Phase 3 leftover: a curated entity view for the `Cycle` kind, replacing
the generic default page with something that surfaces the fields that matter.

New-frontend-system extension (mirrors the existing nav module): an
`EntityCardBlueprint` info-card gated by `filter: { kind: 'cycle' }`, wired via a
`cycleModule` added to `createApp({ features })`. It attaches to the catalog
default Overview automatically. The card (`CycleCard.tsx`, `useEntity` +
core-components `InfoCard`/`StructuredMetadataTable`) shows the Cycle's type,
timeframe (start → end), what it is `of`, and where it `happensAt`.

Adds `@backstage/plugin-catalog-react` (^3.1.0) and `@backstage/catalog-model` to
packages/app (were transitive-only).

Verified headlessly: `tsc` clean; `make ci` green (lint + `App.test.tsx` renders
the app with the module registered). The visual render is a `make dev` eyeball —
the card only appears on `kind: Cycle` entities (e.g. soccer-2026-spring).

Co-Authored-By: Cervator <cervator@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 94c7ad51-300d-4fe7-aa5c-5ed864c59254

📥 Commits

Reviewing files that changed from the base of the PR and between a763719 and 12289b9.

📒 Files selected for processing (3)
  • docs/development/testing.md
  • packages/app/src/modules/cycle/CycleCard.tsx
  • scripts/smoke-catalog.sh

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added support for the narrated Saga catalog entity kind, including example Saga documentation and sample ingestion data.
    • Added a Cycle overview card for custom Cycle entities in the app.
  • Bug Fixes
    • Improved Saga validation and automatic ownership/dependency relation generation during catalog ingestion.
  • Tests
    • Added a smoke-catalog ingestion proof in stub mode and expanded CI/test coverage to include Cycle/Saga processing.
    • Added repo-wide typechecking to the CI gate.
  • Documentation
    • Added an ADR for Saga and updated testing guidance to reference the new smoke-test workflow.

Walkthrough

This PR adds a Saga catalog kind with backend validation, relation emission, catalog module wiring, example content, documentation updates, a frontend Cycle overview card, and a new smoke-catalog verification path.

Changes

Saga catalog kind and supporting changes

Layer / File(s) Summary
ADR and testing docs
docs/adrs/0008-saga-git-backed-kind.md, docs/adrs/README.md, docs/development/testing.md
Adds ADR 0008 for the Git-backed Saga kind, indexes it, and updates testing docs for Saga processor tests and the smoke-catalog check.
SagaProcessor validation and relations
packages/backend/src/modules/saga/SagaProcessor.ts, packages/backend/src/modules/saga/SagaProcessor.test.ts
Implements Saga validation and relation emission logic and adds tests for valid, invalid, and non-Saga entities.
Backend module registration and config
packages/backend/src/modules/saga/catalogModuleSaga.ts, packages/backend/src/index.ts, app-config.yaml
Registers the Saga catalog module, wires it into backend startup, and allows Saga in the catalog import rules.
Example Saga entity and narrative doc
examples/mtl.yaml, examples/sagas/soccer-2026-spring.md
Adds a seeded Saga entity and its referenced markdown narrative example.
Cycle overview card frontend module
packages/app/src/modules/cycle/CycleCard.tsx, packages/app/src/modules/cycle/index.tsx, packages/app/src/App.tsx, packages/app/package.json
Adds a Cycle overview card, registers it as a frontend extension, and includes the catalog UI dependencies and app feature wiring.
smoke-catalog script and Make targets
Makefile, scripts/smoke-catalog.sh
Adds a smoke-catalog make target and script that boots the backend, polls the catalog API, checks entities and relations, and exits pass/fail.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Catalog
  participant SagaProcessor
  participant Entity

  Catalog->>SagaProcessor: validateEntityKind(entity)
  SagaProcessor->>Entity: check spec.skald, spec.touches, saga-doc annotation
  SagaProcessor-->>Catalog: throw error or return true
  Catalog->>SagaProcessor: postProcessEntity(entity)
  SagaProcessor->>SagaProcessor: parse skald/owner/touches refs
  SagaProcessor-->>Catalog: emit ownedBy/ownerOf, dependsOn/dependencyOf relations
Loading
sequenceDiagram
  participant Makefile
  participant SmokeScript
  participant Backend
  participant CatalogAPI

  Makefile->>SmokeScript: run smoke-catalog.sh
  SmokeScript->>Backend: start in stub mode with static token config
  SmokeScript->>Backend: poll .dev/backend.log for "Listening on"
  SmokeScript->>CatalogAPI: GET entities/by-name (Cycle, Saga, Group)
  CatalogAPI-->>SmokeScript: entity JSON with relations
  SmokeScript->>SmokeScript: run PASS/FAIL assertions
  SmokeScript-->>Makefile: exit 0 (pass) or exit 1 (fail with log tail)
Loading

Possibly related PRs

  • SiliconSaga/leidangr#1: Both PRs extend the same Makefile-driven smoke-test workflow by adding headless catalog ingestion smoke targets/scripts.
  • SiliconSaga/leidangr#3: Both PRs touch catalog ingestion wiring and Makefile CI/test targets around the custom entity pipeline.

Suggested reviewers: Cervator

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately highlights the main additions: Saga kind, catalog smoke test, and Cycle card.
Description check ✅ Passed The description is clearly aligned with the changeset and summarizes the Saga kind, smoke test, and Cycle card work.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/phase3-leftovers

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: 6

🤖 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 `@Makefile`:
- Line 12: The Makefile’s ci composite target does not include smoke-catalog, so
the headless stub-mode verification for the new Saga/Cycle ingestion path is
skipped in CI. Update the ci target to invoke smoke-catalog alongside the
existing config-check, lint, test, and test-app steps, or split it into a
dedicated CI job if that better fits the pipeline. Use the existing
smoke-catalog target and the ci target definition as the symbols to update.

In `@packages/app/src/modules/cycle/CycleCard.tsx`:
- Around line 23-30: The CycleCard metadata is rendering entity refs as plain
strings instead of clickable catalog links. Update the rendering in CycleCard to
use EntityRefLink for spec.of and EntityRefLinks for each spec.happensAt entry,
replacing the raw values while keeping the same fallback behavior for missing
data. Use the existing metadata setup in CycleCard and the Backstage
catalog-react link components to show resolved, user-friendly entity names.

In `@packages/backend/src/modules/saga/SagaProcessor.test.ts`:
- Around line 31-65: Add a test in SagaProcessor.validateEntityKind coverage for
the new malformed entity-ref path: the current cases in SagaProcessor.test.ts
validate missing and empty fields but not the isParseableRef failure branch.
Extend the existing validateEntityKind describe block with a case that passes a
Saga whose spec.skald is an invalid ref string, and assert it rejects with the
specific spec.skald invalid entity ref error so the parsing logic is directly
covered.

In `@scripts/smoke-catalog.sh`:
- Line 12: The smoke-catalog script does not guard the directory change, so if
the cd in the script startup fails it will continue from the wrong working
directory. Update the shell setup around the existing cd command to fail fast on
directory-change errors, using the script’s top-level initialization logic so
the script exits immediately instead of proceeding with an invalid cwd.
- Around line 53-54: The byname() helper in the smoke-catalog script calls curl
without any timeout, so the polling loop can hang if the backend stalls. Update
the curl invocation in byname() to include both a connection timeout and an
overall max time, keeping the existing fallback behavior and hdr array usage
intact so the smoke-catalog loop respects its intended budget.
- Around line 69-88: The smoke test in the check block is short-circuiting
because the individual check calls are chained with &&, so a single failure
prevents later assertions from running. Update the sequence around check, CYCLE,
GROUP, and SAGA to execute each check unconditionally while still tracking
whether any failed, and only set pass=1 if all required checks succeed. Keep the
PASS/FAIL reporting inside check so every assertion prints its result.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 253fd368-39d7-4747-88d1-1850222daff8

📥 Commits

Reviewing files that changed from the base of the PR and between 73aa2a0 and 82a476f.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (16)
  • Makefile
  • app-config.yaml
  • docs/adrs/0008-saga-git-backed-kind.md
  • docs/adrs/README.md
  • docs/development/testing.md
  • examples/mtl.yaml
  • examples/sagas/soccer-2026-spring.md
  • packages/app/package.json
  • packages/app/src/App.tsx
  • packages/app/src/modules/cycle/CycleCard.tsx
  • packages/app/src/modules/cycle/index.tsx
  • packages/backend/src/index.ts
  • packages/backend/src/modules/saga/SagaProcessor.test.ts
  • packages/backend/src/modules/saga/SagaProcessor.ts
  • packages/backend/src/modules/saga/catalogModuleSaga.ts
  • scripts/smoke-catalog.sh

Comment thread Makefile Outdated
Comment thread packages/app/src/modules/cycle/CycleCard.tsx Outdated
Comment thread packages/backend/src/modules/saga/SagaProcessor.test.ts
Comment thread scripts/smoke-catalog.sh Outdated
Comment thread scripts/smoke-catalog.sh Outdated
Comment thread scripts/smoke-catalog.sh Outdated

Copilot AI 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.

Pull request overview

Completes Phase 3 “leftovers” by adding the narrated Saga catalog kind (Git-backed index entity), introducing a committed end-to-end stub-mode catalog ingestion smoke (make smoke-catalog), and adding a curated Cycle overview card to the new frontend system so kind: Cycle shows key fields on the entity Overview.

Changes:

  • Add SagaProcessor + backend catalog module wiring, seed entity + ADR, and catalog rules/config updates to allow/ingest Saga.
  • Add make smoke-catalog + scripts/smoke-catalog.sh to boot the backend headlessly and assert Cycle/Saga ingestion via the catalog API.
  • Add a Cycle-specific overview card extension (new frontend system) and required app deps.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
yarn.lock Locks new app dependencies for catalog model/react usage.
scripts/smoke-catalog.sh New stub-mode, headless backend boot + catalog API assertions for Cycle/Saga ingestion.
packages/backend/src/modules/saga/SagaProcessor.ts Implements Saga kind validation + relation emission.
packages/backend/src/modules/saga/SagaProcessor.test.ts Unit tests for SagaProcessor validation and emitted relations.
packages/backend/src/modules/saga/catalogModuleSaga.ts Registers SagaProcessor via the catalog processing extension point.
packages/backend/src/index.ts Wires the saga backend module into the backend runtime.
packages/app/src/modules/cycle/index.tsx Registers a Cycle-only overview card extension via EntityCardBlueprint.
packages/app/src/modules/cycle/CycleCard.tsx Implements the curated Cycle overview card UI.
packages/app/src/App.tsx Adds the cycle frontend module to app features.
packages/app/package.json Adds required dependencies for the new cycle module implementation.
Makefile Adds smoke-catalog target.
examples/sagas/soccer-2026-spring.md Adds example narrative body referenced by the Saga entity annotation.
examples/mtl.yaml Seeds a Saga entity referencing the narrative and touches relations.
docs/development/testing.md Documents the new real-ingestion smoke and test layout updates.
docs/adrs/README.md Adds ADR 0008 to the index.
docs/adrs/0008-saga-git-backed-kind.md Records the Saga-kind decision and scope.
app-config.yaml Allows Saga in the example location’s catalog rules.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/backend/src/modules/saga/SagaProcessor.ts
Comment thread packages/backend/src/modules/saga/SagaProcessor.test.ts
Comment thread scripts/smoke-catalog.sh Outdated
Cervator added 3 commits July 8, 2026 09:49
Two small gate improvements so a single `make ci` (and, once the realm adapter
points at it, `ws test leidangr`) is a reliable full local gate:

- `test-app` now runs with `CI=true`, forcing backstage-cli repo test to a single
  run. Without it, backstage-cli watches when attached to a TTY and never exits —
  which would hang `make ci` / `ws test` in an interactive terminal.
- Added a `tsc` target and folded it into `ci`, so the gate also typechecks
  (catches wiring/import errors the linter misses — the class of thing the Phase 3
  module work leaned on `tsc` for).

`ci` is now: config-check → lint → tsc → test (envelope) → test-app. Verified it
runs green and exits cleanly without an external `CI=true`.

Co-Authored-By: Cervator <cervator@gmail.com>
…ardening

Addresses the CR #4 review (5 of 6 findings; the 6th declined — see the thread).

- CycleCard: render `spec.of` / `spec.happensAt` as clickable `EntityRefLink`(s)
  via `@backstage/plugin-catalog-react`, instead of raw ref strings.
- SagaProcessor test: add a malformed-`skald`-ref case exercising the
  `isParseableRef` failure branch (parses fine for multi-colon strings, so the
  test uses an empty-name ref `user:default/` which parseEntityRef rejects).
- smoke-catalog.sh: guard `cd` (SC2164, `|| exit 1`); add curl
  `--connect-timeout 3 --max-time 5` so a stalled backend can't hang the poll
  loop past its budget; run every check unconditionally with `|| pass=0` instead
  of `&&`-chaining, so one failure no longer hides the remaining assertions.

Declined: adding `smoke-catalog` to the `ci` target — `ci` is the fast inner-loop
gate (and, via the adapter, `ws test`); a ~40s backend boot belongs in a dedicated
CI job, not the quick gate (CodeRabbit offered that alternative too).

Verified: `make ci` green (23 envelope + 17 units incl. the new saga case, tsc,
lint); `make smoke-catalog` PASS (Cycle + Saga ingest with all relations).

Co-Authored-By: Cervator <cervator@gmail.com>
Copilot: the smoke asserted relations by grepping an ordered JSON substring
(`"type":…,"targetRef":…`), which is brittle — a harmless serialization change in
key order would fail the smoke even though the relation is present.

Add a `check_rel` helper that parses the entity JSON with `jq` and asserts
`(.relations // []) | any(.type == $t and .targetRef == $r)` — order-independent.
Relation checks use it; single-field presence checks (kind, annotation, group
type) keep the plain substring grep. Verified: `make smoke-catalog` still PASS.

Co-Authored-By: Cervator <cervator@gmail.com>

@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: 1

🤖 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 `@packages/app/src/modules/cycle/CycleCard.tsx`:
- Around line 31-36: `CycleCard` currently calls `parseEntityRef` directly for
`spec.of` and each entry in `spec.happensAt`, so malformed refs can throw and
break rendering instead of showing `—`. Update the `CycleCard` render path to
safely parse these values with a guard or try/catch helper, and only pass valid
refs into `EntityRefLink` and `EntityRefLinks`; if parsing fails or the value is
invalid, fall back to the existing dash placeholder.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 9f9f9c97-7b18-4db5-b1f6-599487ad08f3

📥 Commits

Reviewing files that changed from the base of the PR and between 82a476f and a763719.

📒 Files selected for processing (4)
  • Makefile
  • packages/app/src/modules/cycle/CycleCard.tsx
  • packages/backend/src/modules/saga/SagaProcessor.test.ts
  • scripts/smoke-catalog.sh

Comment thread packages/app/src/modules/cycle/CycleCard.tsx Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 16 out of 17 changed files in this pull request and generated 3 comments.

Comment thread docs/development/testing.md Outdated
Comment thread scripts/smoke-catalog.sh Outdated
Comment thread scripts/smoke-catalog.sh Outdated
…ke hardening

Round-2 review (all 4 findings valid, all addressed):

- CycleCard (CodeRabbit, Major): `parseEntityRef` throws on a malformed ref, which
  would break the card render. Added a `safeRef` try/catch helper; `spec.of` and
  each `spec.happensAt` entry parse safely and fall back to the `—` placeholder if
  invalid, so only valid refs reach EntityRefLink(s).
- testing.md (Copilot): the `ci`-gate doc now lists `tsc` (folded into `make ci`
  via the cherry-picked Makefile change).
- smoke-catalog.sh (Copilot): `set -e` + a fail-fast prerequisite check
  (corepack/curl/jq), matching smoke-gitea; and `check()` now greps fixed-string
  (`-qF`) so metacharacters like the `.` in `siliconsaga.org/saga-doc` can't
  cause an imprecise match.

Verified: `make ci` green (23 envelope + 17 units, tsc, lint); `make smoke-catalog`
PASS (set -e guards all hold).

Co-Authored-By: Cervator <cervator@gmail.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 16 out of 17 changed files in this pull request and generated 3 comments.

Comment thread scripts/smoke-catalog.sh
Comment on lines +14 to +17
# Fail fast if a prerequisite is missing rather than half-running.
for _cmd in corepack curl jq; do
command -v "$_cmd" >/dev/null 2>&1 || { echo "smoke-catalog: missing prerequisite '$_cmd'" >&2; exit 1; }
done
Comment thread scripts/smoke-catalog.sh
Comment on lines +46 to +51
up=""
for _ in $(seq 1 150); do
if grep -q "Listening on" "$LOG" 2>/dev/null; then up=1; break; fi
if ! kill -0 "$PID" 2>/dev/null; then break; fi
sleep 1
done
Comment thread scripts/smoke-catalog.sh
Comment on lines +61 to +72
# Backend readiness != catalog-ingestion readiness. Poll until the custom entities
# appear (or the timeout expires) rather than sleeping once and querying once.
CYCLE='{}'; SAGA='{}'; GROUP='{}'
for _ in $(seq 1 120); do
CYCLE="$(byname cycle/default/soccer-2026-spring)"
SAGA="$(byname saga/default/saga-soccer-2026-spring)"
GROUP="$(byname group/default/mtl)"
if printf '%s' "$CYCLE" | grep -q 'soccer-2026-spring' \
&& printf '%s' "$SAGA" | grep -q 'saga-soccer-2026-spring' \
&& printf '%s' "$GROUP" | grep -q '"name":"mtl"'; then break; fi
sleep 1
done
@Cervator
Cervator merged commit e21bb22 into main Jul 8, 2026
2 checks passed
@Cervator
Cervator deleted the feat/phase3-leftovers branch July 8, 2026 16:27
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.

3 participants