The assistant that interrogates your idea before spending compute on it.
Second Shift is an always-on personal assistant that turns half-formed ideas into real artifacts overnight. You capture an idea by voice or text whenever you have one. Overnight, a machine you own researches it and builds something. In the morning you ask "what happened since we last talked," get a briefing — and then it interviews you, asking the questions it got stuck on. Your answers become tracked decisions that feed the next night's run.
Overnight agents are a commodity. The interview is the product.
Built for the Nebius x NVIDIA Global AI Hackathon, Personal AI track.
Week one, as of 2 Sep 2026. Capture works end to end and is taking real ideas daily; everything downstream of it is still ahead. The rest of this README describes the target — this table describes the present.
| Milestone | State |
|---|---|
| Repo scaffold | done |
| Persistence, telemetry, compute profiles, Privacy Airlock | done |
| Capture path (PWA → logged entry, text) | done — in daily use |
| Capture path (voice → ASR) | not started; text-first, so it gates nothing |
| The brain — plaintext memory under git | done — receiving every entry |
| Eval harness — pinned rubric, pinned brain state, repeated sampling | done — baseline recorded 2 Sep, six prompts; scoring waits on a judge |
| Synthetic night generator | done — 1,200+ events, every row is_synthetic = 1 |
| Local reasoning on the Spark | done — behind the Reasoner interface; a real completion was made through an agent on 2 Sep |
| Nebius Token Factory | credentials live and verified against the real API; the cloud Reasoner is not implemented |
| Nebius Serverless Jobs | not started |
| Retrieval — local embedding and policy-filtered assembly | done — measured on the machine: 40ms rebuild, 48 KiB index |
| Agents — six roles, versioned prompts pinned by content | done — prompts are drafts awaiting judgment |
| Configuration — resolved view with provenance | done — python -m secondshift.config show; not yet run on the always-on machine |
| Night orchestrator | done — checkpointed six-stage walk, quarantine over downgrade; never run against the real reasoner |
| Artifacts — files on disk, variant groups, outcomes | done — hashed from what landed; cost_per_accepted_artifact returns a number once a keep is recorded |
| Research — redaction before egress | done — queries are constructed, never filtered from raw text; local-only makes zero calls. Never run against the live Tavily API: no credential here |
| Morning interview | server half only — briefing, questions with rationale, answering, policy upgrade. No screen yet; frontend has now landed, so it is unblocked |
| Frontend shell and token system | done — one token file, navigation between every surface, demo label from the served profile |
| Night scrubber UI | done — reads a recorded night, scrubs by pointer or keyboard |
| Judge demo instance | not started |
Eighteen capabilities have shipped across seventeen OpenSpec changes. Their
specifications are in openspec/specs/; the changes that built them, with their
task lists, are in openspec/changes/archive/. Both directories are the
authority on that count — this sentence has been wrong before, so count them
rather than trusting it:
npx openspec list --specs && ls openspec/changes/archive/capture ──▶ queue ──▶ night run ──▶ artifacts + open questions
▲ │
│ ▼
decisions ◀────────────── morning interview ◀─┘
Each stage of the night run commits as it completes. If the 2am build stage fails, morning still has the brief, the research, and the questions. Graceful degradation is correct behavior, not a failure state.
Idea in, artifact out, memory in between.
That boundary is load-bearing. See NOT_BUILDING.md for what is deliberately excluded and why.
- The brain is a folder of plaintext under git. Skills, style guide, failure ledger, profile — human-readable markdown, diffable across time. No opaque memory database.
- Privacy Airlock. Every idea carries a policy set at capture:
local-only(never leaves the machine) orcloud-assisted(redaction pass, then Nebius Token Factory). Retrieval always runs locally; only assembled, policy-filtered context is ever transmitted. The brain itself never leaves. - No empty mornings. The night pipeline is a checkpointed state machine. Every stage that completes is committed and presentable.
- Text-first, voice layered on. Every voice interaction has a working text equivalent.
- Two deployments, one codebase. Personal instance on owned hardware; judge instance on Nebius with a synthetic persona and zero real data, labeled in-UI as a demo.
| Layer | Technology |
|---|---|
| Capture | PWA — Next.js / React, Web Audio API |
| ASR | Nemotron Speech Streaming 0.6B, local |
| Local reasoning | Nemotron 3.5 Lightning 30B A3B (NVFP4), vLLM |
| Cloud reasoning | Nemotron 3 Super / Ultra via Nebius Token Factory |
| Overnight compute | Nebius Serverless Jobs |
| Judge demo hosting | Nebius |
| Web research | Tavily |
| Embeddings | Llama Nemotron Embed VL 1B v2, local |
| Memory | Plaintext markdown + SQLite, git-versioned |
| Orchestrator | Python + FastAPI, SQLite job queue, systemd timers |
| Dashboard | Next.js + Tailwind, server-sent events |
| TTS | MagpieTTS via NeMo Speech — non-blocking |
Target hardware: NVIDIA DGX Spark (GB10 Grace Blackwell, 128GB unified memory, aarch64, CUDA 13.0, sm_121).
Every model in the runtime path is an NVIDIA open model. See docs/MODELS.md for exact bindings and THIRD_PARTY.md for licenses.
Every agent invocation and every model call is logged from run one — provider, model, tokens, latency, cost, and the privacy policy it ran under. This is not housekeeping. It is how the Privacy Airlock is proven rather than claimed (local-only ideas consume visibly zero cloud tokens), and how "it gets better at being me" becomes a measurable trend instead of an assertion.
Python 3.12 and Node 20+. Every command runs from the repository root.
python3.12 -m venv apps/api/.venv
apps/api/.venv/bin/pip install -c apps/api/constraints.txt -e "apps/api[dev]"
apps/api/.venv/bin/pip install -e packages/seed
npm --prefix apps/web installThe suites and the two source checks:
apps/api/.venv/bin/python -m pytest apps/api/tests -q
npm --prefix apps/web run test && npm --prefix apps/web run typecheck
scripts/check-no-environment.sh && scripts/check-american-english.shTo see a night without a GPU, credentials or a network, generate a synthetic one and point the API at it:
apps/api/.venv/bin/python -m secondshift_seed --seed 42 --db /tmp/night.db
SECOND_SHIFT_DB=/tmp/night.db SECOND_SHIFT_PROFILE=cloud \
apps/api/.venv/bin/uvicorn secondshift.api.main:app --port 8080
npm --prefix apps/web run devEvery row it writes carries is_synthetic = 1, and the rollup views exclude
them, so a generated night can never be mistaken for a real one.
Never run uv run on the DGX Spark: it re-resolves the environment for the
wrong architecture and destroys it. Use the virtual environment above.