Skip to content

feat(web): EYT-147 Dispositionswerkbank Slice 1 — die Woche ist die Werkbank - #101

Open
DYAI2025 wants to merge 11 commits into
masterfrom
feat/eyt-147-dispositionswerkbank-slice-1
Open

feat(web): EYT-147 Dispositionswerkbank Slice 1 — die Woche ist die Werkbank#101
DYAI2025 wants to merge 11 commits into
masterfrom
feat/eyt-147-dispositionswerkbank-slice-1

Conversation

@DYAI2025

@DYAI2025 DYAI2025 commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Current status — EYT-158 implemented (06.09.2026)

  • EYT-158: IMPLEMENTED / TECHNICALLY_ACCEPTED
  • Exact PR head: 191b605d3841aba3a47dad41a14a30c7fbb3cdcb
  • Base: master @ f8e96e4ceb4f00ae5f5ac777c6eb47aa8f766d6f
  • Exact-head CI: run 34024585441SUCCESS
  • Verified behavior: worksite-first planning; multiple internal employees in one team; exactly one primary worksite-day card; confirmed server readback; reload and second-browser consistency; keyboard/focus/200%/axe/1440/1920 gates green.
  • Human-PO Visual Gate: PASS
  • Merge status: SERIAL_INTEGRATION_GATE / READY_FOR_MERGE_PENDING_ORCHESTRATOR_FINALIZATION

Product truth

EasyTree plans Arboscus worksites and deployments, not employees as primary calendar objects.

Auftraggeber → Baustelle → Einsatz → Baustellentage → Einsatzanforderungen and allocated resources

EYT-158 proves the functional vertical for a future WorksiteDay: create worksite-first, assign multiple internal employees as one team, persist through the real API/PostgreSQL path, and render exactly one primary WorksiteDay card from confirmed server state.

Accepted implementation evidence

  • EYT-152 server-side write prerequisite remains accepted.
  • EYT-158 exact implementation commit: 191b605d3841aba3a47dad41a14a30c7fbb3cdcb.
  • Exact-head CI run 34024585441 completed successfully.
  • Auth journey, read-through, DB gates, unit tests, build, lint, typecheck, format, web smoke and secret scan are green on the exact head.
  • Human-PO Visual Gate passed.

Serial integration state

  • EYT-158 / CODEX = technically accepted integration candidate.
  • EYT-160 / CLAUDE_CODE remains frozen on 7a00a96d187ac0f68dd0d6026fb6d1ea8fb27d73 until the EYT-158 integration decision is completed.
  • Parallel merge remains forbidden; integration is serial and orchestrator-gated.

Carry-over risks

These are pre-existing follow-up items and are not blockers for the EYT-158 implementation candidate unless new evidence shows regression:

  1. follow-up-draft publish semantics vs. assignments_no_published_overlap;
  2. canonical mixed-command lock ordering between planWorksiteDay and createAssignment.

Current verdict

EYT-158 TECHNICALLY_ACCEPTED — SERIAL_INTEGRATION_GATE — EXACT_HEAD_CI_GREEN — HUMAN_PO_VISUAL_PASS

No deployment is authorized by this status update. Jira Done is not implied by commit, CI or merge alone.

BenPerro and others added 4 commits August 31, 2026 02:05
…e ihrer Woche legen

