Planning Proposal Engine & Capacity Reserve Calculations #25
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implement the planning proposal engine (
POST /v1/plansandlife plan --period today|week), calculating working window occupancy, enforcing the 40% unscheduled capacity reserve, applying personal policy constraints (max 3 intended outcomes per day, 1 active discretionary project), compiling ordered atomic proposal mutation steps, calculating canonical SHA-256 proposal digests, and storing proposals in SQLite without performing any writes to the Radicale CalDAV server.Background & Technical Rationale
Calendar management systems frequently suffer from over-allocation: users schedule every available minute, leaving zero buffer for unexpected interruptions, overrun meetings, or cognitive fatigue. Furthermore, automated scheduling engines often make destructive or unexpected changes directly to remote calendar stores without human oversight.
Life resolves these challenges by introducing a two-stage planning model rooted in strict mathematical reserves and human-in-the-loop review:
complete: false), the engine refuses confident free-time allocation, surfacesincomplete_calendarwarnings, and marks remaining capacity as unknown.proposalsartifact with an unforgeable cryptographic digest (SHA-256). Under no circumstances does proposal generation mutate Radicale calendar components (VEVENT) or task components (VTODO). Remote mutations occur only when the user explicitly reviews and executes the proposal via a separate approval workflow.Exact Technical References & Specifications
1. Workflows Specification (
docs/technical/workflows.md)Section:
## Planning and interruption(lines 24–26):Section:
## Personal policy defaults(lines 42–50):2. Domain Entities Specification (
docs/technical/domain-model.md)Section:
## Entities(lines 7–18):3. Calendar Semantics & Event Transparency (
docs/technical/calendar.md)Section:
## Query and time semantics(lines 24–27):4. CLI and API Route & Payloads (
docs/technical/cli-api.md)Section:
## Command-to-route table(line 42):Section:
## Command payloads and results(lines 89, 104):Section:
## Error identifiers(lines 110–127):5. Database Schema (
docs/technical/timeline-consistency.md)Section:
## Illustrative schema(lines 63–75):6. Verification Scenario W06 (
docs/technical/verification.md)Section:
## Workflow scenarios(line 20):What to build
1. Working Window & Capacity Calculator (
src/domain/policy/capacity.rs)WorkingWindowresolution per weekday from configuration (e.g., Monday 09:00–17:00 in configured IANA timezone).VEVENToccurrences intersecting the planning window from Radicale.STATUS: CANCELLED-> ignores event (0 minutes consumed).TRANSP: TRANSPARENT-> ignores event for busy capacity (0 minutes consumed).TRANSP: OPAQUE(or missing transparency default) -> consumes interval between start and end. IfSTATUS: TENTATIVE, treat conservatively as busy.complete: false, set allocatable capacity to 0, emitincomplete_calendarwarning, and do not attempt automatic free-time allocation.2. Planning Policy Validator (
src/domain/policy/planning.rs)> 3, reject proposal generation unless an explicitpolicy_exceptionsentry with codeexceed_daily_outcomes_capis supplied in the request (reason is optional and recorded if supplied, perdocs/technical/workflows.md:50).policy_exceptionswith codemultiple_active_projects.estimated_minutes(X-LIFE-ESTIMATED-MINUTES), emitunknown_estimatewarning. Do not fabricate an estimate. Such tasks may either remain unallocated or be allocated an explicit default block only when permitted by caller policy overrides.docs/technical/workflows.md:52).3. Step Builder & Canonical Digest Generator (
src/domain/proposal.rs)step_id: Stable alphanumeric identifier within the proposal (step_1,step_2, ...).action:create_event(for scheduled work blocks) orupdate_task(to setplanned_startor status).item_id: For updates, the existing opaque item ID; for creates, a newly generated UUID prefixed withevt_.collection_id: The target calendar or task collection.baseline_etag: The live ETag retrieved during pre-planning read (must be null forcreate_event).payload: Normalized JSON representing the component properties to create or patch.reason: Explanation string (e.g., "Schedule 90m focus block for Task XYZ within allocatable window").schema_version, sorted/orderedsteps,policy_exceptions, andbaseline_etags.digest = "sha256:" + hex(sha256(canonical_bytes)).expires_at = created_at + 24 hours(default TTL).4. SQLite Proposal Repository (
src/storage/proposal_repo.rs)proposalstable:proposal_id: Generated ID (prop_...).schema_version:1.state:'pending'.digest: Computed SHA-256 digest string.created_at: Current UTC ISO-8601 timestamp.expires_at: ISO-8601 timestamp 24 hours in the future.steps_json: Serialized JSON array of steps.policy_json: Serialized JSON of applied policy rules, capacity calculations, and exceptions.operation_id: Null until application attempt.approval_json: Null.5. Axum Handler & CLI Subcommand (
src/api/plans.rs,src/cli/plan.rs)POST /v1/plans:life plan --period today|week [--input -] [--json]Acceptance Criteria
life plan --period todayreads live events and computes Gross Window, subtracts opaque busy events, and reserves exactly 40% of the remaining capacity as unscheduled buffer time (verifying Scenario W06).TRANSP:TRANSPARENT) and cancelled events (STATUS:CANCELLED) are verified not to consume busy capacity.complete: false) returnsincomplete_calendarwarning and refuses confident free-time allocation.proposalswithstate: "pending", a valid SHA-256 digest, 24-hour expiration, and performs ZERO writes to Radicale.proposal_idanddigest.docs/technical/workflows.md:50).Notes
ceil(remaining × unscheduled_fraction)where remaining = gross − busy; the test explicitly assertsreserved != 192(i.e. not 40% of gross).live_task_inventoryis now shared with the#24next command; the CLI unimplemented-command fixture moved fromplantoreplan.Blocked by
Issue #025: Planning Proposal Engine & Capacity Reserve Calculationsto Planning Proposal Engine & Capacity Reserve Calculations