Sfoglia il codice sorgente

HANDOFF.md: mark Phase 12 shipped

Maintenance rule (§14). Moves Phase 12 from planned → shipped with its
SHA (a634582), refreshes §3 for the new migrations/002 and tests/Domain,
tests/Db directories, tightens §4/§5 value constraints (max_working_days
narrowed from {0, 0.5, …, 5} to {0, 1, 2, 3, 4, 5} and active_days_mask
added), updates §6 to describe the new PATCH /sprints/{id}/week/{week_id}
body, bumps the §11 test-count smoke ("OK (88 tests, 208 assertions)")
and §13 git history, and resets the §12 resume prompt to "12 phases
shipped, no scheduled work."

No code changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
achiappa 2 settimane fa
parent
commit
59eb1d7f31
1 ha cambiato i file con 28 aggiunte e 6 eliminazioni
  1. 28 6
      HANDOFF.md

+ 28 - 6
HANDOFF.md

@@ -72,27 +72,38 @@ per-cell audit trail.
 │   │                    SprintWorkerDayRepository, TaskRepository,
 │   │                    TaskAssignmentRepository, AuditRepository
 │   └── Services/        AuditLogger, CapacityCalculator
-├── migrations/          001_init.sql  (full schema per spec §3)
+├── migrations/          001_init.sql (full schema per spec §3)
+│                        002_sprint_week_active_days.sql (Phase 12 — mask column)
 ├── views/               layout.php, home.php, auth/local.php,
 │                        workers/index.php, users/index.php,
 │                        sprints/{new,show,settings}.php,
 │                        audit/index.php
 ├── tests/               TestCase + Services/ + Repositories/ + Controllers/ + Cascade/
+│                                 + Domain/ + Db/
 └── data/                SQLite + sessions directory (volume-mounted, gitignored)
 ```
 
-## 4. Schema (migrations/001_init.sql)
+## 4. Schema (migrations/001_init.sql + 002_sprint_week_active_days.sql)
 
 Tables (already applied): `users`, `workers`, `sprints`, `sprint_weeks`,
 `sprint_workers`, `sprint_worker_days`, `tasks`, `task_assignments`,
 `audit_log`, plus the `schema_version` tracking table.
 
+`sprint_weeks.active_days_mask INTEGER NOT NULL DEFAULT 31` (Phase 12) is
+a 5-bit mask — bit0=Mo, bit1=Di, bit2=Mi, bit3=Do, bit4=Fr — and is the
+source of truth for "is this a workday this week." `max_working_days`
+lives on as a cached `popcount(mask)` projection, so the two columns
+are always in sync.
+
 Indexes: `idx_audit_occurred_at`, `idx_audit_entity`, `idx_tasks_sprint`,
 `idx_sw_sprint`.
 
 Value constraints enforced in PHP (not SQL):
 - All `days` fields: non-negative multiple of 0.5.
-- `max_working_days`, `sprint_worker_days.days` ∈ {0, 0.5, …, 5}.
+- `sprint_weeks.max_working_days` ∈ {0, 1, 2, 3, 4, 5} — derived from the
+  weekday mask, so half-days are gone at the week level (Phase 12).
+- `sprint_weeks.active_days_mask` ∈ 0..31 (bits Mo..Fr).
+- `sprint_worker_days.days` ∈ {0, 0.5, …, 5}.
 - `task_assignments.days` ≥ 0, no hard upper bound.
 - `reserve_fraction`, `rtb` ∈ [0, 1].
 
@@ -157,7 +168,7 @@ JSON (admin-only, CSRF via `X-CSRF-Token` header; envelope per spec §7):
 | POST   | `/sprints/{id}/workers/reorder`              | reorder sprint workers |
 | PATCH  | `/sprints/{id}/workers/{sw_id}`              | set rtb |
 | PATCH  | `/sprints/{id}/week-cells`                   | batch day cells |
-| PATCH  | `/sprints/{id}/week/{week_id}`               | set max_working_days |
+| PATCH  | `/sprints/{id}/week/{week_id}`               | set active_days_mask or active_days (derives max_working_days) |
 | POST   | `/sprints/{id}/tasks`                        | create task |
 | POST   | `/sprints/{id}/tasks/reorder`                | reorder tasks |
 | PATCH  | `/tasks/{id}`                                | title/owner/priority |
@@ -247,6 +258,15 @@ with a `BOOTSTRAP_ADMIN` audit row.
       a Node css-builder Docker stage; inline onclick replaced by
       `data-href` + `app.js`; CSP dropped `'unsafe-inline'` and the
       Tailwind CDN host. Strict CSP now in effect.
+- [x] **Phase 12 — Per-week weekday selection (Mo–Fr) drives Arbeitstage**
+      (`a634582`): `sprint_weeks.active_days_mask` is the new source of
+      truth; `max_working_days` is a cached `popcount(mask)` projection.
+      Sprint Settings exposes five checkboxes (Mo Di Mi Do Fr) per week;
+      the sprint view's Arbeitstage header reads the derived count
+      read-only. `PATCH /sprints/{id}/week/{week_id}` now accepts
+      `active_days_mask` or `active_days`; `max_working_days` in the body
+      is rejected. Migration 002 backfills legacy rows (half-days round
+      up, clamped to 0..5). +14 tests, 88 total (was 74).
 
 ### Upcoming
 
@@ -300,7 +320,7 @@ for f in $(git ls-files '*.php'); do php -l "$f" | tail -1 | sed "s|^|$f: |"; do
 Run the test suite:
 ```bash
 vendor/bin/phpunit
-# → OK (74 tests, 138 assertions)
+# → OK (88 tests, 208 assertions)
 ```
 
 ## 12. How to resume in a fresh Claude session
@@ -308,7 +328,7 @@ vendor/bin/phpunit
 Tell Claude:
 
 > Working on `/Users/achiappa/Development/claude_code_private/sprint_planer_web`.
-> Read `HANDOFF.md`, the git log, and `ACCEPTANCE.md`. All 11 phases are
+> Read `HANDOFF.md`, the git log, and `ACCEPTANCE.md`. All 12 phases are
 > shipped (see §9). There is no scheduled coding work. The only
 > outstanding items are in §10 (mostly a manual acceptance walkthrough
 > in the running container). If I ask for new work, follow the
@@ -321,6 +341,8 @@ before acting — nothing here is load-bearing once it grows stale.
 ## 13. Git history (as of this handoff)
 
 ```
+a634582 Phase 12: per-week weekday selection (Mo–Fr) drives Arbeitstage
+a1a1266 HANDOFF.md: mark Phases 8–11 shipped + codify the maintenance rule
 ab9430b Phase 11: vendor Tailwind + drop inline onclick + tighten CSP
 c35a934 Phase 10: multi-select owner filter + column visibility toggle
 f7f5db5 Phase 9: users management page (promote / demote admin)