Reine Zuordnungsfunktion über die kanonischen Domain-Helfer
(planningWeekDateRange, dayAfter, localBusinessDate): der Kalendertag eines
Einsatzes ist der Tag seines Beginns in der Organisationszone, eine
Nachtschicht bleibt am Tag ihres Beginns. Nichts verschwindet: Einsätze
ausserhalb der Woche wandern sichtbar nach ausserhalb, unbekannte Zone oder
unlesbarer Wochenschlüssel ergeben unbestimmbar mit Grund statt eines leeren
Rasters. Drei Gegenmutationen ausgeführt (UTC-Datumszuordnung,
ausserhalb-Verschlucken, Id-only-Sortierung) — jede macht genau ihren Test
rot; Fixtures widersprechen dem Id-Tiebreak absichtlich.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Die Planungsansicht zeigt die Woche als räumliche Tagesachse Mo–So;
Einsätze stehen als kompakte Karten (Zeit, Baustelle, Person) am Kalendertag
ihres Beginns, der Planstand trägt zusätzlich Form (gestrichelt/Kante) statt
nur Farbe. Das unveränderte Einsatzformular wandert in einen nichtmodalen
seitlichen Inspector hinter „Einsatz anlegen“: anfangs geschlossen, Fokus
beim Öffnen im ersten Feld, Escape und Schließen stellen den Fokus auf den
Auslöser zurück, nach Erfolg bleibt er offen (Erfolgsmeldung überlebt den
Read-through). Genau eine primäre Aktion je Zustand: mit
veröffentlichbarem Entwurf ist es „Plan veröffentlichen“, sonst „Einsatz
anlegen“. Die Standmarke der Publish-Aktion entfällt auf versionslosen
Wochen — es gibt dort keinen Stand zu benennen. Alle Serverwahrheits-,
Testid- und data-Anker bleiben erhalten; CSS nur über die Basisdesign-Tokens,
die Planungsfläche bekommt über :has() die Breite, die eine Wochenachse
braucht, ohne die vermessene Startseiten-Geometrie zu bewegen. Zwei
Gegenmutationen ausgeführt (Inspector anfangs offen; Auslöser unbedingt
primär) — beide rot an den benannten Tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
read-through: wocheOeffnen wartet auf Auslöser+Liste statt auf das nicht
mehr dauerhaft gerenderte Formular; inspectorOeffnen (idempotent) vor jedem
Formularzugriff, auch in den Responsive-/A11y-Fällen 1440/375. auth-journey:
neuer Schritt 9c1b legt in der eigenen Woche 2026-W34 (W32/W33/W35–W37
tragen abgenommene Zahlen bzw. Angriffe) einen Einsatz über den Inspector an
— echte GoTrue-Identität, 201 vom realen Command, serverbestätigte Karte am
Dienstag, Reload mit derselben Id, Woche wird Entwurf; danach zurück in die
Publish-Woche, sonst veröffentlichte 9d den falschen Entwurf (im ersten Lauf
gemessen). Staging-Journey öffnet den Inspector im Anlege-Helfer und misst
die Tastaturöffnung (Enter auf dem Auslöser → Fokus im ersten Feld); dieser
Spec ist aktualisiert, aber mangels Staging-Deploys dieses Heads nicht
ausgeführt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Slices

Versionierte Parity-Matrix am Baseline-Head f8e96e4: jede Vertragsoperation
mit realer UI-Route oder begründetem Nicht-UI-Systempfad; Edit/Löschen/
Drag&Drop/Karten-Konflikte als CAPABILITY_GAP benannt statt erfunden.
Evidenz-README mit Befehlen, gemessenen Zahlen, fünf ausgeführten
Gegenmutationen und den Screenshots aus dem grünen lokalen
auth-journey-Lauf (1440/1920, Entwurf, Inspector, serverbestätigte Karte,
veröffentlicht, zweiter Kontext).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@sourcery-ai sourcery-ai 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.

Sorry @DYAI2025, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 3 days and 7 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Reviewer's Guide

Der PR verwandelt /planung in eine responsive Wochenarbeitsfläche: Einsätze werden über kanonische Zeitzonen- und Kalenderlogik auf sieben Tage verteilt, über einen fokussierten nichtmodalen Inspector angelegt und weiterhin über unveränderte Server-Commands bestätigt und veröffentlicht; umfangreiche Unit-, E2E- und Evidenzanpassungen sichern Serverwahrheit, Accessibility und bewusst ausgelassene Capability-Gaps ab.

Sequence diagram for creating and publishing a planning assignment

sequenceDiagram
    actor Disponentin
    participant Planung as Planung
    participant Inspector as AssignmentForm
    participant Gateway as PlanningGateway
    participant Server as PlanningAPI

    Disponentin->>Planung: click werkbank-einsatz-anlegen
    Planung->>Inspector: open and focus first field
    Disponentin->>Inspector: fill assignment fields
    Disponentin->>Inspector: click einsatz-speichern
    Inspector->>Gateway: createAssignment
    Gateway->>Server: POST /planung/einsaetze
    Server-->>Gateway: 201 assignment id
    Gateway-->>Planung: server response
    Planung->>Gateway: getPlanningWindow
    Gateway->>Server: GET /planung/fenster
    Server-->>Gateway: assignment and draft version
    Gateway-->>Planung: updated planning window
    Disponentin->>Planung: click planung-veroeffentlichen
    Planung->>Gateway: publishPlan
    Gateway->>Server: POST /planung/versionen
    Server-->>Gateway: published version id
    Gateway-->>Planung: publish result
