Autonomy for ordinary life.
A local-first, vendor-independent runtime for turning human goals into policy-checked actions and verified real-world outcomes.
Launch Handsoff · 90-second judge path · Architecture · Run locally
Important
Handsoff has completed Milestone 4: the hackathon application. The repository contains the deterministic simulation core, six reference scenarios, append-only evidence, contained Gemini planning with offline fallback, bounded read-only Supermemory context, an interactive whole-home Streamlit surface, and a one-click judge comparison. This repository does not control real devices.
- Open the live Streamlit application.
- Select Whole-home evening arrival and Gemini + Supermemory context.
- Click Run judge comparison once.
- Watch one goal coordinate eight bounded household effects, then inspect the comparison, policy decision, execution trace, independent verification, ledger, and memory boundary.
The comparison runs two fresh and isolated traces. The deterministic reference establishes the control; the contextual trace shows exactly what Gemini and bounded Supermemory context changed. Provider failure remains visible and falls back safely. Neither provider can declare capabilities, authorize execution, alter trusted observations, or manufacture verification.
| Human goal | Untrusted intelligence | Deterministic authority | Observed evidence |
|---|---|---|---|
| Declare the outcome and acceptance conditions | Gemini may propose; Supermemory may supply bounded context | Typed policy alone may allow or deny each capability | Fresh post-action observations determine whether the goal actually succeeded |
Most consumer automation begins with commands:
If this event occurs, send this instruction to that device.
Handsoff begins with an outcome:
Prepare my environment for arrival in five minutes.
The system is designed to compile that objective into an inspectable typed plan, evaluate every proposed action with deterministic policy, execute only allowlisted capabilities, and verify the resulting world state from fresh telemetry. A successful API response is not treated as proof that a physical effect occurred.
The model can propose a plan. It can never grant itself authority to act.
The application presents that control plane as one home rather than a list of disconnected apps. A single simulated arrival goal coordinates the driveway signal, garage, EV charger, climate, welcome lighting, ceiling fan, television, ice maker, and guarded coffee preparation. Every active device is backed by the same typed policy, transition, observation, and verification evidence shown below the house.
| Conventional automation | Handsoff target architecture |
|---|---|
| Device commands and trigger chains | Goals with explicit acceptance conditions |
| Vendor-specific orchestration | Typed, replaceable capability adapters |
| API success treated as completion | Independent telemetry-based outcome verification |
| Implicit or scattered authority | Deterministic, versioned policy decisions |
| Best-effort handling of stale state | Timestamp, freshness, confidence, and contradiction checks |
| Partial failure hidden behind a success path | Explicit partial-success, failure, timeout, and compensation states |
| Cloud provider as the control plane | Local policy, execution state, and operational ledger |
Handsoff is not intended to replace Matter, Home Assistant, device firmware, or vendor APIs. It is a user-owned coordination and verification layer above bounded integrations.
- 90-second judge path
- The idea
- Why this architecture exists
- System model
- Safety invariants
- Canonical demonstration
- Judge comparison
- Current implementation status
- Autonomy modes
- Repository structure
- Getting started
- Validation
- Dependency strategy
- Streamlit and Supermemory path
- Roadmap
- Engineering documentation
- Security and privacy
- Engineering standard
- License and naming
Handsoff uses a modular monolith with hexagonal boundaries. Domain logic remains independent of web frameworks, databases, model SDKs, device providers, and user-interface code. External systems attach through explicit ports and constrained adapters.
flowchart LR
GOAL["Human objective"] --> GC["Goal compiler"]
STATE["Timestamped world state"] --> GC
CAPS["Capability registry"] --> GC
MODEL["Optional model planner"] -. "typed proposal only" .-> GC
MEMORY["Optional preference memory"] -. "context only" .-> GC
GC --> PLAN["Untrusted plan proposal"]
PLAN --> SCHEMA["Strict schema validation"]
SCHEMA --> POLICY["Deterministic policy kernel"]
POLICY -->|deny| LEDGER["Append-only evidence ledger"]
POLICY -->|approval required| USER["Human approval boundary"]
USER --> POLICY
POLICY -->|allow| EXEC["Execution state machine"]
EXEC --> ADAPTERS["Bounded capability adapters"]
ADAPTERS --> TELEMETRY["Observed telemetry"]
TELEMETRY --> VERIFY["Outcome verifier"]
VERIFY --> LEDGER
VERIFY --> STATE
| Component | May propose | May authorize | May execute | May verify |
|---|---|---|---|---|
| User | Yes | Through explicit approval | No direct runtime bypass | Defines acceptance conditions |
| Gemini planner adapter | Yes | No | No | No |
| Optional semantic memory | Context only | No | No | No |
| Deterministic policy kernel | No | Yes | No | No |
| Execution state machine | No | Enforces prior decision | Through bounded adapters | No |
| Outcome verifier | No | No | No | Yes, from explicit conditions and observations |
See Architecture for the fixed architectural decisions, target bounded contexts, trust boundary, and structural constraints.
These are executable simulation invariants. Milestones 2 and 3 implement and test their runtime and planner boundaries.
- No model-to-actuator path. Model output is untrusted proposed data.
- Least authority. Every adapter exposes typed, versioned, allowlisted capabilities.
- Fail closed. Ambiguity, stale telemetry, invalid schemas, policy failure, or unavailable verification prevents actuation.
- State is time-bounded. Observations require timestamps, freshness limits, source identity, and quality indicators.
- Acceptance is not verification. An adapter accepting a command does not prove the intended effect occurred.
- Duplicate effects are bounded. Commands require idempotency behavior and duplicate-action prevention.
- Autonomy mode is explicit. Runtime mode is configured and recorded, never inferred from provider availability.
- R3 actions are prohibited. Safety-critical, vehicle-motion, life-support, fire, gas, high-energy, and security-critical actions cannot execute in the prototype.
- Evidence precedes claims. Plans, policy decisions, approvals, transitions, observations, and verification results require an inspectable trace.
- Providers remain replaceable. Gemini, Supermemory, Home Assistant, and other vendors remain outside the deterministic critical path.
The full adversary model, required controls, residual risks, and risk classes are documented in the Threat model.
The first target scenario is:
Prepare my environment for arrival in five minutes.
The nominal simulator coordinates eight bounded effects from one goal: garage entry, EV-charger readiness, climate setpoint, guarded coffee preparation, fan speed, ice production, welcome lighting, and the fictional program Orbit Seven on the living-room television. Destination confidence and device preconditions remain policy inputs rather than visual assumptions.
The Streamlit application renders these systems inside an interactive cutaway home. Green activity signals mean ready or independently verified; red signals mean blocked or failed; amber means guarded. Selecting a device exposes its evidence-derived state. The fireplace is deliberately present but permanently marked R3 locked: the prototype never exposes fire or gas ignition as a capability.
The architecture is not demonstrated by a single happy path. The approved scenario suite must cover:
| Scenario | Required behavior |
|---|---|
| Nominal arrival | All permitted actions complete and every acceptance condition is verified |
| False proximity | No arrival actions execute when destination confidence is insufficient |
| Blocked garage | The garage action is withheld while obstruction telemetry is active |
| Demand response | Energy policy produces a bounded alternative rather than an unsafe override |
| Stale telemetry | Required stale observations block execution |
| Partial failure | The trace reports partial success, failure, or compensation—never false success |
| Malicious external text | Untrusted content cannot create an undeclared capability |
All six named fixtures are committed, schema-validated, executed through the deterministic runtime, and compared against policy, dispatch, terminal-state, and verification expectations.
The primary hackathon workflow is Run judge comparison. One click executes two fresh, isolated traces for the selected goal:
- a deterministic reference with no external context; and
- a Gemini-plus-Supermemory path with deterministic planning and empty-context fallback when either provider is unavailable.
The UI compares behavior-level action semantics—targets, parameters, capability dependencies, failure behavior, preconditions, and acceptance evidence—while excluding generated identifiers and timestamps. It then reports the observed relationship between trusted inputs, declared capability containment, deterministic policy, terminal state, and independent verification. Context may alter an untrusted proposal; the comparison does not grant context any authority.
The complete hackathon judge guide includes the 90-second demonstration, architecture graphic, submission copy, screenshot set, live-provider acceptance procedure, and claims boundary.
| Area | Status | Evidence in this repository |
|---|---|---|
| Git and Python foundation | Implemented | Python 3.12 project metadata, package boundary, and locked dependency graph |
| Engineering documentation | Implemented | Product charter, architecture, privacy boundaries, threat model, verification plan, and ADRs |
| Repository quality gates | Implemented | Formatting, linting, strict typing, tests, coverage, audit, secret, docs, and repository checks |
| Strict domain contracts | Implemented | Goals, observations, capabilities, plans, policy results, approvals, transitions, events, verification, and scenarios |
| Policy and transition invariants | Implemented at contract layer | Contradictory policy results, R3 authorization, illegal state transitions, cycles, and undeclared references are rejected |
| Deterministic test clock | Implemented | UTC-only monotonic clock behind a clock port |
| Reference scenario fixtures | Implemented | Six self-contained simulation-only YAML fixtures with deterministic expected outcomes |
| Deterministic runtime and simulator | Implemented | World model, registry, policy kernel, approval binding, state machine, verifier, retries, duplicate suppression, and six executable scenarios |
| Operational ledger | Implemented | Ordered append-only in-memory and transactional SQLite repositories |
| Gemini planner adapter | Implemented and optional | Minimized prompt, Pydantic structured output, trusted binding checks, no tools, deterministic fallback |
| Planner evaluation | Implemented | Configuration, schema validity, hallucinations, parameters, preconditions, policy result, latency, and token usage |
| Memory boundary | Implemented and optional | Context-only port, no-op and synthetic adapters, read-only Supermemory search, fixed scope, five-result limit, normalization, and fail-closed fallback |
| Operator interface | Implemented | Responsive whole-home spatial runtime, one-click judge comparison, and narrative outcome, proposal, policy, transitions, verification, ledger, and memory evidence views |
| Supermemory demonstration | Implemented and optional | Hybrid retrieval supplies bounded untrusted planner context; no writes or authority path exist |
| Home Assistant integration | Post-hackathon | Not part of the M4 completion line |
| Real device actuation | Prohibited | No real actuation in the prototype |
The package version is 0.4.0. The deterministic CLI, planner-evaluation runner, and Streamlit operator application are supported hackathon workflows.
| Mode | State source | Planning | Execution | Status |
|---|---|---|---|---|
| Simulation | Deterministic simulated state | Yes | Simulated actions only | Implemented |
| Shadow | Live read-only state | Yes | None | Architecture-ready; optional demonstration |
| Supervised | Live state | Yes | Only after explicit approval | Post-prototype |
| Live bounded | Live state | Yes | Allowlisted low-risk actions | Post-security review |
No mode performs real actuation. Shadow, supervised, and live-bounded modes remain post-hackathon work.
The repository now contains the complete hackathon application:
handsoff/
├── AGENTS.md # Repository engineering agreement
├── README.md # Project entry point
├── pyproject.toml # Python project and quality-tool configuration
├── uv.lock # Exact dependency resolution
├── .python-version # Python 3.12 baseline
├── .env.example # Empty configuration placeholders only
├── streamlit_app.py # Public operator entrypoint
├── requirements.txt # Community Cloud project extras
├── .streamlit/config.toml # Non-secret presentation configuration
├── docs/
│ ├── product-charter.md
│ ├── architecture.md
│ ├── privacy-boundaries.md
│ ├── threat-model.md
│ ├── verification-plan.md
│ ├── streamlit-deployment.md
│ ├── hackathon-judge-guide.md
│ ├── release-checklist.md
│ ├── assets/
│ └── adr/
│ ├── 0001-modular-monolith.md
│ ├── 0002-model-is-not-controller.md
│ ├── 0003-simulator-first.md
│ └── 0004-streamlit-hackathon-interface.md
├── scripts/
│ ├── check_docs.py
│ ├── check_repository.py
│ ├── check_secrets.py
│ ├── evaluate_planner.py
│ ├── run_demo.py
│ └── validate.py
├── src/handsoff/
│ ├── adapters/
│ │ ├── clock/ # Deterministic test time
│ │ ├── devices/simulator/ # Scripted effects; no real devices
│ │ ├── memory/ # No-op, synthetic, Supermemory, and fail-closed adapters
│ │ ├── persistence/ # In-memory and SQLite ledgers
│ │ └── planner/ # Fixture, Gemini, and fallback planners
│ ├── application/ # Policy, execution, verification, scenarios
│ ├── domain/
│ │ ├── capabilities.py
│ │ ├── events.py
│ │ ├── execution.py
│ │ ├── goals.py
│ │ ├── observations.py
│ │ ├── planning.py
│ │ ├── plans.py
│ │ ├── policies.py
│ │ └── scenarios.py
│ ├── ports/ # Planner, memory, adapter, ledger, and clock
│ ├── presentation/ # Typed facade, semantic comparison, ecosystem projection, and session state
│ ├── __init__.py
│ └── py.typed
├── scenarios/
│ ├── blocked_garage.yaml
│ ├── demand_response.yaml
│ ├── false_proximity.yaml
│ ├── nominal_arrival.yaml
│ ├── partial_failure.yaml
│ └── stale_telemetry.yaml
└── tests/
├── contract/
├── fixtures/
├── integration/
├── property/
├── scenarios/
├── unit/
└── test_foundation.py
The Streamlit composition and deployment boundary are specified in the deployment guide.
- Git
uv0.11 or later- Python 3.12;
uvcan provision the interpreter if it is not already installed
git clone https://github.com/Vedangalle/handsoff.git
cd handsoff
uv python install 3.12
uv sync --frozenThis installs the project and default development dependency group exactly from uv.lock.
To reproduce the environment used by the complete validation suite, including the optional Gemini planner dependency boundary:
uv sync --frozen --all-extrasNo credential is required for deterministic execution, replay, evaluation, or validation. .env.example contains names and empty values only. Do not add real credentials to fixtures, prompts, logs, screenshots, tests, or version control.
uv run --frozen python scripts/run_demo.pyThis executes all six fixtures and reports measured policy decision, terminal state, and ledger-event count. It performs no network call and requires no credential.
uv run --frozen python scripts/evaluate_planner.pyThis emits JSON Lines evaluation records for the deterministic baseline. Live Gemini evaluation is intentionally opt-in and is never part of repository validation.
Install the application and optional Gemini extra, then launch the operator surface:
uv sync --frozen --all-extras
uv run --frozen --all-extras streamlit run streamlit_app.pyOpen the local URL printed by Streamlit. Select Whole-home evening arrival and click Run judge comparison for the primary workflow. It runs a deterministic reference and a separate Gemini-plus-Supermemory trace, then renders recalled context, behavior-level proposal changes, authority invariants, and the complete contextual evidence trace. With no credentials, the comparison remains complete and explicitly reports safe fallback.
The default Offline memory lab is also presentation-ready: it requires no credential, makes no network call, and supplies clearly labeled synthetic preference records through the same bounded memory port. Run the selected mode and inspect the verified house. The presentation follows an approach → entry → comfort → kitchen → media sequence: the car arrives, garage opens, charger prepares, climate and welcome lighting settle, fan rotates in place, ice and guarded coffee preparation begin, and the television resumes Orbit Seven. Device inspection remains user-controlled and reduced-motion preferences disable the cinematic sequence. Then select Obstructed garage to see the same spatial surface fail closed. Every state remains traceable through the proposal, policy reasons, transitions, verification results, ordered ledger, and memory boundary below the house.
The synthetic mode is deliberately honest about what it proves. It demonstrates context retrieval, normalization, planner containment, and the authority boundary; it does not claim that a live Supermemory request occurred. Deterministic baseline also remains fully offline. Live Gemini and Supermemory modes are optional comparisons for deployments with newly issued server-side credentials.
Optional local provider configuration belongs in ignored .streamlit/secrets.toml:
GOOGLE_API_KEY = ""
SUPERMEMORY_API_KEY = ""
HANDSOFF_MEMORY_SCOPE = "handsoff-public-demo-v1"Never commit that file. The browser cannot choose provider endpoints, model identifiers, or Supermemory container tags. Missing or invalid providers fall back visibly to deterministic planning or empty memory context without weakening policy.
Run the complete CI-equivalent local gate:
uv run --frozen --all-extras python scripts/validate.pyThe aggregate command stops at the first failure and executes the gates below. The latest release gate completed with 295 tests passing, 100% line coverage, and 100% branch coverage. These are repository validation results, not production reliability or real-device measurements.
| Gate | Command | What it establishes |
|---|---|---|
| Format | ruff format --check . |
Python formatting matches the repository configuration |
| Lint | ruff check . |
Configured Ruff rules pass |
| Static typing | mypy src scripts tests streamlit_app.py |
Strict Python 3.12 analysis passes |
| Tests | coverage run -m pytest |
The current test suite passes under strict pytest settings |
| Coverage | coverage report |
Package branch coverage meets the configured threshold |
| Lock consistency | uv lock --check |
pyproject.toml and uv.lock agree |
| Dependency audit | pip-audit --local --cache-dir .cache/pip-audit |
Installed dependencies have no reported known vulnerabilities |
| Secret scan | python scripts/check_secrets.py |
Git-visible files contain no detected secret candidates |
| Documentation | python scripts/check_docs.py |
Required documents, relative links, and Mermaid fence structure pass |
| Repository boundary | python scripts/check_repository.py |
Milestone, branch, placeholder, ignore, Python, and license invariants hold |
| Whitespace | git diff --check |
The tracked diff has no whitespace errors |
The detailed evidence contract, known limitations of documentation validation, and future test hierarchy are in the Verification plan.
The deterministic core must remain installable and testable without Gemini, Supermemory, or Home Assistant.
pydantic— strict schemas at trust boundariessqlalchemyandalembic— local SQLite persistence boundary and migration toolinghttpx— bounded external-adapter transportpyyaml— human-readable deterministic scenario fixtures
google-genaiis isolated in theplanner-geminiextra. The adapter is implemented but never enabled implicitly.streamlit==1.59.2is pinned in theappextra. The Supermemory adapter uses the existinghttpxboundary and adds no provider SDK to the deterministic core.- No Home Assistant dependency has been selected.
Milestone 4 is a single-process Streamlit application over typed application services. Its interactive cutaway-home projection is derived from committed scenario and runtime evidence; the embedded component has no authority path of its own. It supports four visible single-run modes plus a one-click deterministic-versus-contextual judge comparison. The core and complete visual demonstration remain functional when both external providers are disabled.
The public demo uses one fixed server-configured, demo-only Supermemory scope; retrieves at most five hybrid-search results; normalizes and truncates each result; labels it untrusted; and passes it only to planner context. Browser users cannot select container tags or write shared memory. Provider keys remain in Streamlit Community Cloud secrets, never in Git or session output.
The full process, session-isolation requirements, secret placeholders, packaging plan, and acceptance criteria are in Streamlit and Supermemory deployment.
The prototype core does not use LangChain, a general agent framework, Celery, Redis, Kafka, Kubernetes, a vector database, an embedded policy DSL, or a direct Matter implementation. Additional infrastructure must be justified by measured requirements, not architectural fashion.
| Milestone | Scope | State |
|---|---|---|
| M0 — Repository foundation | Git, Python project, lockfile, documentation, ADRs, and local quality gates | Complete |
| M1 — Contracts and deterministic tests | Domain vocabulary, strict schemas, test clock, scenario schema, six fixtures, and fail-first invariant tests | Complete |
| M2 — Deterministic runtime | World model, capability registry, policy kernel, state machine, verifier, ledger, simulator, and executable scenarios | Complete |
| M3 — Contained planner | Minimized Gemini structured output, trusted binding checks, deterministic fallback, optional memory port, and model evaluation | Complete |
| M4 — Hackathon application | Interactive whole-home spatial runtime, complete evidence UI, optional read-only Supermemory context, and one-click judge comparison | Complete |
Milestone 4 is the completed hackathon line. There are no additional committed milestones. Home Assistant shadow integration, live telemetry, and any real-device work are optional post-hackathon extensions requiring separate architecture and security approval.
| Document | Purpose |
|---|---|
| Product charter | Mission, user, prototype wedge, principles, promise, and non-goals |
| Architecture | Fixed decisions, data flow, trust boundary, bounded contexts, and target structure |
| Privacy boundaries | Data zones, credential handling, external-provider disclosure, and residual privacy risk |
| Threat model | Assets, adversaries, abuse paths, controls, risk classes, and residual risk |
| Verification plan | Evidence standard, current gates, future test hierarchy, and prototype acceptance criteria |
| Streamlit deployment | M4 process, Supermemory boundary, session isolation, secrets, packaging, and acceptance |
| Hackathon judge guide | Judge workflow, architecture graphic, 90-second script, submission copy, screenshots, live acceptance, and claims boundary |
| Release checklist | Automated freeze, owner-only deployment and video steps, and rollback procedure |
| ADR 0001 | Modular monolith with hexagonal boundaries |
| ADR 0002 | Model planning without model authority |
| ADR 0003 | Deterministic simulation before live integration |
| ADR 0004 | Streamlit hackathon surface and consolidation of the optional memory demo |
| AGENTS.md | Repository-specific engineering, review, security, and validation agreement |
Architecture decisions 1–10 were approved on 2026-07-13. Vedang explicitly revised the hackathon interface and completion line on the same date; ADR 0004 records the Streamlit decision and supersedes only the FastAPI-specific portion of decision 9.
Handsoff may eventually process data that reveals location, occupancy, routine, energy use, media context, device state, and action history. “Local-first” means the trusted operational core remains local by default; it does not mean configured external-provider calls remain on-device.
- Credentials belong in ignored local environment files or OS credential interfaces, never source control or model context.
- External-provider inputs must be minimized and documented.
- Optional memory cannot grant authority, change policy, execute actions, or verify outcomes.
- Evidence exports require review and redaction before leaving the local boundary.
- No real household data is required for the deterministic demonstration.
Report suspected security issues privately to the repository owner rather than publishing credential material or exploit details in an issue. No claim of production security, regulatory compliance, formal verification, penetration testing, or hardware-in-the-loop validation is made.
Changes are expected to preserve architectural boundaries, document assumptions, distinguish observed evidence from planned behavior, and include verification proportional to risk. Before proposing a commit, run the aggregate validation suite and inspect the exact diff and Git status.
Repository-specific instructions are defined in AGENTS.md.
No software license has been selected. The absence of a license means permission to use, copy, modify, or distribute this work should not be inferred. A LICENSE file and package license metadata will be added only after an explicit owner decision.
Handsoff is a hackathon working title, not a cleared commercial identity. Trademark, company-name, package-name, repository-name, social-handle, and domain clearance remain future work.
Handsoff · Autonomy for ordinary life.
Maintained by Vedang Alle
