manifesto: hard-offline first, one shot when the world blinks back

This commit is contained in:
cyclez 2026-03-25 22:30:51 +01:00
parent edcfd937e2
commit d3aec3d535
4 changed files with 296 additions and 0 deletions

View File

@ -0,0 +1,115 @@
# Emergency Runtime Architecture
## Summary
The emergency runtime is a downstream profile of Project N.O.M.A.D. for a dedicated handheld device.
The architectural center is not "online mode versus offline mode".
The center is a hard-offline local runtime that can ingest updates while the network exists.
## Product truth
- The primary asset is the local corpus.
- The primary read path is local search and local maps.
- The primary update path is opportunistic sync.
- Network loss is a normal operating assumption.
- In hostile or uncertain conditions, the device may need to remain on `OFF` and use only explicit one-shot exceptions.
## Downstream strategy
This fork should stay incrementally compatible with Project N.O.M.A.D. where practical.
Reuse first:
- collections and manifest shapes
- provider adapters and source metadata
- content ingestion and packaging logic
- offline maps plumbing where useful
Break away only where required by the emergency device use case:
- admin panel as primary UX
- Docker-orchestrated runtime assumptions
- mandatory Ollama/Qdrant path
- server-first deployment shape
## Runtime shape
The recommended runtime shape is:
1. installable mobile PWA
2. local daemon on the device
3. loopback HTTP API between UI and daemon
4. local SQLite plus FTS for text search
5. local filesystem storage for content and maps
The read path should remain local even when the device has connectivity.
## Network policy model
### `ON`
Use when continuous background sync is acceptable.
Behavior:
- daemon may probe connectivity
- daemon may refresh manifests on schedule
- daemon may download and index changed packages
- UI still resolves from local data first
### `OFF`
Use for battery conservation, OPSEC, or deterministic offline operation.
Behavior:
- daemon does not perform normal network requests
- probing is suppressed
- cached reachability state may become stale
- local corpus remains fully usable
### Armed one-shot sync
Use when the device should stay logically `OFF` but the operator wants to exploit a short or uncertain network window.
Behavior:
1. choose a bounded scope: `all`, `manifests`, `documents`, `maps`, or a single source
2. keep base policy at `OFF`
3. if a usable network is available, run one short sync job
4. if a usable network is not available yet, remain armed until timeout
5. auto-disarm after one attempt, success, failure, or timeout
Recommended defaults for v1:
- one-shot timeout: 10 minutes
- byte cap config exists but is disabled by default
- download count cap config exists but is disabled by default
## Operational rule
Treat network policy and observed reachability as separate concerns:
- policy answers "may the device use the network?"
- reachability answers "is a usable network currently present?"
This matters because in insecure scenarios a device may observe a usable network and still need to remain on `OFF`.
## Initial repo strategy
Keep emergency-specific work additive and easy to diff against upstream.
Recommended approach:
- keep upstream structure intact where possible
- add emergency docs under `docs/emergency/`
- add emergency runtime code in new bounded paths instead of patching unrelated upstream areas early
- prefer adapters and feature flags over broad rewrites
## Immediate milestones
1. Document the emergency profile and local API.
2. Identify the smallest reusable seams from upstream.
3. Build a loopback-only daemon skeleton for status, search, and one-shot sync.
4. Keep the first implementation local-search-first and map-capable.

View File

@ -0,0 +1,33 @@
# Emergency Bootstrap Prompt
Use this brief when scaffolding emergency-specific work in this downstream fork.
## Goal
Build an emergency runtime profile on top of Project N.O.M.A.D. that favors hard-offline usefulness, local search, and bounded sync.
## Constraints
- Keep upstream compatibility where practical.
- Prefer additive paths over invasive rewrites.
- Assume the device is a dedicated Android or Ubuntu handheld.
- Keep v1 deterministic: search, excerpt, source, maps.
- Do not make LLM or vector infrastructure a hard runtime dependency.
## Network model
- Base policy: `ON` or `OFF`
- Explicit exception: armed one-shot sync
- One-shot must support:
- bounded scope
- timeout
- byte cap setting
- download count cap setting
- auto-disarm
## Quality bar
- Keep the read path local.
- Keep network usage explicit.
- Keep the delta against upstream small and understandable.
- Prefer boring and reliable over clever abstractions.