Loading

State diagram for planning version status and primary action

stateDiagram-v2
    [*] --> KeineVersion
    KeineVersion --> Entwurf: createAssignment / Read-through
    Entwurf --> Veröffentlicht: publishPlan
    Veröffentlicht --> Veröffentlicht: reload / getPlanningWindow

    state KeineVersion {
        [*] --> EinsatzAnlegenPrimaer
    }
    state Entwurf {
        [*] --> VeröffentlichenPrimaer
    }
    state Veröffentlicht {
        [*] --> EinsatzAnlegenPrimaer
    }
Loading

Flow diagram for rendering the weekly planning workbench

flowchart TD
    A[Planning window from server] --> B[wochenraster]
    B --> C{Week key and time zone valid?}
    C -- No --> D[Show warning and flat assignment list]
    C -- Yes --> E[planningWeekDateRange]
    E --> F[localBusinessDate for assignment start]
    F --> G{Start belongs to one of seven days?}
    G -- Yes --> H[Render assignment card in matching day column]
    G -- No --> I[Render in Ausserhalb dieser Woche]
    H --> J[Show time, worksite, and employee]
    I --> J
Loading

File-Level Changes

Change Details Files
Die Planungsansicht wird von einer flachen Einsatzliste zu einer responsiven Dispositionswerkbank mit Wochenraster, Planstandsanzeige und zustandsabhängiger Primäraktion umgebaut.
  • Breite und Toolbar-Anordnung auf der Planungsfläche angepasst, ohne andere Shell-Flächen zu verändern.
  • Sieben Tagesspalten mit Einsatzkarten für Uhrzeit, Baustelle und Person eingeführt.
  • Entwurfs- und Veröffentlichungszustände über Text, Statusbadge und Kartenform dargestellt.
  • Einsätze außerhalb der Woche sichtbar in einem separaten Bereich ausgegeben.
  • Versionslose Wochen von der irreführenden Entwurfsmarke befreit.
apps/web/app/globals.css
apps/web/components/planning-publish-action.tsx
apps/web/components/planning-window-view.tsx
Die Tageszuordnung und Zeitdarstellung werden in einer dedizierten, domainbasierten Rasterlogik gekapselt.
  • Wochenschlüssel und Zeitzone validiert und bei Fehlern auf eine ehrliche flache Liste zurückgefallen.
  • Beginn eines Einsatzes anhand der Organisationszeitzone dem passenden Kalendertag zugeordnet.
  • Nachtschichten, Jahreswechsel, DST-Fälle, Sortierung und Ausnahmen berücksichtigt.
  • Wanduhrzeiten explizit in der Organisationszeitzone formatiert.
apps/web/lib/wochenraster.ts
apps/web/test/wochenraster.test.ts
Das Anlegen eines Einsatzes wird in einen nichtmodalen Inspector mit definiertem Fokus- und Aktionsverhalten verlagert.
  • Formular initial aus dem DOM entfernt und über „Einsatz anlegen“ geöffnet.
  • Fokus beim Öffnen ins erste Formularfeld gesetzt.
  • Escape und Schließen-Schaltfläche schließen den Inspector und stellen den Fokus auf den Auslöser zurück.
  • Primäraktion abhängig von Veröffentlichungsrecht und Planstand auf genau eine Schaltfläche begrenzt.
apps/web/components/planning-window-view.tsx
apps/web/test/dispositionswerkbank.test.tsx
apps/web/test/planning-window-view.test.tsx
Die bestehenden Browser- und Journey-Tests werden auf den Inspector und die reale Wochenreise aktualisiert und um Server-Read-through-Nachweise ergänzt.
  • E2E-Helfer öffnen den Inspector idempotent vor Formularinteraktionen.
  • Reale Anlage, Read-through, Reload, Entwurfsstatus und Folge-Publish in die Auth-Journey aufgenommen.
  • Tastaturfokus, responsive Darstellung und bestehende Serverwahrheitsprüfungen angepasst.
  • Erhöhtes Testtimeout für die belastete Serverwahrheits-Suite dokumentiert.
