Commit Graph

3 Commits

Author SHA1 Message Date
SellPL c723efb186 feat(core): add workspace skeleton and the pure decision engine
Establishes the cargo workspace and the shared `blocker-core` crate. The
engine is deliberately written before any platform code, because CLAUDE.md
section 2 makes it the single source of decision truth and M1 acceptance
requires it to be pure.

**Workspace** — five crates plus a test crate, zero external dependencies.
Section 3 requires every crate to justify its binary-size cost, so M0 adds
none. [profile.release] is workspace-only (cargo rejects it in members) and
carries the section 5 settings that make the 5 MB stripped budget reachable.

**Purity contract** — `evaluate(&EngineInput) -> Decision` reads no clock, no
disk and no OS API; everything arrives in the input. `tests/purity.rs`
enforces this mechanically by asserting blocker-core has zero dependencies, so
a stray I/O reach-in fails the build rather than silently making the golden
tables useless as a parity contract.

Decisions worth calling out:

- **Monotonic time is a separate type from wall time.** Section 1.5.3 requires
  a system date change never to shorten a lock. Keeping them apart makes that
  structural rather than a rule to remember.
- **`start > end` means overnight.** No `crosses_midnight` flag: the comparison
  already encodes it and a second field is a second way to be wrong. The
  weekday for a window that started yesterday evening is yesterday's, which
  `overnight_window_survives_past_midnight` pins down.
- **`next_wakeup` is armed over every non-paused schedule, not only active
  ones.** Filtering to active conditions first would let the daemon sleep
  straight through the moment a schedule is due to start.
- **Allowlist needs the installed-app inventory.** `EngineInput` carries
  `installed_apps`; an empty slice fails open rather than guessing.
- **Wall-clock correction extends, never shortens, and clamps to the 24h cap.**
  Extending unbounded would satisfy anti-tamper and violate section 1.5.4.
- **`cast_possible_truncation` is denied workspace-wide.** Truncating a
  millisecond counter would corrupt a lock timer.

Verified: 22 tests pass, `cargo fmt --check` clean, `cargo clippy -D warnings`
clean, stripped release daemon 0.279 MB against the 5 MB budget.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-02 13:10:25 +00:00
SellPL aa1c582f3c chore: add repo hygiene config and project spec
Bootstrap the repository with the shared configuration every other piece
depends on:

- .gitignore: strict. Keeps build output, cargo caches, Android keystores,
  signing keys, .env files, local SQLite databases, IDE state and any
  credential-shaped filename out of history. CLAUDE.md 10.1 requires these
  never enter the repo.
- .editorconfig, rustfmt.toml, clippy.toml: formatting and lint policy.
  clippy.toml is written in the lints-file form so lints are not duplicated
  into every crate manifest.

CLAUDE.md is committed verbatim; it is the project spec and the parity
contract for every platform layer.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-02 13:10:25 +00:00
SellPL 81d5122e4b chore: initial empty commit
Establishes the main branch so feature branches have a base to merge
into. The repository was created empty, so main did not exist and no pull
request could target it.

This commit is deliberately empty. Nothing lands on main without review
(CLAUDE.md 10.2); it exists only so that m0/bootstrap has somewhere to be
merged from.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-01 16:16:51 +03:00