119
docs/emergency/LOCAL_API.md Normal file
View File

@ -0,0 +1,119 @@
# Emergency Local API
## Purpose
This API exists to expose the emergency runtime to a local PWA over loopback only.
The API is not public and should not be exposed on the internet.
## Base URL
```text
http://127.0.0.1:4187/api/v1
```
## Core model
- Read operations are local-first.
- Base network policy is `ON` or `OFF`.
- One-shot sync is an explicit bounded exception path.
## Key endpoints
### `GET /status`
Returns high-level runtime state.
Example:
```json
{
"network_policy": "OFF",
"network": {
"reachable": null,
"last_checked_at": "2026-03-24T18:20:00Z",
"probe_allowed": false
},
"oneshot": {
"armed": true,
"state": "armed",
"scope": "manifests",
"timeout_seconds": 600,
"enforce_byte_cap": false,
"byte_cap_mb": 0,
"enforce_download_cap": false,
"download_cap_count": 0,
"armed_at": "2026-03-24T18:30:00Z",
"expires_at": "2026-03-24T18:40:00Z"
},
"sync": {
"state": "idle",
"last_success_at": "2026-03-24T18:20:00Z"
}
}
```
### `GET /mode`
Returns base network policy and one-shot state.
### `PUT /mode`
Sets base network policy.
Request:
```json
{
"network_policy": "OFF"
}
```
Allowed values:
- `ON`
- `OFF`
### `POST /sync/oneshot`
Triggers or arms a bounded one-shot sync while leaving base policy unchanged.
Request:
```json
{
"scope": "manifests",
"reason": "manual",
"arm_if_offline": true,
"timeout_seconds": 600,
"enforce_byte_cap": false,
"byte_cap_mb": 0,
"enforce_download_cap": false,
"download_cap_count": 0
}
```
Behavior:
- if network is available now, queue one short sync job
- if network is unavailable and `arm_if_offline = true`, keep the request armed until timeout
- auto-disarm after one attempt, success, failure, or timeout
### `POST /sync/run`
Triggers a normal sync cycle.
This route is intended for policy `ON`.
### `GET /search`
Returns local search results only.
### `GET /documents/:document_id`
Returns locally stored document content and provenance metadata.
## Notes
- `network.reachable` may be `null` when active probing is suppressed by `OFF`.
- One-shot is the preferred explicit exception path from `OFF`.
- Cap fields are present in v1 but disabled by default until payload sizes are better understood.

29
docs/emergency/README.md Normal file
View File

@ -0,0 +1,29 @@
# Emergency Runtime Profile
This folder defines a downstream emergency profile for Project N.O.M.A.D.
The profile is designed for a dedicated Android device running Ubuntu/Linux where the system must remain useful with zero network and treat network availability as an opportunistic ingest path, not as part of the main read path.
## Core principles
- Hard-offline first: search, maps, and critical reads must work from local storage.
- Incremental compatibility: reuse upstream Project N.O.M.A.D. code where practical and keep the delta small.
- Device-first runtime: prefer a local daemon plus a mobile-friendly PWA over server/admin assumptions.
- Bounded sync: network use should be explicit, short, and policy-driven.
## Network policy model
- `ON`: normal background sync is allowed.
- `OFF`: no normal network activity is allowed.
- Armed one-shot sync: a bounded exception that can remain armed while base policy stays `OFF`.
## Document map
- [Architecture](./ARCHITECTURE.md)
- [Local API](./LOCAL_API.md)
- [Bootstrap Prompt](./BOOTSTRAP_PROMPT.md)
## Intended use
This is not a chat-first product.
It is a continuity-of-information runtime that keeps a local corpus current while it can, then continues to serve that corpus when the network disappears or should not be used.