apps/web/e2e/auth-journey/journey.pwtest.ts
apps/web/e2e/read-through.spec.ts
apps/web/e2e/staging/journey.pwtest.ts
apps/web/test/werkbank-serverwahrheit.test.tsx
Die Slice-Evidenz und Capability-Grenzen werden dokumentiert, ohne API-, Datenbank- oder Dependency-Änderungen einzuführen.
  • Lokale Format-, Lint-, Typ-, Build-, Unit-, Smoke-, Read-through- und Auth-Ergebnisse festgehalten.
  • Bewusste Nicht-Implementierungen wie Bearbeiten, Löschen, Drag-and-Drop und Kartenkonflikte abgegrenzt.
  • Browser-, Accessibility- und Gegenmutations-Evidenz ergänzt.
docs/evidence/2026-08-31-eyt-147-slice-1/README.md
docs/evidence/2026-08-31-eyt-147-slice-1/ui-parity-matrix.md
apps/web/test/planning-publish-action.test.tsx

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

…r Maschine

PO-Review-Reparatur des ersten Werkbank-Slices, vier Findings:

- R1: keine rohe Planversions-UUID und kein roher ISO-Zeitstempel mehr im
  sichtbaren Text; die echten Server-Ids bleiben unveraendert in den
  data-*-Seams, der Publish-Instant neu in data-published-at-utc.
- R2: genau EIN sichtbares StatusBadge fuer den Planstand (Wochenansicht);
  planung-stand-marke bleibt als unsichtbarer Seam mit Testanker,
  Screenreader-Text und data-stand erhalten.
- R3: das Einsatzformular im Inspector traegt die Basisdesign-v2-Tokens
  (Feldgruppen, Beginn/Ende nebeneinander, Meldungs-Toene); Semantik,
  Testanker, Validierung und Zeitzonenlogik unveraendert.
- R4: sichtbare Texte auf korrektes Deutsch (Veroeffentlicht -> Veröffentlicht,
  Ausserhalb -> Außerhalb, fuer -> für); technische Werte unveraendert.

Neuer Guard werkbank-oberflaechenguards.test.tsx (UUID-/Instant-Leck,
Seam-Erhalt, Badge-Zaehlung); beide Gegenmutationen ausgefuehrt, rot
gemessen, byte-identisch zurueckgenommen. Browser-Evidenz aus frischem
gruenem auth-journey-Lauf regeneriert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sourcery-ai[bot]
sourcery-ai Bot previously approved these changes Aug 31, 2026

@sourcery-ai sourcery-ai 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.

Sourcery assessment

Approved.

@DYAI2025 DYAI2025 changed the title feat(web): EYT-147 Dispositionswerkbank Slice 1 — die Woche ist das Produkt feat(web): EYT-147 Dispositionswerkbank Slice 1 — die Woche ist die Werkbank Aug 31, 2026
Migration 0019 legt das Daten- und Sicherheitsfundament der
baustellenzentrierten Planung an (EYT-125 Architektur, EYT-147 Slice M1):

- public.worksite_days als stabile, versionsuebergreifende Tagesidentitaet
  (I-4 unique auf org_id, worksite_id, local_date; keine Zeiten, kein
  eigener Publish-Marker)
- public.worksite_day_configurations als revisionsgebundener Tagesstand
  (I-3 unique auf plan_version_id, worksite_day_id)
- assignments.worksite_day_configuration_id additiv und nullable, mit
  tenantgebundenem FK und I-1-Zugehoerigkeitstrigger. Kein Backfill.
- idempotency_records.result_payload mit Spalten-Lesegrenze; die einzige
  Lesestelle ist app.read_idempotency_result
- app.remove_assignment_from_worksite_day, app.read_idempotency_result und
  app.lock_week_draft

plan_versions.published_at bleibt die alleinige Publish-Wahrheit. Auf
assignments entsteht keine zweite Schreibpolicy, und update/delete bleiben
entzogen; der INSERT-Grant waechst um genau eine Spalte.

supabase/tests/0014_worksite_days.sql fuehrt 80 Zusicherungen, rot vor der
Migration gemessen. 0005_schema_meta_gate.sql bekommt die zwei neuen
Tabellen und eine auf idempotency_records eingegrenzte Ausnahme, weil 0019
dort das Tabellen-select entzieht.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014DZFb9AFuQTGm12SuneDCA
BenPerro and others added 4 commits September 3, 2026 11:53
Additive transport boundary for the worksite-centred planning of EYT-147,
milestone M2 of Confluence 41484289 — contracts only, no server logic.

- WorksiteDayDto: stable worksiteDayId and revision-bound configurationId as
  two required fields, lockVersion, localDate (LocalDateSchema, calendar-checked),
  team with assignmentIds; team may be empty in the RESPONSE only.
- planWorksiteDay (POST /planung/baustellentage, 201) and updateWorksiteDayTeam
  (POST /planung/baustellentage/team, 200): strict commands, team.min(1),
  duplicate/overlap rules per employee, expectedLockVersion against the day
  IDENTITY (migration 0019 R-20: one stale truth per day), Idempotency-Key.
- PlanningWindow.worksiteDays[] optional (additive: today's server omits it),
  cross-checked against assignments and resources.worksites.
- WORKSITE_DAY_PROBLEM_TYPE vocabulary, published in the 409 descriptions.
- openapi/v1.json regenerated from the same Zod source (39 schemas, 21 ops).
- Both routes listed in NOT_YET_IMPLEMENTED (contract-only until M3/M4); the
  stale assertion turns red in the run that implements them.

Not in this commit: application services, DB mutations, publish/copy path, UI.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014DZFb9AFuQTGm12SuneDCA
Behebt die drei M2-Contract-Findings des PO-Reviews (Jira EYT-151,
Kommentar 15164). Weiterhin contracts-only: keine Migration, keine
Application-/DB-Logik, kein UI, keine neue Abhaengigkeit.

Important 1 — Baustellen-Uebereinstimmung fehlte:
`PlanningWindowSchema` verglich Teammitglied und referenzierte Zuweisung auf
Person und Intervall, aber nicht auf die Baustelle. Sind BEIDE Baustellen in
`resources.worksites` bekannt, passierte ein widerspruechlicher Payload die
Runtime-Validation: die Tageskarte zeigte die Person auf Baustelle A, die
Einsatzliste auf Baustelle B, und beide Ansichten sahen fuer sich richtig aus.
Die bestehende Pruefung fragt nur, ob die Baustelle BEKANNT ist, nicht ob es
DIESELBE ist.

Important 2 — Primaerprojektion nicht gegen Dubletten geschuetzt:
`worksiteDays[]` sicherte die Einmaligkeit der Assignments, nicht die der
Tageszeilen. Jetzt erscheinen `worksiteDayId` und `configurationId` je Fenster
hoechstens einmal — beide Achsen einzeln geprueft, nicht als Paar: ein Paar
waere schon dann eindeutig, wenn derselbe Tag zweimal mit verschiedenen
Revisionen stuende, und genau das ist die zweite Stale-Wahrheit je Tag, die
Migration 0019 R-20 ausschliesst.

Minor — unerreichbarer 409:
`WORKSITE_DAY_TEAM_REQUIRED` wurde als 409 beider Routen veroeffentlicht,
obwohl `WorksiteDayTeamCommandSchema.min(1)` das leere Team an der
REQUEST-Grenze ablehnt und der Planungscontroller jeden fehlgeschlagenen
`safeParse` ausnahmslos mit 400 beantwortet — nach erfolgreicher
Schemapruefung kann der Fall nicht mehr entstehen. Der 409-Zweig faellt weg,
die Konstante bleibt fuer die 400-Grenze in M3/M4 benannt. `team.minItems: 1`
bleibt nachweislich im Dokument; ein neuer Fall misst, dass die
TEAM_REQUIRED-Semantik dort NICHT mehr behauptet wird.

Tests zuerst: die drei negativen Faelle waren vor dem Fix rot (Zuweisung auf
anderer Baustelle; doppelte worksiteDayId; doppelte configurationId), je mit
positiver Gegenprobe, damit kein Fall aus einem anderen Grund gruen ist.
`openapi/v1.json` aus derselben Zod-Quelle neu erzeugt (39 Schemata, 21
Operationen unveraendert).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014DZFb9AFuQTGm12SuneDCA
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.

2 participants